//
-// 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 <SDL2/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;
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?
-//kludge, for now
-//static uint8_t keys[0x1000]; // 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 1
-if (((addr >= 0x4180) && (addr <= 0x4191)) || (addr == 0x4380))
- printf("WriteMem: CPU #1 writing $%02X to $%04X...\n", b, addr);
+#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 1
-if (((addr >= 0x0180) && (addr <= 0x0191)) || (addr == 0x0380))
- printf("WriteMem: CPU #2 writing $%02X to $%04X...\n", b, addr);
-#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)
- {
- 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
+ else if (((address >= 0x4000) && (address <= 0xBFFF))
+ || (address >= 0xF000))
+ return;
+ else if ((address >= 0x1000) && (address <= 0x113F))
+// else if ((address >= 0x1000) && (address <= 0x11FF))
{
- 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)
{
-#if 0
- ifstream ff;
- char ch;
-
- ff.open(filename, ios::binary | ios::in);
-
- if (ff)
- {
- // Read it in...
- for(long i=0; i<32768; i++)
- {
- ff.get(ch);
- grom[address+i] = ch;
- }
+ return 0xFF;
+}
- ff.close();
- }
- return ff;
-#else
- FILE * file = fopen(filename, "rb");
-
- if (!file)
- return false;
+void V63701WritePort1(uint8_t data)
+{
+// printf("V63701WritePort1: Wrote $%02X...\n", data);
+}
- fread(&grom[address], 1, 0x8000, file);
- return true;
-#endif
+void V63701WritePort2(uint8_t data)
+{
+// printf("V63701WritePort2: Wrote $%02X...\n", data);
}
//
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)
- {
- for(uint32_t i=0; i<length; i++) // Read it in...
- {
- ff.get(ch);
- mem[address+i] = ch;
- }
+ if (!file)
+ return false;
- ff.close(); // Close 'da file...
- }
+ fread(&mem[address], 1, length, file);
+ fclose(file);
- return ff;
+ return true;
}
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
ff2.open("./ROMs/"PROM2, ios::binary | ios::in);
// If open was successful...
- if (ff1)
+ if (ff1 && ff2)
{
// Palette is 12-bit RGB, we stretch it to 24-bit
for(int i=0; i<256; i++)
{
char c1, c2;
- uint8_t r, g, b;
ff1.get(c1);
ff2.get(c2);
- r = (uint8_t)c1 & 0x0F;
- g = (uint8_t)c1 >> 4;
- b = (uint8_t)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;
}
}
// 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
+ // 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
return ff1;
}
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
+ // Skip intermediate data
+ file.ignore(len + 4);
}
- file.get(ch); len = (int)(uint8_t)ch; // & finally get length of data
+ // & finally get length of data
+ 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;
}
+#if 0
//
// Load PSG samples from disk
//
}
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);
}
}
}
}
+#endif
+FILE * psg1, * psg2;
//
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
+// bool active = true; // Program running flag
SDL_Event event; // SDL "event"
extern uint8_t palette[768]; // Screen physical palette
cout << endl << "THUNDER v"THUNDER_VERSION" ";
cout << "by James Hammons" << endl;
- cout << "Serial #20149404 / Prerelease" << endl;
+ cout << "Serial #20149417 / 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;
-#if 0
- cout << "Initializing SDL..." << endl;
-
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
- {
- cout << "Couldn't initialize SDL: " << SDL_GetError() << endl;
- return -1;
- }
-#endif
-
// 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
-#if 0
- for(long i=0; i<0x10000; i++)
- {
- gram[i] = 0; grom[i] = 0; // Zero out memory
- gram2[i] = 0; grom2[i] = 0;
- }
-#else
memset(gram, 0, 0x10000);
memset(grom, 0, 0x10000);
memset(gram2, 0, 0x10000);
memset(grom2, 0, 0x10000);
-#endif
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;
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(ROM3, grom3, 0, 0x8000)) // Load 3rd ROM into its own space
{ cout << "Could not open file '" << ROM3 << "'!" << endl; return -1; }
- if (!LoadImg(ROM4, grom4, 0, 0x8000)) // Load 4rd ROM into its own space
- { cout << "Could not open file '" << ROM4 << "'!" << endl; return -1; }
-
if (!LoadImg(ROM17, data_rom, 0, 0x10000)) // Load 17th ROM
{ cout << "Could not open file '" << ROM17 << "'!" << endl; return -1; }
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++;
- }//*/
+ // Load MCU program + data
+ if (!LoadImg(MCUROM, mcuMem, 0xF000, 0x1000)) // Load MCU ROM
+ { cout << "Could not open file '" << MCUROM << "'!" << endl; return -1; }
+
+ if (!LoadImg(ROM4, mcuMem, 0x4000, 0x8000)) // Load 4th ROM
+ { cout << "Could not open file '" << ROM4 << "'!" << endl; return -1; }
+
+// Now emulated! :-D
+ // Load PSG samples if they're there...
+// LoadPSGs();
// Set up V6809 execution contexts
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;
-
- 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
+// uint32_t my_clock = 0;
+ running = true; // Set running status...
+// trace1 = false;
+// SetRefreshRate(refresh2); // Tell GUI our refresh rate
+ // Set all inputs to inactive...
+ input1.byte = input2.byte = input3.byte = input4.byte = input5.byte = 0xFF;
+// mcu.port1 = 0xFF;
+// mcu.port2 = 0xFF;
#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);
- }
+ // 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
-#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
- }
+ banksw1 = 0; // Will this work?
+ banksw2 = 0;
+ InitGUI(); // Reset # of coins
WriteLog("About to set up screen...\n");
-#if 0
- 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;
- }
-#else
- InitVideo();
-#endif
-
-#if 0
- SDL_Color colors[256];
+ InitVideo();
- 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];
- }
-
- SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256);
-#endif
+ oldTicks = SDL_GetTicks();
-#if 0
- for(int i=0; i<256; i++)
- keys[i] = 0; // Clear keyboard buffer...
-#endif
+WriteLog("About to set up audio...\n");
+ InitSound();
- oldTicks = SDL_GetTicks();
+memset(scrBuffer, 0xFF, VIRTUAL_SCREEN_WIDTH*VIRTUAL_SCREEN_HEIGHT*sizeof(uint32_t));
+RenderScreenBuffer();
-WriteLog("About to set up audio...\n");
#if 1
- // 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_PauseAudio(0); // Get that audio going!
+psg1 = fopen("psgchan1.raw", "wb");
+psg2 = fopen("psgchan3.raw", "wb");
#endif
-memset(scrBuffer, 0xFF, VIRTUAL_SCREEN_WIDTH*VIRTUAL_SCREEN_HEIGHT*sizeof(uint32_t));
-RenderScreenBuffer();
WriteLog("About to enter main loop...\n");
- while (running)
- {
- HandleGUIDebounce(); // Debounce GUI keys
+ while (running)
+ {
+ HandleGUIDebounce(); // Debounce GUI keys
- if (game_over_switch)
- {
- game_over_switch--; // Countdown...
+#if 0
+ if (game_over_switch)
+ {
+ game_over_switch--; // Countdown...
- if (game_over_switch == 0)
- gram1[0x4380] = 0; // Kill music!
- }
+ if (game_over_switch == 0)
+ gram1[0x4380] = 0; // Kill music!
+ }
+#endif
+
+// Dipswitches are presented to the main CPUs as 0 or 1 at locations
+// $423D - $425B by the MCU
//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;
-
- // SDL key handling...
-
-// SDL_PumpEvents(); // Force key events into the buffer.
- SDL_Event event;
-
- while (SDL_PollEvent(&event))
+ //gram1[0x423D] = self_test; // Reset DSW1-1
+// gram1[0x4268] = 0; // Reset Video test
+
+ // SDL key handling...
+
+ SDL_Event event;
+
+ while (SDL_PollEvent(&event))
+ {
+ switch (event.type)
+ {
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_ESCAPE)
+ running = false;
+ // Do PCX snapshot (F4)
+ else if (event.key.keysym.sym == SDLK_F4)
{
- switch (event.type)
- {
- case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_ESCAPE)
- running = false;
- else if (event.key.keysym.sym == SDLK_F10)
- gram1[0x41A5]++; // Coin? (F10)
- else if (event.key.keysym.sym == SDLK_c)
- gram1[0x418C]++; // ? (C) Start
- }
+// SpawnSound(USERSOUND, SCAMERA);
+ SavePCXSnapshot();
+// debounce = 10;
}
+#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
+
+ 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
+
+ break;
+ }
+ }
#if 0
if (keys[SDLK_ESCAPE])
#endif
#endif
- if (enable_cpu)
+ 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
// 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<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
- {
- 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;
- }
- }
- 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 << ".";
+ // 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);
}
+ } // END: enable_cpu
- cout << endl;
- }
- else if (lbuff[0] == 'v') // View screen
- {
- BlitChar(screen, chr_rom, gram1);
- getch();
- }
+ // 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...
- if (lbuff[0] == 'q')
- active = false; //break; // Quit
+ oldTicks = SDL_GetTicks();
+//cout << "Finished frame..." << endl;
}
- SDL_Quit(); // Shut down SDL
+ SDL_Quit();
+#if 1
+fclose(psg1);
+fclose(psg2);
+#endif
+#if 0
+ // Deallocate sounds if they were loaded
for(int i=0; i<16; i++)
if (psg_adrs[i])
- delete[] psg_adrs[i]; // Deallocate if loaded
-
+ delete[] psg_adrs[i];
+#endif
+#if 0
for(int i=0; i<14; i++)
if (fm_adrs[i])
- delete[] fm_adrs[i]; // Deallocate if loaded
+ delete[] fm_adrs[i];
+#endif
LogDone();