X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fstargem2.cpp;fp=src%2Fstargem2.cpp;h=32248fcdd8d6bc854fe611d5f02c778a1c00e88a;hb=d1485d7c8a16bf3dd7601bbf6016998eb28bf989;hp=9ee92439be4807c372777dee64f32405a92cef8c;hpb=b20e94784ba06541fa3583d365e2f511a698a9c5;p=stargem2 diff --git a/src/stargem2.cpp b/src/stargem2.cpp index 9ee9243..32248fc 100755 --- a/src/stargem2.cpp +++ b/src/stargem2.cpp @@ -10,6 +10,7 @@ // --- ---------- ------------------------------------------------------------ // JLH 06/15/2006 Added changelog ;-) // JLH 06/15/2006 Switched over to timeslice execution code +// JLH 07/15/2009 Solved problem with DEMO mode (IRQ handling) // #include "SDL.h" @@ -31,9 +32,8 @@ #include "dis6809.h" #include "dis6808.h" -#define __DEBUG__ - -#define LOG_PIA1_IO +//#define __DEBUG__ +//#define LOG_PIA1_IO using namespace std; @@ -55,6 +55,7 @@ bool paletteDirty = false; static bool running = true; // Machine running state flag... static uint32 startTicks; static uint8 * keys; // SDL raw keyboard matrix +static uint64 clockFrameStart; // V6809 clock at the start of the frame // Local timer callback functions @@ -85,14 +86,34 @@ uint8 RdMem6809(uint16 addr) // 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 + { +//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... + } +#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 + } 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 + } //temp... /*extern uint16 pcr; @@ -119,7 +140,7 @@ void WrMem6809(uint16 addr, uint8 b) gram[addr] = b; - if (addr > 0x0006 && addr < 0x97F7) // 304 pixels 152-128=24-16=8 + if (addr >= 0x0006 && addr < 0x97F7) // 304 pixels 152-128=24-16=8 { // NOTE: Screen was 304 x 256, but we truncate the vertical dimension here... uint16 sx = (addr >> 7) & 0x01FE, sy = addr & 0x00FF; @@ -127,30 +148,21 @@ void WrMem6809(uint16 addr, uint8 b) if (sy > 5 && sy < 246) { uint32 saddr = 8 + sx + ((sy - 6) * 320); // Calc screen address -//Hmm. This approach won't work with palette color cycling... -#if 0 - scrBuffer[saddr + 0] = b >> 4; - scrBuffer[saddr + 1] = b & 0x0F; -#else scrBuffer[saddr + 0] = palette[color[b >> 4]]; scrBuffer[saddr + 1] = palette[color[b & 0x0F]]; -#endif } } else if (addr >= 0xC000 && addr <= 0xC00F) -//Let's see if we can fix the color cycling here... [DONE] -#if 0 - color[addr - 0xC000] = b; // color[] from VIDEO.CPP (not any more!) -#else { // 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 !!!" +//#warning "This should only touch memory right before a render. !!! FIX !!!" +//Now it does. :-) color[addr - 0xC000] = b; #if 0 - for(uint32 addr=0x0007; addr<0x97F7; addr++) + for(uint32 addr=0x0006; addr<0x97F7; addr++) { uint16 sx = (addr >> 7) & 0x01FE, sy = addr & 0x00FF; @@ -167,7 +179,6 @@ void WrMem6809(uint16 addr, uint8 b) paletteDirty = true; #endif } -#endif else if (addr == 0xC80E) { sram[0x0402] = b; // Connect PIAs in 6809 & 6808 @@ -196,6 +207,7 @@ void WrMem6808(uint16 addr, uint8 b) // 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; } @@ -249,13 +261,17 @@ 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]); +// for(int i=0x0006; i<0x97F8; i++) // Set up backbuffer... ;-) +// WrMem6809(i, gram[i]); + + paletteDirty = true; // Set up backbuffer... mainCPU.RdMem = RdMem6809; // Make sure our function pointers are mainCPU.WrMem = WrMem6809; // pointing to the right places! soundCPU.RdMem = RdMem6808; soundCPU.WrMem = WrMem6808; + mainCPU.clock = 0; // Zero out our clocks... + soundCPU.clock = 0; return true; } @@ -286,6 +302,7 @@ int main(int /*argc*/, char * /*argv*/[]) { InitLog("stargem2.log"); WriteLog("StarGem2 - A portable Stargate emulator by James L. Hammons\n"); + WriteLog("(C) 2009 Underground Software\n\n"); LoadSettings(); @@ -303,8 +320,6 @@ int main(int /*argc*/, char * /*argv*/[]) #endif // Zero out memory -// for(long i=0; i<0x10000; i++) -// gram[i] = grom[i] = sram[i] = srom[i] = 0; memset(gram, 0, 0x10000); memset(grom, 0, 0x10000); memset(sram, 0, 0x10000); @@ -334,10 +349,6 @@ int main(int /*argc*/, char * /*argv*/[]) if (i > 8) baseAddress += 0x4000; -#if 0 -WriteLog("Loading ROM image '%s' at $%04X...\n", ROMs[i], baseAddress); -#endif -// if (!LoadImg(ROMs[i], grom + (i * 0x1000), 0x1000)) if (!LoadImg(ROMs[i], grom + baseAddress, 0x1000)) { WriteLog("Could not open file '%s'!\n", ROMs[i]); @@ -373,178 +384,15 @@ WriteLog("Loading ROM image '%s' at $%04X...\n", ROMs[i], baseAddress); WriteLog("About to intialize audio...\n"); SoundInit(); -// uint8 * keys = SDL_GetKeyState(NULL); keys = SDL_GetKeyState(NULL); - -// running = true; // Set running status... srom[0xF800] = 0x37; // Fix checksum so ST works... - -#if 0 - -//kludge... -//This didn't work--it still acted like the old way (interrupt @ VC = 0) -//gram[0xCB00] = 64*3; - - WriteLog("Entering main loop...\n"); - while (running) - { - SDL_PumpEvents(); // Force key events into the buffer. - gram[0xC804] = gram[0xC806] = gram[0xC80C] = 0; // Reset PIA ports... - - if (keys[SDLK_ESCAPE]) - running = false; // ESC to exit... - - if (keys[SDLK_SEMICOLON]) - gram[0xC804] |= 0x01; // Fire (;) - if (keys[SDLK_l]) - gram[0xC804] |= 0x02; // Thrust (L) - if (keys[SDLK_SPACE]) - gram[0xC804] |= 0x04; // Smart Bomb (space) - if (keys[SDLK_BACKSPACE]) - gram[0xC804] |= 0x08; // Hyperspace (BkSp) - if (keys[SDLK_2]) - gram[0xC804] |= 0x10; // Two Player Start (2) - if (keys[SDLK_1]) - gram[0xC804] |= 0x20; // One Player Start (1) - if (keys[SDLK_RETURN]) - gram[0xC804] |= 0x40; // Reverse (Enter) - if (keys[SDLK_f]) - gram[0xC804] |= 0x80; // Down (F) - - if (keys[SDLK_r]) - gram[0xC806] |= 0x01; // Up (R) - if (keys[SDLK_a]) - gram[0xC806] |= 0x02; // Inviso (A) - - if (keys[SDLK_F1]) - gram[0xC80C] |= 0x01; // Auto up (F1) - if (keys[SDLK_F2]) - gram[0xC80C] |= 0x02; // Advance (F2) - if (keys[SDLK_5]) - gram[0xC80C] |= 0x04; // Right Coin (5) - if (keys[SDLK_F3]) - gram[0xC80C] |= 0x08; // High Score Reset (F3) - if (keys[SDLK_3]) - gram[0xC80C] |= 0x10; // Left Coin (3) - if (keys[SDLK_4]) - gram[0xC80C] |= 0x20; // Center Coin (4) - if (keys[SDLK_F4]) - gram[0xC80C] |= 0x40; // Slam Switch (F4) - - if (keys[SDLK_F5]) // Sound CPU self-test (F5) - soundCPU.cpuFlags |= V6808_ASSERT_LINE_NMI; - if (keys[SDLK_F6]) // Reset the 6808 (F6) - soundCPU.cpuFlags |= V6808_ASSERT_LINE_RESET; - -/* -$CB00 is scanline counter, bits 2-7 (1 frame/240 =69.44... usec) - -Some places of interest to look at: - -RdMem: Reading address C80E [=0C, PC=15C3] <- Inside interrupt (read, then discarded)... -RdMem: Reading address CB00 [=43, PC=15C6] <- interrupt -RdMem: Reading address C80C [=00, PC=0758] <- input (?) -RdMem: Reading address C80C [=00, PC=07B9] <- input (?) -RdMem: Reading address C806 [=00, PC=078C] <- input -RdMem: Reading address C804 [=00, PC=2679] <- input -*/ - uint32 startTicks = SDL_GetTicks(); -// long video_clk = 0; -// gram[0xCB00] = 0; - -/* -//This is where the interrupt mask is restored in CC... Hmm... -//This enables interrupts *after* the previous interrupt has occurred... Hmm. -//Could $C80F (rom_pia_ctrlb) be the IRQ inhibit? Yes, it is! - - // the IRQ signal comes into CB1, and is set to VA11 - pia_1_cb1_w(0, scanline & 0x20); -... - // the COUNT240 signal comes into CA1, and is set to the logical AND of VA10-VA13 - pia_1_ca1_w(0, 0); -... - // the COUNT240 signal comes into CA1, and is set to the logical AND of VA10-VA13 - pia_1_ca1_w(0, 1); -*/ - -//WriteLog("--> Start of frame...\n"); - for(int i=0; i<3; i++) - { -//Not sure, but this *might* fix IRQ problem... -//Checking the PIA IRQ mask for an IRQ seems to work OK. Now if only the timing elsewhere was right... - if (gram[0xC80F] & 0x01) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ - - Execute6809(&mainCPU, 4000); - mainCPU.clock -= 4000; // Remove 4K ticks from clock (in case it overflowed) -//Not sure, but this *might* fix IRQ problem... -//Checking the PIA IRQ mask for an IRQ seems to work OK. Now if only the timing elsewhere was right... -/* if (gram[0xC80F] & 0x01) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ - - gram[0xCB00] += 64; // Update video counter... - } - -//Hmm. -/*if (gram[0xC80E] & 0x01) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ -//48 lines... (+ 16) -//gram[0xCB00] = 0; - Execute6809(&mainCPU, 3000); - mainCPU.clock -= 3000; // Remove 3K ticks from clock (in case it overflowed) -//Not sure, but this *might* fix IRQ problem... -//if (gram[0xC80F] & 0x01) -//This isn't the right port on the PIA, but it does seem to make it through the demo now... -//Lesse if this works... Seems to! - if (gram[0xC80D] & 0x01) // Do COUNT240 IRQ (if enabled!) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ; - -/*if (gram[0xC80F] & 0x01) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ; -gram[0xCB00] = 0; //*/ - - gram[0xCB00] += 48; // Update video counter... - - Execute6809(&mainCPU, 1000); - mainCPU.clock -= 1000; // Remove 1K ticks from clock (in case it overflowed) -//Eh? -//Ok, this is the interrupt it's looking for, but still... -//if (gram[0xC80F] & 0x01) -// mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ; - - gram[0xCB00] += 16; // Update video counter... - -// RenderScreenBuffer(); - RenderScreenBuffer2(); // 1 frame = 16667 cycles -// WriteLog("Main: Rendered back buffer. [6809 PC=%04X]\n", pcr); - - Execute6809(&mainCPU, 667); // Do QnD VBLANK - - // 1/60 sec = ? ms (16.6 ms) - while (SDL_GetTicks() - startTicks < 16); // Wait for next frame... - -//kludge, temp... -//Very interesting! It's the palette rotation that's slowing it down! -//Fixed now, but this allows the color rotation while the wrong timing is in effect... -/*for(int i=0; i<16; i++) - WrMem(0xC000 + i, gram[0x9C26 + i]);//*/ - } - -/*uint16 pc = 0x15BA; -for(int i=0; i<200; i++) -//while (pc < 0x9000) - pc += Decode6809(pc);//*/ - -#else - 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(BlinkTimer, 250000); // Set up blinking at 1/4 s intervals // 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, 520.83333334*32.00); // Set scanline callback at 1/32 of frame + clockFrameStart = mainCPU.clock; startTicks = SDL_GetTicks(); WriteLog("Entering main loop...\n"); @@ -555,7 +403,9 @@ for(int i=0; i<200; i++) 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!) - mainCPU.clock -= USEC_TO_M6809_CYCLES(timeToNextEvent); +//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(); } @@ -579,8 +429,6 @@ while (pc < 0xFFFF) pc += Decode6809(pc); WriteLog("\n"); }//*/ -#endif - #endif SoundDone(); @@ -643,15 +491,9 @@ static void FrameCallback(void) if (keys[SDLK_F6]) // Reset the 6808 (F6) soundCPU.cpuFlags |= V6808_ASSERT_LINE_RESET; -#if 0 -//Grr... -for(int i=0; i<16; i++) - WrMem6809(0xC000 + i, gram[0x9C26 + i]);//*/ -#endif - if (paletteDirty) { - for(uint32 addr=0x0007; addr<0x97F7; addr++) + for(uint32 addr=0x0006; addr<0x97F7; addr++) { uint16 sx = (addr >> 7) & 0x01FE, sy = addr & 0x00FF; @@ -670,11 +512,8 @@ for(int i=0; i<16; i++) RenderScreenBuffer(); // 1 frame = 1/60 sec ~ 16667 cycles SetCallbackTime(FrameCallback, 16666.66666667); + clockFrameStart = mainCPU.clock; -//Hmm. Yield some time? -//This works, but doesn't seem to yield much CPU--maybe 10% -//SDL_Delay(2); -//The following works much better--yields as much as 50% // Wait for next frame... while (SDL_GetTicks() - startTicks < 16) SDL_Delay(1); @@ -684,50 +523,26 @@ for(int i=0; i<16; i++) static void ScanlineCallback(void) { -// CA1 of PIA 1 maps to $C80C-F... <-- Count240 is in PIA1... -// What about COUNT240??? -// COUNT240 asserts between scanlines 240-256, and clears everywhere else. so !!! FIX !!! #if 0 - // NOTE that this is writing to CA1!!! - pia_1_ca1_w(0, 0); // COUNT240 off - pia_1_ca1_w(0, 1); // COUNT240 on - pia_1_cb1_w(0, scanline & 0x20); // Signal into CB1 - // NOTE: The reads to $CB00 are at a granularity of 4, not 8 - { 0xcb00, 0xcb00, williams_video_counter_r }, -READ_HANDLER( williams_video_counter_r ) -{ - return cpu_getscanline() & 0xFC; -} -#endif -// mainCPU.cpuFlags &= ~V6809_ASSERT_LINE_IRQ; - -//wil wok? Yes, but still screws up on the demo... -/* if (gram[0xCB00] & 0x20) - if (gram[0xC80F] & 0x01) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ - if ((gram[0xCB00] & 0x20) && (gram[0xC80F] & 0x01)) mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ +#else + mainCPU.cpuFlags &= ~V6809_ASSERT_LINE_IRQ; -/* if ((gram[0xCB00] >= 0xF0) && (gram[0xCB00] & 0x20) && (gram[0xC80F] & 0x01)) + if ((RdMem6809(0xCB00) & 0x20) && (gram[0xC80F] & 0x01)) mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ +#endif -// Hmm. No. But this *should* do it... Why doesn't it??? /* The problem is that this is already asserted above, by virtue of the fact that 240 = $F0 = bit 5 is set! So this does nothing! So obviously, the above IRQ assertion is wrong--just need to figure out how the write of $20 and $00 affects the PBCTRL in the PIA. It looks like Stargate never asserts the COUNT240 IRQ, and could be because of the above... -*/ - if ((gram[0xCB00] >= 240) && (gram[0xC80D] & 0x09)) // Do COUNT240 IRQ (if enabled!) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ; -//Is $C80E COUNT240? Hmm... Doesn't seem to be. Bleh. -/* if (gram[0xCB00] >= 240) - gram[0xC80E] = 0xFF; - else - gram[0xC80E] = 0x00;//*/ -// gram[0xC80E] = (gram[0xCB00] >= 240 ? 0xFF : 0x00); +Apparently, COUNT240 is unimportant, at least as far as STARGATE is concerned... +*/ +// if ((gram[0xCB00] >= 240) && (gram[0xC80D] & 0x09)) // Do COUNT240 IRQ (if enabled!) +// mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ; // This should set everything between $CB00-CBFF... // gram[0xCB00] += 8; // Update video counter...