From 391160ebf962ebc973ffa085d7f636fb4f137bc2 Mon Sep 17 00:00:00 2001 From: nattthebear Date: Mon, 29 May 2017 13:50:40 -0400 Subject: [PATCH] vboyEE: settings and syncsettings --- BizHawk.Client.EmuHawk/MainForm.Designer.cs | 76 ++++++---- BizHawk.Client.EmuHawk/MainForm.cs | 9 ++ .../BizHawk.Emulation.Cores.csproj | 1 + .../Consoles/Nintendo/VB/LibVirtualBoyee.cs | 45 +++++- .../Consoles/Nintendo/VB/VirtualBoyee.cs | 138 +++++++++++++++++- output64/dll/vb.wbx | Bin 96270 -> 95246 bytes waterbox/vb/vb.cpp | 54 ++++--- 7 files changed, 272 insertions(+), 51 deletions(-) diff --git a/BizHawk.Client.EmuHawk/MainForm.Designer.cs b/BizHawk.Client.EmuHawk/MainForm.Designer.cs index 31c1a0b0cb..61cca7e7df 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Designer.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Designer.cs @@ -357,6 +357,10 @@ this.C64SettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.IntvSubMenu = new System.Windows.Forms.ToolStripMenuItem(); this.IntVControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.sNESToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.preferencesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.virtualBoyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.preferencesToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.HelpSubMenu = new System.Windows.Forms.ToolStripMenuItem(); this.OnlineHelpMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.ForumsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -436,8 +440,6 @@ this.ShowMenuContextMenuSeparator = new System.Windows.Forms.ToolStripSeparator(); this.ShowMenuContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.timerMouseIdle = new System.Windows.Forms.Timer(this.components); - this.sNESToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.preferencesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.MainformMenu.SuspendLayout(); this.MainStatusBar.SuspendLayout(); this.MainFormContextMenu.SuspendLayout(); @@ -470,8 +472,9 @@ this.AppleSubMenu, this.C64SubMenu, this.IntvSubMenu, - this.HelpSubMenu, - this.sNESToolStripMenuItem}); + this.sNESToolStripMenuItem, + this.virtualBoyToolStripMenuItem, + this.HelpSubMenu}); this.MainformMenu.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.Flow; this.MainformMenu.Location = new System.Drawing.Point(0, 0); this.MainformMenu.Name = "MainformMenu"; @@ -2720,7 +2723,7 @@ this.GBAmGBAMenuItem, this.GBAVBANextMenuItem}); this.GBACoreSelectionSubMenu.Name = "GBACoreSelectionSubMenu"; - this.GBACoreSelectionSubMenu.Size = new System.Drawing.Size(152, 22); + this.GBACoreSelectionSubMenu.Size = new System.Drawing.Size(129, 22); this.GBACoreSelectionSubMenu.Text = "&Core"; this.GBACoreSelectionSubMenu.DropDownOpened += new System.EventHandler(this.GBACoreSelectionSubMenu_DropDownOpened); // @@ -2741,19 +2744,19 @@ // GBAcoresettingsToolStripMenuItem1 // this.GBAcoresettingsToolStripMenuItem1.Name = "GBAcoresettingsToolStripMenuItem1"; - this.GBAcoresettingsToolStripMenuItem1.Size = new System.Drawing.Size(152, 22); + this.GBAcoresettingsToolStripMenuItem1.Size = new System.Drawing.Size(129, 22); this.GBAcoresettingsToolStripMenuItem1.Text = "&Settings..."; this.GBAcoresettingsToolStripMenuItem1.Click += new System.EventHandler(this.GBAcoresettingsToolStripMenuItem1_Click); // // toolStripSeparator33 // this.toolStripSeparator33.Name = "toolStripSeparator33"; - this.toolStripSeparator33.Size = new System.Drawing.Size(149, 6); + this.toolStripSeparator33.Size = new System.Drawing.Size(126, 6); // // GbaGpuViewerMenuItem // this.GbaGpuViewerMenuItem.Name = "GbaGpuViewerMenuItem"; - this.GbaGpuViewerMenuItem.Size = new System.Drawing.Size(152, 22); + this.GbaGpuViewerMenuItem.Size = new System.Drawing.Size(129, 22); this.GbaGpuViewerMenuItem.Text = "GPU Viewer"; this.GbaGpuViewerMenuItem.Click += new System.EventHandler(this.GbaGpuViewerMenuItem_Click); // @@ -3025,7 +3028,7 @@ // SaturnPreferencesMenuItem // this.SaturnPreferencesMenuItem.Name = "SaturnPreferencesMenuItem"; - this.SaturnPreferencesMenuItem.Size = new System.Drawing.Size(152, 22); + this.SaturnPreferencesMenuItem.Size = new System.Drawing.Size(144, 22); this.SaturnPreferencesMenuItem.Text = "Preferences..."; this.SaturnPreferencesMenuItem.Click += new System.EventHandler(this.SaturnPreferencesMenuItem_Click); // @@ -3174,6 +3177,36 @@ this.IntVControllerSettingsMenuItem.Text = "Controller Settings..."; this.IntVControllerSettingsMenuItem.Click += new System.EventHandler(this.IntVControllerSettingsMenuItem_Click); // + // sNESToolStripMenuItem + // + this.sNESToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.preferencesToolStripMenuItem}); + this.sNESToolStripMenuItem.Name = "sNESToolStripMenuItem"; + this.sNESToolStripMenuItem.Size = new System.Drawing.Size(44, 17); + this.sNESToolStripMenuItem.Text = "&SNES"; + // + // preferencesToolStripMenuItem + // + this.preferencesToolStripMenuItem.Name = "preferencesToolStripMenuItem"; + this.preferencesToolStripMenuItem.Size = new System.Drawing.Size(144, 22); + this.preferencesToolStripMenuItem.Text = "Preferences..."; + this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.preferencesToolStripMenuItem_Click); + // + // virtualBoyToolStripMenuItem + // + this.virtualBoyToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.preferencesToolStripMenuItem1}); + this.virtualBoyToolStripMenuItem.Name = "virtualBoyToolStripMenuItem"; + this.virtualBoyToolStripMenuItem.Size = new System.Drawing.Size(67, 17); + this.virtualBoyToolStripMenuItem.Text = "&VirtualBoy"; + // + // preferencesToolStripMenuItem1 + // + this.preferencesToolStripMenuItem1.Name = "preferencesToolStripMenuItem1"; + this.preferencesToolStripMenuItem1.Size = new System.Drawing.Size(152, 22); + this.preferencesToolStripMenuItem1.Text = "Preferences..."; + this.preferencesToolStripMenuItem1.Click += new System.EventHandler(this.preferencesToolStripMenuItem1_Click); + // // HelpSubMenu // this.HelpSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -3190,7 +3223,7 @@ // this.OnlineHelpMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Help; this.OnlineHelpMenuItem.Name = "OnlineHelpMenuItem"; - this.OnlineHelpMenuItem.Size = new System.Drawing.Size(152, 22); + this.OnlineHelpMenuItem.Size = new System.Drawing.Size(140, 22); this.OnlineHelpMenuItem.Text = "&Online Help..."; this.OnlineHelpMenuItem.Click += new System.EventHandler(this.OnlineHelpMenuItem_Click); // @@ -3198,7 +3231,7 @@ // this.ForumsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.TAStudio; this.ForumsMenuItem.Name = "ForumsMenuItem"; - this.ForumsMenuItem.Size = new System.Drawing.Size(152, 22); + this.ForumsMenuItem.Size = new System.Drawing.Size(140, 22); this.ForumsMenuItem.Text = "Forums..."; this.ForumsMenuItem.Click += new System.EventHandler(this.ForumsMenuItem_Click); // @@ -3206,7 +3239,7 @@ // this.FeaturesMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.kitchensink; this.FeaturesMenuItem.Name = "FeaturesMenuItem"; - this.FeaturesMenuItem.Size = new System.Drawing.Size(152, 22); + this.FeaturesMenuItem.Size = new System.Drawing.Size(140, 22); this.FeaturesMenuItem.Text = "&Features"; this.FeaturesMenuItem.Click += new System.EventHandler(this.FeaturesMenuItem_Click); // @@ -3214,7 +3247,7 @@ // this.AboutMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.CorpHawkSmall; this.AboutMenuItem.Name = "AboutMenuItem"; - this.AboutMenuItem.Size = new System.Drawing.Size(152, 22); + this.AboutMenuItem.Size = new System.Drawing.Size(140, 22); this.AboutMenuItem.Text = "&About"; this.AboutMenuItem.Click += new System.EventHandler(this.AboutMenuItem_Click); // @@ -3863,21 +3896,6 @@ this.timerMouseIdle.Interval = 2000; this.timerMouseIdle.Tick += new System.EventHandler(this.timerMouseIdle_Tick); // - // sNESToolStripMenuItem - // - this.sNESToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.preferencesToolStripMenuItem}); - this.sNESToolStripMenuItem.Name = "sNESToolStripMenuItem"; - this.sNESToolStripMenuItem.Size = new System.Drawing.Size(44, 17); - this.sNESToolStripMenuItem.Text = "&SNES"; - // - // preferencesToolStripMenuItem - // - this.preferencesToolStripMenuItem.Name = "preferencesToolStripMenuItem"; - this.preferencesToolStripMenuItem.Size = new System.Drawing.Size(152, 22); - this.preferencesToolStripMenuItem.Text = "Preferences..."; - this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.preferencesToolStripMenuItem_Click); - // // MainForm // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; @@ -4327,5 +4345,7 @@ private System.Windows.Forms.ToolStripSeparator toolStripSeparator36; private System.Windows.Forms.ToolStripMenuItem sNESToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem preferencesToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem virtualBoyToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem preferencesToolStripMenuItem1; } } diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 49ac649b77..6254823ef4 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -1676,6 +1676,7 @@ namespace BizHawk.Client.EmuHawk C64SubMenu.Visible = false; IntvSubMenu.Visible = false; sNESToolStripMenuItem.Visible = false; + virtualBoyToolStripMenuItem.Visible = false; switch (system) { @@ -1761,6 +1762,9 @@ namespace BizHawk.Client.EmuHawk case "INTV": IntvSubMenu.Visible = true; break; + case "VB": + virtualBoyToolStripMenuItem.Visible = true; + break; } } @@ -4275,6 +4279,11 @@ namespace BizHawk.Client.EmuHawk GenericCoreConfig.DoDialog(this, "Snes9x settings"); } + private void preferencesToolStripMenuItem1_Click(object sender, EventArgs e) + { + GenericCoreConfig.DoDialog(this, "VirtualBoy Settings"); + } + private void CreateMultigameFileMenuItem_Click(object sender, EventArgs e) { GlobalWin.Tools.Load(); diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index f84c59f64e..236ff7cce9 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -118,6 +118,7 @@ ..\References\PeNet.dll + 3.5 diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/LibVirtualBoyee.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/LibVirtualBoyee.cs index d41b77ec6e..5a5b3d9341 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/LibVirtualBoyee.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/LibVirtualBoyee.cs @@ -1,6 +1,7 @@ using BizHawk.Common.BizInvoke; using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -87,11 +88,53 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB R = 0x4 } + [StructLayout(LayoutKind.Sequential)] + public class NativeSettings + { + public int InstantReadHack; + public int DisableParallax; + public int ThreeDeeMode; + public int SwapViews; + public int AnaglyphPreset; + public int AnaglyphCustomLeftColor; + public int AnaglyphCustomRightColor; + public int NonAnaglyphColor; + public int LedOnScale; + public int InterlacePrescale; + public int SideBySideSeparation; + + private static int ConvertColor(Color c) + { + var v = c.ToArgb(); + return v & 0xff00 + | v << 16 & 0xff0000 + | v >> 16 & 0xff; + } + + public static NativeSettings FromFrontendSettings(VirtualBoyee.Settings s, VirtualBoyee.SyncSettings ss) + { + return new NativeSettings + { + InstantReadHack = ss.InstantReadHack ? 1 : 0, + DisableParallax = ss.DisableParallax ? 1 : 0, + ThreeDeeMode = (int)s.ThreeDeeMode, + SwapViews = s.SwapViews ? 1 : 0, + AnaglyphPreset = (int)s.AnaglyphPreset, + AnaglyphCustomLeftColor = ConvertColor(s.AnaglyphCustomLeftColor), + AnaglyphCustomRightColor = ConvertColor(s.AnaglyphCustomRightColor), + NonAnaglyphColor = ConvertColor(s.NonAnaglyphColor), + LedOnScale = s.LedOnScale, + InterlacePrescale = s.InterlacePrescale, + SideBySideSeparation = s.SideBySideSeparation + }; + } + } + [UnmanagedFunctionPointer(CC)] public delegate void InputCallback(); [BizImport(CC)] - public abstract bool Load(byte[] rom, int length); + public abstract bool Load(byte[] rom, int length, [In]NativeSettings settings); [BizImport(CC)] public abstract void GetMemoryArea(MemoryArea which, ref IntPtr ptr, ref int size); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs index 10a3a21d6b..41cbdcf5be 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs @@ -5,6 +5,9 @@ using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Waterbox; using System; using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Drawing; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -16,17 +19,21 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB [CoreAttributes("Virtual Boyee", "???", true, false, "0.9.44.1", "https://mednafen.github.io/releases/", false)] public class VirtualBoyee : IEmulator, IVideoProvider, ISoundProvider, IStatable, - IInputPollable, ISaveRam + IInputPollable, ISaveRam, ISettable { private PeRunner _exe; private LibVirtualBoyee _boyee; [CoreConstructor("VB")] - public VirtualBoyee(CoreComm comm, byte[] rom) + public VirtualBoyee(CoreComm comm, byte[] rom, Settings settings, SyncSettings syncSettings) { ServiceProvider = new BasicServiceProvider(this); CoreComm = comm; + _settings = settings ?? new Settings(); + _syncSettings = syncSettings ?? new SyncSettings(); + var nativeSettings = LibVirtualBoyee.NativeSettings.FromFrontendSettings(_settings, _syncSettings); + _exe = new PeRunner(new PeRunnerOptions { Path = comm.CoreFileProvider.DllPath(), @@ -39,7 +46,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB _boyee = BizInvoker.GetInvoker(_exe, _exe); - if (!_boyee.Load(rom, rom.Length)) + if (!_boyee.Load(rom, rom.Length, nativeSettings)) { throw new InvalidOperationException("Core rejected the rom"); } @@ -48,6 +55,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB _inputCallback = InputCallbacks.Call; InitMemoryDomains(); + InitSaveram(); } private bool _disposed = false; @@ -288,6 +296,130 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB (ServiceProvider as BasicServiceProvider).Register(new MemoryDomainList(domains)); } + #endregion + + #region ISettable + + public class SyncSettings + { + [DefaultValue(false)] + public bool InstantReadHack { get; set; } + [DefaultValue(false)] + public bool DisableParallax { get; set; } + + public SyncSettings Clone() + { + return (SyncSettings)MemberwiseClone(); + } + + public static bool NeedsReboot(SyncSettings x, SyncSettings y) + { + return !DeepEquality.DeepEquals(x, y); + } + + public SyncSettings() + { + SettingsUtil.SetDefaultValues(this); + } + } + + public class Settings + { + public enum ThreeDeeModes : int + { + Anaglyph = 0, + CyberScope = 1, + SideBySide = 2, + //OverUnder, + VerticalInterlaced = 4, + HorizontalInterlaced = 5 + } + + [DefaultValue(ThreeDeeModes.Anaglyph)] + public ThreeDeeModes ThreeDeeMode { get; set; } + + [DefaultValue(false)] + public bool SwapViews { get; set; } + + public enum AnaglyphPresets : int + { + Custom, + RedBlue, + RedCyan, + RedElectricCyan, + RedGreen, + GreenMagneto, + YellowBlue + } + + [DefaultValue(AnaglyphPresets.RedBlue)] + public AnaglyphPresets AnaglyphPreset { get; set; } + + [DefaultValue(typeof(Color), "Green")] + public Color AnaglyphCustomLeftColor { get; set; } + [DefaultValue(typeof(Color), "Purple")] + public Color AnaglyphCustomRightColor { get; set; } + + [DefaultValue(typeof(Color), "White")] + public Color NonAnaglyphColor { get; set; } + + [DefaultValue(1750)] + [Range(1000, 2000)] + public int LedOnScale { get; set; } + + [DefaultValue(2)] + [Range(1, 10)] + public int InterlacePrescale { get; set; } + + [DefaultValue(0)] + [Range(0, 1024)] + public int SideBySideSeparation { get; set; } + + public Settings Clone() + { + return (Settings)MemberwiseClone(); + } + + public static bool NeedsReboot(Settings x, Settings y) + { + return !DeepEquality.DeepEquals(x, y); + } + + public Settings() + { + SettingsUtil.SetDefaultValues(this); + } + } + + private Settings _settings; + private SyncSettings _syncSettings; + + public Settings GetSettings() + { + return _settings.Clone(); + } + + public SyncSettings GetSyncSettings() + { + return _syncSettings.Clone(); + } + + public bool PutSettings(Settings o) + { + var ret = Settings.NeedsReboot(_settings, o); + _settings = o; + return ret; + } + + public bool PutSyncSettings(SyncSettings o) + { + var ret = SyncSettings.NeedsReboot(_syncSettings, o); + _syncSettings = o; + return ret; + } + + + #endregion #region ISaveRam diff --git a/output64/dll/vb.wbx b/output64/dll/vb.wbx index 34b3f7d41371f9b49ba21502b2753529d65a9f69..c0b40a17fd43cf464686dbc553b2523d4d049f1e 100644 GIT binary patch delta 19995 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 AGynhq delta 21376 zcmc(H3s@CZ_xJ39K~N3@$}trY)PtfVf_X#5IEs2mH1d|W6vRlnX$Gcd9TZScr=!@Y z)0<{m)@x;D9TU8E0ONp{#7k*vie|;}ig!z8zTcV|l(*NO|J(OH-~T<&vu3Tm*4k^W zz4qQSd(R$NR4pv35eghZGZ{y}8ZMe|#PiL$E=yKD(r}u{ao!wP6w5C;7Tqa9e7wT^&`8zn zbSWAoGE0HZkVbiZ6*Y}<_CSkWFcHDo_WKoE?8g3Pkpr(FmvLrWxy1&aa5zDF#JdMe zke>7I#!{SXywh38aL9|IVawt$`VVD5h894I@#ntIFrTKZ!*<4rj$gWQoZZ+5bleZ3 zqm)WQD=L+Vj(4eKh}rI((BMlyzSD=!prB}f*29?)n$P%GWT(5;G(Q&O>>2r?AOGlX z=gHWH0zcg9JlFjWW8qSD&p|9iiivB^LY$Aqg?aG@XGzcXS=_bFZ{%^#0>;^d3|u{f zcPWbPa&-$2$Jt73!X)B#(0D&s!4py!NYU}l*h9`i@p)eSOWDr73654>rdwbq%arQz zY*!SEV}vQyV*9cB{8*iPu#Riasp3fT)Y4zrBwF0BU%2LXM56C!UO*;BwsL=ytu^V_BLdDR#tcOEx{6 zTjgaFc7SI|FHJ)30>w?j&nTKfceM*kLFT(=`bP<~LD_^nT;oDX-z`kWm44!)9U$UD z$%nXT7-+jNhxCqwiHlxFvBQxLp>KlGA#?_=7JKO8`DANMnq*Ax`!HCPaF6$0MJd3T zzH^h~k{yO)cc{(p!#)~&7d*w7drGpV8`&voS-P3sln$rI8&#zbR3)Q)L)G1LL+UU& z#Cn^m&xUuH+@?tm0V&20ssa$8Un&JCE_T!^3cT%7)nC=r9h&+#s(O~Hesm%RZyI#P zutYVyf2b8^X%)t66$mND{-_Wa%5R=1eLJ~xh^nT~);-tM0FMGG#;Yft;?sfN{9Vb} zI&*^$|J*?5!Kv?fvvbZDv)<&{&(7O3dVBLey`4Q@{Y2={pHjQRhep<7&~Zn_MYE_R zyhNoV;-cYHGUWDmHkv!vi{B6{Ey}yW7sW{P^W)f2$(28d9g=+Kw_%5zQS-a7uHURA zQ_bV4AG~n&Ec+dk^~dT$3^JOmN+0lE)_5=Dc3~6l_K}t>XvPjmpDgIbkB)Z!x*(8+ z{m=?##+#-k+85F2^~^u6P1$J{O#Gx+$!H7Xt6Ms|+a~Z04pFQBxmj9af1DrIQ95sr zL@>rT+xYqK=D0)*w@AgPeBtcBEWJVKULS5izRR{-++;`xon&WX-urNnXgBuWE0wM^ zu_03R$`4qw^ya%qy6pDh%v-Dw??}K%7|`LUXE=H)L+vWN@D9X@c46ydjLWU!_utBi z&)Mx<26G4jb#!;|gCHQT6_hBvlJJ3kHQbGAvpei~si_Yt^c_8s`I_QsUX z{oPw!piY+bBgu{zdn7v|CiajzuYZ`|-&=ZWeINd2FKNa4u`PP^7P#D>y^`6_c@^26 z%x<+YFp}F#5(rAZDY2^Fs|q(z4uvU!$Bx!h*lxK zm$d)0x2zvOOphwzeV{~J#Cvf9HzfUxt~u^Cr`=w}aJZ8MV09=y(G zB$++9$Yv}c!Z;xY!`8S^)myrnp0YOM>m*sajtcg?B8~SVcsAjATrIiM>CaylhxJ4{ z#r#4v$S!p6DNX)jV8?z z;KoiREAXZ;sjHOWG`1KF35FDM;tK-d4SWsAW_+)+G}YO!^{127(umHCJ7>)($i3yA zH8}T{Am*3cRup@v>k;XIvyJubM=-YBi6&DOYzeePqK8MgMD*Vpsx4)5DT`zNf_=e|=E^OzpOPpJ+o*82mqVuHTr*_~RctuY4Wm zWpxN0{)v^qX-upJW?QAXxVqWUbnl#G=2EJ}FnTh73A1A10dbReU}-_D>uRa3vbZ`h z_f~@${bF6EZH+d_p*Ee=NGH~Hqr@xwh$r?1jw`_P{|N|UU6%Zcteu*fpwjy{3nAGd zRD2}mpN)tp`H1?~J12>`%;dZ7ZX%4C>aPY!_T@DlSrh5>+2(xfOVZu5&7Ns+sSydW zvQnL6LV7MX;!1%}>bP9T#X8=i;zHwgV7sBg=RRD<+|zu68^tUuDkuKZXLzJ!wb}oB z5si`DQ|w?>PW+FbNmW}OvXa&77hrw=S!BHt>gS&Jg4-00(c;gHpn8lVS_hYkg+eef ztN5JwRj|ZmVdY`Wj%1u8co`-!=T~{PvjMQt;WE8805A$O|I4)7iDPCfJwr(NdD>qsq?nyM$9|k2v5-^Xiij~DHsTk7{Q1N zVm_tVE|}N*aO+ss2)pqiP}F(-5n%CI9@FfX=l!|;w{9NAymI6c2eu@P5BQ$mEyKX@H@^)soT3+Qz3#Zo{;MFNl;n7 z>zJ6o+lV~77?xxd*rVWQC*BZ#J=cii#bvHM*FwPro|yl5QwsLy2!v2*EP@!7;wo*z ze&Q_t239Z%b8tf{%UOom2;Hrac%l%W-Js=$mD>!8H6`JKKjKP` za8B3}$l6@=AXl4&K_mtMl{H z0={YYpBr)6DFb3F>_U1dM*9IgW7_;IjVOz4xd2NJx-Te8O}KyK##*>uvuQMhN^8nO z`Aw%K7tqAh(#f*n{2P;`u5J^5FkBkzp2&Nhc5Zd|^A3up)%rlO(0g#U0XL5gPe}oL zPVkk-ofr4K&K^oJ(p@q%vxR_LaK#`;%f{#uG zBC+TWy?T+IX4)BcAYH$lR zUYT&2q;A0pk)|$`qdW01fq9+=4?_$#4r<5b%&}qRMq~so8uU5}g4J1Uk;* z4+dUyoc3W@7G83pdJnS8frwEFbJ1$mT`-l(1b-kas?Lrr6F7}^%MA(iFAyf;kV+)n za5EGN)q=$>tW^ob;TD$MCo^=C)}$|jMvZPNtE^v)x=@Wn$vtnimH<%a8Ru+z`Yvz% z1B&-8;*<$*XlR~>W)rHO(uYGY##Xq6PwtzVtCBF4 zMLHBtrb?6vsf69aFtv!)q+3YT$uc31sOn}gh+OVRSD@W6gub?7l=xCTSueYV*X~hG zYMqCFY0f`sIYz!H&SG-_R%-)?W1P=>8=UI>2Nfl@0^4$^R9~ZrQRqX3!@X!)nL)-G zqj1F=4HFQ?V?2hXO=xh;IjDLI^QC2$L%2RmYQDK+x*37eDyPsp(2~2e=e@PkD~Is( z*fWd6^4~va2rI`5C!?UPu_4qgUdF3;sTQx+(3VgCto{PAh?`vJ-o3wAg6rbDob=J= z-oeko)cwU0ULXiR_LZ)0PUNK>QtvJ8tk3PBWl=3Hix7(E8`{Gc3Q6F4oEqJm=zkKu zNeCx;g+?2RUaZj#iOyB^jeel*hT*UM>vE|#%Kx@pig*pnrLbP{+fh3TwbkX)<0#Q` zsn9#c)3lB`wjPt!F^6oI;UlBW&UlAu1XNb|la}dk`H_(s?D)t6=<*&56B90c)P*#llMmblU&u1;y zqd)GwcxP)&%OWJp_)x+(fhmF*PA8{ES+L}tqV#mjPuM7~! z>?SuCXQ~QgLJb&DmmapdQ6{GuiQ=f;;(~HKLrHBNsfkaOXNZxAcZ}dd8E^ZHBeZ>* zP(;2*TXE(#}g! z{7b{7%apd5Vy#fK%q={nl#+Pld2-p8KHz>DNuzX^bZ4JEuk%ZHXZPM z-=5>t$&d#DCPRkJKLxi4Ea{&6LK^=^L||9&;e9T4Vi-W}zmS&v5zIIKLfY|rQ|s-| zQRkG`LjQTCxu?Vo8^qWiBrX(M1AAsW6$NxtqF>bLMnq52XpZPnpwX-duLfFkZos0L zS3vWlP&kJ|nGp3N=5t0wl@*OR1`Zl=0LXKr)(>?l(n+7Ikw$@gKhjp8tC9MBu10$0 zvwM-=+@I0b@B|skHzcd}4E@R8Gst1a+*4sy;CIpZorwQ9_-G_r_YRDd;%!zQ-MBHf zg?tM(vJS(lXHinB%-AoWz24CQv_<0djvpC`u^{!i-Il*_UP`-tnji4IG~muj@17qh ziWGS_nlEcBjlLVlfBK$Ny1Rk*jhjMK^zr^*4`zA1l@4>n4jWCCa42@zW~u^C6g%XZ zYBb_a6K?#(S!%-imxz_>#sI`xeRbbqy(vKxZ8W85#5PkZ2z5JYNk3|_?X~@Y7x->r z>ls+Z&yrigEaLVGi}hfYC9YJIi(?gwN@l$%MrzU6Zi$g~@kG|e6ImBeWL-Rwb@4>j z#S>W<4-9GXzz)S@nY)vkJ8r_nr_AHcPnjo}C$=fI%)PB3q8T<2!0eTr%`PlolkJ_V z9u45k%J=e2FSaZuVw_q!L@SUa+kDI$ZVP2b%s+>xE4aLvzqE-;d5ifoo5=CrtbfxG zjRP5XPj;p;$zrXTo4YYM(Y>ZKieh%prwtGNK!$^)2Ys@w+X5`>;4lW9B-^5%K&Z%H zQ7bmW+=4cCZWIbW+ylnwaX_%jA#Ix4OrK3P|@;}F(g zR+J?7`~)(l3KmV#YJAWRYVP@??+NBpBEgxab7EaEpQG^>>b#5sd4s@OTk}jgWDP%y zJI{pWvidXc0P-PDfzF9_#U8-0Hake7oa>~&`?BO8$l`6i=DO9Dac+sXIj+`XTdEq$ z>Sw`5l?+(0E#78Y4J!M)WJjJ#SsZVga%g3%)vfkggKVI(U8|hEQ+si2o{JR;SDO`F zXUjad3=Ch-%jkk+*v~-;ZJNxjY=+lC)U`(oXn?JjQqbVujUaBR+D5a( zyF0e$8z94rF^oV;jjxTj8+wrqq^8bJq9Y00-*O8pv&^;P_M$YHu{DXZ!1-E=a78HS zzBqUGvU}~rIZP@Al5C1Z>;5>2huZ!2B->6`%kOLL$w5`bUj&UL+Yvgw)H}msJ8Q9b zO6(oLDc{qqLQ`J}v)HUBuzt1c+7ACN7IuQxn=IR z(DzM_`z3qvy*$_r9AZU3AD&p(!4K+PJH`@O%7F!a(?*#PR-8a(dwfbSdIPDBvovf7 zl*60DAELGR2#E3M97+gpW8H!U6cPcdi^?Oa5Al#5x6tAq&mR#FQlEZhLKEWQ z4pq3%m(66>o)fTwZ+i-J8=EeRE%fcv*+^WEb|R1yd2@^n<$A z)T^kMb`+P)E7XpIYD9@*<`1efRfdrFQ;_=+GMrL75bnQ)2N%RsLx=yV*Wu=SA1j3f z^{Ld(v@7K3C<2QZNpZm;{G?q4kqOUgWaNeNp=zrUfjWk~K?B8OBsfaNqgr)UDyEW+ zDP)8EOd&t1s)7}~)DtA67G0;>9$Ydn-_tlmcF@OZ7eQox2Q8ANm6I0r8uX!nJ;<@p zHRIHvGs~b&iq|1YJwW2!X!vQZ8q#%^_`7h)tVH{#pj%Qs)bppnN~@+z6>7t0s_GMa zhbfvlaSD>7>x)zOf&K$ZyHrJOU}3O|nW&IfLq4F5p&0{X`^dhU$RpronG&EvTNNu5 zNgz%+tLmnZ9u1c1Hv%A@`Yp`eqT)?|)u=c%8Fdk%3xaBN#bqASa|p#c$CL_F7=@XL zKJ8Y9c#c%XOd8MUz9YMo-s#tU=z4>C5L_#+dr5YlxYru08onf>33qM}iGC*L)d094 z!Srj01W}+>y7N7%s~FPXP5Lxkr(aRsTvgrdCebbusRQ-0>g9^+#Y)?$a}^|`9-Ur8 zZY+UBUe^4i-1AeR`bnV*l)9;INN%cbYE(B!J0$|?L;D(%&{yN2o!WT6u38T#xn?|- z#y?U>si1rzgJ?Kq1MQ@dejRgzILHJg0(l_A*T^t9XfL9TvE;fEu#^z<2jKZtCiFe5 z-u`+LQg7E?Kxwz@7*I7eHMluOtJ11x9<6?9A3YR8JAz@)wcy^U9?eBI;JEl*zVy&G zEsF3iNO~KZ-_SD! z=Tu^zk9w#vIR+=rw=ba?>e`8Rw%UTDdel{(ng*fMq_i7un27nq!{x%BSibw)d=(rPG#&sR^;{-2fV*W5FMKkH`LhA<;;a+xq4Dr9?a2p!OBjMVw_a@)-eug0 zQf&y$hN(8@WJ;lNSc&x|pq@-7w-ic~vVG(#i`~>_RuPZ2WB~eP3br&8=a{c0aozfly>t6KKw}^2Q2%MtOs8_?>u|!S@W0CyKz4GiZ*1q*%oCR5mf9Cc5i@3?B_!OUC zVfS8;)ra1Q?v+czSU>*!9@!_Hb$MjzkbC)<3zEyupnNQXdAl$g3=2M1DXwa0DL&o6 z(t+Ma|l9&8}@4a(#P(%4kRb$zXb=>!Y8PO#<+ z^aKkVpx-U>w5%v-^ip~upWFVv%=e3rrjI0^&T_*ow zWR8sQ;n8kX-owLWH+pnYG3s>K-=Un&v^PU0F1CVWH+%`&tj-r41q+{2>ENl{V(d_N z4QO3#Gb{n;=7Eg1#zi0!{dVR4E^6u-Hsh-<`9f0`JzxMtC?*2ggsyZAodCz|2o4a! z$CYXuXPcpwrWUHI8F0;s55Se16>JNQeosz)h&2yB@eS%#Z^u&xpWTACg|hc#$3rYO zWED#JuGe41hV_x19OvcLdtNw(n@zaBO8)U7yvoR=s@bC5IEFM2ygpX_904B^1iOWP zV9^izH=RPFXSTBoolwmE^~;2X-J+N@>e0Dc)_DaKVf1i-Sf%>b=zP46COk7 z@V4IQ4JEg5aYvoqDl5nw3>zfk7m()`=(iZ{+c0rcw=coP=Ud0$MK9kd!)HNX(QNTD zya&FyL&bpnibR{?EfmDX^ueUrc1P*%dbGIB0&tXm2dRl1H$j~ketZBt zEMFmy3t{c7zig#$?dgI)-1dHY2WUWv-MAC%`~%`59Np3c9tpWulio|z4m3Wr0$L7l zq}--*bmKHp(AK4@#b2r0VDU}O;<@$Opu(4lFF|fMrsHZW&+S^CjGpfZs(k1<84nax z=>bvht}{9Dok6hXuA7y3e~uHGrFaq-xP|5K$X#19^Qe>f_Ao)*goR}VC>G=Lb7$D% ziLM(5aCz_LuMmPqy2H@bd{2ybz;*J3h4F8pUYTIsBJXa=!mJa?qL}|F+JM&#C;%lB z!szt7AtaDEYkKZ)%~7)}3c0`eW<3#mASb>(DbX8y^a5Ai2&;k{LSxbv^M)W_m6eC@2$-;H4ORAJ{Cv8p=YR+Jd6zCCCaga^t@u znV2^eMNdEC)&J4rps4S?$Hj*rx$N2SFM-N;;XXYZgvE}xsq|L>_E6_`+1ZYzMl}Z; zQeIU|3`_{nx}Ziu601wOmN198rFd0u<= z96w{5e5pN~%m;0gM@F)qfs41**Gk(azZ=P(=`idpe_w?S_8fYD^0r z_MYW*b1`(;8~Ob!5?v`;b}h`zJnAZp+I%vL1ZrSLJ;j zSvYTaRleMjg;-s)>2NVjI|umy1u^e61dl0SjzXF62(Gx_L=eJHKi2siMVyFy2vq-A z=L5WfR*!Xtk=#7DO7Wt@9R#PJ?sU=lcewr4^yzuAY>#4118>i&e}-~#mU@Qr<1FjjklRy+(gabO>k)M?3F#0>ZHmL^Y^H?K%tW=?f8^=@4Ti7&z2Pp!LsyChEk0 zKMoV0PJK?})W^8>+oGW}$%xHqnR=E>B|n@$6r_Ngf-` zW^|d{omM&CbCVtZ4jLG=5Tw~di@{`8f~8JJ)En$**(iz8`t;7%GT)iKWc~Pt8nJdi z^9=s%U#7bf;S&_V6%;5DHv%<0U&ott{GyH*{RPg@`J;4PSHG^@@b!Cw!aMlBmM!nX zVj6O0iSBb;pt-PD7j}@h;?sZ;fW(a&90n%%^=l0he*_k_S-bLcC=O@ z*!jH%i9bLeFampDg05RMXt%#sA-Hx#gULH;6$0xSe5XJlAJCxvK^O*nv`K@>Wl#ik zDAi!}?plRlBLW~;TA{fzydIhcz(aTVH~@$PXcX1cgWwLGwZl>f|HPGJ>^-G?;<(5-dli z2qq&F1bJvFfoZ!2I}td+2xNJL6_+}L{|#*YZ#b>z)B0a+{k5&=|9a8<@6%RHkvxp_ z(BrkrKLKknFeU<@1bzY#0eA)FTHtwrbU+`JUBG3)6`1?i0gkF#Wfq_gd+)4OnxagY z-~tBZgCP1r%m?v4K3S_=Jz4lw9Q%z~gB4{TU|FCBSq~`+L4{F+wM`X;U`mh%-?mf~ z0z)$mHe;bKnyMG|}MK=88h#)lh@4fC)zFVD)dLC1dE|Zun3JIu%JN%jS(P0 zSt|`5fiA(Ja008M{Dz1LvXMrDy2xKc^aQ71j35IB2y{RK_ zfi@r<&;W3;qoSM!Yy&I?%m6$ENCbof8UStym{J`S| z1KR4C=$g@(A;3X^c{)r3CNS%85jq<|Zv%X%(}e#fSpRN?f73s%2T0n>0xIw=^gN&jG(kS-L%?oeg0FSR z112EZ@4y>@363n)@HQRS@&5yCy=UY`2erqA-B%(q`^wDtxnH9^DE0yUhXmjhF^GWTa(sqs%G6h1bTZDQ7% z-``SSWhL~|D^zIZs%~02ri+HFbcYGCS~)yM!yC3~`qQp!<<&ZNm1+F&n;MQ0bUW8& z)nCr0RfMfvfnMQGji!*Q2{`}DTG?C2iMn1&SB=l<{BXTRHF|xEu2-P*t8~8Wlom*! zUhksHw{qMcy23RbPtgseR%(u_b$+VOZ$9H6Y74@3oTvwULD!q6*UQmyf-dKJtWoQ^ zbUPym!$0TJQ!-f>9MUVC(G4EZ%PG42md;Pm%j0!?N$02Nj$L{=e5>B_c3OjSqBNY^ zS7PL!OWmv~a5uERN$sI4MrznsPgz49zpV#U)m>}Rw|aS}j!W;!-&0#$pqHoVxJ1Wq zUze<^LW<6qskbCY$E$Tdr>DA7FS~S{pa*nbZ|Me|zf{jam0k|i%P~4m&~e}ltKOHo zp=90hh6`Fon(2;By1eESjqmzGPwD3xuGD8oc%fE~;kC@AoYu-IMY_JM;qb3CoX|f| zBT{$jSf4hPPFIpEbamVbScweeXC`c@M;U^E-$Ll4aL!Sb`C*+9Q! z(BXIiGnZ^d%fF3goqRTcm;8|2VhnrTrz;+sqg%?W#;{?bZ-NfTI}-Zpn11w(T@9W; zUbYOEgT}J3HpFTPNC2xhJ)7~H0*C=T-$qfkH`B5tk7ZBr>w3v&$FeqjaBn$a9LwPS z2g)l(fIyFxoH4&Xt4ca?jQCg7cP`P9xbZH=z&zEZ_vY`#fL%xzaW1&1M zl?{_yPGTnB*CzLygfC)N+T}%)kb{E7@|H<#RHt&R`p~iJkAk8Ag2D6ESX?l0A|Mbv zK{m&*^;W3Gld6kx3BX&Q!&msAUBF&4#scU-U}+ti1bQ{_Z2VJ#6wo=q=K-TZ*8ux{ z&T->OA9xe~_sa92UBE5B;<%Zh!-0#P9R4c`<0^sYe2pj9N)&QH1Qnu7NeP%f;x7lC z0z47N)Rmx9fsHuXJwrOcYqoLRHP9P?dzWBn6r%ya!**gUfldV;kB@Xl6AkPHj0f!k zzFm&|gXSvm{MhJRj?13DGB1W*9F68Jb^Dd;NT;26fe4LTgSTP)+&f=&SL(1mg9LB{|;)|GKZ zpi_WPc4J&Q=qljhL-GG_4xx|=9M=m>&sWx&cM}oOQw>t4-wx#3E)=&DN|q0(ktiz6(+|pBQvBhj_&3$t9!2Ia^!&NEQ}QtMo(u|?Ee56_ge`7 diff --git a/waterbox/vb/vb.cpp b/waterbox/vb/vb.cpp index 8e79dc7671..5c8a46fdcf 100644 --- a/waterbox/vb/vb.cpp +++ b/waterbox/vb/vb.cpp @@ -25,6 +25,21 @@ namespace MDFN_IEN_VB { +struct NativeSettings +{ + int InstantReadHack; + int DisableParallax; + int ThreeDeeMode; + int SwapViews; + int AnaglyphPreset; + int AnaglyphCustomLeftColor; + int AnaglyphCustomRightColor; + int NonAnaglyphColor; + int LedOnScale; + int InterlacePrescale; + int SideBySideSeparation; +}; + static void (*input_callback)(); static bool lagged; @@ -40,14 +55,14 @@ enum }; static const uint32 AnaglyphPreset_Colors[][2] = - { - {0, 0}, - {0xFF0000, 0x0000FF}, - {0xFF0000, 0x00B7EB}, - {0xFF0000, 0x00FFFF}, - {0xFF0000, 0x00FF00}, - {0x00FF00, 0xFF00FF}, - {0xFFFF00, 0x0000FF}, +{ + {0, 0}, + {0xFF0000, 0x0000FF}, + {0xFF0000, 0x00B7EB}, + {0xFF0000, 0x00FFFF}, + {0xFF0000, 0x00FF00}, + {0x00FF00, 0xFF00FF}, + {0xFFFF00, 0x0000FF}, }; int32 VB_InDebugPeek; @@ -538,7 +553,7 @@ void VB_ExitLoop(void) using namespace MDFN_IEN_VB; -EXPORT int Load(const uint8 *rom, int length) +EXPORT int Load(const uint8 *rom, int length, const NativeSettings* settings) { const uint64 rom_size = length; V810_Emu_Mode cpu_mode = V810_EMU_MODE_ACCURATE; @@ -648,19 +663,20 @@ EXPORT int Load(const uint8 *rom, int length) VB_VSU = new VSU(); VBINPUT_Init(); - VB3DMode = VB3DMODE_ANAGLYPH; - uint32 prescale = 2; - uint32 sbs_separation = 0; - bool reverse = false; + VB3DMode = settings->ThreeDeeMode; + uint32 prescale = settings->InterlacePrescale; + uint32 sbs_separation = settings->SideBySideSeparation; + bool reverse = settings->SwapViews; VIP_Set3DMode(VB3DMode, reverse, prescale, sbs_separation); - VIP_SetParallaxDisable(false); + VIP_SetParallaxDisable(settings->DisableParallax); { - auto presetColor = ANAGLYPH_PRESET_RED_BLUE; + auto presetColor = settings->AnaglyphPreset; - uint32 lcolor, rcolor; + uint32 lcolor = settings->AnaglyphCustomLeftColor; + uint32 rcolor = settings->AnaglyphCustomRightColor; if (presetColor != ANAGLYPH_PRESET_DISABLED) { @@ -668,12 +684,12 @@ EXPORT int Load(const uint8 *rom, int length) rcolor = AnaglyphPreset_Colors[presetColor][1]; } VIP_SetAnaglyphColors(lcolor, rcolor); - VIP_SetDefaultColor(0xf0f0f0); + VIP_SetDefaultColor(settings->NonAnaglyphColor); } - VBINPUT_SetInstantReadHack(true); + VBINPUT_SetInstantReadHack(settings->InstantReadHack); - VIP_SetLEDOnScale(1.75); + VIP_SetLEDOnScale(settings->LedOnScale / 1000.0); VB_Power();