MBC5MemoryRule.cpp (7267B)
1/* 2 * Gearboy - Nintendo Game Boy Emulator 3 * Copyright (C) 2012 Ignacio Sanchez 4 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * any later version. 9 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see http://www.gnu.org/licenses/ 17 * 18 */ 19 20#include "MBC5MemoryRule.h" 21#include "Video.h" 22#include "Memory.h" 23#include "Processor.h" 24#include "Input.h" 25#include "Cartridge.h" 26 27MBC5MemoryRule::MBC5MemoryRule(Processor* pProcessor, 28 Memory* pMemory, Video* pVideo, Input* pInput, 29 Cartridge* pCartridge, Audio* pAudio) : MemoryRule(pProcessor, 30pMemory, pVideo, pInput, pCartridge, pAudio) 31{ 32 m_pRAMBanks = new u8[0x20000]; 33 Reset(false); 34} 35 36MBC5MemoryRule::~MBC5MemoryRule() 37{ 38 SafeDeleteArray(m_pRAMBanks); 39} 40 41void MBC5MemoryRule::Reset(bool bCGB) 42{ 43 m_bCGB = bCGB; 44 m_iCurrentRAMBank = 0; 45 m_iCurrentROMBank = 1; 46 m_iCurrentROMBankHi = 0; 47 m_bRamEnabled = false; 48 for (int i = 0; i < 0x20000; i++) 49 m_pRAMBanks[i] = 0xFF; 50 m_CurrentROMAddress = 0x4000; 51 m_CurrentRAMAddress = 0; 52} 53 54u8 MBC5MemoryRule::PerformRead(u16 address) 55{ 56 switch (address & 0xE000) 57 { 58 case 0x4000: 59 case 0x6000: 60 { 61 u8* pROM = m_pCartridge->GetTheROM(); 62 return pROM[(address - 0x4000) + m_CurrentROMAddress]; 63 } 64 case 0xA000: 65 { 66 if (m_bRamEnabled) 67 { 68 return m_pRAMBanks[(address - 0xA000) + m_CurrentRAMAddress]; 69 } 70 else 71 { 72 Log("--> ** Attempting to read from disabled ram %X", address); 73 return 0xFF; 74 } 75 } 76 default: 77 { 78 return m_pMemory->Retrieve(address); 79 } 80 } 81} 82 83void MBC5MemoryRule::PerformWrite(u16 address, u8 value) 84{ 85 switch (address & 0xE000) 86 { 87 case 0x0000: 88 { 89 if (m_pCartridge->GetRAMSize() > 0) 90 { 91 bool previous = m_bRamEnabled; 92 m_bRamEnabled = ((value & 0x0F) == 0x0A); 93 94 if (IsValidPointer(m_pRamChangedCallback) && previous && !m_bRamEnabled) 95 { 96 (*m_pRamChangedCallback)(); 97 } 98 } 99 break; 100 } 101 case 0x2000: 102 { 103 if (address < 0x3000) 104 { 105 m_iCurrentROMBank = value | (m_iCurrentROMBankHi << 8); 106 } 107 else 108 { 109 m_iCurrentROMBankHi = value & 0x01; 110 m_iCurrentROMBank = (m_iCurrentROMBank & 0xFF) | (m_iCurrentROMBankHi << 8); 111 } 112 m_iCurrentROMBank &= (m_pCartridge->GetROMBankCount() - 1); 113 m_CurrentROMAddress = m_iCurrentROMBank * 0x4000; 114 break; 115 } 116 case 0x4000: 117 { 118 m_iCurrentRAMBank = value & 0x0F; 119 m_iCurrentRAMBank &= (m_pCartridge->GetRAMBankCount() - 1); 120 m_CurrentRAMAddress = m_iCurrentRAMBank * 0x2000; 121 break; 122 } 123 case 0x6000: 124 { 125 Log("--> ** Attempting to write on invalid address %X %X", address, value); 126 break; 127 } 128 case 0xA000: 129 { 130 if (m_bRamEnabled) 131 { 132 m_pRAMBanks[(address - 0xA000) + m_CurrentRAMAddress] = value; 133 } 134 else 135 { 136 Log("--> ** Attempting to write on RAM when ram is disabled %X %X", address, value); 137 } 138 break; 139 } 140 default: 141 { 142 m_pMemory->Load(address, value); 143 break; 144 } 145 } 146} 147 148void MBC5MemoryRule::SaveRam(std::ostream & file) 149{ 150 Log("MBC5MemoryRule save RAM..."); 151 Log("MBC5MemoryRule saving %d banks...", m_pCartridge->GetRAMBankCount()); 152 153 s32 ramSize = m_pCartridge->GetRAMBankCount() * 0x2000; 154 155 for (s32 i = 0; i < ramSize; i++) 156 { 157 u8 ram_byte = m_pRAMBanks[i]; 158 file.write(reinterpret_cast<const char*> (&ram_byte), 1); 159 } 160 161 Log("MBC5MemoryRule save RAM done"); 162} 163 164bool MBC5MemoryRule::LoadRam(std::istream & file, s32 fileSize) 165{ 166 Log("MBC5MemoryRule load RAM..."); 167 Log("MBC5MemoryRule loading %d banks...", m_pCartridge->GetRAMBankCount()); 168 169 s32 ramSize = m_pCartridge->GetRAMBankCount() * 0x2000; 170 171 if ((fileSize > 0) && (fileSize != ramSize)) 172 { 173 Log("MBC5MemoryRule incorrect size. Expected: %d Found: %d", ramSize, fileSize); 174 return false; 175 } 176 177 for (s32 i = 0; i < ramSize; i++) 178 { 179 u8 ram_byte = 0; 180 file.read(reinterpret_cast<char*> (&ram_byte), 1); 181 m_pRAMBanks[i] = ram_byte; 182 } 183 184 Log("MBC5MemoryRule load RAM done"); 185 186 return true; 187} 188 189size_t MBC5MemoryRule::GetRamSize() 190{ 191 return m_pCartridge->GetRAMBankCount() * 0x2000; 192} 193 194u8* MBC5MemoryRule::GetRamBanks() 195{ 196 return m_pRAMBanks; 197} 198 199u8* MBC5MemoryRule::GetCurrentRamBank() 200{ 201 return m_pRAMBanks + m_CurrentRAMAddress; 202} 203 204int MBC5MemoryRule::GetCurrentRamBankIndex() 205{ 206 return m_iCurrentRAMBank; 207} 208 209u8* MBC5MemoryRule::GetRomBank0() 210{ 211 return m_pMemory->GetMemoryMap() + 0x0000; 212} 213 214int MBC5MemoryRule::GetCurrentRomBank0Index() 215{ 216 return 0; 217} 218 219u8* MBC5MemoryRule::GetCurrentRomBank1() 220{ 221 u8* pROM = m_pCartridge->GetTheROM(); 222 return &pROM[m_CurrentROMAddress]; 223} 224 225int MBC5MemoryRule::GetCurrentRomBank1Index() 226{ 227 return m_iCurrentROMBank; 228} 229 230void MBC5MemoryRule::SaveState(std::ostream& stream) 231{ 232 using namespace std; 233 234 stream.write(reinterpret_cast<const char*> (&m_iCurrentRAMBank), sizeof(m_iCurrentRAMBank)); 235 stream.write(reinterpret_cast<const char*> (&m_iCurrentROMBank), sizeof(m_iCurrentROMBank)); 236 stream.write(reinterpret_cast<const char*> (&m_iCurrentROMBankHi), sizeof(m_iCurrentROMBankHi)); 237 stream.write(reinterpret_cast<const char*> (&m_bRamEnabled), sizeof(m_bRamEnabled)); 238 stream.write(reinterpret_cast<const char*> (m_pRAMBanks), 0x20000); 239 stream.write(reinterpret_cast<const char*> (&m_CurrentROMAddress), sizeof(m_CurrentROMAddress)); 240 stream.write(reinterpret_cast<const char*> (&m_CurrentRAMAddress), sizeof(m_CurrentRAMAddress)); 241} 242 243void MBC5MemoryRule::LoadState(std::istream& stream) 244{ 245 using namespace std; 246 247 stream.read(reinterpret_cast<char*> (&m_iCurrentRAMBank), sizeof(m_iCurrentRAMBank)); 248 stream.read(reinterpret_cast<char*> (&m_iCurrentROMBank), sizeof(m_iCurrentROMBank)); 249 stream.read(reinterpret_cast<char*> (&m_iCurrentROMBankHi), sizeof(m_iCurrentROMBankHi)); 250 stream.read(reinterpret_cast<char*> (&m_bRamEnabled), sizeof(m_bRamEnabled)); 251 stream.read(reinterpret_cast<char*> (m_pRAMBanks), 0x20000); 252 stream.read(reinterpret_cast<char*> (&m_CurrentROMAddress), sizeof(m_CurrentROMAddress)); 253 stream.read(reinterpret_cast<char*> (&m_CurrentRAMAddress), sizeof(m_CurrentRAMAddress)); 254}