From f6c1c7eba2f1080d904041719f9570523343fe0b Mon Sep 17 00:00:00 2001 From: goyuken Date: Tue, 25 Feb 2014 22:54:25 +0000 Subject: [PATCH] NES: PPU Viewer: support MMC5 ExAttr mode --- .../tools/NES/NESNameTableViewer.cs | 73 +++++++++++++++++++ .../Consoles/Nintendo/NES/Boards/ExROM.cs | 2 + .../Consoles/Nintendo/NES/Core.cs | 9 +++ 3 files changed, 84 insertions(+) diff --git a/BizHawk.Client.EmuHawk/tools/NES/NESNameTableViewer.cs b/BizHawk.Client.EmuHawk/tools/NES/NESNameTableViewer.cs index 76637d6730..2354a466f3 100644 --- a/BizHawk.Client.EmuHawk/tools/NES/NESNameTableViewer.cs +++ b/BizHawk.Client.EmuHawk/tools/NES/NESNameTableViewer.cs @@ -72,6 +72,65 @@ namespace BizHawk.Client.EmuHawk #endregion + #region MMC5 + + private unsafe void GenerateExAttr(int* dst, int pitch, byte[] palram, byte[] ppumem, byte[] exram) + { + byte[] chr = _nes.GetBoard().VROM ?? _nes.GetBoard().VRAM; + int chr_mask = chr.Length - 1; + + fixed (byte* chrptr = chr, palptr = palram, ppuptr = ppumem, exptr = exram) + { + DrawExNT(dst, pitch, palptr, ppuptr + 0x2000, exptr, chrptr, chr_mask); + DrawExNT(dst + 256, pitch, palptr, ppuptr + 0x2400, exptr, chrptr, chr_mask); + dst += pitch * 240; + DrawExNT(dst, pitch, palptr, ppuptr + 0x2800, exptr, chrptr, chr_mask); + DrawExNT(dst + 256, pitch, palptr, ppuptr + 0x2c00, exptr, chrptr, chr_mask); + } + } + + private unsafe void DrawTile(int* dst, int pitch, byte* pal, byte* tile) + { + dst += 7; + int vinc = pitch + 8; + for (int j = 0; j < 8; j++) + { + int lo = tile[0]; + int hi = tile[8] << 1; + for (int i = 0; i < 8; i++) + { + *dst-- = _nes.LookupColor(pal[lo & 1 | hi & 2]); + lo >>= 1; + hi >>= 1; + } + dst += vinc; + tile++; + } + } + + private unsafe void DrawExNT(int* dst, int pitch, byte* palram, byte* nt, byte* exnt, byte* chr, int chr_mask) + { + for (int ty = 0; ty < 30; ty++) + { + for (int tx = 0; tx < 32; tx++) + { + byte t = *nt++; + byte ex = *exnt++; + + int tilenum = t | (ex & 0x3f) << 8; + int palnum = ex >> 6; + + int tileaddr = tilenum << 4 & chr_mask; + DrawTile(dst, pitch, palram + palnum * 4, chr + tileaddr); + dst += 8; + } + dst -= 256; + dst += pitch * 8; + } + } + + #endregion + private unsafe void Generate(bool now = false) { if (!IsHandleCreated || IsDisposed) @@ -111,6 +170,19 @@ namespace BizHawk.Client.EmuHawk palram[i] = _nes.ppu.PALRAM[i]; } + var board = _nes.GetBoard(); + if (board is ExROM && (board as ExROM).ExAttrActive) + { + byte[] exram = new byte[1024]; + var md = _nes.MemoryDomains["ExRAM"]; + for (int i = 0; i < 1024; i++) + exram[i] = md.PeekByte(i); + + GenerateExAttr(dptr, pitch, palram, ppuBuffer, exram); + goto finish; + } + + int ytable = 0, yline = 0; for (int y = 0; y < 480; y++) { @@ -165,6 +237,7 @@ namespace BizHawk.Client.EmuHawk dptr += pitch - 512; } + finish: NameTableView.Nametables.UnlockBits(bmpdata); NameTableView.Refresh(); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs index 6da89fcf9d..1bcdc6c9d4 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs @@ -52,6 +52,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return new MemoryDomain("ExRAM", EXRAM.Length, MemoryDomain.Endian.Little, (addr) => EXRAM[addr], (addr, val) => EXRAM[addr] = val); } + public bool ExAttrActive { get { return exram_mode == 1; } } + public override void SyncState(Serializer ser) { base.SyncState(ser); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Core.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Core.cs index 91942c2ee9..598697cb5a 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Core.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Core.cs @@ -51,6 +51,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public void SetNoise(int v) { apu.NoiseV = v; } public void SetDMC(int v) { apu.DMCV = v; } + /// + /// for debugging only! + /// + /// + public INESBoard GetBoard() + { + return board; + } + public void Dispose() { if (magicSoundProvider != null) magicSoundProvider.Dispose();