void S9xDoHBlankProcessing () { START_PROFILE_FUNC (S9xDoHBlankProcessing); #ifdef CPU_SHUTDOWN CPU.WaitCounter++; #endif switch (CPU.WhichEvent) { case HBLANK_START_EVENT: if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); break; case HBLANK_END_EVENT: S9xSuperFXExec (); CPU.Cycles -= Settings.H_Max; (IAPUuncached->NextAPUTimerPos) -= (Settings.H_Max * 10000L); if ( (IAPUuncached->APUExecuting)) (APUuncached->Cycles) -= Settings.H_Max; else (APUuncached->Cycles) = 0; CPU.NextEvent = -1; ICPU.Scanline++; if (++CPU.V_Counter > (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) { PPU.OAMAddr = PPU.SavedOAMAddr; PPU.OAMFlip = 0; CPU.V_Counter = 0; CPU.NMIActive = FALSE; ICPU.Frame++; PPU.HVBeamCounterLatched = 0; CPU.Flags |= SCAN_KEYS_FLAG; S9xStartHDMA (); } if (PPU.VTimerEnabled && !PPU.HTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos) { S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); } if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) { // Start of V-blank S9xEndScreenRefresh (); PPU.FirstSprite = 0; IPPU.HDMA = 0; // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. missing.dma_this_frame = 0; IPPU.MaxBrightness = PPU.Brightness; PPU.ForcedBlanking = (FillRAM[0x2100] >> 7) & 1; FillRAM[0x4210] = 0x80; if (FillRAM[0x4200] & 0x80) { CPU.NMIActive = TRUE; CPU.Flags |= NMI_FLAG; CPU.NMICycleCount = CPU.NMITriggerPoint; } } if (CPU.V_Counter == PPU.ScreenHeight + 3) S9xUpdateJoypads (); if (CPU.V_Counter == FIRST_VISIBLE_LINE) { FillRAM[0x4210] = 0; CPU.Flags &= ~NMI_FLAG; S9xStartScreenRefresh (); } if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) { RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE); } break; case HTIMER_BEFORE_EVENT: case HTIMER_AFTER_EVENT: if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)) { S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE); } break; }
void S9xDoHBlankProcessing (struct SCPUState *cpu, struct SAPU *apu, struct SIAPU *iapu) { struct SPPU *ppu = &PPU; struct InternalPPU *ippu = &IPPU; #ifdef CPU_SHUTDOWN cpu->WaitCounter++; #endif switch (cpu->WhichEvent) { case HBLANK_START_EVENT: if (ippu->HDMA && cpu->V_Counter <= ppu->ScreenHeight) ippu->HDMA = S9xDoHDMA (ippu, ppu, cpu); break; case HBLANK_END_EVENT: #ifndef _ZAURUS S9xSuperFXExec (); #endif #ifndef STORM #endif cpu->Cycles -= Settings.H_Max; if (iapu->APUExecuting) apu->Cycles -= Settings.H_Max; else apu->Cycles = 0; cpu->NextEvent = -1; ICPU.Scanline++; if (++cpu->V_Counter > (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) { ppu->OAMAddr = ppu->SavedOAMAddr; ppu->OAMFlip = 0; cpu->V_Counter = 0; cpu->NMIActive = FALSE; ICPU.Frame++; ppu->HVBeamCounterLatched = 0; cpu->Flags |= SCAN_KEYS_FLAG; S9xStartHDMA (); } if (ppu->VTimerEnabled && !ppu->HTimerEnabled && cpu->V_Counter == ppu->IRQVBeamPos) { S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE, cpu); } if (cpu->V_Counter == ppu->ScreenHeight + FIRST_VISIBLE_LINE) { // Start of V-blank S9xEndScreenRefresh (ppu); ppu->FirstSprite = 0; ippu->HDMA = 0; // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. missing.dma_this_frame = 0; ippu->MaxBrightness = ppu->Brightness; ppu->ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; Memory.FillRAM[0x4210] = 0x80; if (Memory.FillRAM[0x4200] & 0x80) { cpu->NMIActive = TRUE; cpu->Flags |= NMI_FLAG; cpu->NMICycleCount = cpu->NMITriggerPoint; } #ifdef OLD_SNAPSHOT_CODE if (cpu->Flags & SAVE_SNAPSHOT_FLAG) { cpu->Flags &= ~SAVE_SNAPSHOT_FLAG; Registers.PC = cpu->PC - cpu->PCBase; S9xPackStatus (); S9xAPUPackStatus (); Snapshot (NULL); } #endif } if (cpu->V_Counter == ppu->ScreenHeight + 3) S9xUpdateJoypads (&IPPU); if (cpu->V_Counter == FIRST_VISIBLE_LINE) { Memory.FillRAM[0x4210] = 0; cpu->Flags &= ~NMI_FLAG; S9xStartScreenRefresh (); } if (cpu->V_Counter >= FIRST_VISIBLE_LINE && cpu->V_Counter < ppu->ScreenHeight + FIRST_VISIBLE_LINE) { RenderLine (cpu->V_Counter - FIRST_VISIBLE_LINE, ppu); } // Use TimerErrorCounter to skip update of SPC700 timers once // every 128 updates. Needed because this section of code is called // once every emulated 63.5 microseconds, which coresponds to // 15.750KHz, but the SPC700 timers need to be updated at multiples // of 8KHz, hence the error correction. // IAPU.TimerErrorCounter++; // if (IAPU.TimerErrorCounter >= ) // IAPU.TimerErrorCounter = 0; // else { if (apu->TimerEnabled [2]) { apu->Timer [2] += 4; while (apu->Timer [2] >= apu->TimerTarget [2]) { iapu->RAM [0xff] = (iapu->RAM [0xff] + 1) & 0xf; apu->Timer [2] -= apu->TimerTarget [2]; #ifdef SPC700_SHUTDOWN iapu->WaitCounter++; iapu->APUExecuting = TRUE; #endif } } if (cpu->V_Counter & 1) { if (apu->TimerEnabled [0]) { apu->Timer [0]++; if (apu->Timer [0] >= apu->TimerTarget [0]) { iapu->RAM [0xfd] = (iapu->RAM [0xfd] + 1) & 0xf; apu->Timer [0] = 0; #ifdef SPC700_SHUTDOWN iapu->WaitCounter++; iapu->APUExecuting = TRUE; #endif } } if (apu->TimerEnabled [1]) { apu->Timer [1]++; if (apu->Timer [1] >= apu->TimerTarget [1]) { iapu->RAM [0xfe] = (iapu->RAM [0xfe] + 1) & 0xf; apu->Timer [1] = 0; #ifdef SPC700_SHUTDOWN iapu->WaitCounter++; iapu->APUExecuting = TRUE; #endif } } } } break; //HBLANK_END_EVENT case HTIMER_BEFORE_EVENT: case HTIMER_AFTER_EVENT: if (ppu->HTimerEnabled && (!ppu->VTimerEnabled || cpu->V_Counter == ppu->IRQVBeamPos)) { S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE, cpu); } break; }
void S9xDoHBlankProcessing () { #ifdef CPU_SHUTDOWN CPU.WaitCounter++; #endif switch (CPU.WhichEvent) { case HBLANK_START_EVENT: if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); break; case HBLANK_END_EVENT: S9xSuperFXExec (); #ifndef STORM if (Settings.SoundSync) S9xGenerateSound (); #endif CPU.Cycles -= Settings.H_Max; if (IAPU.APUExecuting) APU.Cycles -= Settings.H_Max; else APU.Cycles = 0; CPU.NextEvent = -1; ICPU.Scanline++; if (++CPU.V_Counter > (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) { PPU.OAMAddr = PPU.SavedOAMAddr; PPU.OAMFlip = 0; CPU.V_Counter = 0; CPU.NMIActive = FALSE; ICPU.Frame++; PPU.HVBeamCounterLatched = 0; CPU.Flags |= SCAN_KEYS_FLAG; S9xStartHDMA (); } if (PPU.VTimerEnabled && !PPU.HTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos) { S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); } if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) { // Start of V-blank S9xEndScreenRefresh (); PPU.FirstSprite = 0; IPPU.HDMA = 0; // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. missing.dma_this_frame = 0; IPPU.MaxBrightness = PPU.Brightness; PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; Memory.FillRAM[0x4210] = 0x80; if (Memory.FillRAM[0x4200] & 0x80) { CPU.NMIActive = TRUE; CPU.Flags |= NMI_FLAG; CPU.NMICycleCount = CPU.NMITriggerPoint; } #ifdef OLD_SNAPSHOT_CODE if (CPU.Flags & SAVE_SNAPSHOT_FLAG) { CPU.Flags &= ~SAVE_SNAPSHOT_FLAG; Registers.PC = CPU.PC - CPU.PCBase; S9xPackStatus (); S9xAPUPackStatus (); Snapshot (NULL); } #endif } if (CPU.V_Counter == PPU.ScreenHeight + 3) S9xUpdateJoypads (); if (CPU.V_Counter == FIRST_VISIBLE_LINE) { Memory.FillRAM[0x4210] = 0; CPU.Flags &= ~NMI_FLAG; S9xStartScreenRefresh (); } if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) { RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE); } // Use TimerErrorCounter to skip update of SPC700 timers once // every 128 updates. Needed because this section of code is called // once every emulated 63.5 microseconds, which coresponds to // 15.750KHz, but the SPC700 timers need to be updated at multiples // of 8KHz, hence the error correction. // IAPU.TimerErrorCounter++; // if (IAPU.TimerErrorCounter >= ) // IAPU.TimerErrorCounter = 0; // else { if (APU.TimerEnabled [2]) { APU.Timer [2] += 4; while (APU.Timer [2] >= APU.TimerTarget [2]) { IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; APU.Timer [2] -= APU.TimerTarget [2]; #ifdef SPC700_SHUTDOWN IAPU.WaitCounter++; IAPU.APUExecuting = TRUE; #endif } } if (CPU.V_Counter & 1) { if (APU.TimerEnabled [0]) { APU.Timer [0]++; if (APU.Timer [0] >= APU.TimerTarget [0]) { IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf; APU.Timer [0] = 0; #ifdef SPC700_SHUTDOWN IAPU.WaitCounter++; IAPU.APUExecuting = TRUE; #endif } } if (APU.TimerEnabled [1]) { APU.Timer [1]++; if (APU.Timer [1] >= APU.TimerTarget [1]) { IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf; APU.Timer [1] = 0; #ifdef SPC700_SHUTDOWN IAPU.WaitCounter++; IAPU.APUExecuting = TRUE; #endif } } } } break; //HBLANK_END_EVENT case HTIMER_BEFORE_EVENT: case HTIMER_AFTER_EVENT: if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)) { S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE); } break; }