diff --git a/bsnes/Makefile b/bsnes/Makefile index ea24f98a9..167a3a207 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -92,7 +92,7 @@ sync: rm -r phoenix/nall rm -r phoenix/test -archive-all: +archive: if [ -f bsnes.tar.bz2 ]; then rm bsnes.tar.bz2; fi tar -cjf bsnes.tar.bz2 `ls` diff --git a/bsnes/base/base.hpp b/bsnes/base/base.hpp index a0e3414b4..0c087923f 100755 --- a/bsnes/base/base.hpp +++ b/bsnes/base/base.hpp @@ -1,7 +1,7 @@ #ifndef BASE_HPP #define BASE_HPP -static const char Version[] = "087.08"; +static const char Version[] = "087.09"; #include #include diff --git a/bsnes/gba/apu/apu.cpp b/bsnes/gba/apu/apu.cpp index bcadcb2ec..2a4ce3f35 100755 --- a/bsnes/gba/apu/apu.cpp +++ b/bsnes/gba/apu/apu.cpp @@ -19,6 +19,11 @@ void APU::step(unsigned clocks) { } uint32 APU::read(uint32 addr, uint32 size) { + if(addr == 0x04000088) { + //SOUNDBIAS + return 0x0200; + } + return 0u; } @@ -27,6 +32,8 @@ void APU::write(uint32 addr, uint32 size, uint32 word) { void APU::power() { create(APU::Enter, 16777216); + + bus.mmio[0x0088] = this; } } diff --git a/bsnes/gba/cpu/cpu.cpp b/bsnes/gba/cpu/cpu.cpp index 80ed02ede..38fe44321 100755 --- a/bsnes/gba/cpu/cpu.cpp +++ b/bsnes/gba/cpu/cpu.cpp @@ -50,7 +50,6 @@ void CPU::power() { } uint32 CPU::read(uint32 addr, uint32 size) { - if(addr == 0x04000300) return prng() & 1; return 0u; } diff --git a/bsnes/gba/memory/memory.cpp b/bsnes/gba/memory/memory.cpp index 301db043e..aa36a122a 100755 --- a/bsnes/gba/memory/memory.cpp +++ b/bsnes/gba/memory/memory.cpp @@ -5,8 +5,8 @@ namespace GBA { Bus bus; struct UnmappedMemory : Memory { - uint32 read(uint32 addr, uint32 size) { return 0u; } - void write(uint32 addr, uint32 size, uint32 word) {} + uint32 read(uint32 addr, uint32 size) { print(hex<8>(addr), ":", decimal<2>(size), "\n"); return 0u; } + void write(uint32 addr, uint32 size, uint32 word) { print(hex<8>(addr), ":", decimal<2>(size), "=", hex<8>(word), "\n"); } }; static UnmappedMemory unmappedMemory; diff --git a/bsnes/nall/map.hpp b/bsnes/nall/map.hpp index 84709781a..537aa9acc 100755 --- a/bsnes/nall/map.hpp +++ b/bsnes/nall/map.hpp @@ -27,7 +27,7 @@ struct map { signed middle = (first + last) / 2; if(name < list[middle].name) last = middle - 1; //search lower half else if(list[middle].name < name) first = middle + 1; //search upper half - else return { true, middle }; //match found + else return { true, (unsigned)middle }; //match found } return { false, 0u }; } diff --git a/bsnes/nall/udl.hpp b/bsnes/nall/udl.hpp new file mode 100755 index 000000000..40bceba0d --- /dev/null +++ b/bsnes/nall/udl.hpp @@ -0,0 +1,27 @@ +#ifndef NALL_UDL_HPP +#define NALL_UDL_HPP + +//user-defined literals + +#include + +namespace nall { + constexpr inline uintmax_t operator"" _b(const char *n) { return binary(n); } + + //convert to bytes + constexpr inline uintmax_t operator"" _kb(unsigned long long n) { return 1024 * n; } + constexpr inline uintmax_t operator"" _mb(unsigned long long n) { return 1024 * 1024 * n; } + constexpr inline uintmax_t operator"" _gb(unsigned long long n) { return 1024 * 1024 * 1024 * n; } + + //convert to bits + constexpr inline uintmax_t operator"" _kbit(unsigned long long n) { return 1024 * n / 8; } + constexpr inline uintmax_t operator"" _mbit(unsigned long long n) { return 1024 * 1024 * n / 8; } + constexpr inline uintmax_t operator"" _gbit(unsigned long long n) { return 1024 * 1024 * 1024 * n / 8; } + + //convert to hz + constexpr inline uintmax_t operator"" _khz(long double n) { return n * 1000; } + constexpr inline uintmax_t operator"" _mhz(long double n) { return n * 1000000; } + constexpr inline uintmax_t operator"" _ghz(long double n) { return n * 1000000000; } +} + +#endif diff --git a/bsnes/phoenix/core/core.hpp b/bsnes/phoenix/core/core.hpp index d44e05966..d3506235c 100755 --- a/bsnes/phoenix/core/core.hpp +++ b/bsnes/phoenix/core/core.hpp @@ -52,13 +52,13 @@ struct Color { struct Position { signed x, y; inline Position() : x(0), y(0) {} - inline Position(signed x, signed y) : x(x), y(y) {} + template inline Position(X x, Y y) : x(x), y(y) {} }; struct Size { unsigned width, height; inline Size() : width(0), height(0) {} - inline Size(unsigned width, unsigned height) : width(width), height(height) {} + template inline Size(W width, H height) : width(width), height(height) {} }; struct Geometry { @@ -69,7 +69,7 @@ struct Geometry { nall::string text() const; inline Geometry() : x(0), y(0), width(0), height(0) {} inline Geometry(const Position& position, const Size& size) : x(position.x), y(position.y), width(size.width), height(size.height) {} - inline Geometry(signed x, signed y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {} + template inline Geometry(X x, Y y, W width, H height) : x(x), y(y), width(width), height(height) {} Geometry(const nall::string &text); }; diff --git a/bsnes/phoenix/gtk/platform.hpp b/bsnes/phoenix/gtk/platform.hpp index 037dd5a95..56534ca67 100755 --- a/bsnes/phoenix/gtk/platform.hpp +++ b/bsnes/phoenix/gtk/platform.hpp @@ -100,7 +100,8 @@ struct pWindow : public pObject { GtkWidget *statusContainer; GtkWidget *menu; GtkWidget *status; - GdkEventConfigure lastConfigure; + GtkAllocation lastAllocation; + bool onSizePending; void append(Layout &layout); void append(Menu &menu); diff --git a/bsnes/phoenix/gtk/window.cpp b/bsnes/phoenix/gtk/window.cpp index 8248104a4..be3f2a7f3 100755 --- a/bsnes/phoenix/gtk/window.cpp +++ b/bsnes/phoenix/gtk/window.cpp @@ -53,36 +53,27 @@ static gboolean Window_configure(GtkWidget *widget, GdkEvent *event, Window *win settings->save(); } + Geometry geometry = { + client.x, + client.y + window->p.menuHeight(), + client.width, + client.height - window->p.menuHeight() - window->p.statusHeight() + }; + //move - if(event->configure.x != window->p.lastConfigure.x - || event->configure.y != window->p.lastConfigure.y - ) { + if(geometry.x != window->state.geometry.x || geometry.y != window->state.geometry.y) { if(window->state.fullScreen == false) { - window->state.geometry.x = client.x; - window->state.geometry.y = client.y + window->p.menuHeight(); + window->state.geometry.x = geometry.x; + window->state.geometry.y = geometry.y; } if(window->p.locked == false && window->onMove) window->onMove(); } //size - if(event->configure.width != window->p.lastConfigure.width - || event->configure.height != window->p.lastConfigure.height - ) { - if(window->state.fullScreen == false) { - window->state.geometry.width = client.width; - window->state.geometry.height = client.height - window->p.menuHeight() - window->p.statusHeight(); - } - - for(auto &layout : window->state.layout) { - Geometry geometry = window->geometry(); - geometry.x = geometry.y = 0; - layout.setGeometry(geometry); - } - - if(window->p.locked == false && window->onSize) window->onSize(); + if(geometry.width != window->state.geometry.width || geometry.height != window->state.geometry.height) { + window->p.onSizePending = true; } - window->p.lastConfigure = event->configure; return false; } @@ -98,6 +89,33 @@ static gboolean Window_keyReleaseEvent(GtkWidget *widget, GdkEventKey *event, Wi return false; } +static void Window_sizeAllocate(GtkWidget *widget, GtkAllocation *allocation, Window *window) { + //size-allocate sent from gtk_fixed_move(); detect if layout unchanged and return + if(allocation->width == window->p.lastAllocation.width + && allocation->height == window->p.lastAllocation.height) return; + + window->state.geometry.width = allocation->width; + window->state.geometry.height = allocation->height; + + for(auto &layout : window->state.layout) { + Geometry geometry = window->geometry(); + geometry.x = geometry.y = 0; + layout.setGeometry(geometry); + } + + if(window->p.onSizePending && window->p.locked == false && window->onSize) { + window->p.onSizePending = false; + window->onSize(); + } + + window->p.lastAllocation = *allocation; +} + +static void Window_sizeRequest(GtkWidget *widget, GtkRequisition *requisition, Window *window) { + requisition->width = window->state.geometry.width; + requisition->height = window->state.geometry.height; +} + void pWindow::append(Layout &layout) { Geometry geometry = this->geometry(); geometry.x = geometry.y = 0; @@ -131,7 +149,13 @@ Color pWindow::backgroundColor() { } Geometry pWindow::frameMargin() { - if(window.state.fullScreen) return { 0, menuHeight(), 0, menuHeight() + statusHeight() }; + if(window.state.fullScreen) return { + 0, + menuHeight(), + 0, + menuHeight() + statusHeight() + }; + return { settings->frameGeometryX, settings->frameGeometryY + menuHeight(), @@ -145,9 +169,13 @@ bool pWindow::focused() { } Geometry pWindow::geometry() { - if(window.state.fullScreen == true) { - return { 0, menuHeight(), Desktop::size().width, Desktop::size().height - menuHeight() - statusHeight() }; + if(window.state.fullScreen == true) return { + 0, + menuHeight(), + Desktop::size().width, + Desktop::size().height - menuHeight() - statusHeight() }; + return window.state.geometry; } @@ -178,38 +206,23 @@ void pWindow::setFocused() { void pWindow::setFullScreen(bool fullScreen) { if(fullScreen == false) { gtk_window_unfullscreen(GTK_WINDOW(widget)); - gtk_window_set_resizable(GTK_WINDOW(widget), window.state.resizable); - gtk_widget_set_size_request(widget, -1, -1); - gdk_display_sync(gtk_widget_get_display(widget)); - setGeometry(window.state.geometry); } else { gtk_window_fullscreen(GTK_WINDOW(widget)); - gtk_widget_set_size_request(widget, Desktop::size().width, Desktop::size().height); - gtk_window_set_resizable(GTK_WINDOW(widget), false); } - gdk_display_sync(gtk_widget_get_display(widget)); } void pWindow::setGeometry(const Geometry &geometry) { - OS::processEvents(); - Geometry margin = frameMargin(); gtk_window_move(GTK_WINDOW(widget), geometry.x - margin.x, geometry.y - margin.y); -//GdkGeometry geom; -//geom.min_width = 1; -//geom.min_height = 1; -//gtk_window_set_geometry_hints(GTK_WINDOW(widget), GTK_WIDGET(widget), &geom, GDK_HINT_MIN_SIZE); + GdkGeometry geom; + geom.min_width = window.state.resizable ? 1 : window.state.geometry.width; + geom.min_height = window.state.resizable ? 1 : window.state.geometry.height; + gtk_window_set_geometry_hints(GTK_WINDOW(widget), GTK_WIDGET(widget), &geom, GDK_HINT_MIN_SIZE); - gtk_window_set_policy(GTK_WINDOW(widget), true, true, false); +//gtk_window_set_policy(GTK_WINDOW(widget), true, true, false); gtk_widget_set_size_request(formContainer, geometry.width, geometry.height); gtk_window_resize(GTK_WINDOW(widget), geometry.width, geometry.height + menuHeight() + statusHeight()); - - for(auto &layout : window.state.layout) { - Geometry geometry = this->geometry(); - geometry.x = geometry.y = 0; - layout.setGeometry(geometry); - } } void pWindow::setMenuFont(const string &font) { @@ -244,6 +257,19 @@ void pWindow::setTitle(const string &text) { void pWindow::setVisible(bool visible) { gtk_widget_set_visible(widget, visible); + if(visible) { + if(gtk_widget_get_visible(menu)) { + GtkAllocation allocation; + gtk_widget_get_allocation(menu, &allocation); + settings->menuGeometryHeight = allocation.height; + } + + if(gtk_widget_get_visible(status)) { + GtkAllocation allocation; + gtk_widget_get_allocation(status, &allocation); + settings->statusGeometryHeight = allocation.height; + } + } } void pWindow::setWidgetFont(const string &font) { @@ -253,7 +279,10 @@ void pWindow::setWidgetFont(const string &font) { } void pWindow::constructor() { - memset(&lastConfigure, 0, sizeof(GdkEventConfigure)); + lastAllocation.width = 0; + lastAllocation.height = 0; + onSizePending = false; + widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); if(gdk_screen_is_composited(gdk_screen_get_default())) { @@ -289,6 +318,7 @@ void pWindow::constructor() { gtk_widget_show(statusContainer); setTitle(""); + setResizable(window.state.resizable); setGeometry(window.state.geometry); setMenuFont("Sans, 8"); setStatusFont("Sans, 8"); @@ -298,6 +328,9 @@ void pWindow::constructor() { g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window); g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window); g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window); + + g_signal_connect(G_OBJECT(formContainer), "size-allocate", G_CALLBACK(Window_sizeAllocate), (gpointer)&window); + g_signal_connect(G_OBJECT(formContainer), "size-request", G_CALLBACK(Window_sizeRequest), (gpointer)&window); } unsigned pWindow::menuHeight() { diff --git a/bsnes/phoenix/qt/platform.cpp b/bsnes/phoenix/qt/platform.cpp index 0ff46b2b6..86f659c85 100755 --- a/bsnes/phoenix/qt/platform.cpp +++ b/bsnes/phoenix/qt/platform.cpp @@ -1,3 +1,9 @@ +//Qt 4.8.0 and earlier improperly define the QLOCATION macro +//in C++11, it is detected as a malformed user-defined literal +//below is a workaround to fix compilation errors caused by this +#undef QLOCATION +#define QLOCATION "\0" __FILE__ ":" QTOSTRING(__LINE__) + #include "platform.moc.hpp" #include "platform.moc" #include "utility.cpp" diff --git a/bsnes/phoenix/qt/platform.moc b/bsnes/phoenix/qt/platform.moc index bd9cf54bd..645f74578 100755 --- a/bsnes/phoenix/qt/platform.moc +++ b/bsnes/phoenix/qt/platform.moc @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'platform.moc.hpp' ** -** Created: Fri Feb 10 22:23:15 2012 +** Created: Thu Mar 22 11:27:37 2012 ** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3) ** ** WARNING! All changes made in this file will be lost! diff --git a/bsnes/processor/Makefile b/bsnes/processor/Makefile index 4eb320265..2397d5577 100755 --- a/bsnes/processor/Makefile +++ b/bsnes/processor/Makefile @@ -1,8 +1,10 @@ processor_objects := processor_objects += $(if $(findstring arm,$(processors)),processor-arm) processor_objects += $(if $(findstring hg51b,$(processors)),processor-hg51b) +processor_objects += $(if $(findstring upd96050,$(processors)),processor-upd96050) objects += $(processor_objects) processor := processor -obj/processor-arm.o: $(processor)/arm/arm.cpp $(call rwildcard,$(processor)/arm) -obj/processor-hg51b.o: $(processor)/hg51b/hg51b.cpp $(call rwildcard,$(processor)/hg51b) +obj/processor-arm.o: $(processor)/arm/arm.cpp $(call rwildcard,$(processor)/arm) +obj/processor-hg51b.o: $(processor)/hg51b/hg51b.cpp $(call rwildcard,$(processor)/hg51b) +obj/processor-upd96050.o: $(processor)/upd96050/upd96050.cpp $(call rwildcard,$(processor)/upd96050) diff --git a/bsnes/processor/arm/disassembler.cpp b/bsnes/processor/arm/disassembler.cpp index 6a2d423c9..69f7514b0 100755 --- a/bsnes/processor/arm/disassembler.cpp +++ b/bsnes/processor/arm/disassembler.cpp @@ -568,13 +568,13 @@ string ARM::disassemble_thumb_instruction(uint32 pc) { } //move_multiple() - //(ldmia,stmdb) rn,{r...} + //(ldmia,stmia) rn,{r...} if((instruction & 0xf000) == 0xc000) { uint1 load = instruction >> 11; uint3 rn = instruction >> 8; uint8 list = instruction; - output.append(load ? "ldmia " : "stmdb ", registers[rn], "!,{"); + output.append(load ? "ldmia " : "stmia ", registers[rn], "!,{"); for(unsigned l = 0; l < 8; l++) { if(list & (1 << l)) output.append(registers[l], ","); } diff --git a/bsnes/processor/arm/instructions-arm.cpp b/bsnes/processor/arm/instructions-arm.cpp index f3fc50b84..486a19f47 100755 --- a/bsnes/processor/arm/instructions-arm.cpp +++ b/bsnes/processor/arm/instructions-arm.cpp @@ -30,7 +30,7 @@ void ARM::arm_step() { if((instruction() & 0x0fb000f0) == 0x01000000) { arm_op_move_to_register_from_status(); return; } if((instruction() & 0x0fb000f0) == 0x01000090) { arm_op_memory_swap(); return; } if((instruction() & 0x0fb000f0) == 0x01200000) { arm_op_move_to_status_from_register(); return; } - if((instruction() & 0x0ff000f0) == 0x01200010) { arm_op_branch_exchange_register(); return; } //ARMv4 + if((instruction() & 0x0ff000f0) == 0x01200010) { arm_op_branch_exchange_register(); return; } //ARMv4+ if((instruction() & 0x0fb00000) == 0x03200000) { arm_op_move_to_status_from_immediate(); return; } if((instruction() & 0x0e000010) == 0x00000000) { arm_op_data_immediate_shift(); return; } @@ -289,8 +289,8 @@ void ARM::arm_op_move_to_status_from_register() { void ARM::arm_op_branch_exchange_register() { uint4 m = instruction(); - r(15) = r(m); cpsr().t = r(m) & 1; + r(15) = r(m); } //msr{condition} (c,s)psr:{fields},#immediate diff --git a/bsnes/processor/arm/instructions-thumb.cpp b/bsnes/processor/arm/instructions-thumb.cpp index 1dae860ea..00b8d727d 100755 --- a/bsnes/processor/arm/instructions-thumb.cpp +++ b/bsnes/processor/arm/instructions-thumb.cpp @@ -96,15 +96,6 @@ uint32 ARM::thumb_tst(uint32 modify) { return modify; } -void ARM::thumb_cmp(uint32 source, uint32 modify) { - uint32 result = source - modify; - uint32 overflow = ~(source ^ modify) & (source ^ result); - cpsr().n = result >> 31; - cpsr().z = result == 0; - cpsr().c = (1u << 31) & (overflow ^ source ^ modify ^ result); - cpsr().v = (1u << 31) & (overflow); -} - uint32 ARM::thumb_add(uint32 source, uint32 modify, bool carry) { uint32 result = source + modify + carry; uint32 overflow = ~(source ^ modify) & (source ^ result); @@ -116,13 +107,7 @@ uint32 ARM::thumb_add(uint32 source, uint32 modify, bool carry) { } uint32 ARM::thumb_sub(uint32 source, uint32 modify, bool carry) { - uint32 result = source - modify + carry; - uint32 overflow = ~(source ^ modify) & (source ^ result); - cpsr().n = result >> 31; - cpsr().z = result == 0; - cpsr().c = (1u << 31) & (overflow ^ source ^ modify ^ result); - cpsr().v = (1u << 31) & (overflow); - return result; + thumb_add(source, ~modify, carry); } uint32 ARM::thumb_lsl(uint32 source, uint32 modify) { @@ -240,7 +225,7 @@ void ARM::thumb_op_immediate() { switch(opcode) { case 0: r(d) = thumb_tst( immediate); break; - case 1: thumb_cmp(r(d), immediate); break; + case 1: thumb_sub(r(d), immediate); break; case 2: r(d) = thumb_add(r(d), immediate); break; case 3: r(d) = thumb_sub(r(d), immediate); break; } @@ -265,8 +250,8 @@ void ARM::thumb_op_alu() { void ARM::thumb_op_branch_exchange() { uint4 m = instruction() >> 3; - r(15) = r(m); cpsr().t = r(m) & 1; + r(15) = r(m); } //{opcode} rd,rm @@ -423,34 +408,30 @@ void ARM::thumb_op_stack_multiple() { uint1 branch = instruction() >> 8; uint8 list = instruction(); - if(load == 1) { - for(unsigned l = 0; l < 8; l++) { - if(list & (1 << l)) { - r(l) = bus_read(r(13), Word); - r(13) += 4; - } - } - if(branch) { - r(15) = bus_read(r(13), Word); - r(13) += 4; + uint32 sp = 0; + if(load == 1) sp = r(13); + if(load == 0) sp = r(13) - (bit::count(list) + branch) * 4; + + for(unsigned l = 0; l < 8; l++) { + if(list & (1 << l)) { + if(load == 1) r(l) = bus_read(sp, Word); //POP + if(load == 0) bus_write(sp, Word, r(l)); //PUSH + sp += 4; } } - if(load == 0) { - for(unsigned l = 0; l < 8; l++) { - if(list & (1 << l)) { - r(13) -= 4; - bus_write(r(13), Word, r(l)); - } - } - if(branch) { - r(13) -= 4; - bus_write(r(13), Word, r(14)); - } + if(branch) { + //note: ARMv5+ POP sets cpsr().t + if(load == 1) r(15) = bus_read(sp, Word); //POP + if(load == 0) bus_write(sp, Word, r(14)); //PUSH + sp += 4; } + + if(load == 1) r(13) += (bit::count(list) + branch) * 4; + if(load == 0) r(13) -= (bit::count(list) + branch) * 4; } -//(ldmia,stmdb) rn!,{r...} +//(ldmia,stmia) rn!,{r...} //1100 lnnn llll llll //l = load (0 = save) //n = rn @@ -460,21 +441,11 @@ void ARM::thumb_op_move_multiple() { uint3 n = instruction() >> 8; uint8 list = instruction(); - if(load == 1) { - for(unsigned l = 0; l < 8; l++) { - if(list & (1 << l)) { - r(l) = bus_read(r(n), Word); - r(n) += 4; - } - } - } - - if(load == 0) { - for(unsigned l = 0; l < 8; l++) { - if(list & (1 << l)) { - r(n) -= 4; - bus_write(r(n), Word, r(l)); - } + for(unsigned l = 0; l < 8; l++) { + if(list & (1 << l)) { + if(load == 1) r(l) = bus_read(r(n), Word); //LDMIA + if(load == 0) bus_write(r(n), Word, r(l)); //STMIA + r(n) += 4; } } } @@ -513,9 +484,9 @@ void ARM::thumb_op_branch_short() { //1111 0ooo oooo oooo //o = offset void ARM::thumb_op_branch_long_prefix() { - uint11 offsethi = instruction(); + int11 offsethi = instruction(); - r(14) = offsethi; + r(14) = r(15) + ((offsethi * 2) << 11); } //bl address @@ -524,9 +495,8 @@ void ARM::thumb_op_branch_long_prefix() { void ARM::thumb_op_branch_long_suffix() { uint11 offsetlo = instruction(); - int22 displacement = ((uint11)r(14) << 11) | offsetlo; - r(14) = r(15) | 1; - r(15) += displacement * 2; + r(15) = r(14) + (offsetlo * 2); + r(14) = pipeline.decode.address | 1; } #endif diff --git a/bsnes/processor/arm/instructions-thumb.hpp b/bsnes/processor/arm/instructions-thumb.hpp index 4efd14757..0fe6bab35 100755 --- a/bsnes/processor/arm/instructions-thumb.hpp +++ b/bsnes/processor/arm/instructions-thumb.hpp @@ -4,7 +4,6 @@ bool thumb_condition(uint4 condition); void thumb_opcode(uint4 opcode, uint4 d, uint4 s); uint32 thumb_tst(uint32 modify); -void thumb_cmp(uint32 source, uint32 modify); uint32 thumb_add(uint32 source, uint32 modify, bool carry = 0); uint32 thumb_sub(uint32 source, uint32 modify, bool carry = 1); uint32 thumb_lsl(uint32 source, uint32 modify); diff --git a/bsnes/snes/chip/necdsp/disassembler.cpp b/bsnes/processor/upd96050/disassembler.cpp similarity index 100% rename from bsnes/snes/chip/necdsp/disassembler.cpp rename to bsnes/processor/upd96050/disassembler.cpp diff --git a/bsnes/processor/upd96050/instructions.cpp b/bsnes/processor/upd96050/instructions.cpp new file mode 100755 index 000000000..62226738a --- /dev/null +++ b/bsnes/processor/upd96050/instructions.cpp @@ -0,0 +1,222 @@ +void uPD96050::exec() { + uint24 opcode = programROM[regs.pc++]; + switch(opcode >> 22) { + case 0: exec_op(opcode); break; + case 1: exec_rt(opcode); break; + case 2: exec_jp(opcode); break; + case 3: exec_ld(opcode); break; + } + + int32 result = (int32)regs.k * regs.l; //sign + 30-bit result + regs.m = result >> 15; //store sign + top 15-bits + regs.n = result << 1; //store low 15-bits + zero +} + +void uPD96050::exec_op(uint24 opcode) { + uint2 pselect = opcode >> 20; //P select + uint4 alu = opcode >> 16; //ALU operation mode + uint1 asl = opcode >> 15; //accumulator select + uint2 dpl = opcode >> 13; //DP low modify + uint4 dphm = opcode >> 9; //DP high XOR modify + uint1 rpdcr = opcode >> 8; //RP decrement + uint4 src = opcode >> 4; //move source + uint4 dst = opcode >> 0; //move destination + + uint16 idb; + switch(src) { + case 0: idb = regs.trb; break; + case 1: idb = regs.a; break; + case 2: idb = regs.b; break; + case 3: idb = regs.tr; break; + case 4: idb = regs.dp; break; + case 5: idb = regs.rp; break; + case 6: idb = dataROM[regs.rp]; break; + case 7: idb = 0x8000 - regs.flaga.s1; break; + case 8: idb = regs.dr; regs.sr.rqm = 1; break; + case 9: idb = regs.dr; break; + case 10: idb = regs.sr; break; + case 11: idb = regs.si; break; //MSB + case 12: idb = regs.si; break; //LSB + case 13: idb = regs.k; break; + case 14: idb = regs.l; break; + case 15: idb = dataRAM[regs.dp]; break; + } + + if(alu) { + uint16 p, q, r; + Flag flag; + bool c; + + switch(pselect) { + case 0: p = dataRAM[regs.dp]; break; + case 1: p = idb; break; + case 2: p = regs.m; break; + case 3: p = regs.n; break; + } + + switch(asl) { + case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break; + case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break; + } + + switch(alu) { + case 1: r = q | p; break; //OR + case 2: r = q & p; break; //AND + case 3: r = q ^ p; break; //XOR + case 4: r = q - p; break; //SUB + case 5: r = q + p; break; //ADD + case 6: r = q - p - c; break; //SBB + case 7: r = q + p + c; break; //ADC + case 8: r = q - 1; p = 1; break; //DEC + case 9: r = q + 1; p = 1; break; //INC + case 10: r = ~q; break; //CMP + case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR) + case 12: r = (q << 1) | c; break; //SHL1 (ROL) + case 13: r = (q << 2) | 3; break; //SHL2 + case 14: r = (q << 4) | 15; break; //SHL4 + case 15: r = (q << 8) | (q >> 8); break; //XCHG + } + + flag.s0 = (r & 0x8000); + flag.z = (r == 0); + + switch(alu) { + case 1: case 2: case 3: case 10: case 13: case 14: case 15: { + flag.c = 0; + flag.ov0 = 0; + flag.ov1 = 0; + break; + } + case 4: case 5: case 6: case 7: case 8: case 9: { + if(alu & 1) { + //addition + flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000; + flag.c = (r < q); + } else { + //subtraction + flag.ov0 = (q ^ r) & (q ^ p) & 0x8000; + flag.c = (r > q); + } + if(flag.ov0) { + flag.s1 = flag.ov1 ^ !(r & 0x8000); + flag.ov1 = !flag.ov1; + } + break; + } + case 11: { + flag.c = q & 1; + flag.ov0 = 0; + flag.ov1 = 0; + break; + } + case 12: { + flag.c = q >> 15; + flag.ov0 = 0; + flag.ov1 = 0; + break; + } + } + + switch(asl) { + case 0: regs.a = r; regs.flaga = flag; break; + case 1: regs.b = r; regs.flagb = flag; break; + } + } + + exec_ld((idb << 6) + dst); + + switch(dpl) { + case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC + case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC + case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR + } + + regs.dp ^= dphm << 4; + + if(rpdcr) regs.rp--; +} + +void uPD96050::exec_rt(uint24 opcode) { + exec_op(opcode); + regs.pc = regs.stack[--regs.sp]; +} + +void uPD96050::exec_jp(uint24 opcode) { + uint9 brch = opcode >> 13; //branch + uint11 na = opcode >> 2; //next address + uint2 bank = opcode >> 0; //bank address + + uint14 jp = (regs.pc & 0x2000) | (bank << 11) | (na << 0); + + switch(brch) { + case 0x000: regs.pc = regs.so; return; //JMPSO + + case 0x080: if(regs.flaga.c == 0) regs.pc = jp; return; //JNCA + case 0x082: if(regs.flaga.c == 1) regs.pc = jp; return; //JCA + case 0x084: if(regs.flagb.c == 0) regs.pc = jp; return; //JNCB + case 0x086: if(regs.flagb.c == 1) regs.pc = jp; return; //JCB + + case 0x088: if(regs.flaga.z == 0) regs.pc = jp; return; //JNZA + case 0x08a: if(regs.flaga.z == 1) regs.pc = jp; return; //JZA + case 0x08c: if(regs.flagb.z == 0) regs.pc = jp; return; //JNZB + case 0x08e: if(regs.flagb.z == 1) regs.pc = jp; return; //JZB + + case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jp; return; //JNOVA0 + case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jp; return; //JOVA0 + case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jp; return; //JNOVB0 + case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jp; return; //JOVB0 + + case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jp; return; //JNOVA1 + case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jp; return; //JOVA1 + case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jp; return; //JNOVB1 + case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jp; return; //JOVB1 + + case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jp; return; //JNSA0 + case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jp; return; //JSA0 + case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jp; return; //JNSB0 + case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jp; return; //JSB0 + + case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jp; return; //JNSA1 + case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jp; return; //JSA1 + case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jp; return; //JNSB1 + case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jp; return; //JSB1 + + case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jp; return; //JDPL0 + case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jp; return; //JDPLN0 + case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jp; return; //JDPLF + case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jp; return; //JDPLNF + + case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jp; return; //JNRQM + case 0x0be: if(regs.sr.rqm == 1) regs.pc = jp; return; //JRQM + + case 0x100: regs.pc = jp & ~0x2000; return; //LJMP + case 0x101: regs.pc = jp | 0x2000; return; //HJMP + + case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = jp & ~0x2000; return; //LCALL + case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = jp | 0x2000; return; //HCALL + } +} + +void uPD96050::exec_ld(uint24 opcode) { + uint16 id = opcode >> 6; //immediate data + uint4 dst = opcode >> 0; //destination + + switch(dst) { + case 0: break; + case 1: regs.a = id; break; + case 2: regs.b = id; break; + case 3: regs.tr = id; break; + case 4: regs.dp = id; break; + case 5: regs.rp = id; break; + case 6: regs.dr = id; regs.sr.rqm = 1; break; + case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c); break; + case 8: regs.so = id; break; //LSB + case 9: regs.so = id; break; //MSB + case 10: regs.k = id; break; + case 11: regs.k = id; regs.l = dataROM[regs.rp]; break; + case 12: regs.l = id; regs.k = dataRAM[regs.dp | 0x40]; break; + case 13: regs.l = id; break; + case 14: regs.trb = id; break; + case 15: dataRAM[regs.dp] = id; break; + } +} diff --git a/bsnes/snes/chip/necdsp/memory.cpp b/bsnes/processor/upd96050/memory.cpp similarity index 68% rename from bsnes/snes/chip/necdsp/memory.cpp rename to bsnes/processor/upd96050/memory.cpp index 0b11d594c..62c5bb624 100755 --- a/bsnes/snes/chip/necdsp/memory.cpp +++ b/bsnes/processor/upd96050/memory.cpp @@ -1,16 +1,11 @@ -#ifdef NECDSP_CPP - -uint8 NECDSP::sr_read(unsigned) { - cpu.synchronize_coprocessors(); +uint8 uPD96050::sr_read() { return regs.sr >> 8; } -void NECDSP::sr_write(unsigned, uint8 data) { - cpu.synchronize_coprocessors(); +void uPD96050::sr_write(uint8 data) { } -uint8 NECDSP::dr_read(unsigned) { - cpu.synchronize_coprocessors(); +uint8 uPD96050::dr_read() { if(regs.sr.drc == 0) { //16-bit if(regs.sr.drs == 0) { @@ -28,8 +23,7 @@ uint8 NECDSP::dr_read(unsigned) { } } -void NECDSP::dr_write(unsigned, uint8 data) { - cpu.synchronize_coprocessors(); +void uPD96050::dr_write(uint8 data) { if(regs.sr.drc == 0) { //16-bit if(regs.sr.drs == 0) { @@ -47,8 +41,7 @@ void NECDSP::dr_write(unsigned, uint8 data) { } } -uint8 NECDSP::dp_read(unsigned addr) { - cpu.synchronize_coprocessors(); +uint8 uPD96050::dp_read(uint12 addr) { bool hi = addr & 1; addr = (addr >> 1) & 2047; @@ -59,8 +52,7 @@ uint8 NECDSP::dp_read(unsigned addr) { } } -void NECDSP::dp_write(unsigned addr, uint8 data) { - cpu.synchronize_coprocessors(); +void uPD96050::dp_write(uint12 addr, uint8 data) { bool hi = addr & 1; addr = (addr >> 1) & 2047; @@ -70,5 +62,3 @@ void NECDSP::dp_write(unsigned addr, uint8 data) { dataRAM[addr] = (dataRAM[addr] & 0x00ff) | (data << 8); } } - -#endif diff --git a/bsnes/snes/chip/necdsp/registers.hpp b/bsnes/processor/upd96050/registers.hpp similarity index 100% rename from bsnes/snes/chip/necdsp/registers.hpp rename to bsnes/processor/upd96050/registers.hpp diff --git a/bsnes/processor/upd96050/serialization.cpp b/bsnes/processor/upd96050/serialization.cpp new file mode 100755 index 000000000..024cd0875 --- /dev/null +++ b/bsnes/processor/upd96050/serialization.cpp @@ -0,0 +1,49 @@ +void uPD96050::serialize(serializer &s) { + s.array(dataRAM); + + s.array(regs.stack); + s.integer(regs.pc); + s.integer(regs.rp); + s.integer(regs.dp); + s.integer(regs.sp); + + s.integer(regs.k); + s.integer(regs.l); + s.integer(regs.m); + s.integer(regs.n); + s.integer(regs.a); + s.integer(regs.b); + + s.integer(regs.flaga.s1); + s.integer(regs.flaga.s0); + s.integer(regs.flaga.c); + s.integer(regs.flaga.z); + s.integer(regs.flaga.ov1); + s.integer(regs.flaga.ov0); + + s.integer(regs.flagb.s1); + s.integer(regs.flagb.s0); + s.integer(regs.flagb.c); + s.integer(regs.flagb.z); + s.integer(regs.flagb.ov1); + s.integer(regs.flagb.ov0); + + s.integer(regs.tr); + s.integer(regs.trb); + + s.integer(regs.sr.rqm); + s.integer(regs.sr.usf1); + s.integer(regs.sr.usf0); + s.integer(regs.sr.drs); + s.integer(regs.sr.dma); + s.integer(regs.sr.drc); + s.integer(regs.sr.soc); + s.integer(regs.sr.sic); + s.integer(regs.sr.ei); + s.integer(regs.sr.p1); + s.integer(regs.sr.p0); + + s.integer(regs.dr); + s.integer(regs.si); + s.integer(regs.so); +} diff --git a/bsnes/processor/upd96050/upd96050.cpp b/bsnes/processor/upd96050/upd96050.cpp new file mode 100755 index 000000000..390cfefb9 --- /dev/null +++ b/bsnes/processor/upd96050/upd96050.cpp @@ -0,0 +1,45 @@ +#include +#include "upd96050.hpp" + +namespace Processor { + +#include "instructions.cpp" +#include "memory.cpp" +#include "disassembler.cpp" +#include "serialization.cpp" + +void uPD96050::power() { + if(revision == Revision::uPD7725) { + regs.pc.bits(11); + regs.rp.bits(10); + regs.dp.bits( 8); + } + + if(revision == Revision::uPD96050) { + regs.pc.bits(14); + regs.rp.bits(11); + regs.dp.bits(11); + } + + for(unsigned n = 0; n < 16; n++) regs.stack[n] = 0x0000; + regs.pc = 0x0000; + regs.rp = 0x0000; + regs.dp = 0x0000; + regs.sp = 0x0; + regs.k = 0x0000; + regs.l = 0x0000; + regs.m = 0x0000; + regs.n = 0x0000; + regs.a = 0x0000; + regs.b = 0x0000; + regs.flaga = 0x00; + regs.flagb = 0x00; + regs.tr = 0x0000; + regs.trb = 0x0000; + regs.sr = 0x0000; + regs.dr = 0x0000; + regs.si = 0x0000; + regs.so = 0x0000; +} + +} diff --git a/bsnes/processor/upd96050/upd96050.hpp b/bsnes/processor/upd96050/upd96050.hpp new file mode 100755 index 000000000..a20cfa67e --- /dev/null +++ b/bsnes/processor/upd96050/upd96050.hpp @@ -0,0 +1,40 @@ +#ifndef PROCESSOR_UPD96050_HPP +#define PROCESSOR_UPD96050_HPP + +namespace Processor { + +//NEC uPD7720 (not supported) +//NEC uPD7725 +//NEC uPD96050 + +struct uPD96050 { + enum class Revision : unsigned { uPD7725, uPD96050 } revision; + uint24 programROM[16384]; + uint16 dataROM[2048]; + uint16 dataRAM[2048]; + #include "registers.hpp" + + void power(); + void exec(); + void serialize(serializer&); + + void exec_op(uint24 opcode); + void exec_rt(uint24 opcode); + void exec_jp(uint24 opcode); + void exec_ld(uint24 opcode); + + uint8 sr_read(); + void sr_write(uint8 data); + + uint8 dr_read(); + void dr_write(uint8 data); + + uint8 dp_read(uint12 addr); + void dp_write(uint12 addr, uint8 data); + + string disassemble(uint14 ip); +}; + +} + +#endif diff --git a/bsnes/ruby/video/glx.cpp b/bsnes/ruby/video/glx.cpp index 7e1fec0bf..74a4f991c 100755 --- a/bsnes/ruby/video/glx.cpp +++ b/bsnes/ruby/video/glx.cpp @@ -164,8 +164,6 @@ public: bool init() { term(); -// display = XOpenDisplay(0); -// screen = DefaultScreen(display); glXQueryVersion(display, &glx.version_major, &glx.version_minor); //require GLX 1.2+ API if(glx.version_major < 1 || (glx.version_major == 1 && glx.version_minor < 2)) return false; @@ -179,9 +177,9 @@ public: GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DOUBLEBUFFER, True, - GLX_RED_SIZE, (settings.depth / 3), - GLX_GREEN_SIZE, (settings.depth / 3) + (settings.depth % 3), - GLX_BLUE_SIZE, (settings.depth / 3), + GLX_RED_SIZE, (signed)(settings.depth / 3), + GLX_GREEN_SIZE, (signed)(settings.depth / 3) + (signed)(settings.depth % 3), + GLX_BLUE_SIZE, (signed)(settings.depth / 3), None, }; diff --git a/bsnes/snes/chip/necdsp/necdsp.cpp b/bsnes/snes/chip/necdsp/necdsp.cpp index 9f92131a1..b0267dcf1 100755 --- a/bsnes/snes/chip/necdsp/necdsp.cpp +++ b/bsnes/snes/chip/necdsp/necdsp.cpp @@ -3,8 +3,6 @@ #define NECDSP_CPP namespace SNES { -#include "memory.cpp" -#include "disassembler.cpp" #include "serialization.cpp" NECDSP necdsp; @@ -16,231 +14,20 @@ void NECDSP::enter() { scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); } - uint24 opcode = programROM[regs.pc++]; - switch(opcode >> 22) { - case 0: exec_op(opcode); break; - case 1: exec_rt(opcode); break; - case 2: exec_jp(opcode); break; - case 3: exec_ld(opcode); break; - } - - int32 result = (int32)regs.k * regs.l; //sign + 30-bit result - regs.m = result >> 15; //store sign + top 15-bits - regs.n = result << 1; //store low 15-bits + zero - + exec(); step(1); synchronize_cpu(); } } -void NECDSP::exec_op(uint24 opcode) { - uint2 pselect = opcode >> 20; //P select - uint4 alu = opcode >> 16; //ALU operation mode - uint1 asl = opcode >> 15; //accumulator select - uint2 dpl = opcode >> 13; //DP low modify - uint4 dphm = opcode >> 9; //DP high XOR modify - uint1 rpdcr = opcode >> 8; //RP decrement - uint4 src = opcode >> 4; //move source - uint4 dst = opcode >> 0; //move destination +uint8 NECDSP::sr_read(unsigned) { cpu.synchronize_coprocessors(); return uPD96050::sr_read(); } +void NECDSP::sr_write(unsigned, uint8 data) { cpu.synchronize_coprocessors(); return uPD96050::sr_write(data); } - uint16 idb; - switch(src) { - case 0: idb = regs.trb; break; - case 1: idb = regs.a; break; - case 2: idb = regs.b; break; - case 3: idb = regs.tr; break; - case 4: idb = regs.dp; break; - case 5: idb = regs.rp; break; - case 6: idb = dataROM[regs.rp]; break; - case 7: idb = 0x8000 - regs.flaga.s1; break; - case 8: idb = regs.dr; regs.sr.rqm = 1; break; - case 9: idb = regs.dr; break; - case 10: idb = regs.sr; break; - case 11: idb = regs.si; break; //MSB - case 12: idb = regs.si; break; //LSB - case 13: idb = regs.k; break; - case 14: idb = regs.l; break; - case 15: idb = dataRAM[regs.dp]; break; - } +uint8 NECDSP::dr_read(unsigned) { cpu.synchronize_coprocessors(); return uPD96050::dr_read(); } +void NECDSP::dr_write(unsigned, uint8 data) { cpu.synchronize_coprocessors(); return uPD96050::dr_write(data); } - if(alu) { - uint16 p, q, r; - Flag flag; - bool c; - - switch(pselect) { - case 0: p = dataRAM[regs.dp]; break; - case 1: p = idb; break; - case 2: p = regs.m; break; - case 3: p = regs.n; break; - } - - switch(asl) { - case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break; - case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break; - } - - switch(alu) { - case 1: r = q | p; break; //OR - case 2: r = q & p; break; //AND - case 3: r = q ^ p; break; //XOR - case 4: r = q - p; break; //SUB - case 5: r = q + p; break; //ADD - case 6: r = q - p - c; break; //SBB - case 7: r = q + p + c; break; //ADC - case 8: r = q - 1; p = 1; break; //DEC - case 9: r = q + 1; p = 1; break; //INC - case 10: r = ~q; break; //CMP - case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR) - case 12: r = (q << 1) | c; break; //SHL1 (ROL) - case 13: r = (q << 2) | 3; break; //SHL2 - case 14: r = (q << 4) | 15; break; //SHL4 - case 15: r = (q << 8) | (q >> 8); break; //XCHG - } - - flag.s0 = (r & 0x8000); - flag.z = (r == 0); - - switch(alu) { - case 1: case 2: case 3: case 10: case 13: case 14: case 15: { - flag.c = 0; - flag.ov0 = 0; - flag.ov1 = 0; - break; - } - case 4: case 5: case 6: case 7: case 8: case 9: { - if(alu & 1) { - //addition - flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000; - flag.c = (r < q); - } else { - //subtraction - flag.ov0 = (q ^ r) & (q ^ p) & 0x8000; - flag.c = (r > q); - } - if(flag.ov0) { - flag.s1 = flag.ov1 ^ !(r & 0x8000); - flag.ov1 = !flag.ov1; - } - break; - } - case 11: { - flag.c = q & 1; - flag.ov0 = 0; - flag.ov1 = 0; - break; - } - case 12: { - flag.c = q >> 15; - flag.ov0 = 0; - flag.ov1 = 0; - break; - } - } - - switch(asl) { - case 0: regs.a = r; regs.flaga = flag; break; - case 1: regs.b = r; regs.flagb = flag; break; - } - } - - exec_ld((idb << 6) + dst); - - switch(dpl) { - case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC - case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC - case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR - } - - regs.dp ^= dphm << 4; - - if(rpdcr) regs.rp--; -} - -void NECDSP::exec_rt(uint24 opcode) { - exec_op(opcode); - regs.pc = regs.stack[--regs.sp]; -} - -void NECDSP::exec_jp(uint24 opcode) { - uint9 brch = opcode >> 13; //branch - uint11 na = opcode >> 2; //next address - uint2 bank = opcode >> 0; //bank address - - uint14 jp = (regs.pc & 0x2000) | (bank << 11) | (na << 0); - - switch(brch) { - case 0x000: regs.pc = regs.so; return; //JMPSO - - case 0x080: if(regs.flaga.c == 0) regs.pc = jp; return; //JNCA - case 0x082: if(regs.flaga.c == 1) regs.pc = jp; return; //JCA - case 0x084: if(regs.flagb.c == 0) regs.pc = jp; return; //JNCB - case 0x086: if(regs.flagb.c == 1) regs.pc = jp; return; //JCB - - case 0x088: if(regs.flaga.z == 0) regs.pc = jp; return; //JNZA - case 0x08a: if(regs.flaga.z == 1) regs.pc = jp; return; //JZA - case 0x08c: if(regs.flagb.z == 0) regs.pc = jp; return; //JNZB - case 0x08e: if(regs.flagb.z == 1) regs.pc = jp; return; //JZB - - case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jp; return; //JNOVA0 - case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jp; return; //JOVA0 - case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jp; return; //JNOVB0 - case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jp; return; //JOVB0 - - case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jp; return; //JNOVA1 - case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jp; return; //JOVA1 - case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jp; return; //JNOVB1 - case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jp; return; //JOVB1 - - case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jp; return; //JNSA0 - case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jp; return; //JSA0 - case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jp; return; //JNSB0 - case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jp; return; //JSB0 - - case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jp; return; //JNSA1 - case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jp; return; //JSA1 - case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jp; return; //JNSB1 - case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jp; return; //JSB1 - - case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jp; return; //JDPL0 - case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jp; return; //JDPLN0 - case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jp; return; //JDPLF - case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jp; return; //JDPLNF - - case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jp; return; //JNRQM - case 0x0be: if(regs.sr.rqm == 1) regs.pc = jp; return; //JRQM - - case 0x100: regs.pc = jp & ~0x2000; return; //LJMP - case 0x101: regs.pc = jp | 0x2000; return; //HJMP - - case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = jp & ~0x2000; return; //LCALL - case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = jp | 0x2000; return; //HCALL - } -} - -void NECDSP::exec_ld(uint24 opcode) { - uint16 id = opcode >> 6; //immediate data - uint4 dst = opcode >> 0; //destination - - switch(dst) { - case 0: break; - case 1: regs.a = id; break; - case 2: regs.b = id; break; - case 3: regs.tr = id; break; - case 4: regs.dp = id; break; - case 5: regs.rp = id; break; - case 6: regs.dr = id; regs.sr.rqm = 1; break; - case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c); break; - case 8: regs.so = id; break; //LSB - case 9: regs.so = id; break; //MSB - case 10: regs.k = id; break; - case 11: regs.k = id; regs.l = dataROM[regs.rp]; break; - case 12: regs.l = id; regs.k = dataRAM[regs.dp | 0x40]; break; - case 13: regs.l = id; break; - case 14: regs.trb = id; break; - case 15: dataRAM[regs.dp] = id; break; - } -} +uint8 NECDSP::dp_read(unsigned addr) { cpu.synchronize_coprocessors(); return uPD96050::dp_read(addr); } +void NECDSP::dp_write(unsigned addr, uint8 data) { cpu.synchronize_coprocessors(); return uPD96050::dp_write(addr, data); } void NECDSP::init() { } @@ -255,47 +42,11 @@ void NECDSP::unload() { } void NECDSP::power() { - if(revision == Revision::uPD7725) { - regs.pc.bits(11); - regs.rp.bits(10); - regs.dp.bits( 8); - } - - if(revision == Revision::uPD96050) { - regs.pc.bits(14); - regs.rp.bits(11); - regs.dp.bits(11); - } } void NECDSP::reset() { create(NECDSP::Enter, frequency); - - for(unsigned n = 0; n < 16; n++) regs.stack[n] = 0x0000; - regs.pc = 0x0000; - regs.rp = 0x0000; - regs.dp = 0x0000; - regs.sp = 0x0; - regs.k = 0x0000; - regs.l = 0x0000; - regs.m = 0x0000; - regs.n = 0x0000; - regs.a = 0x0000; - regs.b = 0x0000; - regs.flaga = 0x00; - regs.flagb = 0x00; - regs.tr = 0x0000; - regs.trb = 0x0000; - regs.sr = 0x0000; - regs.dr = 0x0000; - regs.si = 0x0000; - regs.so = 0x0000; -} - -NECDSP::NECDSP() { -} - -NECDSP::~NECDSP() { + uPD96050::power(); } } diff --git a/bsnes/snes/chip/necdsp/necdsp.hpp b/bsnes/snes/chip/necdsp/necdsp.hpp index 3c041cf76..fcdd25734 100755 --- a/bsnes/snes/chip/necdsp/necdsp.hpp +++ b/bsnes/snes/chip/necdsp/necdsp.hpp @@ -1,31 +1,7 @@ -//NEC uPD7725 -//NEC uPD96050 - -class NECDSP : public Coprocessor { -public: - enum class Revision : unsigned { uPD7725, uPD96050 } revision; - unsigned frequency; - - #include "registers.hpp" - - uint24 programROM[16384]; - uint16 dataROM[2048]; - uint16 dataRAM[2048]; - - unsigned programROMSize; - unsigned dataROMSize; - unsigned dataRAMSize; - +struct NECDSP : Processor::uPD96050, Coprocessor { static void Enter(); void enter(); - void exec_op(uint24 opcode); - void exec_rt(uint24 opcode); - void exec_jp(uint24 opcode); - void exec_ld(uint24 opcode); - - string disassemble(uint14 ip); - uint8 sr_read(unsigned); void sr_write(unsigned, uint8 data); @@ -42,8 +18,6 @@ public: void reset(); void serialize(serializer&); - NECDSP(); - ~NECDSP(); }; extern NECDSP necdsp; diff --git a/bsnes/snes/chip/necdsp/serialization.cpp b/bsnes/snes/chip/necdsp/serialization.cpp index 8ec267f7c..2d28c7545 100755 --- a/bsnes/snes/chip/necdsp/serialization.cpp +++ b/bsnes/snes/chip/necdsp/serialization.cpp @@ -1,55 +1,8 @@ #ifdef NECDSP_CPP void NECDSP::serialize(serializer &s) { + uPD96050::serialize(s); Thread::serialize(s); - - s.array(dataRAM); - - s.array(regs.stack); - s.integer(regs.pc); - s.integer(regs.rp); - s.integer(regs.dp); - s.integer(regs.sp); - - s.integer(regs.k); - s.integer(regs.l); - s.integer(regs.m); - s.integer(regs.n); - s.integer(regs.a); - s.integer(regs.b); - - s.integer(regs.flaga.s1); - s.integer(regs.flaga.s0); - s.integer(regs.flaga.c); - s.integer(regs.flaga.z); - s.integer(regs.flaga.ov1); - s.integer(regs.flaga.ov0); - - s.integer(regs.flagb.s1); - s.integer(regs.flagb.s0); - s.integer(regs.flagb.c); - s.integer(regs.flagb.z); - s.integer(regs.flagb.ov1); - s.integer(regs.flagb.ov0); - - s.integer(regs.tr); - s.integer(regs.trb); - - s.integer(regs.sr.rqm); - s.integer(regs.sr.usf1); - s.integer(regs.sr.usf0); - s.integer(regs.sr.drs); - s.integer(regs.sr.dma); - s.integer(regs.sr.drc); - s.integer(regs.sr.soc); - s.integer(regs.sr.sic); - s.integer(regs.sr.ei); - s.integer(regs.sr.p1); - s.integer(regs.sr.p0); - - s.integer(regs.dr); - s.integer(regs.si); - s.integer(regs.so); } #endif diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 4eb32b6e0..88548408e 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -4,11 +4,12 @@ #include #include #include +#include namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const unsigned SerializerVersion = 23; + static const unsigned SerializerVersion = 24; } } diff --git a/bsnes/target-ui/Makefile b/bsnes/target-ui/Makefile index aac705298..285b9f396 100755 --- a/bsnes/target-ui/Makefile +++ b/bsnes/target-ui/Makefile @@ -1,4 +1,4 @@ -processors := arm hg51b +processors := arm hg51b upd96050 include processor/Makefile include $(nes)/Makefile diff --git a/bsnes/target-ui/main.cpp b/bsnes/target-ui/main.cpp index 2c2d7c2c4..f3a4b49d8 100755 --- a/bsnes/target-ui/main.cpp +++ b/bsnes/target-ui/main.cpp @@ -123,6 +123,8 @@ Application::Application(int argc, char **argv) { Application::run(); } + if(GBA::cartridge.loaded()) print(GBA::cpu.disassemble_registers(), "\n"); + interface->unloadCartridge(); windowManager->saveGeometry(); windowManager->hideAll();