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.radioButtonManual = 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.timerMessage = new System.Windows.Forms.Timer(this.components);
this.groupBox1.SuspendLayout();
@ -90,7 +89,6 @@
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(134, 133);
@ -141,17 +139,6 @@
this.radioButtonScanline.UseVisualStyleBackColor = true;
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
//
this.labelClipboard.AutoSize = true;
@ -205,7 +192,6 @@
private System.Windows.Forms.HScrollBar hScrollBar1;
private System.Windows.Forms.RadioButton radioButtonManual;
private System.Windows.Forms.RadioButton radioButtonScanline;
private System.Windows.Forms.RadioButton radioButtonFrame;
private System.Windows.Forms.Label labelClipboard;
private System.Windows.Forms.Timer timerMessage;

View File

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

View File

@ -237,6 +237,7 @@
<Compile Include="Consoles\Nintendo\Gameboy\GambatteLink.cs" />
<Compile Include="Consoles\Nintendo\Gameboy\GBColors.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\LibVBANext.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)]
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)]
public class MemoryAreas

View File

@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
isPorted: true,
isReleased: false
)]
public class GBA : IEmulator, IVideoProvider, ISyncSoundProvider
public class GBA : IEmulator, IVideoProvider, ISyncSoundProvider, IGBAGPUViewable
{
public Dictionary<string, int> GetCpuFlagsAndRegisters()
{
@ -83,8 +83,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
LibMeteor.libmeteor_frameadvance();
if (IsLagFrame)
LagCount++;
if (EndOfFrameCallback != null)
EndOfFrameCallback();
}
public int Frame { get; private set; }
@ -306,22 +304,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
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
/// <summary>like libsnes, the library is single-instance</summary>
@ -438,40 +420,45 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
CoreComm.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)
GBAGPUMemoryAreas IGBAGPUViewable.GetMemoryAreas()
{
if (callback == 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);
if (_vram == IntPtr.Zero || _palram == IntPtr.Zero || _oam == IntPtr.Zero || _mmio == IntPtr.Zero)
throw new Exception("libmeteor_getmemoryarea() failed!");
return new GBAGPUMemoryAreas
{
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
vram = _vram,
palram = _palram,
oam = _oam,
mmio = _mmio
};
}
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;
LibMeteor.libmeteor_setscanlinecallback(null, 0);
}
else
{
scanlinecb = new LibMeteor.ScanlineCallback(callback);
LibMeteor.libmeteor_setscanlinecallback(scanlinecb, scanline);
}
}
LibMeteor.ScanlineCallback scanlinecb = null;
void Init()
{
if (attachedcore != null)

View File

@ -14,7 +14,7 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Nintendo.GBA
{
[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;
@ -254,6 +254,39 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
#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()
{
var mm = new List<MemoryDomain>();

Binary file not shown.

View File

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