all nyma cores: support constant size framebuffer
this will do lossless integer scaling using mednafen provided screen geometry data
This commit is contained in:
parent
ddfd6fd49a
commit
b11b50a950
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -38,7 +38,6 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCE
|
||||||
|
|
||||||
protected override IDictionary<string, string> SettingsOverrides { get; } = new Dictionary<string, string>
|
protected override IDictionary<string, string> SettingsOverrides { get; } = new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{ "pce_fast.correct_aspect", null },
|
|
||||||
{ "pce_fast.mouse_sensitivity", null },
|
{ "pce_fast.mouse_sensitivity", null },
|
||||||
{ "pce_fast.disable_softreset", null },
|
{ "pce_fast.disable_softreset", null },
|
||||||
{ "pce_fast.cdbios", null },
|
{ "pce_fast.cdbios", null },
|
||||||
|
|
|
@ -27,7 +27,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Faust
|
||||||
{ "snes_faust.affinity.msu1.data", null },
|
{ "snes_faust.affinity.msu1.data", null },
|
||||||
{ "snes_faust.frame_begin_vblank", null },
|
{ "snes_faust.frame_begin_vblank", null },
|
||||||
{ "snes_faust.msu1.resamp_quality", null },
|
{ "snes_faust.msu1.resamp_quality", null },
|
||||||
{ "snes_faust.correct_aspect", null },
|
|
||||||
{ "snes_faust.spex", null },
|
{ "snes_faust.spex", null },
|
||||||
{ "snes_faust.spex.sound", null },
|
{ "snes_faust.spex.sound", null },
|
||||||
{ "nyma.rtcinitialtime", null },
|
{ "nyma.rtcinitialtime", null },
|
||||||
|
|
|
@ -51,5 +51,10 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK
|
||||||
throw new InvalidOperationException("Core rejected the saveram");
|
throw new InvalidOperationException("Core rejected the saveram");
|
||||||
_exe.RemoveTransientFile("SAV:flash");
|
_exe.RemoveTransientFile("SAV:flash");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override IDictionary<string, string> SettingsOverrides { get; } = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "nyma.constantfb", null }, // TODO: Couldn't we just autodetect this whenever lcm == max == nominal?
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
[BizImport(CC)]
|
[BizImport(CC)]
|
||||||
public abstract bool InitCd(int numdisks);
|
public abstract bool InitCd(int numdisks);
|
||||||
|
|
||||||
public enum CommandType : int
|
public enum CommandType : short
|
||||||
{
|
{
|
||||||
NONE = 0x00,
|
NONE = 0x00,
|
||||||
RESET = 0x01,
|
RESET = 0x01,
|
||||||
|
@ -85,6 +85,10 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CommandType Command;
|
public CommandType Command;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// True to render to a single framebuffer size (LCM * LCM)
|
||||||
|
/// </summary>
|
||||||
|
public short RenderConstantSize;
|
||||||
|
/// <summary>
|
||||||
/// raw data for each input port, assumed to be MAX_PORTS * MAX_PORT_DATA long
|
/// raw data for each input port, assumed to be MAX_PORTS * MAX_PORT_DATA long
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte* InputPortData;
|
public byte* InputPortData;
|
||||||
|
@ -135,6 +139,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
public int NominalHeight;
|
public int NominalHeight;
|
||||||
public VideoSystem VideoSystem;
|
public VideoSystem VideoSystem;
|
||||||
public int FpsFixed;
|
public int FpsFixed;
|
||||||
|
public int LcmWidth;
|
||||||
|
public int LcmHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BizImport(CC, Compatibility = true)]
|
[BizImport(CC, Compatibility = true)]
|
||||||
|
|
|
@ -119,7 +119,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// try to get actual value from settings
|
// try to get actual value from settings
|
||||||
if (NonSyncSettingNames.Contains(name))
|
if (/* TODO: unhack */name == "nyma.constantfb" || NonSyncSettingNames.Contains(name))
|
||||||
_settings.MednafenValues.TryGetValue(name, out val);
|
_settings.MednafenValues.TryGetValue(name, out val);
|
||||||
else
|
else
|
||||||
_syncSettings.MednafenValues.TryGetValue(name, out val);
|
_syncSettings.MednafenValues.TryGetValue(name, out val);
|
||||||
|
@ -208,7 +208,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
s.AllSettingsByKey.Add(setting.SettingsKey, setting);
|
s.AllSettingsByKey.Add(setting.SettingsKey, setting);
|
||||||
if (!SettingsOverrides.ContainsKey(setting.SettingsKey))
|
if (!SettingsOverrides.ContainsKey(setting.SettingsKey))
|
||||||
{
|
{
|
||||||
if (NonSyncSettingNames.Contains(setting.SettingsKey))
|
if (/* TODO: unhack */setting.SettingsKey == "nyma.constantfb" || NonSyncSettingNames.Contains(setting.SettingsKey))
|
||||||
{
|
{
|
||||||
s.Settings.Add(setting);
|
s.Settings.Add(setting);
|
||||||
}
|
}
|
||||||
|
@ -223,6 +223,15 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
|
|
||||||
private static IReadOnlyCollection<SettingT> ExtraSettings = new List<SettingT>
|
private static IReadOnlyCollection<SettingT> ExtraSettings = new List<SettingT>
|
||||||
{
|
{
|
||||||
|
new SettingT
|
||||||
|
{
|
||||||
|
Name = "Constant Framebuffer Size",
|
||||||
|
Description = "Output a constant framebuffer size regardless of internal resolution.",
|
||||||
|
SettingsKey = "nyma.constantfb",
|
||||||
|
DefaultValue = "0",
|
||||||
|
Flags = 0,
|
||||||
|
Type = SettingType.Bool
|
||||||
|
},
|
||||||
new SettingT
|
new SettingT
|
||||||
{
|
{
|
||||||
Name = "Initial Time",
|
Name = "Initial Time",
|
||||||
|
|
|
@ -98,7 +98,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
}
|
}
|
||||||
|
|
||||||
var info = *_nyma.GetSystemInfo();
|
var info = *_nyma.GetSystemInfo();
|
||||||
_videoBuffer = new int[info.MaxWidth * info.MaxHeight];
|
_videoBuffer = new int[Math.Max(info.MaxWidth * info.MaxHeight, info.LcmWidth * info.LcmHeight)];
|
||||||
BufferWidth = info.NominalWidth;
|
BufferWidth = info.NominalWidth;
|
||||||
BufferHeight = info.NominalHeight;
|
BufferHeight = info.NominalHeight;
|
||||||
switch (info.VideoSystem)
|
switch (info.VideoSystem)
|
||||||
|
@ -182,12 +182,13 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
var ret = new LibNymaCore.FrameInfo
|
var ret = new LibNymaCore.FrameInfo
|
||||||
{
|
{
|
||||||
SkipRendering = (short)(render ? 0 : 1),
|
SkipRendering = (short)(render ? 0 : 1),
|
||||||
SkipSoundening =(short)(rendersound ? 0 : 1),
|
SkipSoundening = (short)(rendersound ? 0 : 1),
|
||||||
Command = controller.IsPressed("Power")
|
Command = controller.IsPressed("Power")
|
||||||
? LibNymaCore.CommandType.POWER
|
? LibNymaCore.CommandType.POWER
|
||||||
: controller.IsPressed("Reset")
|
: controller.IsPressed("Reset")
|
||||||
? LibNymaCore.CommandType.RESET
|
? LibNymaCore.CommandType.RESET
|
||||||
: LibNymaCore.CommandType.NONE,
|
: LibNymaCore.CommandType.NONE,
|
||||||
|
RenderConstantSize = (short)(SettingsQuery("nyma.constantfb") != "0" ? 1 : 0),
|
||||||
InputPortData = (byte*)_frameAdvanceInputLock.AddrOfPinnedObject(),
|
InputPortData = (byte*)_frameAdvanceInputLock.AddrOfPinnedObject(),
|
||||||
FrontendTime = GetRtcTime(SettingsQuery("nyma.rtcrealtime") != "0"),
|
FrontendTime = GetRtcTime(SettingsQuery("nyma.rtcrealtime") != "0"),
|
||||||
};
|
};
|
||||||
|
|
|
@ -104,7 +104,9 @@ struct MyFrameInfo: public FrameInfo
|
||||||
int16_t SkipRendering;
|
int16_t SkipRendering;
|
||||||
int16_t SkipSoundening;
|
int16_t SkipSoundening;
|
||||||
// a single MDFN_MSC_* command to run at the start of this frame; 0 if none
|
// a single MDFN_MSC_* command to run at the start of this frame; 0 if none
|
||||||
int32_t Command;
|
int16_t Command;
|
||||||
|
// true to render LCM * LCM instead of raw
|
||||||
|
int16_t RenderConstantSize;
|
||||||
// raw data for each input port, assumed to be MAX_PORTS * MAX_PORT_DATA long
|
// raw data for each input port, assumed to be MAX_PORTS * MAX_PORT_DATA long
|
||||||
uint8_t* InputPortData;
|
uint8_t* InputPortData;
|
||||||
int64_t FrontendTime;
|
int64_t FrontendTime;
|
||||||
|
@ -139,31 +141,80 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo& frame)
|
||||||
int h = EES->DisplayRect.h;
|
int h = EES->DisplayRect.h;
|
||||||
int lineStart = EES->DisplayRect.y;
|
int lineStart = EES->DisplayRect.y;
|
||||||
int lineEnd = lineStart + h;
|
int lineEnd = lineStart + h;
|
||||||
|
|
||||||
auto multiWidth = EES->LineWidths[0] != -1;
|
auto multiWidth = EES->LineWidths[0] != -1;
|
||||||
int w;
|
|
||||||
if (multiWidth)
|
int srcp = Game->fb_width;
|
||||||
|
uint32_t* src = pixels + EES->DisplayRect.x + EES->DisplayRect.y * srcp;
|
||||||
|
uint32_t* dst = frame.VideoBuffer;
|
||||||
|
|
||||||
|
if (!frame.RenderConstantSize || !multiWidth && Game->lcm_width == EES->DisplayRect.w && Game->lcm_height == h)
|
||||||
{
|
{
|
||||||
w = 0;
|
// simple non-resizing blitter
|
||||||
|
// TODO: What does this do with true multiwidth? Probably not anything good
|
||||||
|
|
||||||
|
int w;
|
||||||
|
if (multiWidth)
|
||||||
|
{
|
||||||
|
w = 0;
|
||||||
|
for (int line = lineStart; line < lineEnd; line++)
|
||||||
|
w = std::max(w, EES->LineWidths[line]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
w = EES->DisplayRect.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.Width = w;
|
||||||
|
frame.Height = h;
|
||||||
|
int dstp = w;
|
||||||
|
|
||||||
for (int line = lineStart; line < lineEnd; line++)
|
for (int line = lineStart; line < lineEnd; line++)
|
||||||
w = std::max(w, EES->LineWidths[line]);
|
{
|
||||||
|
memcpy(dst, src, (multiWidth ? EES->LineWidths[line] : w) * sizeof(uint32_t));
|
||||||
|
src += srcp;
|
||||||
|
dst += dstp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
w = EES->DisplayRect.w;
|
// resize to lcm_width * lcm_height
|
||||||
}
|
|
||||||
|
|
||||||
frame.Width = w;
|
frame.Width = Game->lcm_width;
|
||||||
frame.Height = h;
|
frame.Height = Game->lcm_height;
|
||||||
int srcp = Game->fb_width;
|
int dstp = frame.Width;
|
||||||
int dstp = w;
|
|
||||||
uint32_t* src = pixels + EES->DisplayRect.x + EES->DisplayRect.y * srcp;
|
int hf = Game->lcm_height / h;
|
||||||
uint32_t* dst = frame.VideoBuffer;
|
for (int line = lineStart; line < lineEnd; line++)
|
||||||
for (int line = lineStart; line < lineEnd; line++)
|
{
|
||||||
{
|
int w = multiWidth ? EES->LineWidths[line] : EES->DisplayRect.w;
|
||||||
memcpy(dst, src, (multiWidth ? EES->LineWidths[line] : w) * sizeof(uint32_t));
|
auto srcNext = src + srcp;
|
||||||
src += srcp;
|
if (frame.Width == w)
|
||||||
dst += dstp;
|
{
|
||||||
|
memcpy(dst, src, w * sizeof(uint32_t));
|
||||||
|
dst += dstp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// stretch horizontal
|
||||||
|
int wf = Game->lcm_width / w;
|
||||||
|
auto dstNext = dst + dstp;
|
||||||
|
for (int x = 0; x < w; x++)
|
||||||
|
{
|
||||||
|
for (int n = 0; n < wf; n++)
|
||||||
|
*dst++ = *src;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
while (dst < dstNext) // 1024 % 3 == 1, not quite "lcm"
|
||||||
|
*dst++ = src[-1];
|
||||||
|
}
|
||||||
|
src = srcNext;
|
||||||
|
for (int y = 1; y < hf; y++)
|
||||||
|
{
|
||||||
|
// stretch vertical
|
||||||
|
memcpy(dst, dst - dstp, dstp * sizeof(uint32_t));
|
||||||
|
dst += dstp;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,6 +227,8 @@ struct SystemInfo
|
||||||
int32_t NominalHeight;
|
int32_t NominalHeight;
|
||||||
int32_t VideoSystem;
|
int32_t VideoSystem;
|
||||||
int32_t FpsFixed;
|
int32_t FpsFixed;
|
||||||
|
int32_t LcmWidth;
|
||||||
|
int32_t LcmHeight;
|
||||||
};
|
};
|
||||||
SystemInfo SI;
|
SystemInfo SI;
|
||||||
|
|
||||||
|
@ -187,6 +240,8 @@ ECL_EXPORT SystemInfo* GetSystemInfo()
|
||||||
SI.NominalHeight = Game->nominal_height;
|
SI.NominalHeight = Game->nominal_height;
|
||||||
SI.VideoSystem = Game->VideoSystem;
|
SI.VideoSystem = Game->VideoSystem;
|
||||||
SI.FpsFixed = Game->fps;
|
SI.FpsFixed = Game->fps;
|
||||||
|
SI.LcmWidth = Game->lcm_width;
|
||||||
|
SI.LcmHeight = Game->lcm_height;
|
||||||
return &SI;
|
return &SI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue