1#include "../../include/cartridge.hpp"
6Cartridge::Cartridge() {
10 std::memset(&header, 0,
sizeof(header));
14Cartridge::Cartridge(
const std::vector<u8>& rom_data) {
18bool Cartridge::load_rom(
const std::vector<u8>& rom_data) {
19 if (rom_data.empty()) {
24 mbc_type = MBCType::None;
26 if (rom.size() >= 0x150) {
27 std::memcpy(&header, &rom[0x100],
sizeof(rom_header));
31 std::memcpy(title_buf, header.title, 16);
35 u8 type = header.type;
36 if (type >= 0x01 && type <= 0x03) {
37 mbc_type = MBCType::MBC1;
38 }
else if (type >= 0x0F && type <= 0x13) {
39 mbc_type = MBCType::MBC3;
40 }
else if (type >= 0x19 && type <= 0x1E) {
41 mbc_type = MBCType::MBC5;
45 u32 ram_size_bytes = 0;
46 switch (header.ram_size) {
47 case 1: ram_size_bytes = 2048;
break;
48 case 2: ram_size_bytes = 8192;
break;
49 case 3: ram_size_bytes = 32768;
break;
50 case 4: ram_size_bytes = 131072;
break;
51 case 5: ram_size_bytes = 65536;
break;
52 default: ram_size_bytes = 0;
break;
55 if (ram_size_bytes > 0) {
56 ram.resize(ram_size_bytes, 0);
61 std::memset(&header, 0,
sizeof(rom_header));
75u8 Cartridge::read(u16 address)
const {
76 if (address <= 0x3FFF) {
77 if (mbc_type == MBCType::MBC1 && banking_mode == 1) {
78 u32 bank = (rom_bank_high << 5);
79 u32 address_in_rom = (bank * 0x4000) + address;
80 if (address_in_rom < rom.size())
return rom[address_in_rom];
82 if (address < rom.size())
return rom[address];
85 if (address >= 0x4000 && address <= 0x7FFF) {
86 u32 bank = current_rom_bank;
87 u32 address_in_rom = (address - 0x4000) + (bank * 0x4000);
88 if (address_in_rom < rom.size())
return rom[address_in_rom];
91 if (address >= 0xA000 && address <= 0xBFFF) {
92 if (ram_enabled && !ram.empty()) {
94 if (mbc_type == MBCType::MBC1 && banking_mode == 1) {
95 ram_bank = current_ram_bank;
96 }
else if (mbc_type == MBCType::MBC3 || mbc_type == MBCType::MBC5) {
97 ram_bank = current_ram_bank;
99 u32 ram_address = (ram_bank * 0x2000) + (address - 0xA000);
100 if (ram_address < ram.size())
return ram[ram_address];
107void Cartridge::write(u16 address, u8 value) {
109 if (address <= 0x1FFF) {
110 if (mbc_type != MBCType::None) {
111 ram_enabled = ((value & 0x0F) == 0x0A);
116 if (address >= 0x2000 && address <= 0x3FFF) {
117 if (mbc_type == MBCType::MBC1) {
118 rom_bank_low = value & 0x1F;
119 if (rom_bank_low == 0) rom_bank_low = 1;
120 current_rom_bank = (rom_bank_high << 5) | rom_bank_low;
121 }
else if (mbc_type == MBCType::MBC3) {
122 current_rom_bank = value & 0x7F;
123 if (current_rom_bank == 0) current_rom_bank = 1;
124 }
else if (mbc_type == MBCType::MBC5) {
125 if (address <= 0x2FFF) {
126 rom_bank_low = value;
128 rom_bank_high = value & 0x01;
130 current_rom_bank = (rom_bank_high << 8) | rom_bank_low;
135 if (address >= 0x4000 && address <= 0x5FFF) {
136 if (mbc_type == MBCType::MBC1) {
137 rom_bank_high = value & 0x03;
138 current_ram_bank = value & 0x03;
139 current_rom_bank = (rom_bank_high << 5) | rom_bank_low;
140 }
else if (mbc_type == MBCType::MBC3) {
141 current_ram_bank = value & 0x0F;
142 }
else if (mbc_type == MBCType::MBC5) {
143 current_ram_bank = value & 0x0F;
148 if (address >= 0x6000 && address <= 0x7FFF) {
149 if (mbc_type == MBCType::MBC1) {
150 banking_mode = value & 0x01;
155 if (address >= 0xA000 && address <= 0xBFFF) {
156 if (ram_enabled && !ram.empty()) {
158 if (mbc_type == MBCType::MBC1 && banking_mode == 1) {
159 ram_bank = current_ram_bank;
160 }
else if (mbc_type == MBCType::MBC3 || mbc_type == MBCType::MBC5) {
161 ram_bank = current_ram_bank;
163 u32 ram_address = (ram_bank * 0x2000) + (address - 0xA000);
164 if (ram_address < ram.size()) ram[ram_address] = value;
169void Cartridge::reset() {
170 current_rom_bank = 1;
171 current_ram_bank = 0;
177 std::fill(ram.begin(), ram.end(), 0);