c# changes for 3d5c2120f2
This commit is contained in:
parent
3d5c2120f2
commit
07126b1e48
|
@ -593,18 +593,6 @@ namespace BizHawk.Client.Common
|
|||
videoProvider.BufferWidth, videoProvider.BufferHeight, out virtualWidth, out virtualHeight);
|
||||
}
|
||||
|
||||
// TODO: it is bad that this is happening outside the filter chain
|
||||
// the filter chain has the ability to add padding...
|
||||
// for now, we have to have some hacks. this could be improved by refactoring the filter setup hacks to be in one place only though
|
||||
// could the PADDING be done as filters too? that would be nice.
|
||||
var fCoreScreenControl = CreateCoreScreenControl();
|
||||
if (fCoreScreenControl != null)
|
||||
{
|
||||
var sz = fCoreScreenControl.PresizeInput("default", new(bufferWidth, bufferHeight));
|
||||
virtualWidth = bufferWidth = sz.Width;
|
||||
virtualHeight = bufferHeight = sz.Height;
|
||||
}
|
||||
|
||||
var padding = CalculateCompleteContentPaddingSum(true, false);
|
||||
virtualWidth += padding.Horizontal;
|
||||
virtualHeight += padding.Vertical;
|
||||
|
@ -768,24 +756,10 @@ namespace BizHawk.Client.Common
|
|||
|
||||
var bufferWidth = videoProvider.BufferWidth;
|
||||
var bufferHeight = videoProvider.BufferHeight;
|
||||
var presenterTextureWidth = bufferWidth;
|
||||
var presenterTextureHeight = bufferHeight;
|
||||
|
||||
var vw = videoProvider.VirtualWidth;
|
||||
var vh = videoProvider.VirtualHeight;
|
||||
|
||||
// TODO: it is bad that this is happening outside the filter chain
|
||||
// the filter chain has the ability to add padding...
|
||||
// for now, we have to have some hacks. this could be improved by refactoring the filter setup hacks to be in one place only though
|
||||
// could the PADDING be done as filters too? that would be nice.
|
||||
var fCoreScreenControl = CreateCoreScreenControl();
|
||||
if(fCoreScreenControl != null)
|
||||
{
|
||||
var sz = fCoreScreenControl.PresizeInput("default", new(bufferWidth, bufferHeight));
|
||||
presenterTextureWidth = vw = sz.Width;
|
||||
presenterTextureHeight = vh = sz.Height;
|
||||
}
|
||||
|
||||
if (GlobalConfig.DispFixAspectRatio)
|
||||
{
|
||||
switch (GlobalConfig.DispManagerAR)
|
||||
|
@ -862,7 +836,7 @@ namespace BizHawk.Client.Common
|
|||
if (fPresent != null)
|
||||
{
|
||||
fPresent.VirtualTextureSize = new(vw, vh);
|
||||
fPresent.TextureSize = new(presenterTextureWidth, presenterTextureHeight);
|
||||
fPresent.TextureSize = new(bufferWidth, bufferHeight);
|
||||
fPresent.BackgroundColor = videoProvider.BackgroundColor;
|
||||
fPresent.Config_FixAspectRatio = GlobalConfig.DispFixAspectRatio;
|
||||
fPresent.Config_FixScaleInteger = GlobalConfig.DispFixScaleInteger;
|
||||
|
|
|
@ -182,268 +182,25 @@ namespace BizHawk.Client.Common.Filters
|
|||
{
|
||||
private readonly NDS _nds;
|
||||
|
||||
// TODO: actually use this
|
||||
#if false
|
||||
private bool Nop = false;
|
||||
#endif
|
||||
|
||||
// matrices used for transforming screens
|
||||
private Matrix4x4 matTop, matBot;
|
||||
private Matrix4x4 matTopInvert, matBotInvert;
|
||||
|
||||
// final output area size
|
||||
private Size outputSize;
|
||||
|
||||
private static float Round(float f)
|
||||
=> (float)Math.Round(f);
|
||||
|
||||
public ScreenControlNDS(NDS nds)
|
||||
{
|
||||
_nds = nds;
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
//we're going to be blitting the source as pieces to a new render target, so we need our input to be a texture
|
||||
DeclareInput(SurfaceDisposition.Texture);
|
||||
}
|
||||
|
||||
private void CrunchNumbers()
|
||||
{
|
||||
MatrixStack top = new(), bot = new();
|
||||
|
||||
// set up transforms for each screen based on screen control values
|
||||
// this will be TRICKY depending on how many features we have, but once it's done, everything should be easy
|
||||
|
||||
var settings = _nds.GetSettings();
|
||||
|
||||
switch (settings.ScreenLayout)
|
||||
{
|
||||
//gap only applies to vertical, I guess
|
||||
case NDS.ScreenLayoutKind.Vertical:
|
||||
bot.Translate(0, 192);
|
||||
bot.Translate(0, settings.ScreenGap);
|
||||
break;
|
||||
case NDS.ScreenLayoutKind.Horizontal:
|
||||
bot.Translate(256, 0);
|
||||
break;
|
||||
case NDS.ScreenLayoutKind.Top:
|
||||
case NDS.ScreenLayoutKind.Bottom:
|
||||
// do nothing here, we'll discard the other screen
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
// this doesn't make any sense, it's likely to be too much for a monitor to gracefully handle too
|
||||
if (settings.ScreenLayout != NDS.ScreenLayoutKind.Horizontal)
|
||||
{
|
||||
var rot = settings.ScreenRotation switch
|
||||
{
|
||||
NDS.ScreenRotationKind.Rotate90 => 90,
|
||||
NDS.ScreenRotationKind.Rotate180 => 180,
|
||||
NDS.ScreenRotationKind.Rotate270 => 270,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
top.RotateZ(rot);
|
||||
bot.RotateZ(rot);
|
||||
}
|
||||
|
||||
// TODO: refactor some of the below into a class that doesn't require having top and bottom replica code
|
||||
|
||||
matTop = top.Top;
|
||||
matBot = bot.Top;
|
||||
|
||||
// apply transforms from standard input screen positions to output screen positions
|
||||
var top_TL = Vector2.Transform(new(0, 0), matTop);
|
||||
var top_TR = Vector2.Transform(new(256, 0), matTop);
|
||||
var top_BL = Vector2.Transform(new(0, 192), matTop);
|
||||
var top_BR = Vector2.Transform(new(256, 192), matTop);
|
||||
var bot_TL = Vector2.Transform(new(0, 0), matBot);
|
||||
var bot_TR = Vector2.Transform(new(256, 0), matBot);
|
||||
var bot_BL = Vector2.Transform(new(0, 192), matBot);
|
||||
var bot_BR = Vector2.Transform(new(256, 192), matBot);
|
||||
|
||||
// in case of math errors in the transforms, we'll round this stuff.. although...
|
||||
// we're gonna use matrix transforms for drawing later, so it isn't extremely helpful
|
||||
|
||||
// TODO - need more consideration of numerical precision here, because the typical case should be rock solid
|
||||
top_TL.X = Round(top_TL.X); top_TL.Y = Round(top_TL.Y);
|
||||
top_TR.X = Round(top_TR.X); top_TR.Y = Round(top_TR.Y);
|
||||
top_BL.X = Round(top_BL.X); top_BL.Y = Round(top_BL.Y);
|
||||
top_BR.X = Round(top_BR.X); top_BR.Y = Round(top_BR.Y);
|
||||
bot_TL.X = Round(bot_TL.X); bot_TL.Y = Round(bot_TL.Y);
|
||||
bot_TR.X = Round(bot_TR.X); bot_TR.Y = Round(bot_TR.Y);
|
||||
bot_BL.X = Round(bot_BL.X); bot_BL.Y = Round(bot_BL.Y);
|
||||
bot_BR.X = Round(bot_BR.X); bot_BR.Y = Round(bot_BR.Y);
|
||||
|
||||
#if false
|
||||
// precalculate some useful metrics
|
||||
top_width = (int)(top_TR.X - top_TL.X);
|
||||
top_height = (int)(top_BR.Y - top_TR.Y);
|
||||
bot_width = (int)(bot_TR.X - bot_TL.X);
|
||||
bot_height = (int)(bot_BR.Y - bot_TR.Y);
|
||||
#endif
|
||||
|
||||
// the size can now be determined in a kind of fluffily magical way by transforming edges and checking the bounds
|
||||
float fxmin = 100000, fymin = 100000, fxmax = -100000, fymax = -100000;
|
||||
if (settings.ScreenLayout != NDS.ScreenLayoutKind.Bottom)
|
||||
{
|
||||
fxmin = Math.Min(Math.Min(Math.Min(Math.Min(top_TL.X, top_TR.X), top_BL.X), top_BR.X), fxmin);
|
||||
fymin = Math.Min(Math.Min(Math.Min(Math.Min(top_TL.Y, top_TR.Y), top_BL.Y), top_BR.Y), fymin);
|
||||
fxmax = Math.Max(Math.Max(Math.Max(Math.Max(top_TL.X, top_TR.X), top_BL.X), top_BR.X), fxmax);
|
||||
fymax = Math.Max(Math.Max(Math.Max(Math.Max(top_TL.Y, top_TR.Y), top_BL.Y), top_BR.Y), fymax);
|
||||
}
|
||||
if (settings.ScreenLayout != NDS.ScreenLayoutKind.Top)
|
||||
{
|
||||
fxmin = Math.Min(Math.Min(Math.Min(Math.Min(bot_TL.X, bot_TR.X), bot_BL.X), bot_BR.X), fxmin);
|
||||
fymin = Math.Min(Math.Min(Math.Min(Math.Min(bot_TL.Y, bot_TR.Y), bot_BL.Y), bot_BR.Y), fymin);
|
||||
fxmax = Math.Max(Math.Max(Math.Max(Math.Max(bot_TL.X, bot_TR.X), bot_BL.X), bot_BR.X), fxmax);
|
||||
fymax = Math.Max(Math.Max(Math.Max(Math.Max(bot_TL.Y, bot_TR.Y), bot_BL.Y), bot_BR.Y), fymax);
|
||||
}
|
||||
|
||||
// relocate whatever we got back into the viewable area
|
||||
top.Translate(-fxmin, -fymin);
|
||||
bot.Translate(-fxmin, -fymin);
|
||||
matTop = top.Top;
|
||||
matBot = bot.Top;
|
||||
|
||||
// do some more rounding
|
||||
unsafe
|
||||
{
|
||||
fixed (Matrix4x4* matTopP = &matTop, matBotP = &matBot)
|
||||
{
|
||||
float* matTopF = (float*)matTopP, matBotF = (float*)matBotP;
|
||||
for (var i = 0; i < 4 * 4; i++)
|
||||
{
|
||||
if (Math.Abs(matTopF[i]) < 0.0000001f)
|
||||
{
|
||||
matTopF[i] = 0;
|
||||
}
|
||||
|
||||
if (Math.Abs(matBotF[i]) < 0.0000001f)
|
||||
{
|
||||
matBotF[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Matrix4x4.Invert(matTop, out matTopInvert);
|
||||
Matrix4x4.Invert(matBot, out matBotInvert);
|
||||
|
||||
outputSize = new((int)(fxmax - fxmin), (int)(fymax - fymin));
|
||||
}
|
||||
|
||||
public override Size PresizeInput(string channel, Size size)
|
||||
{
|
||||
CrunchNumbers();
|
||||
return outputSize;
|
||||
}
|
||||
|
||||
public override Size PresizeOutput(string channel, Size size)
|
||||
{
|
||||
CrunchNumbers();
|
||||
return base.PresizeOutput(channel, outputSize);
|
||||
}
|
||||
|
||||
public override void SetInputFormat(string channel, SurfaceState state)
|
||||
{
|
||||
CrunchNumbers();
|
||||
var ss = new SurfaceState(new(outputSize), SurfaceDisposition.RenderTarget);
|
||||
DeclareOutput(ss, channel);
|
||||
}
|
||||
|
||||
public override Vector2 UntransformPoint(string channel, Vector2 point)
|
||||
{
|
||||
var settings = _nds.GetSettings();
|
||||
var invert = settings.ScreenInvert
|
||||
&& settings.ScreenLayout != NDS.ScreenLayoutKind.Top
|
||||
&& settings.ScreenLayout != NDS.ScreenLayoutKind.Bottom;
|
||||
|
||||
point = Vector2.Transform(point, invert ? matTopInvert : matBotInvert);
|
||||
|
||||
// hack to accomodate input tracking system's float-point sense (based on the core's VideoBuffer height)
|
||||
// actually, this is needed for a reason similar to the "TouchScreenStart" that I removed.
|
||||
// So, something like that needs readding if we're to get rid of this hack.
|
||||
// (should redo it as a mouse coordinate offset or something.. but the key is to pipe it to the point where this is needed.. that is where MainForm does DisplayManager.UntransformPoint()
|
||||
point.Y *= 2;
|
||||
|
||||
// in case we're in this layout, we get confused, so fix it
|
||||
if (settings.ScreenLayout == NDS.ScreenLayoutKind.Top) point = new(0.0f, 0.0f);
|
||||
|
||||
// TODO: we probably need more subtle logic here.
|
||||
// some capability to return -1,-1 perhaps in case the cursor is nowhere.
|
||||
// not sure about that
|
||||
|
||||
return point;
|
||||
var ret = _nds.GetTouchCoords((int)point.X, (int)point.Y);
|
||||
var vp = _nds.AsVideoProvider();
|
||||
ret.X *= vp.BufferWidth / 255.0f;
|
||||
ret.Y *= vp.BufferHeight / 191.0f;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override Vector2 TransformPoint(string channel, Vector2 point)
|
||||
{
|
||||
return Vector2.Transform(point, matTop);
|
||||
}
|
||||
|
||||
public override void Run()
|
||||
{
|
||||
#if false
|
||||
if (Nop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: this could be more efficient (draw only in gap)
|
||||
FilterProgram.GL.ClearColor(Color.Black);
|
||||
|
||||
FilterProgram.GuiRenderer.Begin(outputSize);
|
||||
FilterProgram.GuiRenderer.DisableBlending();
|
||||
|
||||
// TODO: may depend on input, or other factors, not sure yet
|
||||
// watch out though... if we filter linear, then screens will bleed into each other.
|
||||
// so we will have to break them into render targets first.
|
||||
InputTexture.SetFilterNearest();
|
||||
|
||||
//draw screens
|
||||
var renderTop = false;
|
||||
var renderBottom = false;
|
||||
var settings = _nds.GetSettings();
|
||||
switch (settings.ScreenLayout)
|
||||
{
|
||||
case NDS.ScreenLayoutKind.Bottom:
|
||||
renderBottom = true;
|
||||
break;
|
||||
case NDS.ScreenLayoutKind.Top:
|
||||
renderTop = true;
|
||||
break;
|
||||
case NDS.ScreenLayoutKind.Vertical:
|
||||
case NDS.ScreenLayoutKind.Horizontal:
|
||||
renderTop = renderBottom = true;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
var invert = settings.ScreenInvert && renderTop && renderBottom;
|
||||
|
||||
if (renderTop)
|
||||
{
|
||||
FilterProgram.GuiRenderer.Modelview.Push();
|
||||
FilterProgram.GuiRenderer.Modelview.PreMultiplyMatrix(invert ? matBot : matTop);
|
||||
FilterProgram.GuiRenderer.DrawSubrect(InputTexture, 0, 0, 256, 192, 0.0f, 0.0f, 1.0f, 0.5f);
|
||||
FilterProgram.GuiRenderer.Modelview.Pop();
|
||||
}
|
||||
|
||||
if (renderBottom)
|
||||
{
|
||||
FilterProgram.GuiRenderer.Modelview.Push();
|
||||
FilterProgram.GuiRenderer.Modelview.PreMultiplyMatrix(invert ? matTop : matBot);
|
||||
FilterProgram.GuiRenderer.DrawSubrect(InputTexture, 0, 0, 256, 192, 0.0f, 0.5f, 1.0f, 1.0f);
|
||||
FilterProgram.GuiRenderer.Modelview.Pop();
|
||||
}
|
||||
|
||||
FilterProgram.GuiRenderer.End();
|
||||
// TODO
|
||||
Console.WriteLine($"TODO ScreenControlNDS TransformPoint {point.X} / {point.Y}");
|
||||
return base.TransformPoint(channel, point);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -157,15 +157,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
}
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CC)]
|
||||
public delegate IntPtr RequestGLContextCallback();
|
||||
|
||||
[UnmanagedFunctionPointer(CC)]
|
||||
public delegate void ReleaseGLContextCallback(IntPtr context);
|
||||
|
||||
[UnmanagedFunctionPointer(CC)]
|
||||
public delegate void ActivateGLContextCallback(IntPtr context);
|
||||
|
||||
[UnmanagedFunctionPointer(CC)]
|
||||
public delegate IntPtr GetGLProcAddressCallback(string proc);
|
||||
|
||||
|
@ -263,5 +254,45 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
|
||||
[BizImport(CC)]
|
||||
public abstract void ReadFrameBuffer(int[] buffer);
|
||||
|
||||
public enum ScreenLayout : int
|
||||
{
|
||||
Natural,
|
||||
Vertical,
|
||||
Horizontal,
|
||||
// TODO? do we want this?
|
||||
// Hybrid,
|
||||
}
|
||||
|
||||
public enum ScreenRotation : int
|
||||
{
|
||||
Deg0,
|
||||
Deg90,
|
||||
Deg180,
|
||||
Deg270,
|
||||
}
|
||||
|
||||
public enum ScreenSizing : int
|
||||
{
|
||||
Even = 0,
|
||||
TopOnly = 4,
|
||||
BotOnly = 5,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ScreenSettings
|
||||
{
|
||||
public ScreenLayout ScreenLayout;
|
||||
public ScreenRotation ScreenRotation;
|
||||
public ScreenSizing ScreenSizing;
|
||||
public int ScreenGap;
|
||||
public bool ScreenSwap;
|
||||
}
|
||||
|
||||
[BizImport(CC)]
|
||||
public abstract void SetScreenSettings(ref ScreenSettings screenSettings, out int width, out int height, out int vwidth, out int vheight);
|
||||
|
||||
[BizImport(CC)]
|
||||
public abstract void GetTouchCoords(ref int x, ref int y);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
private readonly IVideoProvider _vp;
|
||||
private readonly LibMelonDS _core;
|
||||
private readonly Action _activateGLContextCallback;
|
||||
private readonly int[] _vbuf = new int[256 * 16 * 384 * 16];
|
||||
|
||||
internal bool VideoDirty;
|
||||
|
||||
|
@ -25,18 +24,19 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
|
||||
public int[] GetVideoBuffer()
|
||||
{
|
||||
var vb = _vp.GetVideoBuffer();
|
||||
if (VideoDirty)
|
||||
{
|
||||
_activateGLContextCallback();
|
||||
_core.ReadFrameBuffer(_vbuf);
|
||||
_core.ReadFrameBuffer(vb);
|
||||
VideoDirty = false;
|
||||
}
|
||||
|
||||
return _vbuf;
|
||||
return vb;
|
||||
}
|
||||
|
||||
public int VirtualWidth => 256;
|
||||
public int VirtualHeight => 384;
|
||||
public int VirtualWidth { get; internal set; }
|
||||
public int VirtualHeight { get; internal set; }
|
||||
public int BufferWidth => _vp.BufferWidth;
|
||||
public int BufferHeight => _vp.BufferHeight;
|
||||
public int VsyncNumerator => _vp.VsyncNumerator;
|
||||
|
|
|
@ -101,25 +101,33 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
|
||||
public enum ScreenLayoutKind
|
||||
{
|
||||
Natural,
|
||||
Vertical,
|
||||
Horizontal,
|
||||
[Display(Name = "Top Only")]
|
||||
Top,
|
||||
[Display(Name = "Bottom Only")]
|
||||
Bottom,
|
||||
}
|
||||
|
||||
public enum ScreenRotationKind
|
||||
{
|
||||
[Display(Name = "0°")]
|
||||
Rotate0,
|
||||
[Display(Name = "90°")]
|
||||
Rotate90,
|
||||
[Display(Name = "180°")]
|
||||
Rotate180,
|
||||
[Display(Name = "270°")]
|
||||
Rotate270,
|
||||
}
|
||||
|
||||
public class NDSSettings
|
||||
{
|
||||
[DisplayName("Screen Layout")]
|
||||
[Description("Adjusts the layout of the screens")]
|
||||
[DefaultValue(ScreenLayoutKind.Vertical)]
|
||||
[Description("Adjusts the layout of the screens. Natural will change between Vertical and Horizontal depending on Screen Rotation")]
|
||||
[DefaultValue(ScreenLayoutKind.Natural)]
|
||||
[TypeConverter(typeof(DescribableEnumConverter))]
|
||||
public ScreenLayoutKind ScreenLayout { get; set; }
|
||||
|
||||
[DisplayName("Invert Screens")]
|
||||
|
@ -130,6 +138,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
[DisplayName("Rotation")]
|
||||
[Description("Adjusts the orientation of the screens")]
|
||||
[DefaultValue(ScreenRotationKind.Rotate0)]
|
||||
[TypeConverter(typeof(DescribableEnumConverter))]
|
||||
public ScreenRotationKind ScreenRotation { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
|
@ -147,13 +156,16 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
public enum AudioBitDepthType : int
|
||||
{
|
||||
Auto,
|
||||
[Display(Name = "10")]
|
||||
Ten,
|
||||
[Display(Name = "16")]
|
||||
Sixteen,
|
||||
}
|
||||
|
||||
[DisplayName("Audio Bit Depth")]
|
||||
[Description("Auto will set the audio bit depth most accurate to the console (10 for DS, 16 for DSi).")]
|
||||
[DefaultValue(AudioBitDepthType.Auto)]
|
||||
[TypeConverter(typeof(DescribableEnumConverter))]
|
||||
public AudioBitDepthType AudioBitDepth { get; set; }
|
||||
|
||||
[DisplayName("Alt Lag")]
|
||||
|
@ -445,9 +457,56 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
public NDSSyncSettings GetSyncSettings()
|
||||
=> _syncSettings.Clone();
|
||||
|
||||
private void RefreshScreenSettings(NDSSettings settings)
|
||||
{
|
||||
var screenSettings = new LibMelonDS.ScreenSettings
|
||||
{
|
||||
ScreenLayout = settings.ScreenLayout switch
|
||||
{
|
||||
ScreenLayoutKind.Natural => LibMelonDS.ScreenLayout.Natural,
|
||||
ScreenLayoutKind.Vertical => LibMelonDS.ScreenLayout.Vertical,
|
||||
ScreenLayoutKind.Horizontal => LibMelonDS.ScreenLayout.Horizontal,
|
||||
_ => LibMelonDS.ScreenLayout.Natural,
|
||||
},
|
||||
ScreenRotation = settings.ScreenRotation switch
|
||||
{
|
||||
ScreenRotationKind.Rotate0 => LibMelonDS.ScreenRotation.Deg0,
|
||||
ScreenRotationKind.Rotate90 => LibMelonDS.ScreenRotation.Deg90,
|
||||
ScreenRotationKind.Rotate180 => LibMelonDS.ScreenRotation.Deg180,
|
||||
ScreenRotationKind.Rotate270 => LibMelonDS.ScreenRotation.Deg270,
|
||||
_ => LibMelonDS.ScreenRotation.Deg0,
|
||||
},
|
||||
ScreenSizing = settings.ScreenLayout switch
|
||||
{
|
||||
ScreenLayoutKind.Top => LibMelonDS.ScreenSizing.TopOnly,
|
||||
ScreenLayoutKind.Bottom => LibMelonDS.ScreenSizing.BotOnly,
|
||||
_ => LibMelonDS.ScreenSizing.Even,
|
||||
},
|
||||
ScreenGap = Math.Max(0, Math.Min(settings.ScreenGap, 128)),
|
||||
ScreenSwap = settings.ScreenInvert
|
||||
};
|
||||
|
||||
_openGLProvider.ActivateGLContext(_glContext); // SetScreenSettings will re-present the frame, so needs OpenGL context active
|
||||
_core.SetScreenSettings(ref screenSettings, out var w , out var h, out var vw, out var vh);
|
||||
|
||||
BufferWidth = w;
|
||||
BufferHeight = h;
|
||||
_glTextureProvider.VirtualWidth = vw;
|
||||
_glTextureProvider.VirtualHeight = vh;
|
||||
_glTextureProvider.VideoDirty = true;
|
||||
}
|
||||
|
||||
public PutSettingsDirtyBits PutSettings(NDSSettings o)
|
||||
{
|
||||
var ret = NDSSettings.NeedsScreenResize(_settings, o);
|
||||
|
||||
// ScreenInvert changing won't need a screen resize
|
||||
// but it will change the underlying image
|
||||
if (_glContext != null && (ret || _settings.ScreenInvert != o.ScreenInvert))
|
||||
{
|
||||
RefreshScreenSettings(o);
|
||||
}
|
||||
|
||||
_settings = o;
|
||||
return ret ? PutSettingsDirtyBits.ScreenLayoutChanged : PutSettingsDirtyBits.None;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
|
@ -64,12 +65,22 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
|
||||
private readonly MelonDSGLTextureProvider _glTextureProvider;
|
||||
private readonly IOpenGLProvider _openGLProvider;
|
||||
private readonly object _glContext;
|
||||
private readonly LibMelonDS.GetGLProcAddressCallback _getGLProcAddressCallback;
|
||||
private object _glContext;
|
||||
|
||||
private IntPtr GetGLProcAddressCallback(string proc)
|
||||
=> _openGLProvider.GetGLProcAddress(proc);
|
||||
|
||||
public Vector2 GetTouchCoords(int x, int y)
|
||||
{
|
||||
if (_glContext != null)
|
||||
{
|
||||
_core.GetTouchCoords(ref x, ref y);
|
||||
}
|
||||
|
||||
return new(x, y);
|
||||
}
|
||||
|
||||
[CoreConstructor(VSystemID.Raw.NDS)]
|
||||
public NDS(CoreLoadParameters<NDSSettings, NDSSyncSettings> lp)
|
||||
: base(lp.Comm, new()
|
||||
|
@ -77,7 +88,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
DefaultWidth = 256,
|
||||
DefaultHeight = 384,
|
||||
MaxWidth = 256 * 16,
|
||||
MaxHeight = 384 * 16,
|
||||
MaxHeight = (384 + 128) * 16,
|
||||
MaxSamples = 1024,
|
||||
DefaultFpsNumerator = 33513982,
|
||||
DefaultFpsDenominator = 560190,
|
||||
|
@ -145,6 +156,18 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
}
|
||||
}
|
||||
|
||||
if (_activeSyncSettings.ThreeDeeRenderer == NDSSyncSettings.ThreeDeeRendererType.Software)
|
||||
{
|
||||
if (!_openGLProvider.SupportsGLVersion(3, 1))
|
||||
{
|
||||
lp.Comm.Notify("OpenGL 3.1 is not supported on this machine, screen control options will not work.", null);
|
||||
}
|
||||
else
|
||||
{
|
||||
_glContext = _openGLProvider.RequestGLContext(3, 1, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
_core = PreInit<LibMelonDS>(new()
|
||||
{
|
||||
Filename = "melonDS.wbx",
|
||||
|
@ -242,7 +265,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
_configCallbackInterface.AllCallbacksInArray(_adapter),
|
||||
_fileCallbackInterface.AllCallbacksInArray(_adapter),
|
||||
_logCallback,
|
||||
_getGLProcAddressCallback);
|
||||
_glContext != null ? _getGLProcAddressCallback : null);
|
||||
if (error != IntPtr.Zero)
|
||||
{
|
||||
using (_exe.EnterExit())
|
||||
|
@ -284,6 +307,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
{
|
||||
_glTextureProvider = new(this, _core, () => _openGLProvider.ActivateGLContext(_glContext));
|
||||
_serviceProvider.Register<IVideoProvider>(_glTextureProvider);
|
||||
RefreshScreenSettings(_settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,6 +468,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
|
|||
if (_glContext != null)
|
||||
{
|
||||
_openGLProvider.ReleaseGLContext(_glContext);
|
||||
_glContext = null;
|
||||
}
|
||||
|
||||
base.Dispose();
|
||||
|
|
Loading…
Reference in New Issue