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 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 WriteLog("%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 WriteLog("%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 RdMem(dpc); }
458 uint16 FetchW(void) { return (uint16)((RdMem(dpc) << 8) | RdMem(dpc+1)); }
459 uint8 FetchB(void) { return RdMemB(dpc); }
460 uint16 FetchWB(void) { return (uint16)((RdMemB(dpc) << 8) | RdMemB(dpc+1)); }
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 WriteLog(outbuf); WriteLog("\n"); // 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 bool charbase; // From 'SCREEN.CPP'
934 fstream ff; // Declare fstream without file hooks...
935 bool brk = false, brk2 = false; // Breakpoint set flag
936 uint16 brkpnt, brkpnt2; // Where the breakpoint is...
937 bool running; // CPU running state flag...
938 bool self_test = false; // Self-test switch
939 bool scr_type = false; // false=chars, true=pixels
940 uint16 debounce = 0; // Key de-bounce counter
941 uint16 fire_debounce = 0; // Fire button debounce counter
942 // bool refresh2 = true; // Default to 60 Hz...
943 uint8 x; // General placeholder...
944 bool active = true; // Program running flag
946 SDL_Event event; // SDL "event"
947 extern uint8 palette[768]; // Screen physical palette
948 uint32 ticks, oldTicks;
950 cout << endl << "THUNDER v"THUNDER_VERSION" ";
951 cout << "by James Hammons" << endl;
952 cout << "Serial #20090723 / Prerelease" << endl;
953 cout << "(C) 2003, 2009 Underground Software" << endl << endl;
955 cout << "This emulator is free software. If you paid for it you were RIPPED OFF"
958 cout << "Initializing SDL..." << endl;
960 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
962 cout << "Couldn't initialize SDL: " << SDL_GetError() << endl;
966 SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder");
968 keys = SDL_GetKeyState(NULL); // Get the SDL keyboard matrix
971 cout << "Allocating memory..." << endl;
972 //Does this anyway... set_new_handler(0); // Make 'new' return NULL on failure...
973 gram1 = new uint8[0x10000];
974 if (gram1 == NULL) { cout << "Could not allocate RAM space #1!" << endl
975 << "Aborting!" << endl; return -1; }
976 grom1 = new uint8[0x10000];
977 if (grom1 == NULL) { cout << "Could not allocate ROM space #1!" << endl
978 << "Aborting!" << endl; return -1; }
979 gram2 = new uint8[0x10000];
980 if (gram2 == NULL) { cout << "Could not allocate RAM space #2!" << endl
981 << "Aborting!" << endl; return -1; }
982 grom2 = new uint8[0x10000];
983 if (grom2 == NULL) { cout << "Could not allocate ROM space #2!" << endl
984 << "Aborting!" << endl; return -1; }
985 chr_rom = new uint8[0x60000];
986 if (chr_rom == NULL) { cout << "Could not allocate character RAM!" << endl
987 << "Aborting!" << endl; return -1; }
988 grom3 = new uint8[0x8000];
989 if (grom3 == NULL) { cout << "Could not allocate ROM space #4!" << endl
990 << "Aborting!" << endl; return -1; }
991 grom4 = new uint8[0x8000];
992 if (grom4 == NULL) { cout << "Could not allocate ROM space #5!" << endl
993 << "Aborting!" << endl; return -1; }
994 data_rom = new uint8[0x40000];
995 if (data_rom == NULL) { cout << "Could not allocate ROM level data!" << endl
996 << "Aborting!" << endl; return -1; }
997 spr_rom = new uint8[0x80000];
998 if (spr_rom == NULL) { cout << "Could not allocate ROM sprite data!" << endl
999 << "Aborting!" << endl; return -1; }
1000 voice_rom = new uint8[0x20000];
1001 if (voice_rom == NULL) { cout << "Could not allocate ROM voice data!" << endl
1002 << "Aborting!" << endl; return -1; }
1005 gram = gram1; grom = grom1; // Needed only for debugger
1007 for(long i=0; i<0x10000; i++)
1009 gram[i] = 0; grom[i] = 0; // Zero out memory
1010 gram2[i] = 0; grom2[i] = 0;
1012 game_over_switch = 0; // Init game over delay
1013 // 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;
1015 cout << "Loading ROMs..." << endl;
1016 // LoadCMOS(); // Load CMOS at $CC00-$CFFF
1017 if (!ReadColorPROMs()) // Load virtual PROMs
1018 { cout << "Could not open PROM files!" << endl; return -1; }
1020 if (!LoadImg(ROM1, grom1, 0x8000, 0x8000)) // Load $8000-$FFFF 1st ROM
1021 { cout << "Could not open file '" << ROM1 << "'!" << endl; return -1; }
1023 if (!LoadImg(ROM2, grom2, 0x8000, 0x8000)) // Load $8000-$FFFF 2nd ROM
1024 { cout << "Could not open file '" << ROM2 << "'!" << endl; return -1; }
1026 if (!LoadImg(ROM3, grom3, 0, 0x8000)) // Load 3rd ROM into its own space
1027 { cout << "Could not open file '" << ROM3 << "'!" << endl; return -1; }
1029 if (!LoadImg(ROM4, grom4, 0, 0x8000)) // Load 4rd ROM into its own space
1030 { cout << "Could not open file '" << ROM4 << "'!" << endl; return -1; }
1032 if (!LoadImg(ROM17, data_rom, 0, 0x10000)) // Load 17th ROM
1033 { cout << "Could not open file '" << ROM17 << "'!" << endl; return -1; }
1035 if (!LoadImg(ROM18, data_rom, 0x10000, 0x10000)) // Load 18th ROM
1036 { cout << "Could not open file '" << ROM18 << "'!" << endl; return -1; }
1038 if (!LoadImg(ROM19, data_rom, 0x20000, 0x10000)) // Load 19th ROM
1039 { cout << "Could not open file '" << ROM19 << "'!" << endl; return -1; }
1041 if (!LoadImg(ROM20, data_rom, 0x30000, 0x10000)) // Load 20th ROM
1042 { cout << "Could not open file '" << ROM20 << "'!" << endl; return -1; }
1044 if (!LoadImg(ROM9, spr_rom, 0, 0x10000)) // Load 9th ROM
1045 { cout << "Could not open file '" << ROM9 << "'!" << endl; return -1; }
1047 if (!LoadImg(ROM10, spr_rom, 0x10000, 0x10000)) // Load 10th ROM
1048 { cout << "Could not open file '" << ROM10 << "'!" << endl; return -1; }
1050 if (!LoadImg(ROM11, spr_rom, 0x20000, 0x10000)) // Load 11th ROM
1051 { cout << "Could not open file '" << ROM11 << "'!" << endl; return -1; }
1053 if (!LoadImg(ROM12, spr_rom, 0x30000, 0x10000)) // Load 12th ROM
1054 { cout << "Could not open file '" << ROM12 << "'!" << endl; return -1; }
1056 if (!LoadImg(ROM13, spr_rom, 0x40000, 0x10000)) // Load 13th ROM
1057 { cout << "Could not open file '" << ROM13 << "'!" << endl; return -1; }
1059 if (!LoadImg(ROM14, spr_rom, 0x50000, 0x10000)) // Load 14th ROM
1060 { cout << "Could not open file '" << ROM14 << "'!" << endl; return -1; }
1062 if (!LoadImg(ROM15, spr_rom, 0x60000, 0x10000)) // Load 15th ROM
1063 { cout << "Could not open file '" << ROM15 << "'!" << endl; return -1; }
1065 if (!LoadImg(ROM16, spr_rom, 0x70000, 0x10000)) // Load 16th ROM
1066 { cout << "Could not open file '" << ROM16 << "'!" << endl; return -1; }
1068 if (!LoadImg(ROM21, voice_rom, 0, 0x10000)) // Load 21st ROM
1069 { cout << "Could not open file '" << ROM21 << "'!" << endl; return -1; }
1071 if (!LoadImg(ROM22, voice_rom, 0x10000, 0x10000)) // Load 22nd ROM
1072 { cout << "Could not open file '" << ROM22 << "'!" << endl; return -1; }
1074 if (!UnpackFonts()) // Load 5, 6, 7, 8th ROMs
1076 cout << "Could not open font files!" << endl;
1080 // Load samples if they're there...
1084 // Quick 'n' Dirty voice dump (sound 0x0E)
1085 /* uint32 adc = (voice_rom[26]<<8) | voice_rom[27];
1086 bool doneWitIt = false;
1090 if (voice_rom[adc] < 0x10) tr << "0";
1091 tr << hex << (int)voice_rom[adc] << " ";
1092 if (crh++ > 24) { crh = 0; tr << endl; }
1093 if ((voice_rom[adc] == 0xFF) && (voice_rom[adc-1] != 0x00))
1098 // Set up V6809 execution contexts
1100 memset(&cpu1, 0, sizeof(V6809REGS));
1103 cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
1105 memset(&cpu2, 0, sizeof(V6809REGS));
1106 cpu2.RdMem = RdMemB;
1107 cpu2.WrMem = WrMemB;
1108 cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
1110 bool firstTime = true; // kludge...
1112 WriteLog("About to go to the main loop...\n");
1118 firstTime = false; // crappy kludge...
1125 if (lbuff[0] == 'd')
1132 printf("%04X: ", dpc);
1133 uint16 pc_save = cpu1.pc, pcB_save = cpu2.pc;
1134 cpu1.pc = dpc; cpu2.pc = dpc;
1135 for(int i=0; i<16; i++)
1136 printf("%02X ", (looking_at_rom ? Fetch() : FetchB()));
1138 cpu1.pc = dpc; cpu2.pc = dpc;
1139 for(int i=0; i<16; i++)
1141 uint8 a = (looking_at_rom ? Fetch() : FetchB());
1142 if (a<10) cout << (char)(a+48);
1143 if ((a>9) && (a<37)) cout << (char)(a+55);
1144 if (a>36) cout << ".";
1147 dpc = (looking_at_rom ? cpu1.pc : cpu2.pc);
1148 cpu1.pc = pc_save; cpu2.pc = pcB_save;
1150 else if (lbuff[0] == 'e')
1157 printf("%04X: ", dpc);
1158 for(int i=0; i<16; i++) printf("%02X ", (uint8)gram[dpc++]);
1161 else if (lbuff[0] == 'l')
1168 for(int i=0; i<23; i++)
1171 else if (lbuff[0] == 't')
1182 Execute6809(&cpu1, 1);
1184 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1185 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1186 cout << " iclock=" << cpu1.clock << endl;
1192 Execute6809(&cpu2, 1);
1194 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1195 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1196 cout << " iclock=" << cpu2.clock << endl;
1199 else if ((lbuff[0] == 'r') || (lbuff[0] == 'c')) // Run/continue...
1201 WriteLog("Executing 'run' command...\n");
1202 uint32 my_clock = 0;
1203 running = true; // Set running status...
1205 SetRefreshRate(refresh2); // Tell GUI our refresh rate
1206 //for(uint16 i=0; i<0x8000; i++) gram2[i] = grom3[i]; //Temp
1208 if (lbuff[0] == 'r') // If run, then reset CPUs
1210 WriteLog("Executing secondary 'run' command...\n");
1211 gram1[0x4182] = 0xA6; // Temp kludge
1212 gram1[0x4184] = 0xA6;
1213 gram1[0x4183] = 0x00; // More of the same
1214 gram1[0x4185] = 0x00;
1215 banksw1 = 0; // Will this work?
1217 // iclock = 0; // Reset instr clock #1...
1218 InitGUI(); // Reset # of coins
1221 cpu1.pc = ((grom1[0xFFFE]<<8) | grom1[0xFFFF]); // Reset 6809 #1
1224 lbuff[0] = 32; cpu1.pc = htod(lbuff);
1226 else cpu1.cc = 0xFF; // Set CC register
1228 cpu2.pc = ((grom2[0xFFFE]<<8) | grom2[0xFFFF]); // Reset 6809 #2
1229 cpu2.cc = 0xFF; // Set CC register
1230 while(iclock < 8000) // was 17000, 20000, 5000
1232 Execute6809(&cpu1, 1); Execute6809(&cpu2, 1);
1236 WriteLog("--> CPU clock #1: %u\n", cpu1.clock);
1237 // Will *this* help video sync? NO
1238 while (cpu1.clock < 8000) // was 17000, 20000, 5000
1240 Execute6809(&cpu1, 1);
1241 Execute6809(&cpu2, 1);
1246 WriteLog("About to set up screen...\n");
1247 // if (!SetVESA2()) running = false; // Set up screen
1248 // Set up screen (windowed)
1249 screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); //video_bpp, videoflags);
1252 cout << "Failed to initialize screen!" << endl;
1256 SDL_Color colors[256];
1257 for(int i=0; i<256; i++)
1259 colors[i].r = palette[i*3+0];
1260 colors[i].g = palette[i*3+1];
1261 colors[i].b = palette[i*3+2];
1263 SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256);
1266 // This confirms that we're getting video to the screen...
1267 SDL_LockSurface(screen);
1270 uint8 * pixels = (uint8 *)(screen->pixels);
1272 for(uint32 y=0; y<480; y++)
1273 for(uint32 x=0; x<640; x++)
1274 pixels[(y * 640) + x] = pixel++;
1276 SDL_UnlockSurface(screen);
1277 SDL_UpdateRect(screen, 0, 0, 0, 0);
1280 for(int i=0; i<256; i++)
1281 keys[i] = 0; // Clear keyboard buffer...
1283 oldTicks = SDL_GetTicks();
1285 WriteLog("About to set up audio...\n");
1286 // This crap SHOULD be in sound.cpp (not yet created)...
1287 SDL_AudioSpec desired, obtained;
1288 desired.freq = 22050;
1289 desired.format = AUDIO_U8;
1290 desired.channels = 1;
1291 desired.samples = 600;
1292 desired.callback = SoundFunc;
1293 desired.userdata = NULL;
1294 // Also, should check to see if it got the hardware it needed, correct sample size, etc.
1295 if (SDL_OpenAudio(&desired, &obtained) < 0)
1297 cout << "Couldn't open audio: " << SDL_GetError() << endl;
1300 SDL_PauseAudio(0); // Get that audio going!
1302 WriteLog("About to enter main loop...\n");
1305 HandleGUIDebounce(); // Debounce GUI keys
1306 if (game_over_switch)
1308 game_over_switch--; // Countdown...
1309 if (game_over_switch == 0)
1310 gram1[0x4380] = 0; // Kill music!
1312 //gram1[0x423D] = self_test; // Reset DSW1-1
1313 gram1[0x4268] = 0; // Reset Video test
1314 gram1[0x427A] = 0; gram1[0x427C] = 0;
1315 gram1[0x427B] = 0; gram1[0x427D] = 0;
1316 gram1[0x427E] = 0; gram1[0x427F] = 0;
1317 gram1[0x4280] = 0; gram1[0x4281] = 0;
1318 gram1[0x4276] = 0; gram1[0x426A] = 0;
1319 gram1[0x4278] = 0; gram1[0x426C] = 0;
1320 gram1[0x4262] = 0; gram1[0x4260] = 0;
1321 //gram1[0x4247] = 0;
1323 // SDL key handling...
1325 SDL_PumpEvents(); // Force key events into the buffer.
1327 if (keys[SDLK_ESCAPE])
1328 running = false; // ESC to exit...
1331 debounce--; // Debounce toggle keys...
1336 self_test = !self_test; // Self-test (F1-toggle)
1337 debounce = 10; // Key debounce value...
1341 gram1[0x4268] = 1; // Video test (F2)
1342 debounce = 10; // Key debounce value...
1346 scr_type = !scr_type; // Toggle screen (F12)
1347 debounce = 10; // Key debounce value...
1351 show_scr = !show_scr; // Toggle bkgrnd (F3)
1356 enable_cpu = !enable_cpu; // Toggle CPUs (F6)
1361 refresh2 = !refresh2; // Toggle 30/60Hz (F5)
1362 SetRefreshRate(refresh2); // Inform GUI of refresh
1367 debounce = 10; // Key debounce value...
1369 if (keys[SDLK_F4]) // Do PCX snapshot (F4)
1371 SpawnSound(USERSOUND, SCAMERA);
1375 if (keys[SDLK_TAB]) // Tab active/deactivate GUI
1384 //if (keys[0x3E]) gram1[0x4247] = 1; // Screen hold DS (F4)
1385 if (keys[SDLK_RIGHT]) // Right arrow
1388 SelectRight(); // If GUI active...
1391 if (!keys[SDLK_LEFT]) // Disallow opposite directions @ same time
1392 gram1[0x427F] = 1; // Stick right
1395 if (keys[SDLK_LEFT])
1398 SelectLeft(); // If GUI active...
1401 if (!keys[SDLK_RIGHT]) // Disallow opposite directions@same time
1402 gram1[0x4281] = 1; // Left arrow
1408 SelectUp(); // If GUI active...
1411 if (!keys[SDLK_DOWN]) // Disallow opposite directions@same time
1412 gram1[0x427B] = 1; // Up arrow
1415 if (keys[SDLK_DOWN])
1418 SelectDown(); // If GUI active...
1421 if (!keys[SDLK_UP]) // Disallow opposite directions@same time
1422 gram1[0x427D] = 1; // Down arrow
1425 if (keys[SDLK_RETURN]) // Return
1427 uint8 retval = UserSelectedSomething();
1430 if (retval == REFRESH)
1432 refresh2 = !refresh2;
1433 SetRefreshRate(refresh2);
1437 gram1[0x427A] = 1; // (1)
1439 gram1[0x427C] = 1; // (2)
1441 gram1[0x427E] = 1; // (3)
1443 gram1[0x4280] = 1; // (5)
1444 if (keys[SDLK_q] | keys[29])
1445 gram1[0x4276] = 1; // (Q) Jump
1447 gram1[0x426A] = 1; // (W)
1450 if (keys[SDLK_e] | keys[56]) // (E) Fire
1456 if (gram1[0x3F08] == 0xFF) // Ugly kludge for debouncing gun
1463 gram1[0x426C] = 1; // (R)
1465 gram1[0x4262] = 1; // (T)
1467 gram1[0x4260] = 1; // (Y)
1469 gram1[0x41A5]++; // Coin? (F10)
1471 gram1[0x4189]++; // ? (Z) credits l dig
1473 gram1[0x418A]++; // ? (X) credits r dig
1475 gram1[0x418C]++; // ? (C) Start
1477 gram1[0x418D]++; // ? (V)
1479 SpawnSound(USERSOUND, 0); // Do user sound (F7)
1480 // if (keys[SDLK_F8])
1482 // gram1[0x4380] = 0; // (F8) kill music (this worx)
1483 // charbase = false; // Switch chars out...
1485 // if (keys[SDLK_F9]) gram1[0x4285] = 1; // (F9) strobe unknown loc
1486 if (keys[SDLK_F11]) // (F11)
1488 Execute6809(&cpu1, 10);
1489 Execute6809(&cpu2, 10);
1492 //F12 is used above, but the values are ignored. So we'll do it here too.
1495 cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
1496 cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
1504 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1506 Execute6809(&cpu1, 25000);
1507 cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)
1510 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1512 Execute6809(&cpu2, 25000);
1513 cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/
1515 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1516 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1517 // while (cpu1.clock < 25000)
1518 for(uint32 i=0; i<250; i++)
1520 // Gay, but what are ya gonna do?
1521 // There's better ways, such as keeping track of when slave writes to master, etc...
1522 Execute6809(&cpu1, 100);
1523 Execute6809(&cpu2, 100);
1526 // cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)
1527 // cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/
1529 } // END: enable_cpu
1531 // if (refresh_++ == 1) // 30 Hz...
1534 // BlitWilliamsScreen(gram1); // Display the screen...
1536 // BlitChar(screen, chr_rom, gram1);
1537 // refresh_ = (refresh2 ? 1 : 0); // 60/30 Hz...
1540 //temp, for testing...
1541 BlitChar(screen, chr_rom, gram1);
1543 // Speed throttling happens here...
1544 while (SDL_GetTicks() - oldTicks < 16) // Actually, it's 16.66... Need to account for that somehow
1545 SDL_Delay(1); // Release our timeslice...
1547 oldTicks = SDL_GetTicks();
1548 //cout << "Finished frame..." << endl;
1551 // Stop_audio_output();
1553 // ReleaseKeyboard(); // Release the interrupt...
1554 // RestoreOldMode(); // Restore screen
1555 if (brk && (cpu1.pc == brkpnt))
1556 cout << "CPU 1: Break at " << hex << cpu1.pc << endl;
1557 if (brk2 && (cpu2.pc == brkpnt2))
1558 cout << "CPU 2: Break at " << hex << cpu2.pc << endl;
1560 lbuff[0] = 'q'; // Temp kludge...
1562 else if (lbuff[0] == 'b') // Set/clear breakpoint
1567 brkpnt = htod(lbuff);
1569 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1574 cout << "Breakpoint cleared" << endl;
1577 else if (lbuff[0] == 'a') // Set/clear breakpoint #2
1582 brkpnt2 = htod(lbuff);
1584 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1589 cout << "Breakpoint cleared" << endl;
1592 else if (lbuff[0] == 'i') // Inspect registers
1594 printf("CPU1: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1595 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1596 cout << " iclk=" << dec << cpu1.clock << endl;
1597 printf("CPU2: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1598 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1599 cout << " iclk=" << dec << cpu2.clock << endl;
1601 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1603 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1605 else if (strncmp(lbuff, "swap", 4) == 0) // Swap ROMs
1607 looking_at_rom = !looking_at_rom;
1608 cout << "Swapped: Looking at ";
1609 (looking_at_rom ? cout << "ROM #1" : cout << "ROM #2");
1612 else if (strncmp(lbuff, "seek", 4) == 0) // Seek non-zero bytes in RAM
1616 for(int i=0; i<4; i++)
1624 while ((x == 0) && (dpc != 0xFFFF)); // Keep going until something found
1627 printf("%04X: ", dpc); // Show data found...
1628 for(int i=0; i<16; i++)
1629 printf("%02X ", gram1[(uint16)(dpc+i)]);
1631 for(int i=0; i<16; i++)
1633 uint8 a = gram1[dpc++];
1635 cout << (char)(a+48);
1636 if ((a>9) && (a<37))
1637 cout << (char)(a+55);
1643 else if (lbuff[0] == 'v') // View screen
1645 // SetVESA2(); // Set up screen
1646 BlitChar(screen, chr_rom, gram1);
1648 // RestoreOldMode();
1651 if (lbuff[0] == 'q')
1652 active = false; //break; // Quit
1655 SDL_Quit(); // Shut down SDL
1658 delete[] gram1; // Deallocate RAM & ROM spaces
1670 for(int i=0; i<16; i++)
1672 delete[] psg_adrs[i]; // Deallocate if loaded
1674 for(int i=0; i<14; i++)
1676 delete[] fm_adrs[i]; // Deallocate if loaded