all nyma cores: support constant size framebuffer

this will do lossless integer scaling using mednafen provided screen geometry data
This commit is contained in:
nattthebear 2020-06-08 13:05:17 -04:00
parent ddfd6fd49a
commit b11b50a950
12 changed files with 100 additions and 26 deletions

Binary file not shown.

BIN
output/dll/faust.wbx.gz Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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 },

View File

@ -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 },

View File

@ -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?
};
} }
} }

View File

@ -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)]

View File

@ -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",

View File

@ -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"),
}; };

View File

@ -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;
} }