gb gpu view: fix bug due to scroll bar hilarity. gba gpu view: implement scanline callbacks

This commit is contained in:
goyuken 2012-11-30 05:16:37 +00:00
parent f23e777032
commit 6412d6d93e
9 changed files with 239 additions and 3 deletions
BizHawk.Emulation/Consoles/Nintendo/GBA
BizHawk.MultiClient
libmeteor

View File

@ -250,5 +250,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
/// <param name="val"></param>
[DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void libmeteor_writebus(uint addr, byte val);
/// <summary>
/// type of the scanline callback
/// </summary>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ScanlineCallback();
/// <summary>
/// set a callback to coincide with vcount interrupts
/// </summary>
/// <param name="callback">null to clear</param>
/// <param name="scanline">0-227, 160 occurring first in a frame</param>
[DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void libmeteor_setscanlinecallback(ScanlineCallback callback, int scanline);
}
}

View File

@ -25,6 +25,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
{
if (bios.Length != 16384)
throw new Exception("GBA bios must be exactly 16384 bytes!");
if (rom.Length > 32 * 1024 * 1024)
throw new Exception("Rom is too big!");
Init();
LibMeteor.libmeteor_hardreset();
LibMeteor.libmeteor_loadbios(bios, (uint)bios.Length);
@ -46,6 +48,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
LibMeteor.libmeteor_frameadvance();
if (IsLagFrame)
LagCount++;
if (EndOfFrameCallback != null)
EndOfFrameCallback();
}
public int Frame { get; private set; }
@ -376,6 +380,40 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
CoreInputComm.Tracer.Put(msg);
}
Action EndOfFrameCallback = null;
LibMeteor.ScanlineCallback scanlinecb = null;
/// <summary>
///
/// </summary>
/// <param name="callback">null to cancel</param>
/// <param name="scanline">0-227, null = end of frame</param>
public void SetScanlineCallback(Action callback, int? scanline)
{
if (callback == null)
{
LibMeteor.libmeteor_setscanlinecallback(null, 400);
EndOfFrameCallback = null;
scanlinecb = null;
}
else if (scanline == null)
{
LibMeteor.libmeteor_setscanlinecallback(null, 400);
EndOfFrameCallback = callback;
scanlinecb = null;
}
else if (scanline >= 0 && scanline <= 227)
{
scanlinecb = new LibMeteor.ScanlineCallback(callback);
LibMeteor.libmeteor_setscanlinecallback(scanlinecb, (int)scanline);
EndOfFrameCallback = null;
}
else
{
throw new ArgumentOutOfRangeException("Scanline must be in [0, 227]!");
}
}
void Init()
{
if (attachedcore != null)

View File

@ -32,6 +32,13 @@
this.panel1 = new System.Windows.Forms.Panel();
this.label1 = new System.Windows.Forms.Label();
this.buttonShowWidget = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.radioButtonFrame = new System.Windows.Forms.RadioButton();
this.radioButtonScanline = new System.Windows.Forms.RadioButton();
this.radioButtonManual = new System.Windows.Forms.RadioButton();
this.hScrollBar1 = new System.Windows.Forms.HScrollBar();
this.buttonRefresh = new System.Windows.Forms.Button();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// listBoxWidgets
@ -72,11 +79,80 @@
this.buttonShowWidget.UseVisualStyleBackColor = true;
this.buttonShowWidget.Click += new System.EventHandler(this.buttonShowWidget_Click);
//
// groupBox1
//
this.groupBox1.Controls.Add(this.buttonRefresh);
this.groupBox1.Controls.Add(this.hScrollBar1);
this.groupBox1.Controls.Add(this.radioButtonManual);
this.groupBox1.Controls.Add(this.radioButtonScanline);
this.groupBox1.Controls.Add(this.radioButtonFrame);
this.groupBox1.Location = new System.Drawing.Point(15, 220);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(117, 173);
this.groupBox1.TabIndex = 4;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Refresh";
//
// radioButtonFrame
//
this.radioButtonFrame.AutoSize = true;
this.radioButtonFrame.Location = new System.Drawing.Point(6, 19);
this.radioButtonFrame.Name = "radioButtonFrame";
this.radioButtonFrame.Size = new System.Drawing.Size(54, 17);
this.radioButtonFrame.TabIndex = 0;
this.radioButtonFrame.Text = "Frame";
this.radioButtonFrame.UseVisualStyleBackColor = true;
this.radioButtonFrame.CheckedChanged += new System.EventHandler(this.radioButtonFrame_CheckedChanged);
//
// radioButtonScanline
//
this.radioButtonScanline.AutoSize = true;
this.radioButtonScanline.Location = new System.Drawing.Point(6, 42);
this.radioButtonScanline.Name = "radioButtonScanline";
this.radioButtonScanline.Size = new System.Drawing.Size(66, 17);
this.radioButtonScanline.TabIndex = 1;
this.radioButtonScanline.Text = "Scanline";
this.radioButtonScanline.UseVisualStyleBackColor = true;
this.radioButtonScanline.CheckedChanged += new System.EventHandler(this.radioButtonScanline_CheckedChanged);
//
// radioButtonManual
//
this.radioButtonManual.AutoSize = true;
this.radioButtonManual.Location = new System.Drawing.Point(6, 81);
this.radioButtonManual.Name = "radioButtonManual";
this.radioButtonManual.Size = new System.Drawing.Size(60, 17);
this.radioButtonManual.TabIndex = 2;
this.radioButtonManual.TabStop = true;
this.radioButtonManual.Text = "Manual";
this.radioButtonManual.UseVisualStyleBackColor = true;
this.radioButtonManual.CheckedChanged += new System.EventHandler(this.radioButtonManual_CheckedChanged);
//
// hScrollBar1
//
this.hScrollBar1.LargeChange = 20;
this.hScrollBar1.Location = new System.Drawing.Point(3, 62);
this.hScrollBar1.Maximum = 246;
this.hScrollBar1.Name = "hScrollBar1";
this.hScrollBar1.Size = new System.Drawing.Size(111, 16);
this.hScrollBar1.TabIndex = 3;
this.hScrollBar1.ValueChanged += new System.EventHandler(this.hScrollBar1_ValueChanged);
//
// buttonRefresh
//
this.buttonRefresh.Location = new System.Drawing.Point(6, 104);
this.buttonRefresh.Name = "buttonRefresh";
this.buttonRefresh.Size = new System.Drawing.Size(75, 23);
this.buttonRefresh.TabIndex = 4;
this.buttonRefresh.Text = "Refresh";
this.buttonRefresh.UseVisualStyleBackColor = true;
this.buttonRefresh.Click += new System.EventHandler(this.buttonRefresh_Click);
//
// GBAGPUView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(636, 405);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.buttonShowWidget);
this.Controls.Add(this.label1);
this.Controls.Add(this.panel1);
@ -84,7 +160,10 @@
this.Name = "GBAGPUView";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
this.Text = "GBA GPU Viewer";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.GBAGPUView_FormClosed);
this.Load += new System.EventHandler(this.GBAGPUView_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -96,6 +175,12 @@
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button buttonShowWidget;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button buttonRefresh;
private System.Windows.Forms.HScrollBar hScrollBar1;
private System.Windows.Forms.RadioButton radioButtonManual;
private System.Windows.Forms.RadioButton radioButtonScanline;
private System.Windows.Forms.RadioButton radioButtonFrame;
}
}

View File

@ -35,6 +35,9 @@ namespace BizHawk.MultiClient.GBAtools
Buffer.BlockCopy(tmp, 0, ColorConversion, sizeof(int) * tmp.Length, sizeof(int) * tmp.Length);
GenerateWidgets();
radioButtonFrame.Checked = true;
hScrollBar1_ValueChanged(null, null);
RecomputeRefresh();
}
#region drawing primitives
@ -659,7 +662,22 @@ namespace BizHawk.MultiClient.GBAtools
return;
if (gba != null)
{
DrawEverything();
if (cbscanline_emu != cbscanline)
{
cbscanline_emu = cbscanline;
if (cbscanline == -2) // manual, do nothing
{
gba.SetScanlineCallback(null, null);
}
else if (cbscanline == -1) // end of frame
{
gba.SetScanlineCallback(DrawEverything, null);
}
else
{
gba.SetScanlineCallback(DrawEverything, cbscanline);
}
}
}
}
@ -688,5 +706,65 @@ namespace BizHawk.MultiClient.GBAtools
{
ShowSelectedWidget();
}
int cbscanline;
int cbscanline_emu = 500;
void RecomputeRefresh()
{
if (radioButtonFrame.Checked)
{
hScrollBar1.Enabled = false;
buttonRefresh.Enabled = false;
cbscanline = -1;
}
else if (radioButtonScanline.Checked)
{
hScrollBar1.Enabled = true;
buttonRefresh.Enabled = false;
cbscanline = (hScrollBar1.Value + 160) % 228;
}
else if (radioButtonManual.Checked)
{
hScrollBar1.Enabled = false;
buttonRefresh.Enabled = true;
cbscanline = -2;
}
}
private void radioButtonFrame_CheckedChanged(object sender, EventArgs e)
{
RecomputeRefresh();
}
private void radioButtonScanline_CheckedChanged(object sender, EventArgs e)
{
RecomputeRefresh();
}
private void hScrollBar1_ValueChanged(object sender, EventArgs e)
{
cbscanline = (hScrollBar1.Value + 160) % 228;
radioButtonScanline.Text = "Scanline " + cbscanline;
}
private void radioButtonManual_CheckedChanged(object sender, EventArgs e)
{
RecomputeRefresh();
}
private void buttonRefresh_Click(object sender, EventArgs e)
{
DrawEverything();
}
private void GBAGPUView_FormClosed(object sender, FormClosedEventArgs e)
{
if (gba != null)
{
gba.SetScanlineCallback(null, null);
gba = null;
}
}
}
}

View File

@ -211,7 +211,7 @@
// hScrollBarScanline
//
this.hScrollBarScanline.Location = new System.Drawing.Point(76, 45);
this.hScrollBarScanline.Maximum = 153;
this.hScrollBarScanline.Maximum = 162;
this.hScrollBarScanline.Name = "hScrollBarScanline";
this.hScrollBarScanline.Size = new System.Drawing.Size(192, 16);
this.hScrollBarScanline.TabIndex = 21;

View File

@ -217,3 +217,21 @@ EXPORT void libmeteor_writebus(uint32_t addr, uint8_t val)
{
AMeteor::_memory.Write8(addr, val);
}
int slcallbackline = 400;
void (*slcallback)() = NULL;
EXPORT void libmeteor_setscanlinecallback(void (*callback)(), int scanline)
{
if (!callback)
slcallbackline = 400;
else
slcallbackline = scanline;
slcallback = callback;
}
void scanlinecallback_bizhawk()
{
if (slcallback)
slcallback();
}

View File

@ -32,6 +32,8 @@ void abort_bizhawk(const char *msg);
void keyupdate_bizhawk();
extern bool traceenabled;
void trace_bizhawk(std::string msg);
extern int slcallbackline;
void scanlinecallback_bizhawk();
#if 0
#define met_abort(str) \

View File

@ -94,7 +94,8 @@ namespace AMeteor
else // no vcount match
dispstat &= ~(uint16_t)0x4;
// scanline callback for frontend
// ...
if (slcallbackline == vcount)
scanlinecallback_bizhawk();
}
else // if we were not H-Blanking
{