Merge pull request #122 from death-droid/NrageChanges

NRage GBCart, use actual address ranges rather than hacky method. No rea...
This commit is contained in:
zilmar 2015-02-24 05:26:27 +11:00
commit 67deab4699
1 changed files with 208 additions and 138 deletions

View File

@ -535,8 +535,10 @@ bool WriteCartNorm(LPGBCART Cart, WORD dwAddress, BYTE *Data)
return true; return true;
} }
if (Cart->RomData[0x149] == 1) { // Whoops... Only 1/4 of the RAM space is used. if (Cart->RomData[0x149] == 1)
if ((dwAddress >= 0xA000) && (dwAddress <= 0xA7FF)) { // Write to RAM { // Whoops... Only 1/4 of the RAM space is used.
if ((dwAddress >= 0xA000) && (dwAddress <= 0xA7FF))
{ // Write to RAM
DebugWriteA("RAM write: Unbanked\n"); DebugWriteA("RAM write: Unbanked\n");
CopyMemory(&Cart->RamData[dwAddress - 0xA000], Data, 32); CopyMemory(&Cart->RamData[dwAddress - 0xA000], Data, 32);
} }
@ -544,8 +546,11 @@ bool WriteCartNorm(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
DebugWriteA("RAM write: Unbanked (out of range!)\n"); DebugWriteA("RAM write: Unbanked (out of range!)\n");
} }
} else { }
if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) { // Write to RAM else
{
if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF))
{ // Write to RAM
DebugWriteA("RAM write: Unbanked\n"); DebugWriteA("RAM write: Unbanked\n");
CopyMemory(&Cart->RamData[dwAddress - 0xA000], Data, 32); CopyMemory(&Cart->RamData[dwAddress - 0xA000], Data, 32);
} }
@ -556,15 +561,13 @@ bool WriteCartNorm(LPGBCART Cart, WORD dwAddress, BYTE *Data)
// Done // Done
bool ReadCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data) bool ReadCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
switch (dwAddress >> 13) if ((dwAddress >= 0) && (dwAddress <= 0x3FFF))
{ {
case 0:
case 1: // if ((dwAddress >= 0) && (dwAddress <= 0x3FFF))
CopyMemory(Data, &Cart->RomData[dwAddress], 32); CopyMemory(Data, &Cart->RomData[dwAddress], 32);
DebugWriteA("Nonbanked ROM read - MBC1\n"); DebugWriteA("Nonbanked ROM read - MBC1\n");
break; }
case 2: else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF))
case 3: // else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF)) {
if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks) if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks)
{ {
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
@ -576,22 +579,30 @@ bool ReadCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data)
CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo << 14)], 32); CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo << 14)], 32);
DebugWriteA("Banked ROM read: Bank %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Banked ROM read: Bank %02X\n", Cart->iCurrentRomBankNo);
} }
break; }
case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF))
if (Cart->bHasRam){ // && Cart->bRamEnableState) { {
if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks) { if (Cart->bHasRam)
{ // && Cart->bRamEnableState) {
if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks)
{
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
DebugWriteA("Failed RAM read: (Banking Error) %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("Failed RAM read: (Banking Error) %02X\n", Cart->iCurrentRamBankNo);
} else { }
else
{
CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], 32); CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], 32);
DebugWriteA("RAM read: Bank %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("RAM read: Bank %02X\n", Cart->iCurrentRamBankNo);
} }
} else { }
else
{
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
DebugWriteA("Failed RAM read: (RAM not present)\n"); DebugWriteA("Failed RAM read: (RAM not present)\n");
} }
break; }
default: else
{
DebugWriteA("Bad read from MBC1 cart, address %04X\n", dwAddress); DebugWriteA("Bad read from MBC1 cart, address %04X\n", dwAddress);
} }
@ -601,37 +612,43 @@ bool ReadCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data)
// Done // Done
bool WriteCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data) bool WriteCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
switch (dwAddress >> 13) if ((dwAddress >= 0x0000) && (dwAddress <= 0x1FFF)) // RAM enable
{ {
case 0: // if ((dwAddress >= 0) && (dwAddress <= 0x1FFF)) // RAM enable
Cart->bRamEnableState = (Data[0] == 0x0A); Cart->bRamEnableState = (Data[0] == 0x0A);
DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState); DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState);
break; }
case 1: // else if ((dwAddress >= 0x2000) && (dwAddress <= 0x3FFF)) // ROM bank select else if ((dwAddress >= 0x2000) && (dwAddress <= 0x3FFF)) // ROM bank select
{
Cart->iCurrentRomBankNo &= 0x60; // keep MSB Cart->iCurrentRomBankNo &= 0x60; // keep MSB
Cart->iCurrentRomBankNo |= Data[0] & 0x1F; Cart->iCurrentRomBankNo |= Data[0] & 0x1F;
// emulate quirk: 0x00 -> 0x01, 0x20 -> 0x21, 0x40->0x41, 0x60 -> 0x61 // emulate quirk: 0x00 -> 0x01, 0x20 -> 0x21, 0x40->0x41, 0x60 -> 0x61
if ((Cart->iCurrentRomBankNo & 0x1F) == 0) { if ((Cart->iCurrentRomBankNo & 0x1F) == 0)
{
Cart->iCurrentRomBankNo |= 0x01; Cart->iCurrentRomBankNo |= 0x01;
} }
DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo);
break; }
case 2: // else if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM bank select else if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM bank select
if (Cart->bMBC1RAMbanking) { {
if (Cart->bMBC1RAMbanking)
{
Cart->iCurrentRamBankNo = Data[0] & 0x03; Cart->iCurrentRamBankNo = Data[0] & 0x03;
DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo);
} }
else { else
{
Cart->iCurrentRomBankNo &= 0x1F; Cart->iCurrentRomBankNo &= 0x1F;
Cart->iCurrentRomBankNo |= ((Data[0] & 0x03) << 5); // set bits 5 and 6 of ROM bank Cart->iCurrentRomBankNo |= ((Data[0] & 0x03) << 5); // set bits 5 and 6 of ROM bank
DebugWriteA("Set ROM Bank MSB, ROM bank now: %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Set ROM Bank MSB, ROM bank now: %02X\n", Cart->iCurrentRomBankNo);
} }
break; }
case 3: // else if ((dwAddress >= 0x6000) && (dwAddress <= 0x7FFF)) // MBC1 mode select else if ((dwAddress >= 0x6000) && (dwAddress <= 0x7FFF)) // MBC1 mode select
{
// this is overly complicated, but it keeps us from having to do bitwise math later // this is overly complicated, but it keeps us from having to do bitwise math later
// Basically we shuffle the 2 "magic bits" between iCurrentRomBankNo and iCurrentRamBankNo as necessary. // Basically we shuffle the 2 "magic bits" between iCurrentRomBankNo and iCurrentRamBankNo as necessary.
if (Cart->bMBC1RAMbanking != (Data[0] & 0x01)) { if (Cart->bMBC1RAMbanking != (Data[0] & 0x01))
{
// we should only alter the ROM and RAM bank numbers if we have changed modes // we should only alter the ROM and RAM bank numbers if we have changed modes
Cart->bMBC1RAMbanking = Data[0] & 0x01; Cart->bMBC1RAMbanking = Data[0] & 0x01;
if (Cart->bMBC1RAMbanking) if (Cart->bMBC1RAMbanking)
@ -651,9 +668,9 @@ bool WriteCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
DebugWriteA("Already in MBC1 mode: %s\n", Cart->bMBC1RAMbanking ? "ROMbanking" : "RAMbanking"); DebugWriteA("Already in MBC1 mode: %s\n", Cart->bMBC1RAMbanking ? "ROMbanking" : "RAMbanking");
} }
}
break; else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) // Write to RAM
case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) // Write to RAM {
if (Cart->bHasRam) // && Cart->bRamEnableState) if (Cart->bHasRam) // && Cart->bRamEnableState)
{ {
DebugWriteA("RAM write: Bank %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("RAM write: Bank %02X\n", Cart->iCurrentRamBankNo);
@ -663,8 +680,9 @@ bool WriteCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
DebugWriteA("Failed RAM write: (RAM not present)\n"); DebugWriteA("Failed RAM write: (RAM not present)\n");
} }
break; }
default: else
{
DebugWriteA("Bad write to MBC1 cart, address %04X\n", dwAddress); DebugWriteA("Bad write to MBC1 cart, address %04X\n", dwAddress);
} }
@ -674,33 +692,39 @@ bool WriteCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data)
// Done // Done
bool ReadCartMBC2(LPGBCART Cart, WORD dwAddress, BYTE *Data) bool ReadCartMBC2(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
switch (dwAddress >> 13) if ((dwAddress <= 0x3FFF))
{ {
case 0:
case 1: // if ((dwAddress <= 0x3FFF))
CopyMemory(Data, &Cart->RomData[dwAddress], 32); CopyMemory(Data, &Cart->RomData[dwAddress], 32);
DebugWriteA("Nonbanked ROM read - MBC2\n"); DebugWriteA("Nonbanked ROM read - MBC2\n");
break; }
case 2: else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF))
case 3: // else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF)) {
if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks) { if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks)
{
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
DebugWriteA("Banked ROM read: (Banking Error) %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Banked ROM read: (Banking Error) %02X\n", Cart->iCurrentRomBankNo);
} else { }
else
{
CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo << 14)], 32); CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo << 14)], 32);
DebugWriteA("Banked ROM read: Bank %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Banked ROM read: Bank %02X\n", Cart->iCurrentRomBankNo);
} }
break; }
case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF))
if (Cart->bHasRam && Cart->bRamEnableState) { {
if (Cart->bHasRam && Cart->bRamEnableState)
{
CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000], 32); CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000], 32);
DebugWriteA("RAM read: Unbanked\n"); DebugWriteA("RAM read: Unbanked\n");
} else { }
else
{
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
DebugWriteA("Failed RAM read: (RAM not present or not active)\n"); DebugWriteA("Failed RAM read: (RAM not present or not active)\n");
} }
break; }
default: else
{
DebugWriteA("Bad read from MBC2 cart, address %04X\n", dwAddress); DebugWriteA("Bad read from MBC2 cart, address %04X\n", dwAddress);
} }
@ -710,32 +734,37 @@ bool ReadCartMBC2(LPGBCART Cart, WORD dwAddress, BYTE *Data)
// Done // Done
bool WriteCartMBC2(LPGBCART Cart, WORD dwAddress, BYTE *Data) bool WriteCartMBC2(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
switch (dwAddress >> 13) if ((dwAddress >= 0x0000) && (dwAddress <= 0x1FFF)) // We shouldn't be able to read/write to RAM unless this is toggled on
{ {
case 0: // if ((dwAddress <= 0x1FFF)) // We shouldn't be able to read/write to RAM unless this is toggled on
Cart->bRamEnableState = (Data[0] == 0x0A); Cart->bRamEnableState = (Data[0] == 0x0A);
DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState); DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState);
break; }
case 1: // else if ((dwAddress >= 0x2000) && (dwAddress <= 0x3FFF)) // ROM bank select else if ((dwAddress >= 0x2000) && (dwAddress <= 0x3FFF)) // ROM bank select
{
Cart->iCurrentRomBankNo = Data[0] & 0x0F; Cart->iCurrentRomBankNo = Data[0] & 0x0F;
if (Cart->iCurrentRomBankNo == 0) { if (Cart->iCurrentRomBankNo == 0) {
Cart->iCurrentRomBankNo = 1; Cart->iCurrentRomBankNo = 1;
} }
DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo);
break; }
case 2: // if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM bank select else if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM bank select
if (Cart->bHasRam) { {
if (Cart->bHasRam)
{
Cart->iCurrentRamBankNo = Data[0] & 0x07; Cart->iCurrentRamBankNo = Data[0] & 0x07;
DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo);
} }
break; }
case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF) && Cart->bRamEnableState) // Write to RAM else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF) && Cart->bRamEnableState) // Write to RAM
if (Cart->bHasRam) { {
if (Cart->bHasRam)
{
DebugWriteA("RAM write: Bank %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("RAM write: Bank %02X\n", Cart->iCurrentRamBankNo);
CopyMemory(&Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], Data, 32); CopyMemory(&Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], Data, 32);
} }
break; }
default: else
{
DebugWriteA("Bad write to MBC2 cart, address %04X\n", dwAddress); DebugWriteA("Bad write to MBC2 cart, address %04X\n", dwAddress);
} }
@ -745,43 +774,50 @@ bool WriteCartMBC2(LPGBCART Cart, WORD dwAddress, BYTE *Data)
// Done // Done
bool ReadCartMBC3(LPGBCART Cart, WORD dwAddress, BYTE *Data) bool ReadCartMBC3(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
int i; if ((dwAddress < 0x4000)) //Rom Bank 0
switch (dwAddress >> 13)
{ {
case 0:
case 1: // if ((dwAddress <= 0x3FFF))
CopyMemory(Data, &Cart->RomData[dwAddress], 32); CopyMemory(Data, &Cart->RomData[dwAddress], 32);
DebugWriteA("Nonbanked ROM read - MBC3\n"); DebugWriteA("Nonbanked ROM read - MBC3\n");
break; }
case 2: else if ((dwAddress >= 0x4000) && (dwAddress < 0x8000)) //Switchable Rom Bank
case 3: // else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF)) {
if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks) { if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks)
{
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
DebugWriteA("Banked ROM read: (Banking Error) %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Banked ROM read: (Banking Error) %02X\n", Cart->iCurrentRomBankNo);
} else { }
else
{
CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo * 0x4000)], 32); CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo * 0x4000)], 32);
DebugWriteA("Banked ROM read: Bank %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Banked ROM read: Bank %02X\n", Cart->iCurrentRomBankNo);
} }
break; }
case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) else if ((dwAddress >= 0xA000) && (dwAddress <= 0xC000)) //Upper Bounds of memory map
if (Cart->bHasTimer && (Cart->iCurrentRamBankNo >= 0x08 && Cart->iCurrentRamBankNo <= 0x0c)) { {
if (Cart->bHasTimer && (Cart->iCurrentRamBankNo >= 0x08 && Cart->iCurrentRamBankNo <= 0x0c))
{
// w00t! the Timer was just read!! // w00t! the Timer was just read!!
if (Cart->TimerDataLatched) { if (Cart->TimerDataLatched)
for (i=0; i<32; i++) {
for (int i = 0; i < 32; i++)
Data[i] = Cart->LatchedTimerData[Cart->iCurrentRamBankNo - 0x08]; Data[i] = Cart->LatchedTimerData[Cart->iCurrentRamBankNo - 0x08];
} else { }
else
{
UpdateRTC(Cart); UpdateRTC(Cart);
for (i=0; i<32; i++) for (int i = 0; i < 32; i++)
Data[i] = Cart->TimerData[Cart->iCurrentRamBankNo - 0x08]; Data[i] = Cart->TimerData[Cart->iCurrentRamBankNo - 0x08];
} }
} }
else if (Cart->bHasRam) { else if (Cart->bHasRam)
if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks) { {
if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks)
{
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
DebugWriteA("Failed RAM read: (Banking Error) %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("Failed RAM read: (Banking Error) %02X\n", Cart->iCurrentRamBankNo);
} }
else { else
{
CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo * 0x2000)], 32); CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo * 0x2000)], 32);
DebugWriteA("RAM read: Bank %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("RAM read: Bank %02X\n", Cart->iCurrentRamBankNo);
} }
@ -790,12 +826,15 @@ bool ReadCartMBC3(LPGBCART Cart, WORD dwAddress, BYTE *Data)
// //for (i=0; i<32; i++) Data[i] = 0; // //for (i=0; i<32; i++) Data[i] = 0;
// DebugWriteA("Failed RAM read: (RAM not active)\n"); // DebugWriteA("Failed RAM read: (RAM not active)\n");
//} //}
} else { }
else
{
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
DebugWriteA("Failed RAM read: (RAM not present)\n"); DebugWriteA("Failed RAM read: (RAM not present)\n");
} }
break; }
default: else
{
DebugWriteA("Bad read from MBC3 cart, address %04X\n", dwAddress); DebugWriteA("Bad read from MBC3 cart, address %04X\n", dwAddress);
} }
@ -807,56 +846,69 @@ bool WriteCartMBC3(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
int i; int i;
switch (dwAddress >> 13) if ((dwAddress >= 0x0000) && (dwAddress <= 0x1FFF)) // We shouldn't be able to read/write to RAM unless this is toggled on
{ {
case 0: // if ((dwAddress <= 0x1FFF)) // We shouldn't be able to read/write to RAM unless this is toggled on
Cart->bRamEnableState = (Data[0] == 0x0A); Cart->bRamEnableState = (Data[0] == 0x0A);
DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState); DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState);
break; }
case 1: // else if ((dwAddress >= 0x2000) && (dwAddress <= 0x3FFF)) // ROM bank select else if ((dwAddress >= 0x2000) && (dwAddress <= 0x3FFF)) // ROM bank select
{
Cart->iCurrentRomBankNo = Data[0] & 0x7F; Cart->iCurrentRomBankNo = Data[0] & 0x7F;
if (Cart->iCurrentRomBankNo == 0) { if (Cart->iCurrentRomBankNo == 0) {
Cart->iCurrentRomBankNo = 1; Cart->iCurrentRomBankNo = 1;
} }
DebugWriteA("Set Rom Bank: %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Set Rom Bank: %02X\n", Cart->iCurrentRomBankNo);
break; }
case 2: // if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM/Clock bank select else if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM/Clock bank select
if (Cart->bHasRam) { {
if (Cart->bHasRam)
{
Cart->iCurrentRamBankNo = Data[0] & 0x03; Cart->iCurrentRamBankNo = Data[0] & 0x03;
DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo);
if (Cart->bHasTimer && (Data[0] >= 0x08 && Data[0] <= 0x0c)) { if (Cart->bHasTimer && (Data[0] >= 0x08 && Data[0] <= 0x0c))
{
// Set the bank for the timer // Set the bank for the timer
Cart->iCurrentRamBankNo = Data[0]; Cart->iCurrentRamBankNo = Data[0];
} }
} }
break; }
case 3: // else if ((dwAddress >= 0x6000) && (dwAddress <= 0x7FFF)) // Latch timer data else if ((dwAddress >= 0x6000) && (dwAddress <= 0x7FFF)) // Latch timer data
{
CopyMemory(Cart->LatchedTimerData, Cart->TimerData, 5 * sizeof(Cart->TimerData[0])); CopyMemory(Cart->LatchedTimerData, Cart->TimerData, 5 * sizeof(Cart->TimerData[0]));
if (Data[0] & 1) { if (Data[0] & 1)
{
// Update timer, save latch values, and set latch state // Update timer, save latch values, and set latch state
UpdateRTC(Cart); UpdateRTC(Cart);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
Cart->LatchedTimerData[i] = Cart->TimerData[i]; Cart->LatchedTimerData[i] = Cart->TimerData[i];
Cart->TimerDataLatched = true; Cart->TimerDataLatched = true;
DebugWriteA("Timer Data Latch: Enable\n"); DebugWriteA("Timer Data Latch: Enable\n");
} else { }
else
{
Cart->TimerDataLatched = false; Cart->TimerDataLatched = false;
DebugWriteA("Timer Data Latch: Disable\n"); DebugWriteA("Timer Data Latch: Disable\n");
} }
break; }
case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) // Write to RAM else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) // Write to RAM
if (Cart->bHasRam) { {
if (Cart->iCurrentRamBankNo >= 0x08 && Cart->iCurrentRamBankNo <= 0x0c) { if (Cart->bHasRam)
{
if (Cart->iCurrentRamBankNo >= 0x08 && Cart->iCurrentRamBankNo <= 0x0c)
{
// Write to the timer // Write to the timer
DebugWriteA("Timer write: Bank %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("Timer write: Bank %02X\n", Cart->iCurrentRamBankNo);
Cart->TimerData[Cart->iCurrentRamBankNo - 0x08] = Data[0]; Cart->TimerData[Cart->iCurrentRamBankNo - 0x08] = Data[0];
} else { }
else
{
DebugWriteA("RAM write: Bank %02X%s\n", Cart->iCurrentRamBankNo, Cart->bRamEnableState ? "" : " -- NOT ENABLED (but wrote anyway)"); DebugWriteA("RAM write: Bank %02X%s\n", Cart->iCurrentRamBankNo, Cart->bRamEnableState ? "" : " -- NOT ENABLED (but wrote anyway)");
CopyMemory(&Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo * 0x2000)], Data, 32); CopyMemory(&Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo * 0x2000)], Data, 32);
} }
} }
break; }
default: else
{
DebugWriteA("Bad write to MBC3 cart, address %04X\n", dwAddress); DebugWriteA("Bad write to MBC3 cart, address %04X\n", dwAddress);
} }
@ -866,42 +918,51 @@ bool WriteCartMBC3(LPGBCART Cart, WORD dwAddress, BYTE *Data)
// Done // Done
bool ReadCartMBC5(LPGBCART Cart, WORD dwAddress, BYTE *Data) bool ReadCartMBC5(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
switch (dwAddress >> 13)
if ((dwAddress < 0x4000)) //Rom Bank 0
{ {
case 0:
case 1: // if ((dwAddress <= 0x3FFF))
CopyMemory(Data, &Cart->RomData[dwAddress], 32); CopyMemory(Data, &Cart->RomData[dwAddress], 32);
DebugWriteA("Nonbanked ROM read - MBC5\n"); DebugWriteA("Nonbanked ROM read - MBC5\n");
break; }
case 2: else if ((dwAddress >= 0x4000) && (dwAddress < 0x8000)) //Switchable ROM BANK
case 3: // else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF)) {
if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks) { if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks)
{
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
DebugWriteA("Banked ROM read: (Banking Error)"); DebugWriteA("Banked ROM read: (Banking Error)");
DebugWriteByteA(Cart->iCurrentRomBankNo); DebugWriteByteA(Cart->iCurrentRomBankNo);
DebugWriteA("\n"); DebugWriteA("\n");
} else { }
else {
CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo << 14)], 32); CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo << 14)], 32);
DebugWriteA("Banked ROM read: Bank="); DebugWriteA("Banked ROM read: Bank=");
DebugWriteByteA(Cart->iCurrentRomBankNo); DebugWriteByteA(Cart->iCurrentRomBankNo);
DebugWriteA("\n"); DebugWriteA("\n");
} }
break; }
case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) else if ((dwAddress >= 0xA000) && (dwAddress <= 0xC000)) //Upper bounds of memory map
if (Cart->bHasRam) { {
if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks) { if (Cart->bHasRam)
{
if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks)
{
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
DebugWriteA("Failed RAM read: (Banking Error) %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("Failed RAM read: (Banking Error) %02X\n", Cart->iCurrentRamBankNo);
} else { }
else
{
CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], 32); CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], 32);
DebugWriteA("RAM read: Bank %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("RAM read: Bank %02X\n", Cart->iCurrentRamBankNo);
} }
} else { }
else
{
ZeroMemory(Data, 32); ZeroMemory(Data, 32);
DebugWriteA("Failed RAM read: (RAM Not Present)\n"); DebugWriteA("Failed RAM read: (RAM Not Present)\n");
} }
break; }
default: else
{
DebugWriteA("Bad read from MBC5 cart, address %04X\n", dwAddress); DebugWriteA("Bad read from MBC5 cart, address %04X\n", dwAddress);
} }
@ -911,43 +972,52 @@ bool ReadCartMBC5(LPGBCART Cart, WORD dwAddress, BYTE *Data)
// Done // Done
bool WriteCartMBC5(LPGBCART Cart, WORD dwAddress, BYTE *Data) bool WriteCartMBC5(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{ {
switch (dwAddress >> 13) if ((dwAddress >= 0x0000) && (dwAddress <= 0x1FFF)) // We shouldn't be able to read/write to RAM unless this is toggled on
{ {
case 0: // if ((dwAddress <= 0x1FFF)) // We shouldn't be able to read/write to RAM unless this is toggled on
Cart->bRamEnableState = (Data[0] == 0x0A); Cart->bRamEnableState = (Data[0] == 0x0A);
DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState); DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState);
break; }
case 1: // else if ((dwAddress >= 0x2000) && (dwAddress <= 0x2FFF)) // ROM bank select, low bits else if ((dwAddress >= 0x2000) && (dwAddress <= 0x2FFF)) // ROM bank select, low bits
{
Cart->iCurrentRomBankNo &= 0xFF00; Cart->iCurrentRomBankNo &= 0xFF00;
Cart->iCurrentRomBankNo |= Data[0]; Cart->iCurrentRomBankNo |= Data[0];
// Cart->iCurrentRomBankNo = ((int) Data[0]) | (Cart->iCurrentRomBankNo & 0x100); // Cart->iCurrentRomBankNo = ((int) Data[0]) | (Cart->iCurrentRomBankNo & 0x100);
DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo);
break; }
case 2: // else if ((dwAddress >= 0x3000) && (dwAddress <= 0x3FFF)) // ROM bank select, high bit else if ((dwAddress >= 0x3000) && (dwAddress <= 0x3FFF)) // ROM bank select, high bit
{
Cart->iCurrentRomBankNo &= 0x00FF; Cart->iCurrentRomBankNo &= 0x00FF;
Cart->iCurrentRomBankNo |= (Data[0] & 0x01) << 8; Cart->iCurrentRomBankNo |= (Data[0] & 0x01) << 8;
// Cart->iCurrentRomBankNo = (Cart->iCurrentRomBankNo & 0xFF) | ((((int) Data[0]) & 1) * 0x100); // Cart->iCurrentRomBankNo = (Cart->iCurrentRomBankNo & 0xFF) | ((((int) Data[0]) & 1) * 0x100);
DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo); DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo);
break; }
case 3: // if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM bank select else if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM bank select
if (Cart->bHasRam) { {
if (Cart->bHasRam)
{
Cart->iCurrentRamBankNo = Data[0] & 0x0F; Cart->iCurrentRamBankNo = Data[0] & 0x0F;
DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo);
} }
break; }
case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) // Write to RAM else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) // Write to RAM
if (Cart->bHasRam) { {
if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks) { if (Cart->bHasRam)
{
if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks)
{
DebugWriteA("RAM write: Buffer error on "); DebugWriteA("RAM write: Buffer error on ");
DebugWriteByteA(Cart->iCurrentRamBankNo); DebugWriteByteA(Cart->iCurrentRamBankNo);
DebugWriteA("\n"); DebugWriteA("\n");
} else { }
else
{
DebugWriteA("RAM write: Bank %02X\n", Cart->iCurrentRamBankNo); DebugWriteA("RAM write: Bank %02X\n", Cart->iCurrentRamBankNo);
CopyMemory(&Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], Data, 32); CopyMemory(&Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], Data, 32);
} }
} }
break; }
default: else
{
DebugWriteA("Bad write to MBC5 cart, address %04X\n", dwAddress); DebugWriteA("Bad write to MBC5 cart, address %04X\n", dwAddress);
} }