Added option to boot up (some) mappers in a random state (useful for homebrew dev)

This commit is contained in:
Sour 2018-04-14 22:12:05 -04:00
parent fd4a8cbf43
commit 6d1ca4503e
26 changed files with 102 additions and 57 deletions

View file

@ -10,7 +10,7 @@ class AXROM : public BaseMapper
void InitMapper() override
{
SelectPRGPage(0, 0);
SelectPRGPage(0, GetPowerOnByte());
SelectCHRPage(0, 0);
}

View file

@ -330,6 +330,18 @@ void BaseMapper::InitializeRam(void* data, uint32_t length)
break;
}
}
uint8_t BaseMapper::GetPowerOnByte(uint8_t defaultValue)
{
if(EmulationSettings::CheckFlag(EmulationFlags::RandomizeMapperPowerOnState)) {
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<> dist(0, 255);
return dist(mt);
} else {
return defaultValue;
}
}
bool BaseMapper::HasBattery()
{

View file

@ -134,6 +134,8 @@ protected:
uint32_t GetPRGPageCount();
uint32_t GetCHRPageCount();
uint8_t GetPowerOnByte(uint8_t defaultValue = 0);
void RestoreOriginalPrgRam();
void InitializeChrRam(int32_t chrRamSize = -1);

View file

@ -10,7 +10,7 @@ protected:
void InitMapper() override
{
SelectPRGPage(0, 0);
SelectPRGPage(0, GetPowerOnByte());
SelectCHRPage(0, 0);
}

View file

@ -14,7 +14,7 @@ protected:
void InitMapper() override
{
SelectPRGPage(0, 0);
SelectCHRPage(0, 0);
SelectCHRPage(0, GetPowerOnByte());
//Needed for mighty bomb jack (j)
_vramOpenBusValue = 0xFF;

View file

@ -24,7 +24,7 @@ protected:
BaseMapper::InitializeRam(_extraNametables[i], 0x400);
AddNametable(4 + i, _extraNametables[i]);
}
_reg = 0;
_reg = GetPowerOnByte();
UpdateState();
}

View file

@ -80,6 +80,8 @@ enum EmulationFlags : uint64_t
AllowMismatchingSaveState = 0x10000000000000,
RandomizeMapperPowerOnState = 0x20000000000000,
ForceMaxSpeed = 0x4000000000000000,
ConsoleMode = 0x8000000000000000,
};

View file

@ -10,8 +10,8 @@ class GxRom : public BaseMapper
void InitMapper() override
{
SelectPRGPage(0, 0);
SelectCHRPage(0, 0);
SelectPRGPage(0, GetPowerOnByte() & 0x03);
SelectCHRPage(0, GetPowerOnByte() & 0x03);
}
void WriteRegister(uint16_t addr, uint8_t value) override

View file

@ -11,10 +11,10 @@ protected:
void InitMapper() override
{
SelectPRGPage(0, 0);
SelectPRGPage(0, GetPowerOnByte());
SelectPRGPage(1, -1);
SelectCHRPage(0, 0);
SelectCHRPage(0, GetPowerOnByte());
}
void WriteRegister(uint16_t addr, uint8_t value) override

View file

@ -179,9 +179,9 @@ class MMC1 : public BaseMapper
virtual void InitMapper() override
{
_state.Reg8000 = 0x0C; //On powerup: bits 2,3 of $8000 are set (this ensures the $8000 is bank 0, and $C000 is the last bank - needed for SEROM/SHROM/SH1ROM which do no support banking)
_state.RegA000 = 0x00;
_state.RegC000 = 0x00;
_state.Reg8000 = GetPowerOnByte(0x0C); //On powerup: bits 2,3 of $8000 are set (this ensures the $8000 is bank 0, and $C000 is the last bank - needed for SEROM/SHROM/SH1ROM which do no support banking)
_state.RegA000 = GetPowerOnByte();
_state.RegC000 = GetPowerOnByte();
_state.RegE000 = (_databaseInfo.Board.find("MMC1B") != string::npos ? 0x10 : 0x00); //WRAM Disable: enabled by default for MMC1B
//"MMC1A: PRG RAM is always enabled" - Normally these roms should be classified as mapper 155

View file

@ -29,18 +29,15 @@ class MMC2 : public BaseMapper
{
_leftLatch = 1;
_rightLatch = 1;
_leftChrPage[0] = 0;
_leftChrPage[1] = 0;
_rightChrPage[0] = 0;
_rightChrPage[1] = 0;
_leftChrPage[0] = GetPowerOnByte() & 0x1F;
_leftChrPage[1] = GetPowerOnByte() & 0x1F;
_rightChrPage[0] = GetPowerOnByte() & 0x1F;
_rightChrPage[1] = GetPowerOnByte() & 0x1F;
_needChrUpdate = false;
SelectPRGPage(0, 0);
SelectPRGPage(1, -3);
SelectPRGPage(2, -2);
SelectPRGPage(3, -1);
SelectCHRPage(0, 0);
SelectCHRPage(0, 1);
}
void StreamState(bool saving) override

View file

@ -68,21 +68,26 @@ class MMC3 : public BaseMapper
void ResetMmc3()
{
_state.Reg8000 = 0;
_state.RegA000 = 0;
_state.RegA001 = 0;
_chrMode = 0;
_prgMode = 0;
_currentRegister = 0;
memset(_registers, 0, sizeof(_registers));
_state.Reg8000 = GetPowerOnByte();
_state.RegA000 = GetPowerOnByte();
_state.RegA001 = GetPowerOnByte();
_chrMode = GetPowerOnByte() & 0x01;
_prgMode = GetPowerOnByte() & 0x01;
_currentRegister = GetPowerOnByte();
for(int i = 0; i < sizeof(_registers); i++) {
_registers[i] = GetPowerOnByte();
}
_irqCounter = 0;
_irqReloadValue = 0;
_irqReload = false;
_irqEnabled = false;
_irqCounter = GetPowerOnByte();
_irqReloadValue = GetPowerOnByte();
_irqReload = GetPowerOnByte() & 0x01;
_irqEnabled = GetPowerOnByte() & 0x01;
_wramEnabled = false;
_wramWriteProtected = false;
_wramEnabled = GetPowerOnByte() & 0x01;
_wramWriteProtected = GetPowerOnByte() & 0x01;
_needIrq = false;
}

View file

@ -12,15 +12,13 @@ class MMC4 : public MMC2
{
_leftLatch = 1;
_rightLatch = 1;
_leftChrPage[0] = 0;
_leftChrPage[1] = 0;
_rightChrPage[0] = 0;
_rightChrPage[1] = 0;
_leftChrPage[0] = GetPowerOnByte() & 0x1F;
_leftChrPage[1] = GetPowerOnByte() & 0x1F;
_rightChrPage[0] = GetPowerOnByte() & 0x1F;
_rightChrPage[1] = GetPowerOnByte() & 0x1F;
_needChrUpdate = false;
SelectPRGPage(0, 0);
SelectPRGPage(1, -1);
SelectCHRPage(0, 0);
SelectCHRPage(0, 1);
}
public:

View file

@ -11,8 +11,6 @@ protected:
void InitMapper() override
{
SelectPRGPage(0, 0);
SelectPRGPage(1, -1);
SelectCHRPage(0, 0);
}

View file

@ -85,12 +85,15 @@ class VRC2_4 : public BaseMapper
{
DetectVariant();
_prgMode = 0;
_prgReg0 = 0;
_prgReg1 = 0;
_prgMode = GetPowerOnByte() & 0x01;
_prgReg0 = GetPowerOnByte() & 0x1F;
_prgReg1 = GetPowerOnByte() & 0x1F;
_hasIRQ = false;
memset(_loCHRRegs, 0, sizeof(_loCHRRegs));
memset(_hiCHRRegs, 0, sizeof(_hiCHRRegs));
for(int i = 0; i < 8; i++) {
_loCHRRegs[i] = GetPowerOnByte() & 0x0F;
_hiCHRRegs[i] = GetPowerOnByte() & 0x1F;
}
UpdateState();
}

View file

@ -23,6 +23,7 @@ namespace Mesen.GUI.Config
public bool DisablePpuReset = false;
public bool EnableOamDecay = false;
public bool UseNes101Hvc101Behavior = false;
public bool EnableMapperRandomPowerOnState = false;
public bool UseAlternativeMmc3Irq = false;
@ -62,6 +63,7 @@ namespace Mesen.GUI.Config
InteropEmu.SetFlag(EmulationFlags.DisablePpuReset, emulationInfo.DisablePpuReset);
InteropEmu.SetFlag(EmulationFlags.EnableOamDecay, emulationInfo.EnableOamDecay);
InteropEmu.SetFlag(EmulationFlags.UseNes101Hvc101Behavior, emulationInfo.UseNes101Hvc101Behavior);
InteropEmu.SetFlag(EmulationFlags.RandomizeMapperPowerOnState, emulationInfo.EnableMapperRandomPowerOnState);
InteropEmu.SetOverclockRate(emulationInfo.OverclockRate, emulationInfo.OverclockAdjustApu);
InteropEmu.SetPpuNmiConfig(emulationInfo.PpuExtraScanlinesBeforeNmi, emulationInfo.PpuExtraScanlinesAfterNmi);

View file

@ -296,7 +296,8 @@
<Control ID="chkDisablePaletteRead">Impedeix la lectura de la paleta de la PPU</Control>
<Control ID="chkDisablePpuReset">No reestableixis la PPU al reiniciar la consola (comportament de la Famicom)</Control>
<Control ID="chkUseNes101Hvc101Behavior">Simula el comportament de la NES/HVC-101 (Top-loader / AV Famicom)</Control>
<Control ID="chkMapperRandomPowerOnState">Randomize power-on state for mappers</Control>
<Control ID="tpgOverclocking">Forçament</Control>
<Control ID="grpOverclocking">Forçament de CPU</Control>
<Control ID="lblOverclockWarning">ADVERTÈNCIA: El forçament de la CPU afecta a l'estabilitat de la emulació i pot causar fallades en alguns jocs.</Control>

View file

@ -295,7 +295,8 @@
<Control ID="chkDisablePaletteRead">Impedir la reproducción de la paleta de la PPU</Control>
<Control ID="chkDisablePpuReset">No resetear la PPU al resetear la consola (Famicom)</Control>
<Control ID="chkUseNes101Hvc101Behavior">Simular el comportamiento de NES/HVC-101 (Top-loader / AV Famicom)</Control>
<Control ID="chkMapperRandomPowerOnState">Randomize power-on state for mappers</Control>
<Control ID="tpgOverclocking">Overclocking</Control>
<Control ID="grpOverclocking">Overclocking de CPU</Control>
<Control ID="lblOverclockWarning">ATENCIÓN: ¡El overclocking afecta a la estabilidad de la emulación y puede bloquear algunos juegos!</Control>

View file

@ -295,6 +295,7 @@
<Control ID="chkDisablePaletteRead">Empêcher la lecture de la palette du PPU</Control>
<Control ID="chkDisablePpuReset">Ne pas faire un reset du PPU lors du reset de la console (Famicom)</Control>
<Control ID="chkUseNes101Hvc101Behavior">Simuler le comportement du NES/HVC-101 (Top Loader / AV Famicom)</Control>
<Control ID="chkMapperRandomPowerOnState">Démarrer le jeu avec le mapper dans un état aléatoire</Control>
<Control ID="lblRamPowerOnState">État initial de la mémoire au démarrage : </Control>

View file

@ -296,6 +296,7 @@
<Control ID="chkDisablePaletteRead">PPUのパレットラムを読み込み不可能にする</Control>
<Control ID="chkDisablePpuReset">ゲーム機をリセットする時に、PPUをリセットしない ファミコン同様</Control>
<Control ID="chkUseNes101Hvc101Behavior">AV仕様ファミコンHVC-101とNES-101の仕様を使う</Control>
<Control ID="chkMapperRandomPowerOnState">ランダムな状態でゲームを起動する</Control>
<Control ID="lblRamPowerOnState">起動時のメモリの状態 : </Control>

View file

@ -295,6 +295,7 @@
<Control ID="chkDisablePaletteRead">Desativar leitura da paleta da PPU</Control>
<Control ID="chkDisablePpuReset">Não reiniciar a PPU ao reiniciar o console (Comportamento do Famicom)</Control>
<Control ID="chkUseNes101Hvc101Behavior">Utilizar comportamento do NES/HVC-101 (Top-loader / AV Famicom)</Control>
<Control ID="chkMapperRandomPowerOnState">Randomize power-on state for mappers</Control>
<Control ID="tpgOverclocking">Overclock</Control>
<Control ID="grpOverclocking">Overclock da CPU</Control>

View file

@ -295,6 +295,7 @@
<Control ID="chkDisablePaletteRead">Disable PPU palette reads</Control>
<Control ID="chkDisablePpuReset">Do not reset PPU when resetting console (Famicom behavior)</Control>
<Control ID="chkUseNes101Hvc101Behavior">Use NES/HVC-101 (Top-loader / AV Famicom) behavior</Control>
<Control ID="chkMapperRandomPowerOnState">Randomize power-on state for mappers</Control>
<Control ID="tpgOverclocking">Разгон</Control>
<Control ID="grpOverclocking">Разгон CPU</Control>

View file

@ -295,6 +295,7 @@
<Control ID="chkDisablePaletteRead">Вiдключити PPU читання палiтри</Control>
<Control ID="chkDisablePpuReset">Не скидувати PPU при перезавантаженні консолі (Поведiнка Famicom)</Control>
<Control ID="chkUseNes101Hvc101Behavior">Використовувати NES/HVC-101 (Top-loader / AV Famicom) поведінку</Control>
<Control ID="chkMapperRandomPowerOnState">Randomize power-on state for mappers</Control>
<Control ID="tpgOverclocking">Розгін</Control>
<Control ID="grpOverclocking">Розгін CPU</Control>

View file

@ -88,6 +88,7 @@ namespace Mesen.GUI.Forms.Config
this.chkShowLagCounter = new System.Windows.Forms.CheckBox();
this.btnResetLagCounter = new System.Windows.Forms.Button();
this.tmrUpdateClockRate = new System.Windows.Forms.Timer(this.components);
this.chkMapperRandomPowerOnState = new Mesen.GUI.Controls.ctrlRiskyOption();
this.tabMain.SuspendLayout();
this.tpgGeneral.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
@ -111,7 +112,7 @@ namespace Mesen.GUI.Forms.Config
//
// baseConfigPanel
//
this.baseConfigPanel.Location = new System.Drawing.Point(0, 299);
this.baseConfigPanel.Location = new System.Drawing.Point(0, 321);
this.baseConfigPanel.Size = new System.Drawing.Size(533, 29);
//
// tabMain
@ -123,7 +124,7 @@ namespace Mesen.GUI.Forms.Config
this.tabMain.Location = new System.Drawing.Point(0, 0);
this.tabMain.Name = "tabMain";
this.tabMain.SelectedIndex = 0;
this.tabMain.Size = new System.Drawing.Size(533, 299);
this.tabMain.Size = new System.Drawing.Size(533, 321);
this.tabMain.TabIndex = 2;
//
// tpgGeneral
@ -349,7 +350,7 @@ namespace Mesen.GUI.Forms.Config
this.tpgAdvanced.Location = new System.Drawing.Point(4, 22);
this.tpgAdvanced.Name = "tpgAdvanced";
this.tpgAdvanced.Padding = new System.Windows.Forms.Padding(3);
this.tpgAdvanced.Size = new System.Drawing.Size(525, 273);
this.tpgAdvanced.Size = new System.Drawing.Size(525, 295);
this.tpgAdvanced.TabIndex = 1;
this.tpgAdvanced.Text = "Advanced";
this.tpgAdvanced.UseVisualStyleBackColor = true;
@ -358,9 +359,10 @@ namespace Mesen.GUI.Forms.Config
//
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.chkMapperRandomPowerOnState, 0, 10);
this.tableLayoutPanel1.Controls.Add(this.chkEnableOamDecay, 0, 4);
this.tableLayoutPanel1.Controls.Add(this.chkRemoveSpriteLimit, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel8, 0, 10);
this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel8, 0, 11);
this.tableLayoutPanel1.Controls.Add(this.chkDisablePaletteRead, 0, 8);
this.tableLayoutPanel1.Controls.Add(this.chkDisableOamAddrBug, 0, 7);
this.tableLayoutPanel1.Controls.Add(this.chkDisablePpuReset, 0, 5);
@ -372,7 +374,8 @@ namespace Mesen.GUI.Forms.Config
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 12;
this.tableLayoutPanel1.RowCount = 13;
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());
@ -385,7 +388,7 @@ namespace Mesen.GUI.Forms.Config
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.Size = new System.Drawing.Size(519, 267);
this.tableLayoutPanel1.Size = new System.Drawing.Size(519, 289);
this.tableLayoutPanel1.TabIndex = 0;
//
// chkEnableOamDecay
@ -415,7 +418,7 @@ namespace Mesen.GUI.Forms.Config
this.flowLayoutPanel8.Controls.Add(this.lblRamPowerOnState);
this.flowLayoutPanel8.Controls.Add(this.cboRamPowerOnState);
this.flowLayoutPanel8.Dock = System.Windows.Forms.DockStyle.Fill;
this.flowLayoutPanel8.Location = new System.Drawing.Point(0, 228);
this.flowLayoutPanel8.Location = new System.Drawing.Point(0, 253);
this.flowLayoutPanel8.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutPanel8.Name = "flowLayoutPanel8";
this.flowLayoutPanel8.Size = new System.Drawing.Size(519, 27);
@ -500,9 +503,9 @@ namespace Mesen.GUI.Forms.Config
this.chkAllowInvalidInput.Checked = false;
this.chkAllowInvalidInput.Dock = System.Windows.Forms.DockStyle.Fill;
this.chkAllowInvalidInput.Location = new System.Drawing.Point(0, 207);
this.chkAllowInvalidInput.MinimumSize = new System.Drawing.Size(0, 21);
this.chkAllowInvalidInput.MinimumSize = new System.Drawing.Size(0, 23);
this.chkAllowInvalidInput.Name = "chkAllowInvalidInput";
this.chkAllowInvalidInput.Size = new System.Drawing.Size(519, 21);
this.chkAllowInvalidInput.Size = new System.Drawing.Size(519, 23);
this.chkAllowInvalidInput.TabIndex = 1;
this.chkAllowInvalidInput.Text = "Allow invalid input (e.g Down + Up or Left + Right at the same time)";
//
@ -911,12 +914,24 @@ namespace Mesen.GUI.Forms.Config
this.tmrUpdateClockRate.Enabled = true;
this.tmrUpdateClockRate.Tick += new System.EventHandler(this.tmrUpdateClockRate_Tick);
//
// chkMapperRandomPowerOnState
//
this.chkMapperRandomPowerOnState.AutoSize = true;
this.chkMapperRandomPowerOnState.Checked = false;
this.chkMapperRandomPowerOnState.Dock = System.Windows.Forms.DockStyle.Fill;
this.chkMapperRandomPowerOnState.Location = new System.Drawing.Point(0, 230);
this.chkMapperRandomPowerOnState.MinimumSize = new System.Drawing.Size(0, 23);
this.chkMapperRandomPowerOnState.Name = "chkMapperRandomPowerOnState";
this.chkMapperRandomPowerOnState.Size = new System.Drawing.Size(519, 23);
this.chkMapperRandomPowerOnState.TabIndex = 11;
this.chkMapperRandomPowerOnState.Text = "Randomize power-on state for mappers";
//
// frmEmulationConfig
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.ClientSize = new System.Drawing.Size(533, 328);
this.ClientSize = new System.Drawing.Size(533, 350);
this.Controls.Add(this.tabMain);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
@ -1023,5 +1038,6 @@ namespace Mesen.GUI.Forms.Config
private MesenNumericUpDown nudRewindSpeed;
private System.Windows.Forms.Label lblRewindSpeedHint;
private System.Windows.Forms.CheckBox chkAdaptiveSpriteLimit;
private ctrlRiskyOption chkMapperRandomPowerOnState;
}
}

View file

@ -38,6 +38,7 @@ namespace Mesen.GUI.Forms.Config
AddBinding("DisablePpuReset", chkDisablePpuReset);
AddBinding("EnableOamDecay", chkEnableOamDecay);
AddBinding("UseNes101Hvc101Behavior", chkUseNes101Hvc101Behavior);
AddBinding("EnableMapperRandomPowerOnState", chkMapperRandomPowerOnState);
AddBinding("OverclockRate", nudOverclockRate);
AddBinding("OverclockAdjustApu", chkOverclockAdjustApu);

View file

@ -1540,6 +1540,8 @@ namespace Mesen.GUI
AllowMismatchingSaveStates = 0x10000000000000,
RandomizeMapperPowerOnState = 0x20000000000000,
ForceMaxSpeed = 0x4000000000000000,
ConsoleMode = 0x8000000000000000,
}