mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
NES: Added Rainbow support (mapper 682)
This commit is contained in:
parent
8e6846eaf6
commit
d751502a58
43 changed files with 2283 additions and 284 deletions
|
@ -20,6 +20,10 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="NES\Epsm.h" />
|
||||
<ClInclude Include="NES\Mappers\Homebrew\Rainbow.h" />
|
||||
<ClInclude Include="NES\Mappers\Homebrew\RainbowAudio.h" />
|
||||
<ClInclude Include="NES\Debugger\IExtModeMapperDebug.h" />
|
||||
<ClInclude Include="NES\Mappers\Homebrew\FlashS29.h" />
|
||||
<ClInclude Include="NES\OpnInterface.h" />
|
||||
<ClInclude Include="SMS\Input\ColecoVisionController.h" />
|
||||
<ClInclude Include="Debugger\AddressInfo.h" />
|
||||
|
@ -852,6 +856,7 @@
|
|||
<ClCompile Include="NES\APU\BaseExpansionAudio.cpp" />
|
||||
<ClCompile Include="NES\Loaders\StudyBoxLoader.cpp" />
|
||||
<ClCompile Include="NES\Loaders\UnifLoader.cpp" />
|
||||
<ClCompile Include="NES\Mappers\Homebrew\Rainbow.cpp" />
|
||||
<ClCompile Include="Shared\Utilities\emu2413.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='PGO Profile|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
|
|
|
@ -2928,6 +2928,18 @@
|
|||
<ClInclude Include="NES\OpnInterface.h">
|
||||
<Filter>NES</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NES\Mappers\Homebrew\Rainbow.h">
|
||||
<Filter>NES\Mappers\Homebrew</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NES\Mappers\Homebrew\RainbowAudio.h">
|
||||
<Filter>NES\Mappers\Homebrew</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NES\Debugger\IExtModeMapperDebug.h">
|
||||
<Filter>NES\Mappers\Homebrew</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NES\Mappers\Homebrew\FlashS29.h">
|
||||
<Filter>NES\Mappers\Homebrew</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Shared\Video\RotateFilter.cpp">
|
||||
|
@ -3266,6 +3278,9 @@
|
|||
<ClCompile Include="NES\Epsm.cpp">
|
||||
<Filter>NES</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NES\Mappers\Homebrew\Rainbow.cpp">
|
||||
<Filter>NES\Mappers\Homebrew</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="PCE">
|
||||
|
|
|
@ -101,6 +101,7 @@ public:
|
|||
case MemoryType::NesInternalRam:
|
||||
case MemoryType::NesMemory:
|
||||
case MemoryType::NesNametableRam:
|
||||
case MemoryType::NesMapperRam:
|
||||
case MemoryType::NesPaletteRam:
|
||||
case MemoryType::NesPpuMemory:
|
||||
case MemoryType::NesPrgRom:
|
||||
|
|
|
@ -242,12 +242,12 @@ public:
|
|||
|
||||
void GetTileView(GetTileViewOptions options, uint8_t *source, uint32_t srcSize, const uint32_t* palette, uint32_t *outBuffer);
|
||||
|
||||
virtual DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState) = 0;
|
||||
virtual DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState) = 0;
|
||||
virtual FrameInfo GetTilemapSize(GetTilemapOptions options, BaseState& state) = 0;
|
||||
virtual DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer) = 0;
|
||||
virtual DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer) = 0;
|
||||
|
||||
virtual DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state) = 0;
|
||||
virtual void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) = 0;
|
||||
virtual DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState) = 0;
|
||||
virtual void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) = 0;
|
||||
|
||||
int32_t GetTilePixel(AddressInfo tileAddress, TileFormat format, int32_t x, int32_t y);
|
||||
void SetTilePixel(AddressInfo tileAddress, TileFormat format, int32_t x, int32_t y, int32_t color);
|
||||
|
|
|
@ -15,7 +15,7 @@ void GbaPpuTools::SetMemoryAccessData(uint16_t scanline, uint8_t* data)
|
|||
memcpy(_memoryAccess + scanline * 308 * 4, data, 308 * 4);
|
||||
}
|
||||
|
||||
DebugTilemapInfo GbaPpuTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
DebugTilemapInfo GbaPpuTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
{
|
||||
GbaPpuState& state = (GbaPpuState&)baseState;
|
||||
FrameInfo outputSize = GetTilemapSize(options, state);
|
||||
|
@ -256,7 +256,7 @@ FrameInfo GbaPpuTools::GetTilemapSize(GetTilemapOptions options, BaseState& base
|
|||
return { 0, 0 };
|
||||
}
|
||||
|
||||
DebugTilemapTileInfo GbaPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
|
||||
DebugTilemapTileInfo GbaPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugTilemapTileInfo result = {};
|
||||
|
||||
|
@ -397,7 +397,7 @@ void GbaPpuTools::GetSpritePreview(GetSpritePreviewOptions options, BaseState& b
|
|||
}
|
||||
}
|
||||
|
||||
DebugSpritePreviewInfo GbaPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state)
|
||||
DebugSpritePreviewInfo GbaPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugSpritePreviewInfo info = {};
|
||||
info.Height = 256;
|
||||
|
@ -586,7 +586,7 @@ void GbaPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePreview
|
|||
}
|
||||
}
|
||||
|
||||
void GbaPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
void GbaPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
{
|
||||
GbaPpuState& state = (GbaPpuState&)baseState;
|
||||
for(int i = 0; i < 128; i++) {
|
||||
|
|
|
@ -20,12 +20,12 @@ public:
|
|||
|
||||
void SetMemoryAccessData(uint16_t scanline, uint8_t* data);
|
||||
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
FrameInfo GetTilemapSize(GetTilemapOptions options, BaseState& state) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState) override;
|
||||
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
|
||||
DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
|
||||
void SetPaletteColor(int32_t colorIndex, uint32_t color) override;
|
||||
|
|
|
@ -10,7 +10,7 @@ GbPpuTools::GbPpuTools(Debugger* debugger, Emulator *emu) : PpuTools(debugger, e
|
|||
{
|
||||
}
|
||||
|
||||
DebugTilemapInfo GbPpuTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
DebugTilemapInfo GbPpuTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
{
|
||||
GbPpuState& state = (GbPpuState&)baseState;
|
||||
uint32_t offset = options.Layer == 1 ? 0x1C00 : 0x1800;
|
||||
|
@ -108,7 +108,7 @@ FrameInfo GbPpuTools::GetTilemapSize(GetTilemapOptions options, BaseState& state
|
|||
return { 256, 256 };
|
||||
}
|
||||
|
||||
DebugTilemapTileInfo GbPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
|
||||
DebugTilemapTileInfo GbPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugTilemapTileInfo result = {};
|
||||
|
||||
|
@ -158,7 +158,7 @@ DebugTilemapTileInfo GbPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint
|
|||
return result;
|
||||
}
|
||||
|
||||
DebugSpritePreviewInfo GbPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state)
|
||||
DebugSpritePreviewInfo GbPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugSpritePreviewInfo info = {};
|
||||
info.Height = 256;
|
||||
|
@ -241,7 +241,7 @@ void GbPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePreview,
|
|||
}
|
||||
}
|
||||
|
||||
void GbPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
void GbPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
{
|
||||
GbPpuState& state = (GbPpuState&)baseState;
|
||||
for(int i = 0; i < 40; i++) {
|
||||
|
|
|
@ -16,12 +16,12 @@ private:
|
|||
public:
|
||||
GbPpuTools(Debugger* debugger, Emulator *emu);
|
||||
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
FrameInfo GetTilemapSize(GetTilemapOptions options, BaseState& state) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState) override;
|
||||
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
|
||||
DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
|
||||
void SetPaletteColor(int32_t colorIndex, uint32_t color) override;
|
||||
|
|
|
@ -138,14 +138,24 @@ void BaseMapper::SetCpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, PrgMe
|
|||
case PrgMemoryType::PrgRom: source = _prgRom; sourceSize = _prgSize; break;
|
||||
case PrgMemoryType::SaveRam: source = _saveRam; sourceSize = _saveRamSize; break;
|
||||
case PrgMemoryType::WorkRam: source = _workRam; sourceSize = _workRamSize; break;
|
||||
case PrgMemoryType::MapperRam: source = _mapperRam; sourceSize = _mapperRamSize; break;
|
||||
}
|
||||
|
||||
int firstSlot = startAddr >> 8;
|
||||
int slotCount = (endAddr - startAddr + 1) >> 8;
|
||||
for(int i = 0; i < slotCount; i++) {
|
||||
_prgMemoryOffset[firstSlot + i] = sourceOffset + i * 0x100;
|
||||
_prgMemoryType[firstSlot + i] = type;
|
||||
_prgMemoryAccess[firstSlot + i] = (MemoryAccessType)accessType;
|
||||
if(sourceSize == 0) {
|
||||
_prgPages[i] = nullptr;
|
||||
_prgMemoryAccess[i] = MemoryAccessType::NoAccess;
|
||||
} else {
|
||||
while(sourceOffset >= sourceSize) {
|
||||
sourceOffset -= sourceSize;
|
||||
}
|
||||
_prgPages[firstSlot + i] = source + sourceOffset;
|
||||
_prgMemoryOffset[firstSlot + i] = sourceOffset + i * 0x100;
|
||||
_prgMemoryType[firstSlot + i] = type;
|
||||
_prgMemoryAccess[firstSlot + i] = (MemoryAccessType)accessType;
|
||||
}
|
||||
}
|
||||
|
||||
SetCpuMemoryMapping(startAddr, endAddr, source, sourceOffset, sourceSize, accessType);
|
||||
|
@ -233,6 +243,9 @@ void BaseMapper::SetPpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, uint1
|
|||
pageCount = _nametableCount;
|
||||
defaultAccessType |= MemoryAccessType::Write;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new std::runtime_error("Invalid parameter");
|
||||
}
|
||||
|
||||
if(pageCount == 0) {
|
||||
|
@ -285,14 +298,27 @@ void BaseMapper::SetPpuMemoryMapping(uint16_t startAddr, uint16_t endAddr, ChrMe
|
|||
sourceMemory = _nametableRam;
|
||||
sourceSize = _ntRamSize;
|
||||
break;
|
||||
|
||||
case ChrMemoryType::MapperRam:
|
||||
sourceMemory = _mapperRam;
|
||||
sourceSize = _mapperRamSize;
|
||||
break;
|
||||
}
|
||||
|
||||
int firstSlot = startAddr >> 8;
|
||||
int slotCount = (endAddr - startAddr + 1) >> 8;
|
||||
for(int i = 0; i < slotCount; i++) {
|
||||
_chrMemoryOffset[firstSlot + i] = sourceOffset + i * 256;
|
||||
_chrMemoryType[firstSlot + i] = type;
|
||||
_chrMemoryAccess[firstSlot + i] = (MemoryAccessType)accessType;
|
||||
if(sourceSize == 0) {
|
||||
_chrPages[i] = nullptr;
|
||||
_chrMemoryAccess[i] = MemoryAccessType::NoAccess;
|
||||
} else {
|
||||
while(sourceOffset >= sourceSize) {
|
||||
sourceOffset -= sourceSize;
|
||||
}
|
||||
_chrMemoryOffset[firstSlot + i] = sourceOffset + i * 256;
|
||||
_chrMemoryType[firstSlot + i] = type;
|
||||
_chrMemoryAccess[firstSlot + i] = (MemoryAccessType)accessType;
|
||||
}
|
||||
}
|
||||
|
||||
SetPpuMemoryMapping(startAddr, endAddr, sourceMemory, sourceOffset, sourceSize, accessType);
|
||||
|
@ -534,6 +560,7 @@ void BaseMapper::Serialize(Serializer& s)
|
|||
SVArray(_chrRam, _chrRamSize);
|
||||
SVArray(_workRam, _workRamSize);
|
||||
SVArray(_saveRam, _saveRamSize);
|
||||
SVArray(_mapperRam, _mapperRamSize);
|
||||
SVArray(_nametableRam, _ntRamSize);
|
||||
|
||||
SVArray(_prgMemoryOffset, 0x100);
|
||||
|
@ -647,8 +674,13 @@ void BaseMapper::Initialize(NesConsole* console, RomData& romData)
|
|||
_workRam = new uint8_t[_workRamSize];
|
||||
_emu->RegisterMemory(MemoryType::NesWorkRam, _workRam, _workRamSize);
|
||||
|
||||
_mapperRamSize = GetMapperRamSize();
|
||||
_mapperRam = new uint8_t[_mapperRamSize];
|
||||
_emu->RegisterMemory(MemoryType::NesMapperRam, _mapperRam, _mapperRamSize);
|
||||
|
||||
_console->InitializeRam(_saveRam, _saveRamSize);
|
||||
_console->InitializeRam(_workRam, _workRamSize);
|
||||
_console->InitializeRam(_mapperRam, _mapperRamSize);
|
||||
|
||||
_nametableCount = GetNametableCount();
|
||||
if(_nametableCount == 0) {
|
||||
|
@ -728,6 +760,7 @@ BaseMapper::~BaseMapper()
|
|||
delete[] _prgRom;
|
||||
delete[] _saveRam;
|
||||
delete[] _workRam;
|
||||
delete[] _mapperRam;
|
||||
delete[] _nametableRam;
|
||||
}
|
||||
|
||||
|
@ -941,7 +974,16 @@ void BaseMapper::DebugWriteVram(uint16_t addr, uint8_t value, bool disableSideEf
|
|||
void BaseMapper::WriteVram(uint16_t addr, uint8_t value)
|
||||
{
|
||||
_emu->ProcessPpuWrite<CpuType::Nes>(addr, value, MemoryType::NesPpuMemory);
|
||||
MapperWriteVram(addr, value);
|
||||
}
|
||||
|
||||
void BaseMapper::MapperWriteVram(uint16_t addr, uint8_t value)
|
||||
{
|
||||
InternalWriteVram(addr, value);
|
||||
}
|
||||
|
||||
void BaseMapper::InternalWriteVram(uint16_t addr, uint8_t value)
|
||||
{
|
||||
if(_chrMemoryAccess[addr >> 8] & MemoryAccessType::Write) {
|
||||
_chrPages[addr >> 8][(uint8_t)addr] = value;
|
||||
}
|
||||
|
@ -969,16 +1011,19 @@ AddressInfo BaseMapper::GetAbsoluteAddress(uint16_t relativeAddr)
|
|||
info.Address = relativeAddr & _internalRamMask;
|
||||
info.Type = MemoryType::NesInternalRam;
|
||||
} else {
|
||||
uint8_t *prgAddr = _prgPages[relativeAddr >> 8] + (uint8_t)relativeAddr;
|
||||
if(prgAddr >= _prgRom && prgAddr < _prgRom + _prgSize) {
|
||||
info.Address = (uint32_t)(prgAddr - _prgRom);
|
||||
uint8_t *addr = _prgPages[relativeAddr >> 8] + (uint8_t)relativeAddr;
|
||||
if(addr >= _prgRom && addr < _prgRom + _prgSize) {
|
||||
info.Address = (uint32_t)(addr - _prgRom);
|
||||
info.Type = MemoryType::NesPrgRom;
|
||||
} else if(prgAddr >= _workRam && prgAddr < _workRam + _workRamSize) {
|
||||
info.Address = (uint32_t)(prgAddr - _workRam);
|
||||
} else if(addr >= _workRam && addr < _workRam + _workRamSize) {
|
||||
info.Address = (uint32_t)(addr - _workRam);
|
||||
info.Type = MemoryType::NesWorkRam;
|
||||
} else if(prgAddr >= _saveRam && prgAddr < _saveRam + _saveRamSize) {
|
||||
info.Address = (uint32_t)(prgAddr - _saveRam);
|
||||
} else if(addr >= _saveRam && addr < _saveRam + _saveRamSize) {
|
||||
info.Address = (uint32_t)(addr - _saveRam);
|
||||
info.Type = MemoryType::NesSaveRam;
|
||||
} else if(addr >= _mapperRam && addr < _mapperRam + _mapperRamSize) {
|
||||
info.Address = (uint32_t)(addr - _mapperRam);
|
||||
info.Type = MemoryType::NesMapperRam;
|
||||
} else {
|
||||
info.Address = -1;
|
||||
info.Type = MemoryType::None;
|
||||
|
@ -1000,6 +1045,9 @@ void BaseMapper::GetPpuAbsoluteAddress(uint16_t relativeAddr, AddressInfo& info)
|
|||
} else if(addr >= _chrRam && addr < _chrRam + _chrRamSize) {
|
||||
info.Address = (uint32_t)(addr - _chrRam);
|
||||
info.Type = MemoryType::NesChrRam;
|
||||
} else if(addr >= _mapperRam && addr < _mapperRam + _mapperRamSize) {
|
||||
info.Address = (uint32_t)(addr - _mapperRam);
|
||||
info.Type = MemoryType::NesMapperRam;
|
||||
} else if(addr >= _nametableRam && addr < _nametableRam + _nametableCount * BaseMapper::NametableSize) {
|
||||
info.Address = (uint32_t)(addr - _nametableRam);
|
||||
info.Type = MemoryType::NesNametableRam;
|
||||
|
@ -1025,6 +1073,7 @@ AddressInfo BaseMapper::GetRelativeAddress(AddressInfo& addr)
|
|||
case MemoryType::NesPrgRom: ptrAddress = _prgRom; break;
|
||||
case MemoryType::NesWorkRam: ptrAddress = _workRam; break;
|
||||
case MemoryType::NesSaveRam: ptrAddress = _saveRam; break;
|
||||
case MemoryType::NesMapperRam: ptrAddress = _mapperRam; break;
|
||||
case MemoryType::NesInternalRam: return { (int32_t)(addr.Address & _internalRamMask), MemoryType::NesMemory };
|
||||
default: return { GetPpuRelativeAddress(addr), MemoryType::NesPpuMemory };
|
||||
}
|
||||
|
@ -1049,6 +1098,7 @@ int32_t BaseMapper::GetPpuRelativeAddress(AddressInfo& addr)
|
|||
case MemoryType::NesChrRom: ptrAddress = _chrRom; break;
|
||||
case MemoryType::NesChrRam: ptrAddress = _chrRam; break;
|
||||
case MemoryType::NesNametableRam: ptrAddress = _nametableRam; break;
|
||||
case MemoryType::NesMapperRam: ptrAddress = _mapperRam; break;
|
||||
case MemoryType::NesPaletteRam: return 0x3F00 | (addr.Address & 0x1F); break;
|
||||
default: return -1;
|
||||
}
|
||||
|
@ -1106,6 +1156,7 @@ CartridgeState BaseMapper::GetState()
|
|||
state.SaveRamPageSize = GetSaveRamPageSize();
|
||||
|
||||
vector<MapperStateEntry> entries = GetMapperStateEntries();
|
||||
assert(entries.size() <= 200);
|
||||
state.CustomEntryCount = (uint32_t)entries.size();
|
||||
for(int i = 0; i < entries.size(); i++) {
|
||||
state.CustomEntries[i] = entries[i];
|
||||
|
|
|
@ -81,6 +81,9 @@ protected:
|
|||
bool _hasChrBattery = false;
|
||||
int16_t _vramOpenBusValue = -1;
|
||||
|
||||
uint8_t* _mapperRam = nullptr;
|
||||
uint32_t _mapperRamSize = 0;
|
||||
|
||||
virtual void InitMapper() = 0;
|
||||
virtual void InitMapper(RomData &romData);
|
||||
virtual uint16_t GetPrgPageSize() = 0;
|
||||
|
@ -104,6 +107,8 @@ protected:
|
|||
virtual uint32_t GetWorkRamSize() { return 0x2000; }
|
||||
virtual uint32_t GetWorkRamPageSize() { return 0x2000; }
|
||||
|
||||
virtual uint32_t GetMapperRamSize() { return 0; }
|
||||
|
||||
virtual uint16_t RegisterStartAddress() { return 0x8000; }
|
||||
virtual uint16_t RegisterEndAddress() { return 0xFFFF; }
|
||||
virtual bool AllowRegisterRead() { return false; }
|
||||
|
@ -140,7 +145,7 @@ protected:
|
|||
void RemovePpuMemoryMapping(uint16_t startAddr, uint16_t endAddr);
|
||||
|
||||
bool HasBattery();
|
||||
void LoadBattery();
|
||||
virtual void LoadBattery();
|
||||
string GetBatteryFilename();
|
||||
|
||||
uint32_t GetPrgPageCount();
|
||||
|
@ -168,6 +173,8 @@ protected:
|
|||
void SetMirroringType(MirroringType type);
|
||||
MirroringType GetMirroringType();
|
||||
|
||||
void InternalWriteVram(uint16_t addr, uint8_t value);
|
||||
|
||||
__forceinline uint8_t InternalReadVram(uint16_t addr)
|
||||
{
|
||||
if(_chrMemoryAccess[addr >> 8] & MemoryAccessType::Read) {
|
||||
|
@ -222,7 +229,8 @@ public:
|
|||
void WritePrgRam(uint16_t addr, uint8_t value);
|
||||
|
||||
virtual uint8_t MapperReadVram(uint16_t addr, MemoryOperationType operationType);
|
||||
|
||||
virtual void MapperWriteVram(uint16_t addr, uint8_t value);
|
||||
|
||||
__forceinline uint8_t ReadVram(uint16_t addr, MemoryOperationType type = MemoryOperationType::PpuRenderingRead)
|
||||
{
|
||||
uint8_t value;
|
||||
|
|
63
Core/NES/Debugger/IExtModeMapperDebug.h
Normal file
63
Core/NES/Debugger/IExtModeMapperDebug.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
|
||||
struct NtExtConfig
|
||||
{
|
||||
uint16_t SourceOffset;
|
||||
bool AttrExtMode;
|
||||
bool BgExtMode;
|
||||
bool FillMode;
|
||||
};
|
||||
|
||||
struct ExtModeConfig
|
||||
{
|
||||
NtExtConfig Nametables[5];
|
||||
bool SpriteExtMode;
|
||||
uint8_t ChrSource;
|
||||
uint8_t WindowBank;
|
||||
uint8_t WindowScrollX;
|
||||
uint8_t WindowScrollY;
|
||||
uint8_t BgExtBank;
|
||||
uint8_t SpriteExtBank;
|
||||
uint8_t SpriteExtData[64];
|
||||
uint8_t ExtRam[0x2000];
|
||||
};
|
||||
|
||||
class IExtModeMapperDebug
|
||||
{
|
||||
public:
|
||||
virtual ExtModeConfig GetExModeConfig()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual bool HasExtendedAttributes(ExtModeConfig& extCfg, uint8_t ntIndex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool HasExtendedBackground(ExtModeConfig& extCfg, uint8_t ntIndex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool HasExtendedSprites(ExtModeConfig& extCfg)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual uint8_t GetExAttributePalette(ExtModeConfig& extCfg, uint8_t ntIndex, uint16_t ntAddr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual uint8_t GetExBackgroundChrData(ExtModeConfig& extCfg, uint8_t ntIndex, uint16_t ntAddr, uint16_t chrAddr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual uint8_t GetExSpriteChrData(ExtModeConfig& extCfg, uint8_t spriteIndex, uint16_t chrAddr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
|
@ -1,125 +1,136 @@
|
|||
#include "pch.h"
|
||||
#include "NES/Debugger/NesPpuTools.h"
|
||||
#include "NES/Mappers/Nintendo/MMC5.h"
|
||||
#include "NES/Debugger/IExtModeMapperDebug.h"
|
||||
#include "NES/BaseMapper.h"
|
||||
#include "NES/BaseNesPpu.h"
|
||||
#include "NES/NesConsole.h"
|
||||
#include "NES/NesConstants.h"
|
||||
#include "NES/NesTypes.h"
|
||||
#include "NES/NesDefaultVideoFilter.h"
|
||||
#include "NES/Mappers/Homebrew/Rainbow.h"
|
||||
#include "Debugger/DebugTypes.h"
|
||||
#include "Debugger/MemoryDumper.h"
|
||||
#include "Debugger/MemoryAccessCounter.h"
|
||||
#include "Shared/SettingTypes.h"
|
||||
|
||||
static constexpr uint32_t grayscalePalette[4] = { 0xFF000000, 0xFF808080, 0xFFC0C0C0, 0xFFFFFFFF };
|
||||
|
||||
NesPpuTools::NesPpuTools(Debugger* debugger, Emulator *emu, NesConsole* console) : PpuTools(debugger, emu)
|
||||
{
|
||||
_console = console;
|
||||
_mapper = console->GetMapper();
|
||||
}
|
||||
|
||||
DebugTilemapInfo NesPpuTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
void NesPpuTools::GetPpuToolsState(BaseState& state)
|
||||
{
|
||||
MMC5* mmc5 = dynamic_cast<MMC5*>(_mapper);
|
||||
NesPpuToolsState nesState = {};
|
||||
|
||||
IExtModeMapperDebug* exMode = dynamic_cast<IExtModeMapperDebug*>(_mapper);
|
||||
if(exMode) {
|
||||
nesState.ExtConfig = exMode->GetExModeConfig();
|
||||
}
|
||||
|
||||
(NesPpuToolsState&)state = nesState;
|
||||
}
|
||||
|
||||
void NesPpuTools::DrawNametable(uint8_t* ntSource, uint32_t ntBaseAddr, uint8_t ntIndex, GetTilemapOptions options, NesPpuState& state, IExtModeMapperDebug* exMode, ExtModeConfig& extCfg, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer, uint32_t bufferWidth)
|
||||
{
|
||||
uint16_t baseAttributeAddr = ntBaseAddr + 960;
|
||||
|
||||
for(uint8_t row = 0; row < 30; row++) {
|
||||
for(uint8_t column = 0; column < 32; column++) {
|
||||
uint16_t ntOffset = (row << 5) + column;
|
||||
uint16_t attributeAddress = baseAttributeAddr + ((row & 0xFC) << 1) + (column >> 2);
|
||||
uint8_t tileIndex = ntSource[ntBaseAddr + ntOffset];
|
||||
uint8_t attribute = ntSource[attributeAddress];
|
||||
uint8_t shift = (column & 0x02) | ((row & 0x02) << 1);
|
||||
|
||||
uint8_t paletteBaseAddr;
|
||||
if(exMode && exMode->HasExtendedAttributes(extCfg, ntIndex)) {
|
||||
paletteBaseAddr = exMode->GetExAttributePalette(extCfg, ntIndex, ntOffset) << 2;
|
||||
} else {
|
||||
paletteBaseAddr = ((attribute >> shift) & 0x03) << 2;
|
||||
}
|
||||
|
||||
uint16_t tileAddr = state.Control.BackgroundPatternAddr + (tileIndex << 4);
|
||||
if(options.DisplayMode == TilemapDisplayMode::AttributeView) {
|
||||
for(uint8_t y = 0; y < 8; y++) {
|
||||
for(uint8_t x = 0; x < 8; x++) {
|
||||
uint8_t color = ((x & 0x04) >> 2) + ((y & 0x04) >> 1);
|
||||
outBuffer[(row*bufferWidth*8) + (column << 3) + (y*bufferWidth) + x] = palette[paletteBaseAddr + color];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(uint8_t y = 0; y < 8; y++) {
|
||||
uint8_t lowByte, highByte;
|
||||
if(exMode && exMode->HasExtendedBackground(extCfg, ntIndex)) {
|
||||
lowByte = exMode->GetExBackgroundChrData(extCfg, ntIndex, ntOffset, tileAddr + y);
|
||||
highByte = exMode->GetExBackgroundChrData(extCfg, ntIndex, ntOffset, tileAddr + y + 8);
|
||||
} else {
|
||||
lowByte = vram[tileAddr + y];
|
||||
highByte = vram[tileAddr + y + 8];
|
||||
}
|
||||
|
||||
uint32_t offset = (row*bufferWidth*8) + (column << 3) + (y*bufferWidth);
|
||||
for(uint8_t x = 0; x < 8; x++) {
|
||||
uint8_t color = ((lowByte >> (7 - x)) & 0x01) | (((highByte >> (7 - x)) & 0x01) << 1);
|
||||
if(options.DisplayMode == TilemapDisplayMode::Grayscale) {
|
||||
outBuffer[offset + x] = grayscalePalette[color];
|
||||
} else {
|
||||
outBuffer[offset + x] = palette[paletteBaseAddr + color];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DebugTilemapInfo NesPpuTools::GetWindowTilemap(GetTilemapOptions options, NesPpuState& state, IExtModeMapperDebug* exMode, ExtModeConfig& extCfg, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
{
|
||||
uint16_t baseAddr = extCfg.WindowBank * 0x400;
|
||||
|
||||
DrawNametable(extCfg.ExtRam, baseAddr, 4, options, state, exMode, extCfg, vram, palette, outBuffer, 256);
|
||||
|
||||
DebugTilemapInfo result = {};
|
||||
result.Bpp = 2;
|
||||
result.Format = TileFormat::NesBpp2;
|
||||
result.TileWidth = 8;
|
||||
result.TileHeight = 8;
|
||||
result.ColumnCount = 32;
|
||||
result.RowCount = 30;
|
||||
result.TilemapAddress = extCfg.WindowBank * 0x400;
|
||||
result.TilesetAddress = state.Control.BackgroundPatternAddr;
|
||||
result.ScrollWidth = NesConstants::ScreenWidth;
|
||||
result.ScrollHeight = NesConstants::ScreenHeight;
|
||||
result.ScrollX = extCfg.WindowScrollX;
|
||||
result.ScrollY = extCfg.WindowScrollY;
|
||||
return result;
|
||||
}
|
||||
|
||||
DebugTilemapInfo NesPpuTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
{
|
||||
IExtModeMapperDebug* exMode = dynamic_cast<IExtModeMapperDebug*>(_mapper);
|
||||
NesPpuState& state = (NesPpuState&)baseState;
|
||||
uint16_t bgAddr = state.Control.BackgroundPatternAddr;
|
||||
ExtModeConfig& extCfg = ((NesPpuToolsState&)ppuToolsState).ExtConfig;
|
||||
|
||||
for(int i = 0; i < 32; i+=4) {
|
||||
palette[i] = palette[0];
|
||||
}
|
||||
|
||||
AddressCounters* accessCounters = options.AccessCounters;
|
||||
uint8_t* prevVram = options.CompareVram != nullptr ? options.CompareVram : vram;
|
||||
if(options.Layer == 1 && exMode) {
|
||||
return GetWindowTilemap(options, state, exMode, extCfg, vram, palette, outBuffer);
|
||||
}
|
||||
|
||||
uint64_t masterClock = options.MasterClock;
|
||||
uint32_t clockRate = _console->GetMasterClockRate() / _console->GetFps();
|
||||
|
||||
auto isHighlighted = [&](uint16_t addr, TilemapHighlightMode mode) -> bool {
|
||||
switch(mode) {
|
||||
default:
|
||||
case TilemapHighlightMode::None: return false;
|
||||
|
||||
//Highlight if modified since the last update
|
||||
case TilemapHighlightMode::Changes: return prevVram[addr] != vram[addr];
|
||||
|
||||
//Highlight if modified in the last frame
|
||||
case TilemapHighlightMode::Writes: return accessCounters && masterClock - accessCounters[addr].WriteStamp < clockRate;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr uint32_t grayscalePalette[4] = { 0xFF000000, 0xFF808080, 0xFFC0C0C0, 0xFFFFFFFF };
|
||||
for(int nametableIndex = 0; nametableIndex < 4; nametableIndex++) {
|
||||
uint16_t baseAddr = 0x2000 + nametableIndex * 0x400;
|
||||
uint16_t baseAttributeAddr = baseAddr + 960;
|
||||
uint32_t bufferOffset = ((nametableIndex & 0x01) ? 256 : 0) + ((nametableIndex & 0x02) ? 512 * 240 : 0);
|
||||
for(uint8_t row = 0; row < 30; row++) {
|
||||
for(uint8_t column = 0; column < 32; column++) {
|
||||
uint16_t ntIndex = (row << 5) + column;
|
||||
uint16_t attributeAddress = baseAttributeAddr + ((row & 0xFC) << 1) + (column >> 2);
|
||||
uint8_t tileIndex = vram[baseAddr + ntIndex];
|
||||
uint8_t attribute = vram[attributeAddress];
|
||||
bool tileHighlighted = isHighlighted(baseAddr + ntIndex, options.TileHighlightMode);
|
||||
bool attrHighlighted = isHighlighted(attributeAddress, options.AttributeHighlightMode);
|
||||
uint8_t shift = (column & 0x02) | ((row & 0x02) << 1);
|
||||
|
||||
uint8_t paletteBaseAddr;
|
||||
if(mmc5 && mmc5->IsExtendedAttributes()) {
|
||||
paletteBaseAddr = mmc5->GetExAttributeNtPalette(ntIndex) << 2;
|
||||
} else {
|
||||
paletteBaseAddr = ((attribute >> shift) & 0x03) << 2;
|
||||
}
|
||||
|
||||
uint16_t tileAddr = bgAddr + (tileIndex << 4);
|
||||
if(options.DisplayMode == TilemapDisplayMode::AttributeView) {
|
||||
for(uint8_t y = 0; y < 8; y++) {
|
||||
for(uint8_t x = 0; x < 8; x++) {
|
||||
uint8_t color = ((x & 0x04) >> 2) + ((y & 0x04) >> 1);
|
||||
outBuffer[bufferOffset + (row << 12) + (column << 3) + (y << 9) + x] = palette[paletteBaseAddr + color];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(uint8_t y = 0; y < 8; y++) {
|
||||
uint8_t lowByte, highByte;
|
||||
if(mmc5 && mmc5->IsExtendedAttributes()) {
|
||||
lowByte = mmc5->GetExAttributeTileData(ntIndex, tileAddr + y);
|
||||
highByte = mmc5->GetExAttributeTileData(ntIndex, tileAddr + y + 8);
|
||||
} else {
|
||||
lowByte = vram[tileAddr + y];
|
||||
highByte = vram[tileAddr + y + 8];
|
||||
}
|
||||
|
||||
uint32_t offset = bufferOffset + (row << 12) + (column << 3) + (y << 9);
|
||||
for(uint8_t x = 0; x < 8; x++) {
|
||||
uint8_t color = ((lowByte >> (7 - x)) & 0x01) | (((highByte >> (7 - x)) & 0x01) << 1);
|
||||
if(options.DisplayMode == TilemapDisplayMode::Grayscale) {
|
||||
outBuffer[offset+x] = grayscalePalette[color];
|
||||
} else {
|
||||
outBuffer[offset+x] = palette[paletteBaseAddr + color];
|
||||
}
|
||||
|
||||
if(tileHighlighted) {
|
||||
static constexpr uint32_t tileChangedColor = 0x80FF0000;
|
||||
if(x == 0 || y == 0 || x == 7 || y == 7) {
|
||||
outBuffer[offset + x] = 0xFF000000 | tileChangedColor;
|
||||
} else {
|
||||
BlendColors((uint8_t*)&outBuffer[offset + x], (uint8_t*)&tileChangedColor);
|
||||
}
|
||||
}
|
||||
|
||||
if(attrHighlighted) {
|
||||
static constexpr uint32_t attrChangedColor = 0x80FFFF00;
|
||||
bool isEdge = (
|
||||
((column & 3) == 0 && x == 0) ||
|
||||
((row & 3) == 0 && y == 0) ||
|
||||
((column & 3) == 3 && x == 7) ||
|
||||
((row & 3) == 3 && y == 7)
|
||||
);
|
||||
if(isEdge) {
|
||||
outBuffer[offset + x] = 0xFF000000 | attrChangedColor;
|
||||
} else {
|
||||
BlendColors((uint8_t*)&outBuffer[offset + x], (uint8_t*)&attrChangedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DrawNametable(vram, baseAddr, nametableIndex, options, state, exMode, extCfg, vram, palette, outBuffer+bufferOffset, 512);
|
||||
|
||||
if(options.DisplayMode != TilemapDisplayMode::AttributeView) {
|
||||
if(options.TileHighlightMode != TilemapHighlightMode::None || options.AttributeHighlightMode != TilemapHighlightMode::None) {
|
||||
ApplyHighlights(options, nametableIndex, vram, outBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +143,7 @@ DebugTilemapInfo NesPpuTools::GetTilemap(GetTilemapOptions options, BaseState& b
|
|||
result.ColumnCount = 64;
|
||||
result.RowCount = 60;
|
||||
result.TilemapAddress = 0x2000;
|
||||
result.TilesetAddress = bgAddr;
|
||||
result.TilesetAddress = state.Control.BackgroundPatternAddr;
|
||||
result.ScrollWidth = NesConstants::ScreenWidth;
|
||||
result.ScrollHeight = NesConstants::ScreenHeight;
|
||||
|
||||
|
@ -190,6 +201,74 @@ DebugTilemapInfo NesPpuTools::GetTilemap(GetTilemapOptions options, BaseState& b
|
|||
return result;
|
||||
}
|
||||
|
||||
void NesPpuTools::ApplyHighlights(GetTilemapOptions options, uint8_t nametableIndex, uint8_t* vram, uint32_t* outBuffer)
|
||||
{
|
||||
uint16_t baseAddr = 0x2000 + nametableIndex * 0x400;
|
||||
uint16_t baseAttributeAddr = baseAddr + 960;
|
||||
uint32_t bufferOffset = ((nametableIndex & 0x01) ? 256 : 0) + ((nametableIndex & 0x02) ? 512 * 240 : 0);
|
||||
|
||||
AddressCounters* accessCounters = options.AccessCounters;
|
||||
uint8_t* prevVram = options.CompareVram != nullptr ? options.CompareVram : vram;
|
||||
|
||||
uint64_t masterClock = options.MasterClock;
|
||||
uint32_t clockRate = _console->GetMasterClockRate() / _console->GetFps();
|
||||
|
||||
auto isHighlighted = [&](uint16_t addr, TilemapHighlightMode mode) -> bool {
|
||||
switch(mode) {
|
||||
default:
|
||||
case TilemapHighlightMode::None: return false;
|
||||
|
||||
//Highlight if modified since the last update
|
||||
case TilemapHighlightMode::Changes: return prevVram[addr] != vram[addr];
|
||||
|
||||
//Highlight if modified in the last frame
|
||||
case TilemapHighlightMode::Writes: return accessCounters && masterClock - accessCounters[addr].WriteStamp < clockRate;
|
||||
}
|
||||
};
|
||||
|
||||
for(uint8_t row = 0; row < 30; row++) {
|
||||
for(uint8_t column = 0; column < 32; column++) {
|
||||
uint16_t ntOffset = (row << 5) + column;
|
||||
uint16_t attributeAddress = baseAttributeAddr + ((row & 0xFC) << 1) + (column >> 2);
|
||||
bool tileHighlighted = isHighlighted(baseAddr + ntOffset, options.TileHighlightMode);
|
||||
bool attrHighlighted = isHighlighted(attributeAddress, options.AttributeHighlightMode);
|
||||
|
||||
if(!tileHighlighted && !attrHighlighted) {
|
||||
break;
|
||||
}
|
||||
|
||||
for(uint8_t y = 0; y < 8; y++) {
|
||||
uint32_t offset = bufferOffset + (row << 12) + (column << 3) + (y << 9);
|
||||
for(uint8_t x = 0; x < 8; x++) {
|
||||
if(tileHighlighted) {
|
||||
static constexpr uint32_t tileChangedColor = 0x80FF0000;
|
||||
if(x == 0 || y == 0 || x == 7 || y == 7) {
|
||||
outBuffer[offset + x] = 0xFF000000 | tileChangedColor;
|
||||
} else {
|
||||
BlendColors((uint8_t*)&outBuffer[offset + x], (uint8_t*)&tileChangedColor);
|
||||
}
|
||||
}
|
||||
|
||||
if(attrHighlighted) {
|
||||
static constexpr uint32_t attrChangedColor = 0x80FFFF00;
|
||||
bool isEdge = (
|
||||
((column & 3) == 0 && x == 0) ||
|
||||
((row & 3) == 0 && y == 0) ||
|
||||
((column & 3) == 3 && x == 7) ||
|
||||
((row & 3) == 3 && y == 7)
|
||||
);
|
||||
if(isEdge) {
|
||||
outBuffer[offset + x] = 0xFF000000 | attrChangedColor;
|
||||
} else {
|
||||
BlendColors((uint8_t*)&outBuffer[offset + x], (uint8_t*)&attrChangedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NesPpuTools::GetSpritePreview(GetSpritePreviewOptions options, BaseState& baseState, DebugSpriteInfo* sprites, uint32_t* spritePreviews, uint32_t* palette, uint32_t* outBuffer)
|
||||
{
|
||||
uint32_t bgColor = GetSpriteBackgroundColor(options.Background, palette, false);
|
||||
|
@ -222,10 +301,15 @@ void NesPpuTools::GetSpritePreview(GetSpritePreviewOptions options, BaseState& b
|
|||
|
||||
FrameInfo NesPpuTools::GetTilemapSize(GetTilemapOptions options, BaseState& state)
|
||||
{
|
||||
return { 512, 480 };
|
||||
if(options.Layer == 0) {
|
||||
return { 512, 480 };
|
||||
} else if(options.Layer == 1 && dynamic_cast<IExtModeMapperDebug*>(_mapper)) {
|
||||
return { 256, 240 };
|
||||
}
|
||||
return { 0,0 };
|
||||
}
|
||||
|
||||
DebugTilemapTileInfo NesPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
|
||||
DebugTilemapTileInfo NesPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugTilemapTileInfo result = {};
|
||||
|
||||
|
@ -243,20 +327,21 @@ DebugTilemapTileInfo NesPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uin
|
|||
row -= 30;
|
||||
}
|
||||
|
||||
MMC5* mmc5 = dynamic_cast<MMC5*>(_mapper);
|
||||
IExtModeMapperDebug* exMode = dynamic_cast<IExtModeMapperDebug*>(_mapper);
|
||||
ExtModeConfig& extCfg = ((NesPpuToolsState&)ppuToolsState).ExtConfig;
|
||||
NesPpuState& state = (NesPpuState&)baseState;
|
||||
|
||||
uint16_t bgAddr = state.Control.BackgroundPatternAddr;
|
||||
uint16_t baseAddr = 0x2000 + nametableIndex * 0x400;
|
||||
uint16_t baseAttributeAddr = baseAddr + 960;
|
||||
uint16_t ntIndex = (row << 5) + column;
|
||||
uint16_t ntOffset = (row << 5) + column;
|
||||
uint16_t attributeAddress = baseAttributeAddr + ((row & 0xFC) << 1) + (column >> 2);
|
||||
uint8_t attribute = vram[attributeAddress];
|
||||
uint8_t shift = (column & 0x02) | ((row & 0x02) << 1);
|
||||
|
||||
uint8_t paletteBaseAddr;
|
||||
if(mmc5 && mmc5->IsExtendedAttributes()) {
|
||||
paletteBaseAddr = mmc5->GetExAttributeNtPalette(ntIndex) << 2;
|
||||
if(exMode && exMode->HasExtendedAttributes(extCfg, nametableIndex)) {
|
||||
paletteBaseAddr = exMode->GetExAttributePalette(extCfg, nametableIndex, ntOffset) << 2;
|
||||
} else {
|
||||
paletteBaseAddr = ((attribute >> shift) & 0x03) << 2;
|
||||
}
|
||||
|
@ -265,7 +350,7 @@ DebugTilemapTileInfo NesPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uin
|
|||
result.Column = column;
|
||||
result.Width = 8;
|
||||
result.Height = 8;
|
||||
result.TileMapAddress = baseAddr + ntIndex;
|
||||
result.TileMapAddress = baseAddr + ntOffset;
|
||||
result.TileIndex = vram[result.TileMapAddress];
|
||||
result.TileAddress = bgAddr + (result.TileIndex << 4);
|
||||
result.PaletteIndex = paletteBaseAddr >> 2;
|
||||
|
@ -276,8 +361,11 @@ DebugTilemapTileInfo NesPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uin
|
|||
return result;
|
||||
}
|
||||
|
||||
void NesPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePreview, uint32_t i, GetSpritePreviewOptions& options, NesPpuState& state, uint8_t* vram, uint8_t* oamRam, uint32_t* palette)
|
||||
void NesPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePreview, uint32_t i, GetSpritePreviewOptions& options, NesPpuState& state, NesPpuToolsState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette)
|
||||
{
|
||||
IExtModeMapperDebug* exMode = dynamic_cast<IExtModeMapperDebug*>(_mapper);
|
||||
ExtModeConfig& extCfg = ppuToolsState.ExtConfig;
|
||||
|
||||
sprite.Bpp = 2;
|
||||
sprite.Format = TileFormat::NesBpp2;
|
||||
sprite.SpriteIndex = i;
|
||||
|
@ -329,8 +417,17 @@ void NesPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePreview
|
|||
}
|
||||
|
||||
for(int x = 0; x < 8; x++) {
|
||||
uint8_t shift = horizontalMirror ? (7 - x) : x;
|
||||
uint8_t color = GetTilePixelColor<TileFormat::NesBpp2>(vram, 0x3FFF, pixelStart, shift);
|
||||
uint8_t lowByte, highByte;
|
||||
if(exMode && exMode->HasExtendedSprites(extCfg)) {
|
||||
lowByte = exMode->GetExSpriteChrData(extCfg, i, pixelStart);
|
||||
highByte = exMode->GetExSpriteChrData(extCfg, i, pixelStart + 8);
|
||||
} else {
|
||||
lowByte = vram[pixelStart];
|
||||
highByte = vram[pixelStart + 8];
|
||||
}
|
||||
|
||||
uint8_t shift = horizontalMirror ? x : (7 - x);
|
||||
uint8_t color = ((lowByte >> shift) & 0x01) | (((highByte >> shift) & 0x01) << 1);
|
||||
|
||||
uint32_t outOffset = (y * 8) + x;
|
||||
if(color > 0) {
|
||||
|
@ -342,18 +439,19 @@ void NesPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePreview
|
|||
}
|
||||
}
|
||||
|
||||
void NesPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
void NesPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
{
|
||||
NesPpuState& state = (NesPpuState&)baseState;
|
||||
NesPpuToolsState& nesToolsState = (NesPpuToolsState&)ppuToolsState;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
outBuffer[i].Init();
|
||||
GetSpriteInfo(outBuffer[i], spritePreviews+i*_spritePreviewSize, i, options, state, vram, oamRam, palette);
|
||||
GetSpriteInfo(outBuffer[i], spritePreviews+i*_spritePreviewSize, i, options, state, nesToolsState, vram, oamRam, palette);
|
||||
}
|
||||
|
||||
GetSpritePreview(options, baseState, outBuffer, spritePreviews, palette, screenPreview);
|
||||
}
|
||||
|
||||
DebugSpritePreviewInfo NesPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state)
|
||||
DebugSpritePreviewInfo NesPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugSpritePreviewInfo info = {};
|
||||
info.Height = 256;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "Debugger/PpuTools.h"
|
||||
#include "NES/Debugger/IExtModeMapperDebug.h"
|
||||
|
||||
class Debugger;
|
||||
class Emulator;
|
||||
|
@ -8,23 +9,35 @@ class BaseMapper;
|
|||
class NesConsole;
|
||||
struct NesPpuState;
|
||||
|
||||
struct NesPpuToolsState
|
||||
{
|
||||
ExtModeConfig ExtConfig;
|
||||
};
|
||||
|
||||
class NesPpuTools final : public PpuTools
|
||||
{
|
||||
private:
|
||||
NesConsole* _console = nullptr;
|
||||
BaseMapper* _mapper = nullptr;
|
||||
void GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePreview, uint32_t spriteIndex, GetSpritePreviewOptions& options, NesPpuState& state, uint8_t* vram, uint8_t* oamRam, uint32_t* palette);
|
||||
void GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePreview, uint32_t spriteIndex, GetSpritePreviewOptions& options, NesPpuState& state, NesPpuToolsState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette);
|
||||
void GetSpritePreview(GetSpritePreviewOptions options, BaseState& state, DebugSpriteInfo* sprites, uint32_t* spritePreviews, uint32_t* palette, uint32_t *outBuffer);
|
||||
|
||||
DebugTilemapInfo GetWindowTilemap(GetTilemapOptions options, NesPpuState& state, IExtModeMapperDebug* exMode, ExtModeConfig& extCfg, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer);
|
||||
|
||||
void DrawNametable(uint8_t* ntSource, uint32_t ntBaseAddr, uint8_t ntIndex, GetTilemapOptions options, NesPpuState& state, IExtModeMapperDebug* exMode, ExtModeConfig& extCfg, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer, uint32_t bufferWidth);
|
||||
void ApplyHighlights(GetTilemapOptions options, uint8_t nametableIndex, uint8_t* vram, uint32_t* outBuffer);
|
||||
|
||||
public:
|
||||
NesPpuTools(Debugger* debugger, Emulator *emu, NesConsole* console);
|
||||
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
FrameInfo GetTilemapSize(GetTilemapOptions options, BaseState& state) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState) override;
|
||||
void GetPpuToolsState(BaseState& state) override;
|
||||
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreview, uint32_t* screenPreview) override;
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
FrameInfo GetTilemapSize(GetTilemapOptions options, BaseState& state) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState) override;
|
||||
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreview, uint32_t* screenPreview) override;
|
||||
|
||||
DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
|
||||
void SetPaletteColor(int32_t colorIndex, uint32_t color) override;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "NES/Mappers/Homebrew/Cheapocabra.h"
|
||||
#include "NES/Mappers/Homebrew/FaridSlrom.h"
|
||||
#include "NES/Mappers/Homebrew/FaridUnrom.h"
|
||||
#include "NES/Mappers/Homebrew/Rainbow.h"
|
||||
#include "NES/Mappers/Homebrew/SealieComputing.h"
|
||||
#include "NES/Mappers/Homebrew/UnRom512.h"
|
||||
#include "NES/Mappers/Homebrew/UnlDripGame.h"
|
||||
|
@ -320,6 +321,8 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
|
|||
case 1: return new Nina01();
|
||||
case 2: return new BnRom();
|
||||
}
|
||||
break;
|
||||
|
||||
case 35: return new Mapper35();
|
||||
case 36: return new Txc22000();
|
||||
case 37: return new MMC3_37();
|
||||
|
@ -614,6 +617,8 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
|
|||
case 528: break; //831128C
|
||||
case 529: return new T230();
|
||||
case 530: return new Ax5705();
|
||||
|
||||
case 682: return new Rainbow();
|
||||
|
||||
case UnifBoards::Ac08: return new Ac08(); //mapper 42?
|
||||
case UnifBoards::Cc21: return new Cc21();
|
||||
|
|
220
Core/NES/Mappers/Homebrew/FlashS29.h
Normal file
220
Core/NES/Mappers/Homebrew/FlashS29.h
Normal file
|
@ -0,0 +1,220 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "Utilities/ISerializable.h"
|
||||
#include "Utilities/Serializer.h"
|
||||
#include "Shared/MessageManager.h"
|
||||
|
||||
class FlashS29 final : public ISerializable
|
||||
{
|
||||
private:
|
||||
enum class ChipMode
|
||||
{
|
||||
WaitingForCommand,
|
||||
Write,
|
||||
Erase
|
||||
};
|
||||
|
||||
enum class ChipModel
|
||||
{
|
||||
S29AL008,
|
||||
S29AL016,
|
||||
S29JL032,
|
||||
S29GL064S
|
||||
};
|
||||
|
||||
ChipModel _model = {};
|
||||
|
||||
ChipMode _mode = ChipMode::WaitingForCommand;
|
||||
uint8_t _cycle = 0;
|
||||
bool _softwareId = false;
|
||||
bool _unlockBypass = false;
|
||||
|
||||
//ROM data and size
|
||||
uint8_t* _data = nullptr;
|
||||
uint32_t _size = 0;
|
||||
|
||||
void ProcessUnlockBypassMode(uint8_t value)
|
||||
{
|
||||
if(_cycle == 0) {
|
||||
if(value == 0xA0) {
|
||||
//1st write of unlock bypass write
|
||||
_mode = ChipMode::Write;
|
||||
} else if(value == 0x90) {
|
||||
//1st write of unlock bypass reset
|
||||
_cycle++;
|
||||
} else {
|
||||
ResetState();
|
||||
}
|
||||
} else if(_cycle == 1) {
|
||||
if(value == 0x00) {
|
||||
//2nd write of unlock bypass reset
|
||||
_unlockBypass = false;
|
||||
}
|
||||
ResetState();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void Serialize(Serializer& s)
|
||||
{
|
||||
SV(_mode);
|
||||
SV(_cycle);
|
||||
SV(_softwareId);
|
||||
SV(_unlockBypass);
|
||||
}
|
||||
|
||||
public:
|
||||
FlashS29(uint8_t* data, uint32_t size)
|
||||
{
|
||||
_data = data;
|
||||
_size = size;
|
||||
|
||||
switch(_size) {
|
||||
case 0x100000: _model = ChipModel::S29AL008; break;
|
||||
case 0x200000: _model = ChipModel::S29AL016; break;
|
||||
case 0x400000: _model = ChipModel::S29JL032; break;
|
||||
case 0x800000: _model = ChipModel::S29GL064S; break;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsSoftwareIdMode()
|
||||
{
|
||||
return _softwareId;
|
||||
}
|
||||
|
||||
int16_t Read(uint32_t addr)
|
||||
{
|
||||
if(_softwareId) {
|
||||
switch(addr & 0x1FF) {
|
||||
case 0x00: return 0x01;
|
||||
|
||||
case 0x02: {
|
||||
switch(_model) {
|
||||
case ChipModel::S29AL008: return 0x5B;
|
||||
case ChipModel::S29AL016: return 0x49;
|
||||
case ChipModel::S29JL032: return 0x7E;
|
||||
case ChipModel::S29GL064S: return 0x7E;
|
||||
default: return 0xFF;
|
||||
}
|
||||
}
|
||||
case 0x1C: {
|
||||
switch(_model) {
|
||||
case ChipModel::S29JL032: return 0x0A;
|
||||
case ChipModel::S29GL064S: return 0x10;
|
||||
default: return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
case 0x1E: {
|
||||
switch(_model) {
|
||||
case ChipModel::S29JL032: return 0x00;
|
||||
case ChipModel::S29GL064S: return 0x00;
|
||||
default: return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
default: return 0xFF;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ResetState()
|
||||
{
|
||||
_mode = ChipMode::WaitingForCommand;
|
||||
_cycle = 0;
|
||||
}
|
||||
|
||||
void Write(uint32_t addr, uint8_t value)
|
||||
{
|
||||
uint16_t cmd = addr & 0xFFF;
|
||||
if(_mode == ChipMode::WaitingForCommand) {
|
||||
if(_unlockBypass) {
|
||||
ProcessUnlockBypassMode(value);
|
||||
return;
|
||||
}
|
||||
|
||||
if(_cycle == 0) {
|
||||
if(cmd == 0xAAA && value == 0xAA) {
|
||||
//1st write, $AAA = $AA
|
||||
_cycle++;
|
||||
} else if(value == 0xF0) {
|
||||
//Software ID exit
|
||||
ResetState();
|
||||
_softwareId = false;
|
||||
}
|
||||
} else if(_cycle == 1 && cmd == 0x555 && value == 0x55) {
|
||||
//2nd write, $555 = $55
|
||||
_cycle++;
|
||||
} else if(_cycle == 2 && cmd == 0xAAA) {
|
||||
//3rd write, determines command type
|
||||
_cycle++;
|
||||
switch(value) {
|
||||
case 0x20: ResetState(); _unlockBypass = true; break;
|
||||
case 0x80: _mode = ChipMode::Erase; break;
|
||||
case 0x90: ResetState(); _softwareId = true; break;
|
||||
case 0xA0: _mode = ChipMode::Write; break;
|
||||
case 0xF0: ResetState(); _softwareId = false; break;
|
||||
}
|
||||
} else {
|
||||
_cycle = 0;
|
||||
}
|
||||
} else if(_mode == ChipMode::Write) {
|
||||
//Write a single byte
|
||||
if(addr < _size) {
|
||||
_data[addr] &= value;
|
||||
}
|
||||
ResetState();
|
||||
} else if(_mode == ChipMode::Erase) {
|
||||
if(_cycle == 3) {
|
||||
//4th write for erase command, $AAA = $AA
|
||||
if(cmd == 0xAAA && value == 0xAA) {
|
||||
_cycle++;
|
||||
} else {
|
||||
ResetState();
|
||||
}
|
||||
} else if(_cycle == 4) {
|
||||
//5th write for erase command, $555 = $55
|
||||
if(cmd == 0x555 && value == 0x55) {
|
||||
_cycle++;
|
||||
} else {
|
||||
ResetState();
|
||||
}
|
||||
} else if(_cycle == 5) {
|
||||
if(cmd == 0xAAA && value == 0x10) {
|
||||
//Chip erase
|
||||
memset(_data, 0xFF, _size);
|
||||
} else if(value == 0x30) {
|
||||
//Sector erase
|
||||
uint32_t pageCount = _size / 0x10000;
|
||||
uint32_t page = addr / 0x10000;
|
||||
if(page == pageCount - 1) {
|
||||
//Last sector is split into multiple smaller sectors
|
||||
vector<int> sectorSizes;
|
||||
switch(_model) {
|
||||
case ChipModel::S29AL008: sectorSizes = vector<int> { 32, 8, 8, 16 }; break;
|
||||
case ChipModel::S29AL016: sectorSizes = vector<int> { 32, 8, 8, 16 }; break;
|
||||
case ChipModel::S29JL032: sectorSizes = vector<int> { 8, 8, 8, 8, 8, 8, 8, 8 }; break;
|
||||
case ChipModel::S29GL064S: sectorSizes = vector<int> { 8, 8, 8, 8, 8, 8, 8, 8 }; break;
|
||||
}
|
||||
|
||||
uint32_t offsetKb = (addr & 0xFFFF) / 1024;
|
||||
uint32_t segOffset = 0;
|
||||
uint32_t segSize = 0;
|
||||
for(int i = 0; i < sectorSizes.size(); i++) {
|
||||
if(segOffset + sectorSizes[i] > offsetKb) {
|
||||
break;
|
||||
}
|
||||
segOffset += sectorSizes[i];
|
||||
segSize = sectorSizes[i];
|
||||
}
|
||||
memset(_data + page * 0x10000 + segOffset * 1024, 0xFF, segSize * 1024);
|
||||
} else {
|
||||
memset(_data + page * 0x10000, 0xFF, 0x10000);
|
||||
}
|
||||
}
|
||||
ResetState();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
1130
Core/NES/Mappers/Homebrew/Rainbow.cpp
Normal file
1130
Core/NES/Mappers/Homebrew/Rainbow.cpp
Normal file
File diff suppressed because it is too large
Load diff
184
Core/NES/Mappers/Homebrew/Rainbow.h
Normal file
184
Core/NES/Mappers/Homebrew/Rainbow.h
Normal file
|
@ -0,0 +1,184 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "NES/BaseMapper.h"
|
||||
#include "NES/Debugger/IExtModeMapperDebug.h"
|
||||
|
||||
class RainbowAudio;
|
||||
class FlashS29;
|
||||
|
||||
class Rainbow : public BaseMapper, public IExtModeMapperDebug
|
||||
{
|
||||
private:
|
||||
struct NtControl
|
||||
{
|
||||
bool AttrExtMode;
|
||||
bool BgExtMode;
|
||||
uint8_t FpgaRamSrc;
|
||||
bool FillMode;
|
||||
uint8_t Source;
|
||||
|
||||
uint8_t ToByte()
|
||||
{
|
||||
return (
|
||||
((uint8_t)AttrExtMode << 0) |
|
||||
((uint8_t)BgExtMode << 1) |
|
||||
(FpgaRamSrc << 2) |
|
||||
((uint8_t)FillMode << 5) |
|
||||
(Source << 6)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
unique_ptr<RainbowAudio> _audio;
|
||||
unique_ptr<FlashS29> _prgFlash;
|
||||
unique_ptr<FlashS29> _chrFlash;
|
||||
|
||||
vector<uint8_t> _orgPrgRom;
|
||||
vector<uint8_t> _orgChrRom;
|
||||
|
||||
uint16_t _highBanks[8] = {};
|
||||
uint16_t _lowBanks[2] = {};
|
||||
uint16_t _chrBanks[16] = {};
|
||||
|
||||
uint8_t _fpgaRamBank = 0;
|
||||
|
||||
uint8_t _highMode = 0;
|
||||
uint8_t _lowMode = 0;
|
||||
uint8_t _chrMode = 0;
|
||||
uint8_t _chrSource = 0;
|
||||
bool _windowEnabled = false;
|
||||
bool _spriteExtMode = false;
|
||||
uint8_t _bgExtModeOffset = 0;
|
||||
|
||||
uint8_t _ntBanks[4] = {};
|
||||
NtControl _ntControl[4] = {};
|
||||
|
||||
uint8_t _fillModeTileIndex = 0;
|
||||
uint8_t _fillModeAttrIndex = 0;
|
||||
|
||||
NtControl _windowControl = {};
|
||||
uint8_t _windowBank = 0;
|
||||
uint8_t _windowX1 = 0;
|
||||
uint8_t _windowX2 = 0;
|
||||
uint8_t _windowY1 = 0;
|
||||
uint8_t _windowY2 = 0;
|
||||
uint8_t _windowScrollX = 0;
|
||||
uint8_t _windowScrollY = 0;
|
||||
bool _inWindow = false;
|
||||
|
||||
bool _slIrqEnabled = false;
|
||||
bool _slIrqPending = false;
|
||||
uint8_t _slIrqScanline = 0;
|
||||
uint8_t _slIrqOffset = 0;
|
||||
|
||||
uint16_t _lastPpuReadAddr = 0;
|
||||
int16_t _scanlineCounter = 0;
|
||||
uint8_t _ppuIdleCounter = 0;
|
||||
uint8_t _ntReadCounter = 0;
|
||||
uint8_t _ppuReadCounter = 0;
|
||||
|
||||
bool _inFrame = false;
|
||||
bool _inHBlank = false;
|
||||
uint8_t _jitterCounter = 0;
|
||||
|
||||
uint16_t _cpuIrqCounter = 0;
|
||||
uint16_t _cpuIrqReloadValue = 0;
|
||||
bool _cpuIrqEnabled = false;
|
||||
bool _cpuIrqPending = false;
|
||||
bool _cpuIrqEnableAfterAck = false;
|
||||
bool _cpuIrqAckOn4011 = false;
|
||||
|
||||
uint16_t _fpgaRamAddr = 0;
|
||||
uint8_t _fpgaRamInc = 0;
|
||||
|
||||
bool _nmiVectorEnabled = false;
|
||||
bool _irqVectorEnabled = false;
|
||||
uint16_t _nmiVectorAddr = 0;
|
||||
uint16_t _irqVectorAddr = 0;
|
||||
|
||||
bool _overrideTileFetch = false;
|
||||
uint8_t _extData = 0;
|
||||
uint8_t _ntFetchCounter = 0;
|
||||
|
||||
uint8_t _spriteExtData[64] = {};
|
||||
uint8_t _oamPosY[64] = {};
|
||||
uint8_t _oamMappings[8] = {};
|
||||
uint8_t _spriteExtBank = 0;
|
||||
bool _largeSprites = false;
|
||||
uint8_t _oamAddr = 0;
|
||||
|
||||
uint8_t _oamExtUpdatePage = 0;
|
||||
uint8_t _oamSlowUpdatePage = 0;
|
||||
uint8_t _oamCode[0x506] = {};
|
||||
bool _oamCodeLocked = false;
|
||||
|
||||
bool _espEnabled = false;
|
||||
bool _wifiIrqEnabled = false;
|
||||
bool _wifiIrqPending = false;
|
||||
bool _dataSent = false;
|
||||
bool _dataReceived = false;
|
||||
bool _dataReady = false;
|
||||
uint8_t _sendSrcAddr = 0;
|
||||
uint8_t _recvDstAddr = 0;
|
||||
|
||||
uint8_t ReadChr(uint32_t addr);
|
||||
void UpdateInWindowFlag();
|
||||
void UpdateIrqStatus();
|
||||
void AckCpuIrq();
|
||||
void ProcessSpriteEval();
|
||||
void DetectScanlineStart(uint16_t addr);
|
||||
|
||||
void GenerateOamClear();
|
||||
void GenerateExtUpdate();
|
||||
void GenerateOamSlowUpdate();
|
||||
|
||||
PrgMemoryType GetWorkRamType();
|
||||
void SelectHighBank(uint16_t start, uint16_t size, uint8_t reg);
|
||||
void SelectLowBank(uint16_t start, uint16_t size, uint8_t reg);
|
||||
void SelectChrBank(uint16_t start, uint16_t size, uint8_t reg);
|
||||
void UpdateState();
|
||||
|
||||
void ApplySaveData();
|
||||
|
||||
protected:
|
||||
uint16_t GetPrgPageSize() override { return 0x1000; }
|
||||
uint16_t GetChrPageSize() override { return 0x200; }
|
||||
uint32_t GetMapperRamSize() override { return 0x2000; }
|
||||
uint16_t RegisterStartAddress() override { return 0x4100; }
|
||||
uint16_t RegisterEndAddress() override { return 0x4785; }
|
||||
bool AllowRegisterRead() override { return true; }
|
||||
bool EnableCpuClockHook() override { return true; }
|
||||
bool EnableCustomVramRead() override { return true; }
|
||||
|
||||
void InitMapper() override;
|
||||
void SaveBattery() override;
|
||||
void Reset(bool softReset) override;
|
||||
void OnAfterResetPowerOn() override;
|
||||
|
||||
uint8_t MapperReadVram(uint16_t addr, MemoryOperationType memoryOperationType) override;
|
||||
void MapperWriteVram(uint16_t addr, uint8_t value) override;
|
||||
|
||||
public:
|
||||
Rainbow();
|
||||
|
||||
void WriteRam(uint16_t addr, uint8_t value) override;
|
||||
uint8_t ReadRam(uint16_t addr) override;
|
||||
|
||||
void ProcessCpuClock() override;
|
||||
|
||||
uint8_t ReadRegister(uint16_t addr) override;
|
||||
void WriteRegister(uint16_t addr, uint8_t value) override;
|
||||
|
||||
//Debugger
|
||||
vector<MapperStateEntry> GetMapperStateEntries() override;
|
||||
bool HasExtendedAttributes(ExtModeConfig& cfg, uint8_t ntIndex) override;
|
||||
bool HasExtendedBackground(ExtModeConfig& cfg, uint8_t ntIndex) override;
|
||||
bool HasExtendedSprites(ExtModeConfig& cfg) override;
|
||||
uint8_t DebugReadChr(ExtModeConfig& cfg, uint32_t addr);
|
||||
uint8_t GetExAttributePalette(ExtModeConfig& cfg, uint8_t ntIndex, uint16_t ntOffset) override;
|
||||
uint8_t GetExBackgroundChrData(ExtModeConfig& cfg, uint8_t ntIndex, uint16_t ntOffset, uint16_t chrAddr) override;
|
||||
uint8_t GetExSpriteChrData(ExtModeConfig& cfg, uint8_t spriteIndex, uint16_t chrAddr) override;
|
||||
ExtModeConfig GetExModeConfig() override;
|
||||
|
||||
void Serialize(Serializer& s) override;
|
||||
};
|
91
Core/NES/Mappers/Homebrew/RainbowAudio.h
Normal file
91
Core/NES/Mappers/Homebrew/RainbowAudio.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
#pragma once
|
||||
#include "NES/APU/BaseExpansionAudio.h"
|
||||
#include "NES/Mappers/Audio/Vrc6Pulse.h"
|
||||
#include "NES/Mappers/Audio/Vrc6Saw.h"
|
||||
#include "NES/APU/NesApu.h"
|
||||
#include "NES/NesConsole.h"
|
||||
#include "Utilities/Serializer.h"
|
||||
|
||||
class RainbowAudio : public BaseExpansionAudio
|
||||
{
|
||||
private:
|
||||
Vrc6Pulse _pulse1;
|
||||
Vrc6Pulse _pulse2;
|
||||
Vrc6Saw _saw;
|
||||
bool _outputExpPin6 = false;
|
||||
bool _outputExpPin9 = false;
|
||||
bool _outputTo4011 = false;
|
||||
uint8_t _volume = 0;
|
||||
uint8_t _lastOutput = 0;
|
||||
|
||||
protected:
|
||||
void Serialize(Serializer& s) override
|
||||
{
|
||||
SV(_pulse1);
|
||||
SV(_pulse2);
|
||||
SV(_saw);
|
||||
SV(_outputExpPin6);
|
||||
SV(_outputExpPin9);
|
||||
SV(_outputTo4011);
|
||||
SV(_volume);
|
||||
SV(_lastOutput);
|
||||
}
|
||||
|
||||
void ClockAudio() override
|
||||
{
|
||||
_pulse1.Clock();
|
||||
_pulse2.Clock();
|
||||
_saw.Clock();
|
||||
|
||||
uint8_t outputLevel = _pulse1.GetVolume() + _pulse2.GetVolume() + _saw.GetVolume();
|
||||
if(_outputExpPin6 || _outputExpPin9) {
|
||||
_console->GetApu()->AddExpansionAudioDelta(AudioChannel::VRC6, (int16_t)outputLevel - (int16_t)_lastOutput);
|
||||
}
|
||||
_lastOutput = outputLevel;
|
||||
}
|
||||
|
||||
public:
|
||||
RainbowAudio(NesConsole* console) : BaseExpansionAudio(console)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
_lastOutput = 0;
|
||||
}
|
||||
|
||||
uint8_t GetLastOutput()
|
||||
{
|
||||
return _lastOutput;
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value)
|
||||
{
|
||||
addr &= 0x0F;
|
||||
|
||||
switch(addr) {
|
||||
case 0x00: case 0x01: case 0x02:
|
||||
_pulse1.WriteReg(addr, value);
|
||||
break;
|
||||
|
||||
case 0x03: case 0x04: case 0x05:
|
||||
_pulse2.WriteReg(addr - 0x03, value);
|
||||
break;
|
||||
|
||||
case 0x06: case 0x07: case 0x08:
|
||||
_saw.WriteReg(addr - 0x06, value);
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
_outputExpPin6 = value & 0x01;
|
||||
_outputExpPin9 = value & 0x02;
|
||||
_outputTo4011 = value & 0x04;
|
||||
break;
|
||||
|
||||
case 0x0A:
|
||||
_volume = value & 0x0F;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -4,19 +4,18 @@
|
|||
#include "NES/NesConsole.h"
|
||||
#include "NES/NesCpu.h"
|
||||
#include "NES/Mappers/Audio/Mmc5Audio.h"
|
||||
#include "NES/Debugger/IExtModeMapperDebug.h"
|
||||
#include "NES/Mappers/Nintendo/Mmc5MemoryHandler.h"
|
||||
#include "Utilities/HexUtilities.h"
|
||||
|
||||
class MMC5 : public BaseMapper
|
||||
class MMC5 : public BaseMapper, public IExtModeMapperDebug
|
||||
{
|
||||
private:
|
||||
static constexpr int ExRamSize = 0x400;
|
||||
|
||||
unique_ptr<Mmc5Audio> _audio;
|
||||
unique_ptr<Mmc5MemoryHandler> _mmc5MemoryHandler;
|
||||
|
||||
uint8_t* _fillNametable;
|
||||
uint8_t* _emptyNametable;
|
||||
uint8_t* _fillNametable = nullptr;
|
||||
uint8_t* _emptyNametable = nullptr;
|
||||
|
||||
uint8_t _prgRamProtect1 = 0;
|
||||
uint8_t _prgRamProtect2 = 0;
|
||||
|
@ -93,34 +92,18 @@ private:
|
|||
// 1x 8kb : 0 0 0 0 - - - -
|
||||
// 2x 8kb : 0 0 0 0 1 1 1 1
|
||||
// 1x 32kb : 0 1 2 3 - - - -
|
||||
int32_t realWorkRamSize = _workRamSize - (HasBattery() ? 0 : MMC5::ExRamSize);
|
||||
int32_t realSaveRamSize = _saveRamSize - (!HasBattery() ? 0 : MMC5::ExRamSize);
|
||||
if(IsNes20() || _romInfo.IsInDatabase) {
|
||||
memoryType = PrgMemoryType::WorkRam;
|
||||
if(HasBattery() && (bankNumber <= 3 || realSaveRamSize > 0x2000)) {
|
||||
if(HasBattery() && (bankNumber <= 3 || _saveRamSize > 0x2000)) {
|
||||
memoryType = PrgMemoryType::SaveRam;
|
||||
}
|
||||
|
||||
if(realSaveRamSize + realWorkRamSize != 0x4000 && bankNumber >= 4) {
|
||||
if(_saveRamSize + _workRamSize != 0x4000 && bankNumber >= 4) {
|
||||
//When not 2x 8kb (=16kb), banks 4/5/6/7 select the empty socket and return open bus
|
||||
accessType = MemoryAccessType::NoAccess;
|
||||
}
|
||||
} else {
|
||||
memoryType = HasBattery() ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam;
|
||||
}
|
||||
|
||||
if(memoryType == PrgMemoryType::WorkRam) {
|
||||
//Properly mirror work ram (by ignoring the extra 1kb ExRAM section)
|
||||
bankNumber &= (realWorkRamSize / 0x2000) - 1;
|
||||
if(_workRamSize == MMC5::ExRamSize) {
|
||||
accessType = MemoryAccessType::NoAccess;
|
||||
}
|
||||
} else if(memoryType == PrgMemoryType::SaveRam) {
|
||||
//Properly mirror work ram (by ignoring the extra 1kb ExRAM section)
|
||||
bankNumber &= (realSaveRamSize / 0x2000) - 1;
|
||||
if(_saveRamSize == MMC5::ExRamSize) {
|
||||
accessType = MemoryAccessType::NoAccess;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accessType = MemoryAccessType::Read;
|
||||
|
@ -253,8 +236,7 @@ private:
|
|||
SetNametable(i, nametableId);
|
||||
} else if(nametableId == 2) {
|
||||
if(_extendedRamMode <= 1) {
|
||||
uint8_t* source = HasBattery() ? (_saveRam + (_saveRamSize - MMC5::ExRamSize)) : (_workRam + (_workRamSize - MMC5::ExRamSize));
|
||||
SetPpuMemoryMapping(0x2000 + i * 0x400, 0x2000 + i * 0x400 + 0x3FF, source, 0, MMC5::ExRamSize, MemoryAccessType::ReadWrite);
|
||||
SetPpuMemoryMapping(0x2000 + i * 0x400, 0x2000 + i * 0x400 + 0x3FF, ChrMemoryType::MapperRam, 0, MemoryAccessType::ReadWrite);
|
||||
} else {
|
||||
SetPpuMemoryMapping(0x2000 + i * 0x400, 0x2000 + i * 0x400 + 0x3FF, _emptyNametable, 0, BaseMapper::NametableSize, MemoryAccessType::Read);
|
||||
}
|
||||
|
@ -281,11 +263,7 @@ private:
|
|||
accessType = MemoryAccessType::Read;
|
||||
}
|
||||
|
||||
if(HasBattery()) {
|
||||
SetCpuMemoryMapping(0x5C00, 0x5FFF, PrgMemoryType::SaveRam, _saveRamSize - MMC5::ExRamSize, accessType);
|
||||
} else {
|
||||
SetCpuMemoryMapping(0x5C00, 0x5FFF, PrgMemoryType::WorkRam, _workRamSize - MMC5::ExRamSize, accessType);
|
||||
}
|
||||
SetCpuMemoryMapping(0x5C00, 0x5FFF, PrgMemoryType::MapperRam, 0, accessType);
|
||||
|
||||
SetNametableMapping(_nametableMapping);
|
||||
}
|
||||
|
@ -306,6 +284,7 @@ private:
|
|||
protected:
|
||||
uint16_t GetPrgPageSize() override { return 0x2000; }
|
||||
uint16_t GetChrPageSize() override { return 0x400; }
|
||||
uint32_t GetMapperRamSize() override { return 0x400; }
|
||||
uint16_t RegisterStartAddress() override { return 0x5000; }
|
||||
uint16_t RegisterEndAddress() override { return 0x5206; }
|
||||
uint32_t GetSaveRamPageSize() override { return 0x2000; }
|
||||
|
@ -327,12 +306,6 @@ protected:
|
|||
//Emulate as if a single 64k block of work/save ram existed
|
||||
size = _romInfo.HasBattery ? 0x10000 : 0;
|
||||
}
|
||||
|
||||
if(HasBattery()) {
|
||||
//If there's a battery on the board, exram gets saved, too.
|
||||
size += MMC5::ExRamSize;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -347,10 +320,6 @@ protected:
|
|||
//Emulate as if a single 64k block of work/save ram existed (+ 1kb of ExRAM)
|
||||
size = (_romInfo.HasBattery ? 0 : 0x10000);
|
||||
}
|
||||
if(!HasBattery()) {
|
||||
size += MMC5::ExRamSize;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -393,6 +362,27 @@ protected:
|
|||
_console->GetMemoryManager()->RegisterWriteHandler(_mmc5MemoryHandler.get(), 0x2000, 0x2007);
|
||||
}
|
||||
|
||||
void LoadBattery() override
|
||||
{
|
||||
if(HasBattery() && _saveRamSize > 0) {
|
||||
//Load EXRAM and save ram from the same file
|
||||
vector<uint8_t> data(_saveRamSize + _mapperRamSize);
|
||||
_emu->GetBatteryManager()->LoadBattery(".sav", _saveRam, _saveRamSize + _mapperRamSize);
|
||||
memcpy(_saveRam, data.data(), _saveRamSize);
|
||||
memcpy(_mapperRam, data.data()+_saveRamSize, _mapperRamSize);
|
||||
}
|
||||
}
|
||||
|
||||
void SaveBattery() override
|
||||
{
|
||||
if(HasBattery()) {
|
||||
//Save EXRAM and save ram to the same file
|
||||
vector<uint8_t> data(_saveRam, _saveRam + _saveRamSize);
|
||||
data.insert(data.end(), _mapperRam, _mapperRam + _mapperRamSize);
|
||||
_emu->GetBatteryManager()->SaveBattery(".sav", data.data(), (uint32_t)data.size());
|
||||
}
|
||||
}
|
||||
|
||||
void Serialize(Serializer& s) override
|
||||
{
|
||||
BaseMapper::Serialize(s);
|
||||
|
@ -681,31 +671,52 @@ protected:
|
|||
}
|
||||
|
||||
public:
|
||||
bool IsExtendedAttributes()
|
||||
bool HasExtendedAttributes(ExtModeConfig& cfg, uint8_t ntIndex) override
|
||||
{
|
||||
return _extendedRamMode == 1;
|
||||
return cfg.Nametables[0].AttrExtMode;
|
||||
}
|
||||
|
||||
bool HasExtendedBackground(ExtModeConfig& cfg, uint8_t ntIndex) override
|
||||
{
|
||||
if(ntIndex == 4) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return cfg.Nametables[0].BgExtMode;
|
||||
}
|
||||
|
||||
uint8_t GetExAttributeNtPalette(uint16_t ntAddr)
|
||||
uint8_t GetExAttributePalette(ExtModeConfig& cfg, uint8_t ntIndex, uint16_t ntOffset) override
|
||||
{
|
||||
ntAddr &= 0x3FF;
|
||||
uint8_t value = InternalReadRam(0x5C00 + ntAddr);
|
||||
uint8_t value = cfg.ExtRam[ntOffset];
|
||||
return (value & 0xC0) >> 6;
|
||||
}
|
||||
|
||||
uint32_t GetExAttributeAbsoluteTileAddr(uint16_t ntAddr, uint16_t chrAddr)
|
||||
uint8_t GetExBackgroundChrData(ExtModeConfig& cfg, uint8_t ntIndex, uint16_t ntOffset, uint16_t chrAddr) override
|
||||
{
|
||||
ntAddr &= 0x3FF;
|
||||
uint8_t value = InternalReadRam(0x5C00 + ntAddr);
|
||||
|
||||
//"The pattern fetches ignore the standard CHR banking bits, and instead use the top two bits of $5130 and the bottom 6 bits from Expansion RAM to choose a 4KB bank to select the tile from."
|
||||
uint16_t chrBank = (value & 0x3F) | (_chrUpperBits << 6);
|
||||
|
||||
return (chrBank << 12) + (chrAddr & 0xFFF);
|
||||
if(ntIndex == 4) {
|
||||
//Split mode
|
||||
return ReadFromChr((cfg.Nametables[4].SourceOffset << 12) + (chrAddr & 0xFFF));
|
||||
} else {
|
||||
uint8_t value = cfg.ExtRam[ntOffset];
|
||||
uint16_t chrBank = (value & 0x3F) | (cfg.BgExtBank << 6);
|
||||
uint32_t addr = (chrBank << 12) + (chrAddr & 0xFFF);
|
||||
return ReadFromChr(addr);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t GetExAttributeTileData(uint16_t ntAddr, uint16_t chrAddr)
|
||||
ExtModeConfig GetExModeConfig() override
|
||||
{
|
||||
return ReadFromChr(GetExAttributeAbsoluteTileAddr(ntAddr, chrAddr));
|
||||
ExtModeConfig cfg = {};
|
||||
|
||||
cfg.Nametables[0].AttrExtMode = _extendedRamMode == 1;
|
||||
cfg.Nametables[0].BgExtMode = _extendedRamMode == 1;
|
||||
cfg.BgExtBank = _chrUpperBits;
|
||||
|
||||
cfg.Nametables[4].SourceOffset = _verticalSplitBank;
|
||||
cfg.WindowScrollY = _verticalSplitScroll;
|
||||
|
||||
memcpy(cfg.ExtRam, _mapperRam, _mapperRamSize);
|
||||
|
||||
return cfg;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -60,7 +60,7 @@ void NesMemoryManager::InitializeMemoryHandlers(INesMemoryHandler** memoryHandle
|
|||
{
|
||||
for(uint16_t address : *addresses) {
|
||||
if(!allowOverride && memoryHandlers[address] != &_openBusHandler && memoryHandlers[address] != handler) {
|
||||
throw std::runtime_error("Not supported");
|
||||
throw std::runtime_error("Can't override existing mapping");
|
||||
}
|
||||
memoryHandlers[address] = handler;
|
||||
}
|
||||
|
@ -77,11 +77,18 @@ void NesMemoryManager::RegisterIODevice(INesMemoryHandler*handler)
|
|||
|
||||
void NesMemoryManager::RegisterWriteHandler(INesMemoryHandler* handler, uint32_t start, uint32_t end)
|
||||
{
|
||||
for(uint32_t i = start; i < end; i++) {
|
||||
for(uint32_t i = start; i <= end; i++) {
|
||||
_ramWriteHandlers[i] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
void NesMemoryManager::RegisterReadHandler(INesMemoryHandler* handler, uint32_t start, uint32_t end)
|
||||
{
|
||||
for(uint32_t i = start; i <= end; i++) {
|
||||
_ramReadHandlers[i] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
void NesMemoryManager::UnregisterIODevice(INesMemoryHandler*handler)
|
||||
{
|
||||
MemoryRanges ranges;
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
void Reset(bool softReset);
|
||||
void RegisterIODevice(INesMemoryHandler* handler);
|
||||
void RegisterWriteHandler(INesMemoryHandler* handler, uint32_t start, uint32_t end);
|
||||
void RegisterReadHandler(INesMemoryHandler* handler, uint32_t start, uint32_t end);
|
||||
void UnregisterIODevice(INesMemoryHandler* handler);
|
||||
|
||||
uint8_t DebugRead(uint16_t addr);
|
||||
|
|
|
@ -59,6 +59,7 @@ enum class PrgMemoryType
|
|||
PrgRom,
|
||||
SaveRam,
|
||||
WorkRam,
|
||||
MapperRam,
|
||||
};
|
||||
|
||||
enum class ChrMemoryType
|
||||
|
@ -66,7 +67,8 @@ enum class ChrMemoryType
|
|||
Default,
|
||||
ChrRom,
|
||||
ChrRam,
|
||||
NametableRam
|
||||
NametableRam,
|
||||
MapperRam,
|
||||
};
|
||||
|
||||
enum MemoryAccessType
|
||||
|
@ -165,7 +167,7 @@ struct CartridgeState
|
|||
bool HasBattery = false;
|
||||
|
||||
uint32_t CustomEntryCount = 0;
|
||||
MapperStateEntry CustomEntries[100] = {};
|
||||
MapperStateEntry CustomEntries[200] = {};
|
||||
};
|
||||
|
||||
struct PPUStatusFlags
|
||||
|
|
|
@ -29,7 +29,7 @@ FrameInfo PceVdcTools::GetTilemapSize(GetTilemapOptions options, BaseState& base
|
|||
}
|
||||
}
|
||||
|
||||
DebugTilemapTileInfo PceVdcTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
|
||||
DebugTilemapTileInfo PceVdcTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugTilemapTileInfo result = {};
|
||||
|
||||
|
@ -61,7 +61,7 @@ DebugTilemapTileInfo PceVdcTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uin
|
|||
return result;
|
||||
}
|
||||
|
||||
DebugTilemapInfo PceVdcTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
DebugTilemapInfo PceVdcTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
{
|
||||
PceVdcState& state = options.Layer == 0 ? ((PceVideoState&)baseState).Vdc : ((PceVideoState&)baseState).Vdc2;
|
||||
|
||||
|
@ -296,7 +296,7 @@ void PceVdcTools::InternalGetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* sprit
|
|||
}
|
||||
}
|
||||
|
||||
void PceVdcTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
void PceVdcTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
{
|
||||
PceVdcState& state = ((PceVideoState&)baseState).Vdc;
|
||||
for(int i = 0, len = _console->IsSuperGrafx() ? 128 : 64; i < len; i++) {
|
||||
|
@ -307,7 +307,7 @@ void PceVdcTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& base
|
|||
GetSpritePreview(options, baseState, outBuffer, spritePreviews, palette, screenPreview);
|
||||
}
|
||||
|
||||
DebugSpritePreviewInfo PceVdcTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& baseState)
|
||||
DebugSpritePreviewInfo PceVdcTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
PceVdcState& state = ((PceVideoState&)baseState).Vdc;
|
||||
|
||||
|
|
|
@ -27,12 +27,12 @@ public:
|
|||
|
||||
void SetViewerUpdateTiming(uint32_t viewerId, uint16_t scanline, uint16_t cycle) override;
|
||||
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
FrameInfo GetTilemapSize(GetTilemapOptions options, BaseState& state) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState) override;
|
||||
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
|
||||
DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
|
||||
void SetPaletteColor(int32_t colorIndex, uint32_t color) override;
|
||||
|
|
|
@ -19,7 +19,7 @@ FrameInfo SmsVdpTools::GetTilemapSize(GetTilemapOptions options, BaseState& base
|
|||
return { isTextMode ? 240u : 256u, state.NametableHeight };
|
||||
}
|
||||
|
||||
DebugTilemapInfo SmsVdpTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
DebugTilemapInfo SmsVdpTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
{
|
||||
SmsVdpState& state = (SmsVdpState&)baseState;
|
||||
|
||||
|
@ -149,7 +149,7 @@ DebugTilemapInfo SmsVdpTools::GetTilemap(GetTilemapOptions options, BaseState& b
|
|||
return result;
|
||||
}
|
||||
|
||||
DebugTilemapTileInfo SmsVdpTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
|
||||
DebugTilemapTileInfo SmsVdpTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugTilemapTileInfo result = {};
|
||||
|
||||
|
@ -277,7 +277,7 @@ void SmsVdpTools::GetSpritePreview(GetSpritePreviewOptions options, BaseState& b
|
|||
}
|
||||
}
|
||||
|
||||
DebugSpritePreviewInfo SmsVdpTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& baseState)
|
||||
DebugSpritePreviewInfo SmsVdpTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
SmsVdpState& state = (SmsVdpState&)baseState;
|
||||
DebugSpritePreviewInfo info = {};
|
||||
|
@ -391,7 +391,7 @@ void SmsVdpTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePreview
|
|||
}
|
||||
}
|
||||
|
||||
void SmsVdpTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
void SmsVdpTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
{
|
||||
SmsVdpState& state = (SmsVdpState&)baseState;
|
||||
int spriteCount = state.UseMode4 ? 64 : 32;
|
||||
|
|
|
@ -18,12 +18,12 @@ private:
|
|||
public:
|
||||
SmsVdpTools(Debugger* debugger, Emulator *emu, SmsConsole* console);
|
||||
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
FrameInfo GetTilemapSize(GetTilemapOptions options, BaseState& state) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState) override;
|
||||
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
|
||||
DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
|
||||
void SetPaletteColor(int32_t colorIndex, uint32_t color) override;
|
||||
|
|
|
@ -40,7 +40,7 @@ void SnesPpuTools::SetPpuRowBuffers(uint16_t scanline, uint16_t xStart, uint16_t
|
|||
}
|
||||
}
|
||||
|
||||
DebugTilemapInfo SnesPpuTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
DebugTilemapInfo SnesPpuTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
{
|
||||
SnesPpuState& state = (SnesPpuState&)baseState;
|
||||
FrameInfo outputSize = GetTilemapSize(options, state);
|
||||
|
@ -229,10 +229,10 @@ static constexpr uint8_t _oamSizes[8][2][2] = {
|
|||
{ { 2, 4 }, { 4, 4 } } //16x32 + 32x32
|
||||
};
|
||||
|
||||
void SnesPpuTools::GetSpritePreview(GetSpritePreviewOptions options, BaseState& baseState, DebugSpriteInfo* sprites, uint32_t* spritePreviews, uint32_t* palette, uint32_t* outBuffer)
|
||||
void SnesPpuTools::GetSpritePreview(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, DebugSpriteInfo* sprites, uint32_t* spritePreviews, uint32_t* palette, uint32_t* outBuffer)
|
||||
{
|
||||
SnesPpuState& state = (SnesPpuState&)baseState;
|
||||
DebugSpritePreviewInfo size = GetSpritePreviewInfo(options, state);
|
||||
DebugSpritePreviewInfo size = GetSpritePreviewInfo(options, state, ppuToolsState);
|
||||
uint32_t bgColor = GetSpriteBackgroundColor(options.Background, palette, false);
|
||||
|
||||
std::fill(outBuffer, outBuffer + size.Width * size.Height, GetSpriteBackgroundColor(options.Background, palette, true));
|
||||
|
@ -393,7 +393,7 @@ void SnesPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePrevie
|
|||
}
|
||||
}
|
||||
|
||||
void SnesPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
void SnesPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
{
|
||||
SnesPpuState& state = (SnesPpuState&)baseState;
|
||||
for(int i = 0; i < 128; i++) {
|
||||
|
@ -401,7 +401,7 @@ void SnesPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& bas
|
|||
GetSpriteInfo(outBuffer[i], spritePreviews + (i * _spritePreviewSize), i, options, state, vram, oamRam, palette);
|
||||
}
|
||||
|
||||
GetSpritePreview(options, baseState, outBuffer, spritePreviews, palette, screenPreview);
|
||||
GetSpritePreview(options, baseState, ppuToolsState, outBuffer, spritePreviews, palette, screenPreview);
|
||||
}
|
||||
|
||||
FrameInfo SnesPpuTools::GetTilemapSize(GetTilemapOptions options, BaseState& baseState)
|
||||
|
@ -444,7 +444,7 @@ FrameInfo SnesPpuTools::GetTilemapSize(GetTilemapOptions options, BaseState& bas
|
|||
return size;
|
||||
}
|
||||
|
||||
DebugTilemapTileInfo SnesPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
|
||||
DebugTilemapTileInfo SnesPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugTilemapTileInfo result = {};
|
||||
|
||||
|
@ -514,7 +514,7 @@ DebugTilemapTileInfo SnesPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, ui
|
|||
return result;
|
||||
}
|
||||
|
||||
DebugSpritePreviewInfo SnesPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& baseState)
|
||||
DebugSpritePreviewInfo SnesPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
SnesPpuState& state = (SnesPpuState&)baseState;
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ private:
|
|||
template<TileFormat format> void RenderTilemap(GetTilemapOptions& options, int rowCount, LayerConfig& layer, int columnCount, uint8_t* vram, int tileHeight, int tileWidth, bool largeTileHeight, bool largeTileWidth, uint8_t bpp, uint32_t* outBuffer, FrameInfo outputSize, const uint32_t* palette, uint16_t basePaletteOffset);
|
||||
|
||||
DebugTilemapInfo RenderScreenView(uint8_t layer, uint32_t* outBuffer);
|
||||
void GetSpritePreview(GetSpritePreviewOptions options, BaseState& state, DebugSpriteInfo* sprites, uint32_t* spritePreviews, uint32_t* palette, uint32_t* outBuffer);
|
||||
void GetSpritePreview(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState, DebugSpriteInfo* sprites, uint32_t* spritePreviews, uint32_t* palette, uint32_t* outBuffer);
|
||||
|
||||
public:
|
||||
SnesPpuTools(Debugger* debugger, Emulator *emu);
|
||||
|
@ -44,12 +44,12 @@ public:
|
|||
void SetPpuScanlineState(uint16_t scanline, uint8_t mode, int32_t mode7startX, int32_t mode7startY, int32_t mode7endX, int32_t mode7endY);
|
||||
void SetPpuRowBuffers(uint16_t scanline, uint16_t xStart, uint16_t xEnd, uint16_t mainScreenRowBuffer[256], uint16_t subScreenRowBuffer[256]);
|
||||
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer) override;
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer) override;
|
||||
FrameInfo GetTilemapSize(GetTilemapOptions options, BaseState& state) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState) override;
|
||||
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState) override;
|
||||
|
||||
DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
|
||||
void SetPaletteColor(int32_t colorIndex, uint32_t color) override;
|
||||
|
|
|
@ -48,6 +48,7 @@ enum class MemoryType
|
|||
NesWorkRam,
|
||||
NesSaveRam,
|
||||
NesNametableRam,
|
||||
NesMapperRam,
|
||||
NesSpriteRam,
|
||||
NesSecondarySpriteRam,
|
||||
NesPaletteRam,
|
||||
|
|
|
@ -17,7 +17,7 @@ FrameInfo WsPpuTools::GetTilemapSize(GetTilemapOptions options, BaseState& baseS
|
|||
return { 256, 256 };
|
||||
}
|
||||
|
||||
DebugTilemapInfo WsPpuTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
DebugTilemapInfo WsPpuTools::GetTilemap(GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t* outBuffer)
|
||||
{
|
||||
WsPpuState& state = (WsPpuState&)baseState;
|
||||
|
||||
|
@ -115,7 +115,7 @@ DebugTilemapInfo WsPpuTools::GetTilemap(GetTilemapOptions options, BaseState& ba
|
|||
return result;
|
||||
}
|
||||
|
||||
DebugTilemapTileInfo WsPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
|
||||
DebugTilemapTileInfo WsPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugTilemapTileInfo result = {};
|
||||
|
||||
|
@ -200,7 +200,7 @@ void WsPpuTools::GetSpritePreview(GetSpritePreviewOptions options, BaseState& ba
|
|||
}
|
||||
}
|
||||
|
||||
DebugSpritePreviewInfo WsPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& baseState)
|
||||
DebugSpritePreviewInfo WsPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState)
|
||||
{
|
||||
DebugSpritePreviewInfo info = {};
|
||||
info.Height = 256;
|
||||
|
@ -318,7 +318,7 @@ void WsPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t* spritePreview,
|
|||
}
|
||||
}
|
||||
|
||||
void WsPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
void WsPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview)
|
||||
{
|
||||
WsPpuState& state = (WsPpuState&)baseState;
|
||||
int spriteCount = 128;
|
||||
|
|
|
@ -18,12 +18,12 @@ private:
|
|||
public:
|
||||
WsPpuTools(Debugger* debugger, Emulator *emu, WsConsole* console);
|
||||
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
DebugTilemapInfo GetTilemap(GetTilemapOptions options, BaseState& state, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t *outBuffer) override;
|
||||
FrameInfo GetTilemapSize(GetTilemapOptions options, BaseState& state) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState) override;
|
||||
DebugTilemapTileInfo GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState, BaseState& ppuToolsState) override;
|
||||
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState) override;
|
||||
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[], uint32_t* spritePreviews, uint32_t* screenPreview) override;
|
||||
|
||||
DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
|
||||
void SetPaletteColor(int32_t colorIndex, uint32_t color) override;
|
||||
|
|
|
@ -159,12 +159,12 @@ extern "C"
|
|||
DllExport void __stdcall GetTileView(CpuType cpuType, GetTileViewOptions options, uint8_t* source, uint32_t srcSize, uint32_t* colors, uint32_t* buffer) { WithToolVoid(GetPpuTools(cpuType), GetTileView(options, source, srcSize, colors, buffer)); }
|
||||
|
||||
DllExport void __stdcall GetPpuToolsState(CpuType cpuType, BaseState& state) { return WithToolVoid(GetPpuTools(cpuType), GetPpuToolsState(state)); }
|
||||
DllExport DebugTilemapInfo __stdcall GetTilemap(CpuType cpuType, GetTilemapOptions options, BaseState& state, uint8_t* vram, uint32_t* palette, uint32_t* outputBuffer) { return WithTool(DebugTilemapInfo, GetPpuTools(cpuType), GetTilemap(options, state, vram, palette, outputBuffer)); }
|
||||
DllExport DebugTilemapInfo __stdcall GetTilemap(CpuType cpuType, GetTilemapOptions options, BaseState& state, BaseState& ppuToolsState, uint8_t* vram, uint32_t* palette, uint32_t* outputBuffer) { return WithTool(DebugTilemapInfo, GetPpuTools(cpuType), GetTilemap(options, state, ppuToolsState, vram, palette, outputBuffer)); }
|
||||
DllExport FrameInfo __stdcall GetTilemapSize(CpuType cpuType, GetTilemapOptions options, BaseState& state) { return WithTool(FrameInfo, GetPpuTools(cpuType), GetTilemapSize(options, state)); }
|
||||
DllExport DebugTilemapTileInfo __stdcall GetTilemapTileInfo(uint32_t x, uint32_t y, CpuType cpuType, GetTilemapOptions options, uint8_t* vram, BaseState& state) { return WithTool(DebugTilemapTileInfo, GetPpuTools(cpuType), GetTilemapTileInfo(x, y, vram, options, state)); }
|
||||
DllExport DebugTilemapTileInfo __stdcall GetTilemapTileInfo(uint32_t x, uint32_t y, CpuType cpuType, GetTilemapOptions options, uint8_t* vram, BaseState& state, BaseState& ppuToolsState) { return WithTool(DebugTilemapTileInfo, GetPpuTools(cpuType), GetTilemapTileInfo(x, y, vram, options, state, ppuToolsState)); }
|
||||
|
||||
DllExport DebugSpritePreviewInfo __stdcall GetSpritePreviewInfo(CpuType cpuType, GetSpritePreviewOptions options, BaseState& state) { return WithTool(DebugSpritePreviewInfo, GetPpuTools(cpuType), GetSpritePreviewInfo(options, state)); }
|
||||
DllExport void __stdcall GetSpriteList(CpuType cpuType, GetSpritePreviewOptions options, BaseState& state, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo sprites[], uint32_t* spritePreviews, uint32_t* screenPreview) { WithToolVoid(GetPpuTools(cpuType), GetSpriteList(options, state, vram, oamRam, palette, sprites, spritePreviews, screenPreview)); }
|
||||
DllExport DebugSpritePreviewInfo __stdcall GetSpritePreviewInfo(CpuType cpuType, GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState) { return WithTool(DebugSpritePreviewInfo, GetPpuTools(cpuType), GetSpritePreviewInfo(options, state, ppuToolsState)); }
|
||||
DllExport void __stdcall GetSpriteList(CpuType cpuType, GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo sprites[], uint32_t* spritePreviews, uint32_t* screenPreview) { WithToolVoid(GetPpuTools(cpuType), GetSpriteList(options, state, ppuToolsState, vram, oamRam, palette, sprites, spritePreviews, screenPreview)); }
|
||||
|
||||
DllExport DebugPaletteInfo __stdcall GetPaletteInfo(CpuType cpuType, GetPaletteInfoOptions options) { return WithTool(DebugPaletteInfo, GetPpuTools(cpuType), GetPaletteInfo(options)); }
|
||||
DllExport void __stdcall SetPaletteColor(CpuType cpuType, int32_t colorIndex, uint32_t color) { WithToolVoid(GetPpuTools(cpuType), SetPaletteColor(colorIndex, color)); }
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace Mesen.Config
|
|||
case MemoryType.GbVideoRam:
|
||||
case MemoryType.GbSpriteRam:
|
||||
case MemoryType.NesNametableRam:
|
||||
case MemoryType.NesMapperRam:
|
||||
case MemoryType.NesSpriteRam:
|
||||
case MemoryType.NesSecondarySpriteRam:
|
||||
case MemoryType.NesPaletteRam:
|
||||
|
|
|
@ -494,7 +494,8 @@
|
|||
{ "name": "nes", "description": "NES - Main CPU - 2A03 (6502)" },
|
||||
{ "name": "pce", "description": "PC Engine - Main CPU - HuC6280" },
|
||||
{ "name": "sms", "description": "SMS - Main CPU - Z80" },
|
||||
{ "name": "gba", "description": "GBA - Main CPU - ARM7TDMI" }
|
||||
{ "name": "gba", "description": "GBA - Main CPU - ARM7TDMI" },
|
||||
{ "name": "ws", "description": "WS - Main CPU - NEC V30MZ" },
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -540,6 +541,7 @@
|
|||
{ "name": "pceMemory", "description": "PC Engine - CPU memory" },
|
||||
{ "name": "smsMemory", "description": "SMS - CPU memory" },
|
||||
{ "name": "gbaMemory", "description": "GBA - CPU memory" },
|
||||
{ "name": "wsMemory", "description": "WS - CPU memory" },
|
||||
|
||||
{ "name": "snesDebug", "description": "SNES - S-CPU memory (no read/write side-effects)" },
|
||||
{ "name": "spcDebug", "description": "SNES - SPC memory (no read/write side-effects)" },
|
||||
|
@ -553,6 +555,7 @@
|
|||
{ "name": "pceDebug", "description": "PC Engine - CPU memory (no read/write side-effects)" },
|
||||
{ "name": "smsDebug", "description": "SMS - CPU memory (no read/write side-effects)" },
|
||||
{ "name": "gbaDebug", "description": "GBA - CPU memory (no read/write side-effects)" },
|
||||
{ "name": "wsDebug", "description": "WS - CPU memory (no read/write side-effects)" },
|
||||
|
||||
{ "name": "snesPrgRom", "description": "SNES - PRG ROM" },
|
||||
{ "name": "snesWorkRam", "description": "SNES - Work RAM" },
|
||||
|
@ -584,6 +587,7 @@
|
|||
{ "name": "nesWorkRam", "description": "NES - Work RAM" },
|
||||
{ "name": "nesSaveRam", "description": "NES - Save RAM" },
|
||||
{ "name": "nesNametableRam", "description": "NES - Nametable RAM (CIRAM)" },
|
||||
{ "name": "nesMapperRam", "description": "NES - Mapper RAM (EXRAM)" },
|
||||
{ "name": "nesSpriteRam", "description": "NES - Sprite RAM (OAM)" },
|
||||
{ "name": "nesSecondarySpriteRam", "description": "NES - Secondary Sprite RAM" },
|
||||
{ "name": "nesPaletteRam", "description": "NES - Palette RAM" },
|
||||
|
@ -619,6 +623,14 @@
|
|||
{ "name": "gbaVideoRam", "description": "GBA - Video RAM" },
|
||||
{ "name": "gbaSpriteRam", "description": "GBA - Sprite RAM" },
|
||||
{ "name": "gbaPaletteRam", "description": "GBA - Palette RAM" }
|
||||
|
||||
{ "name": "wsPrgRom", "description": "WS - ROM" }
|
||||
{ "name": "wsWorkRam", "description": "WS - Work RAM" }
|
||||
{ "name": "wsCartRam", "description": "WS - Save RAM" }
|
||||
{ "name": "wsCartEeprom", "description": "WS - Cart EEPROM" }
|
||||
{ "name": "wsBootRom", "description": "WS - Boot ROM" }
|
||||
{ "name": "wsInternalEeprom", "description": "WS - Internal EEPROM" }
|
||||
{ "name": "wsPort", "description": "WS - I/O Port" }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -74,18 +74,21 @@ namespace Mesen.Debugger.ViewModels
|
|||
Dictionary<NesPrgMemoryType, Color> mainColors = new() {
|
||||
{ NesPrgMemoryType.WorkRam, Color.FromRgb(0xCD, 0xDC, 0xFA) },
|
||||
{ NesPrgMemoryType.SaveRam, Color.FromRgb(0xFA, 0xDC, 0xCD) },
|
||||
{ NesPrgMemoryType.PrgRom, Color.FromRgb(0xC4, 0xE7, 0xD4) }
|
||||
{ NesPrgMemoryType.PrgRom, Color.FromRgb(0xC4, 0xE7, 0xD4) },
|
||||
{ NesPrgMemoryType.MapperRam, Color.FromRgb(0xFF, 0xEB, 0x6F) }
|
||||
};
|
||||
|
||||
Dictionary<NesPrgMemoryType, Color> altColors = new() {
|
||||
{ NesPrgMemoryType.WorkRam, Color.FromRgb(0xBD, 0xCC, 0xEA) },
|
||||
{ NesPrgMemoryType.SaveRam, Color.FromRgb(0xEA, 0xCC, 0xBD) },
|
||||
{ NesPrgMemoryType.PrgRom, Color.FromRgb(0xA4, 0xD7, 0xB4) }
|
||||
{ NesPrgMemoryType.PrgRom, Color.FromRgb(0xA4, 0xD7, 0xB4) },
|
||||
{ NesPrgMemoryType.MapperRam, Color.FromRgb(0xEF, 0xDB, 0x5F) }
|
||||
};
|
||||
|
||||
Dictionary<NesPrgMemoryType, string> blockNames = new() {
|
||||
{ NesPrgMemoryType.WorkRam, "WRAM" },
|
||||
{ NesPrgMemoryType.SaveRam, "SRAM" },
|
||||
{ NesPrgMemoryType.MapperRam, "EXRAM" },
|
||||
{ NesPrgMemoryType.PrgRom, "" }
|
||||
};
|
||||
|
||||
|
@ -121,7 +124,8 @@ namespace Mesen.Debugger.ViewModels
|
|||
int page = memoryType.Value switch {
|
||||
NesPrgMemoryType.WorkRam => (int)(state.PrgMemoryOffset[startIndex] / state.WorkRamPageSize),
|
||||
NesPrgMemoryType.SaveRam => (int)(state.PrgMemoryOffset[startIndex] / state.SaveRamPageSize),
|
||||
_ or NesPrgMemoryType.PrgRom => (int)(state.PrgMemoryOffset[startIndex] / state.PrgPageSize)
|
||||
NesPrgMemoryType.PrgRom => (int)(state.PrgMemoryOffset[startIndex] / state.PrgPageSize),
|
||||
_ => -1
|
||||
};
|
||||
|
||||
mappings.Add(new MemoryMappingBlock() { Length = currentSize, Name = blockNames[memoryType.Value], Page = page, Note = accessNotes[accessType], Color = color });
|
||||
|
@ -166,13 +170,15 @@ namespace Mesen.Debugger.ViewModels
|
|||
Dictionary<NesChrMemoryType, Color> mainColors = new() {
|
||||
{ NesChrMemoryType.NametableRam, Color.FromRgb(0xF4, 0xC7, 0xD4) },
|
||||
{ NesChrMemoryType.ChrRom, Color.FromRgb(0xC4, 0xE7, 0xD4) },
|
||||
{ NesChrMemoryType.ChrRam, Color.FromRgb(0xC4, 0xE0, 0xF4) }
|
||||
{ NesChrMemoryType.ChrRam, Color.FromRgb(0xC4, 0xE0, 0xF4) },
|
||||
{ NesChrMemoryType.MapperRam, Color.FromRgb(0xFF, 0xEB, 0x6F) }
|
||||
};
|
||||
|
||||
Dictionary<NesChrMemoryType, Color> altColors = new() {
|
||||
{ NesChrMemoryType.NametableRam, Color.FromRgb(0xD4, 0xA7, 0xB4) },
|
||||
{ NesChrMemoryType.ChrRom, Color.FromRgb(0xA4, 0xD7, 0xB4) },
|
||||
{ NesChrMemoryType.ChrRam, Color.FromRgb(0xB4, 0xD0, 0xE4) }
|
||||
{ NesChrMemoryType.ChrRam, Color.FromRgb(0xB4, 0xD0, 0xE4) },
|
||||
{ NesChrMemoryType.MapperRam, Color.FromRgb(0xEF, 0xDB, 0x5F) }
|
||||
};
|
||||
|
||||
Dictionary<NesMemoryAccessType, string> accessNotes = new() {
|
||||
|
@ -202,13 +208,16 @@ namespace Mesen.Debugger.ViewModels
|
|||
int page = memoryType.Value switch {
|
||||
NesChrMemoryType.NametableRam => (int)(state.ChrMemoryOffset[startIndex] / 0x400),
|
||||
NesChrMemoryType.ChrRom => (int)(state.ChrMemoryOffset[startIndex] / state.ChrPageSize),
|
||||
_ or NesChrMemoryType.ChrRam => (int)(state.ChrMemoryOffset[startIndex] / state.ChrRamPageSize),
|
||||
NesChrMemoryType.ChrRam => (int)(state.ChrMemoryOffset[startIndex] / state.ChrRamPageSize),
|
||||
_ => -1
|
||||
};
|
||||
|
||||
string name = "";
|
||||
if(memoryType == NesChrMemoryType.NametableRam) {
|
||||
name = "NT" + page.ToString();
|
||||
page = -1;
|
||||
} else if(memoryType == NesChrMemoryType.MapperRam) {
|
||||
name = "EXRAM";
|
||||
}
|
||||
|
||||
mappings.Add(new MemoryMappingBlock() { Length = currentSize, Name = name, Page = page, Note = accessNotes[accessType], Color = color });
|
||||
|
|
|
@ -495,6 +495,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
{
|
||||
lock(_updateLock) {
|
||||
_coreData.PpuState = DebugApi.GetPpuState(CpuType);
|
||||
_coreData.PpuToolsState = DebugApi.GetPpuToolsState(CpuType);
|
||||
|
||||
UpdateVramData();
|
||||
|
||||
|
@ -534,7 +535,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
_coreData.CopyTo(_data);
|
||||
}
|
||||
|
||||
if(_data.PpuState == null || _data.Palette == null) {
|
||||
if(_data.PpuState == null || _data.Palette == null || _data.PpuToolsState == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -542,7 +543,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
Background = Config.Background
|
||||
};
|
||||
|
||||
DebugSpritePreviewInfo previewInfo = DebugApi.GetSpritePreviewInfo(CpuType, options, _data.PpuState);
|
||||
DebugSpritePreviewInfo previewInfo = DebugApi.GetSpritePreviewInfo(CpuType, options, _data.PpuState, _data.PpuToolsState);
|
||||
InitBitmap((int)previewInfo.Width, (int)previewInfo.Height);
|
||||
|
||||
UInt32[] palette = _data.Palette.Value.GetRgbPalette();
|
||||
|
@ -553,7 +554,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
BottomClipSize = Config.ShowOffscreenRegions ? 0 : (int)(previewInfo.Height - (previewInfo.VisibleHeight + previewInfo.VisibleY));
|
||||
|
||||
using(var framebuffer = ViewerBitmap.Lock(true)) {
|
||||
DebugApi.GetSpriteList(ref _spriteList, ref _spritePreviews, CpuType, options, _data.PpuState, _data.Vram, _data.SpriteRam, palette, framebuffer.FrameBuffer.Address);
|
||||
DebugApi.GetSpriteList(ref _spriteList, ref _spritePreviews, CpuType, options, _data.PpuState, _data.PpuToolsState, _data.Vram, _data.SpriteRam, palette, framebuffer.FrameBuffer.Address);
|
||||
}
|
||||
|
||||
InitPreviews(_spriteList, _spritePreviews, previewInfo);
|
||||
|
@ -672,6 +673,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
public class SpriteViewerData
|
||||
{
|
||||
public BaseState? PpuState;
|
||||
public BaseState? PpuToolsState;
|
||||
public byte[] SpriteRam = Array.Empty<byte>();
|
||||
public byte[] Vram = Array.Empty<byte>();
|
||||
public DebugPaletteInfo? Palette = null;
|
||||
|
@ -680,6 +682,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
{
|
||||
dst.PpuState = PpuState;
|
||||
dst.Palette = Palette;
|
||||
dst.PpuToolsState = PpuToolsState;
|
||||
CopyArray(SpriteRam, ref dst.SpriteRam);
|
||||
CopyArray(Vram, ref dst.Vram);
|
||||
}
|
||||
|
|
|
@ -332,6 +332,19 @@ namespace Mesen.Debugger.ViewModels
|
|||
break;
|
||||
|
||||
case CpuType.Nes:
|
||||
FrameInfo size = DebugApi.GetTilemapSize(CpuType.Nes, new GetTilemapOptions() { Layer = 1 }, new NesPpuState());
|
||||
if(size.Width != 0 && size.Height != 0) {
|
||||
Tabs = new List<TilemapViewerTab>() {
|
||||
new() { Title = "Nametables", Layer = 0 },
|
||||
new() { Title = "Window", Layer = 1 }
|
||||
};
|
||||
} else {
|
||||
Tabs = new List<TilemapViewerTab>() {
|
||||
new() { Title = "", Layer = 0 }
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
case CpuType.Sms:
|
||||
Tabs = new List<TilemapViewerTab>() {
|
||||
new() { Title = "", Layer = 0 }
|
||||
|
@ -384,7 +397,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
|
||||
private DebugTilemapTileInfo? GetSelectedTileInfo()
|
||||
{
|
||||
if(_data.PpuState == null || _data.Vram == null) {
|
||||
if(_data.PpuState == null || _data.PpuToolsState == null || _data.Vram == null) {
|
||||
return null;
|
||||
} else {
|
||||
PixelPoint p;
|
||||
|
@ -396,7 +409,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
}
|
||||
p = PixelPoint.FromPoint(SelectionRect.TopLeft, 1);
|
||||
}
|
||||
return DebugApi.GetTilemapTileInfo((uint)p.X, (uint)p.Y, CpuType, GetOptions(SelectedTab), _data.Vram, _data.PpuState);
|
||||
return DebugApi.GetTilemapTileInfo((uint)p.X, (uint)p.Y, CpuType, GetOptions(SelectedTab), _data.Vram, _data.PpuState, _data.PpuToolsState);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,7 +484,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
_coreData.CopyTo(_data);
|
||||
}
|
||||
|
||||
if(_data.PpuState == null) {
|
||||
if(_data.PpuState == null || _data.PpuToolsState == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -500,7 +513,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
InitBitmap((int)size.Width, (int)size.Height);
|
||||
|
||||
using(var framebuffer = ViewerBitmap.Lock()) {
|
||||
_data.TilemapInfo = DebugApi.GetTilemap(CpuType, options, _data.PpuState, _data.Vram, _data.RgbPalette, framebuffer.FrameBuffer.Address);
|
||||
_data.TilemapInfo = DebugApi.GetTilemap(CpuType, options, _data.PpuState, _data.PpuToolsState, _data.Vram, _data.RgbPalette, framebuffer.FrameBuffer.Address);
|
||||
}
|
||||
|
||||
if(_data.TilemapInfo.Bpp == 0) {
|
||||
|
@ -559,11 +572,11 @@ namespace Mesen.Debugger.ViewModels
|
|||
|
||||
public DynamicTooltip? GetPreviewPanel(PixelPoint p, DynamicTooltip? tooltipToUpdate)
|
||||
{
|
||||
if(_data.PpuState == null) {
|
||||
if(_data.PpuState == null || _data.PpuToolsState == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DebugTilemapTileInfo? result = DebugApi.GetTilemapTileInfo((uint)p.X, (uint)p.Y, CpuType, GetOptions(SelectedTab), _data.Vram, _data.PpuState);
|
||||
DebugTilemapTileInfo? result = DebugApi.GetTilemapTileInfo((uint)p.X, (uint)p.Y, CpuType, GetOptions(SelectedTab), _data.Vram, _data.PpuState, _data.PpuToolsState);
|
||||
if(result == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -667,7 +680,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
|
||||
private void EditTileGrid(int columnCount, int rowCount, Window wnd)
|
||||
{
|
||||
if(_data.PpuState == null) {
|
||||
if(_data.PpuState == null || _data.PpuToolsState == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -677,7 +690,7 @@ namespace Mesen.Debugger.ViewModels
|
|||
int palette = -1;
|
||||
for(int row = 0; row < rowCount; row++) {
|
||||
for(int col = 0; col < columnCount; col++) {
|
||||
DebugTilemapTileInfo? tile = DebugApi.GetTilemapTileInfo((uint)(p.X + GridSizeX*col), (uint)(p.Y + GridSizeY*row), CpuType, GetOptions(SelectedTab), _data.Vram, _data.PpuState);
|
||||
DebugTilemapTileInfo? tile = DebugApi.GetTilemapTileInfo((uint)(p.X + GridSizeX*col), (uint)(p.Y + GridSizeY*row), CpuType, GetOptions(SelectedTab), _data.Vram, _data.PpuState, _data.PpuToolsState);
|
||||
if(tile == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@ namespace Mesen.Debugger.Windows
|
|||
{
|
||||
public class BreakpointEditWindow : MesenWindow
|
||||
{
|
||||
[Obsolete("For designer only")]
|
||||
public BreakpointEditWindow() : this(new BreakpointEditViewModel()) { }
|
||||
|
||||
public BreakpointEditWindow(BreakpointEditViewModel model)
|
||||
{
|
||||
DataContext = model;
|
||||
|
|
|
@ -101,6 +101,7 @@ public enum NesPrgMemoryType
|
|||
PrgRom,
|
||||
SaveRam,
|
||||
WorkRam,
|
||||
MapperRam,
|
||||
}
|
||||
|
||||
public enum NesChrMemoryType
|
||||
|
@ -108,7 +109,8 @@ public enum NesChrMemoryType
|
|||
Default,
|
||||
ChrRom,
|
||||
ChrRam,
|
||||
NametableRam
|
||||
NametableRam,
|
||||
MapperRam,
|
||||
}
|
||||
|
||||
public enum NesMemoryAccessType
|
||||
|
@ -210,7 +212,7 @@ public struct NesCartridgeState
|
|||
public bool HasBattery;
|
||||
|
||||
public UInt32 CustomEntryCount;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 200)]
|
||||
public MapperStateEntry[] CustomEntries;
|
||||
}
|
||||
|
||||
|
@ -337,3 +339,32 @@ public struct NesApuState
|
|||
public NesApuDmcState Dmc;
|
||||
public NesApuFrameCounterState FrameCounter;
|
||||
}
|
||||
|
||||
public struct NtExtConfig
|
||||
{
|
||||
public UInt16 SourceOffset;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool AttrExtMode;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool BgExtMode;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool FillMode;
|
||||
};
|
||||
|
||||
public struct ExtModeConfig
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
|
||||
public NtExtConfig[] Nametables;
|
||||
|
||||
[MarshalAs(UnmanagedType.I1)] public bool SpriteExtMode;
|
||||
public byte BgExtBank;
|
||||
public byte SpriteExtBank;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
|
||||
public byte[] SpriteExtData;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x2000)]
|
||||
public byte[] ExtRam;
|
||||
};
|
||||
|
||||
public struct NesPpuToolsState : BaseState
|
||||
{
|
||||
public ExtModeConfig ExtConfig;
|
||||
}
|
|
@ -138,7 +138,7 @@ namespace Mesen.Interop
|
|||
{
|
||||
return cpuType switch {
|
||||
CpuType.Snes => GetPpuToolsState<SnesPpuToolsState>(cpuType),
|
||||
CpuType.Nes => GetPpuToolsState<EmptyPpuToolsState>(cpuType),
|
||||
CpuType.Nes => GetPpuToolsState<NesPpuToolsState>(cpuType),
|
||||
CpuType.Gameboy => GetPpuToolsState<EmptyPpuToolsState>(cpuType),
|
||||
CpuType.Pce => GetPpuToolsState<EmptyPpuToolsState>(cpuType),
|
||||
CpuType.Sms => GetPpuToolsState<EmptyPpuToolsState>(cpuType),
|
||||
|
@ -283,8 +283,8 @@ namespace Mesen.Interop
|
|||
DebugApi.GetMemoryStateWrapper(type, dst);
|
||||
}
|
||||
|
||||
[DllImport(DllPath)] private static extern DebugTilemapInfo GetTilemap(CpuType cpuType, InteropGetTilemapOptions options, IntPtr state, byte[] vram, UInt32[] palette, IntPtr outputBuffer);
|
||||
public unsafe static DebugTilemapInfo GetTilemap(CpuType cpuType, GetTilemapOptions options, BaseState state, byte[] vram, UInt32[] palette, IntPtr outputBuffer)
|
||||
[DllImport(DllPath)] private static extern DebugTilemapInfo GetTilemap(CpuType cpuType, InteropGetTilemapOptions options, IntPtr state, IntPtr ppuToolsState, byte[] vram, UInt32[] palette, IntPtr outputBuffer);
|
||||
public unsafe static DebugTilemapInfo GetTilemap(CpuType cpuType, GetTilemapOptions options, BaseState state, BaseState ppuToolsState, byte[] vram, UInt32[] palette, IntPtr outputBuffer)
|
||||
{
|
||||
Debug.Assert(state.GetType().IsValueType);
|
||||
Debug.Assert(IsValidPpuState(ref state, cpuType));
|
||||
|
@ -293,10 +293,14 @@ namespace Mesen.Interop
|
|||
fixed(AddressCounters* accessCounters = options.AccessCounters) {
|
||||
byte* stateBuffer = stackalloc byte[GetStateSize(state)];
|
||||
Marshal.StructureToPtr(state, (IntPtr)stateBuffer, false);
|
||||
|
||||
byte* ppuToolsStateBuffer = stackalloc byte[GetStateSize(ppuToolsState)];
|
||||
Marshal.StructureToPtr(ppuToolsState, (IntPtr)ppuToolsStateBuffer, false);
|
||||
|
||||
InteropGetTilemapOptions interopOptions = options.ToInterop();
|
||||
interopOptions.CompareVram = (IntPtr)compareVramPtr;
|
||||
interopOptions.AccessCounters = (IntPtr)accessCounters;
|
||||
return DebugApi.GetTilemap(cpuType, interopOptions, (IntPtr)stateBuffer, vram, palette, outputBuffer);
|
||||
return DebugApi.GetTilemap(cpuType, interopOptions, (IntPtr)stateBuffer, (IntPtr)ppuToolsStateBuffer, vram, palette, outputBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -309,36 +313,45 @@ namespace Mesen.Interop
|
|||
|
||||
byte* ptr = stackalloc byte[GetStateSize(state)];
|
||||
Marshal.StructureToPtr(state, (IntPtr)ptr, false);
|
||||
|
||||
return DebugApi.GetTilemapSize(cpuType, options.ToInterop(), (IntPtr)ptr);
|
||||
}
|
||||
|
||||
[DllImport(DllPath)] private static extern DebugTilemapTileInfo GetTilemapTileInfo(UInt32 x, UInt32 y, CpuType cpuType, InteropGetTilemapOptions options, byte[] vram, IntPtr state);
|
||||
public unsafe static DebugTilemapTileInfo? GetTilemapTileInfo(UInt32 x, UInt32 y, CpuType cpuType, GetTilemapOptions options, byte[] vram, BaseState state)
|
||||
[DllImport(DllPath)] private static extern DebugTilemapTileInfo GetTilemapTileInfo(UInt32 x, UInt32 y, CpuType cpuType, InteropGetTilemapOptions options, byte[] vram, IntPtr state, IntPtr ppuToolsState);
|
||||
public unsafe static DebugTilemapTileInfo? GetTilemapTileInfo(UInt32 x, UInt32 y, CpuType cpuType, GetTilemapOptions options, byte[] vram, BaseState state, BaseState ppuToolsState)
|
||||
{
|
||||
Debug.Assert(state.GetType().IsValueType);
|
||||
Debug.Assert(IsValidPpuState(ref state, cpuType));
|
||||
|
||||
byte* ptr = stackalloc byte[GetStateSize(state)];
|
||||
Marshal.StructureToPtr(state, (IntPtr)ptr, false);
|
||||
DebugTilemapTileInfo info = DebugApi.GetTilemapTileInfo(x, y, cpuType, options.ToInterop(), vram, (IntPtr)ptr);
|
||||
|
||||
byte* ppuToolsStateBuffer = stackalloc byte[GetStateSize(ppuToolsState)];
|
||||
Marshal.StructureToPtr(ppuToolsState, (IntPtr)ppuToolsStateBuffer, false);
|
||||
|
||||
DebugTilemapTileInfo info = DebugApi.GetTilemapTileInfo(x, y, cpuType, options.ToInterop(), vram, (IntPtr)ptr, (IntPtr)ppuToolsStateBuffer);
|
||||
return info.Row >= 0 ? info : null;
|
||||
}
|
||||
|
||||
[DllImport(DllPath)] public static extern void GetTileView(CpuType cpuType, GetTileViewOptions options, byte[] source, int srcSize, UInt32[] palette, IntPtr buffer);
|
||||
|
||||
[DllImport(DllPath)] private static extern DebugSpritePreviewInfo GetSpritePreviewInfo(CpuType cpuType, GetSpritePreviewOptions options, IntPtr state);
|
||||
public unsafe static DebugSpritePreviewInfo GetSpritePreviewInfo(CpuType cpuType, GetSpritePreviewOptions options, BaseState state)
|
||||
[DllImport(DllPath)] private static extern DebugSpritePreviewInfo GetSpritePreviewInfo(CpuType cpuType, GetSpritePreviewOptions options, IntPtr state, IntPtr ppuToolsState);
|
||||
public unsafe static DebugSpritePreviewInfo GetSpritePreviewInfo(CpuType cpuType, GetSpritePreviewOptions options, BaseState state, BaseState ppuToolsState)
|
||||
{
|
||||
Debug.Assert(state.GetType().IsValueType);
|
||||
Debug.Assert(IsValidPpuState(ref state, cpuType));
|
||||
|
||||
byte* ptr = stackalloc byte[GetStateSize(state)];
|
||||
Marshal.StructureToPtr(state, (IntPtr)ptr, false);
|
||||
return DebugApi.GetSpritePreviewInfo(cpuType, options, (IntPtr)ptr);
|
||||
|
||||
byte* ppuToolsStateBuffer = stackalloc byte[GetStateSize(ppuToolsState)];
|
||||
Marshal.StructureToPtr(ppuToolsState, (IntPtr)ppuToolsStateBuffer, false);
|
||||
|
||||
return DebugApi.GetSpritePreviewInfo(cpuType, options, (IntPtr)ptr, (IntPtr)ppuToolsStateBuffer);
|
||||
}
|
||||
|
||||
[DllImport(DllPath)] private static extern void GetSpriteList(CpuType cpuType, GetSpritePreviewOptions options, IntPtr state, byte[] vram, byte[]? spriteRam, UInt32[] palette, IntPtr sprites, IntPtr spritePreviews, IntPtr screenPreview);
|
||||
public unsafe static void GetSpriteList(ref DebugSpriteInfo[] result, ref UInt32[] spritePreviews, CpuType cpuType, GetSpritePreviewOptions options, BaseState state, byte[] vram, byte[] spriteRam, UInt32[] palette, IntPtr screenPreview)
|
||||
[DllImport(DllPath)] private static extern void GetSpriteList(CpuType cpuType, GetSpritePreviewOptions options, IntPtr state, IntPtr ppuToolsState, byte[] vram, byte[]? spriteRam, UInt32[] palette, IntPtr sprites, IntPtr spritePreviews, IntPtr screenPreview);
|
||||
public unsafe static void GetSpriteList(ref DebugSpriteInfo[] result, ref UInt32[] spritePreviews, CpuType cpuType, GetSpritePreviewOptions options, BaseState state, BaseState ppuToolsState, byte[] vram, byte[] spriteRam, UInt32[] palette, IntPtr screenPreview)
|
||||
{
|
||||
Debug.Assert(state.GetType().IsValueType);
|
||||
Debug.Assert(IsValidPpuState(ref state, cpuType));
|
||||
|
@ -346,7 +359,10 @@ namespace Mesen.Interop
|
|||
byte* statePtr = stackalloc byte[GetStateSize(state)];
|
||||
Marshal.StructureToPtr(state, (IntPtr)statePtr, false);
|
||||
|
||||
int count = (int)GetSpritePreviewInfo(cpuType, options, (IntPtr)statePtr).SpriteCount;
|
||||
byte* ppuToolsStateBuffer = stackalloc byte[GetStateSize(ppuToolsState)];
|
||||
Marshal.StructureToPtr(ppuToolsState, (IntPtr)ppuToolsStateBuffer, false);
|
||||
|
||||
int count = (int)GetSpritePreviewInfo(cpuType, options, (IntPtr)statePtr, (IntPtr)ppuToolsStateBuffer).SpriteCount;
|
||||
if(count != result.Length) {
|
||||
Array.Resize(ref result, count);
|
||||
}
|
||||
|
@ -357,7 +373,7 @@ namespace Mesen.Interop
|
|||
|
||||
fixed(DebugSpriteInfo* spritesPtr = result) {
|
||||
fixed(UInt32* spritePreviewsPtr = spritePreviews) {
|
||||
DebugApi.GetSpriteList(cpuType, options, (IntPtr)statePtr, vram, spriteRam.Length > 0 ? spriteRam : null, palette, (IntPtr)spritesPtr, (IntPtr)spritePreviewsPtr, screenPreview);
|
||||
DebugApi.GetSpriteList(cpuType, options, (IntPtr)statePtr, (IntPtr)ppuToolsStateBuffer, vram, spriteRam.Length > 0 ? spriteRam : null, palette, (IntPtr)spritesPtr, (IntPtr)spritePreviewsPtr, screenPreview);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -614,6 +630,7 @@ namespace Mesen.Interop
|
|||
NesWorkRam,
|
||||
NesSaveRam,
|
||||
NesNametableRam,
|
||||
NesMapperRam,
|
||||
NesSpriteRam,
|
||||
NesSecondarySpriteRam,
|
||||
NesPaletteRam,
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace Mesen.Interop
|
|||
case MemoryType.NesChrRom:
|
||||
case MemoryType.NesInternalRam:
|
||||
case MemoryType.NesNametableRam:
|
||||
case MemoryType.NesMapperRam:
|
||||
case MemoryType.NesPaletteRam:
|
||||
case MemoryType.NesSpriteRam:
|
||||
case MemoryType.NesPpuMemory:
|
||||
|
@ -272,6 +273,7 @@ namespace Mesen.Interop
|
|||
case MemoryType.NesWorkRam:
|
||||
case MemoryType.NesSaveRam:
|
||||
case MemoryType.NesInternalRam:
|
||||
case MemoryType.NesMapperRam:
|
||||
case MemoryType.NesMemory:
|
||||
|
||||
//PC Engine
|
||||
|
@ -455,6 +457,7 @@ namespace Mesen.Interop
|
|||
MemoryType.NesPrgRom => "PRG",
|
||||
MemoryType.NesWorkRam => "WRAM",
|
||||
MemoryType.NesSaveRam => "SRAM",
|
||||
MemoryType.NesMapperRam => "EXRAM",
|
||||
MemoryType.NesInternalRam => "RAM",
|
||||
|
||||
MemoryType.NesSpriteRam => "SPR",
|
||||
|
|
|
@ -336,7 +336,7 @@
|
|||
<Control ID="chkDisablePpu2004Reads">Disable PPU $2004 reads (Famicom behavior)</Control>
|
||||
<Control ID="chkDisablePpuReset">Do not reset PPU when resetting console (Famicom behavior)</Control>
|
||||
<Control ID="chkDisableGameGenieBusConflicts">Disable Game Genie bus conflict emulation</Control>
|
||||
<Control ID="chkDisableFlashSaves">Disable flash saves (UNROM512 / GTROM)</Control>
|
||||
<Control ID="chkDisableFlashSaves">Disable flash saves (UNROM512 / GTROM / Rainbow)</Control>
|
||||
<Control ID="chkEnableDmcSampleDuplicationGlitch">Enable DMC sample duplication glitch (late-G & H CPU behavior)</Control>
|
||||
<Control ID="chkEnableCpuTestMode">Enable CPU test mode registers</Control>
|
||||
<Control ID="lblConsoleType">Console model:</Control>
|
||||
|
@ -2716,6 +2716,7 @@ E
|
|||
<Value ID="NesWorkRam">Work RAM</Value>
|
||||
<Value ID="NesSaveRam">Save RAM</Value>
|
||||
<Value ID="NesNametableRam">Nametable RAM (CIRAM)</Value>
|
||||
<Value ID="NesMapperRam">Mapper RAM (EXRAM)</Value>
|
||||
<Value ID="NesSpriteRam">Sprite RAM (OAM)</Value>
|
||||
<Value ID="NesSecondarySpriteRam">Secondary OAM RAM</Value>
|
||||
<Value ID="NesChrRom">CHR ROM</Value>
|
||||
|
|
|
@ -177,7 +177,7 @@ vector<uint8_t> IpsPatcher::CreatePatch(vector<uint8_t> originalData, vector<uin
|
|||
patchRecord.RepeatCount = rleCount;
|
||||
patchRecord.Value = rleByte;
|
||||
} else {
|
||||
patchRecord.Replacement = vector<uint8_t>(&newData[patchRecord.Address], &newData[patchRecord.Address + patchRecord.Length]);
|
||||
patchRecord.Replacement = vector<uint8_t>(newData.data() + patchRecord.Address, newData.data() + patchRecord.Address + patchRecord.Length);
|
||||
}
|
||||
patchRecord.WriteRecord(patchFile);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue