Skip to content

Commit

Permalink
SNES: Fixed regression in Kawasaki Carribean Challenge (palette corru…
Browse files Browse the repository at this point in the history
…ption)

Caused by CGRAM writes on scanline 0 being blocked, even though they apparently should work correctly
  • Loading branch information
SourMesen committed Dec 25, 2024
1 parent 0dfc8ac commit 44337e5
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 24 deletions.
43 changes: 19 additions & 24 deletions Core/SNES/SnesPpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,16 @@ bool SnesPpu::IsDoubleWidth()
return _state.HiResMode || _state.BgMode == 5 || _state.BgMode == 6;
}

bool SnesPpu::CanAccessCgram()
{
return _scanline >= _nmiScanline || _scanline == 0 || _state.ForcedBlank || _memoryManager->GetHClock() < 88 || _memoryManager->GetHClock() >= 1096;
}

bool SnesPpu::CanAccessVram()
{
return _scanline >= _nmiScanline || _state.ForcedBlank;
}

void SnesPpu::SetLocationLatchRequest(uint16_t x, uint16_t y)
{
//Used by super scope
Expand Down Expand Up @@ -1672,14 +1682,9 @@ uint16_t SnesPpu::GetOamAddress()

void SnesPpu::UpdateVramReadBuffer()
{
uint16_t addr = GetVramAddress();
if(_scanline >= _nmiScanline || _state.ForcedBlank) {
_state.VramReadBuffer = _vram[addr];
} else {
//During rendering, this can't read the correct VRAM address
//Unknown: does it read from the address the ppu is currently reading from (like oam/cgram)?
_state.VramReadBuffer = 0;
}
//During rendering, this can't read the correct VRAM address
//Unknown: does it read from the address the ppu is currently reading from (like oam/cgram)?
_state.VramReadBuffer = CanAccessVram() ? _vram[GetVramAddress()] : 0;
}

uint16_t SnesPpu::GetVramAddress()
Expand Down Expand Up @@ -1768,13 +1773,8 @@ uint8_t SnesPpu::Read(uint16_t addr)
//CGDATAREAD - CGRAM Data read
uint8_t value;

uint16_t cgAddr;
if(_scanline >= _nmiScanline || _state.ForcedBlank || _memoryManager->GetHClock() < 88 || _memoryManager->GetHClock() >= 1096) {
cgAddr = _state.CgramAddress;
} else {
//During rendering, writes to CGRAM end up writing to the address the PPU is currently reading
cgAddr = _state.InternalCgramAddress;
}
//During rendering, reads to CGRAM end up returning the value a the address the PPU is currently reading
uint16_t cgAddr = CanAccessCgram() ? _state.CgramAddress : _state.InternalCgramAddress;

if(_state.CgramAddressLatch){
value = ((_cgram[cgAddr] >> 8) & 0x7F) | (_state.Ppu2OpenBus & 0x80);
Expand Down Expand Up @@ -2040,7 +2040,7 @@ void SnesPpu::Write(uint32_t addr, uint8_t value)

case 0x2118:
//VMDATAL - VRAM Data Write low byte
if(_scanline >= _nmiScanline || _state.ForcedBlank) {
if(CanAccessVram()) {
//Only write the value if in vblank or forced blank (writes to VRAM outside vblank/forced blank are not allowed)
_emu->ProcessPpuWrite<CpuType::Snes>(GetVramAddress() << 1, value, MemoryType::SnesVideoRam);
_vram[GetVramAddress()] = value | (_vram[GetVramAddress()] & 0xFF00);
Expand All @@ -2054,7 +2054,7 @@ void SnesPpu::Write(uint32_t addr, uint8_t value)

case 0x2119:
//VMDATAH - VRAM Data Write high byte
if(_scanline >= _nmiScanline || _state.ForcedBlank) {
if(CanAccessVram()) {
//Only write the value if in vblank or forced blank (writes to VRAM outside vblank/forced blank are not allowed)
_emu->ProcessPpuWrite<CpuType::Snes>((GetVramAddress() << 1) + 1, value, MemoryType::SnesVideoRam);
_vram[GetVramAddress()] = (value << 8) | (_vram[GetVramAddress()] & 0xFF);
Expand Down Expand Up @@ -2104,13 +2104,8 @@ void SnesPpu::Write(uint32_t addr, uint8_t value)
//MSB ignores the 7th bit (colors are 15-bit only)
value &= 0x7F;

uint16_t cgAddr;
if(_scanline >= _nmiScanline || _state.ForcedBlank || _memoryManager->GetHClock() < 88 || _memoryManager->GetHClock() >= 1096) {
cgAddr = _state.CgramAddress;
} else {
//During rendering, writes to CGRAM end up writing to the address the PPU is currently reading
cgAddr = _state.InternalCgramAddress;
}
//During rendering, writes to CGRAM end up writing to the address the PPU is currently reading
uint16_t cgAddr = CanAccessCgram() ? _state.CgramAddress : _state.InternalCgramAddress;

_emu->ProcessPpuWrite<CpuType::Snes>(cgAddr << 1, _state.CgramWriteBuffer, MemoryType::SnesCgRam);
_emu->ProcessPpuWrite<CpuType::Snes>((cgAddr << 1) + 1, value, MemoryType::SnesCgRam);
Expand Down
3 changes: 3 additions & 0 deletions Core/SNES/SnesPpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ class SnesPpu : public ISerializable
bool IsDoubleHeight();
bool IsDoubleWidth();

bool CanAccessCgram();
bool CanAccessVram();

void EvaluateNextLineSprites();
void FetchSpriteData();
__forceinline void FetchSpritePosition(uint8_t oamAddress);
Expand Down

0 comments on commit 44337e5

Please sign in to comment.