BS-X: Allow memory packs in other cartridges

This commit is contained in:
Sour 2020-02-22 17:42:18 -05:00
parent 5978e89a6c
commit 3da787b88f
6 changed files with 69 additions and 18 deletions

View file

@ -57,7 +57,7 @@ shared_ptr<BaseCartridge> BaseCartridge::CreateCartridge(Console* console, Virtu
cart->_romPath = romFile;
if(FolderUtilities::GetExtension(romFile.GetFileName()) == ".bs") {
cart->_bsxMemPack.reset(new BsxMemoryPack(romData));
cart->_bsxMemPack.reset(new BsxMemoryPack(console, romData, false));
if(!FirmwareHelper::LoadBsxFirmware(console, &cart->_prgRom, cart->_prgRomSize)) {
return nullptr;
}
@ -329,6 +329,10 @@ void BaseCartridge::SaveBattery()
if(_coprocessor && _hasBattery) {
_coprocessor->SaveBattery();
}
if(_bsxMemPack) {
_bsxMemPack->SaveBattery();
}
}
void BaseCartridge::Init(MemoryMappings &mm)
@ -363,6 +367,7 @@ void BaseCartridge::Init(MemoryMappings &mm)
void BaseCartridge::RegisterHandlers(MemoryMappings &mm)
{
if(MapSpecificCarts(mm) || _coprocessorType == CoprocessorType::GSU || _coprocessorType == CoprocessorType::SDD1 || _coprocessorType == CoprocessorType::SPC7110 || _coprocessorType == CoprocessorType::CX4) {
MapBsxMemoryPack(mm);
return;
}
@ -403,6 +408,8 @@ void BaseCartridge::RegisterHandlers(MemoryMappings &mm)
mm.RegisterHandler(0x70, 0x7D, 0x0000, 0x7FFF, _saveRamHandlers);
mm.RegisterHandler(0xA0, 0xBF, 0x6000, 0x7FFF, _saveRamHandlers);
}
MapBsxMemoryPack(mm);
}
void BaseCartridge::LoadEmbeddedFirmware()
@ -444,7 +451,7 @@ void BaseCartridge::InitCoprocessor()
if(!_bsxMemPack) {
//Create an empty memory pack if the BIOS was loaded directly (instead of a .bs file)
vector<uint8_t> emptyMemPack;
_bsxMemPack.reset(new BsxMemoryPack(emptyMemPack));
_bsxMemPack.reset(new BsxMemoryPack(_console, emptyMemPack, false));
}
_coprocessor.reset(new BsxCart(_console, _bsxMemPack.get()));
@ -489,6 +496,32 @@ bool BaseCartridge::MapSpecificCarts(MemoryMappings &mm)
return false;
}
void BaseCartridge::MapBsxMemoryPack(MemoryMappings& mm)
{
string code = GetGameCode();
if(!_bsxMemPack && code.size() == 4 && code[0] == 'Z' && _cartInfo.DeveloperId == 0x33) {
//Game with data pack slot (e.g Sound Novel Tsukuuru, etc.)
vector<uint8_t> saveData = _console->GetBatteryManager()->LoadBattery(".bs");
if(saveData.empty()) {
//Make a 1 megabyte flash cartridge by default (use $FF for all bytes)
saveData.resize(0x100000, 0xFF);
}
_bsxMemPack.reset(new BsxMemoryPack(_console, saveData, true));
if(_flags & CartFlags::LoRom) {
mm.RegisterHandler(0xC0, 0xEF, 0x0000, 0x7FFF, _bsxMemPack->GetMemoryHandlers());
mm.RegisterHandler(0xC0, 0xEF, 0x8000, 0xFFFF, _bsxMemPack->GetMemoryHandlers());
} else {
mm.RegisterHandler(0x20, 0x3F, 0x8000, 0xFFFF, _bsxMemPack->GetMemoryHandlers(), 8);
mm.RegisterHandler(0x60, 0x7D, 0x0000, 0xFFFF, _bsxMemPack->GetMemoryHandlers());
mm.RegisterHandler(0xA0, 0xBF, 0x8000, 0xFFFF, _bsxMemPack->GetMemoryHandlers(), 8);
mm.RegisterHandler(0xE0, 0xFF, 0x0000, 0xFFFF, _bsxMemPack->GetMemoryHandlers());
}
//TODO: SA-1 cartridges, etc.
}
}
void BaseCartridge::ApplyConfigOverrides()
{
string name = GetCartName();
@ -539,16 +572,16 @@ void BaseCartridge::Serialize(Serializer &s)
string BaseCartridge::GetGameCode()
{
string code;
if(_cartInfo.GameCode[0] >= ' ') {
if(_cartInfo.GameCode[0] > ' ') {
code += _cartInfo.GameCode[0];
}
if(_cartInfo.GameCode[1] >= ' ') {
if(_cartInfo.GameCode[1] > ' ') {
code += _cartInfo.GameCode[1];
}
if(_cartInfo.GameCode[2] >= ' ') {
if(_cartInfo.GameCode[2] > ' ') {
code += _cartInfo.GameCode[2];
}
if(_cartInfo.GameCode[3] >= ' ') {
if(_cartInfo.GameCode[3] > ' ') {
code += _cartInfo.GameCode[3];
}
return code;

View file

@ -62,7 +62,8 @@ private:
CoprocessorType GetSt01xVersion();
CoprocessorType GetDspVersion();
bool MapSpecificCarts(MemoryMappings &mm);
bool MapSpecificCarts(MemoryMappings& mm);
void MapBsxMemoryPack(MemoryMappings& mm);
void ApplyConfigOverrides();
void LoadRom();

View file

@ -1,12 +1,16 @@
#include "stdafx.h"
#include "BsxMemoryPack.h"
#include "Console.h"
#include "BatteryManager.h"
#include "../Utilities/IpsPatcher.h"
BsxMemoryPack::BsxMemoryPack(vector<uint8_t>& data)
BsxMemoryPack::BsxMemoryPack(Console* console, vector<uint8_t>& data, bool persistFlash)
{
_console = console;
_orgData = data;
_dataSize = (uint32_t)data.size();
_data = new uint8_t[_dataSize];
_persistFlash = persistFlash;
memcpy(_data, data.data(), _dataSize);
_calculatedSize = std::min<uint8_t>(0x0C, (uint8_t)log2(_dataSize >> 10));
@ -21,6 +25,13 @@ BsxMemoryPack::~BsxMemoryPack()
delete[] _data;
}
void BsxMemoryPack::SaveBattery()
{
if(_persistFlash) {
_console->GetBatteryManager()->SaveBattery(".bs", _data, _dataSize);
}
}
void BsxMemoryPack::Serialize(Serializer& s)
{
s.Stream(_enableCsr, _enableEsr, _enableVendorInfo, _writeByte, _command);
@ -105,12 +116,10 @@ BsxMemoryPack::BsxMemoryPackHandler::BsxMemoryPackHandler(BsxMemoryPack* memPack
uint8_t BsxMemoryPack::BsxMemoryPackHandler::Read(uint32_t addr)
{
if(addr >= 0xC00000) {
if(_memPack->_enableEsr) {
switch(addr & 0xFFFF) {
case 0x0002: return 0xC0;
case 0x0004: return 0x82;
}
if(_offset == 0 && _memPack->_enableEsr) {
switch(addr & 0xFFF) {
case 0x0002: return 0xC0;
case 0x0004: return 0x82;
}
}
@ -143,7 +152,7 @@ void BsxMemoryPack::BsxMemoryPackHandler::Write(uint32_t addr, uint8_t value)
uint8_t currentByte = RamHandler::Read(addr);
RamHandler::Write(addr, value & currentByte);
_memPack->_writeByte = false;
} else if(addr == 0xC00000) {
} else if(_offset == 0 && (addr & 0xFFF) == 0) {
_memPack->ProcessCommand(value, _page);
}
}

View file

@ -5,9 +5,12 @@
#include "../Utilities/ISerializable.h"
class BsxMemoryPackHandler;
class Console;
class BsxMemoryPack : public ISerializable
{
private:
Console* _console = nullptr;
vector<uint8_t> _orgData;
uint8_t* _data = nullptr;
uint32_t _dataSize = 0;
@ -15,6 +18,7 @@ class BsxMemoryPack : public ISerializable
uint8_t _calculatedSize = 0x0C;
bool _persistFlash = false;
bool _enableCsr = false;
bool _enableEsr = false;
bool _enableVendorInfo = false;
@ -22,9 +26,11 @@ class BsxMemoryPack : public ISerializable
uint16_t _command = 0;
public:
BsxMemoryPack(vector<uint8_t>& data);
BsxMemoryPack(Console* console, vector<uint8_t>& data, bool persistFlash);
virtual ~BsxMemoryPack();
void SaveBattery();
void Serialize(Serializer& s) override;
void ProcessCommand(uint8_t value, uint32_t page);

View file

@ -18,7 +18,7 @@ struct SnesCartInformation
uint8_t SramSize;
uint8_t DestinationCode;
uint8_t Reserved2;
uint8_t DeveloperId;
uint8_t Version;
uint8_t ChecksumComplement[2];

View file

@ -7,9 +7,11 @@ class RamHandler : public IMemoryHandler
{
private:
uint8_t * _ram;
uint32_t _offset;
uint32_t _mask;
protected:
uint32_t _offset;
public:
RamHandler(uint8_t *ram, uint32_t offset, uint32_t size, SnesMemoryType memoryType)
{