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>
{
{ "pce_fast.correct_aspect", null },
{ "pce_fast.mouse_sensitivity", null },
{ "pce_fast.disable_softreset", 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.frame_begin_vblank", null },
{ "snes_faust.msu1.resamp_quality", null },
{ "snes_faust.correct_aspect", null },
{ "snes_faust.spex", null },
{ "snes_faust.spex.sound", null },
{ "nyma.rtcinitialtime", null },

View File

@ -51,5 +51,10 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK
throw new InvalidOperationException("Core rejected the saveram");
_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)]
public abstract bool InitCd(int numdisks);
public enum CommandType : int
public enum CommandType : short
{
NONE = 0x00,
RESET = 0x01,
@ -85,6 +85,10 @@ namespace BizHawk.Emulation.Cores.Waterbox
/// </summary>
public CommandType Command;
/// <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
/// </summary>
public byte* InputPortData;
@ -135,6 +139,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
public int NominalHeight;
public VideoSystem VideoSystem;
public int FpsFixed;
public int LcmWidth;
public int LcmHeight;
}
[BizImport(CC, Compatibility = true)]

View File

@ -119,7 +119,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
else
{
// 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);
else
_syncSettings.MednafenValues.TryGetValue(name, out val);
@ -208,7 +208,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
s.AllSettingsByKey.Add(setting.SettingsKey, setting);
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);
}
@ -223,6 +223,15 @@ namespace BizHawk.Emulation.Cores.Waterbox
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
{
Name = "Initial Time",

View File

@ -98,7 +98,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
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;
BufferHeight = info.NominalHeight;
switch (info.VideoSystem)
@ -182,12 +182,13 @@ namespace BizHawk.Emulation.Cores.Waterbox
var ret = new LibNymaCore.FrameInfo
{
SkipRendering = (short)(render ? 0 : 1),
SkipSoundening =(short)(rendersound ? 0 : 1),
SkipSoundening = (short)(rendersound ? 0 : 1),
Command = controller.IsPressed("Power")
? LibNymaCore.CommandType.POWER
: controller.IsPressed("Reset")
? LibNymaCore.CommandType.RESET
: LibNymaCore.CommandType.NONE,
RenderConstantSize = (short)(SettingsQuery("nyma.constantfb") != "0" ? 1 : 0),
InputPortData = (byte*)_frameAdvanceInputLock.AddrOfPinnedObject(),
FrontendTime = GetRtcTime(SettingsQuery("nyma.rtcrealtime") != "0"),
};

View File

@ -104,7 +104,9 @@ struct MyFrameInfo: public FrameInfo
int16_t SkipRendering;
int16_t SkipSoundening;
// 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
uint8_t* InputPortData;
int64_t FrontendTime;
@ -139,31 +141,80 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo& frame)
int h = EES->DisplayRect.h;
int lineStart = EES->DisplayRect.y;
int lineEnd = lineStart + h;
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++)
w = std::max(w, EES->LineWidths[line]);
{
memcpy(dst, src, (multiWidth ? EES->LineWidths[line] : w) * sizeof(uint32_t));
src += srcp;
dst += dstp;
}
}
else
{
w = EES->DisplayRect.w;
}
// resize to lcm_width * lcm_height
frame.Width = w;
frame.Height = h;
int srcp = Game->fb_width;
int dstp = w;
uint32_t* src = pixels + EES->DisplayRect.x + EES->DisplayRect.y * srcp;
uint32_t* dst = frame.VideoBuffer;
for (int line = lineStart; line < lineEnd; line++)
{
memcpy(dst, src, (multiWidth ? EES->LineWidths[line] : w) * sizeof(uint32_t));
src += srcp;
dst += dstp;
frame.Width = Game->lcm_width;
frame.Height = Game->lcm_height;
int dstp = frame.Width;
int hf = Game->lcm_height / h;
for (int line = lineStart; line < lineEnd; line++)
{
int w = multiWidth ? EES->LineWidths[line] : EES->DisplayRect.w;
auto srcNext = src + srcp;
if (frame.Width == w)
{
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 VideoSystem;
int32_t FpsFixed;
int32_t LcmWidth;
int32_t LcmHeight;
};
SystemInfo SI;
@ -187,6 +240,8 @@ ECL_EXPORT SystemInfo* GetSystemInfo()
SI.NominalHeight = Game->nominal_height;
SI.VideoSystem = Game->VideoSystem;
SI.FpsFixed = Game->fps;
SI.LcmWidth = Game->lcm_width;
SI.LcmHeight = Game->lcm_height;
return &SI;
}