From 2a90e129996d5de69c6a3338341edac5784e156a Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sun, 5 Jun 2011 13:45:04 +1000 Subject: [PATCH] Update to v079 release. byuu says: This release includes Nintendo Super System DIP switch emulation and improved PPU rendering accuracy, among other things. Changelog: - added Nintendo Super System DIP switch emulation [requires XML setting maps] - emulated Super Game Boy $6001 VRAM offset selection port [ikari_01] - fixed randomness initialization of S-SMP port registers [fixes DBZ:Hyper Dimension and Ninja Warriors] - mosaic V-countdown caches BGOFS registers (fixes Super Turrican 2 effect) [reported by zal16] - non-mosaic BGOFS registers are always cached at H=60 (fixes NHL '94 and Super Mario World flickering) - fixed 2xSaI family of renderers on 64-bit systems - cleaned up SMP source code - phoenix: fixed a bug when closing bsnes while minimized Please note that the mosaic BGOFS fix is only for the accuracy profile. Unfortunately the older scanline-based compatibility renderer's code is nearly unmaintainable at this point, so I haven't yet been able to backport the fixes. Also, I have written a new cycle-accurate SMP core that does not use libco. The aim is to implement it into Snes9X v1.54. But it would of course be prudent to test the new core first. [...then in the next post...] Decided to keep that Super Mario World part a surprise, so ... surprise! Realized while working on the Super Turrican 2 mosaic fix, and from looking at NHL '94 and Dai Kaijuu Monogatari 2's behavior, that BGOFS registers must be cached between H=0 and H=88 for the entire scanline ... they can't work otherwise, and it'd be stupid for the PPU to re-add the offset to the position on every pixel anyway. I chose H=60 for now. Once I am set up with the RGB monitor and the North American cartridge dumping is completed, I'll set it on getting exact timings for all these things. It'll probably require a smallish speed hit to allow exact-cycle timing events for everything in the PPU. --- bsnes/data/cheats.xml | 517 +++++++++++++----- bsnes/nall/directory.hpp | 9 +- bsnes/nall/file.hpp | 71 +-- bsnes/nall/platform.hpp | 15 +- bsnes/nall/string/cast.hpp | 6 +- bsnes/phoenix/core/core.cpp | 4 + bsnes/phoenix/core/core.hpp | 13 + bsnes/phoenix/core/layout/vertical-layout.cpp | 4 - bsnes/phoenix/core/layout/vertical-layout.hpp | 1 - bsnes/phoenix/core/state.hpp | 10 + bsnes/phoenix/gtk/gtk.cpp | 28 +- bsnes/phoenix/gtk/gtk.hpp | 10 + bsnes/phoenix/gtk/timer.cpp | 24 + bsnes/phoenix/phoenix.cpp | 9 +- bsnes/phoenix/phoenix.hpp | 5 + bsnes/phoenix/qt/qt.cpp | 1 + bsnes/phoenix/qt/qt.moc | 63 ++- bsnes/phoenix/qt/qt.moc.hpp | 17 + bsnes/phoenix/qt/timer.cpp | 21 + bsnes/phoenix/reference/font.cpp | 4 + bsnes/phoenix/reference/reference.cpp | 2 + bsnes/phoenix/reference/reference.hpp | 23 + bsnes/phoenix/reference/timer.cpp | 8 + bsnes/phoenix/reference/widget/canvas.cpp | 9 + bsnes/phoenix/reference/widget/widget.cpp | 8 + bsnes/phoenix/windows/timer.cpp | 31 ++ bsnes/phoenix/windows/window.cpp | 7 +- bsnes/phoenix/windows/windows.cpp | 1 + bsnes/phoenix/windows/windows.hpp | 11 + bsnes/snes/ppu/background/background.cpp | 35 +- bsnes/snes/ppu/background/background.hpp | 9 +- bsnes/snes/ppu/background/mode7.cpp | 10 +- bsnes/snes/ppu/ppu.cpp | 4 + bsnes/snes/ppu/serialization.cpp | 5 +- bsnes/snes/snes.hpp | 2 +- snesfilter/2xSaI/2xSaI.cpp | 2 +- snesfilter/2xSaI/Super-2xSaI.cpp | 2 +- snesfilter/2xSaI/Super-Eagle.cpp | 2 +- 38 files changed, 784 insertions(+), 219 deletions(-) create mode 100755 bsnes/phoenix/gtk/timer.cpp create mode 100755 bsnes/phoenix/qt/timer.cpp create mode 100755 bsnes/phoenix/reference/timer.cpp create mode 100755 bsnes/phoenix/reference/widget/canvas.cpp create mode 100755 bsnes/phoenix/windows/timer.cpp diff --git a/bsnes/data/cheats.xml b/bsnes/data/cheats.xml index 949d894e..b49542f4 100755 --- a/bsnes/data/cheats.xml +++ b/bsnes/data/cheats.xml @@ -1673,6 +1673,10 @@ Have Fezi-copter + 6DAC-6FDD + + + Have Fezi-copter (alt) 7E0064FF @@ -3535,7 +3539,6 @@ Invincibility 2D87-AD04 - EDA6-AFDD Infinite lives @@ -5042,6 +5045,10 @@ BioMetal (USA) + + Invincibility (blinking) + 406D-DDD2 + Infinite lives C26E-6D02 @@ -9409,6 +9416,14 @@ Cutthroat Island (USA) + + Stage select menu after character select screen + 3C6B-479E + + + Stage select menu after character select screen (alt) + 878C9DEA + Infinite health - P1 7E09F428 @@ -17330,6 +17345,18 @@ Infinite time A2C0-A7D0 + + Hit anywhere + 3CA4-0FD0 + 40AD-04A0 + 7DA4-0F00 + 89A4-0D60 + F9A4-0DA0 + + + Enemies never get knocked down, attack until they die + 7E0D7000 + Slower timer D4C9-AFD0 @@ -17338,10 +17365,6 @@ Faster timer DDC9-AFD0 - - Enemies never get knocked down, hit them until they die - 7E0D7000 - Enemy 1 has no health 7E101400 @@ -24315,6 +24338,19 @@ Infinite Arrows 17E5-22E6 + + Hit anywhere (disable before fighting Ganon, use the Boomerang instead of Sword to hit switches) + 40E2-6D96 + 6D3E-A7FC + 403F-DD28 + 40EC-AF26 + 6D34-D7F8 + 4068-A0E6 + + + Get items from anywhere + 402F-07B6 + Always get Faerie at the Pond Of Happiness (as if you threw in 100 rupees) 7EF36A64 @@ -24336,7 +24372,7 @@ DDB5-049E - Enemies that normally drop items will drop them 100% of the time + 100% enemy drop rate (from enemies that normally drop items) DDE8-142C @@ -30756,6 +30792,10 @@ One hit kills 40DE-7FD2 + + Hit anywhere + 6DD8-7DD2 + Multi-jump 1DFC-E400 @@ -30805,6 +30845,10 @@ One hit kills (most enemies) 6DB5-CD97 + + Hit anywhere + 40B1-34F4 + Immune to drain attack C2AD-4401 @@ -30890,10 +30934,6 @@ Infinite lives (alt) 7E1F8009 - - Start with all weapons and all enemies defeated (except Sigma) - 23BD-3F07 - Infinite weapons once obtained C9B3-4769 @@ -30902,6 +30942,10 @@ One hit kills (most enemies) 6DB5-CD97 + + Hit anywhere + 40B1-34F4 + Have all equipment 7E1F99FF @@ -30944,6 +30988,10 @@ Weapon charges to 1st power level faster DDB1-4F61 + + Start with all weapons and all enemies defeated (except Sigma) + 23BD-3F07 + Start with less health D6BE-47AF @@ -31063,6 +31111,12 @@ Have sub-tank 4 full 7E1FB9FF + + Hit anywhere + 4028-A73F + C222-6734 + D4E7-DDFB + One hit kills 6D2D-AF14 @@ -31084,10 +31138,6 @@ Infinite health C2AD-6FF7 - - Start with max health bar - F02A-ADF4 - Infinite lives 7E1FB409 @@ -31108,14 +31158,14 @@ 82CB-0D2F 82CA-0F2F - - Always Super Shot - 7E0A6702 - Infinite Air Dash 7E0A3478 + + Always have Super Shot + 7E0A6702 + Have Zero-Saber 7E1FB2FC @@ -31129,8 +31179,10 @@ 7E0CF801 - Skip bosses at start of game and proceed to stage select - B933-DF6C + Hit anywhere + 40AC-A7B4 + 6DA0-ADF7 + 6DAF-AD97 Multi-jump @@ -31150,6 +31202,14 @@ Ultra mega-jump D886-6F26 + + Skip bosses at start of game and proceed to stage select + B933-DF6C + + + Start with max health bar + F02A-ADF4 + Metal Combat - Falcon's Revenge (USA) @@ -31984,6 +32044,13 @@ First strike of any kind wins round DDBC-370F + + Hit anywhere - P1 + 3DBF-3D0F + 27BF-3D6F + F6BF-3DAF + 74BF-3F0F + All throws do more damage 56B9-4DAD @@ -32507,13 +32574,37 @@ C239-CD62 - First round / one button fatalities + First round and one button fatalities 7E3AF001 Infinite continues A220-3FB6 + + P1 takes all damage + DD37-CF62 + + + P2 takes all damage + 6D37-CF02 + + + Hit anywhere - P1 + 0AE6-3F0E + 0AE6-340E + 0AE6-34DE + 39E6-346E + 39E6-3FAE + 3DE6-3DDE + 6D30-1462 + C4E6-3F6E + D4E6-3D0E + DDE6-3D6E + EDE6-3DAE + D7E6-3FDE + EE30-14A2 + Press A on main menu for Sound Test D42E-44D8 @@ -32530,14 +32621,6 @@ Press X on main menu for Scott's Menu D42B-1FD8 - - P1 takes all damage - DD37-CF62 - - - P2 takes all damage - 6D37-CF02 - Always fight Kano CE8F-3FB7 @@ -32710,6 +32793,10 @@ Infinite time 6DC7-1DAA + + Infinite continues + C2C4-47AA + No health - P1 DDB1-1FF7 @@ -32719,12 +32806,15 @@ DDB5-1FF7 - Have 127x more fatality time - 5EC2-CF02 + Hit anywhere - P1 + 0DB0-4F97 + 2DB0-4FF7 + 3DB0-4D97 + DDB0-4DB7 - Infinite continues - C2C4-47AA + Have 127x more fatality time + 5EC2-CF02 Disable throws - 2P mode @@ -44004,6 +44094,13 @@ DD80-7FAD D580-74DD + + Hit anywhere (except projectiles) - P1 + 3DC7-8D0D + 6DC7-8D6D + BDC7-8FDD + DBC7-8DAD + Street Fighter II (USA) @@ -44017,6 +44114,13 @@ Win 1 bout to win the match instead of 2 out of 3 (disable before fighting M. Bison) DF80-AD64 + + Hit anywhere (except projectiles) - P1 + 3D29-A4A7 + 8D29-A767 + DD29-A7D7 + D329-A707 + Dizziness wears off very quickly EDBE-0F09 @@ -44389,6 +44493,13 @@ Infinite time (alt) 7E18F399 + + Hit anywhere (except projectiles) - P1 + 3D98-8704 + 8D9A-8DD4 + DD98-8764 + D598-87A4 + Select same character - both players 7E184820 @@ -46655,19 +46766,19 @@ Super Double Dragon (USA) - Invincibility - C267-0DD6 - - - Infinite health + Invincibility - both players 1D6F-0766 - Infinite lives - C286-6F05 + Invincibility - P1 + C267-0DD6 Infinite lives - P1 + C286-6F05 + + + Infinite lives - P1 (alt) 4A86-6F05 @@ -46706,6 +46817,30 @@ 1 life - 2P game A DF88-0D6B + + Start on Mission 2 (enable on Mode Seclect screen, then disable) + 7E001C14 + + + Start on Mission 3 (enable on Mode Seclect screen, then disable) + 7E001C17 + + + Start on Mission 4 (enable on Mode Seclect screen, then disable) + 7E001C1C + + + Start on Mission 5 (enable on Mode Seclect screen, then disable) + 7E001C1D + + + Start on Mission 6 (enable on Mode Seclect screen, then disable) + 7E001C1F + + + Start on Mission 7 (enable on Mode Seclect screen, then disable) + 7E001C20 + Super Ghouls'n Ghosts (USA) @@ -46896,6 +47031,11 @@ Super Mario All-Stars (USA) (SMB) Invincibility + 62E7-A7D2 + 2DE7-A7A2 + + + (SMB) Invincibility (Starman effect) 292B-67DE @@ -46923,16 +47063,27 @@ 6D84-DF03 - (SMB) Play as Big Mario - 7E07AE05 - - - (SMB) Play as Fire Mario - 23C2BB03 + (SMB) Always Fiery Mario after first hit + CB29-AF0E + D429-AF6E + CB8B-676A + DD8B-67AA (SMB) Multi-jump - 23C2BB02 + 2D8E-D7D2 + + + (SMB) Fireballs hit anywhere + 4028-D4DE + + + (SMB) Fireballs can kill Bullet Bill + 4025-07AE + + + (SMB) Fireballs can kill Buzzy Beetle + 6D2E-DD6E (SMB) Run without holding the dash button @@ -47022,13 +47173,21 @@ 7E00853B - (SMB2) Always big + (SMB2) Infinite hearts + DD32-6966 + + + (SMB2) Always big Mario 7E04C31F - (SMB2) Always small + (SMB2) Always small Mario 7E04C30F + + (SMB2) Infinite lives + C26E-D5A6 + (SMB2) Multi-jump - all characters D966-6166 @@ -47061,10 +47220,6 @@ (SMB2) 99 lives after continue 1761-05D0 - - (SMB2) Infinite lives - C26E-D5A6 - (SMB2) Continue with 3 hearts instead of 2 DF6B-A9A1 @@ -47073,10 +47228,6 @@ (SMB2) Continue with 4 hearts D46B-A9A1 - - (SMB2) Never lose hearts - DD32-6966 - (SMB2) Jumping in place charges super jump 7A60-A966 @@ -47097,38 +47248,55 @@ (SMB3) Invincibility (Starman) 7E0553FF + + (SMB3) Infinite lives + 82BB-0C6D + (SMB3) Infinite time 6D3D-6619 - (SMB3) Play as Small Mario + (SMB3) Always Small Mario 7E00BB00 - (SMB3) Play as Big Mario + (SMB3) Always Big Mario 7E00BB01 - (SMB3) Play as Fire Mario + (SMB3) Always Fire Mario 7E00BB02 - (SMB3) Play as Raccoon Mario + (SMB3) Always Raccoon Mario 7E00BB03 - (SMB3) Play as Frog Mario + (SMB3) Always Frog Mario 7E00BB04 - (SMB3) Play as Tanooki Mario + (SMB3) Always Tanooki Mario 7E00BB05 - (SMB3) Play as Hammer Bros. Mario + (SMB3) Always Hammer Bros. Mario 7E00BB06 + + (SMB3) Fireballs hit anywhere + 4083-D8F3 + 408D-08F3 + + + (SMB3) Tail hits anywhere + 40C4-6C22 + + + (SMB3) Fireballs can kill most enemies + 4084-0BB3 + (SMB3) Have Magic Whistle 7E1D800C @@ -47146,7 +47314,7 @@ DDAF-A8A3 - (SMB3) Fly for an unlimited amount of time + (SMB3) Infinite flying time EEA4-AB63 @@ -47216,10 +47384,6 @@ (SMB3) After getting star, invincible until end of level (may have to disable to jump) C23B-680D - - (SMB3) Infinite lives - 82BB-0C6D - (SMB3) 1 life after continue DFBB-DBAF @@ -47289,13 +47453,13 @@ Super Mario All-Stars + Super Mario World (USA) (SMB) Invincibility - 292B-67DE - - - (SMB) Invincibility (alt) 62E7-A7D2 2DE7-A7A2 + + (SMB) Invincibility (Starman effect) + 292B-67DE + (SMB) Invincibility (Starman) 7E07AF0F @@ -47305,21 +47469,28 @@ 7E075A05 - (SMB) Play as Big Mario - 7E07AE05 - - - (SMB) Play as Big Mario (alt) - 23C2BB02 - - - (SMB) Play as Fire Mario - 23C2BB03 + (SMB) Always Fiery Mario after first hit + CB29-AF0E + D429-AF6E + CB8B-676A + DD8B-67AA (SMB) Multi-jump 2D8E-D7D2 + + (SMB) Fireballs hit anywhere + 4028-D4DE + + + (SMB) Fireballs can kill Bullet Bill + 4025-07AE + + + (SMB) Fireballs can kill Buzzy Beetle + 6D2E-DD6E + (SMB) Run without holding the dash button DD8E-D702 @@ -47341,17 +47512,9 @@ C26E-D5A6 - (SMB2) Never lose hearts + (SMB2) Infinite hearts DD32-6966 - - (SMB2) Always Big - 7E04C31F - - - (SMB2) Always Small - 7E04C30F - (SMB2) Multi-jump - all characters D966-6166 @@ -47381,33 +47544,37 @@ 7E0553FF - (SMB3) Play as Small Mario + (SMB3) Always Small Mario 7E00BB00 - (SMB3) Play as Big Mario + (SMB3) Always Big Mario 7E00BB01 - (SMB3) Play as Fire Mario + (SMB3) Always Fiery Mario 7E00BB02 - (SMB3) Play as Raccoon Mario + (SMB3) Always Raccoon Mario 7E00BB03 - (SMB3) Play as Frog Mario + (SMB3) Always Frog Mario 7E00BB04 - (SMB3) Play as Tanooki Mario + (SMB3) Always Tanooki Mario 7E00BB05 - (SMB3) Play as Hammer Bros Mario + (SMB3) Always Hammer Bros Mario 7E00BB06 + + (SMB3) Infinite flying time + 23CB26FF + (SMB3) Have Magic Whistle 7E1D800C @@ -47417,12 +47584,17 @@ 7E056EFF - (SMB3) Fly at anytime (run meter always full) - 23CB1F00 + (SMB3) Fireballs hit anywhere + 4083-D8F3 + 408D-08F3 - (SMB3) Fly for an unlimited amount of time - 23CB26FF + (SMB3) Tail hits anywhere + 40C4-6C22 + + + (SMB3) Fireballs can kill most enemies + 4084-0BB3 (SMW) Invincibility @@ -47445,9 +47617,13 @@ 7E001902 - (SMW) Always Fire Mario + (SMW) Always Fiery Mario 7E001903 + + (SMW) Always have Yoshi + 7E0DC101 + (SMW) Infinite time 7E0F3109 @@ -47458,10 +47634,6 @@ (SMW) Infinite P-Balloon time 7E1891FF - - (SMW) Always have Yoshi - 7E0DC101 - (SMW) Infinite flying time for Yoshi C2EC-0700 @@ -47892,6 +48064,10 @@ 89E4-AFD9 89C6-D4DB + + Infinite lives + C222-D4DD + Infinite flying time for Yoshi C2EC-0700 @@ -47905,8 +48081,24 @@ 7E1891FF - Infinite lives - C222-D4DD + Always Small Mario + 7E001900 + + + Always Big Mario + 7E001901 + + + Always Cape Mario + 7E001902 + + + Always Fiery Mario + 7E001903 + + + Always have Yoshi + 7E0DC101 Multi-jump @@ -47921,6 +48113,31 @@ F53F-6767 DD3F-67A7 + + Cape hit anywhere + 40BE-AD66 + + + Fireballs hits anywhere + 40C2-D7A6 + + + Fireballs shoot straight + DDEA-6F07 + DDB2-AFD8 + + + Fireballs turn most enemies into Flowers + 59C4-0466 + + + Fireballs turn most enemies into 1-Up Mushrooms + 56C4-0466 + + + Fireballs turn most enemies into Starmen + 51C4-0466 + Low-jump D02C-AF6F @@ -47933,26 +48150,6 @@ Mega-jump DF2C-AF6F - - Always Small Mario - 7E001900 - - - Always Big Mario - 7E001901 - - - Always Cape Mario - 7E001902 - - - Always Fire Mario - 7E001903 - - - Always have Yoshi - 7E0DC101 - Little Yoshi grows after eating 1 enemy instead of 5 DFCE-64A0 @@ -47969,11 +48166,6 @@ Little Yoshi grows after eating 4 enemies D0CE-64A0 - - Shoot fireballs straight - DDEA-6F07 - DDB2-AFD8 - Activate green blocks (disable before entering the Green Switch Palace) 7E1F2701 @@ -48477,6 +48669,11 @@ Super-jumps don't drain energy C22A-456D + + Enemies die on contact (Speed Booster effect) + 6DC8-4CDF + 6DCC-4BDF + Kill most enemies on contact (prevents bomb-bouncing) 7E0A6E0F @@ -50434,6 +50631,13 @@ Instant win - P1 7E0771FF + + Hit anywhere (except projectiles) - P1 + 3D1D-5DDF + 8D1D-5DAF + 0D1D-5D0F + D51D-5D6F + No charging required for some special moves D002-EDD5 @@ -54788,13 +54992,29 @@ 7D7B-FE7C - First round / one button fatalities + First round and one button fatalities 7E3BE301 Max fatality time DF73-2A7C + + Hit anywhere - P1 + 0AEB-3F97 + 0AEB-34F7 + 31EB-34B7 + 35EB-3F27 + 3DEB-3DF7 + 46EB-3FB7 + 84EB-3497 + BD3C-C49F + D4EB-3D97 + DDEB-3DB7 + D7EB-3FF7 + EDEB-3D27 + EE3C-C4BF + Blank versus screen EE37-CF02 @@ -55467,6 +55687,21 @@ 7E1B8963 + + Ushio to Tora (Japan) + + Invincibility + 7E022226 + + + Infinite health + 7E021E40 + + + Infinite lives + 7E060863 + + Utopia - The Creation of a Nation (USA) @@ -57692,15 +57927,15 @@ - Zool - Ninja of the Nth Dimension (USA) + Zool - Ninja of the 'Nth' Dimension (USA) + + Invincibility + 7E05DCFF + Invincibility (blinking) 7E1D8B49 - - Invincibility (not blinking) - 7E05DCFF - Infinite health 7E1CF1FA diff --git a/bsnes/nall/directory.hpp b/bsnes/nall/directory.hpp index c4f94c9a..4d3bcba5 100755 --- a/bsnes/nall/directory.hpp +++ b/bsnes/nall/directory.hpp @@ -42,20 +42,21 @@ struct directory { if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(string(name, "/")); + if(wildcard(name, pattern)) list.append(name); } } while(FindNextFile(handle, &data) != false) { if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(string(name, "/")); + if(wildcard(name, pattern)) list.append(name); } } } FindClose(handle); } if(list.size() > 0) sort(&list[0], list.size()); + foreach(name, list) name.append("/"); //must append after sorting return list; } @@ -109,14 +110,14 @@ struct directory { if(!strcmp(ep->d_name, ".")) continue; if(!strcmp(ep->d_name, "..")) continue; if(ep->d_type & DT_DIR) { - if(wildcard(ep->d_name, pattern)) list.append(string(ep->d_name, "/")); + if(wildcard(ep->d_name, pattern)) list.append(ep->d_name); } } closedir(dp); } if(list.size() > 0) sort(&list[0], list.size()); + foreach(name, list) name.append("/"); //must append after sorting return list; - } inline lstring directory::files(const string &pathname, const string &pattern) { diff --git a/bsnes/nall/file.hpp b/bsnes/nall/file.hpp index 103c7d4a..8c4ef894 100755 --- a/bsnes/nall/file.hpp +++ b/bsnes/nall/file.hpp @@ -1,15 +1,7 @@ #ifndef NALL_FILE_HPP #define NALL_FILE_HPP -#include -#include - -#if !defined(_WIN32) - #include -#else - #include -#endif - +#include #include #include #include @@ -28,6 +20,7 @@ namespace nall { public: enum class mode : unsigned { read, write, readwrite, writeread }; enum class index : unsigned { absolute, relative }; + enum class time : unsigned { create, modify, access }; uint8_t read() { if(!fp) return 0xff; //file not open @@ -142,52 +135,60 @@ namespace nall { return file_offset >= file_size; } - static bool exists(const char *fn) { + static bool exists(const char *filename) { #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); + struct stat64 data; + return stat64(filename, &data) == 0; #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); + struct __stat64 data; + return _wstat64(utf16_t(filename), &data) == 0; #endif - if(fp) { - fclose(fp); - return true; - } - return false; } - static unsigned size(const char *fn) { + static uintmax_t size(const char *filename) { #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); + struct stat64 data; + stat64(filename, &data); #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); + struct __stat64 data; + _wstat64(utf16_t(filename), &data); #endif - unsigned filesize = 0; - if(fp) { - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - fclose(fp); + return S_ISREG(data.st_mode) ? data.st_size : 0u; + } + + static time_t timestamp(const char *filename, file::time mode = file::time::create) { + #if !defined(_WIN32) + struct stat64 data; + stat64(filename, &data); + #else + struct __stat64 data; + _wstat64(utf16_t(filename), &data); + #endif + switch(mode) { default: + case file::time::create: return data.st_ctime; + case file::time::modify: return data.st_mtime; + case file::time::access: return data.st_atime; } - return filesize; } bool open() { return fp; } - bool open(const char *fn, mode mode_) { + bool open(const char *filename, mode mode_) { if(fp) return false; switch(file_mode = mode_) { #if !defined(_WIN32) - case mode::read: fp = fopen(fn, "rb"); break; - case mode::write: fp = fopen(fn, "wb+"); break; //need read permission for buffering - case mode::readwrite: fp = fopen(fn, "rb+"); break; - case mode::writeread: fp = fopen(fn, "wb+"); break; + case mode::read: fp = fopen(filename, "rb" ); break; + case mode::write: fp = fopen(filename, "wb+"); break; //need read permission for buffering + case mode::readwrite: fp = fopen(filename, "rb+"); break; + case mode::writeread: fp = fopen(filename, "wb+"); break; #else - case mode::read: fp = _wfopen(utf16_t(fn), L"rb"); break; - case mode::write: fp = _wfopen(utf16_t(fn), L"wb+"); break; - case mode::readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break; - case mode::writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break; + case mode::read: fp = _wfopen(utf16_t(filename), L"rb" ); break; + case mode::write: fp = _wfopen(utf16_t(filename), L"wb+"); break; + case mode::readwrite: fp = _wfopen(utf16_t(filename), L"rb+"); break; + case mode::writeread: fp = _wfopen(utf16_t(filename), L"wb+"); break; #endif } if(!fp) return false; diff --git a/bsnes/nall/platform.hpp b/bsnes/nall/platform.hpp index 72eeec09..a7314493 100755 --- a/bsnes/nall/platform.hpp +++ b/bsnes/nall/platform.hpp @@ -1,6 +1,12 @@ #ifndef NALL_PLATFORM_HPP #define NALL_PLATFORM_HPP +#if defined(_WIN32) + //minimum version needed for _wstat64, etc + #undef __MSVCRT_VERSION__ + #define __MSVCRT_VERSION__ 0x0601 +#endif + #include //========================= @@ -18,16 +24,19 @@ #include #include +#include +#include + #if defined(_WIN32) #include #include #include + #include #undef interface #define dllexport __declspec(dllexport) #else #include #include - #include #define dllexport #endif @@ -53,11 +62,11 @@ #if defined(_WIN32) #define getcwd _getcwd #define ftruncate _chsize - #define putenv _putenv #define mkdir(n, m) _wmkdir(nall::utf16_t(n)) + #define putenv _putenv #define rmdir _rmdir - #define vsnprintf _vsnprintf #define usleep(n) Sleep(n / 1000) + #define vsnprintf _vsnprintf #endif //================ diff --git a/bsnes/nall/string/cast.hpp b/bsnes/nall/string/cast.hpp index 14f005da..9498392c 100755 --- a/bsnes/nall/string/cast.hpp +++ b/bsnes/nall/string/cast.hpp @@ -6,8 +6,10 @@ namespace nall { //this is needed, as C++0x does not support explicit template specialization inside classes template<> inline const char* to_string (bool v) { return v ? "true" : "false"; } template<> inline const char* to_string (signed int v) { static char temp[256]; snprintf(temp, 255, "%+d", v); return temp; } -template<> inline const char* to_string (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; } -template<> inline const char* to_string (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; } +template<> inline const char* to_string (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; } +template<> inline const char* to_string (intmax_t v) { static char temp[256]; snprintf(temp, 255, "%+lld", (long long)v); return temp; } +template<> inline const char* to_string (uintmax_t v) { static char temp[256]; snprintf(temp, 255, "%llu", (unsigned long long)v); return temp; } +template<> inline const char* to_string (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; } template<> inline const char* to_string (char *v) { return v; } template<> inline const char* to_string (const char *v) { return v; } template<> inline const char* to_string (string v) { return v; } diff --git a/bsnes/phoenix/core/core.cpp b/bsnes/phoenix/core/core.cpp index ddb868cb..89d26718 100755 --- a/bsnes/phoenix/core/core.cpp +++ b/bsnes/phoenix/core/core.cpp @@ -34,6 +34,10 @@ void Font::setSize(unsigned size) { state.size = size; return p.setSize(size); } void Font::setUnderline(bool underline) { state.underline = underline; return p.setUnderline(underline); } Font::Font() : state(*new State), p(*new pFont(*this)) { p.constructor(); } +void Timer::setEnabled(bool enabled) { state.enabled = enabled; return p.setEnabled(enabled); } +void Timer::setInterval(unsigned milliseconds) { state.milliseconds = milliseconds; return p.setInterval(milliseconds); } +Timer::Timer() : state(*new State), p(*new pTimer(*this)) { p.constructor(); } + MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::information(parent, text, buttons); } MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::question(parent, text, buttons); } MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::warning(parent, text, buttons); } diff --git a/bsnes/phoenix/core/core.hpp b/bsnes/phoenix/core/core.hpp index 2f087b42..f09e6a2c 100755 --- a/bsnes/phoenix/core/core.hpp +++ b/bsnes/phoenix/core/core.hpp @@ -6,6 +6,7 @@ struct Widget; struct pOS; struct pFont; +struct pTimer; struct pWindow; struct pAction; struct pMenu; @@ -82,6 +83,18 @@ struct Font : Object { pFont &p; }; +struct Timer : Object { + nall::function onTimeout; + + void setEnabled(bool enabled = true); + void setInterval(unsigned milliseconds); + + Timer(); + struct State; + State &state; + pTimer &p; +}; + struct MessageWindow : Object { enum class Buttons : unsigned { Ok, diff --git a/bsnes/phoenix/core/layout/vertical-layout.cpp b/bsnes/phoenix/core/layout/vertical-layout.cpp index e3185001..373c8249 100755 --- a/bsnes/phoenix/core/layout/vertical-layout.cpp +++ b/bsnes/phoenix/core/layout/vertical-layout.cpp @@ -69,10 +69,6 @@ Geometry VerticalLayout::minimumLayoutGeometry() { return { 0, 0, maximumWidth ? MaximumSize : margin * 2 + width, maximumHeight ? MaximumSize : margin * 2 + height }; } -void VerticalLayout::reset() { - children.reset(); -} - void VerticalLayout::setGeometry(const Geometry &containerGeometry) { auto children = this->children; foreach(child, children) { diff --git a/bsnes/phoenix/core/layout/vertical-layout.hpp b/bsnes/phoenix/core/layout/vertical-layout.hpp index fb78247e..a280c269 100755 --- a/bsnes/phoenix/core/layout/vertical-layout.hpp +++ b/bsnes/phoenix/core/layout/vertical-layout.hpp @@ -5,7 +5,6 @@ struct VerticalLayout : public Layout { void append(Widget &widget, unsigned width, unsigned height, unsigned spacing = 0); Geometry minimumGeometry(); Geometry minimumLayoutGeometry(); - void reset(); void setGeometry(const Geometry &geometry); void setMargin(unsigned margin); void setParent(Window &parent); diff --git a/bsnes/phoenix/core/state.hpp b/bsnes/phoenix/core/state.hpp index a4d99bf7..75df5abb 100755 --- a/bsnes/phoenix/core/state.hpp +++ b/bsnes/phoenix/core/state.hpp @@ -13,6 +13,16 @@ struct Font::State { } }; +struct Timer::State { + bool enabled; + unsigned milliseconds; + + State() { + enabled = false; + milliseconds = 0; + } +}; + struct Window::State { bool backgroundColor; unsigned backgroundColorRed, backgroundColorGreen, backgroundColorBlue; diff --git a/bsnes/phoenix/gtk/gtk.cpp b/bsnes/phoenix/gtk/gtk.cpp index c711d7a2..1c06df83 100755 --- a/bsnes/phoenix/gtk/gtk.cpp +++ b/bsnes/phoenix/gtk/gtk.cpp @@ -2,6 +2,7 @@ #include "settings.cpp" #include "font.cpp" +#include "timer.cpp" #include "message-window.cpp" #include "window.cpp" @@ -31,10 +32,29 @@ Font pOS::defaultFont; Geometry pOS::availableGeometry() { - //TODO: is there a GTK+ function for this? - //should return desktopGeometry() sans panels, toolbars, docks, etc. - Geometry geometry = desktopGeometry(); - return { geometry.x + 64, geometry.y + 64, geometry.width - 128, geometry.height - 128 }; + Display *display = XOpenDisplay(0); + int screen = DefaultScreen(display); + + static Atom atom = X11None; + if(atom == X11None) atom = XInternAtom(display, "_NET_WORKAREA", True); + + int format; + unsigned char *data = 0; + unsigned long items, after; + Atom returnAtom; + + int result = XGetWindowProperty( + display, RootWindow(display, screen), atom, 0, 4, False, XA_CARDINAL, &returnAtom, &format, &items, &after, &data + ); + + XCloseDisplay(display); + + if(result == Success && returnAtom == XA_CARDINAL && format == 32 && items == 4) { + unsigned long *workarea = (unsigned long*)data; + return { (signed)workarea[0], (signed)workarea[1], (unsigned)workarea[2], (unsigned)workarea[3] }; + } + + return desktopGeometry(); } Geometry pOS::desktopGeometry() { diff --git a/bsnes/phoenix/gtk/gtk.hpp b/bsnes/phoenix/gtk/gtk.hpp index f6abacce..8a27fb03 100755 --- a/bsnes/phoenix/gtk/gtk.hpp +++ b/bsnes/phoenix/gtk/gtk.hpp @@ -57,6 +57,16 @@ struct pFont : public pObject { void constructor(); }; +struct pTimer : public pObject { + Timer &timer; + + void setEnabled(bool enabled); + void setInterval(unsigned milliseconds); + + pTimer(Timer &timer) : timer(timer) {} + void constructor(); +}; + struct pMessageWindow : public pObject { static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons); static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons); diff --git a/bsnes/phoenix/gtk/timer.cpp b/bsnes/phoenix/gtk/timer.cpp new file mode 100755 index 00000000..d04183f8 --- /dev/null +++ b/bsnes/phoenix/gtk/timer.cpp @@ -0,0 +1,24 @@ +static guint Timer_trigger(pTimer *self) { + //timer may have been disabled prior to triggering, so check state + if(self->timer.state.enabled) { + if(self->timer.onTimeout) self->timer.onTimeout(); + } + //callback may have disabled timer, so check state again + if(self->timer.state.enabled) { + g_timeout_add(self->timer.state.milliseconds, (GSourceFunc)Timer_trigger, (gpointer)self); + } + //kill this timer instance (it is spawned above if needed again) + return false; +} + +void pTimer::setEnabled(bool enabled) { + if(enabled) { + g_timeout_add(timer.state.milliseconds, (GSourceFunc)Timer_trigger, (gpointer)this); + } +} + +void pTimer::setInterval(unsigned milliseconds) { +} + +void pTimer::constructor() { +} diff --git a/bsnes/phoenix/phoenix.cpp b/bsnes/phoenix/phoenix.cpp index 28307897..d73c3b6a 100755 --- a/bsnes/phoenix/phoenix.cpp +++ b/bsnes/phoenix/phoenix.cpp @@ -1,3 +1,6 @@ +#ifndef PHOENIX_CPP +#define PHOENIX_CPP + #if defined(PHOENIX_WINDOWS) #define UNICODE #define WINVER 0x0501 @@ -14,13 +17,15 @@ #include #include #elif defined(PHOENIX_GTK) - #define None X11None + #define None #define Window X11Window + #define X11None 0L #include #include #include #include + #include #undef None #undef Window @@ -35,3 +40,5 @@ using namespace nall; namespace phoenix { #include "core/core.cpp" } + +#endif diff --git a/bsnes/phoenix/phoenix.hpp b/bsnes/phoenix/phoenix.hpp index aa0d94ab..bea075c1 100755 --- a/bsnes/phoenix/phoenix.hpp +++ b/bsnes/phoenix/phoenix.hpp @@ -1,3 +1,6 @@ +#ifndef PHOENIX_HPP +#define PHOENIX_HPP + #include #include #include @@ -11,3 +14,5 @@ namespace phoenix { #include "core/core.hpp" } + +#endif diff --git a/bsnes/phoenix/qt/qt.cpp b/bsnes/phoenix/qt/qt.cpp index d971d04b..42bd10ee 100755 --- a/bsnes/phoenix/qt/qt.cpp +++ b/bsnes/phoenix/qt/qt.cpp @@ -3,6 +3,7 @@ #include "settings.cpp" #include "font.cpp" +#include "timer.cpp" #include "message-window.cpp" #include "window.cpp" diff --git a/bsnes/phoenix/qt/qt.moc b/bsnes/phoenix/qt/qt.moc index 5f8602a4..dd08a286 100755 --- a/bsnes/phoenix/qt/qt.moc +++ b/bsnes/phoenix/qt/qt.moc @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'qt.moc.hpp' ** -** Created: Wed Mar 23 16:17:23 2011 +** Created: Tue May 24 19:33:16 2011 ** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0) ** ** WARNING! All changes made in this file will be lost! @@ -16,6 +16,67 @@ #endif QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_pTimer[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 8, 7, 7, 7, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_pTimer[] = { + "pTimer\0\0onTimeout()\0" +}; + +const QMetaObject pTimer::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_pTimer, + qt_meta_data_pTimer, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &pTimer::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *pTimer::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *pTimer::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_pTimer)) + return static_cast(const_cast< pTimer*>(this)); + if (!strcmp(_clname, "pObject")) + return static_cast< pObject*>(const_cast< pTimer*>(this)); + return QObject::qt_metacast(_clname); +} + +int pTimer::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: onTimeout(); break; + default: ; + } + _id -= 1; + } + return _id; +} static const uint qt_meta_data_pWindow[] = { // content: diff --git a/bsnes/phoenix/qt/qt.moc.hpp b/bsnes/phoenix/qt/qt.moc.hpp index d7466d6b..ba6ab2ad 100755 --- a/bsnes/phoenix/qt/qt.moc.hpp +++ b/bsnes/phoenix/qt/qt.moc.hpp @@ -56,6 +56,23 @@ struct pFont : public pObject { void update(); }; +struct pTimer : public QObject, public pObject { + Q_OBJECT + +public: + Timer &timer; + QTimer *qtTimer; + + void setEnabled(bool enabled); + void setInterval(unsigned milliseconds); + + pTimer(Timer &timer) : timer(timer) {} + void constructor(); + +public slots: + void onTimeout(); +}; + struct pMessageWindow : public pObject { static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons); static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons); diff --git a/bsnes/phoenix/qt/timer.cpp b/bsnes/phoenix/qt/timer.cpp new file mode 100755 index 00000000..eba78b5a --- /dev/null +++ b/bsnes/phoenix/qt/timer.cpp @@ -0,0 +1,21 @@ +void pTimer::setEnabled(bool enabled) { + if(enabled) { + qtTimer->start(); + } else { + qtTimer->stop(); + } +} + +void pTimer::setInterval(unsigned milliseconds) { + qtTimer->setInterval(milliseconds); +} + +void pTimer::constructor() { + qtTimer = new QTimer; + qtTimer->setInterval(0); + connect(qtTimer, SIGNAL(timeout()), SLOT(onTimeout())); +} + +void pTimer::onTimeout() { + if(timer.onTimeout) timer.onTimeout(); +} diff --git a/bsnes/phoenix/reference/font.cpp b/bsnes/phoenix/reference/font.cpp index 9690c1d9..77d98f70 100755 --- a/bsnes/phoenix/reference/font.cpp +++ b/bsnes/phoenix/reference/font.cpp @@ -1,3 +1,7 @@ +Geometry pFont::geometry(const string &text) { + return { 0, 0, 0, 0 }; +} + void pFont::setBold(bool bold) { } diff --git a/bsnes/phoenix/reference/reference.cpp b/bsnes/phoenix/reference/reference.cpp index a70254b6..d2b04b8e 100755 --- a/bsnes/phoenix/reference/reference.cpp +++ b/bsnes/phoenix/reference/reference.cpp @@ -1,6 +1,7 @@ #include "reference.hpp" #include "font.cpp" +#include "timer.cpp" #include "message-window.cpp" #include "window.cpp" @@ -13,6 +14,7 @@ #include "widget/widget.cpp" #include "widget/button.cpp" +#include "widget/canvas.cpp" #include "widget/check-box.cpp" #include "widget/combo-box.cpp" #include "widget/hex-edit.cpp" diff --git a/bsnes/phoenix/reference/reference.hpp b/bsnes/phoenix/reference/reference.hpp index 5f8ebf59..6c48b171 100755 --- a/bsnes/phoenix/reference/reference.hpp +++ b/bsnes/phoenix/reference/reference.hpp @@ -29,6 +29,7 @@ struct pOS : public pObject { struct pFont : public pObject { Font &font; + Geometry geometry(const string &text); void setBold(bool bold); void setFamily(const string &family); void setItalic(bool italic); @@ -39,6 +40,16 @@ struct pFont : public pObject { void constructor(); }; +struct pTimer : public pObject { + Timer &timer; + + void setEnabled(bool enabled); + void setInterval(unsigned milliseconds); + + pTimer(Timer &timer) : timer(timer) {} + void constructor(); +}; + struct pMessageWindow : public pObject { static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons); static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons); @@ -136,6 +147,8 @@ struct pWidget : public pObject { Widget &widget; bool enabled(); + Font& font(); + Geometry minimumGeometry(); void setEnabled(bool enabled); void setFocused(); void setFont(Font &font); @@ -155,6 +168,16 @@ struct pButton : public pWidget { void constructor(); }; +struct pCanvas : public pWidget { + Canvas &canvas; + + uint32_t* buffer(); + void update(); + + pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {} + void constructor(); +}; + struct pCheckBox : public pWidget { CheckBox &checkBox; diff --git a/bsnes/phoenix/reference/timer.cpp b/bsnes/phoenix/reference/timer.cpp new file mode 100755 index 00000000..6cbe571a --- /dev/null +++ b/bsnes/phoenix/reference/timer.cpp @@ -0,0 +1,8 @@ +void pTimer::setEnabled(bool enabled) { +} + +void pTimer::setInterval(unsigned milliseconds) { +} + +void pTimer::constructor() { +} diff --git a/bsnes/phoenix/reference/widget/canvas.cpp b/bsnes/phoenix/reference/widget/canvas.cpp new file mode 100755 index 00000000..70295166 --- /dev/null +++ b/bsnes/phoenix/reference/widget/canvas.cpp @@ -0,0 +1,9 @@ +uint32_t* pCanvas::buffer() { + return 0; +} + +void pCanvas::update() { +} + +void pCanvas::constructor() { +} diff --git a/bsnes/phoenix/reference/widget/widget.cpp b/bsnes/phoenix/reference/widget/widget.cpp index 40387671..a7787587 100755 --- a/bsnes/phoenix/reference/widget/widget.cpp +++ b/bsnes/phoenix/reference/widget/widget.cpp @@ -2,6 +2,14 @@ bool pWidget::enabled() { return false; } +Font& pWidget::font() { + throw; +} + +Geometry pWidget::minimumGeometry() { + return { 0, 0, 0, 0 }; +} + void pWidget::setEnabled(bool enabled) { } diff --git a/bsnes/phoenix/windows/timer.cpp b/bsnes/phoenix/windows/timer.cpp new file mode 100755 index 00000000..8e2b3216 --- /dev/null +++ b/bsnes/phoenix/windows/timer.cpp @@ -0,0 +1,31 @@ +static linear_vector timers; + +static void CALLBACK Timer_timeoutProc(HWND hwnd, UINT msg, UINT_PTR timerID, DWORD time) { + foreach(timer, timers) { + if(timer->htimer == timerID) { + if(timer->timer.onTimeout) timer->timer.onTimeout(); + return; + } + } +} + +void pTimer::setEnabled(bool enabled) { + if(htimer) { + KillTimer(NULL, htimer); + htimer = 0; + } + + if(enabled == true) { + htimer = SetTimer(NULL, 0U, timer.state.milliseconds, Timer_timeoutProc); + } +} + +void pTimer::setInterval(unsigned milliseconds) { + //destroy and recreate timer if interval changed + setEnabled(timer.state.enabled); +} + +void pTimer::constructor() { + timers.append(this); + htimer = 0; +} diff --git a/bsnes/phoenix/windows/window.cpp b/bsnes/phoenix/windows/window.cpp index 1961b410..752bd0c1 100755 --- a/bsnes/phoenix/windows/window.cpp +++ b/bsnes/phoenix/windows/window.cpp @@ -36,8 +36,11 @@ Geometry pWindow::frameMargin() { Geometry pWindow::geometry() { Geometry margin = frameMargin(); - RECT rc; - GetWindowRect(hwnd, &rc); + + //note: GetWindowRect returns -32000(x),-32000(y) when window is minimized + WINDOWPLACEMENT wp; + GetWindowPlacement(hwnd, &wp); + RECT rc = wp.rcNormalPosition; signed x = rc.left + margin.x; signed y = rc.top + margin.y; diff --git a/bsnes/phoenix/windows/windows.cpp b/bsnes/phoenix/windows/windows.cpp index 4c3596a4..94b1497a 100755 --- a/bsnes/phoenix/windows/windows.cpp +++ b/bsnes/phoenix/windows/windows.cpp @@ -2,6 +2,7 @@ #include "object.cpp" #include "font.cpp" +#include "timer.cpp" #include "message-window.cpp" #include "window.cpp" diff --git a/bsnes/phoenix/windows/windows.hpp b/bsnes/phoenix/windows/windows.hpp index 70933131..76bace93 100755 --- a/bsnes/phoenix/windows/windows.hpp +++ b/bsnes/phoenix/windows/windows.hpp @@ -49,6 +49,17 @@ struct pFont : public pObject { void constructor(); }; +struct pTimer : public pObject { + Timer &timer; + UINT_PTR htimer; + + void setEnabled(bool enabled); + void setInterval(unsigned milliseconds); + + pTimer(Timer &timer) : timer(timer) {} + void constructor(); +}; + struct pMessageWindow : public pObject { static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons); static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons); diff --git a/bsnes/snes/ppu/background/background.cpp b/bsnes/snes/ppu/background/background.cpp index d654ceaf..cb3544cb 100755 --- a/bsnes/snes/ppu/background/background.cpp +++ b/bsnes/snes/ppu/background/background.cpp @@ -2,10 +2,16 @@ #include "mode7.cpp" +//V = 0, H = 0 void PPU::Background::frame() { } +//H = 0 void PPU::Background::scanline() { +} + +//H = 60 +void PPU::Background::begin() { bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); x = -7; y = self.vcounter(); @@ -13,20 +19,26 @@ void PPU::Background::scanline() { if(y == 1) { mosaic.vcounter = regs.mosaic + 1; mosaic.voffset = 1; - mosaic.vscroll = regs.voffset; - mosaic.hscroll = regs.hoffset; + cache.hoffset = regs.hoffset; + cache.voffset = regs.voffset; } else if(--mosaic.vcounter == 0) { mosaic.vcounter = regs.mosaic + 1; mosaic.voffset += regs.mosaic + 1; - mosaic.vscroll = regs.voffset; - mosaic.hscroll = regs.hoffset; + cache.hoffset = regs.hoffset; + cache.voffset = regs.voffset; } - tile_counter = (7 - (mosaic.hscroll & 7)) << hires; + tile_counter = (7 - (cache.hoffset & 7)) << hires; for(unsigned n = 0; n < 8; n++) data[n] = 0; mosaic.hcounter = regs.mosaic + 1; mosaic.hoffset = 0; + + if(regs.mode == Mode::Mode7) return begin_mode7(); + if(regs.mosaic == 0) { + cache.hoffset = regs.hoffset; + cache.voffset = regs.voffset; + } } void PPU::Background::get_tile() { @@ -53,8 +65,8 @@ void PPU::Background::get_tile() { unsigned px = x << hires; unsigned py = (regs.mosaic == 0 ? y : mosaic.voffset); - unsigned hscroll = mosaic.hscroll; - unsigned vscroll = mosaic.vscroll; + unsigned hscroll = cache.hoffset; + unsigned vscroll = cache.voffset; if(hires) { hscroll <<= 1; if(self.regs.interlace) py = (py << 1) + self.field(); @@ -67,8 +79,8 @@ void PPU::Background::get_tile() { uint16 offset_x = (x + (hscroll & 7)); if(offset_x >= 8) { - unsigned hval = self.bg3.get_tile((offset_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 0); - unsigned vval = self.bg3.get_tile((offset_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 8); + unsigned hval = self.bg3.get_tile((offset_x - 8) + (self.bg3.cache.hoffset & ~7), self.bg3.cache.voffset + 0); + unsigned vval = self.bg3.get_tile((offset_x - 8) + (self.bg3.cache.hoffset & ~7), self.bg3.cache.voffset + 8); unsigned valid_mask = (id == ID::BG1 ? 0x2000 : 0x4000); if(self.regs.bgmode == 4) { @@ -205,6 +217,9 @@ void PPU::Background::reset() { regs.hoffset = random(0x0000); regs.voffset = random(0x0000); + cache.hoffset = 0; + cache.voffset = 0; + output.main.palette = 0; output.main.priority = 0; output.sub.palette = 0; @@ -216,10 +231,8 @@ void PPU::Background::reset() { mosaic.vcounter = 0; mosaic.voffset = 0; - mosaic.vscroll = 0; mosaic.hcounter = 0; mosaic.hoffset = 0; - mosaic.hscroll = 0; x = 0; y = 0; diff --git a/bsnes/snes/ppu/background/background.hpp b/bsnes/snes/ppu/background/background.hpp index 86bd420d..26553af4 100755 --- a/bsnes/snes/ppu/background/background.hpp +++ b/bsnes/snes/ppu/background/background.hpp @@ -25,6 +25,11 @@ class Background { uint16 voffset; } regs; + struct Cache { + uint16 hoffset; + uint16 voffset; + } cache; + struct Output { struct Pixel { unsigned priority; //0 = none (transparent) @@ -36,10 +41,8 @@ class Background { struct Mosaic : Output::Pixel { unsigned vcounter; unsigned voffset; - unsigned vscroll; unsigned hcounter; unsigned hoffset; - unsigned hscroll; } mosaic; struct { @@ -56,6 +59,7 @@ class Background { void frame(); void scanline(); + void begin(); void run(bool screen); void reset(); @@ -63,6 +67,7 @@ class Background { unsigned get_tile_color(); unsigned get_tile(unsigned x, unsigned y); signed clip(signed n); + void begin_mode7(); void run_mode7(); void serialize(serializer&); diff --git a/bsnes/snes/ppu/background/mode7.cpp b/bsnes/snes/ppu/background/mode7.cpp index 8304f82e..bb630647 100755 --- a/bsnes/snes/ppu/background/mode7.cpp +++ b/bsnes/snes/ppu/background/mode7.cpp @@ -5,6 +5,12 @@ signed PPU::Background::clip(signed n) { return n & 0x2000 ? (n | ~1023) : (n & 1023); } +//H = 60 +void PPU::Background::begin_mode7() { + cache.hoffset = self.regs.mode7_hoffset; + cache.voffset = self.regs.mode7_voffset; +} + void PPU::Background::run_mode7() { signed a = sclip<16>(self.regs.m7a); signed b = sclip<16>(self.regs.m7b); @@ -13,8 +19,8 @@ void PPU::Background::run_mode7() { signed cx = sclip<13>(self.regs.m7x); signed cy = sclip<13>(self.regs.m7y); - signed hoffset = sclip<13>(self.regs.mode7_hoffset); - signed voffset = sclip<13>(self.regs.mode7_voffset); + signed hoffset = sclip<13>(cache.hoffset); + signed voffset = sclip<13>(cache.voffset); if(Background::x++ & ~255) return; unsigned x = mosaic.hoffset; diff --git a/bsnes/snes/ppu/ppu.cpp b/bsnes/snes/ppu/ppu.cpp index b4a8de4c..f8a65e15 100755 --- a/bsnes/snes/ppu/ppu.cpp +++ b/bsnes/snes/ppu/ppu.cpp @@ -39,6 +39,10 @@ void PPU::enter() { scanline(); add_clocks(60); + bg1.begin(); + bg2.begin(); + bg3.begin(); + bg4.begin(); if(vcounter() <= 239) { for(signed pixel = -7; pixel <= 255; pixel++) { diff --git a/bsnes/snes/ppu/serialization.cpp b/bsnes/snes/ppu/serialization.cpp index eaeb28d3..edf90f13 100755 --- a/bsnes/snes/ppu/serialization.cpp +++ b/bsnes/snes/ppu/serialization.cpp @@ -109,6 +109,9 @@ void PPU::Background::serialize(serializer &s) { s.integer(regs.hoffset); s.integer(regs.voffset); + s.integer(cache.hoffset); + s.integer(cache.voffset); + s.integer(output.main.priority); s.integer(output.main.palette); s.integer(output.main.tile); @@ -126,10 +129,8 @@ void PPU::Background::serialize(serializer &s) { s.integer(mosaic.vcounter); s.integer(mosaic.voffset); - s.integer(mosaic.vscroll); s.integer(mosaic.hcounter); s.integer(mosaic.hoffset); - s.integer(mosaic.hscroll); s.integer(tile_counter); s.integer(tile); diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 113e28b0..9848141f 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -1,7 +1,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "078.07"; + static const char Version[] = "079"; static const unsigned SerializerVersion = 20; } } diff --git a/snesfilter/2xSaI/2xSaI.cpp b/snesfilter/2xSaI/2xSaI.cpp index 5f5a21f2..d9dc61fa 100755 --- a/snesfilter/2xSaI/2xSaI.cpp +++ b/snesfilter/2xSaI/2xSaI.cpp @@ -28,5 +28,5 @@ dllexport void filter_render( } } - _2xSaI32((unsigned char*)temp, 1024, 0, (unsigned char*)output, outpitch, width, height); + _2xSaI32((unsigned char*)temp, width * sizeof(uint32_t), 0, (unsigned char*)output, outpitch, width, height); } diff --git a/snesfilter/2xSaI/Super-2xSaI.cpp b/snesfilter/2xSaI/Super-2xSaI.cpp index eea01528..267e11e5 100755 --- a/snesfilter/2xSaI/Super-2xSaI.cpp +++ b/snesfilter/2xSaI/Super-2xSaI.cpp @@ -28,5 +28,5 @@ dllexport void filter_render( } } - Super2xSaI32((unsigned char*)temp, 1024, 0, (unsigned char*)output, outpitch, width, height); + Super2xSaI32((unsigned char*)temp, width * sizeof(uint32_t), 0, (unsigned char*)output, outpitch, width, height); } diff --git a/snesfilter/2xSaI/Super-Eagle.cpp b/snesfilter/2xSaI/Super-Eagle.cpp index 1e89de1f..c548348c 100755 --- a/snesfilter/2xSaI/Super-Eagle.cpp +++ b/snesfilter/2xSaI/Super-Eagle.cpp @@ -28,5 +28,5 @@ dllexport void filter_render( } } - SuperEagle32((unsigned char*)temp, 1024, 0, (unsigned char*)output, outpitch, width, height); + SuperEagle32((unsigned char*)temp, width * sizeof(uint32_t), 0, (unsigned char*)output, outpitch, width, height); }