vbanext: support GPU VIEW. it should still work in meteor...

This commit is contained in:
goyuken 2014-08-17 19:02:10 +00:00
parent 23ae71382e
commit 9c24c180f2
9 changed files with 139 additions and 85 deletions

View File

@ -39,7 +39,6 @@
this.hScrollBar1 = new System.Windows.Forms.HScrollBar(); this.hScrollBar1 = new System.Windows.Forms.HScrollBar();
this.radioButtonManual = new System.Windows.Forms.RadioButton(); this.radioButtonManual = new System.Windows.Forms.RadioButton();
this.radioButtonScanline = new System.Windows.Forms.RadioButton(); this.radioButtonScanline = new System.Windows.Forms.RadioButton();
this.radioButtonFrame = new System.Windows.Forms.RadioButton();
this.labelClipboard = new System.Windows.Forms.Label(); this.labelClipboard = new System.Windows.Forms.Label();
this.timerMessage = new System.Windows.Forms.Timer(this.components); this.timerMessage = new System.Windows.Forms.Timer(this.components);
this.groupBox1.SuspendLayout(); this.groupBox1.SuspendLayout();
@ -90,7 +89,6 @@
this.groupBox1.Controls.Add(this.hScrollBar1); this.groupBox1.Controls.Add(this.hScrollBar1);
this.groupBox1.Controls.Add(this.radioButtonManual); this.groupBox1.Controls.Add(this.radioButtonManual);
this.groupBox1.Controls.Add(this.radioButtonScanline); this.groupBox1.Controls.Add(this.radioButtonScanline);
this.groupBox1.Controls.Add(this.radioButtonFrame);
this.groupBox1.Location = new System.Drawing.Point(15, 220); this.groupBox1.Location = new System.Drawing.Point(15, 220);
this.groupBox1.Name = "groupBox1"; this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(134, 133); this.groupBox1.Size = new System.Drawing.Size(134, 133);
@ -141,17 +139,6 @@
this.radioButtonScanline.UseVisualStyleBackColor = true; this.radioButtonScanline.UseVisualStyleBackColor = true;
this.radioButtonScanline.CheckedChanged += new System.EventHandler(this.radioButtonScanline_CheckedChanged); this.radioButtonScanline.CheckedChanged += new System.EventHandler(this.radioButtonScanline_CheckedChanged);
// //
// 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);
//
// labelClipboard // labelClipboard
// //
this.labelClipboard.AutoSize = true; this.labelClipboard.AutoSize = true;
@ -205,7 +192,6 @@
private System.Windows.Forms.HScrollBar hScrollBar1; private System.Windows.Forms.HScrollBar hScrollBar1;
private System.Windows.Forms.RadioButton radioButtonManual; private System.Windows.Forms.RadioButton radioButtonManual;
private System.Windows.Forms.RadioButton radioButtonScanline; private System.Windows.Forms.RadioButton radioButtonScanline;
private System.Windows.Forms.RadioButton radioButtonFrame;
private System.Windows.Forms.Label labelClipboard; private System.Windows.Forms.Label labelClipboard;
private System.Windows.Forms.Timer timerMessage; private System.Windows.Forms.Timer timerMessage;

View File

@ -11,7 +11,7 @@ namespace BizHawk.Client.EmuHawk
{ {
public partial class GBAGPUView : Form, IToolForm public partial class GBAGPUView : Form, IToolForm
{ {
GBA gba; IGBAGPUViewable gba;
// emulator memory areas // emulator memory areas
private IntPtr vram; private IntPtr vram;
@ -37,9 +37,8 @@ namespace BizHawk.Client.EmuHawk
ColorConversion = new int[65536]; ColorConversion = new int[65536];
Buffer.BlockCopy(tmp, 0, ColorConversion, 0, sizeof(int) * tmp.Length); Buffer.BlockCopy(tmp, 0, ColorConversion, 0, sizeof(int) * tmp.Length);
Buffer.BlockCopy(tmp, 0, ColorConversion, sizeof(int) * tmp.Length, sizeof(int) * tmp.Length); Buffer.BlockCopy(tmp, 0, ColorConversion, sizeof(int) * tmp.Length, sizeof(int) * tmp.Length);
radioButtonManual.Checked = true;
GenerateWidgets(); GenerateWidgets();
radioButtonFrame.Checked = true;
hScrollBar1_ValueChanged(null, null); hScrollBar1_ValueChanged(null, null);
RecomputeRefresh(); RecomputeRefresh();
} }
@ -680,10 +679,14 @@ namespace BizHawk.Client.EmuHawk
public void Restart() public void Restart()
{ {
gba = Global.Emulator as GBA; gba = Global.Emulator as IGBAGPUViewable;
if (gba != null) if (gba != null)
{ {
gba.GetGPUMemoryAreas(out vram, out palram, out oam, out mmio); var mem = gba.GetMemoryAreas();
vram = mem.vram;
palram = mem.palram;
oam = mem.oam;
mmio = mem.mmio;
} }
else else
{ {
@ -702,17 +705,13 @@ namespace BizHawk.Client.EmuHawk
if (_cbscanlineEmu != _cbscanline) if (_cbscanlineEmu != _cbscanline)
{ {
_cbscanlineEmu = _cbscanline; _cbscanlineEmu = _cbscanline;
if (_cbscanline == -2) // manual, do nothing if (!_cbscanline.HasValue) // manual, deactivate callback
{ {
gba.SetScanlineCallback(null, null); gba.SetScanlineCallback(null, 0);
}
else if (_cbscanline == -1) // end of frame
{
gba.SetScanlineCallback(DrawEverything, null);
} }
else else
{ {
gba.SetScanlineCallback(DrawEverything, _cbscanline); gba.SetScanlineCallback(DrawEverything, _cbscanline.Value);
} }
} }
} }
@ -751,18 +750,12 @@ namespace BizHawk.Client.EmuHawk
#region refresh control #region refresh control
private int _cbscanline; private int? _cbscanline = null;
private int _cbscanlineEmu = 500; private int? _cbscanlineEmu = 500;
private void RecomputeRefresh() private void RecomputeRefresh()
{ {
if (radioButtonFrame.Checked) if (radioButtonScanline.Checked)
{
hScrollBar1.Enabled = false;
buttonRefresh.Enabled = false;
_cbscanline = -1;
}
else if (radioButtonScanline.Checked)
{ {
hScrollBar1.Enabled = true; hScrollBar1.Enabled = true;
buttonRefresh.Enabled = false; buttonRefresh.Enabled = false;
@ -772,7 +765,7 @@ namespace BizHawk.Client.EmuHawk
{ {
hScrollBar1.Enabled = false; hScrollBar1.Enabled = false;
buttonRefresh.Enabled = true; buttonRefresh.Enabled = true;
_cbscanline = -2; _cbscanline = null;
} }
} }
@ -808,7 +801,7 @@ namespace BizHawk.Client.EmuHawk
{ {
if (gba != null) if (gba != null)
{ {
gba.SetScanlineCallback(null, null); gba.SetScanlineCallback(null, 0);
gba = null; gba = null;
} }
} }

View File

@ -237,6 +237,7 @@
<Compile Include="Consoles\Nintendo\Gameboy\GambatteLink.cs" /> <Compile Include="Consoles\Nintendo\Gameboy\GambatteLink.cs" />
<Compile Include="Consoles\Nintendo\Gameboy\GBColors.cs" /> <Compile Include="Consoles\Nintendo\Gameboy\GBColors.cs" />
<Compile Include="Consoles\Nintendo\Gameboy\LibGambatte.cs" /> <Compile Include="Consoles\Nintendo\Gameboy\LibGambatte.cs" />
<Compile Include="Consoles\Nintendo\GBA\IGBAGPUViewable.cs" />
<Compile Include="Consoles\Nintendo\GBA\LibMeteor.cs" /> <Compile Include="Consoles\Nintendo\GBA\LibMeteor.cs" />
<Compile Include="Consoles\Nintendo\GBA\LibVBANext.cs" /> <Compile Include="Consoles\Nintendo\GBA\LibVBANext.cs" />
<Compile Include="Consoles\Nintendo\GBA\Meteor.cs" /> <Compile Include="Consoles\Nintendo\GBA\Meteor.cs" />

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Cores.Nintendo.GBA
{
public interface IGBAGPUViewable
{
GBAGPUMemoryAreas GetMemoryAreas();
/// <summary>
/// calls correspond to entering hblank (maybe) and in a regular frame, the sequence of calls will be 160, 161, ..., 227, 0, ..., 159
/// </summary>
/// <param name="callback"></param>
/// <param name="scanline"></param>
void SetScanlineCallback(Action callback, int scanline);
}
public class GBAGPUMemoryAreas
{
public IntPtr vram;
public IntPtr oam;
public IntPtr mmio;
public IntPtr palram;
}
}

View File

@ -130,6 +130,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
[DllImport(dllname, CallingConvention = cc)] [DllImport(dllname, CallingConvention = cc)]
public static extern byte SystemBusRead(IntPtr g, int addr); public static extern byte SystemBusRead(IntPtr g, int addr);
[UnmanagedFunctionPointer(cc)]
public delegate void StandardCallback();
[DllImport(dllname, CallingConvention = cc)]
public static extern void SetScanlineCallback(IntPtr g, StandardCallback cb, int scanline);
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public class MemoryAreas public class MemoryAreas

View File

@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
isPorted: true, isPorted: true,
isReleased: false isReleased: false
)] )]
public class GBA : IEmulator, IVideoProvider, ISyncSoundProvider public class GBA : IEmulator, IVideoProvider, ISyncSoundProvider, IGBAGPUViewable
{ {
public Dictionary<string, int> GetCpuFlagsAndRegisters() public Dictionary<string, int> GetCpuFlagsAndRegisters()
{ {
@ -83,8 +83,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
LibMeteor.libmeteor_frameadvance(); LibMeteor.libmeteor_frameadvance();
if (IsLagFrame) if (IsLagFrame)
LagCount++; LagCount++;
if (EndOfFrameCallback != null)
EndOfFrameCallback();
} }
public int Frame { get; private set; } public int Frame { get; private set; }
@ -306,22 +304,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
MemoryDomains = new MemoryDomainList(_MemoryDomains); MemoryDomains = new MemoryDomainList(_MemoryDomains);
} }
public void GetGPUMemoryAreas(out IntPtr vram, out IntPtr palram, out IntPtr oam, out IntPtr mmio)
{
IntPtr _vram = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.vram);
IntPtr _palram = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.palram);
IntPtr _oam = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.oam);
IntPtr _mmio = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.io);
if (_vram == IntPtr.Zero || _palram == IntPtr.Zero || _oam == IntPtr.Zero || _mmio == IntPtr.Zero)
throw new Exception("libmeteor_getmemoryarea() failed!");
vram = _vram;
palram = _palram;
oam = _oam;
mmio = _mmio;
}
#endregion #endregion
/// <summary>like libsnes, the library is single-instance</summary> /// <summary>like libsnes, the library is single-instance</summary>
@ -438,39 +420,44 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
CoreComm.Tracer.Put(msg); CoreComm.Tracer.Put(msg);
} }
Action EndOfFrameCallback = null; GBAGPUMemoryAreas IGBAGPUViewable.GetMemoryAreas()
LibMeteor.ScanlineCallback scanlinecb = null; {
IntPtr _vram = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.vram);
IntPtr _palram = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.palram);
IntPtr _oam = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.oam);
IntPtr _mmio = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.io);
/// <summary> if (_vram == IntPtr.Zero || _palram == IntPtr.Zero || _oam == IntPtr.Zero || _mmio == IntPtr.Zero)
/// throw new Exception("libmeteor_getmemoryarea() failed!");
/// </summary>
/// <param name="callback">null to cancel</param> return new GBAGPUMemoryAreas
/// <param name="scanline">0-227, null = end of frame</param>
public void SetScanlineCallback(Action callback, int? scanline)
{ {
if (callback == null) vram = _vram,
{ palram = _palram,
LibMeteor.libmeteor_setscanlinecallback(null, 400); oam = _oam,
EndOfFrameCallback = null; mmio = _mmio
scanlinecb = null; };
} }
else if (scanline == null)
void IGBAGPUViewable.SetScanlineCallback(Action callback, int scanline)
{ {
LibMeteor.libmeteor_setscanlinecallback(null, 400); if (scanline < 0 || scanline > 227)
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]!"); throw new ArgumentOutOfRangeException("Scanline must be in [0, 227]!");
} }
if (callback == null)
{
scanlinecb = null;
LibMeteor.libmeteor_setscanlinecallback(null, 0);
} }
else
{
scanlinecb = new LibMeteor.ScanlineCallback(callback);
LibMeteor.libmeteor_setscanlinecallback(scanlinecb, scanline);
}
}
LibMeteor.ScanlineCallback scanlinecb = null;
void Init() void Init()
{ {

View File

@ -14,7 +14,7 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Nintendo.GBA namespace BizHawk.Emulation.Cores.Nintendo.GBA
{ {
[CoreAttributes("VBA-Next", "TODO", true, false, "cd508312a29ed8c29dacac1b11c2dce56c338a54", "https://github.com/libretro/vba-next")] [CoreAttributes("VBA-Next", "TODO", true, false, "cd508312a29ed8c29dacac1b11c2dce56c338a54", "https://github.com/libretro/vba-next")]
public class VBANext : IEmulator, IVideoProvider, ISyncSoundProvider public class VBANext : IEmulator, IVideoProvider, ISyncSoundProvider, IGBAGPUViewable
{ {
IntPtr Core; IntPtr Core;
@ -254,6 +254,39 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
#region Debugging #region Debugging
LibVBANext.StandardCallback scanlinecb;
GBAGPUMemoryAreas IGBAGPUViewable.GetMemoryAreas()
{
var s = new LibVBANext.MemoryAreas();
LibVBANext.GetMemoryAreas(Core, s);
return new GBAGPUMemoryAreas
{
mmio = s.mmio,
oam = s.oam,
palram = s.palram,
vram = s.vram
};
}
void IGBAGPUViewable.SetScanlineCallback(Action callback, int scanline)
{
if (scanline < 0 || scanline > 227)
{
throw new ArgumentOutOfRangeException("Scanline must be in [0, 227]!");
}
if (callback == null)
{
scanlinecb = null;
LibVBANext.SetScanlineCallback(Core, scanlinecb, 0);
}
else
{
scanlinecb = new LibVBANext.StandardCallback(callback);
LibVBANext.SetScanlineCallback(Core, scanlinecb, scanline);
}
}
void InitMemoryDomains() void InitMemoryDomains()
{ {
var mm = new List<MemoryDomain>(); var mm = new List<MemoryDomain>();

Binary file not shown.

View File

@ -12548,6 +12548,8 @@ updateLoop:
io_registers[REG_IF] |= 2; io_registers[REG_IF] |= 2;
UPDATE_REG(0x202, io_registers[REG_IF]); UPDATE_REG(0x202, io_registers[REG_IF]);
} }
if (scanlineCallback && scanlineCallbackLine == io_registers[REG_VCOUNT])
scanlineCallback();
} }
if(io_registers[REG_VCOUNT] >= 228) if(io_registers[REG_VCOUNT] >= 228)
@ -12565,7 +12567,6 @@ updateLoop:
// if in H-Blank, leave it and move to drawing mode // if in H-Blank, leave it and move to drawing mode
io_registers[REG_VCOUNT] += 1; io_registers[REG_VCOUNT] += 1;
UPDATE_REG(0x06, io_registers[REG_VCOUNT]); UPDATE_REG(0x06, io_registers[REG_VCOUNT]);
graphics.lcdTicks += 1008; graphics.lcdTicks += 1008;
io_registers[REG_DISPSTAT] &= 0xFFFD; io_registers[REG_DISPSTAT] &= 0xFFFD;
if(io_registers[REG_VCOUNT] == 160) if(io_registers[REG_VCOUNT] == 160)
@ -12643,6 +12644,8 @@ updateLoop:
io_registers[REG_IF] |= 2; io_registers[REG_IF] |= 2;
UPDATE_REG(0x202, io_registers[REG_IF]); UPDATE_REG(0x202, io_registers[REG_IF]);
} }
if (scanlineCallback && scanlineCallbackLine == io_registers[REG_VCOUNT])
scanlineCallback();
} }
} }
@ -12936,6 +12939,9 @@ s16 *systemAudioFrameDest;
int *systemAudioFrameSamp; int *systemAudioFrameSamp;
bool lagged; bool lagged;
void (*scanlineCallback)();
int scanlineCallbackLine;
void systemDrawScreen (void) void systemDrawScreen (void)
{ {
// upconvert 555->888 (TODO: BETTER) // upconvert 555->888 (TODO: BETTER)
@ -13342,6 +13348,17 @@ template<bool isReader>bool SyncBatteryRam(NewState *ns)
return CPUReadByte(addr); return CPUReadByte(addr);
} }
void SetScanlineCallback(void (*cb)(), int scanline)
{
// the sequence of calls in a frame will be:
// 160,161,...,227,0,1,...,160
// calls coincide with entering hblank, or something like that
if (scanline < 0 || scanline > 227)
cb = nullptr;
scanlineCallback = cb;
scanlineCallbackLine = scanline;
}
}; // class Gigazoid }; // class Gigazoid
// zeroing mem operators: these are very important // zeroing mem operators: these are very important
@ -13483,4 +13500,9 @@ EXPORT u8 SystemBusRead(Gigazoid *g, u32 addr)
return g->BusRead(addr); return g->BusRead(addr);
} }
EXPORT void SetScanlineCallback(Gigazoid *g, void (*cb)(), int scanline)
{
g->SetScanlineCallback(cb, scanline);
}
#include "optable.inc" #include "optable.inc"