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 {
|
||||
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 License[] = "GPLv3";
|
||||
}
|
||||
|
|
|
@ -44,7 +44,9 @@ struct directory {
|
|||
}
|
||||
|
||||
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;
|
||||
return (result & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
|
|
@ -20,13 +20,15 @@ struct FamicomCartridge {
|
|||
};
|
||||
|
||||
FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
|
||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||
markup = "";
|
||||
if(size < 16) return;
|
||||
if(data[0] != 'N') return;
|
||||
if(data[1] != 'E') return;
|
||||
if(data[2] != 'S') return;
|
||||
if(data[3] != 26) return;
|
||||
|
||||
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||
|
||||
mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
|
||||
mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
|
||||
prgrom = data[4] * 0x4000;
|
||||
|
|
|
@ -45,7 +45,9 @@ GameBoyAdvanceCartridge::GameBoyAdvanceCartridge(const uint8_t *data, unsigned s
|
|||
}
|
||||
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(" <rom name='program.rom' size='0x", hex(size), "'/>\n");
|
||||
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) {
|
||||
markup = "";
|
||||
if(size < 0x8000) return;
|
||||
|
||||
read_header(data, size);
|
||||
|
||||
string xml;
|
||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||
markup = "";
|
||||
if(type == TypeGameBoy) return;
|
||||
if(type == TypeBsx) return;
|
||||
if(type == TypeSufamiTurbo) return;
|
||||
|
||||
if(type == TypeBsx) {
|
||||
markup.append("<cartridge/>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == TypeSufamiTurbo) {
|
||||
markup.append("<cartridge/>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == TypeGameBoy) {
|
||||
markup.append("<cartridge/>\n");
|
||||
return;
|
||||
}
|
||||
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||
|
||||
const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
|
||||
markup.append("<cartridge region='", region == NTSC ? "NTSC" : "PAL", "'>\n");
|
||||
|
@ -302,7 +294,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
|||
" <map mode='direct' address='80-bf:6000-7fff'/>\n"
|
||||
" </ram>\n"
|
||||
" </mcu>\n"
|
||||
" <iram >\n"
|
||||
" <iram>\n"
|
||||
" <map mode='linear' address='00-3f:3000-37ff'/>\n"
|
||||
" <map mode='linear' address='80-bf:3000-37ff'/>\n"
|
||||
" </iram>\n"
|
||||
|
|
|
@ -18,10 +18,26 @@ namespace nall {
|
|||
}
|
||||
|
||||
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 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) {
|
||||
return unlink(filename) == 0;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ ifeq ($(platform),x)
|
|||
endif
|
||||
else ifeq ($(platform),win)
|
||||
phoenixflags := -DPHOENIX_WINDOWS
|
||||
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32
|
||||
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
|
||||
else
|
||||
phoenixflags := -DPHOENIX_REFERENCE
|
||||
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() {
|
||||
state.selection = 0;
|
||||
state.text.reset();
|
||||
|
@ -1056,6 +1066,12 @@ void ListView::modify_(unsigned row, const lstring &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() {
|
||||
state.checked.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...}); }
|
||||
|
||||
void append_(const nall::lstring &list);
|
||||
void modify(unsigned row, const nall::string &text);
|
||||
void remove(unsigned row);
|
||||
void reset();
|
||||
unsigned selection();
|
||||
void setSelection(unsigned row);
|
||||
|
@ -499,6 +501,7 @@ struct ListView : private nall::base_from_member<pListView&>, Widget {
|
|||
void autoSizeColumns();
|
||||
bool checked(unsigned row);
|
||||
void modify_(unsigned row, const nall::lstring &list);
|
||||
void remove(unsigned row);
|
||||
void reset();
|
||||
bool selected();
|
||||
unsigned selection();
|
||||
|
|
|
@ -287,6 +287,8 @@ struct pComboBox : public pWidget {
|
|||
unsigned itemCounter;
|
||||
|
||||
void append(const string &text);
|
||||
void modify(unsigned row, const string &text);
|
||||
void remove(unsigned row);
|
||||
Geometry minimumGeometry();
|
||||
void reset();
|
||||
unsigned selection();
|
||||
|
@ -393,6 +395,7 @@ struct pListView : public pWidget {
|
|||
void autoSizeColumns();
|
||||
bool checked(unsigned row);
|
||||
void modify(unsigned row, const lstring &text);
|
||||
void remove(unsigned row);
|
||||
void reset();
|
||||
bool selected();
|
||||
unsigned selection();
|
||||
|
|
|
@ -18,6 +18,23 @@ Geometry pComboBox::minimumGeometry() {
|
|||
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() {
|
||||
locked = true;
|
||||
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);
|
||||
}
|
||||
|
||||
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() {
|
||||
listView.state.selected = false;
|
||||
listView.state.selection = 0;
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <commctrl.h>
|
||||
#include <io.h>
|
||||
#include <shlobj.h>
|
||||
#include <nall/windows/registry.hpp>
|
||||
#include <nall/windows/utf8.hpp>
|
||||
#elif defined(PHOENIX_QT)
|
||||
#include <QApplication>
|
||||
#include <QtGui>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
** 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)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
|
|
|
@ -354,6 +354,8 @@ public:
|
|||
QComboBox *qtComboBox;
|
||||
|
||||
void append(const string &text);
|
||||
void modify(unsigned row, const string &text);
|
||||
void remove(unsigned row);
|
||||
Geometry minimumGeometry();
|
||||
void reset();
|
||||
unsigned selection();
|
||||
|
@ -486,6 +488,7 @@ public:
|
|||
void autoSizeColumns();
|
||||
bool checked(unsigned row);
|
||||
void modify(unsigned row, const lstring &text);
|
||||
void remove(unsigned row);
|
||||
void reset();
|
||||
bool selected();
|
||||
unsigned selection();
|
||||
|
|
|
@ -11,6 +11,18 @@ Geometry pComboBox::minimumGeometry() {
|
|||
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() {
|
||||
locked = true;
|
||||
while(qtComboBox->count()) qtComboBox->removeItem(0);
|
||||
|
|
|
@ -23,13 +23,21 @@ bool pListView::checked(unsigned row) {
|
|||
void pListView::modify(unsigned row, const lstring &text) {
|
||||
locked = true;
|
||||
QTreeWidgetItem *item = qtListView->topLevelItem(row);
|
||||
if(!item) return;
|
||||
if(item == nullptr) return;
|
||||
for(unsigned n = 0; n < text.size(); n++) {
|
||||
item->setText(n, QString::fromUtf8(text[n]));
|
||||
}
|
||||
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() {
|
||||
qtListView->clear();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ bool pRadioItem::checked() {
|
|||
void pRadioItem::setChecked() {
|
||||
}
|
||||
|
||||
void pRadioItem::setGroup(const array<RadioItem&> &group) {
|
||||
void pRadioItem::setGroup(const set<RadioItem&> &group) {
|
||||
}
|
||||
|
||||
void pRadioItem::setText(const string &text) {
|
||||
|
|
|
@ -2,8 +2,8 @@ bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
|||
return false;
|
||||
}
|
||||
|
||||
array<bool> pKeyboard::state() {
|
||||
array<bool> output;
|
||||
vector<bool> pKeyboard::state() {
|
||||
vector<bool> output;
|
||||
output.resize((unsigned)Keyboard::Scancode::Limit);
|
||||
for(auto &n : output) n = false;
|
||||
return output;
|
||||
|
|
|
@ -15,7 +15,7 @@ struct pDesktop {
|
|||
|
||||
struct pKeyboard {
|
||||
static bool pressed(Keyboard::Scancode scancode);
|
||||
static array<bool> state();
|
||||
static vector<bool> state();
|
||||
};
|
||||
|
||||
struct pMouse {
|
||||
|
@ -157,7 +157,7 @@ struct pRadioItem : public pAction {
|
|||
|
||||
bool checked();
|
||||
void setChecked();
|
||||
void setGroup(const array<RadioItem&> &group);
|
||||
void setGroup(const set<RadioItem&> &group);
|
||||
void setText(const string &text);
|
||||
|
||||
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
||||
|
@ -227,6 +227,8 @@ struct pComboBox : public pWidget {
|
|||
ComboBox &comboBox;
|
||||
|
||||
void append(const string &text);
|
||||
void modify(unsigned row, const string &text);
|
||||
void remove(unsigned row);
|
||||
void reset();
|
||||
unsigned selection();
|
||||
void setSelection(unsigned row);
|
||||
|
@ -297,6 +299,7 @@ struct pListView : public pWidget {
|
|||
void autoSizeColumns();
|
||||
bool checked(unsigned row);
|
||||
void modify(unsigned row, const lstring &text);
|
||||
void remove(unsigned row);
|
||||
void reset();
|
||||
bool selected();
|
||||
unsigned selection();
|
||||
|
@ -304,6 +307,7 @@ struct pListView : public pWidget {
|
|||
void setChecked(unsigned row, bool checked);
|
||||
void setHeaderText(const lstring &text);
|
||||
void setHeaderVisible(bool visible);
|
||||
void setImage(unsigned row, unsigned column, const image &image);
|
||||
void setSelected(bool selected);
|
||||
void setSelection(unsigned row);
|
||||
|
||||
|
@ -325,7 +329,7 @@ struct pRadioBox : public pWidget {
|
|||
|
||||
bool checked();
|
||||
void setChecked();
|
||||
void setGroup(const array<RadioBox&> &group);
|
||||
void setGroup(const set<RadioBox&> &group);
|
||||
void setText(const string &text);
|
||||
|
||||
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
void pComboBox::append(const string &text) {
|
||||
}
|
||||
|
||||
void pComboBox::modify(unsigned row, const string &text) {
|
||||
}
|
||||
|
||||
void pComboBox::remove(unsigned row) {
|
||||
}
|
||||
|
||||
void pComboBox::reset() {
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@ bool pListView::checked(unsigned row) {
|
|||
void pListView::modify(unsigned row, const lstring &text) {
|
||||
}
|
||||
|
||||
void pListView::remove(unsigned row) {
|
||||
}
|
||||
|
||||
void pListView::reset() {
|
||||
}
|
||||
|
||||
|
@ -33,6 +36,9 @@ void pListView::setHeaderText(const lstring &text) {
|
|||
void pListView::setHeaderVisible(bool visible) {
|
||||
}
|
||||
|
||||
void pListView::setImage(unsigned row, unsigned column, const image &image) {
|
||||
}
|
||||
|
||||
void pListView::setSelected(bool selected) {
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ bool pRadioBox::checked() {
|
|||
void pRadioBox::setChecked() {
|
||||
}
|
||||
|
||||
void pRadioBox::setGroup(const array<RadioBox&> &group) {
|
||||
void pRadioBox::setGroup(const set<RadioBox&> &group) {
|
||||
}
|
||||
|
||||
void pRadioBox::setText(const string &text) {
|
||||
|
|
|
@ -23,6 +23,13 @@ static string FileDialog(bool save, Window &parent, const string &path, const ls
|
|||
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;
|
||||
memset(&ofn, 0, 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="*"/>
|
||||
</dependentAssembly>
|
||||
</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>
|
||||
|
|
|
@ -384,6 +384,20 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
|||
}
|
||||
} else if(nmhdr->code == LVN_ITEMACTIVATE) {
|
||||
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;
|
||||
|
|
|
@ -283,6 +283,8 @@ struct pComboBox : public pWidget {
|
|||
ComboBox &comboBox;
|
||||
|
||||
void append(const string &text);
|
||||
void modify(unsigned row, const string &text);
|
||||
void remove(unsigned row);
|
||||
Geometry minimumGeometry();
|
||||
void reset();
|
||||
unsigned selection();
|
||||
|
@ -375,6 +377,7 @@ struct pListView : public pWidget {
|
|||
void autoSizeColumns();
|
||||
bool checked(unsigned row);
|
||||
void modify(unsigned row, const lstring &text);
|
||||
void remove(unsigned row);
|
||||
void reset();
|
||||
bool selected();
|
||||
unsigned selection();
|
||||
|
|
|
@ -9,6 +9,23 @@ Geometry pComboBox::minimumGeometry() {
|
|||
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() {
|
||||
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) {
|
||||
wchar_t empty[] = L"";
|
||||
unsigned row = ListView_GetItemCount(hwnd);
|
||||
LVITEM item;
|
||||
item.mask = LVIF_TEXT | LVIF_IMAGE;
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = row;
|
||||
item.iSubItem = 0;
|
||||
item.iImage = row;
|
||||
item.pszText = empty;
|
||||
locked = true;
|
||||
ListView_InsertItem(hwnd, &item);
|
||||
locked = false;
|
||||
for(unsigned n = 0; n < list.size(); n++) {
|
||||
utf16_t wtext(list[n]);
|
||||
ListView_SetItemText(hwnd, row, n, wtext);
|
||||
for(unsigned column = 0; column < list.size(); column++) {
|
||||
utf16_t wtext(list(column, ""));
|
||||
ListView_SetItemText(hwnd, row, column, wtext);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +36,16 @@ bool pListView::checked(unsigned row) {
|
|||
|
||||
void pListView::modify(unsigned row, const lstring &list) {
|
||||
for(unsigned n = 0; n < list.size(); n++) {
|
||||
utf16_t wtext(list[n]);
|
||||
utf16_t wtext(list(n, ""));
|
||||
ListView_SetItemText(hwnd, row, n, wtext);
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::remove(unsigned row) {
|
||||
ListView_DeleteItem(hwnd, row);
|
||||
setImageList();
|
||||
}
|
||||
|
||||
void pListView::reset() {
|
||||
ListView_DeleteAllItems(hwnd);
|
||||
}
|
||||
|
@ -54,7 +67,7 @@ unsigned pListView::selection() {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -90,7 +103,6 @@ void pListView::setHeaderVisible(bool visible) {
|
|||
}
|
||||
|
||||
void pListView::setImage(unsigned row, unsigned column, const image &image) {
|
||||
if(column != 0) return; //ListView can only set icons on first column
|
||||
setImageList();
|
||||
}
|
||||
|
||||
|
@ -124,9 +136,9 @@ void pListView::constructor() {
|
|||
setHeaderText(listView.state.headerText);
|
||||
setHeaderVisible(listView.state.headerVisible);
|
||||
setCheckable(listView.state.checkable);
|
||||
setImageList();
|
||||
for(auto &text : listView.state.text) append(text);
|
||||
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);
|
||||
autoSizeColumns();
|
||||
synchronize();
|
||||
|
@ -147,31 +159,52 @@ void pListView::setGeometry(const Geometry &geometry) {
|
|||
}
|
||||
|
||||
void pListView::setImageList() {
|
||||
auto &list = listView.state.image;
|
||||
|
||||
if(imageList) {
|
||||
ImageList_Destroy(imageList);
|
||||
imageList = nullptr;
|
||||
}
|
||||
|
||||
unsigned images = 0;
|
||||
for(auto &image : listView.state.image) {
|
||||
if(image.empty() == false) images++;
|
||||
bool found = false;
|
||||
for(auto &row : listView.state.image) {
|
||||
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.scale(16, 16, Interpolation::Linear);
|
||||
HBITMAP hbitmap = CreateBitmap(image);
|
||||
ImageList_Add(imageList, hbitmap, NULL);
|
||||
image.scale(15, 15, Interpolation::Linear);
|
||||
ImageList_Add(imageList, CreateBitmap(image), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
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">
|
||||
<rom name="program.rom" size="0x100000"/>
|
||||
<ram name="save.ram" size="0x8000"/>
|
||||
<bsx>
|
||||
<psram name="bsx.ram" size="0x40000"/>
|
||||
<bsx>
|
||||
<mcu>
|
||||
<map address="00-3f:8000-ffff"/>
|
||||
<map address="80-bf:8000-ffff"/>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<system type="NES">
|
||||
<system name="Famicom">
|
||||
</system>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<system type="GBA">
|
||||
<system name="Game Boy Advance">
|
||||
<bios firmware="bios.rom" sha256="fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570"/>
|
||||
</system>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<system type="GBC">
|
||||
<system name="Game Boy Color">
|
||||
<boot firmware="boot.rom" sha256="4bf5021be357ce523a59ac5f4efff5d6371ae50112a6db0adf4a75916ad760a9"/>
|
||||
</system>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<system type="GB">
|
||||
<system name="Game Boy">
|
||||
<boot firmware="boot.rom" sha256="cf053eccb4ccafff9e67339d4e78e98dce7d1ed59be819d2a1ba2232c6fce1c7"/>
|
||||
</system>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<system type="SNES">
|
||||
<system name="Super Famicom">
|
||||
<smp firmware="spc700.rom" sha256="c95f88b299030d5afa55b1031e2b5ef2dff650c4b4e6bb6f8b1359436521278f"/>
|
||||
</system>
|
||||
|
|
|
@ -80,6 +80,7 @@ private:
|
|||
|
||||
void parse_markup_rom(XML::Node&);
|
||||
void parse_markup_ram(XML::Node&);
|
||||
void parse_markup_psram(XML::Node&);
|
||||
void parse_markup_icd2(XML::Node&);
|
||||
void parse_markup_bsx(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_ram(cartridge["ram"]);
|
||||
parse_markup_psram(cartridge["psram"]);
|
||||
parse_markup_icd2(cartridge["icd2"]);
|
||||
parse_markup_bsx(cartridge["bsx"]);
|
||||
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) {
|
||||
if(root.exists() == false) return;
|
||||
has_gb_slot = true;
|
||||
|
@ -121,10 +127,6 @@ void Cartridge::parse_markup_bsx(XML::Node &root) {
|
|||
|
||||
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"]) {
|
||||
if(node.name != "map") continue;
|
||||
if(bsxflash.memory.size() == 0) continue;
|
||||
|
@ -228,7 +230,6 @@ void Cartridge::parse_markup_sa1(XML::Node &root) {
|
|||
mapping.append(m);
|
||||
}
|
||||
|
||||
parse_markup_memory(ram, bwram, ID::RAM, true);
|
||||
for(auto &node : bwram) {
|
||||
if(node.name != "map") continue;
|
||||
Mapping m(sa1.cpubwram);
|
||||
|
|
|
@ -1,34 +1,40 @@
|
|||
include nall/Makefile
|
||||
include phoenix/Makefile
|
||||
|
||||
application := purify
|
||||
resource :=
|
||||
flags := -std=gnu++0x -I. -O3 -fomit-frame-pointer
|
||||
link := -s
|
||||
|
||||
ifeq ($(platform),win)
|
||||
flags += -DPHOENIX_WINDOWS
|
||||
link += -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32
|
||||
else ifeq ($(phoenix),qt)
|
||||
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`
|
||||
resource := resource.o
|
||||
flags := -m32 -mwindows $(flags)
|
||||
link := -m32 -mwindows $(flags)
|
||||
endif
|
||||
|
||||
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
|
||||
$(cpp) -c -o phoenix.o phoenix/phoenix.cpp $(flags)
|
||||
phoenix.o:
|
||||
$(cpp) -c -o phoenix.o phoenix/phoenix.cpp $(flags) $(phoenixflags)
|
||||
|
||||
$(application).o: $(application).cpp
|
||||
$(cpp) -c -o $(application).o $(application).cpp $(flags)
|
||||
|
||||
resource: force
|
||||
sourcery resource/resource.xml resource/resource.cpp resource/resource.hpp
|
||||
|
||||
install:
|
||||
sudo cp $(application) /usr/local/bin/$(application)
|
||||
|
||||
uninstall:
|
||||
sudo rm /usr/local/bin/$(application)
|
||||
|
||||
clean:
|
||||
$(delete) *.o
|
||||
-@$(call delete,*.o)
|
||||
|
||||
sync:
|
||||
if [ -d ./nall ]; then rm -r ./nall; fi
|
||||
|
@ -36,4 +42,7 @@ sync:
|
|||
cp -r ../nall ./nall
|
||||
cp -r ../phoenix ./phoenix
|
||||
rm -r nall/test
|
||||
rm -r phoenix/nall
|
||||
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)
|
||||
compiler := gcc
|
||||
else ifeq ($(platform),osx)
|
||||
compiler := gcc-mp-4.6
|
||||
compiler := gcc-mp-4.7
|
||||
else
|
||||
compiler := gcc-4.6
|
||||
compiler := gcc-4.7
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define NALL_ANY_HPP
|
||||
|
||||
#include <typeinfo>
|
||||
#include <nall/type_traits.hpp>
|
||||
#include <nall/traits.hpp>
|
||||
|
||||
namespace nall {
|
||||
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
|
||||
#define NALL_BIT_HPP
|
||||
|
||||
#include <nall/stdint.hpp>
|
||||
|
||||
namespace nall {
|
||||
template<unsigned bits>
|
||||
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 {
|
||||
|
||||
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 lstring folders(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)
|
||||
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) {
|
||||
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;
|
||||
return (result & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
@ -94,6 +115,21 @@ struct directory {
|
|||
return folders;
|
||||
}
|
||||
#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) {
|
||||
DIR *dp = opendir(pathname);
|
||||
if(!dp) return false;
|
||||
|
|
|
@ -1,29 +1,40 @@
|
|||
#ifndef NALL_NES_CARTRIDGE_HPP
|
||||
#define NALL_NES_CARTRIDGE_HPP
|
||||
#ifndef NALL_EMULATION_FAMICOM_HPP
|
||||
#define NALL_EMULATION_FAMICOM_HPP
|
||||
|
||||
#include <nall/sha256.hpp>
|
||||
#include <nall/string.hpp>
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct FamicomCartridge {
|
||||
string markup;
|
||||
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) {
|
||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||
markup = "";
|
||||
if(size < 16) return;
|
||||
if(data[0] != 'N') return;
|
||||
if(data[1] != 'E') return;
|
||||
if(data[2] != 'S') return;
|
||||
if(data[3] != 26) return;
|
||||
|
||||
unsigned mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
|
||||
unsigned mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
|
||||
unsigned prgrom = data[4] * 0x4000;
|
||||
unsigned chrrom = data[5] * 0x2000;
|
||||
unsigned prgram = 0u;
|
||||
unsigned chrram = chrrom == 0u ? 8192u : 0u;
|
||||
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||
|
||||
mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
|
||||
mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
|
||||
prgrom = data[4] * 0x4000;
|
||||
chrrom = data[5] * 0x2000;
|
||||
prgram = 0u;
|
||||
chrram = chrrom == 0u ? 8192u : 0u;
|
||||
|
||||
markup.append("<cartridge sha256='", sha256(data, size), "'>\n");
|
||||
|
||||
|
@ -153,13 +164,13 @@ FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
|
|||
}
|
||||
|
||||
markup.append(" <prg>\n");
|
||||
if(prgrom) markup.append(" <rom size='", prgrom, "'/>\n");
|
||||
if(prgram) markup.append(" <ram size='", prgram, "' nonvolatile='true'/>\n");
|
||||
if(prgrom) markup.append(" <rom name='program.rom' size='0x", hex(prgrom), "'/>\n");
|
||||
if(prgram) markup.append(" <ram name='save.ram' size='0x", hex(prgram), "'/>\n");
|
||||
markup.append(" </prg>\n");
|
||||
|
||||
markup.append(" <chr>\n");
|
||||
if(chrrom) markup.append(" <rom size='", chrrom, "'/>\n");
|
||||
if(chrram) markup.append(" <ram size='", chrram, "'/>\n");
|
||||
if(chrrom) markup.append(" <rom name='character.rom' size='0x", hex(chrrom), "'/>\n");
|
||||
if(chrram) markup.append(" <ram size='0x", hex(chrram), "'/>\n");
|
||||
markup.append(" </chr>\n");
|
||||
|
||||
markup.append("</cartridge>\n");
|
|
@ -1,7 +1,8 @@
|
|||
#ifndef NALL_GBA_CARTRIDGE_HPP
|
||||
#define NALL_GBA_CARTRIDGE_HPP
|
||||
#ifndef NALL_EMULATION_GAME_BOY_ADVANCE_HPP
|
||||
#define NALL_EMULATION_GAME_BOY_ADVANCE_HPP
|
||||
|
||||
#include <nall/sha256.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
|
||||
namespace nall {
|
||||
|
@ -44,16 +45,18 @@ GameBoyAdvanceCartridge::GameBoyAdvanceCartridge(const uint8_t *data, unsigned s
|
|||
}
|
||||
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(" <rom size='", size, "'/>\n");
|
||||
markup.append(" <rom name='program.rom' size='0x", hex(size), "'/>\n");
|
||||
if(0);
|
||||
else if(identifiers.beginswith("SRAM_V" )) markup.append(" <ram type='SRAM' size='32768'/>\n");
|
||||
else if(identifiers.beginswith("SRAM_F_V" )) markup.append(" <ram type='FRAM' size='32768'/>\n");
|
||||
else if(identifiers.beginswith("EEPROM_V" )) markup.append(" <ram type='EEPROM' size='0'/>\n");
|
||||
else if(identifiers.beginswith("FLASH_V" )) markup.append(" <ram type='FlashROM' size='65536'/>\n");
|
||||
else if(identifiers.beginswith("FLASH512_V")) markup.append(" <ram type='FlashROM' size='65536'/>\n");
|
||||
else if(identifiers.beginswith("FLASH1M_V" )) markup.append(" <ram type='FlashROM' size='131072'/>\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 name='save.ram' type='FRAM' size='0x8000'/>\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 name='save.ram' type='FlashROM' size='0x10000'/>\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 name='save.ram' type='FlashROM' size='0x20000'/>\n");
|
||||
if(identifiers.empty() == false) markup.append(" <!-- detected: ", identifiers, " -->\n");
|
||||
|
||||
markup.append("</cartridge>\n");
|
|
@ -1,5 +1,8 @@
|
|||
#ifndef NALL_GB_CARTRIDGE_HPP
|
||||
#define NALL_GB_CARTRIDGE_HPP
|
||||
#ifndef NALL_EMULATION_GAME_BOY_HPP
|
||||
#define NALL_EMULATION_GAME_BOY_HPP
|
||||
|
||||
#include <nall/sha256.hpp>
|
||||
#include <nall/string.hpp>
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
@ -17,6 +20,9 @@ struct GameBoyCartridge {
|
|||
|
||||
unsigned romsize;
|
||||
unsigned ramsize;
|
||||
|
||||
bool cgb;
|
||||
bool cgbonly;
|
||||
} info;
|
||||
};
|
||||
|
||||
|
@ -47,6 +53,9 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
|
|||
memcpy(romdata, header, 0x8000);
|
||||
}
|
||||
|
||||
info.cgb = (romdata[0x0143] & 0x80) == 0x80;
|
||||
info.cgbonly = (romdata[0x0143] & 0xc0) == 0xc0;
|
||||
|
||||
switch(romdata[0x0147]) {
|
||||
case 0x00: info.mapper = "none"; 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
|
||||
|
||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||
markup.append("<cartridge mapper='", info.mapper, "' rtc='", info.rtc, "' rumble='", info.rumble, "'>\n");
|
||||
markup.append(" <rom size='0x", hex(romsize), "'/>\n");
|
||||
if(info.ramsize > 0) markup.append(" <ram size='0x", hex(info.ramsize), "' nonvolatile='", info.battery, "'/>\n");
|
||||
markup.append("<cartridge>\n");
|
||||
markup.append(" <board type='", info.mapper, "'/>\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.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
|
||||
#define NALL_SNES_USART_HPP
|
||||
#ifndef NALL_EMULATION_SUPER_FAMICOM_USART_HPP
|
||||
#define NALL_EMULATION_SUPER_FAMICOM_USART_HPP
|
||||
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/function.hpp>
|
|
@ -1,5 +1,8 @@
|
|||
#ifndef NALL_SNES_CARTRIDGE_HPP
|
||||
#define NALL_SNES_CARTRIDGE_HPP
|
||||
#ifndef NALL_EMULATION_SUPER_FAMICOM_HPP
|
||||
#define NALL_EMULATION_SUPER_FAMICOM_HPP
|
||||
|
||||
#include <nall/sha256.hpp>
|
||||
#include <nall/string.hpp>
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
@ -11,8 +14,6 @@ struct SuperFamicomCartridge {
|
|||
inline void read_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 gameboy_ram_size(const uint8_t *data, unsigned size);
|
||||
inline bool gameboy_has_rtc(const uint8_t *data, unsigned size);
|
||||
|
||||
enum HeaderField {
|
||||
CartName = 0x00,
|
||||
|
@ -105,35 +106,23 @@ struct SuperFamicomCartridge {
|
|||
};
|
||||
|
||||
SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) {
|
||||
markup = "";
|
||||
if(size < 0x8000) return;
|
||||
|
||||
read_header(data, size);
|
||||
|
||||
string xml;
|
||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||
markup = "";
|
||||
if(type == TypeGameBoy) return;
|
||||
if(type == TypeBsx) return;
|
||||
if(type == TypeSufamiTurbo) return;
|
||||
|
||||
if(type == TypeBsx) {
|
||||
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;
|
||||
}
|
||||
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||
|
||||
const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
|
||||
markup.append("<cartridge region='", region == NTSC ? "NTSC" : "PAL", "'>\n");
|
||||
|
||||
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='80-ff:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
|
@ -144,6 +133,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
|||
);
|
||||
|
||||
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"
|
||||
" <rom>\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) {
|
||||
markup.append(
|
||||
" <rom>\n"
|
||||
" <map mode='shadow' address='00-0f:8000-ffff'/>\n"
|
||||
" <map mode='shadow' address='80-bf:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='c0-cf:0000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <rom name='program.rom' size='0x", hex(rom_size), "'/>\n"
|
||||
" <ram name='save.ram' size='", hex(ram_size), "'/>\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"
|
||||
" <map address='00-3f:4800-483f'/>\n"
|
||||
" <map address='80-bf:4800-483f'/>\n"
|
||||
" </mmio>\n"
|
||||
" <mcu>\n"
|
||||
" <map address='d0-ff:0000-ffff' offset='0x100000' size='0x", hex(size - 0x100000), "'/>\n"
|
||||
" </mcu>\n"
|
||||
" <dcu>\n"
|
||||
" <map address='50:0000-ffff'/>\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(
|
||||
" <rtc>\n"
|
||||
" <epsonrtc name='rtc.ram' size='0x10'>\n"
|
||||
" <map address='00-3f:4840-4842'/>\n"
|
||||
" <map address='80-bf:4840-4842'/>\n"
|
||||
" </rtc>\n"
|
||||
);
|
||||
markup.append(
|
||||
" </spc7110>\n"
|
||||
" </epsonrtc>\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == LoROM) {
|
||||
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='80-ff:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
);
|
||||
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='a0-bf:6000-7fff'/>\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) {
|
||||
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='linear' address='40-7f:0000-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"
|
||||
);
|
||||
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='a0-bf:6000-7fff'/>\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) {
|
||||
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='40-7f:0000-ffff'/>\n"
|
||||
" <map mode='linear' address='80-bf:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
);
|
||||
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='a0-bf:6000-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) {
|
||||
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='linear' address='40-7f:0000-ffff' offset='0x400000'/>\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"
|
||||
);
|
||||
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='a0-bf:6000-7fff'/>\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"
|
||||
" <rom>\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='c0-df:0000-ffff'/>\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='60-7f:0000-ffff'/>\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"
|
||||
" </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"
|
||||
" <mcu>\n"
|
||||
" <rom>\n"
|
||||
|
@ -294,11 +294,11 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
|||
" <map mode='direct' address='80-bf:6000-7fff'/>\n"
|
||||
" </ram>\n"
|
||||
" </mcu>\n"
|
||||
" <iram size='0x800'>\n"
|
||||
" <iram >\n"
|
||||
" <map mode='linear' address='00-3f:3000-37ff'/>\n"
|
||||
" <map mode='linear' address='80-bf:3000-37ff'/>\n"
|
||||
" </iram>\n"
|
||||
" <bwram size='0x", hex(ram_size), "'>\n"
|
||||
" <bwram>\n"
|
||||
" <map mode='linear' address='40-4f:0000-ffff'/>\n"
|
||||
" </bwram>\n"
|
||||
" <mmio>\n"
|
||||
|
@ -307,15 +307,16 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
|||
" </mmio>\n"
|
||||
" </sa1>\n"
|
||||
);
|
||||
}
|
||||
|
||||
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='20-3f:8000-ffff' offset='0x100000'/>\n"
|
||||
" <map mode='linear' address='80-9f:8000-ffff' offset='0x200000'/>\n"
|
||||
" <map mode='linear' address='a0-bf:8000-ffff' offset='0x100000'/>\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='f0-ff:0000-7fff'/>\n"
|
||||
" </ram>\n"
|
||||
|
@ -327,13 +328,13 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
|||
);
|
||||
|
||||
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='linear' address='40-5f:0000-ffff'/>\n"
|
||||
" <map mode='shadow' address='80-9f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='c0-df:0000-ffff'/>\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='a0-bf:6000-7fff'/>\n"
|
||||
" </ram>\n"
|
||||
|
@ -348,6 +349,9 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
|||
);
|
||||
|
||||
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"
|
||||
" <mcu>\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(
|
||||
" <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='80-9f:8000-ffff'/>\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='a0-bf:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <ram size='0x20000'>\n"
|
||||
" <ram>\n"
|
||||
" <map mode='linear' address='60-63:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='e0-e3:8000-ffff'/>\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='c0-df:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <ram size='0x20000'>\n"
|
||||
" <ram>\n"
|
||||
" <map mode='linear' address='70-73:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='f0-f3:8000-ffff'/>\n"
|
||||
" </ram>\n"
|
||||
|
@ -393,10 +397,10 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
|||
);
|
||||
|
||||
if(has_srtc) markup.append(
|
||||
" <srtc>\n"
|
||||
" <sharprtc name='rtc.ram' size='0x10'>\n"
|
||||
" <map address='00-3f:2800-2801'/>\n"
|
||||
" <map address='80-bf:2800-2801'/>\n"
|
||||
" </srtc>\n"
|
||||
" </sharprtc>\n"
|
||||
);
|
||||
|
||||
if(has_sdd1) markup.append(
|
||||
|
@ -535,6 +539,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
|||
);
|
||||
|
||||
markup.append("</cartridge>\n");
|
||||
markup.transform("'", "\"");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
|
@ -6,6 +6,7 @@
|
|||
#include <nall/string.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
#include <nall/windows/utf8.hpp>
|
||||
#include <nall/stream/memory.hpp>
|
||||
|
||||
namespace nall {
|
||||
inline FILE* fopen_utf8(const string &utf8_filename, const char *mode) {
|
||||
|
@ -16,25 +17,53 @@ namespace nall {
|
|||
#endif
|
||||
}
|
||||
|
||||
class file {
|
||||
public:
|
||||
enum class mode : unsigned { read, write, readwrite, writeread };
|
||||
struct file {
|
||||
enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append };
|
||||
enum class index : unsigned { absolute, relative };
|
||||
enum class time : unsigned { create, modify, access };
|
||||
|
||||
static bool read(const string &filename, uint8_t *&data, unsigned &size) {
|
||||
data = 0;
|
||||
file fp;
|
||||
if(fp.open(filename, mode::read) == false) return false;
|
||||
size = fp.size();
|
||||
data = new uint8_t[size];
|
||||
fp.read(data, size);
|
||||
fp.close();
|
||||
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 read(const string &filename, const uint8_t *&data, unsigned &size) {
|
||||
return file::read(filename, (uint8_t*&)data, size);
|
||||
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) {
|
||||
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) {
|
||||
|
@ -134,13 +163,13 @@ namespace nall {
|
|||
file_offset = req_offset;
|
||||
}
|
||||
|
||||
int offset() const {
|
||||
if(!fp) return -1; //file not open
|
||||
unsigned offset() const {
|
||||
if(!fp) return 0; //file not open
|
||||
return file_offset;
|
||||
}
|
||||
|
||||
int size() const {
|
||||
if(!fp) return -1; //file not open
|
||||
unsigned size() const {
|
||||
if(!fp) return 0; //file not open
|
||||
return file_size;
|
||||
}
|
||||
|
||||
|
@ -232,7 +261,7 @@ namespace nall {
|
|||
|
||||
file() {
|
||||
memset(buffer, 0, sizeof buffer);
|
||||
buffer_offset = -1;
|
||||
buffer_offset = -1; //invalidate buffer
|
||||
buffer_dirty = false;
|
||||
fp = 0;
|
||||
file_offset = 0;
|
||||
|
|
|
@ -19,12 +19,10 @@ struct gzip {
|
|||
};
|
||||
|
||||
bool gzip::decompress(const string &filename) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
if(file::read(filename, data, size) == false) return false;
|
||||
bool result = decompress(data, size);
|
||||
delete[] data;
|
||||
return result;
|
||||
if(auto memory = file::read(filename)) {
|
||||
return decompress(memory.data(), memory.size());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gzip::decompress(const uint8_t *data, unsigned size) {
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <nall/platform.hpp>
|
||||
|
|
|
@ -36,6 +36,8 @@ struct image {
|
|||
inline image(const 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(const string &filename);
|
||||
inline image(const uint8_t *data, unsigned size);
|
||||
inline image();
|
||||
inline ~image();
|
||||
|
||||
|
@ -43,6 +45,7 @@ struct image {
|
|||
inline void write(uint8_t *data, uint64_t value) const;
|
||||
|
||||
inline void free();
|
||||
inline bool empty() const;
|
||||
inline void allocate(unsigned width, unsigned height);
|
||||
inline void clear(uint64_t color);
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
width = 0, height = 0, pitch = 0;
|
||||
|
||||
|
@ -187,6 +222,12 @@ void image::free() {
|
|||
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) {
|
||||
if(data != nullptr && this->width == width && this->height == height) return;
|
||||
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 void source(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();
|
||||
|
||||
|
@ -88,14 +86,6 @@ void ips::modify(const uint8_t *data, unsigned 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) {
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ struct map {
|
|||
}
|
||||
|
||||
inline RHS& operator()(const LHS &name) {
|
||||
if(auto position = find(name)) return list[position()].data;
|
||||
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 blockStride;
|
||||
unsigned blockOffset;
|
||||
array<unsigned> block;
|
||||
vector<unsigned> block;
|
||||
|
||||
unsigned tileWidth;
|
||||
unsigned tileHeight;
|
||||
unsigned tileStride;
|
||||
unsigned tileOffset;
|
||||
array<unsigned> tile;
|
||||
vector<unsigned> tile;
|
||||
|
||||
unsigned mosaicWidth;
|
||||
unsigned mosaicHeight;
|
||||
unsigned mosaicStride;
|
||||
unsigned mosaicOffset;
|
||||
array<unsigned> mosaic;
|
||||
vector<unsigned> mosaic;
|
||||
|
||||
unsigned paddingWidth;
|
||||
unsigned paddingHeight;
|
||||
unsigned paddingColor;
|
||||
array<unsigned> palette;
|
||||
vector<unsigned> palette;
|
||||
|
||||
inline unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; }
|
||||
inline unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; }
|
||||
|
@ -52,7 +52,7 @@ struct context {
|
|||
return result;
|
||||
}
|
||||
|
||||
inline void eval(array<unsigned> &buffer, const string &expression_) {
|
||||
inline void eval(vector<unsigned> &buffer, const string &expression_) {
|
||||
string expression = expression_;
|
||||
bool function = false;
|
||||
for(auto &c : expression) {
|
||||
|
|
|
@ -60,10 +60,7 @@
|
|||
|
||||
#if defined(_WIN32)
|
||||
#define getcwd _getcwd
|
||||
#define ftruncate _chsize
|
||||
#define mkdir(n, m) _wmkdir(nall::utf16_t(n))
|
||||
#define putenv _putenv
|
||||
#define rmdir _rmdir
|
||||
#define vsnprintf _vsnprintf
|
||||
inline void usleep(unsigned milliseconds) { Sleep(milliseconds / 1000); }
|
||||
#endif
|
||||
|
@ -86,57 +83,4 @@
|
|||
#define alwaysinline inline
|
||||
#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
|
||||
|
||||
|
|
|
@ -58,12 +58,10 @@ protected:
|
|||
};
|
||||
|
||||
bool png::decode(const string &filename) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
if(file::read(filename, data, size) == false) return false;
|
||||
bool result = decode(data, size);
|
||||
delete[] data;
|
||||
return result;
|
||||
if(auto memory = file::read(filename)) {
|
||||
return decode(memory.data(), memory.size());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool png::decode(const uint8_t *sourceData, unsigned sourceSize) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef NALL_PRIORITYQUEUE_HPP
|
||||
#define NALL_PRIORITYQUEUE_HPP
|
||||
#ifndef NALL_PRIORITY_QUEUE_HPP
|
||||
#define NALL_PRIORITY_QUEUE_HPP
|
||||
|
||||
#include <limits>
|
||||
#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 {
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
struct filestream : stream {
|
||||
inline bool seekable() const { return true; }
|
||||
inline bool readable() const { return true; }
|
||||
inline bool writable() const { return pwritable; }
|
||||
inline bool randomaccess() const { return false; }
|
||||
using stream::read;
|
||||
using stream::write;
|
||||
|
||||
inline unsigned size() const { return pfile.size(); }
|
||||
inline unsigned offset() const { return pfile.offset(); }
|
||||
inline void seek(unsigned offset) const { pfile.seek(offset); }
|
||||
bool seekable() const { return true; }
|
||||
bool readable() const { return true; }
|
||||
bool writable() const { return pwritable; }
|
||||
bool randomaccess() const { return false; }
|
||||
|
||||
inline uint8_t read() const { return pfile.read(); }
|
||||
inline void write(uint8_t data) const { pfile.write(data); }
|
||||
unsigned size() const { return pfile.size(); }
|
||||
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);
|
||||
pwritable = pfile.open();
|
||||
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:
|
||||
mutable file pfile;
|
||||
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 {
|
||||
|
||||
struct gzipstream : memorystream {
|
||||
inline gzipstream(const stream &stream) {
|
||||
using stream::read;
|
||||
using stream::write;
|
||||
|
||||
gzipstream(const stream &stream) {
|
||||
unsigned size = stream.size();
|
||||
uint8_t *data = new uint8_t[size];
|
||||
stream.read(data, size);
|
||||
|
@ -18,7 +24,7 @@ struct gzipstream : memorystream {
|
|||
memcpy(pdata, archive.data, psize);
|
||||
}
|
||||
|
||||
inline ~gzipstream() {
|
||||
~gzipstream() {
|
||||
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 {
|
||||
|
||||
struct httpstream : stream {
|
||||
inline bool seekable() const { return true; }
|
||||
inline bool readable() const { return true; }
|
||||
inline bool writable() const { return true; }
|
||||
inline bool randomaccess() const { return true; }
|
||||
using stream::read;
|
||||
using stream::write;
|
||||
|
||||
inline unsigned size() const { return psize; }
|
||||
inline unsigned offset() const { return poffset; }
|
||||
inline void seek(unsigned offset) const { poffset = offset; }
|
||||
bool seekable() const { return true; }
|
||||
bool readable() const { return true; }
|
||||
bool writable() const { return true; }
|
||||
bool randomaccess() const { return true; }
|
||||
|
||||
inline uint8_t read() const { return pdata[poffset++]; }
|
||||
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]; }
|
||||
inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||
uint8_t read() const { return pdata[poffset++]; }
|
||||
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;
|
||||
uri.ltrim<1>("http://");
|
||||
lstring part = uri.split<1>("/");
|
||||
|
@ -29,7 +35,7 @@ struct httpstream : stream {
|
|||
connection.download(part[1], pdata, psize);
|
||||
}
|
||||
|
||||
inline ~httpstream() {
|
||||
~httpstream() {
|
||||
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 {
|
||||
|
||||
struct memorystream : stream {
|
||||
inline bool seekable() const { return true; }
|
||||
inline bool readable() const { return true; }
|
||||
inline bool writable() const { return pwritable; }
|
||||
inline bool randomaccess() const { return true; }
|
||||
using stream::read;
|
||||
using stream::write;
|
||||
|
||||
inline unsigned size() const { return psize; }
|
||||
inline unsigned offset() const { return poffset; }
|
||||
inline void seek(unsigned offset) const { poffset = offset; }
|
||||
bool seekable() const { return true; }
|
||||
bool readable() const { return true; }
|
||||
bool writable() const { return pwritable; }
|
||||
bool randomaccess() const { return true; }
|
||||
|
||||
inline uint8_t read() const { return pdata[poffset++]; }
|
||||
inline void write(uint8_t data) const { pdata[poffset++] = data; }
|
||||
uint8_t *data() const { return pdata; }
|
||||
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]; }
|
||||
inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||
uint8_t read() const { return pdata[poffset++]; }
|
||||
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;
|
||||
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;
|
||||
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 {
|
||||
|
||||
struct mmapstream : stream {
|
||||
inline bool seekable() const { return true; }
|
||||
inline bool readable() const { return true; }
|
||||
inline bool writable() const { return pwritable; }
|
||||
inline bool randomaccess() const { return false; }
|
||||
using stream::read;
|
||||
using stream::write;
|
||||
|
||||
inline unsigned size() const { return pmmap.size(); }
|
||||
inline unsigned offset() const { return poffset; }
|
||||
inline void seek(unsigned offset) const { poffset = offset; }
|
||||
bool seekable() const { return true; }
|
||||
bool readable() const { return true; }
|
||||
bool writable() const { return pwritable; }
|
||||
bool randomaccess() const { return true; }
|
||||
|
||||
inline uint8_t read() const { return pdata[poffset++]; }
|
||||
inline void write(uint8_t data) const { pdata[poffset++] = data; }
|
||||
unsigned size() const { return pmmap.size(); }
|
||||
unsigned offset() const { return poffset; }
|
||||
void seek(unsigned offset) const { poffset = offset; }
|
||||
|
||||
inline uint8_t read(unsigned offset) const { return pdata[offset]; }
|
||||
inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||
uint8_t read() const { return pdata[poffset++]; }
|
||||
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);
|
||||
pwritable = pmmap.open();
|
||||
if(!pwritable) pmmap.open(filename, filemap::mode::read);
|
||||
|
|
|
@ -9,6 +9,7 @@ struct stream {
|
|||
virtual bool writable() const = 0;
|
||||
virtual bool randomaccess() const = 0;
|
||||
|
||||
virtual uint8_t* data() const { return nullptr; }
|
||||
virtual unsigned size() const = 0;
|
||||
virtual unsigned offset() const = 0;
|
||||
virtual void seek(unsigned offset) const = 0;
|
||||
|
@ -16,44 +17,45 @@ struct stream {
|
|||
virtual uint8_t read() const = 0;
|
||||
virtual void write(uint8_t data) const = 0;
|
||||
|
||||
inline virtual uint8_t read(unsigned) const { return 0; }
|
||||
inline virtual void write(unsigned, uint8_t) const {}
|
||||
virtual uint8_t read(unsigned) const { return 0; }
|
||||
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();
|
||||
}
|
||||
|
||||
inline void copy(uint8_t *&data, unsigned &length) 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 readl(unsigned length = 1) const {
|
||||
uintmax_t data = 0, shift = 0;
|
||||
while(length--) { data |= read() << shift; shift += 8; }
|
||||
return data;
|
||||
}
|
||||
|
||||
inline uintmax_t readm(unsigned length = 1) const {
|
||||
uintmax_t readm(unsigned length = 1) const {
|
||||
uintmax_t data = 0;
|
||||
while(length--) data = (data << 8) | read();
|
||||
return data;
|
||||
}
|
||||
|
||||
inline void read(uint8_t *data, unsigned length) const {
|
||||
void read(uint8_t *data, unsigned length) const {
|
||||
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--) {
|
||||
write(data);
|
||||
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;
|
||||
while(length--) {
|
||||
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++);
|
||||
}
|
||||
|
||||
struct byte {
|
||||
inline operator uint8_t() const { return s.read(offset); }
|
||||
inline byte& operator=(uint8_t data) { s.write(offset, data); }
|
||||
inline byte(const stream &s, unsigned offset) : s(s), offset(offset) {}
|
||||
operator uint8_t() const { return s.read(offset); }
|
||||
byte& operator=(uint8_t data) { s.write(offset, data); }
|
||||
byte(const stream &s, unsigned offset) : s(s), offset(offset) {}
|
||||
|
||||
private:
|
||||
const stream &s;
|
||||
const unsigned offset;
|
||||
};
|
||||
|
||||
inline byte operator[](unsigned offset) const {
|
||||
byte operator[](unsigned offset) const {
|
||||
return byte(*this, offset);
|
||||
}
|
||||
|
||||
inline stream() {}
|
||||
inline virtual ~stream() {}
|
||||
stream() {}
|
||||
virtual ~stream() {}
|
||||
stream(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 {
|
||||
|
||||
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();
|
||||
uint8_t *data = new uint8_t[size];
|
||||
stream.read(data, size);
|
||||
|
@ -20,7 +26,7 @@ struct zipstream : memorystream {
|
|||
}
|
||||
}
|
||||
|
||||
inline ~zipstream() {
|
||||
~zipstream() {
|
||||
if(pdata) delete[] pdata;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
|
||||
#include <nall/array.hpp>
|
||||
#include <nall/atoi.hpp>
|
||||
#include <nall/function.hpp>
|
||||
#include <nall/platform.hpp>
|
||||
|
|
|
@ -112,6 +112,8 @@ namespace nall {
|
|||
struct lstring : vector<string> {
|
||||
inline optional<unsigned> find(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& isplit(const char*, const char*);
|
||||
|
@ -121,8 +123,14 @@ namespace nall {
|
|||
inline bool operator==(const lstring&) const;
|
||||
inline bool operator!=(const lstring&) const;
|
||||
|
||||
inline lstring();
|
||||
inline lstring(std::initializer_list<string>);
|
||||
inline lstring& operator=(const lstring&);
|
||||
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:
|
||||
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);
|
||||
|
||||
//platform.hpp
|
||||
inline string realpath(const char *name);
|
||||
inline string activepath();
|
||||
inline string realpath(const string &name);
|
||||
inline string userpath();
|
||||
inline string currentpath();
|
||||
inline string configpath();
|
||||
|
||||
//strm.hpp
|
||||
inline unsigned strmcpy(char *target, const char *source, unsigned length);
|
||||
|
|
|
@ -7,12 +7,12 @@ namespace nall {
|
|||
namespace BML {
|
||||
|
||||
inline static string indent(const char *s, unsigned depth) {
|
||||
array<char> output;
|
||||
vector<char> output;
|
||||
do {
|
||||
for(unsigned n = 0; n < depth; n++) output.append('\t');
|
||||
do output.append(*s); while(*s && *s++ != '\n');
|
||||
} while(*s);
|
||||
return output.get();
|
||||
return output.data();
|
||||
}
|
||||
|
||||
struct Node {
|
||||
|
|
|
@ -146,6 +146,11 @@ string lstring::concatenate(const char *separator) const {
|
|||
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 {
|
||||
if(this == &source) return true;
|
||||
if(size() != source.size()) return false;
|
||||
|
@ -159,11 +164,35 @@ bool lstring::operator!=(const lstring &source) const {
|
|||
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) {
|
||||
for(auto &data : list) append(data);
|
||||
lstring& lstring::operator=(lstring &source) {
|
||||
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 {
|
||||
|
||||
string currentpath() {
|
||||
char path[PATH_MAX];
|
||||
if(::getcwd(path)) {
|
||||
string result(path);
|
||||
string activepath() {
|
||||
string result;
|
||||
#ifdef _WIN32
|
||||
wchar_t path[PATH_MAX] = L"";
|
||||
_wgetcwd(path, PATH_MAX);
|
||||
result = (const char*)utf8_t(path);
|
||||
result.transform("\\", "/");
|
||||
#else
|
||||
char path[PATH_MAX] = "";
|
||||
getcwd(path, PATH_MAX);
|
||||
result = path;
|
||||
#endif
|
||||
if(result.empty()) result = ".";
|
||||
if(result.endswith("/") == false) result.append("/");
|
||||
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() {
|
||||
char path[PATH_MAX];
|
||||
if(::userpath(path)) {
|
||||
string result(path);
|
||||
string result;
|
||||
#ifdef _WIN32
|
||||
wchar_t path[PATH_MAX] = L"";
|
||||
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path);
|
||||
result = (const char*)utf8_t(path);
|
||||
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("/");
|
||||
return result;
|
||||
}
|
||||
return currentpath();
|
||||
}
|
||||
|
||||
string realpath(const char *name) {
|
||||
char path[PATH_MAX];
|
||||
if(::realpath(name, path)) {
|
||||
string result(path);
|
||||
result.transform("\\", "/");
|
||||
return result;
|
||||
}
|
||||
string configpath() {
|
||||
#ifdef _WIN32
|
||||
return userpath();
|
||||
#else
|
||||
return {userpath(), ".config/"};
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ struct Node {
|
|||
string name;
|
||||
string data;
|
||||
bool attribute;
|
||||
array<Node*> children;
|
||||
vector<Node*> children;
|
||||
|
||||
inline bool exists() const {
|
||||
return !name.empty();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef NALL_STATIC_HPP
|
||||
#define NALL_STATIC_HPP
|
||||
#ifndef NALL_TRAITS_HPP
|
||||
#define NALL_TRAITS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#define NALL_VARINT_HPP
|
||||
|
||||
#include <nall/bit.hpp>
|
||||
#include <nall/type_traits.hpp>
|
||||
#include <nall/traits.hpp>
|
||||
|
||||
namespace nall {
|
||||
template<unsigned bits> struct uint_t {
|
||||
|
|
|
@ -21,6 +21,10 @@ namespace nall {
|
|||
unsigned objectsize;
|
||||
|
||||
public:
|
||||
operator bool() const { return pool; }
|
||||
T* data() { return pool; }
|
||||
|
||||
bool empty() const { return pool == nullptr; }
|
||||
unsigned size() const { return objectsize; }
|
||||
unsigned capacity() const { return poolsize; }
|
||||
|
||||
|
@ -45,6 +49,13 @@ namespace nall {
|
|||
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>
|
||||
void append(const T& data, Args&&... args) {
|
||||
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 _WIN32_WINNT 0x0501
|
||||
#define NOMINMAX
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef interface
|
||||
|
||||
|
|
|
@ -80,28 +80,22 @@ struct zip {
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool extract(File &file, uint8_t *&data, unsigned &size) {
|
||||
data = 0, size = 0;
|
||||
inline vector<uint8_t> extract(File &file) {
|
||||
vector<uint8_t> buffer;
|
||||
|
||||
if(file.cmode == 0) {
|
||||
size = file.size;
|
||||
data = new uint8_t[size];
|
||||
memcpy(data, file.data, size);
|
||||
return true;
|
||||
buffer.resize(file.size);
|
||||
memcpy(buffer.data(), file.data, file.size);
|
||||
}
|
||||
|
||||
if(file.cmode == 8) {
|
||||
size = file.size;
|
||||
data = new uint8_t[size];
|
||||
if(inflate(data, size, file.data, file.csize) == false) {
|
||||
delete[] data;
|
||||
size = 0;
|
||||
return false;
|
||||
buffer.resize(file.size);
|
||||
if(inflate(buffer.data(), buffer.size(), file.data, file.csize) == false) {
|
||||
buffer.reset();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline void close() {
|
||||
|
|
|
@ -14,7 +14,7 @@ ifeq ($(platform),x)
|
|||
endif
|
||||
else ifeq ($(platform),win)
|
||||
phoenixflags := -DPHOENIX_WINDOWS
|
||||
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32
|
||||
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
|
||||
else
|
||||
phoenixflags := -DPHOENIX_REFERENCE
|
||||
phoenixlink :=
|
||||
|
|
|
@ -83,7 +83,7 @@ bool Keyboard::released(Keyboard::Scancode scancode) {
|
|||
return !pressed(scancode);
|
||||
}
|
||||
|
||||
array<bool> Keyboard::state() {
|
||||
vector<bool> Keyboard::state() {
|
||||
return pKeyboard::state();
|
||||
}
|
||||
|
||||
|
@ -326,6 +326,11 @@ void Window::setMenuVisible(bool visible) {
|
|||
return p.setMenuVisible(visible);
|
||||
}
|
||||
|
||||
void Window::setModal(bool modal) {
|
||||
state.modal = modal;
|
||||
return p.setModal(modal);
|
||||
}
|
||||
|
||||
void Window::setResizable(bool resizable) {
|
||||
state.resizable = resizable;
|
||||
return p.setResizable(resizable);
|
||||
|
@ -423,7 +428,7 @@ Action::~Action() {
|
|||
//Menu
|
||||
//====
|
||||
|
||||
void Menu::append(const array<Action&> &list) {
|
||||
void Menu::append(const set<Action&> &list) {
|
||||
for(auto &action : list) {
|
||||
if(state.action.append(action)) {
|
||||
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) {
|
||||
if(state.action.remove(action)) {
|
||||
action.state.menu = 0;
|
||||
|
@ -537,7 +542,7 @@ CheckItem::~CheckItem() {
|
|||
//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);
|
||||
if(list.size()) list[0].setChecked();
|
||||
}
|
||||
|
@ -557,6 +562,10 @@ void RadioItem::setText(const string &text) {
|
|||
return p.setText(text);
|
||||
}
|
||||
|
||||
string RadioItem::text() {
|
||||
return state.text;
|
||||
}
|
||||
|
||||
RadioItem::RadioItem():
|
||||
state(*new State),
|
||||
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() {
|
||||
state.selection = 0;
|
||||
state.text.reset();
|
||||
|
@ -845,6 +864,14 @@ void ComboBox::setSelection(unsigned row) {
|
|||
return p.setSelection(row);
|
||||
}
|
||||
|
||||
string ComboBox::text() {
|
||||
return state.text(selection());
|
||||
}
|
||||
|
||||
string ComboBox::text(unsigned row) {
|
||||
return state.text(row);
|
||||
}
|
||||
|
||||
ComboBox::ComboBox():
|
||||
state(*new State),
|
||||
base_from_member<pComboBox&>(*new pComboBox(*this)),
|
||||
|
@ -1039,8 +1066,15 @@ void ListView::modify_(unsigned row, const lstring &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() {
|
||||
state.checked.reset();
|
||||
state.image.reset();
|
||||
state.text.reset();
|
||||
return p.reset();
|
||||
}
|
||||
|
@ -1073,6 +1107,11 @@ void ListView::setHeaderVisible(bool 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) {
|
||||
state.selected = selected;
|
||||
return p.setSelected(selected);
|
||||
|
@ -1121,7 +1160,7 @@ ProgressBar::~ProgressBar() {
|
|||
//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);
|
||||
if(list.size()) list[0].setChecked();
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ struct Keyboard {
|
|||
#include "keyboard.hpp"
|
||||
static bool pressed(Scancode scancode);
|
||||
static bool released(Scancode scancode);
|
||||
static nall::array<bool> state();
|
||||
static nall::vector<bool> state();
|
||||
Keyboard() = delete;
|
||||
};
|
||||
|
||||
|
@ -199,6 +199,7 @@ struct Window : private nall::base_from_member<pWindow&>, Object {
|
|||
void setGeometry(const Geometry &geometry);
|
||||
void setMenuFont(const nall::string &font);
|
||||
void setMenuVisible(bool visible = true);
|
||||
void setModal(bool modal = true);
|
||||
void setResizable(bool resizable = true);
|
||||
void setStatusFont(const nall::string &font);
|
||||
void setStatusText(const nall::string &text);
|
||||
|
@ -231,12 +232,12 @@ struct Action : Object {
|
|||
};
|
||||
|
||||
struct Menu : private nall::base_from_member<pMenu&>, Action {
|
||||
template<typename... Args> void append(Args&... args) { append({ args... }); }
|
||||
template<typename... Args> void remove(Args&... args) { remove({ args... }); }
|
||||
template<typename... Args> void append(Args&... args) { append({args...}); }
|
||||
template<typename... Args> void remove(Args&... args) { remove({args...}); }
|
||||
|
||||
void append(const nall::array<Action&> &list);
|
||||
void remove(const nall::array<Action&> &list);
|
||||
void setImage(const nall::image &image);
|
||||
void append(const nall::set<Action&> &list);
|
||||
void remove(const nall::set<Action&> &list);
|
||||
void setImage(const nall::image &image = nall::image{});
|
||||
void setText(const nall::string &text);
|
||||
|
||||
Menu();
|
||||
|
@ -255,7 +256,7 @@ struct Separator : private nall::base_from_member<pSeparator&>, Action {
|
|||
struct Item : private nall::base_from_member<pItem&>, Action {
|
||||
nall::function<void ()> onActivate;
|
||||
|
||||
void setImage(const nall::image &image);
|
||||
void setImage(const nall::image &image = nall::image{});
|
||||
void setText(const nall::string &text);
|
||||
|
||||
Item();
|
||||
|
@ -280,14 +281,15 @@ struct CheckItem : private nall::base_from_member<pCheckItem&>, Action {
|
|||
};
|
||||
|
||||
struct RadioItem : private nall::base_from_member<pRadioItem&>, Action {
|
||||
template<typename... Args> static void group(Args&... args) { group({ args... }); }
|
||||
static void group(const nall::array<RadioItem&> &list);
|
||||
template<typename... Args> static void group(Args&... args) { group({args...}); }
|
||||
static void group(const nall::set<RadioItem&> &list);
|
||||
|
||||
nall::function<void ()> onActivate;
|
||||
|
||||
bool checked();
|
||||
void setChecked();
|
||||
void setText(const nall::string &text);
|
||||
nall::string text();
|
||||
|
||||
RadioItem();
|
||||
~RadioItem();
|
||||
|
@ -350,7 +352,7 @@ struct Widget : private nall::base_from_member<pWidget&>, Sizable {
|
|||
struct Button : private nall::base_from_member<pButton&>, Widget {
|
||||
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);
|
||||
|
||||
Button();
|
||||
|
@ -396,12 +398,16 @@ struct CheckBox : private nall::base_from_member<pCheckBox&>, Widget {
|
|||
struct ComboBox : private nall::base_from_member<pComboBox&>, Widget {
|
||||
nall::function<void ()> onChange;
|
||||
|
||||
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 modify(unsigned row, const nall::string &text);
|
||||
void remove(unsigned row);
|
||||
void reset();
|
||||
unsigned selection();
|
||||
void setSelection(unsigned row);
|
||||
nall::string text();
|
||||
nall::string text(unsigned row);
|
||||
|
||||
ComboBox();
|
||||
~ComboBox();
|
||||
|
@ -487,14 +493,15 @@ struct ListView : private nall::base_from_member<pListView&>, Widget {
|
|||
nall::function<void ()> onChange;
|
||||
nall::function<void (unsigned)> onToggle;
|
||||
|
||||
template<typename... Args> void append(const Args&... args) { append_({ args... }); }
|
||||
template<typename... Args> void modify(unsigned row, const Args&... args) { modify_(row, { args... }); }
|
||||
template<typename... Args> void setHeaderText(const Args&... args) { setHeaderText_({ args... }); }
|
||||
template<typename... Args> void append(const Args&... args) { append_({args...}); }
|
||||
template<typename... Args> void modify(unsigned row, const Args&... args) { modify_(row, {args...}); }
|
||||
template<typename... Args> void setHeaderText(const Args&... args) { setHeaderText_({args...}); }
|
||||
|
||||
void append_(const nall::lstring &list);
|
||||
void autoSizeColumns();
|
||||
bool checked(unsigned row);
|
||||
void modify_(unsigned row, const nall::lstring &list);
|
||||
void remove(unsigned row);
|
||||
void reset();
|
||||
bool selected();
|
||||
unsigned selection();
|
||||
|
@ -502,6 +509,7 @@ struct ListView : private nall::base_from_member<pListView&>, Widget {
|
|||
void setChecked(unsigned row, bool checked = true);
|
||||
void setHeaderText_(const nall::lstring &list);
|
||||
void setHeaderVisible(bool visible = true);
|
||||
void setImage(unsigned row, unsigned column, const nall::image &image = nall::image{});
|
||||
void setSelected(bool selected = true);
|
||||
void setSelection(unsigned row);
|
||||
|
||||
|
@ -523,8 +531,8 @@ struct ProgressBar : private nall::base_from_member<pProgressBar&>, Widget {
|
|||
};
|
||||
|
||||
struct RadioBox : private nall::base_from_member<pRadioBox&>, Widget {
|
||||
template<typename... Args> static void group(Args&... args) { group({ args... }); }
|
||||
static void group(const nall::array<RadioBox&> &list);
|
||||
template<typename... Args> static void group(Args&... args) { group({args...}); }
|
||||
static void group(const nall::set<RadioBox&> &list);
|
||||
|
||||
nall::function<void ()> onActivate;
|
||||
|
||||
|
|
|
@ -14,26 +14,28 @@ struct Window::State {
|
|||
bool fullScreen;
|
||||
Geometry geometry;
|
||||
bool ignore;
|
||||
array<Layout&> layout;
|
||||
array<Menu&> menu;
|
||||
set<Layout&> layout;
|
||||
set<Menu&> menu;
|
||||
string menuFont;
|
||||
bool menuVisible;
|
||||
bool modal;
|
||||
bool resizable;
|
||||
string statusFont;
|
||||
string statusText;
|
||||
bool statusVisible;
|
||||
string title;
|
||||
bool visible;
|
||||
array<Widget&> widget;
|
||||
set<Widget&> widget;
|
||||
string widgetFont;
|
||||
|
||||
State() {
|
||||
backgroundColorOverride = false;
|
||||
backgroundColor = { 0, 0, 0, 255 };
|
||||
backgroundColor = {0, 0, 0, 255};
|
||||
fullScreen = false;
|
||||
geometry = { 128, 128, 256, 256 };
|
||||
geometry = {128, 128, 256, 256};
|
||||
ignore = false;
|
||||
menuVisible = false;
|
||||
modal = false;
|
||||
resizable = true;
|
||||
statusVisible = false;
|
||||
visible = false;
|
||||
|
@ -55,7 +57,7 @@ struct Action::State {
|
|||
};
|
||||
|
||||
struct Menu::State {
|
||||
array<Action&> action;
|
||||
set<Action&> action;
|
||||
nall::image image;
|
||||
string text;
|
||||
|
||||
|
@ -82,7 +84,7 @@ struct CheckItem::State {
|
|||
|
||||
struct RadioItem::State {
|
||||
bool checked;
|
||||
array<RadioItem&> group;
|
||||
set<RadioItem&> group;
|
||||
string text;
|
||||
|
||||
State() {
|
||||
|
@ -115,7 +117,7 @@ struct Widget::State {
|
|||
State() {
|
||||
abstract = false;
|
||||
enabled = true;
|
||||
geometry = { 0, 0, 0, 0 };
|
||||
geometry = {0, 0, 0, 0};
|
||||
visible = true;
|
||||
}
|
||||
};
|
||||
|
@ -208,9 +210,10 @@ struct LineEdit::State {
|
|||
|
||||
struct ListView::State {
|
||||
bool checkable;
|
||||
array<bool> checked;
|
||||
vector<bool> checked;
|
||||
lstring headerText;
|
||||
bool headerVisible;
|
||||
vector<vector<nall::image>> image;
|
||||
bool selected;
|
||||
unsigned selection;
|
||||
vector<lstring> text;
|
||||
|
@ -233,7 +236,7 @@ struct ProgressBar::State {
|
|||
|
||||
struct RadioBox::State {
|
||||
bool checked;
|
||||
array<RadioBox&> group;
|
||||
set<RadioBox&> group;
|
||||
string text;
|
||||
|
||||
State() {
|
||||
|
|
|
@ -3,8 +3,12 @@ static void Item_activate(Item *self) {
|
|||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void pItem::setText(const string &text) {
|
||||
|
|
|
@ -14,8 +14,12 @@ void pMenu::remove(Action &action) {
|
|||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
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