]> Shamusworld >> Repos - thunder/blobdiff - src/thunder.cpp
Code cleanup/removal of cruft.
[thunder] / src / thunder.cpp
index 4cd035c2304fb993c21ebd587a86bc37d0d41996..ace26f29716faf7b51b9f8a977d4b8abf637e077 100644 (file)
@@ -1,5 +1,5 @@
 //
-// Thunder: A Rolling Thunder Emulator w/6809 debugger
+// Thunder: A Rolling Thunder Emulator
 //
 // by James Hammons
 // (C) 2004, 2014 Underground Software
 // ---  ----------  -----------------------------------------------------------
 // JLH  07/23/2009  Added changelog ;-)
 // JLH  08/12/2009  Stabilized emulation so that it works
+// JLH  04/04/2014  Converted to SDL 2
+// JLH  04/17/2014  Removed a metric fuck-tonne of cruft, added YM2151 & MCU
 //
 
-#define THUNDER_VERSION                "1.0.0"
+#define THUNDER_VERSION                "1.1.0"
 
+#include <SDL2/SDL.h>
 #include <iostream>
 #include <iomanip>
 #include <fstream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
-//#include <conio.h>                   // For getch()
-#include <curses.h>                    // For getch()
 #include <time.h>
-#include "SDL.h"                                                               // Get yer SDL out...!
-#include "v6809.h"
-#include "screen.h"
 #include "gui.h"
 #include "log.h"
+#include "psg.h"
+#include "screen.h"
+#include "sound.h"
+#include "v63701.h"
+#include "v6809.h"
+#include "video.h"
+#include "ym2151.h"
+
 
-using namespace std;                                                   // Yes!
+using namespace std;
 
 
 #define ROM1   "rt3-1b.9c"
@@ -68,634 +74,263 @@ using namespace std;                                                      // Yes!
 
 SDL_Surface * screen;
 
-uint8_t * gram, * grom;                                // Allocate RAM & ROM pointers
-uint8_t gram1[0x10000], gram2[0x10000], grom1[0x10000], grom2[0x10000];        // Actual memory
-uint8_t grom3[0x8000], grom4[0x8000], data_rom[0x40000], spr_rom[0x80000], voice_rom[0x20000];
-uint8_t chr_rom[0x60000];                      // Character ROM pointer
-
-V6809REGS cpu1, cpu2;
-
-bool trace1 = false;                           // ditto...
-bool looking_at_rom = true;                    // true = R1, false = R2
-uint32_t banksw1, banksw2;                     // Bank switch addresses
-uint16_t game_over_switch;                     // Game over delay
-uint16_t dpc;                                          // Debug pc reg...
-bool show_scr = true;                          // Whether or not to show background
-bool enable_cpu = true;                                // Whether or not to enable CPUs
-bool irqGoA = true;                                    // IRQ switch for CPU #1
-bool irqGoB = true;                                    // IRQ switch for CPU #2
-
-uint16_t refresh_ = 0;                         // Crappy global screen stuff...
+uint8_t * gram, * grom;                        // Allocate RAM & ROM pointers
+// Actual memory
+uint8_t gram1[0x10000], gram2[0x10000], grom1[0x10000], grom2[0x10000];
+uint8_t grom3[0x8000], data_rom[0x40000], spr_rom[0x80000], voice_rom[0x20000];
+uint8_t chr_rom[0x60000];              // Character ROM pointer
+uint8_t mcuMem[0x10000];               // 64K for MCU
+
+V6809REGS cpu1, cpu2;                  // CPU execution contexts
+V63701REGS mcu;
+
+bool trace1 = false;                   // ditto...
+bool looking_at_rom = true;            // true = R1, false = R2
+uint32_t banksw1, banksw2;             // Bank switch addresses
+uint16_t game_over_switch;             // Game over delay
+uint16_t dpc;                                  // Debug pc reg...
+bool show_scr = true;                  // Whether or not to show background
+bool enable_cpu = true;                        // Whether or not to enable CPUs
+bool irqGoA = true;                            // IRQ switch for CPU #1
+bool irqGoB = true;                            // IRQ switch for CPU #2
+
+uint16_t refresh_ = 0;                 // Crappy global screen stuff...
 bool refresh2 = true;
 
 uint32_t psg_lens[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 uint8_t * psg_adrs[16];
-uint32_t voc_lens[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-uint8_t * voc_adrs[32];
-uint32_t fm_lens[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-uint8_t * fm_adrs[14];
+
+Byte input1, input2, input3, input4, input5;
 
 fstream tr;                                                    // Tracelog hook
 uint16_t pcx;                                          // Where we at?
 
-static uint8_t * keys;                         // SDL raw keyboard matrix
-
-static char op_mat1[256] = {
-  1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
-  0, 0, 5, 5, 0, 0, 4, 4, 0, 5, 8, 0, 8, 5, 6, 6,
-  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-  7, 7, 7, 7, 6, 6, 6, 6, 0, 5, 5, 5, 8, 5, 5, 5,
-  5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
-  5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 5, 0, 5,
-  7, 0, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7,
-  2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
-  8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 3, 9, 0,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  8, 8, 8, 9, 8, 8, 8, 0, 8, 8, 8, 8, 9, 0, 9, 0,
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
-op_mat2[256] = {
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0,
-  0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
-  0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 7,
-  0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 },
-op_mat3[256] = {
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
-  0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
-  0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
-  0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-static char mnemonics[256][6] = {
-  "NEG  ","???  ","???  ","COM  ","LSR  ","???  ","ROR  ","ASR  ",
-  "LSL  ","ROL  ","DEC  ","???  ","INC  ","TST  ","JMP  ","CLR  ",
-  "PAGE1","PAGE2","NOP  ","SYNC ","???  ","???  ","LBRA ","LBSR ",
-  "???  ","DAA  ","ORCC ","???  ","ANDCC","SEX  ","EXG  ","TFR  ",
-  "BRA  ","BRN  ","BHI  ","BLS  ","BHS  ","BLO  ","BNE  ","BEQ  ",
-  "BVC  ","BVS  ","BPL  ","BMI  ","BGE  ","BLT  ","BGT  ","BLE  ",
-  "LEAX ","LEAY ","LEAS ","LEAU ","PSHS ","PULS ","PSHU ","PULU ",
-  "???  ","RTS  ","ABX  ","RTI  ","CWAI ","MUL  ","RESET","SWI  ",
-  "NEGA ","???  ","???  ","COMA ","LSRA ","???  ","RORA ","ASRA ",
-  "LSLA ","ROLA ","DECA ","???  ","INCA ","TSTA ","???  ","CLRA ",
-  "NEGB ","???  ","???  ","COMB ","LSRB ","???  ","RORB ","ASRB ",
-  "LSLB ","ROLB ","DECB ","???  ","INCB ","TSTB ","???  ","CLRB ",
-  "NEG  ","???  ","???  ","COM  ","LSR  ","???  ","ROR  ","ASR  ",
-  "LSL  ","ROL  ","DEC  ","???  ","INC  ","TST  ","JMP  ","CLR  ",
-  "NEG  ","???  ","???  ","COM  ","LSR  ","???  ","ROR  ","ASR  ",
-  "LSL  ","ROL  ","DEC  ","???  ","INC  ","TST  ","JMP  ","CLR  ",
-  "SUBA ","CMPA ","SCBA ","SUBD ","ANDA ","BITA ","LDA  ","???  ",
-  "EORA ","ADCA ","ORA  ","ADDA ","CMPX ","BSR  ","LDX  ","???  ",
-  "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA  ","STA  ",
-  "EORA ","ADCA ","ORA  ","ADDA ","CMPX ","JSR  ","LDX  ","STX  ",
-  "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA  ","STA  ",
-  "EORA ","ADCA ","ORA  ","ADDA ","CMPX ","JSR  ","LDX  ","STX  ",
-  "SUBA ","CMPA ","SBCA ","SUBD ","ANDA ","BITA ","LDA  ","STA  ",
-  "EORA ","ADCA ","ORA  ","ADDA ","CMPX ","JSR  ","LDX  ","STX  ",
-  "SUBB ","CMPB ","SCBB ","ADDD ","ANDB ","BITB ","LDB  ","???  ",
-  "EORB ","ADCB ","ORB  ","ADDB ","LDD  ","???  ","LDU  ","???  ",
-  "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB  ","STB  ",
-  "EORB ","ADCB ","ORB  ","ADDB ","LDD  ","STD  ","LDU  ","STU  ",
-  "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB  ","STB  ",
-  "EORB ","ADCB ","ORB  ","ADDB ","LDD  ","STD  ","LDU  ","STU  ",
-  "SUBB ","CMPB ","SBCB ","ADDD ","ANDB ","BITB ","LDB  ","STB  ",
-  "EORB ","ADCB ","ORB  ","ADDB ","LDD  ","STD  ","LDU  ","STU  " },
-mnemonics2[256][6] = {
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","LBRN ","LBHI ","LBLS ","LBHS ","LBLO ","LBNE ","LBEQ ",
-  "LBVC ","LBVS ","LBPL ","LBMI ","LBGE ","LBLT ","LBGT ","LBLE ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","SWI2 ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","CMPD ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","CMPY ","???  ","LDY  ","???  ",
-  "???  ","???  ","???  ","CMPD ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","CMPY ","???  ","LDY  ","STY  ",
-  "???  ","???  ","???  ","CMPD ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","CMPY ","???  ","LDY  ","STY  ",
-  "???  ","???  ","???  ","CMPD ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","CMPY ","???  ","LDY  ","STY  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","LDS  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","LDS  ","STS  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","LDS  ","STS  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","LDS  ","STS  " },
-mnemonics3[256][6] = {
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","SWI3 ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","CMPU ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","CMPS ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","CMPU ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","CMPS ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","CMPU ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","CMPS ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","CMPU ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","CMPS ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  ",
-  "???  ","???  ","???  ","???  ","???  ","???  ","???  ","???  " },
-tregs[16][3] = {
-  "D",  "X", "Y",  "U",  "S",  "PC", "??", "??",
-  "A",  "B", "CC", "DP", "??", "??", "??", "??" },
-iregs[4][2] = {"X", "Y", "U", "S" };
+// Function prototypes
+uint8_t MCUReadMemory(uint16_t address);
+void MCUWriteMemory(uint16_t address, uint8_t data);
 
 
 //
-// Read a byte from memory (without touching PC. Not a Fetch!)
+// Read a byte from memory
 //
 uint8_t RdMem(uint16_t addr)
 {
        uint8_t b;
 
-       // $4000-4300 is RAM shared with the microcontroller...
-
        if (addr < 0x8000)
        {
-               if (addr > 0x5FFF)
-                       b = data_rom[banksw1 + (addr - 0x6000)];        // Get char data
+               // Memory shared with MCU (CPU #1 only! CPU #2 does not)
+               if ((addr >= 0x4000) && (addr <= 0x43FF))
+                       return mcuMem[addr - 0x3000];
+//             if ((addr >= 0x4000) && (addr <= 0x41FF))
+//                     return MCUReadMemory(addr - 0x3000);
+//             if ((addr >= 0x4200) && (addr <= 0x43FF))
+//                     return mcuMem[addr - 0x3000];
+
+               if (addr >= 0x6000)
+                       return data_rom[banksw1 + (addr - 0x6000)];     // Get char data
                else
-                       b = gram1[addr];
+                       return gram1[addr];
        }
-       else
-               b = grom1[addr];
 
-       return b;
+       return grom1[addr];
 }
 
 
 //
 // Write a byte to memory
 //
-void WrMem(uint16_t addr, uint8_t b)
+void WrMem(uint16_t address, uint8_t data)
 {
        extern bool disasm;
-       extern bool charbase;                                                           // Needed for screen. Extern it in it??
-  //extern uint16_t sr, ur, xr, yr;            // Needed for tracelog
-  //extern uint16_t pcr;
-/*  if ((addr>0x40FF) && (addr<0x4390))
-  {
-    tr << hex << addr << ":" << (int)b;
-    //for(int i=0; i<32; i++)
-    //{
-    //  if (gram1[0x4400+i]<0x10)  tr << "0";
-    //  tr << hex << (uint16_t)gram1[0x4400+i] << " ";
-    //}
-    tr << endl;
-  }//*/
+       extern bool charbase;   // Needed for screen. Extern it in it??
 #if 0
-       if (addr == 0x4182)
+       if (address == 0x4182)
        {
                WriteLog("\nWriteMem: CPU #1 writing $%02X to $4182!\n\n", b);
        }
 #endif
+#if 0
+if (((address >= 0x4180) && (address <= 0x4191)) || (address == 0x4380))
+       printf("WriteMem: CPU #1 writing $%02X to $%04X...\n", b, address);
+#endif
 
-       if (addr == 0x6000)
-               SpawnSound(GAMESOUND, gram1[0x6200], 0);                // Do voice chan 1
-       if (addr == 0x6400)
-               SpawnSound(GAMESOUND, gram1[0x6600], 1);                // Do voice chan 2
-       if (addr == 0x6800)
-               banksw1 = (uint32_t)b << 13;                                            // Set char data bankswitch base address
-       if (addr > 0x4284 && addr < 0x42A5 && b)
-               SpawnSound(PSGSOUND, addr - 0x4285);                    // Do PSG sound on chans 2, 3
-       if (addr == 0x4380)
-       {
-               SpawnSound(FMSOUND, b);                                                 // Do FM sound on channel 4
-               if (b == 12)
-                       game_over_switch = 240;                                         // Set game over delay...
-       }
-       if (addr < 0x423D || addr > 0x425C)                                     // Protect writes to DSWs
-               gram1[addr] = b;
-       if (addr == 0x8800)
-               charbase = false;                                                               // Char banksw1
-       if (addr == 0x8C00)
-               charbase = true;                                                                // Char banksw2
-       if (addr == 0x8400)                                                                     // Frame go strobe? VBlank acknowledge?
+       if (address == 0x6000)
+{
+//printf("Spawning VOICE channel #1: $6000=$%02X, $6200=$%02X\n", b, gram1[0x6200]);
+               SpawnSound(GAMESOUND, gram1[0x6200], 0);        // Do voice chan 1
+}
+       if (address == 0x6400)
+{
+//printf("Spawning VOICE channel #2: $6400=$%02X, $6600=$%02X\n", b, gram1[0x6600]);
+               SpawnSound(GAMESOUND, gram1[0x6600], 1);        // Do voice chan 2
+}
+       if (address == 0x6800)
+               banksw1 = (uint32_t)data << 13;                         // Set char data bankswitch base address
+       if (address > 0x4284 && address < 0x42A5 && data)
+               SpawnSound(PSGSOUND, address - 0x4285);         // Do PSG sound on chans 2, 3
+
+//if ((address >= 0x4284) && (address < 0x42A5))
+//{
+//     printf("WrMem: Wrote $%02X to PSG address $%04X...\n", data, address);
+//}
+       // Memory shared with MCU (CPU #1 only! CPU #2 does not)
+       if ((address >= 0x4000) && (address <= 0x43FF))
+               mcuMem[address - 0x3000] = data;
+//     if ((address >= 0x4000) && (address <= 0x41FF))
+//             MCUWriteMemory(address - 0x3000, data);
+//     if ((address >= 0x4200) && (address <= 0x43FF))
+//             mcuMem[address - 0x3000] = data;
+       else
+               gram1[address] = data;
+
+       if (address == 0x8800)
+               charbase = false;                                                       // Char banksw1
+       if (address == 0x8C00)
+               charbase = true;                                                        // Char banksw2
+       if (address == 0x8400)                                                          // Frame go strobe? VBlank acknowledge?
        {
-               if (refresh_++ == 1)                                                            // 30 Hz...
-               {
-                       BlitChar(screen, chr_rom, gram1);
-                       refresh_ = (refresh2 ? 1 : 0);                          // 60/30 Hz...
-               }
+               BlitChar(screen, chr_rom, gram1);
 
                // IRQ Ack (may also be frame go...
                ClearLineOfCurrentV6809(V6809_ASSERT_LINE_IRQ);
 #if 1
        if (disasm)
-               WriteLog("WriteMem: CPU #1 Acknowledging IRQ...\n", b);
+               WriteLog("WriteMem: CPU #1 Acknowledging IRQ...\n", data);
 #endif
        }
 }
 
 
 //
-// Read a byte from memory (without touching PC. Not a Fetch!) (2nd processor)
+// Read a byte from memory (2nd processor)
 //
-uint8_t RdMemB(uint16_t addr)
+uint8_t RdMemB(uint16_t address)
 {
-//  extern uint16_t cpu2.s, cpu2.u, cpu2.x, cpu2.y;            // Needed for tracelog
-       uint8_t b;
-
-       if (addr < 0x8000)
+       if (address < 0x8000)
        {
-               if (addr < 0x2000)
-                       b = gram1[addr + 0x4000];
-               if (addr > 0x1FFF && addr < 0x6000)
-                       b = gram1[addr - 0x2000];
-               if (addr > 0x5FFF)
-                       b = grom3[banksw2 + (addr - 0x6000)];           // Correct?
+               if (address < 0x2000)
+                       return gram1[address + 0x4000];
+               else if ((address >= 0x2000) && (address < 0x6000))
+                       return gram1[address - 0x2000];
+               else if (address >= 0x6000)
+                       return grom3[banksw2 + (address - 0x6000)];
        }
-       else
-               b = grom2[addr];
-
-/*  if ((addr>0x3FFF) && (addr<0x4400))  tr << "R-" << hex << pcx << ": "
-                                        << addr << "-"
-                                        << (int)looking_at_rom
-                                        << " [" << (int)b
-                                        << "] XR:" << xr << " YR:" << yr
-                                        << " SR:" << sr << " UR:" << ur
-                                        << endl; //*/
-       return b;
+
+       return grom2[address];
 }
 
 
 //
 // Write a byte to memory (2nd processor)
 //
-void WrMemB(uint16_t addr, uint8_t b)
+void WrMemB(uint16_t address, uint8_t data)
 {
        extern bool disasm;
        extern bool charbase;
-  //extern uint16_t sr, ur, xr, yr;            // Needed for tracelog
-  //extern uint16_t pcr;
-/*  if ((addr>0x00FF) && (addr<0x0390))
-  {
-    tr << hex << addr << ":" << (int)b;
-    //for(int i=0; i<32; i++)
-    //{
-    //  if (gram1[0x4400+i]<0x10)  tr << "0";
-    //  tr << hex << (uint16_t)gram1[0x4400+i] << " ";
-    //}
-    tr << endl;
-  }//*/
-#if 0
-       if (addr == 0x0182)
-       {
-               WriteLog("\nWriteMem: CPU #2 writing $%02X to $0182 ($4182)!\n\n", b);
-       }
-#endif
 
-       if (addr == 0x6000)
-               SpawnSound(GAMESOUND, gram1[0x6200], 0);                // Do voice chan 1
-       if (addr == 0x6400)
-               SpawnSound(GAMESOUND, gram1[0x6600], 1);                // Do voice chan 2
-       if (addr > 0x0284 && addr < 0x02A5 && b)
-               SpawnSound(PSGSOUND, addr - 0x0285);                    // Do PSG sound on chans 2, 3
-       if (addr == 0xD803)
-               banksw2 = (uint32_t)(b & 0x03) << 13;                           // Set sprite data bank switch
-       if (addr == 0x0380)
-       {
-               SpawnSound(FMSOUND, b);                                                 // Do FM sound on chan 4
-               if (b == 12)
-                       game_over_switch = 240;                                         // Set game over delay...
-       }
-       if (addr < 0x023D || addr > 0x025C)                                     // Protect writes against DSWs
-       {
-               if (addr < 0x2000)
-                       gram1[addr + 0x4000] = b;
-               if (addr > 0x1FFF && addr < 0x6000)
-                       gram1[addr - 0x2000] = b;
-               if (addr > 0x5FFF)
-                       gram1[addr] = b;
-       }
-       if (addr == 0x8800)
+       // Set sprite data bank switch
+       if (address == 0xD803)
+               banksw2 = (uint32_t)(data & 0x03) << 13;
+
+       if (address < 0x2000)
+               gram1[address + 0x4000] = data;
+
+       if ((address >= 0x2000) && (address < 0x6000))
+               gram1[address - 0x2000] = data;
+
+       if (address == 0x8800)
        {
                // IRQ Ack (may also be frame go...)
                ClearLineOfCurrentV6809(V6809_ASSERT_LINE_IRQ);
 #if 1
        if (disasm)
-               WriteLog("WriteMem: CPU #2 Acknowledging IRQ...\n", b);
+               WriteLog("WriteMem: CPU #2 Acknowledging IRQ...\n", data);
 #endif
        }
 }
 
 
-//
-// Display bytes in mem in hex
-//
-void DisplayBytes(uint16_t src, unsigned long dst)
+uint8_t MCUReadMemory(uint16_t address)
 {
-       uint8_t cnt = 0;
-       WriteLog("%04X: ", src);
-
-       if (src > dst)
-               dst += 0x10000;        // That should fix the FFFF bug...
-
-       for(unsigned long i=src; i<dst; i++)
-       {
-               WriteLog("%02X ", (uint8_t)(looking_at_rom ? RdMem(i) : RdMemB(i)));
-               cnt++;
-       }
-
-       // Pad the leftover spaces...
-       for(unsigned long i=cnt; i<5; i++)
-               WriteLog("   ");
+       if (address < 0x20)
+               return InternalRegisterRead(address);
+       else if ((address >= 0x1000) && (address <= 0x113F))
+//     else if ((address >= 0x1000) && (address <= 0x11FF))
+               return ReadPSG(address - 0x1000);
+       else if ((address >= 0x2000) && (address <= 0x2001))
+               return YMReadReg(0);
+       // Various joystick + buttons; all are active low.
+       else if (address == 0x2020)
+               return input1.byte;
+       else if (address == 0x2021)
+               return input2.byte;
+       // This is DSW1 & 2. All switch settings are active low.
+       else if (address == 0x2030)
+               return input4.byte;
+       else if (address == 0x2031)
+               return input5.byte;
+
+       return mcuMem[address];
 }
 
 
-// temp crap...
-uint8_t Fetch(void) { return RdMem(dpc); }
-uint16_t FetchW(void) { return (uint16_t)((RdMem(dpc) << 8) | RdMem(dpc+1)); }
-uint8_t FetchB(void) { return RdMemB(dpc); }
-uint16_t FetchWB(void) { return (uint16_t)((RdMemB(dpc) << 8) | RdMemB(dpc+1)); }
-
-
-//
-// Decode a 6809 instruction at 'addr'
-//
-void Decode_6809()
+void MCUWriteMemory(uint16_t address, uint8_t data)
 {
-       uint8_t (* DFetch)();           // Decode Fetch() pointer...
-       uint16_t (* DFetchW)();          // Decode FetchW() pointer...
-       DFetch  = (looking_at_rom ? Fetch : FetchB);
-       DFetchW = (looking_at_rom ? FetchW : FetchWB);
-
-       /*  extern*/ uint16_t pcr, pcrB;              // Pull in 'pcr' from '6809.cpp'
-       uint16_t pc_save = pcr, pcB_save = pcrB;
-       pcr  = dpc;  pcrB = dpc;
-       uint8_t opcode = DFetch();             // Get the opcode ('fetch' cycle)
-       uint8_t opcode2, operand;
-       uint16_t loperand;
-       uint8_t admode = op_mat1[opcode];     // addressing mode
-       char outbuf[80], mnem[6], tmp[30];
-
-       strcpy(mnem, mnemonics[opcode]);  // Copy page 1 opcode
-
-       if (opcode == 0x10)             // Extended opcode?
-       {
-               opcode2 = DFetch();     // Then get next byte
-               admode = op_mat2[opcode2];    // And use it as index into 'op_mat2'
-               strcpy(mnem, mnemonics2[opcode2]);  // Overwrite mnemonic
-       }
+       static uint8_t ymRegister;
 
-       if (opcode == 0x11)             // Same as above...
+       if (address < 0x20)
        {
-               opcode2 = DFetch();
-               admode = op_mat3[opcode2];
-               strcpy(mnem, mnemonics3[opcode2]);  // Overwrite mnemonic
+               InternalRegisterWrite(address, data);
+               return;
        }
-
-       // Decode it...
-       switch (admode)
+       else if (((address >= 0x4000) && (address <= 0xBFFF))
+               || (address >= 0xF000))
+               return;
+       else if ((address >= 0x1000) && (address <= 0x113F))
+//     else if ((address >= 0x1000) && (address <= 0x11FF))
        {
-       case 0:  // Illegal
-               sprintf(outbuf, "???");
-               break;
-       case 1:  // Zero page
-               operand = DFetch();   // Get ZP address
-               sprintf(outbuf, "%s $%02X", mnem, operand);
-               break;
-       case 2:  // Absolute
-               loperand = DFetchW(); // Get ABS address
-               sprintf(outbuf, "%s $%04X", mnem, loperand);
-               break;
-       case 3:  // Relative
-       {
-               operand = DFetch();   // Get offset
-               uint16_t tmpc = (looking_at_rom ? pcr : pcrB);
-               sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16_t)(int8_t)operand);
-               break;
+               WritePSG(address - 0x1000, data);
+               return;
        }
-       case 4:  // Long Relative
+       else if (address == 0x2000)
        {
-               loperand = DFetchW(); // Get long offset
-               uint16_t tmpc = (looking_at_rom ? pcr : pcrB);
-               sprintf(outbuf, "%s $%04X", mnem, tmpc+(int16_t)loperand);
-               break;
+               ymRegister = data;
+               return;
        }
-       case 5:  // Inherent
-               sprintf(outbuf, "%s ", mnem);
-               break;
-       case 6:  // Txfr/exchg/push/pull
+       else if (address == 0x2001)
        {
-               operand = DFetch();   // Get txfr/exg/push/pull byte
-
-               if ((opcode == 0x1E) || (opcode == 0x1F))  // Is it TXF/EXG?
-               {
-                       sprintf(tmp, "%s,%s", tregs[operand>>4], tregs[operand&0x0F]);
-               }
-               else
-               {
-                       tmp[0] = 0;
-                       if (operand&0x01)  strcat(tmp, "CC ");
-                       if (operand&0x02)  strcat(tmp, "A ");
-                       if (operand&0x04)  strcat(tmp, "B ");
-                       if (operand&0x08)  strcat(tmp, "DP ");
-                       if (operand&0x10)  strcat(tmp, "X ");
-                       if (operand&0x20)  strcat(tmp, "Y ");
-                       if (operand&0x40)  (((opcode==0x34)||(opcode==0x35))
-                                               ? strcat(tmp, "U ") : strcat(tmp, "S "));
-                       if (operand&0x80)  strcat(tmp, "PC");
-               }
-               sprintf(outbuf, "%s %s", mnem, tmp);
-               break;
+               YMWriteReg(0, ymRegister, data);
+               return;
        }
-       case 7:  // Indexed (the tough one!)
-       {
-               operand = DFetch();   // Get IDX byte
-               uint8_t reg = ((operand & 0x60) >> 5), idxind = ((operand & 0x10) >> 4),
-                       lo_nyb = (operand & 0x0F),  boff;
-               uint16_t woff;
 
-               strcpy(tmp, "??");
-
-               if (!(operand & 0x80))      // Hi bit set? Then decode 4 bit offset
-               {
-                       sprintf(tmp, "(%d),%s", (idxind ? -(16-lo_nyb) : lo_nyb),
-                                       iregs[reg]);
-               }
-               else   // Add the ($nnnn,R) code dude...
-               {
-                       if (idxind)
-                       {
-                               switch (lo_nyb)
-                               {
-                               case 1:   sprintf(tmp, "(,%s++)", iregs[reg]);  break;
-                               case 3:   sprintf(tmp, "(,--%s)", iregs[reg]);  break;
-                               case 4:   sprintf(tmp, "(,%s)", iregs[reg]);  break;
-                               case 5:   sprintf(tmp, "(B,%s)", iregs[reg]);  break;
-                               case 6:   sprintf(tmp, "(A,%s)", iregs[reg]);  break;
-                               case 8:
-                               { boff = DFetch();  sprintf(tmp, "($%02X,%s)", boff,
-                                                                               iregs[reg]);  break; }
-                               case 9:
-                               { woff = DFetchW();  sprintf(tmp, "($%04X,%s)", woff,
-                                                                                       iregs[reg]);  break; }
-                               case 11:  sprintf(tmp, "(D,%s)", iregs[reg]);  break;
-                               case 12:
-                               { boff = DFetch();  sprintf(tmp, "($%02X,PC)", boff);  break; }
-                               case 13:
-                               { woff = DFetchW();  sprintf(tmp, "($%04X,PC)", woff);  break; }
-                               case 15:
-                               { woff = DFetchW();  sprintf(tmp, "[$%04X]", woff);  break; }
-                               default:  strcpy(tmp, "??");
-                               }
-                       }
-                       else
-                       {
-                               switch (lo_nyb)
-                               {
-                               case 0:   sprintf(tmp, ",%s+", iregs[reg]);  break;
-                               case 1:   sprintf(tmp, ",%s++", iregs[reg]);  break;
-                               case 2:   sprintf(tmp, ",-%s", iregs[reg]);  break;
-                               case 3:   sprintf(tmp, ",--%s", iregs[reg]);  break;
-                               case 4:   sprintf(tmp, ",%s", iregs[reg]);  break;
-                               case 5:   sprintf(tmp, "(B),%s", iregs[reg]);  break;
-                               case 6:   sprintf(tmp, "(A),%s", iregs[reg]);  break;
-                               case 8:
-                               { boff = DFetch();  sprintf(tmp, "($%02X),%s", boff,
-                                                                               iregs[reg]);  break; }
-                               case 9:
-                               { woff = DFetchW();  sprintf(tmp, "($%04X),%s", woff,
-                                                                               iregs[reg]);  break; }
-                               case 11:  sprintf(tmp, "(D),%s", iregs[reg]);  break;
-                               case 12:
-                               { boff = DFetch();  sprintf(tmp, "($%02X),PC", boff);  break; }
-                               case 13:
-                               { woff = DFetchW();  sprintf(tmp, "($%04X),PC", woff);  break; }
-                               default:  strcpy(tmp, "??");
-                               }
-                       }
-               }
-
-               sprintf(outbuf, "%s %s", mnem, tmp);
-               break;
-       }
-       case 8:  // Immediate
-               operand = DFetch();   // Get IMM byte
-               sprintf(outbuf, "%s #$%02X", mnem, operand);
-               break;
-       case 9:  // Long Immediate
-               loperand = DFetchW(); // Get IMM word
-               sprintf(outbuf, "%s #$%04X", mnem, loperand);
-               break;
-       }
-
-       DisplayBytes(dpc, (looking_at_rom ? pcr : pcrB));  // Show bytes
-       WriteLog(outbuf);
-       WriteLog("\n");     // display opcode & addressing, etc
-       dpc = (looking_at_rom ? pcr : pcrB);  // Advance debug PC
-       pcr = pc_save;
-       pcrB = pcB_save;  // Restore PCs
+       // RAM is from $0 - $3FFF, $C000 - $EFFF
+       mcuMem[address] = data;
 }
 
 
-//
-// Convert hex to dec
-//
-uint16_t htod(char * str)
+uint8_t V63701ReadPort1(void)
 {
-       uint16_t value = 0;
-       int len = strlen(str);
-
-       for(int i=0; i<len; i++)
-       {
-               if (str[i] >= '0' && str[i] <= '9')
-               {
-                       value = (value << 4) | (unsigned)(str[i] - '0');
-               }
-               else if (str[i] >= 'a' && str[i] <= 'f')
-               {
-                       value = (value << 4) | (unsigned)((str[i] - 'a') + 10);
-               }
-               else if (str[i] >= 'A' && str[i] <= 'F')
-               {
-                       value = (value << 4) | (unsigned)((str[i] - 'A') + 10);
-               }
-       }
-
-       return value;
+//     printf("V63701ReadPort1: Read $%02X...\n", input3.byte);
+       return input3.byte;
 }
 
 
-//
-// Load 32K file into ROM image space
-//
-bool Load32KImg(char * filename, uint16_t address)
+uint8_t V63701ReadPort2(void)
 {
-       ifstream ff;
-       char ch;
+       return 0xFF;
+}
 
-       ff.open(filename, ios::binary | ios::in);  // Open 'da file...
 
-       if (ff)
-       {
-               for(long i=0; i<32768; i++)                // Read it in...
-               {
-                       ff.get(ch);
-                       grom[address+i] = ch;
-               }
+void V63701WritePort1(uint8_t data)
+{
+//     printf("V63701WritePort1: Wrote $%02X...\n", data);
+}
 
-               ff.close();                                // Close 'da file...
-       }
 
-       return ff;
+void V63701WritePort2(uint8_t data)
+{
+//     printf("V63701WritePort2: Wrote $%02X...\n", data);
 }
 
 
@@ -705,27 +340,22 @@ bool Load32KImg(char * filename, uint16_t address)
 //
 bool LoadImg(const char * filename, uint8_t * mem, uint32_t address, uint32_t length)
 {
-       ifstream ff;
-       char path[80];
-       char ch;
+       char path[128];
 
        strcpy(path, "./ROMs/");
        strcat(path, filename);
-//  ff.open(filename, ios::binary | ios::in);  // Open 'da file...
-       ff.open(path, ios::binary | ios::in);       // Open 'da file...
+       FILE * file = fopen(path, "rb");
 
-       if (ff)
+       if (!file)
        {
-               for(uint32_t i=0; i<length; i++)             // Read it in...
-               {
-                       ff.get(ch);
-                       mem[address+i] = ch;
-               }
-
-               ff.close();                               // Close 'da file...
+               printf("Could not open file \"%s\"!\n", filename);
+               return false;
        }
 
-       return ff;
+       fread(&mem[address], 1, length, file);
+       fclose(file);
+
+       return true;
 }
 
 
@@ -737,11 +367,11 @@ bool ReadColorPROMs(void)
        fstream ff1, ff2;
        //  uint8_t ch;
        char ch;
-       extern uint8_t palette[768];     // Screen physical palette
+       extern uint32_t palette[256];     // Screen physical palette
        extern uint8_t ccolor[256][8];   // Character color PROM values
        extern uint8_t scolor[128][16];  // Sprite color PROM values
 
-       ff1.open("./ROMs/"PROM3, ios::binary|ios::in);
+       ff1.open("./ROMs/"PROM3, ios::binary | ios::in);
 
        if (ff1)
        {
@@ -757,7 +387,7 @@ bool ReadColorPROMs(void)
                ff1.close();
        }
 
-       ff1.open("./ROMs/"PROM4, ios::binary|ios::in);
+       ff1.open("./ROMs/"PROM4, ios::binary | ios::in);
 
        if (ff1)
        {
@@ -773,29 +403,35 @@ bool ReadColorPROMs(void)
                ff1.close();
        }
 
-       ff1.open("./ROMs/"PROM1, ios::binary|ios::in);
-       ff2.open("./ROMs/"PROM2, ios::binary|ios::in);
+       ff1.open("./ROMs/"PROM1, ios::binary | ios::in);
+       ff2.open("./ROMs/"PROM2, ios::binary | ios::in);
 
-       if (ff1)    // If open was successful...
+       // If open was successful...
+       if (ff1 && ff2)
        {
-               for(int i=0; i<768; i+=3)
+               // Palette is 12-bit RGB, we stretch it to 24-bit
+               for(int i=0; i<256; i++)
                {
-                       ff1.get(ch);
-                       palette[i]   = (uint8_t)(ch&0x0F);
-                       palette[i+1] = (uint8_t)(ch>>4);
-                       ff2.get(ch);
-                       palette[i+2] = (uint8_t)ch;
+                       char c1, c2;
+                       ff1.get(c1);
+                       ff2.get(c2);
+                       uint8_t r = (uint8_t)c1 & 0x0F;
+                       uint8_t g = (uint8_t)c1 >> 4;
+                       uint8_t b = (uint8_t)c2;
+                       palette[i] = 0xFF000000 | (b << 20) | (b << 16) | (g << 12) | (g << 8) | (r << 4) | r;
                }
 
-               // Do palette stretching here... I.e. add 0 to hinyb 0, 1 to hinyb 1, etc.
-
-               for(int i=0; i<768; i++)
-               palette[i] = ((palette[i]<<4)&0xF0) | (palette[i]&0x0F);
-
                ff1.close();
                ff2.close();
        }
 
+       // PROM5 has the following in it (tile address decoder):
+       // 00:  00 20 40 60  02 22 42 62  04 24 44 64  06 26 46 66
+       // 10:  88 A8 C8 E8  8A AA CA EA  8C AC CC EC  8E AE CE EE 
+
+       if (!ff1)
+               printf("Could not open PROM files!\n");
+
        return ff1;
 }
 
@@ -858,120 +494,7 @@ bool UnpackFonts(void)
        f1.close();
        f2.close();
 
-       return true;                                // Made it!
-}
-
-
-//
-// Get length of sample from WAV format
-//
-uint32_t GetWAVLength(fstream & file)
-{
-       char ch;
-       uint32_t len;
-
-       file.ignore(16);                                                                        // Skip header BS
-
-       for(int i=0; i<2; i++)
-       {
-               file.get(ch);  len = (int)(uint8_t)ch;
-               file.get(ch);  len |= (int)(uint8_t)ch << 8;
-               file.get(ch);  len |= (int)(uint8_t)ch << 16;
-               file.get(ch);  len |= (int)(uint8_t)ch << 24;
-
-               file.ignore(len + 4);                                                   // Skip intermediate data
-       }
-
-       file.get(ch);  len = (int)(uint8_t)ch;                                  // & finally get length of data
-       file.get(ch);  len |= (int)(uint8_t)ch << 8;
-       file.get(ch);  len |= (int)(uint8_t)ch << 16;
-       file.get(ch);  len |= (int)(uint8_t)ch << 24;
-
-       return len;
-}
-
-
-//
-// Load PSG samples from disk
-//
-void LoadPSGs(void)
-{
-       char file[40];
-       char ch;
-       uint32_t len;
-
-       for(int i=0; i<16; i++)
-       {
-               fstream fp;
-
-               psg_adrs[i] = NULL;                                                             // Zero out pointer
-               sprintf(file, "./sounds/psg%i.wav", i);                 // Create filename
-
-               fp.open(file, ios::binary | ios::in);                   // Attempt to open it...
-
-               if (fp)
-               {
-                       len = GetWAVLength(fp);                                         // Get WAV data length...
-                       psg_adrs[i] = new uint8_t[len];                         // Attempt to allocate space...
-
-                       if (psg_adrs[i] != NULL)
-                       {
-                               for(int j=0; j<(signed)len; j++)
-                               {
-                                       fp.get(ch);
-                                       psg_adrs[i][j] = ch;                            // & load it in...
-                               }
-
-                               psg_lens[i] = len;
-//                             cout << "Found sample file: " << file << "\t[Length: " << dec << len << "]" << endl;
-                               printf("Found sample file: %s\t[Length: %u]\n", file, len);
-                       }
-
-                       fp.close();
-               }
-       }
-}
-
-
-//
-// Load FM samples from disk
-//
-void LoadFMs(void)
-{
-       char file[200];
-       char ch;
-       uint32_t len;
-
-       for(int i=0; i<14; i++)
-       {
-               fstream fp;
-
-               fm_adrs[i] = NULL;                                                              // Zero out pointer
-               sprintf(file, "./sounds/fm%i.wav", i);                  // Create filename
-
-               fp.open(file, ios::binary | ios::in);                   // Attempt to open it...
-
-               if (fp)
-               {
-                       len = GetWAVLength(fp);                                         // Get WAV length...
-                       fm_adrs[i] = new uint8_t[len];                                  // Attempt to allocate space...
-
-                       if (fm_adrs[i] != NULL)
-                       {
-                               for(int j=0; j<(signed)len; j++)
-                               {
-                                       fp.get(ch);
-                                       fm_adrs[i][j] = ch;                                     // & load it in...
-                               }
-
-                               fm_lens[i] = len;
-//                             cout << "Found sample file: " << file << " [Length: " << dec << len << "]" << endl;
-                               printf("Found sample file: %s\t[Length: %u]\n", file, len);
-                       }
-
-                       fp.close();
-               }
-       }
+       return true;
 }
 
 
@@ -982,142 +505,103 @@ int main(int argc, char * argv[])
 {
        InitLog("thunder.log");
 
-extern bool disasm;    // From 'V6809.CPP'
-       extern bool charbase;                                           // From 'SCREEN.CPP'
+       extern bool disasm;                             // From 'V6809.CPP'
+       extern bool charbase;                   // From 'SCREEN.CPP'
        charbase = false;
 
-       char lbuff[80];
-       fstream ff;                       // Declare fstream without file hooks...
-       bool brk = false, brk2 = false;   // Breakpoint set flag
-       uint16_t brkpnt, brkpnt2;             // Where the breakpoint is...
-       bool running;                     // CPU running state flag...
-       bool self_test = false;           // Self-test switch
-       bool scr_type = false;            // false=chars, true=pixels
-       uint16_t debounce = 0;                // Key de-bounce counter
-       uint16_t fire_debounce = 0;           // Fire button debounce counter
-//  bool refresh2 = true;             // Default to 60 Hz...
-       uint8_t x;                           // General placeholder...
-       bool active = true;                                             // Program running flag
-
-       SDL_Event event;                                                                // SDL "event"
-       extern uint8_t palette[768];                                    // Screen physical palette
+       bool running;                                   // CPU running state flag...
+       SDL_Event event;                                // SDL "event"
+       extern uint8_t palette[768];    // Screen physical palette
        uint32_t ticks, oldTicks;
 
-       cout << endl << "THUNDER v"THUNDER_VERSION" ";
-       cout << "by James Hammons" << endl;
-       cout << "Serial #20149404 / Prerelease" << endl;
-       cout << "© 2003, 2014 Underground Software" << endl << endl;
-
-       cout << "This emulator is free software. If you paid for it you were RIPPED OFF"
-               << endl << endl;
+       printf("THUNDER v"THUNDER_VERSION" by James Hammons\n");
+       printf("Serial #20149417 / Prerelease\n");
+       printf("© 2003, 2014 Underground Software\n\n");
+       printf("This emulator is free software. If you paid for it you were RIPPED OFF\n\n");
 
-       cout << "Initializing SDL..." << endl;
+//     SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder");
 
-       if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
-       {
-               cout << "Couldn't initialize SDL: " << SDL_GetError() << endl;
-               return -1;
-       }
+       // Needed only for debugger
+       gram = gram1;  grom = grom1;
 
-       SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder");
-
-       keys = SDL_GetKeyState(NULL);                           // Get the SDL keyboard matrix
-
-       gram = gram1;  grom = grom1;           // Needed only for debugger
-
-       for(long i=0; i<0x10000; i++)
-       {
-               gram[i] = 0;  grom[i] = 0;           // Zero out memory
-               gram2[i] = 0;  grom2[i] = 0;
-       }
-
-       game_over_switch = 0;   // Init game over delay
-//  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;
+       memset(gram, 0, 0x10000);
+       memset(grom, 0, 0x10000);
+       memset(gram2, 0, 0x10000);
+       memset(grom2, 0, 0x10000);
 
        cout << "Loading ROMs..." << endl;
-//  LoadCMOS();                            // Load CMOS at $CC00-$CFFF
-       if (!ReadColorPROMs())                   // Load virtual PROMs
-       { cout << "Could not open PROM files!" << endl;  return -1; }
-
-       if (!LoadImg(ROM1, grom1, 0x8000, 0x8000)) // Load $8000-$FFFF 1st ROM
-       { cout << "Could not open file '" << ROM1 << "'!" << endl;  return -1; }
+       if (!ReadColorPROMs())
+               return -1;
 
-       if (!LoadImg(ROM2, grom2, 0x8000, 0x8000)) // Load $8000-$FFFF 2nd ROM
-       { cout << "Could not open file '" << ROM2 << "'!" << endl;  return -1; }
+       // Load $8000-$FFFF 1st ROM
+       if (!LoadImg(ROM1, grom1, 0x8000, 0x8000))
+               return -1;
 
-       if (!LoadImg(ROM3, grom3, 0, 0x8000))      // Load 3rd ROM into its own space
-       { cout << "Could not open file '" << ROM3 << "'!" << endl;  return -1; }
+        // Load $8000-$FFFF 2nd ROM
+       if (!LoadImg(ROM2, grom2, 0x8000, 0x8000))
+               return -1;
 
-       if (!LoadImg(ROM4, grom4, 0, 0x8000))      // Load 4rd ROM into its own space
-       { cout << "Could not open file '" << ROM4 << "'!" << endl;  return -1; }
+       // Load 3rd ROM into its own space
+       if (!LoadImg(ROM3, grom3, 0, 0x8000))
+               return -1;
 
-       if (!LoadImg(ROM17, data_rom, 0,       0x10000))  // Load 17th ROM
-       { cout << "Could not open file '" << ROM17 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM17, data_rom, 0,       0x10000))
+               return -1;
 
-       if (!LoadImg(ROM18, data_rom, 0x10000, 0x10000))  // Load 18th ROM
-       { cout << "Could not open file '" << ROM18 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM18, data_rom, 0x10000, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM19, data_rom, 0x20000, 0x10000))  // Load 19th ROM
-       { cout << "Could not open file '" << ROM19 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM19, data_rom, 0x20000, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM20, data_rom, 0x30000, 0x10000))  // Load 20th ROM
-       { cout << "Could not open file '" << ROM20 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM20, data_rom, 0x30000, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM9,  spr_rom, 0,       0x10000))   // Load 9th ROM
-       { cout << "Could not open file '" << ROM9 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM9,  spr_rom, 0,       0x10000))
+               return -1;
 
-       if (!LoadImg(ROM10, spr_rom, 0x10000, 0x10000))   // Load 10th ROM
-       { cout << "Could not open file '" << ROM10 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM10, spr_rom, 0x10000, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM11, spr_rom, 0x20000, 0x10000))   // Load 11th ROM
-       { cout << "Could not open file '" << ROM11 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM11, spr_rom, 0x20000, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM12, spr_rom, 0x30000, 0x10000))   // Load 12th ROM
-       { cout << "Could not open file '" << ROM12 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM12, spr_rom, 0x30000, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM13, spr_rom, 0x40000, 0x10000))   // Load 13th ROM
-       { cout << "Could not open file '" << ROM13 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM13, spr_rom, 0x40000, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM14, spr_rom, 0x50000, 0x10000))   // Load 14th ROM
-       { cout << "Could not open file '" << ROM14 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM14, spr_rom, 0x50000, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM15, spr_rom, 0x60000, 0x10000))   // Load 15th ROM
-       { cout << "Could not open file '" << ROM15 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM15, spr_rom, 0x60000, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM16, spr_rom, 0x70000, 0x10000))   // Load 16th ROM
-       { cout << "Could not open file '" << ROM16 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM16, spr_rom, 0x70000, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM21, voice_rom, 0, 0x10000))  // Load 21st ROM
-       { cout << "Could not open file '" << ROM21 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM21, voice_rom, 0, 0x10000))
+               return -1;
 
-       if (!LoadImg(ROM22, voice_rom, 0x10000, 0x10000))  // Load 22nd ROM
-       { cout << "Could not open file '" << ROM22 << "'!" << endl;  return -1; }
+       if (!LoadImg(ROM22, voice_rom, 0x10000, 0x10000))
+               return -1;
 
-       if (!UnpackFonts())                         // Load 5, 6, 7, 8th ROMs
+       // Load 5, 6, 7, 8th ROMs
+       if (!UnpackFonts())
        {
                cout << "Could not open font files!" << endl;
                return -1;
        }
 
-       // Load samples if they're there...
-       LoadPSGs();
-       LoadFMs();
-
-  // Quick 'n' Dirty voice dump (sound 0x0E)
-/*  uint32_t adc = (voice_rom[26]<<8) | voice_rom[27];
-  bool doneWitIt = false;
-  int crh = 0;
-  while (!doneWitIt)
-  {
-    if (voice_rom[adc] < 0x10)  tr << "0";
-    tr << hex << (int)voice_rom[adc] << " ";
-    if (crh++ > 24)  { crh = 0;  tr << endl; }
-    if ((voice_rom[adc] == 0xFF) && (voice_rom[adc-1] != 0x00))
-      doneWitIt = true;
-    adc++;
-  }//*/
-
-       // Set up V6809 execution contexts
+       // Load MCU program + data
+       if (!LoadImg(MCUROM, mcuMem, 0xF000, 0x1000))
+               return -1;
+
+       if (!LoadImg(ROM4, mcuMem, 0x4000, 0x8000))
+               return -1;
+
+       // Set up V6809, V63701 execution contexts
 
        memset(&cpu1, 0, sizeof(V6809REGS));
        cpu1.RdMem = RdMem;
@@ -1129,229 +613,195 @@ extern bool disasm;    // From 'V6809.CPP'
        cpu2.WrMem = WrMemB;
        cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
 
-       bool firstTime = true;                                                          // kludge...
+       memset(&mcu, 0, sizeof(V63701REGS));
+       mcu.RdMem = MCUReadMemory;
+       mcu.WrMem = MCUWriteMemory;
+       mcu.cpuFlags |= V63701_ASSERT_LINE_RESET;
 
-WriteLog("About to go to the main loop...\n");
-       while (active)
-       {
-               cout << ">";
-               if (firstTime)
-               {
-                       firstTime = false;                                                      // crappy kludge...
-                       lbuff[0] = 'r';
-                       lbuff[1] = 0;
-               }
-               else
-                       cin >> lbuff;
+       running = true;                                                         // Set running status...
 
-               if (lbuff[0] == 'd')
-               {
-                       if (lbuff[1] != 0)
-                       {
-                               lbuff[0] = 32;
-                               dpc = htod(lbuff);
-                       }
-                       printf("%04X: ", dpc);
-                       uint16_t pc_save = cpu1.pc, pcB_save = cpu2.pc;
-                       cpu1.pc = dpc;  cpu2.pc = dpc;
-                       for(int i=0; i<16; i++)
-                               printf("%02X ", (looking_at_rom ? Fetch() : FetchB()));
-                       cout << " ";
-                       cpu1.pc = dpc;  cpu2.pc = dpc;
-                       for(int i=0; i<16; i++)
-                       {
-                               uint8_t a = (looking_at_rom ? Fetch() : FetchB());
-                               if (a<10)             cout << (char)(a+48);
-                               if ((a>9) && (a<37))  cout << (char)(a+55);
-                               if (a>36)             cout << ".";
-                       }
-                       cout << endl;
-                       dpc = (looking_at_rom ? cpu1.pc : cpu2.pc);
-                       cpu1.pc = pc_save;  cpu2.pc = pcB_save;
-               }
-               else if (lbuff[0] == 'e')
-               {
-                       if (lbuff[1] != 0)
-                       {
-                               lbuff[0] = 32;
-                               dpc = htod(lbuff);
-                       }
-                       printf("%04X: ", dpc);
-                       for(int i=0; i<16; i++)  printf("%02X ", (uint8_t)gram[dpc++]);
-                       cout << endl;
-               }
-               else if (lbuff[0] == 'l')
-               {
-                       if (lbuff[1] != 0)
-                       {
-                               lbuff[0] = 32;
-                               dpc = htod(lbuff);
-                       }
-                       for(int i=0; i<23; i++)
-                               Decode_6809();
-               }
-               else if (lbuff[0] == 't')
-               {
-                       if (lbuff[1] != 0)
-                       {
-                               lbuff[0] = 32;
-                               dpc = htod(lbuff);
-                       }
-                       if (looking_at_rom)
-                       {
-                               cpu1.pc = dpc;
-                               Decode_6809();
-                               Execute6809(&cpu1, 1);
-                               dpc = cpu1.pc;
-                               printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
-                                       cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
-                               cout << " iclock=" << cpu1.clock << endl;
-                       }
-                       else
-                       {
-                               cpu2.pc = dpc;
-                               Decode_6809();
-                               Execute6809(&cpu2, 1);
-                               dpc = cpu2.pc;
-                               printf("A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
-                                       cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
-                               cout << " iclock=" << cpu2.clock << endl;
-                       }
-               }
-               else if ((lbuff[0] == 'r') || (lbuff[0] == 'c')) // Run/continue...
-               {
-WriteLog("Executing 'run' command...\n");
-                       uint32_t my_clock = 0;
-                       running = true;                                                         // Set running status...
-                       trace1 = false;
-                       SetRefreshRate(refresh2);                                       // Tell GUI our refresh rate
-      //for(uint16_t i=0; i<0x8000; i++)  gram2[i] = grom3[i]; //Temp
-
-                       if (lbuff[0] == 'r')                                            // If run, then reset CPUs
-                       {
-WriteLog("Executing secondary 'run' command...\n");
-#if 1
-                               // This is data that is supposed to come from the MCU... So that's why it hangs
-                               gram1[0x4182] = 0xA6;          // Temp kludge
-                               gram1[0x4184] = 0xA6;
-                               gram1[0x4183] = 0x00;          // More of the same
-                               gram1[0x4185] = 0x00;
-#endif
-                               banksw1 = 0;                   // Will this work?
-                               banksw2 = 0;
-//        iclock = 0;                // Reset instr clock #1...
-                               InitGUI();                 // Reset # of coins
-
-#if 0
-                               cpu1.pc = ((grom1[0xFFFE]<<8) | grom1[0xFFFF]); // Reset 6809 #1
-                               if (lbuff[1] != 0)
-                               {
-                               lbuff[0] = 32;  cpu1.pc = htod(lbuff);
-                               }
-                               else  cpu1.cc = 0xFF;                         // Set CC register
-
-                               cpu2.pc = ((grom2[0xFFFE]<<8) | grom2[0xFFFF]); // Reset 6809 #2
-                               cpu2.cc = 0xFF;                              // Set CC register
-                               while(iclock < 8000)  // was 17000, 20000, 5000
-                               {
-                               Execute6809(&cpu1, 1);  Execute6809(&cpu2, 1);
-                               }
-#endif
-#if 0
-WriteLog("--> CPU clock #1: %u\n", cpu1.clock);
-                               // Will *this* help video sync? NO
-                               while (cpu1.clock < 8000)                               // was 17000, 20000, 5000
-                               {
-                                       Execute6809(&cpu1, 1);
-                                       Execute6809(&cpu2, 1);
-                               }
-#endif
-                       }
+       // Set all inputs to inactive...
+       input1.byte = input2.byte = input3.byte = input4.byte = input5.byte = 0xFF;
+       banksw1 = 0;                   // Will this work?
+       banksw2 = 0;
+       InitGUI();                 // Reset # of coins
 
 WriteLog("About to set up screen...\n");
-                       screen = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 8, SDL_SWSURFACE  | SDL_DOUBLEBUF);
-                       if (screen == NULL)
-                       {
-                               cout << "Failed to initialize screen!" << endl;
-                               running = false;
-                       }
-
-                       SDL_Color colors[256];
-
-                       for(int i=0; i<256; i++)
-                       {
-                               colors[i].r = palette[i*3+0];
-                               colors[i].g = palette[i*3+1];
-                               colors[i].b = palette[i*3+2];
-                       }
+       InitVideo();
 
-                       SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256);
+       oldTicks = SDL_GetTicks();
 
-#if 0
-       // This confirms that we're getting video to the screen...
-       SDL_LockSurface(screen);
+WriteLog("About to set up audio...\n");
+       InitSound();
 
-       uint8_t pixel = 0;
-       uint8_t * pixels = (uint8_t *)(screen->pixels);
+memset(scrBuffer, 0xFF, VIRTUAL_SCREEN_WIDTH*VIRTUAL_SCREEN_HEIGHT*sizeof(uint32_t));
+RenderScreenBuffer();
 
-       for(uint32_t y=0; y<480; y++)
-               for(uint32_t x=0; x<640; x++)
-                       pixels[(y * 640) + x] = pixel++;
+WriteLog("About to enter main loop...\n");
+       while (running)
+       {
+               HandleGUIDebounce();                                    // Debounce GUI keys
 
-       SDL_UnlockSurface(screen);
-       SDL_UpdateRect(screen, 0, 0, 0, 0);
-#endif
+// Dipswitches are presented to the main CPUs as 0 or 1 at locations
+// $423D - $425B by the MCU
 
-                       for(int i=0; i<256; i++)
-                               keys[i] = 0;                            // Clear keyboard buffer...
+//testing... (works)
+//gram1[0x423D] = 1;
+               //gram1[0x423D] = self_test;                    // Reset DSW1-1
+//             gram1[0x4268] = 0;                                              // Reset Video test
 
-                       oldTicks = SDL_GetTicks();
+               // SDL key handling...
 
-WriteLog("About to set up audio...\n");
-                       // This crap SHOULD be in sound.cpp (not yet created)...
-                       SDL_AudioSpec desired, obtained;
-                       desired.freq = 22050;
-                       desired.format = AUDIO_U8;
-                       desired.channels = 1;
-                       desired.samples = 600;
-                       desired.callback = SoundFunc;
-                       desired.userdata = NULL;
-                       // Also, should check to see if it got the hardware it needed, correct sample size, etc.
-                       if (SDL_OpenAudio(&desired, &obtained) < 0)
-                       {
-                               cout << "Couldn't open audio: " << SDL_GetError() << endl;
-                               return -1;
-                       }
+               SDL_Event event;
 
-                       SDL_PauseAudio(0);                                                      // Get that audio going!
-
-WriteLog("About to enter main loop...\n");
-                       while (running)
+               while (SDL_PollEvent(&event))
+               {
+                       switch (event.type)
                        {
-                               HandleGUIDebounce();                                    // Debounce GUI keys
-                               if (game_over_switch)
+                       case SDL_KEYDOWN:
+                               if (event.key.keysym.sym == SDLK_ESCAPE)
+                                       running = false;
+                               // Do PCX snapshot (F4)
+                               else if (event.key.keysym.sym == SDLK_F4)
                                {
-                                       game_over_switch--;  // Countdown...
-                                       if (game_over_switch == 0)
-                                               gram1[0x4380] = 0; // Kill music!
+//                                     SpawnSound(USERSOUND, SCAMERA);
+                                       SavePCXSnapshot();
                                }
-//testing... (works)
-//gram1[0x423D] = 1;
-                               //gram1[0x423D] = self_test;                    // Reset DSW1-1
-                               gram1[0x4268] = 0;                                              // Reset Video test
-                               gram1[0x427A] = 0;  gram1[0x427C] = 0;
-                               gram1[0x427B] = 0;  gram1[0x427D] = 0;
-                               gram1[0x427E] = 0;  gram1[0x427F] = 0;
-                               gram1[0x4280] = 0;  gram1[0x4281] = 0;
-                               gram1[0x4276] = 0;  gram1[0x426A] = 0;
-                               gram1[0x4278] = 0;  gram1[0x426C] = 0;
-                               gram1[0x4262] = 0;  gram1[0x4260] = 0;
-                               //gram1[0x4247] = 0;
+#if 1
+                               else if (event.key.keysym.sym == SDLK_5)
+                                       input1.bit.b5 = 0;
+                               else if (event.key.keysym.sym == SDLK_1)
+                                       input1.bit.b6 = 0;
+                               else if (event.key.keysym.sym == SDLK_RIGHT)
+                                       input3.bit.b5 = 0;
+                               else if (event.key.keysym.sym == SDLK_LEFT)
+                                       input3.bit.b4 = 0;
+                               else if (event.key.keysym.sym == SDLK_UP)
+                                       input2.bit.b2 = 0;
+                               else if (event.key.keysym.sym == SDLK_DOWN)
+                                       input1.bit.b2 = 0;
+                               else if (event.key.keysym.sym == SDLK_q)        // (Q)  Jump
+                                       input1.bit.b1 = 0;
+                               else if (event.key.keysym.sym == SDLK_e)        // (E) Fire
+                                       input3.bit.b3 = 0;
+#else
+                               else if (event.key.keysym.sym == SDLK_1)
+                                       input1.bit.b0 = 0;
+                               else if (event.key.keysym.sym == SDLK_2)
+                                       input1.bit.b1 = 0;
+                               else if (event.key.keysym.sym == SDLK_3)
+                                       input1.bit.b2 = 0;
+                               else if (event.key.keysym.sym == SDLK_4)
+                                       input1.bit.b3 = 0;
+                               else if (event.key.keysym.sym == SDLK_5)
+                                       input1.bit.b4 = 0;
+                               else if (event.key.keysym.sym == SDLK_6)
+                                       input1.bit.b5 = 0;
+                               else if (event.key.keysym.sym == SDLK_7)
+                                       input1.bit.b6 = 0;
+                               else if (event.key.keysym.sym == SDLK_8)
+                                       input1.bit.b7 = 0;
+
+                               else if (event.key.keysym.sym == SDLK_q)
+                                       input2.bit.b0 = 0;
+                               else if (event.key.keysym.sym == SDLK_w)
+                                       input2.bit.b1 = 0;
+                               else if (event.key.keysym.sym == SDLK_e)
+                                       input2.bit.b2 = 0;
+                               else if (event.key.keysym.sym == SDLK_r)
+                                       input2.bit.b3 = 0;
+                               else if (event.key.keysym.sym == SDLK_t)
+                                       input2.bit.b4 = 0;
+                               else if (event.key.keysym.sym == SDLK_y)
+                                       input2.bit.b5 = 0;
+                               else if (event.key.keysym.sym == SDLK_u)
+                                       input2.bit.b6 = 0;
+                               else if (event.key.keysym.sym == SDLK_i)
+                                       input2.bit.b7 = 0;
+
+                               else if (event.key.keysym.sym == SDLK_a)
+                                       input3.bit.b0 = 0;
+                               else if (event.key.keysym.sym == SDLK_s)
+                                       input3.bit.b1 = 0;
+                               else if (event.key.keysym.sym == SDLK_d)
+                                       input3.bit.b2 = 0;
+                               else if (event.key.keysym.sym == SDLK_f)
+                                       input3.bit.b3 = 0;
+                               else if (event.key.keysym.sym == SDLK_g)
+                                       input3.bit.b4 = 0;
+#endif
 
-                               // SDL key handling...
+                               break;
+                       case SDL_KEYUP:
+#if 1
+                               if (event.key.keysym.sym == SDLK_5)
+                                       input1.bit.b5 = 1;
+                               else if (event.key.keysym.sym == SDLK_1)
+                                       input1.bit.b6 = 1;
+                               else if (event.key.keysym.sym == SDLK_RIGHT)
+                                       input3.bit.b5 = 1;
+                               else if (event.key.keysym.sym == SDLK_LEFT)
+                                       input3.bit.b4 = 1;
+                               else if (event.key.keysym.sym == SDLK_UP)
+                                       input2.bit.b2 = 1;
+                               else if (event.key.keysym.sym == SDLK_DOWN)
+                                       input1.bit.b2 = 1;
+                               else if (event.key.keysym.sym == SDLK_q)        // (Q)  Jump
+                                       input1.bit.b1 = 1;
+                               else if (event.key.keysym.sym == SDLK_e)        // (E) Fire
+                                       input3.bit.b3 = 1;
+#else
+                               if (event.key.keysym.sym == SDLK_1)
+                                       input1.bit.b0 = 1;
+                               else if (event.key.keysym.sym == SDLK_2)
+                                       input1.bit.b1 = 1;
+                               else if (event.key.keysym.sym == SDLK_3)
+                                       input1.bit.b2 = 1;
+                               else if (event.key.keysym.sym == SDLK_4)
+                                       input1.bit.b3 = 1;
+                               else if (event.key.keysym.sym == SDLK_5)
+                                       input1.bit.b4 = 1;
+                               else if (event.key.keysym.sym == SDLK_6)
+                                       input1.bit.b5 = 1;
+                               else if (event.key.keysym.sym == SDLK_7)
+                                       input1.bit.b6 = 1;
+                               else if (event.key.keysym.sym == SDLK_8)
+                                       input1.bit.b7 = 1;
+
+                               else if (event.key.keysym.sym == SDLK_q)
+                                       input2.bit.b0 = 1;
+                               else if (event.key.keysym.sym == SDLK_w)
+                                       input2.bit.b1 = 1;
+                               else if (event.key.keysym.sym == SDLK_e)
+                                       input2.bit.b2 = 1;
+                               else if (event.key.keysym.sym == SDLK_r)
+                                       input2.bit.b3 = 1;
+                               else if (event.key.keysym.sym == SDLK_t)
+                                       input2.bit.b4 = 1;
+                               else if (event.key.keysym.sym == SDLK_y)
+                                       input2.bit.b5 = 1;
+                               else if (event.key.keysym.sym == SDLK_u)
+                                       input2.bit.b6 = 1;
+                               else if (event.key.keysym.sym == SDLK_i)
+                                       input2.bit.b7 = 1;
+
+                               else if (event.key.keysym.sym == SDLK_a)
+                                       input3.bit.b0 = 1;
+                               else if (event.key.keysym.sym == SDLK_s)
+                                       input3.bit.b1 = 1;
+                               else if (event.key.keysym.sym == SDLK_d)
+                                       input3.bit.b2 = 1;
+                               else if (event.key.keysym.sym == SDLK_f)
+                                       input3.bit.b3 = 1;
+                               else if (event.key.keysym.sym == SDLK_g)
+                                       input3.bit.b4 = 1;
+#endif
 
-                               SDL_PumpEvents();                               // Force key events into the buffer.
+                               break;
+                       }
+               }
 
+#if 0
                                if (keys[SDLK_ESCAPE])
                                        running = false;                     // ESC to exit...
 
@@ -1525,51 +975,12 @@ WriteLog("About to enter main loop...\n");
 
                                if (keys[SDLK_F7])
                                        SpawnSound(USERSOUND, 0);       // Do user sound (F7)
-
-//                             if (keys[SDLK_F8])
-//                             {
-//                                     gram1[0x4380] = 0;                      // (F8) kill music (this worx)
-//                                     charbase = false;                       // Switch chars out...
-//                             }
-//                             if (keys[SDLK_F9])  gram1[0x4285] = 1;          // (F9) strobe unknown loc
-
-                               if (keys[SDLK_F11])                             // (F11)
-                               {
-                                       Execute6809(&cpu1, 10);
-                                       Execute6809(&cpu2, 10);
-                               }
-//                     }
-//F12 is used above, but the values are ignored. So we'll do it here too.
-                               if (keys[SDLK_F12])
-                               {
-                                       cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
-                                       cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
-                               }
-
-                               if (keys[SDLK_d])                               // (D) start disassembly
-                                       disasm = true;
-#if 0
-       if (keys[SDLK_k])
-               gram1[0x5606] = 0x00;
-       if (keys[SDLK_l])
-       {
-               gram1[0x5607] = 0x01; // Hangs here... (CPU #1 waiting...)
-               WriteLog("\nMAIN: Stuffed $01 in $5607!!!\n\n");
-       }
-       if (keys[SDLK_o])
-       {
-               gram1[0x5FF3] = 0x02;
-               WriteLog("\nMAIN: Stuffed $02 in $5FF3!!!\n\n");
-       }
 #endif
 
-
-                               if (enable_cpu)
-//                             if (true)
-                               {
-                                       // We can do this here because we're not executing the cores yet.
-                                       cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
-                                       cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
+               // We can do this here because we're not executing the cores yet.
+               cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ;
+               cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ;
+               mcu.cpuFlags |= V63701_ASSERT_LINE_IRQ;
 //                                     while (cpu1.clock < 25000)
 // 1.538 MHz = 25633.333... cycles per frame (1/60 s)
 // 25600 cycles/frame
@@ -1579,165 +990,34 @@ WriteLog("About to enter main loop...\n");
 // 640 * 40
 // 800 * 32
 // Interesting, putting IRQs at 30 Hz makes it run at the correct speed. Still hangs in the demo, though.
-                                       for(uint32_t i=0; i<640; i++)
-//                                     for(uint32_t i=0; i<1280; i++)
-                                       {
-                                               // Gay, but what are ya gonna do?
-                                               // There's better ways, such as keeping track of when slave writes to master, etc...
-                                               Execute6809(&cpu1, 40);
-                                               Execute6809(&cpu2, 40);
-                                       }
-                               } // END: enable_cpu
-
-//        if (refresh_++ == 1)                // 30 Hz...
-//        {
-//          if (scr_type)
-//            BlitWilliamsScreen(gram1);     // Display the screen...
-//          else
-//            BlitChar(screen, chr_rom, gram1);
-//          refresh_ = (refresh2 ? 1 : 0);    // 60/30 Hz...
-//        }
-
-#if 0
-//temp, for testing...
-BlitChar(screen, chr_rom, gram1);
-#endif
-                               // Speed throttling happens here...
-                               while (SDL_GetTicks() - oldTicks < 16)  // Actually, it's 16.66... Need to account for that somehow
-//                             while (SDL_GetTicks() - oldTicks < 32)  // Actually, it's 16.66... Need to account for that somehow
-                                       SDL_Delay(1);                           // Release our timeslice...
-
-                               oldTicks = SDL_GetTicks();
-//cout << "Finished frame..." << endl;
-                       }
-
-//      Stop_audio_output();
-//      ReleaseTimer();
-//      ReleaseKeyboard();               // Release the interrupt...
-//      RestoreOldMode();                // Restore screen
-                       if (brk && (cpu1.pc == brkpnt))
-                               cout << "CPU 1: Break at " << hex << cpu1.pc << endl;
-                       if (brk2 && (cpu2.pc == brkpnt2))
-                               cout << "CPU 2: Break at " << hex << cpu2.pc << endl;
-
-                       lbuff[0] = 'q';                         // Temp kludge...
-               }
-               else if (lbuff[0] == 'b')  // Set/clear breakpoint
+               for(int i=0; i<640; i++)
                {
-                       if (lbuff[1] != 0)
-                       {
-                               lbuff[0] = 32;
-                               brkpnt = htod(lbuff);
-                               brk = true;
-                               cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
-                       }
-                       else
-                       {
-                               brk = false;
-                               cout << "Breakpoint cleared" << endl;
-                       }
+                       // Gay, but what are ya gonna do?
+                       // There's better ways, such as keeping track of when slave writes to master, etc...
+                       Execute6809(&cpu1, 40);
+                       Execute6809(&cpu2, 40);
+
+                       // MCU runs at 1,536,000 Hz
+                       // 1536000 / 60 / 640 == 40
+                       Execute63701(&mcu, 40);
                }
-               else if (lbuff[0] == 'a')  // Set/clear breakpoint #2
-               {
-                       if (lbuff[1] != 0)
-                       {
-                               lbuff[0] = 32;
-                               brkpnt2 = htod(lbuff);
-                               brk2 = true;
-                               cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
-                       }
-                       else
-                       {
-                               brk2 = false;
-                               cout << "Breakpoint cleared" << endl;
-                       }
-               }
-               else if (lbuff[0] == 'i')  // Inspect registers
-               {
-                       printf("CPU1: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
-                                       cpu1.a, cpu1.b, cpu1.cc, cpu1.dp, cpu1.x, cpu1.y, cpu1.s, cpu1.u, cpu1.pc);
-                       cout << " iclk=" << dec << cpu1.clock << endl;
-                       printf("CPU2: A=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X",
-                                       cpu2.a, cpu2.b, cpu2.cc, cpu2.dp, cpu2.x, cpu2.y, cpu2.s, cpu2.u, cpu2.pc);
-                       cout << " iclk=" << dec << cpu2.clock << endl;
-
-                       if (brk)
-                               cout << "Breakpoint #1 set at " << hex << brkpnt << dec << endl;
-
-                       if (brk2)
-                               cout << "Breakpoint #2 set at " << hex << brkpnt2 << dec << endl;
-               }
-               else if (strncmp(lbuff, "swap", 4) == 0)  // Swap ROMs
-               {
-                       looking_at_rom = !looking_at_rom;
-                       cout << "Swapped:  Looking at ";
-                       (looking_at_rom ? cout << "ROM #1" : cout << "ROM #2");
-                       cout << endl;
-               }
-               else if (strncmp(lbuff, "seek", 4) == 0)  // Seek non-zero bytes in RAM
-               {
 
-                       if (lbuff[4] != 0)
-                       {
-                               for(int i=0; i<4; i++)
-                               lbuff[i] = 32;
-                               dpc = htod(lbuff);
-                       }
-
-                       do
-                       {
-                               x = gram1[dpc++];
-                       }
-                       while ((x == 0) && (dpc != 0xFFFF)); // Keep going until something found
-                       dpc--;
-
-                       printf("%04X: ", dpc);       // Show data found...
-
-                       for(int i=0; i<16; i++)
-                               printf("%02X ", gram1[(uint16_t)(dpc+i)]);
-
-                       cout << " ";
-
-                       for(int i=0; i<16; i++)
-                       {
-                               uint8_t a = gram1[dpc++];
-
-                               if (a<10)
-                                       cout << (char)(a+48);
-                               if ((a>9) && (a<37))
-                                       cout << (char)(a+55);
-                               if (a>36)
-                                       cout << ".";
-                       }
-
-                       cout << endl;
-               }
-               else if (lbuff[0] == 'v')    // View screen
-               {
-                       BlitChar(screen, chr_rom, gram1);
-                       getch();
-               }
+               // Speed throttling happens here...
+               // Actually, it's 16.66... Need to account for that somehow
+               while (SDL_GetTicks() - oldTicks < 16)
+                       SDL_Delay(1);                           // Release our timeslice...
 
-               if (lbuff[0] == 'q')
-                       active = false; //break;  // Quit
+               oldTicks = SDL_GetTicks();
        }
 
-       SDL_Quit();                                                                     // Shut down SDL
-
-       for(int i=0; i<16; i++)
-               if (psg_adrs[i])
-                       delete[] psg_adrs[i];                           // Deallocate if loaded
-
-       for(int i=0; i<14; i++)
-               if (fm_adrs[i])
-                       delete[] fm_adrs[i];                            // Deallocate if loaded
-
+       SDL_Quit();
        LogDone();
 
        return 1;
 }
 
 #if 0
+/*
 Hitachi uC runs at 6.144 MHz
 YM2151 runs at 3.579580 MHz
 
@@ -1827,24 +1107,16 @@ Address             Dir Data     Name      Description
 
 Notes:
 -----
-- we are using an unusually high CPU interleave factor (800) to avoid hangs
-  in rthunder. The two 6809 in this game synchronize using a semaphore at
-  5606/5607 (CPU1) 1606/1607 (CPU2). CPU1 clears 5606, does some quick things,
-  and then increments 5606. While it does its quick things (which require
-  about 40 clock cycles) it expects CPU2 to clear 5607.
-  Raising the interleave factor to 1000 makes wndrmomo crash during attract
-  mode. I haven't investigated on the cause.
-
 - There are two watchdogs, one per CPU (or maybe three). Handling them
   separately is necessary to allow entering service mode without manually
   resetting in rthunder and genpeitd: only one of the CPUs stops writing to
   the watchdog.
 
 - The sprite hardware buffers spriteram: the program writes the sprite list to
-  offsets 4-9 of every 16-byte block, then at the end writes to offset 0x1ff2 of
-  sprite RAM to signal the chip that the list is complete. The chip will copy
-  the list from 4-9 to 10-15 and use it from there. This has not been verified
-  on the real hardware, but it is the most logical way of doing it.
+  offsets 4-9 of every 16-byte block, then at the end writes to offset 0x1ff2
+  of sprite RAM to signal the chip that the list is complete. The chip will
+  copy the list from 4-9 to 10-15 and use it from there. This has not been
+  verified on the real hardware, but it is the most logical way of doing it.
   Emulating this behaviour and not using an external buffer is important in
   rthunder: when you insert a coin, the whole sprite RAM is cleared, but 0x1ff2
   is not written to. If we buffered spriteram to an external buffer, this would
@@ -1863,6 +1135,6 @@ TODO:
   but they don't seem to work as expected. During the first few frames they are
   written out of order and hooking them up in the usual way causes the MCU to
   stop receiving interrupts.
-
+*/
 #endif