]> Shamusworld >> Repos - thunder/commitdiff
Oops, forgot to pull first before the changes. :-P
authorShamus Hammons <jlhamm@acm.org>
Fri, 13 Jan 2023 17:35:16 +0000 (11:35 -0600)
committerShamus Hammons <jlhamm@acm.org>
Fri, 13 Jan 2023 17:35:16 +0000 (11:35 -0600)
Merge branch 'master' of http://shamusworld.gotdns.org/git/thunder

1  2 
makefile
src/gui.h
src/sound.cpp
src/thunder.cpp
src/video.h

diff --combined makefile
index 5f2d1b615e7c5735b7282edbc2d329257affb197,11b7da914562fae539cfc2944c05f8ba1bcabaed..722d9831a1222d9c7251bd0e3b2c6a6b1d271fa7
+++ b/makefile
@@@ -6,14 -6,15 +6,15 @@@
  # This software is licensed under the GPL v3 or later
  #
  
 -ifeq "$(OSTYPE)" "msys"                                                       # Win32
 +ifeq "$(OSTYPE)" "msys"       # Win32
  
  SYSTYPE    = __GCCWIN32__
  EXESUFFIX  = .exe
  GLLIB      = -lopengl32
  ICON       = obj/icon.o
- SDLLIBTYPE = --libs
+ SDLLIBTYPE = --static-libs
  MSG        = Win32 on MinGW
+ EXTRA      = -static
  
  else
  #ifeq "$(OSTYPE)" "darwin"
@@@ -51,7 -52,7 +52,7 @@@ CPPFLAGS = -MMD -Wall -Wno-switch -Wno-
  LDFLAGS =
  
  # Ugh, let's get rid of the ref to -lcurses [DONE]
- LIBS = `sdl2-config $(SDLLIBTYPE)` -lstdc++ -lz -lm $(GLLIB)
+ LIBS = `sdl2-config $(SDLLIBTYPE)` -lstdc++ -lz -lm $(GLLIB) $(EXTRA)
  
  INCS = -I. -Isrc
  
@@@ -81,7 -82,7 +82,7 @@@ all: checkenv message obj $(TARGET)$(EX
  checkenv:
        @echo
        @echo -en "\033[01;33m***\033[00;32m Checking compilation environment... \033[00m"
- ifeq "" "$(shell which sdl-config)"
+ ifeq "" "$(shell which sdl2-config)"
        @echo
        @echo
        @echo -e "\033[01;33mIt seems that you don't have the SDL development libraries installed.
diff --combined src/gui.h
index 6dfb03f72270113d17a3c526f2e56eb667255f6b,bc3ed2e6613136865be669073a80a80d0e7c18ce..4a472c9d476a4ce8b213c50a2ff683597d7f930c
+++ b/src/gui.h
@@@ -4,11 -4,12 +4,11 @@@
  // by James Hammmons
  // (C) 1998, 2014 Underground Software
  //
 -
  #ifndef __GUI_H__
  #define __GUI_H__
  
  #include <stdint.h>
- #include <SDL2/SDL.h>
+ #include <SDL.h>
  
  // Message macros
  
diff --combined src/sound.cpp
index f2af13a3a07ba5bca5a2a5749847493a67a626cb,8d87ad9ea12b14f086df6be0e6ca16a045859219..27d7a3903b04246fee8c97e76b465f8071a4d040
  //
  
  #include "sound.h"
- #include <SDL2/SDL.h>
+ #include <SDL.h>
  #include "psg.h"
  #include "resource.h"
  #include "ym2151.h"
  
 -
 -#define SAMPLE_RATE 48000
 +#define SAMPLE_RATE  48000
 +#define BUFFER_SIZE  512
  
  // Function prototypes
  void SoundFunc(void *, Uint8 *, int);
  extern uint8_t voice_rom[];                   // PCM data pointer
  
  static bool soundInitialized = false;
 -const float sampleBase = (float)SAMPLE_RATE/6000.0;  // Voice is between 5512.5 and 6000 Hz
 -bool snd_go = false;
 -bool chan1_go = false, chan2_go = false;//, chan3_go = false;
 -bool /*chan4_go = false, chan5_go = false,*/ chan6_go = false;
 -uint8_t * sndp1, * sndp2, /* sndp3, * sndp4, * sndp5,*/ * sndp6;
 -uint32_t rom_pos, end_pos;
 +const float sampleBase = (float)SAMPLE_RATE / 6000.0;  // Voice is between 5512.5 and 6000 Hz
 +bool chan1_go = false, chan2_go = false;
 +bool chan6_go = false;
 +uint8_t * sndp1, * sndp2, * sndp6;
  uint32_t spos1, end_pos1;
  uint32_t spos2, end_pos2;
 -//uint32_t spos3, end_pos3;
 -//uint32_t spos4, end_pos4;
 -//uint32_t spos5, end_pos5;
  uint32_t spos6, end_pos6;
 -float sample1;
 -int16_t prevSamp1;
 -//int8_t delta_x1;
 -float sample2;
 -int16_t prevSamp2;
 -//int8_t delta_x2;
 +float sample1, sample2;
 +int16_t prevSamp1, prevSamp2;
  uint16_t snd_num;
 -uint8_t * snd_array[3] = { sunknown, scya, scamera }; // From RESOURCE.H
 +// From RESOURCE.H
 +uint8_t * snd_array[3] = { sunknown, scya, scamera };
  uint32_t snd_lens[3]   = { sunknownlen, scyalen, scameralen };
  
 -
  void InitSound(void)
  {
        // params 1, 4 & 5 are useless
 -//    if (YMInit(1, 3579580, 22050, 16, 512))//, (SAMPLE **)sbp))
 -      if (YMInit(1, 3579580, SAMPLE_RATE, 16, 512))
 +//    if (YMInit(1, 3579580, SAMPLE_RATE, 16, 512))
 +      if (YMInit(3579580, SAMPLE_RATE))
        {
                printf("SOUND: Could not init YM2151 emulator!\n");
 -              return;// -1;
 +              return;
        }
  
        InitPSG(SAMPLE_RATE);
        desired.freq = SAMPLE_RATE;
        desired.format = AUDIO_S16;
        desired.channels = 1;
 -      desired.samples = 1024;
 +      desired.samples = BUFFER_SIZE * 2;      // Size is in BYTES, so x2
        desired.callback = SoundFunc;
        desired.userdata = NULL;
  
 -      // Also, should check to see if it got the hardware it needed, correct sample size, etc.
 +      // Also, should check to see if it got the hardware it needed, correct sample size, etc. (actually, SDL guarantees we get what we asked for--I think)
        if (SDL_OpenAudio(&desired, &obtained) < 0)
        {
                soundInitialized = false;
        soundInitialized = true;
  }
  
 -
  void SpawnSound(int type, int snd, int channel/* = 0*/)
  {
 -//    extern uint32_t psg_lens[16];
 -//    extern uint8_t * psg_adrs[16];
 -//    extern uint32_t voc_lens[32];
 -//    extern uint8_t * voc_adrs[32];
 -//    extern uint32_t fm_lens[14];
 -//    extern uint8_t * fm_adrs[14];
 -
        if (!soundInitialized)
                return;
  
        snd_num = snd;
 -//    SpawnMsg(MSHOWNUMS);
  
        // Voice type sounds...
        if (type == GAMESOUND)
                        chan2_go = true;
                }
        }
 -#if 0
 -      else if (type == PSGSOUND)
 -      {
 -              if (snd_num & 0x10)                                                             // Second channel?
 -              {
 -                      spos3 = 0;
 -                      end_pos3 = psg_lens[snd_num & 0x0F];
 -                      sndp3 = psg_adrs[snd_num & 0x0F];
 -                      chan3_go = true;
 -
 -                      if (spos3 == end_pos3)
 -                              chan3_go = false;                                               // No sound loaded, so don't do it!
 -              }
 -              else                                                                                    // First channel
 -              {
 -                      spos4 = 0;
 -                      end_pos4 = psg_lens[snd_num & 0x0F];
 -                      sndp4 = psg_adrs[snd_num & 0x0F];
 -                      chan4_go = true;
 -
 -                      if (spos4 == end_pos4)
 -                              chan4_go = false;                                               // No sound loaded, so don't do it!
 -              }
 -      }
 -#endif
 -#if 0
 -      else if (type == FMSOUND)
 -      {
 -              spos5 = 0;
 -              end_pos5 = fm_lens[snd_num];
 -              sndp5 = fm_adrs[snd_num];
 -              chan5_go = true;
 -
 -              if (spos5 == end_pos5)
 -                      chan5_go = false;                                                       // No sound loaded, so don't do it!
 -      }
 -#endif
        else if (type == USERSOUND)
        {
                spos6 = 0;
        }
  }
  
 -
  void SoundFunc(void * userdata, Uint8 * buffer, int num)
  {
 -      static bool psg1go = false, psg2go = false;
 -      // Length / 2 is because it's set up for 16-bit samples
 -//    YM2151UpdateOne(buffer, length / 2);
 -      // Have to go into ym2151.cpp and change this manually back to 8 bit
 +      // We do num / 2 because num is in BYTES, and the buffer uses signed WORDs.
        YM2151UpdateOne(buffer, num / 2);
 -//    return;
        UpdatePSG(buffer, num / 2);
  
        // 0-22 different sounds...
 -      uint16_t cnt = 0;//, sample;
 +      uint16_t cnt = 0;
        uint8_t start_samp1, end_samp1, start_samp2, end_samp2;
        int16_t samp1 = 0, samp2 = 0, samp6 = 0;                        // Zero samples...
  
 -      if (!(chan1_go || chan2_go /*|| chan3_go || chan4_go || chan5_go*/ || chan6_go))
 +      if (!(chan1_go || chan2_go || chan6_go))
                return;
  
        while (cnt != (num / 2))
                        {
                                uint8_t voiceSample = voice_rom[spos2++];
                                samp2 = ((int16_t)voiceSample - 128) * 160;
 -//                            samp2 = voice_rom[spos2++];
  
                                if (voiceSample == 0xFF)
                                {
                        sample2 -= 1.0;
                }
  
 -#if 0
 -              if (chan3_go)
 -              {
 -                      samp3 = ((psg1go ? sndp3[spos3++] : sndp3[spos3]) - 128) * 160;
 -                      psg1go = !psg1go;
 -
 -                      if (spos3 == end_pos3)
 -                      {
 -                              chan3_go = false;
 -                              samp3 = 0; // Kill channel 3 if done...
 -                      }
 -              }
 -
 -              if (chan4_go)
 -              {
 -                      samp4 = ((psg2go ? sndp4[spos4++] : sndp4[spos4]) - 128) * 160;
 -                      psg2go = !psg2go;
 -
 -                      if (spos4 == end_pos4)
 -                      {
 -                              chan4_go = false;
 -                              samp4 = 0; // Kill channel 4 if done...
 -                      }
 -              }
 -
 -              if (chan5_go)
 -              {
 -                      samp5 = sndp5[spos5++];
 -
 -                      if (spos5 == end_pos5)
 -                      {
 -                              chan5_go = false;
 -                              samp5 = 128; // Kill channel 5 if done...
 -                      }
 -              }
 -#endif
                if (chan6_go)
                {
                        samp6 = sndp6[spos6++];
                }
  
                // Mix 'em...
 -//            sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640;
                int32_t sample = samp1 + samp2 + samp6;
                sample += ((int16_t *)buffer)[cnt];
  
                // If it overflowed, clip it
 -//            if (sample & 0xFFFF0000)
 -//                    sample = (sample & 0x8000 ? 0x00 : 0xFF);
 -//                    sample = (sample & 0x80000000 ? 0x0000 : 0xFFFF);
                if (sample > 32767)
                        sample = 32767;
                else if (sample < -32767)
                ((int16_t *)buffer)[cnt++] = (int16_t)sample;
        }
  }
 -
diff --combined src/thunder.cpp
index 2914a96c5ae80eab26a7347e3e388609e6aa77ca,f53dd689ce541f235d9dbac35bde9cf5323efc62..9a06f3f60183ee9dd6024d7072a2bc36065f93dd
@@@ -2,7 -2,7 +2,7 @@@
  // Thunder: A Rolling Thunder Emulator
  //
  // by James Hammons
 -// (C) 2004, 2014 Underground Software
 +// (C) 2004, 2023 Underground Software
  //
  // JLH = James Hammons <jlhamm@acm.org>
  //
  // 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
 +// JLH  01/13/2023  Finally fixed the sprite lag problem  :-D
  //
  
 -#define THUNDER_VERSION               "1.2.0"
 +#define THUNDER_VERSION               "1.2.1"
  
- #include <SDL2/SDL.h>
+ #include <SDL.h>
  #include <string>
  #include <stdio.h>
  #include <stdlib.h>
@@@ -33,6 -32,7 +33,6 @@@
  #include "video.h"
  #include "ym2151.h"
  
 -
  #define ROM1   "rt3-1b.9c"
  #define ROM2   "rt3-2b.12c"
  #define ROM3   "rt3-3.12d"
@@@ -62,6 -62,7 +62,6 @@@
  #define PROM5  "mb7112e.6u"
  #define MCUROM "rt1-mcu.bin"
  
 -
  // Global defines
  
  uint8_t gram1[0x10000], grom1[0x10000], grom2[0x10000];
@@@ -79,13 -80,11 +79,13 @@@ uint32_t banksw1, banksw2
  // MCU inputs
  Byte input1, input2, input3, input4, input5;
  
 +// Copy sprites flag
 +bool copySprites = false;
 +
  // Function prototypes
  uint8_t MCUReadMemory(uint16_t address);
  void MCUWriteMemory(uint16_t address, uint8_t data);
  
 -
  //
  // Read a byte from memory
  //
@@@ -108,11 -107,14 +108,11 @@@ uint8_t MainReadMemory(uint16_t addr
        return grom1[addr];
  }
  
 -
  //
  // Write a byte to memory
  //
  void MainWriteMemory(uint16_t address, uint8_t data)
  {
 -      extern bool disasm;
 -
        if (address == 0x6000)
                SpawnSound(GAMESOUND, gram1[0x6200], 0);        // Do voice chan 1
        if (address == 0x6400)
                gram1[address] = data;
  
        if (address == 0x5FF2)
 -              CopySprites();
 +              copySprites = true;
        if (address == 0x8800)
                charBankSwitch = false;         // Char banksw1
        if (address == 0x8C00)
                charBankSwitch = true;          // Char banksw2
 -      if (address == 0x8400)          // Frame go strobe? VBlank acknowledge?
 -      {
 -//            BlitChar(charROM, gram1);
 -
 -              // IRQ Ack (may also be frame go...)
 -              ClearLineOfCurrentV6809(V6809_ASSERT_LINE_IRQ);
 -#if 1
 -      if (disasm)
 -              WriteLog("WriteMem: CPU #1 Acknowledging IRQ...\n", data);
 -#endif
 -      }
 +      if (address == 0x8400)                  // Frame go strobe? VBlank acknowledge?
 +              ClearLineOfCurrentV6809(V6809_LINE_IRQ); // IRQ Ack
  }
  
 -
  //
  // Read a byte from memory (2nd processor)
  //
@@@ -154,11 -166,14 +154,11 @@@ uint8_t SubReadMemory(uint16_t address
        return grom2[address];
  }
  
 -
  //
  // Write a byte to memory (2nd processor)
  //
  void SubWriteMemory(uint16_t address, uint8_t data)
  {
 -      extern bool disasm;
 -
        // Set sprite data bank switch
        if (address == 0xD803)
                banksw2 = (uint32_t)(data & 0x03) << 13;
                gram1[address - 0x2000] = data;
  
        if (address == 0x1FF2)
 -              CopySprites();
 +              copySprites = true;
  
        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", data);
 -#endif
 -      }
 +              ClearLineOfCurrentV6809(V6809_LINE_IRQ); // IRQ Ack
  }
  
 -
  uint8_t MCUReadMemory(uint16_t address)
  {
        if (address < 0x20)
        return mcuMem[address];
  }
  
 -
  void MCUWriteMemory(uint16_t address, uint8_t data)
  {
        static uint8_t ymRegister;
        mcuMem[address] = data;
  }
  
 -
  uint8_t V63701ReadPort1(void)
  {
  //    printf("V63701ReadPort1: Read $%02X...\n", input3.byte);
        return input3.byte;
  }
  
 -
  uint8_t V63701ReadPort2(void)
  {
        return 0xFF;
  }
  
 -
  void V63701WritePort1(uint8_t data)
  {
  //    printf("V63701WritePort1: Wrote $%02X...\n", data);
  }
  
 -
  void V63701WritePort2(uint8_t data)
  {
  //    printf("V63701WritePort2: Wrote $%02X...\n", data);
  }
  
 -
  //
  // Generic Load file into image space
  // (No error checking performed!  Responsibility of caller!)
@@@ -269,18 -298,19 +269,18 @@@ bool LoadImg(const char * filename, uin
                return false;
        }
  
 -      fread(&mem[address], 1, length, file);
 +      size_t ignored = fread(&mem[address], 1, length, file);
        fclose(file);
  
        return true;
  }
  
 -
  //
  // Read color PROMs
  //
  bool ReadColorPROMs(void)
  {
 -      FILE * file1 = fopen("./ROMs/"PROM3, "rb");
 +      FILE * file1 = fopen("./ROMs/" PROM3, "rb");
  
        if (file1)
        {
                fclose(file1);
        }
  
 -      file1 = fopen("./ROMs/"PROM4, "rb");
 +      file1 = fopen("./ROMs/" PROM4, "rb");
  
        if (file1)
        {
                fclose(file1);
        }
  
 -      file1 = fopen("./ROMs/"PROM1, "rb");
 -      FILE * file2 = fopen("./ROMs/"PROM2, "rb");
 +      file1 = fopen("./ROMs/" PROM1, "rb");
 +      FILE * file2 = fopen("./ROMs/" PROM2, "rb");
  
        // If open was successful...
        if (file1 && file2)
  
        // 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 
 +      // 10:  88 A8 C8 E8  8A AA CA EA  8C AC CC EC  8E AE CE EE
  
        if (!file1)
        {
        return true;
  }
  
 -
  //
  // Unpack font data
  //
  bool UnpackFonts(void)
  {
        // 0x4000 $800 chars
 -      FILE * file1 = fopen("./ROMs/"ROM7, "rb");
 -      FILE * file2 = fopen("./ROMs/"ROM8, "rb");
 +      FILE * file1 = fopen("./ROMs/" ROM7, "rb");
 +      FILE * file2 = fopen("./ROMs/" ROM8, "rb");
  
        if (!file1 || !file2)
        {
 -              printf("Could not open either "ROM7" or "ROM8"!\n");
 +              printf("Could not open either " ROM7 " or " ROM8 "!\n");
                return false;
        }
  
        fclose(file1);
        fclose(file2);
  
 -      file1 = fopen("./ROMs/"ROM5, "rb");
 -      file2 = fopen("./ROMs/"ROM6, "rb");
 +      file1 = fopen("./ROMs/" ROM5, "rb");
 +      file2 = fopen("./ROMs/" ROM6, "rb");
  
        if (!file1 || !file2)
        {
 -              printf("Could not open either "ROM5" or "ROM6"!\n");
 +              printf("Could not open either " ROM5 " or " ROM6 "!\n");
                return false;
        }
  
        return true;
  }
  
 -
  //
  // Main loop
  //
@@@ -412,14 -444,16 +412,14 @@@ int main(int argc, char * argv[]
  {
        InitLog("thunder.log");
  
 -      extern bool disasm;                             // From 'V6809.CPP'
 -
        bool running;                                   // CPU running state flag...
        SDL_Event event;                                // SDL "event"
        uint32_t ticks, oldTicks;
        uint8_t frameTickCount = 0;
  
 -      printf("THUNDER v"THUNDER_VERSION" by James Hammons\n");
 -      printf("Serial #20149417 / Prerelease\n");
 -      printf("© 2003, 2014 Underground Software\n\n");
 +      printf("THUNDER v" THUNDER_VERSION " by James Hammons\n");
 +      printf("Serial #20230113 / Prerelease\n");
 +      printf("© 2003, 2023 Underground Software\n\n");
        printf("This emulator is free software. If you paid for it you were RIPPED OFF\n\n");
  
  //    SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder");
        memset(&cpu1, 0, sizeof(V6809REGS));
        cpu1.RdMem = MainReadMemory;
        cpu1.WrMem = MainWriteMemory;
 -      cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET;
 +      cpu1.cpuFlags |= V6809_LINE_RESET;
  
        memset(&cpu2, 0, sizeof(V6809REGS));
        cpu2.RdMem = SubReadMemory;
        cpu2.WrMem = SubWriteMemory;
 -      cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET;
 +      cpu2.cpuFlags |= V6809_LINE_RESET;
  
        memset(&mcu, 0, sizeof(V63701REGS));
        mcu.RdMem = MCUReadMemory;
        mcu.WrMem = MCUWriteMemory;
 -      mcu.cpuFlags |= V63701_ASSERT_LINE_RESET;
 +      mcu.cpuFlags |= V63701_LINE_RESET;
  
        running = true;
  
        InitGUI();                 // Reset # of coins
  
        // Set up DIP switches...
 -      input4.bit.b0 = 1;              // DSW B-0: Contiues (1 = 6, 0 = 3)
 +      input4.bit.b0 = 1;              // DSW B-0: Continues (1 = 6, 0 = 3)
        input4.bit.b1 = 1;              // DSW B-2: ???
        input4.bit.b2 = 1;              // DSW B-4: Difficulty (1 = normal, 0 = easy)
        input4.bit.b3 = 1;              // DSW B-6: Bonus lives (70K/200K = 1, 100K/300K = 0)
@@@ -545,6 -579,9 +545,6 @@@ WriteLog("About to set up screen...\n")
  WriteLog("About to set up audio...\n");
        InitSound();
  
 -//memset(scrBuffer, 0xFF, VIRTUAL_SCREEN_WIDTH*VIRTUAL_SCREEN_HEIGHT*sizeof(uint32_t));
 -//RenderScreenBuffer();
 -
  WriteLog("About to enter main loop...\n");
        while (running)
        {
  // 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
 -
                // SDL key handling...
  
                SDL_Event event;
  #endif
  
                // 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;
 +              cpu1.cpuFlags |= V6809_LINE_IRQ;
 +              cpu2.cpuFlags |= V6809_LINE_IRQ;
 +              mcu.cpuFlags |= V63701_LINE_IRQ;
  //                                    while (cpu1.clock < 25000)
  // 1.538 MHz = 25633.333... cycles per frame (1/60 s)
  // 25600 cycles/frame
  // 40 works, until it doesn't... :-P
  // 640 * 40
  // 800 * 32
 +// 20 seems to work...  :-)
  // Interesting, putting IRQs at 30 Hz makes it run at the correct speed. Still hangs in the demo, though.
 -              for(int i=0; i<640; i++)
 +//            for(int i=0; i<640; i++)
 +              for(int 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);
 +//                    Execute6809(&cpu1, 40);
 +//                    Execute6809(&cpu2, 40);
 +                      Execute6809(&cpu1, 20);
 +                      Execute6809(&cpu2, 20);
  
                        // MCU runs at 1,536,000 Hz
                        // 1536000 / 60 / 640 == 40
 -                      Execute63701(&mcu, 40);
 +//                    Execute63701(&mcu, 40);
 +                      Execute63701(&mcu, 20);
                }
  
                BlitChar(charROM, gram1);
  
 +              // Make sure that the sprite RAM lags by one frame...  :-)
 +              if (copySprites)
 +              {
 +                      CopySprites();
 +                      copySprites = false;
 +              }
 +
                frameTickCount++;
  
                if (frameTickCount == 3)
  
        return 1;
  }
 -
 -#if 0
 -/*
 -Hitachi uC runs at 6.144 MHz
 -YM2151 runs at 3.579580 MHz
 -
 -
 -Rolling Thunder Memory map
 ---------------------------
 -Most of the decoding is done by custom chips (CUS47 and CUS41), so the memory
 -map is inferred by program behaviour. The customs also handle internally irq
 -and watchdog.
 -
 -The main CPU memory map is the same in all games because CUS47 is used by all
 -games. The sub CPU and sound CPU, on the other hand, change because CUS41 is
 -replaced by other chips.
 -
 -All RAM is shared between main and sub CPU, except for sound RAM which is
 -shared between main and sound CPU; the portion of object RAM that is overlapped
 -by sound RAM is used exclusively by the sub CPU.
 -
 -MAIN CPU:
 -
 -Address             Dir Data     Name      Description
 -------------------- --- -------- --------- -----------------------
 -000x xxxx xxxx xxxx R/W xxxxxxxx SCROLL0   tilemap 0/1 RAM (shared with sub CPU)
 -001x xxxx xxxx xxxx R/W xxxxxxxx SCROLL1   tilemap 2/3 RAM (shared with sub CPU)
 -0100 00xx xxxx xxxx R/W xxxxxxxx SOUND     sound RAM (through CUS30, shared with MCU)
 -0100 0000 xxxx xxxx R/W xxxxxxxx           portion holding the sound wave data
 -0100 0001 00xx xxxx R/W xxxxxxxx           portion holding the sound registers
 -010x xxxx xxxx xxxx R/W xxxxxxxx OBJECT    work RAM (shared with sub CPU) [1]
 -0101 1xxx xxxx xxxx R/W xxxxxxxx           portion holding sprite registers
 -011x xxxx xxxx xxxx R   xxxxxxxx ROM 9D    program ROM (banked) [2]
 -1xxx xxxx xxxx xxxx R   xxxxxxxx ROM 9C    program ROM
 -1000 00-- ---- ----   W --------           watchdog reset (RES generated by CUS47)
 -1000 01-- ---- ----   W --------           main CPU irq acknowledge (IRQ generated by CUS47)
 -1000 1x-- ---- ----   W -------- BANK      tile gfx bank select (data is in A10) (latch in CUS47)
 -1001 00-- ---- -x0x   W xxxxxxxx LATCH0    tilemap 0/1 X scroll + priority
 -1001 00-- ---- -x10   W xxxxxxxx LATCH0    tilemap 0/1 Y scroll
 -1001 00-- ---- --11   W ------xx BAMNKM    ROM 9D bank select
 -1001 01-- ---- -x0x   W xxxxxxxx LATCH1    tilemap 2/3 X scroll + priority
 -1001 01-- ---- -x10   W xxxxxxxx LATCH1    tilemap 2/3 Y scroll
 -1001 01-- ---- --11   W ------xx BAMNKS    ROM 12D bank select
 -1100 00-- ---- ----   W xxxxxxxx BACKCOLOR background color
 -
 -[1] Note that this is partially overlapped by sound RAM
 -[2] In Rolling Thunder and others, replaced by the ROM/voice expansion board
 -
 -
 -SUB CPU:
 -
 -Address             Dir Data     Name      Description
 -------------------- --- -------- --------- -----------------------
 -000x xxxx xxxx xxxx R/W xxxxxxxx SUBOBJ    work RAM (shared with main CPU)
 -0001 1xxx xxxx xxxx R/W xxxxxxxx           portion holding sprite registers
 -001x xxxx xxxx xxxx R/W xxxxxxxx SUBSCR0   tilemap 0/1 RAM (shared with main CPU)
 -010x xxxx xxxx xxxx R/W xxxxxxxx SUBSCR1   tilemap 2/3 RAM (shared with main CPU)
 -011x xxxx xxxx xxxx R   xxxxxxxx ROM 12D   program ROM (banked) [1]
 -1xxx xxxx xxxx xxxx R   xxxxxxxx ROM 12C   program ROM
 -1000 0--- ---- ----   W --------           watchdog reset (MRESET generated by CUS41)
 -1000 1--- ---- ----   W --------           main CPU irq acknowledge (generated by CUS41)
 -1101 0--- ---- -x0x   W xxxxxxxx LATCH0    tilemap 0/1 X scroll + priority
 -1101 0--- ---- -x10   W xxxxxxxx LATCH0    tilemap 0/1 Y scroll
 -1101 0--- ---- --11   W ------xx BAMNKM    ROM 9D bank select
 -1101 1--- ---- -x0x   W xxxxxxxx LATCH1    tilemap 2/3 X scroll + priority
 -1101 1--- ---- -x10   W xxxxxxxx LATCH1    tilemap 2/3 Y scroll
 -1101 1--- ---- --11   W ------xx BAMNKS    ROM 12D bank select
 -
 -[1] Only used by Rolling Thunder
 -
 -
 -MCU:
 -
 -Address             Dir Data     Name      Description
 -------------------- --- -------- --------- -----------------------
 -0000 0000 xxxx xxxx                        MCU internal registers, timers, ports and RAM
 -0001 xxxx xxxx xxxx R/W xxxxxxxx RAM 3F    sound RAM (through CUS30, partially shared with main CPU)
 -0001 0000 xxxx xxxx R/W xxxxxxxx           portion holding the sound wave data
 -0001 0001 00xx xxxx R/W xxxxxxxx           portion holding the sound registers
 -0010 0--- --00 ---x R/W xxxxxxxx YMCS      YM2151
 -0010 0--- --01 ----                        n.c.
 -0010 0--- --10 ---- R   xxxxxxxx PORTA     switch inputs
 -0010 0--- --11 ---- R   xxxxxxxx PORTB     dip switches
 -01xx xxxx xxxx xxxx R   xxxxxxxx ROM 6B    program ROM (lower half)
 -10xx xxxx xxxx xxxx R   xxxxxxxx ROM 6B    program ROM (upper half)
 -1011 0--- ---- ----   W                    unknown (CUS41)
 -1011 1--- ---- ----   W                    unknown (CUS41)
 -1111 xxxx xxxx xxxx R   xxxxxxxx           MCU internal ROM
 -
 -
 -Notes:
 ------
 -- 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.
 -  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
 -  cause dangling sprites because the buffer would not be updated.
 -
 -- spriteram buffering fixes sprite lag, but causes a glitch in rthunder when
 -  entering a door. The *closed* door is made of tiles, but the *moving* door is
 -  made of sprites. Since sprites are delayed by 1 frame, when you enter a door
 -  there is one frame where neither the tile-based closed door nor the
 -  sprite-based moving door is shown, so it flickers. This behavior has been
 -  confirmed on a real PCB.
 -
 -TODO:
 -----
 -- The two unknown writes for the MCU are probably watchdog reset and irq acknowledge,
 -  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
 -
diff --combined src/video.h
index acacc76945cb4946bdad148a6b012c29bb6efc0d,b3afeaf1b6580159019a4d941f6935a4cef82968..8d1847ec29a52227c5e7ee0fa579e81984e03943
@@@ -1,10 -1,11 +1,10 @@@
  //
  // VIDEO.H: Header file
  //
 -
  #ifndef __VIDEO_H__
  #define __VIDEO_H__
  
- #include <SDL2/SDL.h>
+ #include <SDL.h>
  #include <stdint.h>                                                   // For uint32_t
  
  #define VIRTUAL_SCREEN_WIDTH  288
@@@ -24,3 -25,4 +24,3 @@@ extern uint32_t scrBuffer[]
  //extern uint32_t mainScrBuffer[];
  
  #endif        // __VIDEO_H__
 -