diff --git a/bsnes/nall/string.hpp b/bsnes/nall/string.hpp index 2341911c..884e31e8 100755 --- a/bsnes/nall/string.hpp +++ b/bsnes/nall/string.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include #undef NALL_STRING_INTERNAL_HPP diff --git a/bsnes/nall/string/base.hpp b/bsnes/nall/string/base.hpp index ede21ff6..33ff1c7a 100755 --- a/bsnes/nall/string/base.hpp +++ b/bsnes/nall/string/base.hpp @@ -128,8 +128,6 @@ namespace nall { inline char chrlower(char c); inline char chrupper(char c); inline int istrcmp(const char *str1, const char *str2); - inline bool wildcard(const char *str, const char *pattern); - inline bool iwildcard(const char *str, const char *pattern); inline bool strbegin(const char *str, const char *key); inline bool istrbegin(const char *str, const char *key); inline bool strend(const char *str, const char *key); @@ -190,6 +188,10 @@ namespace nall { //variadic.hpp template inline void print(Args&&... args); + + //wildcard.hpp + inline bool wildcard(const char *str, const char *pattern); + inline bool iwildcard(const char *str, const char *pattern); }; #endif diff --git a/bsnes/nall/string/cast.hpp b/bsnes/nall/string/cast.hpp index 452b6bec..12f525ad 100755 --- a/bsnes/nall/string/cast.hpp +++ b/bsnes/nall/string/cast.hpp @@ -2,39 +2,184 @@ namespace nall { -//this is needed, as C++0x does not support explicit template specialization inside classes -template<> inline const char* to_string(bool v) { return v ? "true" : "false"; } -template<> inline const char* to_string(char v) { static char temp[256]; return integer(temp, v); } +//convert any (supported) type to a const char* without constructing a new nall::string +//this is used inside istring(...) to build nall::string values +template struct stringify; -template<> inline const char* to_string (signed char v) { static char temp[256]; return integer(temp, v); } -template<> inline const char* to_string (signed short v) { static char temp[256]; return integer(temp, v); } -template<> inline const char* to_string (signed int v) { static char temp[256]; return integer(temp, v); } -template<> inline const char* to_string (signed long v) { static char temp[256]; return integer(temp, v); } -template<> inline const char* to_string(signed long long v) { static char temp[256]; return integer(temp, v); } +// base types -template<> inline const char* to_string (unsigned char v) { static char temp[256]; return decimal(temp, v); } -template<> inline const char* to_string (unsigned short v) { static char temp[256]; return decimal(temp, v); } -template<> inline const char* to_string (unsigned int v) { static char temp[256]; return decimal(temp, v); } -template<> inline const char* to_string (unsigned long v) { static char temp[256]; return decimal(temp, v); } -template<> inline const char* to_string(unsigned long long v) { static char temp[256]; return decimal(temp, v); } +template<> struct stringify { + bool value; + operator const char*() const { return value ? "true" : "false"; } + stringify(bool value) : value(value) {} +}; -template<> inline const char* to_string (float v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; } -template<> inline const char* to_string (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; } -template<> inline const char* to_string(long double v) { static char temp[256]; snprintf(temp, 255, "%Lf", v); return temp; } +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(char value) { integer(data, value); } +}; -template<> inline const char* to_string (char *v) { return v; } -template<> inline const char* to_string (const char *v) { return v; } -template<> inline const char* to_string (string v) { return v; } -template<> inline const char* to_string (const string &v) { return v; } -template<> inline const char* to_string (cstring v) { return v; } -template<> inline const char* to_string(const cstring &v) { return v; } +// signed integers + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(signed char value) { integer(data, value); } +}; + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(signed short value) { integer(data, value); } +}; + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(signed int value) { integer(data, value); } +}; + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(signed long value) { integer(data, value); } +}; + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(signed long long value) { integer(data, value); } +}; + +template struct stringify> { + char data[256]; + operator const char*() const { return data; } + stringify(int_t value) { integer(data, value); } +}; + +// unsigned integers + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(unsigned char value) { decimal(data, value); } +}; + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(unsigned short value) { decimal(data, value); } +}; + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(unsigned int value) { decimal(data, value); } +}; + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(unsigned long value) { decimal(data, value); } +}; + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(unsigned long long value) { decimal(data, value); } +}; + +template struct stringify> { + char data[256]; + operator const char*() const { return data; } + stringify(uint_t value) { decimal(data, value); } +}; + +// floating-point + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(float value) { snprintf(data, 255, "%f", value); } +}; + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(double value) { snprintf(data, 255, "%f", value); } +}; + +template<> struct stringify { + char data[256]; + operator const char*() const { return data; } + stringify(long double value) { snprintf(data, 255, "%Lf", value); } +}; + +// strings + +template<> struct stringify { + const char *value; + operator const char*() const { return value; } + stringify(char *value) : value(value) {} +}; + +template<> struct stringify { + const char *value; + operator const char*() const { return value; } + stringify(const char *value) : value(value) {} +}; + +template<> struct stringify { + const string &value; + operator const char*() const { return value; } + stringify(const string &value) : value(value) {} +}; + +template<> struct stringify { + const string &value; + operator const char*() const { return value; } + stringify(const string &value) : value(value) {} +}; + +template<> struct stringify { + const char *value; + operator const char*() const { return value; } + stringify(const cstring &value) : value(value) {} +}; + +template<> struct stringify { + const char *value; + operator const char*() const { return value; } + stringify(const cstring &value) : value(value) {} +}; #if defined(QSTRING_H) -template<> inline const char* to_string(QString v) { return v.toUtf8().constData(); } -template<> inline const char* to_string(const QString &v) { return v.toUtf8().constData(); } -string::operator QString() const { return QString::fromUtf8(*this); } + +template<> struct stringify { + const QString &value; + operator const char*() const { return value.toUtf8().constData(); } + stringify(const QString &value) : value(value) {} +}; + +template<> struct stringify { + const QString &value; + operator const char*() const { return value.toUtf8().constData(); } + stringify(const QString &value) : value(value) {} +}; + +string::operator QString() const { + return QString::fromUtf8(*this); +} + #endif +// + +template stringify make_string(T value) { + return stringify(std::forward(value)); +} + } #endif diff --git a/bsnes/nall/string/compare.hpp b/bsnes/nall/string/compare.hpp index ce0af487..941c8e67 100755 --- a/bsnes/nall/string/compare.hpp +++ b/bsnes/nall/string/compare.hpp @@ -18,46 +18,6 @@ int istrcmp(const char *str1, const char *str2) { return (int)chrlower(*str1) - (int)chrlower(*str2); } -bool wildcard(const char *s, const char *p) { - const char *cp = 0, *mp = 0; - while(*s && *p != '*') { - if(*p != '?' && *s != *p) return false; - p++, s++; - } - while(*s) { - if(*p == '*') { - if(!*++p) return true; - mp = p, cp = s + 1; - } else if(*p == '?' || *p == *s) { - p++, s++; - } else { - p = mp, s = cp++; - } - } - while(*p == '*') p++; - return !*p; -} - -bool iwildcard(const char *s, const char *p) { - const char *cp = 0, *mp = 0; - while(*s && *p != '*') { - if(*p != '?' && chrlower(*s) != chrlower(*p)) return false; - p++, s++; - } - while(*s) { - if(*p == '*') { - if(!*++p) return true; - mp = p, cp = s + 1; - } else if(*p == '?' || chrlower(*p) == chrlower(*s)) { - p++, s++; - } else { - p = mp, s = cp++; - } - } - while(*p == '*') p++; - return !*p; -} - bool strbegin(const char *str, const char *key) { int i, ssl = strlen(str), ksl = strlen(key); diff --git a/bsnes/nall/string/core.hpp b/bsnes/nall/string/core.hpp index 95a778a6..5ae2bd48 100755 --- a/bsnes/nall/string/core.hpp +++ b/bsnes/nall/string/core.hpp @@ -7,7 +7,7 @@ static void istring(string &output) { template static void istring(string &output, const T &value, Args&&... args) { - output.append_(to_string(value)); + output.append_(make_string(value)); istring(output, std::forward(args)...); } diff --git a/bsnes/nall/string/math.hpp b/bsnes/nall/string/math.hpp index bbe8e87d..8356e162 100755 --- a/bsnes/nall/string/math.hpp +++ b/bsnes/nall/string/math.hpp @@ -86,8 +86,8 @@ static int eval(const char *&s, int depth = 0) { if(depth >= 13) break; if(x == '*') { value *= eval(++s, 13); continue; } - if(x == '/') { value /= eval(++s, 13); continue; } - if(x == '%') { value %= eval(++s, 13); continue; } + if(x == '/') { int result = eval(++s, 13); if(result == 0) throw "division_by_zero"; value /= result; continue; } + if(x == '%') { int result = eval(++s, 13); if(result == 0) throw "division_by_zero"; value %= result; continue; } if(depth >= 12) break; if(x == '+') { value += eval(++s, 12); continue; } diff --git a/bsnes/nall/string/wildcard.hpp b/bsnes/nall/string/wildcard.hpp new file mode 100755 index 00000000..9d2359d5 --- /dev/null +++ b/bsnes/nall/string/wildcard.hpp @@ -0,0 +1,78 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +namespace nall { + +bool wildcard(const char *s, const char *p) { + const char *cp = 0, *mp = 0; + while(*s && *p != '*') { + if(*p != '?' && *s != *p) return false; + p++, s++; + } + while(*s) { + if(*p == '*') { + if(!*++p) return true; + mp = p, cp = s + 1; + } else if(*p == '?' || *p == *s) { + p++, s++; + } else { + p = mp, s = cp++; + } + } + while(*p == '*') p++; + return !*p; +} + +bool iwildcard(const char *s, const char *p) { + const char *cp = 0, *mp = 0; + while(*s && *p != '*') { + if(*p != '?' && chrlower(*s) != chrlower(*p)) return false; + p++, s++; + } + while(*s) { + if(*p == '*') { + if(!*++p) return true; + mp = p, cp = s + 1; + } else if(*p == '?' || chrlower(*p) == chrlower(*s)) { + p++, s++; + } else { + p = mp, s = cp++; + } + } + while(*p == '*') p++; + return !*p; +} + +inline bool tokenize(const char *s, const char *p) { + while(*s) { + if(*p == '*') { + while(*s) if(tokenize(s++, p + 1)) return true; + return !*++p; + } + if(*s++ != *p++) return false; + } + while(*p == '*') p++; + return !*p; +} + +inline bool tokenize(lstring &list, const char *s, const char *p) { + while(*s) { + if(*p == '*') { + const char *b = s; + while(*s) { + if(tokenize(list, s++, p + 1)) { + list.prepend(substr(b, 0, --s - b)); + return true; + } + } + list.prepend(b); + return !*++p; + } + if(*s++ != *p++) return false; + } + while(*p == '*') { list.prepend(s); p++; } + return !*p; +} + +} + +#endif diff --git a/bsnes/nall/vector.hpp b/bsnes/nall/vector.hpp index 7c605855..1af16d29 100755 --- a/bsnes/nall/vector.hpp +++ b/bsnes/nall/vector.hpp @@ -55,6 +55,11 @@ namespace nall { new(pool + objectsize++) T(data); } + void prepend(const T& data) { + append(data); + for(unsigned n = objectsize - 1; n; n--) swap(pool[n], pool[n - 1]); + } + void remove(unsigned index, unsigned count = 1) { for(unsigned n = index; count + n < objectsize; n++) { pool[n] = pool[count + n]; diff --git a/bsnes/phoenix/gtk/platform.cpp b/bsnes/phoenix/gtk/platform.cpp index 2b1ee30e..7cdb75bb 100755 --- a/bsnes/phoenix/gtk/platform.cpp +++ b/bsnes/phoenix/gtk/platform.cpp @@ -150,8 +150,6 @@ void pOS::processEvents() { } void pOS::quit() { - settings->save(); - gtk_main_quit(); } diff --git a/bsnes/phoenix/gtk/widget/list-view.cpp b/bsnes/phoenix/gtk/widget/list-view.cpp index 83efaaaa..712a135f 100755 --- a/bsnes/phoenix/gtk/widget/list-view.cpp +++ b/bsnes/phoenix/gtk/widget/list-view.cpp @@ -28,22 +28,17 @@ void pListView::autoSizeColumns() { bool pListView::checked(unsigned row) { GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget)); - GtkTreePath *path = gtk_tree_path_new_from_string(string(row)); GtkTreeIter iter; bool state; - gtk_tree_model_get_iter(model, &iter, path); + if(gtk_tree_model_get_iter_from_string(model, &iter, string(row)) == false) return false; gtk_tree_model_get(model, &iter, 0, &state, -1); - gtk_tree_path_free(path); return state; } void pListView::modify(unsigned row, const lstring &text) { GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget)); GtkTreeIter iter; - for(unsigned i = 0; i <= row; i++) { - if(i == 0) gtk_tree_model_get_iter_first(model, &iter); - else gtk_tree_model_iter_next(model, &iter); - } + gtk_tree_model_get_iter_from_string(model, &iter, string(row)); for(unsigned n = 0; n < text.size(); n++) gtk_list_store_set(store, &iter, 1 + n, (const char*)text[n], -1); } @@ -59,30 +54,18 @@ void pListView::reset() { bool pListView::selected() { GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget)); - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget)); - GtkTreeIter iter; - if(gtk_tree_model_get_iter_first(model, &iter) == false) return false; - if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return true; - for(unsigned n = 1;; n++) { - if(gtk_tree_model_iter_next(model, &iter) == false) return false; - if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return true; - } - return false; + return gtk_tree_selection_get_selected(selection, 0, 0); } unsigned pListView::selection() { - if(selected() == false) return listView.state.selection; - GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget)); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget)); GtkTreeIter iter; - if(gtk_tree_model_get_iter_first(model, &iter) == false) return 0; - if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return 0; - for(unsigned n = 1;; n++) { - if(gtk_tree_model_iter_next(model, &iter) == false) return 0; - if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return n; - } - return 0; + if(gtk_tree_selection_get_selected(selection, 0, &iter) == false) return listView.state.selection; + char *path = gtk_tree_model_get_string_from_iter(model, &iter); + unsigned row = decimal(path); + g_free(path); + return row; } void pListView::setCheckable(bool checkable) { @@ -91,11 +74,9 @@ void pListView::setCheckable(bool checkable) { void pListView::setChecked(unsigned row, bool checked) { GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget)); - GtkTreePath *path = gtk_tree_path_new_from_string(string(row)); GtkTreeIter iter; - gtk_tree_model_get_iter(model, &iter, path); + gtk_tree_model_get_iter_from_string(model, &iter, string(row)); gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, checked, -1); - gtk_tree_path_free(path); } void pListView::setHeaderText(const lstring &text) { @@ -117,25 +98,12 @@ void pListView::setSelected(bool selected) { } void pListView::setSelection(unsigned row) { - signed current = -1; - if(selected()) current = selection(); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget)); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget)); gtk_tree_selection_unselect_all(selection); - GtkTreeIter iter; - if(gtk_tree_model_get_iter_first(model, &iter) == false) return; - if(row == 0) { - gtk_tree_selection_select_iter(selection, &iter); - return; - } - for(unsigned n = 1;; n++) { - if(gtk_tree_model_iter_next(model, &iter) == false) return; - if(row == n) { - gtk_tree_selection_select_iter(selection, &iter); - return; - } - } + if(gtk_tree_model_get_iter_from_string(model, &iter, string(row)) == false) return; + gtk_tree_selection_select_iter(selection, &iter); } void pListView::constructor() { diff --git a/bsnes/phoenix/gtk/window.cpp b/bsnes/phoenix/gtk/window.cpp index 7d20bd85..13943689 100755 --- a/bsnes/phoenix/gtk/window.cpp +++ b/bsnes/phoenix/gtk/window.cpp @@ -42,6 +42,7 @@ static gboolean Window_configure(GtkWidget *widget, GdkEvent *event, Window *win settings->frameGeometryY = client.y - border.y; settings->frameGeometryWidth = border.width - client.width; settings->frameGeometryHeight = border.height - client.height; + settings->save(); } //move diff --git a/bsnes/phoenix/qt/platform.cpp b/bsnes/phoenix/qt/platform.cpp index bbcb9981..a8c11c9a 100755 --- a/bsnes/phoenix/qt/platform.cpp +++ b/bsnes/phoenix/qt/platform.cpp @@ -113,8 +113,6 @@ void pOS::processEvents() { } void pOS::quit() { - settings->save(); - QApplication::quit(); //note: QApplication cannot be deleted; or libQtGui will crash qtApplication = 0; diff --git a/bsnes/phoenix/qt/platform.moc b/bsnes/phoenix/qt/platform.moc index 7e04fac2..b542700e 100755 --- a/bsnes/phoenix/qt/platform.moc +++ b/bsnes/phoenix/qt/platform.moc @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'platform.moc.hpp' ** -** Created: Wed Nov 2 21:16:00 2011 +** Created: Wed Nov 9 02:07:41 2011 ** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0) ** ** WARNING! All changes made in this file will be lost! diff --git a/bsnes/phoenix/qt/window.cpp b/bsnes/phoenix/qt/window.cpp index 4710e4e4..05d62962 100755 --- a/bsnes/phoenix/qt/window.cpp +++ b/bsnes/phoenix/qt/window.cpp @@ -67,9 +67,10 @@ void pWindow::remove(Widget &widget) { void pWindow::setBackgroundColor(const Color &color) { QPalette palette; - palette.setColor(QPalette::Window, QColor(color.red, color.green, color.blue)); + palette.setColor(QPalette::Window, QColor(color.red, color.green, color.blue, color.alpha)); qtContainer->setPalette(palette); qtContainer->setAutoFillBackground(true); + qtWindow->setAttribute(Qt::WA_TranslucentBackground, color.alpha != 255); } void pWindow::setFocused() { @@ -220,6 +221,8 @@ void pWindow::updateFrameGeometry() { pOS::syncX(); settings->statusGeometryHeight = qtStatus->height(); } + + settings->save(); } void pWindow::QtWindow::closeEvent(QCloseEvent *event) { diff --git a/bsnes/ruby/audio/alsa.cpp b/bsnes/ruby/audio/alsa.cpp index 45b4a8bd..992c328d 100755 --- a/bsnes/ruby/audio/alsa.cpp +++ b/bsnes/ruby/audio/alsa.cpp @@ -205,7 +205,7 @@ public: void term() { if(device.handle) { - snd_pcm_drain(device.handle); + //snd_pcm_drain(device.handle); //prevents popping noise; but causes multi-second lag snd_pcm_close(device.handle); device.handle = 0; } diff --git a/bsnes/snes/Makefile b/bsnes/snes/Makefile index d380cd8a..a1a3ef33 100755 --- a/bsnes/snes/Makefile +++ b/bsnes/snes/Makefile @@ -26,6 +26,8 @@ else ifeq ($(profile),performance) snessmp := $(snes)/alt/smp snesdsp := $(snes)/alt/dsp snesppu := $(snes)/alt/ppu-performance +else + $(error Unknown profile: $(profile)) endif obj/snes-interface.o : $(snes)/interface/interface.cpp $(call rwildcard,$(snes)/interface) diff --git a/bsnes/snes/config/config.cpp b/bsnes/snes/config/config.cpp index 701af94c..3fcb72e0 100755 --- a/bsnes/snes/config/config.cpp +++ b/bsnes/snes/config/config.cpp @@ -7,7 +7,7 @@ Configuration::Configuration() { controller_port2 = Input::Device::Joypad; expansion_port = System::ExpansionPortDevice::BSX; region = System::Region::Autodetect; - random = true; + random = false; //true; cpu.version = 2; cpu.ntsc_frequency = 21477272; //315 / 88 * 6000000 diff --git a/bsnes/snes/smp/core-old/algorithms.cpp b/bsnes/snes/smp/core-old/algorithms.cpp new file mode 100755 index 00000000..30a21076 --- /dev/null +++ b/bsnes/snes/smp/core-old/algorithms.cpp @@ -0,0 +1,126 @@ +#ifdef SMPCORE_CPP + +uint8 SMPcore::op_adc(uint8 x, uint8 y) { + int r = x + y + regs.p.c; + regs.p.n = r & 0x80; + regs.p.v = ~(x ^ y) & (x ^ r) & 0x80; + regs.p.h = (x ^ y ^ r) & 0x10; + regs.p.z = (uint8)r == 0; + regs.p.c = r > 0xff; + return r; +} + +uint16 SMPcore::op_addw(uint16 x, uint16 y) { + uint16 r; + regs.p.c = 0; + r = op_adc(x, y); + r |= op_adc(x >> 8, y >> 8) << 8; + regs.p.z = r == 0; + return r; +} + +uint8 SMPcore::op_and(uint8 x, uint8 y) { + x &= y; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMPcore::op_cmp(uint8 x, uint8 y) { + int r = x - y; + regs.p.n = r & 0x80; + regs.p.z = (uint8)r == 0; + regs.p.c = r >= 0; + return x; +} + +uint16 SMPcore::op_cmpw(uint16 x, uint16 y) { + int r = x - y; + regs.p.n = r & 0x8000; + regs.p.z = (uint16)r == 0; + regs.p.c = r >= 0; + return x; +} + +uint8 SMPcore::op_eor(uint8 x, uint8 y) { + x ^= y; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMPcore::op_or(uint8 x, uint8 y) { + x |= y; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMPcore::op_sbc(uint8 x, uint8 y) { + int r = x - y - !regs.p.c; + regs.p.n = r & 0x80; + regs.p.v = (x ^ y) & (x ^ r) & 0x80; + regs.p.h = !((x ^ y ^ r) & 0x10); + regs.p.z = (uint8)r == 0; + regs.p.c = r >= 0; + return r; +} + +uint16 SMPcore::op_subw(uint16 x, uint16 y) { + uint16 r; + regs.p.c = 1; + r = op_sbc(x, y); + r |= op_sbc(x >> 8, y >> 8) << 8; + regs.p.z = r == 0; + return r; +} + +uint8 SMPcore::op_inc(uint8 x) { + x++; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMPcore::op_dec(uint8 x) { + x--; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMPcore::op_asl(uint8 x) { + regs.p.c = x & 0x80; + x <<= 1; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMPcore::op_lsr(uint8 x) { + regs.p.c = x & 0x01; + x >>= 1; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMPcore::op_rol(uint8 x) { + unsigned carry = (unsigned)regs.p.c; + regs.p.c = x & 0x80; + x = (x << 1) | carry; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMPcore::op_ror(uint8 x) { + unsigned carry = (unsigned)regs.p.c << 7; + regs.p.c = x & 0x01; + x = carry | (x >> 1); + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +#endif diff --git a/bsnes/snes/smp/core-old/core.cpp b/bsnes/snes/smp/core-old/core.cpp new file mode 100755 index 00000000..af6cd599 --- /dev/null +++ b/bsnes/snes/smp/core-old/core.cpp @@ -0,0 +1,35 @@ +#include + +#define SMPCORE_CPP +namespace SNES { + +#include "serialization.cpp" +#include "algorithms.cpp" +#include "disassembler/disassembler.cpp" + +#define A 0 +#define X 1 +#define Y 2 +#define SP 3 + +#include "opcode_mov.cpp" +#include "opcode_pc.cpp" +#include "opcode_read.cpp" +#include "opcode_rmw.cpp" +#include "opcode_misc.cpp" +#include "table.cpp" + +#undef A +#undef X +#undef Y +#undef SP + +void SMPcore::op_step() { + (this->*opcode_table[op_readpc()])(); +} + +SMPcore::SMPcore() { + initialize_opcode_table(); +} + +} diff --git a/bsnes/snes/smp/core-old/core.hpp b/bsnes/snes/smp/core-old/core.hpp new file mode 100755 index 00000000..ec6c0e33 --- /dev/null +++ b/bsnes/snes/smp/core-old/core.hpp @@ -0,0 +1,118 @@ +struct SMPcore { + #include "registers.hpp" + #include "memory.hpp" + #include "disassembler/disassembler.hpp" + + regs_t regs; + uint16 dp, sp, rd, wr, bit, ya; + + virtual void op_io() = 0; + virtual uint8 op_read(uint16 addr) = 0; + virtual void op_write(uint16 addr, uint8 data) = 0; + void op_step(); + + uint8 op_adc (uint8 x, uint8 y); + uint16 op_addw(uint16 x, uint16 y); + uint8 op_and (uint8 x, uint8 y); + uint8 op_cmp (uint8 x, uint8 y); + uint16 op_cmpw(uint16 x, uint16 y); + uint8 op_eor (uint8 x, uint8 y); + uint8 op_inc (uint8 x); + uint8 op_dec (uint8 x); + uint8 op_or (uint8 x, uint8 y); + uint8 op_sbc (uint8 x, uint8 y); + uint16 op_subw(uint16 x, uint16 y); + uint8 op_asl (uint8 x); + uint8 op_lsr (uint8 x); + uint8 op_rol (uint8 x); + uint8 op_ror (uint8 x); + + template void op_mov_reg_reg(); + void op_mov_sp_x(); + template void op_mov_reg_const(); + void op_mov_a_ix(); + void op_mov_a_ixinc(); + template void op_mov_reg_dp(); + template void op_mov_reg_dpr(); + template void op_mov_reg_addr(); + template void op_mov_a_addrr(); + void op_mov_a_idpx(); + void op_mov_a_idpy(); + void op_mov_dp_dp(); + void op_mov_dp_const(); + void op_mov_ix_a(); + void op_mov_ixinc_a(); + template void op_mov_dp_reg(); + template void op_mov_dpr_reg(); + template void op_mov_addr_reg(); + template void op_mov_addrr_a(); + void op_mov_idpx_a(); + void op_mov_idpy_a(); + void op_movw_ya_dp(); + void op_movw_dp_ya(); + void op_mov1_c_bit(); + void op_mov1_bit_c(); + + void op_bra(); + template void op_branch(); + template void op_bitbranch(); + void op_cbne_dp(); + void op_cbne_dpx(); + void op_dbnz_dp(); + void op_dbnz_y(); + void op_jmp_addr(); + void op_jmp_iaddrx(); + void op_call(); + void op_pcall(); + template void op_tcall(); + void op_brk(); + void op_ret(); + void op_reti(); + + template void op_read_reg_const(); + template void op_read_a_ix(); + template void op_read_reg_dp(); + template void op_read_a_dpx(); + template void op_read_reg_addr(); + template void op_read_a_addrr(); + template void op_read_a_idpx(); + template void op_read_a_idpy(); + template void op_read_ix_iy(); + template void op_read_dp_dp(); + template void op_read_dp_const(); + template void op_read_ya_dp(); + void op_cmpw_ya_dp(); + template void op_and1_bit(); + void op_eor1_bit(); + void op_not1_bit(); + template void op_or1_bit(); + + template void op_adjust_reg(); + template void op_adjust_dp(); + template void op_adjust_dpx(); + template void op_adjust_addr(); + template void op_adjust_addr_a(); + template void op_adjustw_dp(); + + void op_nop(); + void op_wait(); + void op_xcn(); + void op_daa(); + void op_das(); + template void op_setbit(); + void op_notc(); + template void op_seti(); + template void op_setbit_dp(); + template void op_push_reg(); + void op_push_p(); + template void op_pop_reg(); + void op_pop_p(); + void op_mul_ya(); + void op_div_ya_x(); + + void (SMPcore::*opcode_table[256])(); + void initialize_opcode_table(); + + void core_serialize(serializer&); + SMPcore(); +}; diff --git a/bsnes/snes/smp/core/disassembler/disassembler.cpp b/bsnes/snes/smp/core-old/disassembler/disassembler.cpp similarity index 100% rename from bsnes/snes/smp/core/disassembler/disassembler.cpp rename to bsnes/snes/smp/core-old/disassembler/disassembler.cpp diff --git a/bsnes/snes/smp/core/disassembler/disassembler.hpp b/bsnes/snes/smp/core-old/disassembler/disassembler.hpp similarity index 100% rename from bsnes/snes/smp/core/disassembler/disassembler.hpp rename to bsnes/snes/smp/core-old/disassembler/disassembler.hpp diff --git a/bsnes/snes/smp/core-old/memory.hpp b/bsnes/snes/smp/core-old/memory.hpp new file mode 100755 index 00000000..4b7afba0 --- /dev/null +++ b/bsnes/snes/smp/core-old/memory.hpp @@ -0,0 +1,19 @@ +alwaysinline uint8_t op_readpc() { + return op_read(regs.pc++); +} + +alwaysinline uint8_t op_readsp() { + return op_read(0x0100 | ++regs.sp); +} + +alwaysinline void op_writesp(uint8_t data) { + op_write(0x0100 | regs.sp--, data); +} + +alwaysinline uint8_t op_readdp(uint8_t addr) { + return op_read(((unsigned)regs.p.p << 8) + addr); +} + +alwaysinline void op_writedp(uint8_t addr, uint8_t data) { + op_write(((unsigned)regs.p.p << 8) + addr, data); +} diff --git a/bsnes/snes/smp/core/opcode_misc.cpp b/bsnes/snes/smp/core-old/opcode_misc.cpp similarity index 100% rename from bsnes/snes/smp/core/opcode_misc.cpp rename to bsnes/snes/smp/core-old/opcode_misc.cpp diff --git a/bsnes/snes/smp/core/opcode_mov.cpp b/bsnes/snes/smp/core-old/opcode_mov.cpp similarity index 100% rename from bsnes/snes/smp/core/opcode_mov.cpp rename to bsnes/snes/smp/core-old/opcode_mov.cpp diff --git a/bsnes/snes/smp/core/opcode_pc.cpp b/bsnes/snes/smp/core-old/opcode_pc.cpp similarity index 100% rename from bsnes/snes/smp/core/opcode_pc.cpp rename to bsnes/snes/smp/core-old/opcode_pc.cpp diff --git a/bsnes/snes/smp/core/opcode_read.cpp b/bsnes/snes/smp/core-old/opcode_read.cpp similarity index 100% rename from bsnes/snes/smp/core/opcode_read.cpp rename to bsnes/snes/smp/core-old/opcode_read.cpp diff --git a/bsnes/snes/smp/core/opcode_rmw.cpp b/bsnes/snes/smp/core-old/opcode_rmw.cpp similarity index 100% rename from bsnes/snes/smp/core/opcode_rmw.cpp rename to bsnes/snes/smp/core-old/opcode_rmw.cpp diff --git a/bsnes/snes/smp/core-old/registers.hpp b/bsnes/snes/smp/core-old/registers.hpp new file mode 100755 index 00000000..261f19f5 --- /dev/null +++ b/bsnes/snes/smp/core-old/registers.hpp @@ -0,0 +1,44 @@ +struct regya_t { + uint8_t &hi, &lo; + + inline operator uint16_t() const { + return (hi << 8) + lo; + } + + inline regya_t& operator=(uint16_t data) { + hi = data >> 8; + lo = data; + return *this; + } + + regya_t(uint8_t &hi_, uint8_t &lo_) : hi(hi_), lo(lo_) {} +}; + +struct flag_t { + bool n, v, p, b, h, i, z, c; + + inline operator unsigned() const { + return (n << 7) + (v << 6) + (p << 5) + (b << 4) + + (h << 3) + (i << 2) + (z << 1) + (c << 0); + } + + inline unsigned operator=(uint8_t data) { + n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10; + h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01; + return data; + } + + inline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); } + inline unsigned operator^=(unsigned data) { return operator=(operator unsigned() ^ data); } + inline unsigned operator&=(unsigned data) { return operator=(operator unsigned() & data); } + + flag_t() : n(0), v(0), p(0), b(0), h(0), i(0), z(0), c(0) {} +}; + +struct regs_t { + uint16_t pc; + uint8_t r[4], &a, &x, &y, &sp, &s; + regya_t ya; + flag_t p; + regs_t() : a(r[0]), x(r[1]), y(r[2]), s(r[3]), sp(r[3]), ya(r[2], r[0]) {} +}; diff --git a/bsnes/snes/smp/core-old/serialization.cpp b/bsnes/snes/smp/core-old/serialization.cpp new file mode 100755 index 00000000..883d013c --- /dev/null +++ b/bsnes/snes/smp/core-old/serialization.cpp @@ -0,0 +1,26 @@ +#ifdef SMPCORE_CPP + +void SMPcore::core_serialize(serializer &s) { + s.integer(regs.pc); + s.integer(regs.a); + s.integer(regs.x); + s.integer(regs.y); + s.integer(regs.sp); + s.integer(regs.p.n); + s.integer(regs.p.v); + s.integer(regs.p.p); + s.integer(regs.p.b); + s.integer(regs.p.h); + s.integer(regs.p.i); + s.integer(regs.p.z); + s.integer(regs.p.c); + + s.integer(dp); + s.integer(sp); + s.integer(rd); + s.integer(wr); + s.integer(bit); + s.integer(ya); +} + +#endif diff --git a/bsnes/snes/smp/core/table.cpp b/bsnes/snes/smp/core-old/table.cpp similarity index 100% rename from bsnes/snes/smp/core/table.cpp rename to bsnes/snes/smp/core-old/table.cpp diff --git a/bsnes/snes/smp/core/algorithms.cpp b/bsnes/snes/smp/core/algorithms.cpp index 30a21076..cbc31bea 100755 --- a/bsnes/snes/smp/core/algorithms.cpp +++ b/bsnes/snes/smp/core/algorithms.cpp @@ -10,15 +10,6 @@ uint8 SMPcore::op_adc(uint8 x, uint8 y) { return r; } -uint16 SMPcore::op_addw(uint16 x, uint16 y) { - uint16 r; - regs.p.c = 0; - r = op_adc(x, y); - r |= op_adc(x >> 8, y >> 8) << 8; - regs.p.z = r == 0; - return r; -} - uint8 SMPcore::op_and(uint8 x, uint8 y) { x &= y; regs.p.n = x & 0x80; @@ -26,6 +17,14 @@ uint8 SMPcore::op_and(uint8 x, uint8 y) { return x; } +uint8 SMPcore::op_asl(uint8 x) { + regs.p.c = x & 0x80; + x <<= 1; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + uint8 SMPcore::op_cmp(uint8 x, uint8 y) { int r = x - y; regs.p.n = r & 0x80; @@ -34,11 +33,10 @@ uint8 SMPcore::op_cmp(uint8 x, uint8 y) { return x; } -uint16 SMPcore::op_cmpw(uint16 x, uint16 y) { - int r = x - y; - regs.p.n = r & 0x8000; - regs.p.z = (uint16)r == 0; - regs.p.c = r >= 0; +uint8 SMPcore::op_dec(uint8 x) { + x--; + regs.p.n = x & 0x80; + regs.p.z = x == 0; return x; } @@ -49,6 +47,27 @@ uint8 SMPcore::op_eor(uint8 x, uint8 y) { return x; } +uint8 SMPcore::op_inc(uint8 x) { + x++; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMPcore::op_ld(uint8 x, uint8 y) { + regs.p.n = y & 0x80; + regs.p.z = y == 0; + return y; +} + +uint8 SMPcore::op_lsr(uint8 x) { + regs.p.c = x & 0x01; + x >>= 1; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + uint8 SMPcore::op_or(uint8 x, uint8 y) { x |= y; regs.p.n = x & 0x80; @@ -56,6 +75,24 @@ uint8 SMPcore::op_or(uint8 x, uint8 y) { return x; } +uint8 SMPcore::op_rol(uint8 x) { + unsigned carry = regs.p.c << 0; + regs.p.c = x & 0x80; + x = (x << 1) | carry; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMPcore::op_ror(uint8 x) { + unsigned carry = regs.p.c << 7; + regs.p.c = x & 0x01; + x = carry | (x >> 1); + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + uint8 SMPcore::op_sbc(uint8 x, uint8 y) { int r = x - y - !regs.p.c; regs.p.n = r & 0x80; @@ -66,7 +103,36 @@ uint8 SMPcore::op_sbc(uint8 x, uint8 y) { return r; } -uint16 SMPcore::op_subw(uint16 x, uint16 y) { +uint8 SMPcore::op_st(uint8 x, uint8 y) { + return y; +} + +// + +uint16 SMPcore::op_adw(uint16 x, uint16 y) { + uint16 r; + regs.p.c = 0; + r = op_adc(x, y); + r |= op_adc(x >> 8, y >> 8) << 8; + regs.p.z = r == 0; + return r; +} + +uint16 SMPcore::op_cpw(uint16 x, uint16 y) { + int r = x - y; + regs.p.n = r & 0x8000; + regs.p.z = (uint16)r == 0; + regs.p.c = r >= 0; + return x; +} + +uint16 SMPcore::op_ldw(uint16 x, uint16 y) { + regs.p.n = y & 0x8000; + regs.p.z = y == 0; + return y; +} + +uint16 SMPcore::op_sbw(uint16 x, uint16 y) { uint16 r; regs.p.c = 1; r = op_sbc(x, y); @@ -75,52 +141,4 @@ uint16 SMPcore::op_subw(uint16 x, uint16 y) { return r; } -uint8 SMPcore::op_inc(uint8 x) { - x++; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_dec(uint8 x) { - x--; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_asl(uint8 x) { - regs.p.c = x & 0x80; - x <<= 1; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_lsr(uint8 x) { - regs.p.c = x & 0x01; - x >>= 1; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_rol(uint8 x) { - unsigned carry = (unsigned)regs.p.c; - regs.p.c = x & 0x80; - x = (x << 1) | carry; - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - -uint8 SMPcore::op_ror(uint8 x) { - unsigned carry = (unsigned)regs.p.c << 7; - regs.p.c = x & 0x01; - x = carry | (x >> 1); - regs.p.n = x & 0x80; - regs.p.z = x == 0; - return x; -} - #endif diff --git a/bsnes/snes/smp/core/core.cpp b/bsnes/snes/smp/core/core.cpp index 51fa453e..9c94d00a 100755 --- a/bsnes/snes/smp/core/core.cpp +++ b/bsnes/snes/smp/core/core.cpp @@ -3,29 +3,270 @@ #define SMPCORE_CPP namespace SNES { -#include "serialization.cpp" #include "algorithms.cpp" -#include "disassembler/disassembler.cpp" +#include "opcodes.cpp" +#include "disassembler.cpp" +#include "serialization.cpp" -#define A 0 -#define X 1 -#define Y 2 -#define SP 3 - -#include "opcode_mov.cpp" -#include "opcode_pc.cpp" -#include "opcode_read.cpp" -#include "opcode_rmw.cpp" -#include "opcode_misc.cpp" -#include "table.cpp" - -#undef A -#undef X -#undef Y -#undef SP - -SMPcore::SMPcore() { - initialize_opcode_table(); +void SMPcore::op_step() { + switch(opcode = op_readpc()) { + case 0x00: return op_nop(); + case 0x01: return op_jst(); + case 0x02: return op_set_bit(); + case 0x03: return op_branch_bit(); + case 0x04: return op_read_dp<&SMPcore::op_or>(regs.a); + case 0x05: return op_read_addr<&SMPcore::op_or>(regs.a); + case 0x06: return op_read_ix<&SMPcore::op_or>(); + case 0x07: return op_read_idpx<&SMPcore::op_or>(); + case 0x08: return op_read_const<&SMPcore::op_or>(regs.a); + case 0x09: return op_write_dp_dp<&SMPcore::op_or>(); + case 0x0a: return op_set_addr_bit(); + case 0x0b: return op_adjust_dp<&SMPcore::op_asl>(); + case 0x0c: return op_adjust_addr<&SMPcore::op_asl>(); + case 0x0d: return op_push(regs.p); + case 0x0e: return op_test_addr(1); + case 0x0f: return op_brk(); + case 0x10: return op_branch(regs.p.n == 0); + case 0x11: return op_jst(); + case 0x12: return op_set_bit(); + case 0x13: return op_branch_bit(); + case 0x14: return op_read_dpi<&SMPcore::op_or>(regs.a, regs.x); + case 0x15: return op_read_addri<&SMPcore::op_or>(regs.x); + case 0x16: return op_read_addri<&SMPcore::op_or>(regs.y); + case 0x17: return op_read_idpy<&SMPcore::op_or>(); + case 0x18: return op_write_dp_const<&SMPcore::op_or>(); + case 0x19: return op_write_ix_iy<&SMPcore::op_or>(); + case 0x1a: return op_adjust_dpw(-1); + case 0x1b: return op_adjust_dpx<&SMPcore::op_asl>(); + case 0x1c: return op_adjust<&SMPcore::op_asl>(regs.a); + case 0x1d: return op_adjust<&SMPcore::op_dec>(regs.x); + case 0x1e: return op_read_addr<&SMPcore::op_cmp>(regs.x); + case 0x1f: return op_jmp_iaddrx(); + case 0x20: return op_set_flag(regs.p.p, 0); + case 0x21: return op_jst(); + case 0x22: return op_set_bit(); + case 0x23: return op_branch_bit(); + case 0x24: return op_read_dp<&SMPcore::op_and>(regs.a); + case 0x25: return op_read_addr<&SMPcore::op_and>(regs.a); + case 0x26: return op_read_ix<&SMPcore::op_and>(); + case 0x27: return op_read_idpx<&SMPcore::op_and>(); + case 0x28: return op_read_const<&SMPcore::op_and>(regs.a); + case 0x29: return op_write_dp_dp<&SMPcore::op_and>(); + case 0x2a: return op_set_addr_bit(); + case 0x2b: return op_adjust_dp<&SMPcore::op_rol>(); + case 0x2c: return op_adjust_addr<&SMPcore::op_rol>(); + case 0x2d: return op_push(regs.a); + case 0x2e: return op_bne_dp(); + case 0x2f: return op_branch(true); + case 0x30: return op_branch(regs.p.n == 1); + case 0x31: return op_jst(); + case 0x32: return op_set_bit(); + case 0x33: return op_branch_bit(); + case 0x34: return op_read_dpi<&SMPcore::op_and>(regs.a, regs.x); + case 0x35: return op_read_addri<&SMPcore::op_and>(regs.x); + case 0x36: return op_read_addri<&SMPcore::op_and>(regs.y); + case 0x37: return op_read_idpy<&SMPcore::op_and>(); + case 0x38: return op_write_dp_const<&SMPcore::op_and>(); + case 0x39: return op_write_ix_iy<&SMPcore::op_and>(); + case 0x3a: return op_adjust_dpw(+1); + case 0x3b: return op_adjust_dpx<&SMPcore::op_rol>(); + case 0x3c: return op_adjust<&SMPcore::op_rol>(regs.a); + case 0x3d: return op_adjust<&SMPcore::op_inc>(regs.x); + case 0x3e: return op_read_dp<&SMPcore::op_cmp>(regs.x); + case 0x3f: return op_jsr_addr(); + case 0x40: return op_set_flag(regs.p.p, 1); + case 0x41: return op_jst(); + case 0x42: return op_set_bit(); + case 0x43: return op_branch_bit(); + case 0x44: return op_read_dp<&SMPcore::op_eor>(regs.a); + case 0x45: return op_read_addr<&SMPcore::op_eor>(regs.a); + case 0x46: return op_read_ix<&SMPcore::op_eor>(); + case 0x47: return op_read_idpx<&SMPcore::op_eor>(); + case 0x48: return op_read_const<&SMPcore::op_eor>(regs.a); + case 0x49: return op_write_dp_dp<&SMPcore::op_eor>(); + case 0x4a: return op_set_addr_bit(); + case 0x4b: return op_adjust_dp<&SMPcore::op_lsr>(); + case 0x4c: return op_adjust_addr<&SMPcore::op_lsr>(); + case 0x4d: return op_push(regs.x); + case 0x4e: return op_test_addr(0); + case 0x4f: return op_jsp_dp(); + case 0x50: return op_branch(regs.p.v == 0); + case 0x51: return op_jst(); + case 0x52: return op_set_bit(); + case 0x53: return op_branch_bit(); + case 0x54: return op_read_dpi<&SMPcore::op_eor>(regs.a, regs.x); + case 0x55: return op_read_addri<&SMPcore::op_eor>(regs.x); + case 0x56: return op_read_addri<&SMPcore::op_eor>(regs.y); + case 0x57: return op_read_idpy<&SMPcore::op_eor>(); + case 0x58: return op_write_dp_const<&SMPcore::op_eor>(); + case 0x59: return op_write_ix_iy<&SMPcore::op_eor>(); + case 0x5a: return op_read_dpw<&SMPcore::op_cpw>(); + case 0x5b: return op_adjust_dpx<&SMPcore::op_lsr>(); + case 0x5c: return op_adjust<&SMPcore::op_lsr>(regs.a); + case 0x5d: return op_transfer(regs.a, regs.x); + case 0x5e: return op_read_addr<&SMPcore::op_cmp>(regs.y); + case 0x5f: return op_jmp_addr(); + case 0x60: return op_set_flag(regs.p.c, 0); + case 0x61: return op_jst(); + case 0x62: return op_set_bit(); + case 0x63: return op_branch_bit(); + case 0x64: return op_read_dp<&SMPcore::op_cmp>(regs.a); + case 0x65: return op_read_addr<&SMPcore::op_cmp>(regs.a); + case 0x66: return op_read_ix<&SMPcore::op_cmp>(); + case 0x67: return op_read_idpx<&SMPcore::op_cmp>(); + case 0x68: return op_read_const<&SMPcore::op_cmp>(regs.a); + case 0x69: return op_write_dp_dp<&SMPcore::op_cmp>(); + case 0x6a: return op_set_addr_bit(); + case 0x6b: return op_adjust_dp<&SMPcore::op_ror>(); + case 0x6c: return op_adjust_addr<&SMPcore::op_ror>(); + case 0x6d: return op_push(regs.y); + case 0x6e: return op_bne_dpdec(); + case 0x6f: return op_rts(); + case 0x70: return op_branch(regs.p.v == 1); + case 0x71: return op_jst(); + case 0x72: return op_set_bit(); + case 0x73: return op_branch_bit(); + case 0x74: return op_read_dpi<&SMPcore::op_cmp>(regs.a, regs.x); + case 0x75: return op_read_addri<&SMPcore::op_cmp>(regs.x); + case 0x76: return op_read_addri<&SMPcore::op_cmp>(regs.y); + case 0x77: return op_read_idpy<&SMPcore::op_cmp>(); + case 0x78: return op_write_dp_const<&SMPcore::op_cmp>(); + case 0x79: return op_write_ix_iy<&SMPcore::op_cmp>(); + case 0x7a: return op_read_dpw<&SMPcore::op_adw>(); + case 0x7b: return op_adjust_dpx<&SMPcore::op_ror>(); + case 0x7c: return op_adjust<&SMPcore::op_ror>(regs.a); + case 0x7d: return op_transfer(regs.x, regs.a); + case 0x7e: return op_read_dp<&SMPcore::op_cmp>(regs.y); + case 0x7f: return op_rti(); + case 0x80: return op_set_flag(regs.p.c, 1); + case 0x81: return op_jst(); + case 0x82: return op_set_bit(); + case 0x83: return op_branch_bit(); + case 0x84: return op_read_dp<&SMPcore::op_adc>(regs.a); + case 0x85: return op_read_addr<&SMPcore::op_adc>(regs.a); + case 0x86: return op_read_ix<&SMPcore::op_adc>(); + case 0x87: return op_read_idpx<&SMPcore::op_adc>(); + case 0x88: return op_read_const<&SMPcore::op_adc>(regs.a); + case 0x89: return op_write_dp_dp<&SMPcore::op_adc>(); + case 0x8a: return op_set_addr_bit(); + case 0x8b: return op_adjust_dp<&SMPcore::op_dec>(); + case 0x8c: return op_adjust_addr<&SMPcore::op_dec>(); + case 0x8d: return op_read_const<&SMPcore::op_ld>(regs.y); + case 0x8e: return op_plp(); + case 0x8f: return op_write_dp_const<&SMPcore::op_st>(); + case 0x90: return op_branch(regs.p.c == 0); + case 0x91: return op_jst(); + case 0x92: return op_set_bit(); + case 0x93: return op_branch_bit(); + case 0x94: return op_read_dpi<&SMPcore::op_adc>(regs.a, regs.x); + case 0x95: return op_read_addri<&SMPcore::op_adc>(regs.x); + case 0x96: return op_read_addri<&SMPcore::op_adc>(regs.y); + case 0x97: return op_read_idpy<&SMPcore::op_adc>(); + case 0x98: return op_write_dp_const<&SMPcore::op_adc>(); + case 0x99: return op_write_ix_iy<&SMPcore::op_adc>(); + case 0x9a: return op_read_dpw<&SMPcore::op_sbw>(); + case 0x9b: return op_adjust_dpx<&SMPcore::op_dec>(); + case 0x9c: return op_adjust<&SMPcore::op_dec>(regs.a); + case 0x9d: return op_transfer(regs.s, regs.x); + case 0x9e: return op_div_ya_x(); + case 0x9f: return op_xcn(); + case 0xa0: return op_set_flag(regs.p.i, 1); + case 0xa1: return op_jst(); + case 0xa2: return op_set_bit(); + case 0xa3: return op_branch_bit(); + case 0xa4: return op_read_dp<&SMPcore::op_sbc>(regs.a); + case 0xa5: return op_read_addr<&SMPcore::op_sbc>(regs.a); + case 0xa6: return op_read_ix<&SMPcore::op_sbc>(); + case 0xa7: return op_read_idpx<&SMPcore::op_sbc>(); + case 0xa8: return op_read_const<&SMPcore::op_sbc>(regs.a); + case 0xa9: return op_write_dp_dp<&SMPcore::op_sbc>(); + case 0xaa: return op_set_addr_bit(); + case 0xab: return op_adjust_dp<&SMPcore::op_inc>(); + case 0xac: return op_adjust_addr<&SMPcore::op_inc>(); + case 0xad: return op_read_const<&SMPcore::op_cmp>(regs.y); + case 0xae: return op_pull(regs.a); + case 0xaf: return op_sta_ixinc(); + case 0xb0: return op_branch(regs.p.c == 1); + case 0xb1: return op_jst(); + case 0xb2: return op_set_bit(); + case 0xb3: return op_branch_bit(); + case 0xb4: return op_read_dpi<&SMPcore::op_sbc>(regs.a, regs.x); + case 0xb5: return op_read_addri<&SMPcore::op_sbc>(regs.x); + case 0xb6: return op_read_addri<&SMPcore::op_sbc>(regs.y); + case 0xb7: return op_read_idpy<&SMPcore::op_sbc>(); + case 0xb8: return op_write_dp_const<&SMPcore::op_sbc>(); + case 0xb9: return op_write_ix_iy<&SMPcore::op_sbc>(); + case 0xba: return op_read_dpw<&SMPcore::op_ldw>(); + case 0xbb: return op_adjust_dpx<&SMPcore::op_inc>(); + case 0xbc: return op_adjust<&SMPcore::op_inc>(regs.a); + case 0xbd: return op_transfer(regs.x, regs.s); + case 0xbe: return op_das(); + case 0xbf: return op_lda_ixinc(); + case 0xc0: return op_set_flag(regs.p.i, 0); + case 0xc1: return op_jst(); + case 0xc2: return op_set_bit(); + case 0xc3: return op_branch_bit(); + case 0xc4: return op_write_dp(regs.a); + case 0xc5: return op_write_addr(regs.a); + case 0xc6: return op_sta_ix(); + case 0xc7: return op_sta_idpx(); + case 0xc8: return op_read_const<&SMPcore::op_cmp>(regs.x); + case 0xc9: return op_write_addr(regs.x); + case 0xca: return op_set_addr_bit(); + case 0xcb: return op_write_dp(regs.y); + case 0xcc: return op_write_addr(regs.y); + case 0xcd: return op_read_const<&SMPcore::op_ld>(regs.x); + case 0xce: return op_pull(regs.x); + case 0xcf: return op_mul_ya(); + case 0xd0: return op_branch(regs.p.z == 0); + case 0xd1: return op_jst(); + case 0xd2: return op_set_bit(); + case 0xd3: return op_branch_bit(); + case 0xd4: return op_write_dpi(regs.a, regs.x); + case 0xd5: return op_write_addri(regs.x); + case 0xd6: return op_write_addri(regs.y); + case 0xd7: return op_sta_idpy(); + case 0xd8: return op_write_dp(regs.x); + case 0xd9: return op_write_dpi(regs.x, regs.y); + case 0xda: return op_stw_dp(); + case 0xdb: return op_write_dpi(regs.y, regs.x); + case 0xdc: return op_adjust<&SMPcore::op_dec>(regs.y); + case 0xdd: return op_transfer(regs.y, regs.a); + case 0xde: return op_bne_dpx(); + case 0xdf: return op_daa(); + case 0xe0: return op_clv(); + case 0xe1: return op_jst(); + case 0xe2: return op_set_bit(); + case 0xe3: return op_branch_bit(); + case 0xe4: return op_read_dp<&SMPcore::op_ld>(regs.a); + case 0xe5: return op_read_addr<&SMPcore::op_ld>(regs.a); + case 0xe6: return op_read_ix<&SMPcore::op_ld>(); + case 0xe7: return op_read_idpx<&SMPcore::op_ld>(); + case 0xe8: return op_read_const<&SMPcore::op_ld>(regs.a); + case 0xe9: return op_read_addr<&SMPcore::op_ld>(regs.x); + case 0xea: return op_set_addr_bit(); + case 0xeb: return op_read_dp<&SMPcore::op_ld>(regs.y); + case 0xec: return op_read_addr<&SMPcore::op_ld>(regs.y); + case 0xed: return op_cmc(); + case 0xee: return op_pull(regs.y); + case 0xef: return op_wait(); + case 0xf0: return op_branch(regs.p.z == 1); + case 0xf1: return op_jst(); + case 0xf2: return op_set_bit(); + case 0xf3: return op_branch_bit(); + case 0xf4: return op_read_dpi<&SMPcore::op_ld>(regs.a, regs.x); + case 0xf5: return op_read_addri<&SMPcore::op_ld>(regs.x); + case 0xf6: return op_read_addri<&SMPcore::op_ld>(regs.y); + case 0xf7: return op_read_idpy<&SMPcore::op_ld>(); + case 0xf8: return op_read_dp<&SMPcore::op_ld>(regs.x); + case 0xf9: return op_read_dpi<&SMPcore::op_ld>(regs.x, regs.y); + case 0xfa: return op_write_dp_dp<&SMPcore::op_st>(); + case 0xfb: return op_read_dpi<&SMPcore::op_ld>(regs.y, regs.x); + case 0xfc: return op_adjust<&SMPcore::op_inc>(regs.y); + case 0xfd: return op_transfer(regs.a, regs.y); + case 0xfe: return op_bne_ydec(); + case 0xff: return op_wait(); + } } } diff --git a/bsnes/snes/smp/core/core.hpp b/bsnes/snes/smp/core/core.hpp index 5b14a88f..6adf6f6b 100755 --- a/bsnes/snes/smp/core/core.hpp +++ b/bsnes/snes/smp/core/core.hpp @@ -1,117 +1,96 @@ struct SMPcore { - #include "registers.hpp" - #include "memory.hpp" - #include "disassembler/disassembler.hpp" - - regs_t regs; - uint16 dp, sp, rd, wr, bit, ya; - virtual void op_io() = 0; virtual uint8 op_read(uint16 addr) = 0; virtual void op_write(uint16 addr, uint8 data) = 0; + void op_step(); - uint8 op_adc (uint8 x, uint8 y); - uint16 op_addw(uint16 x, uint16 y); - uint8 op_and (uint8 x, uint8 y); - uint8 op_cmp (uint8 x, uint8 y); - uint16 op_cmpw(uint16 x, uint16 y); - uint8 op_eor (uint8 x, uint8 y); - uint8 op_inc (uint8 x); - uint8 op_dec (uint8 x); - uint8 op_or (uint8 x, uint8 y); - uint8 op_sbc (uint8 x, uint8 y); - uint16 op_subw(uint16 x, uint16 y); - uint8 op_asl (uint8 x); - uint8 op_lsr (uint8 x); - uint8 op_rol (uint8 x); - uint8 op_ror (uint8 x); + #include "registers.hpp" + #include "memory.hpp" - template void op_mov_reg_reg(); - void op_mov_sp_x(); - template void op_mov_reg_const(); - void op_mov_a_ix(); - void op_mov_a_ixinc(); - template void op_mov_reg_dp(); - template void op_mov_reg_dpr(); - template void op_mov_reg_addr(); - template void op_mov_a_addrr(); - void op_mov_a_idpx(); - void op_mov_a_idpy(); - void op_mov_dp_dp(); - void op_mov_dp_const(); - void op_mov_ix_a(); - void op_mov_ixinc_a(); - template void op_mov_dp_reg(); - template void op_mov_dpr_reg(); - template void op_mov_addr_reg(); - template void op_mov_addrr_a(); - void op_mov_idpx_a(); - void op_mov_idpy_a(); - void op_movw_ya_dp(); - void op_movw_dp_ya(); - void op_mov1_c_bit(); - void op_mov1_bit_c(); - - void op_bra(); - template void op_branch(); - template void op_bitbranch(); - void op_cbne_dp(); - void op_cbne_dpx(); - void op_dbnz_dp(); - void op_dbnz_y(); - void op_jmp_addr(); - void op_jmp_iaddrx(); - void op_call(); - void op_pcall(); - template void op_tcall(); - void op_brk(); - void op_ret(); - void op_reti(); - - template void op_read_reg_const(); - template void op_read_a_ix(); - template void op_read_reg_dp(); - template void op_read_a_dpx(); - template void op_read_reg_addr(); - template void op_read_a_addrr(); - template void op_read_a_idpx(); - template void op_read_a_idpy(); - template void op_read_ix_iy(); - template void op_read_dp_dp(); - template void op_read_dp_const(); - template void op_read_ya_dp(); - void op_cmpw_ya_dp(); - template void op_and1_bit(); - void op_eor1_bit(); - void op_not1_bit(); - template void op_or1_bit(); - - template void op_adjust_reg(); - template void op_adjust_dp(); - template void op_adjust_dpx(); - template void op_adjust_addr(); - template void op_adjust_addr_a(); - template void op_adjustw_dp(); - - void op_nop(); - void op_wait(); - void op_xcn(); - void op_daa(); - void op_das(); - template void op_setbit(); - void op_notc(); - template void op_seti(); - template void op_setbit_dp(); - template void op_push_reg(); - void op_push_p(); - template void op_pop_reg(); - void op_pop_p(); - void op_mul_ya(); - void op_div_ya_x(); - - void (SMPcore::*opcode_table[256])(); - void initialize_opcode_table(); + regs_t regs; + word_t dp, sp, rd, wr, bit, ya; + uint8 opcode; void core_serialize(serializer&); - SMPcore(); + string disassemble_opcode(uint16 addr); + +protected: + uint8 op_adc(uint8, uint8); + uint8 op_and(uint8, uint8); + uint8 op_asl(uint8); + uint8 op_cmp(uint8, uint8); + uint8 op_dec(uint8); + uint8 op_eor(uint8, uint8); + uint8 op_inc(uint8); + uint8 op_ld (uint8, uint8); + uint8 op_lsr(uint8); + uint8 op_or (uint8, uint8); + uint8 op_rol(uint8); + uint8 op_ror(uint8); + uint8 op_sbc(uint8, uint8); + uint8 op_st (uint8, uint8); + uint16 op_adw(uint16, uint16); + uint16 op_cpw(uint16, uint16); + uint16 op_ldw(uint16, uint16); + uint16 op_sbw(uint16, uint16); + + template void op_adjust(uint8&); + template void op_adjust_addr(); + template void op_adjust_dp(); + void op_adjust_dpw(signed); + template void op_adjust_dpx(); + void op_branch(bool); + void op_branch_bit(); + void op_pull(uint8&); + void op_push(uint8); + template void op_read_addr(uint8&); + template void op_read_addri(uint8&); + template void op_read_const(uint8&); + template void op_read_dp(uint8&); + template void op_read_dpi(uint8&, uint8&); + template void op_read_dpw(); + template void op_read_idpx(); + template void op_read_idpy(); + template void op_read_ix(); + void op_set_addr_bit(); + void op_set_bit(); + void op_set_flag(bool&, bool); + void op_test_addr(bool); + void op_transfer(uint8&, uint8&); + void op_write_addr(uint8&); + void op_write_addri(uint8&); + void op_write_dp(uint8&); + void op_write_dpi(uint8&, uint8&); + template void op_write_dp_const(); + template void op_write_dp_dp(); + template void op_write_ix_iy(); + + void op_bne_dp(); + void op_bne_dpdec(); + void op_bne_dpx(); + void op_bne_ydec(); + void op_brk(); + void op_clv(); + void op_cmc(); + void op_daa(); + void op_das(); + void op_div_ya_x(); + void op_jmp_addr(); + void op_jmp_iaddrx(); + void op_jsp_dp(); + void op_jsr_addr(); + void op_jst(); + void op_lda_ixinc(); + void op_mul_ya(); + void op_nop(); + void op_plp(); + void op_rti(); + void op_rts(); + void op_sta_idpx(); + void op_sta_idpy(); + void op_sta_ix(); + void op_sta_ixinc(); + void op_stw_dp(); + void op_wait(); + void op_xcn(); }; diff --git a/bsnes/snes/smp/core/disassembler.cpp b/bsnes/snes/smp/core/disassembler.cpp new file mode 100755 index 00000000..73f973d3 --- /dev/null +++ b/bsnes/snes/smp/core/disassembler.cpp @@ -0,0 +1,311 @@ +#ifdef SMPCORE_CPP + +string SMPcore::disassemble_opcode(uint16 addr) { + auto read = [&](uint16 addr) -> uint8 { + if((addr & 0xfff0) == 0x00f0) return 0x00; + if((addr & 0xffc0) == 0xffc0) return smp.iplrom[addr & 0x3f]; + return smp.apuram[addr]; + }; + + auto relative = [&](unsigned length, int8 offset) -> uint16 { + uint16 pc = addr + length; + return pc + offset; + }; + + auto a = [&] { return hex<4>((read(addr + 1) << 0) + (read(addr + 2) << 8)); }; + auto b = [&](unsigned n) { return hex<2>(read(addr + 1 + n)); }; + auto r = [&](unsigned r, unsigned n = 0) { return hex<4>(addr + r + (int8)read(addr + 1 + n)); }; + auto dp = [&](unsigned n) { return hex<3>((regs.p.p << 8) + read(addr + 1 + n)); }; + auto ab = [&] { + unsigned n = (read(addr + 1) << 0) + (read(addr + 2) << 8); + return string{ hex<4>(addr & 0x1fff), ":", hex<1>(addr >> 13) }; + }; + + auto mnemonic = [&]() -> string { + switch(read(addr)) { + case 0x00: return { "nop" }; + case 0x01: return { "jst $ffde" }; + case 0x02: return { "set $", dp(0), ":0" }; + case 0x03: return { "bbs $", dp(0), ":0=$", r(+3, 1) }; + case 0x04: return { "ora $", dp(0) }; + case 0x05: return { "ora $", a() }; + case 0x06: return { "ora (x)" }; + case 0x07: return { "ora ($", dp(0), ",x)" }; + case 0x08: return { "ora #$", b(0) }; + case 0x09: return { "orr $", dp(1), "=$", dp(0) }; + case 0x0a: return { "orc $", ab() }; + case 0x0b: return { "asl $", dp(0) }; + case 0x0c: return { "asl $", a() }; + case 0x0d: return { "php" }; + case 0x0e: return { "tsb $", a() }; + case 0x0f: return { "brk" }; + case 0x10: return { "bpl $", r(+2) }; + case 0x11: return { "jst $ffdc" }; + case 0x12: return { "clr $", dp(0), ":0" }; + case 0x13: return { "bbc $", dp(0), ":0=$", r(+3, 1) }; + case 0x14: return { "ora $", dp(0), ",x" }; + case 0x15: return { "ora $", a(), ",x" }; + case 0x16: return { "ora $", a(), ",y" }; + case 0x17: return { "ora ($", dp(0), "),y" }; + case 0x18: return { "orr $", dp(1), "=#$", b(0) }; + case 0x19: return { "orr (x)=(y)" }; + case 0x1a: return { "dew $", dp(0) }; + case 0x1b: return { "asl $", dp(0), ",x" }; + case 0x1c: return { "asl" }; + case 0x1d: return { "dex" }; + case 0x1e: return { "cpx $", a() }; + case 0x1f: return { "jmp ($", a(), ",x)" }; + case 0x20: return { "clp" }; + case 0x21: return { "jst $ffda" }; + case 0x22: return { "set $", dp(0), ":1" }; + case 0x23: return { "bbs $", dp(0), ":1=$", r(+3, 1) }; + case 0x24: return { "and $", dp(0) }; + case 0x25: return { "and $", a() }; + case 0x26: return { "and (x)" }; + case 0x27: return { "and ($", dp(0), ",x)" }; + case 0x29: return { "and $", dp(1), "=$", dp(0) }; + case 0x2a: return { "orc !$", ab() }; + case 0x2b: return { "rol $", dp(0) }; + case 0x2c: return { "rol $", a() }; + case 0x2d: return { "pha" }; + case 0x2e: return { "bne $", dp(0), "=$", r(+3, 1) }; + case 0x28: return { "and #$", b(0) }; + case 0x2f: return { "bra $", r(+2) }; + case 0x30: return { "bmi $", r(+2) }; + case 0x31: return { "jst $ffd8" }; + case 0x32: return { "clr $", dp(0), ":1" }; + case 0x33: return { "bbc $", dp(0), ":1=$", r(+3, 1) }; + case 0x34: return { "and $", dp(0), ",x" }; + case 0x35: return { "and $", a(), ",x" }; + case 0x36: return { "and $", a(), ",y" }; + case 0x37: return { "and ($", dp(0), "),y" }; + case 0x38: return { "and $", dp(1), "=#$", b(0) }; + case 0x39: return { "and (x)=(y)" }; + case 0x3a: return { "inw $", dp(0) }; + case 0x3b: return { "rol $", dp(0), ",x" }; + case 0x3c: return { "rol" }; + case 0x3d: return { "inx" }; + case 0x3e: return { "cpx $", dp(0) }; + case 0x3f: return { "jsr $", a() }; + case 0x40: return { "sep" }; + case 0x41: return { "jst $ffd6" }; + case 0x42: return { "set $", dp(0), ":2" }; + case 0x43: return { "bbs $", dp(0), ":2=$", r(+3, 1) }; + case 0x44: return { "eor $", dp(0) }; + case 0x45: return { "eor $", a() }; + case 0x46: return { "eor (x)" }; + case 0x47: return { "eor ($", dp(0), ",x)" }; + case 0x48: return { "eor #$", b(0) }; + case 0x49: return { "eor $", dp(1), "=$", dp(0) }; + case 0x4a: return { "and $", ab() }; + case 0x4b: return { "lsr $", dp(0) }; + case 0x4c: return { "lsr $", a() }; + case 0x4d: return { "phx" }; + case 0x4e: return { "trb $", a() }; + case 0x4f: return { "jsp $ff", b(0) }; + case 0x50: return { "bvc $", r(+2) }; + case 0x51: return { "jst $ffd4" }; + case 0x52: return { "clr $", dp(0), ":2" }; + case 0x53: return { "bbc $", dp(0), ":2=$", r(+3, 1) }; + case 0x54: return { "eor $", dp(0), ",x" }; + case 0x55: return { "eor $", a(), ",x" }; + case 0x56: return { "eor $", a(), ",y" }; + case 0x57: return { "eor ($", dp(0), "),y" }; + case 0x58: return { "eor $", dp(1), "=#$", b(0) }; + case 0x59: return { "eor (x)=(y)" }; + case 0x5a: return { "cpw $", a() }; + case 0x5b: return { "lsr $", dp(0), ",x" }; + case 0x5c: return { "lsr" }; + case 0x5d: return { "tax" }; + case 0x5e: return { "cpy $", a() }; + case 0x5f: return { "jmp $", a() }; + case 0x60: return { "clc" }; + case 0x61: return { "jst $ffd2" }; + case 0x62: return { "set $", dp(0), ":3" }; + case 0x63: return { "bbs $", dp(0), ":3=$", r(+3, 1) }; + case 0x64: return { "cmp $", dp(0) }; + case 0x65: return { "cmp $", a() }; + case 0x66: return { "cmp (x)" }; + case 0x67: return { "cmp ($", dp(0), ",x)" }; + case 0x68: return { "cmp #$", b(0) }; + case 0x69: return { "cmp $", dp(1), "=$", dp(0) }; + case 0x6a: return { "and !$", ab() }; + case 0x6b: return { "ror $", dp(0) }; + case 0x6c: return { "ror $", a() }; + case 0x6d: return { "phy" }; + case 0x6e: return { "bne --$", dp(0), "=$", r(+3, 1) }; + case 0x6f: return { "rts" }; + case 0x70: return { "bvs $", r(+2) }; + case 0x71: return { "jst $ffd0" }; + case 0x72: return { "clr $", dp(0), ":3" }; + case 0x73: return { "bbc $", dp(0), ":3=$", r(+3, 1) }; + case 0x74: return { "cmp $", dp(0), ",x" }; + case 0x75: return { "cmp $", a(), ",x" }; + case 0x76: return { "cmp $", a(), ",y" }; + case 0x77: return { "cmp ($", dp(0), "),y" }; + case 0x78: return { "cmp $", dp(1), "=#$", b(0) }; + case 0x79: return { "cmp (x)=(y)" }; + case 0x7a: return { "adw $", a() }; + case 0x7b: return { "ror $", dp(0), ",x" }; + case 0x7c: return { "ror" }; + case 0x7d: return { "txa" }; + case 0x7e: return { "cpy $", dp(0) }; + case 0x7f: return { "rti" }; + case 0x80: return { "sec" }; + case 0x81: return { "jst $ffce" }; + case 0x82: return { "set $", dp(0), ":4" }; + case 0x83: return { "bbs $", dp(0), ":4=$", r(+3, 1) }; + case 0x84: return { "adc $", dp(0) }; + case 0x85: return { "adc $", a() }; + case 0x86: return { "adc (x)" }; + case 0x87: return { "adc ($", dp(0), ",x)" }; + case 0x88: return { "adc #$", b(0) }; + case 0x89: return { "adc $", dp(1), "=$", dp(0) }; + case 0x8a: return { "eor $", ab() }; + case 0x8b: return { "dec $", dp(0) }; + case 0x8c: return { "dec $", a() }; + case 0x8d: return { "ldy #$", b(0) }; + case 0x8e: return { "plp" }; + case 0x8f: return { "str $", dp(1), "=#$", b(0) }; + case 0x90: return { "bcc $", r(+2) }; + case 0x91: return { "jst $ffcc" }; + case 0x92: return { "clr $", dp(0), ":4" }; + case 0x93: return { "bbc $", dp(0), ":4=$", r(+3, 1) }; + case 0x94: return { "adc $", dp(0), ",x" }; + case 0x95: return { "adc $", a(), ",x" }; + case 0x96: return { "adc $", a(), ",y" }; + case 0x97: return { "adc ($", dp(0), "),y" }; + case 0x98: return { "adc $", dp(1), "=#$", b(0) }; + case 0x99: return { "adc (x)=(y)" }; + case 0x9a: return { "sbw $", a() }; + case 0x9b: return { "dec $", dp(0), ",x" }; + case 0x9c: return { "dec" }; + case 0x9d: return { "tsx" }; + case 0x9e: return { "div" }; + case 0x9f: return { "xcn" }; + case 0xa0: return { "sei" }; + case 0xa1: return { "jst $ffca" }; + case 0xa2: return { "set $", dp(0), ":5" }; + case 0xa3: return { "bbs $", dp(0), ":5=$", r(+3, 1) }; + case 0xa4: return { "sbc $", dp(0) }; + case 0xa5: return { "sbc $", a() }; + case 0xa6: return { "sbc (x)" }; + case 0xa7: return { "sbc ($", dp(0), ",x)" }; + case 0xa8: return { "sbc #$", b(0) }; + case 0xa9: return { "sbc $", dp(1), "=$", dp(0) }; + case 0xaa: return { "ldc $", ab() }; + case 0xab: return { "inc $", dp(0) }; + case 0xac: return { "inc $", a() }; + case 0xad: return { "cpy #$", b(0) }; + case 0xae: return { "pla" }; + case 0xaf: return { "sta (x++)" }; + case 0xb0: return { "bcs $", r(+2) }; + case 0xb1: return { "jst $ffc8" }; + case 0xb2: return { "clr $", dp(0), ":5" }; + case 0xb3: return { "bbc $", dp(0), ":5=$", r(+3, 1) }; + case 0xb4: return { "sbc $", dp(0), ",x" }; + case 0xb5: return { "sbc $", a(), ",x" }; + case 0xb6: return { "sbc $", a(), ",y" }; + case 0xb7: return { "sbc ($", dp(0), "),y" }; + case 0xb8: return { "sbc $", dp(1), "=#$", b(0) }; + case 0xb9: return { "sbc (x)=(y)" }; + case 0xba: return { "ldw $", dp(0) }; + case 0xbb: return { "inc $", dp(0), ",x" }; + case 0xbc: return { "inc" }; + case 0xbd: return { "txs" }; + case 0xbe: return { "das" }; + case 0xbf: return { "lda (x++)" }; + case 0xc0: return { "cli" }; + case 0xc1: return { "jst $ffc6" }; + case 0xc2: return { "set $", dp(0), ":6" }; + case 0xc3: return { "bbs $", dp(0), ":6=$", r(+3, 1) }; + case 0xc4: return { "sta $", dp(0) }; + case 0xc5: return { "sta $", a() }; + case 0xc6: return { "sta (x)" }; + case 0xc7: return { "sta ($", dp(0), ",x)" }; + case 0xc8: return { "cpx #$", b(0) }; + case 0xc9: return { "stx $", a() }; + case 0xca: return { "stc $", ab() }; + case 0xcb: return { "sty $", dp(0) }; + case 0xcc: return { "sty $", a() }; + case 0xcd: return { "ldx #$", b(0) }; + case 0xce: return { "plx" }; + case 0xcf: return { "mul" }; + case 0xd0: return { "bne $", r(+2) }; + case 0xd1: return { "jst $ffc4" }; + case 0xd2: return { "clr $", dp(0), ":6" }; + case 0xd3: return { "bbc $", dp(0), ":6=$", r(+3, 1) }; + case 0xd4: return { "sta $", dp(0), ",x" }; + case 0xd5: return { "sta $", a(), ",x" }; + case 0xd6: return { "sta $", a(), ",y" }; + case 0xd7: return { "sta ($", dp(0), "),y" }; + case 0xd8: return { "stx $", dp(0) }; + case 0xd9: return { "stx $", dp(0), ",y" }; + case 0xda: return { "stw $", dp(0) }; + case 0xdb: return { "sty $", dp(0), ",x" }; + case 0xdc: return { "dey" }; + case 0xdd: return { "tya" }; + case 0xde: return { "bne $", dp(0), ",x=$", r(+3, 1) }; + case 0xdf: return { "daa" }; + case 0xe0: return { "clv" }; + case 0xe1: return { "jst $ffc2" }; + case 0xe2: return { "set $", dp(0), ":7" }; + case 0xe3: return { "bbs $", dp(0), ":7=$", r(+3, 1) }; + case 0xe4: return { "lda $", dp(0) }; + case 0xe5: return { "lda $", a() }; + case 0xe6: return { "lda (x)" }; + case 0xe7: return { "lda ($", dp(0), ",x)" }; + case 0xe8: return { "lda #$", b(0) }; + case 0xe9: return { "ldx $", a() }; + case 0xea: return { "not $", ab() }; + case 0xeb: return { "ldy $", dp(0) }; + case 0xec: return { "ldy $", a() }; + case 0xed: return { "cmc" }; + case 0xee: return { "ply" }; + case 0xef: return { "wai" }; + case 0xf0: return { "beq $", r(+2) }; + case 0xf1: return { "jst $ffc0" }; + case 0xf2: return { "clr $", dp(0), ":7" }; + case 0xf3: return { "bbc $", dp(0), ":7=$", r(+3, 1) }; + case 0xf4: return { "lda $", dp(0), ",x" }; + case 0xf5: return { "lda $", a(), ",x" }; + case 0xf6: return { "lda $", a(), ",y" }; + case 0xf7: return { "lda ($", dp(0), "),y" }; + case 0xf8: return { "ldx $", dp(0) }; + case 0xf9: return { "ldx $", dp(0), ",y" }; + case 0xfa: return { "str $", dp(1), "=$", dp(0) }; + case 0xfb: return { "ldy $", dp(0), ",x" }; + case 0xfc: return { "iny" }; + case 0xfd: return { "tay" }; + case 0xfe: return { "bne --y=$", r(+2) }; + case 0xff: return { "stp" }; + } + throw; + }; + + string output = { "..", hex<4>(addr), " ", mnemonic() }; + + unsigned length = output.length(); + while(length++ < 30) output.append(" "); + + output.append( + "YA:", hex<4>(regs.ya), + " A:", hex<2>(regs.a), + " X:", hex<2>(regs.x), + " Y:", hex<2>(regs.y), + " S:", hex<2>(regs.s), + " ", + regs.p.n ? "N" : "n", + regs.p.v ? "V" : "v", + regs.p.p ? "P" : "p", + regs.p.b ? "B" : "b", + regs.p.h ? "H" : "h", + regs.p.i ? "I" : "i", + regs.p.z ? "Z" : "z", + regs.p.c ? "C" : "c" + ); + + return output; +} + +#endif diff --git a/bsnes/snes/smp/core/memory.hpp b/bsnes/snes/smp/core/memory.hpp index 4b7afba0..c4b6d99f 100755 --- a/bsnes/snes/smp/core/memory.hpp +++ b/bsnes/snes/smp/core/memory.hpp @@ -1,19 +1,19 @@ -alwaysinline uint8_t op_readpc() { +alwaysinline uint8 op_readpc() { return op_read(regs.pc++); } -alwaysinline uint8_t op_readsp() { - return op_read(0x0100 | ++regs.sp); +alwaysinline uint8 op_readsp() { + return op_read(0x0100 | ++regs.s); } -alwaysinline void op_writesp(uint8_t data) { - op_write(0x0100 | regs.sp--, data); +alwaysinline void op_writesp(uint8 data) { + return op_write(0x0100 | regs.s--, data); } -alwaysinline uint8_t op_readdp(uint8_t addr) { - return op_read(((unsigned)regs.p.p << 8) + addr); +alwaysinline uint8 op_readdp(uint8 addr) { + return op_read((regs.p.p << 8) + addr); } -alwaysinline void op_writedp(uint8_t addr, uint8_t data) { - op_write(((unsigned)regs.p.p << 8) + addr, data); +alwaysinline void op_writedp(uint8 addr, uint8 data) { + return op_write((regs.p.p << 8) + addr, data); } diff --git a/bsnes/snes/smp/core/opcodes.cpp b/bsnes/snes/smp/core/opcodes.cpp new file mode 100755 index 00000000..09251f45 --- /dev/null +++ b/bsnes/snes/smp/core/opcodes.cpp @@ -0,0 +1,559 @@ +#ifdef SMPCORE_CPP +#define call (this->*op) + +template +void SMPcore::op_adjust(uint8 &r) { + op_io(); + r = call(r); +} + +template +void SMPcore::op_adjust_addr() { + dp.l = op_readpc(); + dp.h = op_readpc(); + rd = op_read(dp); + rd = call(rd); + op_write(dp, rd); +} + +template +void SMPcore::op_adjust_dp() { + dp = op_readpc(); + rd = op_readdp(dp); + rd = call(rd); + op_writedp(dp, rd); +} + +void SMPcore::op_adjust_dpw(signed n) { + dp = op_readpc(); + rd.w = op_readdp(dp) + n; + op_writedp(dp++, rd.l); + rd.h += op_readdp(dp); + op_writedp(dp++, rd.h); + regs.p.n = rd & 0x8000; + regs.p.z = rd == 0; +} + +template +void SMPcore::op_adjust_dpx() { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = call(rd); + op_writedp(dp + regs.x, rd); +} + +void SMPcore::op_branch(bool condition) { + rd = op_readpc(); + if(condition == false) return; + op_io(); + op_io(); + regs.pc += (int8)rd; +} + +void SMPcore::op_branch_bit() { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((bool)(sp & (1 << (opcode >> 5))) == (bool)(opcode & 0x10)) return; + op_io(); + op_io(); + regs.pc += (int8)rd; +} + +void SMPcore::op_pull(uint8 &r) { + op_io(); + op_io(); + r = op_readsp(); +} + +void SMPcore::op_push(uint8 r) { + op_io(); + op_io(); + op_writesp(r); +} + +template +void SMPcore::op_read_addr(uint8 &r) { + dp.l = op_readpc(); + dp.h = op_readpc(); + rd = op_read(dp); + r = call(r, rd); +} + +template +void SMPcore::op_read_addri(uint8 &r) { + dp.l = op_readpc(); + dp.h = op_readpc(); + op_io(); + rd = op_read(dp + r); + regs.a = call(regs.a, rd); +} + +template +void SMPcore::op_read_const(uint8 &r) { + rd = op_readpc(); + r = call(r, rd); +} + +template +void SMPcore::op_read_dp(uint8 &r) { + dp = op_readpc(); + rd = op_readdp(dp); + r = call(r, rd); +} + +template +void SMPcore::op_read_dpi(uint8 &r, uint8 &i) { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + i); + r = call(r, rd); +} + +template +void SMPcore::op_read_dpw() { + dp = op_readpc(); + rd.l = op_readdp(dp++); + if(op != &SMPcore::op_cpw) op_io(); + rd.h = op_readdp(dp++); + regs.ya = call(regs.ya, rd); +} + +template +void SMPcore::op_read_idpx() { + dp = op_readpc() + regs.x; + op_io(); + sp.l = op_readdp(dp++); + sp.h = op_readdp(dp++); + rd = op_read(sp); + regs.a = call(regs.a, rd); +} + +template +void SMPcore::op_read_idpy() { + dp = op_readpc(); + op_io(); + sp.l = op_readdp(dp++); + sp.h = op_readdp(dp++); + rd = op_read(sp + regs.y); + regs.a = call(regs.a, rd); +} + +template +void SMPcore::op_read_ix() { + op_io(); + rd = op_readdp(regs.x); + regs.a = call(regs.a, rd); +} + +void SMPcore::op_set_addr_bit() { + dp.l = op_readpc(); + dp.h = op_readpc(); + bit = dp >> 13; + dp &= 0x1fff; + rd = op_read(dp); + switch(opcode >> 5) { + case 0: //orc addr:bit + case 1: //orc !addr:bit + op_io(); + regs.p.c |= (rd & (1 << bit)) ^ (bool)(opcode & 0x20); + break; + case 2: //and addr:bit + case 3: //and !addr:bit + regs.p.c &= (rd & (1 << bit)) ^ (bool)(opcode & 0x20); + break; + case 4: //eor addr:bit + op_io(); + regs.p.c ^= (rd & (1 << bit)); + break; + case 5: //ldc addr:bit + regs.p.c = (rd & (1 << bit)); + break; + case 6: //stc addr:bit + op_io(); + rd = (rd & ~(1 << bit)) | (regs.p.c << bit); + op_write(dp, rd); + break; + case 7: //not addr:bit + rd ^= 1 << bit; + op_write(dp, rd); + break; + } +} + +void SMPcore::op_set_bit() { + dp = op_readpc(); + rd = op_readdp(dp) & ~(1 << (opcode >> 5)); + op_writedp(dp, rd | (!(opcode & 0x10) << (opcode >> 5))); +} + +void SMPcore::op_set_flag(bool &flag, bool data) { + op_io(); + if(&flag == ®s.p.i) op_io(); + flag = data; +} + +void SMPcore::op_test_addr(bool set) { + dp.l = op_readpc(); + dp.h = op_readpc(); + rd = op_read(dp); + regs.p.n = (regs.a - rd) & 0x80; + regs.p.z = (regs.a - rd) == 0; + op_read(dp); + op_write(dp, set ? rd | regs.a : rd & ~regs.a); +} + +void SMPcore::op_transfer(uint8 &from, uint8 &to) { + op_io(); + to = from; + if(&to == ®s.s) return; + regs.p.n = (to & 0x80); + regs.p.z = (to == 0); +} + +void SMPcore::op_write_addr(uint8 &r) { + dp.l = op_readpc(); + dp.h = op_readpc(); + op_read(dp); + op_write(dp, r); +} + +void SMPcore::op_write_addri(uint8 &i) { + dp.l = op_readpc(); + dp.h = op_readpc(); + op_io(); + dp += i; + op_read(dp); + op_write(dp, regs.a); +} + +void SMPcore::op_write_dp(uint8 &r) { + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, r); +} + +void SMPcore::op_write_dpi(uint8 &r, uint8 &i) { + dp = op_readpc() + i; + op_io(); + op_readdp(dp); + op_writedp(dp, r); +} + +template +void SMPcore::op_write_dp_const() { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = call(wr, rd); + op != &SMPcore::op_cmp ? op_writedp(dp, wr) : op_io(); +} + +template +void SMPcore::op_write_dp_dp() { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + if(op != &SMPcore::op_st) wr = op_readdp(dp); + wr = call(wr, rd); + op != &SMPcore::op_cmp ? op_writedp(dp, wr) : op_io(); +} + +template +void SMPcore::op_write_ix_iy() { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = call(wr, rd); + op != &SMPcore::op_cmp ? op_writedp(regs.x, wr) : op_io(); +} + +// + +void SMPcore::op_bne_dp() { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if(regs.a == sp) return; + op_io(); + op_io(); + regs.pc += (int8)rd; +} + +void SMPcore::op_bne_dpdec() { + dp = op_readpc(); + wr = op_readdp(dp); + op_writedp(dp, --wr); + rd = op_readpc(); + if(wr == 0) return; + op_io(); + op_io(); + regs.pc += (int8)rd; +} + +void SMPcore::op_bne_dpx() { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp + regs.x); + rd = op_readpc(); + op_io(); + if(regs.a == sp) return; + op_io(); + op_io(); + regs.pc += (int8)rd; +} + +void SMPcore::op_bne_ydec() { + rd = op_readpc(); + op_io(); + op_io(); + if(--regs.y == 0) return; + op_io(); + op_io(); + regs.pc += (int8)rd; +} + +void SMPcore::op_brk() { + rd.l = op_read(0xffde); + rd.h = op_read(0xffdf); + op_io(); + op_io(); + op_writesp(regs.pc.h); + op_writesp(regs.pc.l); + op_writesp(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; +} + +void SMPcore::op_clv() { + op_io(); + regs.p.v = 0; + regs.p.h = 0; +} + +void SMPcore::op_cmc() { + op_io(); + op_io(); + regs.p.c = !regs.p.c; +} + +void SMPcore::op_daa() { + op_io(); + op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = (regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +void SMPcore::op_das() { + op_io(); + op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = (regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +void SMPcore::op_div_ya_x() { + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = (regs.y >= regs.x); + regs.p.h = ((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + } + //result is set based on a (quotient) only + regs.p.n = (regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +void SMPcore::op_jmp_addr() { + rd.l = op_readpc(); + rd.h = op_readpc(); + regs.pc = rd; +} + +void SMPcore::op_jmp_iaddrx() { + dp.l = op_readpc(); + dp.h = op_readpc(); + op_io(); + dp += regs.x; + rd.l = op_read(dp++); + rd.h = op_read(dp++); + regs.pc = rd; +} + +void SMPcore::op_jsp_dp() { + rd = op_readpc(); + op_io(); + op_io(); + op_writesp(regs.pc.h); + op_writesp(regs.pc.l); + regs.pc = 0xff00 | rd; +} + +void SMPcore::op_jsr_addr() { + rd.l = op_readpc(); + rd.h = op_readpc(); + op_io(); + op_io(); + op_io(); + op_writesp(regs.pc.h); + op_writesp(regs.pc.l); + regs.pc = rd; +} + +void SMPcore::op_jst() { + dp = 0xffde - ((opcode >> 4) << 1); + rd.l = op_read(dp++); + rd.h = op_read(dp++); + op_io(); + op_io(); + op_io(); + op_writesp(regs.pc.h); + op_writesp(regs.pc.l); + regs.pc = rd; +} + +void SMPcore::op_lda_ixinc() { + op_io(); + regs.a = op_readdp(regs.x++); + op_io(); + regs.p.n = regs.a & 0x80; + regs.p.z = regs.a == 0; +} + +void SMPcore::op_mul_ya() { + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = (regs.y & 0x80); + regs.p.z = (regs.y == 0); +} + +void SMPcore::op_nop() { + op_io(); +} + +void SMPcore::op_plp() { + op_io(); + op_io(); + regs.p = op_readsp(); +} + +void SMPcore::op_rti() { + regs.p = op_readsp(); + rd.l = op_readsp(); + rd.h = op_readsp(); + op_io(); + op_io(); + regs.pc = rd; +} + +void SMPcore::op_rts() { + rd.l = op_readsp(); + rd.h = op_readsp(); + op_io(); + op_io(); + regs.pc = rd; +} + +void SMPcore::op_sta_idpx() { + sp = op_readpc() + regs.x; + op_io(); + dp.l = op_readdp(sp++); + dp.h = op_readdp(sp++); + op_read(dp); + op_write(dp, regs.a); +} + +void SMPcore::op_sta_idpy() { + sp = op_readpc(); + dp.l = op_readdp(sp++); + dp.h = op_readdp(sp++); + op_io(); + dp += regs.y; + op_read(dp); + op_write(dp, regs.a); +} + +void SMPcore::op_sta_ix() { + op_io(); + op_readdp(regs.x); + op_writedp(regs.x, regs.a); +} + +void SMPcore::op_sta_ixinc() { + op_io(); + op_io(); + op_writedp(regs.x++, regs.a); +} + +void SMPcore::op_stw_dp() { + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp++, regs.a); + op_writedp(dp++, regs.y); +} + +void SMPcore::op_wait() { + while(true) { + op_io(); + op_io(); + } +} + +void SMPcore::op_xcn() { + op_io(); + op_io(); + op_io(); + op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = regs.a & 0x80; + regs.p.z = regs.a == 0; +} + +#undef call +#endif diff --git a/bsnes/snes/smp/core/registers.hpp b/bsnes/snes/smp/core/registers.hpp index baed447b..8a4916fc 100755 --- a/bsnes/snes/smp/core/registers.hpp +++ b/bsnes/snes/smp/core/registers.hpp @@ -1,44 +1,49 @@ -struct regya_t { - uint8_t &hi, &lo; - - inline operator uint16_t() const { - return (hi << 8) + lo; - } - - inline regya_t& operator=(uint16_t data) { - hi = data >> 8; - lo = data; - return *this; - } - - regya_t(uint8_t &hi_, uint8_t &lo_) : hi(hi_), lo(lo_) {} -}; - struct flag_t { bool n, v, p, b, h, i, z, c; inline operator unsigned() const { - return (n << 7) + (v << 6) + (p << 5) + (b << 4) - + (h << 3) + (i << 2) + (z << 1) + (c << 0); + return (n << 7) | (v << 6) | (p << 5) | (b << 4) + | (h << 3) | (i << 2) | (z << 1) | (c << 0); } - inline unsigned operator=(uint8_t data) { + inline unsigned operator=(uint8 data) { n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10; h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01; return data; } - inline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); } - inline unsigned operator^=(unsigned data) { return operator=(operator unsigned() ^ data); } - inline unsigned operator&=(unsigned data) { return operator=(operator unsigned() & data); } + inline unsigned operator|=(uint8 data) { return operator=(operator unsigned() | data); } + inline unsigned operator^=(uint8 data) { return operator=(operator unsigned() ^ data); } + inline unsigned operator&=(uint8 data) { return operator=(operator unsigned() & data); } +}; - flag_t() : n(0), v(0), p(0), b(0), h(0), i(0), z(0), c(0) {} +struct word_t { + union { + uint16 w; + struct { uint8 order_lsb2(l, h); }; + }; + + inline operator unsigned() const { return w; } + inline unsigned operator=(unsigned data) { w = data; return w; } + + inline unsigned operator++() { return ++w; } + inline unsigned operator--() { return --w; } + inline unsigned operator++(int) { unsigned data = w++; return data; } + inline unsigned operator--(int) { unsigned data = w--; return data; } + + inline unsigned operator|=(unsigned data) { w |= data; return w; } + inline unsigned operator^=(unsigned data) { w ^= data; return w; } + inline unsigned operator&=(unsigned data) { w &= data; return w; } + inline unsigned operator+=(unsigned data) { w += data; return w; } + inline unsigned operator-=(unsigned data) { w -= data; return w; } }; struct regs_t { - uint16_t pc; - uint8_t r[4], &a, &x, &y, &sp; - regya_t ya; + word_t pc; + union { + uint16 ya; + struct { uint8 order_lsb2(a, y); }; + }; + uint8 x, s; flag_t p; - regs_t() : a(r[0]), x(r[1]), y(r[2]), sp(r[3]), ya(r[2], r[0]) {} }; diff --git a/bsnes/snes/smp/core/serialization.cpp b/bsnes/snes/smp/core/serialization.cpp index 883d013c..c25e2294 100755 --- a/bsnes/snes/smp/core/serialization.cpp +++ b/bsnes/snes/smp/core/serialization.cpp @@ -5,7 +5,7 @@ void SMPcore::core_serialize(serializer &s) { s.integer(regs.a); s.integer(regs.x); s.integer(regs.y); - s.integer(regs.sp); + s.integer(regs.s); s.integer(regs.p.n); s.integer(regs.p.v); s.integer(regs.p.p); @@ -15,12 +15,13 @@ void SMPcore::core_serialize(serializer &s) { s.integer(regs.p.z); s.integer(regs.p.c); - s.integer(dp); - s.integer(sp); - s.integer(rd); - s.integer(wr); - s.integer(bit); - s.integer(ya); + s.integer(opcode); + s.integer(dp.w); + s.integer(sp.w); + s.integer(rd.w); + s.integer(wr.w); + s.integer(bit.w); + s.integer(ya.w); } #endif diff --git a/bsnes/snes/smp/smp.cpp b/bsnes/snes/smp/smp.cpp index c9419300..d01f6ffc 100755 --- a/bsnes/snes/smp/smp.cpp +++ b/bsnes/snes/smp/smp.cpp @@ -48,10 +48,6 @@ void SMP::enter() { } } -void SMP::op_step() { - (this->*opcode_table[op_readpc()])(); -} - void SMP::power() { //targets not initialized/changed upon reset timer0.target = 0; @@ -68,7 +64,7 @@ void SMP::reset() { regs.a = 0x00; regs.x = 0x00; regs.y = 0x00; - regs.sp = 0xef; + regs.s = 0xef; regs.p = 0x02; for(auto &n : apuram) n = random(0x00); diff --git a/bsnes/snes/smp/smp.hpp b/bsnes/snes/smp/smp.hpp index 5c2d9904..6b387cba 100755 --- a/bsnes/snes/smp/smp.hpp +++ b/bsnes/snes/smp/smp.hpp @@ -48,7 +48,6 @@ private: } status; static void Enter(); - debugvirtual void op_step(); friend class SMPcore; friend class SMPDebugger; diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 91196f9e..dffeeee3 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -4,7 +4,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const unsigned SerializerVersion = 22; + static const unsigned SerializerVersion = 23; } } diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index 9c5cddea..59bac117 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -27,7 +27,7 @@ void Application::run() { } Application::Application(int argc, char **argv) { - title = "bsnes v084"; + title = "bsnes v084.01"; application = this; quit = false;