]> Shamusworld >> Repos - thunder/blob - src/thunder.cpp
fde0f3ef48289d66db1b384421d113357cab70ac
[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 char op_mat1[256] = {
130   1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
131   0, 0, 5, 5, 0, 0, 4, 4, 0, 5, 8, 0, 8, 5, 6, 6,
132   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
133   7, 7, 7, 7, 6, 6, 6, 6, 0, 5, 5, 5, 8, 5, 5, 5,
134   5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
135   5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
136   7, 0, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7,
137   2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
138   8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 3, 9, 0,
139   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
140   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
141   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
142   8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 0, 9, 0,
143   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
144   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
145   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
146 op_mat2[256] = {
147   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
148   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
149   0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
150   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
151   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
152   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
153   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
154   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
155   0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0,
156   0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
157   0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 7,
158   0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2,
159   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
160   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
161   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7,
162   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 },
163 op_mat3[256] = {
164   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
165   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
166   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
167   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
168   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
170   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
171   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
172   0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
173   0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
174   0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
175   0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
176   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
178   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
179   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
180 static char mnemonics[256][6] = {
181   "NEG  ","???  ","???  ","COM  ","LSR  ","???  ","ROR  ","ASR  ",
182   "LSL  ","ROL  ","DEC  ","???  ","INC  ","TST  ","JMP  ","CLR  ",
183   "PAGE1","PAGE2","NOP  ","SYNC ","???  ","???  ","LBRA ","LBSR ",
184   "???  ","DAA  ","ORCC ","???  ","ANDCC","SEX  ","EXG  ","TFR  ",
185   "BRA  ","BRN  ","BHI  ","BLS  ","BHS  ","BLO  ","BNE  ","BEQ  ",
186   "BVC  ","BVS  ","BPL  ","BMI  ","BGE  ","BLT  ","BGT  ","BLE  ",
187   "LEAX ","LEAY ","LEAS ","LEAU ","PSHS ","PULS ","PSHU ","PULU ",
188   "???  ","RTS  ","ABX  ","RTI  ","CWAI ","MUL  ","RESET","SWI  ",
189   "NEGA ","???  ","???  ","COMA ","LSRA ","???  ","RORA ","ASRA ",
190   "LSLA ","ROLA ","DECA ","???  ","INCA ","TSTA ","???  ","CLRA ",
191   "NEGB ","???  ","???  ","COMB ","LSRB ","???  ","RORB ","ASRB ",
192   "LSLB ","ROLB ","DECB ","???  ","INCB ","TSTB ","???  ","CLRB ",
193   "NEG  ","???  ","???  ","COM  ","LSR  ","???  ","ROR  ","ASR  ",
194   "LSL  ","ROL  ","DEC  ","???  ","INC  ","TST  ","JMP  ","CLR  ",
195   "NEG  ","???  ","???  ","COM  ","LSR  ","???  ","ROR  ","ASR  ",
196   "LSL  ","ROL  ","DEC  ","???  ","INC  ","TST  ","JMP  ","CLR  ",
197   "SUBA ","CMPA ","SCBA ","SUBD ","ANDA ","BITA ","LDA  ","???  ",
198   "EORA ","ADCA ","ORA  ","ADDA ","CMPX ","BSR  ","LDX  ","???  ",
199   "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA  ","STA  ",
200   "EORA ","ADCA ","ORA  ","ADDA ","CMPX ","JSR  ","LDX  ","STX  ",
201   "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA  ","STA  ",
202   "EORA ","ADCA ","ORA  ","ADDA ","CMPX ","JSR  ","LDX  ","STX  ",
203   "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA  ","STA  ",
204   "EORA ","ADCA ","ORA  ","ADDA ","CMPX ","JSR  ","LDX  ","STX  ",
205   "SUBB ","CMPB ","SCBB ","ADDD ","ANDB ","BITB ","LDB  ","???  ",
206   "EORB ","ADCB ","ORB  ","ADDB ","LDD  ","???  ","LDU  ","???  ",
207   "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB  ","STB  ",
208   "EORB ","ADCB ","ORB  ","ADDB ","LDD  ","STD  ","LDU  ","STU  ",
209   "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB  ","STB  ",
210   "EORB ","ADCB ","ORB  ","ADDB ","LDD  ","STD  ","LDU  ","STU  ",
211   "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB  ","STB  ",
212   "EORB ","ADCB ","ORB  ","ADDB ","LDD  ","STD  ","LDU  ","STU  " },
213 mnemonics2[256][6] = {
214   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
215   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
216   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
217   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
218   "???  ","LBRN ","LBHI ","LBLS ","LBHS ","LBLO ","LBNE ","LBEQ ",
219   "LBVC ","LBVS ","LBPL ","LBMI ","LBGE ","LBLT ","LBGT ","LBLE ",
220   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
221   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","SWI2 ",
222   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
223   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
224   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
225   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
226   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
227   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
228   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
229   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
230   "???  ","???  ","???  ","CMPD ","???  ","???  ","???  ","???  ",
231   "???  ","???  ","???  ","???  ","CMPY ","???  ","LDY  ","???  ",
232   "???  ","???  ","???  ","CMPD ","???  ","???  ","???  ","???  ",
233   "???  ","???  ","???  ","???  ","CMPY ","???  ","LDY  ","STY  ",
234   "???  ","???  ","???  ","CMPD ","???  ","???  ","???  ","???  ",
235   "???  ","???  ","???  ","???  ","CMPY ","???  ","LDY  ","STY  ",
236   "???  ","???  ","???  ","CMPD ","???  ","???  ","???  ","???  ",
237   "???  ","???  ","???  ","???  ","CMPY ","???  ","LDY  ","STY  ",
238   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
239   "???  ","???  ","???  ","???  ","???  ","???  ","LDS  ","???  ",
240   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
241   "???  ","???  ","???  ","???  ","???  ","???  ","LDS  ","STS  ",
242   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
243   "???  ","???  ","???  ","???  ","???  ","???  ","LDS  ","STS  ",
244   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
245   "???  ","???  ","???  ","???  ","???  ","???  ","LDS  ","STS  " },
246 mnemonics3[256][6] = {
247   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
248   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
249   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
250   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
251   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
252   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
253   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
254   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","SWI3 ",
255   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
256   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
257   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
258   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
259   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
260   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
261   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
262   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
263   "???  ","???  ","???  ","CMPU ","???  ","???  ","???  ","???  ",
264   "???  ","???  ","???  ","???  ","CMPS ","???  ","???  ","???  ",
265   "???  ","???  ","???  ","CMPU ","???  ","???  ","???  ","???  ",
266   "???  ","???  ","???  ","???  ","CMPS ","???  ","???  ","???  ",
267   "???  ","???  ","???  ","CMPU ","???  ","???  ","???  ","???  ",
268   "???  ","???  ","???  ","???  ","CMPS ","???  ","???  ","???  ",
269   "???  ","???  ","???  ","CMPU ","???  ","???  ","???  ","???  ",
270   "???  ","???  ","???  ","???  ","CMPS ","???  ","???  ","???  ",
271   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
272   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
273   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
274   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
275   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
276   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
277   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
278   "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  " },
279 tregs[16][3] = {
280   "D",  "X", "Y",  "U",  "S",  "PC", "??", "??",
281   "A",  "B", "CC", "DP", "??", "??", "??", "??" },
282 iregs[4][2] = {"X", "Y", "U", "S" };
283
284 //
285 // Read a byte from memory (without touching PC. Not a Fetch!)
286 //
287 uint8 RdMem(uint16 addr)
288 {
289         uint8 b;
290
291         if (addr < 0x8000)
292         {
293                 if (addr > 0x5FFF)
294                         b = data_rom[banksw1 + (addr - 0x6000)];        // Get char data
295                 else
296                         b = gram1[addr];
297         }
298         else
299                 b = grom1[addr];
300
301         return b;
302 }
303
304 //
305 // Write a byte to memory
306 //
307 void WrMem(uint16 addr, uint8 b)
308 {
309         extern bool charbase;                                                           // Needed for screen. Extern it in it??
310   //extern uint16 sr, ur, xr, yr;            // Needed for tracelog
311   //extern uint16 pcr;
312 /*  if ((addr>0x40FF) && (addr<0x4390))
313   {
314     tr << hex << addr << ":" << (int)b;
315     //for(int i=0; i<32; i++)
316     //{
317     //  if (gram1[0x4400+i]<0x10)  tr << "0";
318     //  tr << hex << (uint16)gram1[0x4400+i] << " ";
319     //}
320     tr << endl;
321   }//*/
322
323         if (addr == 0x6000)
324                 SpawnSound(GAMESOUND, gram1[0x6200], 0);                // Do voice chan 1
325         if (addr == 0x6400)
326                 SpawnSound(GAMESOUND, gram1[0x6600], 1);                // Do voice chan 2
327         if (addr == 0x6800)
328                 banksw1 = (uint32)b << 13;                                              // Set char data bankswitch base address
329         if (addr > 0x4284 && addr < 0x42A5 && b)
330                 SpawnSound(PSGSOUND, addr - 0x4285);                    // Do PSG sound on chans 2, 3
331         if (addr == 0x4380)
332         {
333                 SpawnSound(FMSOUND, b);                                                 // Do FM sound on channel 4
334                 if (b == 12)
335                         game_over_switch = 240;                                         // Set game over delay...
336         }
337         if (addr < 0x423D || addr > 0x425C)                                     // Protect writes to DSWs
338                 gram1[addr] = b;
339         if (addr == 0x8800)
340                 charbase = false;                                                               // Char banksw1
341         if (addr == 0x8C00)
342                 charbase = true;                                                                // Char banksw2
343         if (addr == 0x8400)                                                                     // Frame go strobe? VBlank acknowledge?
344         {
345                 if (refresh_++ == 1)                                                            // 30 Hz...
346                 {
347                         BlitChar(screen, chr_rom, gram1);
348                         refresh_ = (refresh2 ? 1 : 0);                          // 60/30 Hz...
349                 }
350 //              irqGoA = true; // Will this work??? no...
351                 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
352         }
353 }
354
355 //
356 // Read a byte from memory (without touching PC. Not a Fetch!) (2nd processor)
357 //
358 uint8 RdMemB(uint16 addr)
359 {
360 //  extern uint16 cpu2.s, cpu2.u, cpu2.x, cpu2.y;            // Needed for tracelog
361         uint8 b;
362
363         if (addr < 0x8000)
364         {
365                 if (addr < 0x2000)
366                         b = gram1[addr + 0x4000];
367                 if (addr > 0x1FFF && addr < 0x6000)
368                         b = gram1[addr - 0x2000];
369                 if (addr > 0x5FFF)
370                         b = grom3[banksw2 + (addr - 0x6000)];           // Correct?
371         }
372         else
373                 b = grom2[addr];
374
375 /*  if ((addr>0x3FFF) && (addr<0x4400))  tr << "R-" << hex << pcx << ": "
376                                         << addr << "-"
377                                         << (int)looking_at_rom
378                                         << " [" << (int)b
379                                         << "] XR:" << xr << " YR:" << yr
380                                         << " SR:" << sr << " UR:" << ur
381                                         << endl; //*/
382         return b;
383 }
384
385 //
386 // Write a byte to memory (2nd processor)
387 //
388 void WrMemB(uint16 addr, uint8 b)
389 {
390         extern bool charbase;
391   //extern uint16 sr, ur, xr, yr;            // Needed for tracelog
392   //extern uint16 pcr;
393 /*  if ((addr>0x00FF) && (addr<0x0390))
394   {
395     tr << hex << addr << ":" << (int)b;
396     //for(int i=0; i<32; i++)
397     //{
398     //  if (gram1[0x4400+i]<0x10)  tr << "0";
399     //  tr << hex << (uint16)gram1[0x4400+i] << " ";
400     //}
401     tr << endl;
402   }//*/
403
404         if (addr == 0x8800)
405 //              irqGoB = true;                                                                  // Will it work??? no...
406                 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;//wil wok???
407         if (addr == 0x6000)
408                 SpawnSound(GAMESOUND, gram1[0x6200], 0);                // Do voice chan 1
409         if (addr == 0x6400)
410                 SpawnSound(GAMESOUND, gram1[0x6600], 1);                // Do voice chan 2
411         if (addr > 0x0284 && addr < 0x02A5 && b)
412                 SpawnSound(PSGSOUND, addr - 0x0285);                    // Do PSG sound on chans 2, 3
413         if (addr == 0xD803)
414                 banksw2 = (uint32)(b & 0x03) << 13;                             // Set sprite data bank switch
415         if (addr == 0x0380)
416         {
417                 SpawnSound(FMSOUND, b);                                                 // Do FM sound on chan 4
418                 if (b == 12)
419                         game_over_switch = 240;                                         // Set game over delay...
420         }
421         if (addr < 0x023D || addr > 0x025C)                                     // Protect writes against DSWs
422         {
423                 if (addr < 0x2000)
424                         gram1[addr + 0x4000] = b;
425                 if (addr > 0x1FFF && addr < 0x6000)
426                         gram1[addr - 0x2000] = b;
427                 if (addr > 0x5FFF)
428                         gram1[addr] = b;
429         }
430 }
431
432 //
433 // Display bytes in mem in hex
434 //
435 void DisplayBytes(uint16 src, unsigned long dst)
436 {
437   uint8 cnt;
438   unsigned long i;
439
440   printf("%04X: ", src);
441   cnt = 0;                               // Init counter...
442   if (src > dst)  dst += 0x10000;        // That should fix the FFFF bug...
443   for(i=src; i<dst; i++)
444   {
445     printf("%02X ", (uint8)(looking_at_rom ? RdMem(i) : RdMemB(i)));
446     cnt++;                               // Bump counter...
447   }
448   for(i=cnt; i<5; i++)                   // Pad the leftover spaces...
449   {
450     cout << "   ";
451   }
452 }
453
454 // temp crap...
455 uint8 Fetch(void) { return 0; }
456 uint16 FetchW(void) { return 0; }
457 uint8 FetchB(void) { return 0; }
458 uint16 FetchWB(void) { return 0; }
459
460 //
461 // Decode a 6809 instruction at 'addr'
462 //
463 void Decode_6809()
464 {
465   uint8 (* DFetch)();           // Decode Fetch() pointer...
466   uint16 (* DFetchW)();          // Decode FetchW() pointer...
467   DFetch  = (looking_at_rom ? Fetch : FetchB);
468   DFetchW = (looking_at_rom ? FetchW : FetchWB);
469
470 /*  extern*/ uint16 pcr, pcrB;              // Pull in 'pcr' from '6809.cpp'
471   uint16 pc_save = pcr, pcB_save = pcrB;
472   pcr  = dpc;  pcrB = dpc;
473   uint8 opcode = DFetch();             // Get the opcode ('fetch' cycle)
474   uint8 opcode2, operand;
475   uint16 loperand;
476   uint8 admode = op_mat1[opcode];     // addressing mode
477   char outbuf[80], mnem[6], tmp[30];
478
479   strcpy(mnem, mnemonics[opcode]);  // Copy page 1 opcode
480   if (opcode == 0x10)             // Extended opcode?
481   {
482     opcode2 = DFetch();     // Then get next byte
483     admode = op_mat2[opcode2];    // And use it as index into 'op_mat2'
484     strcpy(mnem, mnemonics2[opcode2]);  // Overwrite mnemonic
485   }
486   if (opcode == 0x11)             // Same as above...
487   {
488     opcode2 = DFetch();
489     admode = op_mat3[opcode2];
490     strcpy(mnem, mnemonics3[opcode2]);  // Overwrite mnemonic
491   }
492   switch(admode)                  // Decode it...
493   {
494     case 0:  // Illegal
495     { sprintf(outbuf, "???");  break; }
496     case 1:  // Zero page
497     { operand = DFetch();   // Get ZP address
498       sprintf(outbuf, "%s $%02X", mnem, operand);
499       break; }
500     case 2:  // Absolute
501     { loperand = DFetchW(); // Get ABS address
502       sprintf(outbuf, "%s $%04X", mnem, loperand);
503       break; }
504     case 3:  // Relative
505     { operand = DFetch();   // Get offset
506       uint16 tmpc = (looking_at_rom ? pcr : pcrB);
507       sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16)(int8)operand);
508       break; }
509     case 4:  // Long Relative
510     { loperand = DFetchW(); // Get long offset
511       uint16 tmpc = (looking_at_rom ? pcr : pcrB);
512       sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16)loperand);
513       break; }
514     case 5:  // Inherent
515     { sprintf(outbuf, "%s ", mnem);
516       break; }
517     case 6:  // Txfr/exchg/push/pull
518     { operand = DFetch();   // Get txfr/exg/push/pull byte
519       if ((opcode == 0x1E) || (opcode == 0x1F))  // Is it TXF/EXG?
520       {
521         sprintf(tmp, "%s,%s", tregs[operand>>4], tregs[operand&0x0F]);
522       }
523       else
524       {
525         tmp[0] = 0;
526         if (operand&0x01)  strcat(tmp, "CC ");
527         if (operand&0x02)  strcat(tmp, "A ");
528         if (operand&0x04)  strcat(tmp, "B ");
529         if (operand&0x08)  strcat(tmp, "DP ");
530         if (operand&0x10)  strcat(tmp, "X ");
531         if (operand&0x20)  strcat(tmp, "Y ");
532         if (operand&0x40)  (((opcode==0x34)||(opcode==0x35))
533                        ? strcat(tmp, "U ") : strcat(tmp, "S "));
534         if (operand&0x80)  strcat(tmp, "PC");
535       }
536       sprintf(outbuf, "%s %s", mnem, tmp);
537       break; }
538     case 7:  // Indexed (the tough one!)
539     { operand = DFetch();   // Get IDX byte
540       uint8 reg = ((operand & 0x60) >> 5), idxind = ((operand & 0x10) >> 4),
541            lo_nyb = (operand & 0x0F),  boff;
542       uint16 woff;
543
544       strcpy(tmp, "??");
545       if (!(operand & 0x80))      // Hi bit set? Then decode 4 bit offset
546       {
547         sprintf(tmp, "(%d),%s", (idxind ? -(16-lo_nyb) : lo_nyb),
548                 iregs[reg]);
549       }
550       else   // Add the ($nnnn,R) code dude...
551       {
552         if (idxind)
553         {
554           switch(lo_nyb)
555           {
556             case 1:   sprintf(tmp, "(,%s++)", iregs[reg]);  break;
557             case 3:   sprintf(tmp, "(,--%s)", iregs[reg]);  break;
558             case 4:   sprintf(tmp, "(,%s)", iregs[reg]);  break;
559             case 5:   sprintf(tmp, "(B,%s)", iregs[reg]);  break;
560             case 6:   sprintf(tmp, "(A,%s)", iregs[reg]);  break;
561             case 8:
562             { boff = DFetch();  sprintf(tmp, "($%02X,%s)", boff,
563                                        iregs[reg]);  break; }
564             case 9:
565             { woff = DFetchW();  sprintf(tmp, "($%04X,%s)", woff,
566                                         iregs[reg]);  break; }
567             case 11:  sprintf(tmp, "(D,%s)", iregs[reg]);  break;
568             case 12:
569             { boff = DFetch();  sprintf(tmp, "($%02X,PC)", boff);  break; }
570             case 13:
571             { woff = DFetchW();  sprintf(tmp, "($%04X,PC)", woff);  break; }
572             case 15:
573             { woff = DFetchW();  sprintf(tmp, "[$%04X]", woff);  break; }
574             default:  strcpy(tmp, "??");
575           }
576         }
577         else
578         {
579           switch(lo_nyb)
580           {
581             case 0:   sprintf(tmp, ",%s+", iregs[reg]);  break;
582             case 1:   sprintf(tmp, ",%s++", iregs[reg]);  break;
583             case 2:   sprintf(tmp, ",-%s", iregs[reg]);  break;
584             case 3:   sprintf(tmp, ",--%s", iregs[reg]);  break;
585             case 4:   sprintf(tmp, ",%s", iregs[reg]);  break;
586             case 5:   sprintf(tmp, "(B),%s", iregs[reg]);  break;
587             case 6:   sprintf(tmp, "(A),%s", iregs[reg]);  break;
588             case 8:
589             { boff = DFetch();  sprintf(tmp, "($%02X),%s", boff,
590                                        iregs[reg]);  break; }
591             case 9:
592             { woff = DFetchW();  sprintf(tmp, "($%04X),%s", woff,
593                                        iregs[reg]);  break; }
594             case 11:  sprintf(tmp, "(D),%s", iregs[reg]);  break;
595             case 12:
596             { boff = DFetch();  sprintf(tmp, "($%02X),PC", boff);  break; }
597             case 13:
598             { woff = DFetchW();  sprintf(tmp, "($%04X),PC", woff);  break; }
599             default:  strcpy(tmp, "??");
600           }
601         }
602       }
603       sprintf(outbuf, "%s %s", mnem, tmp);
604       break; }
605     case 8:  // Immediate
606     { operand = DFetch();   // Get IMM byte
607       sprintf(outbuf, "%s #$%02X", mnem, operand);
608       break; }
609     case 9:  // Long Immediate
610     { loperand = DFetchW(); // Get IMM word
611       sprintf(outbuf, "%s #$%04X", mnem, loperand);
612       break; }
613   }
614   DisplayBytes(dpc, (looking_at_rom ? pcr : pcrB));  // Show bytes
615   cout << outbuf << endl;     // display opcode & addressing, etc
616   dpc = (looking_at_rom ? pcr : pcrB);  // Advance debug PC
617   pcr = pc_save;  pcrB = pcB_save;  // Restore PCs
618 }
619
620 //
621 // Convert hex to dec
622 //
623 uint16 htod(char *str)
624 {
625   uint16 value = 0;
626   int len = strlen(str);
627
628   for(int i=0; i<len; i++)
629   {
630     if (str[i]>='0' && str[i]<='9')
631     {
632       value = (value<<4) | (unsigned)(str[i]-'0');
633     }
634     if (str[i]>='a' && str[i]<='f')
635     {
636       value = (value<<4) | (unsigned)(str[i]-'a')+10;
637     }
638     if (str[i]>='A' && str[i]<='F')
639     {
640       value = (value<<4) | (unsigned)(str[i]-'A')+10;
641     }
642   }
643   return(value);
644 }
645
646 //
647 // Load 32K file into ROM image space
648 //
649 bool Load32KImg(char * filename, uint16 address)
650 {
651   ifstream ff;
652   char ch;
653
654   ff.open(filename, ios::binary | ios::in);  // Open 'da file...
655   if (ff)
656   {
657     for(long i=0; i<32768; i++)                // Read it in...
658     {
659       ff.get(ch);
660       grom[address+i] = ch;
661     }
662     ff.close();                                // Close 'da file...
663   }
664   return(ff);
665 }
666
667 //
668 // Generic Load file into image space
669 // (No error checking performed!  Responsibility of caller!)
670 //
671 bool LoadImg(const char * filename, uint8 * mem, uint32 address, uint32 length)
672 {
673   ifstream ff;
674   char path[80];
675   char ch;
676
677   strcpy(path, "./ROMs/");
678   strcat(path, filename);
679 //  ff.open(filename, ios::binary | ios::in);  // Open 'da file...
680   ff.open(path, ios::binary | ios::in);       // Open 'da file...
681   if (ff)
682   {
683     for(uint32 i=0; i<length; i++)             // Read it in...
684     {
685       ff.get(ch);
686       mem[address+i] = ch;
687     }
688     ff.close();                               // Close 'da file...
689   }
690   return(ff);
691 }
692
693 //
694 // Read color PROMs
695 //
696 bool ReadColorPROMs(void)
697 {
698   fstream ff1, ff2;
699 //  uint8 ch;
700   char ch;
701   extern uint8 palette[768];     // Screen physical palette
702   extern uint8 ccolor[256][8];   // Character color PROM values
703   extern uint8 scolor[128][16];  // Sprite color PROM values
704
705   ff1.open("./ROMs/"PROM3, ios::binary|ios::in);
706   if (ff1)
707   {
708     for(int i=0; i<256; i++) // Load char pallete with PROM values
709     {
710       for(int j=0; j<8; j++)
711       {
712         ff1.get(ch);
713         ccolor[i][j] = (uint8)ch;
714       }
715     }
716     ff1.close();
717   }
718   ff1.open("./ROMs/"PROM4, ios::binary|ios::in);
719   if (ff1)
720   {
721     for(int i=0; i<128; i++) // Load sprite pallete with PROM values
722     {
723       for(int j=0; j<16; j++)
724       {
725         ff1.get(ch);
726         scolor[i][j] = (uint8)ch;
727       }
728     }
729     ff1.close();
730   }
731
732   ff1.open("./ROMs/"PROM1, ios::binary|ios::in);
733   ff2.open("./ROMs/"PROM2, ios::binary|ios::in);
734   if (ff1)    // If open was successful...
735   {
736     for(int i=0; i<768; i+=3)
737     {
738       ff1.get(ch);
739       palette[i]   = (uint8)(ch&0x0F);
740       palette[i+1] = (uint8)(ch>>4);
741       ff2.get(ch);
742       palette[i+2] = (uint8)ch;
743     }
744
745     // Do palette stretching here... I.e. add 0 to hinyb 0, 1 to hinyb 1, etc.
746
747     for(int i=0; i<768; i++)
748       palette[i] = ((palette[i]<<4)&0xF0) | (palette[i]&0x0F);
749
750     ff1.close();
751     ff2.close();
752   }
753   return ff1;
754 }
755
756 //
757 // Unpack font data
758 //
759 bool UnpackFonts(void)
760 {
761 //  uint8 b1, b2, b3;
762   char b1, b2, b3;
763   fstream f1, f2;
764   //0x4000 $800 chars
765   f1.open("./ROMs/"ROM7, ios::binary | ios::in);
766   f2.open("./ROMs/"ROM8, ios::binary | ios::in);
767   if ((!f1) || (!f2))  return false;  // Return if not found...
768   for(long i=0; i<0x40000; i+=64)
769   {
770     for(int j=0; j<64; j+=8)
771     {
772       f1.get(b1);  f1.get(b2);  f2.get(b3);
773       b3 ^= 0xFF; // Invert top data...
774       chr_rom[i+j] = ((b3 & 0x80) >> 5) | ((b1 & 0x80) >> 6) | ((b1 & 0x08) >> 3);
775       chr_rom[i+j+1] = ((b3 & 0x40) >> 4) | ((b1 & 0x40) >> 5) | ((b1 & 0x04) >> 2);
776       chr_rom[i+j+2] = ((b3 & 0x20) >> 3) | ((b1 & 0x20) >> 4) | ((b1 & 0x02) >> 1);
777       chr_rom[i+j+3] = ((b3 & 0x10) >> 2) | ((b1 & 0x10) >> 3) | (b1 & 0x01);
778       chr_rom[i+j+4] = ((b3 & 0x08) >> 1) | ((b2 & 0x80) >> 6) | ((b2 & 0x08) >> 3);
779       chr_rom[i+j+5] = (b3 & 0x04)        | ((b2 & 0x40) >> 5) | ((b2 & 0x04) >> 2);
780       chr_rom[i+j+6] = ((b3 & 0x02) << 1) | ((b2 & 0x20) >> 4) | ((b2 & 0x02) >> 1);
781       chr_rom[i+j+7] = ((b3 & 0x01) << 2) | ((b2 & 0x10) >> 3) | (b2 & 0x01);
782     }
783   }
784   f1.close();
785   f2.close();
786
787   f1.open("./ROMs/"ROM5, ios::binary | ios::in);
788   f2.open("./ROMs/"ROM6, ios::binary | ios::in);
789   for(long i=0x40000; i<0x60000; i+=64)
790   {
791     for(int j=0; j<64; j+=8)
792     {
793       f1.get(b1);  f1.get(b2);  f2.get(b3);
794       b3 ^= 0xFF;                             // Invert top data
795       chr_rom[i+j] = ((b3 & 0x80) >> 5) | ((b1 & 0x80) >> 6) | ((b1 & 0x08) >> 3);
796       chr_rom[i+j+1] = ((b3 & 0x40) >> 4) | ((b1 & 0x40) >> 5) | ((b1 & 0x04) >> 2);
797       chr_rom[i+j+2] = ((b3 & 0x20) >> 3) | ((b1 & 0x20) >> 4) | ((b1 & 0x02) >> 1);
798       chr_rom[i+j+3] = ((b3 & 0x10) >> 2) | ((b1 & 0x10) >> 3) | (b1 & 0x01);
799       chr_rom[i+j+4] = ((b3 & 0x08) >> 1) | ((b2 & 0x80) >> 6) | ((b2 & 0x08) >> 3);
800       chr_rom[i+j+5] = (b3 & 0x04)        | ((b2 & 0x40) >> 5) | ((b2 & 0x04) >> 2);
801       chr_rom[i+j+6] = ((b3 & 0x02) << 1) | ((b2 & 0x20) >> 4) | ((b2 & 0x02) >> 1);
802       chr_rom[i+j+7] = ((b3 & 0x01) << 2) | ((b2 & 0x10) >> 3) | (b2 & 0x01);
803     }
804   }
805   f1.close();
806   f2.close();
807   return true;                                // Made it!
808 }
809
810 //
811 // Get length of sample from WAV format
812 //
813 uint32 GetWAVLength(fstream &file)
814 {
815         char ch;
816         uint32 len;
817
818         file.ignore(16);                                                                        // Skip header BS
819
820         for(int i=0; i<2; i++)
821         {
822                 file.get(ch);  len = (int)(uint8)ch;
823                 file.get(ch);  len |= (int)(uint8)ch << 8;
824                 file.get(ch);  len |= (int)(uint8)ch << 16;
825                 file.get(ch);  len |= (int)(uint8)ch << 24;
826
827                 file.ignore(len + 4);                                                   // Skip intermediate data
828         }
829
830         file.get(ch);  len = (int)(uint8)ch;                                    // & finally get length of data
831         file.get(ch);  len |= (int)(uint8)ch << 8;
832         file.get(ch);  len |= (int)(uint8)ch << 16;
833         file.get(ch);  len |= (int)(uint8)ch << 24;
834
835         return len;
836 }
837
838 //
839 // Load PSG samples from disk
840 //
841 void LoadPSGs(void)
842 {
843         char file[40];
844         char ch;
845         uint32 len;
846
847         for(int i=0; i<16; i++)
848         {
849                 fstream fp;
850
851                 psg_adrs[i] = NULL;                                                             // Zero out pointer
852                 sprintf(file, "./sounds/psg%i.wav", i);                 // Create filename
853
854                 fp.open(file, ios::binary | ios::in);                   // Attempt to open it...
855
856                 if (fp)
857                 {
858                         len = GetWAVLength(fp);                                         // Get WAV data length...
859
860                         psg_adrs[i] = new uint8[len];                           // Attempt to allocate space...
861
862                         if (psg_adrs[i] != NULL)
863                         {
864                                 for(int j=0; j<(signed)len; j++)
865                                 {
866                                         fp.get(ch);
867                                         psg_adrs[i][j] = ch;                            // & load it in...
868                                 }
869
870                                 psg_lens[i] = len;
871                                 cout << "Found sample file: " << file << " [Length: " << dec << len << "]" << endl;
872                         }
873
874                         fp.close();
875                 }
876         }
877 }
878
879 //
880 // Load FM samples from disk
881 //
882 void LoadFMs(void)
883 {
884         char file[200];
885         char ch;
886         uint32 len;
887
888         for(int i=0; i<14; i++)
889         {
890                 fstream fp;
891
892                 fm_adrs[i] = NULL;                                                              // Zero out pointer
893                 sprintf(file, "./sounds/fm%i.wav", i);                  // Create filename
894
895                 fp.open(file, ios::binary | ios::in);                   // Attempt to open it...
896
897                 if (fp)
898                 {
899                         len = GetWAVLength(fp);                                         // Get WAV length...
900
901                         fm_adrs[i] = new uint8[len];                                    // Attempt to allocate space...
902
903                         if (fm_adrs[i] != NULL)
904                         {
905                                 for(int j=0; j<(signed)len; j++)
906                                 {
907                                         fp.get(ch);
908                                         fm_adrs[i][j] = ch;                                     // & load it in...
909                                 }
910
911                                 fm_lens[i] = len;
912                                 cout << "Found sample file: " << file << " [Length: " << dec << len
913                                         << "]" << endl;
914                         }
915
916                         fp.close();
917                 }
918         }
919 }
920
921 //
922 // Main loop
923 //
924 int main(int argc, char * argv[])
925 {
926         InitLog("thunder.log");
927
928 /*  extern uint16 cpu1.pc, cpu1.s, cpu1.u, cpu1.x, cpu1.y;            // Pull in vars from '6809.cpp'
929   extern uint8 cpu1.a, cpu1.b, cpu1.cc, cpu1.dp;
930   extern long iclock;
931   extern bool illegal;
932   extern uint16 cpu2.pc, cpu2.s, cpu2.u, cpu2.x, cpu2.y;       // Pull in vars from '6809B.cpp'
933   extern uint8 cpu2.a, cpu2.b, cpu2.cc, cpu2.dp;
934   extern long iclockB;
935   extern bool illegalB;
936   extern void (* exec_op0[256])();   // Array of page zero opcode functions...
937   extern void (* exec_op1[256])();   // Array of page one opcode functions...
938   extern void (* exec_op2[256])();   // Array of page two opcode functions...
939   extern void (* exec_op0B[256])();  // Array of page zero opcode functions...
940   extern void (* exec_op1B[256])();  // Array of page one opcode functions...
941   extern void (* exec_op2B[256])();  // Array of page two opcode functions...*/
942   extern bool charbase;                                                                 // From 'SCREEN.CPP'
943 //  extern unsigned int vesa_memptr;
944   charbase = false;
945
946   char lbuff[80];
947   fstream ff;                       // Declare fstream without file hooks...
948   bool brk = false, brk2 = false;   // Breakpoint set flag
949   uint16 brkpnt, brkpnt2;             // Where the breakpoint is...
950   bool running;                     // CPU running state flag...
951   bool self_test = false;           // Self-test switch
952   bool scr_type = false;            // false=chars, true=pixels
953   uint16 debounce = 0;                // Key de-bounce counter
954   uint16 fire_debounce = 0;           // Fire button debounce counter
955 //  bool refresh2 = true;             // Default to 60 Hz...
956   uint8 x;                           // General placeholder...
957   bool active = true;               // Program running flag
958
959 //  SDL_Surface * screen = NULL;      // SDL screen pointer
960   SDL_Event event;                  // SDL "event"
961 //  int keyPressed;                   // SDL key pressed...
962   uint8 keys[256];                   // Keyboard "switch-like" buffer
963   extern uint8 palette[768];         // Screen physical palette
964   uint32 ticks, oldTicks;
965
966 //  tr.open("exe.log", ios::binary | ios::out); // Tracelog
967
968   cout << endl << "THUNDER v"THUNDER_VERSION" ";
969   cout << "by James Hammmmons" << endl;
970   cout << "Serial #20090723 / Prerelease" << endl;
971   cout << "(C) 2003, 2009 Underground Software" << endl << endl;
972
973   cout << "This emulator is free software. If you paid for it you were RIPPED OFF"
974        << endl << endl;
975
976   cout << "Initializing SDL..." << endl;
977
978   if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
979   {
980     cout << "Couldn't initialize SDL: " << SDL_GetError() << endl;
981     return -1;
982   }
983
984   SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder");
985
986   cout << "Allocating memory..." << endl;
987 //Does this anyway...  set_new_handler(0);    // Make 'new' return NULL on failure...
988   gram1 = new uint8[0x10000];
989   if (gram1 == NULL)  { cout << "Could not allocate RAM space #1!" << endl
990                       << "Aborting!" << endl;  return -1; }
991   grom1 = new uint8[0x10000];
992   if (grom1 == NULL)  { cout << "Could not allocate ROM space #1!" << endl
993                       << "Aborting!" << endl;  return -1; }
994   gram2 = new uint8[0x10000];
995   if (gram2 == NULL)  { cout << "Could not allocate RAM space #2!" << endl
996                       << "Aborting!" << endl;  return -1; }
997   grom2 = new uint8[0x10000];
998   if (grom2 == NULL)  { cout << "Could not allocate ROM space #2!" << endl
999                       << "Aborting!" << endl;  return -1; }
1000   chr_rom = new uint8[0x60000];
1001   if (chr_rom == NULL)  { cout << "Could not allocate character RAM!" << endl
1002                       << "Aborting!" << endl;  return -1; }
1003   grom3 = new uint8[0x8000];
1004   if (grom3 == NULL)  { cout << "Could not allocate ROM space #4!" << endl
1005                       << "Aborting!" << endl;  return -1; }
1006   grom4 = new uint8[0x8000];
1007   if (grom4 == NULL)  { cout << "Could not allocate ROM space #5!" << endl
1008                       << "Aborting!" << endl;  return -1; }
1009   data_rom = new uint8[0x40000];
1010   if (data_rom == NULL)  { cout << "Could not allocate ROM level data!" << endl
1011                       << "Aborting!" << endl;  return -1; }
1012   spr_rom = new uint8[0x80000];
1013   if (spr_rom == NULL)  { cout << "Could not allocate ROM sprite data!" << endl
1014                       << "Aborting!" << endl;  return -1; }
1015   voice_rom = new uint8[0x20000];
1016   if (voice_rom == NULL)  { cout << "Could not allocate ROM voice data!" << endl
1017                       << "Aborting!" << endl;  return -1; }
1018
1019   gram = gram1;  grom = grom1;           // Needed only for debugger
1020
1021   for(long i=0; i<0x10000; i++)
1022   {
1023     gram[i] = 0;  grom[i] = 0;           // Zero out memory
1024     gram2[i] = 0;  grom2[i] = 0;
1025   }
1026   game_over_switch = 0;   // Init game over delay
1027 //  cpu1.a = 0; cpu1.b = 0; cpu1.cc = 0; cpu1.dp = 0; cpu1.x = 0; cpu1.y = 0; cpu1.s = 0; ur = 0; cpu1.pc = 0;
1028
1029   cout << "Loading ROMs..." << endl;
1030 //  LoadCMOS();                            // Load CMOS at $CC00-$CFFF
1031   if (!ReadColorPROMs())                   // Load virtual PROMs
1032   { cout << "Could not open PROM files!" << endl;  return -1; }
1033
1034   if (!LoadImg(ROM1, grom1, 0x8000, 0x8000)) // Load $8000-$FFFF 1st ROM
1035   { cout << "Could not open file '" << ROM1 << "'!" << endl;  return -1; }
1036
1037   if (!LoadImg(ROM2, grom2, 0x8000, 0x8000)) // Load $8000-$FFFF 2nd ROM
1038   { cout << "Could not open file '" << ROM2 << "'!" << endl;  return -1; }
1039
1040   if (!LoadImg(ROM3, grom3, 0, 0x8000))      // Load 3rd ROM into its own space
1041   { cout << "Could not open file '" << ROM3 << "'!" << endl;  return -1; }
1042
1043   if (!LoadImg(ROM4, grom4, 0, 0x8000))      // Load 4rd ROM into its own space
1044   { cout << "Could not open file '" << ROM4 << "'!" << endl;  return -1; }
1045
1046   if (!LoadImg(ROM17, data_rom, 0,       0x10000))  // Load 17th ROM
1047   { cout << "Could not open file '" << ROM17 << "'!" << endl;  return -1; }
1048
1049   if (!LoadImg(ROM18, data_rom, 0x10000, 0x10000))  // Load 18th ROM
1050   { cout << "Could not open file '" << ROM18 << "'!" << endl;  return -1; }
1051
1052   if (!LoadImg(ROM19, data_rom, 0x20000, 0x10000))  // Load 19th ROM
1053   { cout << "Could not open file '" << ROM19 << "'!" << endl;  return -1; }
1054
1055   if (!LoadImg(ROM20, data_rom, 0x30000, 0x10000))  // Load 20th ROM
1056   { cout << "Could not open file '" << ROM20 << "'!" << endl;  return -1; }
1057
1058   if (!LoadImg(ROM9,  spr_rom, 0,       0x10000))   // Load 9th ROM
1059   { cout << "Could not open file '" << ROM9 << "'!" << endl;  return -1; }
1060
1061   if (!LoadImg(ROM10, spr_rom, 0x10000, 0x10000))   // Load 10th ROM
1062   { cout << "Could not open file '" << ROM10 << "'!" << endl;  return -1; }
1063
1064   if (!LoadImg(ROM11, spr_rom, 0x20000, 0x10000))   // Load 11th ROM
1065   { cout << "Could not open file '" << ROM11 << "'!" << endl;  return -1; }
1066
1067   if (!LoadImg(ROM12, spr_rom, 0x30000, 0x10000))   // Load 12th ROM
1068   { cout << "Could not open file '" << ROM12 << "'!" << endl;  return -1; }
1069
1070   if (!LoadImg(ROM13, spr_rom, 0x40000, 0x10000))   // Load 13th ROM
1071   { cout << "Could not open file '" << ROM13 << "'!" << endl;  return -1; }
1072
1073   if (!LoadImg(ROM14, spr_rom, 0x50000, 0x10000))   // Load 14th ROM
1074   { cout << "Could not open file '" << ROM14 << "'!" << endl;  return -1; }
1075
1076   if (!LoadImg(ROM15, spr_rom, 0x60000, 0x10000))   // Load 15th ROM
1077   { cout << "Could not open file '" << ROM15 << "'!" << endl;  return -1; }
1078
1079   if (!LoadImg(ROM16, spr_rom, 0x70000, 0x10000))   // Load 16th ROM
1080   { cout << "Could not open file '" << ROM16 << "'!" << endl;  return -1; }
1081
1082   if (!LoadImg(ROM21, voice_rom, 0, 0x10000))  // Load 21st ROM
1083   { cout << "Could not open file '" << ROM21 << "'!" << endl;  return -1; }
1084
1085   if (!LoadImg(ROM22, voice_rom, 0x10000, 0x10000))  // Load 22nd ROM
1086   { cout << "Could not open file '" << ROM22 << "'!" << endl;  return -1; }
1087
1088   if (!UnpackFonts())                         // Load 5, 6, 7, 8th ROMs
1089   {
1090     cout << "Could not open font files!" << endl;
1091     return -1;
1092   }
1093
1094         // Load samples if they're there...
1095         LoadPSGs();
1096         LoadFMs();
1097
1098   // Quick 'n' Dirty voice dump (sound 0x0E)
1099 /*  uint32 adc = (voice_rom[26]<<8) | voice_rom[27];
1100   bool doneWitIt = false;
1101   int crh = 0;
1102   while (!doneWitIt)
1103   {
1104     if (voice_rom[adc] < 0x10)  tr << "0";
1105     tr << hex << (int)voice_rom[adc] << " ";
1106     if (crh++ > 24)  { crh = 0;  tr << endl; }
1107     if ((voice_rom[adc] == 0xFF) && (voice_rom[adc-1] != 0x00))
1108       doneWitIt = true;
1109     adc++;
1110   }//*/
1111
1112         // Set up V6809 execution contexts
1113
1114         memset(&cpu1, 0, sizeof(V6809REGS));
1115         cpu1.RdMem = RdMem;
1116         cpu1.WrMem = WrMem;
1117         cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
1118
1119         memset(&cpu2, 0, sizeof(V6809REGS));
1120         cpu2.RdMem = RdMemB;
1121         cpu2.WrMem = WrMemB;
1122         cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
1123
1124         bool firstTime = true;                                                          // kludge...
1125
1126 WriteLog("About to go to the main loop...\n");
1127         while (active)
1128         {
1129                 cout << ">";
1130                 if (firstTime)
1131                 {
1132                         firstTime = false;                                                      // crappy kludge...
1133                         lbuff[0] = 'r';
1134                         lbuff[1] = 0;
1135                 }
1136                 else
1137                         cin >> lbuff;
1138
1139                 if (lbuff[0] == 'd')
1140                 {
1141                         if (lbuff[1] != 0)
1142                         {
1143                                 lbuff[0] = 32;
1144                                 dpc = htod(lbuff);
1145                         }
1146                         printf("%04X: ", dpc);
1147                         uint16 pc_save = cpu1.pc, pcB_save = cpu2.pc;
1148                         cpu1.pc = dpc;  cpu2.pc = dpc;
1149                         for(int i=0; i<16; i++)
1150                                 printf("%02X ", (looking_at_rom ? Fetch() : FetchB()));
1151                         cout << " ";
1152                         cpu1.pc = dpc;  cpu2.pc = dpc;
1153                         for(int i=0; i<16; i++)
1154                         {
1155                                 uint8 a = (looking_at_rom ? Fetch() : FetchB());
1156                                 if (a<10)             cout << (char)(a+48);
1157                                 if ((a>9) && (a<37))  cout << (char)(a+55);
1158                                 if (a>36)             cout << ".";
1159                         }
1160                         cout << endl;
1161                         dpc = (looking_at_rom ? cpu1.pc : cpu2.pc);
1162                         cpu1.pc = pc_save;  cpu2.pc = pcB_save;
1163                 }
1164                 else if (lbuff[0] == 'e')
1165                 {
1166                         if (lbuff[1] != 0)
1167                         {
1168                                 lbuff[0] = 32;
1169                                 dpc = htod(lbuff);
1170                         }
1171                         printf("%04X: ", dpc);
1172                         for(int i=0; i<16; i++)  printf("%02X ", (uint8)gram[dpc++]);
1173                         cout << endl;
1174                 }
1175                 else if (lbuff[0] == 'l')
1176                 {
1177                         if (lbuff[1] != 0)
1178                         {
1179                                 lbuff[0] = 32;
1180                                 dpc = htod(lbuff);
1181                         }
1182                         for(int i=0; i<23; i++)
1183                                 Decode_6809();
1184                 }
1185                 else if (lbuff[0] == 't')
1186                 {
1187                         if (lbuff[1] != 0)
1188                         {
1189                                 lbuff[0] = 32;
1190                                 dpc = htod(lbuff);
1191                         }
1192                         if (looking_at_rom)
1193                         {
1194                                 cpu1.pc = dpc;
1195                                 Decode_6809();
1196                                 Execute6809(&cpu1, 1);
1197                                 dpc = cpu1.pc;
1198                                 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1199                                         cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1200                                 cout << " iclock=" << cpu1.clock << endl;
1201                         }
1202                         else
1203                         {
1204                                 cpu2.pc = dpc;
1205                                 Decode_6809();
1206                                 Execute6809(&cpu2, 1);
1207                                 dpc = cpu2.pc;
1208                                 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1209                                         cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1210                                 cout << " iclock=" << cpu2.clock << endl;
1211                         }
1212                 }
1213                 else if ((lbuff[0] == 'r') || (lbuff[0] == 'c')) // Run/continue...
1214                 {
1215 WriteLog("Executing 'run' command...\n");
1216                         uint32 my_clock = 0;
1217                         running = true;                                                         // Set running status...
1218                         trace1 = false;
1219                         SetRefreshRate(refresh2);                                       // Tell GUI our refresh rate
1220       //for(uint16 i=0; i<0x8000; i++)  gram2[i] = grom3[i]; //Temp
1221
1222                         if (lbuff[0] == 'r')                                            // If run, then reset CPUs
1223                         {
1224 WriteLog("Executing secondary 'run' command...\n");
1225                                 gram1[0x4182] = 0xA6;          // Temp kludge
1226                                 gram1[0x4184] = 0xA6;
1227                                 gram1[0x4183] = 0x00;          // More of the same
1228                                 gram1[0x4185] = 0x00;
1229                                 banksw1 = 0;                   // Will this work?
1230                                 banksw2 = 0;
1231 //        iclock = 0;                // Reset instr clock #1...
1232                                 InitGUI();                 // Reset # of coins
1233
1234 /*        cpu1.pc = ((grom1[0xFFFE]<<8) | grom1[0xFFFF]); // Reset 6809 #1
1235         if (lbuff[1] != 0)
1236         {
1237           lbuff[0] = 32;  cpu1.pc = htod(lbuff);
1238         }
1239         else  cpu1.cc = 0xFF;                         // Set CC register
1240
1241         cpu2.pc = ((grom2[0xFFFE]<<8) | grom2[0xFFFF]); // Reset 6809 #2
1242         cpu2.cc = 0xFF;                              // Set CC register
1243         while(iclock < 8000)  // was 17000, 20000, 5000
1244         {
1245           Execute6809(&cpu1, 1);  Execute6809(&cpu2, 1);
1246         }*/
1247 WriteLog("--> CPU clock #1: %u\n", cpu1.clock);
1248                                 // Will *this* help video sync?
1249                                 while (cpu1.clock < 8000)                               // was 17000, 20000, 5000
1250                                 {
1251                                         Execute6809(&cpu1, 1);
1252                                         Execute6809(&cpu2, 1);
1253                                 }
1254                         }
1255
1256 WriteLog("About to set up screen...\n");
1257 //      if (!SetVESA2())  running = false;        // Set up screen
1258                         // Set up screen (windowed)
1259                         screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); //video_bpp, videoflags);
1260                         if (screen == NULL)
1261                         {
1262                                 cout << "Failed to initialize screen!" << endl;
1263                                 running = false;
1264                         }
1265
1266                         SDL_Color colors[256];
1267                         for(int i=0; i<256; i++)
1268                         {
1269                                 colors[i].r = palette[i*3+0];
1270                                 colors[i].g = palette[i*3+1];
1271                                 colors[i].b = palette[i*3+2];
1272                         }
1273                         SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256);
1274
1275 #if 1
1276         // This confirms that we're getting video to the screen...
1277         SDL_LockSurface(screen);
1278
1279         uint8 pixel = 0;
1280         uint8 * pixels = (uint8 *)(screen->pixels);
1281
1282         for(uint32 y=0; y<480; y++)
1283                 for(uint32 x=0; x<640; x++)
1284                         pixels[(y * 640) + x] = pixel++;
1285
1286         SDL_UnlockSurface(screen);
1287         SDL_UpdateRect(screen, 0, 0, 0, 0);
1288 #endif
1289
1290                         for(int i=0; i<256; i++)
1291                                 keys[i] = 0;                            // Clear keyboard buffer...
1292
1293                         oldTicks = SDL_GetTicks();
1294
1295 WriteLog("About to set up audio...\n");
1296                         // This crap SHOULD be in sound.cpp (not yet created)...
1297                         SDL_AudioSpec desired, obtained;
1298                         desired.freq = 22050;
1299                         desired.format = AUDIO_U8;
1300                         desired.channels = 1;
1301                         desired.samples = 600;
1302                         desired.callback = SoundFunc;
1303                         desired.userdata = NULL;
1304                         // Also, should check to see if it got the hardware it needed, correct sample size, etc.
1305                         if (SDL_OpenAudio(&desired, &obtained) < 0)
1306                         {
1307                                 cout << "Couldn't open audio: " << SDL_GetError() << endl;
1308                                 return -1;
1309                         }
1310                         SDL_PauseAudio(0);                                                      // Get that audio going!
1311
1312 WriteLog("About to enter main loop...\n");
1313                         while (running)
1314                         {
1315                                 HandleGUIDebounce();                                    // Debounce GUI keys
1316                                 if (game_over_switch)
1317                                 {
1318                                         game_over_switch--;  // Countdown...
1319                                         if (game_over_switch == 0)
1320                                                 gram1[0x4380] = 0; // Kill music!
1321                                 }
1322                                 //gram1[0x423D] = self_test;                    // Reset DSW1-1
1323                                 gram1[0x4268] = 0;                                              // Reset Video test
1324                                 gram1[0x427A] = 0;  gram1[0x427C] = 0;
1325                                 gram1[0x427B] = 0;  gram1[0x427D] = 0;
1326                                 gram1[0x427E] = 0;  gram1[0x427F] = 0;
1327                                 gram1[0x4280] = 0;  gram1[0x4281] = 0;
1328                                 gram1[0x4276] = 0;  gram1[0x426A] = 0;
1329                                 gram1[0x4278] = 0;  gram1[0x426C] = 0;
1330                                 gram1[0x4262] = 0;  gram1[0x4260] = 0;
1331                                 //gram1[0x4247] = 0;
1332
1333                                 // SDL key handling...
1334
1335 #warning "MAKE REPOSITORY FOR THIS THING! !!! FIX !!!"
1336 #warning "AND USE THE OLD SOURCE FOR THE BASE!!!"
1337 #warning "KEYS ARE FUCKED UP! !!! FIX !!!"
1338 //                              keyPressed = 0;                                                 // Reset keypress
1339                                 while (SDL_PollEvent(&event) != 0)              // Bleed out all pending key events...
1340                                 {
1341                                         if (event.type == SDL_KEYDOWN)
1342                                                 keys[event.key.keysym.scancode] = 1;
1343                                         if (event.type == SDL_KEYUP)
1344                                                 keys[event.key.keysym.scancode] = 0;
1345                                 }
1346
1347 //        {
1348                                 if (keys[0x01])
1349                                         running = false;                     // ESC to exit...
1350
1351                                 if (debounce)
1352                                         debounce--;                          // Debounce toggle keys...
1353                                 else
1354                                 {
1355                                         if (keys[0x3B])
1356                                         {
1357                                                 self_test = !self_test;            // Self-test (F1-toggle)
1358                                                 debounce = 10;                     // Key debounce value...
1359                                         }
1360                                         if (keys[0x3C])
1361                                         {
1362                                                 gram1[0x4268] = 1;                 // Video test (F2)
1363                                                 debounce = 10;                     // Key debounce value...
1364                                         }
1365                                         if (keys[0x58])
1366                                         {
1367                                                 scr_type = !scr_type;              // Toggle screen (F12)
1368                                                 debounce = 10;                     // Key debounce value...
1369                                         }
1370                                         if (keys[0x3D])
1371                                         {
1372                                                 show_scr = !show_scr;              // Toggle bkgrnd (F3)
1373                                                 debounce = 10;
1374                                         }
1375                                         if (keys[0x40])
1376                                         {
1377                                                 enable_cpu = !enable_cpu;          // Toggle CPUs (F6)
1378                                                 debounce = 10;
1379                                         }
1380                                         if (keys[0x3F])
1381                                         {
1382                                                 refresh2 = !refresh2;             // Toggle 30/60Hz (F5)
1383                                                 SetRefreshRate(refresh2);         // Inform GUI of refresh
1384                                                 if (refresh2)
1385                                                         SpawnMsg(M60FPS);
1386                                                 else
1387                                                         SpawnMsg(M30FPS);
1388                                                 debounce = 10;                    // Key debounce value...
1389                                         }
1390                                         if (keys[0x3E])                      // Do PCX snapshot (F4)
1391                                         {
1392                                                 SpawnSound(USERSOUND, SCAMERA);
1393                                                 SnapPCX(screen);
1394                                                 debounce = 10;
1395                                         }
1396                                         if (keys[0x0F])                      // Tab active/deactivate GUI
1397                                         {
1398                                                 if (ShowGUI())
1399                                                         DeactivateGUI();
1400                                                 else
1401                                                         ActivateGUI();
1402                                                 debounce = 10;
1403                                         }
1404                                 }
1405                                 //if (keys[0x3E])  gram1[0x4247] = 1;  // Screen hold DS (F4)
1406                                 if (keys[77+128])                                               // Right arrow
1407                                 {
1408                                         if (ShowGUI())
1409                                                 SelectRight();                     // If GUI active...
1410                                         else
1411                                         {
1412                                                 if (!keys[75+128])                     // Disallow opposite directions @ same time
1413                                                         gram1[0x427F] = 1;               // Stick right
1414                                         }
1415                                 }
1416                                 if (keys[75+128])
1417                                 {
1418                                         if (ShowGUI())
1419                                                 SelectLeft();                      // If GUI active...
1420                                         else
1421                                         {
1422                                                 if (!keys[77+128])                     // Disallow opposite directions@same time
1423                                                 gram1[0x4281] = 1;               // Left arrow
1424                                         }
1425                                 }
1426                                 if (keys[72+128])
1427                                 {
1428                                         if (ShowGUI())
1429                                                 SelectUp();                        // If GUI active...
1430                                         else
1431                                         {
1432                                                 if (!keys[80+128])                     // Disallow opposite directions@same time
1433                                                         gram1[0x427B] = 1;               // Up arrow
1434                                         }
1435                                 }
1436                                 if (keys[80+128])
1437                                 {
1438                                         if (ShowGUI())
1439                                                 SelectDown();                                   // If GUI active...
1440                                         else
1441                                         {
1442                                                 if (!keys[72+128])                              // Disallow opposite directions@same time
1443                                                         gram1[0x427D] = 1;                      // Down arrow
1444                                         }
1445                                 }
1446                                 if (keys[28])                                                   // Return
1447                                 {
1448                                         uint8 retval = UserSelectedSomething();
1449                                         if (retval == EXIT)
1450                                                 running = false;
1451                                         if (retval == REFRESH)
1452                                         {
1453                                                 refresh2 = !refresh2;
1454                                                 SetRefreshRate(refresh2);
1455                                         }
1456                                 }
1457                                 if (keys[0x02])
1458                                         gram1[0x427A] = 1;                                      // (1)
1459                                 if (keys[0x03])
1460                                         gram1[0x427C] = 1;                                      // (2)
1461                                 if (keys[0x04])
1462                                         gram1[0x427E] = 1;                                      // (3)
1463                                 if (keys[0x06])
1464                                         gram1[0x4280] = 1;                                      // (5)
1465                                 if (keys[0x10]|keys[29])
1466                                         gram1[0x4276] = 1;                                      // (Q)  Jump
1467                                 if (keys[0x11])
1468                                         gram1[0x426A] = 1;                                      // (W)
1469                                 if (fire_debounce)
1470                                         fire_debounce--;
1471                                 if (keys[0x12]|keys[56])                                // (E) Fire
1472                                 {
1473                                         if (!fire_debounce)
1474                                         {
1475                                                 gram1[0x4278] = 1;
1476                                                 if (gram1[0x3F08] == 0xFF)              // Ugly kludge for debouncing gun
1477                                                 {
1478                                                         fire_debounce = 8;
1479                                                 }
1480                                                 else
1481                                                 {
1482                                                         fire_debounce = 2;
1483                                                 }
1484                                         }
1485                                 }
1486                                 if (keys[0x13])
1487                                         gram1[0x426C] = 1;                                      // (R)
1488                                 if (keys[0x14])
1489                                         gram1[0x4262] = 1;                                      // (T)
1490                                 if (keys[0x15])
1491                                         gram1[0x4260] = 1;                                      // (Y)
1492                                 if (keys[0x44])
1493                                         gram1[0x41A5]++;                                        // Coin? (F10)
1494                                 if (keys[0x2C])
1495                                         gram1[0x4189]++;                                        // ? (Z) credits l dig
1496                                 if (keys[0x2D])
1497                                         gram1[0x418A]++;                                        // ? (X) credits r dig
1498                                 if (keys[0x2E])
1499                                         gram1[0x418C]++;                                        // ? (C) Start
1500                                 if (keys[0x2F])
1501                                         gram1[0x418D]++;                                        // ? (V)
1502                                 if (keys[0x41])
1503                                         SpawnSound(USERSOUND, 0);                       // Do user sound (F7)
1504 //                              if (keys[0x42])
1505 //                              {
1506 //                                      gram1[0x4380] = 0;                                      // (F8) kill music (this worx)
1507 //                                      charbase = false;                                       // Switch chars out...
1508 //                              }
1509 //                              if (keys[0x43])  gram1[0x4285] = 1;             // (F9) strobe unknown loc
1510                                 if (keys[0x45])                                                 // (F11)
1511                                 {
1512                                         Execute6809(&cpu1, 10);
1513                                         Execute6809(&cpu2, 10);
1514                                 }
1515 //                      }
1516
1517 //                              if (enable_cpu)
1518                                 if (true)
1519                                 {
1520 /*//                                    if (irqGoA)
1521                                                 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1522
1523                                         Execute6809(&cpu1, 25000);
1524                                         cpu1.clock -= 25000;                            // Remove 25K ticks from clock (in case it overflowed)
1525
1526 //                                      if (irqGoB)
1527                                                 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1528
1529                                         Execute6809(&cpu2, 25000);
1530                                         cpu2.clock -= 25000;                            // Remove 25K ticks from clock (in case it overflowed)//*/
1531
1532 //                                      cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1533 //                                      cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1534                                         while (cpu1.clock < 25000)
1535                                         {
1536                                                 // Gay, but what are ya gonna do?
1537                                                 Execute6809(&cpu1, 5);
1538                                                 Execute6809(&cpu2, 5);
1539                                         }
1540
1541                                         cpu1.clock -= 25000;                            // Remove 25K ticks from clock (in case it overflowed)
1542                                         cpu2.clock -= 25000;                            // Remove 25K ticks from clock (in case it overflowed)//*/
1543
1544                                 } // END: enable_cpu
1545
1546 //        if (refresh_++ == 1)                // 30 Hz...
1547 //        {
1548 //          if (scr_type)
1549 //            BlitWilliamsScreen(gram1);     // Display the screen...
1550 //          else
1551 //            BlitChar(screen, chr_rom, gram1);
1552 //          refresh_ = (refresh2 ? 1 : 0);    // 60/30 Hz...
1553 //        }
1554 //temp, for testing...
1555 BlitChar(screen, chr_rom, gram1);
1556
1557                                 // Speed throttling happens here...
1558                                 while (SDL_GetTicks() - oldTicks < 16)  // Actually, it's 16.66... Need to account for that somehow
1559                                         SDL_Delay(1);                           // Release our timeslice...
1560
1561                                 oldTicks = SDL_GetTicks();
1562 //cout << "Finished frame..." << endl;
1563                         }
1564
1565 //      Stop_audio_output();
1566 //      ReleaseTimer();
1567 //      ReleaseKeyboard();               // Release the interrupt...
1568 //      RestoreOldMode();                // Restore screen
1569                         if (brk && (cpu1.pc == brkpnt))
1570                                 cout << "CPU 1: Break at " << hex << cpu1.pc << endl;
1571                         if (brk2 && (cpu2.pc == brkpnt2))
1572                                 cout << "CPU 2: Break at " << hex << cpu2.pc << endl;
1573
1574                         lbuff[0] = 'q';                         // Temp kludge...
1575                 }
1576                 else if (lbuff[0] == 'b')  // Set/clear breakpoint
1577                 {
1578                         if (lbuff[1] != 0)
1579                         {
1580                                 lbuff[0] = 32;
1581                                 brkpnt = htod(lbuff);
1582                                 brk = true;
1583                                 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1584                         }
1585                         else
1586                         {
1587                                 brk = false;
1588                                 cout << "Breakpoint cleared" << endl;
1589                         }
1590                 }
1591                 else if (lbuff[0] == 'a')  // Set/clear breakpoint #2
1592                 {
1593                         if (lbuff[1] != 0)
1594                         {
1595                                 lbuff[0] = 32;
1596                                 brkpnt2 = htod(lbuff);
1597                                 brk2 = true;
1598                                 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1599                         }
1600                         else
1601                         {
1602                                 brk2 = false;
1603                                 cout << "Breakpoint cleared" << endl;
1604                         }
1605                 }
1606                 else if (lbuff[0] == 'i')  // Inspect registers
1607                 {
1608       printf("CPU1: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1609               cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1610       cout << " iclk=" << dec << cpu1.clock << endl;
1611       printf("CPU2: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1612               cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1613       cout << " iclk=" << dec << cpu2.clock << endl;
1614       if (brk)
1615         cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1616       if (brk2)
1617         cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1618     }
1619                 else if (strncmp(lbuff, "swap", 4) == 0)  // Swap ROMs
1620     {
1621       looking_at_rom = !looking_at_rom;
1622       cout << "Swapped:  Looking at ";
1623       (looking_at_rom ? cout << "ROM #1" : cout << "ROM #2");
1624       cout << endl;
1625     }
1626                 else if (strncmp(lbuff, "seek", 4) == 0)  // Seek non-zero bytes in RAM
1627     {
1628       if (lbuff[4] != 0)
1629       {
1630         for(int i=0; i<4; i++)
1631           lbuff[i] = 32;
1632         dpc = htod(lbuff);
1633       }
1634       do
1635       {
1636         x = gram1[dpc++];
1637       }
1638       while ((x == 0) && (dpc != 0xFFFF)); // Keep going until something found
1639       dpc--;
1640
1641       printf("%04X: ", dpc);       // Show data found...
1642       for(int i=0; i<16; i++)
1643         printf("%02X ", gram1[(uint16)(dpc+i)]);
1644       cout << " ";
1645       for(int i=0; i<16; i++)
1646       {
1647         uint8 a = gram1[dpc++];
1648         if (a<10)
1649           cout << (char)(a+48);
1650         if ((a>9) && (a<37))
1651           cout << (char)(a+55);
1652         if (a>36)
1653           cout << ".";
1654       }
1655       cout << endl;
1656     }
1657                 else if (lbuff[0] == 'v')    // View screen
1658                 {
1659 //                      SetVESA2();                           // Set up screen
1660                         BlitChar(screen, chr_rom, gram1);
1661                         getch();
1662 //                      RestoreOldMode();
1663                 }
1664
1665                 if (lbuff[0] == 'q')
1666                         active = false; //break;  // Quit
1667         }
1668
1669         SDL_Quit();                                                                                     // Shut down SDL
1670
1671         delete[] gram1;                                                                         // Deallocate RAM & ROM spaces
1672         delete[] grom1;
1673         delete[] gram2;
1674         delete[] grom2;
1675         delete[] chr_rom;
1676         delete[] grom3;
1677         delete[] grom4;
1678         delete[] data_rom;
1679         delete[] spr_rom;
1680         delete[] voice_rom;
1681
1682         for(int i=0; i<16; i++)
1683                 if (psg_adrs[i] != NULL)
1684                         delete[] psg_adrs[i];                                           // Deallocate if loaded
1685
1686         for(int i=0; i<14; i++)
1687                 if (fm_adrs[i] != NULL)
1688                         delete[] fm_adrs[i];                                            // Deallocate if loaded
1689
1690 //      tr.close();                                                                                     // Close tracelog
1691         LogDone();
1692
1693         return 1;
1694 }