static void __fastcall gradius3_main_write_byte(UINT32 address, UINT8 data) { if ((address & 0xfe0000) == 0x180000) { DrvShareRAM2[(address & 0x1ffff)^1] = data; expand_graphics_single(address); return; } switch (address) { case 0x0c0000: case 0x0c0001: { // if enabling CPU B, burn off some cycles to keep things sync'd. if (gradius3_cpub_enable & 8 && ~data & 8) { INT32 cycles_to_burn = SekTotalCycles(); SekClose(); SekOpen(1); SekIdle(cycles_to_burn - SekTotalCycles()); SekClose(); SekOpen(0); } gradius3_priority =(data & 0x04)>>2; gradius3_cpub_enable = data & 0x08; irqA_enable = data & 0x20; } return; case 0x0d8000: case 0x0d8001: interrupt_triggered = irqB_mask & 0x04; return; case 0x0e0000: case 0x0e0001: // watchdog return; case 0x0e8000: *soundlatch = data; return; case 0x0f0000: ZetSetVector(0xff); ZetSetIRQLine(0, CPU_IRQSTATUS_ACK); return; } if (address >= 0x14c000 && address <= 0x153fff) { address -= 0x14c000; K052109Write(address / 2, data); return; } }
void __fastcall gradius3_main_write_byte(unsigned int address, unsigned char data) { switch (address) { case 0x0c0000: case 0x0c0001: { // if enabling CPU B, burn off some cycles to keep things sync'd. if (gradius3_cpub_enable & 8 && ~data & 8) { int cycles_to_burn = SekTotalCycles(); SekClose(); SekOpen(1); SekIdle(cycles_to_burn - SekTotalCycles()); SekClose(); SekOpen(0); } gradius3_priority = data & 0x04; gradius3_cpub_enable = data & 0x08; irqA_enable = data & 0x20; } return; case 0x0d8000: case 0x0d8001: interrupt_triggered = irqB_mask & 0x04; return; case 0x0e0000: case 0x0e0001: // watchdog return; case 0x0e8000: *soundlatch = data; return; case 0x0f0000: ZetSetVector(0xff); ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); return; } if (address >= 0x14c000 && address <= 0x153fff) { address -= 0x14c000; K052109Write(address / 2, data); return; } }
static inline void pgm_cpu_sync() { INT32 nCycles = SekTotalCycles() - Arm7TotalCycles(); if (nCycles > 100) { Arm7Run(nCycles); } }
// Execute a beam-synchronised interrupt and schedule the next one static void DoIRQ() { // 0x4E - bit 9 = 1: Beam Synchronized interrupts disabled // 0x50 - Beam synchronized interrupt #1 occurs at raster line. // 0x52 - Beam synchronized interrupt #2 occurs at raster line. // Trigger IRQ and copy registers. if (nIrqLine >= nFirstLine) { nInterrupt++; nRasterline[nInterrupt] = nIrqLine - nFirstLine; } SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); SekRun(nCpsCycles * 0x01 / nCpsNumScanlines); if (nRasterline[nInterrupt] < 224) { CopyCpsReg(nInterrupt); CopyCpsFrg(nInterrupt); } else { nRasterline[nInterrupt] = 0; } // Schedule next interrupt if (!bEnableAutoIrq50) { if (nIrqLine >= nIrqLine50) { nIrqLine50 = nCpsNumScanlines; } } else { if (bEnableAutoIrq50 && nIrqLine == nIrqLine50) { nIrqLine50 += 32; } } if (!bEnableAutoIrq52 && nIrqLine >= nIrqLine52) { nIrqLine52 = nCpsNumScanlines; } else { if (bEnableAutoIrq52 && nIrqLine == nIrqLine52) { nIrqLine52 += 32; } } ScheduleIRQ(); if (nIrqCycles < SekTotalCycles()) { nIrqCycles = SekTotalCycles() + 1; } return; }
static inline void cpu_sync() // sync z80 & 68k { int t = ((SekTotalCycles() * 3) / 10) - ZetTotalCycles(); if (t > 0) { BurnTimerUpdate(t); } }
void QsndSyncZ80() { int nCycles = (long long)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles; QUARK_LOG_VAR(nCycles); QUARK_LOG_VAR(nCpsZ80Cycles); QUARK_LOG_VAR(nCpsCycles); QUARK_LOG_VAR(SekTotalCycles()); QUARK_LOG_VAR(nSekCyclesTotal); QUARK_LOG_VAR(nSekCyclesToDo); QUARK_LOG_VAR(ZetTotalCycles()); if (nCycles <= ZetTotalCycles()) { return; } BurnTimerUpdate(nCycles); }
void QsndSyncZ80() { int nCycles = (long long)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles; if (nCycles <= ZetTotalCycles()) { return; } BurnTimerUpdate(nCycles); }
inline void toaplan1SynchroniseZ80(int nExtraCycles) { int nCycles = ((long long)SekTotalCycles() * nCyclesTotal[1] / nCyclesTotal[0]) + nExtraCycles; if (nCycles <= ZetTotalCycles()) { return; } nToa1Cycles68KSync = nCycles - nExtraCycles; BurnTimerUpdate(nCycles); }
int SupermanFrame() { if (SupermanReset) { // Reset machine SupermanDoReset(); } SupermanInpMake(); SekNewFrame(); ZetNewFrame(); SekOpen(0); ZetOpen(0); SekIdle(nCyclesDone[0]); ZetIdle(nCyclesDone[1]); nCyclesTotal[0] = 8000000 / 60; nCyclesTotal[1] = 4000000 / 60; SekRun(nCyclesTotal[0] - SekTotalCycles()); SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); nCycles68KSync = SekTotalCycles(); BurnTimerEndFrame(nCyclesTotal[1]); BurnYM2610Update(nBurnSoundLen); nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; nCyclesDone[1] = ZetTotalCycles() - nCyclesTotal[1]; ZetClose(); SekClose(); if (pBurnDraw) { SupermanDraw(); // Draw screen if needed } return 0; }
void Sf2mdtSoundCommand(UINT16 d) { INT32 nCyclesToDo = ((INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles) - ZetTotalCycles(); INT32 nEnd = Sf2mdtSoundPos + (INT64)Sf2mdtMSM5205Interleave * nCyclesToDo / nCpsZ80Cycles; for (INT32 i = Sf2mdtSoundPos; i < nEnd; i++) { ZetRun(Sf2mdtCyclesPerSegment); MSM5205Update(); Sf2mdtSoundPos = i; } Sf2mdtSoundLatch = d & 0xff; ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); }
static INT32 DrvFrame() { INT32 nInterleave = 4; if (DrvReset) { DrvDoReset(); } memset (DrvInputs, 0, 3); for (INT32 i = 0; i < 8; i++) { DrvInputs[0] |= (DrvJoy1[i] & 1) << i; DrvInputs[1] |= (DrvJoy2[i] & 1) << i; DrvInputs[2] |= (DrvJoy3[i] & 1) << i; } ToaClearOpposites(&DrvInputs[0]); ToaClearOpposites(&DrvInputs[1]); SekNewFrame(); SekOpen(0); SekIdle(nCyclesDone[0]); nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); SekSetCyclesScanline(nCyclesTotal[0] / 262); nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); bVBlank = false; for (INT32 i = 0; i < nInterleave; i++) { INT32 nNext; // Run 68000 nNext = (i + 1) * nCyclesTotal[0] / nInterleave; // Trigger VBlank interrupt if (nNext > nToaCyclesVBlankStart) { if (SekTotalCycles() < nToaCyclesVBlankStart) { nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); SekRun(nCyclesSegment); } if (pBurnDraw) { DrvDraw(); } ToaBufferFCU2Sprites(); bVBlank = true; if (bEnableInterrupts) { SekSetIRQLine(4, CPU_IRQSTATUS_AUTO); } } nCyclesSegment = nNext - SekTotalCycles(); if (bVBlank || (!CheckSleep(0))) { SekRun(nCyclesSegment); } else { SekIdle(nCyclesSegment); } } nToa1Cycles68KSync = SekTotalCycles(); // BurnTimerEndFrameYM3812(nCyclesTotal[1]); // BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); if (pBurnSoundOut) { BurnSampleRender(pBurnSoundOut, nBurnSoundLen); #ifdef TOAPLAN_SOUND_SAMPLES_HACK if (Start > 0) Wait++; if (Wait >= (108 + Start2)) { StopSamplesChannel0(); SetVolumeSamplesChannel0(1.00); BurnSamplePlay(0x07); Start = 0; Start2 = 1; Wait = 0; } if (Start2 == 0) ESEFadeout2(); #endif } nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; // bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); ToaBufferFCU2Sprites(); SekSetIRQLine(2, CPU_IRQSTATUS_AUTO); // sprite buffer finished... SekClose(); return 0; }
static INT32 DrvFrame() { INT32 nInterleave = 4; if (DrvReset) { // Reset machine DrvDoReset(); } // Compile digital inputs DrvInput[0] = 0x00; // Buttons DrvInput[1] = 0x00; // Player 1 DrvInput[4] = 0x00; // Player 2 for (INT32 i = 0; i < 8; i++) { DrvInput[0] |= (DrvJoy1[i] & 1) << i; DrvInput[1] |= (DrvJoy2[i] & 1) << i; DrvInput[4] |= (DrvButton[i] & 1) << i; } ToaClearOpposites(&DrvInput[0]); ToaClearOpposites(&DrvInput[1]); SekNewFrame(); ZetNewFrame(); SekOpen(0); ZetOpen(0); SekIdle(nCyclesDone[0]); ZetIdle(nCyclesDone[1]); nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); nCyclesTotal[1] = INT32(28000000.0 / 8 / REFRESHRATE); SekSetCyclesScanline(nCyclesTotal[0] / 262); nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); bVBlank = false; for (INT32 i = 0; i < nInterleave; i++) { INT32 nNext; // Run 68000 nNext = (i + 1) * nCyclesTotal[0] / nInterleave; // Trigger VBlank interrupt if (nNext > nToaCyclesVBlankStart) { if (SekTotalCycles() < nToaCyclesVBlankStart) { nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); SekRun(nCyclesSegment); } if (pBurnDraw) { DrvDraw(); // Draw screen if needed } ToaBufferFCU2Sprites(); bVBlank = true; if (bEnableInterrupts) { SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); } } nCyclesSegment = nNext - SekTotalCycles(); if (bVBlank || (!CheckSleep(0))) { // See if this CPU is busywaiting SekRun(nCyclesSegment); } else { SekIdle(nCyclesSegment); } BurnTimerUpdateYM3812(i * (nCyclesTotal[1] / nInterleave)); } nToa1Cycles68KSync = SekTotalCycles(); BurnTimerEndFrameYM3812(nCyclesTotal[1]); if (pBurnSoundOut) BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; nCyclesDone[1] = ZetTotalCycles() - nCyclesTotal[1]; // bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); ZetClose(); SekClose(); // ToaBufferFCU2Sprites(); return 0; }
static INT32 DrvFrame() { INT32 nInterleave = 4; if (DrvReset) { DrvDoReset(); } memset (DrvInputs, 0, 3); for (INT32 i = 0; i < 8; i++) { DrvInputs[0] |= (DrvJoy1[i] & 1) << i; DrvInputs[1] |= (DrvJoy2[i] & 1) << i; DrvInputs[2] |= (DrvJoy3[i] & 1) << i; } ToaClearOpposites(&DrvInputs[0]); ToaClearOpposites(&DrvInputs[1]); SekNewFrame(); ZetNewFrame(); SekOpen(0); ZetOpen(0); SekIdle(nCyclesDone[0]); ZetIdle(nCyclesDone[1]); nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); nCyclesTotal[1] = INT32(28000000.0 / 8 / REFRESHRATE); SekSetCyclesScanline(nCyclesTotal[0] / 262); nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); bVBlank = false; for (INT32 i = 0; i < nInterleave; i++) { INT32 nNext; // Run 68000 nNext = (i + 1) * nCyclesTotal[0] / nInterleave; // Trigger VBlank interrupt if (nNext > nToaCyclesVBlankStart) { if (SekTotalCycles() < nToaCyclesVBlankStart) { nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); SekRun(nCyclesSegment); } if (pBurnDraw) { DrvDraw(); } memcpy (DrvSprBuf, DrvSprRAM, 0x1000); bVBlank = true; if (bEnableInterrupts) { SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); } } nCyclesSegment = nNext - SekTotalCycles(); if (bVBlank || (!CheckSleep(0))) { SekRun(nCyclesSegment); } else { SekIdle(nCyclesSegment); } BurnTimerUpdateYM3812(i * (nCyclesTotal[1] / nInterleave)); } nToa1Cycles68KSync = SekTotalCycles(); BurnTimerEndFrameYM3812(nCyclesTotal[1]); if (pBurnSoundOut) BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; SekClose(); ZetClose(); return 0; }
INT32 Cps2Frame() { INT32 nDisplayEnd, nNext; // variables to keep track of executed 68K cyles INT32 i; if (CpsReset) { DrvReset(); } // extern INT32 prevline; // prevline = -1; SekNewFrame(); if (!Cps2DisableQSnd) QsndNewFrame(); nCpsCycles = (INT32)(((INT64)nCPS68KClockspeed * nBurnCPUSpeedAdjust) / 0x0100); SekOpen(0); SekSetCyclesScanline(nCpsCycles / nCpsNumScanlines); CpsRwGetInp(); // Update the input port values // Check the volumes every 5 frames or so #if 0 if (GetCurrentFrame() % 5 == 0) { if (Cps2VolUp) Cps2Volume++; if (Cps2VolDwn) Cps2Volume--; if (Cps2Volume > 39) Cps2Volume = 39; if (Cps2Volume < 0) Cps2Volume = 0; QscSetRoute(BURN_SND_QSND_OUTPUT_1, Cps2Volume / 39.0, BURN_SND_ROUTE_LEFT); QscSetRoute(BURN_SND_QSND_OUTPUT_2, Cps2Volume / 39.0, BURN_SND_ROUTE_RIGHT); } #endif nDisplayEnd = nCpsCycles * (nFirstLine + 224) / nCpsNumScanlines; // Account for VBlank nInterrupt = 0; memset(nRasterline, 0, MAX_RASTER + 2 * sizeof(nRasterline[0])); // Determine which (if any) of the line counters generates the first IRQ bEnableAutoIrq50 = bEnableAutoIrq52 = false; nIrqLine50 = nIrqLine52 = nCpsNumScanlines; if (BURN_ENDIAN_SWAP_INT16(*((UINT16*)(CpsReg + 0x50))) & 0x8000) { bEnableAutoIrq50 = true; } if (bEnableAutoIrq50 || (BURN_ENDIAN_SWAP_INT16(*((UINT16*)(CpsReg + 0x4E))) & 0x0200) == 0) { nIrqLine50 = (BURN_ENDIAN_SWAP_INT16(*((UINT16*)(CpsReg + 0x50))) & 0x01FF); } if (BURN_ENDIAN_SWAP_INT16(*((UINT16*)(CpsReg + 0x52))) & 0x8000) { bEnableAutoIrq52 = true; } if (bEnableAutoIrq52 || (BURN_ENDIAN_SWAP_INT16(*((UINT16*)(CpsReg + 0x4E))) & 0x0200) == 0) { nIrqLine52 = (BURN_ENDIAN_SWAP_INT16(*((UINT16*)(CpsReg + 0x52))) & 0x01FF); } ScheduleIRQ(); SekIdle(nCpsCyclesExtra); if (nIrqCycles < nCpsCycles * nFirstLine / nCpsNumScanlines) { SekRun(nIrqCycles); DoIRQ(); } nNext = nCpsCycles * nFirstLine / nCpsNumScanlines; if (SekTotalCycles() < nNext) { SekRun(nNext - SekTotalCycles()); } CopyCpsReg(0); // Get inititial copy of registers CopyCpsFrg(0); // if (nIrqLine >= nCpsNumScanlines && (BURN_ENDIAN_SWAP_INT16(*((UINT16*)(CpsReg + 0x4E))) & 0x0200) == 0) { nIrqLine50 = BURN_ENDIAN_SWAP_INT16(*((UINT16*)(CpsReg + 0x50))) & 0x01FF; nIrqLine52 = BURN_ENDIAN_SWAP_INT16(*((UINT16*)(CpsReg + 0x52))) & 0x01FF; ScheduleIRQ(); } { nNext = (nDisplayEnd) / 3; // find out next cycle count to run to while (nNext > nIrqCycles && nInterrupt < MAX_RASTER) { SekRun(nIrqCycles - SekTotalCycles()); DoIRQ(); } SekRun(nNext - SekTotalCycles()); // run cpu nNext = (2 * nDisplayEnd) / 3; // find out next cycle count to run to while (nNext > nIrqCycles && nInterrupt < MAX_RASTER) { SekRun(nIrqCycles - SekTotalCycles()); DoIRQ(); } SekRun(nNext - SekTotalCycles()); // run cpu nNext = (3 * nDisplayEnd) / 3; // find out next cycle count to run to while (nNext > nIrqCycles && nInterrupt < MAX_RASTER) { SekRun(nIrqCycles - SekTotalCycles()); DoIRQ(); } SekRun(nNext - SekTotalCycles()); // run cpu } CpsObjGet(); // Get objects // nCpsCyclesSegment[0] = (nCpsCycles * nVBlank) / nCpsNumScanlines; // nDone += SekRun(nCpsCyclesSegment[0] - nDone); SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); // VBlank //if (pBurnDraw) CpsDraw(); SekRun(nCpsCycles - SekTotalCycles()); nCpsCyclesExtra = SekTotalCycles() - nCpsCycles; if (!Cps2DisableQSnd) QsndEndFrame(); SekClose(); // bprintf(PRINT_NORMAL, _T(" -\n")); #if 0 && defined FBA_DEBUG if (nInterrupt) { bprintf(PRINT_IMPORTANT, _T("Beam synchronized interrupt at line %2X.\r"), nRasterline[nInterrupt]); } else { bprintf(PRINT_NORMAL, _T("Beam synchronized interrupt disabled. \r")); } extern INT32 counter; if (counter) { bprintf(PRINT_NORMAL, _T("\n\nSlices start at: ")); for (i = 0; i < MAX_RASTER + 2; i++) { bprintf(PRINT_NORMAL, _T("%2X "), nRasterline[i]); } bprintf(PRINT_NORMAL, _T("\n")); for (i = 0; i < 0x80; i++) { if (*((UINT16*)(CpsSaveReg[0] + i * 2)) != *((UINT16*)(CpsSaveReg[nInterrupt] + i * 2))) { bprintf(PRINT_NORMAL, _T("Register %2X: %4X -> %4X\n"), i * 2, *((UINT16*)(CpsSaveReg[0] + i * 2)), *((UINT16*)(CpsSaveReg[nInterrupt] + i * 2))); } } bprintf(PRINT_NORMAL, _T("\n")); for (i = 0; i < 0x010; i++) { if (CpsSaveFrg[0][i] != CpsSaveFrg[nInterrupt][i]) { bprintf(PRINT_NORMAL, _T("FRG %X: %02X -> %02X\n"), i, CpsSaveFrg[0][i], CpsSaveFrg[nInterrupt][i]); } } bprintf(PRINT_NORMAL, _T("\n")); if (((CpsSaveFrg[0][4] << 8) | CpsSaveFrg[0][5]) != ((CpsSaveFrg[nInterrupt][4] << 8) | CpsSaveFrg[nInterrupt][5])) { bprintf(PRINT_NORMAL, _T("Layer-sprite priority: %04X -> %04X\n"), ((CpsSaveFrg[0][4] << 8) | CpsSaveFrg[0][5]), ((CpsSaveFrg[nInterrupt][4] << 8) | CpsSaveFrg[nInterrupt][5])); } bprintf(PRINT_NORMAL, _T("\n")); for (INT32 j = 0; j <= nInterrupt; j++) { if (j) { bprintf(PRINT_NORMAL, _T("IRQ : %i (triggered at line %3i)\n\n"), j, nRasterline[j]); } else { bprintf(PRINT_NORMAL, _T("Initial register status\n\n")); } for (i = 0; i < 0x080; i+= 8) { bprintf(PRINT_NORMAL, _T("%2X: %4X %4X %4X %4X %4X %4X %4X %4X\n"), i * 2, *((UINT16*)(CpsSaveReg[j] + 0 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 2 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 4 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 6 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 8 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 10 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 12 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 14 + i * 2))); } bprintf(PRINT_NORMAL, _T("\nFRG: ")); for (i = 0; i < 0x010; i++) { bprintf(PRINT_NORMAL, _T("%02X "), CpsSaveFrg[j][i]); } bprintf(PRINT_NORMAL, _T("\n\n")); } extern INT32 bRunPause; bRunPause = 1; counter = 0; } #endif return 0; }
INT32 Cps1Frame() { INT32 nDisplayEnd, nNext, i; if (CpsReset) { DrvReset(); } SekNewFrame(); if (Cps1Qs == 1) { QsndNewFrame(); } else { if (!Cps1DisablePSnd) { ZetOpen(0); PsndNewFrame(); } } if (CpsRunFrameStartCallbackFunction) { CpsRunFrameStartCallbackFunction(); } nCpsCycles = (INT32)((INT64)nCPS68KClockspeed * nBurnCPUSpeedAdjust >> 8); CpsRwGetInp(); // Update the input port values nDisplayEnd = (nCpsCycles * (nFirstLine + 224)) / nCpsNumScanlines; // Account for VBlank SekOpen(0); SekIdle(nCpsCyclesExtra); SekRun(nCpsCycles * nFirstLine / nCpsNumScanlines); // run 68K for the first few lines CpsObjGet(); // Get objects for (i = 0; i < 4; i++) { nNext = ((i + 1) * nCpsCycles) >> 2; // find out next cycle count to run to if (i == 2 && CpsRunFrameMiddleCallbackFunction) { CpsRunFrameMiddleCallbackFunction(); } if (SekTotalCycles() < nDisplayEnd && nNext > nDisplayEnd) { SekRun(nNext - nDisplayEnd); // run 68K memcpy(CpsSaveReg[0], CpsReg, 0x100); // Registers correct now SekSetIRQLine(Cps1VBlankIRQLine, SEK_IRQSTATUS_AUTO); // Trigger VBlank interrupt } SekRun(nNext - SekTotalCycles()); // run 68K // if (pBurnDraw) { // CpsDraw(); // Draw frame // } } //if (pBurnDraw) { CpsDraw(); // Draw frame if (Cps1Qs == 1) { QsndEndFrame(); } else { if (!Cps1DisablePSnd) { PsndSyncZ80(nCpsZ80Cycles); PsmUpdate(nBurnSoundLen); ZetClose(); } } if (CpsRunFrameEndCallbackFunction) { CpsRunFrameEndCallbackFunction(); } nCpsCyclesExtra = SekTotalCycles() - nCpsCycles; SekClose(); return 0; }
inline static double DrvGetTime() { return (double)SekTotalCycles() / 10000000; }
static int dec0SynchroniseStream(int nSoundRate) { int result = (long long)SekTotalCycles() * nSoundRate / 10000000; BurnTimerUpdate(result); return result; }
static int DrvFrame() { int nInterleave = 4; if (DrvReset) { DrvDoReset(); } memset (DrvInputs, 0, 3); for (int i = 0; i < 8; i++) { DrvInputs[0] |= (DrvJoy1[i] & 1) << i; DrvInputs[1] |= (DrvJoy2[i] & 1) << i; DrvInputs[2] |= (DrvJoy3[i] & 1) << i; } ToaClearOpposites(&DrvInputs[0]); ToaClearOpposites(&DrvInputs[1]); SekOpen(0); SekNewFrame(); SekIdle(nCyclesDone[0]); nCyclesTotal[0] = (int)((long long)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); SekSetCyclesScanline(nCyclesTotal[0] / 262); nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); bVBlank = false; for (int i = 0; i < nInterleave; i++) { int nNext; // Run 68000 nNext = (i + 1) * nCyclesTotal[0] / nInterleave; // Trigger VBlank interrupt if (nNext > nToaCyclesVBlankStart) { if (SekTotalCycles() < nToaCyclesVBlankStart) { nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); SekRun(nCyclesSegment); } if (pBurnDraw) { DrvDraw(); } ToaBufferFCU2Sprites(); bVBlank = true; if (bEnableInterrupts) { SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); } } nCyclesSegment = nNext - SekTotalCycles(); if (bVBlank || (!CheckSleep(0))) { SekRun(nCyclesSegment); } else { SekIdle(nCyclesSegment); } } nToa1Cycles68KSync = SekTotalCycles(); // BurnTimerEndFrameYM3812(nCyclesTotal[1]); // BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; // bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); ToaBufferFCU2Sprites(); SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); // sprite buffer finished... SekClose(); return 0; }