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