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:
Tim Allen 2012-06-25 22:49:39 +10:00
parent 36795e8061
commit fbd52c7e5f
258 changed files with 2503 additions and 17004 deletions

View File

@ -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";
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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;
}

View File

@ -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 :=

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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))));

View File

@ -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;

View File

@ -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>

View File

@ -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!

View File

@ -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();

View File

@ -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);

View File

@ -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();
}

View File

@ -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) {

View File

@ -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;

View File

@ -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) {}

View File

@ -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() {
}

View File

@ -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) {
}

View File

@ -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) {

View File

@ -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);

View File

@ -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>

View File

@ -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;

View File

@ -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();

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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"/>

View File

@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<system type="NES">
<system name="Famicom">
</system>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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&);

View File

@ -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);

View File

@ -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:

View File

@ -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;
}

View File

@ -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

View File

@ -2,7 +2,7 @@
#define NALL_ANY_HPP
#include <typeinfo>
#include <nall/type_traits.hpp>
#include <nall/traits.hpp>
namespace nall {
struct any {

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -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");

View File

@ -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");

View File

@ -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("'", "\"");
}

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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>

View File

@ -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();

52
purify/nall/invoke.hpp Executable file
View File

@ -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

View File

@ -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) {
}

View File

@ -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());
}

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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) {

View File

@ -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>

View File

@ -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

View File

@ -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

158
purify/nall/set.hpp Executable file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,4 +1,5 @@
#ifdef NALL_STREAM_INTERNAL_HPP
#ifndef NALL_STREAM_AUTO_HPP
#define NALL_STREAM_AUTO_HPP
namespace nall {

View File

@ -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;

View File

@ -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;
}
};

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
};

39
purify/nall/stream/vector.hpp Executable file
View File

@ -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

View File

@ -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;
}
};

View File

@ -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>

View File

@ -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);

View File

@ -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 {

View File

@ -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));
}
}

View File

@ -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
}
}

View File

@ -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();

View File

@ -1,5 +1,5 @@
#ifndef NALL_STATIC_HPP
#define NALL_STATIC_HPP
#ifndef NALL_TRAITS_HPP
#define NALL_TRAITS_HPP
#include <type_traits>

View File

@ -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 {

View File

@ -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);

30
purify/nall/windows/guid.hpp Executable file
View File

@ -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

120
purify/nall/windows/registry.hpp Executable file
View File

@ -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

View File

@ -12,6 +12,7 @@
#define UNICODE
#define _WIN32_WINNT 0x0501
#define NOMINMAX
#include <winsock2.h>
#include <windows.h>
#undef interface

View File

@ -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() {

View File

@ -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 :=

View File

@ -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();
}

View File

@ -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);
@ -234,9 +235,9 @@ struct Menu : private nall::base_from_member<pMenu&>, Action {
template<typename... Args> void append(Args&... args) { append({args...}); }
template<typename... Args> void 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();
@ -281,13 +282,14 @@ 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);
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();
@ -399,9 +401,13 @@ 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);
nall::string text();
nall::string text(unsigned row);
ComboBox();
~ComboBox();
@ -495,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();
@ -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);
@ -524,7 +532,7 @@ 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);
static void group(const nall::set<RadioBox&> &list);
nall::function<void ()> onActivate;

View File

@ -14,17 +14,18 @@ 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() {
@ -34,6 +35,7 @@ struct Window::State {
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() {
@ -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() {

View File

@ -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) {

View File

@ -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