]> Shamusworld >> Repos - thunder/blob - src/thunder.cpp
ed3f6c239377f124af84d5fd1b21a0e658c88bf6
[thunder] / src / thunder.cpp
1 //
2 // Thunder: A Rolling Thunder Emulator w/6809 debugger
3 //
4 // by James L. Hammons
5 // (c) 2004, 2009 Underground Software
6 //
7 // JLH = James L. Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  07/23/2009  Added changelog ;-)
12 //
13
14 #define THUNDER_VERSION       "0.9.9"
15
16 #include <iostream>
17 #include <iomanip>
18 #include <fstream>
19 #include <string>
20 #include <new>
21 #include <stdio.h>
22 #include <stdlib.h>
23 //#include <conio.h>                    // For getch()
24 #include <curses.h>                     // For getch()
25 #include <time.h>
26 #include "SDL.h"                                                                                // Get yer SDL out...!
27 #include "types.h"
28 #include "v6809.h"
29 #include "screen.h"
30 #include "gui.h"
31 #include "log.h"
32
33 using namespace std;                                                                    // Yes!
34
35 #if 0
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"
63 #else
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"
92 #endif
93
94 // Global defines
95
96 SDL_Surface * screen;
97
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
102
103 V6809REGS cpu1, cpu2;
104
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
114
115 uint16 refresh_ = 0;                // Crappy global screen stuff...
116 bool refresh2 = true;
117
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 };
124 uint8 * fm_adrs[14];
125
126 fstream tr;    // Tracelog hook
127 uint16    pcx;   // Where we at?
128
129 static uint8 * keys;                                                    // SDL raw keyboard matrix
130
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 },
148 op_mat2[256] = {
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 },
165 op_mat3[256] = {
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   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  " },
281 tregs[16][3] = {
282   "D",  "X", "Y",  "U",  "S",  "PC", "??", "??",
283   "A",  "B", "CC", "DP", "??", "??", "??", "??" },
284 iregs[4][2] = {"X", "Y", "U", "S" };
285
286 //
287 // Read a byte from memory (without touching PC. Not a Fetch!)
288 //
289 uint8 RdMem(uint16 addr)
290 {
291         uint8 b;
292
293         if (addr < 0x8000)
294         {
295                 if (addr > 0x5FFF)
296                         b = data_rom[banksw1 + (addr - 0x6000)];        // Get char data
297                 else
298                         b = gram1[addr];
299         }
300         else
301                 b = grom1[addr];
302
303         return b;
304 }
305
306 //
307 // Write a byte to memory
308 //
309 void WrMem(uint16 addr, uint8 b)
310 {
311         extern bool charbase;                                                           // Needed for screen. Extern it in it??
312   //extern uint16 sr, ur, xr, yr;            // Needed for tracelog
313   //extern uint16 pcr;
314 /*  if ((addr>0x40FF) && (addr<0x4390))
315   {
316     tr << hex << addr << ":" << (int)b;
317     //for(int i=0; i<32; i++)
318     //{
319     //  if (gram1[0x4400+i]<0x10)  tr << "0";
320     //  tr << hex << (uint16)gram1[0x4400+i] << " ";
321     //}
322     tr << endl;
323   }//*/
324
325         if (addr == 0x6000)
326                 SpawnSound(GAMESOUND, gram1[0x6200], 0);                // Do voice chan 1
327         if (addr == 0x6400)
328                 SpawnSound(GAMESOUND, gram1[0x6600], 1);                // Do voice chan 2
329         if (addr == 0x6800)
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
333         if (addr == 0x4380)
334         {
335                 SpawnSound(FMSOUND, b);                                                 // Do FM sound on channel 4
336                 if (b == 12)
337                         game_over_switch = 240;                                         // Set game over delay...
338         }
339         if (addr < 0x423D || addr > 0x425C)                                     // Protect writes to DSWs
340                 gram1[addr] = b;
341         if (addr == 0x8800)
342                 charbase = false;                                                               // Char banksw1
343         if (addr == 0x8C00)
344                 charbase = true;                                                                // Char banksw2
345         if (addr == 0x8400)                                                                     // Frame go strobe? VBlank acknowledge?
346         {
347                 if (refresh_++ == 1)                                                            // 30 Hz...
348                 {
349                         BlitChar(screen, chr_rom, gram1);
350                         refresh_ = (refresh2 ? 1 : 0);                          // 60/30 Hz...
351                 }
352 //              irqGoA = true; // Will this work??? no...
353                 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
354         }
355 }
356
357 //
358 // Read a byte from memory (without touching PC. Not a Fetch!) (2nd processor)
359 //
360 uint8 RdMemB(uint16 addr)
361 {
362 //  extern uint16 cpu2.s, cpu2.u, cpu2.x, cpu2.y;            // Needed for tracelog
363         uint8 b;
364
365         if (addr < 0x8000)
366         {
367                 if (addr < 0x2000)
368                         b = gram1[addr + 0x4000];
369                 if (addr > 0x1FFF && addr < 0x6000)
370                         b = gram1[addr - 0x2000];
371                 if (addr > 0x5FFF)
372                         b = grom3[banksw2 + (addr - 0x6000)];           // Correct?
373         }
374         else
375                 b = grom2[addr];
376
377 /*  if ((addr>0x3FFF) && (addr<0x4400))  tr << "R-" << hex << pcx << ": "
378                                         << addr << "-"
379                                         << (int)looking_at_rom
380                                         << " [" << (int)b
381                                         << "] XR:" << xr << " YR:" << yr
382                                         << " SR:" << sr << " UR:" << ur
383                                         << endl; //*/
384         return b;
385 }
386
387 //
388 // Write a byte to memory (2nd processor)
389 //
390 void WrMemB(uint16 addr, uint8 b)
391 {
392         extern bool charbase;
393   //extern uint16 sr, ur, xr, yr;            // Needed for tracelog
394   //extern uint16 pcr;
395 /*  if ((addr>0x00FF) && (addr<0x0390))
396   {
397     tr << hex << addr << ":" << (int)b;
398     //for(int i=0; i<32; i++)
399     //{
400     //  if (gram1[0x4400+i]<0x10)  tr << "0";
401     //  tr << hex << (uint16)gram1[0x4400+i] << " ";
402     //}
403     tr << endl;
404   }//*/
405
406         if (addr == 0x8800)
407 //              irqGoB = true;                                                                  // Will it work??? no...
408                 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
409         if (addr == 0x6000)
410                 SpawnSound(GAMESOUND, gram1[0x6200], 0);                // Do voice chan 1
411         if (addr == 0x6400)
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
415         if (addr == 0xD803)
416                 banksw2 = (uint32)(b & 0x03) << 13;                             // Set sprite data bank switch
417         if (addr == 0x0380)
418         {
419                 SpawnSound(FMSOUND, b);                                                 // Do FM sound on chan 4
420                 if (b == 12)
421                         game_over_switch = 240;                                         // Set game over delay...
422         }
423         if (addr < 0x023D || addr > 0x025C)                                     // Protect writes against DSWs
424         {
425                 if (addr < 0x2000)
426                         gram1[addr + 0x4000] = b;
427                 if (addr > 0x1FFF && addr < 0x6000)
428                         gram1[addr - 0x2000] = b;
429                 if (addr > 0x5FFF)
430                         gram1[addr] = b;
431         }
432 }
433
434 //
435 // Display bytes in mem in hex
436 //
437 void DisplayBytes(uint16 src, unsigned long dst)
438 {
439   uint8 cnt;
440   unsigned long i;
441
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++)
446   {
447     printf("%02X ", (uint8)(looking_at_rom ? RdMem(i) : RdMemB(i)));
448     cnt++;                               // Bump counter...
449   }
450   for(i=cnt; i<5; i++)                   // Pad the leftover spaces...
451   {
452     cout << "   ";
453   }
454 }
455
456 // temp crap...
457 uint8 Fetch(void) { return 0; }
458 uint16 FetchW(void) { return 0; }
459 uint8 FetchB(void) { return 0; }
460 uint16 FetchWB(void) { return 0; }
461
462 //
463 // Decode a 6809 instruction at 'addr'
464 //
465 void Decode_6809()
466 {
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);
471
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;
477   uint16 loperand;
478   uint8 admode = op_mat1[opcode];     // addressing mode
479   char outbuf[80], mnem[6], tmp[30];
480
481   strcpy(mnem, mnemonics[opcode]);  // Copy page 1 opcode
482   if (opcode == 0x10)             // Extended opcode?
483   {
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
487   }
488   if (opcode == 0x11)             // Same as above...
489   {
490     opcode2 = DFetch();
491     admode = op_mat3[opcode2];
492     strcpy(mnem, mnemonics3[opcode2]);  // Overwrite mnemonic
493   }
494   switch(admode)                  // Decode it...
495   {
496     case 0:  // Illegal
497     { sprintf(outbuf, "???");  break; }
498     case 1:  // Zero page
499     { operand = DFetch();   // Get ZP address
500       sprintf(outbuf, "%s $%02X", mnem, operand);
501       break; }
502     case 2:  // Absolute
503     { loperand = DFetchW(); // Get ABS address
504       sprintf(outbuf, "%s $%04X", mnem, loperand);
505       break; }
506     case 3:  // Relative
507     { operand = DFetch();   // Get offset
508       uint16 tmpc = (looking_at_rom ? pcr : pcrB);
509       sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16)(int8)operand);
510       break; }
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);
515       break; }
516     case 5:  // Inherent
517     { sprintf(outbuf, "%s ", mnem);
518       break; }
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?
522       {
523         sprintf(tmp, "%s,%s", tregs[operand>>4], tregs[operand&0x0F]);
524       }
525       else
526       {
527         tmp[0] = 0;
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");
537       }
538       sprintf(outbuf, "%s %s", mnem, tmp);
539       break; }
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;
544       uint16 woff;
545
546       strcpy(tmp, "??");
547       if (!(operand & 0x80))      // Hi bit set? Then decode 4 bit offset
548       {
549         sprintf(tmp, "(%d),%s", (idxind ? -(16-lo_nyb) : lo_nyb),
550                 iregs[reg]);
551       }
552       else   // Add the ($nnnn,R) code dude...
553       {
554         if (idxind)
555         {
556           switch(lo_nyb)
557           {
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;
563             case 8:
564             { boff = DFetch();  sprintf(tmp, "($%02X,%s)", boff,
565                                        iregs[reg]);  break; }
566             case 9:
567             { woff = DFetchW();  sprintf(tmp, "($%04X,%s)", woff,
568                                         iregs[reg]);  break; }
569             case 11:  sprintf(tmp, "(D,%s)", iregs[reg]);  break;
570             case 12:
571             { boff = DFetch();  sprintf(tmp, "($%02X,PC)", boff);  break; }
572             case 13:
573             { woff = DFetchW();  sprintf(tmp, "($%04X,PC)", woff);  break; }
574             case 15:
575             { woff = DFetchW();  sprintf(tmp, "[$%04X]", woff);  break; }
576             default:  strcpy(tmp, "??");
577           }
578         }
579         else
580         {
581           switch(lo_nyb)
582           {
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;
590             case 8:
591             { boff = DFetch();  sprintf(tmp, "($%02X),%s", boff,
592                                        iregs[reg]);  break; }
593             case 9:
594             { woff = DFetchW();  sprintf(tmp, "($%04X),%s", woff,
595                                        iregs[reg]);  break; }
596             case 11:  sprintf(tmp, "(D),%s", iregs[reg]);  break;
597             case 12:
598             { boff = DFetch();  sprintf(tmp, "($%02X),PC", boff);  break; }
599             case 13:
600             { woff = DFetchW();  sprintf(tmp, "($%04X),PC", woff);  break; }
601             default:  strcpy(tmp, "??");
602           }
603         }
604       }
605       sprintf(outbuf, "%s %s", mnem, tmp);
606       break; }
607     case 8:  // Immediate
608     { operand = DFetch();   // Get IMM byte
609       sprintf(outbuf, "%s #$%02X", mnem, operand);
610       break; }
611     case 9:  // Long Immediate
612     { loperand = DFetchW(); // Get IMM word
613       sprintf(outbuf, "%s #$%04X", mnem, loperand);
614       break; }
615   }
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
620 }
621
622 //
623 // Convert hex to dec
624 //
625 uint16 htod(char *str)
626 {
627   uint16 value = 0;
628   int len = strlen(str);
629
630   for(int i=0; i<len; i++)
631   {
632     if (str[i]>='0' && str[i]<='9')
633     {
634       value = (value<<4) | (unsigned)(str[i]-'0');
635     }
636     if (str[i]>='a' && str[i]<='f')
637     {
638       value = (value<<4) | (unsigned)(str[i]-'a')+10;
639     }
640     if (str[i]>='A' && str[i]<='F')
641     {
642       value = (value<<4) | (unsigned)(str[i]-'A')+10;
643     }
644   }
645   return(value);
646 }
647
648 //
649 // Load 32K file into ROM image space
650 //
651 bool Load32KImg(char * filename, uint16 address)
652 {
653   ifstream ff;
654   char ch;
655
656   ff.open(filename, ios::binary | ios::in);  // Open 'da file...
657   if (ff)
658   {
659     for(long i=0; i<32768; i++)                // Read it in...
660     {
661       ff.get(ch);
662       grom[address+i] = ch;
663     }
664     ff.close();                                // Close 'da file...
665   }
666   return(ff);
667 }
668
669 //
670 // Generic Load file into image space
671 // (No error checking performed!  Responsibility of caller!)
672 //
673 bool LoadImg(const char * filename, uint8 * mem, uint32 address, uint32 length)
674 {
675   ifstream ff;
676   char path[80];
677   char ch;
678
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...
683   if (ff)
684   {
685     for(uint32 i=0; i<length; i++)             // Read it in...
686     {
687       ff.get(ch);
688       mem[address+i] = ch;
689     }
690     ff.close();                               // Close 'da file...
691   }
692   return(ff);
693 }
694
695 //
696 // Read color PROMs
697 //
698 bool ReadColorPROMs(void)
699 {
700   fstream ff1, ff2;
701 //  uint8 ch;
702   char ch;
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
706
707   ff1.open("./ROMs/"PROM3, ios::binary|ios::in);
708   if (ff1)
709   {
710     for(int i=0; i<256; i++) // Load char pallete with PROM values
711     {
712       for(int j=0; j<8; j++)
713       {
714         ff1.get(ch);
715         ccolor[i][j] = (uint8)ch;
716       }
717     }
718     ff1.close();
719   }
720   ff1.open("./ROMs/"PROM4, ios::binary|ios::in);
721   if (ff1)
722   {
723     for(int i=0; i<128; i++) // Load sprite pallete with PROM values
724     {
725       for(int j=0; j<16; j++)
726       {
727         ff1.get(ch);
728         scolor[i][j] = (uint8)ch;
729       }
730     }
731     ff1.close();
732   }
733
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...
737   {
738     for(int i=0; i<768; i+=3)
739     {
740       ff1.get(ch);
741       palette[i]   = (uint8)(ch&0x0F);
742       palette[i+1] = (uint8)(ch>>4);
743       ff2.get(ch);
744       palette[i+2] = (uint8)ch;
745     }
746
747     // Do palette stretching here... I.e. add 0 to hinyb 0, 1 to hinyb 1, etc.
748
749     for(int i=0; i<768; i++)
750       palette[i] = ((palette[i]<<4)&0xF0) | (palette[i]&0x0F);
751
752     ff1.close();
753     ff2.close();
754   }
755   return ff1;
756 }
757
758 //
759 // Unpack font data
760 //
761 bool UnpackFonts(void)
762 {
763 //  uint8 b1, b2, b3;
764   char b1, b2, b3;
765   fstream f1, f2;
766   //0x4000 $800 chars
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)
771   {
772     for(int j=0; j<64; j+=8)
773     {
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);
784     }
785   }
786   f1.close();
787   f2.close();
788
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)
792   {
793     for(int j=0; j<64; j+=8)
794     {
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);
805     }
806   }
807   f1.close();
808   f2.close();
809   return true;                                // Made it!
810 }
811
812 //
813 // Get length of sample from WAV format
814 //
815 uint32 GetWAVLength(fstream &file)
816 {
817         char ch;
818         uint32 len;
819
820         file.ignore(16);                                                                        // Skip header BS
821
822         for(int i=0; i<2; i++)
823         {
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;
828
829                 file.ignore(len + 4);                                                   // Skip intermediate data
830         }
831
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;
836
837         return len;
838 }
839
840 //
841 // Load PSG samples from disk
842 //
843 void LoadPSGs(void)
844 {
845         char file[40];
846         char ch;
847         uint32 len;
848
849         for(int i=0; i<16; i++)
850         {
851                 fstream fp;
852
853                 psg_adrs[i] = NULL;                                                             // Zero out pointer
854                 sprintf(file, "./sounds/psg%i.wav", i);                 // Create filename
855
856                 fp.open(file, ios::binary | ios::in);                   // Attempt to open it...
857
858                 if (fp)
859                 {
860                         len = GetWAVLength(fp);                                         // Get WAV data length...
861
862                         psg_adrs[i] = new uint8[len];                           // Attempt to allocate space...
863
864                         if (psg_adrs[i] != NULL)
865                         {
866                                 for(int j=0; j<(signed)len; j++)
867                                 {
868                                         fp.get(ch);
869                                         psg_adrs[i][j] = ch;                            // & load it in...
870                                 }
871
872                                 psg_lens[i] = len;
873                                 cout << "Found sample file: " << file << " [Length: " << dec << len << "]" << endl;
874                         }
875
876                         fp.close();
877                 }
878         }
879 }
880
881 //
882 // Load FM samples from disk
883 //
884 void LoadFMs(void)
885 {
886         char file[200];
887         char ch;
888         uint32 len;
889
890         for(int i=0; i<14; i++)
891         {
892                 fstream fp;
893
894                 fm_adrs[i] = NULL;                                                              // Zero out pointer
895                 sprintf(file, "./sounds/fm%i.wav", i);                  // Create filename
896
897                 fp.open(file, ios::binary | ios::in);                   // Attempt to open it...
898
899                 if (fp)
900                 {
901                         len = GetWAVLength(fp);                                         // Get WAV length...
902
903                         fm_adrs[i] = new uint8[len];                                    // Attempt to allocate space...
904
905                         if (fm_adrs[i] != NULL)
906                         {
907                                 for(int j=0; j<(signed)len; j++)
908                                 {
909                                         fp.get(ch);
910                                         fm_adrs[i][j] = ch;                                     // & load it in...
911                                 }
912
913                                 fm_lens[i] = len;
914                                 cout << "Found sample file: " << file << " [Length: " << dec << len
915                                         << "]" << endl;
916                         }
917
918                         fp.close();
919                 }
920         }
921 }
922
923 //
924 // Main loop
925 //
926 int main(int argc, char * argv[])
927 {
928         InitLog("thunder.log");
929
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;
932   extern long iclock;
933   extern bool illegal;
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;
936   extern long iclockB;
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;
946   charbase = false;
947
948   char lbuff[80];
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
960
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;
966
967 //  tr.open("exe.log", ios::binary | ios::out); // Tracelog
968
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;
973
974   cout << "This emulator is free software. If you paid for it you were RIPPED OFF"
975        << endl << endl;
976
977   cout << "Initializing SDL..." << endl;
978
979   if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
980   {
981     cout << "Couldn't initialize SDL: " << SDL_GetError() << endl;
982     return -1;
983   }
984
985   SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder");
986
987         keys = SDL_GetKeyState(NULL);                           // Get the SDL keyboard matrix
988
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; }
1021
1022   gram = gram1;  grom = grom1;           // Needed only for debugger
1023
1024   for(long i=0; i<0x10000; i++)
1025   {
1026     gram[i] = 0;  grom[i] = 0;           // Zero out memory
1027     gram2[i] = 0;  grom2[i] = 0;
1028   }
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;
1031
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; }
1036
1037   if (!LoadImg(ROM1, grom1, 0x8000, 0x8000)) // Load $8000-$FFFF 1st ROM
1038   { cout << "Could not open file '" << ROM1 << "'!" << endl;  return -1; }
1039
1040   if (!LoadImg(ROM2, grom2, 0x8000, 0x8000)) // Load $8000-$FFFF 2nd ROM
1041   { cout << "Could not open file '" << ROM2 << "'!" << endl;  return -1; }
1042
1043   if (!LoadImg(ROM3, grom3, 0, 0x8000))      // Load 3rd ROM into its own space
1044   { cout << "Could not open file '" << ROM3 << "'!" << endl;  return -1; }
1045
1046   if (!LoadImg(ROM4, grom4, 0, 0x8000))      // Load 4rd ROM into its own space
1047   { cout << "Could not open file '" << ROM4 << "'!" << endl;  return -1; }
1048
1049   if (!LoadImg(ROM17, data_rom, 0,       0x10000))  // Load 17th ROM
1050   { cout << "Could not open file '" << ROM17 << "'!" << endl;  return -1; }
1051
1052   if (!LoadImg(ROM18, data_rom, 0x10000, 0x10000))  // Load 18th ROM
1053   { cout << "Could not open file '" << ROM18 << "'!" << endl;  return -1; }
1054
1055   if (!LoadImg(ROM19, data_rom, 0x20000, 0x10000))  // Load 19th ROM
1056   { cout << "Could not open file '" << ROM19 << "'!" << endl;  return -1; }
1057
1058   if (!LoadImg(ROM20, data_rom, 0x30000, 0x10000))  // Load 20th ROM
1059   { cout << "Could not open file '" << ROM20 << "'!" << endl;  return -1; }
1060
1061   if (!LoadImg(ROM9,  spr_rom, 0,       0x10000))   // Load 9th ROM
1062   { cout << "Could not open file '" << ROM9 << "'!" << endl;  return -1; }
1063
1064   if (!LoadImg(ROM10, spr_rom, 0x10000, 0x10000))   // Load 10th ROM
1065   { cout << "Could not open file '" << ROM10 << "'!" << endl;  return -1; }
1066
1067   if (!LoadImg(ROM11, spr_rom, 0x20000, 0x10000))   // Load 11th ROM
1068   { cout << "Could not open file '" << ROM11 << "'!" << endl;  return -1; }
1069
1070   if (!LoadImg(ROM12, spr_rom, 0x30000, 0x10000))   // Load 12th ROM
1071   { cout << "Could not open file '" << ROM12 << "'!" << endl;  return -1; }
1072
1073   if (!LoadImg(ROM13, spr_rom, 0x40000, 0x10000))   // Load 13th ROM
1074   { cout << "Could not open file '" << ROM13 << "'!" << endl;  return -1; }
1075
1076   if (!LoadImg(ROM14, spr_rom, 0x50000, 0x10000))   // Load 14th ROM
1077   { cout << "Could not open file '" << ROM14 << "'!" << endl;  return -1; }
1078
1079   if (!LoadImg(ROM15, spr_rom, 0x60000, 0x10000))   // Load 15th ROM
1080   { cout << "Could not open file '" << ROM15 << "'!" << endl;  return -1; }
1081
1082   if (!LoadImg(ROM16, spr_rom, 0x70000, 0x10000))   // Load 16th ROM
1083   { cout << "Could not open file '" << ROM16 << "'!" << endl;  return -1; }
1084
1085   if (!LoadImg(ROM21, voice_rom, 0, 0x10000))  // Load 21st ROM
1086   { cout << "Could not open file '" << ROM21 << "'!" << endl;  return -1; }
1087
1088   if (!LoadImg(ROM22, voice_rom, 0x10000, 0x10000))  // Load 22nd ROM
1089   { cout << "Could not open file '" << ROM22 << "'!" << endl;  return -1; }
1090
1091   if (!UnpackFonts())                         // Load 5, 6, 7, 8th ROMs
1092   {
1093     cout << "Could not open font files!" << endl;
1094     return -1;
1095   }
1096
1097         // Load samples if they're there...
1098         LoadPSGs();
1099         LoadFMs();
1100
1101   // Quick 'n' Dirty voice dump (sound 0x0E)
1102 /*  uint32 adc = (voice_rom[26]<<8) | voice_rom[27];
1103   bool doneWitIt = false;
1104   int crh = 0;
1105   while (!doneWitIt)
1106   {
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))
1111       doneWitIt = true;
1112     adc++;
1113   }//*/
1114
1115         // Set up V6809 execution contexts
1116
1117         memset(&cpu1, 0, sizeof(V6809REGS));
1118         cpu1.RdMem = RdMem;
1119         cpu1.WrMem = WrMem;
1120         cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
1121
1122         memset(&cpu2, 0, sizeof(V6809REGS));
1123         cpu2.RdMem = RdMemB;
1124         cpu2.WrMem = WrMemB;
1125         cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
1126
1127         bool firstTime = true;                                                          // kludge...
1128
1129 WriteLog("About to go to the main loop...\n");
1130         while (active)
1131         {
1132                 cout << ">";
1133                 if (firstTime)
1134                 {
1135                         firstTime = false;                                                      // crappy kludge...
1136                         lbuff[0] = 'r';
1137                         lbuff[1] = 0;
1138                 }
1139                 else
1140                         cin >> lbuff;
1141
1142                 if (lbuff[0] == 'd')
1143                 {
1144                         if (lbuff[1] != 0)
1145                         {
1146                                 lbuff[0] = 32;
1147                                 dpc = htod(lbuff);
1148                         }
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()));
1154                         cout << " ";
1155                         cpu1.pc = dpc;  cpu2.pc = dpc;
1156                         for(int i=0; i<16; i++)
1157                         {
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 << ".";
1162                         }
1163                         cout << endl;
1164                         dpc = (looking_at_rom ? cpu1.pc : cpu2.pc);
1165                         cpu1.pc = pc_save;  cpu2.pc = pcB_save;
1166                 }
1167                 else if (lbuff[0] == 'e')
1168                 {
1169                         if (lbuff[1] != 0)
1170                         {
1171                                 lbuff[0] = 32;
1172                                 dpc = htod(lbuff);
1173                         }
1174                         printf("%04X: ", dpc);
1175                         for(int i=0; i<16; i++)  printf("%02X ", (uint8)gram[dpc++]);
1176                         cout << endl;
1177                 }
1178                 else if (lbuff[0] == 'l')
1179                 {
1180                         if (lbuff[1] != 0)
1181                         {
1182                                 lbuff[0] = 32;
1183                                 dpc = htod(lbuff);
1184                         }
1185                         for(int i=0; i<23; i++)
1186                                 Decode_6809();
1187                 }
1188                 else if (lbuff[0] == 't')
1189                 {
1190                         if (lbuff[1] != 0)
1191                         {
1192                                 lbuff[0] = 32;
1193                                 dpc = htod(lbuff);
1194                         }
1195                         if (looking_at_rom)
1196                         {
1197                                 cpu1.pc = dpc;
1198                                 Decode_6809();
1199                                 Execute6809(&cpu1, 1);
1200                                 dpc = cpu1.pc;
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;
1204                         }
1205                         else
1206                         {
1207                                 cpu2.pc = dpc;
1208                                 Decode_6809();
1209                                 Execute6809(&cpu2, 1);
1210                                 dpc = cpu2.pc;
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;
1214                         }
1215                 }
1216                 else if ((lbuff[0] == 'r') || (lbuff[0] == 'c')) // Run/continue...
1217                 {
1218 WriteLog("Executing 'run' command...\n");
1219                         uint32 my_clock = 0;
1220                         running = true;                                                         // Set running status...
1221                         trace1 = false;
1222                         SetRefreshRate(refresh2);                                       // Tell GUI our refresh rate
1223       //for(uint16 i=0; i<0x8000; i++)  gram2[i] = grom3[i]; //Temp
1224
1225                         if (lbuff[0] == 'r')                                            // If run, then reset CPUs
1226                         {
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?
1233                                 banksw2 = 0;
1234 //        iclock = 0;                // Reset instr clock #1...
1235                                 InitGUI();                 // Reset # of coins
1236
1237 /*        cpu1.pc = ((grom1[0xFFFE]<<8) | grom1[0xFFFF]); // Reset 6809 #1
1238         if (lbuff[1] != 0)
1239         {
1240           lbuff[0] = 32;  cpu1.pc = htod(lbuff);
1241         }
1242         else  cpu1.cc = 0xFF;                         // Set CC register
1243
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
1247         {
1248           Execute6809(&cpu1, 1);  Execute6809(&cpu2, 1);
1249         }*/
1250 WriteLog("--> CPU clock #1: %u\n", cpu1.clock);
1251                                 // Will *this* help video sync?
1252                                 while (cpu1.clock < 8000)                               // was 17000, 20000, 5000
1253                                 {
1254                                         Execute6809(&cpu1, 1);
1255                                         Execute6809(&cpu2, 1);
1256                                 }
1257                         }
1258
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);
1263                         if (screen == NULL)
1264                         {
1265                                 cout << "Failed to initialize screen!" << endl;
1266                                 running = false;
1267                         }
1268
1269                         SDL_Color colors[256];
1270                         for(int i=0; i<256; i++)
1271                         {
1272                                 colors[i].r = palette[i*3+0];
1273                                 colors[i].g = palette[i*3+1];
1274                                 colors[i].b = palette[i*3+2];
1275                         }
1276                         SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256);
1277
1278 #if 1
1279         // This confirms that we're getting video to the screen...
1280         SDL_LockSurface(screen);
1281
1282         uint8 pixel = 0;
1283         uint8 * pixels = (uint8 *)(screen->pixels);
1284
1285         for(uint32 y=0; y<480; y++)
1286                 for(uint32 x=0; x<640; x++)
1287                         pixels[(y * 640) + x] = pixel++;
1288
1289         SDL_UnlockSurface(screen);
1290         SDL_UpdateRect(screen, 0, 0, 0, 0);
1291 #endif
1292
1293                         for(int i=0; i<256; i++)
1294                                 keys[i] = 0;                            // Clear keyboard buffer...
1295
1296                         oldTicks = SDL_GetTicks();
1297
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)
1309                         {
1310                                 cout << "Couldn't open audio: " << SDL_GetError() << endl;
1311                                 return -1;
1312                         }
1313                         SDL_PauseAudio(0);                                                      // Get that audio going!
1314
1315 WriteLog("About to enter main loop...\n");
1316                         while (running)
1317                         {
1318                                 HandleGUIDebounce();                                    // Debounce GUI keys
1319                                 if (game_over_switch)
1320                                 {
1321                                         game_over_switch--;  // Countdown...
1322                                         if (game_over_switch == 0)
1323                                                 gram1[0x4380] = 0; // Kill music!
1324                                 }
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;
1335
1336                                 // SDL key handling...
1337
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...
1342 //                              {
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;
1347 //                              }
1348
1349 //        {
1350                                 if (keys[SDLK_ESCAPE])
1351                                         running = false;                     // ESC to exit...
1352
1353                                 if (debounce)
1354                                         debounce--;                          // Debounce toggle keys...
1355                                 else
1356                                 {
1357                                         if (keys[SDLK_F1])
1358                                         {
1359                                                 self_test = !self_test;            // Self-test (F1-toggle)
1360                                                 debounce = 10;                     // Key debounce value...
1361                                         }
1362                                         if (keys[SDLK_F2])
1363                                         {
1364                                                 gram1[0x4268] = 1;                 // Video test (F2)
1365                                                 debounce = 10;                     // Key debounce value...
1366                                         }
1367                                         if (keys[SDLK_F12])
1368                                         {
1369                                                 scr_type = !scr_type;              // Toggle screen (F12)
1370                                                 debounce = 10;                     // Key debounce value...
1371                                         }
1372                                         if (keys[SDLK_F3])
1373                                         {
1374                                                 show_scr = !show_scr;              // Toggle bkgrnd (F3)
1375                                                 debounce = 10;
1376                                         }
1377                                         if (keys[SDLK_F6])
1378                                         {
1379                                                 enable_cpu = !enable_cpu;          // Toggle CPUs (F6)
1380                                                 debounce = 10;
1381                                         }
1382                                         if (keys[SDLK_F5])
1383                                         {
1384                                                 refresh2 = !refresh2;             // Toggle 30/60Hz (F5)
1385                                                 SetRefreshRate(refresh2);         // Inform GUI of refresh
1386                                                 if (refresh2)
1387                                                         SpawnMsg(M60FPS);
1388                                                 else
1389                                                         SpawnMsg(M30FPS);
1390                                                 debounce = 10;                    // Key debounce value...
1391                                         }
1392                                         if (keys[SDLK_F4])                      // Do PCX snapshot (F4)
1393                                         {
1394                                                 SpawnSound(USERSOUND, SCAMERA);
1395                                                 SnapPCX(screen);
1396                                                 debounce = 10;
1397                                         }
1398                                         if (keys[SDLK_TAB])                      // Tab active/deactivate GUI
1399                                         {
1400                                                 if (ShowGUI())
1401                                                         DeactivateGUI();
1402                                                 else
1403                                                         ActivateGUI();
1404                                                 debounce = 10;
1405                                         }
1406                                 }
1407                                 //if (keys[0x3E])  gram1[0x4247] = 1;  // Screen hold DS (F4)
1408                                 if (keys[SDLK_RIGHT])                                           // Right arrow
1409                                 {
1410                                         if (ShowGUI())
1411                                                 SelectRight();                     // If GUI active...
1412                                         else
1413                                         {
1414                                                 if (!keys[SDLK_LEFT])                     // Disallow opposite directions @ same time
1415                                                         gram1[0x427F] = 1;               // Stick right
1416                                         }
1417                                 }
1418                                 if (keys[SDLK_LEFT])
1419                                 {
1420                                         if (ShowGUI())
1421                                                 SelectLeft();                      // If GUI active...
1422                                         else
1423                                         {
1424                                                 if (!keys[SDLK_RIGHT])                     // Disallow opposite directions@same time
1425                                                 gram1[0x4281] = 1;               // Left arrow
1426                                         }
1427                                 }
1428                                 if (keys[SDLK_UP])
1429                                 {
1430                                         if (ShowGUI())
1431                                                 SelectUp();                        // If GUI active...
1432                                         else
1433                                         {
1434                                                 if (!keys[SDLK_DOWN])                     // Disallow opposite directions@same time
1435                                                         gram1[0x427B] = 1;               // Up arrow
1436                                         }
1437                                 }
1438                                 if (keys[SDLK_DOWN])
1439                                 {
1440                                         if (ShowGUI())
1441                                                 SelectDown();                                   // If GUI active...
1442                                         else
1443                                         {
1444                                                 if (!keys[SDLK_UP])                             // Disallow opposite directions@same time
1445                                                         gram1[0x427D] = 1;                      // Down arrow
1446                                         }
1447                                 }
1448                                 if (keys[SDLK_RETURN])                                                  // Return
1449                                 {
1450                                         uint8 retval = UserSelectedSomething();
1451                                         if (retval == EXIT)
1452                                                 running = false;
1453                                         if (retval == REFRESH)
1454                                         {
1455                                                 refresh2 = !refresh2;
1456                                                 SetRefreshRate(refresh2);
1457                                         }
1458                                 }
1459                                 if (keys[SDLK_1])
1460                                         gram1[0x427A] = 1;                                      // (1)
1461                                 if (keys[SDLK_2])
1462                                         gram1[0x427C] = 1;                                      // (2)
1463                                 if (keys[SDLK_3])
1464                                         gram1[0x427E] = 1;                                      // (3)
1465                                 if (keys[SDLK_5])
1466                                         gram1[0x4280] = 1;                                      // (5)
1467                                 if (keys[0x10]|keys[29])
1468                                         gram1[0x4276] = 1;                                      // (Q)  Jump
1469                                 if (keys[0x11])
1470                                         gram1[0x426A] = 1;                                      // (W)
1471                                 if (fire_debounce)
1472                                         fire_debounce--;
1473                                 if (keys[0x12]|keys[56])                                // (E) Fire
1474                                 {
1475                                         if (!fire_debounce)
1476                                         {
1477                                                 gram1[0x4278] = 1;
1478                                                 if (gram1[0x3F08] == 0xFF)              // Ugly kludge for debouncing gun
1479                                                 {
1480                                                         fire_debounce = 8;
1481                                                 }
1482                                                 else
1483                                                 {
1484                                                         fire_debounce = 2;
1485                                                 }
1486                                         }
1487                                 }
1488                                 if (keys[0x13])
1489                                         gram1[0x426C] = 1;                                      // (R)
1490                                 if (keys[0x14])
1491                                         gram1[0x4262] = 1;                                      // (T)
1492                                 if (keys[0x15])
1493                                         gram1[0x4260] = 1;                                      // (Y)
1494                                 if (keys[SDLK_F10])
1495                                         gram1[0x41A5]++;                                        // Coin? (F10)
1496                                 if (keys[SDLK_z])
1497                                         gram1[0x4189]++;                                        // ? (Z) credits l dig
1498                                 if (keys[SDLK_x])
1499                                         gram1[0x418A]++;                                        // ? (X) credits r dig
1500                                 if (keys[SDLK_c])
1501                                         gram1[0x418C]++;                                        // ? (C) Start
1502                                 if (keys[SDLK_v])
1503                                         gram1[0x418D]++;                                        // ? (V)
1504                                 if (keys[SDLK_F7])
1505                                         SpawnSound(USERSOUND, 0);                       // Do user sound (F7)
1506 //                              if (keys[0x42])
1507 //                              {
1508 //                                      gram1[0x4380] = 0;                                      // (F8) kill music (this worx)
1509 //                                      charbase = false;                                       // Switch chars out...
1510 //                              }
1511 //                              if (keys[0x43])  gram1[0x4285] = 1;             // (F9) strobe unknown loc
1512                                 if (keys[SDLK_F1])                                                      // (F11)
1513                                 {
1514                                         Execute6809(&cpu1, 10);
1515                                         Execute6809(&cpu2, 10);
1516                                 }
1517 //                      }
1518
1519 //                              if (enable_cpu)
1520                                 if (true)
1521                                 {
1522 /*//                                    if (irqGoA)
1523                                                 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1524
1525                                         Execute6809(&cpu1, 25000);
1526                                         cpu1.clock -= 25000;                            // Remove 25K ticks from clock (in case it overflowed)
1527
1528 //                                      if (irqGoB)
1529                                                 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1530
1531                                         Execute6809(&cpu2, 25000);
1532                                         cpu2.clock -= 25000;                            // Remove 25K ticks from clock (in case it overflowed)//*/
1533
1534 //                                      cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1535 //                                      cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1536                                         while (cpu1.clock < 25000)
1537                                         {
1538                                                 // Gay, but what are ya gonna do?
1539                                                 Execute6809(&cpu1, 5);
1540                                                 Execute6809(&cpu2, 5);
1541                                         }
1542
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)//*/
1545
1546                                 } // END: enable_cpu
1547
1548 //        if (refresh_++ == 1)                // 30 Hz...
1549 //        {
1550 //          if (scr_type)
1551 //            BlitWilliamsScreen(gram1);     // Display the screen...
1552 //          else
1553 //            BlitChar(screen, chr_rom, gram1);
1554 //          refresh_ = (refresh2 ? 1 : 0);    // 60/30 Hz...
1555 //        }
1556 //temp, for testing...
1557 BlitChar(screen, chr_rom, gram1);
1558
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...
1562
1563                                 oldTicks = SDL_GetTicks();
1564 //cout << "Finished frame..." << endl;
1565                         }
1566
1567 //      Stop_audio_output();
1568 //      ReleaseTimer();
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;
1575
1576                         lbuff[0] = 'q';                         // Temp kludge...
1577                 }
1578                 else if (lbuff[0] == 'b')  // Set/clear breakpoint
1579                 {
1580                         if (lbuff[1] != 0)
1581                         {
1582                                 lbuff[0] = 32;
1583                                 brkpnt = htod(lbuff);
1584                                 brk = true;
1585                                 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1586                         }
1587                         else
1588                         {
1589                                 brk = false;
1590                                 cout << "Breakpoint cleared" << endl;
1591                         }
1592                 }
1593                 else if (lbuff[0] == 'a')  // Set/clear breakpoint #2
1594                 {
1595                         if (lbuff[1] != 0)
1596                         {
1597                                 lbuff[0] = 32;
1598                                 brkpnt2 = htod(lbuff);
1599                                 brk2 = true;
1600                                 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1601                         }
1602                         else
1603                         {
1604                                 brk2 = false;
1605                                 cout << "Breakpoint cleared" << endl;
1606                         }
1607                 }
1608                 else if (lbuff[0] == 'i')  // Inspect registers
1609                 {
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;
1616       if (brk)
1617         cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1618       if (brk2)
1619         cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1620     }
1621                 else if (strncmp(lbuff, "swap", 4) == 0)  // Swap ROMs
1622     {
1623       looking_at_rom = !looking_at_rom;
1624       cout << "Swapped:  Looking at ";
1625       (looking_at_rom ? cout << "ROM #1" : cout << "ROM #2");
1626       cout << endl;
1627     }
1628                 else if (strncmp(lbuff, "seek", 4) == 0)  // Seek non-zero bytes in RAM
1629     {
1630       if (lbuff[4] != 0)
1631       {
1632         for(int i=0; i<4; i++)
1633           lbuff[i] = 32;
1634         dpc = htod(lbuff);
1635       }
1636       do
1637       {
1638         x = gram1[dpc++];
1639       }
1640       while ((x == 0) && (dpc != 0xFFFF)); // Keep going until something found
1641       dpc--;
1642
1643       printf("%04X: ", dpc);       // Show data found...
1644       for(int i=0; i<16; i++)
1645         printf("%02X ", gram1[(uint16)(dpc+i)]);
1646       cout << " ";
1647       for(int i=0; i<16; i++)
1648       {
1649         uint8 a = gram1[dpc++];
1650         if (a<10)
1651           cout << (char)(a+48);
1652         if ((a>9) && (a<37))
1653           cout << (char)(a+55);
1654         if (a>36)
1655           cout << ".";
1656       }
1657       cout << endl;
1658     }
1659                 else if (lbuff[0] == 'v')    // View screen
1660                 {
1661 //                      SetVESA2();                           // Set up screen
1662                         BlitChar(screen, chr_rom, gram1);
1663                         getch();
1664 //                      RestoreOldMode();
1665                 }
1666
1667                 if (lbuff[0] == 'q')
1668                         active = false; //break;  // Quit
1669         }
1670
1671         SDL_Quit();                                                                                     // Shut down SDL
1672
1673         delete[] gram1;                                                                         // Deallocate RAM & ROM spaces
1674         delete[] grom1;
1675         delete[] gram2;
1676         delete[] grom2;
1677         delete[] chr_rom;
1678         delete[] grom3;
1679         delete[] grom4;
1680         delete[] data_rom;
1681         delete[] spr_rom;
1682         delete[] voice_rom;
1683
1684         for(int i=0; i<16; i++)
1685                 if (psg_adrs[i] != NULL)
1686                         delete[] psg_adrs[i];                                           // Deallocate if loaded
1687
1688         for(int i=0; i<14; i++)
1689                 if (fm_adrs[i] != NULL)
1690                         delete[] fm_adrs[i];                                            // Deallocate if loaded
1691
1692 //      tr.close();                                                                                     // Close tracelog
1693         LogDone();
1694
1695         return 1;
1696 }