partially functional ppu viewing tools for quicknes
This commit is contained in:
parent
53dc38ee66
commit
d305b2f538
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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* );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue