mirror of https://github.com/bsnes-emu/bsnes.git
Update to v089r13 release.
[also, replace the old purify tool with the new tool by the same name. There were some previous releases outside the WIP thread, but this is the first one that actually works with a WIP release. -Ed.] byuu says: Fixes up loading issues with recent purify changes, and purify also works on BS/ST file types now and should be a bit more crash-resistant.
This commit is contained in:
parent
36795e8061
commit
fbd52c7e5f
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "089.12";
|
static const char Version[] = "089.13";
|
||||||
static const char Author[] = "byuu";
|
static const char Author[] = "byuu";
|
||||||
static const char License[] = "GPLv3";
|
static const char License[] = "GPLv3";
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,9 @@ struct directory {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool directory::exists(const string &pathname) {
|
inline bool directory::exists(const string &pathname) {
|
||||||
DWORD result = GetFileAttributes(utf16_t(pathname));
|
string name = pathname;
|
||||||
|
name.trim<1>("\"");
|
||||||
|
DWORD result = GetFileAttributes(utf16_t(name));
|
||||||
if(result == INVALID_FILE_ATTRIBUTES) return false;
|
if(result == INVALID_FILE_ATTRIBUTES) return false;
|
||||||
return (result & FILE_ATTRIBUTE_DIRECTORY);
|
return (result & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,15 @@ struct FamicomCartridge {
|
||||||
};
|
};
|
||||||
|
|
||||||
FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
|
FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
|
||||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
markup = "";
|
||||||
if(size < 16) return;
|
if(size < 16) return;
|
||||||
if(data[0] != 'N') return;
|
if(data[0] != 'N') return;
|
||||||
if(data[1] != 'E') return;
|
if(data[1] != 'E') return;
|
||||||
if(data[2] != 'S') return;
|
if(data[2] != 'S') return;
|
||||||
if(data[3] != 26) return;
|
if(data[3] != 26) return;
|
||||||
|
|
||||||
|
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
|
|
||||||
mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
|
mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
|
||||||
mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
|
mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
|
||||||
prgrom = data[4] * 0x4000;
|
prgrom = data[4] * 0x4000;
|
||||||
|
|
|
@ -45,7 +45,9 @@ GameBoyAdvanceCartridge::GameBoyAdvanceCartridge(const uint8_t *data, unsigned s
|
||||||
}
|
}
|
||||||
identifiers = list.concatenate(",");
|
identifiers = list.concatenate(",");
|
||||||
|
|
||||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
markup = "";
|
||||||
|
|
||||||
|
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
markup.append("<cartridge sha256='", sha256(data, size), "'>\n");
|
markup.append("<cartridge sha256='", sha256(data, size), "'>\n");
|
||||||
markup.append(" <rom name='program.rom' size='0x", hex(size), "'/>\n");
|
markup.append(" <rom name='program.rom' size='0x", hex(size), "'/>\n");
|
||||||
if(0);
|
if(0);
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef NALL_EMULATION_SATELLAVIEW_HPP
|
||||||
|
#define NALL_EMULATION_SATELLAVIEW_HPP
|
||||||
|
|
||||||
|
#include <nall/sha256.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
struct SatellaviewCartridge {
|
||||||
|
string markup;
|
||||||
|
inline SatellaviewCartridge(const uint8_t *data, unsigned size);
|
||||||
|
};
|
||||||
|
|
||||||
|
SatellaviewCartridge::SatellaviewCartridge(const uint8_t *data, unsigned size) {
|
||||||
|
markup = "";
|
||||||
|
|
||||||
|
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
|
markup.append("<cartridge sha256='", sha256(data, size) ,"'>\n");
|
||||||
|
markup.append(" <rom name='program.rom' size='0x", hex(size), "'/>\n");
|
||||||
|
markup.append("</cartridge>\n");
|
||||||
|
markup.transform("'", "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef NALL_EMULATION_SUFAMI_TURBO_HPP
|
||||||
|
#define NALL_EMULATION_SUFAMI_TURBO_HPP
|
||||||
|
|
||||||
|
#include <nall/sha256.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
struct SufamiTurboCartridge {
|
||||||
|
string markup;
|
||||||
|
inline SufamiTurboCartridge(const uint8_t *data, unsigned size);
|
||||||
|
};
|
||||||
|
|
||||||
|
SufamiTurboCartridge::SufamiTurboCartridge(const uint8_t *data, unsigned size) {
|
||||||
|
markup = "";
|
||||||
|
|
||||||
|
if(size < 0x20000) return; //too small to be a valid game?
|
||||||
|
if(memcmp(data, "BANDAI SFC-ADX", 14)) return; //missing required header?
|
||||||
|
unsigned romsize = data[0x36] * 0x20000; //128KB
|
||||||
|
unsigned ramsize = data[0x37] * 0x800; //2KB
|
||||||
|
bool linkable = data[0x35] != 0x00; //TODO: unconfirmed
|
||||||
|
|
||||||
|
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
|
markup.append("<cartridge linkable='", linkable, "' sha256='", sha256(data, size) ,"'>\n");
|
||||||
|
markup.append(" <rom name='program.rom' size='0x", hex(romsize), "'/>\n");
|
||||||
|
markup.append(" <ram name='save.ram' size='0x", hex(ramsize), "'/>\n");
|
||||||
|
markup.append("</cartridge>\n");
|
||||||
|
markup.transform("'", "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -106,25 +106,17 @@ struct SuperFamicomCartridge {
|
||||||
};
|
};
|
||||||
|
|
||||||
SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) {
|
SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) {
|
||||||
|
markup = "";
|
||||||
|
if(size < 0x8000) return;
|
||||||
|
|
||||||
read_header(data, size);
|
read_header(data, size);
|
||||||
|
|
||||||
string xml;
|
markup = "";
|
||||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
if(type == TypeGameBoy) return;
|
||||||
|
if(type == TypeBsx) return;
|
||||||
|
if(type == TypeSufamiTurbo) return;
|
||||||
|
|
||||||
if(type == TypeBsx) {
|
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
markup.append("<cartridge/>\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type == TypeSufamiTurbo) {
|
|
||||||
markup.append("<cartridge/>\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type == TypeGameBoy) {
|
|
||||||
markup.append("<cartridge/>\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
|
const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
|
||||||
markup.append("<cartridge region='", region == NTSC ? "NTSC" : "PAL", "'>\n");
|
markup.append("<cartridge region='", region == NTSC ? "NTSC" : "PAL", "'>\n");
|
||||||
|
|
|
@ -18,10 +18,26 @@ namespace nall {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file {
|
struct file {
|
||||||
enum class mode : unsigned { read, write, readwrite, writeread };
|
enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append };
|
||||||
enum class index : unsigned { absolute, relative };
|
enum class index : unsigned { absolute, relative };
|
||||||
enum class time : unsigned { create, modify, access };
|
enum class time : unsigned { create, modify, access };
|
||||||
|
|
||||||
|
static bool copy(const string &sourcename, const string &targetname) {
|
||||||
|
file rd, wr;
|
||||||
|
if(rd.open(sourcename, mode::read) == false) return false;
|
||||||
|
if(wr.open(targetname, mode::write) == false) return false;
|
||||||
|
for(unsigned n = 0; n < rd.size(); n++) wr.write(rd.read());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool move(const string &sourcename, const string &targetname) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
return rename(sourcename, targetname) == 0;
|
||||||
|
#else
|
||||||
|
return _wrename(utf16_t(sourcename), utf16_t(targetname)) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static bool remove(const string &filename) {
|
static bool remove(const string &filename) {
|
||||||
return unlink(filename) == 0;
|
return unlink(filename) == 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ ifeq ($(platform),x)
|
||||||
endif
|
endif
|
||||||
else ifeq ($(platform),win)
|
else ifeq ($(platform),win)
|
||||||
phoenixflags := -DPHOENIX_WINDOWS
|
phoenixflags := -DPHOENIX_WINDOWS
|
||||||
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32
|
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
|
||||||
else
|
else
|
||||||
phoenixflags := -DPHOENIX_REFERENCE
|
phoenixflags := -DPHOENIX_REFERENCE
|
||||||
phoenixlink :=
|
phoenixlink :=
|
||||||
|
|
|
@ -839,6 +839,16 @@ void ComboBox::append_(const lstring &list) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ComboBox::modify(unsigned row, const string &text) {
|
||||||
|
state.text(row) = text;
|
||||||
|
p.modify(row, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComboBox::remove(unsigned row) {
|
||||||
|
state.text.remove(row);
|
||||||
|
p.remove(row);
|
||||||
|
}
|
||||||
|
|
||||||
void ComboBox::reset() {
|
void ComboBox::reset() {
|
||||||
state.selection = 0;
|
state.selection = 0;
|
||||||
state.text.reset();
|
state.text.reset();
|
||||||
|
@ -1056,6 +1066,12 @@ void ListView::modify_(unsigned row, const lstring &text) {
|
||||||
return p.modify(row, text);
|
return p.modify(row, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListView::remove(unsigned row) {
|
||||||
|
state.text.remove(row);
|
||||||
|
state.image.remove(row);
|
||||||
|
return p.remove(row);
|
||||||
|
}
|
||||||
|
|
||||||
void ListView::reset() {
|
void ListView::reset() {
|
||||||
state.checked.reset();
|
state.checked.reset();
|
||||||
state.image.reset();
|
state.image.reset();
|
||||||
|
|
|
@ -401,6 +401,8 @@ struct ComboBox : private nall::base_from_member<pComboBox&>, Widget {
|
||||||
template<typename... Args> void append(const Args&... args) { append_({args...}); }
|
template<typename... Args> void append(const Args&... args) { append_({args...}); }
|
||||||
|
|
||||||
void append_(const nall::lstring &list);
|
void append_(const nall::lstring &list);
|
||||||
|
void modify(unsigned row, const nall::string &text);
|
||||||
|
void remove(unsigned row);
|
||||||
void reset();
|
void reset();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
void setSelection(unsigned row);
|
void setSelection(unsigned row);
|
||||||
|
@ -499,6 +501,7 @@ struct ListView : private nall::base_from_member<pListView&>, Widget {
|
||||||
void autoSizeColumns();
|
void autoSizeColumns();
|
||||||
bool checked(unsigned row);
|
bool checked(unsigned row);
|
||||||
void modify_(unsigned row, const nall::lstring &list);
|
void modify_(unsigned row, const nall::lstring &list);
|
||||||
|
void remove(unsigned row);
|
||||||
void reset();
|
void reset();
|
||||||
bool selected();
|
bool selected();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
|
|
|
@ -287,6 +287,8 @@ struct pComboBox : public pWidget {
|
||||||
unsigned itemCounter;
|
unsigned itemCounter;
|
||||||
|
|
||||||
void append(const string &text);
|
void append(const string &text);
|
||||||
|
void modify(unsigned row, const string &text);
|
||||||
|
void remove(unsigned row);
|
||||||
Geometry minimumGeometry();
|
Geometry minimumGeometry();
|
||||||
void reset();
|
void reset();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
|
@ -393,6 +395,7 @@ struct pListView : public pWidget {
|
||||||
void autoSizeColumns();
|
void autoSizeColumns();
|
||||||
bool checked(unsigned row);
|
bool checked(unsigned row);
|
||||||
void modify(unsigned row, const lstring &text);
|
void modify(unsigned row, const lstring &text);
|
||||||
|
void remove(unsigned row);
|
||||||
void reset();
|
void reset();
|
||||||
bool selected();
|
bool selected();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
|
|
|
@ -18,6 +18,23 @@ Geometry pComboBox::minimumGeometry() {
|
||||||
return { 0, 0, maximumWidth + 44, geometry.height + 12 };
|
return { 0, 0, maximumWidth + 44, geometry.height + 12 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pComboBox::modify(unsigned row, const string &text) {
|
||||||
|
locked = true;
|
||||||
|
unsigned position = selection();
|
||||||
|
gtk_combo_box_remove_text(GTK_COMBO_BOX(gtkWidget), row);
|
||||||
|
gtk_combo_box_insert_text(GTK_COMBO_BOX(gtkWidget), row, text);
|
||||||
|
gtk_combo_box_set_active(GTK_COMBO_BOX(gtkWidget), position);
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pComboBox::remove(unsigned row) {
|
||||||
|
locked = true;
|
||||||
|
unsigned position = selection();
|
||||||
|
gtk_combo_box_remove_text(GTK_COMBO_BOX(gtkWidget), row);
|
||||||
|
if(position == row) gtk_combo_box_set_active(GTK_COMBO_BOX(gtkWidget), 0);
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
void pComboBox::reset() {
|
void pComboBox::reset() {
|
||||||
locked = true;
|
locked = true;
|
||||||
gtk_list_store_clear(GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(gtkWidget))));
|
gtk_list_store_clear(GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(gtkWidget))));
|
||||||
|
|
|
@ -42,6 +42,13 @@ void pListView::modify(unsigned row, const lstring &text) {
|
||||||
for(unsigned n = 0; n < text.size(); n++) gtk_list_store_set(store, &iter, 1 + n * 2 + 1, (const char*)text[n], -1);
|
for(unsigned n = 0; n < text.size(); n++) gtk_list_store_set(store, &iter, 1 + n * 2 + 1, (const char*)text[n], -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pListView::remove(unsigned row) {
|
||||||
|
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gtk_tree_model_get_iter_from_string(model, &iter, string(row));
|
||||||
|
gtk_list_store_remove(store, &iter);
|
||||||
|
}
|
||||||
|
|
||||||
void pListView::reset() {
|
void pListView::reset() {
|
||||||
listView.state.selected = false;
|
listView.state.selected = false;
|
||||||
listView.state.selection = 0;
|
listView.state.selection = 0;
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
|
#include <nall/windows/registry.hpp>
|
||||||
|
#include <nall/windows/utf8.hpp>
|
||||||
#elif defined(PHOENIX_QT)
|
#elif defined(PHOENIX_QT)
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Meta object code from reading C++ file 'platform.moc.hpp'
|
** Meta object code from reading C++ file 'platform.moc.hpp'
|
||||||
**
|
**
|
||||||
** Created: Sun Jun 17 11:38:40 2012
|
** Created: Mon Jun 18 07:31:52 2012
|
||||||
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
|
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
|
||||||
**
|
**
|
||||||
** WARNING! All changes made in this file will be lost!
|
** WARNING! All changes made in this file will be lost!
|
||||||
|
|
|
@ -354,6 +354,8 @@ public:
|
||||||
QComboBox *qtComboBox;
|
QComboBox *qtComboBox;
|
||||||
|
|
||||||
void append(const string &text);
|
void append(const string &text);
|
||||||
|
void modify(unsigned row, const string &text);
|
||||||
|
void remove(unsigned row);
|
||||||
Geometry minimumGeometry();
|
Geometry minimumGeometry();
|
||||||
void reset();
|
void reset();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
|
@ -486,6 +488,7 @@ public:
|
||||||
void autoSizeColumns();
|
void autoSizeColumns();
|
||||||
bool checked(unsigned row);
|
bool checked(unsigned row);
|
||||||
void modify(unsigned row, const lstring &text);
|
void modify(unsigned row, const lstring &text);
|
||||||
|
void remove(unsigned row);
|
||||||
void reset();
|
void reset();
|
||||||
bool selected();
|
bool selected();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
|
|
|
@ -11,6 +11,18 @@ Geometry pComboBox::minimumGeometry() {
|
||||||
return { 0, 0, maximumWidth + 32, geometry.height + 12 };
|
return { 0, 0, maximumWidth + 32, geometry.height + 12 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pComboBox::modify(unsigned row, const string &text) {
|
||||||
|
qtComboBox->setItemText(row, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pComboBox::remove(unsigned row) {
|
||||||
|
locked = true;
|
||||||
|
unsigned position = selection();
|
||||||
|
qtComboBox->removeItem(row);
|
||||||
|
if(position == row) qtComboBox->setCurrentIndex(0);
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
void pComboBox::reset() {
|
void pComboBox::reset() {
|
||||||
locked = true;
|
locked = true;
|
||||||
while(qtComboBox->count()) qtComboBox->removeItem(0);
|
while(qtComboBox->count()) qtComboBox->removeItem(0);
|
||||||
|
|
|
@ -23,13 +23,21 @@ bool pListView::checked(unsigned row) {
|
||||||
void pListView::modify(unsigned row, const lstring &text) {
|
void pListView::modify(unsigned row, const lstring &text) {
|
||||||
locked = true;
|
locked = true;
|
||||||
QTreeWidgetItem *item = qtListView->topLevelItem(row);
|
QTreeWidgetItem *item = qtListView->topLevelItem(row);
|
||||||
if(!item) return;
|
if(item == nullptr) return;
|
||||||
for(unsigned n = 0; n < text.size(); n++) {
|
for(unsigned n = 0; n < text.size(); n++) {
|
||||||
item->setText(n, QString::fromUtf8(text[n]));
|
item->setText(n, QString::fromUtf8(text[n]));
|
||||||
}
|
}
|
||||||
locked = false;
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pListView::remove(unsigned row) {
|
||||||
|
locked = true;
|
||||||
|
QTreeWidgetItem *item = qtListView->topLevelItem(row);
|
||||||
|
if(item == nullptr) return;
|
||||||
|
delete item;
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
void pListView::reset() {
|
void pListView::reset() {
|
||||||
qtListView->clear();
|
qtListView->clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ bool pRadioItem::checked() {
|
||||||
void pRadioItem::setChecked() {
|
void pRadioItem::setChecked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioItem::setGroup(const array<RadioItem&> &group) {
|
void pRadioItem::setGroup(const set<RadioItem&> &group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioItem::setText(const string &text) {
|
void pRadioItem::setText(const string &text) {
|
||||||
|
|
|
@ -2,8 +2,8 @@ bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
array<bool> pKeyboard::state() {
|
vector<bool> pKeyboard::state() {
|
||||||
array<bool> output;
|
vector<bool> output;
|
||||||
output.resize((unsigned)Keyboard::Scancode::Limit);
|
output.resize((unsigned)Keyboard::Scancode::Limit);
|
||||||
for(auto &n : output) n = false;
|
for(auto &n : output) n = false;
|
||||||
return output;
|
return output;
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct pDesktop {
|
||||||
|
|
||||||
struct pKeyboard {
|
struct pKeyboard {
|
||||||
static bool pressed(Keyboard::Scancode scancode);
|
static bool pressed(Keyboard::Scancode scancode);
|
||||||
static array<bool> state();
|
static vector<bool> state();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pMouse {
|
struct pMouse {
|
||||||
|
@ -157,7 +157,7 @@ struct pRadioItem : public pAction {
|
||||||
|
|
||||||
bool checked();
|
bool checked();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const array<RadioItem&> &group);
|
void setGroup(const set<RadioItem&> &group);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
||||||
|
@ -227,6 +227,8 @@ struct pComboBox : public pWidget {
|
||||||
ComboBox &comboBox;
|
ComboBox &comboBox;
|
||||||
|
|
||||||
void append(const string &text);
|
void append(const string &text);
|
||||||
|
void modify(unsigned row, const string &text);
|
||||||
|
void remove(unsigned row);
|
||||||
void reset();
|
void reset();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
void setSelection(unsigned row);
|
void setSelection(unsigned row);
|
||||||
|
@ -297,6 +299,7 @@ struct pListView : public pWidget {
|
||||||
void autoSizeColumns();
|
void autoSizeColumns();
|
||||||
bool checked(unsigned row);
|
bool checked(unsigned row);
|
||||||
void modify(unsigned row, const lstring &text);
|
void modify(unsigned row, const lstring &text);
|
||||||
|
void remove(unsigned row);
|
||||||
void reset();
|
void reset();
|
||||||
bool selected();
|
bool selected();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
|
@ -304,6 +307,7 @@ struct pListView : public pWidget {
|
||||||
void setChecked(unsigned row, bool checked);
|
void setChecked(unsigned row, bool checked);
|
||||||
void setHeaderText(const lstring &text);
|
void setHeaderText(const lstring &text);
|
||||||
void setHeaderVisible(bool visible);
|
void setHeaderVisible(bool visible);
|
||||||
|
void setImage(unsigned row, unsigned column, const image &image);
|
||||||
void setSelected(bool selected);
|
void setSelected(bool selected);
|
||||||
void setSelection(unsigned row);
|
void setSelection(unsigned row);
|
||||||
|
|
||||||
|
@ -325,7 +329,7 @@ struct pRadioBox : public pWidget {
|
||||||
|
|
||||||
bool checked();
|
bool checked();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const array<RadioBox&> &group);
|
void setGroup(const set<RadioBox&> &group);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
void pComboBox::append(const string &text) {
|
void pComboBox::append(const string &text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pComboBox::modify(unsigned row, const string &text) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void pComboBox::remove(unsigned row) {
|
||||||
|
}
|
||||||
|
|
||||||
void pComboBox::reset() {
|
void pComboBox::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@ bool pListView::checked(unsigned row) {
|
||||||
void pListView::modify(unsigned row, const lstring &text) {
|
void pListView::modify(unsigned row, const lstring &text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pListView::remove(unsigned row) {
|
||||||
|
}
|
||||||
|
|
||||||
void pListView::reset() {
|
void pListView::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +36,9 @@ void pListView::setHeaderText(const lstring &text) {
|
||||||
void pListView::setHeaderVisible(bool visible) {
|
void pListView::setHeaderVisible(bool visible) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pListView::setImage(unsigned row, unsigned column, const image &image) {
|
||||||
|
}
|
||||||
|
|
||||||
void pListView::setSelected(bool selected) {
|
void pListView::setSelected(bool selected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ bool pRadioBox::checked() {
|
||||||
void pRadioBox::setChecked() {
|
void pRadioBox::setChecked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioBox::setGroup(const array<RadioBox&> &group) {
|
void pRadioBox::setGroup(const set<RadioBox&> &group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioBox::setText(const string &text) {
|
void pRadioBox::setText(const string &text) {
|
||||||
|
|
|
@ -23,6 +23,13 @@ static string FileDialog(bool save, Window &parent, const string &path, const ls
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(path.empty() == false) {
|
||||||
|
//clear COMDLG32 MRU (most recently used) file list
|
||||||
|
//this is required in order for lpstrInitialDir to be honored in Windows 7 and above
|
||||||
|
registry::remove("HKCU/Software/Microsoft/Windows/CurrentVersion/Explorer/ComDlg32/LastVisitedPidlMRU/");
|
||||||
|
registry::remove("HKCU/Software/Microsoft/Windows/CurrentVersion/Explorer/ComDlg32/OpenSavePidlMRU/");
|
||||||
|
}
|
||||||
|
|
||||||
OPENFILENAME ofn;
|
OPENFILENAME ofn;
|
||||||
memset(&ofn, 0, sizeof(OPENFILENAME));
|
memset(&ofn, 0, sizeof(OPENFILENAME));
|
||||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||||
|
|
|
@ -6,4 +6,9 @@
|
||||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
|
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||||
|
<dpiAware>true</dpiAware>
|
||||||
|
</asmv3:windowsSettings>
|
||||||
|
</asmv3:application>
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|
|
@ -384,6 +384,20 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
||||||
}
|
}
|
||||||
} else if(nmhdr->code == LVN_ITEMACTIVATE) {
|
} else if(nmhdr->code == LVN_ITEMACTIVATE) {
|
||||||
if(listView.onActivate) listView.onActivate();
|
if(listView.onActivate) listView.onActivate();
|
||||||
|
} else if(nmhdr->code == NM_CUSTOMDRAW) {
|
||||||
|
LPNMLVCUSTOMDRAW lvcd = (LPNMLVCUSTOMDRAW)nmhdr;
|
||||||
|
switch(lvcd->nmcd.dwDrawStage) {
|
||||||
|
case CDDS_PREPAINT:
|
||||||
|
return CDRF_NOTIFYITEMDRAW;
|
||||||
|
case CDDS_ITEMPREPAINT:
|
||||||
|
if(listView.state.headerText.size() >= 2) {
|
||||||
|
//draw alternating row colors of there are two or more columns
|
||||||
|
if(lvcd->nmcd.dwItemSpec % 2) lvcd->clrTextBk = GetSysColor(COLOR_WINDOW) ^ 0x070707;
|
||||||
|
}
|
||||||
|
return CDRF_DODEFAULT;
|
||||||
|
default:
|
||||||
|
return CDRF_DODEFAULT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -283,6 +283,8 @@ struct pComboBox : public pWidget {
|
||||||
ComboBox &comboBox;
|
ComboBox &comboBox;
|
||||||
|
|
||||||
void append(const string &text);
|
void append(const string &text);
|
||||||
|
void modify(unsigned row, const string &text);
|
||||||
|
void remove(unsigned row);
|
||||||
Geometry minimumGeometry();
|
Geometry minimumGeometry();
|
||||||
void reset();
|
void reset();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
|
@ -375,6 +377,7 @@ struct pListView : public pWidget {
|
||||||
void autoSizeColumns();
|
void autoSizeColumns();
|
||||||
bool checked(unsigned row);
|
bool checked(unsigned row);
|
||||||
void modify(unsigned row, const lstring &text);
|
void modify(unsigned row, const lstring &text);
|
||||||
|
void remove(unsigned row);
|
||||||
void reset();
|
void reset();
|
||||||
bool selected();
|
bool selected();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
|
|
|
@ -9,6 +9,23 @@ Geometry pComboBox::minimumGeometry() {
|
||||||
return { 0, 0, maximumWidth + 24, pFont::geometry(hfont, " ").height + 10 };
|
return { 0, 0, maximumWidth + 24, pFont::geometry(hfont, " ").height + 10 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pComboBox::modify(unsigned row, const string &text) {
|
||||||
|
locked = true;
|
||||||
|
unsigned position = selection();
|
||||||
|
SendMessage(hwnd, CB_DELETESTRING, row, 0);
|
||||||
|
SendMessage(hwnd, CB_INSERTSTRING, row, (LPARAM)(wchar_t*)utf16_t(text));
|
||||||
|
setSelection(position);
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pComboBox::remove(unsigned row) {
|
||||||
|
locked = true;
|
||||||
|
unsigned position = selection();
|
||||||
|
SendMessage(hwnd, CB_DELETESTRING, row, 0);
|
||||||
|
if(position == row) setSelection(0);
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
void pComboBox::reset() {
|
void pComboBox::reset() {
|
||||||
SendMessage(hwnd, CB_RESETCONTENT, 0, 0);
|
SendMessage(hwnd, CB_RESETCONTENT, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,31 @@
|
||||||
|
unsigned ListView_GetColumnCount(HWND hwnd) {
|
||||||
|
unsigned count = 0;
|
||||||
|
LVCOLUMN column;
|
||||||
|
column.mask = LVCF_WIDTH;
|
||||||
|
while(ListView_GetColumn(hwnd, count++, &column));
|
||||||
|
return --count;
|
||||||
|
}
|
||||||
|
|
||||||
void pListView::append(const lstring &list) {
|
void pListView::append(const lstring &list) {
|
||||||
wchar_t empty[] = L"";
|
wchar_t empty[] = L"";
|
||||||
unsigned row = ListView_GetItemCount(hwnd);
|
unsigned row = ListView_GetItemCount(hwnd);
|
||||||
LVITEM item;
|
LVITEM item;
|
||||||
item.mask = LVIF_TEXT | LVIF_IMAGE;
|
item.mask = LVIF_TEXT;
|
||||||
item.iItem = row;
|
item.iItem = row;
|
||||||
item.iSubItem = 0;
|
item.iSubItem = 0;
|
||||||
item.iImage = row;
|
|
||||||
item.pszText = empty;
|
item.pszText = empty;
|
||||||
locked = true;
|
locked = true;
|
||||||
ListView_InsertItem(hwnd, &item);
|
ListView_InsertItem(hwnd, &item);
|
||||||
locked = false;
|
locked = false;
|
||||||
for(unsigned n = 0; n < list.size(); n++) {
|
for(unsigned column = 0; column < list.size(); column++) {
|
||||||
utf16_t wtext(list[n]);
|
utf16_t wtext(list(column, ""));
|
||||||
ListView_SetItemText(hwnd, row, n, wtext);
|
ListView_SetItemText(hwnd, row, column, wtext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListView::autoSizeColumns() {
|
void pListView::autoSizeColumns() {
|
||||||
for(unsigned n = 0; n < max(1, listView.state.headerText.size()); n++) {
|
unsigned columns = ListView_GetColumnCount(hwnd);
|
||||||
|
for(unsigned n = 0; n < columns; n++) {
|
||||||
ListView_SetColumnWidth(hwnd, n, LVSCW_AUTOSIZE_USEHEADER);
|
ListView_SetColumnWidth(hwnd, n, LVSCW_AUTOSIZE_USEHEADER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,11 +36,16 @@ bool pListView::checked(unsigned row) {
|
||||||
|
|
||||||
void pListView::modify(unsigned row, const lstring &list) {
|
void pListView::modify(unsigned row, const lstring &list) {
|
||||||
for(unsigned n = 0; n < list.size(); n++) {
|
for(unsigned n = 0; n < list.size(); n++) {
|
||||||
utf16_t wtext(list[n]);
|
utf16_t wtext(list(n, ""));
|
||||||
ListView_SetItemText(hwnd, row, n, wtext);
|
ListView_SetItemText(hwnd, row, n, wtext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pListView::remove(unsigned row) {
|
||||||
|
ListView_DeleteItem(hwnd, row);
|
||||||
|
setImageList();
|
||||||
|
}
|
||||||
|
|
||||||
void pListView::reset() {
|
void pListView::reset() {
|
||||||
ListView_DeleteAllItems(hwnd);
|
ListView_DeleteAllItems(hwnd);
|
||||||
}
|
}
|
||||||
|
@ -54,7 +67,7 @@ unsigned pListView::selection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListView::setCheckable(bool checkable) {
|
void pListView::setCheckable(bool checkable) {
|
||||||
ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT | (checkable ? LVS_EX_CHECKBOXES : 0));
|
ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES | (checkable ? LVS_EX_CHECKBOXES : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListView::setChecked(unsigned row, bool checked) {
|
void pListView::setChecked(unsigned row, bool checked) {
|
||||||
|
@ -90,7 +103,6 @@ void pListView::setHeaderVisible(bool visible) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListView::setImage(unsigned row, unsigned column, const image &image) {
|
void pListView::setImage(unsigned row, unsigned column, const image &image) {
|
||||||
if(column != 0) return; //ListView can only set icons on first column
|
|
||||||
setImageList();
|
setImageList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,9 +136,9 @@ void pListView::constructor() {
|
||||||
setHeaderText(listView.state.headerText);
|
setHeaderText(listView.state.headerText);
|
||||||
setHeaderVisible(listView.state.headerVisible);
|
setHeaderVisible(listView.state.headerVisible);
|
||||||
setCheckable(listView.state.checkable);
|
setCheckable(listView.state.checkable);
|
||||||
setImageList();
|
|
||||||
for(auto &text : listView.state.text) append(text);
|
for(auto &text : listView.state.text) append(text);
|
||||||
for(unsigned n = 0; n < listView.state.checked.size(); n++) setChecked(n, listView.state.checked[n]);
|
for(unsigned n = 0; n < listView.state.checked.size(); n++) setChecked(n, listView.state.checked[n]);
|
||||||
|
setImageList();
|
||||||
if(listView.state.selected) setSelection(listView.state.selection);
|
if(listView.state.selected) setSelection(listView.state.selection);
|
||||||
autoSizeColumns();
|
autoSizeColumns();
|
||||||
synchronize();
|
synchronize();
|
||||||
|
@ -147,31 +159,52 @@ void pListView::setGeometry(const Geometry &geometry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListView::setImageList() {
|
void pListView::setImageList() {
|
||||||
|
auto &list = listView.state.image;
|
||||||
|
|
||||||
if(imageList) {
|
if(imageList) {
|
||||||
ImageList_Destroy(imageList);
|
ImageList_Destroy(imageList);
|
||||||
imageList = nullptr;
|
imageList = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned images = 0;
|
bool found = false;
|
||||||
for(auto &image : listView.state.image) {
|
for(auto &row : listView.state.image) {
|
||||||
if(image.empty() == false) images++;
|
for(auto &column : row) {
|
||||||
|
if(column.empty() == false) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(images == 0) return;
|
|
||||||
|
|
||||||
imageList = ImageList_Create(16, 16, ILC_COLOR32, listView.state.text.size(), 0);
|
|
||||||
|
|
||||||
for(unsigned rowID = 0; rowID < listView.state.image.size(); rowID++) {
|
|
||||||
auto &row = listView.state.image(rowID);
|
|
||||||
nall::image image = row(0);
|
|
||||||
if(image.empty()) {
|
|
||||||
image.allocate(16, 16);
|
|
||||||
image.clear(~0);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(found == false) return;
|
||||||
|
|
||||||
|
imageList = ImageList_Create(15, 15, ILC_COLOR32, 1, 0);
|
||||||
|
nall::image image;
|
||||||
|
image.allocate(15, 15);
|
||||||
|
image.clear(GetSysColor(COLOR_WINDOW));
|
||||||
|
ImageList_Add(imageList, CreateBitmap(image), NULL);
|
||||||
|
|
||||||
|
for(unsigned row = 0; row < list.size(); row++) {
|
||||||
|
for(unsigned column = 0; column < list(row).size(); column++) {
|
||||||
|
nall::image image = list(row)(column);
|
||||||
|
if(image.empty()) continue;
|
||||||
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||||
image.scale(16, 16, Interpolation::Linear);
|
image.scale(15, 15, Interpolation::Linear);
|
||||||
HBITMAP hbitmap = CreateBitmap(image);
|
ImageList_Add(imageList, CreateBitmap(image), NULL);
|
||||||
ImageList_Add(imageList, hbitmap, NULL);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView_SetImageList(hwnd, imageList, LVSIL_SMALL);
|
ListView_SetImageList(hwnd, imageList, LVSIL_SMALL);
|
||||||
|
|
||||||
|
unsigned ID = 1;
|
||||||
|
for(unsigned row = 0; row < list.size(); row++) {
|
||||||
|
for(unsigned column = 0; column < list(row).size(); column++) {
|
||||||
|
if(list(row)(column).empty()) continue; //I_IMAGENONE does not work properly
|
||||||
|
LVITEM item;
|
||||||
|
item.mask = LVIF_IMAGE;
|
||||||
|
item.iItem = row;
|
||||||
|
item.iSubItem = column;
|
||||||
|
item.iImage = ID++;
|
||||||
|
ListView_SetItem(hwnd, &item);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<cartridge region="NTSC">
|
<cartridge region="NTSC">
|
||||||
<rom name="program.rom" size="0x100000"/>
|
<rom name="program.rom" size="0x100000"/>
|
||||||
<ram name="save.ram" size="0x8000"/>
|
<ram name="save.ram" size="0x8000"/>
|
||||||
<bsx>
|
|
||||||
<psram name="bsx.ram" size="0x40000"/>
|
<psram name="bsx.ram" size="0x40000"/>
|
||||||
|
<bsx>
|
||||||
<mcu>
|
<mcu>
|
||||||
<map address="00-3f:8000-ffff"/>
|
<map address="00-3f:8000-ffff"/>
|
||||||
<map address="80-bf:8000-ffff"/>
|
<map address="80-bf:8000-ffff"/>
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<system type="NES">
|
<system name="Famicom">
|
||||||
</system>
|
</system>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<system type="GBA">
|
<system name="Game Boy Advance">
|
||||||
<bios firmware="bios.rom" sha256="fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570"/>
|
<bios firmware="bios.rom" sha256="fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570"/>
|
||||||
</system>
|
</system>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<system type="GBC">
|
<system name="Game Boy Color">
|
||||||
<boot firmware="boot.rom" sha256="4bf5021be357ce523a59ac5f4efff5d6371ae50112a6db0adf4a75916ad760a9"/>
|
<boot firmware="boot.rom" sha256="4bf5021be357ce523a59ac5f4efff5d6371ae50112a6db0adf4a75916ad760a9"/>
|
||||||
</system>
|
</system>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<system type="GB">
|
<system name="Game Boy">
|
||||||
<boot firmware="boot.rom" sha256="cf053eccb4ccafff9e67339d4e78e98dce7d1ed59be819d2a1ba2232c6fce1c7"/>
|
<boot firmware="boot.rom" sha256="cf053eccb4ccafff9e67339d4e78e98dce7d1ed59be819d2a1ba2232c6fce1c7"/>
|
||||||
</system>
|
</system>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<system type="SNES">
|
<system name="Super Famicom">
|
||||||
<smp firmware="spc700.rom" sha256="c95f88b299030d5afa55b1031e2b5ef2dff650c4b4e6bb6f8b1359436521278f"/>
|
<smp firmware="spc700.rom" sha256="c95f88b299030d5afa55b1031e2b5ef2dff650c4b4e6bb6f8b1359436521278f"/>
|
||||||
</system>
|
</system>
|
||||||
|
|
|
@ -80,6 +80,7 @@ private:
|
||||||
|
|
||||||
void parse_markup_rom(XML::Node&);
|
void parse_markup_rom(XML::Node&);
|
||||||
void parse_markup_ram(XML::Node&);
|
void parse_markup_ram(XML::Node&);
|
||||||
|
void parse_markup_psram(XML::Node&);
|
||||||
void parse_markup_icd2(XML::Node&);
|
void parse_markup_icd2(XML::Node&);
|
||||||
void parse_markup_bsx(XML::Node&);
|
void parse_markup_bsx(XML::Node&);
|
||||||
void parse_markup_sufamiturbo(XML::Node&);
|
void parse_markup_sufamiturbo(XML::Node&);
|
||||||
|
|
|
@ -9,6 +9,7 @@ void Cartridge::parse_markup(const char *markup) {
|
||||||
|
|
||||||
parse_markup_rom(cartridge["rom"]);
|
parse_markup_rom(cartridge["rom"]);
|
||||||
parse_markup_ram(cartridge["ram"]);
|
parse_markup_ram(cartridge["ram"]);
|
||||||
|
parse_markup_psram(cartridge["psram"]);
|
||||||
parse_markup_icd2(cartridge["icd2"]);
|
parse_markup_icd2(cartridge["icd2"]);
|
||||||
parse_markup_bsx(cartridge["bsx"]);
|
parse_markup_bsx(cartridge["bsx"]);
|
||||||
parse_markup_sufamiturbo(cartridge["sufamiturbo"]);
|
parse_markup_sufamiturbo(cartridge["sufamiturbo"]);
|
||||||
|
@ -98,6 +99,11 @@ void Cartridge::parse_markup_ram(XML::Node &root) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Cartridge::parse_markup_psram(XML::Node &root) {
|
||||||
|
if(root.exists() == false) return;
|
||||||
|
parse_markup_memory(bsxcartridge.psram, root, ID::BsxPSRAM, true);
|
||||||
|
}
|
||||||
|
|
||||||
void Cartridge::parse_markup_icd2(XML::Node &root) {
|
void Cartridge::parse_markup_icd2(XML::Node &root) {
|
||||||
if(root.exists() == false) return;
|
if(root.exists() == false) return;
|
||||||
has_gb_slot = true;
|
has_gb_slot = true;
|
||||||
|
@ -121,10 +127,6 @@ void Cartridge::parse_markup_bsx(XML::Node &root) {
|
||||||
|
|
||||||
interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs");
|
interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs");
|
||||||
|
|
||||||
if(has_bs_cart) {
|
|
||||||
parse_markup_memory(bsxcartridge.psram, root["psram"], ID::BsxPSRAM, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto &node : root["slot"]) {
|
for(auto &node : root["slot"]) {
|
||||||
if(node.name != "map") continue;
|
if(node.name != "map") continue;
|
||||||
if(bsxflash.memory.size() == 0) continue;
|
if(bsxflash.memory.size() == 0) continue;
|
||||||
|
@ -228,7 +230,6 @@ void Cartridge::parse_markup_sa1(XML::Node &root) {
|
||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_markup_memory(ram, bwram, ID::RAM, true);
|
|
||||||
for(auto &node : bwram) {
|
for(auto &node : bwram) {
|
||||||
if(node.name != "map") continue;
|
if(node.name != "map") continue;
|
||||||
Mapping m(sa1.cpubwram);
|
Mapping m(sa1.cpubwram);
|
||||||
|
|
|
@ -1,34 +1,40 @@
|
||||||
include nall/Makefile
|
include nall/Makefile
|
||||||
|
include phoenix/Makefile
|
||||||
|
|
||||||
application := purify
|
application := purify
|
||||||
|
resource :=
|
||||||
flags := -std=gnu++0x -I. -O3 -fomit-frame-pointer
|
flags := -std=gnu++0x -I. -O3 -fomit-frame-pointer
|
||||||
link := -s
|
link := -s
|
||||||
|
|
||||||
ifeq ($(platform),win)
|
ifeq ($(platform),win)
|
||||||
flags += -DPHOENIX_WINDOWS
|
resource := resource.o
|
||||||
link += -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32
|
flags := -m32 -mwindows $(flags)
|
||||||
else ifeq ($(phoenix),qt)
|
link := -m32 -mwindows $(flags)
|
||||||
flags += -DPHOENIX_QT `pkg-config --cflags QtCore QtGui`
|
|
||||||
link += `pkg-config --libs QtCore QtGui`
|
|
||||||
else
|
|
||||||
flags += -DPHOENIX_GTK `pkg-config --cflags gtk+-2.0`
|
|
||||||
link += `pkg-config --libs gtk+-2.0`
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: phoenix.o $(application).o
|
all: phoenix.o $(application).o
|
||||||
$(cpp) -o $(application) phoenix.o $(application).o $(link)
|
ifeq ($(platform),win)
|
||||||
|
windres --target=pe-i386 phoenix/windows/phoenix.rc $(resource)
|
||||||
|
endif
|
||||||
|
$(cpp) -o $(application) phoenix.o $(application).o $(resource) $(link) $(phoenixlink)
|
||||||
|
|
||||||
phoenix.o: phoenix/phoenix.cpp
|
phoenix.o:
|
||||||
$(cpp) -c -o phoenix.o phoenix/phoenix.cpp $(flags)
|
$(cpp) -c -o phoenix.o phoenix/phoenix.cpp $(flags) $(phoenixflags)
|
||||||
|
|
||||||
$(application).o: $(application).cpp
|
$(application).o: $(application).cpp
|
||||||
$(cpp) -c -o $(application).o $(application).cpp $(flags)
|
$(cpp) -c -o $(application).o $(application).cpp $(flags)
|
||||||
|
|
||||||
|
resource: force
|
||||||
|
sourcery resource/resource.xml resource/resource.cpp resource/resource.hpp
|
||||||
|
|
||||||
install:
|
install:
|
||||||
sudo cp $(application) /usr/local/bin/$(application)
|
sudo cp $(application) /usr/local/bin/$(application)
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
sudo rm /usr/local/bin/$(application)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(delete) *.o
|
-@$(call delete,*.o)
|
||||||
|
|
||||||
sync:
|
sync:
|
||||||
if [ -d ./nall ]; then rm -r ./nall; fi
|
if [ -d ./nall ]; then rm -r ./nall; fi
|
||||||
|
@ -36,4 +42,7 @@ sync:
|
||||||
cp -r ../nall ./nall
|
cp -r ../nall ./nall
|
||||||
cp -r ../phoenix ./phoenix
|
cp -r ../phoenix ./phoenix
|
||||||
rm -r nall/test
|
rm -r nall/test
|
||||||
|
rm -r phoenix/nall
|
||||||
rm -r phoenix/test
|
rm -r phoenix/test
|
||||||
|
|
||||||
|
force:
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
#include <nall/platform.hpp>
|
|
||||||
#include <nall/file.hpp>
|
|
||||||
#include <nall/string.hpp>
|
|
||||||
using namespace nall;
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
string filedata;
|
|
||||||
if(filedata.readfile("database-gameboyadvance.bsv") == false) return 0;
|
|
||||||
lstring lines = filedata.split("\n");
|
|
||||||
unsigned count;
|
|
||||||
|
|
||||||
file fp;
|
|
||||||
if(fp.open("database-gameboyadvance-analysis.txt", file::mode::write) == false) return 0;
|
|
||||||
|
|
||||||
fp.print("Multiple Tags:\n");
|
|
||||||
fp.print("--------------\n\n");
|
|
||||||
count = 0;
|
|
||||||
for(auto &line : lines) {
|
|
||||||
if(line.empty()) continue;
|
|
||||||
lstring part = line.split("{}");
|
|
||||||
if(part(2).position(",")) fp.print(part(3), "\n", part(2), "\n\n"), count++;
|
|
||||||
}
|
|
||||||
fp.print("Total: ", count, "\n\n");
|
|
||||||
|
|
||||||
fp.print("EEPROM:\n");
|
|
||||||
fp.print("-------\n");
|
|
||||||
count = 0;
|
|
||||||
for(auto &line : lines) {
|
|
||||||
if(line.empty()) continue;
|
|
||||||
lstring part = line.split("{}");
|
|
||||||
if(part(2).position("EEPROM")) fp.print(part(3), "\n", part(2), "\n\n"), count++;
|
|
||||||
}
|
|
||||||
fp.print("Total: ", count, "\n\n");
|
|
||||||
|
|
||||||
fp.print("No RAM:\n");
|
|
||||||
fp.print("-------\n");
|
|
||||||
count = 0;
|
|
||||||
for(auto &line : lines) {
|
|
||||||
if(line.empty()) continue;
|
|
||||||
lstring part = line.split("{}");
|
|
||||||
if(part(2).empty()) fp.print(part(3), "\n"), count++;
|
|
||||||
}
|
|
||||||
fp.print("\nTotal: ", count, "\n\n");
|
|
||||||
|
|
||||||
fp.close();
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -35,9 +35,9 @@ ifeq ($(compiler),)
|
||||||
ifeq ($(platform),win)
|
ifeq ($(platform),win)
|
||||||
compiler := gcc
|
compiler := gcc
|
||||||
else ifeq ($(platform),osx)
|
else ifeq ($(platform),osx)
|
||||||
compiler := gcc-mp-4.6
|
compiler := gcc-mp-4.7
|
||||||
else
|
else
|
||||||
compiler := gcc-4.6
|
compiler := gcc-4.7
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define NALL_ANY_HPP
|
#define NALL_ANY_HPP
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <nall/type_traits.hpp>
|
#include <nall/traits.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
struct any {
|
struct any {
|
||||||
|
|
|
@ -1,289 +0,0 @@
|
||||||
#ifndef NALL_ARRAY_HPP
|
|
||||||
#define NALL_ARRAY_HPP
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <initializer_list>
|
|
||||||
#include <utility>
|
|
||||||
#include <nall/algorithm.hpp>
|
|
||||||
#include <nall/bit.hpp>
|
|
||||||
#include <nall/sort.hpp>
|
|
||||||
#include <nall/type_traits.hpp>
|
|
||||||
#include <nall/utility.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
template<typename T, typename Enable = void> struct array;
|
|
||||||
|
|
||||||
//non-reference array
|
|
||||||
//===================
|
|
||||||
|
|
||||||
template<typename T> struct array<T, typename std::enable_if<!std::is_reference<T>::value>::type> {
|
|
||||||
struct exception_out_of_bounds{};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
T *pool;
|
|
||||||
unsigned poolsize, objectsize;
|
|
||||||
|
|
||||||
public:
|
|
||||||
unsigned size() const { return objectsize; }
|
|
||||||
unsigned capacity() const { return poolsize; }
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
if(pool) free(pool);
|
|
||||||
pool = nullptr;
|
|
||||||
poolsize = 0;
|
|
||||||
objectsize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reserve(unsigned newsize) {
|
|
||||||
if(newsize == poolsize) return;
|
|
||||||
|
|
||||||
pool = (T*)realloc(pool, newsize * sizeof(T));
|
|
||||||
poolsize = newsize;
|
|
||||||
objectsize = min(objectsize, newsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(unsigned newsize) {
|
|
||||||
if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2
|
|
||||||
objectsize = newsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* get(unsigned minsize = 0) {
|
|
||||||
if(minsize > objectsize) resize(minsize);
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(const T data) {
|
|
||||||
operator()(objectsize) = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(const T data[], unsigned length) {
|
|
||||||
for(unsigned n = 0; n < length; n++) operator()(objectsize) = data[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove() {
|
|
||||||
if(size() > 0) resize(size - 1); //remove last element only
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove(unsigned index, unsigned count = 1) {
|
|
||||||
for(unsigned i = index; count + i < objectsize; i++) {
|
|
||||||
pool[i] = pool[count + i];
|
|
||||||
}
|
|
||||||
if(count + index >= objectsize) resize(index); //every element >= index was removed
|
|
||||||
else resize(objectsize - count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sort() {
|
|
||||||
nall::sort(pool, objectsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Comparator> void sort(const Comparator &lessthan) {
|
|
||||||
nall::sort(pool, objectsize, lessthan);
|
|
||||||
}
|
|
||||||
|
|
||||||
optional<unsigned> find(const T data) {
|
|
||||||
for(unsigned n = 0; n < size(); n++) if(pool[n] == data) return { true, n };
|
|
||||||
return { false, 0u };
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
memset(pool, 0, objectsize * sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
array() : pool(nullptr), poolsize(0), objectsize(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
array(std::initializer_list<T> list) : pool(nullptr), poolsize(0), objectsize(0) {
|
|
||||||
for(auto &data : list) append(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
~array() {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
//copy
|
|
||||||
array& operator=(const array &source) {
|
|
||||||
if(pool) free(pool);
|
|
||||||
objectsize = source.objectsize;
|
|
||||||
poolsize = source.poolsize;
|
|
||||||
pool = (T*)malloc(sizeof(T) * poolsize); //allocate entire pool size,
|
|
||||||
memcpy(pool, source.pool, sizeof(T) * objectsize); //... but only copy used pool objects
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
array(const array &source) : pool(nullptr), poolsize(0), objectsize(0) {
|
|
||||||
operator=(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
//move
|
|
||||||
array& operator=(array &&source) {
|
|
||||||
if(pool) free(pool);
|
|
||||||
pool = source.pool;
|
|
||||||
poolsize = source.poolsize;
|
|
||||||
objectsize = source.objectsize;
|
|
||||||
source.pool = nullptr;
|
|
||||||
source.reset();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
array(array &&source) : pool(nullptr), poolsize(0), objectsize(0) {
|
|
||||||
operator=(std::move(source));
|
|
||||||
}
|
|
||||||
|
|
||||||
//access
|
|
||||||
inline T& operator[](unsigned position) {
|
|
||||||
if(position >= objectsize) throw exception_out_of_bounds();
|
|
||||||
return pool[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const T& operator[](unsigned position) const {
|
|
||||||
if(position >= objectsize) throw exception_out_of_bounds();
|
|
||||||
return pool[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline T& operator()(unsigned position) {
|
|
||||||
if(position >= objectsize) resize(position + 1);
|
|
||||||
return pool[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const T& operator()(unsigned position, const T& data) {
|
|
||||||
if(position >= objectsize) return data;
|
|
||||||
return pool[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
//iteration
|
|
||||||
T* begin() { return &pool[0]; }
|
|
||||||
T* end() { return &pool[objectsize]; }
|
|
||||||
const T* begin() const { return &pool[0]; }
|
|
||||||
const T* end() const { return &pool[objectsize]; }
|
|
||||||
};
|
|
||||||
|
|
||||||
//reference array
|
|
||||||
//===============
|
|
||||||
|
|
||||||
template<typename TR> struct array<TR, typename std::enable_if<std::is_reference<TR>::value>::type> {
|
|
||||||
struct exception_out_of_bounds{};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
typedef typename std::remove_reference<TR>::type T;
|
|
||||||
T **pool;
|
|
||||||
unsigned poolsize, objectsize;
|
|
||||||
|
|
||||||
public:
|
|
||||||
unsigned size() const { return objectsize; }
|
|
||||||
unsigned capacity() const { return poolsize; }
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
if(pool) free(pool);
|
|
||||||
pool = nullptr;
|
|
||||||
poolsize = 0;
|
|
||||||
objectsize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reserve(unsigned newsize) {
|
|
||||||
if(newsize == poolsize) return;
|
|
||||||
|
|
||||||
pool = (T**)realloc(pool, sizeof(T*) * newsize);
|
|
||||||
poolsize = newsize;
|
|
||||||
objectsize = min(objectsize, newsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(unsigned newsize) {
|
|
||||||
if(newsize > poolsize) reserve(bit::round(newsize));
|
|
||||||
objectsize = newsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
bool append(T& data, Args&&... args) {
|
|
||||||
bool result = append(data);
|
|
||||||
append(std::forward<Args>(args)...);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool append(T& data) {
|
|
||||||
if(find(data)) return false;
|
|
||||||
unsigned offset = objectsize++;
|
|
||||||
if(offset >= poolsize) resize(offset + 1);
|
|
||||||
pool[offset] = &data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool remove(T& data) {
|
|
||||||
if(auto position = find(data)) {
|
|
||||||
for(signed i = position(); i < objectsize - 1; i++) pool[i] = pool[i + 1];
|
|
||||||
resize(objectsize - 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
optional<unsigned> find(const T& data) {
|
|
||||||
for(unsigned n = 0; n < objectsize; n++) if(pool[n] == &data) return { true, n };
|
|
||||||
return { false, 0u };
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args> array(Args&&... args) : pool(nullptr), poolsize(0), objectsize(0) {
|
|
||||||
construct(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
~array() {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
array& operator=(const array &source) {
|
|
||||||
if(pool) free(pool);
|
|
||||||
objectsize = source.objectsize;
|
|
||||||
poolsize = source.poolsize;
|
|
||||||
pool = (T**)malloc(sizeof(T*) * poolsize);
|
|
||||||
memcpy(pool, source.pool, sizeof(T*) * objectsize);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
array& operator=(const array &&source) {
|
|
||||||
if(pool) free(pool);
|
|
||||||
pool = source.pool;
|
|
||||||
poolsize = source.poolsize;
|
|
||||||
objectsize = source.objectsize;
|
|
||||||
source.pool = nullptr;
|
|
||||||
source.reset();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator[](unsigned position) const {
|
|
||||||
if(position >= objectsize) throw exception_out_of_bounds();
|
|
||||||
return *pool[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
//iteration
|
|
||||||
struct iterator {
|
|
||||||
bool operator!=(const iterator &source) const { return position != source.position; }
|
|
||||||
T& operator*() { return source.operator[](position); }
|
|
||||||
iterator& operator++() { position++; return *this; }
|
|
||||||
iterator(const array &source, unsigned position) : source(source), position(position) {}
|
|
||||||
private:
|
|
||||||
const array &source;
|
|
||||||
unsigned position;
|
|
||||||
};
|
|
||||||
|
|
||||||
iterator begin() { return iterator(*this, 0); }
|
|
||||||
iterator end() { return iterator(*this, objectsize); }
|
|
||||||
const iterator begin() const { return iterator(*this, 0); }
|
|
||||||
const iterator end() const { return iterator(*this, objectsize); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void construct() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void construct(const array& source) { operator=(source); }
|
|
||||||
void construct(const array&& source) { operator=(std::move(source)); }
|
|
||||||
|
|
||||||
template<typename... Args> void construct(T& data, Args&&... args) {
|
|
||||||
append(data);
|
|
||||||
construct(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef NALL_BIT_HPP
|
#ifndef NALL_BIT_HPP
|
||||||
#define NALL_BIT_HPP
|
#define NALL_BIT_HPP
|
||||||
|
|
||||||
|
#include <nall/stdint.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<unsigned bits>
|
template<unsigned bits>
|
||||||
inline uintmax_t uclamp(const uintmax_t x) {
|
inline uintmax_t uclamp(const uintmax_t x) {
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
#ifndef NALL_BITARRAY_HPP
|
|
||||||
#define NALL_BITARRAY_HPP
|
|
||||||
|
|
||||||
#include <nall/stdint.hpp>
|
|
||||||
|
|
||||||
//statically-sized bit array
|
|
||||||
//no bounds-checking on read/write
|
|
||||||
//packed into uint8_t array (8 bits per byte)
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
struct bitarray {
|
|
||||||
uint8_t *pool;
|
|
||||||
unsigned poolsize;
|
|
||||||
|
|
||||||
uint8_t* data() { return pool; }
|
|
||||||
const uint8_t* data() const { return pool; }
|
|
||||||
unsigned size() const { return poolsize; }
|
|
||||||
unsigned bytesize() const { return (poolsize >> 3) + ((poolsize & 7) > 0); }
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
if(pool) free(pool);
|
|
||||||
pool = nullptr;
|
|
||||||
poolsize = 0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(unsigned allocsize) {
|
|
||||||
if(allocsize == poolsize) return;
|
|
||||||
pool = (uint8_t*)realloc(pool, allocsize);
|
|
||||||
poolsize = allocsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator[](unsigned offset) const {
|
|
||||||
return pool[offset >> 3] & (0x80 >> (offset & 7));
|
|
||||||
}
|
|
||||||
|
|
||||||
void set() {
|
|
||||||
memset(pool, 0xff, (poolsize >> 3) + ((poolsize & 7) > 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(unsigned offset) {
|
|
||||||
pool[offset >> 3] |= 0x80 >> (offset & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
memset(pool, 0, (poolsize >> 3) + ((poolsize & 7) > 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear(unsigned offset) {
|
|
||||||
pool[offset >> 3] &=~0x80 >> (offset & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(unsigned offset, bool data) {
|
|
||||||
data ? set(offset) : clear(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct bit {
|
|
||||||
bitarray &array;
|
|
||||||
unsigned offset;
|
|
||||||
operator bool() const { return const_cast<const bitarray&>(array)[offset]; }
|
|
||||||
bit& operator=(bool data) { array.set(offset, data); return *this; }
|
|
||||||
bit& operator=(const bit& data) { return operator=((bool)data); }
|
|
||||||
bit(bitarray &array, unsigned offset) : array(array), offset(offset) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
bit operator[](unsigned offset) {
|
|
||||||
return bit(*this, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
bitarray() : pool(nullptr), poolsize(0u) {}
|
|
||||||
bitarray(unsigned allocsize) {
|
|
||||||
pool = (uint8_t*)malloc((allocsize >> 3) + ((allocsize & 7) > 0));
|
|
||||||
poolsize = allocsize;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -17,6 +17,8 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct directory {
|
struct directory {
|
||||||
|
static bool create(const string &pathname, unsigned permissions = 0755); //recursive
|
||||||
|
static bool remove(const string &pathname);
|
||||||
static bool exists(const string &pathname);
|
static bool exists(const string &pathname);
|
||||||
static lstring folders(const string &pathname, const string &pattern = "*");
|
static lstring folders(const string &pathname, const string &pattern = "*");
|
||||||
static lstring files(const string &pathname, const string &pattern = "*");
|
static lstring files(const string &pathname, const string &pattern = "*");
|
||||||
|
@ -24,8 +26,27 @@ struct directory {
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(PLATFORM_WINDOWS)
|
#if defined(PLATFORM_WINDOWS)
|
||||||
|
inline bool directory::create(const string &pathname, unsigned permissions) {
|
||||||
|
string fullpath = pathname, path;
|
||||||
|
fullpath.transform("/", "\\");
|
||||||
|
fullpath.rtrim<1>("\\");
|
||||||
|
lstring pathpart = fullpath.split("\\");
|
||||||
|
bool result = false;
|
||||||
|
for(auto &part : pathpart) {
|
||||||
|
path.append(part, "\\");
|
||||||
|
result = _wmkdir(utf16_t(path)) == 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool directory::remove(const string &pathname) {
|
||||||
|
return _wrmdir(utf16_t(pathname)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool directory::exists(const string &pathname) {
|
inline bool directory::exists(const string &pathname) {
|
||||||
DWORD result = GetFileAttributes(utf16_t(pathname));
|
string name = pathname;
|
||||||
|
name.trim<1>("\"");
|
||||||
|
DWORD result = GetFileAttributes(utf16_t(name));
|
||||||
if(result == INVALID_FILE_ATTRIBUTES) return false;
|
if(result == INVALID_FILE_ATTRIBUTES) return false;
|
||||||
return (result & FILE_ATTRIBUTE_DIRECTORY);
|
return (result & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
|
@ -94,6 +115,21 @@ struct directory {
|
||||||
return folders;
|
return folders;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
inline bool directory::create(const string &pathname, unsigned permissions) {
|
||||||
|
string fullpath = pathname, path = "/";
|
||||||
|
fullpath.trim<1>("/");
|
||||||
|
lstring pathpart = fullpath.split("/");
|
||||||
|
for(auto &part : pathpart) {
|
||||||
|
if(!directory::exists(path)) mkdir(path, permissions);
|
||||||
|
path.append(part, "/");
|
||||||
|
}
|
||||||
|
return mkdir(path, permissions) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool directory::remove(const string &pathname) {
|
||||||
|
return rmdir(pathname) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool directory::exists(const string &pathname) {
|
inline bool directory::exists(const string &pathname) {
|
||||||
DIR *dp = opendir(pathname);
|
DIR *dp = opendir(pathname);
|
||||||
if(!dp) return false;
|
if(!dp) return false;
|
||||||
|
|
|
@ -1,29 +1,40 @@
|
||||||
#ifndef NALL_NES_CARTRIDGE_HPP
|
#ifndef NALL_EMULATION_FAMICOM_HPP
|
||||||
#define NALL_NES_CARTRIDGE_HPP
|
#define NALL_EMULATION_FAMICOM_HPP
|
||||||
|
|
||||||
#include <nall/sha256.hpp>
|
#include <nall/sha256.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct FamicomCartridge {
|
struct FamicomCartridge {
|
||||||
string markup;
|
string markup;
|
||||||
inline FamicomCartridge(const uint8_t *data, unsigned size);
|
inline FamicomCartridge(const uint8_t *data, unsigned size);
|
||||||
|
|
||||||
|
//private:
|
||||||
|
unsigned mapper;
|
||||||
|
unsigned mirror;
|
||||||
|
unsigned prgrom;
|
||||||
|
unsigned prgram;
|
||||||
|
unsigned chrrom;
|
||||||
|
unsigned chrram;
|
||||||
};
|
};
|
||||||
|
|
||||||
FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
|
FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
|
||||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
markup = "";
|
||||||
if(size < 16) return;
|
if(size < 16) return;
|
||||||
if(data[0] != 'N') return;
|
if(data[0] != 'N') return;
|
||||||
if(data[1] != 'E') return;
|
if(data[1] != 'E') return;
|
||||||
if(data[2] != 'S') return;
|
if(data[2] != 'S') return;
|
||||||
if(data[3] != 26) return;
|
if(data[3] != 26) return;
|
||||||
|
|
||||||
unsigned mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
|
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
unsigned mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
|
|
||||||
unsigned prgrom = data[4] * 0x4000;
|
mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
|
||||||
unsigned chrrom = data[5] * 0x2000;
|
mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
|
||||||
unsigned prgram = 0u;
|
prgrom = data[4] * 0x4000;
|
||||||
unsigned chrram = chrrom == 0u ? 8192u : 0u;
|
chrrom = data[5] * 0x2000;
|
||||||
|
prgram = 0u;
|
||||||
|
chrram = chrrom == 0u ? 8192u : 0u;
|
||||||
|
|
||||||
markup.append("<cartridge sha256='", sha256(data, size), "'>\n");
|
markup.append("<cartridge sha256='", sha256(data, size), "'>\n");
|
||||||
|
|
||||||
|
@ -153,13 +164,13 @@ FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
markup.append(" <prg>\n");
|
markup.append(" <prg>\n");
|
||||||
if(prgrom) markup.append(" <rom size='", prgrom, "'/>\n");
|
if(prgrom) markup.append(" <rom name='program.rom' size='0x", hex(prgrom), "'/>\n");
|
||||||
if(prgram) markup.append(" <ram size='", prgram, "' nonvolatile='true'/>\n");
|
if(prgram) markup.append(" <ram name='save.ram' size='0x", hex(prgram), "'/>\n");
|
||||||
markup.append(" </prg>\n");
|
markup.append(" </prg>\n");
|
||||||
|
|
||||||
markup.append(" <chr>\n");
|
markup.append(" <chr>\n");
|
||||||
if(chrrom) markup.append(" <rom size='", chrrom, "'/>\n");
|
if(chrrom) markup.append(" <rom name='character.rom' size='0x", hex(chrrom), "'/>\n");
|
||||||
if(chrram) markup.append(" <ram size='", chrram, "'/>\n");
|
if(chrram) markup.append(" <ram size='0x", hex(chrram), "'/>\n");
|
||||||
markup.append(" </chr>\n");
|
markup.append(" </chr>\n");
|
||||||
|
|
||||||
markup.append("</cartridge>\n");
|
markup.append("</cartridge>\n");
|
|
@ -1,7 +1,8 @@
|
||||||
#ifndef NALL_GBA_CARTRIDGE_HPP
|
#ifndef NALL_EMULATION_GAME_BOY_ADVANCE_HPP
|
||||||
#define NALL_GBA_CARTRIDGE_HPP
|
#define NALL_EMULATION_GAME_BOY_ADVANCE_HPP
|
||||||
|
|
||||||
#include <nall/sha256.hpp>
|
#include <nall/sha256.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
#include <nall/vector.hpp>
|
#include <nall/vector.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
@ -44,16 +45,18 @@ GameBoyAdvanceCartridge::GameBoyAdvanceCartridge(const uint8_t *data, unsigned s
|
||||||
}
|
}
|
||||||
identifiers = list.concatenate(",");
|
identifiers = list.concatenate(",");
|
||||||
|
|
||||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
markup = "";
|
||||||
|
|
||||||
|
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
markup.append("<cartridge sha256='", sha256(data, size), "'>\n");
|
markup.append("<cartridge sha256='", sha256(data, size), "'>\n");
|
||||||
markup.append(" <rom size='", size, "'/>\n");
|
markup.append(" <rom name='program.rom' size='0x", hex(size), "'/>\n");
|
||||||
if(0);
|
if(0);
|
||||||
else if(identifiers.beginswith("SRAM_V" )) markup.append(" <ram type='SRAM' size='32768'/>\n");
|
else if(identifiers.beginswith("SRAM_V" )) markup.append(" <ram name='save.ram' type='SRAM' size='0x8000'/>\n");
|
||||||
else if(identifiers.beginswith("SRAM_F_V" )) markup.append(" <ram type='FRAM' size='32768'/>\n");
|
else if(identifiers.beginswith("SRAM_F_V" )) markup.append(" <ram name='save.ram' type='FRAM' size='0x8000'/>\n");
|
||||||
else if(identifiers.beginswith("EEPROM_V" )) markup.append(" <ram type='EEPROM' size='0'/>\n");
|
else if(identifiers.beginswith("EEPROM_V" )) markup.append(" <ram name='save.ram' type='EEPROM' size='0x0'/>\n");
|
||||||
else if(identifiers.beginswith("FLASH_V" )) markup.append(" <ram type='FlashROM' size='65536'/>\n");
|
else if(identifiers.beginswith("FLASH_V" )) markup.append(" <ram name='save.ram' type='FlashROM' size='0x10000'/>\n");
|
||||||
else if(identifiers.beginswith("FLASH512_V")) markup.append(" <ram type='FlashROM' size='65536'/>\n");
|
else if(identifiers.beginswith("FLASH512_V")) markup.append(" <ram name='save.ram' type='FlashROM' size='0x10000'/>\n");
|
||||||
else if(identifiers.beginswith("FLASH1M_V" )) markup.append(" <ram type='FlashROM' size='131072'/>\n");
|
else if(identifiers.beginswith("FLASH1M_V" )) markup.append(" <ram name='save.ram' type='FlashROM' size='0x20000'/>\n");
|
||||||
if(identifiers.empty() == false) markup.append(" <!-- detected: ", identifiers, " -->\n");
|
if(identifiers.empty() == false) markup.append(" <!-- detected: ", identifiers, " -->\n");
|
||||||
|
|
||||||
markup.append("</cartridge>\n");
|
markup.append("</cartridge>\n");
|
|
@ -1,5 +1,8 @@
|
||||||
#ifndef NALL_GB_CARTRIDGE_HPP
|
#ifndef NALL_EMULATION_GAME_BOY_HPP
|
||||||
#define NALL_GB_CARTRIDGE_HPP
|
#define NALL_EMULATION_GAME_BOY_HPP
|
||||||
|
|
||||||
|
#include <nall/sha256.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
|
@ -17,6 +20,9 @@ struct GameBoyCartridge {
|
||||||
|
|
||||||
unsigned romsize;
|
unsigned romsize;
|
||||||
unsigned ramsize;
|
unsigned ramsize;
|
||||||
|
|
||||||
|
bool cgb;
|
||||||
|
bool cgbonly;
|
||||||
} info;
|
} info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,6 +53,9 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
|
||||||
memcpy(romdata, header, 0x8000);
|
memcpy(romdata, header, 0x8000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.cgb = (romdata[0x0143] & 0x80) == 0x80;
|
||||||
|
info.cgbonly = (romdata[0x0143] & 0xc0) == 0xc0;
|
||||||
|
|
||||||
switch(romdata[0x0147]) {
|
switch(romdata[0x0147]) {
|
||||||
case 0x00: info.mapper = "none"; break;
|
case 0x00: info.mapper = "none"; break;
|
||||||
case 0x01: info.mapper = "MBC1"; break;
|
case 0x01: info.mapper = "MBC1"; break;
|
||||||
|
@ -100,9 +109,10 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
|
||||||
if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit
|
if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit
|
||||||
|
|
||||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||||
markup.append("<cartridge mapper='", info.mapper, "' rtc='", info.rtc, "' rumble='", info.rumble, "'>\n");
|
markup.append("<cartridge>\n");
|
||||||
markup.append(" <rom size='0x", hex(romsize), "'/>\n");
|
markup.append(" <board type='", info.mapper, "'/>\n");
|
||||||
if(info.ramsize > 0) markup.append(" <ram size='0x", hex(info.ramsize), "' nonvolatile='", info.battery, "'/>\n");
|
markup.append(" <rom name='program.rom' size='0x", hex(romsize), "'/>\n");
|
||||||
|
if(info.ramsize > 0) markup.append(" <ram name='save.ram' size='0x", hex(info.ramsize), "'/>\n");
|
||||||
markup.append("</cartridge>\n");
|
markup.append("</cartridge>\n");
|
||||||
markup.transform("'", "\"");
|
markup.transform("'", "\"");
|
||||||
}
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef NALL_EMULATION_SATELLAVIEW_HPP
|
||||||
|
#define NALL_EMULATION_SATELLAVIEW_HPP
|
||||||
|
|
||||||
|
#include <nall/sha256.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
struct SatellaviewCartridge {
|
||||||
|
string markup;
|
||||||
|
inline SatellaviewCartridge(const uint8_t *data, unsigned size);
|
||||||
|
};
|
||||||
|
|
||||||
|
SatellaviewCartridge::SatellaviewCartridge(const uint8_t *data, unsigned size) {
|
||||||
|
markup = "";
|
||||||
|
|
||||||
|
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
|
markup.append("<cartridge sha256='", sha256(data, size) ,"'>\n");
|
||||||
|
markup.append(" <rom name='program.rom' size='0x", hex(size), "'/>\n");
|
||||||
|
markup.append("</cartridge>\n");
|
||||||
|
markup.transform("'", "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef NALL_EMULATION_SUFAMI_TURBO_HPP
|
||||||
|
#define NALL_EMULATION_SUFAMI_TURBO_HPP
|
||||||
|
|
||||||
|
#include <nall/sha256.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
struct SufamiTurboCartridge {
|
||||||
|
string markup;
|
||||||
|
inline SufamiTurboCartridge(const uint8_t *data, unsigned size);
|
||||||
|
};
|
||||||
|
|
||||||
|
SufamiTurboCartridge::SufamiTurboCartridge(const uint8_t *data, unsigned size) {
|
||||||
|
markup = "";
|
||||||
|
|
||||||
|
if(size < 0x20000) return; //too small to be a valid game?
|
||||||
|
if(memcmp(data, "BANDAI SFC-ADX", 14)) return; //missing required header?
|
||||||
|
unsigned romsize = data[0x36] * 0x20000; //128KB
|
||||||
|
unsigned ramsize = data[0x37] * 0x800; //2KB
|
||||||
|
bool linkable = data[0x35] != 0x00; //TODO: unconfirmed
|
||||||
|
|
||||||
|
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
|
markup.append("<cartridge linkable='", linkable, "' sha256='", sha256(data, size) ,"'>\n");
|
||||||
|
markup.append(" <rom name='program.rom' size='0x", hex(romsize), "'/>\n");
|
||||||
|
markup.append(" <ram name='save.ram' size='0x", hex(ramsize), "'/>\n");
|
||||||
|
markup.append("</cartridge>\n");
|
||||||
|
markup.transform("'", "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef NALL_SNES_USART_HPP
|
#ifndef NALL_EMULATION_SUPER_FAMICOM_USART_HPP
|
||||||
#define NALL_SNES_USART_HPP
|
#define NALL_EMULATION_SUPER_FAMICOM_USART_HPP
|
||||||
|
|
||||||
#include <nall/platform.hpp>
|
#include <nall/platform.hpp>
|
||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
|
@ -1,5 +1,8 @@
|
||||||
#ifndef NALL_SNES_CARTRIDGE_HPP
|
#ifndef NALL_EMULATION_SUPER_FAMICOM_HPP
|
||||||
#define NALL_SNES_CARTRIDGE_HPP
|
#define NALL_EMULATION_SUPER_FAMICOM_HPP
|
||||||
|
|
||||||
|
#include <nall/sha256.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
|
@ -11,8 +14,6 @@ struct SuperFamicomCartridge {
|
||||||
inline void read_header(const uint8_t *data, unsigned size);
|
inline void read_header(const uint8_t *data, unsigned size);
|
||||||
inline unsigned find_header(const uint8_t *data, unsigned size);
|
inline unsigned find_header(const uint8_t *data, unsigned size);
|
||||||
inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr);
|
inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr);
|
||||||
inline unsigned gameboy_ram_size(const uint8_t *data, unsigned size);
|
|
||||||
inline bool gameboy_has_rtc(const uint8_t *data, unsigned size);
|
|
||||||
|
|
||||||
enum HeaderField {
|
enum HeaderField {
|
||||||
CartName = 0x00,
|
CartName = 0x00,
|
||||||
|
@ -105,35 +106,23 @@ struct SuperFamicomCartridge {
|
||||||
};
|
};
|
||||||
|
|
||||||
SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) {
|
SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) {
|
||||||
|
markup = "";
|
||||||
|
if(size < 0x8000) return;
|
||||||
|
|
||||||
read_header(data, size);
|
read_header(data, size);
|
||||||
|
|
||||||
string xml;
|
markup = "";
|
||||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
if(type == TypeGameBoy) return;
|
||||||
|
if(type == TypeBsx) return;
|
||||||
|
if(type == TypeSufamiTurbo) return;
|
||||||
|
|
||||||
if(type == TypeBsx) {
|
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
markup.append("<cartridge/>\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type == TypeSufamiTurbo) {
|
|
||||||
markup.append("<cartridge/>\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type == TypeGameBoy) {
|
|
||||||
markup.append("<cartridge rtc='", gameboy_has_rtc(data, size), "'\n");
|
|
||||||
if(gameboy_ram_size(data, size) > 0) {
|
|
||||||
markup.append(" <ram size='0x", hex(gameboy_ram_size(data, size)), "'>\n");
|
|
||||||
}
|
|
||||||
markup.append("</cartridge>\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
|
const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
|
||||||
markup.append("<cartridge region='", region == NTSC ? "NTSC" : "PAL", "'>\n");
|
markup.append("<cartridge region='", region == NTSC ? "NTSC" : "PAL", "'>\n");
|
||||||
|
|
||||||
if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) markup.append(
|
if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) markup.append(
|
||||||
" <rom>\n"
|
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
|
||||||
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
|
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
|
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
|
@ -144,6 +133,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
);
|
);
|
||||||
|
|
||||||
else if(has_cx4) markup.append(
|
else if(has_cx4) markup.append(
|
||||||
|
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
|
||||||
" <hitachidsp model='HG51B169' frequency='20000000' firmware='cx4.rom' sha256='ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18'>\n"
|
" <hitachidsp model='HG51B169' frequency='20000000' firmware='cx4.rom' sha256='ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18'>\n"
|
||||||
" <rom>\n"
|
" <rom>\n"
|
||||||
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
|
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
|
||||||
|
@ -158,47 +148,48 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
|
|
||||||
else if(has_spc7110) {
|
else if(has_spc7110) {
|
||||||
markup.append(
|
markup.append(
|
||||||
" <rom>\n"
|
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
|
||||||
" <map mode='shadow' address='00-0f:8000-ffff'/>\n"
|
" <ram name='save.ram' size='", hex(ram_size), "'/>\n"
|
||||||
" <map mode='shadow' address='80-bf:8000-ffff'/>\n"
|
|
||||||
" <map mode='linear' address='c0-cf:0000-ffff'/>\n"
|
|
||||||
" </rom>\n"
|
|
||||||
" <spc7110>\n"
|
" <spc7110>\n"
|
||||||
" <ram size='0x", hex(ram_size), "'>\n"
|
|
||||||
" <map mode='linear' address='00:6000-7fff'/>\n"
|
|
||||||
" <map mode='linear' address='30:6000-7fff'/>\n"
|
|
||||||
" </ram>\n"
|
|
||||||
" <mmio>\n"
|
" <mmio>\n"
|
||||||
" <map address='00-3f:4800-483f'/>\n"
|
" <map address='00-3f:4800-483f'/>\n"
|
||||||
" <map address='80-bf:4800-483f'/>\n"
|
" <map address='80-bf:4800-483f'/>\n"
|
||||||
" </mmio>\n"
|
" </mmio>\n"
|
||||||
" <mcu>\n"
|
|
||||||
" <map address='d0-ff:0000-ffff' offset='0x100000' size='0x", hex(size - 0x100000), "'/>\n"
|
|
||||||
" </mcu>\n"
|
|
||||||
" <dcu>\n"
|
" <dcu>\n"
|
||||||
" <map address='50:0000-ffff'/>\n"
|
" <map address='50:0000-ffff'/>\n"
|
||||||
" </dcu>\n"
|
" </dcu>\n"
|
||||||
|
" <mcu>\n"
|
||||||
|
" <rom>\n"
|
||||||
|
" <program offset='0x000000' size='0x100000'/>\n"
|
||||||
|
" <data offset='0x100000' size='", hex(rom_size - 0x100000), "'/>\n"
|
||||||
|
" <map address='00-0f:8000-ffff'/>\n"
|
||||||
|
" <map address='80-bf:8000-ffff'/>\n"
|
||||||
|
" <map address='c0-cf:0000-ffff'/>\n"
|
||||||
|
" </rom>\n"
|
||||||
|
" <ram>\n"
|
||||||
|
" <map address='00-3f:6000-7fff'/>\n"
|
||||||
|
" <map address='80-bf:6000-7fff'/>\n"
|
||||||
|
" </ram>\n"
|
||||||
|
" </mcu>\n"
|
||||||
|
" </spc7110>\n"
|
||||||
);
|
);
|
||||||
if(has_spc7110rtc) markup.append(
|
if(has_spc7110rtc) markup.append(
|
||||||
" <rtc>\n"
|
" <epsonrtc name='rtc.ram' size='0x10'>\n"
|
||||||
" <map address='00-3f:4840-4842'/>\n"
|
" <map address='00-3f:4840-4842'/>\n"
|
||||||
" <map address='80-bf:4840-4842'/>\n"
|
" <map address='80-bf:4840-4842'/>\n"
|
||||||
" </rtc>\n"
|
" </epsonrtc>\n"
|
||||||
);
|
|
||||||
markup.append(
|
|
||||||
" </spc7110>\n"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(mapper == LoROM) {
|
else if(mapper == LoROM) {
|
||||||
markup.append(
|
markup.append(
|
||||||
" <rom>\n"
|
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
|
||||||
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
|
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
|
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
);
|
);
|
||||||
if(ram_size > 0) markup.append(
|
if(ram_size > 0) markup.append(
|
||||||
" <ram size='0x", hex(ram_size), "'>\n"
|
" <ram name='save.ram' size='0x", hex(ram_size), "'>\n"
|
||||||
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
||||||
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
||||||
" <map mode='linear' address='70-7f:", range, "'/>\n"
|
" <map mode='linear' address='70-7f:", range, "'/>\n"
|
||||||
|
@ -209,7 +200,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
|
|
||||||
else if(mapper == HiROM) {
|
else if(mapper == HiROM) {
|
||||||
markup.append(
|
markup.append(
|
||||||
" <rom>\n"
|
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
|
||||||
" <map mode='shadow' address='00-3f:8000-ffff'/>\n"
|
" <map mode='shadow' address='00-3f:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='40-7f:0000-ffff'/>\n"
|
" <map mode='linear' address='40-7f:0000-ffff'/>\n"
|
||||||
" <map mode='shadow' address='80-bf:8000-ffff'/>\n"
|
" <map mode='shadow' address='80-bf:8000-ffff'/>\n"
|
||||||
|
@ -217,7 +208,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
);
|
);
|
||||||
if(ram_size > 0) markup.append(
|
if(ram_size > 0) markup.append(
|
||||||
" <ram size='0x", hex(ram_size), "'>\n"
|
" <ram name='save.ram' size='0x", hex(ram_size), "'>\n"
|
||||||
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
||||||
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
||||||
" <map mode='linear' address='70-7f:", range, "'/>\n"
|
" <map mode='linear' address='70-7f:", range, "'/>\n"
|
||||||
|
@ -227,14 +218,14 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
|
|
||||||
else if(mapper == ExLoROM) {
|
else if(mapper == ExLoROM) {
|
||||||
markup.append(
|
markup.append(
|
||||||
" <rom>\n"
|
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
|
||||||
" <map mode='linear' address='00-3f:8000-ffff'/>\n"
|
" <map mode='linear' address='00-3f:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='40-7f:0000-ffff'/>\n"
|
" <map mode='linear' address='40-7f:0000-ffff'/>\n"
|
||||||
" <map mode='linear' address='80-bf:8000-ffff'/>\n"
|
" <map mode='linear' address='80-bf:8000-ffff'/>\n"
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
);
|
);
|
||||||
if(ram_size > 0) markup.append(
|
if(ram_size > 0) markup.append(
|
||||||
" <ram size='0x", hex(ram_size), "'>\n"
|
" <ram name='save.ram' size='0x", hex(ram_size), "'>\n"
|
||||||
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
||||||
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
||||||
" <map mode='linear' address='70-7f:0000-7fff'/>\n"
|
" <map mode='linear' address='70-7f:0000-7fff'/>\n"
|
||||||
|
@ -244,7 +235,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
|
|
||||||
else if(mapper == ExHiROM) {
|
else if(mapper == ExHiROM) {
|
||||||
markup.append(
|
markup.append(
|
||||||
" <rom>\n"
|
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
|
||||||
" <map mode='shadow' address='00-3f:8000-ffff' offset='0x400000'/>\n"
|
" <map mode='shadow' address='00-3f:8000-ffff' offset='0x400000'/>\n"
|
||||||
" <map mode='linear' address='40-7f:0000-ffff' offset='0x400000'/>\n"
|
" <map mode='linear' address='40-7f:0000-ffff' offset='0x400000'/>\n"
|
||||||
" <map mode='shadow' address='80-bf:8000-ffff' offset='0x000000'/>\n"
|
" <map mode='shadow' address='80-bf:8000-ffff' offset='0x000000'/>\n"
|
||||||
|
@ -252,7 +243,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
);
|
);
|
||||||
if(ram_size > 0) markup.append(
|
if(ram_size > 0) markup.append(
|
||||||
" <ram size='0x", hex(ram_size), "'>\n"
|
" <ram name='save.ram' size='0x", hex(ram_size), "'>\n"
|
||||||
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
||||||
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
||||||
" <map mode='linear' address='70-7f:", range, "'/>\n"
|
" <map mode='linear' address='70-7f:", range, "'/>\n"
|
||||||
|
@ -260,7 +251,11 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(mapper == SuperFXROM) markup.append(
|
else if(mapper == SuperFXROM) {
|
||||||
|
markup.append(" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n");
|
||||||
|
if(ram_size > 0)
|
||||||
|
markup.append(" <ram name='save.ram' size='0x", hex(ram_size), "'/>\n");
|
||||||
|
markup.append(
|
||||||
" <superfx revision='2'>\n"
|
" <superfx revision='2'>\n"
|
||||||
" <rom>\n"
|
" <rom>\n"
|
||||||
" <map mode='linear' address='00-3f:8000-ffff'/>\n"
|
" <map mode='linear' address='00-3f:8000-ffff'/>\n"
|
||||||
|
@ -268,7 +263,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
" <map mode='linear' address='80-bf:8000-ffff'/>\n"
|
" <map mode='linear' address='80-bf:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='c0-df:0000-ffff'/>\n"
|
" <map mode='linear' address='c0-df:0000-ffff'/>\n"
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
" <ram size='0x", hex(ram_size), "'>\n"
|
" <ram>\n"
|
||||||
" <map mode='linear' address='00-3f:6000-7fff' size='0x2000'/>\n"
|
" <map mode='linear' address='00-3f:6000-7fff' size='0x2000'/>\n"
|
||||||
" <map mode='linear' address='60-7f:0000-ffff'/>\n"
|
" <map mode='linear' address='60-7f:0000-ffff'/>\n"
|
||||||
" <map mode='linear' address='80-bf:6000-7fff' size='0x2000'/>\n"
|
" <map mode='linear' address='80-bf:6000-7fff' size='0x2000'/>\n"
|
||||||
|
@ -280,8 +275,13 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
" </mmio>\n"
|
" </mmio>\n"
|
||||||
" </superfx>\n"
|
" </superfx>\n"
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
else if(mapper == SA1ROM) markup.append(
|
else if(mapper == SA1ROM) {
|
||||||
|
markup.append(" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n");
|
||||||
|
if(ram_size > 0)
|
||||||
|
markup.append(" <ram name='save.ram' size='0x", hex(ram_size), "'/>\n");
|
||||||
|
markup.append(
|
||||||
" <sa1>\n"
|
" <sa1>\n"
|
||||||
" <mcu>\n"
|
" <mcu>\n"
|
||||||
" <rom>\n"
|
" <rom>\n"
|
||||||
|
@ -294,11 +294,11 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
" <map mode='direct' address='80-bf:6000-7fff'/>\n"
|
" <map mode='direct' address='80-bf:6000-7fff'/>\n"
|
||||||
" </ram>\n"
|
" </ram>\n"
|
||||||
" </mcu>\n"
|
" </mcu>\n"
|
||||||
" <iram size='0x800'>\n"
|
" <iram >\n"
|
||||||
" <map mode='linear' address='00-3f:3000-37ff'/>\n"
|
" <map mode='linear' address='00-3f:3000-37ff'/>\n"
|
||||||
" <map mode='linear' address='80-bf:3000-37ff'/>\n"
|
" <map mode='linear' address='80-bf:3000-37ff'/>\n"
|
||||||
" </iram>\n"
|
" </iram>\n"
|
||||||
" <bwram size='0x", hex(ram_size), "'>\n"
|
" <bwram>\n"
|
||||||
" <map mode='linear' address='40-4f:0000-ffff'/>\n"
|
" <map mode='linear' address='40-4f:0000-ffff'/>\n"
|
||||||
" </bwram>\n"
|
" </bwram>\n"
|
||||||
" <mmio>\n"
|
" <mmio>\n"
|
||||||
|
@ -307,15 +307,16 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
" </mmio>\n"
|
" </mmio>\n"
|
||||||
" </sa1>\n"
|
" </sa1>\n"
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
else if(mapper == BSCLoROM) markup.append(
|
else if(mapper == BSCLoROM) markup.append(
|
||||||
" <rom>\n"
|
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
|
||||||
" <map mode='linear' address='00-1f:8000-ffff' offset='0x000000'/>\n"
|
" <map mode='linear' address='00-1f:8000-ffff' offset='0x000000'/>\n"
|
||||||
" <map mode='linear' address='20-3f:8000-ffff' offset='0x100000'/>\n"
|
" <map mode='linear' address='20-3f:8000-ffff' offset='0x100000'/>\n"
|
||||||
" <map mode='linear' address='80-9f:8000-ffff' offset='0x200000'/>\n"
|
" <map mode='linear' address='80-9f:8000-ffff' offset='0x200000'/>\n"
|
||||||
" <map mode='linear' address='a0-bf:8000-ffff' offset='0x100000'/>\n"
|
" <map mode='linear' address='a0-bf:8000-ffff' offset='0x100000'/>\n"
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
" <ram size='0x", hex(ram_size), "'>\n"
|
" <ram name='save.ram' size='0x", hex(ram_size), "'>\n"
|
||||||
" <map mode='linear' address='70-7f:0000-7fff'/>\n"
|
" <map mode='linear' address='70-7f:0000-7fff'/>\n"
|
||||||
" <map mode='linear' address='f0-ff:0000-7fff'/>\n"
|
" <map mode='linear' address='f0-ff:0000-7fff'/>\n"
|
||||||
" </ram>\n"
|
" </ram>\n"
|
||||||
|
@ -327,13 +328,13 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
);
|
);
|
||||||
|
|
||||||
else if(mapper == BSCHiROM) markup.append(
|
else if(mapper == BSCHiROM) markup.append(
|
||||||
" <rom>\n"
|
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
|
||||||
" <map mode='shadow' address='00-1f:8000-ffff'/>\n"
|
" <map mode='shadow' address='00-1f:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='40-5f:0000-ffff'/>\n"
|
" <map mode='linear' address='40-5f:0000-ffff'/>\n"
|
||||||
" <map mode='shadow' address='80-9f:8000-ffff'/>\n"
|
" <map mode='shadow' address='80-9f:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='c0-df:0000-ffff'/>\n"
|
" <map mode='linear' address='c0-df:0000-ffff'/>\n"
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
" <ram size='0x", hex(ram_size), "'>\n"
|
" <ram name='save.ram' size='0x", hex(ram_size), "'>\n"
|
||||||
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
||||||
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
||||||
" </ram>\n"
|
" </ram>\n"
|
||||||
|
@ -348,6 +349,9 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
);
|
);
|
||||||
|
|
||||||
else if(mapper == BSXROM) markup.append(
|
else if(mapper == BSXROM) markup.append(
|
||||||
|
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
|
||||||
|
" <ram name='save.ram' size='0x", hex(ram_size), "'/>\n"
|
||||||
|
" <psram name='bsx.ram' size='0x40000'/>\n"
|
||||||
" <bsx>\n"
|
" <bsx>\n"
|
||||||
" <mcu>\n"
|
" <mcu>\n"
|
||||||
" <map address='00-3f:8000-ffff'/>\n"
|
" <map address='00-3f:8000-ffff'/>\n"
|
||||||
|
@ -364,7 +368,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
);
|
);
|
||||||
|
|
||||||
else if(mapper == STROM) markup.append(
|
else if(mapper == STROM) markup.append(
|
||||||
" <rom>\n"
|
" <rom name='program.rom' size='0x", hex(rom_size), "'>\n"
|
||||||
" <map mode='linear' address='00-1f:8000-ffff'/>\n"
|
" <map mode='linear' address='00-1f:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='80-9f:8000-ffff'/>\n"
|
" <map mode='linear' address='80-9f:8000-ffff'/>\n"
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
|
@ -374,7 +378,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
" <map mode='linear' address='20-3f:8000-ffff'/>\n"
|
" <map mode='linear' address='20-3f:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='a0-bf:8000-ffff'/>\n"
|
" <map mode='linear' address='a0-bf:8000-ffff'/>\n"
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
" <ram size='0x20000'>\n"
|
" <ram>\n"
|
||||||
" <map mode='linear' address='60-63:8000-ffff'/>\n"
|
" <map mode='linear' address='60-63:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='e0-e3:8000-ffff'/>\n"
|
" <map mode='linear' address='e0-e3:8000-ffff'/>\n"
|
||||||
" </ram>\n"
|
" </ram>\n"
|
||||||
|
@ -384,7 +388,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
" <map mode='linear' address='40-5f:8000-ffff'/>\n"
|
" <map mode='linear' address='40-5f:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='c0-df:8000-ffff'/>\n"
|
" <map mode='linear' address='c0-df:8000-ffff'/>\n"
|
||||||
" </rom>\n"
|
" </rom>\n"
|
||||||
" <ram size='0x20000'>\n"
|
" <ram>\n"
|
||||||
" <map mode='linear' address='70-73:8000-ffff'/>\n"
|
" <map mode='linear' address='70-73:8000-ffff'/>\n"
|
||||||
" <map mode='linear' address='f0-f3:8000-ffff'/>\n"
|
" <map mode='linear' address='f0-f3:8000-ffff'/>\n"
|
||||||
" </ram>\n"
|
" </ram>\n"
|
||||||
|
@ -393,10 +397,10 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
);
|
);
|
||||||
|
|
||||||
if(has_srtc) markup.append(
|
if(has_srtc) markup.append(
|
||||||
" <srtc>\n"
|
" <sharprtc name='rtc.ram' size='0x10'>\n"
|
||||||
" <map address='00-3f:2800-2801'/>\n"
|
" <map address='00-3f:2800-2801'/>\n"
|
||||||
" <map address='80-bf:2800-2801'/>\n"
|
" <map address='80-bf:2800-2801'/>\n"
|
||||||
" </srtc>\n"
|
" </sharprtc>\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
if(has_sdd1) markup.append(
|
if(has_sdd1) markup.append(
|
||||||
|
@ -535,6 +539,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
||||||
);
|
);
|
||||||
|
|
||||||
markup.append("</cartridge>\n");
|
markup.append("</cartridge>\n");
|
||||||
|
markup.transform("'", "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SuperFamicomCartridge::read_header(const uint8_t *data, unsigned size) {
|
void SuperFamicomCartridge::read_header(const uint8_t *data, unsigned size) {
|
||||||
|
@ -861,25 +866,6 @@ unsigned SuperFamicomCartridge::score_header(const uint8_t *data, unsigned size,
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned SuperFamicomCartridge::gameboy_ram_size(const uint8_t *data, unsigned size) {
|
|
||||||
if(size < 512) return 0;
|
|
||||||
switch(data[0x0149]) {
|
|
||||||
case 0x00: return 0 * 1024;
|
|
||||||
case 0x01: return 8 * 1024;
|
|
||||||
case 0x02: return 8 * 1024;
|
|
||||||
case 0x03: return 32 * 1024;
|
|
||||||
case 0x04: return 128 * 1024;
|
|
||||||
case 0x05: return 128 * 1024;
|
|
||||||
default: return 128 * 1024;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SuperFamicomCartridge::gameboy_has_rtc(const uint8_t *data, unsigned size) {
|
|
||||||
if(size < 512) return false;
|
|
||||||
if(data[0x0147] == 0x0f ||data[0x0147] == 0x10) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -6,6 +6,7 @@
|
||||||
#include <nall/string.hpp>
|
#include <nall/string.hpp>
|
||||||
#include <nall/utility.hpp>
|
#include <nall/utility.hpp>
|
||||||
#include <nall/windows/utf8.hpp>
|
#include <nall/windows/utf8.hpp>
|
||||||
|
#include <nall/stream/memory.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
inline FILE* fopen_utf8(const string &utf8_filename, const char *mode) {
|
inline FILE* fopen_utf8(const string &utf8_filename, const char *mode) {
|
||||||
|
@ -16,25 +17,53 @@ namespace nall {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
class file {
|
struct file {
|
||||||
public:
|
enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append };
|
||||||
enum class mode : unsigned { read, write, readwrite, writeread };
|
|
||||||
enum class index : unsigned { absolute, relative };
|
enum class index : unsigned { absolute, relative };
|
||||||
enum class time : unsigned { create, modify, access };
|
enum class time : unsigned { create, modify, access };
|
||||||
|
|
||||||
static bool read(const string &filename, uint8_t *&data, unsigned &size) {
|
static bool copy(const string &sourcename, const string &targetname) {
|
||||||
data = 0;
|
file rd, wr;
|
||||||
file fp;
|
if(rd.open(sourcename, mode::read) == false) return false;
|
||||||
if(fp.open(filename, mode::read) == false) return false;
|
if(wr.open(targetname, mode::write) == false) return false;
|
||||||
size = fp.size();
|
for(unsigned n = 0; n < rd.size(); n++) wr.write(rd.read());
|
||||||
data = new uint8_t[size];
|
|
||||||
fp.read(data, size);
|
|
||||||
fp.close();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool read(const string &filename, const uint8_t *&data, unsigned &size) {
|
static bool move(const string &sourcename, const string &targetname) {
|
||||||
return file::read(filename, (uint8_t*&)data, size);
|
#if !defined(_WIN32)
|
||||||
|
return rename(sourcename, targetname) == 0;
|
||||||
|
#else
|
||||||
|
return _wrename(utf16_t(sourcename), utf16_t(targetname)) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool remove(const string &filename) {
|
||||||
|
return unlink(filename) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool truncate(const string &filename, unsigned size) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
return truncate(filename, size) == 0;
|
||||||
|
#else
|
||||||
|
bool result = false;
|
||||||
|
FILE *fp = fopen(filename, "rb+");
|
||||||
|
if(fp) {
|
||||||
|
result = _chsize(fileno(fp), size) == 0;
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector<uint8_t> read(const string &filename) {
|
||||||
|
vector<uint8_t> memory;
|
||||||
|
file fp;
|
||||||
|
if(fp.open(filename, mode::read)) {
|
||||||
|
memory.resize(fp.size());
|
||||||
|
fp.read(memory.data(), memory.size());
|
||||||
|
}
|
||||||
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool write(const string &filename, const uint8_t *data, unsigned size) {
|
static bool write(const string &filename, const uint8_t *data, unsigned size) {
|
||||||
|
@ -134,13 +163,13 @@ namespace nall {
|
||||||
file_offset = req_offset;
|
file_offset = req_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset() const {
|
unsigned offset() const {
|
||||||
if(!fp) return -1; //file not open
|
if(!fp) return 0; //file not open
|
||||||
return file_offset;
|
return file_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int size() const {
|
unsigned size() const {
|
||||||
if(!fp) return -1; //file not open
|
if(!fp) return 0; //file not open
|
||||||
return file_size;
|
return file_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +261,7 @@ namespace nall {
|
||||||
|
|
||||||
file() {
|
file() {
|
||||||
memset(buffer, 0, sizeof buffer);
|
memset(buffer, 0, sizeof buffer);
|
||||||
buffer_offset = -1;
|
buffer_offset = -1; //invalidate buffer
|
||||||
buffer_dirty = false;
|
buffer_dirty = false;
|
||||||
fp = 0;
|
fp = 0;
|
||||||
file_offset = 0;
|
file_offset = 0;
|
||||||
|
|
|
@ -19,12 +19,10 @@ struct gzip {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool gzip::decompress(const string &filename) {
|
bool gzip::decompress(const string &filename) {
|
||||||
uint8_t *data;
|
if(auto memory = file::read(filename)) {
|
||||||
unsigned size;
|
return decompress(memory.data(), memory.size());
|
||||||
if(file::read(filename, data, size) == false) return false;
|
}
|
||||||
bool result = decompress(data, size);
|
return false;
|
||||||
delete[] data;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gzip::decompress(const uint8_t *data, unsigned size) {
|
bool gzip::decompress(const uint8_t *data, unsigned size) {
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#else
|
#else
|
||||||
#include <windows.h>
|
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <nall/platform.hpp>
|
#include <nall/platform.hpp>
|
||||||
|
|
|
@ -36,6 +36,8 @@ struct image {
|
||||||
inline image(const image &source);
|
inline image(const image &source);
|
||||||
inline image(image &&source);
|
inline image(image &&source);
|
||||||
inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
|
inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
|
||||||
|
inline image(const string &filename);
|
||||||
|
inline image(const uint8_t *data, unsigned size);
|
||||||
inline image();
|
inline image();
|
||||||
inline ~image();
|
inline ~image();
|
||||||
|
|
||||||
|
@ -43,6 +45,7 @@ struct image {
|
||||||
inline void write(uint8_t *data, uint64_t value) const;
|
inline void write(uint8_t *data, uint64_t value) const;
|
||||||
|
|
||||||
inline void free();
|
inline void free();
|
||||||
|
inline bool empty() const;
|
||||||
inline void allocate(unsigned width, unsigned height);
|
inline void allocate(unsigned width, unsigned height);
|
||||||
inline void clear(uint64_t color);
|
inline void clear(uint64_t color);
|
||||||
inline bool load(const string &filename);
|
inline bool load(const string &filename);
|
||||||
|
@ -146,6 +149,38 @@ image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask,
|
||||||
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
image::image(const string &filename) : data(nullptr) {
|
||||||
|
width = 0, height = 0, pitch = 0;
|
||||||
|
|
||||||
|
this->endian = 0;
|
||||||
|
this->depth = 32;
|
||||||
|
this->stride = 4;
|
||||||
|
|
||||||
|
alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0;
|
||||||
|
alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
|
||||||
|
red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
|
||||||
|
green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
|
||||||
|
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
||||||
|
|
||||||
|
load(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
image::image(const uint8_t *data, unsigned size) : data(nullptr) {
|
||||||
|
width = 0, height = 0, pitch = 0;
|
||||||
|
|
||||||
|
this->endian = 0;
|
||||||
|
this->depth = 32;
|
||||||
|
this->stride = 4;
|
||||||
|
|
||||||
|
alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0;
|
||||||
|
alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
|
||||||
|
red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
|
||||||
|
green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
|
||||||
|
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
||||||
|
|
||||||
|
loadPNG(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
image::image() : data(nullptr) {
|
image::image() : data(nullptr) {
|
||||||
width = 0, height = 0, pitch = 0;
|
width = 0, height = 0, pitch = 0;
|
||||||
|
|
||||||
|
@ -187,6 +222,12 @@ void image::free() {
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool image::empty() const {
|
||||||
|
if(data == nullptr) return true;
|
||||||
|
if(width == 0 || height == 0) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void image::allocate(unsigned width, unsigned height) {
|
void image::allocate(unsigned width, unsigned height) {
|
||||||
if(data != nullptr && this->width == width && this->height == height) return;
|
if(data != nullptr && this->width == width && this->height == height) return;
|
||||||
free();
|
free();
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef NALL_INVOKE_HPP
|
||||||
|
#define NALL_INVOKE_HPP
|
||||||
|
|
||||||
|
//void invoke(const string &name, const string& args...);
|
||||||
|
//if a program is specified, it is executed with the arguments provided
|
||||||
|
//if a file is specified, the file is opened using the program associated with said file type
|
||||||
|
//if a folder is specified, the folder is opened using the associated file explorer
|
||||||
|
//if a URL is specified, the default web browser is opened and pointed at the URL requested
|
||||||
|
//path environment variable is always consulted
|
||||||
|
//execution is asynchronous (non-blocking); use system() for synchronous execution
|
||||||
|
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <nall/windows/utf8.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
inline void invoke(const string &name, Args&&... args) {
|
||||||
|
lstring argl(std::forward<Args>(args)...);
|
||||||
|
for(auto &arg : argl) if(arg.position(" ")) arg = {"\"", arg, "\""};
|
||||||
|
string arguments = argl.concatenate(" ");
|
||||||
|
ShellExecuteW(NULL, NULL, utf16_t(name), utf16_t(arguments), NULL, SW_SHOWNORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
inline void invoke(const string &name, Args&&... args) {
|
||||||
|
pid_t pid = fork();
|
||||||
|
if(pid == 0) {
|
||||||
|
const char *argv[1 + sizeof...(args) + 1], **argp = argv;
|
||||||
|
lstring argl(std::forward<Args>(args)...);
|
||||||
|
*argp++ = (const char*)name;
|
||||||
|
for(auto &arg : argl) *argp++ = (const char*)arg;
|
||||||
|
*argp++ = nullptr;
|
||||||
|
|
||||||
|
if(execvp(name, (char* const*)argv) < 0) {
|
||||||
|
execlp("xdg-open", "xdg-open", (const char*)name, nullptr);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -11,8 +11,6 @@ struct ips {
|
||||||
inline bool apply();
|
inline bool apply();
|
||||||
inline void source(const uint8_t *data, unsigned size);
|
inline void source(const uint8_t *data, unsigned size);
|
||||||
inline void modify(const uint8_t *data, unsigned size);
|
inline void modify(const uint8_t *data, unsigned size);
|
||||||
inline bool source(const string &filename);
|
|
||||||
inline bool modify(const string &filename);
|
|
||||||
inline ips();
|
inline ips();
|
||||||
inline ~ips();
|
inline ~ips();
|
||||||
|
|
||||||
|
@ -88,14 +86,6 @@ void ips::modify(const uint8_t *data, unsigned size) {
|
||||||
modifyData = data, modifySize = size;
|
modifyData = data, modifySize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ips::source(const string &filename) {
|
|
||||||
return file::read(filename, sourceData, sourceSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ips::modify(const string &filename) {
|
|
||||||
return file::read(filename, modifyData, modifySize);
|
|
||||||
}
|
|
||||||
|
|
||||||
ips::ips() : data(nullptr), sourceData(nullptr), modifyData(nullptr) {
|
ips::ips() : data(nullptr), sourceData(nullptr), modifyData(nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct map {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline RHS& operator()(const LHS &name) {
|
inline RHS& operator()(const LHS &name) {
|
||||||
|
if(auto position = find(name)) return list[position()].data;
|
||||||
return insert(name, RHS());
|
return insert(name, RHS());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
#ifndef NALL_MODULO_HPP
|
|
||||||
#define NALL_MODULO_HPP
|
|
||||||
|
|
||||||
#include <nall/serializer.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
template<typename T, int size> class modulo_array {
|
|
||||||
public:
|
|
||||||
inline T operator[](int index) const {
|
|
||||||
return buffer[size + index];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline T read(int index) const {
|
|
||||||
return buffer[size + index];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void write(unsigned index, const T value) {
|
|
||||||
buffer[index] =
|
|
||||||
buffer[index + size] =
|
|
||||||
buffer[index + size + size] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serialize(serializer &s) {
|
|
||||||
s.array(buffer, size * 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
modulo_array() {
|
|
||||||
buffer = new T[size * 3]();
|
|
||||||
}
|
|
||||||
|
|
||||||
~modulo_array() {
|
|
||||||
delete[] buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T *buffer;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -17,24 +17,24 @@ struct context {
|
||||||
unsigned blockHeight;
|
unsigned blockHeight;
|
||||||
unsigned blockStride;
|
unsigned blockStride;
|
||||||
unsigned blockOffset;
|
unsigned blockOffset;
|
||||||
array<unsigned> block;
|
vector<unsigned> block;
|
||||||
|
|
||||||
unsigned tileWidth;
|
unsigned tileWidth;
|
||||||
unsigned tileHeight;
|
unsigned tileHeight;
|
||||||
unsigned tileStride;
|
unsigned tileStride;
|
||||||
unsigned tileOffset;
|
unsigned tileOffset;
|
||||||
array<unsigned> tile;
|
vector<unsigned> tile;
|
||||||
|
|
||||||
unsigned mosaicWidth;
|
unsigned mosaicWidth;
|
||||||
unsigned mosaicHeight;
|
unsigned mosaicHeight;
|
||||||
unsigned mosaicStride;
|
unsigned mosaicStride;
|
||||||
unsigned mosaicOffset;
|
unsigned mosaicOffset;
|
||||||
array<unsigned> mosaic;
|
vector<unsigned> mosaic;
|
||||||
|
|
||||||
unsigned paddingWidth;
|
unsigned paddingWidth;
|
||||||
unsigned paddingHeight;
|
unsigned paddingHeight;
|
||||||
unsigned paddingColor;
|
unsigned paddingColor;
|
||||||
array<unsigned> palette;
|
vector<unsigned> palette;
|
||||||
|
|
||||||
inline unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; }
|
inline unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; }
|
||||||
inline unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; }
|
inline unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; }
|
||||||
|
@ -52,7 +52,7 @@ struct context {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void eval(array<unsigned> &buffer, const string &expression_) {
|
inline void eval(vector<unsigned> &buffer, const string &expression_) {
|
||||||
string expression = expression_;
|
string expression = expression_;
|
||||||
bool function = false;
|
bool function = false;
|
||||||
for(auto &c : expression) {
|
for(auto &c : expression) {
|
||||||
|
|
|
@ -60,10 +60,7 @@
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define getcwd _getcwd
|
#define getcwd _getcwd
|
||||||
#define ftruncate _chsize
|
|
||||||
#define mkdir(n, m) _wmkdir(nall::utf16_t(n))
|
|
||||||
#define putenv _putenv
|
#define putenv _putenv
|
||||||
#define rmdir _rmdir
|
|
||||||
#define vsnprintf _vsnprintf
|
#define vsnprintf _vsnprintf
|
||||||
inline void usleep(unsigned milliseconds) { Sleep(milliseconds / 1000); }
|
inline void usleep(unsigned milliseconds) { Sleep(milliseconds / 1000); }
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,57 +83,4 @@
|
||||||
#define alwaysinline inline
|
#define alwaysinline inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//=========================
|
|
||||||
//file system functionality
|
|
||||||
//=========================
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
inline char* realpath(const char *filename, char *resolvedname) {
|
|
||||||
wchar_t fn[_MAX_PATH] = L"";
|
|
||||||
_wfullpath(fn, nall::utf16_t(filename), _MAX_PATH);
|
|
||||||
strcpy(resolvedname, nall::utf8_t(fn));
|
|
||||||
for(unsigned n = 0; resolvedname[n]; n++) if(resolvedname[n] == '\\') resolvedname[n] = '/';
|
|
||||||
return resolvedname;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline char* userpath(char *path) {
|
|
||||||
wchar_t fp[_MAX_PATH] = L"";
|
|
||||||
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp);
|
|
||||||
strcpy(path, nall::utf8_t(fp));
|
|
||||||
for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/';
|
|
||||||
unsigned length = strlen(path);
|
|
||||||
if(path[length] != '/') strcpy(path + length, "/");
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline char* getcwd(char *path) {
|
|
||||||
wchar_t fp[_MAX_PATH] = L"";
|
|
||||||
_wgetcwd(fp, _MAX_PATH);
|
|
||||||
strcpy(path, nall::utf8_t(fp));
|
|
||||||
for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/';
|
|
||||||
unsigned length = strlen(path);
|
|
||||||
if(path[length] != '/') strcpy(path + length, "/");
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
//realpath() already exists
|
|
||||||
|
|
||||||
inline char* userpath(char *path) {
|
|
||||||
*path = 0;
|
|
||||||
struct passwd *userinfo = getpwuid(getuid());
|
|
||||||
if(userinfo) strcpy(path, userinfo->pw_dir);
|
|
||||||
unsigned length = strlen(path);
|
|
||||||
if(path[length] != '/') strcpy(path + length, "/");
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline char *getcwd(char *path) {
|
|
||||||
auto unused = getcwd(path, PATH_MAX);
|
|
||||||
unsigned length = strlen(path);
|
|
||||||
if(path[length] != '/') strcpy(path + length, "/");
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
|
@ -58,12 +58,10 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
bool png::decode(const string &filename) {
|
bool png::decode(const string &filename) {
|
||||||
uint8_t *data;
|
if(auto memory = file::read(filename)) {
|
||||||
unsigned size;
|
return decode(memory.data(), memory.size());
|
||||||
if(file::read(filename, data, size) == false) return false;
|
}
|
||||||
bool result = decode(data, size);
|
return false;
|
||||||
delete[] data;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool png::decode(const uint8_t *sourceData, unsigned sourceSize) {
|
bool png::decode(const uint8_t *sourceData, unsigned sourceSize) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef NALL_PRIORITYQUEUE_HPP
|
#ifndef NALL_PRIORITY_QUEUE_HPP
|
||||||
#define NALL_PRIORITYQUEUE_HPP
|
#define NALL_PRIORITY_QUEUE_HPP
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
|
@ -1,109 +0,0 @@
|
||||||
#ifndef NALL_PRIORITYQUEUE_HPP
|
|
||||||
#define NALL_PRIORITYQUEUE_HPP
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <nall/function.hpp>
|
|
||||||
#include <nall/serializer.hpp>
|
|
||||||
#include <nall/utility.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
template<typename type_t> void priority_queue_nocallback(type_t) {}
|
|
||||||
|
|
||||||
//priority queue implementation using binary min-heap array;
|
|
||||||
//does not require normalize() function.
|
|
||||||
//O(1) find (tick)
|
|
||||||
//O(log n) append (enqueue)
|
|
||||||
//O(log n) remove (dequeue)
|
|
||||||
template<typename type_t> class priority_queue {
|
|
||||||
public:
|
|
||||||
inline void tick(unsigned ticks) {
|
|
||||||
basecounter += ticks;
|
|
||||||
while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue());
|
|
||||||
}
|
|
||||||
|
|
||||||
//counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks);
|
|
||||||
//counter cannot exceed std::numeric_limits<unsigned>::max() >> 1.
|
|
||||||
void enqueue(unsigned counter, type_t event) {
|
|
||||||
unsigned child = heapsize++;
|
|
||||||
counter += basecounter;
|
|
||||||
|
|
||||||
while(child) {
|
|
||||||
unsigned parent = (child - 1) >> 1;
|
|
||||||
if(gte(counter, heap[parent].counter)) break;
|
|
||||||
|
|
||||||
heap[child].counter = heap[parent].counter;
|
|
||||||
heap[child].event = heap[parent].event;
|
|
||||||
child = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
heap[child].counter = counter;
|
|
||||||
heap[child].event = event;
|
|
||||||
}
|
|
||||||
|
|
||||||
type_t dequeue() {
|
|
||||||
type_t event(heap[0].event);
|
|
||||||
unsigned parent = 0;
|
|
||||||
unsigned counter = heap[--heapsize].counter;
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
unsigned child = (parent << 1) + 1;
|
|
||||||
if(child >= heapsize) break;
|
|
||||||
if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++;
|
|
||||||
if(gte(heap[child].counter, counter)) break;
|
|
||||||
|
|
||||||
heap[parent].counter = heap[child].counter;
|
|
||||||
heap[parent].event = heap[child].event;
|
|
||||||
parent = child;
|
|
||||||
}
|
|
||||||
|
|
||||||
heap[parent].counter = counter;
|
|
||||||
heap[parent].event = heap[heapsize].event;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
basecounter = 0;
|
|
||||||
heapsize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serialize(serializer &s) {
|
|
||||||
s.integer(basecounter);
|
|
||||||
s.integer(heapsize);
|
|
||||||
for(unsigned n = 0; n < heapcapacity; n++) {
|
|
||||||
s.integer(heap[n].counter);
|
|
||||||
s.integer(heap[n].event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
priority_queue(unsigned size, function<void (type_t)> callback_ = &priority_queue_nocallback<type_t>)
|
|
||||||
: callback(callback_) {
|
|
||||||
heap = new heap_t[size];
|
|
||||||
heapcapacity = size;
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
~priority_queue() {
|
|
||||||
delete[] heap;
|
|
||||||
}
|
|
||||||
|
|
||||||
priority_queue& operator=(const priority_queue&) = delete;
|
|
||||||
priority_queue(const priority_queue&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
function<void (type_t)> callback;
|
|
||||||
unsigned basecounter;
|
|
||||||
unsigned heapsize;
|
|
||||||
unsigned heapcapacity;
|
|
||||||
struct heap_t {
|
|
||||||
unsigned counter;
|
|
||||||
type_t event;
|
|
||||||
} *heap;
|
|
||||||
|
|
||||||
//return true if x is greater than or equal to y
|
|
||||||
inline bool gte(unsigned x, unsigned y) {
|
|
||||||
return x - y < (std::numeric_limits<unsigned>::max() >> 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,142 +0,0 @@
|
||||||
#ifndef NALL_REFERENCE_ARRAY_HPP
|
|
||||||
#define NALL_REFERENCE_ARRAY_HPP
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <nall/bit.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
template<typename T> struct reference_array {
|
|
||||||
struct exception_out_of_bounds{};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
typedef typename std::remove_reference<T>::type type_t;
|
|
||||||
type_t **pool;
|
|
||||||
unsigned poolsize, buffersize;
|
|
||||||
|
|
||||||
public:
|
|
||||||
unsigned size() const { return buffersize; }
|
|
||||||
unsigned capacity() const { return poolsize; }
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
if(pool) free(pool);
|
|
||||||
pool = nullptr;
|
|
||||||
poolsize = 0;
|
|
||||||
buffersize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reserve(unsigned newsize) {
|
|
||||||
if(newsize == poolsize) return;
|
|
||||||
|
|
||||||
pool = (type_t**)realloc(pool, sizeof(type_t*) * newsize);
|
|
||||||
poolsize = newsize;
|
|
||||||
buffersize = min(buffersize, newsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(unsigned newsize) {
|
|
||||||
if(newsize > poolsize) reserve(bit::round(newsize));
|
|
||||||
buffersize = newsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
bool append(type_t& data, Args&&... args) {
|
|
||||||
bool result = append(data);
|
|
||||||
append(std::forward<Args>(args)...);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool append(type_t& data) {
|
|
||||||
for(unsigned index = 0; index < buffersize; index++) {
|
|
||||||
if(pool[index] == &data) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned index = buffersize++;
|
|
||||||
if(index >= poolsize) resize(index + 1);
|
|
||||||
pool[index] = &data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool remove(type_t& data) {
|
|
||||||
for(unsigned index = 0; index < buffersize; index++) {
|
|
||||||
if(pool[index] == &data) {
|
|
||||||
for(unsigned i = index; i < buffersize - 1; i++) pool[i] = pool[i + 1];
|
|
||||||
resize(buffersize - 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args> reference_array(Args&... args) : pool(nullptr), poolsize(0), buffersize(0) {
|
|
||||||
construct(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
~reference_array() {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
reference_array& operator=(const reference_array &source) {
|
|
||||||
if(pool) free(pool);
|
|
||||||
buffersize = source.buffersize;
|
|
||||||
poolsize = source.poolsize;
|
|
||||||
pool = (type_t**)malloc(sizeof(type_t*) * poolsize);
|
|
||||||
memcpy(pool, source.pool, sizeof(type_t*) * buffersize);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
reference_array& operator=(const reference_array &&source) {
|
|
||||||
if(pool) free(pool);
|
|
||||||
pool = source.pool;
|
|
||||||
poolsize = source.poolsize;
|
|
||||||
buffersize = source.buffersize;
|
|
||||||
source.pool = nullptr;
|
|
||||||
source.reset();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline type_t& operator[](unsigned index) {
|
|
||||||
if(index >= buffersize) throw exception_out_of_bounds();
|
|
||||||
return *pool[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline type_t& operator[](unsigned index) const {
|
|
||||||
if(index >= buffersize) throw exception_out_of_bounds();
|
|
||||||
return *pool[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
//iteration
|
|
||||||
struct iterator {
|
|
||||||
bool operator!=(const iterator &source) const { return index != source.index; }
|
|
||||||
type_t& operator*() { return array.operator[](index); }
|
|
||||||
iterator& operator++() { index++; return *this; }
|
|
||||||
iterator(const reference_array &array, unsigned index) : array(array), index(index) {}
|
|
||||||
private:
|
|
||||||
const reference_array &array;
|
|
||||||
unsigned index;
|
|
||||||
};
|
|
||||||
|
|
||||||
iterator begin() { return iterator(*this, 0); }
|
|
||||||
iterator end() { return iterator(*this, buffersize); }
|
|
||||||
const iterator begin() const { return iterator(*this, 0); }
|
|
||||||
const iterator end() const { return iterator(*this, buffersize); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void construct() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void construct(const reference_array &source) {
|
|
||||||
operator=(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
void construct(const reference_array &&source) {
|
|
||||||
operator=(std::move(source));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args> void construct(T data, Args&... args) {
|
|
||||||
append(data);
|
|
||||||
construct(args...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
#ifndef NALL_SET_HPP
|
||||||
|
#define NALL_SET_HPP
|
||||||
|
|
||||||
|
//set
|
||||||
|
//* unordered
|
||||||
|
//* intended for unique items
|
||||||
|
//* dynamic growth
|
||||||
|
//* reference-based variant
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <utility>
|
||||||
|
#include <nall/algorithm.hpp>
|
||||||
|
#include <nall/bit.hpp>
|
||||||
|
#include <nall/sort.hpp>
|
||||||
|
#include <nall/traits.hpp>
|
||||||
|
#include <nall/utility.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
template<typename T, typename Enable = void> struct set;
|
||||||
|
|
||||||
|
template<typename T> struct set<T, typename std::enable_if<!std::is_reference<T>::value>::type> {
|
||||||
|
struct exception_out_of_bounds{};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
T *pool;
|
||||||
|
unsigned poolsize, objectsize;
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned size() const { return objectsize; }
|
||||||
|
unsigned capacity() const { return poolsize; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//reference set
|
||||||
|
template<typename TR> struct set<TR, typename std::enable_if<std::is_reference<TR>::value>::type> {
|
||||||
|
struct exception_out_of_bounds{};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef typename std::remove_reference<TR>::type T;
|
||||||
|
T **pool;
|
||||||
|
unsigned poolsize, objectsize;
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned size() const { return objectsize; }
|
||||||
|
unsigned capacity() const { return poolsize; }
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
if(pool) free(pool);
|
||||||
|
pool = nullptr;
|
||||||
|
poolsize = 0;
|
||||||
|
objectsize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(unsigned size) {
|
||||||
|
if(size == poolsize) return;
|
||||||
|
pool = (T**)realloc(pool, sizeof(T*) * size);
|
||||||
|
poolsize = size;
|
||||||
|
objectsize = min(objectsize, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(unsigned size) {
|
||||||
|
if(size > poolsize) reserve(bit::round(size)); //amortize growth
|
||||||
|
objectsize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool append(T& data) {
|
||||||
|
if(find(data)) return false;
|
||||||
|
unsigned offset = objectsize++;
|
||||||
|
if(offset >= poolsize) resize(offset + 1);
|
||||||
|
pool[offset] = &data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
bool append(T& data, Args&&... args) {
|
||||||
|
bool result = append(data);
|
||||||
|
append(std::forward<Args>(args)...);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove(T& data) {
|
||||||
|
if(auto position = find(data)) {
|
||||||
|
for(signed i = position(); i < objectsize - 1; i++) pool[i] = pool[i + 1];
|
||||||
|
resize(objectsize - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<unsigned> find(const T& data) {
|
||||||
|
for(unsigned n = 0; n < objectsize; n++) if(pool[n] == &data) return {true, n};
|
||||||
|
return {false, 0u};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args> set(Args&&... args) : pool(nullptr), poolsize(0), objectsize(0) {
|
||||||
|
construct(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
~set() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
set& operator=(const set &source) {
|
||||||
|
if(&source == this) return *this;
|
||||||
|
if(pool) free(pool);
|
||||||
|
objectsize = source.objectsize;
|
||||||
|
poolsize = source.poolsize;
|
||||||
|
pool = (T**)malloc(sizeof(T*) * poolsize);
|
||||||
|
memcpy(pool, source.pool, sizeof(T*) * objectsize);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
set& operator=(const set &&source) {
|
||||||
|
if(&source == this) return *this;
|
||||||
|
if(pool) free(pool);
|
||||||
|
pool = source.pool;
|
||||||
|
poolsize = source.poolsize;
|
||||||
|
objectsize = source.objectsize;
|
||||||
|
source.pool = nullptr;
|
||||||
|
source.reset();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[](unsigned position) const {
|
||||||
|
if(position >= objectsize) throw exception_out_of_bounds();
|
||||||
|
return *pool[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iterator {
|
||||||
|
bool operator!=(const iterator &source) const { return position != source.position; }
|
||||||
|
T& operator*() { return source.operator[](position); }
|
||||||
|
iterator& operator++() { position++; return *this; }
|
||||||
|
iterator(const set &source, unsigned position) : source(source), position(position) {}
|
||||||
|
private:
|
||||||
|
const set &source;
|
||||||
|
unsigned position;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator begin() { return iterator(*this, 0); }
|
||||||
|
iterator end() { return iterator(*this, objectsize); }
|
||||||
|
const iterator begin() const { return iterator(*this, 0); }
|
||||||
|
const iterator end() const { return iterator(*this, objectsize); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void construct() {}
|
||||||
|
void construct(const set &source) { operator=(source); }
|
||||||
|
void construct(const set &&source) { operator=(std::move(source)); }
|
||||||
|
template<typename... Args> void construct(T& data, Args&&... args) {
|
||||||
|
append(data);
|
||||||
|
construct(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,458 +0,0 @@
|
||||||
#ifndef NALL_SNES_CPU_HPP
|
|
||||||
#define NALL_SNES_CPU_HPP
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
struct SNESCPU {
|
|
||||||
enum : unsigned {
|
|
||||||
Implied, //
|
|
||||||
Constant, //#$00
|
|
||||||
AccumConstant, //#$00
|
|
||||||
IndexConstant, //#$00
|
|
||||||
Direct, //$00
|
|
||||||
DirectX, //$00,x
|
|
||||||
DirectY, //$00,y
|
|
||||||
IDirect, //($00)
|
|
||||||
IDirectX, //($00,x)
|
|
||||||
IDirectY, //($00),y
|
|
||||||
ILDirect, //[$00]
|
|
||||||
ILDirectY, //[$00],y
|
|
||||||
Address, //$0000
|
|
||||||
AddressX, //$0000,x
|
|
||||||
AddressY, //$0000,y
|
|
||||||
IAddressX, //($0000,x)
|
|
||||||
ILAddress, //[$0000]
|
|
||||||
PAddress, //PBR:$0000
|
|
||||||
PIAddress, //PBR:($0000)
|
|
||||||
Long, //$000000
|
|
||||||
LongX, //$000000,x
|
|
||||||
Stack, //$00,s
|
|
||||||
IStackY, //($00,s),y
|
|
||||||
BlockMove, //$00,$00
|
|
||||||
RelativeShort, //+/- $00
|
|
||||||
RelativeLong, //+/- $0000
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OpcodeInfo {
|
|
||||||
char name[4];
|
|
||||||
unsigned mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const OpcodeInfo opcodeInfo[256];
|
|
||||||
|
|
||||||
static unsigned getOpcodeLength(bool accum, bool index, uint8_t opcode);
|
|
||||||
static string disassemble(unsigned pc, bool accum, bool index, uint8_t opcode, uint8_t pl, uint8_t ph, uint8_t pb);
|
|
||||||
};
|
|
||||||
|
|
||||||
const SNESCPU::OpcodeInfo SNESCPU::opcodeInfo[256] = {
|
|
||||||
//0x00 - 0x0f
|
|
||||||
{ "brk", Constant },
|
|
||||||
{ "ora", IDirectX },
|
|
||||||
{ "cop", Constant },
|
|
||||||
{ "ora", Stack },
|
|
||||||
|
|
||||||
{ "tsb", Direct },
|
|
||||||
{ "ora", Direct },
|
|
||||||
{ "asl", Direct },
|
|
||||||
{ "ora", ILDirect },
|
|
||||||
|
|
||||||
{ "php", Implied },
|
|
||||||
{ "ora", AccumConstant },
|
|
||||||
{ "asl", Implied },
|
|
||||||
{ "phd", Implied },
|
|
||||||
|
|
||||||
{ "tsb", Address },
|
|
||||||
{ "ora", Address },
|
|
||||||
{ "asl", Address },
|
|
||||||
{ "ora", Long },
|
|
||||||
|
|
||||||
//0x10 - 0x1f
|
|
||||||
{ "bpl", RelativeShort },
|
|
||||||
{ "ora", IDirectY },
|
|
||||||
{ "ora", IDirect },
|
|
||||||
{ "ora", IStackY },
|
|
||||||
|
|
||||||
{ "trb", Direct },
|
|
||||||
{ "ora", DirectX },
|
|
||||||
{ "asl", DirectX },
|
|
||||||
{ "ora", ILDirectY },
|
|
||||||
|
|
||||||
{ "clc", Implied },
|
|
||||||
{ "ora", AddressY },
|
|
||||||
{ "inc", Implied },
|
|
||||||
{ "tcs", Implied },
|
|
||||||
|
|
||||||
{ "trb", Address },
|
|
||||||
{ "ora", AddressX },
|
|
||||||
{ "asl", AddressX },
|
|
||||||
{ "ora", LongX },
|
|
||||||
|
|
||||||
//0x20 - 0x2f
|
|
||||||
{ "jsr", Address },
|
|
||||||
{ "and", IDirectX },
|
|
||||||
{ "jsl", Long },
|
|
||||||
{ "and", Stack },
|
|
||||||
|
|
||||||
{ "bit", Direct },
|
|
||||||
{ "and", Direct },
|
|
||||||
{ "rol", Direct },
|
|
||||||
{ "and", ILDirect },
|
|
||||||
|
|
||||||
{ "plp", Implied },
|
|
||||||
{ "and", AccumConstant },
|
|
||||||
{ "rol", Implied },
|
|
||||||
{ "pld", Implied },
|
|
||||||
|
|
||||||
{ "bit", Address },
|
|
||||||
{ "and", Address },
|
|
||||||
{ "rol", Address },
|
|
||||||
{ "and", Long },
|
|
||||||
|
|
||||||
//0x30 - 0x3f
|
|
||||||
{ "bmi", RelativeShort },
|
|
||||||
{ "and", IDirectY },
|
|
||||||
{ "and", IDirect },
|
|
||||||
{ "and", IStackY },
|
|
||||||
|
|
||||||
{ "bit", DirectX },
|
|
||||||
{ "and", DirectX },
|
|
||||||
{ "rol", DirectX },
|
|
||||||
{ "and", ILDirectY },
|
|
||||||
|
|
||||||
{ "sec", Implied },
|
|
||||||
{ "and", AddressY },
|
|
||||||
{ "dec", Implied },
|
|
||||||
{ "tsc", Implied },
|
|
||||||
|
|
||||||
{ "bit", AddressX },
|
|
||||||
{ "and", AddressX },
|
|
||||||
{ "rol", AddressX },
|
|
||||||
{ "and", LongX },
|
|
||||||
|
|
||||||
//0x40 - 0x4f
|
|
||||||
{ "rti", Implied },
|
|
||||||
{ "eor", IDirectX },
|
|
||||||
{ "wdm", Constant },
|
|
||||||
{ "eor", Stack },
|
|
||||||
|
|
||||||
{ "mvp", BlockMove },
|
|
||||||
{ "eor", Direct },
|
|
||||||
{ "lsr", Direct },
|
|
||||||
{ "eor", ILDirect },
|
|
||||||
|
|
||||||
{ "pha", Implied },
|
|
||||||
{ "eor", AccumConstant },
|
|
||||||
{ "lsr", Implied },
|
|
||||||
{ "phk", Implied },
|
|
||||||
|
|
||||||
{ "jmp", PAddress },
|
|
||||||
{ "eor", Address },
|
|
||||||
{ "lsr", Address },
|
|
||||||
{ "eor", Long },
|
|
||||||
|
|
||||||
//0x50 - 0x5f
|
|
||||||
{ "bvc", RelativeShort },
|
|
||||||
{ "eor", IDirectY },
|
|
||||||
{ "eor", IDirect },
|
|
||||||
{ "eor", IStackY },
|
|
||||||
|
|
||||||
{ "mvn", BlockMove },
|
|
||||||
{ "eor", DirectX },
|
|
||||||
{ "lsr", DirectX },
|
|
||||||
{ "eor", ILDirectY },
|
|
||||||
|
|
||||||
{ "cli", Implied },
|
|
||||||
{ "eor", AddressY },
|
|
||||||
{ "phy", Implied },
|
|
||||||
{ "tcd", Implied },
|
|
||||||
|
|
||||||
{ "jml", Long },
|
|
||||||
{ "eor", AddressX },
|
|
||||||
{ "lsr", AddressX },
|
|
||||||
{ "eor", LongX },
|
|
||||||
|
|
||||||
//0x60 - 0x6f
|
|
||||||
{ "rts", Implied },
|
|
||||||
{ "adc", IDirectX },
|
|
||||||
{ "per", Address },
|
|
||||||
{ "adc", Stack },
|
|
||||||
|
|
||||||
{ "stz", Direct },
|
|
||||||
{ "adc", Direct },
|
|
||||||
{ "ror", Direct },
|
|
||||||
{ "adc", ILDirect },
|
|
||||||
|
|
||||||
{ "pla", Implied },
|
|
||||||
{ "adc", AccumConstant },
|
|
||||||
{ "ror", Implied },
|
|
||||||
{ "rtl", Implied },
|
|
||||||
|
|
||||||
{ "jmp", PIAddress },
|
|
||||||
{ "adc", Address },
|
|
||||||
{ "ror", Address },
|
|
||||||
{ "adc", Long },
|
|
||||||
|
|
||||||
//0x70 - 0x7f
|
|
||||||
{ "bvs", RelativeShort },
|
|
||||||
{ "adc", IDirectY },
|
|
||||||
{ "adc", IDirect },
|
|
||||||
{ "adc", IStackY },
|
|
||||||
|
|
||||||
{ "stz", DirectX },
|
|
||||||
{ "adc", DirectX },
|
|
||||||
{ "ror", DirectX },
|
|
||||||
{ "adc", ILDirectY },
|
|
||||||
|
|
||||||
{ "sei", Implied },
|
|
||||||
{ "adc", AddressY },
|
|
||||||
{ "ply", Implied },
|
|
||||||
{ "tdc", Implied },
|
|
||||||
|
|
||||||
{ "jmp", IAddressX },
|
|
||||||
{ "adc", AddressX },
|
|
||||||
{ "ror", AddressX },
|
|
||||||
{ "adc", LongX },
|
|
||||||
|
|
||||||
//0x80 - 0x8f
|
|
||||||
{ "bra", RelativeShort },
|
|
||||||
{ "sta", IDirectX },
|
|
||||||
{ "brl", RelativeLong },
|
|
||||||
{ "sta", Stack },
|
|
||||||
|
|
||||||
{ "sty", Direct },
|
|
||||||
{ "sta", Direct },
|
|
||||||
{ "stx", Direct },
|
|
||||||
{ "sta", ILDirect },
|
|
||||||
|
|
||||||
{ "dey", Implied },
|
|
||||||
{ "bit", AccumConstant },
|
|
||||||
{ "txa", Implied },
|
|
||||||
{ "phb", Implied },
|
|
||||||
|
|
||||||
{ "sty", Address },
|
|
||||||
{ "sta", Address },
|
|
||||||
{ "stx", Address },
|
|
||||||
{ "sta", Long },
|
|
||||||
|
|
||||||
//0x90 - 0x9f
|
|
||||||
{ "bcc", RelativeShort },
|
|
||||||
{ "sta", IDirectY },
|
|
||||||
{ "sta", IDirect },
|
|
||||||
{ "sta", IStackY },
|
|
||||||
|
|
||||||
{ "sty", DirectX },
|
|
||||||
{ "sta", DirectX },
|
|
||||||
{ "stx", DirectY },
|
|
||||||
{ "sta", ILDirectY },
|
|
||||||
|
|
||||||
{ "tya", Implied },
|
|
||||||
{ "sta", AddressY },
|
|
||||||
{ "txs", Implied },
|
|
||||||
{ "txy", Implied },
|
|
||||||
|
|
||||||
{ "stz", Address },
|
|
||||||
{ "sta", AddressX },
|
|
||||||
{ "stz", AddressX },
|
|
||||||
{ "sta", LongX },
|
|
||||||
|
|
||||||
//0xa0 - 0xaf
|
|
||||||
{ "ldy", IndexConstant },
|
|
||||||
{ "lda", IDirectX },
|
|
||||||
{ "ldx", IndexConstant },
|
|
||||||
{ "lda", Stack },
|
|
||||||
|
|
||||||
{ "ldy", Direct },
|
|
||||||
{ "lda", Direct },
|
|
||||||
{ "ldx", Direct },
|
|
||||||
{ "lda", ILDirect },
|
|
||||||
|
|
||||||
{ "tay", Implied },
|
|
||||||
{ "lda", AccumConstant },
|
|
||||||
{ "tax", Implied },
|
|
||||||
{ "plb", Implied },
|
|
||||||
|
|
||||||
{ "ldy", Address },
|
|
||||||
{ "lda", Address },
|
|
||||||
{ "ldx", Address },
|
|
||||||
{ "lda", Long },
|
|
||||||
|
|
||||||
//0xb0 - 0xbf
|
|
||||||
{ "bcs", RelativeShort },
|
|
||||||
{ "lda", IDirectY },
|
|
||||||
{ "lda", IDirect },
|
|
||||||
{ "lda", IStackY },
|
|
||||||
|
|
||||||
{ "ldy", DirectX },
|
|
||||||
{ "lda", DirectX },
|
|
||||||
{ "ldx", DirectY },
|
|
||||||
{ "lda", ILDirectY },
|
|
||||||
|
|
||||||
{ "clv", Implied },
|
|
||||||
{ "lda", AddressY },
|
|
||||||
{ "tsx", Implied },
|
|
||||||
{ "tyx", Implied },
|
|
||||||
|
|
||||||
{ "ldy", AddressX },
|
|
||||||
{ "lda", AddressX },
|
|
||||||
{ "ldx", AddressY },
|
|
||||||
{ "lda", LongX },
|
|
||||||
|
|
||||||
//0xc0 - 0xcf
|
|
||||||
{ "cpy", IndexConstant },
|
|
||||||
{ "cmp", IDirectX },
|
|
||||||
{ "rep", Constant },
|
|
||||||
{ "cmp", Stack },
|
|
||||||
|
|
||||||
{ "cpy", Direct },
|
|
||||||
{ "cmp", Direct },
|
|
||||||
{ "dec", Direct },
|
|
||||||
{ "cmp", ILDirect },
|
|
||||||
|
|
||||||
{ "iny", Implied },
|
|
||||||
{ "cmp", AccumConstant },
|
|
||||||
{ "dex", Implied },
|
|
||||||
{ "wai", Implied },
|
|
||||||
|
|
||||||
{ "cpy", Address },
|
|
||||||
{ "cmp", Address },
|
|
||||||
{ "dec", Address },
|
|
||||||
{ "cmp", Long },
|
|
||||||
|
|
||||||
//0xd0 - 0xdf
|
|
||||||
{ "bne", RelativeShort },
|
|
||||||
{ "cmp", IDirectY },
|
|
||||||
{ "cmp", IDirect },
|
|
||||||
{ "cmp", IStackY },
|
|
||||||
|
|
||||||
{ "pei", IDirect },
|
|
||||||
{ "cmp", DirectX },
|
|
||||||
{ "dec", DirectX },
|
|
||||||
{ "cmp", ILDirectY },
|
|
||||||
|
|
||||||
{ "cld", Implied },
|
|
||||||
{ "cmp", AddressY },
|
|
||||||
{ "phx", Implied },
|
|
||||||
{ "stp", Implied },
|
|
||||||
|
|
||||||
{ "jmp", ILAddress },
|
|
||||||
{ "cmp", AddressX },
|
|
||||||
{ "dec", AddressX },
|
|
||||||
{ "cmp", LongX },
|
|
||||||
|
|
||||||
//0xe0 - 0xef
|
|
||||||
{ "cpx", IndexConstant },
|
|
||||||
{ "sbc", IDirectX },
|
|
||||||
{ "sep", Constant },
|
|
||||||
{ "sbc", Stack },
|
|
||||||
|
|
||||||
{ "cpx", Direct },
|
|
||||||
{ "sbc", Direct },
|
|
||||||
{ "inc", Direct },
|
|
||||||
{ "sbc", ILDirect },
|
|
||||||
|
|
||||||
{ "inx", Implied },
|
|
||||||
{ "sbc", AccumConstant },
|
|
||||||
{ "nop", Implied },
|
|
||||||
{ "xba", Implied },
|
|
||||||
|
|
||||||
{ "cpx", Address },
|
|
||||||
{ "sbc", Address },
|
|
||||||
{ "inc", Address },
|
|
||||||
{ "sbc", Long },
|
|
||||||
|
|
||||||
//0xf0 - 0xff
|
|
||||||
{ "beq", RelativeShort },
|
|
||||||
{ "sbc", IDirectY },
|
|
||||||
{ "sbc", IDirect },
|
|
||||||
{ "sbc", IStackY },
|
|
||||||
|
|
||||||
{ "pea", Address },
|
|
||||||
{ "sbc", DirectX },
|
|
||||||
{ "inc", DirectX },
|
|
||||||
{ "sbc", ILDirectY },
|
|
||||||
|
|
||||||
{ "sed", Implied },
|
|
||||||
{ "sbc", AddressY },
|
|
||||||
{ "plx", Implied },
|
|
||||||
{ "xce", Implied },
|
|
||||||
|
|
||||||
{ "jsr", IAddressX },
|
|
||||||
{ "sbc", AddressX },
|
|
||||||
{ "inc", AddressX },
|
|
||||||
{ "sbc", LongX },
|
|
||||||
};
|
|
||||||
|
|
||||||
inline unsigned SNESCPU::getOpcodeLength(bool accum, bool index, uint8_t opcode) {
|
|
||||||
switch(opcodeInfo[opcode].mode) { default:
|
|
||||||
case Implied: return 1;
|
|
||||||
case Constant: return 2;
|
|
||||||
case AccumConstant: return 3 - accum;
|
|
||||||
case IndexConstant: return 3 - index;
|
|
||||||
case Direct: return 2;
|
|
||||||
case DirectX: return 2;
|
|
||||||
case DirectY: return 2;
|
|
||||||
case IDirect: return 2;
|
|
||||||
case IDirectX: return 2;
|
|
||||||
case IDirectY: return 2;
|
|
||||||
case ILDirect: return 2;
|
|
||||||
case ILDirectY: return 2;
|
|
||||||
case Address: return 3;
|
|
||||||
case AddressX: return 3;
|
|
||||||
case AddressY: return 3;
|
|
||||||
case IAddressX: return 3;
|
|
||||||
case ILAddress: return 3;
|
|
||||||
case PAddress: return 3;
|
|
||||||
case PIAddress: return 3;
|
|
||||||
case Long: return 4;
|
|
||||||
case LongX: return 4;
|
|
||||||
case Stack: return 2;
|
|
||||||
case IStackY: return 2;
|
|
||||||
case BlockMove: return 3;
|
|
||||||
case RelativeShort: return 2;
|
|
||||||
case RelativeLong: return 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline string SNESCPU::disassemble(unsigned pc, bool accum, bool index, uint8_t opcode, uint8_t pl, uint8_t ph, uint8_t pb) {
|
|
||||||
string name = opcodeInfo[opcode].name;
|
|
||||||
unsigned mode = opcodeInfo[opcode].mode;
|
|
||||||
|
|
||||||
if(mode == Implied) return name;
|
|
||||||
if(mode == Constant) return { name, " #$", hex<2>(pl) };
|
|
||||||
if(mode == AccumConstant) return { name, " #$", accum ? "" : hex<2>(ph), hex<2>(pl) };
|
|
||||||
if(mode == IndexConstant) return { name, " #$", index ? "" : hex<2>(ph), hex<2>(pl) };
|
|
||||||
if(mode == Direct) return { name, " $", hex<2>(pl) };
|
|
||||||
if(mode == DirectX) return { name, " $", hex<2>(pl), ",x" };
|
|
||||||
if(mode == DirectY) return { name, " $", hex<2>(pl), ",y" };
|
|
||||||
if(mode == IDirect) return { name, " ($", hex<2>(pl), ")" };
|
|
||||||
if(mode == IDirectX) return { name, " ($", hex<2>(pl), ",x)" };
|
|
||||||
if(mode == IDirectY) return { name, " ($", hex<2>(pl), "),y" };
|
|
||||||
if(mode == ILDirect) return { name, " [$", hex<2>(pl), "]" };
|
|
||||||
if(mode == ILDirectY) return { name, " [$", hex<2>(pl), "],y" };
|
|
||||||
if(mode == Address) return { name, " $", hex<2>(ph), hex<2>(pl) };
|
|
||||||
if(mode == AddressX) return { name, " $", hex<2>(ph), hex<2>(pl), ",x" };
|
|
||||||
if(mode == AddressY) return { name, " $", hex<2>(ph), hex<2>(pl), ",y" };
|
|
||||||
if(mode == IAddressX) return { name, " ($", hex<2>(ph), hex<2>(pl), ",x)" };
|
|
||||||
if(mode == ILAddress) return { name, " [$", hex<2>(ph), hex<2>(pl), "]" };
|
|
||||||
if(mode == PAddress) return { name, " $", hex<2>(ph), hex<2>(pl) };
|
|
||||||
if(mode == PIAddress) return { name, " ($", hex<2>(ph), hex<2>(pl), ")" };
|
|
||||||
if(mode == Long) return { name, " $", hex<2>(pb), hex<2>(ph), hex<2>(pl) };
|
|
||||||
if(mode == LongX) return { name, " $", hex<2>(pb), hex<2>(ph), hex<2>(pl), ",x" };
|
|
||||||
if(mode == Stack) return { name, " $", hex<2>(pl), ",s" };
|
|
||||||
if(mode == IStackY) return { name, " ($", hex<2>(pl), ",s),y" };
|
|
||||||
if(mode == BlockMove) return { name, " $", hex<2>(ph), ",$", hex<2>(pl) };
|
|
||||||
if(mode == RelativeShort) {
|
|
||||||
unsigned addr = (pc + 2) + (int8_t)(pl << 0);
|
|
||||||
return { name, " $", hex<4>(addr) };
|
|
||||||
}
|
|
||||||
if(mode == RelativeLong) {
|
|
||||||
unsigned addr = (pc + 3) + (int16_t)((ph << 8) + (pl << 0));
|
|
||||||
return { name, " $", hex<4>(addr) };
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,639 +0,0 @@
|
||||||
#ifndef NALL_SNES_SMP_HPP
|
|
||||||
#define NALL_SNES_SMP_HPP
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
struct SNESSMP {
|
|
||||||
enum : unsigned {
|
|
||||||
Implied, //
|
|
||||||
TVector, //0
|
|
||||||
Direct, //$00
|
|
||||||
DirectRelative, //$00,+/-$00
|
|
||||||
ADirect, //a,$00
|
|
||||||
AAbsolute, //a,$0000
|
|
||||||
AIX, //a,(x)
|
|
||||||
AIDirectX, //a,($00+x)
|
|
||||||
AConstant, //a,#$00
|
|
||||||
DirectDirect, //$00,$00
|
|
||||||
CAbsoluteBit, //c,$0000:0
|
|
||||||
Absolute, //$0000
|
|
||||||
P, //p
|
|
||||||
AbsoluteA, //$0000,a
|
|
||||||
Relative, //+/-$00
|
|
||||||
ADirectX, //a,$00+x
|
|
||||||
AAbsoluteX, //a,$0000+x
|
|
||||||
AAbsoluteY, //a,$0000+y
|
|
||||||
AIDirectY, //a,($00)+y
|
|
||||||
DirectConstant, //$00,#$00
|
|
||||||
IXIY, //(x),(y)
|
|
||||||
DirectX, //$00+x
|
|
||||||
A, //a
|
|
||||||
X, //x
|
|
||||||
XAbsolute, //x,$0000
|
|
||||||
IAbsoluteX, //($0000+x)
|
|
||||||
CNAbsoluteBit, //c,!$0000:0
|
|
||||||
XDirect, //x,$00
|
|
||||||
PVector, //$ff00
|
|
||||||
YaDirect, //ya,$00
|
|
||||||
XA, //x,a
|
|
||||||
YAbsolute, //y,$0000
|
|
||||||
Y, //y
|
|
||||||
AX, //a,x
|
|
||||||
YDirect, //y,$00
|
|
||||||
YConstant, //y,#$00
|
|
||||||
XSp, //x,sp
|
|
||||||
YaX, //ya,x
|
|
||||||
IXPA, //(x)+,a
|
|
||||||
SpX, //sp,x
|
|
||||||
AIXP, //a,(x)+
|
|
||||||
DirectA, //$00,a
|
|
||||||
IXA, //(x),a
|
|
||||||
IDirectXA, //($00+x),a
|
|
||||||
XConstant, //x,#$00
|
|
||||||
AbsoluteX, //$0000,x
|
|
||||||
AbsoluteBitC, //$0000:0,c
|
|
||||||
DirectY, //$00,y
|
|
||||||
AbsoluteY, //$0000,y
|
|
||||||
Ya, //ya
|
|
||||||
DirectXA, //$00+x,a
|
|
||||||
AbsoluteXA, //$0000+x,a
|
|
||||||
AbsoluteYA, //$0000+y,a
|
|
||||||
IDirectYA, //($00)+y,a
|
|
||||||
DirectYX, //$00+y,x
|
|
||||||
DirectYa, //$00,ya
|
|
||||||
DirectXY, //$00+x,y
|
|
||||||
AY, //a,y
|
|
||||||
DirectXRelative, //$00+x,+/-$00
|
|
||||||
XDirectY, //x,$00+y
|
|
||||||
YDirectX, //y,$00+x
|
|
||||||
YA, //y,a
|
|
||||||
YRelative, //y,+/-$00
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OpcodeInfo {
|
|
||||||
char name[6];
|
|
||||||
unsigned mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const OpcodeInfo opcodeInfo[256];
|
|
||||||
|
|
||||||
static unsigned getOpcodeLength(uint8_t opcode);
|
|
||||||
static string disassemble(uint16_t pc, uint8_t opcode, uint8_t pl, uint8_t ph);
|
|
||||||
static string disassemble(uint16_t pc, bool p, uint8_t opcode, uint8_t pl, uint8_t ph);
|
|
||||||
};
|
|
||||||
|
|
||||||
const SNESSMP::OpcodeInfo SNESSMP::opcodeInfo[256] = {
|
|
||||||
//0x00 - 0x0f
|
|
||||||
{ "nop ", Implied },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "set0 ", Direct },
|
|
||||||
{ "bbs0 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "or ", ADirect },
|
|
||||||
{ "or ", AAbsolute },
|
|
||||||
{ "or ", AIX },
|
|
||||||
{ "or ", AIDirectX },
|
|
||||||
|
|
||||||
{ "or ", AConstant },
|
|
||||||
{ "or ", DirectDirect },
|
|
||||||
{ "or1 ", CAbsoluteBit },
|
|
||||||
{ "asl ", Direct },
|
|
||||||
|
|
||||||
{ "asl ", Absolute },
|
|
||||||
{ "push ", P },
|
|
||||||
{ "tset ", AbsoluteA },
|
|
||||||
{ "brk ", Implied },
|
|
||||||
|
|
||||||
//0x10 - 0x1f
|
|
||||||
{ "bpl ", Relative },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "clr0 ", Direct },
|
|
||||||
{ "bbc0 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "or ", ADirectX },
|
|
||||||
{ "or ", AAbsoluteX },
|
|
||||||
{ "or ", AAbsoluteY },
|
|
||||||
{ "or ", AIDirectY },
|
|
||||||
|
|
||||||
{ "or ", DirectConstant },
|
|
||||||
{ "or ", IXIY },
|
|
||||||
{ "decw ", Direct },
|
|
||||||
{ "asl ", DirectX },
|
|
||||||
|
|
||||||
{ "asl ", A },
|
|
||||||
{ "dec ", X },
|
|
||||||
{ "cmp ", XAbsolute },
|
|
||||||
{ "jmp ", IAbsoluteX },
|
|
||||||
|
|
||||||
//0x20 - 0x2f
|
|
||||||
{ "clrp ", Implied },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "set1 ", Direct },
|
|
||||||
{ "bbs1 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "and ", ADirect },
|
|
||||||
{ "and ", AAbsolute },
|
|
||||||
{ "and ", AIX },
|
|
||||||
{ "and ", AIDirectX },
|
|
||||||
|
|
||||||
{ "and ", AConstant },
|
|
||||||
{ "and ", DirectDirect },
|
|
||||||
{ "or1 ", CNAbsoluteBit },
|
|
||||||
{ "rol ", Direct },
|
|
||||||
|
|
||||||
{ "rol ", Absolute },
|
|
||||||
{ "push ", A },
|
|
||||||
{ "cbne ", DirectRelative },
|
|
||||||
{ "bra ", Relative },
|
|
||||||
|
|
||||||
//0x30 - 0x3f
|
|
||||||
{ "bmi ", Relative },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "clr1 ", Direct },
|
|
||||||
{ "bbc1 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "and ", ADirectX },
|
|
||||||
{ "and ", AAbsoluteX },
|
|
||||||
{ "and ", AAbsoluteY },
|
|
||||||
{ "and ", AIDirectY },
|
|
||||||
|
|
||||||
{ "and ", DirectConstant },
|
|
||||||
{ "and ", IXIY },
|
|
||||||
{ "incw ", Direct },
|
|
||||||
{ "rol ", DirectX },
|
|
||||||
|
|
||||||
{ "rol ", A },
|
|
||||||
{ "inc ", X },
|
|
||||||
{ "cmp ", XDirect },
|
|
||||||
{ "call ", Absolute },
|
|
||||||
|
|
||||||
//0x40 - 0x4f
|
|
||||||
{ "setp ", Implied },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "set2 ", Direct },
|
|
||||||
{ "bbs2 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "eor ", ADirect },
|
|
||||||
{ "eor ", AAbsolute },
|
|
||||||
{ "eor ", AIX },
|
|
||||||
{ "eor ", AIDirectX },
|
|
||||||
|
|
||||||
{ "eor ", AConstant },
|
|
||||||
{ "eor ", DirectDirect },
|
|
||||||
{ "and1 ", CAbsoluteBit },
|
|
||||||
{ "lsr ", Direct },
|
|
||||||
|
|
||||||
{ "lsr ", Absolute },
|
|
||||||
{ "push ", X },
|
|
||||||
{ "tclr ", AbsoluteA },
|
|
||||||
{ "pcall", PVector },
|
|
||||||
|
|
||||||
//0x50 - 0x5f
|
|
||||||
{ "bvc ", Relative },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "clr2 ", Direct },
|
|
||||||
{ "bbc2 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "eor ", ADirectX },
|
|
||||||
{ "eor ", AAbsoluteX },
|
|
||||||
{ "eor ", AAbsoluteY },
|
|
||||||
{ "eor ", AIDirectY },
|
|
||||||
|
|
||||||
{ "eor ", DirectConstant },
|
|
||||||
{ "eor ", IXIY },
|
|
||||||
{ "cmpw ", YaDirect },
|
|
||||||
{ "lsr ", DirectX },
|
|
||||||
|
|
||||||
{ "lsr ", A },
|
|
||||||
{ "mov ", XA },
|
|
||||||
{ "cmp ", YAbsolute },
|
|
||||||
{ "jmp ", Absolute },
|
|
||||||
|
|
||||||
//0x60 - 0x6f
|
|
||||||
{ "clrc ", Implied },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "set3 ", Direct },
|
|
||||||
{ "bbs3 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "cmp ", ADirect },
|
|
||||||
{ "cmp ", AAbsolute },
|
|
||||||
{ "cmp ", AIX },
|
|
||||||
{ "cmp ", AIDirectX },
|
|
||||||
|
|
||||||
{ "cmp ", AConstant },
|
|
||||||
{ "cmp ", DirectDirect },
|
|
||||||
{ "and1 ", CNAbsoluteBit },
|
|
||||||
{ "ror ", Direct },
|
|
||||||
|
|
||||||
{ "ror ", Absolute },
|
|
||||||
{ "push ", Y },
|
|
||||||
{ "dbnz ", DirectRelative },
|
|
||||||
{ "ret ", Implied },
|
|
||||||
|
|
||||||
//0x70 - 0x7f
|
|
||||||
{ "bvs ", Relative },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "clr3 ", Direct },
|
|
||||||
{ "bbc3 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "cmp ", ADirectX },
|
|
||||||
{ "cmp ", AAbsoluteX },
|
|
||||||
{ "cmp ", AAbsoluteY },
|
|
||||||
{ "cmp ", AIDirectY },
|
|
||||||
|
|
||||||
{ "cmp ", DirectConstant },
|
|
||||||
{ "cmp ", IXIY },
|
|
||||||
{ "addw ", YaDirect },
|
|
||||||
{ "ror ", DirectX },
|
|
||||||
|
|
||||||
{ "ror ", A },
|
|
||||||
{ "mov ", AX },
|
|
||||||
{ "cmp ", YDirect },
|
|
||||||
{ "reti ", Implied },
|
|
||||||
|
|
||||||
//0x80 - 0x8f
|
|
||||||
{ "setc ", Implied },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "set4 ", Direct },
|
|
||||||
{ "bbs4 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "adc ", ADirect },
|
|
||||||
{ "adc ", AAbsolute },
|
|
||||||
{ "adc ", AIX },
|
|
||||||
{ "adc ", AIDirectX },
|
|
||||||
|
|
||||||
{ "adc ", AConstant },
|
|
||||||
{ "adc ", DirectDirect },
|
|
||||||
{ "eor1 ", CAbsoluteBit },
|
|
||||||
{ "dec ", Direct },
|
|
||||||
|
|
||||||
{ "dec ", Absolute },
|
|
||||||
{ "mov ", YConstant },
|
|
||||||
{ "pop ", P },
|
|
||||||
{ "mov ", DirectConstant },
|
|
||||||
|
|
||||||
//0x90 - 0x9f
|
|
||||||
{ "bcc ", Relative },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "clr4 ", Direct },
|
|
||||||
{ "bbc4 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "adc ", ADirectX },
|
|
||||||
{ "adc ", AAbsoluteX },
|
|
||||||
{ "adc ", AAbsoluteY },
|
|
||||||
{ "adc ", AIDirectY },
|
|
||||||
|
|
||||||
{ "adc ", DirectRelative },
|
|
||||||
{ "adc ", IXIY },
|
|
||||||
{ "subw ", YaDirect },
|
|
||||||
{ "dec ", DirectX },
|
|
||||||
|
|
||||||
{ "dec ", A },
|
|
||||||
{ "mov ", XSp },
|
|
||||||
{ "div ", YaX },
|
|
||||||
{ "xcn ", A },
|
|
||||||
|
|
||||||
//0xa0 - 0xaf
|
|
||||||
{ "ei ", Implied },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "set5 ", Direct },
|
|
||||||
{ "bbs5 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "sbc ", ADirect },
|
|
||||||
{ "sbc ", AAbsolute },
|
|
||||||
{ "sbc ", AIX },
|
|
||||||
{ "sbc ", AIDirectX },
|
|
||||||
|
|
||||||
{ "sbc ", AConstant },
|
|
||||||
{ "sbc ", DirectDirect },
|
|
||||||
{ "mov1 ", CAbsoluteBit },
|
|
||||||
{ "inc ", Direct },
|
|
||||||
|
|
||||||
{ "inc ", Absolute },
|
|
||||||
{ "cmp ", YConstant },
|
|
||||||
{ "pop ", A },
|
|
||||||
{ "mov ", IXPA },
|
|
||||||
|
|
||||||
//0xb0 - 0xbf
|
|
||||||
{ "bcs ", Relative },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "clr5 ", Direct },
|
|
||||||
{ "bbc5 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "sbc ", ADirectX },
|
|
||||||
{ "sbc ", AAbsoluteX },
|
|
||||||
{ "sbc ", AAbsoluteY },
|
|
||||||
{ "sbc ", AIDirectY },
|
|
||||||
|
|
||||||
{ "sbc ", DirectConstant },
|
|
||||||
{ "sbc ", IXIY },
|
|
||||||
{ "movw ", YaDirect },
|
|
||||||
{ "inc ", DirectX },
|
|
||||||
|
|
||||||
{ "inc ", A },
|
|
||||||
{ "mov ", SpX },
|
|
||||||
{ "das ", A },
|
|
||||||
{ "mov ", AIXP },
|
|
||||||
|
|
||||||
//0xc0 - 0xcf
|
|
||||||
{ "di ", Implied },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "set6 ", Direct },
|
|
||||||
{ "bbs6 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "mov ", DirectA },
|
|
||||||
{ "mov ", AbsoluteA },
|
|
||||||
{ "mov ", IXA },
|
|
||||||
{ "mov ", IDirectXA },
|
|
||||||
|
|
||||||
{ "cmp ", XConstant },
|
|
||||||
{ "mov ", AbsoluteX },
|
|
||||||
{ "mov1 ", AbsoluteBitC },
|
|
||||||
{ "mov ", DirectY },
|
|
||||||
|
|
||||||
{ "mov ", AbsoluteY },
|
|
||||||
{ "mov ", XConstant },
|
|
||||||
{ "pop ", X },
|
|
||||||
{ "mul ", Ya },
|
|
||||||
|
|
||||||
//0xd0 - 0xdf
|
|
||||||
{ "bne ", Relative },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "clr6 ", Relative },
|
|
||||||
{ "bbc6 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "mov ", DirectXA },
|
|
||||||
{ "mov ", AbsoluteXA },
|
|
||||||
{ "mov ", AbsoluteYA },
|
|
||||||
{ "mov ", IDirectYA },
|
|
||||||
|
|
||||||
{ "mov ", DirectX },
|
|
||||||
{ "mov ", DirectYX },
|
|
||||||
{ "movw ", DirectYa },
|
|
||||||
{ "mov ", DirectXY },
|
|
||||||
|
|
||||||
{ "dec ", Y },
|
|
||||||
{ "mov ", AY },
|
|
||||||
{ "cbne ", DirectXRelative },
|
|
||||||
{ "daa ", A },
|
|
||||||
|
|
||||||
//0xe0 - 0xef
|
|
||||||
{ "clrv ", Implied },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "set7 ", Direct },
|
|
||||||
{ "bbs7 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "mov ", ADirect },
|
|
||||||
{ "mov ", AAbsolute },
|
|
||||||
{ "mov ", AIX },
|
|
||||||
{ "mov ", AIDirectX },
|
|
||||||
|
|
||||||
{ "mov ", AConstant },
|
|
||||||
{ "mov ", XAbsolute },
|
|
||||||
{ "not1 ", CAbsoluteBit },
|
|
||||||
{ "mov ", YDirect },
|
|
||||||
|
|
||||||
{ "mov ", YAbsolute },
|
|
||||||
{ "notc ", Implied },
|
|
||||||
{ "pop ", Y },
|
|
||||||
{ "sleep", Implied },
|
|
||||||
|
|
||||||
//0xf0 - 0xff
|
|
||||||
{ "beq ", Relative },
|
|
||||||
{ "tcall", TVector },
|
|
||||||
{ "clr7 ", Direct },
|
|
||||||
{ "bbc7 ", DirectRelative },
|
|
||||||
|
|
||||||
{ "mov ", ADirectX },
|
|
||||||
{ "mov ", AAbsoluteX },
|
|
||||||
{ "mov ", AAbsoluteY },
|
|
||||||
{ "mov ", AIDirectY },
|
|
||||||
|
|
||||||
{ "mov ", XDirect },
|
|
||||||
{ "mov ", XDirectY },
|
|
||||||
{ "mov ", DirectDirect },
|
|
||||||
{ "mov ", YDirectX },
|
|
||||||
|
|
||||||
{ "inc ", Y },
|
|
||||||
{ "mov ", YA },
|
|
||||||
{ "dbz ", YRelative },
|
|
||||||
{ "stop ", Implied },
|
|
||||||
};
|
|
||||||
|
|
||||||
inline unsigned SNESSMP::getOpcodeLength(uint8_t opcode) {
|
|
||||||
switch(opcodeInfo[opcode].mode) { default:
|
|
||||||
case Implied: return 1; //
|
|
||||||
case TVector: return 1; //0
|
|
||||||
case Direct: return 2; //$00
|
|
||||||
case DirectRelative: return 3; //$00,+/-$00
|
|
||||||
case ADirect: return 2; //a,$00
|
|
||||||
case AAbsolute: return 3; //a,$0000
|
|
||||||
case AIX: return 1; //a,(x)
|
|
||||||
case AIDirectX: return 2; //a,($00+x)
|
|
||||||
case AConstant: return 2; //a,#$00
|
|
||||||
case DirectDirect: return 3; //$00,$00
|
|
||||||
case CAbsoluteBit: return 3; //c,$0000:0
|
|
||||||
case Absolute: return 3; //$0000
|
|
||||||
case P: return 1; //p
|
|
||||||
case AbsoluteA: return 3; //$0000,a
|
|
||||||
case Relative: return 2; //+/-$00
|
|
||||||
case ADirectX: return 2; //a,$00+x
|
|
||||||
case AAbsoluteX: return 3; //a,$0000+x
|
|
||||||
case AAbsoluteY: return 3; //a,$0000+y
|
|
||||||
case AIDirectY: return 2; //a,($00)+y
|
|
||||||
case DirectConstant: return 3; //$00,#$00
|
|
||||||
case IXIY: return 1; //(x),(y)
|
|
||||||
case DirectX: return 2; //$00+x
|
|
||||||
case A: return 1; //a
|
|
||||||
case X: return 1; //x
|
|
||||||
case XAbsolute: return 3; //x,$0000
|
|
||||||
case IAbsoluteX: return 3; //($0000+x)
|
|
||||||
case CNAbsoluteBit: return 3; //c,!$0000:0
|
|
||||||
case XDirect: return 2; //x,$00
|
|
||||||
case PVector: return 2; //$ff00
|
|
||||||
case YaDirect: return 2; //ya,$00
|
|
||||||
case XA: return 1; //x,a
|
|
||||||
case YAbsolute: return 3; //y,$0000
|
|
||||||
case Y: return 1; //y
|
|
||||||
case AX: return 1; //a,x
|
|
||||||
case YDirect: return 2; //y,$00
|
|
||||||
case YConstant: return 2; //y,#$00
|
|
||||||
case XSp: return 1; //x,sp
|
|
||||||
case YaX: return 1; //ya,x
|
|
||||||
case IXPA: return 1; //(x)+,a
|
|
||||||
case SpX: return 1; //sp,x
|
|
||||||
case AIXP: return 1; //a,(x)+
|
|
||||||
case DirectA: return 2; //$00,a
|
|
||||||
case IXA: return 1; //(x),a
|
|
||||||
case IDirectXA: return 2; //($00+x),a
|
|
||||||
case XConstant: return 2; //x,#$00
|
|
||||||
case AbsoluteX: return 3; //$0000,x
|
|
||||||
case AbsoluteBitC: return 3; //$0000:0,c
|
|
||||||
case DirectY: return 2; //$00,y
|
|
||||||
case AbsoluteY: return 3; //$0000,y
|
|
||||||
case Ya: return 1; //ya
|
|
||||||
case DirectXA: return 2; //$00+x,a
|
|
||||||
case AbsoluteXA: return 3; //$0000+x,a
|
|
||||||
case AbsoluteYA: return 3; //$0000+y,a
|
|
||||||
case IDirectYA: return 2; //($00)+y,a
|
|
||||||
case DirectYX: return 2; //$00+y,x
|
|
||||||
case DirectYa: return 2; //$00,ya
|
|
||||||
case DirectXY: return 2; //$00+x,y
|
|
||||||
case AY: return 1; //a,y
|
|
||||||
case DirectXRelative: return 3; //$00+x,+/-$00
|
|
||||||
case XDirectY: return 2; //x,$00+y
|
|
||||||
case YDirectX: return 2; //y,$00+x
|
|
||||||
case YA: return 1; //y,a
|
|
||||||
case YRelative: return 2; //y,+/-$00
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline string SNESSMP::disassemble(uint16_t pc, uint8_t opcode, uint8_t pl, uint8_t ph) {
|
|
||||||
string name = opcodeInfo[opcode].name;
|
|
||||||
unsigned mode = opcodeInfo[opcode].mode;
|
|
||||||
unsigned pa = (ph << 8) + pl;
|
|
||||||
|
|
||||||
if(mode == Implied) return name;
|
|
||||||
if(mode == TVector) return { name, " ", opcode >> 4 };
|
|
||||||
if(mode == Direct) return { name, " $", hex<2>(pl) };
|
|
||||||
if(mode == DirectRelative) return { name, " $", hex<2>(pl), ",$", hex<4>(pc + 3 + (int8_t)ph) };
|
|
||||||
if(mode == ADirect) return { name, " a,$", hex<2>(pl) };
|
|
||||||
if(mode == AAbsolute) return { name, " a,$", hex<4>(pa) };
|
|
||||||
if(mode == AIX) return { name, "a,(x)" };
|
|
||||||
if(mode == AIDirectX) return { name, " a,($", hex<2>(pl), "+x)" };
|
|
||||||
if(mode == AConstant) return { name, " a,#$", hex<2>(pl) };
|
|
||||||
if(mode == DirectDirect) return { name, " $", hex<2>(ph), ",$", hex<2>(pl) };
|
|
||||||
if(mode == CAbsoluteBit) return { name, " c,$", hex<4>(pa & 0x1fff), ":", pa >> 13 };
|
|
||||||
if(mode == Absolute) return { name, " $", hex<4>(pa) };
|
|
||||||
if(mode == P) return { name, " p" };
|
|
||||||
if(mode == AbsoluteA) return { name, " $", hex<4>(pa), ",a" };
|
|
||||||
if(mode == Relative) return { name, " $", hex<4>(pc + 2 + (int8_t)pl) };
|
|
||||||
if(mode == ADirectX) return { name, " a,$", hex<2>(pl), "+x" };
|
|
||||||
if(mode == AAbsoluteX) return { name, " a,$", hex<4>(pa), "+x" };
|
|
||||||
if(mode == AAbsoluteY) return { name, " a,$", hex<4>(pa), "+y" };
|
|
||||||
if(mode == AIDirectY) return { name, " a,($", hex<2>(pl), ")+y" };
|
|
||||||
if(mode == DirectConstant) return { name, " $", hex<2>(ph), ",#$", hex<2>(pl) };
|
|
||||||
if(mode == IXIY) return { name, " (x),(y)" };
|
|
||||||
if(mode == DirectX) return { name, " $", hex<2>(pl), "+x" };
|
|
||||||
if(mode == A) return { name, " a" };
|
|
||||||
if(mode == X) return { name, " x" };
|
|
||||||
if(mode == XAbsolute) return { name, " x,$", hex<4>(pa) };
|
|
||||||
if(mode == IAbsoluteX) return { name, " ($", hex<4>(pa), "+x)" };
|
|
||||||
if(mode == CNAbsoluteBit) return { name, " c,!$", hex<4>(pa & 0x1fff), ":", pa >> 13 };
|
|
||||||
if(mode == XDirect) return { name, " x,$", hex<2>(pl) };
|
|
||||||
if(mode == PVector) return { name, " $ff", hex<2>(pl) };
|
|
||||||
if(mode == YaDirect) return { name, " ya,$", hex<2>(pl) };
|
|
||||||
if(mode == XA) return { name, " x,a" };
|
|
||||||
if(mode == YAbsolute) return { name, " y,$", hex<4>(pa) };
|
|
||||||
if(mode == Y) return { name, " y" };
|
|
||||||
if(mode == AX) return { name, " a,x" };
|
|
||||||
if(mode == YDirect) return { name, " y,$", hex<2>(pl) };
|
|
||||||
if(mode == YConstant) return { name, " y,#$", hex<2>(pl) };
|
|
||||||
if(mode == XSp) return { name, " x,sp" };
|
|
||||||
if(mode == YaX) return { name, " ya,x" };
|
|
||||||
if(mode == IXPA) return { name, " (x)+,a" };
|
|
||||||
if(mode == SpX) return { name, " sp,x" };
|
|
||||||
if(mode == AIXP) return { name, " a,(x)+" };
|
|
||||||
if(mode == DirectA) return { name, " $", hex<2>(pl), ",a" };
|
|
||||||
if(mode == IXA) return { name, " (x),a" };
|
|
||||||
if(mode == IDirectXA) return { name, " ($", hex<2>(pl), "+x),a" };
|
|
||||||
if(mode == XConstant) return { name, " x,#$", hex<2>(pl) };
|
|
||||||
if(mode == AbsoluteX) return { name, " $", hex<4>(pa), ",x" };
|
|
||||||
if(mode == AbsoluteBitC) return { name, " $", hex<4>(pa & 0x1fff), ":", pa >> 13, ",c" };
|
|
||||||
if(mode == DirectY) return { name, " $", hex<2>(pl), ",y" };
|
|
||||||
if(mode == AbsoluteY) return { name, " $", hex<4>(pa), ",y" };
|
|
||||||
if(mode == Ya) return { name, " ya" };
|
|
||||||
if(mode == DirectXA) return { name, " $", hex<2>(pl), "+x,a" };
|
|
||||||
if(mode == AbsoluteXA) return { name, " $", hex<4>(pa), "+x,a" };
|
|
||||||
if(mode == AbsoluteYA) return { name, " $", hex<4>(pa), "+y,a" };
|
|
||||||
if(mode == IDirectYA) return { name, " ($", hex<2>(pl), ")+y,a" };
|
|
||||||
if(mode == DirectYX) return { name, " $", hex<2>(pl), "+y,x" };
|
|
||||||
if(mode == DirectYa) return { name, " $", hex<2>(pl), ",ya" };
|
|
||||||
if(mode == DirectXY) return { name, " $", hex<2>(pl), "+x,y" };
|
|
||||||
if(mode == AY) return { name, " a,y" };
|
|
||||||
if(mode == DirectXRelative) return { name, " $", hex<2>(pl), ",$", hex<4>(pc + 3 + (int8_t)ph) };
|
|
||||||
if(mode == XDirectY) return { name, " x,$", hex<2>(pl), "+y" };
|
|
||||||
if(mode == YDirectX) return { name, " y,$", hex<2>(pl), "+x" };
|
|
||||||
if(mode == YA) return { name, " y,a" };
|
|
||||||
if(mode == YRelative) return { name, " y,$", hex<4>(pc + 2 + (int8_t)pl) };
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline string SNESSMP::disassemble(uint16_t pc, bool p, uint8_t opcode, uint8_t pl, uint8_t ph) {
|
|
||||||
string name = opcodeInfo[opcode].name;
|
|
||||||
unsigned mode = opcodeInfo[opcode].mode;
|
|
||||||
unsigned pdl = (p << 8) + pl;
|
|
||||||
unsigned pdh = (p << 8) + ph;
|
|
||||||
unsigned pa = (ph << 8) + pl;
|
|
||||||
|
|
||||||
if(mode == Implied) return name;
|
|
||||||
if(mode == TVector) return { name, " ", opcode >> 4 };
|
|
||||||
if(mode == Direct) return { name, " $", hex<3>(pdl) };
|
|
||||||
if(mode == DirectRelative) return { name, " $", hex<3>(pdl), ",$", hex<4>(pc + 3 + (int8_t)ph) };
|
|
||||||
if(mode == ADirect) return { name, " a,$", hex<3>(pdl) };
|
|
||||||
if(mode == AAbsolute) return { name, " a,$", hex<4>(pa) };
|
|
||||||
if(mode == AIX) return { name, "a,(x)" };
|
|
||||||
if(mode == AIDirectX) return { name, " a,($", hex<3>(pdl), "+x)" };
|
|
||||||
if(mode == AConstant) return { name, " a,#$", hex<2>(pl) };
|
|
||||||
if(mode == DirectDirect) return { name, " $", hex<3>(pdh), ",$", hex<3>(pdl) };
|
|
||||||
if(mode == CAbsoluteBit) return { name, " c,$", hex<4>(pa & 0x1fff), ":", pa >> 13 };
|
|
||||||
if(mode == Absolute) return { name, " $", hex<4>(pa) };
|
|
||||||
if(mode == P) return { name, " p" };
|
|
||||||
if(mode == AbsoluteA) return { name, " $", hex<4>(pa), ",a" };
|
|
||||||
if(mode == Relative) return { name, " $", hex<4>(pc + 2 + (int8_t)pl) };
|
|
||||||
if(mode == ADirectX) return { name, " a,$", hex<3>(pdl), "+x" };
|
|
||||||
if(mode == AAbsoluteX) return { name, " a,$", hex<4>(pa), "+x" };
|
|
||||||
if(mode == AAbsoluteY) return { name, " a,$", hex<4>(pa), "+y" };
|
|
||||||
if(mode == AIDirectY) return { name, " a,($", hex<3>(pdl), ")+y" };
|
|
||||||
if(mode == DirectConstant) return { name, " $", hex<3>(pdh), ",#$", hex<2>(pl) };
|
|
||||||
if(mode == IXIY) return { name, " (x),(y)" };
|
|
||||||
if(mode == DirectX) return { name, " $", hex<3>(pdl), "+x" };
|
|
||||||
if(mode == A) return { name, " a" };
|
|
||||||
if(mode == X) return { name, " x" };
|
|
||||||
if(mode == XAbsolute) return { name, " x,$", hex<4>(pa) };
|
|
||||||
if(mode == IAbsoluteX) return { name, " ($", hex<4>(pa), "+x)" };
|
|
||||||
if(mode == CNAbsoluteBit) return { name, " c,!$", hex<4>(pa & 0x1fff), ":", pa >> 13 };
|
|
||||||
if(mode == XDirect) return { name, " x,$", hex<3>(pdl) };
|
|
||||||
if(mode == PVector) return { name, " $ff", hex<2>(pl) };
|
|
||||||
if(mode == YaDirect) return { name, " ya,$", hex<3>(pdl) };
|
|
||||||
if(mode == XA) return { name, " x,a" };
|
|
||||||
if(mode == YAbsolute) return { name, " y,$", hex<4>(pa) };
|
|
||||||
if(mode == Y) return { name, " y" };
|
|
||||||
if(mode == AX) return { name, " a,x" };
|
|
||||||
if(mode == YDirect) return { name, " y,$", hex<3>(pdl) };
|
|
||||||
if(mode == YConstant) return { name, " y,#$", hex<2>(pl) };
|
|
||||||
if(mode == XSp) return { name, " x,sp" };
|
|
||||||
if(mode == YaX) return { name, " ya,x" };
|
|
||||||
if(mode == IXPA) return { name, " (x)+,a" };
|
|
||||||
if(mode == SpX) return { name, " sp,x" };
|
|
||||||
if(mode == AIXP) return { name, " a,(x)+" };
|
|
||||||
if(mode == DirectA) return { name, " $", hex<3>(pdl), ",a" };
|
|
||||||
if(mode == IXA) return { name, " (x),a" };
|
|
||||||
if(mode == IDirectXA) return { name, " ($", hex<3>(pdl), "+x),a" };
|
|
||||||
if(mode == XConstant) return { name, " x,#$", hex<2>(pl) };
|
|
||||||
if(mode == AbsoluteX) return { name, " $", hex<4>(pa), ",x" };
|
|
||||||
if(mode == AbsoluteBitC) return { name, " $", hex<4>(pa & 0x1fff), ":", pa >> 13, ",c" };
|
|
||||||
if(mode == DirectY) return { name, " $", hex<3>(pdl), ",y" };
|
|
||||||
if(mode == AbsoluteY) return { name, " $", hex<4>(pa), ",y" };
|
|
||||||
if(mode == Ya) return { name, " ya" };
|
|
||||||
if(mode == DirectXA) return { name, " $", hex<3>(pdl), "+x,a" };
|
|
||||||
if(mode == AbsoluteXA) return { name, " $", hex<4>(pa), "+x,a" };
|
|
||||||
if(mode == AbsoluteYA) return { name, " $", hex<4>(pa), "+y,a" };
|
|
||||||
if(mode == IDirectYA) return { name, " ($", hex<3>(pdl), ")+y,a" };
|
|
||||||
if(mode == DirectYX) return { name, " $", hex<3>(pdl), "+y,x" };
|
|
||||||
if(mode == DirectYa) return { name, " $", hex<3>(pdl), ",ya" };
|
|
||||||
if(mode == DirectXY) return { name, " $", hex<3>(pdl), "+x,y" };
|
|
||||||
if(mode == AY) return { name, " a,y" };
|
|
||||||
if(mode == DirectXRelative) return { name, " $", hex<3>(pdl), ",$", hex<4>(pc + 3 + (int8_t)ph) };
|
|
||||||
if(mode == XDirectY) return { name, " x,$", hex<3>(pdl), "+y" };
|
|
||||||
if(mode == YDirectX) return { name, " y,$", hex<3>(pdl), "+x" };
|
|
||||||
if(mode == YA) return { name, " y,a" };
|
|
||||||
if(mode == YRelative) return { name, " y,$", hex<4>(pc + 2 + (int8_t)pl) };
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,4 +1,5 @@
|
||||||
#ifdef NALL_STREAM_INTERNAL_HPP
|
#ifndef NALL_STREAM_AUTO_HPP
|
||||||
|
#define NALL_STREAM_AUTO_HPP
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,37 @@
|
||||||
#ifdef NALL_STREAM_INTERNAL_HPP
|
#ifndef NALL_STREAM_FILE_HPP
|
||||||
|
#define NALL_STREAM_FILE_HPP
|
||||||
|
|
||||||
|
#include <nall/file.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct filestream : stream {
|
struct filestream : stream {
|
||||||
inline bool seekable() const { return true; }
|
using stream::read;
|
||||||
inline bool readable() const { return true; }
|
using stream::write;
|
||||||
inline bool writable() const { return pwritable; }
|
|
||||||
inline bool randomaccess() const { return false; }
|
|
||||||
|
|
||||||
inline unsigned size() const { return pfile.size(); }
|
bool seekable() const { return true; }
|
||||||
inline unsigned offset() const { return pfile.offset(); }
|
bool readable() const { return true; }
|
||||||
inline void seek(unsigned offset) const { pfile.seek(offset); }
|
bool writable() const { return pwritable; }
|
||||||
|
bool randomaccess() const { return false; }
|
||||||
|
|
||||||
inline uint8_t read() const { return pfile.read(); }
|
unsigned size() const { return pfile.size(); }
|
||||||
inline void write(uint8_t data) const { pfile.write(data); }
|
unsigned offset() const { return pfile.offset(); }
|
||||||
|
void seek(unsigned offset) const { pfile.seek(offset); }
|
||||||
|
|
||||||
inline filestream(const string &filename) {
|
uint8_t read() const { return pfile.read(); }
|
||||||
|
void write(uint8_t data) const { pfile.write(data); }
|
||||||
|
|
||||||
|
filestream(const string &filename) {
|
||||||
pfile.open(filename, file::mode::readwrite);
|
pfile.open(filename, file::mode::readwrite);
|
||||||
pwritable = pfile.open();
|
pwritable = pfile.open();
|
||||||
if(!pwritable) pfile.open(filename, file::mode::read);
|
if(!pwritable) pfile.open(filename, file::mode::read);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filestream(const string &filename, file::mode mode) {
|
||||||
|
pfile.open(filename, mode);
|
||||||
|
pwritable = mode == file::mode::write || mode == file::mode::readwrite;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable file pfile;
|
mutable file pfile;
|
||||||
bool pwritable;
|
bool pwritable;
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
#ifdef NALL_STREAM_INTERNAL_HPP
|
#ifndef NALL_STREAM_GZIP_HPP
|
||||||
|
#define NALL_STREAM_GZIP_HPP
|
||||||
|
|
||||||
|
#include <nall/gzip.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct gzipstream : memorystream {
|
struct gzipstream : memorystream {
|
||||||
inline gzipstream(const stream &stream) {
|
using stream::read;
|
||||||
|
using stream::write;
|
||||||
|
|
||||||
|
gzipstream(const stream &stream) {
|
||||||
unsigned size = stream.size();
|
unsigned size = stream.size();
|
||||||
uint8_t *data = new uint8_t[size];
|
uint8_t *data = new uint8_t[size];
|
||||||
stream.read(data, size);
|
stream.read(data, size);
|
||||||
|
@ -18,7 +24,7 @@ struct gzipstream : memorystream {
|
||||||
memcpy(pdata, archive.data, psize);
|
memcpy(pdata, archive.data, psize);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~gzipstream() {
|
~gzipstream() {
|
||||||
if(pdata) delete[] pdata;
|
if(pdata) delete[] pdata;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,24 +1,30 @@
|
||||||
#ifdef NALL_STREAM_INTERNAL_HPP
|
#ifndef NALL_STREAM_HTTP_HPP
|
||||||
|
#define NALL_STREAM_HTTP_HPP
|
||||||
|
|
||||||
|
#include <nall/http.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct httpstream : stream {
|
struct httpstream : stream {
|
||||||
inline bool seekable() const { return true; }
|
using stream::read;
|
||||||
inline bool readable() const { return true; }
|
using stream::write;
|
||||||
inline bool writable() const { return true; }
|
|
||||||
inline bool randomaccess() const { return true; }
|
|
||||||
|
|
||||||
inline unsigned size() const { return psize; }
|
bool seekable() const { return true; }
|
||||||
inline unsigned offset() const { return poffset; }
|
bool readable() const { return true; }
|
||||||
inline void seek(unsigned offset) const { poffset = offset; }
|
bool writable() const { return true; }
|
||||||
|
bool randomaccess() const { return true; }
|
||||||
|
|
||||||
inline uint8_t read() const { return pdata[poffset++]; }
|
unsigned size() const { return psize; }
|
||||||
inline void write(uint8_t data) const { pdata[poffset++] = data; }
|
unsigned offset() const { return poffset; }
|
||||||
|
void seek(unsigned offset) const { poffset = offset; }
|
||||||
|
|
||||||
inline uint8_t read(unsigned offset) const { return pdata[offset]; }
|
uint8_t read() const { return pdata[poffset++]; }
|
||||||
inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
void write(uint8_t data) const { pdata[poffset++] = data; }
|
||||||
|
|
||||||
inline httpstream(const string &url, unsigned port) : pdata(nullptr), psize(0), poffset(0) {
|
uint8_t read(unsigned offset) const { return pdata[offset]; }
|
||||||
|
void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||||
|
|
||||||
|
httpstream(const string &url, unsigned port) : pdata(nullptr), psize(0), poffset(0) {
|
||||||
string uri = url;
|
string uri = url;
|
||||||
uri.ltrim<1>("http://");
|
uri.ltrim<1>("http://");
|
||||||
lstring part = uri.split<1>("/");
|
lstring part = uri.split<1>("/");
|
||||||
|
@ -29,7 +35,7 @@ struct httpstream : stream {
|
||||||
connection.download(part[1], pdata, psize);
|
connection.download(part[1], pdata, psize);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~httpstream() {
|
~httpstream() {
|
||||||
if(pdata) delete[] pdata;
|
if(pdata) delete[] pdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,31 +1,38 @@
|
||||||
#ifdef NALL_STREAM_INTERNAL_HPP
|
#ifndef NALL_STREAM_MEMORY_HPP
|
||||||
|
#define NALL_STREAM_MEMORY_HPP
|
||||||
|
|
||||||
|
#include <nall/stream/stream.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct memorystream : stream {
|
struct memorystream : stream {
|
||||||
inline bool seekable() const { return true; }
|
using stream::read;
|
||||||
inline bool readable() const { return true; }
|
using stream::write;
|
||||||
inline bool writable() const { return pwritable; }
|
|
||||||
inline bool randomaccess() const { return true; }
|
|
||||||
|
|
||||||
inline unsigned size() const { return psize; }
|
bool seekable() const { return true; }
|
||||||
inline unsigned offset() const { return poffset; }
|
bool readable() const { return true; }
|
||||||
inline void seek(unsigned offset) const { poffset = offset; }
|
bool writable() const { return pwritable; }
|
||||||
|
bool randomaccess() const { return true; }
|
||||||
|
|
||||||
inline uint8_t read() const { return pdata[poffset++]; }
|
uint8_t *data() const { return pdata; }
|
||||||
inline void write(uint8_t data) const { pdata[poffset++] = data; }
|
unsigned size() const { return psize; }
|
||||||
|
unsigned offset() const { return poffset; }
|
||||||
|
void seek(unsigned offset) const { poffset = offset; }
|
||||||
|
|
||||||
inline uint8_t read(unsigned offset) const { return pdata[offset]; }
|
uint8_t read() const { return pdata[poffset++]; }
|
||||||
inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
void write(uint8_t data) const { pdata[poffset++] = data; }
|
||||||
|
|
||||||
inline memorystream() : pdata(nullptr), psize(0), poffset(0), pwritable(true) {}
|
uint8_t read(unsigned offset) const { return pdata[offset]; }
|
||||||
|
void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||||
|
|
||||||
inline memorystream(uint8_t *data, unsigned size) {
|
memorystream() : pdata(nullptr), psize(0), poffset(0), pwritable(true) {}
|
||||||
|
|
||||||
|
memorystream(uint8_t *data, unsigned size) {
|
||||||
pdata = data, psize = size, poffset = 0;
|
pdata = data, psize = size, poffset = 0;
|
||||||
pwritable = true;
|
pwritable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline memorystream(const uint8_t *data, unsigned size) {
|
memorystream(const uint8_t *data, unsigned size) {
|
||||||
pdata = (uint8_t*)data, psize = size, poffset = 0;
|
pdata = (uint8_t*)data, psize = size, poffset = 0;
|
||||||
pwritable = false;
|
pwritable = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,30 @@
|
||||||
#ifdef NALL_STREAM_INTERNAL_HPP
|
#ifndef NALL_STREAM_MMAP_HPP
|
||||||
|
#define NALL_STREAM_MMAP_HPP
|
||||||
|
|
||||||
|
#include <nall/filemap.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct mmapstream : stream {
|
struct mmapstream : stream {
|
||||||
inline bool seekable() const { return true; }
|
using stream::read;
|
||||||
inline bool readable() const { return true; }
|
using stream::write;
|
||||||
inline bool writable() const { return pwritable; }
|
|
||||||
inline bool randomaccess() const { return false; }
|
|
||||||
|
|
||||||
inline unsigned size() const { return pmmap.size(); }
|
bool seekable() const { return true; }
|
||||||
inline unsigned offset() const { return poffset; }
|
bool readable() const { return true; }
|
||||||
inline void seek(unsigned offset) const { poffset = offset; }
|
bool writable() const { return pwritable; }
|
||||||
|
bool randomaccess() const { return true; }
|
||||||
|
|
||||||
inline uint8_t read() const { return pdata[poffset++]; }
|
unsigned size() const { return pmmap.size(); }
|
||||||
inline void write(uint8_t data) const { pdata[poffset++] = data; }
|
unsigned offset() const { return poffset; }
|
||||||
|
void seek(unsigned offset) const { poffset = offset; }
|
||||||
|
|
||||||
inline uint8_t read(unsigned offset) const { return pdata[offset]; }
|
uint8_t read() const { return pdata[poffset++]; }
|
||||||
inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
void write(uint8_t data) const { pdata[poffset++] = data; }
|
||||||
|
|
||||||
inline mmapstream(const string &filename) {
|
uint8_t read(unsigned offset) const { return pdata[offset]; }
|
||||||
|
void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||||
|
|
||||||
|
mmapstream(const string &filename) {
|
||||||
pmmap.open(filename, filemap::mode::readwrite);
|
pmmap.open(filename, filemap::mode::readwrite);
|
||||||
pwritable = pmmap.open();
|
pwritable = pmmap.open();
|
||||||
if(!pwritable) pmmap.open(filename, filemap::mode::read);
|
if(!pwritable) pmmap.open(filename, filemap::mode::read);
|
||||||
|
|
|
@ -9,6 +9,7 @@ struct stream {
|
||||||
virtual bool writable() const = 0;
|
virtual bool writable() const = 0;
|
||||||
virtual bool randomaccess() const = 0;
|
virtual bool randomaccess() const = 0;
|
||||||
|
|
||||||
|
virtual uint8_t* data() const { return nullptr; }
|
||||||
virtual unsigned size() const = 0;
|
virtual unsigned size() const = 0;
|
||||||
virtual unsigned offset() const = 0;
|
virtual unsigned offset() const = 0;
|
||||||
virtual void seek(unsigned offset) const = 0;
|
virtual void seek(unsigned offset) const = 0;
|
||||||
|
@ -16,44 +17,45 @@ struct stream {
|
||||||
virtual uint8_t read() const = 0;
|
virtual uint8_t read() const = 0;
|
||||||
virtual void write(uint8_t data) const = 0;
|
virtual void write(uint8_t data) const = 0;
|
||||||
|
|
||||||
inline virtual uint8_t read(unsigned) const { return 0; }
|
virtual uint8_t read(unsigned) const { return 0; }
|
||||||
inline virtual void write(unsigned, uint8_t) const {}
|
virtual void write(unsigned, uint8_t) const {}
|
||||||
|
|
||||||
inline bool end() const {
|
operator bool() const {
|
||||||
|
return size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool end() const {
|
||||||
return offset() >= size();
|
return offset() >= size();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void copy(uint8_t *&data, unsigned &length) const {
|
uintmax_t readl(unsigned length = 1) const {
|
||||||
seek(0);
|
|
||||||
length = size();
|
|
||||||
data = new uint8_t[length];
|
|
||||||
for(unsigned n = 0; n < length; n++) data[n] = read();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uintmax_t readl(unsigned length = 1) const {
|
|
||||||
uintmax_t data = 0, shift = 0;
|
uintmax_t data = 0, shift = 0;
|
||||||
while(length--) { data |= read() << shift; shift += 8; }
|
while(length--) { data |= read() << shift; shift += 8; }
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uintmax_t readm(unsigned length = 1) const {
|
uintmax_t readm(unsigned length = 1) const {
|
||||||
uintmax_t data = 0;
|
uintmax_t data = 0;
|
||||||
while(length--) data = (data << 8) | read();
|
while(length--) data = (data << 8) | read();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void read(uint8_t *data, unsigned length) const {
|
void read(uint8_t *data, unsigned length) const {
|
||||||
while(length--) *data++ = read();
|
while(length--) *data++ = read();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void writel(uintmax_t data, unsigned length = 1) const {
|
void writel(uintmax_t data, unsigned length = 1) const {
|
||||||
while(length--) {
|
while(length--) {
|
||||||
write(data);
|
write(data);
|
||||||
data >>= 8;
|
data >>= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void writem(uintmax_t data, unsigned length = 1) const {
|
void writem(uintmax_t data, unsigned length = 1) const {
|
||||||
uintmax_t shift = 8 * length;
|
uintmax_t shift = 8 * length;
|
||||||
while(length--) {
|
while(length--) {
|
||||||
shift -= 8;
|
shift -= 8;
|
||||||
|
@ -61,26 +63,26 @@ struct stream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void write(const uint8_t *data, unsigned length) const {
|
void write(const uint8_t *data, unsigned length) const {
|
||||||
while(length--) write(*data++);
|
while(length--) write(*data++);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct byte {
|
struct byte {
|
||||||
inline operator uint8_t() const { return s.read(offset); }
|
operator uint8_t() const { return s.read(offset); }
|
||||||
inline byte& operator=(uint8_t data) { s.write(offset, data); }
|
byte& operator=(uint8_t data) { s.write(offset, data); }
|
||||||
inline byte(const stream &s, unsigned offset) : s(s), offset(offset) {}
|
byte(const stream &s, unsigned offset) : s(s), offset(offset) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const stream &s;
|
const stream &s;
|
||||||
const unsigned offset;
|
const unsigned offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline byte operator[](unsigned offset) const {
|
byte operator[](unsigned offset) const {
|
||||||
return byte(*this, offset);
|
return byte(*this, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline stream() {}
|
stream() {}
|
||||||
inline virtual ~stream() {}
|
virtual ~stream() {}
|
||||||
stream(const stream&) = delete;
|
stream(const stream&) = delete;
|
||||||
stream& operator=(const stream&) = delete;
|
stream& operator=(const stream&) = delete;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef NALL_STREAM_VECTOR_HPP
|
||||||
|
#define NALL_STREAM_VECTOR_HPP
|
||||||
|
|
||||||
|
#include <nall/stream/stream.hpp>
|
||||||
|
#include <nall/vector.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
struct vectorstream : stream {
|
||||||
|
using stream::read;
|
||||||
|
using stream::write;
|
||||||
|
|
||||||
|
bool seekable() const { return true; }
|
||||||
|
bool readable() const { return true; }
|
||||||
|
bool writable() const { return pwritable; }
|
||||||
|
bool randomaccess() const { return true; }
|
||||||
|
|
||||||
|
uint8_t* data() const { return memory.data(); }
|
||||||
|
unsigned size() const { return memory.size(); }
|
||||||
|
unsigned offset() const { return poffset; }
|
||||||
|
void seek(unsigned offset) const { poffset = offset; }
|
||||||
|
|
||||||
|
uint8_t read() const { return memory[poffset++]; }
|
||||||
|
void write(uint8_t data) const { memory[poffset++] = data; }
|
||||||
|
|
||||||
|
uint8_t read(unsigned offset) const { return memory[offset]; }
|
||||||
|
void write(unsigned offset, uint8_t data) const { memory[offset] = data; }
|
||||||
|
|
||||||
|
vectorstream(vector<uint8_t> &memory) : memory(memory), poffset(0), pwritable(true) {}
|
||||||
|
vectorstream(const vector<uint8_t> &memory) : memory((vector<uint8_t>&)memory), poffset(0), pwritable(false) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
vector<uint8_t> &memory;
|
||||||
|
mutable unsigned poffset, pwritable;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,9 +1,15 @@
|
||||||
#ifdef NALL_STREAM_INTERNAL_HPP
|
#ifndef NALL_STREAM_ZIP_HPP
|
||||||
|
#define NALL_STREAM_ZIP_HPP
|
||||||
|
|
||||||
|
#include <nall/zip.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct zipstream : memorystream {
|
struct zipstream : memorystream {
|
||||||
inline zipstream(const stream &stream, const string &filter = "*") {
|
using stream::read;
|
||||||
|
using stream::write;
|
||||||
|
|
||||||
|
zipstream(const stream &stream, const string &filter = "*") {
|
||||||
unsigned size = stream.size();
|
unsigned size = stream.size();
|
||||||
uint8_t *data = new uint8_t[size];
|
uint8_t *data = new uint8_t[size];
|
||||||
stream.read(data, size);
|
stream.read(data, size);
|
||||||
|
@ -20,7 +26,7 @@ struct zipstream : memorystream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~zipstream() {
|
~zipstream() {
|
||||||
if(pdata) delete[] pdata;
|
if(pdata) delete[] pdata;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
|
||||||
#include <nall/array.hpp>
|
|
||||||
#include <nall/atoi.hpp>
|
#include <nall/atoi.hpp>
|
||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
||||||
#include <nall/platform.hpp>
|
#include <nall/platform.hpp>
|
||||||
|
|
|
@ -112,6 +112,8 @@ namespace nall {
|
||||||
struct lstring : vector<string> {
|
struct lstring : vector<string> {
|
||||||
inline optional<unsigned> find(const char*) const;
|
inline optional<unsigned> find(const char*) const;
|
||||||
inline string concatenate(const char*) const;
|
inline string concatenate(const char*) const;
|
||||||
|
inline void append() {}
|
||||||
|
template<typename... Args> inline void append(const string&, Args&&...);
|
||||||
|
|
||||||
template<unsigned Limit = 0> inline lstring& split(const char*, const char*);
|
template<unsigned Limit = 0> inline lstring& split(const char*, const char*);
|
||||||
template<unsigned Limit = 0> inline lstring& isplit(const char*, const char*);
|
template<unsigned Limit = 0> inline lstring& isplit(const char*, const char*);
|
||||||
|
@ -121,8 +123,14 @@ namespace nall {
|
||||||
inline bool operator==(const lstring&) const;
|
inline bool operator==(const lstring&) const;
|
||||||
inline bool operator!=(const lstring&) const;
|
inline bool operator!=(const lstring&) const;
|
||||||
|
|
||||||
inline lstring();
|
inline lstring& operator=(const lstring&);
|
||||||
inline lstring(std::initializer_list<string>);
|
inline lstring& operator=(lstring&);
|
||||||
|
inline lstring& operator=(lstring&&);
|
||||||
|
|
||||||
|
template<typename... Args> inline lstring(Args&&... args);
|
||||||
|
inline lstring(const lstring&);
|
||||||
|
inline lstring(lstring&);
|
||||||
|
inline lstring(lstring&&);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<unsigned Limit, bool Insensitive, bool Quoted> inline lstring& usplit(const char*, const char*);
|
template<unsigned Limit, bool Insensitive, bool Quoted> inline lstring& usplit(const char*, const char*);
|
||||||
|
@ -149,9 +157,10 @@ namespace nall {
|
||||||
inline bool strmath(const char *str, int &result);
|
inline bool strmath(const char *str, int &result);
|
||||||
|
|
||||||
//platform.hpp
|
//platform.hpp
|
||||||
inline string realpath(const char *name);
|
inline string activepath();
|
||||||
|
inline string realpath(const string &name);
|
||||||
inline string userpath();
|
inline string userpath();
|
||||||
inline string currentpath();
|
inline string configpath();
|
||||||
|
|
||||||
//strm.hpp
|
//strm.hpp
|
||||||
inline unsigned strmcpy(char *target, const char *source, unsigned length);
|
inline unsigned strmcpy(char *target, const char *source, unsigned length);
|
||||||
|
|
|
@ -7,12 +7,12 @@ namespace nall {
|
||||||
namespace BML {
|
namespace BML {
|
||||||
|
|
||||||
inline static string indent(const char *s, unsigned depth) {
|
inline static string indent(const char *s, unsigned depth) {
|
||||||
array<char> output;
|
vector<char> output;
|
||||||
do {
|
do {
|
||||||
for(unsigned n = 0; n < depth; n++) output.append('\t');
|
for(unsigned n = 0; n < depth; n++) output.append('\t');
|
||||||
do output.append(*s); while(*s && *s++ != '\n');
|
do output.append(*s); while(*s && *s++ != '\n');
|
||||||
} while(*s);
|
} while(*s);
|
||||||
return output.get();
|
return output.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Node {
|
struct Node {
|
||||||
|
|
|
@ -146,6 +146,11 @@ string lstring::concatenate(const char *separator) const {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename... Args> void lstring::append(const string &data, Args&&... args) {
|
||||||
|
vector::append(data);
|
||||||
|
append(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
bool lstring::operator==(const lstring &source) const {
|
bool lstring::operator==(const lstring &source) const {
|
||||||
if(this == &source) return true;
|
if(this == &source) return true;
|
||||||
if(size() != source.size()) return false;
|
if(size() != source.size()) return false;
|
||||||
|
@ -159,11 +164,35 @@ bool lstring::operator!=(const lstring &source) const {
|
||||||
return !operator==(source);
|
return !operator==(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline lstring::lstring() {
|
lstring& lstring::operator=(const lstring &source) {
|
||||||
|
vector::operator=(source);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline lstring::lstring(std::initializer_list<string> list) {
|
lstring& lstring::operator=(lstring &source) {
|
||||||
for(auto &data : list) append(data);
|
vector::operator=(source);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
lstring& lstring::operator=(lstring &&source) {
|
||||||
|
vector::operator=(std::move(source));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args> lstring::lstring(Args&&... args) {
|
||||||
|
append(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
lstring::lstring(const lstring &source) {
|
||||||
|
vector::operator=(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
lstring::lstring(lstring &source) {
|
||||||
|
vector::operator=(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
lstring::lstring(lstring &&source) {
|
||||||
|
vector::operator=(std::move(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,36 +2,60 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
string currentpath() {
|
string activepath() {
|
||||||
char path[PATH_MAX];
|
string result;
|
||||||
if(::getcwd(path)) {
|
#ifdef _WIN32
|
||||||
string result(path);
|
wchar_t path[PATH_MAX] = L"";
|
||||||
|
_wgetcwd(path, PATH_MAX);
|
||||||
|
result = (const char*)utf8_t(path);
|
||||||
result.transform("\\", "/");
|
result.transform("\\", "/");
|
||||||
|
#else
|
||||||
|
char path[PATH_MAX] = "";
|
||||||
|
getcwd(path, PATH_MAX);
|
||||||
|
result = path;
|
||||||
|
#endif
|
||||||
|
if(result.empty()) result = ".";
|
||||||
if(result.endswith("/") == false) result.append("/");
|
if(result.endswith("/") == false) result.append("/");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return "./";
|
|
||||||
|
string realpath(const string &name) {
|
||||||
|
string result;
|
||||||
|
#ifdef _WIN32
|
||||||
|
wchar_t path[PATH_MAX] = L"";
|
||||||
|
if(_wfullpath(path, utf16_t(name), PATH_MAX)) result = (const char*)utf8_t(path);
|
||||||
|
result.transform("\\", "/");
|
||||||
|
#else
|
||||||
|
char path[PATH_MAX] = "";
|
||||||
|
if(::realpath(name, path)) result = path;
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
string userpath() {
|
string userpath() {
|
||||||
char path[PATH_MAX];
|
string result;
|
||||||
if(::userpath(path)) {
|
#ifdef _WIN32
|
||||||
string result(path);
|
wchar_t path[PATH_MAX] = L"";
|
||||||
|
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path);
|
||||||
|
result = (const char*)utf8_t(path);
|
||||||
result.transform("\\", "/");
|
result.transform("\\", "/");
|
||||||
|
#else
|
||||||
|
char path[PATH_MAX] = "";
|
||||||
|
struct passwd *userinfo = getpwuid(getuid());
|
||||||
|
if(userinfo) strcpy(path, userinfo->pw_dir);
|
||||||
|
result = path;
|
||||||
|
#endif
|
||||||
|
if(result.empty()) result = ".";
|
||||||
if(result.endswith("/") == false) result.append("/");
|
if(result.endswith("/") == false) result.append("/");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return currentpath();
|
|
||||||
}
|
|
||||||
|
|
||||||
string realpath(const char *name) {
|
string configpath() {
|
||||||
char path[PATH_MAX];
|
#ifdef _WIN32
|
||||||
if(::realpath(name, path)) {
|
|
||||||
string result(path);
|
|
||||||
result.transform("\\", "/");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return userpath();
|
return userpath();
|
||||||
|
#else
|
||||||
|
return {userpath(), ".config/"};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ struct Node {
|
||||||
string name;
|
string name;
|
||||||
string data;
|
string data;
|
||||||
bool attribute;
|
bool attribute;
|
||||||
array<Node*> children;
|
vector<Node*> children;
|
||||||
|
|
||||||
inline bool exists() const {
|
inline bool exists() const {
|
||||||
return !name.empty();
|
return !name.empty();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef NALL_STATIC_HPP
|
#ifndef NALL_TRAITS_HPP
|
||||||
#define NALL_STATIC_HPP
|
#define NALL_TRAITS_HPP
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define NALL_VARINT_HPP
|
#define NALL_VARINT_HPP
|
||||||
|
|
||||||
#include <nall/bit.hpp>
|
#include <nall/bit.hpp>
|
||||||
#include <nall/type_traits.hpp>
|
#include <nall/traits.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<unsigned bits> struct uint_t {
|
template<unsigned bits> struct uint_t {
|
||||||
|
|
|
@ -21,6 +21,10 @@ namespace nall {
|
||||||
unsigned objectsize;
|
unsigned objectsize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
operator bool() const { return pool; }
|
||||||
|
T* data() { return pool; }
|
||||||
|
|
||||||
|
bool empty() const { return pool == nullptr; }
|
||||||
unsigned size() const { return objectsize; }
|
unsigned size() const { return objectsize; }
|
||||||
unsigned capacity() const { return poolsize; }
|
unsigned capacity() const { return poolsize; }
|
||||||
|
|
||||||
|
@ -45,6 +49,13 @@ namespace nall {
|
||||||
objectsize = min(size, objectsize);
|
objectsize = min(size, objectsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//requires trivial constructor
|
||||||
|
void resize(unsigned size) {
|
||||||
|
if(size == objectsize) return;
|
||||||
|
if(size < objectsize) return reserve(size);
|
||||||
|
while(size > objectsize) append(T());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void append(const T& data, Args&&... args) {
|
void append(const T& data, Args&&... args) {
|
||||||
append(data);
|
append(data);
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef NALL_WINDOWS_GUID_HPP
|
||||||
|
#define NALL_WINDOWS_GUID_HPP
|
||||||
|
|
||||||
|
#include <nall/random.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
//generate unique GUID
|
||||||
|
inline string guid() {
|
||||||
|
random_lfsr lfsr;
|
||||||
|
lfsr.seed(time(0));
|
||||||
|
for(unsigned n = 0; n < 256; n++) lfsr();
|
||||||
|
|
||||||
|
string output;
|
||||||
|
for(unsigned n = 0; n < 4; n++) output.append(hex<2>(lfsr()));
|
||||||
|
output.append("-");
|
||||||
|
for(unsigned n = 0; n < 2; n++) output.append(hex<2>(lfsr()));
|
||||||
|
output.append("-");
|
||||||
|
for(unsigned n = 0; n < 2; n++) output.append(hex<2>(lfsr()));
|
||||||
|
output.append("-");
|
||||||
|
for(unsigned n = 0; n < 2; n++) output.append(hex<2>(lfsr()));
|
||||||
|
output.append("-");
|
||||||
|
for(unsigned n = 0; n < 6; n++) output.append(hex<2>(lfsr()));
|
||||||
|
return {"{", output, "}"};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,120 @@
|
||||||
|
#ifndef NALL_WINDOWS_REGISTRY_HPP
|
||||||
|
#define NALL_WINDOWS_REGISTRY_HPP
|
||||||
|
|
||||||
|
#include <nall/platform.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
|
#include <shlwapi.h>
|
||||||
|
#ifndef KEY_WOW64_64KEY
|
||||||
|
#define KEY_WOW64_64KEY 0x0100
|
||||||
|
#endif
|
||||||
|
#ifndef KEY_WOW64_32KEY
|
||||||
|
#define KEY_WOW64_32KEY 0x0200
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NWR_FLAGS
|
||||||
|
#define NWR_FLAGS KEY_WOW64_64KEY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NWR_SIZE
|
||||||
|
#define NWR_SIZE 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
struct registry {
|
||||||
|
static bool exists(const string &name) {
|
||||||
|
lstring part = name.split("/");
|
||||||
|
HKEY handle, rootKey = root(part.take(0));
|
||||||
|
string node = part.take();
|
||||||
|
string path = part.concatenate("\\");
|
||||||
|
if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) {
|
||||||
|
wchar_t data[NWR_SIZE] = L"";
|
||||||
|
DWORD size = NWR_SIZE * sizeof(wchar_t);
|
||||||
|
LONG result = RegQueryValueExW(handle, utf16_t(node), NULL, NULL, (LPBYTE)&data, (LPDWORD)&size);
|
||||||
|
RegCloseKey(handle);
|
||||||
|
if(result == ERROR_SUCCESS) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string read(const string &name) {
|
||||||
|
lstring part = name.split("/");
|
||||||
|
HKEY handle, rootKey = root(part.take(0));
|
||||||
|
string node = part.take();
|
||||||
|
string path = part.concatenate("\\");
|
||||||
|
if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) {
|
||||||
|
wchar_t data[NWR_SIZE] = L"";
|
||||||
|
DWORD size = NWR_SIZE * sizeof(wchar_t);
|
||||||
|
LONG result = RegQueryValueExW(handle, utf16_t(node), NULL, NULL, (LPBYTE)&data, (LPDWORD)&size);
|
||||||
|
RegCloseKey(handle);
|
||||||
|
if(result == ERROR_SUCCESS) return (const char*)utf8_t(data);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write(const string &name, const string &data = "") {
|
||||||
|
lstring part = name.split("/");
|
||||||
|
HKEY handle, rootKey = root(part.take(0));
|
||||||
|
string node = part.take(), path;
|
||||||
|
DWORD disposition;
|
||||||
|
for(unsigned n = 0; n < part.size(); n++) {
|
||||||
|
path.append(part[n]);
|
||||||
|
if(RegCreateKeyExW(rootKey, utf16_t(path), 0, NULL, 0, NWR_FLAGS | KEY_ALL_ACCESS, NULL, &handle, &disposition) == ERROR_SUCCESS) {
|
||||||
|
if(n == part.size() - 1) {
|
||||||
|
RegSetValueExW(handle, utf16_t(node), 0, REG_SZ, (BYTE*)(wchar_t*)utf16_t(data), (data.length() + 1) * sizeof(wchar_t));
|
||||||
|
}
|
||||||
|
RegCloseKey(handle);
|
||||||
|
}
|
||||||
|
path.append("\\");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool remove(const string &name) {
|
||||||
|
lstring part = name.split("/");
|
||||||
|
HKEY rootKey = root(part.take(0));
|
||||||
|
string node = part.take();
|
||||||
|
string path = part.concatenate("\\");
|
||||||
|
if(node.empty()) return SHDeleteKeyW(rootKey, utf16_t(path)) == ERROR_SUCCESS;
|
||||||
|
return SHDeleteValueW(rootKey, utf16_t(path), utf16_t(node)) == ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lstring contents(const string &name) {
|
||||||
|
lstring part = name.split("/"), result;
|
||||||
|
HKEY handle, rootKey = root(part.take(0));
|
||||||
|
part.remove();
|
||||||
|
string path = part.concatenate("\\");
|
||||||
|
if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) {
|
||||||
|
DWORD folders, nodes;
|
||||||
|
RegQueryInfoKey(handle, NULL, NULL, NULL, &folders, NULL, NULL, &nodes, NULL, NULL, NULL, NULL);
|
||||||
|
for(unsigned n = 0; n < folders; n++) {
|
||||||
|
wchar_t name[NWR_SIZE] = L"";
|
||||||
|
DWORD size = NWR_SIZE * sizeof(wchar_t);
|
||||||
|
RegEnumKeyEx(handle, n, (wchar_t*)&name, &size, NULL, NULL, NULL, NULL);
|
||||||
|
result.append({(const char*)utf8_t(name), "/"});
|
||||||
|
}
|
||||||
|
for(unsigned n = 0; n < nodes; n++) {
|
||||||
|
wchar_t name[NWR_SIZE] = L"";
|
||||||
|
DWORD size = NWR_SIZE * sizeof(wchar_t);
|
||||||
|
RegEnumValueW(handle, n, (wchar_t*)&name, &size, NULL, NULL, NULL, NULL);
|
||||||
|
result.append((const char*)utf8_t(name));
|
||||||
|
}
|
||||||
|
RegCloseKey(handle);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static HKEY root(const string &name) {
|
||||||
|
if(name == "HKCR") return HKEY_CLASSES_ROOT;
|
||||||
|
if(name == "HKCC") return HKEY_CURRENT_CONFIG;
|
||||||
|
if(name == "HKCU") return HKEY_CURRENT_USER;
|
||||||
|
if(name == "HKLM") return HKEY_LOCAL_MACHINE;
|
||||||
|
if(name == "HKU" ) return HKEY_USERS;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -12,6 +12,7 @@
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
#define _WIN32_WINNT 0x0501
|
#define _WIN32_WINNT 0x0501
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#undef interface
|
#undef interface
|
||||||
|
|
||||||
|
|
|
@ -80,28 +80,22 @@ struct zip {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool extract(File &file, uint8_t *&data, unsigned &size) {
|
inline vector<uint8_t> extract(File &file) {
|
||||||
data = 0, size = 0;
|
vector<uint8_t> buffer;
|
||||||
|
|
||||||
if(file.cmode == 0) {
|
if(file.cmode == 0) {
|
||||||
size = file.size;
|
buffer.resize(file.size);
|
||||||
data = new uint8_t[size];
|
memcpy(buffer.data(), file.data, file.size);
|
||||||
memcpy(data, file.data, size);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(file.cmode == 8) {
|
if(file.cmode == 8) {
|
||||||
size = file.size;
|
buffer.resize(file.size);
|
||||||
data = new uint8_t[size];
|
if(inflate(buffer.data(), buffer.size(), file.data, file.csize) == false) {
|
||||||
if(inflate(data, size, file.data, file.csize) == false) {
|
buffer.reset();
|
||||||
delete[] data;
|
|
||||||
size = 0;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void close() {
|
inline void close() {
|
||||||
|
|
|
@ -14,7 +14,7 @@ ifeq ($(platform),x)
|
||||||
endif
|
endif
|
||||||
else ifeq ($(platform),win)
|
else ifeq ($(platform),win)
|
||||||
phoenixflags := -DPHOENIX_WINDOWS
|
phoenixflags := -DPHOENIX_WINDOWS
|
||||||
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32
|
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
|
||||||
else
|
else
|
||||||
phoenixflags := -DPHOENIX_REFERENCE
|
phoenixflags := -DPHOENIX_REFERENCE
|
||||||
phoenixlink :=
|
phoenixlink :=
|
||||||
|
|
|
@ -83,7 +83,7 @@ bool Keyboard::released(Keyboard::Scancode scancode) {
|
||||||
return !pressed(scancode);
|
return !pressed(scancode);
|
||||||
}
|
}
|
||||||
|
|
||||||
array<bool> Keyboard::state() {
|
vector<bool> Keyboard::state() {
|
||||||
return pKeyboard::state();
|
return pKeyboard::state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +326,11 @@ void Window::setMenuVisible(bool visible) {
|
||||||
return p.setMenuVisible(visible);
|
return p.setMenuVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::setModal(bool modal) {
|
||||||
|
state.modal = modal;
|
||||||
|
return p.setModal(modal);
|
||||||
|
}
|
||||||
|
|
||||||
void Window::setResizable(bool resizable) {
|
void Window::setResizable(bool resizable) {
|
||||||
state.resizable = resizable;
|
state.resizable = resizable;
|
||||||
return p.setResizable(resizable);
|
return p.setResizable(resizable);
|
||||||
|
@ -423,7 +428,7 @@ Action::~Action() {
|
||||||
//Menu
|
//Menu
|
||||||
//====
|
//====
|
||||||
|
|
||||||
void Menu::append(const array<Action&> &list) {
|
void Menu::append(const set<Action&> &list) {
|
||||||
for(auto &action : list) {
|
for(auto &action : list) {
|
||||||
if(state.action.append(action)) {
|
if(state.action.append(action)) {
|
||||||
action.state.menu = this;
|
action.state.menu = this;
|
||||||
|
@ -432,7 +437,7 @@ void Menu::append(const array<Action&> &list) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::remove(const array<Action&> &list) {
|
void Menu::remove(const set<Action&> &list) {
|
||||||
for(auto &action : list) {
|
for(auto &action : list) {
|
||||||
if(state.action.remove(action)) {
|
if(state.action.remove(action)) {
|
||||||
action.state.menu = 0;
|
action.state.menu = 0;
|
||||||
|
@ -537,7 +542,7 @@ CheckItem::~CheckItem() {
|
||||||
//RadioItem
|
//RadioItem
|
||||||
//=========
|
//=========
|
||||||
|
|
||||||
void RadioItem::group(const array<RadioItem&> &list) {
|
void RadioItem::group(const set<RadioItem&> &list) {
|
||||||
for(auto &item : list) item.p.setGroup(item.state.group = list);
|
for(auto &item : list) item.p.setGroup(item.state.group = list);
|
||||||
if(list.size()) list[0].setChecked();
|
if(list.size()) list[0].setChecked();
|
||||||
}
|
}
|
||||||
|
@ -557,6 +562,10 @@ void RadioItem::setText(const string &text) {
|
||||||
return p.setText(text);
|
return p.setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string RadioItem::text() {
|
||||||
|
return state.text;
|
||||||
|
}
|
||||||
|
|
||||||
RadioItem::RadioItem():
|
RadioItem::RadioItem():
|
||||||
state(*new State),
|
state(*new State),
|
||||||
base_from_member<pRadioItem&>(*new pRadioItem(*this)),
|
base_from_member<pRadioItem&>(*new pRadioItem(*this)),
|
||||||
|
@ -830,6 +839,16 @@ void ComboBox::append_(const lstring &list) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ComboBox::modify(unsigned row, const string &text) {
|
||||||
|
state.text(row) = text;
|
||||||
|
p.modify(row, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComboBox::remove(unsigned row) {
|
||||||
|
state.text.remove(row);
|
||||||
|
p.remove(row);
|
||||||
|
}
|
||||||
|
|
||||||
void ComboBox::reset() {
|
void ComboBox::reset() {
|
||||||
state.selection = 0;
|
state.selection = 0;
|
||||||
state.text.reset();
|
state.text.reset();
|
||||||
|
@ -845,6 +864,14 @@ void ComboBox::setSelection(unsigned row) {
|
||||||
return p.setSelection(row);
|
return p.setSelection(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string ComboBox::text() {
|
||||||
|
return state.text(selection());
|
||||||
|
}
|
||||||
|
|
||||||
|
string ComboBox::text(unsigned row) {
|
||||||
|
return state.text(row);
|
||||||
|
}
|
||||||
|
|
||||||
ComboBox::ComboBox():
|
ComboBox::ComboBox():
|
||||||
state(*new State),
|
state(*new State),
|
||||||
base_from_member<pComboBox&>(*new pComboBox(*this)),
|
base_from_member<pComboBox&>(*new pComboBox(*this)),
|
||||||
|
@ -1039,8 +1066,15 @@ void ListView::modify_(unsigned row, const lstring &text) {
|
||||||
return p.modify(row, text);
|
return p.modify(row, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListView::remove(unsigned row) {
|
||||||
|
state.text.remove(row);
|
||||||
|
state.image.remove(row);
|
||||||
|
return p.remove(row);
|
||||||
|
}
|
||||||
|
|
||||||
void ListView::reset() {
|
void ListView::reset() {
|
||||||
state.checked.reset();
|
state.checked.reset();
|
||||||
|
state.image.reset();
|
||||||
state.text.reset();
|
state.text.reset();
|
||||||
return p.reset();
|
return p.reset();
|
||||||
}
|
}
|
||||||
|
@ -1073,6 +1107,11 @@ void ListView::setHeaderVisible(bool visible) {
|
||||||
return p.setHeaderVisible(visible);
|
return p.setHeaderVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListView::setImage(unsigned row, unsigned column, const nall::image &image) {
|
||||||
|
state.image(row)(column) = image;
|
||||||
|
return p.setImage(row, column, image);
|
||||||
|
}
|
||||||
|
|
||||||
void ListView::setSelected(bool selected) {
|
void ListView::setSelected(bool selected) {
|
||||||
state.selected = selected;
|
state.selected = selected;
|
||||||
return p.setSelected(selected);
|
return p.setSelected(selected);
|
||||||
|
@ -1121,7 +1160,7 @@ ProgressBar::~ProgressBar() {
|
||||||
//RadioBox
|
//RadioBox
|
||||||
//========
|
//========
|
||||||
|
|
||||||
void RadioBox::group(const array<RadioBox&> &list) {
|
void RadioBox::group(const set<RadioBox&> &list) {
|
||||||
for(auto &item : list) item.p.setGroup(item.state.group = list);
|
for(auto &item : list) item.p.setGroup(item.state.group = list);
|
||||||
if(list.size()) list[0].setChecked();
|
if(list.size()) list[0].setChecked();
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ struct Keyboard {
|
||||||
#include "keyboard.hpp"
|
#include "keyboard.hpp"
|
||||||
static bool pressed(Scancode scancode);
|
static bool pressed(Scancode scancode);
|
||||||
static bool released(Scancode scancode);
|
static bool released(Scancode scancode);
|
||||||
static nall::array<bool> state();
|
static nall::vector<bool> state();
|
||||||
Keyboard() = delete;
|
Keyboard() = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,6 +199,7 @@ struct Window : private nall::base_from_member<pWindow&>, Object {
|
||||||
void setGeometry(const Geometry &geometry);
|
void setGeometry(const Geometry &geometry);
|
||||||
void setMenuFont(const nall::string &font);
|
void setMenuFont(const nall::string &font);
|
||||||
void setMenuVisible(bool visible = true);
|
void setMenuVisible(bool visible = true);
|
||||||
|
void setModal(bool modal = true);
|
||||||
void setResizable(bool resizable = true);
|
void setResizable(bool resizable = true);
|
||||||
void setStatusFont(const nall::string &font);
|
void setStatusFont(const nall::string &font);
|
||||||
void setStatusText(const nall::string &text);
|
void setStatusText(const nall::string &text);
|
||||||
|
@ -234,9 +235,9 @@ struct Menu : private nall::base_from_member<pMenu&>, Action {
|
||||||
template<typename... Args> void append(Args&... args) { append({args...}); }
|
template<typename... Args> void append(Args&... args) { append({args...}); }
|
||||||
template<typename... Args> void remove(Args&... args) { remove({args...}); }
|
template<typename... Args> void remove(Args&... args) { remove({args...}); }
|
||||||
|
|
||||||
void append(const nall::array<Action&> &list);
|
void append(const nall::set<Action&> &list);
|
||||||
void remove(const nall::array<Action&> &list);
|
void remove(const nall::set<Action&> &list);
|
||||||
void setImage(const nall::image &image);
|
void setImage(const nall::image &image = nall::image{});
|
||||||
void setText(const nall::string &text);
|
void setText(const nall::string &text);
|
||||||
|
|
||||||
Menu();
|
Menu();
|
||||||
|
@ -255,7 +256,7 @@ struct Separator : private nall::base_from_member<pSeparator&>, Action {
|
||||||
struct Item : private nall::base_from_member<pItem&>, Action {
|
struct Item : private nall::base_from_member<pItem&>, Action {
|
||||||
nall::function<void ()> onActivate;
|
nall::function<void ()> onActivate;
|
||||||
|
|
||||||
void setImage(const nall::image &image);
|
void setImage(const nall::image &image = nall::image{});
|
||||||
void setText(const nall::string &text);
|
void setText(const nall::string &text);
|
||||||
|
|
||||||
Item();
|
Item();
|
||||||
|
@ -281,13 +282,14 @@ struct CheckItem : private nall::base_from_member<pCheckItem&>, Action {
|
||||||
|
|
||||||
struct RadioItem : private nall::base_from_member<pRadioItem&>, Action {
|
struct RadioItem : private nall::base_from_member<pRadioItem&>, Action {
|
||||||
template<typename... Args> static void group(Args&... args) { group({args...}); }
|
template<typename... Args> static void group(Args&... args) { group({args...}); }
|
||||||
static void group(const nall::array<RadioItem&> &list);
|
static void group(const nall::set<RadioItem&> &list);
|
||||||
|
|
||||||
nall::function<void ()> onActivate;
|
nall::function<void ()> onActivate;
|
||||||
|
|
||||||
bool checked();
|
bool checked();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setText(const nall::string &text);
|
void setText(const nall::string &text);
|
||||||
|
nall::string text();
|
||||||
|
|
||||||
RadioItem();
|
RadioItem();
|
||||||
~RadioItem();
|
~RadioItem();
|
||||||
|
@ -350,7 +352,7 @@ struct Widget : private nall::base_from_member<pWidget&>, Sizable {
|
||||||
struct Button : private nall::base_from_member<pButton&>, Widget {
|
struct Button : private nall::base_from_member<pButton&>, Widget {
|
||||||
nall::function<void ()> onActivate;
|
nall::function<void ()> onActivate;
|
||||||
|
|
||||||
void setImage(const nall::image &image, Orientation = Orientation::Horizontal);
|
void setImage(const nall::image &image = nall::image{}, Orientation = Orientation::Horizontal);
|
||||||
void setText(const nall::string &text);
|
void setText(const nall::string &text);
|
||||||
|
|
||||||
Button();
|
Button();
|
||||||
|
@ -399,9 +401,13 @@ struct ComboBox : private nall::base_from_member<pComboBox&>, Widget {
|
||||||
template<typename... Args> void append(const Args&... args) { append_({args...}); }
|
template<typename... Args> void append(const Args&... args) { append_({args...}); }
|
||||||
|
|
||||||
void append_(const nall::lstring &list);
|
void append_(const nall::lstring &list);
|
||||||
|
void modify(unsigned row, const nall::string &text);
|
||||||
|
void remove(unsigned row);
|
||||||
void reset();
|
void reset();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
void setSelection(unsigned row);
|
void setSelection(unsigned row);
|
||||||
|
nall::string text();
|
||||||
|
nall::string text(unsigned row);
|
||||||
|
|
||||||
ComboBox();
|
ComboBox();
|
||||||
~ComboBox();
|
~ComboBox();
|
||||||
|
@ -495,6 +501,7 @@ struct ListView : private nall::base_from_member<pListView&>, Widget {
|
||||||
void autoSizeColumns();
|
void autoSizeColumns();
|
||||||
bool checked(unsigned row);
|
bool checked(unsigned row);
|
||||||
void modify_(unsigned row, const nall::lstring &list);
|
void modify_(unsigned row, const nall::lstring &list);
|
||||||
|
void remove(unsigned row);
|
||||||
void reset();
|
void reset();
|
||||||
bool selected();
|
bool selected();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
|
@ -502,6 +509,7 @@ struct ListView : private nall::base_from_member<pListView&>, Widget {
|
||||||
void setChecked(unsigned row, bool checked = true);
|
void setChecked(unsigned row, bool checked = true);
|
||||||
void setHeaderText_(const nall::lstring &list);
|
void setHeaderText_(const nall::lstring &list);
|
||||||
void setHeaderVisible(bool visible = true);
|
void setHeaderVisible(bool visible = true);
|
||||||
|
void setImage(unsigned row, unsigned column, const nall::image &image = nall::image{});
|
||||||
void setSelected(bool selected = true);
|
void setSelected(bool selected = true);
|
||||||
void setSelection(unsigned row);
|
void setSelection(unsigned row);
|
||||||
|
|
||||||
|
@ -524,7 +532,7 @@ struct ProgressBar : private nall::base_from_member<pProgressBar&>, Widget {
|
||||||
|
|
||||||
struct RadioBox : private nall::base_from_member<pRadioBox&>, Widget {
|
struct RadioBox : private nall::base_from_member<pRadioBox&>, Widget {
|
||||||
template<typename... Args> static void group(Args&... args) { group({args...}); }
|
template<typename... Args> static void group(Args&... args) { group({args...}); }
|
||||||
static void group(const nall::array<RadioBox&> &list);
|
static void group(const nall::set<RadioBox&> &list);
|
||||||
|
|
||||||
nall::function<void ()> onActivate;
|
nall::function<void ()> onActivate;
|
||||||
|
|
||||||
|
|
|
@ -14,17 +14,18 @@ struct Window::State {
|
||||||
bool fullScreen;
|
bool fullScreen;
|
||||||
Geometry geometry;
|
Geometry geometry;
|
||||||
bool ignore;
|
bool ignore;
|
||||||
array<Layout&> layout;
|
set<Layout&> layout;
|
||||||
array<Menu&> menu;
|
set<Menu&> menu;
|
||||||
string menuFont;
|
string menuFont;
|
||||||
bool menuVisible;
|
bool menuVisible;
|
||||||
|
bool modal;
|
||||||
bool resizable;
|
bool resizable;
|
||||||
string statusFont;
|
string statusFont;
|
||||||
string statusText;
|
string statusText;
|
||||||
bool statusVisible;
|
bool statusVisible;
|
||||||
string title;
|
string title;
|
||||||
bool visible;
|
bool visible;
|
||||||
array<Widget&> widget;
|
set<Widget&> widget;
|
||||||
string widgetFont;
|
string widgetFont;
|
||||||
|
|
||||||
State() {
|
State() {
|
||||||
|
@ -34,6 +35,7 @@ struct Window::State {
|
||||||
geometry = {128, 128, 256, 256};
|
geometry = {128, 128, 256, 256};
|
||||||
ignore = false;
|
ignore = false;
|
||||||
menuVisible = false;
|
menuVisible = false;
|
||||||
|
modal = false;
|
||||||
resizable = true;
|
resizable = true;
|
||||||
statusVisible = false;
|
statusVisible = false;
|
||||||
visible = false;
|
visible = false;
|
||||||
|
@ -55,7 +57,7 @@ struct Action::State {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Menu::State {
|
struct Menu::State {
|
||||||
array<Action&> action;
|
set<Action&> action;
|
||||||
nall::image image;
|
nall::image image;
|
||||||
string text;
|
string text;
|
||||||
|
|
||||||
|
@ -82,7 +84,7 @@ struct CheckItem::State {
|
||||||
|
|
||||||
struct RadioItem::State {
|
struct RadioItem::State {
|
||||||
bool checked;
|
bool checked;
|
||||||
array<RadioItem&> group;
|
set<RadioItem&> group;
|
||||||
string text;
|
string text;
|
||||||
|
|
||||||
State() {
|
State() {
|
||||||
|
@ -208,9 +210,10 @@ struct LineEdit::State {
|
||||||
|
|
||||||
struct ListView::State {
|
struct ListView::State {
|
||||||
bool checkable;
|
bool checkable;
|
||||||
array<bool> checked;
|
vector<bool> checked;
|
||||||
lstring headerText;
|
lstring headerText;
|
||||||
bool headerVisible;
|
bool headerVisible;
|
||||||
|
vector<vector<nall::image>> image;
|
||||||
bool selected;
|
bool selected;
|
||||||
unsigned selection;
|
unsigned selection;
|
||||||
vector<lstring> text;
|
vector<lstring> text;
|
||||||
|
@ -233,7 +236,7 @@ struct ProgressBar::State {
|
||||||
|
|
||||||
struct RadioBox::State {
|
struct RadioBox::State {
|
||||||
bool checked;
|
bool checked;
|
||||||
array<RadioBox&> group;
|
set<RadioBox&> group;
|
||||||
string text;
|
string text;
|
||||||
|
|
||||||
State() {
|
State() {
|
||||||
|
|
|
@ -3,8 +3,12 @@ static void Item_activate(Item *self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pItem::setImage(const image &image) {
|
void pItem::setImage(const image &image) {
|
||||||
GtkImage *gtkImage = CreateImage(image, /* menuIcon = */ true);
|
if(image.empty() == false) {
|
||||||
|
GtkImage *gtkImage = CreateImage(image, true);
|
||||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage);
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage);
|
||||||
|
} else {
|
||||||
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pItem::setText(const string &text) {
|
void pItem::setText(const string &text) {
|
||||||
|
|
|
@ -14,8 +14,12 @@ void pMenu::remove(Action &action) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenu::setImage(const image &image) {
|
void pMenu::setImage(const image &image) {
|
||||||
GtkImage *gtkImage = CreateImage(image, /* menuIcon = */ true);
|
if(image.empty() == false) {
|
||||||
|
GtkImage *gtkImage = CreateImage(image, true);
|
||||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage);
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage);
|
||||||
|
} else {
|
||||||
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenu::setText(const string &text) {
|
void pMenu::setText(const string &text) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue