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 uint8 * keys; // SDL raw keyboard matrix
131 static char op_mat1[256] = {
132 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
133 0, 0, 5, 5, 0, 0, 4, 4, 0, 5, 8, 0, 8, 5, 6, 6,
134 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
135 7, 7, 7, 7, 6, 6, 6, 6, 0, 5, 5, 5, 8, 5, 5, 5,
136 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
137 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
138 7, 0, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7,
139 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
140 8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 3, 9, 0,
141 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
142 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
143 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
144 8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 0, 9, 0,
145 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
146 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
147 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
151 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
157 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0,
158 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
159 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 7,
160 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2,
161 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
163 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7,
164 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 },
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
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, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
175 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
176 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
177 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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 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, 0 };
182 static char mnemonics[256][6] = {
183 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
184 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
185 "PAGE1","PAGE2","NOP ","SYNC ","??? ","??? ","LBRA ","LBSR ",
186 "??? ","DAA ","ORCC ","??? ","ANDCC","SEX ","EXG ","TFR ",
187 "BRA ","BRN ","BHI ","BLS ","BHS ","BLO ","BNE ","BEQ ",
188 "BVC ","BVS ","BPL ","BMI ","BGE ","BLT ","BGT ","BLE ",
189 "LEAX ","LEAY ","LEAS ","LEAU ","PSHS ","PULS ","PSHU ","PULU ",
190 "??? ","RTS ","ABX ","RTI ","CWAI ","MUL ","RESET","SWI ",
191 "NEGA ","??? ","??? ","COMA ","LSRA ","??? ","RORA ","ASRA ",
192 "LSLA ","ROLA ","DECA ","??? ","INCA ","TSTA ","??? ","CLRA ",
193 "NEGB ","??? ","??? ","COMB ","LSRB ","??? ","RORB ","ASRB ",
194 "LSLB ","ROLB ","DECB ","??? ","INCB ","TSTB ","??? ","CLRB ",
195 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
196 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
197 "NEG ","??? ","??? ","COM ","LSR ","??? ","ROR ","ASR ",
198 "LSL ","ROL ","DEC ","??? ","INC ","TST ","JMP ","CLR ",
199 "SUBA ","CMPA ","SCBA ","SUBD ","ANDA ","BITA ","LDA ","??? ",
200 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","BSR ","LDX ","??? ",
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 "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA ","STA ",
206 "EORA ","ADCA ","ORA ","ADDA ","CMPX ","JSR ","LDX ","STX ",
207 "SUBB ","CMPB ","SCBB ","ADDD ","ANDB ","BITB ","LDB ","??? ",
208 "EORB ","ADCB ","ORB ","ADDB ","LDD ","??? ","LDU ","??? ",
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 "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB ","STB ",
214 "EORB ","ADCB ","ORB ","ADDB ","LDD ","STD ","LDU ","STU " },
215 mnemonics2[256][6] = {
216 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
217 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
218 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
219 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
220 "??? ","LBRN ","LBHI ","LBLS ","LBHS ","LBLO ","LBNE ","LBEQ ",
221 "LBVC ","LBVS ","LBPL ","LBMI ","LBGE ","LBLT ","LBGT ","LBLE ",
222 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
223 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","SWI2 ",
224 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
225 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
226 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
227 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
228 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
229 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
230 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
231 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
232 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
233 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","??? ",
234 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
235 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
236 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
237 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
238 "??? ","??? ","??? ","CMPD ","??? ","??? ","??? ","??? ",
239 "??? ","??? ","??? ","??? ","CMPY ","??? ","LDY ","STY ",
240 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
241 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","??? ",
242 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
243 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS ",
244 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
245 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS ",
246 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
247 "??? ","??? ","??? ","??? ","??? ","??? ","LDS ","STS " },
248 mnemonics3[256][6] = {
249 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
250 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
251 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
252 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
253 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
254 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
255 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
256 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","SWI3 ",
257 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
258 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
259 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
260 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
261 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
262 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
263 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
264 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
265 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
266 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
267 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
268 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
269 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
270 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
271 "??? ","??? ","??? ","CMPU ","??? ","??? ","??? ","??? ",
272 "??? ","??? ","??? ","??? ","CMPS ","??? ","??? ","??? ",
273 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
274 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
275 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
276 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
277 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
278 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
279 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? ",
280 "??? ","??? ","??? ","??? ","??? ","??? ","??? ","??? " },
282 "D", "X", "Y", "U", "S", "PC", "??", "??",
283 "A", "B", "CC", "DP", "??", "??", "??", "??" },
284 iregs[4][2] = {"X", "Y", "U", "S" };
287 // Read a byte from memory (without touching PC. Not a Fetch!)
289 uint8 RdMem(uint16 addr)
296 b = data_rom[banksw1 + (addr - 0x6000)]; // Get char data
307 // Write a byte to memory
309 void WrMem(uint16 addr, uint8 b)
311 extern bool charbase; // Needed for screen. Extern it in it??
312 //extern uint16 sr, ur, xr, yr; // Needed for tracelog
314 /* if ((addr>0x40FF) && (addr<0x4390))
316 tr << hex << addr << ":" << (int)b;
317 //for(int i=0; i<32; i++)
319 // if (gram1[0x4400+i]<0x10) tr << "0";
320 // tr << hex << (uint16)gram1[0x4400+i] << " ";
326 SpawnSound(GAMESOUND, gram1[0x6200], 0); // Do voice chan 1
328 SpawnSound(GAMESOUND, gram1[0x6600], 1); // Do voice chan 2
330 banksw1 = (uint32)b << 13; // Set char data bankswitch base address
331 if (addr > 0x4284 && addr < 0x42A5 && b)
332 SpawnSound(PSGSOUND, addr - 0x4285); // Do PSG sound on chans 2, 3
335 SpawnSound(FMSOUND, b); // Do FM sound on channel 4
337 game_over_switch = 240; // Set game over delay...
339 if (addr < 0x423D || addr > 0x425C) // Protect writes to DSWs
342 charbase = false; // Char banksw1
344 charbase = true; // Char banksw2
345 if (addr == 0x8400) // Frame go strobe? VBlank acknowledge?
347 if (refresh_++ == 1) // 30 Hz...
349 BlitChar(screen, chr_rom, gram1);
350 refresh_ = (refresh2 ? 1 : 0); // 60/30 Hz...
352 // irqGoA = true; // Will this work??? no...
353 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
358 // Read a byte from memory (without touching PC. Not a Fetch!) (2nd processor)
360 uint8 RdMemB(uint16 addr)
362 // extern uint16 cpu2.s, cpu2.u, cpu2.x, cpu2.y; // Needed for tracelog
368 b = gram1[addr + 0x4000];
369 if (addr > 0x1FFF && addr < 0x6000)
370 b = gram1[addr - 0x2000];
372 b = grom3[banksw2 + (addr - 0x6000)]; // Correct?
377 /* if ((addr>0x3FFF) && (addr<0x4400)) tr << "R-" << hex << pcx << ": "
379 << (int)looking_at_rom
381 << "] XR:" << xr << " YR:" << yr
382 << " SR:" << sr << " UR:" << ur
388 // Write a byte to memory (2nd processor)
390 void WrMemB(uint16 addr, uint8 b)
392 extern bool charbase;
393 //extern uint16 sr, ur, xr, yr; // Needed for tracelog
395 /* if ((addr>0x00FF) && (addr<0x0390))
397 tr << hex << addr << ":" << (int)b;
398 //for(int i=0; i<32; i++)
400 // if (gram1[0x4400+i]<0x10) tr << "0";
401 // tr << hex << (uint16)gram1[0x4400+i] << " ";
407 // irqGoB = true; // Will it work??? no...
408 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
410 SpawnSound(GAMESOUND, gram1[0x6200], 0); // Do voice chan 1
412 SpawnSound(GAMESOUND, gram1[0x6600], 1); // Do voice chan 2
413 if (addr > 0x0284 && addr < 0x02A5 && b)
414 SpawnSound(PSGSOUND, addr - 0x0285); // Do PSG sound on chans 2, 3
416 banksw2 = (uint32)(b & 0x03) << 13; // Set sprite data bank switch
419 SpawnSound(FMSOUND, b); // Do FM sound on chan 4
421 game_over_switch = 240; // Set game over delay...
423 if (addr < 0x023D || addr > 0x025C) // Protect writes against DSWs
426 gram1[addr + 0x4000] = b;
427 if (addr > 0x1FFF && addr < 0x6000)
428 gram1[addr - 0x2000] = b;
435 // Display bytes in mem in hex
437 void DisplayBytes(uint16 src, unsigned long dst)
442 printf("%04X: ", src);
443 cnt = 0; // Init counter...
444 if (src > dst) dst += 0x10000; // That should fix the FFFF bug...
445 for(i=src; i<dst; i++)
447 printf("%02X ", (uint8)(looking_at_rom ? RdMem(i) : RdMemB(i)));
448 cnt++; // Bump counter...
450 for(i=cnt; i<5; i++) // Pad the leftover spaces...
457 uint8 Fetch(void) { return 0; }
458 uint16 FetchW(void) { return 0; }
459 uint8 FetchB(void) { return 0; }
460 uint16 FetchWB(void) { return 0; }
463 // Decode a 6809 instruction at 'addr'
467 uint8 (* DFetch)(); // Decode Fetch() pointer...
468 uint16 (* DFetchW)(); // Decode FetchW() pointer...
469 DFetch = (looking_at_rom ? Fetch : FetchB);
470 DFetchW = (looking_at_rom ? FetchW : FetchWB);
472 /* extern*/ uint16 pcr, pcrB; // Pull in 'pcr' from '6809.cpp'
473 uint16 pc_save = pcr, pcB_save = pcrB;
474 pcr = dpc; pcrB = dpc;
475 uint8 opcode = DFetch(); // Get the opcode ('fetch' cycle)
476 uint8 opcode2, operand;
478 uint8 admode = op_mat1[opcode]; // addressing mode
479 char outbuf[80], mnem[6], tmp[30];
481 strcpy(mnem, mnemonics[opcode]); // Copy page 1 opcode
482 if (opcode == 0x10) // Extended opcode?
484 opcode2 = DFetch(); // Then get next byte
485 admode = op_mat2[opcode2]; // And use it as index into 'op_mat2'
486 strcpy(mnem, mnemonics2[opcode2]); // Overwrite mnemonic
488 if (opcode == 0x11) // Same as above...
491 admode = op_mat3[opcode2];
492 strcpy(mnem, mnemonics3[opcode2]); // Overwrite mnemonic
494 switch(admode) // Decode it...
497 { sprintf(outbuf, "???"); break; }
499 { operand = DFetch(); // Get ZP address
500 sprintf(outbuf, "%s $%02X", mnem, operand);
503 { loperand = DFetchW(); // Get ABS address
504 sprintf(outbuf, "%s $%04X", mnem, loperand);
507 { operand = DFetch(); // Get offset
508 uint16 tmpc = (looking_at_rom ? pcr : pcrB);
509 sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16)(int8)operand);
511 case 4: // Long Relative
512 { loperand = DFetchW(); // Get long offset
513 uint16 tmpc = (looking_at_rom ? pcr : pcrB);
514 sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16)loperand);
517 { sprintf(outbuf, "%s ", mnem);
519 case 6: // Txfr/exchg/push/pull
520 { operand = DFetch(); // Get txfr/exg/push/pull byte
521 if ((opcode == 0x1E) || (opcode == 0x1F)) // Is it TXF/EXG?
523 sprintf(tmp, "%s,%s", tregs[operand>>4], tregs[operand&0x0F]);
528 if (operand&0x01) strcat(tmp, "CC ");
529 if (operand&0x02) strcat(tmp, "A ");
530 if (operand&0x04) strcat(tmp, "B ");
531 if (operand&0x08) strcat(tmp, "DP ");
532 if (operand&0x10) strcat(tmp, "X ");
533 if (operand&0x20) strcat(tmp, "Y ");
534 if (operand&0x40) (((opcode==0x34)||(opcode==0x35))
535 ? strcat(tmp, "U ") : strcat(tmp, "S "));
536 if (operand&0x80) strcat(tmp, "PC");
538 sprintf(outbuf, "%s %s", mnem, tmp);
540 case 7: // Indexed (the tough one!)
541 { operand = DFetch(); // Get IDX byte
542 uint8 reg = ((operand & 0x60) >> 5), idxind = ((operand & 0x10) >> 4),
543 lo_nyb = (operand & 0x0F), boff;
547 if (!(operand & 0x80)) // Hi bit set? Then decode 4 bit offset
549 sprintf(tmp, "(%d),%s", (idxind ? -(16-lo_nyb) : lo_nyb),
552 else // Add the ($nnnn,R) code dude...
558 case 1: sprintf(tmp, "(,%s++)", iregs[reg]); break;
559 case 3: sprintf(tmp, "(,--%s)", iregs[reg]); break;
560 case 4: sprintf(tmp, "(,%s)", iregs[reg]); break;
561 case 5: sprintf(tmp, "(B,%s)", iregs[reg]); break;
562 case 6: sprintf(tmp, "(A,%s)", iregs[reg]); break;
564 { boff = DFetch(); sprintf(tmp, "($%02X,%s)", boff,
565 iregs[reg]); break; }
567 { woff = DFetchW(); sprintf(tmp, "($%04X,%s)", woff,
568 iregs[reg]); break; }
569 case 11: sprintf(tmp, "(D,%s)", iregs[reg]); break;
571 { boff = DFetch(); sprintf(tmp, "($%02X,PC)", boff); break; }
573 { woff = DFetchW(); sprintf(tmp, "($%04X,PC)", woff); break; }
575 { woff = DFetchW(); sprintf(tmp, "[$%04X]", woff); break; }
576 default: strcpy(tmp, "??");
583 case 0: sprintf(tmp, ",%s+", iregs[reg]); break;
584 case 1: sprintf(tmp, ",%s++", iregs[reg]); break;
585 case 2: sprintf(tmp, ",-%s", iregs[reg]); break;
586 case 3: sprintf(tmp, ",--%s", iregs[reg]); break;
587 case 4: sprintf(tmp, ",%s", iregs[reg]); break;
588 case 5: sprintf(tmp, "(B),%s", iregs[reg]); break;
589 case 6: sprintf(tmp, "(A),%s", iregs[reg]); break;
591 { boff = DFetch(); sprintf(tmp, "($%02X),%s", boff,
592 iregs[reg]); break; }
594 { woff = DFetchW(); sprintf(tmp, "($%04X),%s", woff,
595 iregs[reg]); break; }
596 case 11: sprintf(tmp, "(D),%s", iregs[reg]); break;
598 { boff = DFetch(); sprintf(tmp, "($%02X),PC", boff); break; }
600 { woff = DFetchW(); sprintf(tmp, "($%04X),PC", woff); break; }
601 default: strcpy(tmp, "??");
605 sprintf(outbuf, "%s %s", mnem, tmp);
608 { operand = DFetch(); // Get IMM byte
609 sprintf(outbuf, "%s #$%02X", mnem, operand);
611 case 9: // Long Immediate
612 { loperand = DFetchW(); // Get IMM word
613 sprintf(outbuf, "%s #$%04X", mnem, loperand);
616 DisplayBytes(dpc, (looking_at_rom ? pcr : pcrB)); // Show bytes
617 cout << outbuf << endl; // display opcode & addressing, etc
618 dpc = (looking_at_rom ? pcr : pcrB); // Advance debug PC
619 pcr = pc_save; pcrB = pcB_save; // Restore PCs
623 // Convert hex to dec
625 uint16 htod(char *str)
628 int len = strlen(str);
630 for(int i=0; i<len; i++)
632 if (str[i]>='0' && str[i]<='9')
634 value = (value<<4) | (unsigned)(str[i]-'0');
636 if (str[i]>='a' && str[i]<='f')
638 value = (value<<4) | (unsigned)(str[i]-'a')+10;
640 if (str[i]>='A' && str[i]<='F')
642 value = (value<<4) | (unsigned)(str[i]-'A')+10;
649 // Load 32K file into ROM image space
651 bool Load32KImg(char * filename, uint16 address)
656 ff.open(filename, ios::binary | ios::in); // Open 'da file...
659 for(long i=0; i<32768; i++) // Read it in...
662 grom[address+i] = ch;
664 ff.close(); // Close 'da file...
670 // Generic Load file into image space
671 // (No error checking performed! Responsibility of caller!)
673 bool LoadImg(const char * filename, uint8 * mem, uint32 address, uint32 length)
679 strcpy(path, "./ROMs/");
680 strcat(path, filename);
681 // ff.open(filename, ios::binary | ios::in); // Open 'da file...
682 ff.open(path, ios::binary | ios::in); // Open 'da file...
685 for(uint32 i=0; i<length; i++) // Read it in...
690 ff.close(); // Close 'da file...
698 bool ReadColorPROMs(void)
703 extern uint8 palette[768]; // Screen physical palette
704 extern uint8 ccolor[256][8]; // Character color PROM values
705 extern uint8 scolor[128][16]; // Sprite color PROM values
707 ff1.open("./ROMs/"PROM3, ios::binary|ios::in);
710 for(int i=0; i<256; i++) // Load char pallete with PROM values
712 for(int j=0; j<8; j++)
715 ccolor[i][j] = (uint8)ch;
720 ff1.open("./ROMs/"PROM4, ios::binary|ios::in);
723 for(int i=0; i<128; i++) // Load sprite pallete with PROM values
725 for(int j=0; j<16; j++)
728 scolor[i][j] = (uint8)ch;
734 ff1.open("./ROMs/"PROM1, ios::binary|ios::in);
735 ff2.open("./ROMs/"PROM2, ios::binary|ios::in);
736 if (ff1) // If open was successful...
738 for(int i=0; i<768; i+=3)
741 palette[i] = (uint8)(ch&0x0F);
742 palette[i+1] = (uint8)(ch>>4);
744 palette[i+2] = (uint8)ch;
747 // Do palette stretching here... I.e. add 0 to hinyb 0, 1 to hinyb 1, etc.
749 for(int i=0; i<768; i++)
750 palette[i] = ((palette[i]<<4)&0xF0) | (palette[i]&0x0F);
761 bool UnpackFonts(void)
767 f1.open("./ROMs/"ROM7, ios::binary | ios::in);
768 f2.open("./ROMs/"ROM8, ios::binary | ios::in);
769 if ((!f1) || (!f2)) return false; // Return if not found...
770 for(long i=0; i<0x40000; i+=64)
772 for(int j=0; j<64; j+=8)
774 f1.get(b1); f1.get(b2); f2.get(b3);
775 b3 ^= 0xFF; // Invert top data...
776 chr_rom[i+j] = ((b3 & 0x80) >> 5) | ((b1 & 0x80) >> 6) | ((b1 & 0x08) >> 3);
777 chr_rom[i+j+1] = ((b3 & 0x40) >> 4) | ((b1 & 0x40) >> 5) | ((b1 & 0x04) >> 2);
778 chr_rom[i+j+2] = ((b3 & 0x20) >> 3) | ((b1 & 0x20) >> 4) | ((b1 & 0x02) >> 1);
779 chr_rom[i+j+3] = ((b3 & 0x10) >> 2) | ((b1 & 0x10) >> 3) | (b1 & 0x01);
780 chr_rom[i+j+4] = ((b3 & 0x08) >> 1) | ((b2 & 0x80) >> 6) | ((b2 & 0x08) >> 3);
781 chr_rom[i+j+5] = (b3 & 0x04) | ((b2 & 0x40) >> 5) | ((b2 & 0x04) >> 2);
782 chr_rom[i+j+6] = ((b3 & 0x02) << 1) | ((b2 & 0x20) >> 4) | ((b2 & 0x02) >> 1);
783 chr_rom[i+j+7] = ((b3 & 0x01) << 2) | ((b2 & 0x10) >> 3) | (b2 & 0x01);
789 f1.open("./ROMs/"ROM5, ios::binary | ios::in);
790 f2.open("./ROMs/"ROM6, ios::binary | ios::in);
791 for(long i=0x40000; i<0x60000; i+=64)
793 for(int j=0; j<64; j+=8)
795 f1.get(b1); f1.get(b2); f2.get(b3);
796 b3 ^= 0xFF; // Invert top data
797 chr_rom[i+j] = ((b3 & 0x80) >> 5) | ((b1 & 0x80) >> 6) | ((b1 & 0x08) >> 3);
798 chr_rom[i+j+1] = ((b3 & 0x40) >> 4) | ((b1 & 0x40) >> 5) | ((b1 & 0x04) >> 2);
799 chr_rom[i+j+2] = ((b3 & 0x20) >> 3) | ((b1 & 0x20) >> 4) | ((b1 & 0x02) >> 1);
800 chr_rom[i+j+3] = ((b3 & 0x10) >> 2) | ((b1 & 0x10) >> 3) | (b1 & 0x01);
801 chr_rom[i+j+4] = ((b3 & 0x08) >> 1) | ((b2 & 0x80) >> 6) | ((b2 & 0x08) >> 3);
802 chr_rom[i+j+5] = (b3 & 0x04) | ((b2 & 0x40) >> 5) | ((b2 & 0x04) >> 2);
803 chr_rom[i+j+6] = ((b3 & 0x02) << 1) | ((b2 & 0x20) >> 4) | ((b2 & 0x02) >> 1);
804 chr_rom[i+j+7] = ((b3 & 0x01) << 2) | ((b2 & 0x10) >> 3) | (b2 & 0x01);
809 return true; // Made it!
813 // Get length of sample from WAV format
815 uint32 GetWAVLength(fstream &file)
820 file.ignore(16); // Skip header BS
822 for(int i=0; i<2; i++)
824 file.get(ch); len = (int)(uint8)ch;
825 file.get(ch); len |= (int)(uint8)ch << 8;
826 file.get(ch); len |= (int)(uint8)ch << 16;
827 file.get(ch); len |= (int)(uint8)ch << 24;
829 file.ignore(len + 4); // Skip intermediate data
832 file.get(ch); len = (int)(uint8)ch; // & finally get length of data
833 file.get(ch); len |= (int)(uint8)ch << 8;
834 file.get(ch); len |= (int)(uint8)ch << 16;
835 file.get(ch); len |= (int)(uint8)ch << 24;
841 // Load PSG samples from disk
849 for(int i=0; i<16; i++)
853 psg_adrs[i] = NULL; // Zero out pointer
854 sprintf(file, "./sounds/psg%i.wav", i); // Create filename
856 fp.open(file, ios::binary | ios::in); // Attempt to open it...
860 len = GetWAVLength(fp); // Get WAV data length...
862 psg_adrs[i] = new uint8[len]; // Attempt to allocate space...
864 if (psg_adrs[i] != NULL)
866 for(int j=0; j<(signed)len; j++)
869 psg_adrs[i][j] = ch; // & load it in...
873 cout << "Found sample file: " << file << " [Length: " << dec << len << "]" << endl;
882 // Load FM samples from disk
890 for(int i=0; i<14; i++)
894 fm_adrs[i] = NULL; // Zero out pointer
895 sprintf(file, "./sounds/fm%i.wav", i); // Create filename
897 fp.open(file, ios::binary | ios::in); // Attempt to open it...
901 len = GetWAVLength(fp); // Get WAV length...
903 fm_adrs[i] = new uint8[len]; // Attempt to allocate space...
905 if (fm_adrs[i] != NULL)
907 for(int j=0; j<(signed)len; j++)
910 fm_adrs[i][j] = ch; // & load it in...
914 cout << "Found sample file: " << file << " [Length: " << dec << len
926 int main(int argc, char * argv[])
928 InitLog("thunder.log");
930 /* extern uint16 cpu1.pc, cpu1.s, cpu1.u, cpu1.x, cpu1.y; // Pull in vars from '6809.cpp'
931 extern uint8 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp;
934 extern uint16 cpu2.pc, cpu2.s, cpu2.u, cpu2.x, cpu2.y; // Pull in vars from '6809B.cpp'
935 extern uint8 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp;
937 extern bool illegalB;
938 extern void (* exec_op0[256])(); // Array of page zero opcode functions...
939 extern void (* exec_op1[256])(); // Array of page one opcode functions...
940 extern void (* exec_op2[256])(); // Array of page two opcode functions...
941 extern void (* exec_op0B[256])(); // Array of page zero opcode functions...
942 extern void (* exec_op1B[256])(); // Array of page one opcode functions...
943 extern void (* exec_op2B[256])(); // Array of page two opcode functions...*/
944 extern bool charbase; // From 'SCREEN.CPP'
945 // extern unsigned int vesa_memptr;
949 fstream ff; // Declare fstream without file hooks...
950 bool brk = false, brk2 = false; // Breakpoint set flag
951 uint16 brkpnt, brkpnt2; // Where the breakpoint is...
952 bool running; // CPU running state flag...
953 bool self_test = false; // Self-test switch
954 bool scr_type = false; // false=chars, true=pixels
955 uint16 debounce = 0; // Key de-bounce counter
956 uint16 fire_debounce = 0; // Fire button debounce counter
957 // bool refresh2 = true; // Default to 60 Hz...
958 uint8 x; // General placeholder...
959 bool active = true; // Program running flag
961 // SDL_Surface * screen = NULL; // SDL screen pointer
962 SDL_Event event; // SDL "event"
963 // int keyPressed; // SDL key pressed...
964 extern uint8 palette[768]; // Screen physical palette
965 uint32 ticks, oldTicks;
967 // tr.open("exe.log", ios::binary | ios::out); // Tracelog
969 cout << endl << "THUNDER v"THUNDER_VERSION" ";
970 cout << "by James Hammons" << endl;
971 cout << "Serial #20090723 / Prerelease" << endl;
972 cout << "(C) 2003, 2009 Underground Software" << endl << endl;
974 cout << "This emulator is free software. If you paid for it you were RIPPED OFF"
977 cout << "Initializing SDL..." << endl;
979 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
981 cout << "Couldn't initialize SDL: " << SDL_GetError() << endl;
985 SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder");
987 keys = SDL_GetKeyState(NULL); // Get the SDL keyboard matrix
989 cout << "Allocating memory..." << endl;
990 //Does this anyway... set_new_handler(0); // Make 'new' return NULL on failure...
991 gram1 = new uint8[0x10000];
992 if (gram1 == NULL) { cout << "Could not allocate RAM space #1!" << endl
993 << "Aborting!" << endl; return -1; }
994 grom1 = new uint8[0x10000];
995 if (grom1 == NULL) { cout << "Could not allocate ROM space #1!" << endl
996 << "Aborting!" << endl; return -1; }
997 gram2 = new uint8[0x10000];
998 if (gram2 == NULL) { cout << "Could not allocate RAM space #2!" << endl
999 << "Aborting!" << endl; return -1; }
1000 grom2 = new uint8[0x10000];
1001 if (grom2 == NULL) { cout << "Could not allocate ROM space #2!" << endl
1002 << "Aborting!" << endl; return -1; }
1003 chr_rom = new uint8[0x60000];
1004 if (chr_rom == NULL) { cout << "Could not allocate character RAM!" << endl
1005 << "Aborting!" << endl; return -1; }
1006 grom3 = new uint8[0x8000];
1007 if (grom3 == NULL) { cout << "Could not allocate ROM space #4!" << endl
1008 << "Aborting!" << endl; return -1; }
1009 grom4 = new uint8[0x8000];
1010 if (grom4 == NULL) { cout << "Could not allocate ROM space #5!" << endl
1011 << "Aborting!" << endl; return -1; }
1012 data_rom = new uint8[0x40000];
1013 if (data_rom == NULL) { cout << "Could not allocate ROM level data!" << endl
1014 << "Aborting!" << endl; return -1; }
1015 spr_rom = new uint8[0x80000];
1016 if (spr_rom == NULL) { cout << "Could not allocate ROM sprite data!" << endl
1017 << "Aborting!" << endl; return -1; }
1018 voice_rom = new uint8[0x20000];
1019 if (voice_rom == NULL) { cout << "Could not allocate ROM voice data!" << endl
1020 << "Aborting!" << endl; return -1; }
1022 gram = gram1; grom = grom1; // Needed only for debugger
1024 for(long i=0; i<0x10000; i++)
1026 gram[i] = 0; grom[i] = 0; // Zero out memory
1027 gram2[i] = 0; grom2[i] = 0;
1029 game_over_switch = 0; // Init game over delay
1030 // 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;
1032 cout << "Loading ROMs..." << endl;
1033 // LoadCMOS(); // Load CMOS at $CC00-$CFFF
1034 if (!ReadColorPROMs()) // Load virtual PROMs
1035 { cout << "Could not open PROM files!" << endl; return -1; }
1037 if (!LoadImg(ROM1, grom1, 0x8000, 0x8000)) // Load $8000-$FFFF 1st ROM
1038 { cout << "Could not open file '" << ROM1 << "'!" << endl; return -1; }
1040 if (!LoadImg(ROM2, grom2, 0x8000, 0x8000)) // Load $8000-$FFFF 2nd ROM
1041 { cout << "Could not open file '" << ROM2 << "'!" << endl; return -1; }
1043 if (!LoadImg(ROM3, grom3, 0, 0x8000)) // Load 3rd ROM into its own space
1044 { cout << "Could not open file '" << ROM3 << "'!" << endl; return -1; }
1046 if (!LoadImg(ROM4, grom4, 0, 0x8000)) // Load 4rd ROM into its own space
1047 { cout << "Could not open file '" << ROM4 << "'!" << endl; return -1; }
1049 if (!LoadImg(ROM17, data_rom, 0, 0x10000)) // Load 17th ROM
1050 { cout << "Could not open file '" << ROM17 << "'!" << endl; return -1; }
1052 if (!LoadImg(ROM18, data_rom, 0x10000, 0x10000)) // Load 18th ROM
1053 { cout << "Could not open file '" << ROM18 << "'!" << endl; return -1; }
1055 if (!LoadImg(ROM19, data_rom, 0x20000, 0x10000)) // Load 19th ROM
1056 { cout << "Could not open file '" << ROM19 << "'!" << endl; return -1; }
1058 if (!LoadImg(ROM20, data_rom, 0x30000, 0x10000)) // Load 20th ROM
1059 { cout << "Could not open file '" << ROM20 << "'!" << endl; return -1; }
1061 if (!LoadImg(ROM9, spr_rom, 0, 0x10000)) // Load 9th ROM
1062 { cout << "Could not open file '" << ROM9 << "'!" << endl; return -1; }
1064 if (!LoadImg(ROM10, spr_rom, 0x10000, 0x10000)) // Load 10th ROM
1065 { cout << "Could not open file '" << ROM10 << "'!" << endl; return -1; }
1067 if (!LoadImg(ROM11, spr_rom, 0x20000, 0x10000)) // Load 11th ROM
1068 { cout << "Could not open file '" << ROM11 << "'!" << endl; return -1; }
1070 if (!LoadImg(ROM12, spr_rom, 0x30000, 0x10000)) // Load 12th ROM
1071 { cout << "Could not open file '" << ROM12 << "'!" << endl; return -1; }
1073 if (!LoadImg(ROM13, spr_rom, 0x40000, 0x10000)) // Load 13th ROM
1074 { cout << "Could not open file '" << ROM13 << "'!" << endl; return -1; }
1076 if (!LoadImg(ROM14, spr_rom, 0x50000, 0x10000)) // Load 14th ROM
1077 { cout << "Could not open file '" << ROM14 << "'!" << endl; return -1; }
1079 if (!LoadImg(ROM15, spr_rom, 0x60000, 0x10000)) // Load 15th ROM
1080 { cout << "Could not open file '" << ROM15 << "'!" << endl; return -1; }
1082 if (!LoadImg(ROM16, spr_rom, 0x70000, 0x10000)) // Load 16th ROM
1083 { cout << "Could not open file '" << ROM16 << "'!" << endl; return -1; }
1085 if (!LoadImg(ROM21, voice_rom, 0, 0x10000)) // Load 21st ROM
1086 { cout << "Could not open file '" << ROM21 << "'!" << endl; return -1; }
1088 if (!LoadImg(ROM22, voice_rom, 0x10000, 0x10000)) // Load 22nd ROM
1089 { cout << "Could not open file '" << ROM22 << "'!" << endl; return -1; }
1091 if (!UnpackFonts()) // Load 5, 6, 7, 8th ROMs
1093 cout << "Could not open font files!" << endl;
1097 // Load samples if they're there...
1101 // Quick 'n' Dirty voice dump (sound 0x0E)
1102 /* uint32 adc = (voice_rom[26]<<8) | voice_rom[27];
1103 bool doneWitIt = false;
1107 if (voice_rom[adc] < 0x10) tr << "0";
1108 tr << hex << (int)voice_rom[adc] << " ";
1109 if (crh++ > 24) { crh = 0; tr << endl; }
1110 if ((voice_rom[adc] == 0xFF) && (voice_rom[adc-1] != 0x00))
1115 // Set up V6809 execution contexts
1117 memset(&cpu1, 0, sizeof(V6809REGS));
1120 cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
1122 memset(&cpu2, 0, sizeof(V6809REGS));
1123 cpu2.RdMem = RdMemB;
1124 cpu2.WrMem = WrMemB;
1125 cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
1127 bool firstTime = true; // kludge...
1129 WriteLog("About to go to the main loop...\n");
1135 firstTime = false; // crappy kludge...
1142 if (lbuff[0] == 'd')
1149 printf("%04X: ", dpc);
1150 uint16 pc_save = cpu1.pc, pcB_save = cpu2.pc;
1151 cpu1.pc = dpc; cpu2.pc = dpc;
1152 for(int i=0; i<16; i++)
1153 printf("%02X ", (looking_at_rom ? Fetch() : FetchB()));
1155 cpu1.pc = dpc; cpu2.pc = dpc;
1156 for(int i=0; i<16; i++)
1158 uint8 a = (looking_at_rom ? Fetch() : FetchB());
1159 if (a<10) cout << (char)(a+48);
1160 if ((a>9) && (a<37)) cout << (char)(a+55);
1161 if (a>36) cout << ".";
1164 dpc = (looking_at_rom ? cpu1.pc : cpu2.pc);
1165 cpu1.pc = pc_save; cpu2.pc = pcB_save;
1167 else if (lbuff[0] == 'e')
1174 printf("%04X: ", dpc);
1175 for(int i=0; i<16; i++) printf("%02X ", (uint8)gram[dpc++]);
1178 else if (lbuff[0] == 'l')
1185 for(int i=0; i<23; i++)
1188 else if (lbuff[0] == 't')
1199 Execute6809(&cpu1, 1);
1201 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1202 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1203 cout << " iclock=" << cpu1.clock << endl;
1209 Execute6809(&cpu2, 1);
1211 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1212 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1213 cout << " iclock=" << cpu2.clock << endl;
1216 else if ((lbuff[0] == 'r') || (lbuff[0] == 'c')) // Run/continue...
1218 WriteLog("Executing 'run' command...\n");
1219 uint32 my_clock = 0;
1220 running = true; // Set running status...
1222 SetRefreshRate(refresh2); // Tell GUI our refresh rate
1223 //for(uint16 i=0; i<0x8000; i++) gram2[i] = grom3[i]; //Temp
1225 if (lbuff[0] == 'r') // If run, then reset CPUs
1227 WriteLog("Executing secondary 'run' command...\n");
1228 gram1[0x4182] = 0xA6; // Temp kludge
1229 gram1[0x4184] = 0xA6;
1230 gram1[0x4183] = 0x00; // More of the same
1231 gram1[0x4185] = 0x00;
1232 banksw1 = 0; // Will this work?
1234 // iclock = 0; // Reset instr clock #1...
1235 InitGUI(); // Reset # of coins
1237 /* cpu1.pc = ((grom1[0xFFFE]<<8) | grom1[0xFFFF]); // Reset 6809 #1
1240 lbuff[0] = 32; cpu1.pc = htod(lbuff);
1242 else cpu1.cc = 0xFF; // Set CC register
1244 cpu2.pc = ((grom2[0xFFFE]<<8) | grom2[0xFFFF]); // Reset 6809 #2
1245 cpu2.cc = 0xFF; // Set CC register
1246 while(iclock < 8000) // was 17000, 20000, 5000
1248 Execute6809(&cpu1, 1); Execute6809(&cpu2, 1);
1250 WriteLog("--> CPU clock #1: %u\n", cpu1.clock);
1251 // Will *this* help video sync?
1252 while (cpu1.clock < 8000) // was 17000, 20000, 5000
1254 Execute6809(&cpu1, 1);
1255 Execute6809(&cpu2, 1);
1259 WriteLog("About to set up screen...\n");
1260 // if (!SetVESA2()) running = false; // Set up screen
1261 // Set up screen (windowed)
1262 screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); //video_bpp, videoflags);
1265 cout << "Failed to initialize screen!" << endl;
1269 SDL_Color colors[256];
1270 for(int i=0; i<256; i++)
1272 colors[i].r = palette[i*3+0];
1273 colors[i].g = palette[i*3+1];
1274 colors[i].b = palette[i*3+2];
1276 SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256);
1279 // This confirms that we're getting video to the screen...
1280 SDL_LockSurface(screen);
1283 uint8 * pixels = (uint8 *)(screen->pixels);
1285 for(uint32 y=0; y<480; y++)
1286 for(uint32 x=0; x<640; x++)
1287 pixels[(y * 640) + x] = pixel++;
1289 SDL_UnlockSurface(screen);
1290 SDL_UpdateRect(screen, 0, 0, 0, 0);
1293 for(int i=0; i<256; i++)
1294 keys[i] = 0; // Clear keyboard buffer...
1296 oldTicks = SDL_GetTicks();
1298 WriteLog("About to set up audio...\n");
1299 // This crap SHOULD be in sound.cpp (not yet created)...
1300 SDL_AudioSpec desired, obtained;
1301 desired.freq = 22050;
1302 desired.format = AUDIO_U8;
1303 desired.channels = 1;
1304 desired.samples = 600;
1305 desired.callback = SoundFunc;
1306 desired.userdata = NULL;
1307 // Also, should check to see if it got the hardware it needed, correct sample size, etc.
1308 if (SDL_OpenAudio(&desired, &obtained) < 0)
1310 cout << "Couldn't open audio: " << SDL_GetError() << endl;
1313 SDL_PauseAudio(0); // Get that audio going!
1315 WriteLog("About to enter main loop...\n");
1318 HandleGUIDebounce(); // Debounce GUI keys
1319 if (game_over_switch)
1321 game_over_switch--; // Countdown...
1322 if (game_over_switch == 0)
1323 gram1[0x4380] = 0; // Kill music!
1325 //gram1[0x423D] = self_test; // Reset DSW1-1
1326 gram1[0x4268] = 0; // Reset Video test
1327 gram1[0x427A] = 0; gram1[0x427C] = 0;
1328 gram1[0x427B] = 0; gram1[0x427D] = 0;
1329 gram1[0x427E] = 0; gram1[0x427F] = 0;
1330 gram1[0x4280] = 0; gram1[0x4281] = 0;
1331 gram1[0x4276] = 0; gram1[0x426A] = 0;
1332 gram1[0x4278] = 0; gram1[0x426C] = 0;
1333 gram1[0x4262] = 0; gram1[0x4260] = 0;
1334 //gram1[0x4247] = 0;
1336 // SDL key handling...
1338 #warning "KEYS ARE FUCKED UP! !!! FIX !!!"
1339 SDL_PumpEvents(); // Force key events into the buffer.
1340 // keyPressed = 0; // Reset keypress
1341 // while (SDL_PollEvent(&event) != 0) // Bleed out all pending key events...
1343 // if (event.type == SDL_KEYDOWN)
1344 // keys[event.key.keysym.scancode] = 1;
1345 // if (event.type == SDL_KEYUP)
1346 // keys[event.key.keysym.scancode] = 0;
1350 if (keys[SDLK_ESCAPE])
1351 running = false; // ESC to exit...
1354 debounce--; // Debounce toggle keys...
1359 self_test = !self_test; // Self-test (F1-toggle)
1360 debounce = 10; // Key debounce value...
1364 gram1[0x4268] = 1; // Video test (F2)
1365 debounce = 10; // Key debounce value...
1369 scr_type = !scr_type; // Toggle screen (F12)
1370 debounce = 10; // Key debounce value...
1374 show_scr = !show_scr; // Toggle bkgrnd (F3)
1379 enable_cpu = !enable_cpu; // Toggle CPUs (F6)
1384 refresh2 = !refresh2; // Toggle 30/60Hz (F5)
1385 SetRefreshRate(refresh2); // Inform GUI of refresh
1390 debounce = 10; // Key debounce value...
1392 if (keys[SDLK_F4]) // Do PCX snapshot (F4)
1394 SpawnSound(USERSOUND, SCAMERA);
1398 if (keys[SDLK_TAB]) // Tab active/deactivate GUI
1407 //if (keys[0x3E]) gram1[0x4247] = 1; // Screen hold DS (F4)
1408 if (keys[SDLK_RIGHT]) // Right arrow
1411 SelectRight(); // If GUI active...
1414 if (!keys[SDLK_LEFT]) // Disallow opposite directions @ same time
1415 gram1[0x427F] = 1; // Stick right
1418 if (keys[SDLK_LEFT])
1421 SelectLeft(); // If GUI active...
1424 if (!keys[SDLK_RIGHT]) // Disallow opposite directions@same time
1425 gram1[0x4281] = 1; // Left arrow
1431 SelectUp(); // If GUI active...
1434 if (!keys[SDLK_DOWN]) // Disallow opposite directions@same time
1435 gram1[0x427B] = 1; // Up arrow
1438 if (keys[SDLK_DOWN])
1441 SelectDown(); // If GUI active...
1444 if (!keys[SDLK_UP]) // Disallow opposite directions@same time
1445 gram1[0x427D] = 1; // Down arrow
1448 if (keys[SDLK_RETURN]) // Return
1450 uint8 retval = UserSelectedSomething();
1453 if (retval == REFRESH)
1455 refresh2 = !refresh2;
1456 SetRefreshRate(refresh2);
1460 gram1[0x427A] = 1; // (1)
1462 gram1[0x427C] = 1; // (2)
1464 gram1[0x427E] = 1; // (3)
1466 gram1[0x4280] = 1; // (5)
1467 if (keys[0x10]|keys[29])
1468 gram1[0x4276] = 1; // (Q) Jump
1470 gram1[0x426A] = 1; // (W)
1473 if (keys[0x12]|keys[56]) // (E) Fire
1478 if (gram1[0x3F08] == 0xFF) // Ugly kludge for debouncing gun
1489 gram1[0x426C] = 1; // (R)
1491 gram1[0x4262] = 1; // (T)
1493 gram1[0x4260] = 1; // (Y)
1495 gram1[0x41A5]++; // Coin? (F10)
1497 gram1[0x4189]++; // ? (Z) credits l dig
1499 gram1[0x418A]++; // ? (X) credits r dig
1501 gram1[0x418C]++; // ? (C) Start
1503 gram1[0x418D]++; // ? (V)
1505 SpawnSound(USERSOUND, 0); // Do user sound (F7)
1508 // gram1[0x4380] = 0; // (F8) kill music (this worx)
1509 // charbase = false; // Switch chars out...
1511 // if (keys[0x43]) gram1[0x4285] = 1; // (F9) strobe unknown loc
1512 if (keys[SDLK_F1]) // (F11)
1514 Execute6809(&cpu1, 10);
1515 Execute6809(&cpu2, 10);
1523 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1525 Execute6809(&cpu1, 25000);
1526 cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)
1529 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1531 Execute6809(&cpu2, 25000);
1532 cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/
1534 // cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1535 // cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1536 while (cpu1.clock < 25000)
1538 // Gay, but what are ya gonna do?
1539 Execute6809(&cpu1, 5);
1540 Execute6809(&cpu2, 5);
1543 cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)
1544 cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/
1546 } // END: enable_cpu
1548 // if (refresh_++ == 1) // 30 Hz...
1551 // BlitWilliamsScreen(gram1); // Display the screen...
1553 // BlitChar(screen, chr_rom, gram1);
1554 // refresh_ = (refresh2 ? 1 : 0); // 60/30 Hz...
1556 //temp, for testing...
1557 BlitChar(screen, chr_rom, gram1);
1559 // Speed throttling happens here...
1560 while (SDL_GetTicks() - oldTicks < 16) // Actually, it's 16.66... Need to account for that somehow
1561 SDL_Delay(1); // Release our timeslice...
1563 oldTicks = SDL_GetTicks();
1564 //cout << "Finished frame..." << endl;
1567 // Stop_audio_output();
1569 // ReleaseKeyboard(); // Release the interrupt...
1570 // RestoreOldMode(); // Restore screen
1571 if (brk && (cpu1.pc == brkpnt))
1572 cout << "CPU 1: Break at " << hex << cpu1.pc << endl;
1573 if (brk2 && (cpu2.pc == brkpnt2))
1574 cout << "CPU 2: Break at " << hex << cpu2.pc << endl;
1576 lbuff[0] = 'q'; // Temp kludge...
1578 else if (lbuff[0] == 'b') // Set/clear breakpoint
1583 brkpnt = htod(lbuff);
1585 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1590 cout << "Breakpoint cleared" << endl;
1593 else if (lbuff[0] == 'a') // Set/clear breakpoint #2
1598 brkpnt2 = htod(lbuff);
1600 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1605 cout << "Breakpoint cleared" << endl;
1608 else if (lbuff[0] == 'i') // Inspect registers
1610 printf("CPU1: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1611 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1612 cout << " iclk=" << dec << cpu1.clock << endl;
1613 printf("CPU2: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1614 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1615 cout << " iclk=" << dec << cpu2.clock << endl;
1617 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1619 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1621 else if (strncmp(lbuff, "swap", 4) == 0) // Swap ROMs
1623 looking_at_rom = !looking_at_rom;
1624 cout << "Swapped: Looking at ";
1625 (looking_at_rom ? cout << "ROM #1" : cout << "ROM #2");
1628 else if (strncmp(lbuff, "seek", 4) == 0) // Seek non-zero bytes in RAM
1632 for(int i=0; i<4; i++)
1640 while ((x == 0) && (dpc != 0xFFFF)); // Keep going until something found
1643 printf("%04X: ", dpc); // Show data found...
1644 for(int i=0; i<16; i++)
1645 printf("%02X ", gram1[(uint16)(dpc+i)]);
1647 for(int i=0; i<16; i++)
1649 uint8 a = gram1[dpc++];
1651 cout << (char)(a+48);
1652 if ((a>9) && (a<37))
1653 cout << (char)(a+55);
1659 else if (lbuff[0] == 'v') // View screen
1661 // SetVESA2(); // Set up screen
1662 BlitChar(screen, chr_rom, gram1);
1664 // RestoreOldMode();
1667 if (lbuff[0] == 'q')
1668 active = false; //break; // Quit
1671 SDL_Quit(); // Shut down SDL
1673 delete[] gram1; // Deallocate RAM & ROM spaces
1684 for(int i=0; i<16; i++)
1685 if (psg_adrs[i] != NULL)
1686 delete[] psg_adrs[i]; // Deallocate if loaded
1688 for(int i=0; i<14; i++)
1689 if (fm_adrs[i] != NULL)
1690 delete[] fm_adrs[i]; // Deallocate if loaded
1692 // tr.close(); // Close tracelog