snes-add scanline render callbacks and add scanline selector to graphics debugger

This commit is contained in:
zeromus 2012-09-22 05:03:52 +00:00
parent 6f28003f48
commit 03cb238ae3
9 changed files with 254 additions and 51 deletions

View File

@ -2,7 +2,7 @@
//TODO //TODO
//libsnes needs to be modified to support multiple instances - THIS IS NECESSARY - or else loading one game and then another breaks things //libsnes needs to be modified to support multiple instances - THIS IS NECESSARY - or else loading one game and then another breaks things
//rename snes.dll so nobody thinks it's a stock snes.dll (we'll be editing it substantially at some point) // edit - this is a lot of work
//wrap dll code around some kind of library-accessing interface so that it doesnt malfunction if the dll is unavailable //wrap dll code around some kind of library-accessing interface so that it doesnt malfunction if the dll is unavailable
using System; using System;
@ -17,27 +17,27 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
{ {
public unsafe static class LibsnesDll public unsafe static class LibsnesDll
{ {
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern string snes_library_id(); public static extern string snes_library_id();
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int snes_library_revision_major(); public static extern int snes_library_revision_major();
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int snes_library_revision_minor(); public static extern int snes_library_revision_minor();
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_init(); public static extern void snes_init();
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_power(); public static extern void snes_power();
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_reset(); public static extern void snes_reset();
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_run(); public static extern void snes_run();
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_term(); public static extern void snes_term();
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_unload_cartridge(); public static extern void snes_unload_cartridge();
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_load_cartridge_normal( public static extern void snes_load_cartridge_normal(
[MarshalAs(UnmanagedType.LPStr)] [MarshalAs(UnmanagedType.LPStr)]
string rom_xml, string rom_xml,
@ -53,49 +53,53 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
public delegate ushort snes_input_state_t(int port, int device, int index, int id); public delegate ushort snes_input_state_t(int port, int device, int index, int id);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void snes_audio_sample_t(ushort left, ushort right); public delegate void snes_audio_sample_t(ushort left, ushort right);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void snes_scanlineStart_t(int line);
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_set_video_refresh(snes_video_refresh_t video_refresh); public static extern void snes_set_video_refresh(snes_video_refresh_t video_refresh);
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_set_input_poll(snes_input_poll_t input_poll); public static extern void snes_set_input_poll(snes_input_poll_t input_poll);
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_set_input_state(snes_input_state_t input_state); public static extern void snes_set_input_state(snes_input_state_t input_state);
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_set_audio_sample(snes_audio_sample_t audio_sample); public static extern void snes_set_audio_sample(snes_audio_sample_t audio_sample);
[DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_set_scanlineStart(snes_scanlineStart_t scanlineStart);
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.U1)] [return: MarshalAs(UnmanagedType.U1)]
public static extern bool snes_check_cartridge( public static extern bool snes_check_cartridge(
[MarshalAs(UnmanagedType.LPArray)] byte[] rom_data, [MarshalAs(UnmanagedType.LPArray)] byte[] rom_data,
int rom_size); int rom_size);
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.U1)] [return: MarshalAs(UnmanagedType.U1)]
public static extern SNES_REGION snes_get_region(); public static extern SNES_REGION snes_get_region();
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int snes_get_memory_size(SNES_MEMORY id); public static extern int snes_get_memory_size(SNES_MEMORY id);
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr snes_get_memory_data(SNES_MEMORY id); public static extern IntPtr snes_get_memory_data(SNES_MEMORY id);
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int snes_serialize_size(); public static extern int snes_serialize_size();
[return: MarshalAs(UnmanagedType.U1)] [return: MarshalAs(UnmanagedType.U1)]
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool snes_serialize(IntPtr data, int size); public static extern bool snes_serialize(IntPtr data, int size);
[return: MarshalAs(UnmanagedType.U1)] [return: MarshalAs(UnmanagedType.U1)]
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool snes_unserialize(IntPtr data, int size); public static extern bool snes_unserialize(IntPtr data, int size);
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void snes_set_layer_enable(int layer, int priority, public static extern void snes_set_layer_enable(int layer, int priority,
[MarshalAs(UnmanagedType.U1)] [MarshalAs(UnmanagedType.U1)]
bool enable bool enable
); );
[DllImport("snes.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libsneshawk.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int snes_peek_logical_register(SNES_REG reg); public static extern int snes_peek_logical_register(SNES_REG reg);
public enum SNES_REG : int public enum SNES_REG : int
@ -180,7 +184,43 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
} }
} }
public class ScanlineHookManager
{
public void Register(object tag, Action<int> callback)
{
var rr = new RegistrationRecord();
rr.tag = tag;
rr.callback = callback;
Unregister(tag);
records.Add(rr);
OnHooksChanged();
}
public int HookCount { get { return records.Count; } }
public virtual void OnHooksChanged() { }
public void Unregister(object tag)
{
records.RemoveAll((r) => r.tag == tag);
}
public void HandleScanline(int scanline)
{
foreach (var rr in records) rr.callback(scanline);
}
List<RegistrationRecord> records = new List<RegistrationRecord>();
class RegistrationRecord
{
public object tag;
public int scanline;
public Action<int> callback;
}
}
public unsafe class LibsnesCore : IEmulator, IVideoProvider, ISoundProvider public unsafe class LibsnesCore : IEmulator, IVideoProvider, ISoundProvider
{ {
bool disposed = false; bool disposed = false;
@ -195,6 +235,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_set_input_poll(null); BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_set_input_poll(null);
BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_set_input_state(null); BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_set_input_state(null);
BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_set_audio_sample(null); BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_set_audio_sample(null);
BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_set_scanlineStart(null);
LibsnesDll.snes_unload_cartridge(); LibsnesDll.snes_unload_cartridge();
LibsnesDll.snes_term(); LibsnesDll.snes_term();
@ -205,11 +246,36 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
//that will be necessary to get it saving to disk //that will be necessary to get it saving to disk
byte[] disposedSaveRam; byte[] disposedSaveRam;
//we can only have one active snes core at a time, due to libsnes being so static. //we can only have one active snes core at a time, due to libsnes being so static.
//so we'll track the current one here and detach the previous one whenever a new one is booted up. //so we'll track the current one here and detach the previous one whenever a new one is booted up.
static LibsnesCore CurrLibsnesCore; static LibsnesCore CurrLibsnesCore;
public class MyScanlineHookManager : ScanlineHookManager
{
public MyScanlineHookManager(LibsnesCore core)
{
this.core = core;
}
LibsnesCore core;
public override void OnHooksChanged()
{
core.OnScanlineHooksChanged();
}
}
public MyScanlineHookManager ScanlineHookManager;
void OnScanlineHooksChanged()
{
if (disposed) return;
if (ScanlineHookManager.HookCount == 0) LibsnesDll.snes_set_scanlineStart(null);
else LibsnesDll.snes_set_scanlineStart(scanlineStart_cb);
}
void snes_scanlineStart(int line)
{
ScanlineHookManager.HandleScanline(line);
}
public LibsnesCore(byte[] romData) public LibsnesCore(byte[] romData)
{ {
//attach this core as the current //attach this core as the current
@ -217,6 +283,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
CurrLibsnesCore.Dispose(); CurrLibsnesCore.Dispose();
CurrLibsnesCore = this; CurrLibsnesCore = this;
ScanlineHookManager = new MyScanlineHookManager(this);
LibsnesDll.snes_init(); LibsnesDll.snes_init();
vidcb = new LibsnesDll.snes_video_refresh_t(snes_video_refresh); vidcb = new LibsnesDll.snes_video_refresh_t(snes_video_refresh);
@ -231,6 +299,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
soundcb = new LibsnesDll.snes_audio_sample_t(snes_audio_sample); soundcb = new LibsnesDll.snes_audio_sample_t(snes_audio_sample);
BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_set_audio_sample(soundcb); BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_set_audio_sample(soundcb);
scanlineStart_cb = new LibsnesDll.snes_scanlineStart_t(snes_scanlineStart);
// start up audio resampler // start up audio resampler
InitAudio(); InitAudio();
@ -253,6 +323,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
LibsnesDll.snes_input_poll_t pollcb; LibsnesDll.snes_input_poll_t pollcb;
LibsnesDll.snes_input_state_t inputcb; LibsnesDll.snes_input_state_t inputcb;
LibsnesDll.snes_audio_sample_t soundcb; LibsnesDll.snes_audio_sample_t soundcb;
LibsnesDll.snes_scanlineStart_t scanlineStart_cb;
ushort snes_input_state(int port, int device, int index, int id) ushort snes_input_state(int port, int device, int index, int id)
{ {

View File

@ -245,6 +245,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
{ {
int tileEntry = vram[tidx * 2]; int tileEntry = vram[tidx * 2];
int src = tileEntry * 64; int src = tileEntry * 64;
if (tileEntry != 0)
{
int zzz = 9;
}
for (int py = 0, pix=src; py < 8; py++) for (int py = 0, pix=src; py < 8; py++)
{ {
for (int px = 0; px < 8; px++, pix++) for (int px = 0; px < 8; px++, pix++)

View File

@ -2210,7 +2210,11 @@ namespace BizHawk.MultiClient
NESNameTableViewer1.UpdateValues(); NESNameTableViewer1.UpdateValues();
NESPPU1.UpdateValues(); NESPPU1.UpdateValues();
PCEBGViewer1.UpdateValues(); PCEBGViewer1.UpdateValues();
SNESGraphicsDebugger1.UpdateValues(); }
public void UpdateToolsLoadstate()
{
SNESGraphicsDebugger1.UpdateToolsLoadstate();
} }
/// <summary> /// <summary>
@ -2222,6 +2226,7 @@ namespace BizHawk.MultiClient
//frame of execution in its list view. //frame of execution in its list view.
LuaConsole1.LuaImp.FrameRegisterAfter(); LuaConsole1.LuaImp.FrameRegisterAfter();
TAStudio1.UpdateValues(); TAStudio1.UpdateValues();
SNESGraphicsDebugger1.UpdateToolsAfter();
} }
private unsafe Image MakeScreenshotImage() private unsafe Image MakeScreenshotImage()
@ -2376,6 +2381,7 @@ namespace BizHawk.MultiClient
Global.OSD.ClearGUIText(); Global.OSD.ClearGUIText();
UpdateToolsBefore(); UpdateToolsBefore();
UpdateToolsAfter(); UpdateToolsAfter();
UpdateToolsLoadstate();
Global.OSD.AddMessage("Loaded state: " + name); Global.OSD.AddMessage("Loaded state: " + name);
} }
else else

View File

@ -95,6 +95,7 @@
this.saveWindowPositionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.saveWindowPositionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.groupBox3 = new System.Windows.Forms.GroupBox(); this.groupBox3 = new System.Windows.Forms.GroupBox();
this.groupBox4 = new System.Windows.Forms.GroupBox(); this.groupBox4 = new System.Windows.Forms.GroupBox();
this.radioButton15 = new System.Windows.Forms.RadioButton();
this.radioButton14 = new System.Windows.Forms.RadioButton(); this.radioButton14 = new System.Windows.Forms.RadioButton();
this.groupBox5 = new System.Windows.Forms.GroupBox(); this.groupBox5 = new System.Windows.Forms.GroupBox();
this.tabctrlDetails = new System.Windows.Forms.TabControl(); this.tabctrlDetails = new System.Windows.Forms.TabControl();
@ -111,9 +112,11 @@
this.tabPage2 = new System.Windows.Forms.TabPage(); this.tabPage2 = new System.Windows.Forms.TabPage();
this.label17 = new System.Windows.Forms.Label(); this.label17 = new System.Windows.Forms.Label();
this.label18 = new System.Windows.Forms.Label(); this.label18 = new System.Windows.Forms.Label();
this.nudScanline = new System.Windows.Forms.NumericUpDown();
this.sliderScanline = new System.Windows.Forms.TrackBar();
this.label19 = new System.Windows.Forms.Label();
this.paletteViewer = new BizHawk.MultiClient.SNESGraphicsViewer(); this.paletteViewer = new BizHawk.MultiClient.SNESGraphicsViewer();
this.viewer = new BizHawk.MultiClient.SNESGraphicsViewer(); this.viewer = new BizHawk.MultiClient.SNESGraphicsViewer();
this.radioButton15 = new System.Windows.Forms.RadioButton();
this.groupBox1.SuspendLayout(); this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout(); this.groupBox2.SuspendLayout();
this.menuStrip1.SuspendLayout(); this.menuStrip1.SuspendLayout();
@ -122,6 +125,8 @@
this.groupBox5.SuspendLayout(); this.groupBox5.SuspendLayout();
this.tabctrlDetails.SuspendLayout(); this.tabctrlDetails.SuspendLayout();
this.tpPalette.SuspendLayout(); this.tpPalette.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudScanline)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.sliderScanline)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
// label1 // label1
@ -136,6 +141,7 @@
// groupBox1 // groupBox1
// //
this.groupBox1.Controls.Add(this.rbBG4); this.groupBox1.Controls.Add(this.rbBG4);
this.groupBox1.Controls.Add(this.label18);
this.groupBox1.Controls.Add(this.rbBG3); this.groupBox1.Controls.Add(this.rbBG3);
this.groupBox1.Controls.Add(this.rbBG2); this.groupBox1.Controls.Add(this.rbBG2);
this.groupBox1.Controls.Add(this.rbBG1); this.groupBox1.Controls.Add(this.rbBG1);
@ -876,6 +882,18 @@
this.groupBox4.TabIndex = 35; this.groupBox4.TabIndex = 35;
this.groupBox4.TabStop = false; this.groupBox4.TabStop = false;
// //
// radioButton15
//
this.radioButton15.AutoSize = true;
this.radioButton15.Enabled = false;
this.radioButton15.Location = new System.Drawing.Point(169, 83);
this.radioButton15.Name = "radioButton15";
this.radioButton15.Size = new System.Drawing.Size(58, 17);
this.radioButton15.TabIndex = 33;
this.radioButton15.TabStop = true;
this.radioButton15.Text = "Mode7";
this.radioButton15.UseVisualStyleBackColor = true;
//
// radioButton14 // radioButton14
// //
this.radioButton14.AutoSize = true; this.radioButton14.AutoSize = true;
@ -891,7 +909,7 @@
// groupBox5 // groupBox5
// //
this.groupBox5.Controls.Add(this.paletteViewer); this.groupBox5.Controls.Add(this.paletteViewer);
this.groupBox5.Location = new System.Drawing.Point(6, 378); this.groupBox5.Location = new System.Drawing.Point(6, 387);
this.groupBox5.Name = "groupBox5"; this.groupBox5.Name = "groupBox5";
this.groupBox5.Size = new System.Drawing.Size(319, 328); this.groupBox5.Size = new System.Drawing.Size(319, 328);
this.groupBox5.TabIndex = 36; this.groupBox5.TabIndex = 36;
@ -905,7 +923,7 @@
this.tabctrlDetails.Location = new System.Drawing.Point(6, 238); this.tabctrlDetails.Location = new System.Drawing.Point(6, 238);
this.tabctrlDetails.Name = "tabctrlDetails"; this.tabctrlDetails.Name = "tabctrlDetails";
this.tabctrlDetails.SelectedIndex = 0; this.tabctrlDetails.SelectedIndex = 0;
this.tabctrlDetails.Size = new System.Drawing.Size(319, 134); this.tabctrlDetails.Size = new System.Drawing.Size(282, 143);
this.tabctrlDetails.TabIndex = 0; this.tabctrlDetails.TabIndex = 0;
// //
// tpPalette // tpPalette
@ -922,7 +940,7 @@
this.tpPalette.Location = new System.Drawing.Point(4, 22); this.tpPalette.Location = new System.Drawing.Point(4, 22);
this.tpPalette.Name = "tpPalette"; this.tpPalette.Name = "tpPalette";
this.tpPalette.Padding = new System.Windows.Forms.Padding(3); this.tpPalette.Padding = new System.Windows.Forms.Padding(3);
this.tpPalette.Size = new System.Drawing.Size(311, 108); this.tpPalette.Size = new System.Drawing.Size(274, 117);
this.tpPalette.TabIndex = 0; this.tpPalette.TabIndex = 0;
this.tpPalette.Text = "Palette"; this.tpPalette.Text = "Palette";
this.tpPalette.UseVisualStyleBackColor = true; this.tpPalette.UseVisualStyleBackColor = true;
@ -1020,7 +1038,7 @@
this.tabPage2.Location = new System.Drawing.Point(4, 22); this.tabPage2.Location = new System.Drawing.Point(4, 22);
this.tabPage2.Name = "tabPage2"; this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3); this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(311, 108); this.tabPage2.Size = new System.Drawing.Size(274, 117);
this.tabPage2.TabIndex = 1; this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "tabPage2"; this.tabPage2.Text = "tabPage2";
this.tabPage2.UseVisualStyleBackColor = true; this.tabPage2.UseVisualStyleBackColor = true;
@ -1038,11 +1056,47 @@
// label18 // label18
// //
this.label18.AutoSize = true; this.label18.AutoSize = true;
this.label18.Location = new System.Drawing.Point(233, 162); this.label18.Location = new System.Drawing.Point(161, 170);
this.label18.Name = "label18"; this.label18.Name = "label18";
this.label18.Size = new System.Drawing.Size(70, 26); this.label18.Size = new System.Drawing.Size(56, 26);
this.label18.TabIndex = 38; this.label18.TabIndex = 38;
this.label18.Text = "Todo: BG pal\r\ninfo"; this.label18.Text = "Todo: BG \r\npal info";
//
// nudScanline
//
this.nudScanline.Location = new System.Drawing.Point(242, 159);
this.nudScanline.Maximum = new decimal(new int[] {
224,
0,
0,
0});
this.nudScanline.Name = "nudScanline";
this.nudScanline.Size = new System.Drawing.Size(77, 20);
this.nudScanline.TabIndex = 39;
this.nudScanline.ValueChanged += new System.EventHandler(this.nudScanline_ValueChanged);
//
// sliderScanline
//
this.sliderScanline.AutoSize = false;
this.sliderScanline.Location = new System.Drawing.Point(294, 180);
this.sliderScanline.Maximum = 224;
this.sliderScanline.Name = "sliderScanline";
this.sliderScanline.Orientation = System.Windows.Forms.Orientation.Vertical;
this.sliderScanline.Size = new System.Drawing.Size(30, 210);
this.sliderScanline.TabIndex = 40;
this.sliderScanline.Text = "label14";
this.sliderScanline.TickFrequency = 16;
this.sliderScanline.Value = 224;
this.sliderScanline.ValueChanged += new System.EventHandler(this.sliderScanline_ValueChanged);
//
// label19
//
this.label19.AutoSize = true;
this.label19.Location = new System.Drawing.Point(242, 182);
this.label19.Name = "label19";
this.label19.Size = new System.Drawing.Size(48, 13);
this.label19.TabIndex = 41;
this.label19.Text = "Scanline";
// //
// paletteViewer // paletteViewer
// //
@ -1065,24 +1119,14 @@
this.viewer.TabIndex = 17; this.viewer.TabIndex = 17;
this.viewer.TabStop = false; this.viewer.TabStop = false;
// //
// radioButton15
//
this.radioButton15.AutoSize = true;
this.radioButton15.Enabled = false;
this.radioButton15.Location = new System.Drawing.Point(169, 83);
this.radioButton15.Name = "radioButton15";
this.radioButton15.Size = new System.Drawing.Size(58, 17);
this.radioButton15.TabIndex = 33;
this.radioButton15.TabStop = true;
this.radioButton15.Text = "Mode7";
this.radioButton15.UseVisualStyleBackColor = true;
//
// SNESGraphicsDebugger // SNESGraphicsDebugger
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(905, 727); this.ClientSize = new System.Drawing.Size(905, 727);
this.Controls.Add(this.label18); this.Controls.Add(this.label19);
this.Controls.Add(this.sliderScanline);
this.Controls.Add(this.nudScanline);
this.Controls.Add(this.label17); this.Controls.Add(this.label17);
this.Controls.Add(this.tabctrlDetails); this.Controls.Add(this.tabctrlDetails);
this.Controls.Add(this.groupBox5); this.Controls.Add(this.groupBox5);
@ -1108,6 +1152,8 @@
this.tabctrlDetails.ResumeLayout(false); this.tabctrlDetails.ResumeLayout(false);
this.tpPalette.ResumeLayout(false); this.tpPalette.ResumeLayout(false);
this.tpPalette.PerformLayout(); this.tpPalette.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudScanline)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.sliderScanline)).EndInit();
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
@ -1201,5 +1247,8 @@
private System.Windows.Forms.Label lblDetailsOBJOrBG; private System.Windows.Forms.Label lblDetailsOBJOrBG;
private System.Windows.Forms.TextBox txtPaletteDetailsIndexHex; private System.Windows.Forms.TextBox txtPaletteDetailsIndexHex;
private System.Windows.Forms.RadioButton radioButton15; private System.Windows.Forms.RadioButton radioButton15;
private System.Windows.Forms.NumericUpDown nudScanline;
private System.Windows.Forms.TrackBar sliderScanline;
private System.Windows.Forms.Label label19;
} }
} }

View File

@ -27,6 +27,15 @@ namespace BizHawk.MultiClient
tabctrlDetails.SelectedIndex = 1; tabctrlDetails.SelectedIndex = 1;
} }
LibsnesCore currentSnesCore;
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (currentSnesCore != null)
currentSnesCore.ScanlineHookManager.Unregister(this);
currentSnesCore = null;
}
string FormatBpp(int bpp) string FormatBpp(int bpp)
{ {
if (bpp == 0) return "---"; if (bpp == 0) return "---";
@ -47,11 +56,57 @@ namespace BizHawk.MultiClient
else return string.Format("@{0} ({1}K)", address.ToHexString(4), address / 1024); else return string.Format("@{0} ({1}K)", address.ToHexString(4), address / 1024);
} }
public void UpdateValues() public void UpdateToolsAfter()
{
SyncCore();
}
public void UpdateToolsLoadstate()
{
SyncCore();
UpdateValues();
}
private void nudScanline_ValueChanged(object sender, EventArgs e)
{
if (suppression) return;
SyncCore();
suppression = true;
sliderScanline.Value = 224 - (int)nudScanline.Value;
suppression = false;
}
private void sliderScanline_ValueChanged(object sender, EventArgs e)
{
if (suppression) return;
SyncCore();
suppression = true;
nudScanline.Value = 224 - sliderScanline.Value;
suppression = false;
}
void SyncCore()
{
LibsnesCore core = Global.Emulator as LibsnesCore;
if (currentSnesCore != core && currentSnesCore != null)
currentSnesCore.ScanlineHookManager.Unregister(this);
currentSnesCore = core;
if(currentSnesCore != null)
currentSnesCore.ScanlineHookManager.Register(this, ScanlineHook);
}
void ScanlineHook(int line)
{
int target = (int)nudScanline.Value;
if (target == line) UpdateValues();
}
void UpdateValues()
{ {
if (!this.IsHandleCreated || this.IsDisposed) return; if (!this.IsHandleCreated || this.IsDisposed) return;
var snes = Global.Emulator as LibsnesCore; if (currentSnesCore == null) return;
if (snes == null) return;
var gd = new SNESGraphicsDecoder(); var gd = new SNESGraphicsDecoder();
var si = gd.ScanScreenInfo(); var si = gd.ScanScreenInfo();
@ -315,6 +370,5 @@ namespace BizHawk.MultiClient
//cd.ShowDialog(this); //cd.ShowDialog(this);
} }
} }
} }

View File

@ -84,6 +84,8 @@ void PPU::scanline() {
regs.range_over = false; regs.range_over = false;
} }
interface->scanlineStart(line);
if(line == 1) { if(line == 1) {
//mosaic reset //mosaic reset
for(int bg = BG1; bg <= BG4; bg++) regs.bg_y[bg] = 1; for(int bg = BG1; bg <= BG4; bg++) regs.bg_y[bg] = 1;

View File

@ -7,6 +7,9 @@ struct Interface {
virtual void message(const string &text); virtual void message(const string &text);
virtual time_t currentTime(); virtual time_t currentTime();
virtual time_t randomSeed(); virtual time_t randomSeed();
//zero 27-sep-2012
virtual void scanlineStart(int line) = 0;
}; };
extern Interface *interface; extern Interface *interface;

View File

@ -40,6 +40,13 @@ struct Interface : public SNES::Interface {
if(paudio_sample) return paudio_sample(left, right); if(paudio_sample) return paudio_sample(left, right);
} }
//zero 27-sep-2012
snes_scanlineStart_t pScanlineStart;
void scanlineStart(int line)
{
if(pScanlineStart) pScanlineStart((int)line);
}
int16_t inputPoll(bool port, SNES::Input::Device device, unsigned index, unsigned id) { int16_t inputPoll(bool port, SNES::Input::Device device, unsigned index, unsigned id) {
if(pinput_state) return pinput_state(port?1:0, (unsigned)device, index, id); if(pinput_state) return pinput_state(port?1:0, (unsigned)device, index, id);
return 0; return 0;
@ -249,6 +256,11 @@ void snes_cheat_set(unsigned index, bool enable, const char *code) {
SNES::cheat.synchronize(); SNES::cheat.synchronize();
} }
//zero 21-sep-2012
void snes_set_scanlineStart(snes_scanlineStart_t cb)
{
interface.pScanlineStart = cb;
}
//zero 03-sep-2012 //zero 03-sep-2012
bool snes_check_cartridge(const uint8_t *rom_data, unsigned rom_size) bool snes_check_cartridge(const uint8_t *rom_data, unsigned rom_size)

View File

@ -131,6 +131,8 @@ unsigned snes_get_memory_size(unsigned id);
//zeromus additions //zeromus additions
bool snes_check_cartridge(const uint8_t *rom_data, unsigned rom_size); bool snes_check_cartridge(const uint8_t *rom_data, unsigned rom_size);
void snes_set_layer_enable(int layer, int priority, bool enable); void snes_set_layer_enable(int layer, int priority, bool enable);
typedef void (*snes_scanlineStart_t)(int);
void snes_set_scanlineStart(snes_scanlineStart_t);
//$2105 //$2105
#define SNES_REG_BG_MODE 0 #define SNES_REG_BG_MODE 0