#include namespace WonderSwan { Cartridge cartridge; #include "memory.cpp" #include "rtc.cpp" #include "io.cpp" #include "serialization.cpp" auto Cartridge::Enter() -> void { while(true) scheduler.synchronize(), cartridge.main(); } auto Cartridge::main() -> void { if(rtc.data) { rtcTickSecond(); rtcCheckAlarm(); } step(3'072'000); } auto Cartridge::step(uint clocks) -> void { Thread::step(clocks); synchronize(cpu); } auto Cartridge::power() -> void { create(Cartridge::Enter, 3'072'000); eeprom.power(); bus.map(this, 0x00c0, 0x00c8); if(rtc.data) bus.map(this, 0x00ca, 0x00cb); bus.map(this, 0x00cc, 0x00cd); r = {}; } auto Cartridge::load() -> bool { information = {}; if(Model::WonderSwan()) { if(auto loaded = platform->load(ID::WonderSwan, "WonderSwan", "ws")) { information.pathID = loaded.pathID(); } else return false; } if(Model::WonderSwanColor() || Model::SwanCrystal()) { if(auto loaded = platform->load(ID::WonderSwanColor, "WonderSwan Color", "wsc")) { information.pathID = loaded.pathID(); } else return false; } if(Model::PocketChallengeV2()) { if(auto loaded = platform->load(ID::PocketChallengeV2, "Pocket Challenge V2", "pc2")) { information.pathID = loaded.pathID(); } else return false; } if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) { information.manifest = fp->reads(); } else return false; auto document = BML::unserialize(information.manifest); if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) { rom.size = memory.size; rom.mask = bit::round(rom.size) - 1; rom.data = new uint8[rom.mask + 1]; memory::fill(rom.data, rom.mask + 1, 0xff); if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Required)) { fp->read(rom.data, rom.size); } } if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) { ram.size = memory.size; ram.mask = bit::round(ram.size) - 1; ram.data = new uint8[ram.mask + 1]; memory::fill(ram.data, ram.mask + 1, 0xff); if(memory.nonVolatile) { if(auto fp = platform->open(pathID(), memory.name(), File::Read)) { fp->read(ram.data, ram.size); } } } if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=EEPROM,content=Save)"]}) { eeprom.setSize(memory.size / sizeof(uint16)); eeprom.erase(); if(auto fp = platform->open(pathID(), memory.name(), File::Read)) { fp->read(eeprom.data(), eeprom.size()); } } if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RTC,content=Time)"]}) { rtc.size = memory.size; rtc.mask = bit::round(rtc.size) - 1; rtc.data = new uint8[rtc.mask + 1]; memory::fill(rtc.data, rtc.mask + 1, 0x00); if(memory.nonVolatile) { if(auto fp = platform->open(pathID(), memory.name(), File::Read)) { fp->read(rtc.data, rtc.size); } } } information.title = document["game/label"].text(); information.orientation = document["game/orientation"].text() == "vertical"; information.sha256 = Hash::SHA256(rom.data, rom.size).digest(); return true; } auto Cartridge::save() -> void { auto document = BML::unserialize(information.manifest); if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) { if(memory.nonVolatile) { if(auto fp = platform->open(pathID(), memory.name(), File::Write)) { fp->write(ram.data, ram.size); } } } if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=EEPROM,content=Save)"]}) { if(auto fp = platform->open(pathID(), memory.name(), File::Write)) { fp->write(eeprom.data(), eeprom.size()); } } if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RTC,content=Time)"]}) { if(memory.nonVolatile) { if(auto fp = platform->open(pathID(), memory.name(), File::Write)) { fp->write(rtc.data, rtc.size); } } } } auto Cartridge::unload() -> void { delete[] rom.data; rom.data = nullptr; rom.size = 0; rom.mask = 0; delete[] ram.data; ram.data = nullptr; ram.size = 0; ram.mask = 0; delete[] rtc.data; rtc.data = nullptr; rtc.size = 0; rtc.mask = 0; } }