Update to v075r01 release.

byuu says:

Changelog:
- fixed Super Game Boy save state support
- both SNES and GameBoy only initialize serialize size on cartridge load
  once now, just like I've already done with memory mapping
- added nall/public_cast.hpp for fun ... don't worry, I'm never actually
  going to use it in production code :D
This commit is contained in:
Tim Allen 2011-01-29 20:48:44 +11:00
parent 6b4104867f
commit eecc085e42
15 changed files with 119 additions and 79 deletions

View File

@ -1,7 +1,7 @@
include nall/Makefile
snes := snes
gameboy := gameboy
profile := accuracy
profile := compatibility
ui := ui
# compiler

View File

@ -70,7 +70,19 @@ void Cartridge::load(const string &xml, const uint8_t *data, unsigned size) {
}
}
switch(info.mapper) { default:
case Mapper::MBC0: mapper = &mbc0; break;
case Mapper::MBC1: mapper = &mbc1; break;
case Mapper::MBC2: mapper = &mbc2; break;
case Mapper::MBC3: mapper = &mbc3; break;
case Mapper::MBC5: mapper = &mbc5; break;
case Mapper::MMM01: mapper = &mmm01; break;
case Mapper::HuC1: mapper = &huc1; break;
case Mapper::HuC3: mapper = &huc3; break;
}
ramdata = new uint8_t[ramsize = info.ramsize]();
system.load();
loaded = true;
}
@ -104,7 +116,19 @@ void Cartridge::ram_write(unsigned addr, uint8 data) {
ramdata[addr] = data;
}
uint8 Cartridge::mmio_read(uint16 addr) {
if(bootrom_enable && within<0x0000, 0x00ff>(addr)) return System::BootROM::sgb[addr];
return mapper->mmio_read(addr);
}
void Cartridge::mmio_write(uint16 addr, uint8 data) {
if(bootrom_enable && addr == 0xff50) bootrom_enable = false;
mapper->mmio_write(addr, data);
}
void Cartridge::power() {
bootrom_enable = true;
mbc0.power();
mbc1.power();
mbc2.power();
@ -113,26 +137,10 @@ void Cartridge::power() {
mmm01.power();
huc1.power();
huc3.power();
map();
}
void Cartridge::map() {
MMIO *mapper = 0;
switch(info.mapper) { default:
case Mapper::MBC0: mapper = &mbc0; break;
case Mapper::MBC1: mapper = &mbc1; break;
case Mapper::MBC2: mapper = &mbc2; break;
case Mapper::MBC3: mapper = &mbc3; break;
case Mapper::MBC5: mapper = &mbc5; break;
case Mapper::MMM01: mapper = &mmm01; break;
case Mapper::HuC1: mapper = &huc1; break;
case Mapper::HuC3: mapper = &huc3; break;
}
if(mapper) {
for(unsigned n = 0x0000; n <= 0x7fff; n++) bus.mmio[n] = mapper;
for(unsigned n = 0xa000; n <= 0xbfff; n++) bus.mmio[n] = mapper;
}
for(unsigned n = 0x0000; n <= 0x7fff; n++) bus.mmio[n] = this;
for(unsigned n = 0xa000; n <= 0xbfff; n++) bus.mmio[n] = this;
bus.mmio[0xff50] = this;
}
Cartridge::Cartridge() {

View File

@ -1,4 +1,4 @@
struct Cartridge : property<Cartridge> {
struct Cartridge : MMIO, property<Cartridge> {
#include "mbc0/mbc0.hpp"
#include "mbc1/mbc1.hpp"
#include "mbc2/mbc2.hpp"
@ -41,6 +41,9 @@ struct Cartridge : property<Cartridge> {
uint8_t *ramdata;
unsigned ramsize;
MMIO *mapper;
bool bootrom_enable;
void load(const string &xml, const uint8_t *data, unsigned size);
void unload();
@ -49,8 +52,10 @@ struct Cartridge : property<Cartridge> {
uint8 ram_read(unsigned addr);
void ram_write(unsigned addr, uint8 data);
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
void map();
void serialize(serializer&);
Cartridge();

View File

@ -2,6 +2,7 @@
void Cartridge::serialize(serializer &s) {
if(info.battery) s.array(ramdata, ramsize);
s.integer(bootrom_enable);
s.integer(mbc1.ram_enable);
s.integer(mbc1.rom_select);

View File

@ -5,7 +5,7 @@
namespace GameBoy {
namespace Info {
static const char Name[] = "bgameboy";
static const char Version[] = "000.13";
static const char Version[] = "000.14";
static unsigned SerializerVersion = 1;
}
}

View File

@ -50,7 +50,7 @@ void Bus::write(uint16 addr, uint8 data) {
}
void Bus::power() {
for(unsigned n = 0; n < 65536; n++) mmio[n] = &unmapped;
for(unsigned n = 0x0000; n <= 0xffff; n++) mmio[n] = &unmapped;
}
}

View File

@ -33,23 +33,14 @@ void System::runthreadtosave() {
}
}
uint8 System::mmio_read(uint16 addr) {
if((addr & 0xff00) == 0x0000) {
return BootROM::sgb[addr];
}
return 0x00;
}
void System::mmio_write(uint16 addr, uint8 data) {
if(addr == 0xff50) {
if(data == 0x01) cartridge.map();
}
}
void System::init(Interface *interface_) {
interface = interface_;
}
void System::load() {
serialize_init();
}
void System::power() {
bus.power();
cartridge.power();
@ -58,11 +49,7 @@ void System::power() {
lcd.power();
scheduler.init();
for(unsigned n = 0x0000; n <= 0x00ff; n++) bus.mmio[n] = this;
bus.mmio[0xff50] = this;
clocks_executed = 0;
serialize_init();
}
}

View File

@ -4,7 +4,7 @@ enum class Input : unsigned {
Up, Down, Left, Right, B, A, Select, Start,
};
struct System : MMIO {
struct System {
struct BootROM {
static const uint8 dmg[256];
static const uint8 sgb[256];
@ -14,10 +14,8 @@ struct System : MMIO {
void runtosave();
void runthreadtosave();
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void init(Interface*);
void load();
void power();
Interface *interface;

38
bsnes/nall/public_cast.hpp Executable file
View File

@ -0,0 +1,38 @@
#ifndef NALL_PUBLIC_CAST_HPP
#define NALL_PUBLIC_CAST_HPP
//this is a proof-of-concept-*only* C++ access-privilege elevation exploit.
//it allows full access to both protected and private member variables, objects and functions
//from the global scope, regardless of inheritance and/or friendship privileges.
//the code itself is 100% legal C++, per C++98 section 14.7.2 paragraph 8:
//"Access checking rules do not apply to names in explicit instantiations."
//C++0x variadic templates are used simply to allow public_cast name to be used
//on second derived class name for simplification, however the basic idea also
//works on C++98.
//usage example:
//struct N { typedef void (Class::*)(); };
//template class public_cast<N, &Class::Function>;
//(class.*public_cast<N>::value)();
namespace nall {
template<typename T, typename T::type... P> struct public_cast;
template<typename T> struct public_cast<T> {
static typename T::type value;
};
template<typename T> typename T::type public_cast<T>::value;
template<typename T, typename T::type P> struct public_cast<T, P> : public_cast<T> {
struct ref_t {
ref_t() { public_cast<T>::value = P; }
};
static ref_t ref;
};
template<typename T, typename T::type P> typename public_cast<T, P>::ref_t public_cast<T, P>::ref;
}
#endif

View File

@ -25,7 +25,7 @@ namespace nall {
inline string& append(unsigned int value);
inline string& append(double value);
inline bool readfile(const char*);
inline bool readfile(const string&);
inline string& replace (const char*, const char*);
inline string& qreplace(const char*, const char*);

View File

@ -95,7 +95,7 @@ string::~string() {
if(data) free(data);
}
bool string::readfile(const char *filename) {
bool string::readfile(const string &filename) {
assign("");
#if !defined(_WIN32)

View File

@ -53,7 +53,7 @@ string integer(intmax_t value) {
return result;
}
template<unsigned length> string linteger(intmax_t value) {
template<unsigned length_> string linteger(intmax_t value) {
bool negative = value < 0;
if(negative) value = abs(value);
@ -68,6 +68,7 @@ template<unsigned length> string linteger(intmax_t value) {
buffer[size++] = negative ? '-' : '+';
buffer[size] = 0;
unsigned length = (length_ == 0 ? size : length_);
char result[length + 1];
memset(result, ' ', length);
result[length] = 0;
@ -79,7 +80,7 @@ template<unsigned length> string linteger(intmax_t value) {
return result;
}
template<unsigned length> string rinteger(intmax_t value) {
template<unsigned length_> string rinteger(intmax_t value) {
bool negative = value < 0;
if(negative) value = abs(value);
@ -94,6 +95,7 @@ template<unsigned length> string rinteger(intmax_t value) {
buffer[size++] = negative ? '-' : '+';
buffer[size] = 0;
unsigned length = (length_ == 0 ? size : length_);
char result[length + 1];
memset(result, ' ', length);
result[length] = 0;
@ -127,7 +129,7 @@ string decimal(uintmax_t value) {
return result;
}
template<unsigned length> string ldecimal(uintmax_t value) {
template<unsigned length_> string ldecimal(uintmax_t value) {
char buffer[64];
unsigned size = 0;
@ -138,6 +140,7 @@ template<unsigned length> string ldecimal(uintmax_t value) {
} while(value);
buffer[size] = 0;
unsigned length = (length_ == 0 ? size : length_);
char result[length + 1];
memset(result, ' ', length);
result[length] = 0;
@ -149,7 +152,7 @@ template<unsigned length> string ldecimal(uintmax_t value) {
return result;
}
template<unsigned length> string rdecimal(uintmax_t value) {
template<unsigned length_> string rdecimal(uintmax_t value) {
char buffer[64];
unsigned size = 0;
@ -160,6 +163,7 @@ template<unsigned length> string rdecimal(uintmax_t value) {
} while(value);
buffer[size] = 0;
unsigned length = (length_ == 0 ? size : length_);
char result[length + 1];
memset(result, ' ', length);
result[length] = 0;
@ -171,50 +175,48 @@ template<unsigned length> string rdecimal(uintmax_t value) {
return result;
}
template<unsigned length> string hex(uintmax_t value) {
string output;
unsigned offset = 0;
template<unsigned length_> string hex(uintmax_t value) {
char buffer[64];
unsigned size = 0;
//render string backwards, as we do not know its length yet
do {
unsigned n = value & 15;
output[offset++] = n < 10 ? '0' + n : 'a' + n - 10;
buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10;
value >>= 4;
} while(value);
while(offset < length) output[offset++] = '0';
output[offset--] = 0;
unsigned length = (length_ == 0 ? size : length_);
char result[length + 1];
memset(result, '0', length);
result[length] = 0;
//reverse the string in-place
for(unsigned i = 0; i < (offset + 1) >> 1; i++) {
char temp = output[i];
output[i] = output[offset - i];
output[offset - i] = temp;
for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
result[x] = buffer[y];
}
return output;
return result;
}
template<unsigned length> string binary(uintmax_t value) {
string output;
unsigned offset = 0;
template<unsigned length_> string binary(uintmax_t value) {
char buffer[256];
unsigned size = 0;
do {
unsigned n = value & 1;
output[offset++] = '0' + n;
buffer[size++] = '0' + n;
value >>= 1;
} while(value);
while(offset < length) output[offset++] = '0';
output[offset--] = 0;
unsigned length = (length_ == 0 ? size : length_);
char result[length + 1];
memset(result, '0', length);
result[length] = 0;
for(unsigned i = 0; i < (offset + 1) >> 1; i++) {
char temp = output[i];
output[i] = output[offset - i];
output[offset - i] = temp;
for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
result[x] = buffer[y];
}
return output;
return result;
}
//using sprintf is certainly not the most ideal method to convert

View File

@ -1,8 +1,8 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "075";
static const unsigned SerializerVersion = 17;
static const char Version[] = "075.01";
static const unsigned SerializerVersion = 18;
}
}

View File

@ -121,6 +121,8 @@ void System::load() {
if(cartridge.has_st0018()) st0018.load();
if(cartridge.has_msu1()) msu1.load();
if(cartridge.has_serial()) serial.load();
serialize_init();
}
void System::unload() {
@ -183,7 +185,6 @@ void System::power() {
if(cartridge.has_serial()) cpu.coprocessors.append(&serial);
scheduler.init();
serialize_init();
cheat.init();
input.update();
@ -221,7 +222,6 @@ void System::reset() {
if(cartridge.has_serial()) cpu.coprocessors.append(&serial);
scheduler.init();
serialize_init();
cheat.init();
input.port_set_device(0, config.controller_port1);

View File

@ -41,6 +41,7 @@ bool Utility::loadState(unsigned slot) {
fp.read(data, size);
fp.close();
serializer s(data, size);
GameBoy::system.power();
return GameBoy::system.unserialize(s);
}