MBC2MemoryRule.cpp (6351B)
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 "MBC2MemoryRule.h" 21#include "Video.h" 22#include "Memory.h" 23#include "Processor.h" 24#include "Input.h" 25#include "Cartridge.h" 26 27MBC2MemoryRule::MBC2MemoryRule(Processor* pProcessor, 28 Memory* pMemory, Video* pVideo, Input* pInput, 29 Cartridge* pCartridge, Audio* pAudio) : MemoryRule(pProcessor, 30pMemory, pVideo, pInput, pCartridge, pAudio) 31{ 32 Reset(false); 33} 34 35MBC2MemoryRule::~MBC2MemoryRule() 36{ 37} 38 39void MBC2MemoryRule::Reset(bool bCGB) 40{ 41 m_bCGB = bCGB; 42 m_iCurrentROMBank = 1; 43 m_CurrentROMAddress = 0x4000; 44 m_bRamEnabled = false; 45} 46 47u8 MBC2MemoryRule::PerformRead(u16 address) 48{ 49 switch (address & 0xE000) 50 { 51 case 0x4000: 52 case 0x6000: 53 { 54 u8* pROM = m_pCartridge->GetTheROM(); 55 return pROM[(address - 0x4000) + m_CurrentROMAddress]; 56 } 57 case 0xA000: 58 { 59 if (address < 0xA200) 60 { 61 if (m_bRamEnabled) 62 return m_pMemory->Retrieve(address); 63 else 64 { 65 Log("--> ** Attempting to read from disabled ram %X", address); 66 return 0xFF; 67 } 68 } 69 else 70 { 71 Log("--> ** Attempting to read from ivalid RAM %X", address); 72 return 0x00; 73 } 74 } 75 default: 76 { 77 return m_pMemory->Retrieve(address); 78 } 79 } 80} 81 82void MBC2MemoryRule::PerformWrite(u16 address, u8 value) 83{ 84 switch (address & 0xE000) 85 { 86 case 0x0000: 87 { 88 if (!(address & 0x0100)) 89 { 90 bool previous = m_bRamEnabled; 91 m_bRamEnabled = ((value & 0x0F) == 0x0A); 92 93 if (IsValidPointer(m_pRamChangedCallback) && previous && !m_bRamEnabled) 94 { 95 (*m_pRamChangedCallback)(); 96 } 97 } 98 else 99 { 100 Log("--> ** Attempting to write on invalid register %X %X", address, value); 101 } 102 break; 103 } 104 case 0x2000: 105 { 106 if (address & 0x0100) 107 { 108 m_iCurrentROMBank = value & 0x0F; 109 if (m_iCurrentROMBank == 0) 110 m_iCurrentROMBank = 1; 111 m_iCurrentROMBank &= (m_pCartridge->GetROMBankCount() - 1); 112 m_CurrentROMAddress = m_iCurrentROMBank * 0x4000; 113 } 114 else 115 { 116 Log("--> ** Attempting to write on invalid register %X %X", address, value); 117 } 118 break; 119 } 120 case 0x4000: 121 case 0x6000: 122 { 123 Log("--> ** Attempting to write on invalid address %X %X", address, value); 124 break; 125 } 126 case 0xA000: 127 { 128 if (address < 0xA200) 129 { 130 if (m_bRamEnabled) 131 { 132 m_pMemory->Load(address, value & 0x0F); 133 } 134 else 135 { 136 Log("--> ** Attempting to write on RAM when ram is disabled %X %X", address, value); 137 } 138 } 139 else 140 { 141 Log("--> ** Attempting to write on invalid RAM %X %X", address, value); 142 } 143 break; 144 } 145 default: 146 { 147 m_pMemory->Load(address, value); 148 break; 149 } 150 } 151} 152 153void MBC2MemoryRule::SaveRam(std::ostream & file) 154{ 155 Log("MBC2MemoryRule save RAM..."); 156 157 for (int i = 0xA000; i < 0xA200; i++) 158 { 159 u8 ram_byte = m_pMemory->Retrieve(i); 160 file.write(reinterpret_cast<const char*> (&ram_byte), 1); 161 } 162 163 Log("MBC2MemoryRule save RAM done"); 164} 165 166bool MBC2MemoryRule::LoadRam(std::istream & file, s32 fileSize) 167{ 168 Log("MBC2MemoryRule load RAM..."); 169 170 if ((fileSize > 0) && (fileSize != 512)) 171 { 172 Log("MBC2MemoryRule incorrect size. Expected: 512 Found: %d", fileSize); 173 return false; 174 } 175 176 for (int i = 0xA000; i < 0xA200; i++) 177 { 178 u8 ram_byte = 0; 179 file.read(reinterpret_cast<char*> (&ram_byte), 1); 180 m_pMemory->Load(i, ram_byte); 181 } 182 183 Log("MBC2MemoryRule load RAM done"); 184 185 return true; 186} 187 188size_t MBC2MemoryRule::GetRamSize() 189{ 190 return 0x200; 191} 192 193u8* MBC2MemoryRule::GetRamBanks() 194{ 195 return m_pMemory->GetMemoryMap() + 0xA000; 196} 197 198u8* MBC2MemoryRule::GetCurrentRamBank() 199{ 200 return m_pMemory->GetMemoryMap() + 0xA000; 201} 202 203int MBC2MemoryRule::GetCurrentRamBankIndex() 204{ 205 return 0; 206} 207 208u8* MBC2MemoryRule::GetCurrentRomBank1() 209{ 210 u8* pROM = m_pCartridge->GetTheROM(); 211 return &pROM[m_CurrentROMAddress]; 212} 213 214u8* MBC2MemoryRule::GetRomBank0() 215{ 216 return m_pMemory->GetMemoryMap() + 0x0000; 217} 218 219int MBC2MemoryRule::GetCurrentRomBank0Index() 220{ 221 return 0; 222} 223 224int MBC2MemoryRule::GetCurrentRomBank1Index() 225{ 226 return m_iCurrentROMBank; 227} 228 229void MBC2MemoryRule::SaveState(std::ostream& stream) 230{ 231 using namespace std; 232 233 stream.write(reinterpret_cast<const char*> (&m_iCurrentROMBank), sizeof(m_iCurrentROMBank)); 234 stream.write(reinterpret_cast<const char*> (&m_bRamEnabled), sizeof(m_bRamEnabled)); 235 stream.write(reinterpret_cast<const char*> (&m_CurrentROMAddress), sizeof(m_CurrentROMAddress)); 236} 237 238void MBC2MemoryRule::LoadState(std::istream& stream) 239{ 240 using namespace std; 241 242 stream.read(reinterpret_cast<char*> (&m_iCurrentROMBank), sizeof(m_iCurrentROMBank)); 243 stream.read(reinterpret_cast<char*> (&m_bRamEnabled), sizeof(m_bRamEnabled)); 244 stream.read(reinterpret_cast<char*> (&m_CurrentROMAddress), sizeof(m_CurrentROMAddress)); 245}