psx - improve framebuffer clipping method, add deinterlacer settings, fix some PAR for PAL games; fix bugs in GameExtraPadding handling

This commit is contained in:
zeromus 2015-08-09 11:35:22 -05:00
parent d0f56ac98d
commit 0cd3a82862
10 changed files with 459 additions and 188 deletions

View File

@ -143,6 +143,28 @@ namespace BizHawk.Client.EmuHawk
}
}
System.Windows.Forms.Padding CalculateCompleteContentPadding(bool user, bool source)
{
var padding = new System.Windows.Forms.Padding();
if(user)
padding += GameExtraPadding;
//an experimental feature
if(source)
if (Global.Emulator is BizHawk.Emulation.Cores.Sony.PSX.Octoshock)
{
var psx = Global.Emulator as BizHawk.Emulation.Cores.Sony.PSX.Octoshock;
var core_padding = psx.VideoProvider_Padding;
padding.Left += core_padding.Width / 2;
padding.Right += core_padding.Width - core_padding.Width / 2;
padding.Top += core_padding.Height / 2;
padding.Bottom += core_padding.Height - core_padding.Height / 2;
}
return padding;
}
FilterProgram BuildDefaultChain(Size chain_insize, Size chain_outsize, bool includeOSD)
{
//select user special FX shader chain
@ -183,18 +205,23 @@ namespace BizHawk.Client.EmuHawk
chain.AddFilter(fInput, "input");
//if a non-zero padding is required, add a filter to allow for that
if (GameExtraPadding.Vertical != 0 || GameExtraPadding.Horizontal != 0)
//note, we have two sources of padding right now.. one can come from the videoprovider and one from the user.
//we're combining these now and just using black, for sake of being lean, despite the discussion below:
//keep in mind, the videoprovider design in principle might call for another color.
//we havent really been using this very hard, but users will probably want black there (they could fill it to another color if needed tho)
var padding = CalculateCompleteContentPadding(true,true);
if (padding.Vertical != 0 || padding.Horizontal != 0)
{
//TODO - add another filter just for this, its cumebrsome to use final presentation... I think. but maybe theres enough similarities to justify it.
//TODO - add another filter just for this, its cumbersome to use final presentation... I think. but maybe theres enough similarities to justify it.
Size size = chain_insize;
size.Width += GameExtraPadding.Horizontal;
size.Height += GameExtraPadding.Vertical;
size.Width += padding.Horizontal;
size.Height += padding.Vertical;
Filters.FinalPresentation fPadding = new Filters.FinalPresentation(size);
chain.AddFilter(fPadding, "padding");
fPadding.GuiRenderer = Renderer;
fPadding.GL = GL;
fPadding.Config_PadOnly = true;
fPadding.Padding = GameExtraPadding;
fPadding.Padding = padding;
}
//add lua layer 'emu'
@ -367,6 +394,14 @@ namespace BizHawk.Client.EmuHawk
virtualHeight = Global.Config.DispCustomUserARHeight;
}
var padding = CalculateCompleteContentPadding(true, false);
virtualWidth += padding.Horizontal;
virtualHeight += padding.Vertical;
padding = CalculateCompleteContentPadding(true, true);
bufferWidth += padding.Horizontal;
bufferHeight += padding.Vertical;
//Console.WriteLine("DISPZOOM " + zoom); //test
//old stuff
@ -505,6 +540,10 @@ namespace BizHawk.Client.EmuHawk
}
}
var padding = CalculateCompleteContentPadding(true,false);
vw += padding.Horizontal;
vh += padding.Vertical;
int[] videoBuffer = videoProvider.GetVideoBuffer();
TESTEROO:

View File

@ -217,7 +217,7 @@ namespace BizHawk.Client.EmuHawk.Filters
//TODO - redundant fix
LL = new LetterboxingLogic();
LL.vx += Padding.Left;
LL.vy += Padding.Right;
LL.vy += Padding.Top;
LL.vw = size.Width;
LL.vh = size.Height;
}
@ -250,7 +250,7 @@ namespace BizHawk.Client.EmuHawk.Filters
//TODO - redundant fix
LL = new LetterboxingLogic();
LL.vx += Padding.Left;
LL.vy += Padding.Right;
LL.vy += Padding.Top;
LL.vw = InputSize.Width;
LL.vh = InputSize.Height;
}

View File

@ -1879,7 +1879,7 @@ namespace BizHawk.Client.EmuHawk
var video = Global.Emulator.VideoProvider();
//bool change = false;
Size currVideoSize = new Size(video.BufferWidth,video.BufferHeight);
Size currVirtualSize = new Size(video.VirtualWidth,video.VirtualWidth);
Size currVirtualSize = new Size(video.VirtualWidth,video.VirtualHeight);
if (currVideoSize != _lastVideoSize || currVirtualSize != _lastVirtualSize)
{
_lastVideoSize = currVideoSize;

View File

@ -44,6 +44,10 @@
this.lblPixelPro = new System.Windows.Forms.Label();
this.rbPixelPro = new System.Windows.Forms.RadioButton();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.rbClipNone = new System.Windows.Forms.RadioButton();
this.rbClipToFramebuffer = new System.Windows.Forms.RadioButton();
this.rbClipBasic = new System.Windows.Forms.RadioButton();
this.lblPAL = new System.Windows.Forms.Label();
this.PAL_LastLineNumeric = new System.Windows.Forms.NumericUpDown();
this.PAL_FirstLineNumeric = new System.Windows.Forms.NumericUpDown();
@ -54,25 +58,25 @@
this.NTSC_LastLineNumeric = new System.Windows.Forms.NumericUpDown();
this.NTSC_FirstLineNumeric = new System.Windows.Forms.NumericUpDown();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.rbClipBasic = new System.Windows.Forms.RadioButton();
this.rbClipToFramebuffer = new System.Windows.Forms.RadioButton();
this.rbClipNone = new System.Windows.Forms.RadioButton();
this.label2 = new System.Windows.Forms.Label();
this.rbWeave = new System.Windows.Forms.RadioButton();
this.rbBobOffset = new System.Windows.Forms.RadioButton();
this.rbBob = new System.Windows.Forms.RadioButton();
this.groupBox4 = new System.Windows.Forms.GroupBox();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox3.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.groupBox3.SuspendLayout();
this.groupBox4.SuspendLayout();
this.SuspendLayout();
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(622, 262);
this.btnCancel.Location = new System.Drawing.Point(622, 309);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 3;
@ -82,7 +86,7 @@
// btnOk
//
this.btnOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnOk.Location = new System.Drawing.Point(541, 262);
this.btnOk.Location = new System.Drawing.Point(541, 309);
this.btnOk.Name = "btnOk";
this.btnOk.Size = new System.Drawing.Size(75, 23);
this.btnOk.TabIndex = 2;
@ -104,7 +108,7 @@
this.groupBox1.Controls.Add(this.rbPixelPro);
this.groupBox1.Location = new System.Drawing.Point(12, 7);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(474, 278);
this.groupBox1.Size = new System.Drawing.Size(474, 293);
this.groupBox1.TabIndex = 6;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Resolution Management";
@ -112,7 +116,7 @@
// linkLabel1
//
this.linkLabel1.AutoSize = true;
this.linkLabel1.Location = new System.Drawing.Point(327, 248);
this.linkLabel1.Location = new System.Drawing.Point(326, 254);
this.linkLabel1.Name = "linkLabel1";
this.linkLabel1.Size = new System.Drawing.Size(53, 13);
this.linkLabel1.TabIndex = 29;
@ -163,7 +167,7 @@
// btnNiceDisplayConfig
//
this.btnNiceDisplayConfig.AutoSize = true;
this.btnNiceDisplayConfig.Location = new System.Drawing.Point(146, 238);
this.btnNiceDisplayConfig.Location = new System.Drawing.Point(145, 244);
this.btnNiceDisplayConfig.Name = "btnNiceDisplayConfig";
this.btnNiceDisplayConfig.Size = new System.Drawing.Size(173, 23);
this.btnNiceDisplayConfig.TabIndex = 24;
@ -225,15 +229,68 @@
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, 245);
this.groupBox2.Size = new System.Drawing.Size(212, 239);
this.groupBox2.TabIndex = 31;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Drawing Area";
//
// groupBox3
//
this.groupBox3.Controls.Add(this.rbClipNone);
this.groupBox3.Controls.Add(this.rbClipToFramebuffer);
this.groupBox3.Controls.Add(this.rbClipBasic);
this.groupBox3.Location = new System.Drawing.Point(7, 131);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(197, 88);
this.groupBox3.TabIndex = 46;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Horizontal Overscan Clipping";
//
// rbClipNone
//
this.rbClipNone.AutoSize = true;
this.rbClipNone.Location = new System.Drawing.Point(6, 19);
this.rbClipNone.Name = "rbClipNone";
this.rbClipNone.Size = new System.Drawing.Size(51, 17);
this.rbClipNone.TabIndex = 48;
this.rbClipNone.TabStop = true;
this.rbClipNone.Text = "None";
this.toolTip1.SetToolTip(this.rbClipNone, resources.GetString("rbClipNone.ToolTip"));
this.rbClipNone.UseVisualStyleBackColor = true;
this.rbClipNone.CheckedChanged += new System.EventHandler(this.rbClipNone_CheckedChanged);
//
// rbClipToFramebuffer
//
this.rbClipToFramebuffer.AutoSize = true;
this.rbClipToFramebuffer.Location = new System.Drawing.Point(6, 65);
this.rbClipToFramebuffer.Name = "rbClipToFramebuffer";
this.rbClipToFramebuffer.Size = new System.Drawing.Size(117, 17);
this.rbClipToFramebuffer.TabIndex = 47;
this.rbClipToFramebuffer.TabStop = true;
this.rbClipToFramebuffer.Text = "Clip To Framebuffer";
this.toolTip1.SetToolTip(this.rbClipToFramebuffer, "Subverts mednafen\'s internal video display field emulation to show only the game\'" +
"s framebuffer.\r\nHorizontal letterbox bars may be re-added in Mednafen-style reso" +
"lution modes to maintain correct AR.");
this.rbClipToFramebuffer.UseVisualStyleBackColor = true;
this.rbClipToFramebuffer.CheckedChanged += new System.EventHandler(this.rbClipToFramebuffer_CheckedChanged);
//
// rbClipBasic
//
this.rbClipBasic.AutoSize = true;
this.rbClipBasic.Location = new System.Drawing.Point(6, 42);
this.rbClipBasic.Name = "rbClipBasic";
this.rbClipBasic.Size = new System.Drawing.Size(91, 17);
this.rbClipBasic.TabIndex = 46;
this.rbClipBasic.TabStop = true;
this.rbClipBasic.Text = "Basic Clipping";
this.toolTip1.SetToolTip(this.rbClipBasic, "A mednafen option -- appears to be 5.5% horizontally");
this.rbClipBasic.UseVisualStyleBackColor = true;
this.rbClipBasic.CheckedChanged += new System.EventHandler(this.rbClipHorizontal_CheckedChanged);
//
// lblPAL
//
this.lblPAL.AutoSize = true;
this.lblPAL.Location = new System.Drawing.Point(131, 22);
this.lblPAL.Location = new System.Drawing.Point(131, 17);
this.lblPAL.Name = "lblPAL";
this.lblPAL.Size = new System.Drawing.Size(27, 13);
this.lblPAL.TabIndex = 44;
@ -241,7 +298,7 @@
//
// PAL_LastLineNumeric
//
this.PAL_LastLineNumeric.Location = new System.Drawing.Point(124, 67);
this.PAL_LastLineNumeric.Location = new System.Drawing.Point(124, 62);
this.PAL_LastLineNumeric.Maximum = new decimal(new int[] {
287,
0,
@ -259,7 +316,7 @@
//
// PAL_FirstLineNumeric
//
this.PAL_FirstLineNumeric.Location = new System.Drawing.Point(124, 41);
this.PAL_FirstLineNumeric.Location = new System.Drawing.Point(124, 36);
this.PAL_FirstLineNumeric.Maximum = new decimal(new int[] {
287,
0,
@ -273,7 +330,7 @@
// lblNTSC
//
this.lblNTSC.AutoSize = true;
this.lblNTSC.Location = new System.Drawing.Point(62, 22);
this.lblNTSC.Location = new System.Drawing.Point(62, 17);
this.lblNTSC.Name = "lblNTSC";
this.lblNTSC.Size = new System.Drawing.Size(36, 13);
this.lblNTSC.TabIndex = 41;
@ -281,9 +338,9 @@
//
// btnAreaFull
//
this.btnAreaFull.Location = new System.Drawing.Point(6, 98);
this.btnAreaFull.Location = new System.Drawing.Point(8, 94);
this.btnAreaFull.Name = "btnAreaFull";
this.btnAreaFull.Size = new System.Drawing.Size(136, 23);
this.btnAreaFull.Size = new System.Drawing.Size(163, 23);
this.btnAreaFull.TabIndex = 40;
this.btnAreaFull.Text = "Full [0,239] and [0,287]";
this.btnAreaFull.UseVisualStyleBackColor = true;
@ -292,7 +349,7 @@
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(4, 69);
this.label4.Location = new System.Drawing.Point(4, 64);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(49, 13);
this.label4.TabIndex = 24;
@ -301,7 +358,7 @@
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(5, 43);
this.label1.Location = new System.Drawing.Point(5, 38);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(48, 13);
this.label1.TabIndex = 23;
@ -309,7 +366,7 @@
//
// NTSC_LastLineNumeric
//
this.NTSC_LastLineNumeric.Location = new System.Drawing.Point(59, 67);
this.NTSC_LastLineNumeric.Location = new System.Drawing.Point(59, 62);
this.NTSC_LastLineNumeric.Maximum = new decimal(new int[] {
239,
0,
@ -327,7 +384,7 @@
//
// NTSC_FirstLineNumeric
//
this.NTSC_FirstLineNumeric.Location = new System.Drawing.Point(59, 41);
this.NTSC_FirstLineNumeric.Location = new System.Drawing.Point(59, 36);
this.NTSC_FirstLineNumeric.Maximum = new decimal(new int[] {
239,
0,
@ -338,67 +395,54 @@
this.NTSC_FirstLineNumeric.TabIndex = 21;
this.NTSC_FirstLineNumeric.ValueChanged += new System.EventHandler(this.DrawingArea_ValueChanged);
//
// groupBox3
// rbWeave
//
this.groupBox3.Controls.Add(this.label2);
this.groupBox3.Controls.Add(this.rbClipNone);
this.groupBox3.Controls.Add(this.rbClipToFramebuffer);
this.groupBox3.Controls.Add(this.rbClipBasic);
this.groupBox3.Location = new System.Drawing.Point(7, 132);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(197, 106);
this.groupBox3.TabIndex = 46;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Horizontal Overscan Clipping";
this.rbWeave.AutoSize = true;
this.rbWeave.Location = new System.Drawing.Point(6, 19);
this.rbWeave.Name = "rbWeave";
this.rbWeave.Size = new System.Drawing.Size(60, 17);
this.rbWeave.TabIndex = 48;
this.rbWeave.TabStop = true;
this.rbWeave.Text = "Weave";
this.toolTip1.SetToolTip(this.rbWeave, "Good for low-motion video");
this.rbWeave.UseVisualStyleBackColor = true;
//
// rbClipBasic
// rbBobOffset
//
this.rbClipBasic.AutoSize = true;
this.rbClipBasic.Location = new System.Drawing.Point(6, 42);
this.rbClipBasic.Name = "rbClipBasic";
this.rbClipBasic.Size = new System.Drawing.Size(91, 17);
this.rbClipBasic.TabIndex = 46;
this.rbClipBasic.TabStop = true;
this.rbClipBasic.Text = "Basic Clipping";
this.toolTip1.SetToolTip(this.rbClipBasic, "A mednafen option -- appears to be 5.5% horizontally");
this.rbClipBasic.UseVisualStyleBackColor = true;
this.rbClipBasic.CheckedChanged += new System.EventHandler(this.rbClipHorizontal_CheckedChanged);
this.rbBobOffset.AutoSize = true;
this.rbBobOffset.Location = new System.Drawing.Point(122, 19);
this.rbBobOffset.Name = "rbBobOffset";
this.rbBobOffset.Size = new System.Drawing.Size(75, 17);
this.rbBobOffset.TabIndex = 47;
this.rbBobOffset.TabStop = true;
this.rbBobOffset.Text = "Bob Offset";
this.toolTip1.SetToolTip(this.rbBobOffset, "Good for high-motion video, but is a bit flickery; reduces the subjective vertica" +
"l resolution.");
this.rbBobOffset.UseVisualStyleBackColor = true;
//
// rbClipToFramebuffer
// rbBob
//
this.rbClipToFramebuffer.AutoSize = true;
this.rbClipToFramebuffer.Location = new System.Drawing.Point(6, 65);
this.rbClipToFramebuffer.Name = "rbClipToFramebuffer";
this.rbClipToFramebuffer.Size = new System.Drawing.Size(117, 17);
this.rbClipToFramebuffer.TabIndex = 47;
this.rbClipToFramebuffer.TabStop = true;
this.rbClipToFramebuffer.Text = "Clip To Framebuffer";
this.toolTip1.SetToolTip(this.rbClipToFramebuffer, "Subverts mednafen\'s internal video display field emulation to show only the game\'" +
"s framebuffer.");
this.rbClipToFramebuffer.UseVisualStyleBackColor = true;
this.rbClipToFramebuffer.CheckedChanged += new System.EventHandler(this.rbClipToFramebuffer_CheckedChanged);
this.rbBob.AutoSize = true;
this.rbBob.Location = new System.Drawing.Point(72, 19);
this.rbBob.Name = "rbBob";
this.rbBob.Size = new System.Drawing.Size(44, 17);
this.rbBob.TabIndex = 46;
this.rbBob.TabStop = true;
this.rbBob.Text = "Bob";
this.toolTip1.SetToolTip(this.rbBob, "Good for causing a headache. All glory to Bob.");
this.rbBob.UseVisualStyleBackColor = true;
//
// rbClipNone
// groupBox4
//
this.rbClipNone.AutoSize = true;
this.rbClipNone.Location = new System.Drawing.Point(6, 19);
this.rbClipNone.Name = "rbClipNone";
this.rbClipNone.Size = new System.Drawing.Size(51, 17);
this.rbClipNone.TabIndex = 48;
this.rbClipNone.TabStop = true;
this.rbClipNone.Text = "None";
this.toolTip1.SetToolTip(this.rbClipNone, resources.GetString("rbClipNone.ToolTip"));
this.rbClipNone.UseVisualStyleBackColor = true;
this.rbClipNone.CheckedChanged += new System.EventHandler(this.rbClipNone_CheckedChanged);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(29, 83);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(79, 13);
this.label2.TabIndex = 49;
this.label2.Text = "(and break AR)";
this.groupBox4.Controls.Add(this.rbWeave);
this.groupBox4.Controls.Add(this.rbBobOffset);
this.groupBox4.Controls.Add(this.rbBob);
this.groupBox4.Location = new System.Drawing.Point(492, 251);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(212, 49);
this.groupBox4.TabIndex = 50;
this.groupBox4.TabStop = false;
this.groupBox4.Text = "Deinterlacing";
//
// PSXOptions
//
@ -406,7 +450,8 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(713, 297);
this.ClientSize = new System.Drawing.Size(713, 344);
this.Controls.Add(this.groupBox4);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.btnCancel);
@ -420,12 +465,14 @@
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox3.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.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.groupBox4.ResumeLayout(false);
this.groupBox4.PerformLayout();
this.ResumeLayout(false);
}
@ -460,6 +507,9 @@
private System.Windows.Forms.RadioButton rbClipNone;
private System.Windows.Forms.RadioButton rbClipToFramebuffer;
private System.Windows.Forms.RadioButton rbClipBasic;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.GroupBox groupBox4;
private System.Windows.Forms.RadioButton rbWeave;
private System.Windows.Forms.RadioButton rbBobOffset;
private System.Windows.Forms.RadioButton rbBob;
}
}

View File

@ -40,6 +40,10 @@ namespace BizHawk.Client.EmuHawk
rbClipBasic.Checked = _settings.HorizontalClipping == Octoshock.eHorizontalClipping.Basic;
rbClipToFramebuffer.Checked = _settings.HorizontalClipping == Octoshock.eHorizontalClipping.Framebuffer;
rbWeave.Checked = _settings.DeinterlaceMode == Octoshock.eDeinterlaceMode.Weave;
rbBob.Checked = _settings.DeinterlaceMode == Octoshock.eDeinterlaceMode.Bob;
rbBobOffset.Checked = _settings.DeinterlaceMode == Octoshock.eDeinterlaceMode.BobOffset;
NTSC_FirstLineNumeric.Value = _settings.ScanlineStart_NTSC;
NTSC_LastLineNumeric.Value = _settings.ScanlineEnd_NTSC;
PAL_FirstLineNumeric.Value = _settings.ScanlineStart_PAL;
@ -70,7 +74,7 @@ namespace BizHawk.Client.EmuHawk
return result;
}
void SyncGuiToTheseSettings(Octoshock.Settings settings)
void SyncSettingsFromGui(Octoshock.Settings settings)
{
if (rbPixelPro.Checked) settings.ResolutionMode = Octoshock.eResolutionMode.PixelPro;
if (rbDebugMode.Checked) settings.ResolutionMode = Octoshock.eResolutionMode.Debug;
@ -81,6 +85,10 @@ namespace BizHawk.Client.EmuHawk
if (rbClipBasic.Checked) settings.HorizontalClipping = Octoshock.eHorizontalClipping.Basic;
if (rbClipToFramebuffer.Checked) settings.HorizontalClipping = Octoshock.eHorizontalClipping.Framebuffer;
if(rbWeave.Checked) _settings.DeinterlaceMode = Octoshock.eDeinterlaceMode.Weave;
if(rbBob.Checked) _settings.DeinterlaceMode = Octoshock.eDeinterlaceMode.Bob;
if(rbBobOffset.Checked) _settings.DeinterlaceMode = Octoshock.eDeinterlaceMode.BobOffset;
settings.ScanlineStart_NTSC = (int)NTSC_FirstLineNumeric.Value;
settings.ScanlineEnd_NTSC = (int)NTSC_LastLineNumeric.Value;
settings.ScanlineStart_PAL = (int)PAL_FirstLineNumeric.Value;
@ -97,7 +105,7 @@ namespace BizHawk.Client.EmuHawk
Global.Config.DispFinalFilter = 1; //bilinear, I hope
}
SyncGuiToTheseSettings(_settings);
SyncSettingsFromGui(_settings);
_settings.Validate();
GlobalWin.MainForm.PutCoreSettings(_settings);
@ -117,7 +125,7 @@ namespace BizHawk.Client.EmuHawk
void SyncLabels()
{
var temp = _settings.Clone();
SyncGuiToTheseSettings(temp);
SyncSettingsFromGui(temp);
_settings.Validate();
//actually, I think this is irrelevant. But it's nice in case we want to do some kind of a more detailed simulation later
@ -125,16 +133,16 @@ namespace BizHawk.Client.EmuHawk
int h = _previewVideoSize.Height;
temp.ResolutionMode = Octoshock.eResolutionMode.PixelPro;
var size = Octoshock.CalculateResolution(_previewVideoStandard, temp, w, h);
lblPixelPro.Text = lblPixelPro_text.Replace("800x480", string.Format("{0}x{1}", size.Width, size.Height)); ;
var ri = Octoshock.CalculateResolution(_previewVideoStandard, temp, w, h);
lblPixelPro.Text = lblPixelPro_text.Replace("800x480", string.Format("{0}x{1}", ri.Resolution.Width, ri.Resolution.Height)); ;
temp.ResolutionMode = Octoshock.eResolutionMode.Mednafen;
size = Octoshock.CalculateResolution(_previewVideoStandard, temp, w, h);
lblMednafen.Text = lblMednafen_text.Replace("320x240", string.Format("{0}x{1}", size.Width, size.Height));
ri = Octoshock.CalculateResolution(_previewVideoStandard, temp, w, h);
lblMednafen.Text = lblMednafen_text.Replace("320x240", string.Format("{0}x{1}", ri.Resolution.Width, ri.Resolution.Height));
temp.ResolutionMode = Octoshock.eResolutionMode.TweakedMednafen;
size = Octoshock.CalculateResolution(_previewVideoStandard, temp, w, h);
lblTweakedMednafen.Text = lblTweakedMednafen_text.Replace("400x300", string.Format("{0}x{1}", size.Width, size.Height));
ri = Octoshock.CalculateResolution(_previewVideoStandard, temp, w, h);
lblTweakedMednafen.Text = lblTweakedMednafen_text.Replace("400x300", string.Format("{0}x{1}", ri.Resolution.Width, ri.Resolution.Height));
}
private void DrawingArea_ValueChanged(object sender, EventArgs e)
@ -172,5 +180,7 @@ But: 1. we think we improved on it a tiny bit with the tweaked mode
And: 2. It's not suitable for detailed scrutinizing of graphics
");
}
}
}

View File

@ -39,13 +39,13 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
private void SetControllerButtons()
{
ControllerDefinition = new ControllerDefinition();
ControllerDefinition.Name = _SyncSettings.Controllers.All(c => c.Type == ControllerSetting.ControllerType.Gamepad)
ControllerDefinition.Name = _SyncSettings.Controllers.All(c => c.Type == ControllerSetting.ControllerType.Gamepad)
? "PSX Gamepad Controller"
: "PSX DualShock Controller"; // Meh, more nuanced logic doesn't really work with a simple property
ControllerDefinition.BoolButtons.Clear();
ControllerDefinition.FloatControls.Clear();
for (int i = 0; i < _SyncSettings.Controllers.Length; i++)
{
if (_SyncSettings.Controllers[i].IsConnected)
@ -102,7 +102,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
ControllerDefinition.FloatRanges.Add(
//new[] {-1f,-1f,-1f} //this is carefully chosen so that we end up with a -1 disc by default (indicating that it's never been set)
//hmm.. I don't see why this wouldn't work
new[] {0f,1f,1f}
new[] { 0f, 1f, 1f }
);
}
@ -217,7 +217,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
public OctoshockDll.eRegion SystemRegion { get; private set; }
public OctoshockDll.eVidStandard SystemVidStandard { get; private set; }
public System.Drawing.Size CurrentVideoSize { get; private set; }
public bool CurrentTrayOpen { get; private set; }
public int CurrentDiscIndexMounted { get; private set; }
@ -327,9 +327,10 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
BufferHeight = 288;
}
CurrentVideoSize = new System.Drawing.Size(BufferWidth, BufferHeight);
var size = Octoshock.CalculateResolution(SystemVidStandard, _Settings, BufferWidth, BufferHeight);
BufferWidth = VirtualWidth = size.Width;
BufferHeight = VirtualHeight = size.Height;
var ri = Octoshock.CalculateResolution(SystemVidStandard, _Settings, BufferWidth, BufferHeight);
BufferWidth = VirtualWidth = ri.Resolution.Width;
BufferHeight = VirtualHeight = ri.Resolution.Height;
//VideoProvider_Padding = new System.Drawing.Size(50,50);
frameBuffer = new int[BufferWidth * BufferHeight];
}
@ -354,7 +355,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
else
{
//must be a psf
if(psf.LibData != null)
if (psf.LibData != null)
fixed (byte* pBuf = psf.LibData)
OctoshockDll.shock_MountEXE(psx, pBuf, psf.LibData.Length, true);
fixed (byte* pBuf = psf.Data)
@ -369,7 +370,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
//setup the controller based on sync settings
SetControllerButtons();
var lookup = new Dictionary<ControllerSetting.ControllerType,OctoshockDll.ePeripheralType> {
var lookup = new Dictionary<ControllerSetting.ControllerType, OctoshockDll.ePeripheralType> {
{ ControllerSetting.ControllerType.Gamepad, OctoshockDll.ePeripheralType.Pad },
{ ControllerSetting.ControllerType.DualAnalog, OctoshockDll.ePeripheralType.DualAnalog },
{ ControllerSetting.ControllerType.DualShock, OctoshockDll.ePeripheralType.DualShock },
@ -482,12 +483,21 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
}
}
public class ResolutionInfo
{
public System.Drawing.Size Resolution, Padding;
public System.Drawing.Size Total { get { return System.Drawing.Size.Add(Resolution, Padding); } }
}
/// <summary>
/// Calculates what the output resolution would be for the given input resolution and settings
/// </summary>
public static System.Drawing.Size CalculateResolution(OctoshockDll.eVidStandard standard, Settings settings, int w, int h)
public static ResolutionInfo CalculateResolution(OctoshockDll.eVidStandard standard, Settings settings, int w, int h)
{
ResolutionInfo ret = new ResolutionInfo();
//some of this logic is duplicated in the c++ side, be sure to check there
//TODO - scanline control + framebuffer mode is majorly broken
int virtual_width = 800;
if (settings.HorizontalClipping == eHorizontalClipping.Basic) virtual_width = 768;
@ -496,39 +506,105 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
int scanline_start = standard == OctoshockDll.eVidStandard.NTSC ? settings.ScanlineStart_NTSC : settings.ScanlineStart_PAL;
int scanline_end = standard == OctoshockDll.eVidStandard.NTSC ? settings.ScanlineEnd_NTSC : settings.ScanlineEnd_PAL;
int scanline_num = scanline_end - scanline_start + 1;
//int scanline_num = h; // I wanted to do this, but our logic for mednafen modes here is based on un-doubled resolution. i could do a hack to divide it by 2 though
int real_scanline_num = standard == OctoshockDll.eVidStandard.NTSC ? 240 : 288;
int VirtualWidth=-1, VirtualHeight=-1;
switch (settings.ResolutionMode)
{
case eResolutionMode.Debug:
VirtualWidth = w;
VirtualHeight = h;
break;
case eResolutionMode.Mednafen:
VirtualWidth = 320;
if (settings.HorizontalClipping == eHorizontalClipping.Basic)
VirtualWidth = 302;
//? not sure what this should be
if (settings.HorizontalClipping == eHorizontalClipping.Framebuffer)
VirtualWidth = 320;
//mednafen uses 320xScanlines as the 1x size
//it does change the 1x width when doing basic clipping.
//and it does easily change the height when doing scanline removal.
//now, our framebuffer cropping mode is more complex...
VirtualWidth = (standard == OctoshockDll.eVidStandard.NTSC) ? 320 : 363;
VirtualHeight = scanline_num;
if (settings.HorizontalClipping == eHorizontalClipping.Basic)
VirtualWidth = (standard == OctoshockDll.eVidStandard.NTSC) ? 302 : 384;
if (settings.HorizontalClipping == eHorizontalClipping.Framebuffer)
{
//mednafen typically sends us a framebuffer with overscan. 350x240 is a nominal example here. it's squished inward to 320x240 for correct PAR.
//ok: here we have a framebuffer without overscan. 320x240 nominal. So the VirtualWidth of what we got is off by a factor of 109.375%
//so a beginning approach would be this:
//VirtualWidth = (int)(VirtualWidth * 320.0f / 350);
//but that will shrink things which are already annoyingly shrunken.
//therefore, lets do that, but then scale the whole window by the same factor so the width becomes unscaled and now the height is scaled up!
//weird, huh?
VirtualHeight = (int)(VirtualHeight * 350.0f / 320);
//now unfortunately we may have lost vertical pixels. common in the case of PAL (rendering 256 on a field of 288)
//therefore we'll be stretching way too much vertically here.
//lets add those pixels back with a new hack
if (standard == OctoshockDll.eVidStandard.PAL)
{
if (h > 288) ret.Padding = new System.Drawing.Size(0, 576 - h);
else ret.Padding = new System.Drawing.Size(0, 288 - h);
}
else
{
if (h > 288) ret.Padding = new System.Drawing.Size(0, 480 - h);
else ret.Padding = new System.Drawing.Size(0, 240 - h);
}
}
break;
//384 / 288 = 1.3333333333333333333333333333333
case eResolutionMode.TweakedMednafen:
if (standard == OctoshockDll.eVidStandard.NTSC)
{
//dont make this 430, it's already been turned into 400 from 368+30 and then some fudge factor
VirtualWidth = 400;
VirtualHeight = (int)(scanline_num * 300.0f / 240);
if (settings.HorizontalClipping == eHorizontalClipping.Basic)
VirtualWidth = 378;
}
else
{
//this is a bit tricky. we know we want 400 for the virtualwidth.
VirtualWidth = 400;
if (settings.HorizontalClipping == eHorizontalClipping.Basic)
VirtualWidth = 378;
//I'll be honest, I was just guessing here mostly
//I need the AR to basically work out to be 363/288 (thats what it was in mednafen mode) so...
VirtualHeight = (int)(scanline_num * (400.0f/363*288) / 288);
}
if (settings.HorizontalClipping == eHorizontalClipping.Framebuffer)
{
//see discussion above
VirtualHeight = (int)(VirtualHeight * 350.0f / 320);
if (standard == OctoshockDll.eVidStandard.PAL)
{
if (h > 288) ret.Padding = new System.Drawing.Size(0, 576 - h);
else ret.Padding = new System.Drawing.Size(0, 288 - h);
}
else
{
if (h > 288) ret.Padding = new System.Drawing.Size(0, 480 - h);
else ret.Padding = new System.Drawing.Size(0, 240 - h);
}
}
break;
case eResolutionMode.PixelPro:
VirtualWidth = virtual_width;
VirtualHeight = scanline_num * 2;
break;
case eResolutionMode.TweakedMednafen:
VirtualWidth = 400;
if (settings.HorizontalClipping == eHorizontalClipping.Basic)
VirtualWidth = 378;
if (settings.HorizontalClipping == eHorizontalClipping.Framebuffer)
VirtualWidth = 400;
VirtualHeight = (int)(scanline_num * 300.0f / real_scanline_num);
case eResolutionMode.Debug:
VirtualWidth = w;
VirtualHeight = h;
break;
}
return new System.Drawing.Size(VirtualWidth, VirtualHeight);
ret.Resolution = new System.Drawing.Size(VirtualWidth, VirtualHeight);
return ret;
}
void PokeDisc()
@ -551,7 +627,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
//if tray open is requested, and valid, apply it
//in the first frame, go ahead and open it up so we have a chance to put a disc in it
if (Controller["Open"] && !CurrentTrayOpen || Frame==0)
if (Controller["Open"] && !CurrentTrayOpen || Frame == 0)
{
OctoshockDll.shock_OpenTray(psx);
CurrentTrayOpen = true;
@ -624,6 +700,10 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
if (_Settings.HorizontalClipping == eHorizontalClipping.Framebuffer)
ropts.renderType = OctoshockDll.eShockRenderType.Framebuffer;
if (_Settings.DeinterlaceMode == eDeinterlaceMode.Weave) ropts.deinterlaceMode = OctoshockDll.eShockDeinterlaceMode.Weave;
if (_Settings.DeinterlaceMode == eDeinterlaceMode.Bob) ropts.deinterlaceMode = OctoshockDll.eShockDeinterlaceMode.Bob;
if (_Settings.DeinterlaceMode == eDeinterlaceMode.BobOffset) ropts.deinterlaceMode = OctoshockDll.eShockDeinterlaceMode.BobOffset;
OctoshockDll.shock_SetRenderOptions(psx, ref ropts);
//prep tracer
@ -668,9 +748,10 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
BufferWidth = w;
BufferHeight = h;
var size = CalculateResolution(this.SystemVidStandard, _Settings, w, h);
VirtualWidth = size.Width;
VirtualHeight = size.Height;
var ri = CalculateResolution(this.SystemVidStandard, _Settings, w, h);
VirtualWidth = ri.Resolution.Width;
VirtualHeight = ri.Resolution.Height;
VideoProvider_Padding = ri.Padding;
int len = w * h;
if (frameBuffer.Length != len)
@ -709,6 +790,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
public int BufferWidth { get; private set; }
public int BufferHeight { get; private set; }
public int BackgroundColor { get { return 0; } }
public System.Drawing.Size VideoProvider_Padding { get; private set; }
#region Debugging
@ -876,7 +958,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
transaction.transaction = OctoshockDll.eShockStateTransaction.BinarySize;
int size = OctoshockDll.shock_StateTransaction(psx, ref transaction);
savebuff = new byte[size];
savebuff2 = new byte[savebuff.Length + 4+ 4+4+1+1+4];
savebuff2 = new byte[savebuff.Length + 4 + 4 + 4 + 1 + 1 + 4];
}
public void SaveStateBinary(BinaryWriter writer)
@ -1019,6 +1101,13 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
Framebuffer
}
public enum eDeinterlaceMode
{
Weave,
Bob,
BobOffset
}
public class Settings
{
[DisplayName("Resolution Mode")]
@ -1046,6 +1135,9 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
[DefaultValue(287)]
public int ScanlineEnd_PAL { get; set; }
[DisplayName("DeinterlaceMode")]
[DefaultValue(eDeinterlaceMode.Weave)]
public eDeinterlaceMode DeinterlaceMode { get; set; }
public void Validate()
{
@ -1053,7 +1145,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
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)
{

View File

@ -89,6 +89,13 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
Framebuffer
};
public enum eShockDeinterlaceMode : int
{
Weave,
Bob,
BobOffset
}
public const int SHOCK_OK = 0;
public const int SHOCK_FALSE = 0;
public const int SHOCK_TRUE = 1;
@ -134,6 +141,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
{
public int scanline_start, scanline_end;
public eShockRenderType renderType;
public eShockDeinterlaceMode deinterlaceMode;
public bool skip;
};

Binary file not shown.

View File

@ -46,6 +46,14 @@
//extern MDFNGI EmulatedPSX;
int16 soundbuf[1024 * 1024]; //how big? big enough.
int VTBackBuffer = 0;
static MDFN_Rect VTDisplayRects[2];
#include "video/Deinterlacer.h"
static bool PrevInterlaced;
static Deinterlacer deint;
static EmulateSpecStruct espec;
namespace MDFN_IEN_PSX
{
@ -983,6 +991,8 @@ static void PSX_Power(bool powering_up)
IRQ_Power();
ForceEventUpdates(0);
deint.ClearState();
}
@ -1343,15 +1353,7 @@ EW_EXPORT s32 shock_PowerOff(void* psx)
//not supported yet
return SHOCK_ERROR;
}
int16 soundbuf[1024*1024]; //how big? big enough.
int VTBackBuffer = 0;
static MDFN_Rect VTDisplayRects[2];
#include "video/Deinterlacer.h"
static bool PrevInterlaced;
static Deinterlacer deint;
static EmulateSpecStruct espec;
EW_EXPORT s32 shock_Step(void* psx, eShockStep step)
{
//only eShockStep_Frame is supported
@ -1378,6 +1380,13 @@ EW_EXPORT s32 shock_Step(void* psx, eShockStep step)
//not sure about this
espec.skip = s_ShockConfig.opts.skip;
if (s_ShockConfig.opts.deinterlaceMode == eShockDeinterlaceMode_Weave)
deint.SetType(Deinterlacer::DEINT_WEAVE);
if (s_ShockConfig.opts.deinterlaceMode == eShockDeinterlaceMode_Bob)
deint.SetType(Deinterlacer::DEINT_BOB);
if (s_ShockConfig.opts.deinterlaceMode == eShockDeinterlaceMode_BobOffset)
deint.SetType(Deinterlacer::DEINT_BOB_OFFSET);
//-------------------------
FIO->UpdateInput();
@ -1442,6 +1451,57 @@ EW_EXPORT s32 shock_Step(void* psx, eShockStep step)
return SHOCK_OK;
}
struct FramebufferCropInfo
{
int width, height, xo, yo;
};
static void _shock_AnalyzeFramebufferCropInfo(int fbIndex, FramebufferCropInfo* info)
{
//presently, except for contrived test programs, it is safe to assume this is the same for the entire frame (no known use by games)
//however, due to the dump_framebuffer, it may be incorrect at scanline 0. so lets use another one for the heuristic here
//you'd think we could use FirstLine instead of kScanlineWidthHeuristicIndex, but sometimes it hasnt been set (screen off) so it's confusing
int width = VTLineWidths[fbIndex][kScanlineWidthHeuristicIndex];
int height = espec.DisplayRect.h;
int yo = espec.DisplayRect.y;
//fix a common error here from disabled screens (?)
//I think we're lucky in selecting these lines kind of randomly. need a better plan.
if (width <= 0) width = VTLineWidths[fbIndex][0];
if (s_ShockConfig.opts.renderType == eShockRenderType_Framebuffer)
{
//printf("%d %d %d %d | %d | %d\n",yo,height, GPU->GetVertStart(), GPU->GetVertEnd(), espec.DisplayRect.y, GPU->FirstLine);
height = GPU->GetVertEnd() - GPU->GetVertStart();
yo = GPU->FirstLine;
if (espec.DisplayRect.h == 288 || espec.DisplayRect.h == 240)
{
}
else
{
height *= 2;
//only return even scanlines to avoid bouncing the interlacing
if (yo & 1) yo--;
}
//this can happen when the display turns on mid-frame
//maybe an off by one error here..?
if (yo + height >= espec.DisplayRect.h)
yo = espec.DisplayRect.h - height;
//sometimes when changing modes we have trouble..?
if (yo<0) yo = 0;
}
info->width = width;
info->height = height;
info->xo = 0;
info->yo = yo;
}
//`normalizes` the framebuffer to 700x480 by pixel doubling and wrecking the AR a little bit as needed
void NormalizeFramebuffer()
{
@ -1470,14 +1530,15 @@ void NormalizeFramebuffer()
//NOTE: this approach is very redundant with the displaymanager AR tracking stuff
//however, it will help us avoid stressing the displaymanager (for example, a 700x240 will freak it out kind of. we could send it a much more sensible 700x480)
//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 width = VTLineWidths[0][kScanlineWidthHeuristicIndex];
if(width <= 0) VTLineWidths[0][0];
//always fetch description
FramebufferCropInfo cropInfo;
_shock_AnalyzeFramebufferCropInfo(0, &cropInfo);
int width = cropInfo.width;
int height = cropInfo.height;
int height = espec.DisplayRect.h;
int virtual_width = 800;
int virtual_height = 480;
if (s_ShockConfig.opts.renderType == eShockRenderType_ClipOverscan)
virtual_width = 756;
if (s_ShockConfig.opts.renderType == eShockRenderType_Framebuffer)
@ -1487,7 +1548,7 @@ void NormalizeFramebuffer()
virtual_width = 736;
}
int xs=1,ys=1,xm=0;
int xs=1,ys=1;
//I. as described above
//if(width == 280 && height == 240) {}
@ -1509,28 +1570,53 @@ void NormalizeFramebuffer()
if(width > 400 && height <= 288) ys=2;
if(width <= 400 && height > 288) xs=2;
if(width > 400 && height > 288) {}
//TODO - shrink it entirely if cropping. EDIT-any idea what this means? if you figure it out, just do it.
xm = (virtual_width-width*xs)/2;
int xm = (virtual_width - width*xs) / 2;
int ym = (virtual_height - height*ys) / 2;
int curr = 0;
//1. double the height, while cropping down
if(ys==2) //should handle ntsc or pal, but not tested yet for pal
if(height != virtual_height)
{
uint32* src = VTBuffer[curr]->pixels + (s_ShockConfig.fb_width*espec.DisplayRect.y) + espec.DisplayRect.x;
uint32* dst = VTBuffer[curr^1]->pixels;
int tocopy = width*4;
for(int y=0;y<height;y++)
//float from top as needed
memset(dst, 0, ym*tocopy);
dst += width;
if(ys==2)
{
memcpy(dst,src,tocopy);
dst += width;
memcpy(dst,src,tocopy);
dst += width;
src += s_FramebufferCurrentWidth;
for(int y=0;y<height;y++)
{
memcpy(dst,src,tocopy);
dst += width;
memcpy(dst,src,tocopy);
dst += width;
src += s_FramebufferCurrentWidth;
}
}
else
{
for(int y=0;y<height;y++)
{
memcpy(dst, src, tocopy);
dst += width;
src += s_FramebufferCurrentWidth;
}
}
//fill bottom
int remaining_lines = virtual_height - ym - height*ys;
memset(dst, 0, remaining_lines*tocopy);
//patch up the metrics
height *= 2;
height = virtual_height; //we floated the content vertically, so this becomes the new height
espec.DisplayRect.x = 0;
espec.DisplayRect.y = 0;
espec.DisplayRect.h = height;
@ -1571,7 +1657,8 @@ void NormalizeFramebuffer()
}
//float the content horizontally
for(int x=0;x<xm;x++)
int remaining_pixels = virtual_width - xm - width*xs;
for(int x=0;x<remaining_pixels;x++)
*dst++ = 0;
}
@ -1600,6 +1687,7 @@ EW_EXPORT s32 shock_GetSamples(void* psx, void* buffer)
return espec.SoundBufSize;
}
EW_EXPORT s32 shock_GetFramebuffer(void* psx, ShockFramebufferInfo* fb)
{
//TODO - fastpath for emitting to the final framebuffer, although if we did that, we'd have to regenerate it every time
@ -1616,40 +1704,16 @@ EW_EXPORT s32 shock_GetFramebuffer(void* psx, ShockFramebufferInfo* fb)
int fbIndex = s_FramebufferCurrent;
//always fetch description
//presently, except for contrived test programs, it is safe to assume this is the same for the entire frame (no known use by games)
//however, due to the dump_framebuffer, it may be incorrect at scanline 0. so lets use another one for the heuristic here
//you'd think we could use FirstLine instead of kScanlineWidthHeuristicIndex, but sometimes it hasnt been set (screen off) so it's confusing
int width = VTLineWidths[fbIndex][kScanlineWidthHeuristicIndex];
int height = espec.DisplayRect.h;
int yo = espec.DisplayRect.y;
FramebufferCropInfo cropInfo;
_shock_AnalyzeFramebufferCropInfo(fbIndex, &cropInfo);
int width = cropInfo.width;
int height = cropInfo.height;
int yo = cropInfo.yo;
//fix a common error here from disabled screens (?)
//I think we're lucky in selecting these lines kind of randomly. need a better plan.
if(width <= 0) width = VTLineWidths[fbIndex][0];
if (s_ShockConfig.opts.renderType == eShockRenderType_Framebuffer)
//sloppy, but the above AnalyzeFramebufferCropInfo() will give us too short of a buffer
if(fb->flags & eShockFramebufferFlags_Normalize)
{
//printf("%d %d %d %d | %d | %d\n",yo,height, GPU->GetVertStart(), GPU->GetVertEnd(), espec.DisplayRect.y, GPU->FirstLine);
height = GPU->GetVertEnd() - GPU->GetVertStart();
yo = GPU->FirstLine;
if(espec.DisplayRect.h == 288 || espec.DisplayRect.h == 240)
{}
else
{
height *= 2;
//only return even scanlines to avoid bouncing the interlacing
if(yo&1) yo--;
}
//this can happen when the display turns on mid-frame
//maybe an off by one error here..?
if (yo + height >= espec.DisplayRect.h)
yo = espec.DisplayRect.h - height;
//sometimes when changing modes we have trouble..?
if (yo<0) yo = 0;
height = espec.DisplayRect.h;
}
fb->width = width;

View File

@ -123,6 +123,13 @@ enum eRegion
REGION_NONE = 3
};
enum eShockDeinterlaceMode
{
eShockDeinterlaceMode_Weave,
eShockDeinterlaceMode_Bob,
eShockDeinterlaceMode_BobOffset
};
enum eShockStep
{
eShockStep_Frame
@ -288,6 +295,7 @@ struct ShockRenderOptions
{
s32 scanline_start, scanline_end;
eShockRenderType renderType;
eShockDeinterlaceMode deinterlaceMode;
bool skip;
};