]> Shamusworld >> Repos - thunder/blobdiff - src/thunder.cpp
Added MCU to execution loop and it works.
[thunder] / src / thunder.cpp
index 09cc40f147fc6d3446369075fa5e7c58356fa512..521980578b027f8d9720e89cf9dd504a548f0d34 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
@@ -16,6 +16,7 @@
 
 #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 <curses.h>                  // For getch()
 #include <time.h>
-#include <SDL2/SDL.h>
-#include "v6809.h"
-#include "screen.h"
 #include "gui.h"
 #include "log.h"
+#include "screen.h"
+#include "sound.h"
+#include "v63701.h"
+#include "v6809.h"
 #include "video.h"
 
 using namespace std;
@@ -74,8 +75,10 @@ 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
+uint8_t mcuMem[0x10000];               // 64K for MCU
 
 V6809REGS cpu1, cpu2;
+V63701REGS mcu;
 
 bool trace1 = false;                   // ditto...
 bool looking_at_rom = true;            // true = R1, false = R2
@@ -92,9 +95,9 @@ 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 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];
 
@@ -113,6 +116,10 @@ uint8_t RdMem(uint16_t addr)
 
        if (addr < 0x8000)
        {
+               // Memory shared with MCU (CPU #1 only! CPU #2 does not)
+               if ((addr >= 0x4000) && (addr <= 0x43FF))
+                       return mcuMem[addr - 0x3000];
+
                if (addr > 0x5FFF)
                        b = data_rom[banksw1 + (addr - 0x6000)];        // Get char data
                else
@@ -151,14 +158,22 @@ if (((addr >= 0x4180) && (addr <= 0x4191)) || (addr == 0x4380))
                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 0
        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
+#endif
+//     if (addr < 0x423D || addr > 0x425C)                                     // Protect writes to DSWs
+
+       // Memory shared with MCU (CPU #1 only! CPU #2 does not)
+       if ((addr >= 0x4000) && (addr <= 0x43FF))
+               mcuMem[addr - 0x3000] = b;
+       else
                gram1[addr] = b;
+
        if (addr == 0x8800)
                charbase = false;                                                               // Char banksw1
        if (addr == 0x8C00)
@@ -195,7 +210,7 @@ uint8_t RdMemB(uint16_t addr)
                if (addr > 0x1FFF && addr < 0x6000)
                        b = gram1[addr - 0x2000];
                if (addr > 0x5FFF)
-                       b = grom3[banksw2 + (addr - 0x6000)];           // Correct?
+                       b = grom3[banksw2 + (addr - 0x6000)];
        }
        else
                b = grom2[addr];
@@ -223,28 +238,32 @@ if (((addr >= 0x0180) && (addr <= 0x0191)) || (addr == 0x0380))
        printf("WriteMem: CPU #2 writing $%02X to $%04X...\n", b, addr);
 #endif
 
+#if 0
        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
+#endif
        if (addr == 0xD803)
                banksw2 = (uint32_t)(b & 0x03) << 13;                           // Set sprite data bank switch
+#if 0
        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
+#endif
+//     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 > 0x5FFF)
+//                     gram1[addr] = b;
        }
        if (addr == 0x8800)
        {
@@ -258,6 +277,83 @@ if (((addr >= 0x0180) && (addr <= 0x0191)) || (addr == 0x0380))
 }
 
 
+uint8_t MCUReadMemory(uint16_t address)
+{
+#if 1
+       if (address < 0x20)
+       {
+//             printf("V63701 read $%02X from $%02X...\n", memory[address], address);
+               return InternalRegisterRead(address);
+       }
+#endif
+
+#if 0
+       // Translate local reads @ $1000-$13FF to $4000-$43FF in shared RAM
+       if ((address >= 0x1000) && (address <= 0x13FF))
+               return gram1[0x3000 + address];
+       else
+#endif
+               if ((address >= 0x2000) && (address <= 0x2001))
+       {
+               return 0;       //for now
+//             return YMReadReg(0);
+       }
+//     else if (address == 0x2020)
+//             return input_port_0_r(0);
+//     else if (address == 0x2021)
+//             return input_port_1_r(0);
+       // This is DSW1 & 2. All switch settings are active low.
+       else if (address == 0x2030)
+               return 0xFF;
+       else if (address == 0x2031)
+               return 0xFF;
+
+       return mcuMem[address];
+}
+
+
+void MCUWriteMemory(uint16_t address, uint8_t data)
+{
+       static uint8_t ymRegister;
+
+#if 1
+       if (address < 0x20)
+       {
+//             printf("V63701 wrote $%02X to $%02X...\n", data, address);
+               InternalRegisterWrite(address, data);
+               return;
+       }
+#endif
+
+#if 0
+       // Translate local reads @ $1000-$13FF to $4000-$43FF in shared RAM
+       if ((address >= 0x1000) && (address <= 0x13FF))
+       {
+               gram1[0x3000 + address] = data;
+               return;
+       }
+#endif
+
+       if (((address >= 0x4000) && (address <= 0xBFFF))
+               || (address >= 0xF000))
+               return;
+       else if (address == 0x2000)
+       {
+               ymRegister = data;
+               return;
+       }
+       else if (address == 0x2001)
+       {
+//printf("Writing $%02X to YM2151 register $%02X...\n", data, ymRegister);
+//             YMWriteReg(0, ymRegister, data);
+               return;
+       }
+
+       // RAM is from $0 - $3FFF, $C000 - $EFFF
+       mcuMem[address] = data;
+}
+
+
 //
 // Generic Load file into image space
 // (No error checking performed!  Responsibility of caller!)
@@ -334,12 +430,11 @@ bool ReadColorPROMs(void)
                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;
                }
 
@@ -348,8 +443,8 @@ bool ReadColorPROMs(void)
        }
 
        // 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;
 }
@@ -434,10 +529,12 @@ uint32_t GetWAVLength(fstream & file)
                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;
@@ -586,8 +683,8 @@ extern bool disasm; // From 'V6809.CPP'
        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(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; }
@@ -637,6 +734,13 @@ extern bool disasm;        // From 'V6809.CPP'
                return -1;
        }
 
+       // 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; }
+
        // Load samples if they're there...
        LoadPSGs();
        LoadFMs();
@@ -653,12 +757,17 @@ extern bool disasm;       // From 'V6809.CPP'
        cpu2.WrMem = WrMemB;
        cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
 
+       memset(&mcu, 0, sizeof(V63701REGS));
+       mcu.RdMem = MCUReadMemory;
+       mcu.WrMem = MCUWriteMemory;
+       mcu.cpuFlags |= V63701_ASSERT_LINE_RESET;
+
        uint32_t my_clock = 0;
        running = true;                                                         // Set running status...
        trace1 = false;
        SetRefreshRate(refresh2);                                       // Tell GUI our refresh rate
 
-#if 1
+#if 0
        // 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;
@@ -676,7 +785,7 @@ WriteLog("About to set up screen...\n");
        oldTicks = SDL_GetTicks();
 
 WriteLog("About to set up audio...\n");
-#if 1
+#if 0
        // This crap SHOULD be in sound.cpp (not yet created)...
        SDL_AudioSpec desired, obtained;
        desired.freq = 22050;
@@ -693,6 +802,8 @@ WriteLog("About to set up audio...\n");
        }
 
        SDL_PauseAudio(0);                                                      // Get that audio going!
+#else
+       InitSound();
 #endif
 
 memset(scrBuffer, 0xFF, VIRTUAL_SCREEN_WIDTH*VIRTUAL_SCREEN_HEIGHT*sizeof(uint32_t));
@@ -703,6 +814,7 @@ WriteLog("About to enter main loop...\n");
        {
                HandleGUIDebounce();                                    // Debounce GUI keys
 
+#if 0
                if (game_over_switch)
                {
                        game_over_switch--;  // Countdown...
@@ -710,20 +822,24 @@ WriteLog("About to enter main loop...\n");
                        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[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[0x427E] = 0;//  gram1[0x427F] = 0;
+//             gram1[0x4280] = 0;//  gram1[0x4281] = 0;
                //gram1[0x4276] = 0;
-               gram1[0x426A] = 0;
+//             gram1[0x426A] = 0;
                //gram1[0x4278] = 0;
-               gram1[0x426C] = 0;
-               gram1[0x4262] = 0;  gram1[0x4260] = 0;
+//             gram1[0x426C] = 0;
+//             gram1[0x4262] = 0;  gram1[0x4260] = 0;
                //gram1[0x4247] = 0;
 
                // SDL key handling...
@@ -737,6 +853,13 @@ WriteLog("About to enter main loop...\n");
                        case SDL_KEYDOWN:
                                if (event.key.keysym.sym == SDLK_ESCAPE)
                                        running = false;
+                               // Do PCX snapshot (F4)
+                               else if (event.key.keysym.sym == SDLK_F4)
+                               {
+//                                     SpawnSound(USERSOUND, SCAMERA);
+                                       SavePCXSnapshot();
+//                                     debounce = 10;
+                               }
                                else if (event.key.keysym.sym == SDLK_F10)
                                        gram1[0x41A5]++;                        // Coin? (F10)
                                else if (event.key.keysym.sym == SDLK_c)
@@ -1024,6 +1147,10 @@ WriteLog("About to enter main loop...\n");
                                // 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