partially functional ppu viewing tools for quicknes

This commit is contained in:
goyuken 2014-12-17 03:27:44 +00:00
parent 53dc38ee66
commit d305b2f538
10 changed files with 174 additions and 8 deletions

View File

@ -1209,8 +1209,6 @@ namespace BizHawk.Client.EmuHawk
{
FDSControlsMenuItem.Enabled = Global.Emulator.BoardName == "FDS";
NESPPUViewerMenuItem.Enabled =
NESNametableViewerMenuItem.Enabled =
NESSoundChannelsMenuItem.Enabled =
MovieSettingsMenuItem.Enabled =
Global.Emulator is NES;

View File

@ -14,8 +14,6 @@ namespace BizHawk.Client.EmuHawk
// TODO:
// Show Scroll Lines + UI Toggle
[RequiredService]
private NES _nes { get; set; }
[RequiredService]
private INESPPUViewable xxx { get; set; }
[RequiredService]
private IEmulator _emu { get; set; }

View File

@ -25,8 +25,6 @@ namespace BizHawk.Client.EmuHawk
private Bitmap _zoomBoxDefaultImage = new Bitmap(64, 64);
private bool _forceChange;
[RequiredService]
private NES _nes { get; set; }
[RequiredService]
private INESPPUViewable xxx { get; set; }
[RequiredService]

View File

@ -215,6 +215,19 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr qn_get_mapper(IntPtr e, ref int number);
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
public static extern byte qn_get_reg2000(IntPtr e);
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr qn_get_palmem(IntPtr e);
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr qn_get_oammem(IntPtr e);
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
public static extern byte qn_peek_ppu(IntPtr e, int addr);
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
public static extern void qn_peek_ppubus(IntPtr e, byte[] dest);
/// <summary>
/// handle "string error" as returned by some quicknes functions
/// </summary>

View File

@ -24,7 +24,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
)]
[ServiceNotApplicable(typeof(IDriveLight))]
public class QuickNES : IEmulator, IVideoProvider, ISyncSoundProvider, IMemoryDomains, ISaveRam, IInputPollable,
IStatable, IDebuggable, ISettable<QuickNES.QuickNESSettings, QuickNES.QuickNESSyncSettings>
IStatable, IDebuggable, ISettable<QuickNES.QuickNESSettings, QuickNES.QuickNESSyncSettings>, Cores.Nintendo.NES.INESPPUViewable
{
#region FPU precision
@ -199,6 +199,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
Blit();
if (rendersound)
DrainAudio();
if (CB1 != null) CB1();
if (CB2 != null) CB2();
}
}
@ -717,5 +720,102 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
}
#endregion
#region INESPPUViewable
// todo: don't just call the callbacks at the end of frame; use the scanline info
Action CB1;
Action CB2;
public int[] GetPalette()
{
return VideoPalette;
}
private byte R2000 { get { return LibQuickNES.qn_get_reg2000(Context); } }
public bool BGBaseHigh
{
get { return (R2000 & 0x10) != 0; }
}
public bool SPBaseHigh
{
get { return (R2000 & 0x08) != 0; }
}
public bool SPTall
{
get { return (R2000 & 0x20) != 0; }
}
byte[] ppubusbuf = new byte[0x3000];
public byte[] GetPPUBus()
{
LibQuickNES.qn_peek_ppubus(Context, ppubusbuf);
return ppubusbuf;
}
byte[] palrambuf = new byte[0x20];
public byte[] GetPalRam()
{
Marshal.Copy(LibQuickNES.qn_get_palmem(Context), palrambuf, 0, 0x20);
return palrambuf;
}
byte[] oambuf = new byte[0x100];
public byte[] GetOam()
{
Marshal.Copy(LibQuickNES.qn_get_oammem(Context), oambuf, 0, 0x100);
return oambuf;
}
public byte PeekPPU(int addr)
{
return LibQuickNES.qn_peek_ppu(Context, addr);
}
// we don't use quicknes's MMC5 at all, so these three methods are just stubs
public byte[] GetExTiles()
{
throw new InvalidOperationException();
}
public bool ExActive
{
get { return false; }
}
public byte[] GetExRam()
{
throw new InvalidOperationException();
}
public MemoryDomain GetCHRROM()
{
return MemoryDomains["CHR VROM"];
}
public void InstallCallback1(Action cb, int sl)
{
CB1 = cb;
}
public void InstallCallback2(Action cb, int sl)
{
CB2 = cb;
}
public void RemoveCallback1()
{
CB1 = null;
}
public void RemoveCallback2()
{
CB2 = null;
}
#endregion
}
}

Binary file not shown.

View File

@ -230,6 +230,18 @@ EXPORT int qn_get_memory_area(Nes_Emu *e, int which, const void **data, int *siz
*writable = 0;
*name = "CHR VROM";
return 1;
case 6:
*data = e->pal_mem();
*size = 32;
*writable = 1;
*name = "PALRAM";
return 1;
case 7:
*data = e->oam_mem();
*size = 256;
*writable = 1;
*name = "OAM";
return 1;
}
}
@ -276,3 +288,29 @@ EXPORT const char *qn_get_mapper(Nes_Emu *e, int *number)
case 10: return "mmc4";
}
}
EXPORT byte qn_get_reg2000(Nes_Emu *e)
{
return e->get_ppu2000();
}
EXPORT byte *qn_get_palmem(Nes_Emu *e)
{
return e->pal_mem();
}
EXPORT byte *qn_get_oammem(Nes_Emu *e)
{
return e->oam_mem();
}
EXPORT byte qn_peek_ppu(Nes_Emu *e, int addr)
{
return e->peek_ppu(addr);
}
EXPORT void qn_peek_ppubus(Nes_Emu *e, byte *dest)
{
for (int i = 0; i < 0x3000; i++)
dest[i] = e->peek_ppu(i);
}

View File

@ -206,9 +206,14 @@ public:
// Prg peek/poke for debuggin
byte peek_prg(nes_addr_t addr) const { return *static_cast<Nes_Cpu>(emu).get_code(addr); }
void poke_prg(nes_addr_t addr, byte value) { *static_cast<Nes_Cpu>(emu).get_code(addr) = value; }
byte peek_ppu(int addr) { return emu.ppu.peekaddr(addr); }
void get_regs(unsigned int *dest) const;
byte get_ppu2000() const { return emu.ppu.w2000; }
byte* pal_mem() { return emu.ppu.palette; }
byte* oam_mem() { return emu.ppu.spr_ram; }
// End of public interface
public:
blargg_err_t set_sample_rate( long rate, class Nes_Buffer* );

View File

@ -54,6 +54,16 @@ Nes_Ppu_Impl::~Nes_Ppu_Impl()
delete impl;
}
int Nes_Ppu_Impl::peekaddr(int addr)
{
if (addr < 0x2000)
return chr_data[map_chr_addr_peek(addr)];
else
return get_nametable(addr)[addr & 0x3ff];
}
void Nes_Ppu_Impl::all_tiles_modified()
{
any_tiles_modified = true;

View File

@ -32,6 +32,7 @@ public:
enum { buffer_height = image_height };
int write_2007( int );
int peekaddr(int);
// Host palette
enum { palette_increment = 64 };
@ -64,8 +65,8 @@ public:
impl_t* impl;
enum { scanline_len = 341 };
protected:
byte spr_ram [0x100];
protected:
void begin_frame();
void run_hblank( int );
int sprite_height() const { return (w2000 >> 2 & 8) + 8; }
@ -104,6 +105,11 @@ private:
enum { chr_page_size = 0x400 };
long chr_pages [chr_addr_size / chr_page_size];
long chr_pages_ex [chr_addr_size / chr_page_size]; // mmc24 only
long map_chr_addr_peek( unsigned a ) const
{
return chr_pages[a / chr_page_size] + a;
}
long map_chr_addr( unsigned a ) /*const*/
{
if (!mmc24_enabled)