more mbc work
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
#include "addressSpace.hpp"
|
#include "addressSpace.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
bool AddressSpace::getBootromState() const {
|
bool AddressSpace::getBootromState() const {
|
||||||
return bootromLoaded;
|
return bootromLoaded;
|
||||||
@@ -24,11 +25,23 @@ void AddressSpace::loadBootrom(const std::string& filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AddressSpace::loadGame(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;
|
std::cerr << "Game was not found!\nQuitting!\n" << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
game.read(reinterpret_cast<char*>(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<Byte>(rom),
|
||||||
|
std::istream_iterator<Byte>());
|
||||||
|
|
||||||
|
memcpy(memoryLayout.romBank0, game.data(), ROM_BANK_SIZE);
|
||||||
|
memcpy(memoryLayout.romBankSwitch, game.data() + ROM_BANK_SIZE, ROM_BANK_SIZE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,17 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "defines.hpp"
|
#include "defines.hpp"
|
||||||
|
|
||||||
class AddressSpace {
|
class AddressSpace {
|
||||||
bool bootromLoaded = true;
|
bool bootromLoaded = true;
|
||||||
Byte bootrom[BOOTROM_SIZE] = {0};
|
Byte bootrom[BOOTROM_SIZE] = {0};
|
||||||
std::ifstream game;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
std::vector<Byte> game;
|
||||||
|
|
||||||
AddressSpace() {
|
AddressSpace() {
|
||||||
// Initialize the memory to zero
|
// Initialize the memory to zero
|
||||||
memoryLayout = {};
|
memoryLayout = {};
|
||||||
@@ -24,7 +27,7 @@ public:
|
|||||||
Byte memory[0x10000];
|
Byte memory[0x10000];
|
||||||
|
|
||||||
struct {
|
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 romBankSwitch[ROM_BANK_SIZE]; // Mapped to 0x4000
|
||||||
Byte vram[0x2000]; // Mapped to 0x8000
|
Byte vram[0x2000]; // Mapped to 0x8000
|
||||||
Byte externalRam[0x2000]; // Mapped to 0xA000
|
Byte externalRam[0x2000]; // Mapped to 0xA000
|
||||||
@@ -47,11 +50,16 @@ public:
|
|||||||
|
|
||||||
void determineMBCInfo();
|
void determineMBCInfo();
|
||||||
MBCType MBC = {};
|
MBCType MBC = {};
|
||||||
uint32_t RomSize = 0;
|
uint32_t romSize = 0;
|
||||||
uint32_t RomPages = 0;
|
uint32_t romBanks = 0;
|
||||||
uint32_t ExternalRamSize = 0;
|
uint32_t externalRamSize = 0;
|
||||||
uint32_t ExternalRamPages = 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
|
//overload [] for echo ram and bootrom support
|
||||||
Byte operator[](const uint32_t address) const {
|
Byte operator[](const uint32_t address) const {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ void GameBoy::addCycles(const uint8_t ticks) {
|
|||||||
void GameBoy::start(std::string bootrom, std::string game) {
|
void GameBoy::start(std::string bootrom, std::string game) {
|
||||||
addressSpace.loadBootrom(bootrom);
|
addressSpace.loadBootrom(bootrom);
|
||||||
addressSpace.loadGame(game);
|
addressSpace.loadGame(game);
|
||||||
|
addressSpace.determineMBCInfo();
|
||||||
|
|
||||||
//init some registers that won't otherwise by set
|
//init some registers that won't otherwise by set
|
||||||
(*JOYP) = 0xCF;
|
(*JOYP) = 0xCF;
|
||||||
@@ -35,18 +36,19 @@ void GameBoy::start(std::string bootrom, std::string game) {
|
|||||||
}
|
}
|
||||||
ppuEnabled = (*LCDC) & 0x80;
|
ppuEnabled = (*LCDC) & 0x80;
|
||||||
|
|
||||||
// if (PC == 0x100)
|
if (PC >= 0xe0)
|
||||||
// display = true;
|
display = true;
|
||||||
// if (display) {
|
if (display) {
|
||||||
// printf("Cycles: %lu, Opcode: 0x%.2x PPU cycles: %lu, PPMode: %d\n", cycles, addressSpace[PC],
|
printf("Cycles: %lu, Opcode: 0x%.2x PPU cycles: %lu, PPMode: %d\n", cycles, addressSpace[PC],
|
||||||
// cyclesSinceLastScanline(), currentMode);
|
cyclesSinceLastScanline(), currentMode);
|
||||||
// printf("PC:0x%.2x, SP:0x%.2x\n", PC, SP);
|
printf("PC:0x%.2x, SP:0x%.2x\n", PC, SP);
|
||||||
// printf("AF:0x%.4x, BC:0x%.4x\n", AF.reg, BC.reg);
|
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("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("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("LCDC:%.2x STAT:0x%.2x LY:%d LYC:%d\n", (*LCDC), (*STAT), (*LY), (*LYC));
|
||||||
// printf("\n");
|
printf("Cart type: 0x%.2x\n", addressSpace.game[0x147]);
|
||||||
// }
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
opcodeResolver();
|
opcodeResolver();
|
||||||
interruptHandler();
|
interruptHandler();
|
||||||
|
|||||||
@@ -114,6 +114,8 @@ class GameBoy {
|
|||||||
uint32_t frameTime = 0;
|
uint32_t frameTime = 0;
|
||||||
const int frameDelay = 1000 / V_SYNC;
|
const int frameDelay = 1000 / V_SYNC;
|
||||||
|
|
||||||
|
bool testMBCWrite(const Byte& address);
|
||||||
|
|
||||||
void opcodeResolver();
|
void opcodeResolver();
|
||||||
void incLY();
|
void incLY();
|
||||||
void ppuUpdate();
|
void ppuUpdate();
|
||||||
|
|||||||
43
src/mbc.cpp
43
src/mbc.cpp
@@ -1 +1,44 @@
|
|||||||
|
#include "addressSpace.hpp"
|
||||||
#include "gameboy.hpp"
|
#include "gameboy.hpp"
|
||||||
|
|
||||||
|
void AddressSpace::determineMBCInfo() {
|
||||||
|
MBC = static_cast<MBCType>(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user