Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 48 additions & 70 deletions src/core/gb/gb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2207,82 +2207,60 @@ uint8_t gbReadMemory(uint16_t address)

int b = gbMemory[0xff00];

if ((b & 0x30) == 0x20) {
b &= 0xf0;

int joy = 0;
if (gbSgbMode && gbSgbMultiplayer) {
switch (gbSgbNextController) {
case 0x0f:
joy = 0;
break;
case 0x0e:
joy = 1;
break;
case 0x0d:
joy = 2;
break;
case 0x0c:
joy = 3;
break;
default:
joy = 0;
}
}
int joystate = gbJoymask[joy];
if (!(joystate & 128))
b |= 0x08;
if (!(joystate & 64))
b |= 0x04;
if (!(joystate & 32))
b |= 0x02;
if (!(joystate & 16))
b |= 0x01;

gbMemory[0xff00] = (uint8_t)b;
} else if ((b & 0x30) == 0x10) {
b &= 0xf0;

int joy = 0;
if (gbSgbMode && gbSgbMultiplayer) {
switch (gbSgbNextController) {
case 0x0f:
joy = 0;
break;
case 0x0e:
joy = 1;
break;
case 0x0d:
joy = 2;
break;
case 0x0c:
joy = 3;
break;
default:
joy = 0;
}
// Choose joystick index for SGB multiplayer if enabled, otherwise 0
int joy = 0;

if (gbSgbMode && gbSgbMultiplayer) {
switch (gbSgbNextController) {
case 0x0f: joy = 0; break;
case 0x0e: joy = 1; break;
case 0x0d: joy = 2; break;
case 0x0c: joy = 3; break;
default: joy = 0; break;
}
int joystate = gbJoymask[joy];
if (!(joystate & 8))
b |= 0x08;
if (!(joystate & 4))
b |= 0x04;
if (!(joystate & 2))
b |= 0x02;
if (!(joystate & 1))
b |= 0x01;

gbMemory[0xff00] = (uint8_t)b;
} else {
}

int joystate = gbJoymask[joy];

if (gbSgbMode && gbSgbMultiplayer) {
}

// Bit 7 - Not used
// Bit 6 - Not used
// Bit 5 - P15 Select Action buttons (0=Select)
// Bit 4 - P14 Select Direction buttons (0=Select)
// Bit 3 - P13 Input: Down or Start (0=Pressed) (Read Only)
// Bit 2 - P12 Input: Up or Select (0=Pressed) (Read Only)
// Bit 1 - P11 Input: Left or B (0=Pressed) (Read Only)
// Bit 0 - P10 Input: Right or A (0=Pressed) (Read Only)
uint8_t data_dir =
(!(joystate & 0x80) ? 0x08 : 0x00) | // Down -> bit3
(!(joystate & 0x40) ? 0x04 : 0x00) | // Up -> bit2
(!(joystate & 0x20) ? 0x02 : 0x00) | // Left -> bit1
(!(joystate & 0x10) ? 0x01 : 0x00); // Right-> bit0

uint8_t data_action =
(!(joystate & 0x08) ? 0x08 : 0x00) | // Start -> bit3
(!(joystate & 0x04) ? 0x04 : 0x00) | // Select -> bit2
(!(joystate & 0x02) ? 0x02 : 0x00) | // B -> bit1
(!(joystate & 0x01) ? 0x01 : 0x00); // A -> bit0

b &= 0xf0; // keep selector bits in upper nibble
switch (b & 0x30) {
case 0x00: b |= data_dir & data_action; break;
case 0x10: b |= data_action; break;
case 0x20: b |= data_dir; break;
case 0x30:
if (gbSgbMode && gbSgbMultiplayer) {
gbMemory[0xff00] = 0xf0 | gbSgbNextController;
b = 0xf0 | gbSgbNextController;
} else {
gbMemory[0xff00] = 0xff;
b = 0xff;
}
break;
}
gbMemory[0xff00] = b;
}
}
return gbMemory[0xff00];
break;
case 0x01:
return gbMemory[0xff01];
case 0x02:
Expand Down
125 changes: 84 additions & 41 deletions src/core/gba/gbaInline.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,31 @@ static inline uint16_t ROMReadOOB(uint32_t address) {
return (address >> 1) & 0xFFFF;
}

static inline bool IsGPIO(uint32_t address) {
// TODO: Need to check which GPIO feature really is enabled
return (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8);
}

// used for ROM boundary check
static inline bool IsEEPROM(uint32_t address) {
return (cpuEEPROMEnabled && (address & eepromMask) == eepromMask);
}

static inline bool isSaveGame() {
return (coreOptions.saveType != 5) && (!eepromInUse || cpuSramEnabled || cpuFlashEnabled);
}

// Reads sram or flash
static inline uint8_t CPUReadBackup(uint32_t address) {
return flashRead(address);
}

// writes sram or flash
static inline void CPUWriteBackup(uint32_t address, uint8_t value) {
if (cpuSaveGameFunc)
(*cpuSaveGameFunc)(address, value);
}

static inline uint32_t CPUReadMemory(uint32_t address)
{
#ifdef VBAM_ENABLE_DEBUGGER
Expand All @@ -133,7 +158,7 @@ static inline uint32_t CPUReadMemory(uint32_t address)
}
}
#endif
uint32_t value = 0xFFFFFFFF;
uint32_t value = 0;

switch (address >> 24) {
case REGION_BIOS:
Expand Down Expand Up @@ -194,27 +219,34 @@ static inline uint32_t CPUReadMemory(uint32_t address)
case REGION_ROM1:
case REGION_ROM1EX:
case REGION_ROM2:
if ((address & 0x01FFFFFC) <= (gbaGetRomSize() - 4))
if (IsEEPROM(address))
return 0; // ignore reads from eeprom region outside 0x0D page reads
else if ((address & 0x01FFFFFC) <= (gbaGetRomSize() - 4))
value = READ32LE(((uint32_t *)&g_rom[address & 0x01FFFFFC]));
else if (cpuEEPROMEnabled && ((address & eepromMask) == eepromMask))
return 0; // ignore reads from eeprom region outside 0x0D page reads
else {
value = (uint16_t)ROMReadOOB(address & 0x01FFFFFC);
value |= (uint16_t)ROMReadOOB((address & 0x01FFFFFC) + 2) << 16;
}
break;
case REGION_ROM2EX:
if (cpuEEPROMEnabled)
// no need to swap this
return eepromRead(address);
goto unreadable;
case REGION_SRAM:
case REGION_SRAMEX:
if (cpuFlashEnabled | cpuSramEnabled) { // no need to swap this
value = flashRead(address) * 0x01010101;
if (isSaveGame()) {
value = CPUReadBackup(address) * 0x01010101;
break;
}
/* fallthrough */
#ifdef GBA_LOGGING
// Just normal log, not openbus
if (systemVerbose & VERBOSE_ILLEGAL_READ) {
log("Illegal word read: %08x at %08x\n",
address,
armMode ? armNextPC - 4 : armNextPC - 2);
}
#endif
return 0xffffffff;
default:
unreadable:
#ifdef GBA_LOGGING
Expand Down Expand Up @@ -274,7 +306,7 @@ static inline uint32_t CPUReadHalfWord(uint32_t address)
}
#endif

uint32_t value = 0xFFFFFFFF;
uint32_t value = 0;

switch (address >> 24) {
case REGION_BIOS:
Expand Down Expand Up @@ -349,28 +381,35 @@ static inline uint32_t CPUReadHalfWord(uint32_t address)
case REGION_ROM1:
case REGION_ROM1EX:
case REGION_ROM2:
if ((address & 0x01FFFFFE) <= (gbaGetRomSize() - 2))
value = READ16LE(((uint16_t *)&g_rom[address & 0x01FFFFFE]));
else if (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
if (IsGPIO(address))
value = rtcRead(address);
else if (cpuEEPROMEnabled && ((address & eepromMask) == eepromMask))
else if (IsEEPROM(address))
return 0; // ignore reads from eeprom region outside 0x0D page reads
else if ((address & 0x01FFFFFE) <= (gbaGetRomSize() - 2))
value = READ16LE(((uint16_t *)&g_rom[address & 0x01FFFFFE]));
else
value = (uint16_t)ROMReadOOB(address & 0x01FFFFFE);
break;
case REGION_ROM2EX:
if (cpuEEPROMEnabled)
// no need to swap this
return eepromRead(address);
goto unreadable;
case REGION_SRAM:
case REGION_SRAMEX:
if (cpuFlashEnabled | cpuSramEnabled) {
// no need to swap this
value = flashRead(address) * 0x0101;
if (isSaveGame()) {
value = CPUReadBackup(address) * 0x0101;
break;
}
/* fallthrough */
#ifdef GBA_LOGGING
// Just normal log, not openbus
if (systemVerbose & VERBOSE_ILLEGAL_READ) {
log("Illegal halfword read: %08x at %08x (%08x)\n",
address,
reg[15].I,
value);
}
#endif
return 0xffff;
default:
unreadable:
#ifdef GBA_LOGGING
Expand Down Expand Up @@ -469,20 +508,21 @@ static inline uint8_t CPUReadByte(uint32_t address)
case REGION_ROM1:
case REGION_ROM1EX:
case REGION_ROM2:
if ((address & 0x01FFFFFF) <= gbaGetRomSize())
return g_rom[address & 0x01FFFFFF];
else if (cpuEEPROMEnabled && ((address & eepromMask) == eepromMask))
if (IsEEPROM(address))
return 0; // ignore reads from eeprom region outside 0x0D page reads
return (uint8_t)ROMReadOOB(address & 0x01FFFFFE);
else if ((address & 0x01FFFFFF) <= gbaGetRomSize())
return g_rom[address & 0x01FFFFFF];
else
return (uint8_t)ROMReadOOB(address & 0x01FFFFFE);
case REGION_ROM2EX:
if (cpuEEPROMEnabled)
return DowncastU8(eepromRead(address));
goto unreadable;
case REGION_SRAM:
case REGION_SRAMEX:
if (cpuSramEnabled | cpuFlashEnabled)
return flashRead(address);

if (isSaveGame()) {
return CPUReadBackup(address);
}
switch (address & 0x00008f00) {
case 0x8200:
return DowncastU8(systemGetSensorX());
Expand All @@ -493,7 +533,15 @@ static inline uint8_t CPUReadByte(uint32_t address)
case 0x8500:
return DowncastU8(systemGetSensorY() >> 8);
}
return 0xFF;
#ifdef GBA_LOGGING
// Just normal log, not openbus
if (systemVerbose & VERBOSE_ILLEGAL_READ) {
log("Illegal byte read: %08x at %08x\n",
address,
armMode ? armNextPC - 4 : armNextPC - 2);
}
#endif
return 0xff;
default:
unreadable:
#ifdef GBA_LOGGING
Expand Down Expand Up @@ -603,12 +651,11 @@ static inline void CPUWriteMemory(uint32_t address, uint32_t value)
goto unwritable;
case REGION_SRAM:
case REGION_SRAMEX:
if ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) {
(*cpuSaveGameFunc)(address, (uint8_t)(value >> (8 * (address & 3))));
if (isSaveGame()) {
CPUWriteBackup(address, (uint8_t)(value >> (8 * (address & 3))));
break;
}
goto unwritable;
// fallthrough
// fallthrough
default:
unwritable:
#ifdef GBA_LOGGING
Expand Down Expand Up @@ -704,7 +751,7 @@ static inline void CPUWriteHalfWord(uint32_t address, uint16_t value)
GBAMatrixWrite16(&GBAMatrix, address & 0x3C, value);
break;
}
if (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) {
if (IsGPIO(address)) {
if (!rtcWrite(address, value))
goto unwritable;
} else if (!agbPrintWrite(address, value))
Expand All @@ -727,11 +774,11 @@ static inline void CPUWriteHalfWord(uint32_t address, uint16_t value)
goto unwritable;
case REGION_SRAM:
case REGION_SRAMEX:
if ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) {
(*cpuSaveGameFunc)(address, (uint8_t)(value >> (8 * (address & 1))));
if (isSaveGame()) {
CPUWriteBackup(address, (uint8_t)(value >> (8 * (address & 1))));
break;
}
/* fallthrough */
// fallthrough
default:
unwritable:
#ifdef GBA_LOGGING
Expand Down Expand Up @@ -867,9 +914,6 @@ static inline void CPUWriteByte(uint32_t address, uint8_t b)
}
break;
case REGION_OAM:
// no need to switch
// byte writes to OAM are ignored
// *((uint16_t *)&g_oam[address & 0x3FE]) = (b << 8) | b;
break;
case REGION_ROM2EX:
if (cpuEEPROMEnabled) {
Expand All @@ -879,12 +923,11 @@ static inline void CPUWriteByte(uint32_t address, uint8_t b)
goto unwritable;
case REGION_SRAM:
case REGION_SRAMEX:
if ((coreOptions.saveType != 5) && ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled)) {
(*cpuSaveGameFunc)(address, b);
if (isSaveGame()) {
CPUWriteBackup(address, b);
break;
}
goto unwritable;
// default
// fallthrough
default:
unwritable:
#ifdef GBA_LOGGING
Expand Down
Loading
Loading