diff options
Diffstat (limited to 'lib/rbcodec/codecs/cRSID/C64/MEM.c')
-rw-r--r-- | lib/rbcodec/codecs/cRSID/C64/MEM.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/cRSID/C64/MEM.c b/lib/rbcodec/codecs/cRSID/C64/MEM.c new file mode 100644 index 0000000000..5be0fc47db --- /dev/null +++ b/lib/rbcodec/codecs/cRSID/C64/MEM.c | |||
@@ -0,0 +1,132 @@ | |||
1 | |||
2 | //Emulation of C64 memories and memory bus (PLA & MUXes) | ||
3 | |||
4 | |||
5 | static inline unsigned char* cRSID_getMemReadPtr (register unsigned short address) { | ||
6 | //cRSID_C64instance* const C64 = &cRSID_C64; //for faster (?) operation we use a global object as memory | ||
7 | if (address<0xA000) return &cRSID_C64.RAMbank[address]; | ||
8 | else if ( 0xD000<=address && address<0xE000 && (cRSID_C64.RAMbank[1]&3) ) { | ||
9 | if (0xD400 <= address && address < 0xD419) return &cRSID_C64.IObankWR[address]; //emulate bitfading aka SID-read of last written reg (e.g. Lift Off ROR $D400,x) | ||
10 | return &cRSID_C64.IObankRD[address]; | ||
11 | } | ||
12 | else if ( (address<0xC000 && (cRSID_C64.RAMbank[1]&3)==3) | ||
13 | || (0xE000<=address && (cRSID_C64.RAMbank[1]&2)) ) return &cRSID_C64.ROMbanks[address]; | ||
14 | return &cRSID_C64.RAMbank[address]; | ||
15 | } | ||
16 | |||
17 | static inline unsigned char* cRSID_getMemReadPtrC64 (cRSID_C64instance* C64, register unsigned short address) { | ||
18 | if (address<0xA000) return &C64->RAMbank[address]; | ||
19 | else if ( 0xD000<=address && address<0xE000 && (C64->RAMbank[1]&3) ) { | ||
20 | if (0xD400 <= address && address < 0xD419) return &cRSID_C64.IObankWR[address]; //emulate peculiar SID-read (e.g. Lift Off) | ||
21 | return &C64->IObankRD[address]; | ||
22 | } | ||
23 | else if ( (address<0xC000 && (C64->RAMbank[1]&3)==3) | ||
24 | || (0xE000<=address && (C64->RAMbank[1]&2)) ) return &C64->ROMbanks[address]; | ||
25 | return &C64->RAMbank[address]; | ||
26 | } | ||
27 | |||
28 | |||
29 | static inline unsigned char* cRSID_getMemWritePtr (register unsigned short address) { | ||
30 | //cRSID_C64instance* const C64 = &cRSID_C64; //for faster (?) operation we use a global object as memory | ||
31 | if (address<0xD000 || 0xE000<=address) return &cRSID_C64.RAMbank[address]; | ||
32 | else if ( cRSID_C64.RAMbank[1]&3 ) { //handle SID-mirrors! (CJ in the USA workaround (writing above $d420, except SID2/SID3)) | ||
33 | if (0xD420 <= address && address < 0xD800) { //CIA/VIC mirrors needed? | ||
34 | if ( !(cRSID_C64.PSIDdigiMode && 0xD418 <= address && address < 0xD500) | ||
35 | && !(cRSID_C64.SID[2].BaseAddress <= address && address < cRSID_C64.SID[2].BaseAddress+0x20) | ||
36 | && !(cRSID_C64.SID[3].BaseAddress <= address && address < cRSID_C64.SID[3].BaseAddress+0x20) ) { | ||
37 | return &cRSID_C64.IObankWR[ 0xD400 + (address&0x1F) ]; //write to $D400..D41F if not in SID2/SID3 address-space | ||
38 | } | ||
39 | else return &cRSID_C64.IObankWR[address]; | ||
40 | } | ||
41 | else return &cRSID_C64.IObankWR[address]; | ||
42 | } | ||
43 | return &cRSID_C64.RAMbank[address]; | ||
44 | } | ||
45 | |||
46 | |||
47 | static inline unsigned char* cRSID_getMemWritePtrC64 (cRSID_C64instance* C64, register unsigned short address) { | ||
48 | if (address<0xD000 || 0xE000<=address) return &C64->RAMbank[address]; | ||
49 | else if ( C64->RAMbank[1]&3 ) { //handle SID-mirrors! (CJ in the USA workaround (writing above $d420, except SID2/SID3/PSIDdigi)) | ||
50 | if (0xD420 <= address && address < 0xD800) { //CIA/VIC mirrors needed? | ||
51 | if ( !(cRSID_C64.PSIDdigiMode && 0xD418 <= address && address < 0xD500) | ||
52 | && !(C64->SID[2].BaseAddress <= address && address < C64->SID[2].BaseAddress+0x20) | ||
53 | && !(C64->SID[3].BaseAddress <= address && address < C64->SID[3].BaseAddress+0x20) ) { | ||
54 | return &C64->IObankWR[ 0xD400 + (address&0x1F) ]; //write to $D400..D41F if not in SID2/SID3 address-space | ||
55 | } | ||
56 | else return &C64->IObankWR[address]; | ||
57 | } | ||
58 | else return &C64->IObankWR[address]; | ||
59 | } | ||
60 | return &C64->RAMbank[address]; | ||
61 | } | ||
62 | |||
63 | |||
64 | static inline unsigned char cRSID_readMem (register unsigned short address) { | ||
65 | return *cRSID_getMemReadPtr(address); | ||
66 | } | ||
67 | |||
68 | static inline unsigned char cRSID_readMemC64 (cRSID_C64instance* C64, register unsigned short address) { | ||
69 | return *cRSID_getMemReadPtrC64(C64,address); | ||
70 | } | ||
71 | |||
72 | |||
73 | static inline void cRSID_writeMem (register unsigned short address, register unsigned char data) { | ||
74 | *cRSID_getMemWritePtr(address)=data; | ||
75 | } | ||
76 | |||
77 | static inline void cRSID_writeMemC64 (cRSID_C64instance* C64, register unsigned short address, register unsigned char data) { | ||
78 | *cRSID_getMemWritePtrC64(C64,address)=data; | ||
79 | } | ||
80 | |||
81 | |||
82 | void cRSID_setROMcontent (cRSID_C64instance* C64) { //fill KERNAL/BASIC-ROM areas with content needed for SID-playback | ||
83 | int i; | ||
84 | static const unsigned char ROM_IRQreturnCode[9] = {0xAD,0x0D,0xDC,0x68,0xA8,0x68,0xAA,0x68,0x40}; //CIA1-acknowledge IRQ-return | ||
85 | static const unsigned char ROM_NMIstartCode[5] = {0x78,0x6c,0x18,0x03,0x40}; //SEI and jmp($0318) | ||
86 | static const unsigned char ROM_IRQBRKstartCode[19] = { //Full IRQ-return (handling BRK with the same RAM vector as IRQ) | ||
87 | 0x48,0x8A,0x48,0x98,0x48,0xBA,0xBD,0x04,0x01,0x29,0x10,0xEA,0xEA,0xEA,0xEA,0xEA,0x6C,0x14,0x03 | ||
88 | }; | ||
89 | |||
90 | for (i=0xA000; i<0x10000; ++i) C64->ROMbanks[i] = 0x60; //RTS (at least return if some unsupported call is made to ROM) | ||
91 | for (i=0xEA31; i<0xEA7E; ++i) C64->ROMbanks[i] = 0xEA; //NOP (full IRQ-return leading to simple IRQ-return without other tasks) | ||
92 | for (i=0; i<9; ++i) C64->ROMbanks [0xEA7E + i] = ROM_IRQreturnCode[i]; | ||
93 | for (i=0; i<4; ++i) C64->ROMbanks [0xFE43 + i] = ROM_NMIstartCode[i]; | ||
94 | for (i=0; i<19; ++i) C64->ROMbanks[0xFF48 + i] = ROM_IRQBRKstartCode[i]; | ||
95 | |||
96 | C64->ROMbanks[0xFFFB] = 0xFE; C64->ROMbanks[0xFFFA] = 0x43; //ROM NMI-vector | ||
97 | C64->ROMbanks[0xFFFF] = 0xFF; C64->ROMbanks[0xFFFE] = 0x48; //ROM IRQ-vector | ||
98 | |||
99 | //copy KERNAL & BASIC ROM contents into the RAM under them? (So PSIDs that don't select bank correctly will work better.) | ||
100 | for (i=0xA000; i<0x10000; ++i) C64->RAMbank[i]=C64->ROMbanks[i]; | ||
101 | } | ||
102 | |||
103 | |||
104 | void cRSID_initMem (cRSID_C64instance* C64) { //set default values that normally KERNEL ensures after startup/reset (only SID-playback related) | ||
105 | static int i; | ||
106 | |||
107 | //data required by both PSID and RSID (according to HVSC SID_file_format.txt): | ||
108 | cRSID_writeMemC64( C64, 0x02A6, C64->VideoStandard ); //$02A6 should be pre-set to: 0:NTSC / 1:PAL | ||
109 | cRSID_writeMemC64( C64, 0x0001, 0x37 ); //initialize bank-reg. (ROM-banks and IO enabled) | ||
110 | |||
111 | //if (C64->ROMbanks[0xE000]==0) { //wasn't a KERNAL-ROM loaded? (e.g. PSID) | ||
112 | cRSID_writeMemC64( C64, 0x00CB, 0x40 ); //Some tunes might check for keypress here (e.g. Master Blaster Intro) | ||
113 | //if(C64->RealSIDmode) { | ||
114 | cRSID_writeMemC64( C64, 0x0315, 0xEA ); cRSID_writeMemC64( C64, 0x0314, 0x31 ); //IRQ | ||
115 | cRSID_writeMemC64( C64, 0x0319, 0xEA/*0xFE*/ ); cRSID_writeMemC64( C64, 0x0318, 0x81/*0x47*/ ); //NMI | ||
116 | //} | ||
117 | |||
118 | for (i=0xD000; i<0xD7FF; ++i) C64->IObankRD[i] = C64->IObankWR[i] = 0; //initialize the whole IO area for a known base-state | ||
119 | if(C64->RealSIDmode) {C64->IObankWR[0xD012] = 0x37; C64->IObankWR[0xD011] = 0x8B;} //else C64->IObankWR[0xD012] = 0; | ||
120 | //C64->IObankWR[0xD019] = 0; //PSID: rasterrow: any value <= $FF, IRQ:enable later if there is VIC-timingsource | ||
121 | |||
122 | C64->IObankRD[0xDC00]=0x10; C64->IObankRD[0xDC01]=0xFF; //Imitate CIA1 keyboard/joy port, some tunes check if buttons are not pressed | ||
123 | if (C64->VideoStandard) { C64->IObankWR[0xDC04]=0x24; C64->IObankWR[0xDC05]=0x40; } //initialize CIAs | ||
124 | else { C64->IObankWR[0xDC04]=0x95; C64->IObankWR[0xDC05]=0x42; } | ||
125 | if(C64->RealSIDmode) C64->IObankWR[0xDC0D] = 0x81; //Reset-default, but for PSID CIA1 TimerA IRQ should be enabled anyway if SID is CIA-timed | ||
126 | C64->IObankWR[0xDC0E] = 0x01; //some tunes (and PSID doc) expect already running CIA (Reset-default) | ||
127 | C64->IObankWR[0xDC0F] = 0x00; //All counters other than CIA1 TimerA should be disabled and set to 0xFF for PSID: | ||
128 | C64->IObankWR[0xDD04] = C64->IObankWR[0xDD05] = 0xFF; //C64->IObankWR[0xDD0E] = C64->IObank[0xDD0F] = 0x00; | ||
129 | //} | ||
130 | |||
131 | } | ||
132 | |||