Skip to content
This repository has been archived by the owner on Oct 4, 2020. It is now read-only.

Commit

Permalink
PPU: Added option to emulate OAM row corruption when disabling render…
Browse files Browse the repository at this point in the history
…ing at certain points during rendering
  • Loading branch information
SourMesen committed Apr 30, 2020
1 parent bf6d161 commit 59fddb7
Show file tree
Hide file tree
Showing 17 changed files with 1,008 additions and 904 deletions.
2 changes: 2 additions & 0 deletions Core/EmulationSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ enum EmulationFlags : uint64_t

PauseOnMovieEnd = 0x0100,

EnablePpuOamRowCorruption = 0x0200,

AllowBackgroundInput = 0x0400,
ReduceSoundInBackground = 0x0800,
MuteSoundInBackground = 0x1000,
Expand Down
60 changes: 60 additions & 0 deletions Core/PPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ PPU::PPU(shared_ptr<Console> console)
0x09, 0x01, 0x34, 0x03, 0x00, 0x04, 0x00, 0x14, 0x08, 0x3A, 0x00, 0x02, 0x00, 0x20, 0x2C, 0x08 };
memcpy(_paletteRAM, paletteRamBootValues, sizeof(_paletteRAM));

//This should (presumably) persist across resets
memset(_corruptOamRow, 0, sizeof(_corruptOamRow));

_console->InitializeRam(_spriteRAM, 0x100);
_console->InitializeRam(_secondarySpriteRAM, 0x20);

Expand Down Expand Up @@ -546,6 +549,11 @@ void PPU::SetMaskRegister(uint8_t value)

if(_renderingEnabled != (_flags.BackgroundEnabled | _flags.SpritesEnabled)) {
_needStateUpdate = true;

if(_renderingEnabled && _scanline < 240) {
//Rendering was just disabled by the write
SetOamCorruptionFlags();
}
}

UpdateMinimumDrawCycles();
Expand Down Expand Up @@ -1222,6 +1230,49 @@ void PPU::DebugUpdateFrameBuffer(bool toGrayscale)
}
}

void PPU::SetOamCorruptionFlags()
{
if(!_settings->CheckFlag(EmulationFlags::EnablePpuOamRowCorruption)) {
return;
}

//Note: Still pending more research, but this currently matches a portion of the issues that have been observed
//When rendering is disabled in some sections of the screen, either:
// A- During Secondary OAM clear (first ~64 cycles)
// B- During OAM tile fetching (cycle ~256 to cycle ~320)
//then OAM memory gets corrupted the next time the PPU starts rendering again (usually at the start of the next frame)
//This usually causes the first "row" of OAM (the first 8 bytes) to get copied over another, causing some sprites to be missing
//and causing an extra set of the first 2 sprites to appear on the screen (not possible to see them except via any overflow they may cause)

if(_cycle >= 1 && _cycle < 65) {
//Every 2 dots causes the corruption to shift down 1 OAM row (8 bytes)
_corruptOamRow[(_cycle - 1) >> 1] = true;
} else if(_cycle >= 257 && _cycle < 321) {
//This section is in 8-dot segments.
//The first 3 dot increment the corrupted row by 1, and then the last 5 dots corrupt the next row for 5 dots.
uint8_t base = (_cycle - 257) >> 3;
uint8_t offset = std::min<uint8_t>(3, (_cycle - 257) & 0x07);
_corruptOamRow[base * 4 + offset] = true;
}
}

void PPU::ProcessOamCorruption()
{
if(!_settings->CheckFlag(EmulationFlags::EnablePpuOamRowCorruption)) {
return;
}

//Copy first OAM row over another row, as needed by corruption flags (can be over itself, which causes no actual harm)
for(int i = 0; i < 32; i++) {
if(_corruptOamRow[i]) {
if(i > 0) {
memcpy(_spriteRAM + i * 8, _spriteRAM, 8);
}
_corruptOamRow[i] = false;
}
}
}

void PPU::Exec()
{
if(_cycle > 339) {
Expand All @@ -1233,6 +1284,10 @@ void PPU::Exec()
//Force prerender scanline sprite fetches to load the dummy $FF tiles (fixes shaking in Ninja Gaiden 3 stage 1 after beating boss)
_spriteCount = 0;

if(_renderingEnabled) {
ProcessOamCorruption();
}

UpdateMinimumDrawCycles();
}

Expand Down Expand Up @@ -1297,6 +1352,9 @@ void PPU::UpdateState()
_prevRenderingEnabled = _renderingEnabled;
if(_renderingEnabled != (_flags.BackgroundEnabled | _flags.SpritesEnabled)) {
_renderingEnabled = _flags.BackgroundEnabled | _flags.SpritesEnabled;
if(_renderingEnabled) {
ProcessOamCorruption();
}
}
if(_prevRenderingEnabled != _renderingEnabled) {
_needStateUpdate = true;
Expand Down Expand Up @@ -1436,6 +1494,8 @@ void PPU::StreamState(bool saving)
_oamDecayCycles[i] = _console->GetCpu()->GetCycleCount();
}

memset(_corruptOamRow, 0, sizeof(_corruptOamRow));

for(int i = 0; i < 257; i++) {
_hasSprite[i] = true;
}
Expand Down
4 changes: 4 additions & 0 deletions Core/PPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class PPU : public IMemoryHandler, public Snapshotable

uint64_t _oamDecayCycles[0x40];
bool _enableOamDecay;
bool _corruptOamRow[32];

void UpdateStatusFlag();

Expand Down Expand Up @@ -140,6 +141,9 @@ class PPU : public IMemoryHandler, public Snapshotable

__forceinline uint8_t ReadSpriteRam(uint8_t addr);
__forceinline void WriteSpriteRam(uint8_t addr, uint8_t value);

void SetOamCorruptionFlags();
void ProcessOamCorruption();

void UpdateMinimumDrawCycles();

Expand Down
2 changes: 2 additions & 0 deletions GUI.NET/Config/EmulationInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class EmulationInfo
public bool RandomizeCpuPpuAlignment = false;
public bool EnablePpu2006ScrollGlitch = false;
public bool EnablePpu2000ScrollGlitch = false;
public bool EnablePpuOamRowCorruption = false;

public bool UseAlternativeMmc3Irq = false;

Expand Down Expand Up @@ -65,6 +66,7 @@ static public void ApplyConfig()
InteropEmu.SetFlag(EmulationFlags.RandomizeCpuPpuAlignment, emulationInfo.RandomizeCpuPpuAlignment);
InteropEmu.SetFlag(EmulationFlags.EnablePpu2000ScrollGlitch, emulationInfo.EnablePpu2000ScrollGlitch);
InteropEmu.SetFlag(EmulationFlags.EnablePpu2006ScrollGlitch, emulationInfo.EnablePpu2006ScrollGlitch);
InteropEmu.SetFlag(EmulationFlags.EnablePpuOamRowCorruption, emulationInfo.EnablePpuOamRowCorruption);

InteropEmu.SetPpuNmiConfig(emulationInfo.PpuExtraScanlinesBeforeNmi, emulationInfo.PpuExtraScanlinesAfterNmi);

Expand Down
1 change: 1 addition & 0 deletions GUI.NET/Dependencies/resources.ca.xml
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@
<Control ID="chkRandomizeCpuPpuAlignment">Randomize power-on/reset CPU/PPU alignment</Control>
<Control ID="chkEnablePpu2006ScrollGlitch">Enable PPU $2006 scroll glitch emulation</Control>
<Control ID="chkEnablePpu2000ScrollGlitch">Enable PPU $2000/$2005/$2006 first-write scroll glitch emulation</Control>
<Control ID="chkEnablePpuOamRowCorruption">Enable PPU OAM row corruption emulation</Control>

<Control ID="tpgOverclocking">Forçament</Control>
<Control ID="grpOverclocking">Forçament de CPU</Control>
Expand Down
5 changes: 3 additions & 2 deletions GUI.NET/Dependencies/resources.en.xml
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@
<Control ID="lblMiscSettings">Miscellaneous Settings</Control>
<Control ID="chkUseAlternativeMmc3Irq">Use alternative MMC3 IRQ behavior</Control>
<Control ID="chkAllowInvalidInput">Allow invalid input (e.g Down + Up or Left + Right at the same time)</Control>
<Control ID="chkEnableOamDecay">Enable OAM RAM decay</Control>
<Control ID="chkEnableOamDecay">Enable PPU OAM decay</Control>
<Control ID="chkDisablePpu2004Reads">Disable PPU $2004 reads (Famicom behavior)</Control>
<Control ID="chkDisableOamAddrBug">Disable PPU OAMADDR bug emulation</Control>
<Control ID="chkDisablePaletteRead">Disable PPU palette reads</Control>
Expand All @@ -327,7 +327,8 @@
<Control ID="chkRandomizeCpuPpuAlignment">Randomize power-on/reset CPU/PPU alignment</Control>
<Control ID="chkEnablePpu2006ScrollGlitch">Enable PPU $2006 scroll glitch emulation</Control>
<Control ID="chkEnablePpu2000ScrollGlitch">Enable PPU $2000/$2005/$2006 first-write scroll glitch emulation</Control>

<Control ID="chkEnablePpuOamRowCorruption">Enable PPU OAM row corruption emulation</Control>

<Control ID="lblRamPowerOnState">Default power on state for RAM:</Control>

<Control ID="tpgOverclocking">Overclocking</Control>
Expand Down
1 change: 1 addition & 0 deletions GUI.NET/Dependencies/resources.es.xml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@
<Control ID="chkRandomizeCpuPpuAlignment">Aleatorizar el encendido/reinicio de la alineación CPU/PPU</Control>
<Control ID="chkEnablePpu2006ScrollGlitch">Habilitar el fallo de emulación de scroll PPU $2006</Control>
<Control ID="chkEnablePpu2000ScrollGlitch">Habilitar el fallo de emulación de scroll de primera escritura PPU $2000/$2005/$2006</Control>
<Control ID="chkEnablePpuOamRowCorruption">Enable PPU OAM row corruption emulation</Control>

<Control ID="tpgOverclocking">Overclocking</Control>
<Control ID="grpOverclocking">Overclocking de CPU</Control>
Expand Down
1 change: 1 addition & 0 deletions GUI.NET/Dependencies/resources.fr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@
<Control ID="chkRandomizeCpuPpuAlignment">Démarrer le jeu avec un alignement CPU/PPU aléatoire</Control>
<Control ID="chkEnablePpu2006ScrollGlitch">Simuler le bug de scrolling lors de l'écriture à $2006</Control>
<Control ID="chkEnablePpu2000ScrollGlitch">Simuler le bug de scrolling lors de l'écriture à $2000/$2005/$2006</Control>
<Control ID="chkEnablePpuOamRowCorruption">Simuler le bug de corruption de la rangée OAM</Control>

<Control ID="lblRamPowerOnState">État initial de la mémoire au démarrage : </Control>

Expand Down
1 change: 1 addition & 0 deletions GUI.NET/Dependencies/resources.it.xml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@
<Control ID="chkRandomizeCpuPpuAlignment">Randomize power-on/reset CPU/PPU alignment</Control>
<Control ID="chkEnablePpu2006ScrollGlitch">Enable PPU $2006 scroll glitch emulation</Control>
<Control ID="chkEnablePpu2000ScrollGlitch">Enable PPU $2000/$2005/$2006 first-write scroll glitch emulation</Control>
<Control ID="chkEnablePpuOamRowCorruption">Enable PPU OAM row corruption emulation</Control>

<Control ID="lblRamPowerOnState">Stato di accensione predefinito per la RAM:</Control>

Expand Down
1 change: 1 addition & 0 deletions GUI.NET/Dependencies/resources.ja.xml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@
<Control ID="chkRandomizeCpuPpuAlignment">ランダムなCPU/PPUアラインメントでゲームを起動する</Control>
<Control ID="chkEnablePpu2006ScrollGlitch">$2006に書き込む時に発生するスクロールバグを再現する</Control>
<Control ID="chkEnablePpu2000ScrollGlitch">$2000・$2005・$2006に書き込む時に発生するスクロールバグを再現する</Control>
<Control ID="chkEnablePpuOamRowCorruption">OAM行のデータの汚染を再現する</Control>

<Control ID="lblRamPowerOnState">起動時のメモリの状態 : </Control>

Expand Down
1 change: 1 addition & 0 deletions GUI.NET/Dependencies/resources.pt.xml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@
<Control ID="chkRandomizeCpuPpuAlignment">Aleatorizar o ligar/reiniciar do alinhamento da CPU/PPU</Control>
<Control ID="chkEnablePpu2006ScrollGlitch">Ativar emulação do erro gráfico PPU $2006 na rolagem</Control>
<Control ID="chkEnablePpu2000ScrollGlitch">Ativar emulação do erro gráfico PPU $2000/$2005/$2006 na rolagem na primeira escrita</Control>
<Control ID="chkEnablePpuOamRowCorruption">Enable PPU OAM row corruption emulation</Control>

<Control ID="lblRamPowerOnState">Estado inicial da RAM durante o início:</Control>

Expand Down
1 change: 1 addition & 0 deletions GUI.NET/Dependencies/resources.ru.xml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@
<Control ID="chkRandomizeCpuPpuAlignment">Рандомизировать включение/перезагрузку выравнивания CPU/PPU</Control>
<Control ID="chkEnablePpu2006ScrollGlitch">Включить PPU $2006 scroll glitch emulation</Control>
<Control ID="chkEnablePpu2000ScrollGlitch">Включить PPU $2000/$2005/$2006 first-write scroll glitch emulation</Control>
<Control ID="chkEnablePpuOamRowCorruption">Enable PPU OAM row corruption emulation</Control>

<Control ID="tpgOverclocking">Разгон</Control>
<Control ID="grpOverclocking">Разгон CPU</Control>
Expand Down
1 change: 1 addition & 0 deletions GUI.NET/Dependencies/resources.uk.xml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@
<Control ID="chkRandomizeCpuPpuAlignment">Randomize power-on/reset CPU/PPU alignment</Control>
<Control ID="chkEnablePpu2006ScrollGlitch">Enable PPU $2006 scroll glitch emulation</Control>
<Control ID="chkEnablePpu2000ScrollGlitch">Enable PPU $2000/$2005/$2006 first-write scroll glitch emulation</Control>
<Control ID="chkEnablePpuOamRowCorruption">Enable PPU OAM row corruption emulation</Control>

<Control ID="tpgOverclocking">Розгін</Control>
<Control ID="grpOverclocking">Розгін CPU</Control>
Expand Down
1 change: 1 addition & 0 deletions GUI.NET/Dependencies/resources.zh.xml
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@
<Control ID="chkRandomizeCpuPpuAlignment">随机 CPU/PPU 开机对齐</Control>
<Control ID="chkEnablePpu2006ScrollGlitch">模拟 PPU $2006 卷轴故障</Control>
<Control ID="chkEnablePpu2000ScrollGlitch">模拟首次写入 PPU $2000/$2005/$2006 卷轴故障</Control>
<Control ID="chkEnablePpuOamRowCorruption">Enable PPU OAM row corruption emulation</Control>

<Control ID="lblRamPowerOnState">默认开机 RAM 状态:</Control>
<Control ID="tpgOverclocking">超频</Control>
Expand Down
Loading

0 comments on commit 59fddb7

Please sign in to comment.