cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

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}