psx - PAL mode now works (required fixing resolution tweaks and firmware setup). also hook up scanline and overscan control options

This commit is contained in:
zeromus 2014-12-17 01:23:24 +00:00
parent 275c72d0c2
commit 3f15ae4e91
10 changed files with 446 additions and 189 deletions

View File

@ -2017,8 +2017,8 @@ namespace BizHawk.Client.EmuHawk
/// </summary>
public void PutCoreSettings(object o)
{
var settable = new SettingsAdapter(Global.Emulator);
if (settable.HasSettings && settable.PutSettings(o))
var settable = new SettingsAdapter(Global.Emulator);
if (settable.HasSettings && settable.PutSettings(o))
{
FlagNeedsReboot();
}

View File

@ -32,21 +32,33 @@
this.btnCancel = new System.Windows.Forms.Button();
this.btnOk = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.label9 = new System.Windows.Forms.Label();
this.rbTweakedMednafenMode = new System.Windows.Forms.RadioButton();
this.label3 = new System.Windows.Forms.Label();
this.rbDebugMode = new System.Windows.Forms.RadioButton();
this.btnNiceDisplayConfig = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.rbMednafenMode = new System.Windows.Forms.RadioButton();
this.label8 = new System.Windows.Forms.Label();
this.rbPixelPro = new System.Windows.Forms.RadioButton();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.label1 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.rbDebugMode = new System.Windows.Forms.RadioButton();
this.label3 = new System.Windows.Forms.Label();
this.rbTweakedMednafenMode = new System.Windows.Forms.RadioButton();
this.label9 = new System.Windows.Forms.Label();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.label6 = new System.Windows.Forms.Label();
this.PAL_LastLineNumeric = new System.Windows.Forms.NumericUpDown();
this.PAL_FirstLineNumeric = new System.Windows.Forms.NumericUpDown();
this.label5 = new System.Windows.Forms.Label();
this.btnAreaFull = new System.Windows.Forms.Button();
this.label4 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.NTSC_LastLineNumeric = new System.Windows.Forms.NumericUpDown();
this.NTSC_FirstLineNumeric = new System.Windows.Forms.NumericUpDown();
this.checkClipHorizontal = new System.Windows.Forms.CheckBox();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.PAL_LastLineNumeric)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.PAL_FirstLineNumeric)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.NTSC_LastLineNumeric)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.NTSC_FirstLineNumeric)).BeginInit();
this.SuspendLayout();
//
// btnCancel
@ -87,7 +99,48 @@
this.groupBox1.Size = new System.Drawing.Size(474, 256);
this.groupBox1.TabIndex = 6;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Resolution Management";
this.groupBox1.Text = "Resolution Management (sample numbers do not reflect Drawing Area choices)";
//
// label9
//
this.label9.Location = new System.Drawing.Point(255, 132);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(213, 79);
this.label9.TabIndex = 28;
this.label9.Text = "Displays all content at as multiple of 400x300.\r\n • Correct aspect ratio\r\n • Gene" +
"rally enjoyable game presentation\r\n • Detail loss at 1x in fewer cases\r\n • Requi" +
"res certain display configuration:\r\n";
//
// rbTweakedMednafenMode
//
this.rbTweakedMednafenMode.AutoSize = true;
this.rbTweakedMednafenMode.Location = new System.Drawing.Point(246, 116);
this.rbTweakedMednafenMode.Name = "rbTweakedMednafenMode";
this.rbTweakedMednafenMode.Size = new System.Drawing.Size(193, 17);
this.rbTweakedMednafenMode.TabIndex = 27;
this.rbTweakedMednafenMode.TabStop = true;
this.rbTweakedMednafenMode.Text = "Tweaked Mednafen Mode (4:3 AR)";
this.rbTweakedMednafenMode.UseVisualStyleBackColor = true;
//
// label3
//
this.label3.Location = new System.Drawing.Point(246, 39);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(213, 50);
this.label3.TabIndex = 26;
this.label3.Text = "Displays all content unmodified\r\n • Window size will constantly change\r\n • Aspect" +
" ratio is usually wrong";
//
// rbDebugMode
//
this.rbDebugMode.AutoSize = true;
this.rbDebugMode.Location = new System.Drawing.Point(246, 19);
this.rbDebugMode.Name = "rbDebugMode";
this.rbDebugMode.Size = new System.Drawing.Size(134, 17);
this.rbDebugMode.TabIndex = 25;
this.rbDebugMode.TabStop = true;
this.rbDebugMode.Text = "Hardcore Debug Mode";
this.rbDebugMode.UseVisualStyleBackColor = true;
//
// btnNiceDisplayConfig
//
@ -140,89 +193,156 @@
this.rbPixelPro.Text = "Pixel Pro Mode";
this.rbPixelPro.UseVisualStyleBackColor = true;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.label1);
this.groupBox2.Controls.Add(this.label5);
this.groupBox2.Location = new System.Drawing.Point(492, 7);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(211, 143);
this.groupBox2.TabIndex = 26;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Non-Functional Options";
//
// label1
//
this.label1.Location = new System.Drawing.Point(6, 21);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(197, 21);
this.label1.TabIndex = 28;
this.label1.Text = "To think about and discuss";
//
// label5
//
this.label5.Location = new System.Drawing.Point(8, 45);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(197, 21);
this.label5.TabIndex = 27;
this.label5.Text = "(Scanline range selection)";
//
// label7
//
this.label7.Location = new System.Drawing.Point(500, 169);
this.label7.Location = new System.Drawing.Point(500, 192);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(197, 29);
this.label7.TabIndex = 30;
this.label7.Text = "Restart the core to take effect.\r\nSorry, its still in development";
//
// rbDebugMode
// groupBox2
//
this.rbDebugMode.AutoSize = true;
this.rbDebugMode.Location = new System.Drawing.Point(246, 19);
this.rbDebugMode.Name = "rbDebugMode";
this.rbDebugMode.Size = new System.Drawing.Size(134, 17);
this.rbDebugMode.TabIndex = 25;
this.rbDebugMode.TabStop = true;
this.rbDebugMode.Text = "Hardcore Debug Mode";
this.rbDebugMode.UseVisualStyleBackColor = true;
this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox2.Controls.Add(this.label6);
this.groupBox2.Controls.Add(this.PAL_LastLineNumeric);
this.groupBox2.Controls.Add(this.PAL_FirstLineNumeric);
this.groupBox2.Controls.Add(this.label5);
this.groupBox2.Controls.Add(this.btnAreaFull);
this.groupBox2.Controls.Add(this.checkClipHorizontal);
this.groupBox2.Controls.Add(this.label4);
this.groupBox2.Controls.Add(this.label1);
this.groupBox2.Controls.Add(this.NTSC_LastLineNumeric);
this.groupBox2.Controls.Add(this.NTSC_FirstLineNumeric);
this.groupBox2.Location = new System.Drawing.Point(492, 7);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(212, 160);
this.groupBox2.TabIndex = 31;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Drawing Area";
//
// label3
// label6
//
this.label3.Location = new System.Drawing.Point(246, 39);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(213, 50);
this.label3.TabIndex = 26;
this.label3.Text = "Displays all content unmodified\r\n • Window size will constantly change\r\n • Aspect" +
" ratio is usually wrong";
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(131, 22);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(27, 13);
this.label6.TabIndex = 44;
this.label6.Text = "PAL";
//
// rbTweakedMednafenMode
// PAL_LastLineNumeric
//
this.rbTweakedMednafenMode.AutoSize = true;
this.rbTweakedMednafenMode.Location = new System.Drawing.Point(246, 116);
this.rbTweakedMednafenMode.Name = "rbTweakedMednafenMode";
this.rbTweakedMednafenMode.Size = new System.Drawing.Size(193, 17);
this.rbTweakedMednafenMode.TabIndex = 27;
this.rbTweakedMednafenMode.TabStop = true;
this.rbTweakedMednafenMode.Text = "Tweaked Mednafen Mode (4:3 AR)";
this.rbTweakedMednafenMode.UseVisualStyleBackColor = true;
this.PAL_LastLineNumeric.Location = new System.Drawing.Point(124, 67);
this.PAL_LastLineNumeric.Maximum = new decimal(new int[] {
287,
0,
0,
0});
this.PAL_LastLineNumeric.Name = "PAL_LastLineNumeric";
this.PAL_LastLineNumeric.Size = new System.Drawing.Size(47, 20);
this.PAL_LastLineNumeric.TabIndex = 43;
this.PAL_LastLineNumeric.Value = new decimal(new int[] {
128,
0,
0,
0});
//
// label9
// PAL_FirstLineNumeric
//
this.label9.Location = new System.Drawing.Point(255, 132);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(213, 79);
this.label9.TabIndex = 28;
this.label9.Text = "Displays all content at as multiple of 400x300.\r\n • Correct aspect ratio\r\n • Gene" +
"rally enjoyable game presentation\r\n • Detail loss at 1x in fewer cases\r\n • Requi" +
"res certain display configuration:\r\n";
this.PAL_FirstLineNumeric.Location = new System.Drawing.Point(124, 41);
this.PAL_FirstLineNumeric.Maximum = new decimal(new int[] {
287,
0,
0,
0});
this.PAL_FirstLineNumeric.Name = "PAL_FirstLineNumeric";
this.PAL_FirstLineNumeric.Size = new System.Drawing.Size(47, 20);
this.PAL_FirstLineNumeric.TabIndex = 42;
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(62, 22);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(36, 13);
this.label5.TabIndex = 41;
this.label5.Text = "NTSC";
//
// btnAreaFull
//
this.btnAreaFull.Location = new System.Drawing.Point(6, 98);
this.btnAreaFull.Name = "btnAreaFull";
this.btnAreaFull.Size = new System.Drawing.Size(136, 23);
this.btnAreaFull.TabIndex = 40;
this.btnAreaFull.Text = "Full [0,239] and [0,287]";
this.btnAreaFull.UseVisualStyleBackColor = true;
this.btnAreaFull.Click += new System.EventHandler(this.btnAreaFull_Click);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(4, 69);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(49, 13);
this.label4.TabIndex = 24;
this.label4.Text = "Last line:";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(5, 43);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(48, 13);
this.label1.TabIndex = 23;
this.label1.Text = "First line:";
//
// NTSC_LastLineNumeric
//
this.NTSC_LastLineNumeric.Location = new System.Drawing.Point(59, 67);
this.NTSC_LastLineNumeric.Maximum = new decimal(new int[] {
239,
0,
0,
0});
this.NTSC_LastLineNumeric.Name = "NTSC_LastLineNumeric";
this.NTSC_LastLineNumeric.Size = new System.Drawing.Size(47, 20);
this.NTSC_LastLineNumeric.TabIndex = 28;
this.NTSC_LastLineNumeric.Value = new decimal(new int[] {
239,
0,
0,
0});
//
// NTSC_FirstLineNumeric
//
this.NTSC_FirstLineNumeric.Location = new System.Drawing.Point(59, 41);
this.NTSC_FirstLineNumeric.Maximum = new decimal(new int[] {
239,
0,
0,
0});
this.NTSC_FirstLineNumeric.Name = "NTSC_FirstLineNumeric";
this.NTSC_FirstLineNumeric.Size = new System.Drawing.Size(47, 20);
this.NTSC_FirstLineNumeric.TabIndex = 21;
//
// checkClipHorizontal
//
this.checkClipHorizontal.AutoSize = true;
this.checkClipHorizontal.Location = new System.Drawing.Point(7, 127);
this.checkClipHorizontal.Name = "checkClipHorizontal";
this.checkClipHorizontal.Size = new System.Drawing.Size(142, 17);
this.checkClipHorizontal.TabIndex = 30;
this.checkClipHorizontal.Text = "Clip Horizontal Overscan";
this.checkClipHorizontal.UseVisualStyleBackColor = true;
//
// PSXOptions
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(713, 275);
this.Controls.Add(this.label7);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.label7);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOk);
@ -234,6 +354,11 @@
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.PAL_LastLineNumeric)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.PAL_FirstLineNumeric)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.NTSC_LastLineNumeric)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.NTSC_FirstLineNumeric)).EndInit();
this.ResumeLayout(false);
}
@ -248,13 +373,21 @@
private System.Windows.Forms.Label label2;
private System.Windows.Forms.RadioButton rbMednafenMode;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.RadioButton rbDebugMode;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.RadioButton rbTweakedMednafenMode;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.NumericUpDown PAL_LastLineNumeric;
private System.Windows.Forms.NumericUpDown PAL_FirstLineNumeric;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Button btnAreaFull;
private System.Windows.Forms.CheckBox checkClipHorizontal;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.NumericUpDown NTSC_LastLineNumeric;
private System.Windows.Forms.NumericUpDown NTSC_FirstLineNumeric;
}
}

View File

@ -23,6 +23,12 @@ namespace BizHawk.Client.EmuHawk
rbDebugMode.Checked = _settings.ResolutionMode == Octoshock.eResolutionMode.Debug;
rbMednafenMode.Checked = _settings.ResolutionMode == Octoshock.eResolutionMode.Mednafen;
rbTweakedMednafenMode.Checked = _settings.ResolutionMode == Octoshock.eResolutionMode.TweakedMednafen;
checkClipHorizontal.Checked = _settings.ClipHorizontalOverscan;
NTSC_FirstLineNumeric.Value = _settings.ScanlineStart_NTSC;
NTSC_LastLineNumeric.Value = _settings.ScanlineEnd_NTSC;
PAL_FirstLineNumeric.Value = _settings.ScanlineStart_PAL;
PAL_LastLineNumeric.Value = _settings.ScanlineEnd_PAL;
}
Octoshock.Settings _settings;
@ -59,11 +65,28 @@ namespace BizHawk.Client.EmuHawk
if(rbMednafenMode.Checked)_settings.ResolutionMode = Octoshock.eResolutionMode.Mednafen;
if(rbTweakedMednafenMode.Checked)_settings.ResolutionMode = Octoshock.eResolutionMode.TweakedMednafen;
_settings.ClipHorizontalOverscan = checkClipHorizontal.Checked;
_settings.ScanlineStart_NTSC = (int)NTSC_FirstLineNumeric.Value;
_settings.ScanlineEnd_NTSC = (int)NTSC_LastLineNumeric.Value;
_settings.ScanlineStart_PAL = (int)PAL_FirstLineNumeric.Value;
_settings.ScanlineEnd_PAL = (int)PAL_LastLineNumeric.Value;
_settings.Validate();
GlobalWin.MainForm.PutCoreSettings(_settings);
DialogResult = DialogResult.OK;
Close();
}
private void btnAreaFull_Click(object sender, EventArgs e)
{
NTSC_FirstLineNumeric.Value = 0;
NTSC_LastLineNumeric.Value = 239;
PAL_FirstLineNumeric.Value = 0;
PAL_LastLineNumeric.Value = 287;
}
}
}

View File

@ -178,6 +178,9 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
List<DiscInterface> discInterfaces = new List<DiscInterface>();
DiscInterface currentDiscInterface;
OctoshockDll.eRegion SystemRegion;
OctoshockDll.eVidStandard SystemVidStandard;
//note: its annoying that we have to have a disc before constructing this.
//might want to change that later. HOWEVER - we need to definitely have a region, at least
public Octoshock(CoreComm comm, List<DiscSystem.Disc> discs, byte[] exe, object settings, object syncSettings)
@ -194,8 +197,9 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
Attach();
//assume this region for EXE and PSF, maybe not correct though
string firmwareRegion = "U";
OctoshockDll.eRegion region = OctoshockDll.eRegion.NA;
SystemRegion = OctoshockDll.eRegion.NA;
if (discs != null)
{
@ -226,28 +230,37 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
//try to acquire the appropriate firmware
if (discInfo.region == OctoshockDll.eRegion.EU) firmwareRegion = "E";
if (discInfo.region == OctoshockDll.eRegion.JP) firmwareRegion = "J";
SystemRegion = discInfo.region;
}
byte[] firmware = comm.CoreFileProvider.GetFirmware("PSX", "U", true, "A PSX `" + firmwareRegion + "` region bios file is required");
//see http://problemkaputt.de/psx-spx.htm
int CpuClock_n = 44100*768;
int CpuClock_d = 1;
int VidClock_n = CpuClock_n*11;
int VidClock_d = CpuClock_d*7;
if (SystemRegion == OctoshockDll.eRegion.EU)
{
CoreComm.VsyncNum = VidClock_n;
CoreComm.VsyncDen = VidClock_d * 314 * 3406;
SystemVidStandard = OctoshockDll.eVidStandard.PAL;
}
else
{
CoreComm.VsyncNum = VidClock_n;
CoreComm.VsyncDen = VidClock_d * 263 * 3413;
SystemVidStandard = OctoshockDll.eVidStandard.NTSC;
}
//TODO - known bad firmwares are a no-go. we should refuse to boot them. (thats the mednafen policy)
byte[] firmware = comm.CoreFileProvider.GetFirmware("PSX", firmwareRegion, true, "A PSX `" + firmwareRegion + "` region bios file is required");
//create the instance
fixed (byte* pFirmware = firmware)
OctoshockDll.shock_Create(out psx, region, pFirmware);
OctoshockDll.shock_Create(out psx, SystemRegion, pFirmware);
SetMemoryDomains();
//these should track values in octoshock gpu.cpp FillVideoParams
//if (discInfo.region == OctoshockDll.eRegion.EU)
//{
// VirtualWidth = 377; // " Dunno :( "
// VirtualHeight = 288;
//}
//else
//{
// VirtualWidth = 320; // Dunno :(
// VirtualHeight = 240;
//}
//BUT-for now theyre normalized (NOTE: THIS MESSES UP THE ASPECT RATIOS)
//TODO - refactor resolution detection and set this accordingly to the first frame of emulation, or at least what the bios is doing first
VirtualWidth = 800;
VirtualHeight = 480;
@ -356,6 +369,13 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
if (!Controller["Eject"]) OctoshockDll.shock_CloseTray(psx);
var ropts = new OctoshockDll.ShockRenderOptions()
{
scanline_start = SystemVidStandard == OctoshockDll.eVidStandard.NTSC ? _Settings.ScanlineStart_NTSC : _Settings.ScanlineStart_PAL,
scanline_end = SystemVidStandard == OctoshockDll.eVidStandard.NTSC ? _Settings.ScanlineEnd_NTSC : _Settings.ScanlineEnd_PAL,
clipOverscan = _Settings.ClipHorizontalOverscan
};
OctoshockDll.shock_SetRenderOptions(psx, ref ropts);
OctoshockDll.shock_Step(psx, OctoshockDll.eShockStep.Frame);
@ -373,6 +393,10 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
BufferWidth = w;
BufferHeight = h;
int virtual_width = ropts.clipOverscan ? 768 : 800;
int scanline_num = ropts.scanline_end - ropts.scanline_start + 1;
int real_scanline_num = SystemVidStandard == OctoshockDll.eVidStandard.NTSC ? 240 : 288;
switch (_Settings.ResolutionMode)
{
case eResolutionMode.Debug:
@ -380,16 +404,18 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
VirtualHeight = h;
break;
case eResolutionMode.Mednafen:
VirtualWidth = 320;
VirtualHeight = 240;
VirtualWidth = ropts.clipOverscan ? 302 : 320;
VirtualHeight = scanline_num;
break;
case eResolutionMode.PixelPro:
VirtualWidth = 800;
VirtualHeight = 480;
VirtualWidth = virtual_width;
VirtualHeight = scanline_num*2;
break;
case eResolutionMode.TweakedMednafen:
VirtualWidth = 400;
VirtualHeight = 300;
{
VirtualWidth = ropts.clipOverscan ? 378 : 400;
VirtualHeight = (int)(scanline_num * 300.0f / real_scanline_num);
}
break;
}
@ -466,7 +492,8 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
#region ISoundProvider
private short[] sbuff = new short[1454 * 2]; //this is the most ive ever seen.. dont know why
//private short[] sbuff = new short[1454 * 2]; //this is the most ive ever seen.. dont know why. two frames worth i guess
private short[] sbuff = new short[1611 * 2]; //need this for pal
private int sbuffcontains = 0;
public ISoundProvider SoundProvider { get { throw new InvalidOperationException(); } }
@ -683,10 +710,52 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
public class Settings
{
[DisplayName("Resolution Mode")]
[Description("Stuf")]
[Description("Stuff")]
[DefaultValue(eResolutionMode.PixelPro)]
public eResolutionMode ResolutionMode { get; set; }
[DisplayName("ScanlineStart_NTSC")]
[DefaultValue(0)]
public int ScanlineStart_NTSC { get; set; }
[DisplayName("ScanlineEnd_NTSC")]
[DefaultValue(239)]
public int ScanlineEnd_NTSC { get; set; }
[DisplayName("ScanlineStart_PAL")]
[DefaultValue(0)]
public int ScanlineStart_PAL { get; set; }
[DisplayName("ScanlineEnd_PAL")]
[DefaultValue(287)]
public int ScanlineEnd_PAL { get; set; }
[DisplayName("Clip Horizontal Overscan")]
[DefaultValue(false)]
public bool ClipHorizontalOverscan { get; set; }
public void Validate()
{
if (ScanlineStart_NTSC < 0) ScanlineStart_NTSC = 0;
if (ScanlineStart_PAL < 0) ScanlineStart_PAL = 0;
if (ScanlineEnd_NTSC > 239) ScanlineEnd_NTSC = 239;
if (ScanlineEnd_PAL > 287) ScanlineEnd_PAL = 287;
//make sure theyre not in the wrong order
if (ScanlineEnd_NTSC < ScanlineStart_NTSC)
{
int temp = ScanlineEnd_NTSC;
ScanlineEnd_NTSC = ScanlineStart_NTSC;
ScanlineStart_NTSC = temp;
}
if (ScanlineEnd_PAL < ScanlineStart_PAL)
{
int temp = ScanlineEnd_PAL;
ScanlineEnd_PAL = ScanlineStart_PAL;
ScanlineStart_PAL = temp;
}
}
public Settings()
{
SettingsUtil.SetDefaultValues(this);
@ -710,6 +779,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
public bool PutSettings(Settings o)
{
_Settings.Validate();
_Settings = o;
//TODO
//var native = _Settings.GetNativeSettings();

View File

@ -20,6 +20,12 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
NONE = 3 //TODO - whats the difference between unset, and region unknown?
}
public enum eVidStandard : int
{
NTSC = 0,
PAL = 1,
}
public enum eShockStep
{
Frame
@ -110,6 +116,13 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
public void* ptr;
};
[StructLayout(LayoutKind.Sequential)]
public struct ShockRenderOptions
{
public int scanline_start, scanline_end;
public bool clipOverscan;
};
[StructLayout(LayoutKind.Sequential)]
public struct ShockMemcardTransaction
{
@ -189,6 +202,9 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
[DllImport(dd, CallingConvention = cc)]
public static extern int shock_CloseTray(IntPtr psx);
[DllImport(dd, CallingConvention = cc)]
public static extern int shock_SetRenderOptions(IntPtr psx, ref ShockRenderOptions opts);
[DllImport(dd, CallingConvention = cc)]
public static extern int shock_Step(IntPtr psx, eShockStep step);

Binary file not shown.

View File

@ -58,6 +58,9 @@
namespace MDFN_IEN_PSX
{
//static data
uint8 PS_GPU::DitherLUT[4][4][512]; // Y, X, 8-bit source value(256 extra for saturation)
static const int8 dither_table[4][4] =
{
{ -4, 0, -3, 1 },
@ -66,29 +69,48 @@ static const int8 dither_table[4][4] =
{ 3, -1, 2, -2 },
};
PS_GPU::PS_GPU(bool pal_clock_and_tv, int sls, int sle, bool show_h_overscan) : BlitterFIFO(0x20) // 0x10 on actual PS1 GPU, 0x20 here(see comment at top of gpu.h) // 0x10)
void PS_GPU::StaticInitialize()
{
static bool initialized = false;
if(initialized) return;
initialized = true;
for(int y = 0; y < 4; y++)
{
for(int x = 0; x < 4; x++)
{
for(int v = 0; v < 512; v++)
{
int value = v + dither_table[y][x];
value >>= 3;
if(value < 0)
value = 0;
if(value > 0x1F)
value = 0x1F;
DitherLUT[y][x][v] = value;
}
}
}
memcpy(&Commands[0x00], Commands_00_1F, sizeof(Commands_00_1F));
memcpy(&Commands[0x20], Commands_20_3F, sizeof(Commands_20_3F));
memcpy(&Commands[0x40], Commands_40_5F, sizeof(Commands_40_5F));
memcpy(&Commands[0x60], Commands_60_7F, sizeof(Commands_60_7F));
memcpy(&Commands[0x80], Commands_80_FF, sizeof(Commands_80_FF));
}
PS_GPU::PS_GPU(bool pal_clock_and_tv) : BlitterFIFO(0x20) // 0x10 on actual PS1 GPU, 0x20 here(see comment at top of gpu.h) // 0x10)
{
//todo - not thread safe
StaticInitialize();
HardwarePALType = pal_clock_and_tv;
hide_hoverscan = !show_h_overscan;
for(int y = 0; y < 4; y++)
for(int x = 0; x < 4; x++)
for(int v = 0; v < 512; v++)
{
int value = v + dither_table[y][x];
value >>= 3;
if(value < 0)
value = 0;
if(value > 0x1F)
value = 0x1F;
DitherLUT[y][x][v] = value;
}
if(HardwarePALType == false) // NTSC clock
{
GPUClockRatio = 103896; // 65536 * 53693181.818 / (44100 * 768)
@ -100,15 +122,6 @@ PS_GPU::PS_GPU(bool pal_clock_and_tv, int sls, int sle, bool show_h_overscan) :
hmc_to_visible = 560;
}
LineVisFirst = sls;
LineVisLast = sle;
memcpy(&Commands[0x00], Commands_00_1F, sizeof(Commands_00_1F));
memcpy(&Commands[0x20], Commands_20_3F, sizeof(Commands_20_3F));
memcpy(&Commands[0x40], Commands_40_5F, sizeof(Commands_40_5F));
memcpy(&Commands[0x60], Commands_60_7F, sizeof(Commands_60_7F));
memcpy(&Commands[0x80], Commands_80_FF, sizeof(Commands_80_FF));
}
PS_GPU::~PS_GPU()
@ -1551,4 +1564,12 @@ SYNCFUNC(PS_GPU)
}
void PS_GPU::SetRenderOptions(::ShockRenderOptions* opts)
{
hide_hoverscan = !!opts->clipOverscan;
LineVisFirst = opts->scanline_start;
LineVisLast = opts->scanline_end;
}
}

View File

@ -6,6 +6,8 @@
#include "cdrom/SimpleFIFO.h"
#include "git.h"
struct ShockRenderOptions;
namespace MDFN_IEN_PSX
{
@ -39,8 +41,11 @@ class PS_GPU
{
public:
PS_GPU(bool pal_clock_and_tv, int sls, int sle, bool show_h_overscan) MDFN_COLD;
void SetRenderOptions(ShockRenderOptions* opts);
PS_GPU(bool pal_clock_and_tv) MDFN_COLD;
~PS_GPU() MDFN_COLD;
static void StaticInitialize() MDFN_COLD;
template<bool isReader>void SyncState(EW::NewState *ns);
@ -167,7 +172,7 @@ class PS_GPU
uint32 abr;
uint32 TexMode;
uint8 DitherLUT[4][4][512]; // Y, X, 8-bit source value(256 extra for saturation)
static uint8 DitherLUT[4][4][512]; // Y, X, 8-bit source value(256 extra for saturation)
bool LineSkipTest(unsigned y);

View File

@ -33,7 +33,8 @@
#include <stdarg.h>
#include <ctype.h>
#define FB_WIDTH 768
#define FB_HEIGHT 576
//extern MDFNGI EmulatedPSX;
@ -1009,21 +1010,24 @@ using namespace MDFN_IEN_PSX;
struct ShockConfig
{
// multires is a hint that, if set, indicates that the system has fairly programmable video modes(particularly, the ability
// to display multiple horizontal resolutions, such as the PCE, PC-FX, or Genesis). In practice, it will cause the driver
// code to set the linear interpolation on by default. (TRUE for psx)
// lcm_width and lcm_height are the least common multiples of all possible
// resolutions in the frame buffer as specified by DisplayRect/LineWidths(Ex for PCE: widths of 256, 341.333333, 512,
// lcm = 1024)
// nominal_width and nominal_height specify the resolution that Mednafen should display
// the framebuffer image in at 1x scaling, scaled from the dimensions of DisplayRect, and optionally the LineWidths array
// passed through espec to the Emulate() function.
int lcm_width;
int lcm_height;
int nominal_width;
int nominal_height;
//// multires is a hint that, if set, indicates that the system has fairly programmable video modes(particularly, the ability
//// to display multiple horizontal resolutions, such as the PCE, PC-FX, or Genesis). In practice, it will cause the driver
//// code to set the linear interpolation on by default. (TRUE for psx)
//// lcm_width and lcm_height are the least common multiples of all possible
//// resolutions in the frame buffer as specified by DisplayRect/LineWidths(Ex for PCE: widths of 256, 341.333333, 512,
//// lcm = 1024)
//// nominal_width and nominal_height specify the resolution that Mednafen should display
//// the framebuffer image in at 1x scaling, scaled from the dimensions of DisplayRect, and optionally the LineWidths array
//// passed through espec to the Emulate() function.
//int lcm_width;
//int lcm_height;
//int nominal_width;
//int nominal_height;
int fb_width; // Width of the framebuffer(not necessarily width of the image). MDFN_Surface width should be >= this.
int fb_height; // Height of the framebuffer passed to the Emulate() function(not necessarily height of the image)
//last used render options
ShockRenderOptions opts;
} s_ShockConfig;
@ -1221,44 +1225,15 @@ EW_EXPORT s32 shock_Create(void** psx, s32 region, void* firmware512k)
CDC = new PS_CDC();
DMA_Init();
//analyze region to determine display area (visible scanline regions and such)
//currently this can't be changed by the user
//[0,239] for NTSC; [0,287] for PAL
int sls, sle;
if(region == REGION_EU)
{
sls = 0;
sle = 287;
}
else
{
sls = 0;
sle = 239;
}
//these steps can't be done without more information
GPU = new PS_GPU(region == REGION_EU, sls, sle, true);
//fetch video parameters, stash in a simpler format
MDFNGI givp;
GPU->FillVideoParams(&givp);
s_ShockConfig.lcm_width = givp.lcm_width;
s_ShockConfig.lcm_height = givp.lcm_height;
s_ShockConfig.fb_height = givp.fb_height;
//s_ShockConfig.fb_width = givp.fb_width;
s_ShockConfig.fb_width = 800; //we're a bit sloppy right now.. use this to make sure theres adequate room for double-sizing a 400px wide screen
s_ShockConfig.fb_height = givp.fb_height;
s_ShockConfig.nominal_width = givp.nominal_width;
s_ShockConfig.nominal_height = givp.nominal_height;
//givp.fps // TODO
GPU = new PS_GPU(region == REGION_EU);
//setup gpu output surfaces
MDFN_PixelFormat nf(MDFN_COLORSPACE_RGB, 16, 8, 0, 24);
for(int i=0;i<2;i++)
{
VTBuffer[i] = new MDFN_Surface(NULL, s_ShockConfig.fb_width, s_ShockConfig.fb_height, s_ShockConfig.fb_width, nf);
VTLineWidths[i] = (int *)calloc(s_ShockConfig.fb_height, sizeof(int));
VTBuffer[i] = new MDFN_Surface(NULL, FB_WIDTH, FB_HEIGHT, FB_WIDTH, nf);
VTLineWidths[i] = (int *)calloc(FB_HEIGHT, sizeof(int));
}
FIO = new FrontIO();
@ -1385,7 +1360,7 @@ EW_EXPORT s32 shock_Step(void* psx, eShockStep step)
//new frame, hasnt been normalized
s_FramebufferNormalized = false;
s_FramebufferCurrent = 0;
s_FramebufferCurrentWidth = s_ShockConfig.fb_width;
s_FramebufferCurrentWidth = 768;
return SHOCK_OK;
}
@ -1398,6 +1373,8 @@ void NormalizeFramebuffer()
//psxtech says horizontal resolutions can be: 256, 320, 368, 512, 640 pixels
//mednafen will turn those into 2800/{ 10, 8, 5, 4, 7 } -> 280,350,560,700,400
//additionally with the crop options we can cut it down by 160/X -> { 16, 20, 32, 40, 22 } -> { 264, 330, 528, 660, 378 }
//this means our virtual area for doubling is no longer 800 but 756
//heres my strategy:
//try to do the smart thing, try to get aspect ratio near the right value
@ -1419,6 +1396,7 @@ void NormalizeFramebuffer()
int width = VTLineWidths[0][0]; //presently, except for contrived test programs, it is safe to assume this is the same for the entire frame (no known use by games)
int height = espec.DisplayRect.h;
int virtual_width = s_ShockConfig.opts.clipOverscan ? 756 : 800;
int xs=1,ys=1,xm=0;
@ -1435,17 +1413,12 @@ void NormalizeFramebuffer()
//if(width == 700 && height == 480) {}
//II. as the snes 'always double size framebuffer'. I think thats a better idea, and we already have the concept
if(width == 280 && height == 240) xs=ys=2;
if(width == 350 && height == 240) xs=ys=2;
if(width == 400 && height == 240) xs=ys=2;
if(width == 560 && height == 240) ys=2;
if(width == 700 && height == 240) ys=2;
if(width == 280 && height == 480) xs=2;
if(width == 350 && height == 480) xs=2;
if(width == 400 && height == 480) xs=2;
if(width == 560 && height == 480) {}
if(width == 700 && height == 480) {}
xm = (800-width*xs)/2;
if(width <= 400 && height <= 276) xs=ys=2;
if(width > 400 && height <= 276) ys=2;
if(width <= 400 && height > 276) xs=2;
if(width > 400 && height > 276) {}
//TODO - shrink it entirely if cropping
xm = (virtual_width-width*xs)/2;
int curr = 0;
@ -1477,7 +1450,7 @@ void NormalizeFramebuffer()
//2. double the width as needed. but always float it.
//note, theres nothing to be done here if the framebuffer is already wide enough
if(width != 800)
if(width != virtual_width)
{
uint32* src = VTBuffer[curr]->pixels + (s_ShockConfig.fb_width*espec.DisplayRect.y) + espec.DisplayRect.x;
uint32* dst = VTBuffer[curr^1]->pixels;
@ -1510,7 +1483,7 @@ void NormalizeFramebuffer()
}
//patch up the metrics
width = 800; //we floated the content horizontally, so this becomes the new width
width = virtual_width; //we floated the content horizontally, so this becomes the new width
espec.DisplayRect.x = 0;
espec.DisplayRect.y = 0;
VTLineWidths[curr^1][0] = width;
@ -2522,3 +2495,10 @@ EW_EXPORT s32 shock_SetRegister_CPU(void* psx, s32 index, u32 value)
return SHOCK_OK;
}
EW_EXPORT s32 shock_SetRenderOptions(void* pxs, ShockRenderOptions* opts)
{
GPU->SetRenderOptions(opts);
s_ShockConfig.opts = *opts;
return SHOCK_OK;
}

View File

@ -258,6 +258,12 @@ struct ShockFramebufferInfo
void* ptr;
};
struct ShockRenderOptions
{
s32 scanline_start, scanline_end;
bool clipOverscan;
};
struct ShockMemcardTransaction
{
eShockMemcardTransaction transaction;
@ -327,6 +333,9 @@ EW_EXPORT s32 shock_SetDisc(void* psx, ShockDiscRef* disc);
//Closes the disc tray. Returns SHOCK_NOCANDO if already closed.
EW_EXPORT s32 shock_CloseTray(void* psx);
//Sets rendering options for next frame
EW_EXPORT s32 shock_SetRenderOptions(void* psx, ShockRenderOptions* opts);
//Steps emulation by the specified interval
//TODO - think about something. After loadstating, the device input state is probably nonsense.
//Normally we'd set the input before frame advancing. But every frontend might not do that, and we might not be stepping by one frame.