From 0f95c0da86db5364bd4171174c0e9b0929c08343 Mon Sep 17 00:00:00 2001 From: Braiden Gent Date: Sun, 31 Mar 2024 02:47:57 -0700 Subject: [PATCH] more mbc work --- src/addressSpace.cpp | 19 ++++++++++++++++--- src/addressSpace.hpp | 22 +++++++++++++++------- src/gameboy.cpp | 26 ++++++++++++++------------ src/gameboy.hpp | 2 ++ src/mbc.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 22 deletions(-) diff --git a/src/addressSpace.cpp b/src/addressSpace.cpp index 06ba7ef..36d9486 100644 --- a/src/addressSpace.cpp +++ b/src/addressSpace.cpp @@ -1,5 +1,6 @@ #include "addressSpace.hpp" #include +#include bool AddressSpace::getBootromState() const { return bootromLoaded; @@ -24,11 +25,23 @@ void AddressSpace::loadBootrom(const std::string& filename) { } void AddressSpace::loadGame(const std::string& filename) { - game.open(filename, std::ios::binary); + std::ifstream rom(filename, std::ios::binary); + rom.unsetf(std::ios::skipws); - if (!game.is_open()) { + if (!rom.is_open()) { std::cerr << "Game was not found!\nQuitting!\n" << std::endl; exit(1); } - game.read(reinterpret_cast(memoryLayout.romBank1), ROM_BANK_SIZE * 2); + + rom.seekg(0, std::ios::end); + const std::streampos rom_size = rom.tellg(); + rom.seekg(0, std::ios::beg); + + game.reserve(rom_size); + game.insert(game.begin(), + std::istream_iterator(rom), + std::istream_iterator()); + + memcpy(memoryLayout.romBank0, game.data(), ROM_BANK_SIZE); + memcpy(memoryLayout.romBankSwitch, game.data() + ROM_BANK_SIZE, ROM_BANK_SIZE); } diff --git a/src/addressSpace.hpp b/src/addressSpace.hpp index 617def7..c1a1413 100644 --- a/src/addressSpace.hpp +++ b/src/addressSpace.hpp @@ -5,14 +5,17 @@ #include #include #include +#include + #include "defines.hpp" class AddressSpace { bool bootromLoaded = true; Byte bootrom[BOOTROM_SIZE] = {0}; - std::ifstream game; public: + std::vector game; + AddressSpace() { // Initialize the memory to zero memoryLayout = {}; @@ -24,7 +27,7 @@ public: Byte memory[0x10000]; struct { - Byte romBank1[ROM_BANK_SIZE]; // Mapped to 0x0000 + Byte romBank0[ROM_BANK_SIZE]; // Mapped to 0x0000 Byte romBankSwitch[ROM_BANK_SIZE]; // Mapped to 0x4000 Byte vram[0x2000]; // Mapped to 0x8000 Byte externalRam[0x2000]; // Mapped to 0xA000 @@ -47,11 +50,16 @@ public: void determineMBCInfo(); MBCType MBC = {}; - uint32_t RomSize = 0; - uint32_t RomPages = 0; - uint32_t ExternalRamSize = 0; - uint32_t ExternalRamPages = 0; - + uint32_t romSize = 0; + uint32_t romBanks = 0; + uint32_t externalRamSize = 0; + uint32_t externalRamBanks = 0; + Byte romBankRegister = 0x01; + Byte ramBankRegister = 0x00; + Byte romRamSelect = 0x00; + //MBC3 + Byte latchClockData = 0x00; + Byte ramBankRTCRegister = 0x00; //overload [] for echo ram and bootrom support Byte operator[](const uint32_t address) const { diff --git a/src/gameboy.cpp b/src/gameboy.cpp index c20e384..2275f74 100644 --- a/src/gameboy.cpp +++ b/src/gameboy.cpp @@ -12,6 +12,7 @@ void GameBoy::addCycles(const uint8_t ticks) { void GameBoy::start(std::string bootrom, std::string game) { addressSpace.loadBootrom(bootrom); addressSpace.loadGame(game); + addressSpace.determineMBCInfo(); //init some registers that won't otherwise by set (*JOYP) = 0xCF; @@ -35,18 +36,19 @@ void GameBoy::start(std::string bootrom, std::string game) { } ppuEnabled = (*LCDC) & 0x80; - // if (PC == 0x100) - // display = true; - // if (display) { - // printf("Cycles: %lu, Opcode: 0x%.2x PPU cycles: %lu, PPMode: %d\n", cycles, addressSpace[PC], - // cyclesSinceLastScanline(), currentMode); - // printf("PC:0x%.2x, SP:0x%.2x\n", PC, SP); - // printf("AF:0x%.4x, BC:0x%.4x\n", AF.reg, BC.reg); - // printf("DE:0x%.4x, HL:0x%.4x\n", DE.reg, HL.reg); - // printf("IME:%d IF:0x%.2x IE:0x%.2x\n", IME, (*IF), (*IE)); - // printf("LCDC:%.2x STAT:0x%.2x LY:%d LYC:%d\n", (*LCDC), (*STAT), (*LY), (*LYC)); - // printf("\n"); - // } + if (PC >= 0xe0) + display = true; + if (display) { + printf("Cycles: %lu, Opcode: 0x%.2x PPU cycles: %lu, PPMode: %d\n", cycles, addressSpace[PC], + cyclesSinceLastScanline(), currentMode); + printf("PC:0x%.2x, SP:0x%.2x\n", PC, SP); + printf("AF:0x%.4x, BC:0x%.4x\n", AF.reg, BC.reg); + printf("DE:0x%.4x, HL:0x%.4x\n", DE.reg, HL.reg); + printf("IME:%d IF:0x%.2x IE:0x%.2x\n", IME, (*IF), (*IE)); + printf("LCDC:%.2x STAT:0x%.2x LY:%d LYC:%d\n", (*LCDC), (*STAT), (*LY), (*LYC)); + printf("Cart type: 0x%.2x\n", addressSpace.game[0x147]); + printf("\n"); + } opcodeResolver(); interruptHandler(); diff --git a/src/gameboy.hpp b/src/gameboy.hpp index 7c97611..ec0cbd6 100644 --- a/src/gameboy.hpp +++ b/src/gameboy.hpp @@ -114,6 +114,8 @@ class GameBoy { uint32_t frameTime = 0; const int frameDelay = 1000 / V_SYNC; + bool testMBCWrite(const Byte& address); + void opcodeResolver(); void incLY(); void ppuUpdate(); diff --git a/src/mbc.cpp b/src/mbc.cpp index 7529ae3..8dfef3a 100644 --- a/src/mbc.cpp +++ b/src/mbc.cpp @@ -1 +1,44 @@ +#include "addressSpace.hpp" #include "gameboy.hpp" + +void AddressSpace::determineMBCInfo() { + MBC = static_cast(memoryLayout.romBank0[0x147]); + romSize = 32768 * (1 << memoryLayout.romBank0[0x147]); + romBanks = (1 << (memoryLayout.romBank0[0x147] + 1)); + + switch (memoryLayout.romBank0[0x0149]) { + case 0x02: + externalRamSize = 8196; + externalRamBanks = 1; + break; + case 0x03: + externalRamSize = 32768; + externalRamBanks = 4; + break; + case 0x04: + externalRamSize = 131072; + externalRamBanks = 16; + break; + case 0x05: + externalRamSize = 65536; + externalRamBanks = 8; + break; + default: + externalRamSize = 0; + externalRamBanks = 0; + break; + } + + if (MBC == MBC2 || MBC2Battery) { + //only the lower 4 bits are usable + externalRamSize = 512; + } +} + +bool GameBoy::testMBCWrite(const Byte& address) { + const Byte* ptr = &address; + if (ptr >= &addressSpace[0x0] && ptr <= &addressSpace[0x7FFF]) + return true; + return false; +} +