snes: do some more savestate prep, including removing the unused cheat system, which cost sixteen megidobites of ram

This commit is contained in:
nattthebear 2017-06-10 15:53:38 -04:00
parent fcbb85a579
commit baf7a7973b
15 changed files with 17 additions and 382 deletions

View File

@ -56,11 +56,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
{
Filename = "libsnes.wbx",
Path = dllPath,
SbrkHeapSizeKB = 32 * 1024,
InvisibleHeapSizeKB = 32 * 1024,
MmapHeapSizeKB = 256 * 1024,
PlainHeapSizeKB = 32 * 1024,
SealedHeapSizeKB = 256 * 1024
SbrkHeapSizeKB = 4 * 1024,
InvisibleHeapSizeKB = 1024,
MmapHeapSizeKB = 32 * 1024, // TODO: see if we can safely make libco stacks smaller
PlainHeapSizeKB = 2 * 1024, // TODO: wasn't there more in here?
SealedHeapSizeKB = 128 * 1024
});
_core = BizInvoker.GetInvoker<CoreImpl>(_exe, _exe);

View File

@ -12,73 +12,38 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
public void SaveStateText(TextWriter writer)
{
/*var temp = SaveStateBinary();
var temp = SaveStateBinary();
temp.SaveAsHexFast(writer);
writer.WriteLine("Frame {0}", Frame); // we don't parse this, it's only for the client to use
writer.WriteLine("Profile {0}", CurrentProfile);*/
}
public void LoadStateText(TextReader reader)
{
/*string hex = reader.ReadLine();
string hex = reader.ReadLine();
byte[] state = new byte[hex.Length / 2];
state.ReadFromHexFast(hex);
LoadStateBinary(new BinaryReader(new MemoryStream(state)));
reader.ReadLine(); // Frame #
var profile = reader.ReadLine().Split(' ')[1];
ValidateLoadstateProfile(profile);*/
}
public void SaveStateBinary(BinaryWriter writer)
{
/*writer.Write(DeterministicEmulation ? _savestatebuff : CoreSaveState());
// other variables
Api.SaveStateBinary(writer);
writer.Write(IsLagFrame);
writer.Write(LagCount);
writer.Write(Frame);
writer.Write(CurrentProfile);
writer.Flush();*/
}
public void LoadStateBinary(BinaryReader reader)
{
/*int size = Api.QUERY_serialize_size();
byte[] buf = reader.ReadBytes(size);
CoreLoadState(buf);
if (DeterministicEmulation) // deserialize controller and fast-foward now
{
// reconstruct savestatebuff at the same time to avoid a costly core serialize
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
bw.Write(buf);
bool framezero = reader.ReadBoolean();
bw.Write(framezero);
if (!framezero)
{
var ssc = new SaveController(ControllerDefinition);
ssc.DeSerialize(reader);
IController tmp = _controller;
_controller = ssc;
_nocallbacks = true;
FrameAdvance(ssc, false, false);
_nocallbacks = false;
_controller = tmp;
ssc.Serialize(bw);
}
bw.Close();
_savestatebuff = ms.ToArray();
}
// other variables
Api.LoadStateBinary(reader);
IsLagFrame = reader.ReadBoolean();
LagCount = reader.ReadInt32();
Frame = reader.ReadInt32();
var profile = reader.ReadString();
ValidateLoadstateProfile(profile);*/
// refresh all callbacks now
Api.QUERY_set_video_refresh(snes_video_refresh);
Api.QUERY_set_input_poll(snes_input_poll);
Api.QUERY_set_input_state(snes_input_state);
Api.QUERY_set_input_notify(snes_input_notify);
Api.QUERY_set_audio_sample(_soundcb);
}
public byte[] SaveStateBinary()
@ -89,13 +54,5 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
bw.Flush();
return ms.ToArray();
}
private void ValidateLoadstateProfile(string profile)
{
if (profile != CurrentProfile)
{
throw new InvalidOperationException($"You've attempted to load a savestate made using a different SNES profile ({profile}) than your current configuration ({CurrentProfile}). We COULD automatically switch for you, but we havent done that yet. This error is to make sure you know that this isnt going to work right now.");
}
}
}
}

View File

@ -169,13 +169,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
}
Api.QUERY_set_path_request(null);
Api.Seal();
RefreshPalette();
Api.QUERY_set_video_refresh(snes_video_refresh);
Api.QUERY_set_input_poll(snes_input_poll);
Api.QUERY_set_input_state(snes_input_state);
Api.QUERY_set_input_notify(snes_input_notify);
Api.QUERY_set_audio_sample(_soundcb);
Api.Seal();
RefreshPalette();
}
private readonly GameInfo _game;

View File

@ -34,7 +34,6 @@ SRCS_ALL:= \
$(ROOT_DIR)/bsnes/base/base.cpp \
$(ROOT_DIR)/bsnes/gameboy/apu/apu.cpp \
$(ROOT_DIR)/bsnes/gameboy/cartridge/cartridge.cpp \
$(ROOT_DIR)/bsnes/gameboy/cheat/cheat.cpp \
$(ROOT_DIR)/bsnes/gameboy/cpu/cpu.cpp \
$(ROOT_DIR)/bsnes/snes/alt/dsp/dsp.cpp \
$(ROOT_DIR)/bsnes/gameboy/interface/interface.cpp \
@ -44,7 +43,6 @@ SRCS_ALL:= \
$(ROOT_DIR)/bsnes/gameboy/system/system.cpp \
$(ROOT_DIR)/bsnes/gameboy/video/video.cpp \
$(ROOT_DIR)/bsnes/snes/cartridge/cartridge.cpp \
$(ROOT_DIR)/bsnes/snes/cheat/cheat.cpp \
$(ROOT_DIR)/bsnes/snes/chip/armdsp/armdsp.cpp \
$(ROOT_DIR)/bsnes/snes/chip/bsx/bsx.cpp \
$(ROOT_DIR)/bsnes/snes/chip/hitachidsp/hitachidsp.cpp \

View File

@ -1,91 +0,0 @@
#include <gameboy/gameboy.hpp>
namespace GameBoy {
Cheat cheat;
bool Cheat::decode(const string &code_, unsigned &addr, unsigned &data, unsigned &comp) {
static bool initialize = false;
static uint8 mapProActionReplay[256], mapGameGenie[256];
if(initialize == false) {
initialize = true;
for(auto &n : mapProActionReplay) n = ~0;
mapProActionReplay['0'] = 0; mapProActionReplay['1'] = 1; mapProActionReplay['2'] = 2; mapProActionReplay['3'] = 3;
mapProActionReplay['4'] = 4; mapProActionReplay['5'] = 5; mapProActionReplay['6'] = 6; mapProActionReplay['7'] = 7;
mapProActionReplay['8'] = 8; mapProActionReplay['9'] = 9; mapProActionReplay['A'] = 10; mapProActionReplay['B'] = 11;
mapProActionReplay['C'] = 12; mapProActionReplay['D'] = 13; mapProActionReplay['E'] = 14; mapProActionReplay['F'] = 15;
for(auto &n : mapGameGenie) n = ~0;
mapGameGenie['0'] = 0; mapGameGenie['1'] = 1; mapGameGenie['2'] = 2; mapGameGenie['3'] = 3;
mapGameGenie['4'] = 4; mapGameGenie['5'] = 5; mapGameGenie['6'] = 6; mapGameGenie['7'] = 7;
mapGameGenie['8'] = 8; mapGameGenie['9'] = 9; mapGameGenie['A'] = 10; mapGameGenie['B'] = 11;
mapGameGenie['C'] = 12; mapGameGenie['D'] = 13; mapGameGenie['E'] = 14; mapGameGenie['F'] = 15;
}
string code = code_;
code.upper();
unsigned length = code.length(), bits = 0;
if(code.wildcard("????:??")) {
code = { substr(code, 0, 4), substr(code, 5, 2) };
for(unsigned n = 0; n < 6; n++) if(mapProActionReplay[code[n]] > 15) return false;
bits = hex(code);
addr = (bits >> 8) & 0xffff;
data = (bits >> 0) & 0xff;
comp = ~0;
return true;
}
if(code.wildcard("????:??:??")) {
code = { substr(code, 0, 4), substr(code, 5, 2), substr(code, 8, 2) };
for(unsigned n = 0; n < 8; n++) if(mapProActionReplay[code[n]] > 15) return false;
bits = hex(code);
addr = (bits >> 16) & 0xffff;
data = (bits >> 8) & 0xff;
comp = (bits >> 0) & 0xff;
return true;
}
if(code.wildcard("???" "-" "???")) {
code = { substr(code, 0, 3), substr(code, 4, 3) };
for(unsigned n = 0; n < 6; n++) if(mapGameGenie[code[n]] > 15) return false;
for(unsigned n = 0; n < 6; n++) bits |= mapGameGenie[code[n]] << (20 - n * 4);
addr = (bits >> 0) & 0xffff;
data = (bits >> 16) & 0xff;
comp = ~0;
addr = (((addr >> 4) | (addr << 12)) & 0xffff) ^ 0xf000;
return true;
}
if(code.wildcard("???" "-" "???" "-" "???")) {
code = { substr(code, 0, 3), substr(code, 4, 3), substr(code, 8, 1), substr(code, 10, 1) };
for(unsigned n = 0; n < 8; n++) if(mapGameGenie[code[n]] > 15) return false;
for(unsigned n = 0; n < 8; n++) bits |= mapGameGenie[code[n]] << (28 - n * 4);
addr = (bits >> 8) & 0xffff;
data = (bits >> 24) & 0xff;
comp = (bits >> 0) & 0xff;
addr = (((addr >> 4) | (addr << 12)) & 0xffff) ^ 0xf000;
comp = (((comp >> 2) | (comp << 6)) & 0xff) ^ 0xba;
return true;
}
return false;
}
void Cheat::synchronize() {
for(auto &n : override) n = false;
for(unsigned n = 0; n < size(); n++) {
override[operator[](n).addr] = true;
}
}
}

View File

@ -1,14 +0,0 @@
struct CheatCode {
unsigned addr;
unsigned data;
unsigned comp;
};
struct Cheat : public linear_vector<CheatCode> {
static bool decode(const string &code, unsigned &addr, unsigned &data, unsigned &comp);
void synchronize();
bool override[65536];
};
extern Cheat cheat;

View File

@ -53,7 +53,6 @@ namespace GameBoy {
#include <gameboy/cpu/cpu.hpp>
#include <gameboy/apu/apu.hpp>
#include <gameboy/lcd/lcd.hpp>
#include <gameboy/cheat/cheat.hpp>
#include <gameboy/video/video.hpp>
};

View File

@ -43,18 +43,6 @@ Memory::~Memory() {
uint8 Bus::read(uint16 addr) {
uint8 data = mmio[addr]->mmio_read(addr);
if(cheat.override[addr]) {
for(unsigned n = 0; n < cheat.size(); n++) {
if(cheat[n].addr == addr) {
if(cheat[n].comp > 255 || cheat[n].comp == data) {
data = cheat[n].data;
break;
}
}
}
}
return data;
}

View File

@ -1,110 +0,0 @@
#include <snes/snes.hpp>
#define CHEAT_CPP
namespace SNES {
Cheat cheat;
bool Cheat::enabled() const {
return system_enabled;
}
void Cheat::enable(bool state) {
system_enabled = state;
cheat_enabled = system_enabled && code_enabled;
}
void Cheat::synchronize() {
memset(override, 0x00, 16 * 1024 * 1024);
code_enabled = size() > 0;
for(unsigned i = 0; i < size(); i++) {
const CheatCode &code = operator[](i);
unsigned addr = mirror(code.addr);
override[addr] = true;
if((addr & 0xffe000) == 0x7e0000) {
//mirror $7e:0000-1fff to $00-3f|80-bf:0000-1fff
unsigned mirroraddr;
for(unsigned x = 0; x <= 0x3f; x++) {
mirroraddr = ((0x00 + x) << 16) + (addr & 0x1fff);
override[mirroraddr] = true;
mirroraddr = ((0x80 + x) << 16) + (addr & 0x1fff);
override[mirroraddr] = true;
}
}
}
cheat_enabled = system_enabled && code_enabled;
}
uint8 Cheat::read(unsigned addr) const {
addr = mirror(addr);
for(unsigned i = 0; i < size(); i++) {
const CheatCode &code = operator[](i);
if(addr == mirror(code.addr)) {
return code.data;
}
}
return 0x00;
}
void Cheat::init() {
memset(override, 0x00, 16 * 1024 * 1024);
}
Cheat::Cheat() {
override = new uint8[16 * 1024 * 1024];
system_enabled = true;
}
Cheat::~Cheat() {
delete[] override;
}
bool Cheat::decode(const string &code, unsigned &addr, unsigned &data) {
string t = code;
t.lower();
#define ischr(n) ((n >= '0' && n <= '9') || (n >= 'a' && n <= 'f'))
if(t.wildcard("??????:??")) {
//Direct
t = { substr(t, 0, 6), substr(t, 7, 2) };
for(unsigned n = 0; n < 8; n++) if(!ischr(t[n])) return false; //validate input
unsigned r = hex(t);
addr = r >> 8;
data = r & 0xff;
return true;
}
if(t.wildcard("????" "-" "????")) {
//Game Genie
t = { substr(t, 0, 4), substr(t, 5, 4) };
for(unsigned n = 0; n < 8; n++) if(!ischr(t[n])) return false; //validate input
t.transform("df4709156bc8a23e", "0123456789abcdef");
unsigned r = hex(t);
static unsigned bits[] = { 13, 12, 11, 10, 5, 4, 3, 2, 23, 22, 21, 20, 1, 0, 15, 14, 19, 18, 17, 16, 9, 8, 7, 6 };
addr = 0;
for(unsigned n = 0; n < 24; n++) addr |= r & (1 << bits[n]) ? 0x800000 >> n : 0;
data = r >> 24;
return true;
} else {
return false;
}
#undef ischr
}
unsigned Cheat::mirror(unsigned addr) const {
//$00-3f|80-bf:0000-1fff -> $7e:0000-1fff
if((addr & 0x40e000) == 0x000000) return (0x7e0000 + (addr & 0x1fff));
return addr;
}
}

View File

@ -1,27 +0,0 @@
struct CheatCode {
unsigned addr;
unsigned data;
};
struct Cheat : public linear_vector<CheatCode> {
uint8 *override;
bool enabled() const;
void enable(bool);
void synchronize();
uint8 read(unsigned) const;
void init();
Cheat();
~Cheat();
static bool decode(const string&, unsigned&, unsigned&);
private:
bool system_enabled;
bool code_enabled;
bool cheat_enabled;
unsigned mirror(unsigned) const;
};
extern Cheat cheat;

View File

@ -55,7 +55,6 @@ MappedRAM::MappedRAM(const char* name) : data_(0), size_(0), write_protect_(fals
//Bus
uint8 Bus::read(unsigned addr) {
if(cheat.override[addr]) return cheat.read(addr);
return reader[lookup[addr]](target[addr]);
}

View File

@ -67,7 +67,6 @@ namespace SNES {
#include <snes/system/system.hpp>
#include <snes/chip/chip.hpp>
#include <snes/cartridge/cartridge.hpp>
#include <snes/cheat/cheat.hpp>
#include <snes/interface/interface.hpp>
#include <snes/memory/memory-inline.hpp>

View File

@ -124,7 +124,6 @@ void System::load() {
if(cartridge.has_link()) link.load();
serialize_init();
cheat.init();
}
void System::unload() {

View File

@ -296,60 +296,6 @@ bool snes_unserialize(const uint8_t *data, unsigned size) {
return SNES::system.unserialize(s);
}
struct CheatList {
bool enable;
string code;
CheatList() : enable(false) {}
};
static linear_vector<CheatList> cheatList;
void snes_cheat_reset(void) {
cheatList.reset();
GameBoy::cheat.reset();
GameBoy::cheat.synchronize();
SNES::cheat.reset();
SNES::cheat.synchronize();
}
void snes_cheat_set(unsigned index, bool enable, const char *code) {
cheatList[index].enable = enable;
cheatList[index].code = code;
lstring list;
for(unsigned n = 0; n < cheatList.size(); n++) {
if(cheatList[n].enable) list.append(cheatList[n].code);
}
if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SuperGameBoy) {
GameBoy::cheat.reset();
for(auto &code : list) {
lstring codelist;
codelist.split("+", code);
for(auto &part : codelist) {
unsigned addr, data, comp;
if(GameBoy::Cheat::decode(part, addr, data, comp)) {
GameBoy::cheat.append({ addr, data, comp });
}
}
}
GameBoy::cheat.synchronize();
return;
}
SNES::cheat.reset();
for(auto &code : list) {
lstring codelist;
codelist.split("+", code);
for(auto &part : codelist) {
unsigned addr, data;
if(SNES::Cheat::decode(part, addr, data)) {
SNES::cheat.append({ addr, data });
}
}
}
SNES::cheat.synchronize();
}
//zero 21-sep-2012
void snes_set_scanlineStart(snes_scanlineStart_t cb)
{
@ -464,7 +410,6 @@ int snes_peek_logical_register(int reg)
bool snes_load_cartridge_normal(
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size
) {
snes_cheat_reset();
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
iface->cart = SnesCartridge(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;
@ -477,7 +422,6 @@ bool snes_load_cartridge_bsx_slotted(
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size
) {
snes_cheat_reset();
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
iface->cart = SnesCartridge(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;
@ -492,7 +436,6 @@ bool snes_load_cartridge_bsx(
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size
) {
snes_cheat_reset();
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
iface->cart = SnesCartridge(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;
@ -508,7 +451,6 @@ bool snes_load_cartridge_sufami_turbo(
const char *sta_xml, const uint8_t *sta_data, unsigned sta_size,
const char *stb_xml, const uint8_t *stb_data, unsigned stb_size
) {
snes_cheat_reset();
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
iface->cart = SnesCartridge(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;
@ -525,7 +467,6 @@ bool snes_load_cartridge_super_game_boy(
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size
) {
snes_cheat_reset();
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
iface->cart = SnesCartridge(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;

View File

@ -118,9 +118,6 @@ unsigned snes_serialize_size(void);
bool snes_serialize(uint8_t *data, unsigned size);
bool snes_unserialize(const uint8_t *data, unsigned size);
void snes_cheat_reset(void);
void snes_cheat_set(unsigned index, bool enable, const char *code);
bool snes_load_cartridge_normal(
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size
);