Skip to content

Commit 9544b47

Browse files
author
dashodanger
committed
Add floating point output, update example player code, style/format updates
1 parent b195dfe commit 9544b47

File tree

13 files changed

+3539
-2192
lines changed

13 files changed

+3539
-2192
lines changed

C64/CIA.c

+140-81
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,152 @@
11

2-
//cRSID CIA emulation
3-
4-
5-
void cRSID_createCIAchip (cRSID_C64instance* C64, cRSID_CIAinstance* CIA, unsigned short baseaddress) {
6-
CIA->C64 = C64;
7-
CIA->ChipModel = 0;
8-
CIA->BaseAddress = baseaddress;
9-
CIA->BasePtrWR = &C64->IObankWR[baseaddress]; CIA->BasePtrRD = &C64->IObankRD[baseaddress];
10-
cRSID_initCIAchip(CIA);
2+
// cRSID CIA emulation
3+
4+
void cRSID_createCIAchip(cRSID_C64instance *C64, cRSID_CIAinstance *CIA, unsigned short baseaddress)
5+
{
6+
CIA->C64 = C64;
7+
CIA->ChipModel = 0;
8+
CIA->BaseAddress = baseaddress;
9+
CIA->BasePtrWR = &C64->IObankWR[baseaddress];
10+
CIA->BasePtrRD = &C64->IObankRD[baseaddress];
11+
cRSID_initCIAchip(CIA);
1112
}
1213

13-
14-
void cRSID_initCIAchip (cRSID_CIAinstance* CIA) {
15-
unsigned char i;
16-
for (i=0; i<0x10; ++i) CIA->BasePtrWR[i] = CIA->BasePtrRD[i] = 0x00;
14+
void cRSID_initCIAchip(cRSID_CIAinstance *CIA)
15+
{
16+
unsigned char i;
17+
for (i = 0; i < 0x10; ++i)
18+
CIA->BasePtrWR[i] = CIA->BasePtrRD[i] = 0x00;
1719
}
1820

19-
20-
static inline char cRSID_emulateCIA (cRSID_CIAinstance* CIA, char cycles) {
21-
static int Tmp;
22-
23-
enum CIAregisters { PORTA=0, PORTB=1, DDRA=2, DDRB=3,
24-
TIMERAL=4, TIMERAH=5, TIMERBL=6, TIMERBH=7, //Write:Set Timer-latch, Read: read Timer
25-
TOD_TENTHSECONDS=8, TOD_SECONDS=9, TOD_MINUTES=0xA, TOD_HOURS=0xB,
26-
SERIAL_DATA=0xC, INTERRUPTS=0xD, CONTROLA=0xE, CONTROLB=0xF };
27-
28-
enum InterruptBitVal { INTERRUPT_HAPPENED=0x80, SET_OR_CLEAR_FLAGS=0x80, //(Read or Write operation determines which one:)
29-
FLAGn=0x10, SERIALPORT=0x08, ALARM=0x04, TIMERB=0x02, TIMERA=0x01 }; //flags/masks of interrupt-sources
30-
31-
enum ControlAbitVal { ENABLE_TIMERA=0x01, PORTB6_TIMERA=0x02, TOGGLED_PORTB6=0x04, ONESHOT_TIMERA=0x08,
32-
FORCELOADA_STROBE=0x10, TIMERA_FROM_CNT=0x20, SERIALPORT_IS_OUTPUT=0x40, TIMEOFDAY_50Hz=0x80 };
33-
34-
enum ControlBbitVal { ENABLE_TIMERB=0x01, PORTB7_TIMERB=0x02, TOGGLED_PORTB7=0x04, ONESHOT_TIMERB=0x08,
35-
FORCELOADB_STROBE=0x10, TIMERB_FROM_CPUCLK=0x00, TIMERB_FROM_CNT=0x20, TIMERB_FROM_TIMERA=0x40,
36-
TIMERB_FROM_TIMERA_AND_CNT = 0x60, TIMEOFDAY_WRITE_SETS_ALARM = 0x80 };
37-
38-
//TimerA
39-
if (CIA->BasePtrWR[CONTROLA] & FORCELOADA_STROBE) { //force latch into counter (strobe-input)
40-
CIA->BasePtrRD[TIMERAH] = CIA->BasePtrWR[TIMERAH]; CIA->BasePtrRD[TIMERAL] = CIA->BasePtrWR[TIMERAL];
41-
}
42-
else if ( (CIA->BasePtrWR[CONTROLA] & (ENABLE_TIMERA|TIMERA_FROM_CNT)) == ENABLE_TIMERA ) { //Enabled, counts Phi2
43-
Tmp = ( (CIA->BasePtrRD[TIMERAH]<<8) + CIA->BasePtrRD[TIMERAL] ) - cycles; //count timer
44-
if (Tmp <= 0) { //Timer counted down
45-
Tmp += (CIA->BasePtrWR[TIMERAH]<<8) + CIA->BasePtrWR[TIMERAL]; //reload timer
46-
if (CIA->BasePtrWR[CONTROLA] & ONESHOT_TIMERA) CIA->BasePtrWR[CONTROLA] &= ~ENABLE_TIMERA; //disable if one-shot
47-
CIA->BasePtrRD[INTERRUPTS] |= TIMERA;
48-
if (CIA->BasePtrWR[INTERRUPTS] & TIMERA) { //generate interrupt if mask allows
49-
CIA->BasePtrRD[INTERRUPTS] |= INTERRUPT_HAPPENED;
50-
}
51-
}
52-
CIA->BasePtrRD[TIMERAH] = (Tmp >> 8); CIA->BasePtrRD[TIMERAL] = Tmp & 0xFF;
53-
}
54-
CIA->BasePtrWR[CONTROLA] &= ~FORCELOADA_STROBE; //strobe is edge-sensitive
55-
CIA->BasePtrRD[CONTROLA] = CIA->BasePtrWR[CONTROLA]; //control-registers are readable
56-
57-
//TimerB
58-
if (CIA->BasePtrWR[CONTROLB] & FORCELOADB_STROBE) { //force latch into counter (strobe-input)
59-
CIA->BasePtrRD[TIMERBH] = CIA->BasePtrWR[TIMERBH]; CIA->BasePtrRD[TIMERBL] = CIA->BasePtrWR[TIMERBL];
60-
} //what about clocking TimerB by TimerA? (maybe not used in any music)
61-
else if ( (CIA->BasePtrWR[CONTROLB] & (ENABLE_TIMERB|TIMERB_FROM_TIMERA)) == ENABLE_TIMERB ) { //Enabled, counts Phi2
62-
Tmp = ( (CIA->BasePtrRD[TIMERBH]<<8) + CIA->BasePtrRD[TIMERBL] ) - cycles;//count timer
63-
if (Tmp <= 0) { //Timer counted down
64-
Tmp += (CIA->BasePtrWR[TIMERBH]<<8) + CIA->BasePtrWR[TIMERBL]; //reload timer
65-
if (CIA->BasePtrWR[CONTROLB] & ONESHOT_TIMERB) CIA->BasePtrWR[CONTROLB] &= ~ENABLE_TIMERB; //disable if one-shot
66-
CIA->BasePtrRD[INTERRUPTS] |= TIMERB;
67-
if (CIA->BasePtrWR[INTERRUPTS] & TIMERB) { //generate interrupt if mask allows
68-
CIA->BasePtrRD[INTERRUPTS] |= INTERRUPT_HAPPENED;
69-
}
70-
}
71-
CIA->BasePtrRD[TIMERBH] = (Tmp >> 8); CIA->BasePtrRD[TIMERBL] = Tmp & 0xFF;
72-
}
73-
CIA->BasePtrWR[CONTROLB] &= ~FORCELOADB_STROBE; //strobe is edge-sensitive
74-
CIA->BasePtrRD[CONTROLB] = CIA->BasePtrWR[CONTROLB]; //control-registers are readable
75-
76-
return (CIA->BasePtrRD[INTERRUPTS] & INTERRUPT_HAPPENED);
21+
static inline char cRSID_emulateCIA(cRSID_CIAinstance *CIA, char cycles)
22+
{
23+
static int Tmp;
24+
25+
enum CIAregisters
26+
{
27+
PORTA = 0,
28+
PORTB = 1,
29+
DDRA = 2,
30+
DDRB = 3,
31+
TIMERAL = 4,
32+
TIMERAH = 5,
33+
TIMERBL = 6,
34+
TIMERBH = 7, // Write:Set Timer-latch, Read: read Timer
35+
TOD_TENTHSECONDS = 8,
36+
TOD_SECONDS = 9,
37+
TOD_MINUTES = 0xA,
38+
TOD_HOURS = 0xB,
39+
SERIAL_DATA = 0xC,
40+
INTERRUPTS = 0xD,
41+
CONTROLA = 0xE,
42+
CONTROLB = 0xF
43+
};
44+
45+
enum InterruptBitVal
46+
{
47+
INTERRUPT_HAPPENED = 0x80,
48+
SET_OR_CLEAR_FLAGS = 0x80, //(Read or Write operation determines which one:)
49+
FLAGn = 0x10,
50+
SERIALPORT = 0x08,
51+
ALARM = 0x04,
52+
TIMERB = 0x02,
53+
TIMERA = 0x01
54+
}; // flags/masks of interrupt-sources
55+
56+
enum ControlAbitVal
57+
{
58+
ENABLE_TIMERA = 0x01,
59+
PORTB6_TIMERA = 0x02,
60+
TOGGLED_PORTB6 = 0x04,
61+
ONESHOT_TIMERA = 0x08,
62+
FORCELOADA_STROBE = 0x10,
63+
TIMERA_FROM_CNT = 0x20,
64+
SERIALPORT_IS_OUTPUT = 0x40,
65+
TIMEOFDAY_50Hz = 0x80
66+
};
67+
68+
enum ControlBbitVal
69+
{
70+
ENABLE_TIMERB = 0x01,
71+
PORTB7_TIMERB = 0x02,
72+
TOGGLED_PORTB7 = 0x04,
73+
ONESHOT_TIMERB = 0x08,
74+
FORCELOADB_STROBE = 0x10,
75+
TIMERB_FROM_CPUCLK = 0x00,
76+
TIMERB_FROM_CNT = 0x20,
77+
TIMERB_FROM_TIMERA = 0x40,
78+
TIMERB_FROM_TIMERA_AND_CNT = 0x60,
79+
TIMEOFDAY_WRITE_SETS_ALARM = 0x80
80+
};
81+
82+
// TimerA
83+
if (CIA->BasePtrWR[CONTROLA] & FORCELOADA_STROBE)
84+
{ // force latch into counter (strobe-input)
85+
CIA->BasePtrRD[TIMERAH] = CIA->BasePtrWR[TIMERAH];
86+
CIA->BasePtrRD[TIMERAL] = CIA->BasePtrWR[TIMERAL];
87+
}
88+
else if ((CIA->BasePtrWR[CONTROLA] & (ENABLE_TIMERA | TIMERA_FROM_CNT)) == ENABLE_TIMERA)
89+
{ // Enabled, counts Phi2
90+
Tmp = ((CIA->BasePtrRD[TIMERAH] << 8) + CIA->BasePtrRD[TIMERAL]) - cycles; // count timer
91+
if (Tmp <= 0)
92+
{ // Timer counted down
93+
Tmp += (CIA->BasePtrWR[TIMERAH] << 8) + CIA->BasePtrWR[TIMERAL]; // reload timer
94+
if (CIA->BasePtrWR[CONTROLA] & ONESHOT_TIMERA)
95+
CIA->BasePtrWR[CONTROLA] &= ~ENABLE_TIMERA; // disable if one-shot
96+
CIA->BasePtrRD[INTERRUPTS] |= TIMERA;
97+
if (CIA->BasePtrWR[INTERRUPTS] & TIMERA)
98+
{ // generate interrupt if mask allows
99+
CIA->BasePtrRD[INTERRUPTS] |= INTERRUPT_HAPPENED;
100+
}
101+
}
102+
CIA->BasePtrRD[TIMERAH] = (Tmp >> 8);
103+
CIA->BasePtrRD[TIMERAL] = Tmp & 0xFF;
104+
}
105+
CIA->BasePtrWR[CONTROLA] &= ~FORCELOADA_STROBE; // strobe is edge-sensitive
106+
CIA->BasePtrRD[CONTROLA] = CIA->BasePtrWR[CONTROLA]; // control-registers are readable
107+
108+
// TimerB
109+
if (CIA->BasePtrWR[CONTROLB] & FORCELOADB_STROBE)
110+
{ // force latch into counter (strobe-input)
111+
CIA->BasePtrRD[TIMERBH] = CIA->BasePtrWR[TIMERBH];
112+
CIA->BasePtrRD[TIMERBL] = CIA->BasePtrWR[TIMERBL];
113+
} // what about clocking TimerB by TimerA? (maybe not used in any music)
114+
else if ((CIA->BasePtrWR[CONTROLB] & (ENABLE_TIMERB | TIMERB_FROM_TIMERA)) == ENABLE_TIMERB)
115+
{ // Enabled, counts Phi2
116+
Tmp = ((CIA->BasePtrRD[TIMERBH] << 8) + CIA->BasePtrRD[TIMERBL]) - cycles; // count timer
117+
if (Tmp <= 0)
118+
{ // Timer counted down
119+
Tmp += (CIA->BasePtrWR[TIMERBH] << 8) + CIA->BasePtrWR[TIMERBL]; // reload timer
120+
if (CIA->BasePtrWR[CONTROLB] & ONESHOT_TIMERB)
121+
CIA->BasePtrWR[CONTROLB] &= ~ENABLE_TIMERB; // disable if one-shot
122+
CIA->BasePtrRD[INTERRUPTS] |= TIMERB;
123+
if (CIA->BasePtrWR[INTERRUPTS] & TIMERB)
124+
{ // generate interrupt if mask allows
125+
CIA->BasePtrRD[INTERRUPTS] |= INTERRUPT_HAPPENED;
126+
}
127+
}
128+
CIA->BasePtrRD[TIMERBH] = (Tmp >> 8);
129+
CIA->BasePtrRD[TIMERBL] = Tmp & 0xFF;
130+
}
131+
CIA->BasePtrWR[CONTROLB] &= ~FORCELOADB_STROBE; // strobe is edge-sensitive
132+
CIA->BasePtrRD[CONTROLB] = CIA->BasePtrWR[CONTROLB]; // control-registers are readable
133+
134+
return (CIA->BasePtrRD[INTERRUPTS] & INTERRUPT_HAPPENED);
77135
}
78136

79-
80-
static inline void cRSID_writeCIAIRQmask (cRSID_CIAinstance* CIA, unsigned char value) {
81-
if (value&0x80) CIA->BasePtrWR[0xD] |= (value&0x1F);
82-
else CIA->BasePtrWR[0xD] &= ~(value&0x1F);
137+
static inline void cRSID_writeCIAIRQmask(cRSID_CIAinstance *CIA, unsigned char value)
138+
{
139+
if (value & 0x80)
140+
CIA->BasePtrWR[0xD] |= (value & 0x1F);
141+
else
142+
CIA->BasePtrWR[0xD] &= ~(value & 0x1F);
83143
}
84144

85-
86-
static inline void cRSID_acknowledgeCIAIRQ (cRSID_CIAinstance* CIA) {
87-
CIA->BasePtrRD[0xD] = 0x00; //reading a CIA interrupt-register clears its read-part and IRQ-flag
145+
static inline void cRSID_acknowledgeCIAIRQ(cRSID_CIAinstance *CIA)
146+
{
147+
CIA->BasePtrRD[0xD] = 0x00; // reading a CIA interrupt-register clears its read-part and IRQ-flag
88148
}
89149

90-
91-
//static inline void cRSID_writeCIARWreg () {
92-
//mirroring write-latch to read-latch for Readable-Writeable registers?
150+
// static inline void cRSID_writeCIARWreg () {
151+
// mirroring write-latch to read-latch for Readable-Writeable registers?
93152
//}

0 commit comments

Comments
 (0)