GBA: Regrettably add VBA bug compat mode

This commit is contained in:
Vicki Pfau 2020-11-29 13:41:53 -08:00
parent 60b59ae312
commit 20f8baa82c
8 changed files with 31 additions and 37 deletions

View File

@ -7,6 +7,7 @@ Features:
- Frame viewer support for Game Boy - Frame viewer support for Game Boy
- Mute option in homebrew ports - Mute option in homebrew ports
- Status indicators for fast-forward and mute in homebrew ports - Status indicators for fast-forward and mute in homebrew ports
- VBA bug compatibility mode for ROM hacks that don't work on real hardware
- Read-only support for MBC6 flash memory - Read-only support for MBC6 flash memory
- New unlicensed GB mappers: Pokémon Jade/Diamond, BBD, and Hitek - New unlicensed GB mappers: Pokémon Jade/Diamond, BBD, and Hitek
- Stack tracing tools in ARM debugger (by ahigerd) - Stack tracing tools in ARM debugger (by ahigerd)

View File

@ -116,6 +116,7 @@ struct GBA {
int32_t cachedRegisters[16]; int32_t cachedRegisters[16];
bool taintedRegisters[16]; bool taintedRegisters[16];
bool vbaBugCompat;
bool hardCrash; bool hardCrash;
bool allowOpposingDirections; bool allowOpposingDirections;

View File

@ -20,6 +20,7 @@ struct GBACartridgeOverride {
int hardware; int hardware;
uint32_t idleLoop; uint32_t idleLoop;
bool mirroring; bool mirroring;
bool vbaBugCompat;
}; };
struct Configuration; struct Configuration;

View File

@ -108,6 +108,7 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) {
gba->idleOptimization = IDLE_LOOP_REMOVE; gba->idleOptimization = IDLE_LOOP_REMOVE;
gba->idleLoop = IDLE_LOOP_NONE; gba->idleLoop = IDLE_LOOP_NONE;
gba->vbaBugCompat = false;
gba->hardCrash = true; gba->hardCrash = true;
gba->allowOpposingDirections = true; gba->allowOpposingDirections = true;

View File

@ -99,8 +99,12 @@ void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uin
} }
switch (address) { switch (address) {
case GPIO_REG_DATA: case GPIO_REG_DATA:
hw->pinState &= ~hw->direction; if (!hw->p->vbaBugCompat) {
hw->pinState |= value & hw->direction; hw->pinState &= ~hw->direction;
hw->pinState |= value & hw->direction;
} else {
hw->pinState = value;
}
_readPins(hw); _readPins(hw);
break; break;
case GPIO_REG_DIRECTION: case GPIO_REG_DIRECTION:

View File

@ -207,6 +207,7 @@ bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOver
override->hardware = HW_NONE; override->hardware = HW_NONE;
override->idleLoop = IDLE_LOOP_NONE; override->idleLoop = IDLE_LOOP_NONE;
override->mirroring = false; override->mirroring = false;
override->vbaBugCompat = false;
bool found = false; bool found = false;
int i; int i;
@ -320,6 +321,8 @@ void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* overri
GBASavedataForceType(&gba->memory.savedata, override->savetype); GBASavedataForceType(&gba->memory.savedata, override->savetype);
} }
gba->vbaBugCompat = override->vbaBugCompat;
if (override->hardware != HW_NO_OVERRIDE) { if (override->hardware != HW_NO_OVERRIDE) {
GBAHardwareClear(&gba->memory.hw); GBAHardwareClear(&gba->memory.hw);
@ -376,6 +379,7 @@ void GBAOverrideApplyDefaults(struct GBA* gba, const struct Configuration* overr
// Enable FLASH1M and RTC on Pokémon FireRed ROM hacks // Enable FLASH1M and RTC on Pokémon FireRed ROM hacks
override.savetype = SAVEDATA_FLASH1M; override.savetype = SAVEDATA_FLASH1M;
override.hardware = HW_RTC; override.hardware = HW_RTC;
override.vbaBugCompat = true;
GBAOverrideApply(gba, &override); GBAOverrideApply(gba, &override);
} else if (GBAOverrideFind(overrides, &override)) { } else if (GBAOverrideFind(overrides, &override)) {
GBAOverrideApply(gba, &override); GBAOverrideApply(gba, &override);

View File

@ -142,6 +142,7 @@ void OverrideView::updateOverrides() {
gba->override.hardware = HW_NO_OVERRIDE; gba->override.hardware = HW_NO_OVERRIDE;
gba->override.idleLoop = IDLE_LOOP_NONE; gba->override.idleLoop = IDLE_LOOP_NONE;
gba->override.mirroring = false; gba->override.mirroring = false;
gba->override.vbaBugCompat = false;
if (!m_ui.hwAutodetect->isChecked()) { if (!m_ui.hwAutodetect->isChecked()) {
gba->override.hardware = HW_NONE; gba->override.hardware = HW_NONE;
@ -164,6 +165,9 @@ void OverrideView::updateOverrides() {
if (m_ui.hwGBPlayer->isChecked()) { if (m_ui.hwGBPlayer->isChecked()) {
gba->override.hardware |= HW_GB_PLAYER_DETECTION; gba->override.hardware |= HW_GB_PLAYER_DETECTION;
} }
if (m_ui.vbaBugCompat->isChecked()) {
gba->override.vbaBugCompat = true;
}
bool ok; bool ok;
uint32_t parsedIdleLoop = m_ui.idleLoop->text().toInt(&ok, 16); uint32_t parsedIdleLoop = m_ui.idleLoop->text().toInt(&ok, 16);
@ -219,6 +223,7 @@ void OverrideView::gameStarted() {
m_ui.hwTilt->setChecked(gba->memory.hw.devices & HW_TILT); m_ui.hwTilt->setChecked(gba->memory.hw.devices & HW_TILT);
m_ui.hwRumble->setChecked(gba->memory.hw.devices & HW_RUMBLE); m_ui.hwRumble->setChecked(gba->memory.hw.devices & HW_RUMBLE);
m_ui.hwGBPlayer->setChecked(gba->memory.hw.devices & HW_GB_PLAYER_DETECTION); m_ui.hwGBPlayer->setChecked(gba->memory.hw.devices & HW_GB_PLAYER_DETECTION);
m_ui.vbaBugCompat->setChecked(gba->vbaBugCompat);
if (gba->idleLoop != IDLE_LOOP_NONE) { if (gba->idleLoop != IDLE_LOOP_NONE) {
m_ui.idleLoop->setText(QString::number(gba->idleLoop, 16)); m_ui.idleLoop->setText(QString::number(gba->idleLoop, 16));

View File

@ -175,41 +175,18 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <widget class="QCheckBox" name="hwGBPlayer">
<item> <property name="text">
<spacer name="horizontalSpacer"> <string>Game Boy Player features</string>
<property name="orientation"> </property>
<enum>Qt::Horizontal</enum> </widget>
</property> </item>
<property name="sizeHint" stdset="0"> <item>
<size> <widget class="QCheckBox" name="vbaBugCompat">
<width>0</width> <property name="text">
<height>0</height> <string>VBA bug compatibility mode</string>
</size> </property>
</property> </widget>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="hwGBPlayer">
<property name="text">
<string>Game Boy Player features</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item> </item>
</layout> </layout>
</widget> </widget>