diff --git a/Makefile b/Makefile
index 771e98ff..98bd46bf 100755
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
include nall/Makefile
snes := snes
-profile := accuracy
+profile := performance
ui := qt
# compiler
@@ -53,8 +53,8 @@ objects := $(patsubst %,obj/%.o,$(objects))
# targets
build: ui_build $(objects)
ifeq ($(platform),osx)
- test -d ../bsnes.app || mkdir -p ../bsnes.app/Contents/MacOS
- $(strip $(cpp) -o ../bsnes.app/Contents/MacOS/bsnes $(objects) $(link))
+ test -d ../bsnes-$(profile).app || mkdir -p ../bsnes-$(profile).app/Contents/MacOS
+ $(strip $(cpp) -o ../bsnes-$(profile).app/Contents/MacOS/bsnes-$(profile) $(objects) $(link))
else
$(strip $(cpp) -o out/bsnes-$(profile) $(objects) $(link))
endif
@@ -87,6 +87,6 @@ clean: ui_clean
-@$(call delete,*.manifest)
archive-all:
- tar -cjf bsnes-`date +%Y%m%d`.tar.bz2 libco nall obj out qt ruby snes Makefile sync.sh
+ tar -cjf bsnes-`date +%Y%m%d`.tar.bz2 launcher libco nall obj out qt ruby snes Makefile sync.sh cc.bat clean.bat
help:;
diff --git a/cc.bat b/cc.bat
new file mode 100755
index 00000000..8e0e8454
--- /dev/null
+++ b/cc.bat
@@ -0,0 +1 @@
+@mingw32-make -j 2
diff --git a/clean.bat b/clean.bat
new file mode 100755
index 00000000..d4c3d600
--- /dev/null
+++ b/clean.bat
@@ -0,0 +1 @@
+@mingw32-make clean
diff --git a/launcher/bsnes.Manifest b/launcher/bsnes.Manifest
new file mode 100755
index 00000000..4602d4fe
--- /dev/null
+++ b/launcher/bsnes.Manifest
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/launcher/bsnes.ico b/launcher/bsnes.ico
new file mode 100755
index 00000000..54acded4
Binary files /dev/null and b/launcher/bsnes.ico differ
diff --git a/launcher/cc.bat b/launcher/cc.bat
new file mode 100755
index 00000000..6889dcc5
--- /dev/null
+++ b/launcher/cc.bat
@@ -0,0 +1,4 @@
+@windres resource.rc resource.o
+@mingw32-g++ -std=gnu++0x -mwindows -s -O3 -fomit-frame-pointer -I.. -o ../out/bsnes launcher.cpp resource.o
+@del *.o
+@pause
diff --git a/launcher/cc.sh b/launcher/cc.sh
new file mode 100755
index 00000000..964034d7
--- /dev/null
+++ b/launcher/cc.sh
@@ -0,0 +1,2 @@
+clear
+g++ -std=gnu++0x -s -O3 -fomit-frame-pointer -I.. -o ../out/bsnes launcher.cpp
diff --git a/launcher/launcher.cpp b/launcher/launcher.cpp
new file mode 100755
index 00000000..3a2acfd7
--- /dev/null
+++ b/launcher/launcher.cpp
@@ -0,0 +1,89 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+using namespace nall;
+
+#if defined(PLATFORM_X) || defined(PLATFORM_OSX)
+ char* userpath(char *path) {
+ *path = 0;
+ struct passwd *userinfo = getpwuid(getuid());
+ if(userinfo) strcpy(path, userinfo->pw_dir);
+ return path;
+ }
+
+ char *getcwd(char *path) {
+ return getcwd(path, PATH_MAX);
+ }
+#elif defined(PLATFORM_WIN)
+ #include
+ #include
+ #include
+ #include
+
+ char* realpath(const char *filename, char *resolvedname) {
+ wchar_t fn[_MAX_PATH] = L"";
+ _wfullpath(fn, nall::utf16_t(filename), _MAX_PATH);
+ strcpy(resolvedname, nall::utf8_t(fn));
+ return resolvedname;
+ }
+
+ char* userpath(char *path) {
+ wchar_t fp[_MAX_PATH] = L"";
+ SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp);
+ strcpy(path, nall::utf8_t(fp));
+ return path;
+ }
+
+ char* getcwd(char *path) {
+ wchar_t fp[_MAX_PATH] = L"";
+ _wgetcwd(fp, _MAX_PATH);
+ strcpy(path, nall::utf8_t(fp));
+ return path;
+ }
+
+ intptr_t execv(const char *cmdname, const char *const *argv) {
+ int argc = __argc;
+ wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ return _wexecv(nall::utf16_t(cmdname), wargv);
+ }
+#endif
+
+int main(int argc, char **argv) {
+ char path[PATH_MAX], *unused;
+ unused = realpath(argv[0], path);
+ string realPath = dir(path);
+ string basePath = string(dir(path), "bsnes.cfg");
+ unused = userpath(path);
+ if(!strend(path, "/") && !strend(path, "\\")) strcat(path, "/");
+ string userPath = string(path, ".bsnes/bsnes.cfg");
+
+ configuration config;
+ string profile;
+ config.attach(profile = "", "system.profile");
+ if(config.load(userPath) == false) config.load(basePath);
+ if(profile == "") profile = "compatibility";
+
+ string binaryName = string("bsnes-", profile);
+ #if defined(PLATFORM_WIN)
+ binaryName << ".dll";
+ #endif
+
+ string fileName = string("/usr/local/bin/", binaryName);
+ if(!file::exists(fileName)) fileName = string("/usr/bin/", binaryName);
+ if(!file::exists(fileName)) fileName = string(realPath, binaryName);
+ if(!file::exists(fileName)) {
+ #if defined(PLATFORM_WIN)
+ MessageBox(0, string("Error: unable to locate binary file :", binaryName), "bsnes", MB_OK);
+ #else
+ print("[bsnes] Error: unable to locate binary file: ", binaryName, "\n");
+ #endif
+ return 0;
+ }
+
+ execv(fileName, argv);
+ return 0;
+}
diff --git a/launcher/resource.rc b/launcher/resource.rc
new file mode 100755
index 00000000..a88dde87
--- /dev/null
+++ b/launcher/resource.rc
@@ -0,0 +1,2 @@
+1 24 "bsnes.Manifest"
+IDI_ICON1 ICON DISCARDABLE "bsnes.ico"
diff --git a/nall/varint.hpp b/nall/varint.hpp
index cc3bb17c..fe4732b1 100755
--- a/nall/varint.hpp
+++ b/nall/varint.hpp
@@ -1,9 +1,9 @@
#ifndef NALL_VARINT_HPP
#define NALL_VARINT_HPP
+#include
#include
#include
-#include
namespace nall {
template class uint_t {
@@ -22,7 +22,7 @@ namespace nall {
>::type
>::type
>::type T;
- static_assert::value> uint_assert;
+ static_assert(!std::is_same::value, "");
T data;
public:
@@ -63,7 +63,7 @@ namespace nall {
>::type
>::type
>::type T;
- static_assert::value> int_assert;
+ static_assert(!std::is_same::value, "");
T data;
public:
diff --git a/qt/application/application.cpp b/qt/application/application.cpp
index 7228bc46..1f9449d2 100755
--- a/qt/application/application.cpp
+++ b/qt/application/application.cpp
@@ -61,12 +61,12 @@ void Application::locateFile(string &filename, bool createDataDirectory) {
}
int Application::main(int &argc, char **argv) {
- CoInitialize(0);
-
app = new App(argc, argv);
#if !defined(PLATFORM_WIN)
- //Windows port uses 256x256 icon from resource file
app->setWindowIcon(QIcon(":/bsnes.png"));
+ #else
+ //Windows port uses 256x256 icon from resource file
+ CoInitialize(0);
#endif
initargs(argc, argv); //ensure argv[]s are in UTF-8 format
diff --git a/qt/settings/profile.cpp b/qt/settings/profile.cpp
index 23b53733..6df07922 100755
--- a/qt/settings/profile.cpp
+++ b/qt/settings/profile.cpp
@@ -20,7 +20,9 @@ ProfileSettingsWindow::ProfileSettingsWindow() {
profileAccuracy->setStyleSheet(
"font-weight: bold;"
"font-size: 12pt;"
+ #if !defined(PLATFORM_WIN)
"background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgba(255, 0, 0, 48), stop: 1 rgba(255, 0, 0, 0));"
+ #endif
);
layout->addWidget(profileAccuracy);
@@ -37,7 +39,9 @@ ProfileSettingsWindow::ProfileSettingsWindow() {
profileCompatibility->setStyleSheet(
"font-weight: bold;"
"font-size: 12pt;"
+ #if !defined(PLATFORM_WIN)
"background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgba(0, 0, 255, 48), stop: 1 rgba(0, 0, 255, 0));"
+ #endif
);
layout->addWidget(profileCompatibility);
@@ -54,12 +58,14 @@ ProfileSettingsWindow::ProfileSettingsWindow() {
profilePerformance->setStyleSheet(
"font-weight: bold;"
"font-size: 12pt;"
+ #if !defined(PLATFORM_WIN)
"background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgba(0, 255, 0, 48), stop: 1 rgba(0, 255, 0, 0));"
+ #endif
);
layout->addWidget(profilePerformance);
profilePerformanceInfo = new QLabel(
- "System Requirements: Intel Atom, Intel Pentium IV or AMD Athlon processor.
"
+ "System Requirements: Intel Pentium IV or AMD Athlon processor.
"
"High accuracy with reasonable compromises for performance.
"
"Sacrifices a small degree of compatibility to run full-speed on older hardware.
"
"Use this mode for slower systems, or if you are running on battery power."
diff --git a/ruby/_test/cc.bat b/ruby/_test/cc.bat
deleted file mode 100755
index 00b9e552..00000000
--- a/ruby/_test/cc.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@g++ -std=gnu++0x -O3 -fomit-frame-pointer -I../.. -o test test.cpp -DAUDIO_DIRECTSOUND -DAUDIO_XAUDIO2 -DINPUT_DIRECTINPUT -lole32 -luuid -ldxguid -ldsound -ldinput8
-@pause
diff --git a/ruby/_test/test.cpp b/ruby/_test/test.cpp
deleted file mode 100755
index 64778930..00000000
--- a/ruby/_test/test.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#include
-#include
-using namespace nall;
-
-#include
-using namespace ruby;
-
-#include
-
-int main() {
- CoInitialize(0);
-
- audio.driver("XAudio2");
- audio.set(Audio::Handle, (uintptr_t)GetDesktopWindow());
- audio.set(Audio::Synchronize, true);
- audio.set(Audio::Frequency, 44100U);
- if(audio.init() == false) {
- printf("Failed to initialize audio driver.\n");
- getch();
- return 0;
- }
-
- input.driver("DirectInput");
- input.set(Input::Handle, (uintptr_t)GetDesktopWindow());
- if(input.init() == false) {
- printf("Failed to initialize input driver.\n");
- getch();
- return 0;
- }
-
- while(true) {
- int16_t table[Scancode::Limit];
- input.poll(table);
- for(unsigned i = 0; i < Scancode::Limit; i++) {
- //if(table[i]) printf("%.4x\n", i);
- }
- }
-
- return 0;
-}
diff --git a/ruby/_test/test.exe b/ruby/_test/test.exe
deleted file mode 100755
index 8032f45a..00000000
Binary files a/ruby/_test/test.exe and /dev/null differ
diff --git a/snes/cpu/cpu.cpp b/snes/cpu/cpu.cpp
index cacfd652..4c194b27 100755
--- a/snes/cpu/cpu.cpp
+++ b/snes/cpu/cpu.cpp
@@ -132,11 +132,6 @@ void CPU::reset() {
mmio_reset();
dma_reset();
timing_reset();
-
- apu_port[0] = 0x00;
- apu_port[1] = 0x00;
- apu_port[2] = 0x00;
- apu_port[3] = 0x00;
}
CPU::CPU() {
diff --git a/snes/cpu/cpu.hpp b/snes/cpu/cpu.hpp
index 2d55c10c..dd7412a7 100755
--- a/snes/cpu/cpu.hpp
+++ b/snes/cpu/cpu.hpp
@@ -7,11 +7,12 @@ public:
void synchronize_ppu();
void synchronize_coprocessor();
+ uint8 port_read(uint2 port) const;
+ void port_write(uint2 port, uint8 data);
+
uint8 pio();
bool joylatch();
alwaysinline bool interrupt_pending() { return status.interrupt_pending; }
- alwaysinline uint8 port_read(uint8 port) { return apu_port[port & 3]; }
- alwaysinline void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
void enter();
void power();
@@ -71,8 +72,11 @@ private:
bool hdma_mode; //0 = init, 1 = run
//MMIO
+ //$2140-217f
+ uint8 port[4];
+
//$2181-$2183
- uint32 wram_addr;
+ uint17 wram_addr;
//$4016-$4017
bool joypad_strobe_latch;
@@ -93,10 +97,11 @@ private:
//$4204-$4206
uint16 wrdiva;
- uint8 wrdivb;
+ uint8 wrdivb;
//$4207-$420a
- uint16 hirq_pos, virq_pos;
+ uint10 hirq_pos;
+ uint10 virq_pos;
//$420d
unsigned rom_speed;
diff --git a/snes/cpu/dma/dma.cpp b/snes/cpu/dma/dma.cpp
index 1e141ba8..e8cdb3ec 100755
--- a/snes/cpu/dma/dma.cpp
+++ b/snes/cpu/dma/dma.cpp
@@ -3,8 +3,6 @@
void CPU::dma_add_clocks(unsigned clocks) {
status.dma_clocks += clocks;
add_clocks(clocks);
- synchronize_ppu();
- synchronize_coprocessor();
}
//=============
diff --git a/snes/cpu/memory/memory.cpp b/snes/cpu/memory/memory.cpp
index bf48dee5..c2c8f1fa 100755
--- a/snes/cpu/memory/memory.cpp
+++ b/snes/cpu/memory/memory.cpp
@@ -1,5 +1,8 @@
#ifdef CPU_CPP
+uint8 CPU::port_read(uint2 port) const { return status.port[port]; }
+void CPU::port_write(uint2 port, uint8 data) { status.port[port] = data; }
+
void CPU::op_io() {
status.clock_count = 6;
dma_edge();
diff --git a/snes/cpu/memory/memory.hpp b/snes/cpu/memory/memory.hpp
index 2ee2b360..d33861d4 100755
--- a/snes/cpu/memory/memory.hpp
+++ b/snes/cpu/memory/memory.hpp
@@ -1,5 +1,3 @@
-uint8 apu_port[4];
-
void op_io();
debugvirtual uint8 op_read(uint32 addr);
debugvirtual void op_write(uint32 addr, uint8 data);
diff --git a/snes/cpu/mmio/mmio.cpp b/snes/cpu/mmio/mmio.cpp
index 9448c288..2ae915cb 100755
--- a/snes/cpu/mmio/mmio.cpp
+++ b/snes/cpu/mmio/mmio.cpp
@@ -5,33 +5,27 @@ bool CPU::joylatch() { return status.joypad_strobe_latch; }
//WMDATA
uint8 CPU::mmio_r2180() {
- uint8 r = bus.read(0x7e0000 | status.wram_addr);
- status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
- return r;
+ return bus.read(0x7e0000 | status.wram_addr++);
}
//WMDATA
void CPU::mmio_w2180(uint8 data) {
- bus.write(0x7e0000 | status.wram_addr, data);
- status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
+ bus.write(0x7e0000 | status.wram_addr++, data);
}
//WMADDL
void CPU::mmio_w2181(uint8 data) {
- status.wram_addr = (status.wram_addr & 0xffff00) | (data);
- status.wram_addr &= 0x01ffff;
+ status.wram_addr = (status.wram_addr & 0x01ff00) | (data << 0);
}
//WMADDM
void CPU::mmio_w2182(uint8 data) {
- status.wram_addr = (status.wram_addr & 0xff00ff) | (data << 8);
- status.wram_addr &= 0x01ffff;
+ status.wram_addr = (status.wram_addr & 0x0100ff) | (data << 8);
}
//WMADDH
void CPU::mmio_w2183(uint8 data) {
- status.wram_addr = (status.wram_addr & 0x00ffff) | (data << 16);
- status.wram_addr &= 0x01ffff;
+ status.wram_addr = (status.wram_addr & 0x00ffff) | (data << 16);
}
//JOYSER0
@@ -42,10 +36,7 @@ void CPU::mmio_w4016(uint8 data) {
bool old_latch = status.joypad_strobe_latch;
bool new_latch = data & 1;
status.joypad_strobe_latch = new_latch;
-
- if(old_latch != new_latch) {
- input.poll();
- }
+ if(old_latch != new_latch) input.poll();
}
//JOYSER0
@@ -69,15 +60,13 @@ uint8 CPU::mmio_r4017() {
//NMITIMEN
void CPU::mmio_w4200(uint8 data) {
- status.auto_joypad_poll = !!(data & 0x01);
+ status.auto_joypad_poll = data & 1;
nmitimen_update(data);
}
//WRIO
void CPU::mmio_w4201(uint8 data) {
- if((status.pio & 0x80) && !(data & 0x80)) {
- ppu.latch_counters();
- }
+ if((status.pio & 0x80) && !(data & 0x80)) ppu.latch_counters();
status.pio = data;
}
@@ -100,7 +89,7 @@ void CPU::mmio_w4203(uint8 data) {
//WRDIVL
void CPU::mmio_w4204(uint8 data) {
- status.wrdiva = (status.wrdiva & 0xff00) | (data);
+ status.wrdiva = (status.wrdiva & 0xff00) | (data << 0);
}
//WRDIVH
@@ -121,26 +110,22 @@ void CPU::mmio_w4206(uint8 data) {
//HTIMEL
void CPU::mmio_w4207(uint8 data) {
- status.hirq_pos = (status.hirq_pos & ~0xff) | (data);
- status.hirq_pos &= 0x01ff;
+ status.hirq_pos = (status.hirq_pos & 0x0100) | (data << 0);
}
//HTIMEH
void CPU::mmio_w4208(uint8 data) {
- status.hirq_pos = (status.hirq_pos & 0xff) | (data << 8);
- status.hirq_pos &= 0x01ff;
+ status.hirq_pos = (status.hirq_pos & 0x00ff) | (data << 8);
}
//VTIMEL
void CPU::mmio_w4209(uint8 data) {
- status.virq_pos = (status.virq_pos & ~0xff) | (data);
- status.virq_pos &= 0x01ff;
+ status.virq_pos = (status.virq_pos & 0x0100) | (data << 0);
}
//VTIMEH
void CPU::mmio_w420a(uint8 data) {
- status.virq_pos = (status.virq_pos & 0xff) | (data << 8);
- status.virq_pos &= 0x01ff;
+ status.virq_pos = (status.virq_pos & 0x00ff) | (data << 8);
}
//DMAEN
@@ -191,16 +176,9 @@ uint8 CPU::mmio_r4211() {
uint8 CPU::mmio_r4212() {
uint8 r = (regs.mdr & 0x3e);
uint16 vs = ppu.overscan() == false ? 225 : 240;
-
- //auto joypad polling
- if(vcounter() >= vs && vcounter() <= (vs + 2))r |= 0x01;
-
- //hblank
- if(hcounter() <= 2 || hcounter() >= 1096)r |= 0x40;
-
- //vblank
- if(vcounter() >= vs)r |= 0x80;
-
+ if(vcounter() >= vs && vcounter() <= (vs + 2)) r |= 0x01; //auto joypad polling
+ if(hcounter() <= 2 || hcounter() >= 1096) r |= 0x40; //hblank
+ if(vcounter() >= vs) r |= 0x80; //vblank
return r;
}
@@ -211,7 +189,7 @@ uint8 CPU::mmio_r4213() {
//RDDIVL
uint8 CPU::mmio_r4214() {
- return status.rddiv;
+ return status.rddiv >> 0;
}
//RDDIVH
@@ -221,7 +199,7 @@ uint8 CPU::mmio_r4215() {
//RDMPYL
uint8 CPU::mmio_r4216() {
- return status.rdmpy;
+ return status.rdmpy >> 0;
}
//RDMPYH
@@ -256,7 +234,7 @@ uint8 CPU::mmio_r43x1(uint8 i) {
//A1TxL
uint8 CPU::mmio_r43x2(uint8 i) {
- return channel[i].source_addr;
+ return channel[i].source_addr >> 0;
}
//A1TxH
@@ -272,7 +250,7 @@ uint8 CPU::mmio_r43x4(uint8 i) {
//DASxL
//union { uint16 transfer_size; uint16 indirect_addr; };
uint8 CPU::mmio_r43x5(uint8 i) {
- return channel[i].transfer_size;
+ return channel[i].transfer_size >> 0;
}
//DASxH
@@ -288,7 +266,7 @@ uint8 CPU::mmio_r43x7(uint8 i) {
//A2AxL
uint8 CPU::mmio_r43x8(uint8 i) {
- return channel[i].hdma_addr;
+ return channel[i].hdma_addr >> 0;
}
//A2AxH
@@ -323,7 +301,7 @@ void CPU::mmio_w43x1(uint8 i, uint8 data) {
//A1TxL
void CPU::mmio_w43x2(uint8 i, uint8 data) {
- channel[i].source_addr = (channel[i].source_addr & 0xff00) | (data);
+ channel[i].source_addr = (channel[i].source_addr & 0xff00) | (data << 0);
}
//A1TxH
@@ -339,7 +317,7 @@ void CPU::mmio_w43x4(uint8 i, uint8 data) {
//DASxL
//union { uint16 transfer_size; uint16 indirect_addr; };
void CPU::mmio_w43x5(uint8 i, uint8 data) {
- channel[i].transfer_size = (channel[i].transfer_size & 0xff00) | (data);
+ channel[i].transfer_size = (channel[i].transfer_size & 0xff00) | (data << 0);
}
//DASxH
@@ -355,7 +333,7 @@ void CPU::mmio_w43x7(uint8 i, uint8 data) {
//A2AxL
void CPU::mmio_w43x8(uint8 i, uint8 data) {
- channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | (data);
+ channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | (data << 0);
}
//A2AxH
@@ -377,6 +355,9 @@ void CPU::mmio_power() {
}
void CPU::mmio_reset() {
+ //$2140-217f
+ foreach(port, status.port) port = 0x00;
+
//$2181-$2183
status.wram_addr = 0x000000;
@@ -386,9 +367,9 @@ void CPU::mmio_reset() {
status.joypad2_bits = ~0;
//$4200
- status.nmi_enabled = false;
- status.hirq_enabled = false;
- status.virq_enabled = false;
+ status.nmi_enabled = false;
+ status.hirq_enabled = false;
+ status.virq_enabled = false;
status.auto_joypad_poll = false;
//$4201
@@ -426,7 +407,7 @@ void CPU::mmio_reset() {
//ALU
alu.mpyctr = 0;
alu.divctr = 0;
- alu.shift = 0;
+ alu.shift = 0;
}
uint8 CPU::mmio_read(unsigned addr) {
@@ -435,7 +416,7 @@ uint8 CPU::mmio_read(unsigned addr) {
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
synchronize_smp();
- return smp.port_read(addr & 3);
+ return smp.port_read(addr);
}
//DMA
@@ -492,7 +473,7 @@ void CPU::mmio_write(unsigned addr, uint8 data) {
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
synchronize_smp();
- port_write(addr & 3, data);
+ port_write(addr, data);
return;
}
diff --git a/snes/cpu/serialization.cpp b/snes/cpu/serialization.cpp
index ac3ceb6d..64f9fe81 100755
--- a/snes/cpu/serialization.cpp
+++ b/snes/cpu/serialization.cpp
@@ -44,6 +44,8 @@ void CPU::serialize(serializer &s) {
s.integer(status.hdma_pending);
s.integer(status.hdma_mode);
+ s.array(status.port);
+
s.integer(status.wram_addr);
s.integer(status.joypad_strobe_latch);
@@ -108,11 +110,6 @@ void CPU::serialize(serializer &s) {
s.integer(pipe.valid);
s.integer(pipe.addr);
s.integer(pipe.data);
-
- s.integer(apu_port[0]);
- s.integer(apu_port[1]);
- s.integer(apu_port[2]);
- s.integer(apu_port[3]);
}
#endif
diff --git a/snes/cpu/timing/joypad.cpp b/snes/cpu/timing/joypad.cpp
index d00cdccb..26c45f6a 100755
--- a/snes/cpu/timing/joypad.cpp
+++ b/snes/cpu/timing/joypad.cpp
@@ -12,16 +12,16 @@ void CPU::run_auto_joypad_poll() {
joy4 |= (port1 & 2) ? (0x8000 >> i) : 0;
}
- status.joy1l = joy1;
+ status.joy1l = joy1 >> 0;
status.joy1h = joy1 >> 8;
- status.joy2l = joy2;
+ status.joy2l = joy2 >> 0;
status.joy2h = joy2 >> 8;
- status.joy3l = joy3;
+ status.joy3l = joy3 >> 0;
status.joy3h = joy3 >> 8;
- status.joy4l = joy4;
+ status.joy4l = joy4 >> 0;
status.joy4h = joy4 >> 8;
}
diff --git a/snes/fast/cpu/cpu.hpp b/snes/fast/cpu/cpu.hpp
index 940564f8..45cf9cac 100755
--- a/snes/fast/cpu/cpu.hpp
+++ b/snes/fast/cpu/cpu.hpp
@@ -37,6 +37,7 @@ private:
enum : unsigned {
DramRefresh,
HdmaRun,
+ ControllerLatch,
};
};
nall::priority_queue queue;
diff --git a/snes/fast/cpu/dma.cpp b/snes/fast/cpu/dma.cpp
index d9d89e05..3e595971 100755
--- a/snes/fast/cpu/dma.cpp
+++ b/snes/fast/cpu/dma.cpp
@@ -122,7 +122,7 @@ void CPU::hdma_run() {
}
if(channels == 0) return;
- add_clocks(24);
+ add_clocks(16);
for(unsigned i = 0; i < 8; i++) {
if(channel[i].hdma_enabled == false || channel[i].hdma_completed == true) continue;
channel[i].dma_enabled = false;
diff --git a/snes/fast/cpu/mmio.cpp b/snes/fast/cpu/mmio.cpp
index 14a3c785..cc7ce5fa 100755
--- a/snes/fast/cpu/mmio.cpp
+++ b/snes/fast/cpu/mmio.cpp
@@ -158,6 +158,7 @@ void CPU::mmio_write(unsigned addr, uint8 data) {
status.irq_transition = false;
}
+ status.irq_lock = true;
return;
}
diff --git a/snes/fast/cpu/timing.cpp b/snes/fast/cpu/timing.cpp
index 7c333db7..04ac1aa5 100755
--- a/snes/fast/cpu/timing.cpp
+++ b/snes/fast/cpu/timing.cpp
@@ -4,6 +4,7 @@ void CPU::queue_event(unsigned id) {
switch(id) {
case QueueEvent::DramRefresh: return add_clocks(40);
case QueueEvent::HdmaRun: return hdma_run();
+ case QueueEvent::ControllerLatch: return ppu.latch_counters();
}
}
@@ -31,7 +32,8 @@ void CPU::add_clocks(unsigned clocks) {
if(status.virq_enabled) {
unsigned cpu_time = vcounter() * 1364 + hcounter();
unsigned irq_time = status.vtime * 1364 + status.htime * 4;
- if(cpu_time > irq_time) irq_time += 262 * 1364;
+ unsigned framelines = (system.region() == System::Region::NTSC ? 262 : 312) + field();
+ if(cpu_time > irq_time) irq_time += framelines * 1364;
bool irq_valid = status.irq_valid;
status.irq_valid = cpu_time <= irq_time && cpu_time + clocks > irq_time;
if(!irq_valid && status.irq_valid) status.irq_line = true;
@@ -66,7 +68,11 @@ void CPU::scanline() {
queue.enqueue(534, QueueEvent::DramRefresh);
if(vcounter() <= (ppu.overscan() == false ? 224 : 239)) {
- queue.enqueue(1104, QueueEvent::HdmaRun);
+ queue.enqueue(1104 + 8, QueueEvent::HdmaRun);
+ }
+
+ if(vcounter() == input.latchy) {
+ queue.enqueue(input.latchx, QueueEvent::ControllerLatch);
}
bool nmi_valid = status.nmi_valid;
diff --git a/snes/fast/ppu/memory/memory.cpp b/snes/fast/ppu/memory/memory.cpp
index 24683db6..7c8908fa 100755
--- a/snes/fast/ppu/memory/memory.cpp
+++ b/snes/fast/ppu/memory/memory.cpp
@@ -105,11 +105,14 @@ void PPU::oam_mmio_write(uint16 addr, uint8 data) {
if(regs.display_disabled == true) {
memory::oam[addr] = data;
+ update_sprite_list(addr, data);
} else {
if(cpu.vcounter() < (!overscan() ? 225 : 240)) {
memory::oam[regs.ioamaddr] = data;
+ update_sprite_list(regs.ioamaddr, data);
} else {
memory::oam[addr] = data;
+ update_sprite_list(addr, data);
}
}
}
diff --git a/snes/fast/ppu/render/oam.cpp b/snes/fast/ppu/render/oam.cpp
index d2e91790..52d6e1fe 100755
--- a/snes/fast/ppu/render/oam.cpp
+++ b/snes/fast/ppu/render/oam.cpp
@@ -1,15 +1,37 @@
#ifdef PPU_CPP
+void PPU::update_sprite_list(unsigned addr, uint8 data) {
+ if(addr < 0x0200) {
+ unsigned i = addr >> 2;
+ switch(addr & 3) {
+ case 0: sprite_list[i].x = (sprite_list[i].x & 0x0100) | data; break;
+ case 1: sprite_list[i].y = (data + 1) & 0xff; break;
+ case 2: sprite_list[i].character = data; break;
+ case 3: sprite_list[i].vflip = data & 0x80;
+ sprite_list[i].hflip = data & 0x40;
+ sprite_list[i].priority = (data >> 4) & 3;
+ sprite_list[i].palette = (data >> 1) & 7;
+ sprite_list[i].use_nameselect = data & 0x01;
+ }
+ } else {
+ unsigned i = (addr & 0x1f) << 2;
+ sprite_list[i + 0].x = ((data & 0x01) << 8) | (sprite_list[i + 0].x & 0xff);
+ sprite_list[i + 0].size = data & 0x02;
+ sprite_list[i + 1].x = ((data & 0x04) << 6) | (sprite_list[i + 1].x & 0xff);
+ sprite_list[i + 1].size = data & 0x08;
+ sprite_list[i + 2].x = ((data & 0x10) << 4) | (sprite_list[i + 2].x & 0xff);
+ sprite_list[i + 2].size = data & 0x20;
+ sprite_list[i + 3].x = ((data & 0x40) << 2) | (sprite_list[i + 3].x & 0xff);
+ sprite_list[i + 3].size = data & 0x80;
+ }
+}
+
void PPU::build_sprite_list() {
if(sprite_list_valid == true) return;
sprite_list_valid = true;
- const uint8 *tableA = memory::oam.data();
- const uint8 *tableB = memory::oam.data() + 512;
-
for(unsigned i = 0; i < 128; i++) {
- const bool x = *tableB & (1 << ((i & 3) << 1)); //0x01, 0x04, 0x10, 0x40
- const bool size = *tableB & (2 << ((i & 3) << 1)); //0x02, 0x08, 0x20, 0x80
+ const bool size = sprite_list[i].size;
switch(cache.oam_basesize) {
case 0: sprite_list[i].width = (!size) ? 8 : 16;
@@ -40,18 +62,6 @@ void PPU::build_sprite_list() {
if(regs.oam_interlace && !size) sprite_list[i].height = 16;
break;
}
-
- sprite_list[i].x = (x << 8) + tableA[0];
- sprite_list[i].y = (tableA[1] + 1) & 0xff;
- sprite_list[i].character = tableA[2];
- sprite_list[i].vflip = tableA[3] & 0x80;
- sprite_list[i].hflip = tableA[3] & 0x40;
- sprite_list[i].priority = (tableA[3] >> 4) & 3;
- sprite_list[i].palette = (tableA[3] >> 1) & 7;
- sprite_list[i].use_nameselect = tableA[3] & 1;
-
- tableA += 4;
- if((i & 3) == 3) tableB++;
}
}
diff --git a/snes/fast/ppu/render/render.hpp b/snes/fast/ppu/render/render.hpp
index 6de43e41..e3dfc37d 100755
--- a/snes/fast/ppu/render/render.hpp
+++ b/snes/fast/ppu/render/render.hpp
@@ -62,6 +62,7 @@ struct sprite_item {
bool vflip, hflip;
uint8 palette;
uint8 priority;
+ bool size;
} sprite_list[128];
bool sprite_list_valid;
unsigned active_sprite;
@@ -75,6 +76,7 @@ struct oam_tileitem {
enum { OAM_PRI_NONE = 4 };
uint8 oam_line_pal[256], oam_line_pri[256];
+void update_sprite_list(unsigned addr, uint8 data);
void build_sprite_list();
bool is_sprite_on_scanline();
void load_oam_tiles();
diff --git a/snes/fast/ppu/serialization.cpp b/snes/fast/ppu/serialization.cpp
index 289932de..2dbf3c2c 100755
--- a/snes/fast/ppu/serialization.cpp
+++ b/snes/fast/ppu/serialization.cpp
@@ -180,6 +180,7 @@ void PPU::serialize(serializer &s) {
s.integer(sprite_list[n].hflip);
s.integer(sprite_list[n].palette);
s.integer(sprite_list[n].priority);
+ s.integer(sprite_list[n].size);
}
s.integer(sprite_list_valid);
s.integer(active_sprite);
diff --git a/snes/input/input.hpp b/snes/input/input.hpp
index e24ac2ed..42b22249 100755
--- a/snes/input/input.hpp
+++ b/snes/input/input.hpp
@@ -82,6 +82,7 @@ private:
friend class System;
friend class Video;
+ friend class CPU;
};
extern Input input;
diff --git a/snes/smp/memory/memory.cpp b/snes/smp/memory/memory.cpp
index 2f5081ce..e872a4ec 100755
--- a/snes/smp/memory/memory.cpp
+++ b/snes/smp/memory/memory.cpp
@@ -11,12 +11,12 @@ alwaysinline void SMP::ram_write(uint16 addr, uint8 data) {
if(status.ram_writable && !status.ram_disabled) memory::apuram[addr] = data;
}
-uint8 SMP::port_read(uint8 port) {
- return memory::apuram[0xf4 + (port & 3)];
+uint8 SMP::port_read(uint2 port) const {
+ return memory::apuram[0xf4 + port];
}
-void SMP::port_write(uint8 port, uint8 data) {
- memory::apuram[0xf4 + (port & 3)] = data;
+void SMP::port_write(uint2 port, uint8 data) {
+ memory::apuram[0xf4 + port] = data;
}
alwaysinline uint8 SMP::op_busread(uint16 addr) {
@@ -45,15 +45,15 @@ alwaysinline uint8 SMP::op_busread(uint16 addr) {
case 0xf6: //CPUIO2
case 0xf7: { //CPUIO3
synchronize_cpu();
- r = cpu.port_read(addr & 3);
+ r = cpu.port_read(addr);
} break;
case 0xf8: { //RAM0
- r = status.smp_f8;
+ r = status.ram0;
} break;
case 0xf9: { //RAM1
- r = status.smp_f9;
+ r = status.ram1;
} break;
case 0xfa: //T0TARGET
@@ -146,7 +146,7 @@ alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
} break;
case 0xf3: { //DSPDATA
- //0x80-0xff is a read-only mirror of 0x00-0x7f
+ //0x80-0xff are read-only mirrors of 0x00-0x7f
if(!(status.dsp_addr & 0x80)) {
dsp.write(status.dsp_addr & 0x7f, data);
}
@@ -157,15 +157,15 @@ alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
case 0xf6: //CPUIO2
case 0xf7: { //CPUIO3
synchronize_cpu();
- port_write(addr & 3, data);
+ port_write(addr, data);
} break;
case 0xf8: { //RAM0
- status.smp_f8 = data;
+ status.ram0 = data;
} break;
case 0xf9: { //RAM1
- status.smp_f9 = data;
+ status.ram1 = data;
} break;
case 0xfa: { //T0TARGET
diff --git a/snes/smp/serialization.cpp b/snes/smp/serialization.cpp
index 334d15ba..2c7f5147 100755
--- a/snes/smp/serialization.cpp
+++ b/snes/smp/serialization.cpp
@@ -19,8 +19,8 @@ void SMP::serialize(serializer &s) {
s.integer(status.dsp_addr);
- s.integer(status.smp_f8);
- s.integer(status.smp_f9);
+ s.integer(status.ram0);
+ s.integer(status.ram1);
s.integer(t0.stage0_ticks);
s.integer(t0.stage1_ticks);
diff --git a/snes/smp/smp.cpp b/snes/smp/smp.cpp
index 6b7da28c..454d6bf5 100755
--- a/snes/smp/smp.cpp
+++ b/snes/smp/smp.cpp
@@ -65,26 +65,26 @@ void SMP::reset() {
create(Enter, system.apu_frequency());
regs.pc = 0xffc0;
- regs.a = 0x00;
- regs.x = 0x00;
- regs.y = 0x00;
+ regs.a = 0x00;
+ regs.x = 0x00;
+ regs.y = 0x00;
regs.sp = 0xef;
- regs.p = 0x02;
+ regs.p = 0x02;
for(unsigned i = 0; i < memory::apuram.size(); i++) {
memory::apuram.write(i, 0x00);
}
status.clock_counter = 0;
- status.dsp_counter = 0;
- status.timer_step = 3;
+ status.dsp_counter = 0;
+ status.timer_step = 3;
//$00f0
- status.clock_speed = 0;
- status.timer_speed = 0;
- status.timers_enabled = true;
- status.ram_disabled = false;
- status.ram_writable = true;
+ status.clock_speed = 0;
+ status.timer_speed = 0;
+ status.timers_enabled = true;
+ status.ram_disabled = false;
+ status.ram_writable = true;
status.timers_disabled = false;
//$00f1
@@ -94,8 +94,8 @@ void SMP::reset() {
status.dsp_addr = 0x00;
//$00f8,$00f9
- status.smp_f8 = 0x00;
- status.smp_f9 = 0x00;
+ status.ram0 = 0x00;
+ status.ram1 = 0x00;
t0.stage0_ticks = 0;
t1.stage0_ticks = 0;
diff --git a/snes/smp/smp.hpp b/snes/smp/smp.hpp
index cb8211e4..a7da3867 100755
--- a/snes/smp/smp.hpp
+++ b/snes/smp/smp.hpp
@@ -5,8 +5,8 @@ public:
alwaysinline void synchronize_cpu();
alwaysinline void synchronize_dsp();
- uint8 port_read(uint8 port);
- void port_write(uint8 port, uint8 data);
+ uint8 port_read(uint2 port) const;
+ void port_write(uint2 port, uint8 data);
void enter();
void power();
@@ -43,7 +43,8 @@ private:
uint8 dsp_addr;
//$00f8,$00f9
- uint8 smp_f8, smp_f9;
+ uint8 ram0;
+ uint8 ram1;
} status;
static void Enter();
diff --git a/snes/snes.hpp b/snes/snes.hpp
index 04c1a35c..fffcad96 100755
--- a/snes/snes.hpp
+++ b/snes/snes.hpp
@@ -1,7 +1,7 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
- static const char Version[] = "067.22";
+ static const char Version[] = "067.23";
static const unsigned SerializerVersion = 12;
}
}
@@ -28,6 +28,7 @@ namespace SNES {
#include
#include
#include
+#include
#include
using namespace nall;
@@ -38,15 +39,20 @@ using namespace nall;
#endif
namespace SNES {
- typedef int8_t int8;
- typedef int16_t int16;
- typedef int32_t int32;
- typedef int64_t int64;
- typedef uint8_t uint8;
+ typedef int8_t int8;
+ typedef int16_t int16;
+ typedef int32_t int32;
+ typedef int64_t int64;
+ typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
+ typedef uint_t<2> uint2;
+ typedef uint_t<10> uint10;
+ typedef uint_t<17> uint17;
+ typedef uint_t<24> uint24;
+
struct Processor {
cothread_t thread;
unsigned frequency;
diff --git a/sync.sh b/sync.sh
index 4fc3d059..0d87f913 100755
--- a/sync.sh
+++ b/sync.sh
@@ -11,3 +11,4 @@ synchronize "ruby"
test -d libco/doc && rm -r libco/doc
test -d libco/test && rm -r libco/test
+test -d ruby/_test && rm -r ruby/_test