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, * gram2, * grom1, * grom2; // Actual memory
100 uint8 * grom3, * grom4, * data_rom, * spr_rom, * voice_rom;
101 uint8 * chr_rom; // Character ROM pointer
103 V6809REGS cpu1, cpu2;
105 bool trace1 = false; // ditto...
106 bool looking_at_rom = true; // true = R1, false = R2
107 uint32 banksw1, banksw2; // Bank switch addresses
108 uint16 game_over_switch; // Game over delay
109 uint16 dpc; // Debug pc reg...
110 bool show_scr = true; // Whether or not to show background
111 bool enable_cpu = true; // Whether or not to enable CPUs
112 bool irqGoA = true; // IRQ switch for CPU #1
113 bool irqGoB = true; // IRQ switch for CPU #2
115 uint16 refresh_ = 0; // Crappy global screen stuff...
116 bool refresh2 = true;
118 uint32 psg_lens[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
119 uint8 * psg_adrs[16];
120 uint32 voc_lens[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
122 uint8 * voc_adrs[32];
123 uint32 fm_lens[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
126 fstream tr; // Tracelog hook
127 uint16 pcx; // Where we at?
129 static char op_mat1[256] = {
130 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
131 0, 0, 5, 5, 0, 0, 4, 4, 0, 5, 8, 0, 8, 5, 6, 6,
132 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
133 7, 7, 7, 7, 6, 6, 6, 6, 0, 5, 5, 5, 8, 5, 5, 5,
134 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
135 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
136 7, 0, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7,
137 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
138 8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 3, 9, 0,
139 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
140 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
141 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
142 8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 0, 9, 0,
143 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
144 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
145 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
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, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
151 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
155 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0,
156 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
157 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 7,
158 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2,
159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
161 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7,
162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 },
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
172 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
173 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
174 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
175 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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 static char mnemonics[256][6] = {
181 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
182 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
183 "PAGE1","PAGE2","NOP ","SYNC ","??? ","??? ","LBRA ","LBSR ",
184 "??? ","DAA ","ORCC ","??? ","ANDCC","SEX ","EXG ","TFR ",
185 "BRA ","BRN ","BHI ","BLS ","BHS ","BLO ","BNE ","BEQ ",
186 "BVC ","BVS ","BPL ","BMI ","BGE ","BLT ","BGT ","BLE ",
187 "LEAX ","LEAY ","LEAS ","LEAU ","PSHS ","PULS ","PSHU ","PULU ",
188 "??? ","RTS ","ABX ","RTI ","CWAI ","MUL ","RESET","SWI ",
189 "NEGA ","??? ","??? ","COMA ","LSRA ","??? ","RORA ","ASRA ",
190 "LSLA ","ROLA ","DECA ","??? ","INCA ","TSTA ","??? ","CLRA ",
191 "NEGB ","??? ","??? ","COMB ","LSRB ","??? ","RORB ","ASRB ",
192 "LSLB ","ROLB ","DECB ","??? ","INCB ","TSTB ","??? ","CLRB ",
193 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
194 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
195 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
196 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
197 "SUBA ","CMPA ","SCBA ","SUBD ","ANDA ","BITA ","LDA ","??? ",
198 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","BSR ","LDX ","??? ",
199 "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA ","STA ",
200 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","JSR ","LDX ","STX ",
201 "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA ","STA ",
202 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","JSR ","LDX ","STX ",
203 "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA ","STA ",
204 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","JSR ","LDX ","STX ",
205 "SUBB ","CMPB ","SCBB ","ADDD ","ANDB ","BITB ","LDB ","??? ",
206 "EORB ","ADCB ","ORB ","ADDB ","LDD ","??? ","LDU ","??? ",
207 "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB ","STB ",
208 "EORB ","ADCB ","ORB ","ADDB ","LDD ","STD ","LDU ","STU ",
209 "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB ","STB ",
210 "EORB ","ADCB ","ORB ","ADDB ","LDD ","STD ","LDU ","STU ",
211 "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB ","STB ",
212 "EORB ","ADCB ","ORB ","ADDB ","LDD ","STD ","LDU ","STU " },
213 mnemonics2[256][6] = {
214 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
215 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
216 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
217 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
218 "??? ","LBRN ","LBHI ","LBLS ","LBHS ","LBLO ","LBNE ","LBEQ ",
219 "LBVC ","LBVS ","LBPL ","LBMI ","LBGE ","LBLT ","LBGT ","LBLE ",
220 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
221 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","SWI2 ",
222 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
223 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
224 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
225 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
226 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
227 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
228 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
229 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
230 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
231 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","??? ",
232 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
233 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
234 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
235 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
236 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
237 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
238 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
239 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","??? ",
240 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
241 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS ",
242 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
243 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS ",
244 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
245 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS " },
246 mnemonics3[256][6] = {
247 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
248 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
249 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
250 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
251 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
252 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
253 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
254 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","SWI3 ",
255 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
256 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
257 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
258 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
259 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
260 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
261 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
262 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
263 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
264 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
265 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
266 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
267 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
268 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
269 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
270 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
271 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
272 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
273 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
274 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
275 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
276 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
277 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
278 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? " },
280 "D", "X", "Y", "U", "S", "PC", "??", "??",
281 "A", "B", "CC", "DP", "??", "??", "??", "??" },
282 iregs[4][2] = {"X", "Y", "U", "S" };
285 // Read a byte from memory (without touching PC. Not a Fetch!)
287 uint8 RdMem(uint16 addr)
294 b = data_rom[banksw1 + (addr - 0x6000)]; // Get char data
305 // Write a byte to memory
307 void WrMem(uint16 addr, uint8 b)
309 extern bool charbase; // Needed for screen. Extern it in it??
310 //extern uint16 sr, ur, xr, yr; // Needed for tracelog
312 /* if ((addr>0x40FF) && (addr<0x4390))
314 tr << hex << addr << ":" << (int)b;
315 //for(int i=0; i<32; i++)
317 // if (gram1[0x4400+i]<0x10) tr << "0";
318 // tr << hex << (uint16)gram1[0x4400+i] << " ";
324 SpawnSound(GAMESOUND, gram1[0x6200], 0); // Do voice chan 1
326 SpawnSound(GAMESOUND, gram1[0x6600], 1); // Do voice chan 2
328 banksw1 = (uint32)b << 13; // Set char data bankswitch base address
329 if (addr > 0x4284 && addr < 0x42A5 && b)
330 SpawnSound(PSGSOUND, addr - 0x4285); // Do PSG sound on chans 2, 3
333 SpawnSound(FMSOUND, b); // Do FM sound on channel 4
335 game_over_switch = 240; // Set game over delay...
337 if (addr < 0x423D || addr > 0x425C) // Protect writes to DSWs
340 charbase = false; // Char banksw1
342 charbase = true; // Char banksw2
343 if (addr == 0x8400) // Frame go strobe? VBlank acknowledge?
345 if (refresh_++ == 1) // 30 Hz...
347 BlitChar(screen, chr_rom, gram1);
348 refresh_ = (refresh2 ? 1 : 0); // 60/30 Hz...
350 // irqGoA = true; // Will this work??? no...
351 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
356 // Read a byte from memory (without touching PC. Not a Fetch!) (2nd processor)
358 uint8 RdMemB(uint16 addr)
360 // extern uint16 cpu2.s, cpu2.u, cpu2.x, cpu2.y; // Needed for tracelog
366 b = gram1[addr + 0x4000];
367 if (addr > 0x1FFF && addr < 0x6000)
368 b = gram1[addr - 0x2000];
370 b = grom3[banksw2 + (addr - 0x6000)]; // Correct?
375 /* if ((addr>0x3FFF) && (addr<0x4400)) tr << "R-" << hex << pcx << ": "
377 << (int)looking_at_rom
379 << "] XR:" << xr << " YR:" << yr
380 << " SR:" << sr << " UR:" << ur
386 // Write a byte to memory (2nd processor)
388 void WrMemB(uint16 addr, uint8 b)
390 extern bool charbase;
391 //extern uint16 sr, ur, xr, yr; // Needed for tracelog
393 /* if ((addr>0x00FF) && (addr<0x0390))
395 tr << hex << addr << ":" << (int)b;
396 //for(int i=0; i<32; i++)
398 // if (gram1[0x4400+i]<0x10) tr << "0";
399 // tr << hex << (uint16)gram1[0x4400+i] << " ";
405 // irqGoB = true; // Will it work??? no...
406 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
408 SpawnSound(GAMESOUND, gram1[0x6200], 0); // Do voice chan 1
410 SpawnSound(GAMESOUND, gram1[0x6600], 1); // Do voice chan 2
411 if (addr > 0x0284 && addr < 0x02A5 && b)
412 SpawnSound(PSGSOUND, addr - 0x0285); // Do PSG sound on chans 2, 3
414 banksw2 = (uint32)(b & 0x03) << 13; // Set sprite data bank switch
417 SpawnSound(FMSOUND, b); // Do FM sound on chan 4
419 game_over_switch = 240; // Set game over delay...
421 if (addr < 0x023D || addr > 0x025C) // Protect writes against DSWs
424 gram1[addr + 0x4000] = b;
425 if (addr > 0x1FFF && addr < 0x6000)
426 gram1[addr - 0x2000] = b;
433 // Display bytes in mem in hex
435 void DisplayBytes(uint16 src, unsigned long dst)
440 printf("%04X: ", src);
441 cnt = 0; // Init counter...
442 if (src > dst) dst += 0x10000; // That should fix the FFFF bug...
443 for(i=src; i<dst; i++)
445 printf("%02X ", (uint8)(looking_at_rom ? RdMem(i) : RdMemB(i)));
446 cnt++; // Bump counter...
448 for(i=cnt; i<5; i++) // Pad the leftover spaces...
455 uint8 Fetch(void) { return 0; }
456 uint16 FetchW(void) { return 0; }
457 uint8 FetchB(void) { return 0; }
458 uint16 FetchWB(void) { return 0; }
461 // Decode a 6809 instruction at 'addr'
465 uint8 (* DFetch)(); // Decode Fetch() pointer...
466 uint16 (* DFetchW)(); // Decode FetchW() pointer...
467 DFetch = (looking_at_rom ? Fetch : FetchB);
468 DFetchW = (looking_at_rom ? FetchW : FetchWB);
470 /* extern*/ uint16 pcr, pcrB; // Pull in 'pcr' from '6809.cpp'
471 uint16 pc_save = pcr, pcB_save = pcrB;
472 pcr = dpc; pcrB = dpc;
473 uint8 opcode = DFetch(); // Get the opcode ('fetch' cycle)
474 uint8 opcode2, operand;
476 uint8 admode = op_mat1[opcode]; // addressing mode
477 char outbuf[80], mnem[6], tmp[30];
479 strcpy(mnem, mnemonics[opcode]); // Copy page 1 opcode
480 if (opcode == 0x10) // Extended opcode?
482 opcode2 = DFetch(); // Then get next byte
483 admode = op_mat2[opcode2]; // And use it as index into 'op_mat2'
484 strcpy(mnem, mnemonics2[opcode2]); // Overwrite mnemonic
486 if (opcode == 0x11) // Same as above...
489 admode = op_mat3[opcode2];
490 strcpy(mnem, mnemonics3[opcode2]); // Overwrite mnemonic
492 switch(admode) // Decode it...
495 { sprintf(outbuf, "???"); break; }
497 { operand = DFetch(); // Get ZP address
498 sprintf(outbuf, "%s $%02X", mnem, operand);
501 { loperand = DFetchW(); // Get ABS address
502 sprintf(outbuf, "%s $%04X", mnem, loperand);
505 { operand = DFetch(); // Get offset
506 uint16 tmpc = (looking_at_rom ? pcr : pcrB);
507 sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16)(int8)operand);
509 case 4: // Long Relative
510 { loperand = DFetchW(); // Get long offset
511 uint16 tmpc = (looking_at_rom ? pcr : pcrB);
512 sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16)loperand);
515 { sprintf(outbuf, "%s ", mnem);
517 case 6: // Txfr/exchg/push/pull
518 { operand = DFetch(); // Get txfr/exg/push/pull byte
519 if ((opcode == 0x1E) || (opcode == 0x1F)) // Is it TXF/EXG?
521 sprintf(tmp, "%s,%s", tregs[operand>>4], tregs[operand&0x0F]);
526 if (operand&0x01) strcat(tmp, "CC ");
527 if (operand&0x02) strcat(tmp, "A ");
528 if (operand&0x04) strcat(tmp, "B ");
529 if (operand&0x08) strcat(tmp, "DP ");
530 if (operand&0x10) strcat(tmp, "X ");
531 if (operand&0x20) strcat(tmp, "Y ");
532 if (operand&0x40) (((opcode==0x34)||(opcode==0x35))
533 ? strcat(tmp, "U ") : strcat(tmp, "S "));
534 if (operand&0x80) strcat(tmp, "PC");
536 sprintf(outbuf, "%s %s", mnem, tmp);
538 case 7: // Indexed (the tough one!)
539 { operand = DFetch(); // Get IDX byte
540 uint8 reg = ((operand & 0x60) >> 5), idxind = ((operand & 0x10) >> 4),
541 lo_nyb = (operand & 0x0F), boff;
545 if (!(operand & 0x80)) // Hi bit set? Then decode 4 bit offset
547 sprintf(tmp, "(%d),%s", (idxind ? -(16-lo_nyb) : lo_nyb),
550 else // Add the ($nnnn,R) code dude...
556 case 1: sprintf(tmp, "(,%s++)", iregs[reg]); break;
557 case 3: sprintf(tmp, "(,--%s)", iregs[reg]); break;
558 case 4: sprintf(tmp, "(,%s)", iregs[reg]); break;
559 case 5: sprintf(tmp, "(B,%s)", iregs[reg]); break;
560 case 6: sprintf(tmp, "(A,%s)", iregs[reg]); break;
562 { boff = DFetch(); sprintf(tmp, "($%02X,%s)", boff,
563 iregs[reg]); break; }
565 { woff = DFetchW(); sprintf(tmp, "($%04X,%s)", woff,
566 iregs[reg]); break; }
567 case 11: sprintf(tmp, "(D,%s)", iregs[reg]); break;
569 { boff = DFetch(); sprintf(tmp, "($%02X,PC)", boff); break; }
571 { woff = DFetchW(); sprintf(tmp, "($%04X,PC)", woff); break; }
573 { woff = DFetchW(); sprintf(tmp, "[$%04X]", woff); break; }
574 default: strcpy(tmp, "??");
581 case 0: sprintf(tmp, ",%s+", iregs[reg]); break;
582 case 1: sprintf(tmp, ",%s++", iregs[reg]); break;
583 case 2: sprintf(tmp, ",-%s", iregs[reg]); break;
584 case 3: sprintf(tmp, ",--%s", iregs[reg]); break;
585 case 4: sprintf(tmp, ",%s", iregs[reg]); break;
586 case 5: sprintf(tmp, "(B),%s", iregs[reg]); break;
587 case 6: sprintf(tmp, "(A),%s", iregs[reg]); break;
589 { boff = DFetch(); sprintf(tmp, "($%02X),%s", boff,
590 iregs[reg]); break; }
592 { woff = DFetchW(); sprintf(tmp, "($%04X),%s", woff,
593 iregs[reg]); break; }
594 case 11: sprintf(tmp, "(D),%s", iregs[reg]); break;
596 { boff = DFetch(); sprintf(tmp, "($%02X),PC", boff); break; }
598 { woff = DFetchW(); sprintf(tmp, "($%04X),PC", woff); break; }
599 default: strcpy(tmp, "??");
603 sprintf(outbuf, "%s %s", mnem, tmp);
606 { operand = DFetch(); // Get IMM byte
607 sprintf(outbuf, "%s #$%02X", mnem, operand);
609 case 9: // Long Immediate
610 { loperand = DFetchW(); // Get IMM word
611 sprintf(outbuf, "%s #$%04X", mnem, loperand);
614 DisplayBytes(dpc, (looking_at_rom ? pcr : pcrB)); // Show bytes
615 cout << outbuf << endl; // display opcode & addressing, etc
616 dpc = (looking_at_rom ? pcr : pcrB); // Advance debug PC
617 pcr = pc_save; pcrB = pcB_save; // Restore PCs
621 // Convert hex to dec
623 uint16 htod(char *str)
626 int len = strlen(str);
628 for(int i=0; i<len; i++)
630 if (str[i]>='0' && str[i]<='9')
632 value = (value<<4) | (unsigned)(str[i]-'0');
634 if (str[i]>='a' && str[i]<='f')
636 value = (value<<4) | (unsigned)(str[i]-'a')+10;
638 if (str[i]>='A' && str[i]<='F')
640 value = (value<<4) | (unsigned)(str[i]-'A')+10;
647 // Load 32K file into ROM image space
649 bool Load32KImg(char * filename, uint16 address)
654 ff.open(filename, ios::binary | ios::in); // Open 'da file...
657 for(long i=0; i<32768; i++) // Read it in...
660 grom[address+i] = ch;
662 ff.close(); // Close 'da file...
668 // Generic Load file into image space
669 // (No error checking performed! Responsibility of caller!)
671 bool LoadImg(const char * filename, uint8 * mem, uint32 address, uint32 length)
677 strcpy(path, "./ROMs/");
678 strcat(path, filename);
679 // ff.open(filename, ios::binary | ios::in); // Open 'da file...
680 ff.open(path, ios::binary | ios::in); // Open 'da file...
683 for(uint32 i=0; i<length; i++) // Read it in...
688 ff.close(); // Close 'da file...
696 bool ReadColorPROMs(void)
701 extern uint8 palette[768]; // Screen physical palette
702 extern uint8 ccolor[256][8]; // Character color PROM values
703 extern uint8 scolor[128][16]; // Sprite color PROM values
705 ff1.open("./ROMs/"PROM3, ios::binary|ios::in);
708 for(int i=0; i<256; i++) // Load char pallete with PROM values
710 for(int j=0; j<8; j++)
713 ccolor[i][j] = (uint8)ch;
718 ff1.open("./ROMs/"PROM4, ios::binary|ios::in);
721 for(int i=0; i<128; i++) // Load sprite pallete with PROM values
723 for(int j=0; j<16; j++)
726 scolor[i][j] = (uint8)ch;
732 ff1.open("./ROMs/"PROM1, ios::binary|ios::in);
733 ff2.open("./ROMs/"PROM2, ios::binary|ios::in);
734 if (ff1) // If open was successful...
736 for(int i=0; i<768; i+=3)
739 palette[i] = (uint8)(ch&0x0F);
740 palette[i+1] = (uint8)(ch>>4);
742 palette[i+2] = (uint8)ch;
745 // Do palette stretching here... I.e. add 0 to hinyb 0, 1 to hinyb 1, etc.
747 for(int i=0; i<768; i++)
748 palette[i] = ((palette[i]<<4)&0xF0) | (palette[i]&0x0F);
759 bool UnpackFonts(void)
765 f1.open("./ROMs/"ROM7, ios::binary | ios::in);
766 f2.open("./ROMs/"ROM8, ios::binary | ios::in);
767 if ((!f1) || (!f2)) return false; // Return if not found...
768 for(long i=0; i<0x40000; i+=64)
770 for(int j=0; j<64; j+=8)
772 f1.get(b1); f1.get(b2); f2.get(b3);
773 b3 ^= 0xFF; // Invert top data...
774 chr_rom[i+j] = ((b3 & 0x80) >> 5) | ((b1 & 0x80) >> 6) | ((b1 & 0x08) >> 3);
775 chr_rom[i+j+1] = ((b3 & 0x40) >> 4) | ((b1 & 0x40) >> 5) | ((b1 & 0x04) >> 2);
776 chr_rom[i+j+2] = ((b3 & 0x20) >> 3) | ((b1 & 0x20) >> 4) | ((b1 & 0x02) >> 1);
777 chr_rom[i+j+3] = ((b3 & 0x10) >> 2) | ((b1 & 0x10) >> 3) | (b1 & 0x01);
778 chr_rom[i+j+4] = ((b3 & 0x08) >> 1) | ((b2 & 0x80) >> 6) | ((b2 & 0x08) >> 3);
779 chr_rom[i+j+5] = (b3 & 0x04) | ((b2 & 0x40) >> 5) | ((b2 & 0x04) >> 2);
780 chr_rom[i+j+6] = ((b3 & 0x02) << 1) | ((b2 & 0x20) >> 4) | ((b2 & 0x02) >> 1);
781 chr_rom[i+j+7] = ((b3 & 0x01) << 2) | ((b2 & 0x10) >> 3) | (b2 & 0x01);
787 f1.open("./ROMs/"ROM5, ios::binary | ios::in);
788 f2.open("./ROMs/"ROM6, ios::binary | ios::in);
789 for(long i=0x40000; i<0x60000; i+=64)
791 for(int j=0; j<64; j+=8)
793 f1.get(b1); f1.get(b2); f2.get(b3);
794 b3 ^= 0xFF; // Invert top data
795 chr_rom[i+j] = ((b3 & 0x80) >> 5) | ((b1 & 0x80) >> 6) | ((b1 & 0x08) >> 3);
796 chr_rom[i+j+1] = ((b3 & 0x40) >> 4) | ((b1 & 0x40) >> 5) | ((b1 & 0x04) >> 2);
797 chr_rom[i+j+2] = ((b3 & 0x20) >> 3) | ((b1 & 0x20) >> 4) | ((b1 & 0x02) >> 1);
798 chr_rom[i+j+3] = ((b3 & 0x10) >> 2) | ((b1 & 0x10) >> 3) | (b1 & 0x01);
799 chr_rom[i+j+4] = ((b3 & 0x08) >> 1) | ((b2 & 0x80) >> 6) | ((b2 & 0x08) >> 3);
800 chr_rom[i+j+5] = (b3 & 0x04) | ((b2 & 0x40) >> 5) | ((b2 & 0x04) >> 2);
801 chr_rom[i+j+6] = ((b3 & 0x02) << 1) | ((b2 & 0x20) >> 4) | ((b2 & 0x02) >> 1);
802 chr_rom[i+j+7] = ((b3 & 0x01) << 2) | ((b2 & 0x10) >> 3) | (b2 & 0x01);
807 return true; // Made it!
811 // Get length of sample from WAV format
813 uint32 GetWAVLength(fstream &file)
818 file.ignore(16); // Skip header BS
820 for(int i=0; i<2; i++)
822 file.get(ch); len = (int)(uint8)ch;
823 file.get(ch); len |= (int)(uint8)ch << 8;
824 file.get(ch); len |= (int)(uint8)ch << 16;
825 file.get(ch); len |= (int)(uint8)ch << 24;
827 file.ignore(len + 4); // Skip intermediate data
830 file.get(ch); len = (int)(uint8)ch; // & finally get length of data
831 file.get(ch); len |= (int)(uint8)ch << 8;
832 file.get(ch); len |= (int)(uint8)ch << 16;
833 file.get(ch); len |= (int)(uint8)ch << 24;
839 // Load PSG samples from disk
847 for(int i=0; i<16; i++)
851 psg_adrs[i] = NULL; // Zero out pointer
852 sprintf(file, "./sounds/psg%i.wav", i); // Create filename
854 fp.open(file, ios::binary | ios::in); // Attempt to open it...
858 len = GetWAVLength(fp); // Get WAV data length...
860 psg_adrs[i] = new uint8[len]; // Attempt to allocate space...
862 if (psg_adrs[i] != NULL)
864 for(int j=0; j<(signed)len; j++)
867 psg_adrs[i][j] = ch; // & load it in...
871 cout << "Found sample file: " << file << " [Length: " << dec << len << "]" << endl;
880 // Load FM samples from disk
888 for(int i=0; i<14; i++)
892 fm_adrs[i] = NULL; // Zero out pointer
893 sprintf(file, "./sounds/fm%i.wav", i); // Create filename
895 fp.open(file, ios::binary | ios::in); // Attempt to open it...
899 len = GetWAVLength(fp); // Get WAV length...
901 fm_adrs[i] = new uint8[len]; // Attempt to allocate space...
903 if (fm_adrs[i] != NULL)
905 for(int j=0; j<(signed)len; j++)
908 fm_adrs[i][j] = ch; // & load it in...
912 cout << "Found sample file: " << file << " [Length: " << dec << len
924 int main(int argc, char * argv[])
926 InitLog("thunder.log");
928 /* extern uint16 cpu1.pc, cpu1.s, cpu1.u, cpu1.x, cpu1.y; // Pull in vars from '6809.cpp'
929 extern uint8 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp;
932 extern uint16 cpu2.pc, cpu2.s, cpu2.u, cpu2.x, cpu2.y; // Pull in vars from '6809B.cpp'
933 extern uint8 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp;
935 extern bool illegalB;
936 extern void (* exec_op0[256])(); // Array of page zero opcode functions...
937 extern void (* exec_op1[256])(); // Array of page one opcode functions...
938 extern void (* exec_op2[256])(); // Array of page two opcode functions...
939 extern void (* exec_op0B[256])(); // Array of page zero opcode functions...
940 extern void (* exec_op1B[256])(); // Array of page one opcode functions...
941 extern void (* exec_op2B[256])(); // Array of page two opcode functions...*/
942 extern bool charbase; // From 'SCREEN.CPP'
943 // extern unsigned int vesa_memptr;
947 fstream ff; // Declare fstream without file hooks...
948 bool brk = false, brk2 = false; // Breakpoint set flag
949 uint16 brkpnt, brkpnt2; // Where the breakpoint is...
950 bool running; // CPU running state flag...
951 bool self_test = false; // Self-test switch
952 bool scr_type = false; // false=chars, true=pixels
953 uint16 debounce = 0; // Key de-bounce counter
954 uint16 fire_debounce = 0; // Fire button debounce counter
955 // bool refresh2 = true; // Default to 60 Hz...
956 uint8 x; // General placeholder...
957 bool active = true; // Program running flag
959 // SDL_Surface * screen = NULL; // SDL screen pointer
960 SDL_Event event; // SDL "event"
961 // int keyPressed; // SDL key pressed...
962 uint8 keys[256]; // Keyboard "switch-like" buffer
963 extern uint8 palette[768]; // Screen physical palette
964 uint32 ticks, oldTicks;
966 // tr.open("exe.log", ios::binary | ios::out); // Tracelog
968 cout << endl << "THUNDER v"THUNDER_VERSION" ";
969 cout << "by James Hammmmons" << endl;
970 cout << "Serial #20090723 / Prerelease" << endl;
971 cout << "(C) 2003, 2009 Underground Software" << endl << endl;
973 cout << "This emulator is free software. If you paid for it you were RIPPED OFF"
976 cout << "Initializing SDL..." << endl;
978 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
980 cout << "Couldn't initialize SDL: " << SDL_GetError() << endl;
984 SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder");
986 cout << "Allocating memory..." << endl;
987 //Does this anyway... set_new_handler(0); // Make 'new' return NULL on failure...
988 gram1 = new uint8[0x10000];
989 if (gram1 == NULL) { cout << "Could not allocate RAM space #1!" << endl
990 << "Aborting!" << endl; return -1; }
991 grom1 = new uint8[0x10000];
992 if (grom1 == NULL) { cout << "Could not allocate ROM space #1!" << endl
993 << "Aborting!" << endl; return -1; }
994 gram2 = new uint8[0x10000];
995 if (gram2 == NULL) { cout << "Could not allocate RAM space #2!" << endl
996 << "Aborting!" << endl; return -1; }
997 grom2 = new uint8[0x10000];
998 if (grom2 == NULL) { cout << "Could not allocate ROM space #2!" << endl
999 << "Aborting!" << endl; return -1; }
1000 chr_rom = new uint8[0x60000];
1001 if (chr_rom == NULL) { cout << "Could not allocate character RAM!" << endl
1002 << "Aborting!" << endl; return -1; }
1003 grom3 = new uint8[0x8000];
1004 if (grom3 == NULL) { cout << "Could not allocate ROM space #4!" << endl
1005 << "Aborting!" << endl; return -1; }
1006 grom4 = new uint8[0x8000];
1007 if (grom4 == NULL) { cout << "Could not allocate ROM space #5!" << endl
1008 << "Aborting!" << endl; return -1; }
1009 data_rom = new uint8[0x40000];
1010 if (data_rom == NULL) { cout << "Could not allocate ROM level data!" << endl
1011 << "Aborting!" << endl; return -1; }
1012 spr_rom = new uint8[0x80000];
1013 if (spr_rom == NULL) { cout << "Could not allocate ROM sprite data!" << endl
1014 << "Aborting!" << endl; return -1; }
1015 voice_rom = new uint8[0x20000];
1016 if (voice_rom == NULL) { cout << "Could not allocate ROM voice data!" << endl
1017 << "Aborting!" << endl; return -1; }
1019 gram = gram1; grom = grom1; // Needed only for debugger
1021 for(long i=0; i<0x10000; i++)
1023 gram[i] = 0; grom[i] = 0; // Zero out memory
1024 gram2[i] = 0; grom2[i] = 0;
1026 game_over_switch = 0; // Init game over delay
1027 // 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;
1029 cout << "Loading ROMs..." << endl;
1030 // LoadCMOS(); // Load CMOS at $CC00-$CFFF
1031 if (!ReadColorPROMs()) // Load virtual PROMs
1032 { cout << "Could not open PROM files!" << endl; return -1; }
1034 if (!LoadImg(ROM1, grom1, 0x8000, 0x8000)) // Load $8000-$FFFF 1st ROM
1035 { cout << "Could not open file '" << ROM1 << "'!" << endl; return -1; }
1037 if (!LoadImg(ROM2, grom2, 0x8000, 0x8000)) // Load $8000-$FFFF 2nd ROM
1038 { cout << "Could not open file '" << ROM2 << "'!" << endl; return -1; }
1040 if (!LoadImg(ROM3, grom3, 0, 0x8000)) // Load 3rd ROM into its own space
1041 { cout << "Could not open file '" << ROM3 << "'!" << endl; return -1; }
1043 if (!LoadImg(ROM4, grom4, 0, 0x8000)) // Load 4rd ROM into its own space
1044 { cout << "Could not open file '" << ROM4 << "'!" << endl; return -1; }
1046 if (!LoadImg(ROM17, data_rom, 0, 0x10000)) // Load 17th ROM
1047 { cout << "Could not open file '" << ROM17 << "'!" << endl; return -1; }
1049 if (!LoadImg(ROM18, data_rom, 0x10000, 0x10000)) // Load 18th ROM
1050 { cout << "Could not open file '" << ROM18 << "'!" << endl; return -1; }
1052 if (!LoadImg(ROM19, data_rom, 0x20000, 0x10000)) // Load 19th ROM
1053 { cout << "Could not open file '" << ROM19 << "'!" << endl; return -1; }
1055 if (!LoadImg(ROM20, data_rom, 0x30000, 0x10000)) // Load 20th ROM
1056 { cout << "Could not open file '" << ROM20 << "'!" << endl; return -1; }
1058 if (!LoadImg(ROM9, spr_rom, 0, 0x10000)) // Load 9th ROM
1059 { cout << "Could not open file '" << ROM9 << "'!" << endl; return -1; }
1061 if (!LoadImg(ROM10, spr_rom, 0x10000, 0x10000)) // Load 10th ROM
1062 { cout << "Could not open file '" << ROM10 << "'!" << endl; return -1; }
1064 if (!LoadImg(ROM11, spr_rom, 0x20000, 0x10000)) // Load 11th ROM
1065 { cout << "Could not open file '" << ROM11 << "'!" << endl; return -1; }
1067 if (!LoadImg(ROM12, spr_rom, 0x30000, 0x10000)) // Load 12th ROM
1068 { cout << "Could not open file '" << ROM12 << "'!" << endl; return -1; }
1070 if (!LoadImg(ROM13, spr_rom, 0x40000, 0x10000)) // Load 13th ROM
1071 { cout << "Could not open file '" << ROM13 << "'!" << endl; return -1; }
1073 if (!LoadImg(ROM14, spr_rom, 0x50000, 0x10000)) // Load 14th ROM
1074 { cout << "Could not open file '" << ROM14 << "'!" << endl; return -1; }
1076 if (!LoadImg(ROM15, spr_rom, 0x60000, 0x10000)) // Load 15th ROM
1077 { cout << "Could not open file '" << ROM15 << "'!" << endl; return -1; }
1079 if (!LoadImg(ROM16, spr_rom, 0x70000, 0x10000)) // Load 16th ROM
1080 { cout << "Could not open file '" << ROM16 << "'!" << endl; return -1; }
1082 if (!LoadImg(ROM21, voice_rom, 0, 0x10000)) // Load 21st ROM
1083 { cout << "Could not open file '" << ROM21 << "'!" << endl; return -1; }
1085 if (!LoadImg(ROM22, voice_rom, 0x10000, 0x10000)) // Load 22nd ROM
1086 { cout << "Could not open file '" << ROM22 << "'!" << endl; return -1; }
1088 if (!UnpackFonts()) // Load 5, 6, 7, 8th ROMs
1090 cout << "Could not open font files!" << endl;
1094 // Load samples if they're there...
1098 // Quick 'n' Dirty voice dump (sound 0x0E)
1099 /* uint32 adc = (voice_rom[26]<<8) | voice_rom[27];
1100 bool doneWitIt = false;
1104 if (voice_rom[adc] < 0x10) tr << "0";
1105 tr << hex << (int)voice_rom[adc] << " ";
1106 if (crh++ > 24) { crh = 0; tr << endl; }
1107 if ((voice_rom[adc] == 0xFF) && (voice_rom[adc-1] != 0x00))
1112 // Set up V6809 execution contexts
1114 memset(&cpu1, 0, sizeof(V6809REGS));
1117 cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
1119 memset(&cpu2, 0, sizeof(V6809REGS));
1120 cpu2.RdMem = RdMemB;
1121 cpu2.WrMem = WrMemB;
1122 cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
1124 bool firstTime = true; // kludge...
1126 WriteLog("About to go to the main loop...\n");
1132 firstTime = false; // crappy kludge...
1139 if (lbuff[0] == 'd')
1146 printf("%04X: ", dpc);
1147 uint16 pc_save = cpu1.pc, pcB_save = cpu2.pc;
1148 cpu1.pc = dpc; cpu2.pc = dpc;
1149 for(int i=0; i<16; i++)
1150 printf("%02X ", (looking_at_rom ? Fetch() : FetchB()));
1152 cpu1.pc = dpc; cpu2.pc = dpc;
1153 for(int i=0; i<16; i++)
1155 uint8 a = (looking_at_rom ? Fetch() : FetchB());
1156 if (a<10) cout << (char)(a+48);
1157 if ((a>9) && (a<37)) cout << (char)(a+55);
1158 if (a>36) cout << ".";
1161 dpc = (looking_at_rom ? cpu1.pc : cpu2.pc);
1162 cpu1.pc = pc_save; cpu2.pc = pcB_save;
1164 else if (lbuff[0] == 'e')
1171 printf("%04X: ", dpc);
1172 for(int i=0; i<16; i++) printf("%02X ", (uint8)gram[dpc++]);
1175 else if (lbuff[0] == 'l')
1182 for(int i=0; i<23; i++)
1185 else if (lbuff[0] == 't')
1196 Execute6809(&cpu1, 1);
1198 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1199 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1200 cout << " iclock=" << cpu1.clock << endl;
1206 Execute6809(&cpu2, 1);
1208 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1209 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1210 cout << " iclock=" << cpu2.clock << endl;
1213 else if ((lbuff[0] == 'r') || (lbuff[0] == 'c')) // Run/continue...
1215 WriteLog("Executing 'run' command...\n");
1216 uint32 my_clock = 0;
1217 running = true; // Set running status...
1219 SetRefreshRate(refresh2); // Tell GUI our refresh rate
1220 //for(uint16 i=0; i<0x8000; i++) gram2[i] = grom3[i]; //Temp
1222 if (lbuff[0] == 'r') // If run, then reset CPUs
1224 WriteLog("Executing secondary 'run' command...\n");
1225 gram1[0x4182] = 0xA6; // Temp kludge
1226 gram1[0x4184] = 0xA6;
1227 gram1[0x4183] = 0x00; // More of the same
1228 gram1[0x4185] = 0x00;
1229 banksw1 = 0; // Will this work?
1231 // iclock = 0; // Reset instr clock #1...
1232 InitGUI(); // Reset # of coins
1234 /* cpu1.pc = ((grom1[0xFFFE]<<8) | grom1[0xFFFF]); // Reset 6809 #1
1237 lbuff[0] = 32; cpu1.pc = htod(lbuff);
1239 else cpu1.cc = 0xFF; // Set CC register
1241 cpu2.pc = ((grom2[0xFFFE]<<8) | grom2[0xFFFF]); // Reset 6809 #2
1242 cpu2.cc = 0xFF; // Set CC register
1243 while(iclock < 8000) // was 17000, 20000, 5000
1245 Execute6809(&cpu1, 1); Execute6809(&cpu2, 1);
1247 WriteLog("--> CPU clock #1: %u\n", cpu1.clock);
1248 // Will *this* help video sync?
1249 while (cpu1.clock < 8000) // was 17000, 20000, 5000
1251 Execute6809(&cpu1, 1);
1252 Execute6809(&cpu2, 1);
1256 WriteLog("About to set up screen...\n");
1257 // if (!SetVESA2()) running = false; // Set up screen
1258 // Set up screen (windowed)
1259 screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); //video_bpp, videoflags);
1262 cout << "Failed to initialize screen!" << endl;
1266 SDL_Color colors[256];
1267 for(int i=0; i<256; i++)
1269 colors[i].r = palette[i*3+0];
1270 colors[i].g = palette[i*3+1];
1271 colors[i].b = palette[i*3+2];
1273 SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256);
1276 // This confirms that we're getting video to the screen...
1277 SDL_LockSurface(screen);
1280 uint8 * pixels = (uint8 *)(screen->pixels);
1282 for(uint32 y=0; y<480; y++)
1283 for(uint32 x=0; x<640; x++)
1284 pixels[(y * 640) + x] = pixel++;
1286 SDL_UnlockSurface(screen);
1287 SDL_UpdateRect(screen, 0, 0, 0, 0);
1290 for(int i=0; i<256; i++)
1291 keys[i] = 0; // Clear keyboard buffer...
1293 oldTicks = SDL_GetTicks();
1295 WriteLog("About to set up audio...\n");
1296 // This crap SHOULD be in sound.cpp (not yet created)...
1297 SDL_AudioSpec desired, obtained;
1298 desired.freq = 22050;
1299 desired.format = AUDIO_U8;
1300 desired.channels = 1;
1301 desired.samples = 600;
1302 desired.callback = SoundFunc;
1303 desired.userdata = NULL;
1304 // Also, should check to see if it got the hardware it needed, correct sample size, etc.
1305 if (SDL_OpenAudio(&desired, &obtained) < 0)
1307 cout << "Couldn't open audio: " << SDL_GetError() << endl;
1310 SDL_PauseAudio(0); // Get that audio going!
1312 WriteLog("About to enter main loop...\n");
1315 HandleGUIDebounce(); // Debounce GUI keys
1316 if (game_over_switch)
1318 game_over_switch--; // Countdown...
1319 if (game_over_switch == 0)
1320 gram1[0x4380] = 0; // Kill music!
1322 //gram1[0x423D] = self_test; // Reset DSW1-1
1323 gram1[0x4268] = 0; // Reset Video test
1324 gram1[0x427A] = 0; gram1[0x427C] = 0;
1325 gram1[0x427B] = 0; gram1[0x427D] = 0;
1326 gram1[0x427E] = 0; gram1[0x427F] = 0;
1327 gram1[0x4280] = 0; gram1[0x4281] = 0;
1328 gram1[0x4276] = 0; gram1[0x426A] = 0;
1329 gram1[0x4278] = 0; gram1[0x426C] = 0;
1330 gram1[0x4262] = 0; gram1[0x4260] = 0;
1331 //gram1[0x4247] = 0;
1333 // SDL key handling...
1335 #warning "MAKE REPOSITORY FOR THIS THING! !!! FIX !!!"
1336 #warning "AND USE THE OLD SOURCE FOR THE BASE!!!"
1337 #warning "KEYS ARE FUCKED UP! !!! FIX !!!"
1338 // keyPressed = 0; // Reset keypress
1339 while (SDL_PollEvent(&event) != 0) // Bleed out all pending key events...
1341 if (event.type == SDL_KEYDOWN)
1342 keys[event.key.keysym.scancode] = 1;
1343 if (event.type == SDL_KEYUP)
1344 keys[event.key.keysym.scancode] = 0;
1349 running = false; // ESC to exit...
1352 debounce--; // Debounce toggle keys...
1357 self_test = !self_test; // Self-test (F1-toggle)
1358 debounce = 10; // Key debounce value...
1362 gram1[0x4268] = 1; // Video test (F2)
1363 debounce = 10; // Key debounce value...
1367 scr_type = !scr_type; // Toggle screen (F12)
1368 debounce = 10; // Key debounce value...
1372 show_scr = !show_scr; // Toggle bkgrnd (F3)
1377 enable_cpu = !enable_cpu; // Toggle CPUs (F6)
1382 refresh2 = !refresh2; // Toggle 30/60Hz (F5)
1383 SetRefreshRate(refresh2); // Inform GUI of refresh
1388 debounce = 10; // Key debounce value...
1390 if (keys[0x3E]) // Do PCX snapshot (F4)
1392 SpawnSound(USERSOUND, SCAMERA);
1396 if (keys[0x0F]) // Tab active/deactivate GUI
1405 //if (keys[0x3E]) gram1[0x4247] = 1; // Screen hold DS (F4)
1406 if (keys[77+128]) // Right arrow
1409 SelectRight(); // If GUI active...
1412 if (!keys[75+128]) // Disallow opposite directions @ same time
1413 gram1[0x427F] = 1; // Stick right
1419 SelectLeft(); // If GUI active...
1422 if (!keys[77+128]) // Disallow opposite directions@same time
1423 gram1[0x4281] = 1; // Left arrow
1429 SelectUp(); // If GUI active...
1432 if (!keys[80+128]) // Disallow opposite directions@same time
1433 gram1[0x427B] = 1; // Up arrow
1439 SelectDown(); // If GUI active...
1442 if (!keys[72+128]) // Disallow opposite directions@same time
1443 gram1[0x427D] = 1; // Down arrow
1446 if (keys[28]) // Return
1448 uint8 retval = UserSelectedSomething();
1451 if (retval == REFRESH)
1453 refresh2 = !refresh2;
1454 SetRefreshRate(refresh2);
1458 gram1[0x427A] = 1; // (1)
1460 gram1[0x427C] = 1; // (2)
1462 gram1[0x427E] = 1; // (3)
1464 gram1[0x4280] = 1; // (5)
1465 if (keys[0x10]|keys[29])
1466 gram1[0x4276] = 1; // (Q) Jump
1468 gram1[0x426A] = 1; // (W)
1471 if (keys[0x12]|keys[56]) // (E) Fire
1476 if (gram1[0x3F08] == 0xFF) // Ugly kludge for debouncing gun
1487 gram1[0x426C] = 1; // (R)
1489 gram1[0x4262] = 1; // (T)
1491 gram1[0x4260] = 1; // (Y)
1493 gram1[0x41A5]++; // Coin? (F10)
1495 gram1[0x4189]++; // ? (Z) credits l dig
1497 gram1[0x418A]++; // ? (X) credits r dig
1499 gram1[0x418C]++; // ? (C) Start
1501 gram1[0x418D]++; // ? (V)
1503 SpawnSound(USERSOUND, 0); // Do user sound (F7)
1506 // gram1[0x4380] = 0; // (F8) kill music (this worx)
1507 // charbase = false; // Switch chars out...
1509 // if (keys[0x43]) gram1[0x4285] = 1; // (F9) strobe unknown loc
1510 if (keys[0x45]) // (F11)
1512 Execute6809(&cpu1, 10);
1513 Execute6809(&cpu2, 10);
1521 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1523 Execute6809(&cpu1, 25000);
1524 cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)
1527 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1529 Execute6809(&cpu2, 25000);
1530 cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/
1532 // cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1533 // cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1534 while (cpu1.clock < 25000)
1536 // Gay, but what are ya gonna do?
1537 Execute6809(&cpu1, 5);
1538 Execute6809(&cpu2, 5);
1541 cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)
1542 cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/
1544 } // END: enable_cpu
1546 // if (refresh_++ == 1) // 30 Hz...
1549 // BlitWilliamsScreen(gram1); // Display the screen...
1551 // BlitChar(screen, chr_rom, gram1);
1552 // refresh_ = (refresh2 ? 1 : 0); // 60/30 Hz...
1554 //temp, for testing...
1555 BlitChar(screen, chr_rom, gram1);
1557 // Speed throttling happens here...
1558 while (SDL_GetTicks() - oldTicks < 16) // Actually, it's 16.66... Need to account for that somehow
1559 SDL_Delay(1); // Release our timeslice...
1561 oldTicks = SDL_GetTicks();
1562 //cout << "Finished frame..." << endl;
1565 // Stop_audio_output();
1567 // ReleaseKeyboard(); // Release the interrupt...
1568 // RestoreOldMode(); // Restore screen
1569 if (brk && (cpu1.pc == brkpnt))
1570 cout << "CPU 1: Break at " << hex << cpu1.pc << endl;
1571 if (brk2 && (cpu2.pc == brkpnt2))
1572 cout << "CPU 2: Break at " << hex << cpu2.pc << endl;
1574 lbuff[0] = 'q'; // Temp kludge...
1576 else if (lbuff[0] == 'b') // Set/clear breakpoint
1581 brkpnt = htod(lbuff);
1583 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1588 cout << "Breakpoint cleared" << endl;
1591 else if (lbuff[0] == 'a') // Set/clear breakpoint #2
1596 brkpnt2 = htod(lbuff);
1598 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1603 cout << "Breakpoint cleared" << endl;
1606 else if (lbuff[0] == 'i') // Inspect registers
1608 printf("CPU1: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1609 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1610 cout << " iclk=" << dec << cpu1.clock << endl;
1611 printf("CPU2: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1612 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1613 cout << " iclk=" << dec << cpu2.clock << endl;
1615 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1617 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1619 else if (strncmp(lbuff, "swap", 4) == 0) // Swap ROMs
1621 looking_at_rom = !looking_at_rom;
1622 cout << "Swapped: Looking at ";
1623 (looking_at_rom ? cout << "ROM #1" : cout << "ROM #2");
1626 else if (strncmp(lbuff, "seek", 4) == 0) // Seek non-zero bytes in RAM
1630 for(int i=0; i<4; i++)
1638 while ((x == 0) && (dpc != 0xFFFF)); // Keep going until something found
1641 printf("%04X: ", dpc); // Show data found...
1642 for(int i=0; i<16; i++)
1643 printf("%02X ", gram1[(uint16)(dpc+i)]);
1645 for(int i=0; i<16; i++)
1647 uint8 a = gram1[dpc++];
1649 cout << (char)(a+48);
1650 if ((a>9) && (a<37))
1651 cout << (char)(a+55);
1657 else if (lbuff[0] == 'v') // View screen
1659 // SetVESA2(); // Set up screen
1660 BlitChar(screen, chr_rom, gram1);
1662 // RestoreOldMode();
1665 if (lbuff[0] == 'q')
1666 active = false; //break; // Quit
1669 SDL_Quit(); // Shut down SDL
1671 delete[] gram1; // Deallocate RAM & ROM spaces
1682 for(int i=0; i<16; i++)
1683 if (psg_adrs[i] != NULL)
1684 delete[] psg_adrs[i]; // Deallocate if loaded
1686 for(int i=0; i<14; i++)
1687 if (fm_adrs[i] != NULL)
1688 delete[] fm_adrs[i]; // Deallocate if loaded
1690 // tr.close(); // Close tracelog