Misc: Added "Remove sprite limit" option
This commit is contained in:
parent
ce34b517b1
commit
56d2580fbf
7 changed files with 64 additions and 13 deletions
|
@ -9,6 +9,7 @@ enum EmulationFlags
|
||||||
ShowFPS = 0x02,
|
ShowFPS = 0x02,
|
||||||
VerticalSync = 0x04,
|
VerticalSync = 0x04,
|
||||||
AllowInvalidInput = 0x08,
|
AllowInvalidInput = 0x08,
|
||||||
|
RemoveSpriteLimit = 0x10,
|
||||||
|
|
||||||
Mmc3IrqAltBehavior = 0x8000,
|
Mmc3IrqAltBehavior = 0x8000,
|
||||||
};
|
};
|
||||||
|
|
50
Core/PPU.cpp
50
Core/PPU.cpp
|
@ -439,13 +439,8 @@ void PPU::LoadTileInfo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPU::LoadSpriteTileInfo()
|
void PPU::LoadSprite(uint8_t spriteY, uint8_t tileIndex, uint8_t attributes, uint8_t spriteX, bool extraSprite)
|
||||||
{
|
{
|
||||||
uint32_t spriteAddr = _spriteIndex * 4;
|
|
||||||
uint8_t spriteY = _secondarySpriteRAM[spriteAddr];
|
|
||||||
uint8_t tileIndex = _secondarySpriteRAM[spriteAddr + 1];
|
|
||||||
uint8_t attributes = _secondarySpriteRAM[spriteAddr + 2];
|
|
||||||
uint8_t spriteX = _secondarySpriteRAM[spriteAddr + 3];
|
|
||||||
bool backgroundPriority = (attributes & 0x20) == 0x20;
|
bool backgroundPriority = (attributes & 0x20) == 0x20;
|
||||||
bool horizontalMirror = (attributes & 0x40) == 0x40;
|
bool horizontalMirror = (attributes & 0x40) == 0x40;
|
||||||
bool verticalMirror = (attributes & 0x80) == 0x80;
|
bool verticalMirror = (attributes & 0x80) == 0x80;
|
||||||
|
@ -464,17 +459,23 @@ void PPU::LoadSpriteTileInfo()
|
||||||
tileAddr = ((tileIndex << 4) | _flags.SpritePatternAddr) + lineOffset;
|
tileAddr = ((tileIndex << 4) | _flags.SpritePatternAddr) + lineOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_spriteIndex < _spriteCount && spriteY < 240) {
|
if((_spriteIndex < _spriteCount || extraSprite) && spriteY < 240) {
|
||||||
_spriteTiles[_spriteIndex].BackgroundPriority = backgroundPriority;
|
_spriteTiles[_spriteIndex].BackgroundPriority = backgroundPriority;
|
||||||
_spriteTiles[_spriteIndex].HorizontalMirror = horizontalMirror;
|
_spriteTiles[_spriteIndex].HorizontalMirror = horizontalMirror;
|
||||||
_spriteTiles[_spriteIndex].VerticalMirror = verticalMirror;
|
_spriteTiles[_spriteIndex].VerticalMirror = verticalMirror;
|
||||||
_spriteTiles[_spriteIndex].PaletteOffset = ((attributes & 0x03) << 2) | 0x10;
|
_spriteTiles[_spriteIndex].PaletteOffset = ((attributes & 0x03) << 2) | 0x10;
|
||||||
_spriteTiles[_spriteIndex].LowByte = _memoryManager->ReadVRAM(tileAddr);
|
if(extraSprite) {
|
||||||
_spriteTiles[_spriteIndex].HighByte = _memoryManager->ReadVRAM(tileAddr + 8);
|
//Use DebugReadVRAM for extra sprites to prevent most side-effects.
|
||||||
|
_spriteTiles[_spriteIndex].LowByte = _memoryManager->DebugReadVRAM(tileAddr);
|
||||||
|
_spriteTiles[_spriteIndex].HighByte = _memoryManager->DebugReadVRAM(tileAddr + 8);
|
||||||
|
} else {
|
||||||
|
_spriteTiles[_spriteIndex].LowByte = _memoryManager->ReadVRAM(tileAddr);
|
||||||
|
_spriteTiles[_spriteIndex].HighByte = _memoryManager->ReadVRAM(tileAddr + 8);
|
||||||
|
}
|
||||||
_spriteTiles[_spriteIndex].TileAddr = tileAddr;
|
_spriteTiles[_spriteIndex].TileAddr = tileAddr;
|
||||||
_spriteTiles[_spriteIndex].OffsetY = lineOffset;
|
_spriteTiles[_spriteIndex].OffsetY = lineOffset;
|
||||||
_spriteTiles[_spriteIndex].SpriteX = spriteX;
|
_spriteTiles[_spriteIndex].SpriteX = spriteX;
|
||||||
} else {
|
} else if(!extraSprite) {
|
||||||
//Fetches to sprite 0xFF for remaining sprites/hidden - used by MMC3 IRQ counter
|
//Fetches to sprite 0xFF for remaining sprites/hidden - used by MMC3 IRQ counter
|
||||||
lineOffset = 0;
|
lineOffset = 0;
|
||||||
tileIndex = 0xFF;
|
tileIndex = 0xFF;
|
||||||
|
@ -491,6 +492,25 @@ void PPU::LoadSpriteTileInfo()
|
||||||
_spriteIndex++;
|
_spriteIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PPU::LoadExtraSprites()
|
||||||
|
{
|
||||||
|
if(_spriteCount == 8 && EmulationSettings::CheckFlag(EmulationFlags::RemoveSpriteLimit)) {
|
||||||
|
for(uint32_t i = _overflowSpriteAddr; i < 0x100; i += 4) {
|
||||||
|
uint8_t spriteY = _spriteRAM[i];
|
||||||
|
if(_scanline >= spriteY && _scanline < spriteY + (_flags.LargeSprites ? 16 : 8)) {
|
||||||
|
LoadSprite(spriteY, _spriteRAM[i + 1], _spriteRAM[i + 2], _spriteRAM[i + 3], true);
|
||||||
|
_spriteCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPU::LoadSpriteTileInfo()
|
||||||
|
{
|
||||||
|
uint8_t *spriteAddr = _secondarySpriteRAM + _spriteIndex * 4;
|
||||||
|
LoadSprite(*spriteAddr, *(spriteAddr+1), *(spriteAddr+2), *(spriteAddr+3), false);
|
||||||
|
}
|
||||||
|
|
||||||
void PPU::LoadNextTile()
|
void PPU::LoadNextTile()
|
||||||
{
|
{
|
||||||
_state.LowBitShift |= _nextTile.LowByte;
|
_state.LowBitShift |= _nextTile.LowByte;
|
||||||
|
@ -677,6 +697,7 @@ void PPU::CopyOAMData()
|
||||||
_sprite0Added = false;
|
_sprite0Added = false;
|
||||||
_spriteInRange = false;
|
_spriteInRange = false;
|
||||||
_secondaryOAMAddr = 0;
|
_secondaryOAMAddr = 0;
|
||||||
|
_overflowSpriteAddr = 0;
|
||||||
|
|
||||||
_oamCopyDone = false;
|
_oamCopyDone = false;
|
||||||
_spriteAddrH = (_state.SpriteRamAddr >> 2) & 0x3F;
|
_spriteAddrH = (_state.SpriteRamAddr >> 2) & 0x3F;
|
||||||
|
@ -684,6 +705,8 @@ void PPU::CopyOAMData()
|
||||||
} else if(_cycle == 256) {
|
} else if(_cycle == 256) {
|
||||||
_sprite0Visible = _sprite0Added;
|
_sprite0Visible = _sprite0Added;
|
||||||
_spriteCount = (_secondaryOAMAddr >> 2);
|
_spriteCount = (_secondaryOAMAddr >> 2);
|
||||||
|
|
||||||
|
LoadExtraSprites();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_cycle & 0x01) {
|
if(_cycle & 0x01) {
|
||||||
|
@ -727,6 +750,11 @@ void PPU::CopyOAMData()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//8 sprites have been found, check next sprite for overflow + emulate PPU bug
|
//8 sprites have been found, check next sprite for overflow + emulate PPU bug
|
||||||
|
if(_overflowSpriteAddr == 0) {
|
||||||
|
//Used to remove sprite limit
|
||||||
|
_overflowSpriteAddr = _spriteAddrH * 4;
|
||||||
|
}
|
||||||
|
|
||||||
if(_spriteInRange) {
|
if(_spriteInRange) {
|
||||||
//Sprite is visible, consider this to be an overflow
|
//Sprite is visible, consider this to be an overflow
|
||||||
_statusFlags.SpriteOverflow = true;
|
_statusFlags.SpriteOverflow = true;
|
||||||
|
@ -878,7 +906,7 @@ void PPU::StreamState(bool saving)
|
||||||
Stream<uint8_t>(_previousTile.HighByte);
|
Stream<uint8_t>(_previousTile.HighByte);
|
||||||
Stream<uint32_t>(_previousTile.PaletteOffset);
|
Stream<uint32_t>(_previousTile.PaletteOffset);
|
||||||
|
|
||||||
for(int i = 0; i < 8; i++) {
|
for(int i = 0; i < 64; i++) {
|
||||||
Stream<uint8_t>(_spriteTiles[i].SpriteX);
|
Stream<uint8_t>(_spriteTiles[i].SpriteX);
|
||||||
Stream<uint8_t>(_spriteTiles[i].LowByte);
|
Stream<uint8_t>(_spriteTiles[i].LowByte);
|
||||||
Stream<uint8_t>(_spriteTiles[i].HighByte);
|
Stream<uint8_t>(_spriteTiles[i].HighByte);
|
||||||
|
|
|
@ -123,11 +123,12 @@ class PPU : public IMemoryHandler, public Snapshotable
|
||||||
TileInfo _nextTile;
|
TileInfo _nextTile;
|
||||||
TileInfo _previousTile;
|
TileInfo _previousTile;
|
||||||
|
|
||||||
SpriteInfo _spriteTiles[8];
|
SpriteInfo _spriteTiles[64];
|
||||||
uint32_t _spriteCount = 0;
|
uint32_t _spriteCount = 0;
|
||||||
uint32_t _secondaryOAMAddr = 0;
|
uint32_t _secondaryOAMAddr = 0;
|
||||||
bool _sprite0Visible = false;
|
bool _sprite0Visible = false;
|
||||||
|
|
||||||
|
uint32_t _overflowSpriteAddr = 0;
|
||||||
uint32_t _spriteIndex = 0;
|
uint32_t _spriteIndex = 0;
|
||||||
|
|
||||||
uint8_t _openBus = 0;
|
uint8_t _openBus = 0;
|
||||||
|
@ -178,7 +179,9 @@ class PPU : public IMemoryHandler, public Snapshotable
|
||||||
void WritePaletteRAM(uint16_t addr, uint8_t value);
|
void WritePaletteRAM(uint16_t addr, uint8_t value);
|
||||||
|
|
||||||
void LoadTileInfo();
|
void LoadTileInfo();
|
||||||
|
void LoadSprite(uint8_t spriteY, uint8_t tileIndex, uint8_t attributes, uint8_t spriteX, bool extraSprite);
|
||||||
void LoadSpriteTileInfo();
|
void LoadSpriteTileInfo();
|
||||||
|
void LoadExtraSprites();
|
||||||
void ShiftTileRegisters();
|
void ShiftTileRegisters();
|
||||||
void InitializeShiftRegisters();
|
void InitializeShiftRegisters();
|
||||||
void LoadNextTile();
|
void LoadNextTile();
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace Mesen.GUI.Config
|
||||||
public bool AutoLoadIpsPatches = true;
|
public bool AutoLoadIpsPatches = true;
|
||||||
public bool AssociateNesFiles = false;
|
public bool AssociateNesFiles = false;
|
||||||
public bool AllowInvalidInput = false;
|
public bool AllowInvalidInput = false;
|
||||||
|
public bool RemoveSpriteLimit = false;
|
||||||
|
|
||||||
public bool UseAlternativeMmc3Irq = false;
|
public bool UseAlternativeMmc3Irq = false;
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ namespace Mesen.GUI.Config
|
||||||
|
|
||||||
InteropEmu.SetFlag(EmulationFlags.Mmc3IrqAltBehavior, preferenceInfo.UseAlternativeMmc3Irq);
|
InteropEmu.SetFlag(EmulationFlags.Mmc3IrqAltBehavior, preferenceInfo.UseAlternativeMmc3Irq);
|
||||||
InteropEmu.SetFlag(EmulationFlags.AllowInvalidInput, preferenceInfo.AllowInvalidInput);
|
InteropEmu.SetFlag(EmulationFlags.AllowInvalidInput, preferenceInfo.AllowInvalidInput);
|
||||||
|
InteropEmu.SetFlag(EmulationFlags.RemoveSpriteLimit, preferenceInfo.RemoveSpriteLimit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
GUI.NET/Forms/Config/frmPreferences.Designer.cs
generated
17
GUI.NET/Forms/Config/frmPreferences.Designer.cs
generated
|
@ -47,6 +47,7 @@
|
||||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||||
this.chkUseAlternativeMmc3Irq = new System.Windows.Forms.CheckBox();
|
this.chkUseAlternativeMmc3Irq = new System.Windows.Forms.CheckBox();
|
||||||
this.chkAllowInvalidInput = new System.Windows.Forms.CheckBox();
|
this.chkAllowInvalidInput = new System.Windows.Forms.CheckBox();
|
||||||
|
this.chkRemoveSpriteLimit = new System.Windows.Forms.CheckBox();
|
||||||
this.tlpMain.SuspendLayout();
|
this.tlpMain.SuspendLayout();
|
||||||
this.flowLayoutPanel6.SuspendLayout();
|
this.flowLayoutPanel6.SuspendLayout();
|
||||||
this.tabMain.SuspendLayout();
|
this.tabMain.SuspendLayout();
|
||||||
|
@ -273,10 +274,13 @@
|
||||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
this.tableLayoutPanel1.Controls.Add(this.chkUseAlternativeMmc3Irq, 0, 0);
|
this.tableLayoutPanel1.Controls.Add(this.chkUseAlternativeMmc3Irq, 0, 0);
|
||||||
this.tableLayoutPanel1.Controls.Add(this.chkAllowInvalidInput, 0, 1);
|
this.tableLayoutPanel1.Controls.Add(this.chkAllowInvalidInput, 0, 1);
|
||||||
|
this.tableLayoutPanel1.Controls.Add(this.chkRemoveSpriteLimit, 0, 2);
|
||||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3);
|
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3);
|
||||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||||
this.tableLayoutPanel1.RowCount = 2;
|
this.tableLayoutPanel1.RowCount = 4;
|
||||||
|
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||||
|
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(380, 207);
|
this.tableLayoutPanel1.Size = new System.Drawing.Size(380, 207);
|
||||||
|
@ -302,6 +306,16 @@
|
||||||
this.chkAllowInvalidInput.Text = "Allow invalid input (e.g Down + Up or Left + Right at the same time)";
|
this.chkAllowInvalidInput.Text = "Allow invalid input (e.g Down + Up or Left + Right at the same time)";
|
||||||
this.chkAllowInvalidInput.UseVisualStyleBackColor = true;
|
this.chkAllowInvalidInput.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
|
// chkRemoveSpriteLimit
|
||||||
|
//
|
||||||
|
this.chkRemoveSpriteLimit.AutoSize = true;
|
||||||
|
this.chkRemoveSpriteLimit.Location = new System.Drawing.Point(3, 49);
|
||||||
|
this.chkRemoveSpriteLimit.Name = "chkRemoveSpriteLimit";
|
||||||
|
this.chkRemoveSpriteLimit.Size = new System.Drawing.Size(205, 17);
|
||||||
|
this.chkRemoveSpriteLimit.TabIndex = 2;
|
||||||
|
this.chkRemoveSpriteLimit.Text = "Remove sprite limit (Reduces flashing)";
|
||||||
|
this.chkRemoveSpriteLimit.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
// frmPreferences
|
// frmPreferences
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
@ -352,5 +366,6 @@
|
||||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||||
private System.Windows.Forms.CheckBox chkUseAlternativeMmc3Irq;
|
private System.Windows.Forms.CheckBox chkUseAlternativeMmc3Irq;
|
||||||
private System.Windows.Forms.CheckBox chkAllowInvalidInput;
|
private System.Windows.Forms.CheckBox chkAllowInvalidInput;
|
||||||
|
private System.Windows.Forms.CheckBox chkRemoveSpriteLimit;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,6 +25,7 @@ namespace Mesen.GUI.Forms.Config
|
||||||
|
|
||||||
AddBinding("UseAlternativeMmc3Irq", chkUseAlternativeMmc3Irq);
|
AddBinding("UseAlternativeMmc3Irq", chkUseAlternativeMmc3Irq);
|
||||||
AddBinding("AllowInvalidInput", chkAllowInvalidInput);
|
AddBinding("AllowInvalidInput", chkAllowInvalidInput);
|
||||||
|
AddBinding("RemoveSpriteLimit", chkRemoveSpriteLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnFormClosed(FormClosedEventArgs e)
|
protected override void OnFormClosed(FormClosedEventArgs e)
|
||||||
|
|
|
@ -432,6 +432,7 @@ namespace Mesen.GUI
|
||||||
ShowFPS = 0x02,
|
ShowFPS = 0x02,
|
||||||
VerticalSync = 0x04,
|
VerticalSync = 0x04,
|
||||||
AllowInvalidInput = 0x08,
|
AllowInvalidInput = 0x08,
|
||||||
|
RemoveSpriteLimit = 0x10,
|
||||||
|
|
||||||
Mmc3IrqAltBehavior = 0x8000,
|
Mmc3IrqAltBehavior = 0x8000,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue