2 // Thunder: A Rolling Thunder Emulator w/6809 debugger
5 // (c) 2004, 2009 Underground Software
7 // JLH = James L. Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 07/23/2009 Added changelog ;-)
14 #define THUNDER_VERSION "0.9.9"
23 //#include <conio.h> // For getch()
24 #include <curses.h> // For getch()
26 #include "SDL.h" // Get yer SDL out...!
33 using namespace std; // Yes!
36 #define ROM1 "RT3-1B.ROM"
37 #define ROM2 "RT3-2B.ROM"
38 #define ROM3 "RT3-3.ROM"
39 #define ROM4 "RT3-4.ROM"
40 #define ROM5 "RT1-5.ROM"
41 #define ROM6 "RT1-6.ROM"
42 #define ROM7 "RT1-7.ROM"
43 #define ROM8 "RT1-8.ROM"
44 #define ROM9 "RT1-9.ROM"
45 #define ROM10 "RT1-10.ROM"
46 #define ROM11 "RT1-11.ROM"
47 #define ROM12 "RT1-12.ROM"
48 #define ROM13 "RT1-13.ROM"
49 #define ROM14 "RT1-14.ROM"
50 #define ROM15 "RT1-15.ROM"
51 #define ROM16 "RT1-16.ROM"
52 #define ROM17 "RT1-17.ROM"
53 #define ROM18 "RT1-18.ROM"
54 #define ROM19 "RT3-19.ROM"
55 #define ROM20 "RT3-20.ROM"
56 #define ROM21 "RT1-21.ROM"
57 #define ROM22 "RT2-22.ROM"
58 #define PROM1 "RT1-1.BIN"
59 #define PROM2 "RT1-2.BIN"
60 #define PROM3 "RT1-3.BIN"
61 #define PROM4 "RT1-4.BIN"
62 #define PROM5 "RT1-5.BIN"
64 #define ROM1 "rt3-1b.9c"
65 #define ROM2 "rt3-2b.12c"
66 #define ROM3 "rt3-3.12d"
67 #define ROM4 "rt1-4.6b"
68 #define ROM5 "rt1-5.4r"
69 #define ROM6 "rt1-6.4s"
70 #define ROM7 "rt1-7.7r"
71 #define ROM8 "rt1-8.7s"
72 #define ROM9 "rt1-9.12h"
73 #define ROM10 "rt1-10.12k"
74 #define ROM11 "rt1-11.12l"
75 #define ROM12 "rt1-12.12m"
76 #define ROM13 "rt1-13.12p"
77 #define ROM14 "rt1-14.12r"
78 #define ROM15 "rt1-15.12t"
79 #define ROM16 "rt1-16.12u"
80 #define ROM17 "rt1-17.f1"
81 #define ROM18 "rt1-18.h1"
82 #define ROM19 "rt1-19.k1"
83 #define ROM20 "rt1-20.m1"
84 #define ROM21 "rt1-21.f3"
85 #define ROM22 "rt1-22.h3"
86 #define PROM1 "mb7124e.3r"
87 #define PROM2 "mb7116e.3s"
88 #define PROM3 "mb7138h.4v"
89 #define PROM4 "mb7138h.6v"
90 #define PROM5 "mb7112e.6u"
91 #define MCUROM "rt1-mcu.bin"
98 uint8 * gram, * grom; // Allocate RAM & ROM pointers
99 uint8 gram1[0x10000], gram2[0x10000], grom1[0x10000], grom2[0x10000]; // Actual memory
100 uint8 grom3[0x8000], grom4[0x8000], data_rom[0x40000], spr_rom[0x80000], voice_rom[0x20000];
101 uint8 chr_rom[0x60000]; // Character ROM pointer
103 gram1 = new uint8[0x10000];
104 grom1 = new uint8[0x10000];
105 gram2 = new uint8[0x10000];
106 grom2 = new uint8[0x10000];
107 chr_rom = new uint8[0x60000];
108 grom3 = new uint8[0x8000];
109 grom4 = new uint8[0x8000];
110 data_rom = new uint8[0x40000];
111 spr_rom = new uint8[0x80000];
112 voice_rom = new uint8[0x20000];
115 V6809REGS cpu1, cpu2;
117 bool trace1 = false; // ditto...
118 bool looking_at_rom = true; // true = R1, false = R2
119 uint32 banksw1, banksw2; // Bank switch addresses
120 uint16 game_over_switch; // Game over delay
121 uint16 dpc; // Debug pc reg...
122 bool show_scr = true; // Whether or not to show background
123 bool enable_cpu = true; // Whether or not to enable CPUs
124 bool irqGoA = true; // IRQ switch for CPU #1
125 bool irqGoB = true; // IRQ switch for CPU #2
127 uint16 refresh_ = 0; // Crappy global screen stuff...
128 bool refresh2 = true;
130 uint32 psg_lens[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
131 uint8 * psg_adrs[16];
132 uint32 voc_lens[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
134 uint8 * voc_adrs[32];
135 uint32 fm_lens[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
138 fstream tr; // Tracelog hook
139 uint16 pcx; // Where we at?
141 static uint8 * keys; // SDL raw keyboard matrix
143 static char op_mat1[256] = {
144 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
145 0, 0, 5, 5, 0, 0, 4, 4, 0, 5, 8, 0, 8, 5, 6, 6,
146 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
147 7, 7, 7, 7, 6, 6, 6, 6, 0, 5, 5, 5, 8, 5, 5, 5,
148 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
149 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
150 7, 0, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7,
151 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
152 8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 3, 9, 0,
153 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
154 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
155 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
156 8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 0, 9, 0,
157 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
158 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
159 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
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, 0,
163 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
164 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0,
170 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
171 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 7,
172 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2,
173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7,
176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 },
178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
184 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
185 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
186 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
187 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
188 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
189 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
190 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
193 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
194 static char mnemonics[256][6] = {
195 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
196 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
197 "PAGE1","PAGE2","NOP ","SYNC ","??? ","??? ","LBRA ","LBSR ",
198 "??? ","DAA ","ORCC ","??? ","ANDCC","SEX ","EXG ","TFR ",
199 "BRA ","BRN ","BHI ","BLS ","BHS ","BLO ","BNE ","BEQ ",
200 "BVC ","BVS ","BPL ","BMI ","BGE ","BLT ","BGT ","BLE ",
201 "LEAX ","LEAY ","LEAS ","LEAU ","PSHS ","PULS ","PSHU ","PULU ",
202 "??? ","RTS ","ABX ","RTI ","CWAI ","MUL ","RESET","SWI ",
203 "NEGA ","??? ","??? ","COMA ","LSRA ","??? ","RORA ","ASRA ",
204 "LSLA ","ROLA ","DECA ","??? ","INCA ","TSTA ","??? ","CLRA ",
205 "NEGB ","??? ","??? ","COMB ","LSRB ","??? ","RORB ","ASRB ",
206 "LSLB ","ROLB ","DECB ","??? ","INCB ","TSTB ","??? ","CLRB ",
207 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
208 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
209 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
210 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
211 "SUBA ","CMPA ","SCBA ","SUBD ","ANDA ","BITA ","LDA ","??? ",
212 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","BSR ","LDX ","??? ",
213 "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA ","STA ",
214 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","JSR ","LDX ","STX ",
215 "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA ","STA ",
216 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","JSR ","LDX ","STX ",
217 "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA ","STA ",
218 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","JSR ","LDX ","STX ",
219 "SUBB ","CMPB ","SCBB ","ADDD ","ANDB ","BITB ","LDB ","??? ",
220 "EORB ","ADCB ","ORB ","ADDB ","LDD ","??? ","LDU ","??? ",
221 "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB ","STB ",
222 "EORB ","ADCB ","ORB ","ADDB ","LDD ","STD ","LDU ","STU ",
223 "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB ","STB ",
224 "EORB ","ADCB ","ORB ","ADDB ","LDD ","STD ","LDU ","STU ",
225 "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB ","STB ",
226 "EORB ","ADCB ","ORB ","ADDB ","LDD ","STD ","LDU ","STU " },
227 mnemonics2[256][6] = {
228 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
229 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
230 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
231 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
232 "??? ","LBRN ","LBHI ","LBLS ","LBHS ","LBLO ","LBNE ","LBEQ ",
233 "LBVC ","LBVS ","LBPL ","LBMI ","LBGE ","LBLT ","LBGT ","LBLE ",
234 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
235 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","SWI2 ",
236 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
237 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
238 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
239 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
240 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
241 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
242 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
243 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
244 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
245 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","??? ",
246 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
247 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
248 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
249 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
250 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
251 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
252 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
253 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","??? ",
254 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
255 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS ",
256 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
257 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS ",
258 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
259 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS " },
260 mnemonics3[256][6] = {
261 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
262 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
263 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
264 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
265 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
266 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
267 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
268 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","SWI3 ",
269 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
270 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
271 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
272 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
273 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
274 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
275 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
276 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
277 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
278 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
279 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
280 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
281 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
282 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
283 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
284 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
285 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
286 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
287 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
288 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
289 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
290 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
291 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
292 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? " },
294 "D", "X", "Y", "U", "S", "PC", "??", "??",
295 "A", "B", "CC", "DP", "??", "??", "??", "??" },
296 iregs[4][2] = {"X", "Y", "U", "S" };
299 // Read a byte from memory (without touching PC. Not a Fetch!)
301 uint8 RdMem(uint16 addr)
308 b = data_rom[banksw1 + (addr - 0x6000)]; // Get char data
319 // Write a byte to memory
321 void WrMem(uint16 addr, uint8 b)
323 extern bool charbase; // Needed for screen. Extern it in it??
324 //extern uint16 sr, ur, xr, yr; // Needed for tracelog
326 /* if ((addr>0x40FF) && (addr<0x4390))
328 tr << hex << addr << ":" << (int)b;
329 //for(int i=0; i<32; i++)
331 // if (gram1[0x4400+i]<0x10) tr << "0";
332 // tr << hex << (uint16)gram1[0x4400+i] << " ";
338 SpawnSound(GAMESOUND, gram1[0x6200], 0); // Do voice chan 1
340 SpawnSound(GAMESOUND, gram1[0x6600], 1); // Do voice chan 2
342 banksw1 = (uint32)b << 13; // Set char data bankswitch base address
343 if (addr > 0x4284 && addr < 0x42A5 && b)
344 SpawnSound(PSGSOUND, addr - 0x4285); // Do PSG sound on chans 2, 3
347 SpawnSound(FMSOUND, b); // Do FM sound on channel 4
349 game_over_switch = 240; // Set game over delay...
351 if (addr < 0x423D || addr > 0x425C) // Protect writes to DSWs
354 charbase = false; // Char banksw1
356 charbase = true; // Char banksw2
357 if (addr == 0x8400) // Frame go strobe? VBlank acknowledge?
359 if (refresh_++ == 1) // 30 Hz...
361 BlitChar(screen, chr_rom, gram1);
362 refresh_ = (refresh2 ? 1 : 0); // 60/30 Hz...
364 // irqGoA = true; // Will this work??? no...
365 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
370 // Read a byte from memory (without touching PC. Not a Fetch!) (2nd processor)
372 uint8 RdMemB(uint16 addr)
374 // extern uint16 cpu2.s, cpu2.u, cpu2.x, cpu2.y; // Needed for tracelog
380 b = gram1[addr + 0x4000];
381 if (addr > 0x1FFF && addr < 0x6000)
382 b = gram1[addr - 0x2000];
384 b = grom3[banksw2 + (addr - 0x6000)]; // Correct?
389 /* if ((addr>0x3FFF) && (addr<0x4400)) tr << "R-" << hex << pcx << ": "
391 << (int)looking_at_rom
393 << "] XR:" << xr << " YR:" << yr
394 << " SR:" << sr << " UR:" << ur
400 // Write a byte to memory (2nd processor)
402 void WrMemB(uint16 addr, uint8 b)
404 extern bool charbase;
405 //extern uint16 sr, ur, xr, yr; // Needed for tracelog
407 /* if ((addr>0x00FF) && (addr<0x0390))
409 tr << hex << addr << ":" << (int)b;
410 //for(int i=0; i<32; i++)
412 // if (gram1[0x4400+i]<0x10) tr << "0";
413 // tr << hex << (uint16)gram1[0x4400+i] << " ";
419 // irqGoB = true; // Will it work??? no...
420 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
422 SpawnSound(GAMESOUND, gram1[0x6200], 0); // Do voice chan 1
424 SpawnSound(GAMESOUND, gram1[0x6600], 1); // Do voice chan 2
425 if (addr > 0x0284 && addr < 0x02A5 && b)
426 SpawnSound(PSGSOUND, addr - 0x0285); // Do PSG sound on chans 2, 3
428 banksw2 = (uint32)(b & 0x03) << 13; // Set sprite data bank switch
431 SpawnSound(FMSOUND, b); // Do FM sound on chan 4
433 game_over_switch = 240; // Set game over delay...
435 if (addr < 0x023D || addr > 0x025C) // Protect writes against DSWs
438 gram1[addr + 0x4000] = b;
439 if (addr > 0x1FFF && addr < 0x6000)
440 gram1[addr - 0x2000] = b;
447 // Display bytes in mem in hex
449 void DisplayBytes(uint16 src, unsigned long dst)
454 printf("%04X: ", src);
455 cnt = 0; // Init counter...
456 if (src > dst) dst += 0x10000; // That should fix the FFFF bug...
457 for(i=src; i<dst; i++)
459 printf("%02X ", (uint8)(looking_at_rom ? RdMem(i) : RdMemB(i)));
460 cnt++; // Bump counter...
462 for(i=cnt; i<5; i++) // Pad the leftover spaces...
469 uint8 Fetch(void) { return 0; }
470 uint16 FetchW(void) { return 0; }
471 uint8 FetchB(void) { return 0; }
472 uint16 FetchWB(void) { return 0; }
475 // Decode a 6809 instruction at 'addr'
479 uint8 (* DFetch)(); // Decode Fetch() pointer...
480 uint16 (* DFetchW)(); // Decode FetchW() pointer...
481 DFetch = (looking_at_rom ? Fetch : FetchB);
482 DFetchW = (looking_at_rom ? FetchW : FetchWB);
484 /* extern*/ uint16 pcr, pcrB; // Pull in 'pcr' from '6809.cpp'
485 uint16 pc_save = pcr, pcB_save = pcrB;
486 pcr = dpc; pcrB = dpc;
487 uint8 opcode = DFetch(); // Get the opcode ('fetch' cycle)
488 uint8 opcode2, operand;
490 uint8 admode = op_mat1[opcode]; // addressing mode
491 char outbuf[80], mnem[6], tmp[30];
493 strcpy(mnem, mnemonics[opcode]); // Copy page 1 opcode
494 if (opcode == 0x10) // Extended opcode?
496 opcode2 = DFetch(); // Then get next byte
497 admode = op_mat2[opcode2]; // And use it as index into 'op_mat2'
498 strcpy(mnem, mnemonics2[opcode2]); // Overwrite mnemonic
500 if (opcode == 0x11) // Same as above...
503 admode = op_mat3[opcode2];
504 strcpy(mnem, mnemonics3[opcode2]); // Overwrite mnemonic
506 switch(admode) // Decode it...
509 { sprintf(outbuf, "???"); break; }
511 { operand = DFetch(); // Get ZP address
512 sprintf(outbuf, "%s $%02X", mnem, operand);
515 { loperand = DFetchW(); // Get ABS address
516 sprintf(outbuf, "%s $%04X", mnem, loperand);
519 { operand = DFetch(); // Get offset
520 uint16 tmpc = (looking_at_rom ? pcr : pcrB);
521 sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16)(int8)operand);
523 case 4: // Long Relative
524 { loperand = DFetchW(); // Get long offset
525 uint16 tmpc = (looking_at_rom ? pcr : pcrB);
526 sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16)loperand);
529 { sprintf(outbuf, "%s ", mnem);
531 case 6: // Txfr/exchg/push/pull
532 { operand = DFetch(); // Get txfr/exg/push/pull byte
533 if ((opcode == 0x1E) || (opcode == 0x1F)) // Is it TXF/EXG?
535 sprintf(tmp, "%s,%s", tregs[operand>>4], tregs[operand&0x0F]);
540 if (operand&0x01) strcat(tmp, "CC ");
541 if (operand&0x02) strcat(tmp, "A ");
542 if (operand&0x04) strcat(tmp, "B ");
543 if (operand&0x08) strcat(tmp, "DP ");
544 if (operand&0x10) strcat(tmp, "X ");
545 if (operand&0x20) strcat(tmp, "Y ");
546 if (operand&0x40) (((opcode==0x34)||(opcode==0x35))
547 ? strcat(tmp, "U ") : strcat(tmp, "S "));
548 if (operand&0x80) strcat(tmp, "PC");
550 sprintf(outbuf, "%s %s", mnem, tmp);
552 case 7: // Indexed (the tough one!)
553 { operand = DFetch(); // Get IDX byte
554 uint8 reg = ((operand & 0x60) >> 5), idxind = ((operand & 0x10) >> 4),
555 lo_nyb = (operand & 0x0F), boff;
559 if (!(operand & 0x80)) // Hi bit set? Then decode 4 bit offset
561 sprintf(tmp, "(%d),%s", (idxind ? -(16-lo_nyb) : lo_nyb),
564 else // Add the ($nnnn,R) code dude...
570 case 1: sprintf(tmp, "(,%s++)", iregs[reg]); break;
571 case 3: sprintf(tmp, "(,--%s)", iregs[reg]); break;
572 case 4: sprintf(tmp, "(,%s)", iregs[reg]); break;
573 case 5: sprintf(tmp, "(B,%s)", iregs[reg]); break;
574 case 6: sprintf(tmp, "(A,%s)", iregs[reg]); break;
576 { boff = DFetch(); sprintf(tmp, "($%02X,%s)", boff,
577 iregs[reg]); break; }
579 { woff = DFetchW(); sprintf(tmp, "($%04X,%s)", woff,
580 iregs[reg]); break; }
581 case 11: sprintf(tmp, "(D,%s)", iregs[reg]); break;
583 { boff = DFetch(); sprintf(tmp, "($%02X,PC)", boff); break; }
585 { woff = DFetchW(); sprintf(tmp, "($%04X,PC)", woff); break; }
587 { woff = DFetchW(); sprintf(tmp, "[$%04X]", woff); break; }
588 default: strcpy(tmp, "??");
595 case 0: sprintf(tmp, ",%s+", iregs[reg]); break;
596 case 1: sprintf(tmp, ",%s++", iregs[reg]); break;
597 case 2: sprintf(tmp, ",-%s", iregs[reg]); break;
598 case 3: sprintf(tmp, ",--%s", iregs[reg]); break;
599 case 4: sprintf(tmp, ",%s", iregs[reg]); break;
600 case 5: sprintf(tmp, "(B),%s", iregs[reg]); break;
601 case 6: sprintf(tmp, "(A),%s", iregs[reg]); break;
603 { boff = DFetch(); sprintf(tmp, "($%02X),%s", boff,
604 iregs[reg]); break; }
606 { woff = DFetchW(); sprintf(tmp, "($%04X),%s", woff,
607 iregs[reg]); break; }
608 case 11: sprintf(tmp, "(D),%s", iregs[reg]); break;
610 { boff = DFetch(); sprintf(tmp, "($%02X),PC", boff); break; }
612 { woff = DFetchW(); sprintf(tmp, "($%04X),PC", woff); break; }
613 default: strcpy(tmp, "??");
617 sprintf(outbuf, "%s %s", mnem, tmp);
620 { operand = DFetch(); // Get IMM byte
621 sprintf(outbuf, "%s #$%02X", mnem, operand);
623 case 9: // Long Immediate
624 { loperand = DFetchW(); // Get IMM word
625 sprintf(outbuf, "%s #$%04X", mnem, loperand);
628 DisplayBytes(dpc, (looking_at_rom ? pcr : pcrB)); // Show bytes
629 cout << outbuf << endl; // display opcode & addressing, etc
630 dpc = (looking_at_rom ? pcr : pcrB); // Advance debug PC
631 pcr = pc_save; pcrB = pcB_save; // Restore PCs
635 // Convert hex to dec
637 uint16 htod(char *str)
640 int len = strlen(str);
642 for(int i=0; i<len; i++)
644 if (str[i]>='0' && str[i]<='9')
646 value = (value<<4) | (unsigned)(str[i]-'0');
648 if (str[i]>='a' && str[i]<='f')
650 value = (value<<4) | (unsigned)(str[i]-'a')+10;
652 if (str[i]>='A' && str[i]<='F')
654 value = (value<<4) | (unsigned)(str[i]-'A')+10;
661 // Load 32K file into ROM image space
663 bool Load32KImg(char * filename, uint16 address)
668 ff.open(filename, ios::binary | ios::in); // Open 'da file...
671 for(long i=0; i<32768; i++) // Read it in...
674 grom[address+i] = ch;
676 ff.close(); // Close 'da file...
682 // Generic Load file into image space
683 // (No error checking performed! Responsibility of caller!)
685 bool LoadImg(const char * filename, uint8 * mem, uint32 address, uint32 length)
691 strcpy(path, "./ROMs/");
692 strcat(path, filename);
693 // ff.open(filename, ios::binary | ios::in); // Open 'da file...
694 ff.open(path, ios::binary | ios::in); // Open 'da file...
697 for(uint32 i=0; i<length; i++) // Read it in...
702 ff.close(); // Close 'da file...
710 bool ReadColorPROMs(void)
715 extern uint8 palette[768]; // Screen physical palette
716 extern uint8 ccolor[256][8]; // Character color PROM values
717 extern uint8 scolor[128][16]; // Sprite color PROM values
719 ff1.open("./ROMs/"PROM3, ios::binary|ios::in);
722 for(int i=0; i<256; i++) // Load char pallete with PROM values
724 for(int j=0; j<8; j++)
727 ccolor[i][j] = (uint8)ch;
732 ff1.open("./ROMs/"PROM4, ios::binary|ios::in);
735 for(int i=0; i<128; i++) // Load sprite pallete with PROM values
737 for(int j=0; j<16; j++)
740 scolor[i][j] = (uint8)ch;
746 ff1.open("./ROMs/"PROM1, ios::binary|ios::in);
747 ff2.open("./ROMs/"PROM2, ios::binary|ios::in);
748 if (ff1) // If open was successful...
750 for(int i=0; i<768; i+=3)
753 palette[i] = (uint8)(ch&0x0F);
754 palette[i+1] = (uint8)(ch>>4);
756 palette[i+2] = (uint8)ch;
759 // Do palette stretching here... I.e. add 0 to hinyb 0, 1 to hinyb 1, etc.
761 for(int i=0; i<768; i++)
762 palette[i] = ((palette[i]<<4)&0xF0) | (palette[i]&0x0F);
773 bool UnpackFonts(void)
779 f1.open("./ROMs/"ROM7, ios::binary | ios::in);
780 f2.open("./ROMs/"ROM8, ios::binary | ios::in);
781 if ((!f1) || (!f2)) return false; // Return if not found...
782 for(long i=0; i<0x40000; i+=64)
784 for(int j=0; j<64; j+=8)
786 f1.get(b1); f1.get(b2); f2.get(b3);
787 b3 ^= 0xFF; // Invert top data...
788 chr_rom[i+j] = ((b3 & 0x80) >> 5) | ((b1 & 0x80) >> 6) | ((b1 & 0x08) >> 3);
789 chr_rom[i+j+1] = ((b3 & 0x40) >> 4) | ((b1 & 0x40) >> 5) | ((b1 & 0x04) >> 2);
790 chr_rom[i+j+2] = ((b3 & 0x20) >> 3) | ((b1 & 0x20) >> 4) | ((b1 & 0x02) >> 1);
791 chr_rom[i+j+3] = ((b3 & 0x10) >> 2) | ((b1 & 0x10) >> 3) | (b1 & 0x01);
792 chr_rom[i+j+4] = ((b3 & 0x08) >> 1) | ((b2 & 0x80) >> 6) | ((b2 & 0x08) >> 3);
793 chr_rom[i+j+5] = (b3 & 0x04) | ((b2 & 0x40) >> 5) | ((b2 & 0x04) >> 2);
794 chr_rom[i+j+6] = ((b3 & 0x02) << 1) | ((b2 & 0x20) >> 4) | ((b2 & 0x02) >> 1);
795 chr_rom[i+j+7] = ((b3 & 0x01) << 2) | ((b2 & 0x10) >> 3) | (b2 & 0x01);
801 f1.open("./ROMs/"ROM5, ios::binary | ios::in);
802 f2.open("./ROMs/"ROM6, ios::binary | ios::in);
803 for(long i=0x40000; i<0x60000; i+=64)
805 for(int j=0; j<64; j+=8)
807 f1.get(b1); f1.get(b2); f2.get(b3);
808 b3 ^= 0xFF; // Invert top data
809 chr_rom[i+j] = ((b3 & 0x80) >> 5) | ((b1 & 0x80) >> 6) | ((b1 & 0x08) >> 3);
810 chr_rom[i+j+1] = ((b3 & 0x40) >> 4) | ((b1 & 0x40) >> 5) | ((b1 & 0x04) >> 2);
811 chr_rom[i+j+2] = ((b3 & 0x20) >> 3) | ((b1 & 0x20) >> 4) | ((b1 & 0x02) >> 1);
812 chr_rom[i+j+3] = ((b3 & 0x10) >> 2) | ((b1 & 0x10) >> 3) | (b1 & 0x01);
813 chr_rom[i+j+4] = ((b3 & 0x08) >> 1) | ((b2 & 0x80) >> 6) | ((b2 & 0x08) >> 3);
814 chr_rom[i+j+5] = (b3 & 0x04) | ((b2 & 0x40) >> 5) | ((b2 & 0x04) >> 2);
815 chr_rom[i+j+6] = ((b3 & 0x02) << 1) | ((b2 & 0x20) >> 4) | ((b2 & 0x02) >> 1);
816 chr_rom[i+j+7] = ((b3 & 0x01) << 2) | ((b2 & 0x10) >> 3) | (b2 & 0x01);
821 return true; // Made it!
825 // Get length of sample from WAV format
827 uint32 GetWAVLength(fstream &file)
832 file.ignore(16); // Skip header BS
834 for(int i=0; i<2; i++)
836 file.get(ch); len = (int)(uint8)ch;
837 file.get(ch); len |= (int)(uint8)ch << 8;
838 file.get(ch); len |= (int)(uint8)ch << 16;
839 file.get(ch); len |= (int)(uint8)ch << 24;
841 file.ignore(len + 4); // Skip intermediate data
844 file.get(ch); len = (int)(uint8)ch; // & finally get length of data
845 file.get(ch); len |= (int)(uint8)ch << 8;
846 file.get(ch); len |= (int)(uint8)ch << 16;
847 file.get(ch); len |= (int)(uint8)ch << 24;
853 // Load PSG samples from disk
861 for(int i=0; i<16; i++)
865 psg_adrs[i] = NULL; // Zero out pointer
866 sprintf(file, "./sounds/psg%i.wav", i); // Create filename
868 fp.open(file, ios::binary | ios::in); // Attempt to open it...
872 len = GetWAVLength(fp); // Get WAV data length...
874 psg_adrs[i] = new uint8[len]; // Attempt to allocate space...
876 if (psg_adrs[i] != NULL)
878 for(int j=0; j<(signed)len; j++)
881 psg_adrs[i][j] = ch; // & load it in...
885 cout << "Found sample file: " << file << " [Length: " << dec << len << "]" << endl;
894 // Load FM samples from disk
902 for(int i=0; i<14; i++)
906 fm_adrs[i] = NULL; // Zero out pointer
907 sprintf(file, "./sounds/fm%i.wav", i); // Create filename
909 fp.open(file, ios::binary | ios::in); // Attempt to open it...
913 len = GetWAVLength(fp); // Get WAV length...
915 fm_adrs[i] = new uint8[len]; // Attempt to allocate space...
917 if (fm_adrs[i] != NULL)
919 for(int j=0; j<(signed)len; j++)
922 fm_adrs[i][j] = ch; // & load it in...
926 cout << "Found sample file: " << file << " [Length: " << dec << len
938 int main(int argc, char * argv[])
940 InitLog("thunder.log");
942 extern bool charbase; // From 'SCREEN.CPP'
946 fstream ff; // Declare fstream without file hooks...
947 bool brk = false, brk2 = false; // Breakpoint set flag
948 uint16 brkpnt, brkpnt2; // Where the breakpoint is...
949 bool running; // CPU running state flag...
950 bool self_test = false; // Self-test switch
951 bool scr_type = false; // false=chars, true=pixels
952 uint16 debounce = 0; // Key de-bounce counter
953 uint16 fire_debounce = 0; // Fire button debounce counter
954 // bool refresh2 = true; // Default to 60 Hz...
955 uint8 x; // General placeholder...
956 bool active = true; // Program running flag
958 SDL_Event event; // SDL "event"
959 extern uint8 palette[768]; // Screen physical palette
960 uint32 ticks, oldTicks;
962 cout << endl << "THUNDER v"THUNDER_VERSION" ";
963 cout << "by James Hammons" << endl;
964 cout << "Serial #20090723 / Prerelease" << endl;
965 cout << "(C) 2003, 2009 Underground Software" << endl << endl;
967 cout << "This emulator is free software. If you paid for it you were RIPPED OFF"
970 cout << "Initializing SDL..." << endl;
972 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
974 cout << "Couldn't initialize SDL: " << SDL_GetError() << endl;
978 SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder");
980 keys = SDL_GetKeyState(NULL); // Get the SDL keyboard matrix
983 cout << "Allocating memory..." << endl;
984 //Does this anyway... set_new_handler(0); // Make 'new' return NULL on failure...
985 gram1 = new uint8[0x10000];
986 if (gram1 == NULL) { cout << "Could not allocate RAM space #1!" << endl
987 << "Aborting!" << endl; return -1; }
988 grom1 = new uint8[0x10000];
989 if (grom1 == NULL) { cout << "Could not allocate ROM space #1!" << endl
990 << "Aborting!" << endl; return -1; }
991 gram2 = new uint8[0x10000];
992 if (gram2 == NULL) { cout << "Could not allocate RAM space #2!" << endl
993 << "Aborting!" << endl; return -1; }
994 grom2 = new uint8[0x10000];
995 if (grom2 == NULL) { cout << "Could not allocate ROM space #2!" << endl
996 << "Aborting!" << endl; return -1; }
997 chr_rom = new uint8[0x60000];
998 if (chr_rom == NULL) { cout << "Could not allocate character RAM!" << endl
999 << "Aborting!" << endl; return -1; }
1000 grom3 = new uint8[0x8000];
1001 if (grom3 == NULL) { cout << "Could not allocate ROM space #4!" << endl
1002 << "Aborting!" << endl; return -1; }
1003 grom4 = new uint8[0x8000];
1004 if (grom4 == NULL) { cout << "Could not allocate ROM space #5!" << endl
1005 << "Aborting!" << endl; return -1; }
1006 data_rom = new uint8[0x40000];
1007 if (data_rom == NULL) { cout << "Could not allocate ROM level data!" << endl
1008 << "Aborting!" << endl; return -1; }
1009 spr_rom = new uint8[0x80000];
1010 if (spr_rom == NULL) { cout << "Could not allocate ROM sprite data!" << endl
1011 << "Aborting!" << endl; return -1; }
1012 voice_rom = new uint8[0x20000];
1013 if (voice_rom == NULL) { cout << "Could not allocate ROM voice data!" << endl
1014 << "Aborting!" << endl; return -1; }
1017 gram = gram1; grom = grom1; // Needed only for debugger
1019 for(long i=0; i<0x10000; i++)
1021 gram[i] = 0; grom[i] = 0; // Zero out memory
1022 gram2[i] = 0; grom2[i] = 0;
1024 game_over_switch = 0; // Init game over delay
1025 // 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;
1027 cout << "Loading ROMs..." << endl;
1028 // LoadCMOS(); // Load CMOS at $CC00-$CFFF
1029 if (!ReadColorPROMs()) // Load virtual PROMs
1030 { cout << "Could not open PROM files!" << endl; return -1; }
1032 if (!LoadImg(ROM1, grom1, 0x8000, 0x8000)) // Load $8000-$FFFF 1st ROM
1033 { cout << "Could not open file '" << ROM1 << "'!" << endl; return -1; }
1035 if (!LoadImg(ROM2, grom2, 0x8000, 0x8000)) // Load $8000-$FFFF 2nd ROM
1036 { cout << "Could not open file '" << ROM2 << "'!" << endl; return -1; }
1038 if (!LoadImg(ROM3, grom3, 0, 0x8000)) // Load 3rd ROM into its own space
1039 { cout << "Could not open file '" << ROM3 << "'!" << endl; return -1; }
1041 if (!LoadImg(ROM4, grom4, 0, 0x8000)) // Load 4rd ROM into its own space
1042 { cout << "Could not open file '" << ROM4 << "'!" << endl; return -1; }
1044 if (!LoadImg(ROM17, data_rom, 0, 0x10000)) // Load 17th ROM
1045 { cout << "Could not open file '" << ROM17 << "'!" << endl; return -1; }
1047 if (!LoadImg(ROM18, data_rom, 0x10000, 0x10000)) // Load 18th ROM
1048 { cout << "Could not open file '" << ROM18 << "'!" << endl; return -1; }
1050 if (!LoadImg(ROM19, data_rom, 0x20000, 0x10000)) // Load 19th ROM
1051 { cout << "Could not open file '" << ROM19 << "'!" << endl; return -1; }
1053 if (!LoadImg(ROM20, data_rom, 0x30000, 0x10000)) // Load 20th ROM
1054 { cout << "Could not open file '" << ROM20 << "'!" << endl; return -1; }
1056 if (!LoadImg(ROM9, spr_rom, 0, 0x10000)) // Load 9th ROM
1057 { cout << "Could not open file '" << ROM9 << "'!" << endl; return -1; }
1059 if (!LoadImg(ROM10, spr_rom, 0x10000, 0x10000)) // Load 10th ROM
1060 { cout << "Could not open file '" << ROM10 << "'!" << endl; return -1; }
1062 if (!LoadImg(ROM11, spr_rom, 0x20000, 0x10000)) // Load 11th ROM
1063 { cout << "Could not open file '" << ROM11 << "'!" << endl; return -1; }
1065 if (!LoadImg(ROM12, spr_rom, 0x30000, 0x10000)) // Load 12th ROM
1066 { cout << "Could not open file '" << ROM12 << "'!" << endl; return -1; }
1068 if (!LoadImg(ROM13, spr_rom, 0x40000, 0x10000)) // Load 13th ROM
1069 { cout << "Could not open file '" << ROM13 << "'!" << endl; return -1; }
1071 if (!LoadImg(ROM14, spr_rom, 0x50000, 0x10000)) // Load 14th ROM
1072 { cout << "Could not open file '" << ROM14 << "'!" << endl; return -1; }
1074 if (!LoadImg(ROM15, spr_rom, 0x60000, 0x10000)) // Load 15th ROM
1075 { cout << "Could not open file '" << ROM15 << "'!" << endl; return -1; }
1077 if (!LoadImg(ROM16, spr_rom, 0x70000, 0x10000)) // Load 16th ROM
1078 { cout << "Could not open file '" << ROM16 << "'!" << endl; return -1; }
1080 if (!LoadImg(ROM21, voice_rom, 0, 0x10000)) // Load 21st ROM
1081 { cout << "Could not open file '" << ROM21 << "'!" << endl; return -1; }
1083 if (!LoadImg(ROM22, voice_rom, 0x10000, 0x10000)) // Load 22nd ROM
1084 { cout << "Could not open file '" << ROM22 << "'!" << endl; return -1; }
1086 if (!UnpackFonts()) // Load 5, 6, 7, 8th ROMs
1088 cout << "Could not open font files!" << endl;
1092 // Load samples if they're there...
1096 // Quick 'n' Dirty voice dump (sound 0x0E)
1097 /* uint32 adc = (voice_rom[26]<<8) | voice_rom[27];
1098 bool doneWitIt = false;
1102 if (voice_rom[adc] < 0x10) tr << "0";
1103 tr << hex << (int)voice_rom[adc] << " ";
1104 if (crh++ > 24) { crh = 0; tr << endl; }
1105 if ((voice_rom[adc] == 0xFF) && (voice_rom[adc-1] != 0x00))
1110 // Set up V6809 execution contexts
1112 memset(&cpu1, 0, sizeof(V6809REGS));
1115 cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
1117 memset(&cpu2, 0, sizeof(V6809REGS));
1118 cpu2.RdMem = RdMemB;
1119 cpu2.WrMem = WrMemB;
1120 cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
1122 bool firstTime = true; // kludge...
1124 WriteLog("About to go to the main loop...\n");
1130 firstTime = false; // crappy kludge...
1137 if (lbuff[0] == 'd')
1144 printf("%04X: ", dpc);
1145 uint16 pc_save = cpu1.pc, pcB_save = cpu2.pc;
1146 cpu1.pc = dpc; cpu2.pc = dpc;
1147 for(int i=0; i<16; i++)
1148 printf("%02X ", (looking_at_rom ? Fetch() : FetchB()));
1150 cpu1.pc = dpc; cpu2.pc = dpc;
1151 for(int i=0; i<16; i++)
1153 uint8 a = (looking_at_rom ? Fetch() : FetchB());
1154 if (a<10) cout << (char)(a+48);
1155 if ((a>9) && (a<37)) cout << (char)(a+55);
1156 if (a>36) cout << ".";
1159 dpc = (looking_at_rom ? cpu1.pc : cpu2.pc);
1160 cpu1.pc = pc_save; cpu2.pc = pcB_save;
1162 else if (lbuff[0] == 'e')
1169 printf("%04X: ", dpc);
1170 for(int i=0; i<16; i++) printf("%02X ", (uint8)gram[dpc++]);
1173 else if (lbuff[0] == 'l')
1180 for(int i=0; i<23; i++)
1183 else if (lbuff[0] == 't')
1194 Execute6809(&cpu1, 1);
1196 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1197 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1198 cout << " iclock=" << cpu1.clock << endl;
1204 Execute6809(&cpu2, 1);
1206 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1207 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1208 cout << " iclock=" << cpu2.clock << endl;
1211 else if ((lbuff[0] == 'r') || (lbuff[0] == 'c')) // Run/continue...
1213 WriteLog("Executing 'run' command...\n");
1214 uint32 my_clock = 0;
1215 running = true; // Set running status...
1217 SetRefreshRate(refresh2); // Tell GUI our refresh rate
1218 //for(uint16 i=0; i<0x8000; i++) gram2[i] = grom3[i]; //Temp
1220 if (lbuff[0] == 'r') // If run, then reset CPUs
1222 WriteLog("Executing secondary 'run' command...\n");
1223 gram1[0x4182] = 0xA6; // Temp kludge
1224 gram1[0x4184] = 0xA6;
1225 gram1[0x4183] = 0x00; // More of the same
1226 gram1[0x4185] = 0x00;
1227 banksw1 = 0; // Will this work?
1229 // iclock = 0; // Reset instr clock #1...
1230 InitGUI(); // Reset # of coins
1232 /* cpu1.pc = ((grom1[0xFFFE]<<8) | grom1[0xFFFF]); // Reset 6809 #1
1235 lbuff[0] = 32; cpu1.pc = htod(lbuff);
1237 else cpu1.cc = 0xFF; // Set CC register
1239 cpu2.pc = ((grom2[0xFFFE]<<8) | grom2[0xFFFF]); // Reset 6809 #2
1240 cpu2.cc = 0xFF; // Set CC register
1241 while(iclock < 8000) // was 17000, 20000, 5000
1243 Execute6809(&cpu1, 1); Execute6809(&cpu2, 1);
1245 WriteLog("--> CPU clock #1: %u\n", cpu1.clock);
1246 // Will *this* help video sync?
1247 while (cpu1.clock < 8000) // was 17000, 20000, 5000
1249 Execute6809(&cpu1, 1);
1250 Execute6809(&cpu2, 1);
1254 WriteLog("About to set up screen...\n");
1255 // if (!SetVESA2()) running = false; // Set up screen
1256 // Set up screen (windowed)
1257 screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); //video_bpp, videoflags);
1260 cout << "Failed to initialize screen!" << endl;
1264 SDL_Color colors[256];
1265 for(int i=0; i<256; i++)
1267 colors[i].r = palette[i*3+0];
1268 colors[i].g = palette[i*3+1];
1269 colors[i].b = palette[i*3+2];
1271 SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256);
1274 // This confirms that we're getting video to the screen...
1275 SDL_LockSurface(screen);
1278 uint8 * pixels = (uint8 *)(screen->pixels);
1280 for(uint32 y=0; y<480; y++)
1281 for(uint32 x=0; x<640; x++)
1282 pixels[(y * 640) + x] = pixel++;
1284 SDL_UnlockSurface(screen);
1285 SDL_UpdateRect(screen, 0, 0, 0, 0);
1288 for(int i=0; i<256; i++)
1289 keys[i] = 0; // Clear keyboard buffer...
1291 oldTicks = SDL_GetTicks();
1293 WriteLog("About to set up audio...\n");
1294 // This crap SHOULD be in sound.cpp (not yet created)...
1295 SDL_AudioSpec desired, obtained;
1296 desired.freq = 22050;
1297 desired.format = AUDIO_U8;
1298 desired.channels = 1;
1299 desired.samples = 600;
1300 desired.callback = SoundFunc;
1301 desired.userdata = NULL;
1302 // Also, should check to see if it got the hardware it needed, correct sample size, etc.
1303 if (SDL_OpenAudio(&desired, &obtained) < 0)
1305 cout << "Couldn't open audio: " << SDL_GetError() << endl;
1308 SDL_PauseAudio(0); // Get that audio going!
1310 WriteLog("About to enter main loop...\n");
1313 HandleGUIDebounce(); // Debounce GUI keys
1314 if (game_over_switch)
1316 game_over_switch--; // Countdown...
1317 if (game_over_switch == 0)
1318 gram1[0x4380] = 0; // Kill music!
1320 //gram1[0x423D] = self_test; // Reset DSW1-1
1321 gram1[0x4268] = 0; // Reset Video test
1322 gram1[0x427A] = 0; gram1[0x427C] = 0;
1323 gram1[0x427B] = 0; gram1[0x427D] = 0;
1324 gram1[0x427E] = 0; gram1[0x427F] = 0;
1325 gram1[0x4280] = 0; gram1[0x4281] = 0;
1326 gram1[0x4276] = 0; gram1[0x426A] = 0;
1327 gram1[0x4278] = 0; gram1[0x426C] = 0;
1328 gram1[0x4262] = 0; gram1[0x4260] = 0;
1329 //gram1[0x4247] = 0;
1331 // SDL key handling...
1333 SDL_PumpEvents(); // Force key events into the buffer.
1335 if (keys[SDLK_ESCAPE])
1336 running = false; // ESC to exit...
1339 debounce--; // Debounce toggle keys...
1344 self_test = !self_test; // Self-test (F1-toggle)
1345 debounce = 10; // Key debounce value...
1349 gram1[0x4268] = 1; // Video test (F2)
1350 debounce = 10; // Key debounce value...
1354 scr_type = !scr_type; // Toggle screen (F12)
1355 debounce = 10; // Key debounce value...
1359 show_scr = !show_scr; // Toggle bkgrnd (F3)
1364 enable_cpu = !enable_cpu; // Toggle CPUs (F6)
1369 refresh2 = !refresh2; // Toggle 30/60Hz (F5)
1370 SetRefreshRate(refresh2); // Inform GUI of refresh
1375 debounce = 10; // Key debounce value...
1377 if (keys[SDLK_F4]) // Do PCX snapshot (F4)
1379 SpawnSound(USERSOUND, SCAMERA);
1383 if (keys[SDLK_TAB]) // Tab active/deactivate GUI
1392 //if (keys[0x3E]) gram1[0x4247] = 1; // Screen hold DS (F4)
1393 if (keys[SDLK_RIGHT]) // Right arrow
1396 SelectRight(); // If GUI active...
1399 if (!keys[SDLK_LEFT]) // Disallow opposite directions @ same time
1400 gram1[0x427F] = 1; // Stick right
1403 if (keys[SDLK_LEFT])
1406 SelectLeft(); // If GUI active...
1409 if (!keys[SDLK_RIGHT]) // Disallow opposite directions@same time
1410 gram1[0x4281] = 1; // Left arrow
1416 SelectUp(); // If GUI active...
1419 if (!keys[SDLK_DOWN]) // Disallow opposite directions@same time
1420 gram1[0x427B] = 1; // Up arrow
1423 if (keys[SDLK_DOWN])
1426 SelectDown(); // If GUI active...
1429 if (!keys[SDLK_UP]) // Disallow opposite directions@same time
1430 gram1[0x427D] = 1; // Down arrow
1433 if (keys[SDLK_RETURN]) // Return
1435 uint8 retval = UserSelectedSomething();
1438 if (retval == REFRESH)
1440 refresh2 = !refresh2;
1441 SetRefreshRate(refresh2);
1445 gram1[0x427A] = 1; // (1)
1447 gram1[0x427C] = 1; // (2)
1449 gram1[0x427E] = 1; // (3)
1451 gram1[0x4280] = 1; // (5)
1452 if (keys[SDLK_q] | keys[29])
1453 gram1[0x4276] = 1; // (Q) Jump
1455 gram1[0x426A] = 1; // (W)
1458 if (keys[SDLK_e] | keys[56]) // (E) Fire
1464 if (gram1[0x3F08] == 0xFF) // Ugly kludge for debouncing gun
1471 gram1[0x426C] = 1; // (R)
1473 gram1[0x4262] = 1; // (T)
1475 gram1[0x4260] = 1; // (Y)
1477 gram1[0x41A5]++; // Coin? (F10)
1479 gram1[0x4189]++; // ? (Z) credits l dig
1481 gram1[0x418A]++; // ? (X) credits r dig
1483 gram1[0x418C]++; // ? (C) Start
1485 gram1[0x418D]++; // ? (V)
1487 SpawnSound(USERSOUND, 0); // Do user sound (F7)
1488 // if (keys[SDLK_F8])
1490 // gram1[0x4380] = 0; // (F8) kill music (this worx)
1491 // charbase = false; // Switch chars out...
1493 // if (keys[SDLK_F9]) gram1[0x4285] = 1; // (F9) strobe unknown loc
1494 if (keys[SDLK_F11]) // (F11)
1496 Execute6809(&cpu1, 10);
1497 Execute6809(&cpu2, 10);
1506 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1508 Execute6809(&cpu1, 25000);
1509 cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)
1512 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1514 Execute6809(&cpu2, 25000);
1515 cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/
1517 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1518 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1519 // while (cpu1.clock < 25000)
1520 for(uint32 i=0; i<250; i++)
1522 // Gay, but what are ya gonna do?
1523 // There's better ways, such as keeping track of when slave writes to master, etc...
1524 Execute6809(&cpu1, 100);
1525 Execute6809(&cpu2, 100);
1528 cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)
1529 cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/
1531 } // END: enable_cpu
1533 // if (refresh_++ == 1) // 30 Hz...
1536 // BlitWilliamsScreen(gram1); // Display the screen...
1538 // BlitChar(screen, chr_rom, gram1);
1539 // refresh_ = (refresh2 ? 1 : 0); // 60/30 Hz...
1542 //temp, for testing...
1543 BlitChar(screen, chr_rom, gram1);
1545 // Speed throttling happens here...
1546 while (SDL_GetTicks() - oldTicks < 16) // Actually, it's 16.66... Need to account for that somehow
1547 SDL_Delay(1); // Release our timeslice...
1549 oldTicks = SDL_GetTicks();
1550 //cout << "Finished frame..." << endl;
1553 // Stop_audio_output();
1555 // ReleaseKeyboard(); // Release the interrupt...
1556 // RestoreOldMode(); // Restore screen
1557 if (brk && (cpu1.pc == brkpnt))
1558 cout << "CPU 1: Break at " << hex << cpu1.pc << endl;
1559 if (brk2 && (cpu2.pc == brkpnt2))
1560 cout << "CPU 2: Break at " << hex << cpu2.pc << endl;
1562 lbuff[0] = 'q'; // Temp kludge...
1564 else if (lbuff[0] == 'b') // Set/clear breakpoint
1569 brkpnt = htod(lbuff);
1571 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1576 cout << "Breakpoint cleared" << endl;
1579 else if (lbuff[0] == 'a') // Set/clear breakpoint #2
1584 brkpnt2 = htod(lbuff);
1586 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1591 cout << "Breakpoint cleared" << endl;
1594 else if (lbuff[0] == 'i') // Inspect registers
1596 printf("CPU1: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1597 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1598 cout << " iclk=" << dec << cpu1.clock << endl;
1599 printf("CPU2: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1600 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1601 cout << " iclk=" << dec << cpu2.clock << endl;
1603 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1605 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1607 else if (strncmp(lbuff, "swap", 4) == 0) // Swap ROMs
1609 looking_at_rom = !looking_at_rom;
1610 cout << "Swapped: Looking at ";
1611 (looking_at_rom ? cout << "ROM #1" : cout << "ROM #2");
1614 else if (strncmp(lbuff, "seek", 4) == 0) // Seek non-zero bytes in RAM
1618 for(int i=0; i<4; i++)
1626 while ((x == 0) && (dpc != 0xFFFF)); // Keep going until something found
1629 printf("%04X: ", dpc); // Show data found...
1630 for(int i=0; i<16; i++)
1631 printf("%02X ", gram1[(uint16)(dpc+i)]);
1633 for(int i=0; i<16; i++)
1635 uint8 a = gram1[dpc++];
1637 cout << (char)(a+48);
1638 if ((a>9) && (a<37))
1639 cout << (char)(a+55);
1645 else if (lbuff[0] == 'v') // View screen
1647 // SetVESA2(); // Set up screen
1648 BlitChar(screen, chr_rom, gram1);
1650 // RestoreOldMode();
1653 if (lbuff[0] == 'q')
1654 active = false; //break; // Quit
1657 SDL_Quit(); // Shut down SDL
1660 delete[] gram1; // Deallocate RAM & ROM spaces
1672 for(int i=0; i<16; i++)
1674 delete[] psg_adrs[i]; // Deallocate if loaded
1676 for(int i=0; i<14; i++)
1678 delete[] fm_adrs[i]; // Deallocate if loaded