2 // Thunder: A Rolling Thunder Emulator w/6809 debugger v0.40
3 // (Last build: 3/6/2004)
7 // (c) 2004 Underground Software
10 #define THUNDER_VERSION "0.4.0"
11 #define THUNDER_BETA_VERSION "6"
20 #include <conio.h> // For getch()
22 #include "SDL.h" // Get yer SDL out...!
29 using namespace std; // Yes!
32 #define ROM1 "RT3-1B.ROM"
33 #define ROM2 "RT3-2B.ROM"
34 #define ROM3 "RT3-3.ROM"
35 #define ROM4 "RT3-4.ROM"
36 #define ROM5 "RT1-5.ROM"
37 #define ROM6 "RT1-6.ROM"
38 #define ROM7 "RT1-7.ROM"
39 #define ROM8 "RT1-8.ROM"
40 #define ROM9 "RT1-9.ROM"
41 #define ROM10 "RT1-10.ROM"
42 #define ROM11 "RT1-11.ROM"
43 #define ROM12 "RT1-12.ROM"
44 #define ROM13 "RT1-13.ROM"
45 #define ROM14 "RT1-14.ROM"
46 #define ROM15 "RT1-15.ROM"
47 #define ROM16 "RT1-16.ROM"
48 #define ROM17 "RT1-17.ROM"
49 #define ROM18 "RT1-18.ROM"
50 #define ROM19 "RT3-19.ROM"
51 #define ROM20 "RT3-20.ROM"
52 #define ROM21 "RT1-21.ROM"
53 #define ROM22 "RT2-22.ROM"
54 #define PROM1 "RT1-1.BIN"
55 #define PROM2 "RT1-2.BIN"
56 #define PROM3 "RT1-3.BIN"
57 #define PROM4 "RT1-4.BIN"
58 #define PROM5 "RT1-5.BIN"
60 #define ROM1 "rt3-1b.9c"
61 #define ROM2 "rt3-2b.12c"
62 #define ROM3 "rt3-3.12d"
63 #define ROM4 "rt1-4.6b"
64 #define ROM5 "rt1-5.4r"
65 #define ROM6 "rt1-6.4s"
66 #define ROM7 "rt1-7.7r"
67 #define ROM8 "rt1-8.7s"
68 #define ROM9 "rt1-9.12h"
69 #define ROM10 "rt1-10.12k"
70 #define ROM11 "rt1-11.12l"
71 #define ROM12 "rt1-12.12m"
72 #define ROM13 "rt1-13.12p"
73 #define ROM14 "rt1-14.12r"
74 #define ROM15 "rt1-15.12t"
75 #define ROM16 "rt1-16.12u"
76 #define ROM17 "rt1-17.f1"
77 #define ROM18 "rt1-18.h1"
78 #define ROM19 "rt1-19.k1"
79 #define ROM20 "rt1-20.m1"
80 #define ROM21 "rt1-21.f3"
81 #define ROM22 "rt1-22.h3"
82 #define PROM1 "mb7124e.3r"
83 #define PROM2 "mb7116e.3s"
84 #define PROM3 "mb7138h.4v"
85 #define PROM4 "mb7138h.6v"
86 #define PROM5 "mb7112e.6u"
87 #define MCUROM "rt1-mcu.bin"
93 BYTE * gram, * grom; // Allocate RAM & ROM pointers
94 BYTE * gram1, * gram2, * grom1, * grom2; // Actual memory
95 BYTE * grom3, * grom4, * data_rom, * spr_rom, * voice_rom;
96 BYTE * chr_rom; // Character ROM pointer
100 bool trace = false; // ditto...
101 bool looking_at_rom = true; // true = R1, false = R2
102 DWORD banksw1, banksw2; // Bank switch addresses
103 WORD game_over_switch; // Game over delay
104 WORD dpc; // Debug pc reg...
105 bool show_scr = true; // Whether or not to show background
106 bool enable_cpu = true; // Whether or not to enable CPUs
107 bool irqGoA = true; // IRQ switch for CPU #1
108 bool irqGoB = true; // IRQ switch for CPU #2
110 WORD refresh = 0; // Crappy global screen stuff...
111 bool refresh2 = true;
113 DWORD psg_lens[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
115 DWORD voc_lens[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
118 DWORD fm_lens[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
121 fstream tr; // Tracelog hook
122 WORD pcx; // Where we at?
124 static char op_mat1[256] = {
125 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
126 0, 0, 5, 5, 0, 0, 4, 4, 0, 5, 8, 0, 8, 5, 6, 6,
127 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
128 7, 7, 7, 7, 6, 6, 6, 6, 0, 5, 5, 5, 8, 5, 5, 5,
129 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
130 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
131 7, 0, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7,
132 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
133 8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 3, 9, 0,
134 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
135 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
136 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
137 8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 0, 9, 0,
138 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
139 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
140 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
147 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
148 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
150 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0,
151 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
152 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 7,
153 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2,
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7,
157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 },
159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
161 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
163 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
164 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
166 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
167 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
168 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
169 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
170 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
175 static char mnemonics[256][6] = {
176 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
177 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
178 "PAGE1","PAGE2","NOP ","SYNC ","??? ","??? ","LBRA ","LBSR ",
179 "??? ","DAA ","ORCC ","??? ","ANDCC","SEX ","EXG ","TFR ",
180 "BRA ","BRN ","BHI ","BLS ","BHS ","BLO ","BNE ","BEQ ",
181 "BVC ","BVS ","BPL ","BMI ","BGE ","BLT ","BGT ","BLE ",
182 "LEAX ","LEAY ","LEAS ","LEAU ","PSHS ","PULS ","PSHU ","PULU ",
183 "??? ","RTS ","ABX ","RTI ","CWAI ","MUL ","RESET","SWI ",
184 "NEGA ","??? ","??? ","COMA ","LSRA ","??? ","RORA ","ASRA ",
185 "LSLA ","ROLA ","DECA ","??? ","INCA ","TSTA ","??? ","CLRA ",
186 "NEGB ","??? ","??? ","COMB ","LSRB ","??? ","RORB ","ASRB ",
187 "LSLB ","ROLB ","DECB ","??? ","INCB ","TSTB ","??? ","CLRB ",
188 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
189 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
190 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
191 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
192 "SUBA ","CMPA ","SCBA ","SUBD ","ANDA ","BITA ","LDA ","??? ",
193 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","BSR ","LDX ","??? ",
194 "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA ","STA ",
195 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","JSR ","LDX ","STX ",
196 "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA ","STA ",
197 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","JSR ","LDX ","STX ",
198 "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA ","STA ",
199 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","JSR ","LDX ","STX ",
200 "SUBB ","CMPB ","SCBB ","ADDD ","ANDB ","BITB ","LDB ","??? ",
201 "EORB ","ADCB ","ORB ","ADDB ","LDD ","??? ","LDU ","??? ",
202 "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB ","STB ",
203 "EORB ","ADCB ","ORB ","ADDB ","LDD ","STD ","LDU ","STU ",
204 "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB ","STB ",
205 "EORB ","ADCB ","ORB ","ADDB ","LDD ","STD ","LDU ","STU ",
206 "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB ","STB ",
207 "EORB ","ADCB ","ORB ","ADDB ","LDD ","STD ","LDU ","STU " },
208 mnemonics2[256][6] = {
209 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
210 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
211 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
212 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
213 "??? ","LBRN ","LBHI ","LBLS ","LBHS ","LBLO ","LBNE ","LBEQ ",
214 "LBVC ","LBVS ","LBPL ","LBMI ","LBGE ","LBLT ","LBGT ","LBLE ",
215 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
216 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","SWI2 ",
217 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
218 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
219 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
220 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
221 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
222 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
223 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
224 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
225 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
226 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","??? ",
227 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
228 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
229 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
230 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
231 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
232 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
233 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
234 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","??? ",
235 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
236 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS ",
237 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
238 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS ",
239 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
240 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS " },
241 mnemonics3[256][6] = {
242 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
243 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
244 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
245 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
246 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
247 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
248 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
249 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","SWI3 ",
250 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
251 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
252 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
253 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
254 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
255 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
256 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
257 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
258 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
259 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
260 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
261 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
262 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
263 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
264 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
265 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
266 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
267 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
268 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
269 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
270 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
271 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
272 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
273 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? " },
275 "D", "X", "Y", "U", "S", "PC", "??", "??",
276 "A", "B", "CC", "DP", "??", "??", "??", "??" },
277 iregs[4][2] = {"X", "Y", "U", "S" };
280 // Fetch a byte out of memory
284 // extern WORD sr, ur, xr, yr; // Needed for tracelog
288 b = (pcr < 0x8000 ? gram1[pcr] : grom1[pcr]);
295 // Fetch a word out of memory (little endian format)
299 WORD w = Fetch() << 8; w |= Fetch();
304 // Read a byte from memory (without touching PC. Not a Fetch!)
306 BYTE RdMem(WORD addr)
313 b = data_rom[banksw1 + (addr - 0x6000)]; // Get char data
324 // Write a byte to memory
326 void WrMem(WORD addr, BYTE b)
328 extern bool charbase; // Needed for screen. Extern it in it??
329 //extern WORD sr, ur, xr, yr; // Needed for tracelog
331 /* if ((addr>0x40FF) && (addr<0x4390))
333 tr << hex << addr << ":" << (int)b;
334 //for(int i=0; i<32; i++)
336 // if (gram1[0x4400+i]<0x10) tr << "0";
337 // tr << hex << (WORD)gram1[0x4400+i] << " ";
343 SpawnSound(GAMESOUND, gram1[0x6200], 0); // Do voice chan 1
345 SpawnSound(GAMESOUND, gram1[0x6600], 1); // Do voice chan 2
347 banksw1 = (DWORD)b << 13; // Set char data bankswitch base address
348 if (addr > 0x4284 && addr < 0x42A5 && b)
349 SpawnSound(PSGSOUND, addr - 0x4285); // Do PSG sound on chans 2, 3
352 SpawnSound(FMSOUND, b); // Do FM sound on channel 4
354 game_over_switch = 240; // Set game over delay...
356 if (addr < 0x423D || addr > 0x425C) // Protect writes to DSWs
359 charbase = false; // Char banksw1
361 charbase = true; // Char banksw2
362 if (addr == 0x8400) // Frame go strobe? VBlank acknowledge?
364 if (refresh++ == 1) // 30 Hz...
366 BlitChar(screen, chr_rom, gram1);
367 refresh = (refresh2 ? 1 : 0); // 60/30 Hz...
369 // irqGoA = true; // Will this work??? no...
370 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
375 // Fetch a byte out of memory (2nd processor)
379 // extern WORD sr, ur, xr, yr; // Needed for tracelog
386 b = gram1[pcrB+0x4000];
387 if ((pcrB>0x1FFF) && (pcrB<0x6000))
388 b = gram1[pcrB-0x2000];
400 // Fetch a word out of memory (little endian format) (2nd processor)
404 WORD w = FetchB() << 8; w |= FetchB();
409 // Read a byte from memory (without touching PC. Not a Fetch!) (2nd processor)
411 BYTE RdMemB(WORD addr)
413 // extern WORD cpu2.s, cpu2.u, cpu2.x, cpu2.y; // Needed for tracelog
419 b = gram1[addr + 0x4000];
420 if (addr > 0x1FFF && addr < 0x6000)
421 b = gram1[addr - 0x2000];
423 b = grom3[banksw2 + (addr - 0x6000)]; // Correct?
428 /* if ((addr>0x3FFF) && (addr<0x4400)) tr << "R-" << hex << pcx << ": "
430 << (int)looking_at_rom
432 << "] XR:" << xr << " YR:" << yr
433 << " SR:" << sr << " UR:" << ur
439 // Write a byte to memory (2nd processor)
441 void WrMemB(WORD addr, BYTE b)
443 extern bool charbase;
444 //extern WORD sr, ur, xr, yr; // Needed for tracelog
446 /* if ((addr>0x00FF) && (addr<0x0390))
448 tr << hex << addr << ":" << (int)b;
449 //for(int i=0; i<32; i++)
451 // if (gram1[0x4400+i]<0x10) tr << "0";
452 // tr << hex << (WORD)gram1[0x4400+i] << " ";
458 // irqGoB = true; // Will it work??? no...
459 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
461 SpawnSound(GAMESOUND, gram1[0x6200], 0); // Do voice chan 1
463 SpawnSound(GAMESOUND, gram1[0x6600], 1); // Do voice chan 2
464 if (addr > 0x0284 && addr < 0x02A5 && b)
465 SpawnSound(PSGSOUND, addr - 0x0285); // Do PSG sound on chans 2, 3
467 banksw2 = (DWORD)(b & 0x03) << 13; // Set sprite data bank switch
470 SpawnSound(FMSOUND, b); // Do FM sound on chan 4
472 game_over_switch = 240; // Set game over delay...
474 if (addr < 0x023D || addr > 0x025C) // Protect writes against DSWs
477 gram1[addr + 0x4000] = b;
478 if (addr > 0x1FFF && addr < 0x6000)
479 gram1[addr - 0x2000] = b;
486 // Display bytes in mem in hex
488 void DisplayBytes(WORD src, unsigned long dst)
493 printf("%04X: ", src);
494 cnt = 0; // Init counter...
495 if (src > dst) dst += 0x10000; // That should fix the FFFF bug...
496 for(i=src; i<dst; i++)
498 printf("%02X ", (BYTE)(looking_at_rom ? RdMem(i) : RdMemB(i)));
499 cnt++; // Bump counter...
501 for(i=cnt; i<5; i++) // Pad the leftover spaces...
508 BYTE Fetch(void) { return 0; }
509 WORD FetchW(void) { return 0; }
510 BYTE FetchB(void) { return 0; }
511 WORD FetchWB(void) { return 0; }
514 // Decode a 6809 instruction at 'addr'
518 BYTE (* DFetch)(); // Decode Fetch() pointer...
519 WORD (* DFetchW)(); // Decode FetchW() pointer...
520 DFetch = (looking_at_rom ? Fetch : FetchB);
521 DFetchW = (looking_at_rom ? FetchW : FetchWB);
523 /* extern*/ WORD pcr, pcrB; // Pull in 'pcr' from '6809.cpp'
524 WORD pc_save = pcr, pcB_save = pcrB;
525 pcr = dpc; pcrB = dpc;
526 BYTE opcode = DFetch(); // Get the opcode ('fetch' cycle)
527 BYTE opcode2, operand;
529 BYTE admode = op_mat1[opcode]; // addressing mode
530 char outbuf[80], mnem[6], tmp[30];
532 strcpy(mnem, mnemonics[opcode]); // Copy page 1 opcode
533 if (opcode == 0x10) // Extended opcode?
535 opcode2 = DFetch(); // Then get next byte
536 admode = op_mat2[opcode2]; // And use it as index into 'op_mat2'
537 strcpy(mnem, mnemonics2[opcode2]); // Overwrite mnemonic
539 if (opcode == 0x11) // Same as above...
542 admode = op_mat3[opcode2];
543 strcpy(mnem, mnemonics3[opcode2]); // Overwrite mnemonic
545 switch(admode) // Decode it...
548 { sprintf(outbuf, "???"); break; }
550 { operand = DFetch(); // Get ZP address
551 sprintf(outbuf, "%s $%02X", mnem, operand);
554 { loperand = DFetchW(); // Get ABS address
555 sprintf(outbuf, "%s $%04X", mnem, loperand);
558 { operand = DFetch(); // Get offset
559 WORD tmpc = (looking_at_rom ? pcr : pcrB);
560 sprintf(outbuf, "%s $%04X", mnem, tmpc+(SWORD)(SBYTE)operand);
562 case 4: // Long Relative
563 { loperand = DFetchW(); // Get long offset
564 WORD tmpc = (looking_at_rom ? pcr : pcrB);
565 sprintf(outbuf, "%s $%04X", mnem, tmpc+(SWORD)loperand);
568 { sprintf(outbuf, "%s ", mnem);
570 case 6: // Txfr/exchg/push/pull
571 { operand = DFetch(); // Get txfr/exg/push/pull byte
572 if ((opcode == 0x1E) || (opcode == 0x1F)) // Is it TXF/EXG?
574 sprintf(tmp, "%s,%s", tregs[operand>>4], tregs[operand&0x0F]);
579 if (operand&0x01) strcat(tmp, "CC ");
580 if (operand&0x02) strcat(tmp, "A ");
581 if (operand&0x04) strcat(tmp, "B ");
582 if (operand&0x08) strcat(tmp, "DP ");
583 if (operand&0x10) strcat(tmp, "X ");
584 if (operand&0x20) strcat(tmp, "Y ");
585 if (operand&0x40) (((opcode==0x34)||(opcode==0x35))
586 ? strcat(tmp, "U ") : strcat(tmp, "S "));
587 if (operand&0x80) strcat(tmp, "PC");
589 sprintf(outbuf, "%s %s", mnem, tmp);
591 case 7: // Indexed (the tough one!)
592 { operand = DFetch(); // Get IDX byte
593 BYTE reg = ((operand & 0x60) >> 5), idxind = ((operand & 0x10) >> 4),
594 lo_nyb = (operand & 0x0F), boff;
598 if (!(operand & 0x80)) // Hi bit set? Then decode 4 bit offset
600 sprintf(tmp, "(%d),%s", (idxind ? -(16-lo_nyb) : lo_nyb),
603 else // Add the ($nnnn,R) code dude...
609 case 1: sprintf(tmp, "(,%s++)", iregs[reg]); break;
610 case 3: sprintf(tmp, "(,--%s)", iregs[reg]); break;
611 case 4: sprintf(tmp, "(,%s)", iregs[reg]); break;
612 case 5: sprintf(tmp, "(B,%s)", iregs[reg]); break;
613 case 6: sprintf(tmp, "(A,%s)", iregs[reg]); break;
615 { boff = DFetch(); sprintf(tmp, "($%02X,%s)", boff,
616 iregs[reg]); break; }
618 { woff = DFetchW(); sprintf(tmp, "($%04X,%s)", woff,
619 iregs[reg]); break; }
620 case 11: sprintf(tmp, "(D,%s)", iregs[reg]); break;
622 { boff = DFetch(); sprintf(tmp, "($%02X,PC)", boff); break; }
624 { woff = DFetchW(); sprintf(tmp, "($%04X,PC)", woff); break; }
626 { woff = DFetchW(); sprintf(tmp, "[$%04X]", woff); break; }
627 default: strcpy(tmp, "??");
634 case 0: sprintf(tmp, ",%s+", iregs[reg]); break;
635 case 1: sprintf(tmp, ",%s++", iregs[reg]); break;
636 case 2: sprintf(tmp, ",-%s", iregs[reg]); break;
637 case 3: sprintf(tmp, ",--%s", iregs[reg]); break;
638 case 4: sprintf(tmp, ",%s", iregs[reg]); break;
639 case 5: sprintf(tmp, "(B),%s", iregs[reg]); break;
640 case 6: sprintf(tmp, "(A),%s", iregs[reg]); break;
642 { boff = DFetch(); sprintf(tmp, "($%02X),%s", boff,
643 iregs[reg]); break; }
645 { woff = DFetchW(); sprintf(tmp, "($%04X),%s", woff,
646 iregs[reg]); break; }
647 case 11: sprintf(tmp, "(D),%s", iregs[reg]); break;
649 { boff = DFetch(); sprintf(tmp, "($%02X),PC", boff); break; }
651 { woff = DFetchW(); sprintf(tmp, "($%04X),PC", woff); break; }
652 default: strcpy(tmp, "??");
656 sprintf(outbuf, "%s %s", mnem, tmp);
659 { operand = DFetch(); // Get IMM byte
660 sprintf(outbuf, "%s #$%02X", mnem, operand);
662 case 9: // Long Immediate
663 { loperand = DFetchW(); // Get IMM word
664 sprintf(outbuf, "%s #$%04X", mnem, loperand);
667 DisplayBytes(dpc, (looking_at_rom ? pcr : pcrB)); // Show bytes
668 cout << outbuf << endl; // display opcode & addressing, etc
669 dpc = (looking_at_rom ? pcr : pcrB); // Advance debug PC
670 pcr = pc_save; pcrB = pcB_save; // Restore PCs
674 // Convert hex to dec
679 int len = strlen(str);
681 for(int i=0; i<len; i++)
683 if (str[i]>='0' && str[i]<='9')
685 value = (value<<4) | (unsigned)(str[i]-'0');
687 if (str[i]>='a' && str[i]<='f')
689 value = (value<<4) | (unsigned)(str[i]-'a')+10;
691 if (str[i]>='A' && str[i]<='F')
693 value = (value<<4) | (unsigned)(str[i]-'A')+10;
700 // Load 32K file into ROM image space
702 bool Load32KImg(char * filename, WORD address)
707 ff.open(filename, ios::binary | ios::in); // Open 'da file...
710 for(long i=0; i<32768; i++) // Read it in...
713 grom[address+i] = ch;
715 ff.close(); // Close 'da file...
721 // Generic Load file into image space
722 // (No error checking performed! Responsibility of caller!)
724 bool LoadImg(char * filename, BYTE * mem, DWORD address, DWORD length)
730 strcpy(path, "./ROMs/");
731 strcat(path, filename);
732 // ff.open(filename, ios::binary | ios::in); // Open 'da file...
733 ff.open(path, ios::binary | ios::in); // Open 'da file...
736 for(DWORD i=0; i<length; i++) // Read it in...
741 ff.close(); // Close 'da file...
749 bool ReadColorPROMs(void)
754 extern BYTE palette[768]; // Screen physical palette
755 extern BYTE ccolor[256][8]; // Character color PROM values
756 extern BYTE scolor[128][16]; // Sprite color PROM values
758 ff1.open("./ROMs/"PROM3, ios::binary|ios::in);
761 for(int i=0; i<256; i++) // Load char pallete with PROM values
763 for(int j=0; j<8; j++)
766 ccolor[i][j] = (BYTE)ch;
771 ff1.open("./ROMs/"PROM4, ios::binary|ios::in);
774 for(int i=0; i<128; i++) // Load sprite pallete with PROM values
776 for(int j=0; j<16; j++)
779 scolor[i][j] = (BYTE)ch;
785 ff1.open("./ROMs/"PROM1, ios::binary|ios::in);
786 ff2.open("./ROMs/"PROM2, ios::binary|ios::in);
787 if (ff1) // If open was successful...
789 for(int i=0; i<768; i+=3)
792 palette[i] = (BYTE)(ch&0x0F);
793 palette[i+1] = (BYTE)(ch>>4);
795 palette[i+2] = (BYTE)ch;
798 // Do palette stretching here... I.e. add 0 to hinyb 0, 1 to hinyb 1, etc.
800 for(int i=0; i<768; i++)
801 palette[i] = ((palette[i]<<4)&0xF0) | (palette[i]&0x0F);
812 bool UnpackFonts(void)
818 f1.open("./ROMs/"ROM7, ios::binary | ios::in);
819 f2.open("./ROMs/"ROM8, ios::binary | ios::in);
820 if ((!f1) || (!f2)) return false; // Return if not found...
821 for(long i=0; i<0x40000; i+=64)
823 for(int j=0; j<64; j+=8)
825 f1.get(b1); f1.get(b2); f2.get(b3);
826 b3 ^= 0xFF; // Invert top data...
827 chr_rom[i+j] = ((b3 & 0x80) >> 5) | ((b1 & 0x80) >> 6) | ((b1 & 0x08) >> 3);
828 chr_rom[i+j+1] = ((b3 & 0x40) >> 4) | ((b1 & 0x40) >> 5) | ((b1 & 0x04) >> 2);
829 chr_rom[i+j+2] = ((b3 & 0x20) >> 3) | ((b1 & 0x20) >> 4) | ((b1 & 0x02) >> 1);
830 chr_rom[i+j+3] = ((b3 & 0x10) >> 2) | ((b1 & 0x10) >> 3) | (b1 & 0x01);
831 chr_rom[i+j+4] = ((b3 & 0x08) >> 1) | ((b2 & 0x80) >> 6) | ((b2 & 0x08) >> 3);
832 chr_rom[i+j+5] = (b3 & 0x04) | ((b2 & 0x40) >> 5) | ((b2 & 0x04) >> 2);
833 chr_rom[i+j+6] = ((b3 & 0x02) << 1) | ((b2 & 0x20) >> 4) | ((b2 & 0x02) >> 1);
834 chr_rom[i+j+7] = ((b3 & 0x01) << 2) | ((b2 & 0x10) >> 3) | (b2 & 0x01);
840 f1.open("./ROMs/"ROM5, ios::binary | ios::in);
841 f2.open("./ROMs/"ROM6, ios::binary | ios::in);
842 for(long i=0x40000; i<0x60000; i+=64)
844 for(int j=0; j<64; j+=8)
846 f1.get(b1); f1.get(b2); f2.get(b3);
847 b3 ^= 0xFF; // Invert top data
848 chr_rom[i+j] = ((b3 & 0x80) >> 5) | ((b1 & 0x80) >> 6) | ((b1 & 0x08) >> 3);
849 chr_rom[i+j+1] = ((b3 & 0x40) >> 4) | ((b1 & 0x40) >> 5) | ((b1 & 0x04) >> 2);
850 chr_rom[i+j+2] = ((b3 & 0x20) >> 3) | ((b1 & 0x20) >> 4) | ((b1 & 0x02) >> 1);
851 chr_rom[i+j+3] = ((b3 & 0x10) >> 2) | ((b1 & 0x10) >> 3) | (b1 & 0x01);
852 chr_rom[i+j+4] = ((b3 & 0x08) >> 1) | ((b2 & 0x80) >> 6) | ((b2 & 0x08) >> 3);
853 chr_rom[i+j+5] = (b3 & 0x04) | ((b2 & 0x40) >> 5) | ((b2 & 0x04) >> 2);
854 chr_rom[i+j+6] = ((b3 & 0x02) << 1) | ((b2 & 0x20) >> 4) | ((b2 & 0x02) >> 1);
855 chr_rom[i+j+7] = ((b3 & 0x01) << 2) | ((b2 & 0x10) >> 3) | (b2 & 0x01);
860 return true; // Made it!
864 // Get length of sample from WAV format
866 DWORD GetWAVLength(fstream &file)
871 file.ignore(16); // Skip header BS
873 for(int i=0; i<2; i++)
875 file.get(ch); len = (int)(BYTE)ch;
876 file.get(ch); len |= (int)(BYTE)ch << 8;
877 file.get(ch); len |= (int)(BYTE)ch << 16;
878 file.get(ch); len |= (int)(BYTE)ch << 24;
880 file.ignore(len + 4); // Skip intermediate data
883 file.get(ch); len = (int)(BYTE)ch; // & finally get length of data
884 file.get(ch); len |= (int)(BYTE)ch << 8;
885 file.get(ch); len |= (int)(BYTE)ch << 16;
886 file.get(ch); len |= (int)(BYTE)ch << 24;
892 // Load PSG samples from disk
900 for(int i=0; i<16; i++)
904 psg_adrs[i] = NULL; // Zero out pointer
905 sprintf(file, "./sounds/psg%i.wav", i); // Create filename
907 fp.open(file, ios::binary | ios::in); // Attempt to open it...
911 len = GetWAVLength(fp); // Get WAV data length...
913 psg_adrs[i] = new BYTE[len]; // Attempt to allocate space...
915 if (psg_adrs[i] != NULL)
917 for(int j=0; j<(signed)len; j++)
920 psg_adrs[i][j] = ch; // & load it in...
924 cout << "Found sample file: " << file << " [Length: " << dec << len << "]" << endl;
933 // Load FM samples from disk
941 for(int i=0; i<14; i++)
945 fm_adrs[i] = NULL; // Zero out pointer
946 sprintf(file, "./sounds/fm%i.wav", i); // Create filename
948 fp.open(file, ios::binary | ios::in); // Attempt to open it...
952 len = GetWAVLength(fp); // Get WAV length...
954 fm_adrs[i] = new BYTE[len]; // Attempt to allocate space...
956 if (fm_adrs[i] != NULL)
958 for(int j=0; j<(signed)len; j++)
961 fm_adrs[i][j] = ch; // & load it in...
965 cout << "Found sample file: " << file << " [Length: " << dec << len
977 int main(int argc, char * argv[])
979 InitLog("thunder.log");
981 /* extern WORD cpu1.pc, cpu1.s, cpu1.u, cpu1.x, cpu1.y; // Pull in vars from '6809.cpp'
982 extern BYTE cpu1.a, cpu1.b, cpu1.cc, cpu1.dp;
985 extern WORD cpu2.pc, cpu2.s, cpu2.u, cpu2.x, cpu2.y; // Pull in vars from '6809B.cpp'
986 extern BYTE cpu2.a, cpu2.b, cpu2.cc, cpu2.dp;
988 extern bool illegalB;
989 extern void (* exec_op0[256])(); // Array of page zero opcode functions...
990 extern void (* exec_op1[256])(); // Array of page one opcode functions...
991 extern void (* exec_op2[256])(); // Array of page two opcode functions...
992 extern void (* exec_op0B[256])(); // Array of page zero opcode functions...
993 extern void (* exec_op1B[256])(); // Array of page one opcode functions...
994 extern void (* exec_op2B[256])(); // Array of page two opcode functions...*/
995 extern bool charbase; // From 'SCREEN.CPP'
996 // extern unsigned int vesa_memptr;
1000 fstream ff; // Declare fstream without file hooks...
1001 bool brk = false, brk2 = false; // Breakpoint set flag
1002 WORD brkpnt, brkpnt2; // Where the breakpoint is...
1003 bool running; // CPU running state flag...
1004 bool self_test = false; // Self-test switch
1005 bool scr_type = false; // false=chars, true=pixels
1006 WORD debounce = 0; // Key de-bounce counter
1007 WORD fire_debounce = 0; // Fire button debounce counter
1008 // bool refresh2 = true; // Default to 60 Hz...
1009 BYTE x; // General placeholder...
1010 bool active = true; // Program running flag
1012 // SDL_Surface * screen = NULL; // SDL screen pointer
1013 SDL_Event event; // SDL "event"
1014 // int keyPressed; // SDL key pressed...
1015 BYTE keys[256]; // Keyboard "switch-like" buffer
1016 extern BYTE palette[768]; // Screen physical palette
1017 DWORD ticks, oldTicks;
1019 // tr.open("exe.log", ios::binary | ios::out); // Tracelog
1021 cout << endl << "THUNDER beta "THUNDER_BETA_VERSION" ";
1022 cout << "by Jimmy Hamm <jlhamm@acm.org>" << endl;
1023 cout << "Serial #20030313 / Prerelease" << endl;
1024 cout << "(C) 2003 Underground Software" << endl << endl;
1026 cout << "This emulator is freeware. If you paid for it you were RIPPED OFF"
1029 cout << "Initializing SDL..." << endl;
1031 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
1033 cout << "Couldn't initialize SDL: " << SDL_GetError() << endl;
1037 SDL_WM_SetCaption("Thunder Beta 6", "Thunder");
1039 cout << "Allocating memory..." << endl;
1040 //Does this anyway... set_new_handler(0); // Make 'new' return NULL on failure...
1041 gram1 = new BYTE[0x10000];
1042 if (gram1 == NULL) { cout << "Could not allocate RAM space #1!" << endl
1043 << "Aborting!" << endl; return -1; }
1044 grom1 = new BYTE[0x10000];
1045 if (grom1 == NULL) { cout << "Could not allocate ROM space #1!" << endl
1046 << "Aborting!" << endl; return -1; }
1047 gram2 = new BYTE[0x10000];
1048 if (gram2 == NULL) { cout << "Could not allocate RAM space #2!" << endl
1049 << "Aborting!" << endl; return -1; }
1050 grom2 = new BYTE[0x10000];
1051 if (grom2 == NULL) { cout << "Could not allocate ROM space #2!" << endl
1052 << "Aborting!" << endl; return -1; }
1053 chr_rom = new BYTE[0x60000];
1054 if (chr_rom == NULL) { cout << "Could not allocate character RAM!" << endl
1055 << "Aborting!" << endl; return -1; }
1056 grom3 = new BYTE[0x8000];
1057 if (grom3 == NULL) { cout << "Could not allocate ROM space #4!" << endl
1058 << "Aborting!" << endl; return -1; }
1059 grom4 = new BYTE[0x8000];
1060 if (grom4 == NULL) { cout << "Could not allocate ROM space #5!" << endl
1061 << "Aborting!" << endl; return -1; }
1062 data_rom = new BYTE[0x40000];
1063 if (data_rom == NULL) { cout << "Could not allocate ROM level data!" << endl
1064 << "Aborting!" << endl; return -1; }
1065 spr_rom = new BYTE[0x80000];
1066 if (spr_rom == NULL) { cout << "Could not allocate ROM sprite data!" << endl
1067 << "Aborting!" << endl; return -1; }
1068 voice_rom = new BYTE[0x20000];
1069 if (voice_rom == NULL) { cout << "Could not allocate ROM voice data!" << endl
1070 << "Aborting!" << endl; return -1; }
1072 gram = gram1; grom = grom1; // Needed only for debugger
1074 for(long i=0; i<0x10000; i++)
1076 gram[i] = 0; grom[i] = 0; // Zero out memory
1077 gram2[i] = 0; grom2[i] = 0;
1079 game_over_switch = 0; // Init game over delay
1080 // cpu1.a = 0; cpu1.b = 0; cpu1.cc = 0; cpu1.dp = 0; cpu1.x = 0; cpu1.y = 0; cpu1.s = 0; ur = 0; cpu1.pc = 0;
1082 cout << "Loading ROMs..." << endl;
1083 // LoadCMOS(); // Load CMOS at $CC00-$CFFF
1084 if (!ReadColorPROMs()) // Load virtual PROMs
1085 { cout << "Could not open PROM files!" << endl; return -1; }
1087 if (!LoadImg(ROM1, grom1, 0x8000, 0x8000)) // Load $8000-$FFFF 1st ROM
1088 { cout << "Could not open file '" << ROM1 << "'!" << endl; return -1; }
1090 if (!LoadImg(ROM2, grom2, 0x8000, 0x8000)) // Load $8000-$FFFF 2nd ROM
1091 { cout << "Could not open file '" << ROM2 << "'!" << endl; return -1; }
1093 if (!LoadImg(ROM3, grom3, 0, 0x8000)) // Load 3rd ROM into its own space
1094 { cout << "Could not open file '" << ROM3 << "'!" << endl; return -1; }
1096 if (!LoadImg(ROM4, grom4, 0, 0x8000)) // Load 4rd ROM into its own space
1097 { cout << "Could not open file '" << ROM4 << "'!" << endl; return -1; }
1099 if (!LoadImg(ROM17, data_rom, 0, 0x10000)) // Load 17th ROM
1100 { cout << "Could not open file '" << ROM17 << "'!" << endl; return -1; }
1102 if (!LoadImg(ROM18, data_rom, 0x10000, 0x10000)) // Load 18th ROM
1103 { cout << "Could not open file '" << ROM18 << "'!" << endl; return -1; }
1105 if (!LoadImg(ROM19, data_rom, 0x20000, 0x10000)) // Load 19th ROM
1106 { cout << "Could not open file '" << ROM19 << "'!" << endl; return -1; }
1108 if (!LoadImg(ROM20, data_rom, 0x30000, 0x10000)) // Load 20th ROM
1109 { cout << "Could not open file '" << ROM20 << "'!" << endl; return -1; }
1111 if (!LoadImg(ROM9, spr_rom, 0, 0x10000)) // Load 9th ROM
1112 { cout << "Could not open file '" << ROM9 << "'!" << endl; return -1; }
1114 if (!LoadImg(ROM10, spr_rom, 0x10000, 0x10000)) // Load 10th ROM
1115 { cout << "Could not open file '" << ROM10 << "'!" << endl; return -1; }
1117 if (!LoadImg(ROM11, spr_rom, 0x20000, 0x10000)) // Load 11th ROM
1118 { cout << "Could not open file '" << ROM11 << "'!" << endl; return -1; }
1120 if (!LoadImg(ROM12, spr_rom, 0x30000, 0x10000)) // Load 12th ROM
1121 { cout << "Could not open file '" << ROM12 << "'!" << endl; return -1; }
1123 if (!LoadImg(ROM13, spr_rom, 0x40000, 0x10000)) // Load 13th ROM
1124 { cout << "Could not open file '" << ROM13 << "'!" << endl; return -1; }
1126 if (!LoadImg(ROM14, spr_rom, 0x50000, 0x10000)) // Load 14th ROM
1127 { cout << "Could not open file '" << ROM14 << "'!" << endl; return -1; }
1129 if (!LoadImg(ROM15, spr_rom, 0x60000, 0x10000)) // Load 15th ROM
1130 { cout << "Could not open file '" << ROM15 << "'!" << endl; return -1; }
1132 if (!LoadImg(ROM16, spr_rom, 0x70000, 0x10000)) // Load 16th ROM
1133 { cout << "Could not open file '" << ROM16 << "'!" << endl; return -1; }
1135 if (!LoadImg(ROM21, voice_rom, 0, 0x10000)) // Load 21st ROM
1136 { cout << "Could not open file '" << ROM21 << "'!" << endl; return -1; }
1138 if (!LoadImg(ROM22, voice_rom, 0x10000, 0x10000)) // Load 22nd ROM
1139 { cout << "Could not open file '" << ROM22 << "'!" << endl; return -1; }
1141 if (!UnpackFonts()) // Load 5, 6, 7, 8th ROMs
1143 cout << "Could not open font files!" << endl;
1147 LoadPSGs(); // Load samples if they're there...
1150 // Quick 'n' Dirty voice dump (sound 0x0E)
1151 /* DWORD adc = (voice_rom[26]<<8) | voice_rom[27];
1152 bool doneWitIt = false;
1156 if (voice_rom[adc] < 0x10) tr << "0";
1157 tr << hex << (int)voice_rom[adc] << " ";
1158 if (crh++ > 24) { crh = 0; tr << endl; }
1159 if ((voice_rom[adc] == 0xFF) && (voice_rom[adc-1] != 0x00))
1164 // Set up V6809 execution contexts
1166 memset(&cpu1, sizeof(V6809REGS), 0);
1169 cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
1171 memset(&cpu2, sizeof(V6809REGS), 0);
1172 cpu2.RdMem = RdMemB;
1173 cpu2.WrMem = WrMemB;
1174 cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
1176 bool firstTime = true; // kludge...
1178 WriteLog("About to go to the main loop...\n");
1184 firstTime = false; // crappy kludge...
1191 if (lbuff[0] == 'd')
1198 printf("%04X: ", dpc);
1199 WORD pc_save = cpu1.pc, pcB_save = cpu2.pc;
1200 cpu1.pc = dpc; cpu2.pc = dpc;
1201 for(int i=0; i<16; i++)
1202 printf("%02X ", (looking_at_rom ? Fetch() : FetchB()));
1204 cpu1.pc = dpc; cpu2.pc = dpc;
1205 for(int i=0; i<16; i++)
1207 BYTE a = (looking_at_rom ? Fetch() : FetchB());
1208 if (a<10) cout << (char)(a+48);
1209 if ((a>9) && (a<37)) cout << (char)(a+55);
1210 if (a>36) cout << ".";
1213 dpc = (looking_at_rom ? cpu1.pc : cpu2.pc);
1214 cpu1.pc = pc_save; cpu2.pc = pcB_save;
1216 else if (lbuff[0] == 'e')
1223 printf("%04X: ", dpc);
1224 for(int i=0; i<16; i++) printf("%02X ", (BYTE)gram[dpc++]);
1227 else if (lbuff[0] == 'l')
1234 for(int i=0; i<23; i++)
1237 else if (lbuff[0] == 't')
1248 Execute6809(&cpu1, 1);
1250 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1251 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1252 cout << " iclock=" << cpu1.clock << endl;
1258 Execute6809(&cpu2, 1);
1260 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1261 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1262 cout << " iclock=" << cpu2.clock << endl;
1265 else if ((lbuff[0] == 'r') || (lbuff[0] == 'c')) // Run/continue...
1267 WriteLog("Executing 'run' command...\n");
1269 running = true; // Set running status...
1271 SetRefreshRate(refresh2); // Tell GUI our refresh rate
1272 //for(WORD i=0; i<0x8000; i++) gram2[i] = grom3[i]; //Temp
1274 if (lbuff[0] == 'r') // If run, then reset CPUs
1276 WriteLog("Executing secondary 'run' command...\n");
1277 gram1[0x4182] = 0xA6; // Temp kludge
1278 gram1[0x4184] = 0xA6;
1279 gram1[0x4183] = 0x00; // More of the same
1280 gram1[0x4185] = 0x00;
1281 banksw1 = 0; // Will this work?
1283 // iclock = 0; // Reset instr clock #1...
1284 InitGUI(); // Reset # of coins
1286 /* cpu1.pc = ((grom1[0xFFFE]<<8) | grom1[0xFFFF]); // Reset 6809 #1
1289 lbuff[0] = 32; cpu1.pc = htod(lbuff);
1291 else cpu1.cc = 0xFF; // Set CC register
1293 cpu2.pc = ((grom2[0xFFFE]<<8) | grom2[0xFFFF]); // Reset 6809 #2
1294 cpu2.cc = 0xFF; // Set CC register
1295 while(iclock < 8000) // was 17000, 20000, 5000
1297 Execute6809(&cpu1, 1); Execute6809(&cpu2, 1);
1299 WriteLog("--> CPU clock #1: %u\n", cpu1.clock);
1300 // Will *this* help video sync?
1301 while (cpu1.clock < 8000) // was 17000, 20000, 5000
1303 Execute6809(&cpu1, 1);
1304 Execute6809(&cpu2, 1);
1308 WriteLog("About to set up screen...\n");
1309 // if (!SetVESA2()) running = false; // Set up screen
1310 // Set up screen (windowed)
1311 screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); //video_bpp, videoflags);
1314 cout << "Failed to initialize screen!" << endl;
1318 SDL_Color colors[256];
1319 for(int i=0; i<256; i++)
1321 colors[i].r = palette[i*3+0];
1322 colors[i].g = palette[i*3+1];
1323 colors[i].b = palette[i*3+2];
1325 SDL_SetPalette(screen, SDL_LOGPAL|SDL_PHYSPAL, colors, 0, 256);
1327 for(int i=0; i<256; i++)
1328 keys[i] = 0; // Clear keyboard buffer...
1330 oldTicks = SDL_GetTicks();
1332 // This crap SHOULD be in sound.cpp (not yet created)...
1333 SDL_AudioSpec desired, obtained;
1334 desired.freq = 22050;
1335 desired.format = AUDIO_U8;
1336 desired.channels = 1;
1337 desired.samples = 600;
1338 desired.callback = SoundFunc;
1339 desired.userdata = NULL;
1340 // Also, should check to see if it got the hardware it needed, correct sample size, etc.
1341 if (SDL_OpenAudio(&desired, &obtained) < 0)
1343 cout << "Couldn't open audio: " << SDL_GetError() << endl;
1346 SDL_PauseAudio(0); // Get that audio going!
1350 HandleGUIDebounce(); // Debounce GUI keys
1351 if (game_over_switch)
1353 game_over_switch--; // Countdown...
1354 if (game_over_switch == 0)
1355 gram1[0x4380] = 0; // Kill music!
1357 //gram1[0x423D] = self_test; // Reset DSW1-1
1358 gram1[0x4268] = 0; // Reset Video test
1359 gram1[0x427A] = 0; gram1[0x427C] = 0;
1360 gram1[0x427B] = 0; gram1[0x427D] = 0;
1361 gram1[0x427E] = 0; gram1[0x427F] = 0;
1362 gram1[0x4280] = 0; gram1[0x4281] = 0;
1363 gram1[0x4276] = 0; gram1[0x426A] = 0;
1364 gram1[0x4278] = 0; gram1[0x426C] = 0;
1365 gram1[0x4262] = 0; gram1[0x4260] = 0;
1366 //gram1[0x4247] = 0;
1368 // SDL key handling...
1370 // keyPressed = 0; // Reset keypress
1371 while (SDL_PollEvent(&event) != 0) // Bleed out all pending key events...
1373 if (event.type == SDL_KEYDOWN)
1374 keys[event.key.keysym.scancode] = 1;
1375 if (event.type == SDL_KEYUP)
1376 keys[event.key.keysym.scancode] = 0;
1381 running = false; // ESC to exit...
1384 debounce--; // Debounce toggle keys...
1389 self_test = !self_test; // Self-test (F1-toggle)
1390 debounce = 10; // Key debounce value...
1394 gram1[0x4268] = 1; // Video test (F2)
1395 debounce = 10; // Key debounce value...
1399 scr_type = !scr_type; // Toggle screen (F12)
1400 debounce = 10; // Key debounce value...
1404 show_scr = !show_scr; // Toggle bkgrnd (F3)
1409 enable_cpu = !enable_cpu; // Toggle CPUs (F6)
1414 refresh2 = !refresh2; // Toggle 30/60Hz (F5)
1415 SetRefreshRate(refresh2); // Inform GUI of refresh
1420 debounce = 10; // Key debounce value...
1422 if (keys[0x3E]) // Do PCX snapshot (F4)
1424 SpawnSound(USERSOUND, SCAMERA);
1428 if (keys[0x0F]) // Tab active/deactivate GUI
1437 //if (keys[0x3E]) gram1[0x4247] = 1; // Screen hold DS (F4)
1438 if (keys[77+128]) // Right arrow
1441 SelectRight(); // If GUI active...
1444 if (!keys[75+128]) // Disallow opposite directions @ same time
1445 gram1[0x427F] = 1; // Stick right
1451 SelectLeft(); // If GUI active...
1454 if (!keys[77+128]) // Disallow opposite directions@same time
1455 gram1[0x4281] = 1; // Left arrow
1461 SelectUp(); // If GUI active...
1464 if (!keys[80+128]) // Disallow opposite directions@same time
1465 gram1[0x427B] = 1; // Up arrow
1471 SelectDown(); // If GUI active...
1474 if (!keys[72+128]) // Disallow opposite directions@same time
1475 gram1[0x427D] = 1; // Down arrow
1478 if (keys[28]) // Return
1480 BYTE retval = UserSelectedSomething();
1483 if (retval == REFRESH)
1485 refresh2 = !refresh2;
1486 SetRefreshRate(refresh2);
1490 gram1[0x427A] = 1; // (1)
1492 gram1[0x427C] = 1; // (2)
1494 gram1[0x427E] = 1; // (3)
1496 gram1[0x4280] = 1; // (5)
1497 if (keys[0x10]|keys[29])
1498 gram1[0x4276] = 1; // (Q) Jump
1500 gram1[0x426A] = 1; // (W)
1503 if (keys[0x12]|keys[56]) // (E) Fire
1508 if (gram1[0x3F08] == 0xFF) // Ugly kludge for debouncing gun
1519 gram1[0x426C] = 1; // (R)
1521 gram1[0x4262] = 1; // (T)
1523 gram1[0x4260] = 1; // (Y)
1525 gram1[0x41A5]++; // Coin? (F10)
1527 gram1[0x4189]++; // ? (Z) credits l dig
1529 gram1[0x418A]++; // ? (X) credits r dig
1531 gram1[0x418C]++; // ? (C) Start
1533 gram1[0x418D]++; // ? (V)
1535 SpawnSound(USERSOUND, 0); // Do user sound (F7)
1538 // gram1[0x4380] = 0; // (F8) kill music (this worx)
1539 // charbase = false; // Switch chars out...
1541 // if (keys[0x43]) gram1[0x4285] = 1; // (F9) strobe unknown loc
1542 if (keys[0x45]) // (F11)
1544 Execute6809(&cpu1, 10);
1545 Execute6809(&cpu2, 10);
1551 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1553 Execute6809(&cpu1, 25000);
1554 cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)
1557 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1559 Execute6809(&cpu2, 25000);
1560 cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/
1562 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1563 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1564 while (cpu1.clock < 25000)
1566 // Gay, but what are ya gonna do?
1567 Execute6809(&cpu1, 5);
1568 Execute6809(&cpu2, 5);
1570 cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)
1571 cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/
1573 /* while (my_clock < 25000) // Cycles in 60th of a sec at 1.5 Mhz
1575 // pcx = cpu1.pc; // Tracelog stuff
1576 if (brk && (cpu1.pc == brkpnt))
1581 if (brk2 && (cpu2.pc == brkpnt2))
1586 DWORD prev = iclock;
1588 BYTE opcode = Fetch(); // Get the opcode
1591 exec_op1[Fetch()]();
1596 exec_op2[Fetch()]();
1607 if ((!(cpu1.cc&0x10)) && irqGoA)
1610 // if (!(cpu1.cc&0x10)) // Process an interrupt?
1612 cpu1.cc |= 0x80; // Set E
1613 WrMem(--cpu1.s, cpu1.pc&0xFF); WrMem(--cpu1.s, cpu1.pc>>8); // Save all regs...
1614 WrMem(--cpu1.s, cpu1.u&0xFF); WrMem(--cpu1.s, cpu1.u>>8);
1615 WrMem(--cpu1.s, cpu1.y&0xFF); WrMem(--cpu1.s, cpu1.y>>8);
1616 WrMem(--cpu1.s, cpu1.x&0xFF); WrMem(--cpu1.s, cpu1.x>>8);
1617 WrMem(--cpu1.s, cpu1.dp); WrMem(--cpu1.s, cpu1.b);
1618 WrMem(--cpu1.s, cpu1.a); WrMem(--cpu1.s, cpu1.cc);
1619 cpu1.cc |= 0x50; // Set F,I
1620 cpu1.pc = (grom1[0xFFF8]<<8) | grom1[0xFFF9]; // And do it!
1621 // Need to find out why RdMem is returning wrong values here...
1626 my_clock += (iclock - prev); // Increment my_clock
1628 // pcx = cpu2.pc; // Tracelog stuff
1629 opcode = FetchB(); // Get the opcode
1632 exec_op1B[FetchB()]();
1637 exec_op2B[FetchB()]();
1640 exec_op0B[opcode]();
1643 if (iclockB > 25000)//24550) // Slightly faster IRQs for SUB processor
1648 if ((!(cpu2.cc&0x10)) && irqGoB)
1651 // if (!(cpu2.cc&0x10)) // Process an interrupt?
1653 cpu2.cc |= 0x80; // Set E
1654 WrMemB(--cpu2.s, cpu2.pc&0xFF); WrMemB(--cpu2.s, cpu2.pc>>8); // Save all regs...
1655 WrMemB(--cpu2.s, cpu2.u&0xFF); WrMemB(--cpu2.s, cpu2.u>>8);
1656 WrMemB(--cpu2.s, cpu2.y&0xFF); WrMemB(--cpu2.s, cpu2.y>>8);
1657 WrMemB(--cpu2.s, cpu2.x&0xFF); WrMemB(--cpu2.s, cpu2.x>>8);
1658 WrMemB(--cpu2.s, cpu2.dp); WrMemB(--cpu2.s, cpu2.b);
1659 WrMemB(--cpu2.s, cpu2.a); WrMemB(--cpu2.s, cpu2.cc);
1660 cpu2.cc |= 0x50; // Set F,I
1661 cpu2.pc = (grom2[0xFFF8]<<8) | grom2[0xFFF9]; // And do it!
1665 // if (brk && (cpu1.pc == brkpnt)) running = false; // Stop running!
1667 my_clock -= 25000; // Remove frame count from iclock*/
1668 } // END: enable_cpu
1669 // if (refresh++ == 1) // 30 Hz...
1672 // BlitWilliamsScreen(gram1); // Display the screen...
1674 // BlitChar(screen, chr_rom, gram1);
1675 // refresh = (refresh2 ? 1 : 0); // 60/30 Hz...
1678 // Speed throttling happens here...
1679 while (SDL_GetTicks() - oldTicks < 16); // Actually, it's 16.66... Need to account for that somehow
1680 oldTicks = SDL_GetTicks();
1683 // Stop_audio_output();
1685 // ReleaseKeyboard(); // Release the interrupt...
1686 // RestoreOldMode(); // Restore screen
1687 if (brk && (cpu1.pc == brkpnt))
1688 cout << "CPU 1: Break at " << hex << cpu1.pc << endl;
1689 if (brk2 && (cpu2.pc == brkpnt2))
1690 cout << "CPU 2: Break at " << hex << cpu2.pc << endl;
1692 lbuff[0] = 'q'; // Temp kludge...
1694 else if (lbuff[0] == 'b') // Set/clear breakpoint
1699 brkpnt = htod(lbuff);
1701 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1706 cout << "Breakpoint cleared" << endl;
1709 else if (lbuff[0] == 'a') // Set/clear breakpoint #2
1714 brkpnt2 = htod(lbuff);
1716 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1721 cout << "Breakpoint cleared" << endl;
1724 else if (lbuff[0] == 'i') // Inspect registers
1726 printf("CPU1: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1727 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1728 cout << " iclk=" << dec << cpu1.clock << endl;
1729 printf("CPU2: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1730 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1731 cout << " iclk=" << dec << cpu2.clock << endl;
1733 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1735 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1737 else if (strncmp(lbuff, "swap", 4) == 0) // Swap ROMs
1739 looking_at_rom = !looking_at_rom;
1740 cout << "Swapped: Looking at ";
1741 (looking_at_rom ? cout << "ROM #1" : cout << "ROM #2");
1744 else if (strncmp(lbuff, "seek", 4) == 0) // Seek non-zero bytes in RAM
1748 for(int i=0; i<4; i++)
1756 while ((x == 0) && (dpc != 0xFFFF)); // Keep going until something found
1759 printf("%04X: ", dpc); // Show data found...
1760 for(int i=0; i<16; i++)
1761 printf("%02X ", gram1[(WORD)(dpc+i)]);
1763 for(int i=0; i<16; i++)
1765 BYTE a = gram1[dpc++];
1767 cout << (char)(a+48);
1768 if ((a>9) && (a<37))
1769 cout << (char)(a+55);
1775 else if (lbuff[0] == 'v') // View screen
1777 // SetVESA2(); // Set up screen
1778 BlitChar(screen, chr_rom, gram1);
1780 // RestoreOldMode();
1783 if (lbuff[0] == 'q')
1784 active = false; //break; // Quit
1787 SDL_Quit(); // Shut down SDL
1789 delete[] gram1; // Deallocate RAM & ROM spaces
1800 for(int i=0; i<16; i++)
1801 if (psg_adrs[i] != NULL)
1802 delete[] psg_adrs[i]; // Deallocate if loaded
1804 for(int i=0; i<14; i++)
1805 if (fm_adrs[i] != NULL)
1806 delete[] fm_adrs[i]; // Deallocate if loaded
1808 // tr.close(); // Close tracelog