]> Shamusworld >> Repos - thunder/blob - src/thunder.cpp
ffbfed9574a7ec070ea679c79c0f2668ace9e130
[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[0x10000], gram2[0x10000], grom1[0x10000], grom2[0x10000];   // Actual memory
100 uint8 grom3[0x8000], grom4[0x8000], data_rom[0x40000], spr_rom[0x80000], voice_rom[0x20000];
101 uint8 chr_rom[0x60000];                                                 // Character ROM pointer
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   WriteLog("%04X: ", src);
443   cnt = 0;                               // Init counter...
444   if (src > dst)  dst += 0x10000;        // That should fix the FFFF bug...
445   for(i=src; i<dst; i++)
446   {
447     WriteLog("%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     WriteLog("   ");
453   }
454 }
455
456 // temp crap...
457 uint8 Fetch(void) { return RdMem(dpc); }
458 uint16 FetchW(void) { return (uint16)((RdMem(dpc) << 8) | RdMem(dpc+1)); }
459 uint8 FetchB(void) { return RdMemB(dpc); }
460 uint16 FetchWB(void) { return (uint16)((RdMemB(dpc) << 8) | RdMemB(dpc+1)); }
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   WriteLog(outbuf); WriteLog("\n");     // display opcode & addressing, etc
618   dpc = (looking_at_rom ? pcr : pcrB);  // Advance debug PC
619   pcr = pc_save;  pcrB = pcB_save;  // Restore PCs
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 bool charbase;                                           // From 'SCREEN.CPP'
931         charbase = false;
932
933   char lbuff[80];
934   fstream ff;                       // Declare fstream without file hooks...
935   bool brk = false, brk2 = false;   // Breakpoint set flag
936   uint16 brkpnt, brkpnt2;             // Where the breakpoint is...
937   bool running;                     // CPU running state flag...
938   bool self_test = false;           // Self-test switch
939   bool scr_type = false;            // false=chars, true=pixels
940   uint16 debounce = 0;                // Key de-bounce counter
941   uint16 fire_debounce = 0;           // Fire button debounce counter
942 //  bool refresh2 = true;             // Default to 60 Hz...
943   uint8 x;                           // General placeholder...
944   bool active = true;                                           // Program running flag
945
946   SDL_Event event;                                                              // SDL "event"
947   extern uint8 palette[768];                                    // Screen physical palette
948   uint32 ticks, oldTicks;
949
950         cout << endl << "THUNDER v"THUNDER_VERSION" ";
951         cout << "by James Hammons" << endl;
952         cout << "Serial #20090723 / Prerelease" << endl;
953         cout << "(C) 2003, 2009 Underground Software" << endl << endl;
954
955         cout << "This emulator is free software. If you paid for it you were RIPPED OFF"
956                 << endl << endl;
957
958         cout << "Initializing SDL..." << endl;
959
960         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
961         {
962                 cout << "Couldn't initialize SDL: " << SDL_GetError() << endl;
963                 return -1;
964         }
965
966         SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder");
967
968         keys = SDL_GetKeyState(NULL);                           // Get the SDL keyboard matrix
969
970 #if 0
971   cout << "Allocating memory..." << endl;
972 //Does this anyway...  set_new_handler(0);    // Make 'new' return NULL on failure...
973   gram1 = new uint8[0x10000];
974   if (gram1 == NULL)  { cout << "Could not allocate RAM space #1!" << endl
975                       << "Aborting!" << endl;  return -1; }
976   grom1 = new uint8[0x10000];
977   if (grom1 == NULL)  { cout << "Could not allocate ROM space #1!" << endl
978                       << "Aborting!" << endl;  return -1; }
979   gram2 = new uint8[0x10000];
980   if (gram2 == NULL)  { cout << "Could not allocate RAM space #2!" << endl
981                       << "Aborting!" << endl;  return -1; }
982   grom2 = new uint8[0x10000];
983   if (grom2 == NULL)  { cout << "Could not allocate ROM space #2!" << endl
984                       << "Aborting!" << endl;  return -1; }
985   chr_rom = new uint8[0x60000];
986   if (chr_rom == NULL)  { cout << "Could not allocate character RAM!" << endl
987                       << "Aborting!" << endl;  return -1; }
988   grom3 = new uint8[0x8000];
989   if (grom3 == NULL)  { cout << "Could not allocate ROM space #4!" << endl
990                       << "Aborting!" << endl;  return -1; }
991   grom4 = new uint8[0x8000];
992   if (grom4 == NULL)  { cout << "Could not allocate ROM space #5!" << endl
993                       << "Aborting!" << endl;  return -1; }
994   data_rom = new uint8[0x40000];
995   if (data_rom == NULL)  { cout << "Could not allocate ROM level data!" << endl
996                       << "Aborting!" << endl;  return -1; }
997   spr_rom = new uint8[0x80000];
998   if (spr_rom == NULL)  { cout << "Could not allocate ROM sprite data!" << endl
999                       << "Aborting!" << endl;  return -1; }
1000   voice_rom = new uint8[0x20000];
1001   if (voice_rom == NULL)  { cout << "Could not allocate ROM voice data!" << endl
1002                       << "Aborting!" << endl;  return -1; }
1003 #endif
1004
1005   gram = gram1;  grom = grom1;           // Needed only for debugger
1006
1007   for(long i=0; i<0x10000; i++)
1008   {
1009     gram[i] = 0;  grom[i] = 0;           // Zero out memory
1010     gram2[i] = 0;  grom2[i] = 0;
1011   }
1012   game_over_switch = 0;   // Init game over delay
1013 //  cpu1.a = 0; cpu1.b = 0; cpu1.cc = 0; cpu1.dp = 0; cpu1.x = 0; cpu1.y = 0; cpu1.s = 0; ur = 0; cpu1.pc = 0;
1014
1015   cout << "Loading ROMs..." << endl;
1016 //  LoadCMOS();                            // Load CMOS at $CC00-$CFFF
1017   if (!ReadColorPROMs())                   // Load virtual PROMs
1018   { cout << "Could not open PROM files!" << endl;  return -1; }
1019
1020   if (!LoadImg(ROM1, grom1, 0x8000, 0x8000)) // Load $8000-$FFFF 1st ROM
1021   { cout << "Could not open file '" << ROM1 << "'!" << endl;  return -1; }
1022
1023   if (!LoadImg(ROM2, grom2, 0x8000, 0x8000)) // Load $8000-$FFFF 2nd ROM
1024   { cout << "Could not open file '" << ROM2 << "'!" << endl;  return -1; }
1025
1026   if (!LoadImg(ROM3, grom3, 0, 0x8000))      // Load 3rd ROM into its own space
1027   { cout << "Could not open file '" << ROM3 << "'!" << endl;  return -1; }
1028
1029   if (!LoadImg(ROM4, grom4, 0, 0x8000))      // Load 4rd ROM into its own space
1030   { cout << "Could not open file '" << ROM4 << "'!" << endl;  return -1; }
1031
1032   if (!LoadImg(ROM17, data_rom, 0,       0x10000))  // Load 17th ROM
1033   { cout << "Could not open file '" << ROM17 << "'!" << endl;  return -1; }
1034
1035   if (!LoadImg(ROM18, data_rom, 0x10000, 0x10000))  // Load 18th ROM
1036   { cout << "Could not open file '" << ROM18 << "'!" << endl;  return -1; }
1037
1038   if (!LoadImg(ROM19, data_rom, 0x20000, 0x10000))  // Load 19th ROM
1039   { cout << "Could not open file '" << ROM19 << "'!" << endl;  return -1; }
1040
1041   if (!LoadImg(ROM20, data_rom, 0x30000, 0x10000))  // Load 20th ROM
1042   { cout << "Could not open file '" << ROM20 << "'!" << endl;  return -1; }
1043
1044   if (!LoadImg(ROM9,  spr_rom, 0,       0x10000))   // Load 9th ROM
1045   { cout << "Could not open file '" << ROM9 << "'!" << endl;  return -1; }
1046
1047   if (!LoadImg(ROM10, spr_rom, 0x10000, 0x10000))   // Load 10th ROM
1048   { cout << "Could not open file '" << ROM10 << "'!" << endl;  return -1; }
1049
1050   if (!LoadImg(ROM11, spr_rom, 0x20000, 0x10000))   // Load 11th ROM
1051   { cout << "Could not open file '" << ROM11 << "'!" << endl;  return -1; }
1052
1053   if (!LoadImg(ROM12, spr_rom, 0x30000, 0x10000))   // Load 12th ROM
1054   { cout << "Could not open file '" << ROM12 << "'!" << endl;  return -1; }
1055
1056   if (!LoadImg(ROM13, spr_rom, 0x40000, 0x10000))   // Load 13th ROM
1057   { cout << "Could not open file '" << ROM13 << "'!" << endl;  return -1; }
1058
1059   if (!LoadImg(ROM14, spr_rom, 0x50000, 0x10000))   // Load 14th ROM
1060   { cout << "Could not open file '" << ROM14 << "'!" << endl;  return -1; }
1061
1062   if (!LoadImg(ROM15, spr_rom, 0x60000, 0x10000))   // Load 15th ROM
1063   { cout << "Could not open file '" << ROM15 << "'!" << endl;  return -1; }
1064
1065   if (!LoadImg(ROM16, spr_rom, 0x70000, 0x10000))   // Load 16th ROM
1066   { cout << "Could not open file '" << ROM16 << "'!" << endl;  return -1; }
1067
1068   if (!LoadImg(ROM21, voice_rom, 0, 0x10000))  // Load 21st ROM
1069   { cout << "Could not open file '" << ROM21 << "'!" << endl;  return -1; }
1070
1071   if (!LoadImg(ROM22, voice_rom, 0x10000, 0x10000))  // Load 22nd ROM
1072   { cout << "Could not open file '" << ROM22 << "'!" << endl;  return -1; }
1073
1074   if (!UnpackFonts())                         // Load 5, 6, 7, 8th ROMs
1075   {
1076     cout << "Could not open font files!" << endl;
1077     return -1;
1078   }
1079
1080         // Load samples if they're there...
1081         LoadPSGs();
1082         LoadFMs();
1083
1084   // Quick 'n' Dirty voice dump (sound 0x0E)
1085 /*  uint32 adc = (voice_rom[26]<<8) | voice_rom[27];
1086   bool doneWitIt = false;
1087   int crh = 0;
1088   while (!doneWitIt)
1089   {
1090     if (voice_rom[adc] < 0x10)  tr << "0";
1091     tr << hex << (int)voice_rom[adc] << " ";
1092     if (crh++ > 24)  { crh = 0;  tr << endl; }
1093     if ((voice_rom[adc] == 0xFF) && (voice_rom[adc-1] != 0x00))
1094       doneWitIt = true;
1095     adc++;
1096   }//*/
1097
1098         // Set up V6809 execution contexts
1099
1100         memset(&cpu1, 0, sizeof(V6809REGS));
1101         cpu1.RdMem = RdMem;
1102         cpu1.WrMem = WrMem;
1103         cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
1104
1105         memset(&cpu2, 0, sizeof(V6809REGS));
1106         cpu2.RdMem = RdMemB;
1107         cpu2.WrMem = WrMemB;
1108         cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
1109
1110         bool firstTime = true;                                                          // kludge...
1111
1112 WriteLog("About to go to the main loop...\n");
1113         while (active)
1114         {
1115                 cout << ">";
1116                 if (firstTime)
1117                 {
1118                         firstTime = false;                                                      // crappy kludge...
1119                         lbuff[0] = 'r';
1120                         lbuff[1] = 0;
1121                 }
1122                 else
1123                         cin >> lbuff;
1124
1125                 if (lbuff[0] == 'd')
1126                 {
1127                         if (lbuff[1] != 0)
1128                         {
1129                                 lbuff[0] = 32;
1130                                 dpc = htod(lbuff);
1131                         }
1132                         printf("%04X: ", dpc);
1133                         uint16 pc_save = cpu1.pc, pcB_save = cpu2.pc;
1134                         cpu1.pc = dpc;  cpu2.pc = dpc;
1135                         for(int i=0; i<16; i++)
1136                                 printf("%02X ", (looking_at_rom ? Fetch() : FetchB()));
1137                         cout << " ";
1138                         cpu1.pc = dpc;  cpu2.pc = dpc;
1139                         for(int i=0; i<16; i++)
1140                         {
1141                                 uint8 a = (looking_at_rom ? Fetch() : FetchB());
1142                                 if (a<10)             cout << (char)(a+48);
1143                                 if ((a>9) && (a<37))  cout << (char)(a+55);
1144                                 if (a>36)             cout << ".";
1145                         }
1146                         cout << endl;
1147                         dpc = (looking_at_rom ? cpu1.pc : cpu2.pc);
1148                         cpu1.pc = pc_save;  cpu2.pc = pcB_save;
1149                 }
1150                 else if (lbuff[0] == 'e')
1151                 {
1152                         if (lbuff[1] != 0)
1153                         {
1154                                 lbuff[0] = 32;
1155                                 dpc = htod(lbuff);
1156                         }
1157                         printf("%04X: ", dpc);
1158                         for(int i=0; i<16; i++)  printf("%02X ", (uint8)gram[dpc++]);
1159                         cout << endl;
1160                 }
1161                 else if (lbuff[0] == 'l')
1162                 {
1163                         if (lbuff[1] != 0)
1164                         {
1165                                 lbuff[0] = 32;
1166                                 dpc = htod(lbuff);
1167                         }
1168                         for(int i=0; i<23; i++)
1169                                 Decode_6809();
1170                 }
1171                 else if (lbuff[0] == 't')
1172                 {
1173                         if (lbuff[1] != 0)
1174                         {
1175                                 lbuff[0] = 32;
1176                                 dpc = htod(lbuff);
1177                         }
1178                         if (looking_at_rom)
1179                         {
1180                                 cpu1.pc = dpc;
1181                                 Decode_6809();
1182                                 Execute6809(&cpu1, 1);
1183                                 dpc = cpu1.pc;
1184                                 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1185                                         cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1186                                 cout << " iclock=" << cpu1.clock << endl;
1187                         }
1188                         else
1189                         {
1190                                 cpu2.pc = dpc;
1191                                 Decode_6809();
1192                                 Execute6809(&cpu2, 1);
1193                                 dpc = cpu2.pc;
1194                                 printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1195                                         cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1196                                 cout << " iclock=" << cpu2.clock << endl;
1197                         }
1198                 }
1199                 else if ((lbuff[0] == 'r') || (lbuff[0] == 'c')) // Run/continue...
1200                 {
1201 WriteLog("Executing 'run' command...\n");
1202                         uint32 my_clock = 0;
1203                         running = true;                                                         // Set running status...
1204                         trace1 = false;
1205                         SetRefreshRate(refresh2);                                       // Tell GUI our refresh rate
1206       //for(uint16 i=0; i<0x8000; i++)  gram2[i] = grom3[i]; //Temp
1207
1208                         if (lbuff[0] == 'r')                                            // If run, then reset CPUs
1209                         {
1210 WriteLog("Executing secondary 'run' command...\n");
1211                                 gram1[0x4182] = 0xA6;          // Temp kludge
1212                                 gram1[0x4184] = 0xA6;
1213                                 gram1[0x4183] = 0x00;          // More of the same
1214                                 gram1[0x4185] = 0x00;
1215                                 banksw1 = 0;                   // Will this work?
1216                                 banksw2 = 0;
1217 //        iclock = 0;                // Reset instr clock #1...
1218                                 InitGUI();                 // Reset # of coins
1219
1220 #if 0
1221                                 cpu1.pc = ((grom1[0xFFFE]<<8) | grom1[0xFFFF]); // Reset 6809 #1
1222                                 if (lbuff[1] != 0)
1223                                 {
1224                                 lbuff[0] = 32;  cpu1.pc = htod(lbuff);
1225                                 }
1226                                 else  cpu1.cc = 0xFF;                         // Set CC register
1227
1228                                 cpu2.pc = ((grom2[0xFFFE]<<8) | grom2[0xFFFF]); // Reset 6809 #2
1229                                 cpu2.cc = 0xFF;                              // Set CC register
1230                                 while(iclock < 8000)  // was 17000, 20000, 5000
1231                                 {
1232                                 Execute6809(&cpu1, 1);  Execute6809(&cpu2, 1);
1233                                 }
1234 #endif
1235 #if 0
1236 WriteLog("--> CPU clock #1: %u\n", cpu1.clock);
1237                                 // Will *this* help video sync? NO
1238                                 while (cpu1.clock < 8000)                               // was 17000, 20000, 5000
1239                                 {
1240                                         Execute6809(&cpu1, 1);
1241                                         Execute6809(&cpu2, 1);
1242                                 }
1243 #endif
1244                         }
1245
1246 WriteLog("About to set up screen...\n");
1247 //      if (!SetVESA2())  running = false;        // Set up screen
1248                         // Set up screen (windowed)
1249                         screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); //video_bpp, videoflags);
1250                         if (screen == NULL)
1251                         {
1252                                 cout << "Failed to initialize screen!" << endl;
1253                                 running = false;
1254                         }
1255
1256                         SDL_Color colors[256];
1257                         for(int i=0; i<256; i++)
1258                         {
1259                                 colors[i].r = palette[i*3+0];
1260                                 colors[i].g = palette[i*3+1];
1261                                 colors[i].b = palette[i*3+2];
1262                         }
1263                         SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256);
1264
1265 #if 0
1266         // This confirms that we're getting video to the screen...
1267         SDL_LockSurface(screen);
1268
1269         uint8 pixel = 0;
1270         uint8 * pixels = (uint8 *)(screen->pixels);
1271
1272         for(uint32 y=0; y<480; y++)
1273                 for(uint32 x=0; x<640; x++)
1274                         pixels[(y * 640) + x] = pixel++;
1275
1276         SDL_UnlockSurface(screen);
1277         SDL_UpdateRect(screen, 0, 0, 0, 0);
1278 #endif
1279
1280                         for(int i=0; i<256; i++)
1281                                 keys[i] = 0;                            // Clear keyboard buffer...
1282
1283                         oldTicks = SDL_GetTicks();
1284
1285 WriteLog("About to set up audio...\n");
1286                         // This crap SHOULD be in sound.cpp (not yet created)...
1287                         SDL_AudioSpec desired, obtained;
1288                         desired.freq = 22050;
1289                         desired.format = AUDIO_U8;
1290                         desired.channels = 1;
1291                         desired.samples = 600;
1292                         desired.callback = SoundFunc;
1293                         desired.userdata = NULL;
1294                         // Also, should check to see if it got the hardware it needed, correct sample size, etc.
1295                         if (SDL_OpenAudio(&desired, &obtained) < 0)
1296                         {
1297                                 cout << "Couldn't open audio: " << SDL_GetError() << endl;
1298                                 return -1;
1299                         }
1300                         SDL_PauseAudio(0);                                                      // Get that audio going!
1301
1302 WriteLog("About to enter main loop...\n");
1303                         while (running)
1304                         {
1305                                 HandleGUIDebounce();                                    // Debounce GUI keys
1306                                 if (game_over_switch)
1307                                 {
1308                                         game_over_switch--;  // Countdown...
1309                                         if (game_over_switch == 0)
1310                                                 gram1[0x4380] = 0; // Kill music!
1311                                 }
1312                                 //gram1[0x423D] = self_test;                    // Reset DSW1-1
1313                                 gram1[0x4268] = 0;                                              // Reset Video test
1314                                 gram1[0x427A] = 0;  gram1[0x427C] = 0;
1315                                 gram1[0x427B] = 0;  gram1[0x427D] = 0;
1316                                 gram1[0x427E] = 0;  gram1[0x427F] = 0;
1317                                 gram1[0x4280] = 0;  gram1[0x4281] = 0;
1318                                 gram1[0x4276] = 0;  gram1[0x426A] = 0;
1319                                 gram1[0x4278] = 0;  gram1[0x426C] = 0;
1320                                 gram1[0x4262] = 0;  gram1[0x4260] = 0;
1321                                 //gram1[0x4247] = 0;
1322
1323                                 // SDL key handling...
1324
1325                                 SDL_PumpEvents();                               // Force key events into the buffer.
1326
1327                                 if (keys[SDLK_ESCAPE])
1328                                         running = false;                     // ESC to exit...
1329
1330                                 if (debounce)
1331                                         debounce--;                          // Debounce toggle keys...
1332                                 else
1333                                 {
1334                                         if (keys[SDLK_F1])
1335                                         {
1336                                                 self_test = !self_test;            // Self-test (F1-toggle)
1337                                                 debounce = 10;                     // Key debounce value...
1338                                         }
1339                                         if (keys[SDLK_F2])
1340                                         {
1341                                                 gram1[0x4268] = 1;                 // Video test (F2)
1342                                                 debounce = 10;                     // Key debounce value...
1343                                         }
1344                                         if (keys[SDLK_F12])
1345                                         {
1346                                                 scr_type = !scr_type;              // Toggle screen (F12)
1347                                                 debounce = 10;                     // Key debounce value...
1348                                         }
1349                                         if (keys[SDLK_F3])
1350                                         {
1351                                                 show_scr = !show_scr;              // Toggle bkgrnd (F3)
1352                                                 debounce = 10;
1353                                         }
1354                                         if (keys[SDLK_F6])
1355                                         {
1356                                                 enable_cpu = !enable_cpu;          // Toggle CPUs (F6)
1357                                                 debounce = 10;
1358                                         }
1359                                         if (keys[SDLK_F5])
1360                                         {
1361                                                 refresh2 = !refresh2;             // Toggle 30/60Hz (F5)
1362                                                 SetRefreshRate(refresh2);         // Inform GUI of refresh
1363                                                 if (refresh2)
1364                                                         SpawnMsg(M60FPS);
1365                                                 else
1366                                                         SpawnMsg(M30FPS);
1367                                                 debounce = 10;                    // Key debounce value...
1368                                         }
1369                                         if (keys[SDLK_F4])                      // Do PCX snapshot (F4)
1370                                         {
1371                                                 SpawnSound(USERSOUND, SCAMERA);
1372                                                 SnapPCX(screen);
1373                                                 debounce = 10;
1374                                         }
1375                                         if (keys[SDLK_TAB])                      // Tab active/deactivate GUI
1376                                         {
1377                                                 if (ShowGUI())
1378                                                         DeactivateGUI();
1379                                                 else
1380                                                         ActivateGUI();
1381                                                 debounce = 10;
1382                                         }
1383                                 }
1384                                 //if (keys[0x3E])  gram1[0x4247] = 1;  // Screen hold DS (F4)
1385                                 if (keys[SDLK_RIGHT])                                           // Right arrow
1386                                 {
1387                                         if (ShowGUI())
1388                                                 SelectRight();                     // If GUI active...
1389                                         else
1390                                         {
1391                                                 if (!keys[SDLK_LEFT])                     // Disallow opposite directions @ same time
1392                                                         gram1[0x427F] = 1;               // Stick right
1393                                         }
1394                                 }
1395                                 if (keys[SDLK_LEFT])
1396                                 {
1397                                         if (ShowGUI())
1398                                                 SelectLeft();                      // If GUI active...
1399                                         else
1400                                         {
1401                                                 if (!keys[SDLK_RIGHT])                     // Disallow opposite directions@same time
1402                                                 gram1[0x4281] = 1;               // Left arrow
1403                                         }
1404                                 }
1405                                 if (keys[SDLK_UP])
1406                                 {
1407                                         if (ShowGUI())
1408                                                 SelectUp();                        // If GUI active...
1409                                         else
1410                                         {
1411                                                 if (!keys[SDLK_DOWN])                     // Disallow opposite directions@same time
1412                                                         gram1[0x427B] = 1;               // Up arrow
1413                                         }
1414                                 }
1415                                 if (keys[SDLK_DOWN])
1416                                 {
1417                                         if (ShowGUI())
1418                                                 SelectDown();                                   // If GUI active...
1419                                         else
1420                                         {
1421                                                 if (!keys[SDLK_UP])                             // Disallow opposite directions@same time
1422                                                         gram1[0x427D] = 1;                      // Down arrow
1423                                         }
1424                                 }
1425                                 if (keys[SDLK_RETURN])                                                  // Return
1426                                 {
1427                                         uint8 retval = UserSelectedSomething();
1428                                         if (retval == EXIT)
1429                                                 running = false;
1430                                         if (retval == REFRESH)
1431                                         {
1432                                                 refresh2 = !refresh2;
1433                                                 SetRefreshRate(refresh2);
1434                                         }
1435                                 }
1436                                 if (keys[SDLK_1])
1437                                         gram1[0x427A] = 1;                      // (1)
1438                                 if (keys[SDLK_2])
1439                                         gram1[0x427C] = 1;                      // (2)
1440                                 if (keys[SDLK_3])
1441                                         gram1[0x427E] = 1;                      // (3)
1442                                 if (keys[SDLK_5])
1443                                         gram1[0x4280] = 1;                      // (5)
1444                                 if (keys[SDLK_q] | keys[29])
1445                                         gram1[0x4276] = 1;                      // (Q)  Jump
1446                                 if (keys[SDLK_w])
1447                                         gram1[0x426A] = 1;                      // (W)
1448                                 if (fire_debounce)
1449                                         fire_debounce--;
1450                                 if (keys[SDLK_e] | keys[56])    // (E) Fire
1451                                 {
1452                                         if (!fire_debounce)
1453                                         {
1454                                                 gram1[0x4278] = 1;
1455
1456                                                 if (gram1[0x3F08] == 0xFF)              // Ugly kludge for debouncing gun
1457                                                         fire_debounce = 8;
1458                                                 else
1459                                                         fire_debounce = 2;
1460                                         }
1461                                 }
1462                                 if (keys[SDLK_r])
1463                                         gram1[0x426C] = 1;                      // (R)
1464                                 if (keys[SDLK_t])
1465                                         gram1[0x4262] = 1;                      // (T)
1466                                 if (keys[SDLK_y])
1467                                         gram1[0x4260] = 1;                      // (Y)
1468                                 if (keys[SDLK_F10])
1469                                         gram1[0x41A5]++;                        // Coin? (F10)
1470                                 if (keys[SDLK_z])
1471                                         gram1[0x4189]++;                        // ? (Z) credits l dig
1472                                 if (keys[SDLK_x])
1473                                         gram1[0x418A]++;                        // ? (X) credits r dig
1474                                 if (keys[SDLK_c])
1475                                         gram1[0x418C]++;                        // ? (C) Start
1476                                 if (keys[SDLK_v])
1477                                         gram1[0x418D]++;                        // ? (V)
1478                                 if (keys[SDLK_F7])
1479                                         SpawnSound(USERSOUND, 0);       // Do user sound (F7)
1480 //                              if (keys[SDLK_F8])
1481 //                              {
1482 //                                      gram1[0x4380] = 0;                      // (F8) kill music (this worx)
1483 //                                      charbase = false;                       // Switch chars out...
1484 //                              }
1485 //                              if (keys[SDLK_F9])  gram1[0x4285] = 1;          // (F9) strobe unknown loc
1486                                 if (keys[SDLK_F11])                             // (F11)
1487                                 {
1488                                         Execute6809(&cpu1, 10);
1489                                         Execute6809(&cpu2, 10);
1490                                 }
1491 //                      }
1492 //F12 is used above, but the values are ignored. So we'll do it here too.
1493                                 if (keys[SDLK_F12])
1494                                 {
1495                                         cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
1496                                         cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
1497                                 }
1498
1499 //                              if (enable_cpu)
1500                                 if (true)
1501                                 {
1502 #if 0
1503 //                                      if (irqGoA)
1504                                                 cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1505
1506                                         Execute6809(&cpu1, 25000);
1507                                         cpu1.clock -= 25000;                            // Remove 25K ticks from clock (in case it overflowed)
1508
1509 //                                      if (irqGoB)
1510                                                 cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1511
1512                                         Execute6809(&cpu2, 25000);
1513                                         cpu2.clock -= 25000;                            // Remove 25K ticks from clock (in case it overflowed)//*/
1514 #else
1515                                         cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1516                                         cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
1517 //                                      while (cpu1.clock < 25000)
1518                                         for(uint32 i=0; i<250; i++)
1519                                         {
1520                                                 // Gay, but what are ya gonna do?
1521                                                 // There's better ways, such as keeping track of when slave writes to master, etc...
1522                                                 Execute6809(&cpu1, 100);
1523                                                 Execute6809(&cpu2, 100);
1524                                         }
1525
1526 //                                      cpu1.clock -= 25000;                            // Remove 25K ticks from clock (in case it overflowed)
1527 //                                      cpu2.clock -= 25000;                            // Remove 25K ticks from clock (in case it overflowed)//*/
1528 #endif
1529                                 } // END: enable_cpu
1530
1531 //        if (refresh_++ == 1)                // 30 Hz...
1532 //        {
1533 //          if (scr_type)
1534 //            BlitWilliamsScreen(gram1);     // Display the screen...
1535 //          else
1536 //            BlitChar(screen, chr_rom, gram1);
1537 //          refresh_ = (refresh2 ? 1 : 0);    // 60/30 Hz...
1538 //        }
1539
1540 //temp, for testing...
1541 BlitChar(screen, chr_rom, gram1);
1542
1543                                 // Speed throttling happens here...
1544                                 while (SDL_GetTicks() - oldTicks < 16)  // Actually, it's 16.66... Need to account for that somehow
1545                                         SDL_Delay(1);                           // Release our timeslice...
1546
1547                                 oldTicks = SDL_GetTicks();
1548 //cout << "Finished frame..." << endl;
1549                         }
1550
1551 //      Stop_audio_output();
1552 //      ReleaseTimer();
1553 //      ReleaseKeyboard();               // Release the interrupt...
1554 //      RestoreOldMode();                // Restore screen
1555                         if (brk && (cpu1.pc == brkpnt))
1556                                 cout << "CPU 1: Break at " << hex << cpu1.pc << endl;
1557                         if (brk2 && (cpu2.pc == brkpnt2))
1558                                 cout << "CPU 2: Break at " << hex << cpu2.pc << endl;
1559
1560                         lbuff[0] = 'q';                         // Temp kludge...
1561                 }
1562                 else if (lbuff[0] == 'b')  // Set/clear breakpoint
1563                 {
1564                         if (lbuff[1] != 0)
1565                         {
1566                                 lbuff[0] = 32;
1567                                 brkpnt = htod(lbuff);
1568                                 brk = true;
1569                                 cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1570                         }
1571                         else
1572                         {
1573                                 brk = false;
1574                                 cout << "Breakpoint cleared" << endl;
1575                         }
1576                 }
1577                 else if (lbuff[0] == 'a')  // Set/clear breakpoint #2
1578                 {
1579                         if (lbuff[1] != 0)
1580                         {
1581                                 lbuff[0] = 32;
1582                                 brkpnt2 = htod(lbuff);
1583                                 brk2 = true;
1584                                 cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1585                         }
1586                         else
1587                         {
1588                                 brk2 = false;
1589                                 cout << "Breakpoint cleared" << endl;
1590                         }
1591                 }
1592                 else if (lbuff[0] == 'i')  // Inspect registers
1593                 {
1594       printf("CPU1: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1595               cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
1596       cout << " iclk=" << dec << cpu1.clock << endl;
1597       printf("CPU2: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
1598               cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
1599       cout << " iclk=" << dec << cpu2.clock << endl;
1600       if (brk)
1601         cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
1602       if (brk2)
1603         cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
1604     }
1605                 else if (strncmp(lbuff, "swap", 4) == 0)  // Swap ROMs
1606     {
1607       looking_at_rom = !looking_at_rom;
1608       cout << "Swapped:  Looking at ";
1609       (looking_at_rom ? cout << "ROM #1" : cout << "ROM #2");
1610       cout << endl;
1611     }
1612                 else if (strncmp(lbuff, "seek", 4) == 0)  // Seek non-zero bytes in RAM
1613     {
1614       if (lbuff[4] != 0)
1615       {
1616         for(int i=0; i<4; i++)
1617           lbuff[i] = 32;
1618         dpc = htod(lbuff);
1619       }
1620       do
1621       {
1622         x = gram1[dpc++];
1623       }
1624       while ((x == 0) && (dpc != 0xFFFF)); // Keep going until something found
1625       dpc--;
1626
1627       printf("%04X: ", dpc);       // Show data found...
1628       for(int i=0; i<16; i++)
1629         printf("%02X ", gram1[(uint16)(dpc+i)]);
1630       cout << " ";
1631       for(int i=0; i<16; i++)
1632       {
1633         uint8 a = gram1[dpc++];
1634         if (a<10)
1635           cout << (char)(a+48);
1636         if ((a>9) && (a<37))
1637           cout << (char)(a+55);
1638         if (a>36)
1639           cout << ".";
1640       }
1641       cout << endl;
1642     }
1643                 else if (lbuff[0] == 'v')    // View screen
1644                 {
1645 //                      SetVESA2();                           // Set up screen
1646                         BlitChar(screen, chr_rom, gram1);
1647                         getch();
1648 //                      RestoreOldMode();
1649                 }
1650
1651                 if (lbuff[0] == 'q')
1652                         active = false; //break;  // Quit
1653         }
1654
1655         SDL_Quit();                                                                     // Shut down SDL
1656
1657 #if 0
1658         delete[] gram1;                                                                         // Deallocate RAM & ROM spaces
1659         delete[] grom1;
1660         delete[] gram2;
1661         delete[] grom2;
1662         delete[] chr_rom;
1663         delete[] grom3;
1664         delete[] grom4;
1665         delete[] data_rom;
1666         delete[] spr_rom;
1667         delete[] voice_rom;
1668 #endif
1669
1670         for(int i=0; i<16; i++)
1671                 if (psg_adrs[i])
1672                         delete[] psg_adrs[i];                           // Deallocate if loaded
1673
1674         for(int i=0; i<14; i++)
1675                 if (fm_adrs[i])
1676                         delete[] fm_adrs[i];                            // Deallocate if loaded
1677
1678         LogDone();
1679
1680         return 1;
1681 }