mirror of https://github.com/bsnes-emu/bsnes.git
177 lines
5.1 KiB
C++
177 lines
5.1 KiB
C++
#include <gba/gba.hpp>
|
|
|
|
namespace GameBoyAdvance {
|
|
|
|
#include "eeprom.cpp"
|
|
#include "flashrom.cpp"
|
|
#include "serialization.cpp"
|
|
Cartridge cartridge;
|
|
|
|
string Cartridge::title() {
|
|
return information.title;
|
|
}
|
|
|
|
void Cartridge::load() {
|
|
interface->loadRequest(ID::Manifest, "manifest.bml");
|
|
|
|
auto document = Markup::Document(information.markup);
|
|
information.title = document["information/title"].text();
|
|
|
|
unsigned rom_size = 0;
|
|
if(document["cartridge/rom"].exists()) {
|
|
auto info = document["cartridge/rom"];
|
|
interface->loadRequest(ID::ROM, info["name"].data);
|
|
rom_size = numeral(info["size"].data);
|
|
for(unsigned addr = rom_size; addr < rom.size; addr++) {
|
|
rom.data[addr] = rom.data[Bus::mirror(addr, rom_size)];
|
|
}
|
|
}
|
|
|
|
has_sram = false;
|
|
has_eeprom = false;
|
|
has_flashrom = false;
|
|
|
|
if(document["cartridge/ram"].exists()) {
|
|
auto info = document["cartridge/ram"];
|
|
|
|
if(info["type"].data == "SRAM" || info["type"].data == "FRAM") {
|
|
has_sram = true;
|
|
ram.size = numeral(info["size"].data);
|
|
ram.mask = ram.size - 1;
|
|
for(unsigned n = 0; n < ram.size; n++) ram.data[n] = 0xff;
|
|
|
|
interface->loadRequest(ID::RAM, info["name"].data);
|
|
memory.append({ID::RAM, info["name"].data});
|
|
}
|
|
|
|
if(info["type"].data == "EEPROM") {
|
|
has_eeprom = true;
|
|
eeprom.size = numeral(info["size"].data);
|
|
eeprom.bits = eeprom.size <= 512 ? 6 : 14;
|
|
if(eeprom.size == 0) eeprom.size = 8192, eeprom.bits = 0; //auto-detect size
|
|
eeprom.mask = rom_size > 16 * 1024 * 1024 ? 0x0fffff00 : 0x0f000000;
|
|
eeprom.test = rom_size > 16 * 1024 * 1024 ? 0x0dffff00 : 0x0d000000;
|
|
for(unsigned n = 0; n < eeprom.size; n++) eeprom.data[n] = 0xff;
|
|
|
|
interface->loadRequest(ID::EEPROM, info["name"].data);
|
|
memory.append({ID::EEPROM, info["name"].data});
|
|
}
|
|
|
|
if(info["type"].data == "FlashROM") {
|
|
has_flashrom = true;
|
|
flashrom.id = numeral(info["id"].data);
|
|
flashrom.size = numeral(info["size"].data);
|
|
for(unsigned n = 0; n < flashrom.size; n++) flashrom.data[n] = 0xff;
|
|
|
|
interface->loadRequest(ID::FlashROM, info["name"].data);
|
|
memory.append({ID::FlashROM, info["name"].data});
|
|
}
|
|
}
|
|
|
|
sha256 = nall::sha256(rom.data, rom_size);
|
|
|
|
system.load();
|
|
loaded = true;
|
|
}
|
|
|
|
void Cartridge::unload() {
|
|
if(loaded == false) return;
|
|
loaded = false;
|
|
memory.reset();
|
|
}
|
|
|
|
void Cartridge::power() {
|
|
eeprom.power();
|
|
flashrom.power();
|
|
}
|
|
|
|
uint8* Cartridge::ram_data() {
|
|
if(has_sram) return ram.data;
|
|
if(has_eeprom) return eeprom.data;
|
|
if(has_flashrom) return flashrom.data;
|
|
return nullptr;
|
|
}
|
|
|
|
unsigned Cartridge::ram_size() {
|
|
if(has_sram) return ram.size;
|
|
if(has_eeprom) return eeprom.size;
|
|
if(has_flashrom) return flashrom.size;
|
|
return 0u;
|
|
}
|
|
|
|
uint32 Cartridge::read(uint8 *data, uint32 addr, uint32 size) {
|
|
if(size == Word) addr &= ~3;
|
|
if(size == Half) addr &= ~1;
|
|
data += addr;
|
|
if(size == Word) return data[0] << 0 | data[1] << 8 | data[2] << 16 | data[3] << 24;
|
|
if(size == Half) return data[0] << 0 | data[1] << 8;
|
|
return data[0];
|
|
}
|
|
|
|
void Cartridge::write(uint8 *data, uint32 addr, uint32 size, uint32 word) {
|
|
if(size == Word) addr &= ~3;
|
|
if(size == Half) addr &= ~1;
|
|
data += addr;
|
|
switch(size) {
|
|
case Word: data[3] = word >> 24;
|
|
data[2] = word >> 16;
|
|
case Half: data[1] = word >> 8;
|
|
case Byte: data[0] = word >> 0;
|
|
}
|
|
}
|
|
|
|
#define RAM_ANALYZE
|
|
|
|
uint32 Cartridge::read(uint32 addr, uint32 size) {
|
|
#ifdef RAM_ANALYZE
|
|
if((addr & 0x0e000000) == 0x0e000000) {
|
|
static bool once = true;
|
|
if(once) once = false, print("* SRAM/FlashROM read detected\n");
|
|
}
|
|
#endif
|
|
|
|
if(has_sram && (addr & 0x0e000000 ) == 0x0e000000 ) return read(ram.data, addr & ram.mask, size);
|
|
if(has_eeprom && (addr & eeprom.mask) == eeprom.test) return eeprom.read();
|
|
if(has_flashrom && (addr & 0x0e000000 ) == 0x0e000000 ) return flashrom.read(addr);
|
|
if(addr < 0x0e000000) return read(rom.data, addr & 0x01ffffff, size);
|
|
return cpu.pipeline.fetch.instruction;
|
|
}
|
|
|
|
void Cartridge::write(uint32 addr, uint32 size, uint32 word) {
|
|
#ifdef RAM_ANALYZE
|
|
if((addr & 0x0e000000) == 0x0e000000) {
|
|
static bool once = true;
|
|
if(once) once = false, print("* SRAM/FlashROM write detected\n");
|
|
}
|
|
if((addr & 0x0f000000) == 0x0d000000) {
|
|
static bool once = true;
|
|
if(once) once = false, print("* EEPROM write detected\n");
|
|
}
|
|
if((addr & 0x0e00ffff) == 0x0e005555 && (word & 0xff) == 0xaa) {
|
|
static bool once = true;
|
|
if(once) once = false, print("* FlashROM write detected\n");
|
|
}
|
|
#endif
|
|
|
|
if(has_sram && (addr & 0x0e000000 ) == 0x0e000000 ) return write(ram.data, addr & ram.mask, size, word);
|
|
if(has_eeprom && (addr & eeprom.mask) == eeprom.test) return eeprom.write(word & 1);
|
|
if(has_flashrom && (addr & 0x0e000000 ) == 0x0e000000 ) return flashrom.write(addr, word);
|
|
}
|
|
|
|
Cartridge::Cartridge() {
|
|
loaded = false;
|
|
rom.data = new uint8[rom.size = 32 * 1024 * 1024];
|
|
ram.data = new uint8[ram.size = 32 * 1024];
|
|
eeprom.data = new uint8[eeprom.size = 8 * 1024];
|
|
flashrom.data = new uint8[flashrom.size = 128 * 1024];
|
|
}
|
|
|
|
Cartridge::~Cartridge() {
|
|
delete[] rom.data;
|
|
delete[] ram.data;
|
|
delete[] eeprom.data;
|
|
delete[] flashrom.data;
|
|
}
|
|
|
|
}
|