Update to bsnes v065r03 release.

Polishing work. My dlopen wrapper accepts an optional path argument
now, and the basename setting is universal instead of just for MSU1,
so serial-based games can load in a dynamic client library directly.

Still need to update snesserver to accept another argument for the
program library name to load.

Upped the serial polling frequency to 8x UART speed per blargg.

And a very tricky change, I updated nall/string to remove sprint(). At
first, I used:
    string name = string() << path << basename << ".msu";


I then improved upon that with:
    string name = sprint(path, basename, ".msu");


Tonight I went ahead and finished this by taking advantage of variadic
templates for the constructor itself. Very tricky because my
conversion functions created new strings to copy data into, which
would create an infinite loop; then of course I also had to leave the
copy constructor behind even after this. So the end result is the
following:
    string name(path, basename, ".msu");


Oh, and I found a typo in MSU1, it wasn't using the proper extension
when loading a save state for the data file.
This commit is contained in:
byuu 2010-07-12 15:56:17 +00:00
parent 20b44ddfd1
commit dce3e61f06
19 changed files with 126 additions and 134 deletions

View File

@ -3,9 +3,9 @@
//dynamic linking support
#include <string.h>
#include <nall/detect.hpp>
#include <nall/stdint.hpp>
#include <nall/string.hpp>
#include <nall/utility.hpp>
#if defined(PLATFORM_X) || defined(PLATFORM_OSX)
@ -18,7 +18,7 @@
namespace nall {
struct library {
bool opened() const { return handle; }
bool open(const char*);
bool open(const char*, const char* = "");
void* sym(const char*);
void close();
@ -33,20 +33,10 @@ namespace nall {
};
#if defined(PLATFORM_X)
inline bool library::open(const char *name) {
inline bool library::open(const char *name, const char *path) {
if(handle) close();
char *t = new char[strlen(name) + 256];
strcpy(t, "lib");
strcat(t, name);
strcat(t, ".so");
handle = (uintptr_t)dlopen(t, RTLD_LAZY);
if(!handle) {
strcpy(t, "/usr/local/lib/lib");
strcat(t, name);
strcat(t, ".so");
handle = (uintptr_t)dlopen(t, RTLD_LAZY);
}
delete[] t;
handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".so"), RTLD_LAZY);
if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY);
return handle;
}
@ -61,20 +51,10 @@ namespace nall {
handle = 0;
}
#elif defined(PLATFORM_OSX)
inline bool library::open(const char *name) {
inline bool library::open(const char *name, const char *path) {
if(handle) close();
char *t = new char[strlen(name) + 256];
strcpy(t, "lib");
strcat(t, name);
strcat(t, ".dylib");
handle = (uintptr_t)dlopen(t, RTLD_LAZY);
if(!handle) {
strcpy(t, "/usr/local/lib/lib");
strcat(t, name);
strcat(t, ".dylib");
handle = (uintptr_t)dlopen(t, RTLD_LAZY);
}
delete[] t;
handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".dylib"), RTLD_LAZY);
if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY);
return handle;
}
@ -89,13 +69,10 @@ namespace nall {
handle = 0;
}
#elif defined(PLATFORM_WIN)
inline bool library::open(const char *name) {
inline bool library::open(const char *name, const char *path) {
if(handle) close();
char *t = new char[strlen(name) + 8];
strcpy(t, name);
strcat(t, ".dll");
handle = (uintptr_t)LoadLibraryW(utf16_t(t));
delete[] t;
string filepath(path, *path && !strend(path, "/") && !strend(path, "\\") ? "\\" : "", name, ".dll");
handle = (uintptr_t)LoadLibraryW(utf16_t(filepath));
return handle;
}
@ -110,7 +87,7 @@ namespace nall {
handle = 0;
}
#else
inline bool library::open(const char*) { return false; }
inline bool library::open(const char*, const char*) { return false; }
inline void* library::sym(const char*) { return 0; }
inline void library::close() {}
#endif

View File

@ -23,10 +23,12 @@
#include <direct.h>
#include <shlobj.h>
#undef interface
#define dllexport __declspec(dllexport)
#else
#include <unistd.h>
#include <pwd.h>
#include <sys/stat.h>
#define dllexport
#endif
//==================

View File

@ -21,6 +21,11 @@ namespace nall {
inline string& assign(const char*);
inline string& append(const char*);
inline string& append(bool);
inline string& append(signed int value);
inline string& append(unsigned int value);
inline string& append(double value);
template<typename T> inline string& operator= (T value);
template<typename T> inline string& operator<<(T value);
@ -38,8 +43,7 @@ namespace nall {
inline string& operator=(const string&);
inline string& operator=(string&&);
inline string();
inline string(const char*);
template<typename... Args> inline string(Args... args);
inline string(const string&);
inline string(string&&);
inline ~string();
@ -129,7 +133,6 @@ namespace nall {
inline string strdouble(double value);
//variadic.hpp
template<typename... Args> inline string sprint(Args... args);
template<typename... Args> inline void print(Args... args);
};

View File

@ -29,6 +29,11 @@ string& string::append(const char *s) {
return *this;
}
string& string::append(bool value) { append(value ? "true" : "false"); return *this; }
string& string::append(signed int value) { append(strsigned(value)); return *this; }
string& string::append(unsigned int value) { append(strunsigned(value)); return *this; }
string& string::append(double value) { append(strdouble(value)); return *this; }
string::operator const char*() const {
return data;
}
@ -63,15 +68,20 @@ string& string::operator=(string &&source) {
return *this;
}
string::string() {
static void istring(string &output) {
}
template<typename T, typename... Args>
static void istring(string &output, T value, Args... args) {
output.append(value);
istring(output, args...);
}
template<typename... Args> string::string(Args... args) {
size = 64;
data = (char*)malloc(size + 1);
*data = 0;
}
string::string(const char *value) {
size = strlen(value);
data = strdup(value);
istring(*this, args...);
}
string::string(const string &value) {
@ -86,7 +96,7 @@ string::string(string &&source) {
}
string::~string() {
free(data);
if(data) free(data);
}
bool string::readfile(const char *filename) {

View File

@ -3,23 +3,8 @@
namespace nall {
static void isprint(string &output) {
}
template<typename T, typename... Args>
static void isprint(string &output, T value, Args... args) {
output << to_string<T>(value);
isprint(output, args...);
}
template<typename... Args> inline string sprint(Args... args) {
string output;
isprint(output, args...);
return output;
}
template<typename... Args> inline void print(Args... args) {
printf("%s", (const char*)sprint(args...));
printf("%s", (const char*)string(args...));
}
}

View File

@ -18,6 +18,10 @@ public:
Version2,
};
//assigned externally to point to file-system datafiles (msu1 and serial)
//example: "/path/to/filename.sfc" would set this to "/path/to/filename"
readwrite<string> basename;
readonly<bool> loaded;
readonly<unsigned> crc32;
readonly<string> sha256;

View File

@ -125,7 +125,7 @@ bool Cheat::encode(string &s, unsigned addr, uint8 data, Type type) {
char t[16];
if(type == Type::ProActionReplay) {
s = sprint(strhex<6>(addr), strhex<2>(data));
s = string(strhex<6>(addr), strhex<2>(data));
return true;
} else if(type == Type::GameGenie) {
unsigned r = addr;
@ -141,7 +141,7 @@ bool Cheat::encode(string &s, unsigned addr, uint8 data, Type type) {
| (!!(r & 0x080000) << 5) | (!!(r & 0x040000) << 4)
| (!!(r & 0x020000) << 3) | (!!(r & 0x010000) << 2)
| (!!(r & 0x000800) << 1) | (!!(r & 0x000400) << 0);
s = sprint(strhex<2>(data), strhex<2>(addr >> 16), "-", strhex<4>(addr & 0xffff));
s = string(strhex<2>(data), strhex<2>(addr >> 16), "-", strhex<4>(addr & 0xffff));
strtr(s, "0123456789abcdef", "df4709156bc8a23e");
return true;
} else {

View File

@ -49,7 +49,7 @@ void MSU1::enable() {
audio.coprocessor_frequency(44100.0);
if(datafile.open()) datafile.close();
datafile.open(string() << basename << ".msu", file::mode_read);
datafile.open(string() << cartridge.basename() << ".msu", file::mode_read);
}
void MSU1::power() {
@ -125,7 +125,7 @@ void MSU1::mmio_write(unsigned addr, uint8 data) {
if(audiofile.open()) audiofile.close();
char track[16];
sprintf(track, "-%u", mmio.audio_track);
if(audiofile.open(string() << basename << track << ".wav", file::mode_read)) {
if(audiofile.open(string() << cartridge.basename() << track << ".wav", file::mode_read)) {
audiofile.seek(mmio.audio_offset = 58); //skip WAV header
}
mmio.audio_busy = false;
@ -143,8 +143,4 @@ void MSU1::mmio_write(unsigned addr, uint8 data) {
}
}
void MSU1::base(const string& name) {
basename = name;
}
}

View File

@ -10,11 +10,9 @@ public:
uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data);
void base(const string &name);
void serialize(serializer&);
private:
string basename;
file datafile;
file audiofile;

View File

@ -11,14 +11,14 @@ void MSU1::serialize(serializer &s) {
s.integer(mmio.audio_play);
if(datafile.open()) datafile.close();
if(datafile.open(string() << basename << ".msun", file::mode_read)) {
if(datafile.open(string() << cartridge.basename() << ".msu", file::mode_read)) {
datafile.seek(mmio.data_offset);
}
if(audiofile.open()) audiofile.close();
char track[16];
sprintf(track, "-%u", mmio.audio_track);
if(audiofile.open(string() << basename << track << ".wav", file::mode_read)) {
if(audiofile.open(string() << cartridge.basename() << track << ".wav", file::mode_read)) {
audiofile.seek(mmio.audio_offset);
}
}

View File

@ -5,16 +5,16 @@ namespace SNES {
Serial serial;
static void snesserial_tick(unsigned clocks) { serial.add_clocks(clocks); }
static void snesserial_tick(unsigned clocks) { serial.add_clocks(clocks * 8); }
static uint8 snesserial_read() { return serial.read(); }
static void snesserial_write(uint8 data) { serial.write(data); }
void Serial::enter() {
scheduler.clock.cop_freq = cartridge.serial_baud_rate() * 4;
scheduler.clock.cop_freq = cartridge.serial_baud_rate() * 8; //over-sample for edge detection
latch = 0;
add_clocks(256 * 4);
add_clocks(256 * 8); //warm-up
if(snesserial_main) snesserial_main(snesserial_tick, snesserial_read, snesserial_write);
while(true) add_clocks(scheduler.clock.cop_freq);
while(true) add_clocks(scheduler.clock.cop_freq); //snesserial_main() fallback
}
void Serial::add_clocks(unsigned clocks) {
@ -25,11 +25,11 @@ void Serial::add_clocks(unsigned clocks) {
uint8 Serial::read() {
while(cpu.joylatch() == 0) add_clocks(1);
while(cpu.joylatch() == 1) add_clocks(1);
add_clocks(2);
add_clocks(4);
uint8 data = 0;
for(unsigned i = 0; i < 8; i++) {
add_clocks(4);
add_clocks(8);
data = (cpu.joylatch() << 7) | (data >> 1);
}
@ -38,16 +38,16 @@ uint8 Serial::read() {
void Serial::write(uint8 data) {
latch = 1;
add_clocks(4);
add_clocks(8);
for(unsigned i = 0; i < 8; i++) {
latch = (data & 0x01) ^ 1;
latch = (data & 1) ^ 1;
data >>= 1;
add_clocks(4);
add_clocks(8);
}
latch = 0;
add_clocks(4);
add_clocks(8);
}
void Serial::init() {
@ -55,7 +55,9 @@ void Serial::init() {
void Serial::enable() {
if(opened()) close();
if(open("snesserial")) {
string name = notdir(cartridge.basename());
string path = dir(cartridge.basename());
if(open(name, path)) {
snesserial_main = sym("snesserial_main");
}
}

View File

@ -4,11 +4,11 @@ bool CPUDebugger::property(unsigned id, string &name, string &value) {
unsigned n = 0;
//internal
if(id == n++) { name = "S-CPU MDR"; value = sprint("0x", strhex<2>(mdr())); return true; }
if(id == n++) { name = "S-CPU MDR"; value = string("0x", strhex<2>(mdr())); return true; }
//$2181-2183
if(id == n++) { name = "$2181-$2183"; value = ""; return true; }
if(id == n++) { name = "WRAM Address"; value = sprint("0x", strhex<6>(wram_address())); return true; }
if(id == n++) { name = "WRAM Address"; value = string("0x", strhex<6>(wram_address())); return true; }
//$4016
if(id == n++) { name = "$4016"; value = ""; return true; }
@ -23,39 +23,39 @@ bool CPUDebugger::property(unsigned id, string &name, string &value) {
//$4201
if(id == n++) { name = "$4201"; value = ""; return true; }
if(id == n++) { name = "PIO"; value = sprint("0x", strhex<2>(pio_bits())); return true; }
if(id == n++) { name = "PIO"; value = string("0x", strhex<2>(pio_bits())); return true; }
//$4202
if(id == n++) { name = "$4202"; value = ""; return true; }
if(id == n++) { name = "Multiplicand"; value = sprint("0x", strhex<2>(multiplicand())); return true; }
if(id == n++) { name = "Multiplicand"; value = string("0x", strhex<2>(multiplicand())); return true; }
//$4203
if(id == n++) { name = "$4203"; value = ""; return true; }
if(id == n++) { name = "Multiplier"; value = sprint("0x", strhex<2>(multiplier())); return true; }
if(id == n++) { name = "Multiplier"; value = string("0x", strhex<2>(multiplier())); return true; }
//$4204-$4205
if(id == n++) { name = "$4204-$4205"; value = ""; return true; }
if(id == n++) { name = "Dividend"; value = sprint("0x", strhex<4>(dividend())); return true; }
if(id == n++) { name = "Dividend"; value = string("0x", strhex<4>(dividend())); return true; }
//$4206
if(id == n++) { name = "$4206"; value = ""; return true; }
if(id == n++) { name = "Divisor"; value = sprint("0x", strhex<2>(divisor())); return true; }
if(id == n++) { name = "Divisor"; value = string("0x", strhex<2>(divisor())); return true; }
//$4207-$4208
if(id == n++) { name = "$4207-$4208"; value = ""; return true; }
if(id == n++) { name = "H-Time"; value = sprint("0x", strhex<4>(htime())); return true; }
if(id == n++) { name = "H-Time"; value = string("0x", strhex<4>(htime())); return true; }
//$4209-$420a
if(id == n++) { name = "$4209-$420a"; value = ""; return true; }
if(id == n++) { name = "V-Time"; value = sprint("0x", strhex<4>(vtime())); return true; }
if(id == n++) { name = "V-Time"; value = string("0x", strhex<4>(vtime())); return true; }
//$420b
if(id == n++) { name = "$420b"; value = ""; return true; }
if(id == n++) { name = "DMA Enable"; value = sprint("0x", strhex<2>(dma_enable())); return true; }
if(id == n++) { name = "DMA Enable"; value = string("0x", strhex<2>(dma_enable())); return true; }
//$420c
if(id == n++) { name = "$420c"; value = ""; return true; }
if(id == n++) { name = "HDMA Enable"; value = sprint("0x", strhex<2>(hdma_enable())); return true; }
if(id == n++) { name = "HDMA Enable"; value = string("0x", strhex<2>(hdma_enable())); return true; }
//$420d
if(id == n++) { name = "$420d"; value = ""; return true; }
@ -72,25 +72,25 @@ bool CPUDebugger::property(unsigned id, string &name, string &value) {
if(id == n++) { name = "Transfer Mode"; value = dma_transfer_mode(i); return true; }
//$43x1
if(id == n++) { name = "B-Bus Address"; value = sprint("0x", strhex<4>(dma_bbus_address(i))); return true; }
if(id == n++) { name = "B-Bus Address"; value = string("0x", strhex<4>(dma_bbus_address(i))); return true; }
//$43x2-$43x3
if(id == n++) { name = "A-Bus Address"; value = sprint("0x", strhex<4>(dma_abus_address(i))); return true; }
if(id == n++) { name = "A-Bus Address"; value = string("0x", strhex<4>(dma_abus_address(i))); return true; }
//$43x4
if(id == n++) { name = "A-Bus Bank"; value = sprint("0x", strhex<2>(dma_abus_bank(i))); return true; }
if(id == n++) { name = "A-Bus Bank"; value = string("0x", strhex<2>(dma_abus_bank(i))); return true; }
//$43x5-$43x6
if(id == n++) { name = "Transfer Size / Indirect Address"; value = sprint("0x", strhex<4>(dma_transfer_size(i))); return true; }
if(id == n++) { name = "Transfer Size / Indirect Address"; value = string("0x", strhex<4>(dma_transfer_size(i))); return true; }
//$43x7
if(id == n++) { name = "Indirect Bank"; value = sprint("0x", strhex<2>(dma_indirect_bank(i))); return true; }
if(id == n++) { name = "Indirect Bank"; value = string("0x", strhex<2>(dma_indirect_bank(i))); return true; }
//$43x8-$43x9
if(id == n++) { name = "Table Address"; value = sprint("0x", strhex<4>(dma_table_address(i))); return true; }
if(id == n++) { name = "Table Address"; value = string("0x", strhex<4>(dma_table_address(i))); return true; }
//$43xa
if(id == n++) { name = "Line Counter"; value = sprint("0x", strhex<2>(dma_line_counter(i))); return true; }
if(id == n++) { name = "Line Counter"; value = string("0x", strhex<2>(dma_line_counter(i))); return true; }
}
return false;

View File

@ -7,39 +7,39 @@ bool DSPDebugger::property(unsigned id, string &name, string &value) {
if(id == n++) { name = "Main Volume - Right"; value = main_volume_right(); return true; }
if(id == n++) { name = "Echo Volume - Left"; value = echo_volume_left(); return true; }
if(id == n++) { name = "Echo Volume - Right"; value = echo_volume_right(); return true; }
if(id == n++) { name = "Key On"; value = sprint("0x", strhex<2>(key_on())); return true; }
if(id == n++) { name = "Key Off"; value = sprint("0x", strhex<2>(key_off())); return true; }
if(id == n++) { name = "Key On"; value = string("0x", strhex<2>(key_on())); return true; }
if(id == n++) { name = "Key Off"; value = string("0x", strhex<2>(key_off())); return true; }
if(id == n++) { name = "Flag - Reset"; value = flag_reset(); return true; }
if(id == n++) { name = "Flag - Mute"; value = flag_mute(); return true; }
if(id == n++) { name = "Flag - Echo Disable"; value = flag_echo_disable(); return true; }
if(id == n++) { name = "Flag - Noise Clock"; value = flag_noise_clock(); return true; }
if(id == n++) { name = "Source End Block"; value = source_end_block(); return true; }
if(id == n++) { name = "Echo Feedback"; value = echo_feedback(); return true; }
if(id == n++) { name = "Pitch Modulation Enable"; value = sprint("0x", strhex<2>(pitch_modulation_enable())); return true; }
if(id == n++) { name = "Noise Enable"; value = sprint("0x", strhex<2>(noise_enable())); return true; }
if(id == n++) { name = "Echo Enable"; value = sprint("0x", strhex<2>(echo_enable())); return true; }
if(id == n++) { name = "Pitch Modulation Enable"; value = string("0x", strhex<2>(pitch_modulation_enable())); return true; }
if(id == n++) { name = "Noise Enable"; value = string("0x", strhex<2>(noise_enable())); return true; }
if(id == n++) { name = "Echo Enable"; value = string("0x", strhex<2>(echo_enable())); return true; }
if(id == n++) { name = "Source Directory"; value = source_directory(); return true; }
if(id == n++) { name = "Echo Start Address"; value = echo_start_address(); return true; }
if(id == n++) { name = "Echo Directory"; value = echo_directory(); return true; }
for(unsigned i = 0; i < 8; i++) {
if(id == n++) {
name = string() << "Coefficient " << i;
value = sprint("0x", strhex<2>(echo_filter_coefficient(i)));
name = string("Coefficient ", i);
value = string("0x", strhex<2>(echo_filter_coefficient(i)));
return true;
}
}
for(unsigned i = 0; i < 8; i++) {
if(id == n++) {
name = string() << "Voice " << i;
name = string("Voice ", i);
value = "";
return true;
}
if(id == n++) { name = "Volume - Left"; value = voice_volume_left(i); return true; }
if(id == n++) { name = "Volume - Right"; value = voice_volume_right(i); return true; }
if(id == n++) { name = "Pitch Height"; value = sprint("0x", strhex<4>(voice_pitch_height(i))); return true; }
if(id == n++) { name = "Pitch Height"; value = string("0x", strhex<4>(voice_pitch_height(i))); return true; }
if(id == n++) { name = "Source Number"; value = voice_source_number(i); return true; }
if(id == n++) { name = "ADSR1"; value = voice_adsr1(i); return true; }
if(id == n++) { name = "ADSR2"; value = voice_adsr2(i); return true; }

View File

@ -4,8 +4,8 @@ bool PPUDebugger::property(unsigned id, string &name, string &value) {
unsigned n = 0;
//internal
if(id == n++) { name = "S-PPU1 MDR"; value = sprint("0x", strhex<2>(ppu1_mdr())); return true; }
if(id == n++) { name = "S-PPU2 MDR"; value = sprint("0x", strhex<2>(ppu2_mdr())); return true; }
if(id == n++) { name = "S-PPU1 MDR"; value = string("0x", strhex<2>(ppu1_mdr())); return true; }
if(id == n++) { name = "S-PPU2 MDR"; value = string("0x", strhex<2>(ppu2_mdr())); return true; }
//$2100
if(id == n++) { name = "$2100"; value = ""; return true; }
@ -16,11 +16,11 @@ bool PPUDebugger::property(unsigned id, string &name, string &value) {
if(id == n++) { name = "$2101"; value = ""; return true; }
if(id == n++) { name = "OAM Base Size"; value = oam_base_size(); return true; }
if(id == n++) { name = "OAM Name Select"; value = oam_name_select(); return true; }
if(id == n++) { name = "OAM Name Base Address"; value = sprint("0x", strhex<4>(oam_name_base_address())); return true; }
if(id == n++) { name = "OAM Name Base Address"; value = string("0x", strhex<4>(oam_name_base_address())); return true; }
//$2102-$2103
if(id == n++) { name = "$2102-$2103"; value = ""; return true; }
if(id == n++) { name = "OAM Base Address"; value = sprint("0x", strhex<4>(oam_base_address())); return true; }
if(id == n++) { name = "OAM Base Address"; value = string("0x", strhex<4>(oam_base_address())); return true; }
if(id == n++) { name = "OAM Priority"; value = oam_priority(); return true; }
//$2105
@ -44,33 +44,33 @@ bool PPUDebugger::property(unsigned id, string &name, string &value) {
//$2107
if(id == n++) { name = "$2107"; value = ""; return true; }
if(id == n++) { name = "BG1 Screen Address"; value = sprint("0x", strhex<4>(bg1_screen_address())); return true; }
if(id == n++) { name = "BG1 Screen Address"; value = string("0x", strhex<4>(bg1_screen_address())); return true; }
if(id == n++) { name = "BG1 Screen Size"; value = screen_size[bg1_screen_size()]; return true; }
//$2108
if(id == n++) { name = "$2108"; value = ""; return true; }
if(id == n++) { name = "BG2 Screen Address"; value = sprint("0x", strhex<4>(bg2_screen_address())); return true; }
if(id == n++) { name = "BG2 Screen Address"; value = string("0x", strhex<4>(bg2_screen_address())); return true; }
if(id == n++) { name = "BG2 Screen Size"; value = screen_size[bg2_screen_size()]; return true; }
//$2109
if(id == n++) { name = "$2109"; value = ""; return true; }
if(id == n++) { name = "BG3 Screen Address"; value = sprint("0x", strhex<4>(bg3_screen_address())); return true; }
if(id == n++) { name = "BG3 Screen Address"; value = string("0x", strhex<4>(bg3_screen_address())); return true; }
if(id == n++) { name = "BG3 Screen Size"; value = screen_size[bg3_screen_size()]; return true; }
//$210a
if(id == n++) { name = "$210a"; value = ""; return true; }
if(id == n++) { name = "BG4 Screen Address"; value = sprint("0x", strhex<4>(bg4_screen_address())); return true; }
if(id == n++) { name = "BG4 Screen Address"; value = string("0x", strhex<4>(bg4_screen_address())); return true; }
if(id == n++) { name = "BG4 Screen Size"; value = screen_size[bg4_screen_size()]; return true; }
//$210b
if(id == n++) { name = "$210b"; value = ""; return true; }
if(id == n++) { name = "BG1 Name Base Address"; value = sprint("0x", strhex<4>(bg1_name_base_address())); return true; }
if(id == n++) { name = "BG2 Name Base Address"; value = sprint("0x", strhex<4>(bg2_name_base_address())); return true; }
if(id == n++) { name = "BG1 Name Base Address"; value = string("0x", strhex<4>(bg1_name_base_address())); return true; }
if(id == n++) { name = "BG2 Name Base Address"; value = string("0x", strhex<4>(bg2_name_base_address())); return true; }
//$210c
if(id == n++) { name = "$210c"; value = ""; return true; }
if(id == n++) { name = "BG3 Name Base Address"; value = sprint("0x", strhex<4>(bg3_name_base_address())); return true; }
if(id == n++) { name = "BG4 Name Base Address"; value = sprint("0x", strhex<4>(bg4_name_base_address())); return true; }
if(id == n++) { name = "BG3 Name Base Address"; value = string("0x", strhex<4>(bg3_name_base_address())); return true; }
if(id == n++) { name = "BG4 Name Base Address"; value = string("0x", strhex<4>(bg4_name_base_address())); return true; }
//$210d
if(id == n++) { name = "$210d"; value = ""; return true; }
@ -114,7 +114,7 @@ bool PPUDebugger::property(unsigned id, string &name, string &value) {
//$2116-$2117
if(id == n++) { name = "$2116-$2117"; value = ""; return true; }
if(id == n++) { name = "VRAM Address"; value = sprint("0x", strhex<4>(vram_address())); return true; }
if(id == n++) { name = "VRAM Address"; value = string("0x", strhex<4>(vram_address())); return true; }
//$211a
if(id == n++) { name = "$211a"; value = ""; return true; }
@ -148,7 +148,7 @@ bool PPUDebugger::property(unsigned id, string &name, string &value) {
//$2121
if(id == n++) { name = "$2121"; value = ""; return true; }
if(id == n++) { name = "CGRAM Address"; value = sprint("0x", strhex<4>(cgram_address())); return true; }
if(id == n++) { name = "CGRAM Address"; value = string("0x", strhex<4>(cgram_address())); return true; }
//$2123
if(id == n++) { name = "$2123"; value = ""; return true; }

View File

@ -17,7 +17,7 @@ bool SMPDebugger::property(unsigned id, string &name, string &value) {
//$00f2
if(id == n++) { name = "$00f2"; value = ""; return true; }
if(id == n++) { name = "DSP Address"; value = sprint("0x", strhex<2>(dsp_address())); return true; }
if(id == n++) { name = "DSP Address"; value = string("0x", strhex<2>(dsp_address())); return true; }
return false;
}

View File

@ -1,4 +1,4 @@
static const char bsnesVersion[] = "065.02";
static const char bsnesVersion[] = "065.03";
static const char bsnesTitle[] = "bsnes";
static const unsigned bsnesSerializerVersion = 10;

View File

@ -102,8 +102,8 @@ void FileBrowser::onChangeCartridge(const string &path) {
else filename = path;
string info;
string image = sprint(nall::basename(filename), ".png");
string patch = sprint(filepath(nall::basename(filename), config().path.patch), ".ups");
string image(nall::basename(filename), ".png");
string patch(filepath(nall::basename(filename), config().path.patch), ".ups");
if(file::exists(filename)) {
if(striend(filename, ".sfc")) {

View File

@ -49,6 +49,7 @@ bool Cartridge::saveStatesSupported() {
if(SNES::cartridge.has_dsp4()) return false;
if(SNES::cartridge.has_st0011()) return false;
if(SNES::cartridge.has_st0018()) return false;
if(SNES::cartridge.has_serial()) return false;
return true;
}
@ -56,7 +57,7 @@ bool Cartridge::saveStatesSupported() {
bool Cartridge::loadNormal(const char *base) {
unload();
if(loadCartridge(baseName = base, cartridge.baseXml, SNES::memory::cartrom) == false) return false;
SNES::msu1.base(nall::basename(baseName));
SNES::cartridge.basename = nall::basename(baseName);
SNES::cartridge.load(SNES::Cartridge::Mode::Normal,
lstring() << cartridge.baseXml);
@ -75,6 +76,8 @@ bool Cartridge::loadBsxSlotted(const char *base, const char *slot) {
unload();
if(loadCartridge(baseName = base, cartridge.baseXml, SNES::memory::cartrom) == false) return false;
loadCartridge(slotAName = slot, cartridge.slotAXml, SNES::memory::bsxflash);
SNES::cartridge.basename = nall::basename(baseName);
SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted,
lstring() << cartridge.baseXml << cartridge.slotAXml);
@ -93,6 +96,8 @@ bool Cartridge::loadBsx(const char *base, const char *slot) {
unload();
if(loadCartridge(baseName = base, cartridge.baseXml, SNES::memory::cartrom) == false) return false;
loadCartridge(slotAName = slot, cartridge.slotAXml, SNES::memory::bsxflash);
SNES::cartridge.basename = nall::basename(baseName);
SNES::cartridge.load(SNES::Cartridge::Mode::Bsx,
lstring() << cartridge.baseXml << cartridge.slotAXml);
@ -113,6 +118,8 @@ bool Cartridge::loadSufamiTurbo(const char *base, const char *slotA, const char
if(loadCartridge(baseName = base, cartridge.baseXml, SNES::memory::cartrom) == false) return false;
loadCartridge(slotAName = slotA, cartridge.slotAXml, SNES::memory::stArom);
loadCartridge(slotBName = slotB, cartridge.slotBXml, SNES::memory::stBrom);
SNES::cartridge.basename = nall::basename(baseName);
SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo,
lstring() << cartridge.baseXml << cartridge.slotAXml << cartridge.slotBXml);
@ -133,6 +140,8 @@ bool Cartridge::loadSuperGameBoy(const char *base, const char *slot) {
unload();
if(loadCartridge(baseName = base, cartridge.baseXml, SNES::memory::cartrom) == false) return false;
loadCartridge(slotAName = slot, cartridge.slotAXml, SNES::memory::gbrom);
SNES::cartridge.basename = nall::basename(baseName);
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy,
lstring() << cartridge.baseXml << cartridge.slotAXml);
@ -207,7 +216,7 @@ bool Cartridge::loadCartridge(string &filename, string &xml, SNES::MappedRAM &me
if(reader.load(filename, data, size) == false) return false;
patchApplied = false;
string name = sprint(filepath(nall::basename(filename), config().path.patch), ".ups");
string name(filepath(nall::basename(filename), config().path.patch), ".ups");
file fp;
if(config().file.applyPatches && fp.open(name, file::mode_read)) {
@ -239,7 +248,7 @@ bool Cartridge::loadCartridge(string &filename, string &xml, SNES::MappedRAM &me
}
}
name = sprint(nall::basename(filename), ".xml");
name = string(nall::basename(filename), ".xml");
if(file::exists(name)) {
//prefer manually created XML cartridge mapping
xml.readfile(name);

View File

@ -2,7 +2,10 @@
State state;
bool State::save(unsigned slot) {
if(!allowed()) return false;
if(!allowed()) {
utility.showMessage("Cannot save state.");
return false;
}
SNES::system.runtosave();
serializer state = SNES::system.serialize();
@ -24,7 +27,10 @@ bool State::save(unsigned slot) {
}
bool State::load(unsigned slot) {
if(!allowed()) return false;
if(!allowed()) {
utility.showMessage("Cannot load state.");
return false;
}
file fp;
bool result = false;