]> Shamusworld >> Repos - stargem2/blobdiff - src/stargem2.cpp
More cleanup, chasing down problems with the demo mode
[stargem2] / src / stargem2.cpp
index 32248fcdd8d6bc854fe611d5f02c778a1c00e88a..8ad9c3632ab33e31a5e602b544beaeeb4aa6f22c 100755 (executable)
@@ -41,6 +41,14 @@ using namespace std;
 #define CMOS           "cmos.ram"
 #define SAVESTATE      "sg2.state"
 
+#define FRAME_DURATION_IN_CYCLES               (M6809_CLOCK_SPEED_IN_HZ / 60.0)
+#define SCANLINE_DURATION_IN_CYCLES            (FRAME_DURATION_IN_CYCLES / 256.0)
+// Interesting... This (1/16) causes the machine to crash in the demo (if run from clean start, otherwise it FUs demo)!
+// (1/32) fucks up the demo...
+// (1/64) works. Weird!
+//#define SG2_PIA_CALLBACK_DURATION            ((FRAME_DURATION_IN_CYCLES * M6809_CYCLE_IN_USEC) / 16.0)
+#define SG2_PIA_CALLBACK_DURATION              ((FRAME_DURATION_IN_CYCLES * M6809_CYCLE_IN_USEC) / 64.0)
+
 // Global variables
 
 uint8 gram[0x10000], grom[0x10000], sram[0x10000], srom[0x10000]; // RAM & ROM spaces
@@ -57,6 +65,17 @@ static uint32 startTicks;
 static uint8 * keys;                                                   // SDL raw keyboard matrix
 static uint64 clockFrameStart;                                 // V6809 clock at the start of the frame
 
+// Function prototypes
+
+uint8 RdMem6809(uint16 addr);
+void WrMem6809(uint16 addr, uint8 b);
+uint8 RdMem6808(uint16 addr);
+void WrMem6808(uint16 addr, uint8 b);
+bool LoadImg(const char * filename, uint8 * ram, int size);
+void SaveCMOS(void);
+bool LoadMachineState(void);
+void SaveMachineState(void);
+
 // Local timer callback functions
 
 static void FrameCallback(void);
@@ -64,152 +83,142 @@ static void ScanlineCallback(void);
 
 
 //
-// 6809 memory functions
+// Main loop
 //
-
-#ifdef LOG_PIA1_IO
-char piaRegsName[4][10] = { "PORTA", "PACTL", "PORTB", "PBCTL" };
-#endif
-uint8 RdMem6809(uint16 addr)
+int main(int /*argc*/, char * /*argv*/[])
 {
-       uint8 b;
+       InitLog("stargem2.log");
+       WriteLog("StarGem2 - A portable Stargate emulator by James L. Hammons\n");
+       WriteLog("(C) 2009 Underground Software\n\n");
 
-       if (addr >= 0x9000 && addr <= 0xCFFF)           // No ROM between $9000 - $CFFF...
-               b = gram[addr];
-       else
-       {
-               if (!gram[0xC900] && addr <= 0x8FFF)    // Check RAM $C900 bank switch
-                       b = gram[addr];
-               else
-                       b = grom[addr];
-       }
+       LoadSettings();
 
-       // A wee kludge (though I doubt it reads from anywhere other than $CB00)...
-       if ((addr & 0xFF00) == 0xCB00)
-#if 0
-               b = gram[0xCB00] & 0xFC;                                // Only bits 2-7 are connected...
+       // Initialize Williams' palette (RGB coded as: 3 bits red, 3 bits green, 2 bits blue)
+       for(uint32 i=0; i<256; i++)
+               palette[i] =
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+               (((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151) << 24)
+                       | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 16)
+                       | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 8) | 0xFF;
 #else
-       {
-//Interesting, this code ALSO fucks up the demo...
-//Except when the correct code is called in the scanline callback function...
-               uint32 elapsedCycles = (uint32)(GetCurrentV6809Clock() - clockFrameStart);
-               uint32 scanline = (uint32)(((double)elapsedCycles * M6809_CYCLE_IN_USEC) / 65.10416666666667);
-//Changes here don't seem to do much...
-//             uint32 scanline = (uint32)(((double)elapsedCycles * M6809_CYCLE_IN_USEC) / 70.0);
-               b = (uint8)scanline & 0xFC;                             // Only bits 2-7 are connected...
-       }
+               ((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151)
+                       | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 8)
+                       | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 16) | 0xFF000000;
 #endif
 
-       // More kludge...
-       if ((addr == 0xC80C) && (gram[0xC80D] & 0x04))  // Read PORTA and DDR is set to Output
-       {
-               ClearLine(V6809_ASSERT_LINE_IRQ);                       // Then clear the IRQ
-//OK, this ALSO fucks up the execution of the demo...
-//             mainCPU.cpuFlags &= ~V6809_ASSERT_LINE_IRQ;                     // Then clear the IRQ
-       }
+       // Zero out memory
+       memset(gram, 0, 0x10000);
+       memset(grom, 0, 0x10000);
+       memset(sram, 0, 0x10000);
+       memset(srom, 0, 0x10000);
 
-       if ((addr == 0xC80E) && (gram[0xC80F] & 0x04))  // Read PORTB and DDR is set to Output
-       {
-               ClearLine(V6809_ASSERT_LINE_IRQ);                       // Then clear the IRQ
-//OK, this ALSO fucks up the execution of the demo...
-//             mainCPU.cpuFlags &= ~V6809_ASSERT_LINE_IRQ;                     // Then clear the IRQ
-       }
+       // Set up V6809 & V6808 execution contexts
 
-//temp...
-/*extern uint16 pcr;
-//if (addr >= 0xC000 && addr <= 0xCBFF)
-if (addr == 0x9C59)
-       WriteLog("RdMem: Reading address %04X [=%02X, PC=%04X]\n", addr, b, pcr);//*/
-#ifdef LOG_PIA1_IO
-/*if (addr >= 0xC80C && addr <= 0xC80F)
-       WriteLog("V6809 RdMem: Reading PIA (%s) address %04X [<-%02X, PC=%04X]\n", piaRegsName[addr&0x03], addr, b, GetCurrentV6809PC());//*/
-#endif
-       return b;
-}
+       memset(&mainCPU, 0, sizeof(V6809REGS));
+       mainCPU.RdMem = RdMem6809;
+       mainCPU.WrMem = WrMem6809;
+       mainCPU.cpuFlags |= V6809_ASSERT_LINE_RESET;
 
-void WrMem6809(uint16 addr, uint8 b)
-{
-//temp...
-//extern V6809REGS regs;
-//if (addr >= 0xC800 && addr <= 0xCBFE)
-//if (addr == 0xC80F || addr == 0xC80D)
-//     WriteLog("WrMem: Writing address %04X with %02X [PC=%04X, $CB00=%02X]\n", addr, b, regs.pc, gram[0xCB00]);//*/
-//if (addr == 0xC80E)
-/*if (addr >= 0xC800 && addr <= 0xC80F)
-       WriteLog("V6809 WrMem: Writing address %04X with %02X [PC=%04X, $CB00=%02X]\n", addr, b, mainCPU.pc, gram[0xCB00]);//*/
+       memset(&soundCPU, 0, sizeof(V6808REGS));
+       soundCPU.RdMem = RdMem6808;
+       soundCPU.WrMem = WrMem6808;
+       soundCPU.cpuFlags |= V6808_ASSERT_LINE_RESET;
 
-       gram[addr] = b;
+       char ROMs[12][8] = {
+               "ROMs/01", "ROMs/02", "ROMs/03", "ROMs/04", "ROMs/05", "ROMs/06",
+               "ROMs/07", "ROMs/08", "ROMs/09", "ROMs/10", "ROMs/11", "ROMs/12"
+               };
 
-       if (addr >= 0x0006 && addr < 0x97F7)                    // 304 pixels  152-128=24-16=8
+       for(int i=0; i<12; i++)
        {
-               // NOTE: Screen was 304 x 256, but we truncate the vertical dimension here...
-               uint16 sx = (addr >> 7) & 0x01FE, sy = addr & 0x00FF;
+               uint32 baseAddress = i * 0x1000;
 
-               if (sy > 5 && sy < 246)
+               if (i > 8)
+                       baseAddress += 0x4000;
+
+               if (!LoadImg(ROMs[i], grom + baseAddress, 0x1000))
                {
-                       uint32 saddr = 8 + sx + ((sy - 6) * 320);       // Calc screen address
-                       scrBuffer[saddr + 0] = palette[color[b >> 4]];
-                       scrBuffer[saddr + 1] = palette[color[b & 0x0F]];
+                       WriteLog("Could not open file '%s'!\n", ROMs[i]);
+                       return -1;
                }
        }
-       else if (addr >= 0xC000 && addr <= 0xC00F)
-       {
-// A better strategy here would probably be to set a flag when the color register changes,
-// then change it before doing the render.
-// ALSO: This approach doesn't take the color to the edges of the screen
-//#warning "This should only touch memory right before a render. !!! FIX !!!"
-//Now it does. :-)
-               color[addr - 0xC000] = b;
 
-#if 0
-               for(uint32 addr=0x0006; addr<0x97F7; addr++)
-               {
-                       uint16 sx = (addr >> 7) & 0x01FE, sy = addr & 0x00FF;
+       if (!LoadImg(SOUNDROM, srom + 0xF800, 0x800))
+       {
+               WriteLog("Could not open file '%s'!\n", SOUNDROM);
+               return -1;
+       }
 
-                       if (sy > 5 && sy < 246)
-                       {
-                               uint32 saddr = 8 + sx + ((sy - 6) * 320);       // Calc screen address
-                               uint8 sb = gram[addr];
+       WriteLog("Stargate ROM images loaded...\n");
+       WriteLog("About to initialize video...\n");
 
-                               scrBuffer[saddr + 0] = palette[color[sb >> 4]];
-                               scrBuffer[saddr + 1] = palette[color[sb & 0x0F]];
-                       }
-               }
-#else
-               paletteDirty = true;
-#endif
-       }
-       else if (addr == 0xC80E)
+       if (!InitVideo())
        {
-               sram[0x0402] = b;                                                               // Connect PIAs in 6809 & 6808
-               soundCPU.cpuFlags |= V6808_ASSERT_LINE_IRQ;             // Start sound IRQ
+               cout << "Aborting!" << endl;
+               return -1;
        }
 
-#ifdef LOG_PIA1_IO
-//if (addr >= 0xC80C && addr <= 0xC80F)
-if (addr == 0xC80D)
-       WriteLog("V6809 WrMem: Writing PIA (%s) address %04X [->%02X, PC=%04X]\n", piaRegsName[addr&0x03], addr, b, GetCurrentV6809PC());//*/
-#endif
-}
+       // Have to do this *after* video init but *before* sound init...!
+       WriteLog("About to load machine state...");
 
-//
-// 6808 memory functions
-//
+       if (!LoadMachineState())
+               WriteLog("Machine state file not found!\n");
+       else
+               WriteLog("done!\n");
 
-uint8 RdMem6808(uint16 addr)
+       if (!LoadImg(CMOS, gram + 0xCC00, 0x400))
+               WriteLog("CMOS RAM not found!\n");
+
+       WriteLog("About to intialize audio...\n");
+       SoundInit();
+       keys = SDL_GetKeyState(NULL);
+       srom[0xF800] = 0x37;                                            // Fix checksum so ST works...
+       running = true;                                                         // Set running status...
+
+       InitializeEventList();                                          // Clear the event list before we use it...
+       SetCallbackTime(FrameCallback, FRAME_DURATION_IN_CYCLES * M6809_CYCLE_IN_USEC);
+       SetCallbackTime(ScanlineCallback, SG2_PIA_CALLBACK_DURATION);
+       clockFrameStart = mainCPU.clock;
+       startTicks = SDL_GetTicks();
+
+       WriteLog("Entering main loop...\n");
+
+       while (running)
+       {
+               double timeToNextEvent = GetTimeToNextEvent();
+               Execute6809(&mainCPU, USEC_TO_M6809_CYCLES(timeToNextEvent));
+               HandleNextEvent();
+       }
+
+#ifdef __DEBUG__
+WriteLog("\n");
+WriteLog("$C900 = $%02X (0=RAM)\n", gram[0xC900]);
+WriteLog("PC: %04X, X: %04X, Y: %04X, S: %04X, U: %04X, A: %02X, B: %02X, DP: %02X, CC: %02X\n", mainCPU.pc, mainCPU.x, mainCPU.y, mainCPU.s, mainCPU.u, mainCPU.a, mainCPU.b, mainCPU.dp, mainCPU.cc);
+WriteLog("\n");
+
+/*uint16 pc = mainCPU.pc;//0x15BA;
+for(int i=0; i<200; i++)
+//while (pc < 0x9000)
 {
-       return (addr < 0xF000 ? sram[addr] : srom[addr]);
-}
+       pc += Decode6809(pc);
+       WriteLog("\n");
+}//*/
 
-void WrMem6808(uint16 addr, uint8 b)
+/*uint32 pc = 0;
+while (pc < 0xFFFF)
 {
-       sram[addr] = b;
+       pc += Decode6809(pc);
+       WriteLog("\n");
+}//*/
+#endif
 
-       // A total guess, but let's try it...
-//It probably depends on how the PIA is configured, so this is most likely wrong.
-// It is wrong: IRQs are cleared on PIA PORTx reads!
-//     if (addr == 0x0401)
-//             soundCPU.cpuFlags &= ~V6808_ASSERT_LINE_IRQ;
+       SoundDone();
+       VideoDone();
+       SaveCMOS();
+       SaveMachineState();
+       LogDone();
+
+       return 0;
 }
 
 //
@@ -261,10 +270,14 @@ bool LoadMachineState(void)
        ignoredResult = fread(&soundCPU, 1, sizeof(V6808REGS), fp);
        fclose(fp);
 
-//     for(int i=0x0006; i<0x97F8; i++)                                        // Set up backbuffer... ;-)
-//             WrMem6809(i, gram[i]);
+       // Set up backbuffer... ;-)
+       for(uint16 i=0x0006; i<0x97F8; i++)                                     // Screen memory
+               WrMem6809(i, gram[i]);
+
+       for(uint16 i=0xC000; i<=0xC00F; i++)                            // Palette memory
+               WrMem6809(i, gram[i]);
 
-       paletteDirty = true;                                                            // Set up backbuffer...
+       paletteDirty = true;
 
        mainCPU.RdMem = RdMem6809;                                                      // Make sure our function pointers are
        mainCPU.WrMem = WrMem6809;                                                      // pointing to the right places!
@@ -272,6 +285,8 @@ bool LoadMachineState(void)
        soundCPU.WrMem = WrMem6808;
        mainCPU.clock = 0;                                                                      // Zero out our clocks...
        soundCPU.clock = 0;
+       mainCPU.clockOverrun = 0;                                                       // And overrun values...
+//notyet       soundCPU.clockOverrun = 0;
 
        return true;
 }
@@ -296,148 +311,132 @@ void SaveMachineState(void)
 }
 
 //
-// Main loop
+// 6809 memory functions
 //
-int main(int /*argc*/, char * /*argv*/[])
+
+#ifdef LOG_PIA1_IO
+char piaRegsName[4][10] = { "PORTA", "PACTL", "PORTB", "PBCTL" };
+#endif
+uint8 RdMem6809(uint16 addr)
 {
-       InitLog("stargem2.log");
-       WriteLog("StarGem2 - A portable Stargate emulator by James L. Hammons\n");
-       WriteLog("(C) 2009 Underground Software\n\n");
+       uint8 b;
 
-       LoadSettings();
+       if (addr >= 0x9000 && addr <= 0xCFFF)           // No ROM between $9000 - $CFFF...
+               b = gram[addr];
+       else
+       {
+               if (!gram[0xC900] && addr <= 0x8FFF)    // Check RAM $C900 bank switch
+                       b = gram[addr];
+               else
+                       b = grom[addr];
+       }
 
-       // Initialize Williams' palette (RGB coded as: 3 bits red, 3 bits green, 2 bits blue)
-       for(uint32 i=0; i<256; i++)
-               palette[i] =
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-               (((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151) << 24)
-                       | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 16)
-                       | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 8) | 0xFF;
+       // A wee kludge (though I doubt it reads from anywhere other than $CB00)...
+       if ((addr & 0xFF00) == 0xCB00)
+#if 0
+               b = gram[0xCB00] & 0xFC;                                // Only bits 2-7 are connected...
 #else
-               ((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151)
-                       | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 8)
-                       | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 16) | 0xFF000000;
+       {
+//Interesting, this code ALSO fucks up the demo...
+//Except when the correct code is called in the scanline callback function...
+               uint32 elapsedCycles = (uint32)(GetCurrentV6809Clock() - clockFrameStart);
+               uint32 scanline = (uint32)((double)elapsedCycles / SCANLINE_DURATION_IN_CYCLES);
+//Changes here don't seem to do much...
+//             uint32 scanline = (uint32)(((double)elapsedCycles * M6809_CYCLE_IN_USEC) / 70.0);
+               b = (uint8)scanline & 0xFC;                             // Only bits 2-7 are connected...
+       }
 #endif
 
-       // Zero out memory
-       memset(gram, 0, 0x10000);
-       memset(grom, 0, 0x10000);
-       memset(sram, 0, 0x10000);
-       memset(srom, 0, 0x10000);
+       // More kludge...
+       if ((addr == 0xC80C) && (gram[0xC80D] & 0x04))  // Read PORTA and DDR is set to Output
+       {
+               ClearLine(V6809_ASSERT_LINE_IRQ);                       // Then clear the IRQ
+//OK, this ALSO fucks up the execution of the demo...
+// Which means that the timing is still off. :-/
+//             mainCPU.cpuFlags &= ~V6809_ASSERT_LINE_IRQ;                     // Then clear the IRQ
+       }
 
-       // Set up V6809 & V6808 execution contexts
+       if ((addr == 0xC80E) && (gram[0xC80F] & 0x04))  // Read PORTB and DDR is set to Output
+       {
+               ClearLine(V6809_ASSERT_LINE_IRQ);                       // Then clear the IRQ
+//OK, this ALSO fucks up the execution of the demo...
+//             mainCPU.cpuFlags &= ~V6809_ASSERT_LINE_IRQ;                     // Then clear the IRQ
+       }
 
-       memset(&mainCPU, 0, sizeof(V6809REGS));
-       mainCPU.RdMem = RdMem6809;
-       mainCPU.WrMem = WrMem6809;
-       mainCPU.cpuFlags |= V6809_ASSERT_LINE_RESET;
+//temp...
+/*extern uint16 pcr;
+//if (addr >= 0xC000 && addr <= 0xCBFF)
+if (addr == 0x9C59)
+       WriteLog("RdMem: Reading address %04X [=%02X, PC=%04X]\n", addr, b, pcr);//*/
+#ifdef LOG_PIA1_IO
+/*if (addr >= 0xC80C && addr <= 0xC80F)
+       WriteLog("V6809 RdMem: Reading PIA (%s) address %04X [<-%02X, PC=%04X]\n", piaRegsName[addr&0x03], addr, b, GetCurrentV6809PC());//*/
+#endif
+       return b;
+}
 
-       memset(&soundCPU, 0, sizeof(V6808REGS));
-       soundCPU.RdMem = RdMem6808;
-       soundCPU.WrMem = WrMem6808;
-       soundCPU.cpuFlags |= V6808_ASSERT_LINE_RESET;
+void WrMem6809(uint16 addr, uint8 b)
+{
+//temp...
+//extern V6809REGS regs;
+//if (addr >= 0xC800 && addr <= 0xCBFE)
+//if (addr == 0xC80F || addr == 0xC80D)
+//     WriteLog("WrMem: Writing address %04X with %02X [PC=%04X, $CB00=%02X]\n", addr, b, regs.pc, gram[0xCB00]);//*/
+//if (addr == 0xC80E)
+/*if (addr >= 0xC800 && addr <= 0xC80F)
+       WriteLog("V6809 WrMem: Writing address %04X with %02X [PC=%04X, $CB00=%02X]\n", addr, b, mainCPU.pc, gram[0xCB00]);//*/
 
-       char ROMs[12][8] = {
-               "ROMs/01", "ROMs/02", "ROMs/03", "ROMs/04", "ROMs/05", "ROMs/06",
-               "ROMs/07", "ROMs/08", "ROMs/09", "ROMs/10", "ROMs/11", "ROMs/12"
-               };
+       gram[addr] = b;
 
-       for(int i=0; i<12; i++)
+       if (addr >= 0x0006 && addr < 0x97F7)                    // 304 pixels  152-128=24-16=8
        {
-               uint32 baseAddress = i * 0x1000;
-
-               if (i > 8)
-                       baseAddress += 0x4000;
+               // NOTE: Screen was 304 x 256, but we truncate the vertical dimension here...
+               uint16 sx = (addr >> 7) & 0x01FE, sy = addr & 0x00FF;
 
-               if (!LoadImg(ROMs[i], grom + baseAddress, 0x1000))
+               if (sy > 5 && sy < 246)
                {
-                       WriteLog("Could not open file '%s'!\n", ROMs[i]);
-                       return -1;
+                       uint32 saddr = 8 + sx + ((sy - 6) * 320);       // Calc screen address
+                       scrBuffer[saddr + 0] = palette[color[b >> 4]];
+                       scrBuffer[saddr + 1] = palette[color[b & 0x0F]];
                }
        }
-
-       if (!LoadImg(SOUNDROM, srom + 0xF800, 0x800))
+       else if (addr >= 0xC000 && addr <= 0xC00F)
        {
-               WriteLog("Could not open file '%s'!\n", SOUNDROM);
-               return -1;
+// This approach doesn't take the BG color to the edges of the screen
+               color[addr - 0xC000] = b;
+               paletteDirty = true;
        }
-
-       WriteLog("Stargate ROM images loaded...\n");
-       WriteLog("About to initialize video...\n");
-
-       if (!InitVideo())
+       else if (addr == 0xC80E)
        {
-               cout << "Aborting!" << endl;
-               return -1;
+               sram[0x0402] = b;                                                               // Connect PIAs in 6809 & 6808
+               soundCPU.cpuFlags |= V6808_ASSERT_LINE_IRQ;             // Start sound IRQ
        }
 
-       // Have to do this *after* video init but *before* sound init...!
-       WriteLog("About to load machine state...");
-
-       if (!LoadMachineState())
-               WriteLog("Machine state file not found!\n");
-       else
-               WriteLog("done!\n");
-
-       if (!LoadImg(CMOS, gram + 0xCC00, 0x400))
-               WriteLog("CMOS RAM not found!\n");
-
-       WriteLog("About to intialize audio...\n");
-       SoundInit();
-       keys = SDL_GetKeyState(NULL);
-       srom[0xF800] = 0x37;                                            // Fix checksum so ST works...
-       running = true;                                                         // Set running status...
-
-       InitializeEventList();                                          // Clear the event list before we use it...
-       SetCallbackTime(FrameCallback, 16666.66666667); // Set frame to fire at 1/60 s interval
-//     SetCallbackTime(ScanlineCallback, 520.83333334); // Set scanline callback at 1/32 of frame
-       SetCallbackTime(ScanlineCallback, 520.83333334/2.0); // Set scanline callback at 1/64 of frame
-       clockFrameStart = mainCPU.clock;
-       startTicks = SDL_GetTicks();
-
-       WriteLog("Entering main loop...\n");
-
-       while (running)
-       {
-               double timeToNextEvent = GetTimeToNextEvent();
-               Execute6809(&mainCPU, USEC_TO_M6809_CYCLES(timeToNextEvent));
-//We MUST remove a frame's worth of time in order for the CPU to function... !!! FIX !!!
-//(Fix so that this is not a requirement!)
-//Very odd... Execution seems to fuck up when using a 64-bit clock...
-//(i.e., when this is commented out!)
-//             mainCPU.clock -= USEC_TO_M6809_CYCLES(timeToNextEvent);
-               HandleNextEvent();
-       }
+#ifdef LOG_PIA1_IO
+//if (addr >= 0xC80C && addr <= 0xC80F)
+if (addr == 0xC80D)
+       WriteLog("V6809 WrMem: Writing PIA (%s) address %04X [->%02X, PC=%04X]\n", piaRegsName[addr&0x03], addr, b, GetCurrentV6809PC());//*/
+#endif
+}
 
-#ifdef __DEBUG__
-WriteLog("\n");
-WriteLog("$C900 = $%02X (0=RAM)\n", gram[0xC900]);
-WriteLog("PC: %04X, X: %04X, Y: %04X, S: %04X, U: %04X, A: %02X, B: %02X, DP: %02X, CC: %02X\n", mainCPU.pc, mainCPU.x, mainCPU.y, mainCPU.s, mainCPU.u, mainCPU.a, mainCPU.b, mainCPU.dp, mainCPU.cc);
-WriteLog("\n");
+//
+// 6808 memory functions
+//
 
-/*uint16 pc = mainCPU.pc;//0x15BA;
-for(int i=0; i<200; i++)
-//while (pc < 0x9000)
+uint8 RdMem6808(uint16 addr)
 {
-       pc += Decode6809(pc);
-       WriteLog("\n");
-}//*/
+       return (addr < 0xF000 ? sram[addr] : srom[addr]);
+}
 
-/*uint32 pc = 0;
-while (pc < 0xFFFF)
+void WrMem6808(uint16 addr, uint8 b)
 {
-       pc += Decode6809(pc);
-       WriteLog("\n");
-}//*/
-#endif
-
-       SoundDone();
-       VideoDone();
-       SaveCMOS();
-       SaveMachineState();
-       LogDone();
+       sram[addr] = b;
 
-       return 0;
+       // A total guess, but let's try it...
+//It probably depends on how the PIA is configured, so this is most likely wrong.
+// It is wrong: IRQs are cleared on PIA PORTx reads!
+//     if (addr == 0x0401)
+//             soundCPU.cpuFlags &= ~V6808_ASSERT_LINE_IRQ;
 }
 
 static void FrameCallback(void)
@@ -511,7 +510,6 @@ static void FrameCallback(void)
        }
 
        RenderScreenBuffer();                                           // 1 frame = 1/60 sec ~ 16667 cycles
-       SetCallbackTime(FrameCallback, 16666.66666667);
        clockFrameStart = mainCPU.clock;
 
        // Wait for next frame...
@@ -519,6 +517,7 @@ static void FrameCallback(void)
                SDL_Delay(1);
 
        startTicks = SDL_GetTicks();
+       SetCallbackTime(FrameCallback, FRAME_DURATION_IN_CYCLES * M6809_CYCLE_IN_USEC);
 }
 
 static void ScanlineCallback(void)
@@ -546,10 +545,9 @@ Apparently, COUNT240 is unimportant, at least as far as STARGATE is concerned...
 
        // This should set everything between $CB00-CBFF...
 //     gram[0xCB00] += 8;                                                      // Update video counter...
-       gram[0xCB00] += 4;                                                      // Update video counter...
+//     gram[0xCB00] += 4;                                                      // Update video counter...
 
-//     SetCallbackTime(ScanlineCallback, 520.83333334); // Set scanline callback at 1/32 of frame
-       SetCallbackTime(ScanlineCallback, 520.83333334/2.0); // Set scanline callback at 1/64 of frame
+       SetCallbackTime(ScanlineCallback, SG2_PIA_CALLBACK_DURATION);
 }