mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-10-02 07:37:11 +02:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0114e10ede |
24
readme.txt
24
readme.txt
@@ -1,5 +1,5 @@
|
|||||||
bsnes
|
bsnes
|
||||||
Version: 0.035
|
Version: 0.036
|
||||||
Author: byuu
|
Author: byuu
|
||||||
|
|
||||||
========
|
========
|
||||||
@@ -38,9 +38,9 @@ If you wish to have multiple configuration profiles for the same user, you will
|
|||||||
need to make copies of the bsnes executable, and use each one in single-user
|
need to make copies of the bsnes executable, and use each one in single-user
|
||||||
mode.
|
mode.
|
||||||
|
|
||||||
==================
|
====================
|
||||||
Known Limitations:
|
Known Limitation(s):
|
||||||
==================
|
====================
|
||||||
|
|
||||||
S-CPU
|
S-CPU
|
||||||
- Multiply / divide register delays not implemented
|
- Multiply / divide register delays not implemented
|
||||||
@@ -60,6 +60,16 @@ Hardware Bugs
|
|||||||
- S-CPU.r1 HDMA crashing bug not emulated
|
- S-CPU.r1 HDMA crashing bug not emulated
|
||||||
- S-CPU<>S-SMP communication bus conflicts not emulated
|
- S-CPU<>S-SMP communication bus conflicts not emulated
|
||||||
|
|
||||||
|
===============
|
||||||
|
Known Issue(s):
|
||||||
|
===============
|
||||||
|
|
||||||
|
On Windows, attempting to load a ZIP, GZ or JMA compressed archive with
|
||||||
|
non-ANSI characters in the filename will fail. This is because Windows
|
||||||
|
requires UTF-16 encoding, but these libraries only work with UTF-8.
|
||||||
|
Note that loading uncompressed images (SMC, SFC, etc) with non-ANSI characters
|
||||||
|
works properly on all platforms.
|
||||||
|
|
||||||
=====================
|
=====================
|
||||||
Unsupported Hardware:
|
Unsupported Hardware:
|
||||||
=====================
|
=====================
|
||||||
@@ -89,9 +99,9 @@ SETA RISC CPU used by Quick-move Shogi Match with Nidan Rank-holder Morita 2
|
|||||||
Super Gameboy
|
Super Gameboy
|
||||||
Cartridge passthrough used for playing Gameboy games
|
Cartridge passthrough used for playing Gameboy games
|
||||||
|
|
||||||
========================
|
==========================
|
||||||
Unsupported Controllers:
|
Unsupported Controller(s):
|
||||||
========================
|
==========================
|
||||||
|
|
||||||
Mouse
|
Mouse
|
||||||
Super Scope
|
Super Scope
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#define BSNES_VERSION "0.035"
|
#define BSNES_VERSION "0.036"
|
||||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||||
|
|
||||||
#define BUSCORE sBus
|
#define BUSCORE sBus
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <nall/bit.hpp>
|
#include <nall/bit.hpp>
|
||||||
#include <nall/config.hpp>
|
#include <nall/config.hpp>
|
||||||
#include <nall/detect.hpp>
|
#include <nall/detect.hpp>
|
||||||
|
#include <nall/file.hpp>
|
||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
||||||
#include <nall/modulo.hpp>
|
#include <nall/modulo.hpp>
|
||||||
#include <nall/new.hpp>
|
#include <nall/new.hpp>
|
||||||
@@ -41,3 +42,9 @@ void alert(const char*, ...);
|
|||||||
void dprintf(const char*, ...);
|
void dprintf(const char*, ...);
|
||||||
|
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
|
||||||
|
//helper: disable access to FILE, when possible (GZIP / JMA require it)
|
||||||
|
//reason: Windows fopen() does not support UTF-8 filenames; use nall::file instead.
|
||||||
|
#if !defined(GZIP_SUPPORT) && !defined(JMA_SUPPORT)
|
||||||
|
#define FILE FILE_deprecated
|
||||||
|
#endif
|
||||||
|
@@ -89,7 +89,7 @@ void Cartridge::load_end() {
|
|||||||
memory::stBrom.write_protect(true);
|
memory::stBrom.write_protect(true);
|
||||||
memory::stBram.write_protect(false);
|
memory::stBram.write_protect(false);
|
||||||
|
|
||||||
if(fexists(get_cheat_filename(cart.fn, "cht"))) {
|
if(file::exists(get_cheat_filename(cart.fn, "cht"))) {
|
||||||
cheat.clear();
|
cheat.clear();
|
||||||
cheat.load(cheatfn);
|
cheat.load(cheatfn);
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ bool Cartridge::unload() {
|
|||||||
char fn[PATH_MAX];
|
char fn[PATH_MAX];
|
||||||
strcpy(fn, cart.fn);
|
strcpy(fn, cart.fn);
|
||||||
modify_extension(fn, "cht");
|
modify_extension(fn, "cht");
|
||||||
if(cheat.count() > 0 || fexists(get_cheat_filename(cart.fn, "cht"))) {
|
if(cheat.count() > 0 || file::exists(get_cheat_filename(cart.fn, "cht"))) {
|
||||||
cheat.save(cheatfn);
|
cheat.save(cheatfn);
|
||||||
cheat.clear();
|
cheat.clear();
|
||||||
}
|
}
|
||||||
|
@@ -89,7 +89,7 @@ char* Cartridge::get_cheat_filename(const char *source, const char *extension) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size, CompressionMode compression) {
|
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size, CompressionMode compression) {
|
||||||
if(fexists(fn) == false) return false;
|
if(file::exists(fn) == false) return false;
|
||||||
|
|
||||||
Reader::Type filetype = Reader::Normal;
|
Reader::Type filetype = Reader::Normal;
|
||||||
if(compression == CompressionInspect) filetype = Reader::detect(fn, true);
|
if(compression == CompressionInspect) filetype = Reader::detect(fn, true);
|
||||||
@@ -122,6 +122,10 @@ bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size, CompressionM
|
|||||||
|
|
||||||
case Reader::ZIP: {
|
case Reader::ZIP: {
|
||||||
ZipReader zf(fn);
|
ZipReader zf(fn);
|
||||||
|
if(!zf.ready()) {
|
||||||
|
alert("Error loading image file (%s)!", fn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
size = zf.size();
|
size = zf.size();
|
||||||
data = zf.read();
|
data = zf.read();
|
||||||
} break;
|
} break;
|
||||||
@@ -169,10 +173,10 @@ bool Cartridge::apply_patch(const uint8_t *pdata, const unsigned psize, uint8_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
||||||
FILE *fp = fopen(fn, "wb");
|
file fp;
|
||||||
if(!fp) return false;
|
if(!fp.open(fn, file::mode_write)) return false;
|
||||||
fwrite(data, 1, size, fp);
|
fp.write(data, size);
|
||||||
fclose(fp);
|
fp.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -295,15 +295,15 @@ bool Cheat::load(const char *fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::save(const char *fn) {
|
bool Cheat::save(const char *fn) {
|
||||||
FILE *fp = fopen(fn, "wb");
|
file fp;
|
||||||
if(!fp) return false;
|
if(!fp.open(fn, file::mode_write)) return false;
|
||||||
for(unsigned i = 0; i < cheat_count; i++) {
|
for(unsigned i = 0; i < cheat_count; i++) {
|
||||||
fprintf(fp, "%9s = %8s, \"%s\"\r\n",
|
fp.print(string()
|
||||||
index[i].code,
|
<< index[i].code << " = "
|
||||||
index[i].enabled ? "enabled" : "disabled",
|
<< (index[i].enabled ? "enabled" : "disabled") << ", \""
|
||||||
index[i].desc);
|
<< index[i].desc << "\"\r\n");
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fp.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -150,7 +150,7 @@ void sCPU::cycle_edge() {
|
|||||||
if(hdma_enabled_channels()) {
|
if(hdma_enabled_channels()) {
|
||||||
dma_add_clocks(8 - dma_counter()); //DMA sync
|
dma_add_clocks(8 - dma_counter()); //DMA sync
|
||||||
status.hdma_mode == 0 ? hdma_init() : hdma_run();
|
status.hdma_mode == 0 ? hdma_init() : hdma_run();
|
||||||
status.dma_state = DMA_CPUsync;
|
if(!dma_enabled_channels()) status.dma_state = DMA_CPUsync;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
bbase : version 0.14 ~byuu (2008-04-16)
|
bbase : version 0.15 ~byuu (2008-09-14)
|
||||||
license: public domain
|
license: public domain
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -52,17 +52,10 @@ using std::max;
|
|||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#define getcwd _getcwd
|
#define getcwd _getcwd
|
||||||
#define ftruncate _chsize
|
#define ftruncate _chsize
|
||||||
#define mkdir _mkdir
|
|
||||||
#define putenv _putenv
|
#define putenv _putenv
|
||||||
#define rmdir _rmdir
|
#define rmdir _rmdir
|
||||||
#define vsnprintf _vsnprintf
|
#define vsnprintf _vsnprintf
|
||||||
#define usleep(n) Sleep(n / 1000)
|
#define usleep(n) Sleep(n / 1000)
|
||||||
|
|
||||||
static char *realpath(const char *file_name, char *resolved_name) {
|
|
||||||
return _fullpath(resolved_name, file_name, PATH_MAX);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define mkdir(path) (mkdir)(path, 0755);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
@@ -87,15 +80,21 @@ using std::max;
|
|||||||
* OS localization
|
* OS localization
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
//userpath(output) retrieves path to user's home folder
|
|
||||||
//output must be at least as large as PATH_MAX
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
static char* realpath(const char *file_name, char *resolved_name) {
|
||||||
|
wchar_t filename[PATH_MAX] = L"";
|
||||||
|
_wfullpath(filename, utf16(file_name), PATH_MAX);
|
||||||
|
strcpy(resolved_name, utf8(filename));
|
||||||
|
return resolved_name;
|
||||||
|
}
|
||||||
|
|
||||||
static char* userpath(char *output) {
|
static char* userpath(char *output) {
|
||||||
strcpy(output, "."); //failsafe
|
wchar_t path[PATH_MAX] = L"."; //failsafe
|
||||||
SHGetFolderPath(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, output);
|
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path);
|
||||||
|
strcpy(output, utf8(path));
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
#define mkdir(path) _wmkdir(utf16(path))
|
||||||
#else
|
#else
|
||||||
static char* userpath(char *output) {
|
static char* userpath(char *output) {
|
||||||
strcpy(output, "."); //failsafe
|
strcpy(output, "."); //failsafe
|
||||||
@@ -103,6 +102,7 @@ static char *userpath(char *output) {
|
|||||||
if(userinfo) { strcpy(output, userinfo->pw_dir); }
|
if(userinfo) { strcpy(output, userinfo->pw_dir); }
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
#define mkdir(path) (mkdir)(path, 0755);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<int min, int max, typename T> inline T minmax(const T x) {
|
template<int min, int max, typename T> inline T minmax(const T x) {
|
||||||
@@ -157,49 +157,4 @@ static unsigned prng() {
|
|||||||
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64 fget(FILE *fp, unsigned length = 1) {
|
|
||||||
uint64 data = 0;
|
|
||||||
for(unsigned i = 0; i < length; i++) {
|
|
||||||
data |= fgetc(fp) << (i << 3);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fput(FILE *fp, uint64 data, unsigned length = 1) {
|
|
||||||
for(unsigned i = 0; i < length; i++) {
|
|
||||||
fputc(data >> (i << 3), fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool fexists(const char *fn) {
|
|
||||||
FILE *fp = fopen(fn, "rb");
|
|
||||||
if(!fp) return false;
|
|
||||||
fclose(fp);
|
|
||||||
fp = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned fsize(FILE *fp) {
|
|
||||||
if(!fp) return 0;
|
|
||||||
unsigned pos = ftell(fp);
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
unsigned size = ftell(fp);
|
|
||||||
fseek(fp, pos, SEEK_SET);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned fsize(const char *fn) {
|
|
||||||
FILE *fp = fopen(fn, "rb");
|
|
||||||
if(!fp) return 0;
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
unsigned size = ftell(fp);
|
|
||||||
fclose(fp);
|
|
||||||
fp = 0;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fresize(FILE *fp, long size) {
|
|
||||||
return ftruncate(fileno(fp), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //ifndef BBASE_H
|
#endif //ifndef BBASE_H
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
mingw32-g++ -c test/test.cpp -I. -I../
|
|
||||||
mingw32-g++ -c hiro.cpp -I. -I../
|
|
||||||
mingw32-g++ -c ../nall/string.cpp -I. -I../
|
|
||||||
mingw32-g++ test.o hiro.o string.o -o test_app.exe -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomctl32 -lcomdlg32
|
|
||||||
@pause
|
|
||||||
@del *.o
|
|
@@ -1,6 +0,0 @@
|
|||||||
clear
|
|
||||||
g++ -c test/test.cpp -I. -I../
|
|
||||||
g++ -c hiro.cpp `pkg-config --cflags gtk+-2.0` -I. -I../
|
|
||||||
g++ -c ../nall/string.cpp -I. -I../
|
|
||||||
g++ test.o hiro.o string.o -o test_app `pkg-config --libs gtk+-2.0` -lXtst
|
|
||||||
rm *.o
|
|
@@ -4,11 +4,14 @@
|
|||||||
using nall::min;
|
using nall::min;
|
||||||
using nall::max;
|
using nall::max;
|
||||||
|
|
||||||
|
#include <nall/utf8.hpp>
|
||||||
|
using nall::utf8;
|
||||||
|
using nall::utf16;
|
||||||
|
|
||||||
namespace libhiro {
|
namespace libhiro {
|
||||||
|
|
||||||
LRESULT CALLBACK phiro_wndproc(HWND, UINT, WPARAM, LPARAM);
|
LRESULT CALLBACK phiro_wndproc(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
#include "utf.cpp"
|
|
||||||
#include "keymap.cpp"
|
#include "keymap.cpp"
|
||||||
#include "widget.cpp"
|
#include "widget.cpp"
|
||||||
#include "window.cpp"
|
#include "window.cpp"
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#define NALL_CONFIG_HPP
|
#define NALL_CONFIG_HPP
|
||||||
|
|
||||||
#include <nall/array.hpp>
|
#include <nall/array.hpp>
|
||||||
|
#include <nall/file.hpp>
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
#include <nall/string.hpp>
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ class configuration {
|
|||||||
public:
|
public:
|
||||||
array<setting*> list;
|
array<setting*> list;
|
||||||
|
|
||||||
bool load(const char *fn) const;
|
bool load(const char *fn);
|
||||||
bool save(const char *fn) const;
|
bool save(const char *fn) const;
|
||||||
void add(setting *setting_) { list.add(setting_); }
|
void add(setting *setting_) { list.add(setting_); }
|
||||||
};
|
};
|
||||||
@@ -116,28 +117,17 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool configuration::load(const char *fn) const {
|
inline bool configuration::load(const char *fn) {
|
||||||
FILE *fp = fopen(fn, "rb");
|
|
||||||
if(!fp) return false;
|
|
||||||
|
|
||||||
string data;
|
|
||||||
lstring line, part, subpart;
|
|
||||||
|
|
||||||
//load the config file into memory
|
//load the config file into memory
|
||||||
fseek(fp, 0, SEEK_END);
|
string data;
|
||||||
int size = ftell(fp);
|
if(!fread(data, fn)) return false;
|
||||||
fseek(fp, 0, SEEK_SET);
|
|
||||||
char *buffer = (char*)malloc(size + 1);
|
|
||||||
fread(buffer, 1, size, fp);
|
|
||||||
fclose(fp);
|
|
||||||
buffer[size] = 0;
|
|
||||||
strcpy(data, buffer);
|
|
||||||
free(buffer);
|
|
||||||
|
|
||||||
//split the file into lines
|
//split the file into lines
|
||||||
replace(data, "\r\n", "\n");
|
replace(data, "\r\n", "\n");
|
||||||
qreplace(data, "\t", "");
|
qreplace(data, "\t", "");
|
||||||
qreplace(data, " ", "");
|
qreplace(data, " ", "");
|
||||||
|
|
||||||
|
lstring line, part, subpart;
|
||||||
split(line, "\n", data);
|
split(line, "\n", data);
|
||||||
|
|
||||||
for(unsigned i = 0; i < count(line); i++) {
|
for(unsigned i = 0; i < count(line); i++) {
|
||||||
@@ -157,8 +147,8 @@ inline bool configuration::load(const char *fn) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool configuration::save(const char *fn) const {
|
inline bool configuration::save(const char *fn) const {
|
||||||
FILE *fp = fopen(fn, "wb");
|
file fp;
|
||||||
if(!fp) return false;
|
if(!fp.open(fn, file::mode_write)) return false;
|
||||||
|
|
||||||
for(unsigned i = 0; i < list.size(); i++) {
|
for(unsigned i = 0; i < list.size(); i++) {
|
||||||
string data;
|
string data;
|
||||||
@@ -166,18 +156,20 @@ inline bool configuration::save(const char *fn) const {
|
|||||||
strcpy(data, list[i]->description);
|
strcpy(data, list[i]->description);
|
||||||
replace(data, "\r\n", "\n");
|
replace(data, "\r\n", "\n");
|
||||||
split(line, "\n", data);
|
split(line, "\n", data);
|
||||||
|
|
||||||
|
string temp;
|
||||||
for(unsigned l = 0; l < count(line); l++) {
|
for(unsigned l = 0; l < count(line); l++) {
|
||||||
if(line[l] != "") fprintf(fp, "# %s\r\n", (const char*)line[l]);
|
if(line[l] != "") fp.print(string() << "# " << line[l] << "\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
string default_, value_;
|
string default_, value_;
|
||||||
list[i]->get_default(default_);
|
list[i]->get_default(default_);
|
||||||
fprintf(fp, "# (default = %s)\r\n", (const char*)default_);
|
fp.print(string() << "# (default = " << default_ << ")\r\n");
|
||||||
list[i]->get(value_);
|
list[i]->get(value_);
|
||||||
fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, (const char*)value_);
|
fp.print(string() << list[i]->name << " = " << value_ << "\r\n\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fp.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
|
#include <nall/utf8.hpp>
|
||||||
#include <nall/utility.hpp>
|
#include <nall/utility.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
@@ -69,6 +70,11 @@ public:
|
|||||||
while(length--) write(*buffer++);
|
while(length--) write(*buffer++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print(const char *string) {
|
||||||
|
if(!string) return;
|
||||||
|
while(*string) write(*string++);
|
||||||
|
}
|
||||||
|
|
||||||
void flush() {
|
void flush() {
|
||||||
buffer_flush();
|
buffer_flush();
|
||||||
fflush(fp);
|
fflush(fp);
|
||||||
@@ -112,13 +118,38 @@ public:
|
|||||||
return file_offset >= file_size;
|
return file_offset >= file_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool exists(const char *fn) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
FILE *fp = fopen(fn, "rb");
|
||||||
|
#else
|
||||||
|
FILE *fp = _wfopen(utf16(fn), L"rb");
|
||||||
|
#endif
|
||||||
|
if(fp) {
|
||||||
|
fclose(fp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open() {
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
bool open(const char *fn, FileMode mode) {
|
bool open(const char *fn, FileMode mode) {
|
||||||
if(fp) return false;
|
if(fp) return false;
|
||||||
|
|
||||||
switch(file_mode = mode) {
|
switch(file_mode = mode) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
case mode_read: fp = fopen(fn, "rb"); break;
|
case mode_read: fp = fopen(fn, "rb"); break;
|
||||||
case mode_write: fp = fopen(fn, "wb+"); break; //need read permission for buffering
|
case mode_write: fp = fopen(fn, "wb+"); break; //need read permission for buffering
|
||||||
case mode_readwrite: fp = fopen(fn, "rb+"); break;
|
case mode_readwrite: fp = fopen(fn, "rb+"); break;
|
||||||
case mode_writeread: fp = fopen(fn, "wb+"); break;
|
case mode_writeread: fp = fopen(fn, "wb+"); break;
|
||||||
|
#else
|
||||||
|
case mode_read: fp = _wfopen(utf16(fn), L"rb"); break;
|
||||||
|
case mode_write: fp = _wfopen(utf16(fn), L"wb+"); break;
|
||||||
|
case mode_readwrite: fp = _wfopen(utf16(fn), L"rb+"); break;
|
||||||
|
case mode_writeread: fp = _wfopen(utf16(fn), L"wb+"); break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if(!fp) return false;
|
if(!fp) return false;
|
||||||
buffer_offset = -1; //invalidate buffer
|
buffer_offset = -1; //invalidate buffer
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#define NALL_FILEMAP_HPP
|
#define NALL_FILEMAP_HPP
|
||||||
|
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
|
#include <nall/utf8.hpp>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -72,7 +73,7 @@ private:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_filehandle = CreateFile(filename, desired_access, FILE_SHARE_READ, NULL,
|
p_filehandle = CreateFileW(utf16(filename), desired_access, FILE_SHARE_READ, NULL,
|
||||||
creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL);
|
creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if(p_filehandle == INVALID_HANDLE_VALUE) return false;
|
if(p_filehandle == INVALID_HANDLE_VALUE) return false;
|
||||||
|
|
||||||
|
82
src/lib/nall/serial.hpp
Normal file
82
src/lib/nall/serial.hpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#ifndef NALL_SERIAL_HPP
|
||||||
|
#define NALL_SERIAL_HPP
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <nall/stdint.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
class serial {
|
||||||
|
public:
|
||||||
|
//-1 on error, otherwise return bytes read
|
||||||
|
int read(uint8_t *data, unsigned length) {
|
||||||
|
if(port_open == false) return -1;
|
||||||
|
return ::read(port, (void*)data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-1 on error, otherwise return bytes written
|
||||||
|
int write(const uint8_t *data, unsigned length) {
|
||||||
|
if(port_open == false) return -1;
|
||||||
|
return ::write(port, (void*)data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open(const char *portname, unsigned rate) {
|
||||||
|
close();
|
||||||
|
|
||||||
|
port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
|
||||||
|
if(port == -1) return false;
|
||||||
|
|
||||||
|
if(ioctl(port, TIOCEXCL) == -1) { close(); return false; }
|
||||||
|
if(fcntl(port, F_SETFL, 0) == -1) { close(); return false; }
|
||||||
|
if(tcgetattr(port, &original_attr) == -1) { close(); return false; }
|
||||||
|
|
||||||
|
termios attr = original_attr;
|
||||||
|
cfmakeraw(&attr);
|
||||||
|
cfsetspeed(&attr, rate);
|
||||||
|
|
||||||
|
attr.c_lflag &=~ (ECHO | ECHONL | ISIG | ICANON | IEXTEN);
|
||||||
|
attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY);
|
||||||
|
attr.c_iflag |= (IGNBRK | IGNPAR);
|
||||||
|
attr.c_oflag &=~ (OPOST);
|
||||||
|
attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB);
|
||||||
|
attr.c_cflag |= (CS8 | CREAD | CLOCAL);
|
||||||
|
attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0;
|
||||||
|
|
||||||
|
if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; }
|
||||||
|
return port_open = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
if(port != -1) {
|
||||||
|
tcdrain(port);
|
||||||
|
if(port_open == true) {
|
||||||
|
tcsetattr(port, TCSANOW, &original_attr);
|
||||||
|
port_open = false;
|
||||||
|
}
|
||||||
|
::close(port);
|
||||||
|
port = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serial() {
|
||||||
|
port = -1;
|
||||||
|
port_open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
~serial() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int port;
|
||||||
|
bool port_open;
|
||||||
|
termios original_attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} //namespace nall
|
||||||
|
|
||||||
|
#endif //ifndef NALL_SERIAL_HPP
|
@@ -4,9 +4,9 @@
|
|||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
template<typename T> inline void swap(T &x, T &y) {
|
template<typename T> inline void swap(T &x, T &y) {
|
||||||
T z = x;
|
T temp = x;
|
||||||
x = y;
|
x = y;
|
||||||
y = z;
|
y = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -22,8 +22,8 @@ void sort(T list[], unsigned length) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename Tcmp>
|
template<typename T, typename Comparator>
|
||||||
void sort(T list[], unsigned length, Tcmp comparator) {
|
void sort(T list[], unsigned length, Comparator comparator) {
|
||||||
for(unsigned d = 0; d < length; d++) {
|
for(unsigned d = 0; d < length; d++) {
|
||||||
unsigned min = d;
|
unsigned min = d;
|
||||||
for(unsigned s = d + 1; s < length; s++) {
|
for(unsigned s = d + 1; s < length; s++) {
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <nall/algorithm.hpp>
|
#include <nall/algorithm.hpp>
|
||||||
#include <nall/static.hpp>
|
#include <nall/static.hpp>
|
||||||
|
#include <nall/utf8.hpp>
|
||||||
|
|
||||||
#include <nall/string.hpp>
|
#include <nall/string.hpp>
|
||||||
#include <nall/string/class.cpp>
|
#include <nall/string/class.cpp>
|
||||||
|
@@ -203,7 +203,11 @@ nall::string temp;
|
|||||||
bool fread(nall::string &str, const char *filename) {
|
bool fread(nall::string &str, const char *filename) {
|
||||||
strcpy(str, "");
|
strcpy(str, "");
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
FILE *fp = fopen(filename, "rb");
|
FILE *fp = fopen(filename, "rb");
|
||||||
|
#else
|
||||||
|
FILE *fp = _wfopen(nall::utf16(filename), L"rb");
|
||||||
|
#endif
|
||||||
if(!fp)return false;
|
if(!fp)return false;
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(fp, 0, SEEK_END);
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <nall/algorithm.hpp>
|
#include <nall/algorithm.hpp>
|
||||||
#include <nall/crc32.hpp>
|
#include <nall/crc32.hpp>
|
||||||
|
#include <nall/file.hpp>
|
||||||
#include <nall/new.hpp>
|
#include <nall/new.hpp>
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
|
|
||||||
@@ -25,8 +26,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
ups::result create(const char *patch_fn, const uint8_t *x_data, unsigned x_size, const uint8_t *y_data, unsigned y_size) {
|
ups::result create(const char *patch_fn, const uint8_t *x_data, unsigned x_size, const uint8_t *y_data, unsigned y_size) {
|
||||||
fp = fopen(patch_fn, "wb");
|
if(!fp.open(patch_fn, file::mode_write)) return patch_unwritable;
|
||||||
if(!fp) return patch_unwritable;
|
|
||||||
|
|
||||||
crc32 = ~0;
|
crc32 = ~0;
|
||||||
uint32_t x_crc32 = crc32_calculate(x_data, x_size);
|
uint32_t x_crc32 = crc32_calculate(x_data, x_size);
|
||||||
@@ -77,7 +77,7 @@ public:
|
|||||||
uint32_t p_crc32 = ~crc32;
|
uint32_t p_crc32 = ~crc32;
|
||||||
for(unsigned i = 0; i < 4; i++) write(p_crc32 >> (i << 3));
|
for(unsigned i = 0; i < 4; i++) write(p_crc32 >> (i << 3));
|
||||||
|
|
||||||
fclose(fp);
|
fp.close();
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILE *fp;
|
file fp;
|
||||||
uint32_t crc32;
|
uint32_t crc32;
|
||||||
const uint8_t *p_buffer;
|
const uint8_t *p_buffer;
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void write(uint8_t n) {
|
void write(uint8_t n) {
|
||||||
fputc(n, fp);
|
fp.write(n);
|
||||||
crc32 = crc32_adjust(crc32, n);
|
crc32 = crc32_adjust(crc32, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,18 @@
|
|||||||
/*****
|
#ifndef NALL_UTF8_HPP
|
||||||
* UTF-8 to UTF-16
|
#define NALL_UTF8_HPP
|
||||||
*****/
|
|
||||||
|
#include <nall/new.hpp>
|
||||||
|
|
||||||
|
//UTF-8 <> UTF-16 conversion
|
||||||
|
//used only for Win32; Linux, etc use UTF-8 internally
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
//UTF-8 to UTF-16
|
||||||
class utf16 {
|
class utf16 {
|
||||||
public:
|
public:
|
||||||
operator wchar_t*() {
|
operator wchar_t*() {
|
||||||
@@ -26,9 +38,7 @@ private:
|
|||||||
wchar_t *buffer;
|
wchar_t *buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****
|
//UTF-16 to UTF-8
|
||||||
* UTF-16 to UTF-8
|
|
||||||
*****/
|
|
||||||
class utf8 {
|
class utf8 {
|
||||||
public:
|
public:
|
||||||
operator char*() {
|
operator char*() {
|
||||||
@@ -53,3 +63,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
char *buffer;
|
char *buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} //namespace nall
|
||||||
|
|
||||||
|
#endif //if defined(_WIN32)
|
||||||
|
|
||||||
|
#endif //ifndef NALL_UTF8_HPP
|
@@ -3,7 +3,7 @@
|
|||||||
#include "filereader.h"
|
#include "filereader.h"
|
||||||
|
|
||||||
unsigned FileReader::size() {
|
unsigned FileReader::size() {
|
||||||
return filesize;
|
return fp.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
//This function will allocate memory even if open() fails.
|
//This function will allocate memory even if open() fails.
|
||||||
@@ -15,44 +15,35 @@ uint8_t* FileReader::read(unsigned length) {
|
|||||||
|
|
||||||
if(length == 0) {
|
if(length == 0) {
|
||||||
//read the entire file into RAM
|
//read the entire file into RAM
|
||||||
data = new(zeromemory) uint8_t[filesize];
|
data = new(zeromemory) uint8_t[fp.size()];
|
||||||
if(fp) fread(data, 1, filesize, fp);
|
if(fp.open()) fp.read(data, fp.size());
|
||||||
} else if(length > filesize) {
|
} else if(length > fp.size()) {
|
||||||
//read the entire file into RAM, pad the rest with 0x00s
|
//read the entire file into RAM, pad the rest with 0x00s
|
||||||
data = new(zeromemory) uint8_t[length];
|
data = new(zeromemory) uint8_t[length];
|
||||||
if(fp) fread(data, 1, filesize, fp);
|
if(fp.open()) fp.read(data, fp.size());
|
||||||
} else { //filesize >= length
|
} else { //filesize >= length
|
||||||
//read only what was requested
|
//read only what was requested
|
||||||
data = new(zeromemory) uint8_t[length];
|
data = new(zeromemory) uint8_t[length];
|
||||||
if(fp) fread(data, 1, length, fp);
|
if(fp.open()) fp.read(data, length);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileReader::ready() {
|
bool FileReader::ready() {
|
||||||
return (fp != 0);
|
return fp.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileReader::FileReader(const char *fn) {
|
FileReader::FileReader(const char *fn) {
|
||||||
fp = fopen(fn, "rb");
|
if(!fp.open(fn, file::mode_read)) return;
|
||||||
if(!fp) return;
|
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
filesize = ftell(fp);
|
|
||||||
rewind(fp);
|
|
||||||
|
|
||||||
//empty file?
|
//empty file?
|
||||||
if(filesize == 0) {
|
if(fp.size() == 0) {
|
||||||
fclose(fp);
|
fp.close();
|
||||||
fp = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileReader::~FileReader() {
|
FileReader::~FileReader() {
|
||||||
if(fp) {
|
if(fp.open()) fp.close();
|
||||||
fclose(fp);
|
|
||||||
fp = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //ifdef READER_CPP
|
#endif //ifdef READER_CPP
|
||||||
|
@@ -8,6 +8,5 @@ public:
|
|||||||
~FileReader();
|
~FileReader();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILE *fp;
|
file fp;
|
||||||
unsigned filesize;
|
|
||||||
};
|
};
|
||||||
|
@@ -13,13 +13,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Reader::Type Reader::detect(const char *fn, bool inspectheader) {
|
Reader::Type Reader::detect(const char *fn, bool inspectheader) {
|
||||||
FILE *fp = fopen(fn, "rb");
|
file fp;
|
||||||
if(!fp) return Unknown;
|
if(!fp.open(fn, file::mode_read)) return Unknown;
|
||||||
|
|
||||||
uint8_t p[8];
|
uint8_t p[8];
|
||||||
memset(p, 0, sizeof p);
|
memset(p, 0, sizeof p);
|
||||||
fread(p, 1, 8, fp);
|
fp.read(p, 8);
|
||||||
fclose(fp);
|
fp.close();
|
||||||
|
|
||||||
if(inspectheader == true) {
|
if(inspectheader == true) {
|
||||||
//inspect file header to determine type
|
//inspect file header to determine type
|
||||||
|
@@ -26,7 +26,11 @@ uint8_t* ZipReader::read(unsigned length) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZipReader::ZipReader(const char *fn) : filesize(0) {
|
bool ZipReader::ready() {
|
||||||
|
return zipready;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipReader::ZipReader(const char *fn) : filesize(0), zipready(false) {
|
||||||
unz_file_info cFileInfo; //Create variable to hold info for a compressed file
|
unz_file_info cFileInfo; //Create variable to hold info for a compressed file
|
||||||
char cFileName[sizeof(cname)];
|
char cFileName[sizeof(cname)];
|
||||||
|
|
||||||
@@ -44,6 +48,7 @@ ZipReader::ZipReader(const char *fn) : filesize(0) {
|
|||||||
if(filesize) {
|
if(filesize) {
|
||||||
unzLocateFile(zipfile, cname, 1);
|
unzLocateFile(zipfile, cname, 1);
|
||||||
unzOpenCurrentFile(zipfile);
|
unzOpenCurrentFile(zipfile);
|
||||||
|
zipready = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@ class ZipReader : public Reader {
|
|||||||
public:
|
public:
|
||||||
unsigned size();
|
unsigned size();
|
||||||
uint8_t* read(unsigned length = 0);
|
uint8_t* read(unsigned length = 0);
|
||||||
|
bool ready();
|
||||||
|
|
||||||
ZipReader(const char *fn);
|
ZipReader(const char *fn);
|
||||||
~ZipReader();
|
~ZipReader();
|
||||||
@@ -14,5 +15,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
unzFile zipfile;
|
unzFile zipfile;
|
||||||
uint32 filesize;
|
uint32 filesize;
|
||||||
|
bool zipready;
|
||||||
char cname[4096];
|
char cname[4096];
|
||||||
};
|
};
|
||||||
|
@@ -4,8 +4,10 @@
|
|||||||
|
|
||||||
void SNES::Audio::update(uint16 l_sample, uint16 r_sample) {
|
void SNES::Audio::update(uint16 l_sample, uint16 r_sample) {
|
||||||
if(pcmfp) {
|
if(pcmfp) {
|
||||||
fput(pcmfp, l_sample, 2);
|
fputc(l_sample >> 0, pcmfp);
|
||||||
fput(pcmfp, r_sample, 2);
|
fputc(l_sample >> 8, pcmfp);
|
||||||
|
fputc(r_sample >> 0, pcmfp);
|
||||||
|
fputc(r_sample >> 8, pcmfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
snesinterface.audio_sample(l_sample, r_sample);
|
snesinterface.audio_sample(l_sample, r_sample);
|
||||||
|
@@ -109,7 +109,7 @@ struct Audio {
|
|||||||
static integral_setting synchronize;
|
static integral_setting synchronize;
|
||||||
} audio;
|
} audio;
|
||||||
integral_setting Audio::output_frequency(config(), "audio.output_frequency", "Sound card audio output frequency", integral_setting::decimal, 48000);
|
integral_setting Audio::output_frequency(config(), "audio.output_frequency", "Sound card audio output frequency", integral_setting::decimal, 48000);
|
||||||
integral_setting Audio::input_frequency(config(), "audio.input_frequency", "Emulator audio input frequency", integral_setting::decimal, 31960);
|
integral_setting Audio::input_frequency(config(), "audio.input_frequency", "Emulator audio input frequency", integral_setting::decimal, 32000);
|
||||||
integral_setting Audio::latency(config(), "audio.latency", "Sound card latency (in ms)", integral_setting::decimal, 100);
|
integral_setting Audio::latency(config(), "audio.latency", "Sound card latency (in ms)", integral_setting::decimal, 100);
|
||||||
integral_setting Audio::volume(config(), "audio.volume", "Audio volume (10 - 100)", integral_setting::decimal, 100);
|
integral_setting Audio::volume(config(), "audio.volume", "Audio volume (10 - 100)", integral_setting::decimal, 100);
|
||||||
integral_setting Audio::mute(config(), "audio.mute", "Mute audio playback", integral_setting::boolean, false);
|
integral_setting Audio::mute(config(), "audio.mute", "Mute audio playback", integral_setting::boolean, false);
|
||||||
|
@@ -302,6 +302,7 @@ bool load_rom(char *fn) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//File -> Load ROM action
|
||||||
void load_rom() {
|
void load_rom() {
|
||||||
char fn[PATH_MAX];
|
char fn[PATH_MAX];
|
||||||
if(load_rom(fn) == false) return;
|
if(load_rom(fn) == false) return;
|
||||||
@@ -311,8 +312,9 @@ void load_rom() {
|
|||||||
void load_cart_normal(const char *filename) {
|
void load_cart_normal(const char *filename) {
|
||||||
if(!filename || !*filename) return;
|
if(!filename || !*filename) return;
|
||||||
|
|
||||||
if(cartridge.loaded() == true) cartridge.unload();
|
unload_rom();
|
||||||
cartridge.load_cart_normal(filename);
|
cartridge.load_cart_normal(filename);
|
||||||
|
if(cartridge.loaded() == false) return;
|
||||||
|
|
||||||
app.pause = false;
|
app.pause = false;
|
||||||
snes.power();
|
snes.power();
|
||||||
@@ -338,8 +340,9 @@ void load_cart_normal(const char *filename) {
|
|||||||
void load_cart_bsx(const char *base, const char *slot) {
|
void load_cart_bsx(const char *base, const char *slot) {
|
||||||
if(!base || !*base) return;
|
if(!base || !*base) return;
|
||||||
|
|
||||||
if(cartridge.loaded() == true) cartridge.unload();
|
unload_rom();
|
||||||
cartridge.load_cart_bsx(base, slot);
|
cartridge.load_cart_bsx(base, slot);
|
||||||
|
if(cartridge.loaded() == false) return;
|
||||||
|
|
||||||
app.pause = false;
|
app.pause = false;
|
||||||
snes.power();
|
snes.power();
|
||||||
@@ -357,8 +360,9 @@ void load_cart_bsx(const char *base, const char *slot) {
|
|||||||
void load_cart_bsc(const char *base, const char *slot) {
|
void load_cart_bsc(const char *base, const char *slot) {
|
||||||
if(!base || !*base) return;
|
if(!base || !*base) return;
|
||||||
|
|
||||||
if(cartridge.loaded() == true) cartridge.unload();
|
unload_rom();
|
||||||
cartridge.load_cart_bsc(base, slot);
|
cartridge.load_cart_bsc(base, slot);
|
||||||
|
if(cartridge.loaded() == false) return;
|
||||||
|
|
||||||
app.pause = false;
|
app.pause = false;
|
||||||
snes.power();
|
snes.power();
|
||||||
@@ -376,8 +380,9 @@ void load_cart_bsc(const char *base, const char *slot) {
|
|||||||
void load_cart_st(const char *base, const char *slotA, const char *slotB) {
|
void load_cart_st(const char *base, const char *slotA, const char *slotB) {
|
||||||
if(!base || !*base) return;
|
if(!base || !*base) return;
|
||||||
|
|
||||||
if(cartridge.loaded() == true) cartridge.unload();
|
unload_rom();
|
||||||
cartridge.load_cart_st(base, slotA, slotB);
|
cartridge.load_cart_st(base, slotA, slotB);
|
||||||
|
if(cartridge.loaded() == false) return;
|
||||||
|
|
||||||
app.pause = false;
|
app.pause = false;
|
||||||
snes.power();
|
snes.power();
|
||||||
@@ -393,11 +398,12 @@ void load_cart_st(const char *base, const char *slotA, const char *slotB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void unload_rom() {
|
void unload_rom() {
|
||||||
if(cartridge.loaded() == true) {
|
if(cartridge.loaded() == false) return;
|
||||||
|
|
||||||
cartridge.unload();
|
cartridge.unload();
|
||||||
video.clear();
|
video.clear();
|
||||||
audio.clear();
|
audio.clear();
|
||||||
}
|
|
||||||
window_main.menu_file_unload.disable();
|
window_main.menu_file_unload.disable();
|
||||||
window_main.menu_file_reset.disable();
|
window_main.menu_file_reset.disable();
|
||||||
window_main.menu_file_power.disable();
|
window_main.menu_file_power.disable();
|
||||||
|
@@ -55,6 +55,7 @@ void dprintf(const char *s, ...) {
|
|||||||
va_start(args, s);
|
va_start(args, s);
|
||||||
vsprintf(str, s, args);
|
vsprintf(str, s, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
fprintf(stdout, "%s\r\n", str);
|
fprintf(stdout, "%s\r\n", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +90,7 @@ void set_config_filenames() {
|
|||||||
//locate bsnes.cfg
|
//locate bsnes.cfg
|
||||||
strcpy(filename, config::path.base);
|
strcpy(filename, config::path.base);
|
||||||
strcat(filename, "bsnes.cfg");
|
strcat(filename, "bsnes.cfg");
|
||||||
if(!fexists(filename)) {
|
if(!file::exists(filename)) {
|
||||||
strcpy(filename, config::path.user);
|
strcpy(filename, config::path.user);
|
||||||
strcat(filename, ".bsnes");
|
strcat(filename, ".bsnes");
|
||||||
mkdir(filename);
|
mkdir(filename);
|
||||||
@@ -100,7 +101,7 @@ void set_config_filenames() {
|
|||||||
//locate locale.cfg
|
//locate locale.cfg
|
||||||
strcpy(filename, config::path.base);
|
strcpy(filename, config::path.base);
|
||||||
strcat(filename, "locale.cfg");
|
strcat(filename, "locale.cfg");
|
||||||
if(!fexists(filename)) {
|
if(!file::exists(filename)) {
|
||||||
strcpy(filename, config::path.user);
|
strcpy(filename, config::path.user);
|
||||||
strcat(filename, ".bsnes");
|
strcat(filename, ".bsnes");
|
||||||
mkdir(filename);
|
mkdir(filename);
|
||||||
@@ -136,18 +137,26 @@ void run() {
|
|||||||
|
|
||||||
#if defined(PLATFORM_WIN)
|
#if defined(PLATFORM_WIN)
|
||||||
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
|
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
|
||||||
int argc = __argc;
|
//On Windows, argv[] is in 7-bit ANSI format, UTF-8 chars are converted to '?'s.
|
||||||
char **argv = __argv;
|
//Need argv[] to be in UTF-8 format to properly determine realpath() and default image filepaths.
|
||||||
|
//To do this, parse command line in UTF-16, and then convert to UTF-8.
|
||||||
|
int argc;
|
||||||
|
wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||||
|
char **argv = new char*[argc];
|
||||||
|
for(unsigned i = 0; i < argc; i++) {
|
||||||
|
argv[i] = new(zeromemory) char[PATH_MAX];
|
||||||
|
strcpy(argv[i], utf8(wargv[i]));
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
#endif
|
#endif /*
|
||||||
/*
|
|
||||||
int main(int argc, char *argv[]) { */
|
int main(int argc, char *argv[]) { */
|
||||||
get_paths(argv[0]);
|
get_paths(argv[0]);
|
||||||
set_config_filenames();
|
set_config_filenames();
|
||||||
|
|
||||||
config::config().load(config::bsnes_cfg);
|
config::config().load(config::bsnes_cfg);
|
||||||
if(fexists(config::bsnes_cfg) == false) {
|
if(file::exists(config::bsnes_cfg) == false) {
|
||||||
//in case program crashes on first run, save config file
|
//in case program crashes on first run, save config file
|
||||||
//settings, so that they can be modified by hand ...
|
//settings, so that they can be modified by hand ...
|
||||||
config::config().save(config::bsnes_cfg);
|
config::config().save(config::bsnes_cfg);
|
||||||
@@ -159,13 +168,15 @@ int main(int argc, char *argv[]) { */
|
|||||||
if(app.term == true) goto app_term;
|
if(app.term == true) goto app_term;
|
||||||
snes.init();
|
snes.init();
|
||||||
|
|
||||||
if(argc >= 2 && fexists(argv[1])) {
|
if(argc >= 2 && file::exists(argv[1])) {
|
||||||
cartridge.load_cart_normal(argv[1]);
|
cartridge.load_cart_normal(argv[1]);
|
||||||
|
if(cartridge.loaded()) {
|
||||||
snes.power();
|
snes.power();
|
||||||
window_main.menu_file_unload.enable();
|
window_main.menu_file_unload.enable();
|
||||||
window_main.menu_file_reset.enable();
|
window_main.menu_file_reset.enable();
|
||||||
window_main.menu_file_power.enable();
|
window_main.menu_file_power.enable();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while(app.term == false) run();
|
while(app.term == false) run();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user