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