mirror of https://github.com/bsnes-emu/bsnes.git
Update to v084r01 release.
I rewrote the S-SMP processor core (implementation of the 256 opcodes), utilizing my new 6502-like syntax. It matches what bass v05r01 uses. Took 10 hours. Due to being able to group the "mov reg,mem" opcodes together with "adc/sbc/ora/and/eor/cmp" sets, the total code size was reduced from 55.7KB to 42.5KB for identical accuracy and speed. I also dropped the trick I was using to pass register variables as template arguments, and instead just use a switch table to pass them as function arguments. Makes the table a lot easier to read. Passes all of my S-SMP tests, and all of blargg's arithmetic/cycle-timing S-SMP tests. Runs Zelda 3 great as well. Didn't test further. This does have the potential to cause some regressions if I've messed anything up, and none of the above tests caught it, so as always, testing would be appreciated. Anyway, yeah. By writing the actual processor with this new mnemonic set, it confirms the parallels I've made. My guess is that Sony really did clone the 6502, but was worried about legal implications or something and changed the mnemonics last-minute. (Note to self: need to re-enable snes.random before v085 official.) EDIT: oh yeah, I also commented out the ALSA snd_pcm_drain() inside term(). Without it, there is a tiny pop when the driver is re-initialized. But with it, the entire emulator would lock up for five whole seconds waiting on that call to complete. I'll take the pop any day over that.
This commit is contained in:
parent
ae6c3c377d
commit
2cc077e12b
|
@ -16,6 +16,7 @@
|
|||
#include <nall/sha256.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
#include <nall/varint.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
|
||||
#include <nall/windows/utf8.hpp>
|
||||
|
@ -39,6 +40,7 @@
|
|||
#include <nall/string/split.hpp>
|
||||
#include <nall/string/utility.hpp>
|
||||
#include <nall/string/variadic.hpp>
|
||||
#include <nall/string/wildcard.hpp>
|
||||
#include <nall/string/wrapper.hpp>
|
||||
#include <nall/string/xml.hpp>
|
||||
#undef NALL_STRING_INTERNAL_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<typename... Args> 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
|
||||
|
|
|
@ -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>(bool v) { return v ? "true" : "false"; }
|
||||
template<> inline const char* to_string<char>(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<typename T> struct stringify;
|
||||
|
||||
template<> inline const char* to_string<signed char> (signed char v) { static char temp[256]; return integer(temp, v); }
|
||||
template<> inline const char* to_string<signed short> (signed short v) { static char temp[256]; return integer(temp, v); }
|
||||
template<> inline const char* to_string<signed int> (signed int v) { static char temp[256]; return integer(temp, v); }
|
||||
template<> inline const char* to_string<signed long> (signed long v) { static char temp[256]; return integer(temp, v); }
|
||||
template<> inline const char* to_string<signed long long>(signed long long v) { static char temp[256]; return integer(temp, v); }
|
||||
// base types
|
||||
|
||||
template<> inline const char* to_string<unsigned char> (unsigned char v) { static char temp[256]; return decimal(temp, v); }
|
||||
template<> inline const char* to_string<unsigned short> (unsigned short v) { static char temp[256]; return decimal(temp, v); }
|
||||
template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; return decimal(temp, v); }
|
||||
template<> inline const char* to_string<unsigned long> (unsigned long v) { static char temp[256]; return decimal(temp, v); }
|
||||
template<> inline const char* to_string<unsigned long long>(unsigned long long v) { static char temp[256]; return decimal(temp, v); }
|
||||
template<> struct stringify<bool> {
|
||||
bool value;
|
||||
operator const char*() const { return value ? "true" : "false"; }
|
||||
stringify(bool value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> inline const char* to_string<float> (float v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
|
||||
template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
|
||||
template<> inline const char* to_string<long double>(long double v) { static char temp[256]; snprintf(temp, 255, "%Lf", v); return temp; }
|
||||
template<> struct stringify<char> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(char value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<> inline const char* to_string<char*> (char *v) { return v; }
|
||||
template<> inline const char* to_string<const char*> (const char *v) { return v; }
|
||||
template<> inline const char* to_string<string> (string v) { return v; }
|
||||
template<> inline const char* to_string<const string&> (const string &v) { return v; }
|
||||
template<> inline const char* to_string<cstring> (cstring v) { return v; }
|
||||
template<> inline const char* to_string<const cstring&>(const cstring &v) { return v; }
|
||||
// signed integers
|
||||
|
||||
template<> struct stringify<signed char> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(signed char value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<signed short> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(signed short value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<signed int> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(signed int value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<signed long> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(signed long value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<signed long long> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(signed long long value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<unsigned bits> struct stringify<int_t<bits>> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(int_t<bits> value) { integer(data, value); }
|
||||
};
|
||||
|
||||
// unsigned integers
|
||||
|
||||
template<> struct stringify<unsigned char> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(unsigned char value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned short> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(unsigned short value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned int> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(unsigned int value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned long> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(unsigned long value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned long long> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(unsigned long long value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
template<unsigned bits> struct stringify<uint_t<bits>> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(uint_t<bits> value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
// floating-point
|
||||
|
||||
template<> struct stringify<float> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(float value) { snprintf(data, 255, "%f", value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<double> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(double value) { snprintf(data, 255, "%f", value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<long double> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(long double value) { snprintf(data, 255, "%Lf", value); }
|
||||
};
|
||||
|
||||
// strings
|
||||
|
||||
template<> struct stringify<char*> {
|
||||
const char *value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(char *value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<const char*> {
|
||||
const char *value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(const char *value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<string> {
|
||||
const string &value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(const string &value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<const string&> {
|
||||
const string &value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(const string &value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<cstring> {
|
||||
const char *value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(const cstring &value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<const cstring&> {
|
||||
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>(QString v) { return v.toUtf8().constData(); }
|
||||
template<> inline const char* to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
|
||||
string::operator QString() const { return QString::fromUtf8(*this); }
|
||||
|
||||
template<> struct stringify<QString> {
|
||||
const QString &value;
|
||||
operator const char*() const { return value.toUtf8().constData(); }
|
||||
stringify(const QString &value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<const QString&> {
|
||||
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<typename T> stringify<T> make_string(T value) {
|
||||
return stringify<T>(std::forward<T>(value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ static void istring(string &output) {
|
|||
|
||||
template<typename T, typename... Args>
|
||||
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>(args)...);
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
|
@ -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];
|
||||
|
|
|
@ -150,8 +150,6 @@ void pOS::processEvents() {
|
|||
}
|
||||
|
||||
void pOS::quit() {
|
||||
settings->save();
|
||||
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
if(gtk_tree_model_get_iter_from_string(model, &iter, string(row)) == false) return;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::constructor() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,35 @@
|
|||
#include <snes/snes.hpp>
|
||||
|
||||
#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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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<int, int> void op_mov_reg_reg();
|
||||
void op_mov_sp_x();
|
||||
template<int> void op_mov_reg_const();
|
||||
void op_mov_a_ix();
|
||||
void op_mov_a_ixinc();
|
||||
template<int> void op_mov_reg_dp();
|
||||
template<int, int> void op_mov_reg_dpr();
|
||||
template<int> void op_mov_reg_addr();
|
||||
template<int> 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<int> void op_mov_dp_reg();
|
||||
template<int, int> void op_mov_dpr_reg();
|
||||
template<int> void op_mov_addr_reg();
|
||||
template<int> 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<int, int> void op_branch();
|
||||
template<int, int> 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<int> void op_tcall();
|
||||
void op_brk();
|
||||
void op_ret();
|
||||
void op_reti();
|
||||
|
||||
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_reg_const();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_ix();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_reg_dp();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_dpx();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_reg_addr();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_a_addrr();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_idpx();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_idpy();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_ix_iy();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_dp_dp();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_dp_const();
|
||||
template<uint16 (SMPcore::*)(uint16, uint16)> void op_read_ya_dp();
|
||||
void op_cmpw_ya_dp();
|
||||
template<int> void op_and1_bit();
|
||||
void op_eor1_bit();
|
||||
void op_not1_bit();
|
||||
template<int> void op_or1_bit();
|
||||
|
||||
template<uint8 (SMPcore::*)(uint8), int> void op_adjust_reg();
|
||||
template<uint8 (SMPcore::*)(uint8)> void op_adjust_dp();
|
||||
template<uint8 (SMPcore::*)(uint8)> void op_adjust_dpx();
|
||||
template<uint8 (SMPcore::*)(uint8)> void op_adjust_addr();
|
||||
template<int> void op_adjust_addr_a();
|
||||
template<int> void op_adjustw_dp();
|
||||
|
||||
void op_nop();
|
||||
void op_wait();
|
||||
void op_xcn();
|
||||
void op_daa();
|
||||
void op_das();
|
||||
template<int, int> void op_setbit();
|
||||
void op_notc();
|
||||
template<int> void op_seti();
|
||||
template<int, int> void op_setbit_dp();
|
||||
template<int> void op_push_reg();
|
||||
void op_push_p();
|
||||
template<int> 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();
|
||||
};
|
|
@ -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);
|
||||
}
|
|
@ -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]) {}
|
||||
};
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<int, int> void op_mov_reg_reg();
|
||||
void op_mov_sp_x();
|
||||
template<int> void op_mov_reg_const();
|
||||
void op_mov_a_ix();
|
||||
void op_mov_a_ixinc();
|
||||
template<int> void op_mov_reg_dp();
|
||||
template<int, int> void op_mov_reg_dpr();
|
||||
template<int> void op_mov_reg_addr();
|
||||
template<int> 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<int> void op_mov_dp_reg();
|
||||
template<int, int> void op_mov_dpr_reg();
|
||||
template<int> void op_mov_addr_reg();
|
||||
template<int> 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<int, int> void op_branch();
|
||||
template<int, int> 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<int> void op_tcall();
|
||||
void op_brk();
|
||||
void op_ret();
|
||||
void op_reti();
|
||||
|
||||
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_reg_const();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_ix();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_reg_dp();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_dpx();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_reg_addr();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_a_addrr();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_idpx();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_idpy();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_ix_iy();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_dp_dp();
|
||||
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_dp_const();
|
||||
template<uint16 (SMPcore::*)(uint16, uint16)> void op_read_ya_dp();
|
||||
void op_cmpw_ya_dp();
|
||||
template<int> void op_and1_bit();
|
||||
void op_eor1_bit();
|
||||
void op_not1_bit();
|
||||
template<int> void op_or1_bit();
|
||||
|
||||
template<uint8 (SMPcore::*)(uint8), int> void op_adjust_reg();
|
||||
template<uint8 (SMPcore::*)(uint8)> void op_adjust_dp();
|
||||
template<uint8 (SMPcore::*)(uint8)> void op_adjust_dpx();
|
||||
template<uint8 (SMPcore::*)(uint8)> void op_adjust_addr();
|
||||
template<int> void op_adjust_addr_a();
|
||||
template<int> void op_adjustw_dp();
|
||||
|
||||
void op_nop();
|
||||
void op_wait();
|
||||
void op_xcn();
|
||||
void op_daa();
|
||||
void op_das();
|
||||
template<int, int> void op_setbit();
|
||||
void op_notc();
|
||||
template<int> void op_seti();
|
||||
template<int, int> void op_setbit_dp();
|
||||
template<int> void op_push_reg();
|
||||
void op_push_p();
|
||||
template<int> 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<uint8 (SMPcore::*op)(uint8)> void op_adjust(uint8&);
|
||||
template<uint8 (SMPcore::*op)(uint8)> void op_adjust_addr();
|
||||
template<uint8 (SMPcore::*op)(uint8)> void op_adjust_dp();
|
||||
void op_adjust_dpw(signed);
|
||||
template<uint8 (SMPcore::*op)(uint8)> void op_adjust_dpx();
|
||||
void op_branch(bool);
|
||||
void op_branch_bit();
|
||||
void op_pull(uint8&);
|
||||
void op_push(uint8);
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_addr(uint8&);
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_addri(uint8&);
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_const(uint8&);
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_dp(uint8&);
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_dpi(uint8&, uint8&);
|
||||
template<uint16 (SMPcore::*op)(uint16, uint16)> void op_read_dpw();
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_idpx();
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_idpy();
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)> 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<uint8 (SMPcore::*op)(uint8, uint8)> void op_write_dp_const();
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_write_dp_dp();
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)> 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();
|
||||
};
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,559 @@
|
|||
#ifdef SMPCORE_CPP
|
||||
#define call (this->*op)
|
||||
|
||||
template<uint8 (SMPcore::*op)(uint8)>
|
||||
void SMPcore::op_adjust(uint8 &r) {
|
||||
op_io();
|
||||
r = call(r);
|
||||
}
|
||||
|
||||
template<uint8 (SMPcore::*op)(uint8)>
|
||||
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<uint8 (SMPcore::*op)(uint8)>
|
||||
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<uint8 (SMPcore::*op)(uint8)>
|
||||
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<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
void SMPcore::op_read_addr(uint8 &r) {
|
||||
dp.l = op_readpc();
|
||||
dp.h = op_readpc();
|
||||
rd = op_read(dp);
|
||||
r = call(r, rd);
|
||||
}
|
||||
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
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<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
void SMPcore::op_read_const(uint8 &r) {
|
||||
rd = op_readpc();
|
||||
r = call(r, rd);
|
||||
}
|
||||
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
void SMPcore::op_read_dp(uint8 &r) {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
r = call(r, rd);
|
||||
}
|
||||
|
||||
template<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
void SMPcore::op_read_dpi(uint8 &r, uint8 &i) {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + i);
|
||||
r = call(r, rd);
|
||||
}
|
||||
|
||||
template<uint16 (SMPcore::*op)(uint16, uint16)>
|
||||
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<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
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<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
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<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
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<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
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<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
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<uint8 (SMPcore::*op)(uint8, uint8)>
|
||||
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
|
|
@ -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;
|
||||
flag_t p;
|
||||
regs_t() : a(r[0]), x(r[1]), y(r[2]), sp(r[3]), ya(r[2], r[0]) {}
|
||||
word_t pc;
|
||||
union {
|
||||
uint16 ya;
|
||||
struct { uint8 order_lsb2(a, y); };
|
||||
};
|
||||
uint8 x, s;
|
||||
flag_t p;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -48,7 +48,6 @@ private:
|
|||
} status;
|
||||
|
||||
static void Enter();
|
||||
debugvirtual void op_step();
|
||||
|
||||
friend class SMPcore;
|
||||
friend class SMPDebugger;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const unsigned SerializerVersion = 22;
|
||||
static const unsigned SerializerVersion = 23;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ void Application::run() {
|
|||
}
|
||||
|
||||
Application::Application(int argc, char **argv) {
|
||||
title = "bsnes v084";
|
||||
title = "bsnes v084.01";
|
||||
|
||||
application = this;
|
||||
quit = false;
|
||||
|
|
Loading…
Reference in New Issue