diff --git a/bsnes/data/cheats.xml b/bsnes/data/cheats.xml index 6784ccb8..949d894e 100755 --- a/bsnes/data/cheats.xml +++ b/bsnes/data/cheats.xml @@ -323,15 +323,15 @@ DFBD-87DD - Start with 62 - E0BD-84AD - DFBD-87DD - - - Start with 2 + Start with 2,000 gold 2DBD-84AD D5BD-87DD + + Start with 62,708 gold + E0BD-84AD + DFBD-87DD + A.S.P. - Air Strike Patrol (USA) @@ -1676,7 +1676,7 @@ 7E0064FF - Start with and keep Fezi-copter (disable after defeating a boss + Start with and keep Fezi-copter (disable after defeating a boss and land before password screen) 3CAD-A46D 60BA-6704 @@ -2163,355 +2163,355 @@ Aerobiz (USA) - In scenario 1 + In scenario 1, Tokyo starts with $649,280,000 DDA6-0DFD - In scenario 1 + In scenario 1, Tokyo starts with $7,202,880,000 D9A6-0DFD - In scenario 1 + In scenario 1, Beijing starts with $420,160,000 94A6-0D2D - In scenario 1 + In scenario 1, Beijing starts with $7,393,600,000 D9A6-0FFD - In scenario 1 + In scenario 1, Hong Kong starts with $449,440,000 95A6-0F2D - In scenario 1 + In scenario 1, Hong Kong starts with $7,453,600,000 D9A6-04FD - In scenario 1 + In scenario 1, Singapore starts with $400,640,000 03A6-042D - In scenario 1 + In scenario 1, Singapore starts with $7,353,600,000 D9A6-07FD - In scenario 1 + In scenario 1, Sydney starts with $297,920,000 7CA6-072D - In scenario 1 + In scenario 1, Sydney starts with $7,153,600,000 D9AB-0DFD - In scenario 1 + In scenario 1, Delhi starts with $317,440,000 73AB-0D2D - In scenario 1 + In scenario 1, Delhi starts with $7,193,600,000 D9AB-0FFD - In scenario 1 + In scenario 1, Tehran starts with $239,360,000 43AB-0F2D - In scenario 1 + In scenario 1, Tehran starts with $7,033,600,000 D9AB-04FD - In scenario 1 + In scenario 1, Cairo starts with $249,120,000 7DAB-042D - In scenario 1 + In scenario 1, Cairo starts with $7,053,600,000 D9AB-07FD - In scenario 1 + In scenario 1, Nairobi starts with $200,320,000 45AB-072D - In scenario 1 + In scenario 1, Nairobi starts with $6,953,600,000 D9AC-0DFD - In scenario 1 + In scenario 1, Lagos starts with $229,600,000 4AAC-0D2D - In scenario 1 + In scenario 1, Lagos starts with $7,013,600,000 D9AC-0FFD - In scenario 1 + In scenario 1, Moscow starts with $289,280,000 DDAC-04FD - In scenario 1 + In scenario 1, Moscow starts with $6,842,880,000 D9AC-04FD - In scenario 1 + In scenario 1, London starts with $949,280,000 DDAC-07FD - In scenario 1 + In scenario 1, London starts with $7,502,880,000 D9AC-07FD - In scenario 1 + In scenario 1, Paris starts with $289,280,000 DDA8-0DFD - In scenario 1 + In scenario 1, Paris starts with $6,842,880,000 D9A8-0DFD - In scenario 1 + In scenario 1, Rome starts with $371,360,000 06A8-0D2D - In scenario 1 + In scenario 1, Rome starts with $7,293,600,000 D9A8-0FFD - In scenario 1 + In scenario 1, New York starts with $189,280,000 DDA8-04FD - In scenario 1 + In scenario 1, New York starts with $6,742,880,000 D9A8-04FD - In scenario 1 + In scenario 1, Vancouver starts with $258,880,000 74A8-042D - In scenario 1 + In scenario 1, Vancouver starts with $7,073,600,000 D9A8-07FD - In scenario 1 + In scenario 1, Los Angeles starts with $649,280,000 DDAA-0DFD - In scenario 1 + In scenario 1, Los Angeles starts with $7,202,880,000 D9AA-0DFD - In scenario 1 + In scenario 1, Honolulu starts with $268,640,000 70AA-0D2D - In scenario 1 + In scenario 1, Honolulu starts with $7,093,600,000 D9AA-0FFD - In scenario 1 + In scenario 1, Mexico City starts with $258,880,000 74AA-0F2D - In scenario 1 + In scenario 1, Mexico City starts with $7,073,600,000 D9AA-04FD - In scenario 1 + In scenario 1, Lima starts with $180,800,000 47AA-042D - In scenario 1 + In scenario 1, Lima starts with $6,913,600,000 D9AA-07FD - In scenario 1 + In scenario 1, Rio de Janeiro starts with $317,440,000 73AA-072D - In scenario 1 + In scenario 1, Rio de Janeiro starts with $7,193,600,000 D9A2-0DFD - In scenario 1 + In scenario 1, Buenos Aires starts with $210,080,000 4BA2-0D2D - In scenario 1 + In scenario 1, Buenos Aires starts with $6,973,600,000 D9A2-0FFD - In scenario 2 + In scenario 2, Tokyo starts with $1,149,280,000 DDA2-04FD - In scenario 2 + In scenario 2, Tokyo starts with $7,702,880,000 D9A2-04FD - In scenario 2 + In scenario 2, Beijing starts with $498,240,000 1FA2-042D - In scenario 2 + In scenario 2, Beijing starts with $7,553,600,000 D9A2-07FD - In scenario 2 + In scenario 2, Hong Kong starts with $649,760,000 53A2-072D - In scenario 2 + In scenario 2, Hong Kong starts with $7,853,600,000 D9A3-0DFD - In scenario 2 + In scenario 2, Singapore starts with $552,160,000 18A3-0D2D - In scenario 2 + In scenario 2, Singapore starts with $7,653,600,000 D9A3-0FFD - In scenario 2 + In scenario 2, Sydney starts with $581,440,000 5FA3-0F2D - In scenario 2 + In scenario 2, Sydney starts with $7,713,600,000 D9A3-04FD - In scenario 2 + In scenario 2, Delhi starts with $517,760,000 19A3-042D - In scenario 2 + In scenario 2, Delhi starts with $7,593,600,000 D9A3-07FD - In scenario 2 + In scenario 2, Tehran starts with $297,920,000 7CA3-072D - In scenario 2 + In scenario 2, Tehran starts with $7,153,600,000 D9AE-0DFD - In scenario 2 + In scenario 2, Cairo starts with $390,880,000 0AAE-0D2D - In scenario 2 + In scenario 2, Cairo starts with $7,333,600,000 D9AE-0FFD - In scenario 2 + In scenario 2, Nairobi starts with $249,120,000 7DAE-0F2D - In scenario 2 + In scenario 2, Nairobi starts with $7,053,600,000 D9AE-04FD - In scenario 2 + In scenario 2, Lagos starts with $299,040,000 7CAE-042D - In scenario 2 + In scenario 2, Lagos starts with $7,149,600,000 D9AE-07FD - In scenario 2 + In scenario 2, Moscow starts with $689,280,000 DDAD-6DFD - In scenario 2 + In scenario 2, Moscow starts with $7,242,880,000 D9AD-6DFD - In scenario 2 + In scenario 2, London starts with $38,560,000 DDAD-6FFD - In scenario 2 + In scenario 2, London starts with $6,592,160,000 D9AD-6FFD - In scenario 2 + In scenario 2, Paris starts with $909,280,000 DDAD-64FD - In scenario 2 + In scenario 2, Paris starts with $7,462,880,000 D9AD-64FD - In scenario 2 + In scenario 2, Rome starts with $571,680,000 1EAD-642D - In scenario 2 + In scenario 2, Rome starts with $7,693,600,000 D9AD-67FD - In scenario 2 + In scenario 2, New York starts with $829,280,000 DDAF-6DFD - In scenario 2 + In scenario 2, New York starts with $7,382,880,000 D9AF-6DFD - In scenario 2 + In scenario 2, Vancouver starts with $420,160,000 94AF-6D2D - In scenario 2 + In scenario 2, Vancouver starts with $7,393,600,000 D9AF-6FFD - In scenario 2 + In scenario 2, Los Angeles starts with $1,109,280,000 DDAF-64FD - In scenario 2 + In scenario 2, Los Angeles starts with $7,662,880,000 D9AF-64FD - In scenario 2 + In scenario 2, Honolulu starts with $381,120,000 0CAF-642D - In scenario 2 + In scenario 2, Honolulu starts with $7,313,600,000 D9AF-67FD - In scenario 2 + In scenario 2, Mexico City starts with $468,960,000 98AF-672D - In scenario 2 + In scenario 2, Mexico City starts with $7,493,600,000 D9A4-6DFD - In scenario 2 + In scenario 2, Lima starts with $258,880,000 74A4-6D2D - In scenario 2 + In scenario 2, Lima starts with $7,073,600,000 D9A4-6FFD - In scenario 2 + In scenario 2, Rio de Janeiro starts with $630,240,000 58A4-6F2D - In scenario 2 + In scenario 2, Rio de Janeiro starts with $7,813,600,000 D9A4-64FD - In scenario 2 + In scenario 2, Buenos Aires starts with $361,600,000 01A4-642D - In scenario 2 + In scenario 2, Buenos Aires starts with $7,273,600,000 D9A4-67FD @@ -2519,195 +2519,195 @@ BDE3-D463 - Set money to less than $655 + Set money to less than $655,350,000 (must have Key) - P1, saved game 1 DDDF-FEDD - Set money to over $327 + Set money to over $327,680,000 (must have Key) - P1, saved game 1 D9DF-FEDD - Set money to over $5 + Set money to over $5,242,880,000 (must have Key) - P1, saved game 1 D6DF-FEDD - Set money to over $10 + Set money to over $10,485,760,000 (must have Key) - P1, saved game 1 FDDF-FEDD - Set money to over $20 + Set money to over $20,971,520,000 (must have Key) - P1, saved game 1 4DDF-FEDD - Set money to over $41 + Set money to over $41,943,040,000 (must have Key) - P1, saved game 1 0DDF-FEDD - Set money to less than $655 + Set money to less than $655,350,000 (must have Key) - P2, saved game 1 DDD9-FEDD - Set money to over $327 + Set money to over $327,680,000 (must have Key) - P2, saved game 1 D9D9-FEDD - Set money to over $5 + Set money to over $5,242,880,000 (must have Key) - P2, saved game 1 D6D9-FEDD - Set money to over $10 + Set money to over $10,485,760,000 (must have Key) - P2, saved game 1 FDD9-FEDD - Set money to over $20 + Set money to over $20,971,520,000 (must have Key) - P2, saved game 1 4DD9-FEDD - Set money to over $41 + Set money to over $41,943,040,000 (must have Key) - P2, saved game 1 0DD9-FEDD - Set money to less than $655 + Set money to less than $655,350,000 (must have Key) - P3, saved game 1 DDDB-FEDD - Set money to over $327 + Set money to over $327,680,000 (must have Key) - P3, saved game 1 D9DB-FEDD - Set money to over $5 + Set money to over $5,242,880,000 (must have Key) - P3, saved game 1 D6DB-FEDD - Set money to over $10 + Set money to over $10,485,760,000 (must have Key) - P3, saved game 1 FDDB-FEDD - Set money to over $20 + Set money to over $20,971,520,000 (must have Key) - P3, saved game 1 4DDB-FEDD - Set money to over $41 + Set money to over $41,943,040,000 (must have Key) - P3, saved game 1 0DDB-FEDD - Set money to less than $655 + Set money to less than $655,350,000 (must have Key) - P4, saved game 1 DDD2-FEDD - Set money to over $327 + Set money to over $327,680,000 (must have Key) - P4, saved game 1 D9D2-FEDD - Set money to over $5 + Set money to over $5,242,880,000 (must have Key) - P4, saved game 1 D6D2-FEDD - Set money to over $10 + Set money to over $10,485,760,000 (must have Key) - P4, saved game 1 FDD2-FEDD - Set money to over $20 + Set money to over $20,971,520,000 (must have Key) - P4, saved game 1 4DD2-FEDD - Set money to over $41 + Set money to over $41,943,040,000 (must have Key) - P4, saved game 1 0DD2-FEDD - Set money to less than $655 + Set money to less than $655,350,000 (must have Key) - P1, saved game 2 DDFF-FEDD - Set money to over $327 + Set money to over $327,680,000 (must have Key) - P1, saved game 2 D9FF-FEDD - Set money to over $5 + Set money to over $5,242,880,000 (must have Key) - P1, saved game 2 D6FF-FEDD - Set money to over $10 + Set money to over $10,485,760,000 (must have Key) - P1, saved game 2 FDFF-FEDD - Set money to over $20 + Set money to over $20,971,520,000 (must have Key) - P1, saved game 2 4DFF-FEDD - Set money to over $41 + Set money to over $41,943,040,000 (must have Key) - P1, saved game 2 0DFF-FEDD - Set money to less than $655 + Set money to less than $655,350,000 (must have Key) - P2, saved game 2 DDF9-FEDD - Set money to over $327 + Set money to over $327,680,000 (must have Key) - P2, saved game 2 D9F9-FEDD - Set money to over $5 + Set money to over $5,242,880,000 (must have Key) - P2, saved game 2 D6F9-FEDD - Set money to over $10 + Set money to over $10,485,760,000 (must have Key) - P2, saved game 2 FDF9-FEDD - Set money to over $20 + Set money to over $20,971,520,000 (must have Key) - P2, saved game 2 4DF9-FEDD - Set money to over $41 + Set money to over $41,943,040,000 (must have Key) - P2, saved game 2 0DF9-FEDD - Set money to less than $655 + Set money to less than $655,350,000 (must have Key) - P3, saved game 2 DDFB-FEDD - Set money to over $327 + Set money to over $327,680,000 (must have Key) - P3, saved game 2 D9FB-FEDD - Set money to over $5 + Set money to over $5,242,880,000 (must have Key) - P3, saved game 2 D6FB-FEDD - Set money to over $10 + Set money to over $10,485,760,000 (must have Key) - P3, saved game 2 FDFB-FEDD - Set money to over $20 + Set money to over $20,971,520,000 (must have Key) - P3, saved game 2 4DFB-FEDD - Set money to over $41 + Set money to over $41,943,040,000 (must have Key) - P3, saved game 2 0DFB-FEDD - Set money to less than $655 + Set money to less than $655,350,000 (must have Key) - P4, saved game 2 DDF2-FEDD - Set money to over $327 + Set money to over $327,680,000 (must have Key) - P4, saved game 2 D9F2-FEDD - Set money to over $5 + Set money to over $5,242,880,000 (must have Key) - P4, saved game 2 D6F2-FEDD - Set money to over $10 + Set money to over $10,485,760,000 (must have Key) - P4, saved game 2 FDF2-FEDD - Set money to over $20 + Set money to over $20,971,520,000 (must have Key) - P4, saved game 2 4DF2-FEDD - Set money to over $41 + Set money to over $41,943,040,000 (must have Key) - P4, saved game 2 0DF2-FEDD @@ -2759,7 +2759,7 @@ 7E036999 - Level select on main menu (use R + up/down to change level + Level select on main menu (use R + up/down to change level, R + left/right to change sub-level) DDB5-3467 DDBA-3FA7 @@ -2927,19 +2927,19 @@ 3C22-3D64 - Less ammo in rifle clips (works with extra clips only + Less ammo in rifle clips (works with extra clips only, not the ones you start with) 742A-44A4 - More ammo in rifle clips (works with extra clips only + More ammo in rifle clips (works with extra clips only, not the ones you start with) CD2A-44A4 - Less ammo in grenade clips (works with extra clips only + Less ammo in grenade clips (works with extra clips only, not the ones you start with) D923-3D64 - More ammo in grenade clips (works with extra clips only + More ammo in grenade clips (works with extra clips only, not the ones you start with) F023-3D64 @@ -3023,7 +3023,7 @@ C236-0DDD - No damage taken from jumping attacks + No damage taken from jumping attacks, tail attacks, rushes C238-0FDD @@ -3337,16 +3337,27 @@ 839011FF - Moon-jump (enable to rise slowly + Moon-jump (enable to rise slowly, disable to fall back down) 7E0415FF Arcade's Greatest Hits - The Atari Collection 1 (USA) + + Asteroids - Invincibility + 1D63-34AE + Asteroids - Infinite lives - both players 896E-3D6E + + Battlezone - Invincibility + ADB3-4FF9 + DDB3-4F99 + 2DB3-4FB9 + 1DBF-4D95 + Battlezone - Infinite lives C9BE-47B9 @@ -3391,7 +3402,7 @@ 828B-AF2E - Start with 60 + Start with 60,000 gold pieces 1D69-AFD0 3C69-AF00 @@ -4019,7 +4030,7 @@ BASS Masters Classic - Pro Edition (USA) - Start with $65 + Start with $65,380 EE40-BA86 @@ -4363,7 +4374,7 @@ FDA9-1DA7 - Once charged + Once charged, weapon always stays charged 1DAA-3FAF @@ -4500,7 +4511,7 @@ 8286-CF01 - Infinite lives - both players (except level 2 + Infinite lives - both players (except level 2, does not work on falling) 8986-CF01 @@ -4691,7 +4702,7 @@ Beauty and the Beast (USA) - Invincibility (disable to pick up rocks + Invincibility (disable to pick up rocks, spikes still do damage) 3CC0-376A 3CC0-37AA @@ -4957,7 +4968,7 @@ Bill Laimbeer's Combat Basketball (USA) - 2-point shots worth 3 + 2-point shots worth 3, 3-point shots worth 4 76BF-A4AF @@ -5002,15 +5013,15 @@ D0B4-67DF - Start with $65 + Start with $65,296 instead of $10,000 EEC5-6F16 - Start with $8 + Start with $8,398,608 6DC5-64C6 - Start with $16 + Start with $16,721,680 EEC5-64C6 @@ -5118,7 +5129,7 @@ 7E0FC518 - Infinite items (enable after obtaining first item + Infinite items (enable after obtaining first item, disable before getting next item, repeat this process) 89C6-1FD4 @@ -5447,7 +5458,7 @@ 7E08DD00 - Move faster + Move faster, same effect as wearing the Cloak 7E08D407 @@ -6075,7 +6086,7 @@ 3CC2-6F6D - One hit kills on enemies + One hit kills on enemies, except bosses 6D68-DFFF @@ -6094,7 +6105,7 @@ Brandish (USA) - Have over 10 + Have over 10,000,000 gold FD53-A3D7 @@ -7792,6 +7803,18 @@ Caravan Shooting Collection (Japan) + + Hector 87 - Infinite health + 7E00E510 + + + Hector 87 - Infinite lives + 7E00E402 + + + Star Force - Invincibility + 7E09CA01 + Star Force - Always have powered-up weapon 7E099E01 @@ -7824,14 +7847,6 @@ Star Soldier - No enemies except bosses 7E062E00 - - Hector 87 - Infinite health - 7E00E510 - - - Hector 87 - Infinite lives - 7E00E402 - Carrier Aces (USA) @@ -8314,7 +8329,7 @@ C256-E536 - Enable Blob's Bomb move (away + Enable Blob's Bomb move (away, away+down, down, towards+down, towards, punch) 6280-DD6F @@ -9118,7 +9133,7 @@ 22B8-0766 - Enable 30 and 99 lives in option menu (99 actually gives 35 + Enable 30 and 99 lives in option menu (99 actually gives 35,081 lives) D987-AFA4 @@ -9184,6 +9199,14 @@ B961-07D9 F361-0709 + + Enable stage select + 40CC-67DF + + + Enable stage select (alt) + 7E1E6001 + Start with 5 bombs on each life (side-view levels) D9BB-AFA1 @@ -9787,7 +9810,7 @@ DDA8-4466 - Extra lives cost $1 + Extra lives cost $1,500 DFA8-4466 @@ -9891,19 +9914,19 @@ 45B4-C404 - Start with $2 + Start with $2,500 D4BD-C7D4 - Start with $3 + Start with $3,500 D7BD-C7D4 - Start with $9 + Start with $9,500 DBBD-C7D4 - Start with $30 + Start with $30,500 7DBD-C7D4 @@ -10354,7 +10377,7 @@ 7E1E3914 - Have all Powers + Have all Powers, Crests, Talismen, Jewels, can hold 5 Spells/Potions 7E1E51FF 7E1E52FF 7E1E53FF @@ -10759,17 +10782,17 @@ D764-64D1 - Armor starts at 1 + Armor starts at 1,112 D0BC-64A9 D064-64D1 - Armor starts at 2 + Armor starts at 2,136 D6BC-64A9 D664-64D1 - Armor starts at 5 + Armor starts at 5,208 F0BC-64A9 F064-64D1 @@ -10806,15 +10829,15 @@ D438-6D0F - Guns start at 2 + Guns start at 2,458 rounds remaining DB38-6D0F - Guns start at 5 + Guns start at 5,018 rounds remaining F738-6D0F - Guns start at 9 + Guns start at 9,882 rounds remaining 4138-6D0F @@ -11224,15 +11247,15 @@ DDB0-34A4 - Bad buddy code (In 2P team mode + Bad buddy code (In 2P team mode, the inactive player can press select to gain control) DD88-CE5A - Both Kongs return (get both Kongs back on map screen after dying + Both Kongs return (get both Kongs back on map screen after dying, doesn't work when you fall off the screen) D76C-327E - Return of Kong (when your last Kong gets hit + Return of Kong (when your last Kong gets hit, the other one returns (reset if you get stuck). Must have had both Kongs at some point). EE66-C27E @@ -11329,15 +11352,15 @@ DDB9-3764 - Bad buddy code (In 2P team mode + Bad buddy code (In 2P team mode, the inactive player can press select to gain control) DD82-CEEA - Both Kongs return (get both Kongs back on map screen after dying + Both Kongs return (get both Kongs back on map screen after dying, doesn't work when you fall off the screen) D76C-337E - Return of Kong (when your last Kong gets hit + Return of Kong (when your last Kong gets hit, the other one returns (reset if you get stuck). Must have had both Kongs at some point). EE66-C37E @@ -11472,20 +11495,20 @@ DDB0-34A4 - Bad buddy code (In 2P team mode + Bad buddy code (In 2P team mode, the inactive player can press select to gain control) DD8B-C28A - Bad buddy code (In 2P team mode + Bad buddy code (In 2P team mode, the inactive player can press select to gain control) (alt) DD8B-C28A DD88-CE5A - Both Kongs return (get both Kongs back on map screen after dying + Both Kongs return (get both Kongs back on map screen after dying, doesn't work when you fall off the screen) D76B-337E - Return of Kong (when your last Kong gets hit + Return of Kong (when your last Kong gets hit, the other one returns (reset if you get stuck). Must have had both Kongs at some point). EE65-C37E @@ -12083,7 +12106,7 @@ 6DB2-A46D - On normal level + On normal level, start with all stats at 2 bars instead of 0 D9B9-64DD @@ -12151,7 +12174,7 @@ DDB7-AFAD - You can heal completely + You can heal completely, not just to the top of each segment DD83-D4AF @@ -12562,7 +12585,7 @@ DDCE-C7DC - One-hit kills + One-hit kills, except skeletons 8F23-3768 @@ -12601,7 +12624,7 @@ Dual Orb II (Japan) - Gain 65 + Gain 65,535 EXP from each battle CEF7-8F9F A8F7-84FF @@ -13159,7 +13182,7 @@ 7E9A1C27 - Fast money (buy a bread w/the code off + Fast money (buy a bread w/the code off, turn code on and sell it for $32,646) EE9A-E5F5 @@ -13303,15 +13326,15 @@ 7E512A07 - Start on Buttville + Start on Buttville, Part 2 7E512A08 - Start on Buttville + Start on Buttville, Part 1 7E512A09 - Start on Level 5 + Start on Level 5, Part 1 7E512A0A @@ -13319,7 +13342,7 @@ 7E512A0B - Start on Level 5 + Start on Level 5, Part 2 7E512A0C @@ -13331,47 +13354,47 @@ 7E512A0E - Start on Andy Asteroids? + Start on Andy Asteroids?, Course 1 7E512A0F - Start on Andy Asteroids? + Start on Andy Asteroids?, Course 2 7E512A10 - Start on Andy Asteroids? + Start on Andy Asteroids?, Course 3 7E512A11 - Start on Andy Asteroids? + Start on Andy Asteroids?, Course 4 7E512A12 - Start on Andy Asteroids? + Start on Andy Asteroids?, Course 5 7E512A13 - Start on Andy Asteroids? + Start on Andy Asteroids?, Course 6 7E512A14 - Start on Who Turned Out The Light? + Start on Who Turned Out The Light?, Part 1 7E512A15 - Start on Who Turned Out The Light? + Start on Who Turned Out The Light?, Part 2 7E512A16 - Start on Who Turned Out The Light? + Start on Who Turned Out The Light?, Part 3 7E512A17 - Start on Who Turned Out The Light? + Start on Who Turned Out The Light?, Part 4 7E512A18 - Start on Who Turned Out The Light? + Start on Who Turned Out The Light?, Part 5 7E512A19 @@ -13648,15 +13671,15 @@ 3CA2-AD96 - Pick a lawful + Pick a lawful, human male fighter and he will be at level 6 D18B-A474 - Pick a lawful + Pick a lawful, human male fighter and he will be at Level 8 D68B-A474 - 999 + 999,999 EXP 1st class 7E05333F 7E053442 7E05350F @@ -13794,31 +13817,31 @@ BA26-A44F - Start with $5 + Start with $5,240 3C26-AF4F CB26-AF1F D426-AF3F - Start with $20 + Start with $20,600 3C26-AF4F CB26-AF1F D626-AF3F - Start with $163 + Start with $163,960 3C26-AF4F CB26-AF1F 0D26-AF3F - Start with $327 + Start with $327,800 3C26-AF4F CB26-AF1F 6D26-AF3F - Start with $652 + Start with $652,920 3C26-AF4F CB26-AF1F EE26-AF3F @@ -14336,7 +14359,7 @@ D77E-7FDD - Computer can't win a round + Computer can't win a round, except last round, game ends after 4 rounds C250-7FA7 @@ -14433,7 +14456,7 @@ 83AF-D40D - Use a cure + Use a cure, gain a cure E3AF-D40D @@ -14464,7 +14487,7 @@ Final Fantasy - Mystic Quest (USA) - Infinite life points (can make enemies invincible + Infinite life points (can make enemies invincible, disable to defeat them) C96B-64AB @@ -14480,7 +14503,7 @@ C9B0-D7A6 - Use a cure + Use a cure, gain a cure E3AF-D40D @@ -14499,11 +14522,11 @@ Final Fantasy II (USA) (Rev 1) - Almost infinite HP (can make big and sometimes normal monsters invincible + Almost infinite HP (can make big and sometimes normal monsters invincible, disable to defeat them) 82AE-6F63 - Infinite MP during battles + Infinite MP during battles, doesn't work on twin attacks 8267-0D62 @@ -14576,16 +14599,16 @@ 3335-076E - Get at least 65 + Get at least 65,536 GP after each battle 3336-0FAE - Get 65 + Get 65,000+ exp points after each battle 7E3592FF 7E359EFF - Get 99 of items that you are given or find in a pot + Get 99 of items that you are given or find in a pot, treasure chest, ect 17BF-D404 @@ -14887,11 +14910,11 @@ Final Fantasy II (USA) - Almost infinite HP (can make big and sometimes normal monsters invincible + Almost infinite HP (can make big and sometimes normal monsters invincible, disable to defeat them) 82A3-6F63 - Infinite MP during battles + Infinite MP during battles, doesn't work on twin attacks 8267-0D62 @@ -14934,15 +14957,15 @@ DA6E-6FD4 - When treasures are awarded after battle + When treasures are awarded after battle, receive 5 instead of 1 D926-D4D9 - When arrows are awarded after battle + When arrows are awarded after battle, receive 50 instead of 10 7425-D769 - When treasures are awarded after battle + When treasures are awarded after battle, receive the rarest D734-0DDE @@ -14978,11 +15001,11 @@ 3C39-07AE - Get at least 65 + Get at least 65,536 GP after each battle 3335-0D6E - Get 99 of items that you are given or find in a pot + Get 99 of items that you are given or find in a pot, treasure chest, ect 17BF-D404 @@ -15026,7 +15049,7 @@ AFB5-DD83 - Get 65 + Get 65,000+ exp points after each battle 7E3592FF 7E359EFF @@ -15319,7 +15342,7 @@ E613-5117 - Auto cast Float + Auto cast Float, Regen, Haste, Shell, Safe and Rflect 3813-51C7 @@ -16312,7 +16335,7 @@ E613-5117 - Auto Cast Float + Auto Cast Float, Regen, Haste, Shell, Safe and Rflect 3813-51C7 @@ -17316,7 +17339,7 @@ DDC9-AFD0 - Enemies never get knocked down + Enemies never get knocked down, hit them until they die 7E0D7000 @@ -17588,7 +17611,7 @@ D433-0D6F - Enemies never get knocked down + Enemies never get knocked down, hit them until they die 7E0D7000 @@ -17882,12 +17905,12 @@ 7E007209 - Infinite Axe + Infinite Axe, Dagger, Grendade (slot 2 item) C9B6-6700 C9BE-6D00 - Infinite Axe + Infinite Axe, Dagger, Grendade (slot 2 item) (alt) 7E007399 @@ -18083,7 +18106,7 @@ DD79-5F0B - Enemies start with 1 HP (If enabled when starting a new game + Enemies start with 1 HP (If enabled when starting a new game, die, or finish the game, you'll restart with 1 HP. When you gain a level it should correct itself.) DD7D-770C CE7D-776C FF7D-77AC @@ -18196,12 +18219,12 @@ DD6D-1FB2 - Always have Starmine Bombs (if you have none + Always have Starmine Bombs (if you have none, fire 3 off) DDB5-3FFD D42F-1F47 - Always get Rank S for dungeons + Always get Rank S for dungeons, regardless of time taken BA2B-3FC4 @@ -18428,7 +18451,7 @@ 7E035002 - Infinite Konami code use (up + Infinite Konami code use (up, up, down, down, left, right, left, right, B, A) C2A9-0DDD @@ -18988,11 +19011,11 @@ 3C68-3706 - With 1 or more wood + With 1 or more wood, take some to get 999 6D87-CFDA - With 0 wood + With 0 wood, take some to get 999 F987-CDDA @@ -19021,7 +19044,7 @@ DD21-DFD4 - Infinite Baseballs + Infinite Baseballs, Slingshot and Rifle ammo DD2A-A76F @@ -19657,7 +19680,7 @@ Imperium (USA) - Invincibility against lesser robots + Invincibility against lesser robots, weapons and lasers 1D34-D4A1 1DC3-DDF7 @@ -19948,7 +19971,7 @@ 7EF0C4FF - Start with 50 + Start with 50,000 gold A0ED-D460 @@ -20340,37 +20363,37 @@ D7AC-6D6D - Start on level 3 + Start on level 3, part 2 CBAB-67AD D0AC-6DDD 6DAC-6D0D - Start on level 3 + Start on level 3, part 3 CBAB-67AD D5AC-6DDD 6DAC-6D0D - Start on level 5 + Start on level 5, part 2 CBAB-67AD D9AC-6DDD 6DAC-6D0D - Start on level 5 + Start on level 5, part 3 CBAB-67AD D6AC-6DDD 6DAC-6D0D - Start on level 7 + Start on level 7, part 2 CBAB-67AD D1AC-6DDD 6DAC-6D0D - Start on level 7 + Start on level 7, part 3 CBAB-67AD DBAC-6DDD 6DAC-6D0D @@ -23806,47 +23829,47 @@ D42D-6D6C - Start with 1 + Start with 1,380 gold D92D-6D6C - Start with 2 + Start with 2,148 gold D62D-6D6C - Start with 8 + Start with 8,292 gold 4D2D-6D6C - Start with 22 + Start with 22,116 gold 912D-6D6C - Start with 65 + Start with 65,380 gold EE2D-6D6C - Start on level 2 + Start on level 2, MP = 8/8, HP = 17/17, EXP = 0/40 D422-040C - Start on level 3 + Start on level 3, MP = 10/10, HP = 23/23, EXP = 0/90 D722-040C - Start on level 4 + Start on level 4, MP = 12/12, HP = 28/28, EXP = 0/170 D022-040C - Start on level 5 + Start on level 5, MP = 19/19, HP =36/36, EXP = 0/280 D922-040C - Start on level 241 + Start on level 241, HP = 255, MP = 255, EXP = 22859, walk at a regular speed EF22-040C - Start on level 242 + Start on level 242, HP = 220, MP = 221, EXP = 30560, walk at a medium speed E422-040C @@ -23913,17 +23936,17 @@ D169-443B - Start with $128 + Start with $128,000 DD6E-440D D96E-446D - Start with $88 + Start with $88,000 5D6E-440D D76E-446D - Start with $12 + Start with $12,800 6D6E-440D @@ -23997,7 +24020,7 @@ 40BE-1DAD - After you die + After you die, your main weapon is fully powered up from then on D0B5-CDAD CBB5-CD6D @@ -24339,7 +24362,7 @@ D7D9-F38B - Trigger doors are open (works with most dungeon doors + Trigger doors are open (works with most dungeon doors, some that even look closed) EED6-BE5B @@ -24535,7 +24558,7 @@ 7EF365FF - Have all Maps + Have all Maps, Compasses and Big Keys EEE1-2276 EEE1-2256 EEE1-2286 @@ -25555,7 +25578,7 @@ DAC2-848B - Lighter gravity effect (disable right after pressing start + Lighter gravity effect (disable right after pressing start, don't enable until first game play screen) 0DCA-5D5B @@ -25841,7 +25864,7 @@ DF3C-0D18 - Immune to all petrifying effects (stone + Immune to all petrifying effects (stone, poison, confused, etc) 6D8F-0DC4 @@ -28948,7 +28971,7 @@ EEEB-17A1 - Gain 35 + Gain 35,000 gold after a battle EEED-4F05 @@ -29474,67 +29497,67 @@ DBAA-5D0F - TD + TD, FG, PAT, S worth 1 point - home team CBA2-8F6D DFA2-8FAD - TD + TD, FG, PAT, S worth 3 points - home team CBA2-8F6D D7A2-8FAD - TD + TD, FG, PAT, S worth 5 points - home team CBA2-8F6D D9A2-8FAD - TD + TD, FG, PAT, S worth 7 points - home team CBA2-8F6D D5A2-8FAD - TD + TD, FG, PAT, S worth 14 points - home team CBA2-8F6D D3A2-8FAD - TD + TD, FG, PAT, S worth 21 points - home team CBA2-8F6D F9A2-8FAD - TD + TD, FG, PAT, S worth 35 points - home team CBA2-8F6D 47A2-8FAD - TD + TD, FG, PAT, S worth 3 points - visitor CBAD-ED0D DFAD-ED6D - TD + TD, FG, PAT, S worth 5 points - visitor CBAD-ED0D D9AD-ED6D - TD + TD, FG, PAT, S worth 7 points - visitor CBAD-ED0D D5AD-ED6D - TD + TD, FG, PAT, S worth 14 points - visitor CBAD-ED0D D3AD-ED6D - TD + TD, FG, PAT, S worth 21 points - visitor CBAD-ED0D F9AD-ED6D - TD + TD, FG, PAT, S worth 35 points - visitor CBAD-ED0D 47AD-ED6D @@ -29823,7 +29846,7 @@ 7E042D09 - Set score to 90 + Set score to 90,000,000 7E044809 @@ -30230,7 +30253,7 @@ B354-E4D8 - Infinite equipment + Infinite equipment, all Gems selectable on pick-up FA85-7464 6D85-7704 FE85-7764 @@ -30460,27 +30483,27 @@ 3CED-34B7 - Start with 100 + Start with 100,000 C-bills 103E-C4AD - Start with 250 + Start with 250,000 C-bills EC3E-C4AD - Start with 562 + Start with 562,000 C-bills D43E-C7DD - Start with 1 + Start with 1,074,000 C-bills D03E-C7DD - Start with 5 + Start with 5,170,000 C-bills F03E-C7DD - Start with 10 + Start with 10,290,000 C-bills 463E-C7DD @@ -30541,12 +30564,12 @@ 1000-7998 - Machine Gun starts at 1 + Machine Gun starts at 1,000 D700-79B8 3600-7998 - Machine Gun starts at 10 + Machine Gun starts at 10,000 4100-79B8 FD00-7998 @@ -30568,12 +30591,12 @@ DD00-75F8 - Large Laser starts at 1 + Large Laser starts at 1,000 3600-7128 D700-75F8 - Large Laser starts at 10 + Large Laser starts at 10,000 FD00-7128 4100-75F8 @@ -30973,7 +30996,7 @@ 7E1FB309 - Have Shouryuken (F + Have Shouryuken (F, D, DF + Fire) (must have max health and health containers) 7E1FB180 @@ -31190,7 +31213,7 @@ C2AD-4D65 - Infinite ammo for all weapons (to change weapons + Infinite ammo for all weapons (to change weapons, turn code off, pick up new weapon, turn back on) C926-C7A1 @@ -31682,7 +31705,7 @@ D468-0DBF - Zach moves faster + Zach moves faster, but the wrong way EE62-04BF @@ -31716,29 +31739,29 @@ Monopoly (USA) (Rev 1) - Land + Land, rent and some other things are free - all players 1D85-6FDF - Land + Land, rent and some other things are $50 - all players 3B85-6FDF 7485-6F0F DD85-6F6F - Land + Land, rent and some other things are $100 - all players 3B85-6FDF 1085-6F0F DD85-6F6F - Land + Land, rent and some other things are $200 - all players 3B85-6FDF A685-6F0F DD85-6F6F - Land + Land, rent and some other things are $500 - all players 3B85-6FDF E085-6F0F DD85-6F6F @@ -31815,29 +31838,29 @@ Monopoly (USA) - Land + Land, rent and some other things are free - all players 1D85-6FDF - Land + Land, rent and some other things are $50 - all players 3B85-6FDF 7485-6F0F DD85-6F6F - Land + Land, rent and some other things are $100 - all players 3B85-6FDF 1085-6F0F DD85-6F6F - Land + Land, rent and some other things are $200 - all players 3B85-6FDF A685-6F0F DD85-6F6F - Land + Land, rent and some other things are $500 - all players 3B85-6FDF E085-6F0F DD85-6F6F @@ -32230,47 +32253,47 @@ 0823-19C4 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's High Punch do more damage F328-3934 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's Low Punch do more damage F32A-3044 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's High Kick do more damage 062E-39C4 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's Low Kick do more damage 062E-3534 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's Head Blow do more damage 7A22-30C4 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's Knee do more damage 062A-3114 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's Crouched Kick do more damage F62F-41C7 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's Uppercut do more damage 562C-35C4 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's Roundhouse Kick do more damage 1D2F-4017 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's Foot Sweep do more damage 7A2D-4147 - Scorpion's + Scorpion's, Sub-Zero's and Reptile's Flying Punch do more damage 0823-3944 @@ -32343,32 +32366,32 @@ DD6A-47AF - After 1st match + After 1st match, almost always fight at the Palace Gates CB6A-44AF DF6A-47DF - After 1st match + After 1st match, almost always fight in the Warrior Shrine CB6A-44AF D46A-47DF - After 1st match + After 1st match, almost always fight in the Pit CB6A-44AF D76A-47DF - After 1st match + After 1st match, almost always fight in the Throne Room CB6A-44AF D06A-47DF - After 1st match + After 1st match, almost always fight in Goro's Lair CB6A-44AF D96A-47DF - After 1st match + After 1st match, almost always fight in the bottom of the pit (screen says Goro's Lair) CB6A-44AF D16A-47DF @@ -32976,11 +32999,11 @@ NBA All-Star Challenge (USA) - P1 can't score in the 1-on-1 + P1 can't score in the 1-on-1, free throw or tournament stages 123B-3F0D - P2 or computer can't score in the 1-on-1 + P2 or computer can't score in the 1-on-1, free throw or tournament events A238-340D @@ -33090,35 +33113,35 @@ 41E5-F47D - Have Power Push + Have Power Push, Powered Up 3pts, Infinite Turbo, Always On Fire, Super Dunks, Max Power, Powered Up Goal Tending and Quick Hands - P1 EEEA-1FDC - Have Power Block + Have Power Block, Powered Up 3pts, Infinite Turbo, Always On Fire, Super Dunks, Max Power, Powered Up Goal Tending and Quick Hands - P2 EEE1-C46C - Have Power Block + Have Power Block, Powered Up 3pts, Infinite Turbo, Always On Fire, Super Dunks, Max Power, Powered Up Goal Tending and Quick Hands - P3 EEEF-3DDC - Have Power Block + Have Power Block, Powered Up 3pts, Infinite Turbo, Always On Fire, Super Dunks, Max Power, Powered Up Goal Tending and Quick Hands - P4 EEE8-3F6C - Have Power-up offense + Have Power-up offense, Speed Up, block opponent to make both fall, Teleport Pass and High Shots - P1 EEEA-1F0C - Have Power-up offense + Have Power-up offense, Speed Up, block opponent to make both fall, Teleport Pass and High Shots - P2 EEE1-C4AC - Have Power-up offense + Have Power-up offense, Speed Up, block opponent to make both fall, Teleport Pass and High Shots - P3 EEEF-3D0C - Have Power-up offense + Have Power-up offense, Speed Up, block opponent to make both fall, Teleport Pass and High Shots - P4 EEE8-3FAC @@ -34017,12 +34040,12 @@ DB34-A767 - P1 shots worth 1 extra point (2-pt. shots worth 3 + P1 shots worth 1 extra point (2-pt. shots worth 3, 3-pt. shots worth 4) 76BA-A404 76B9-6FA7 - P2 shots worth 1 extra point (2-pt. shots worth 3 + P2 shots worth 1 extra point (2-pt. shots worth 3, 3-pt. shots worth 4) 76B0-64A7 76B8-A704 @@ -34102,7 +34125,7 @@ EC67-CF64 - Visitor scores 1 point for goals + Visitor scores 1 point for goals, Home scores 3 1BA1-4D01 @@ -34949,7 +34972,7 @@ DD2F-AFF4 - View 'Edit Units' screen to give everyone 2778 max HP (2000 of it won't be visible + View 'Edit Units' screen to give everyone 2778 max HP (2000 of it won't be visible, and you won't get your HP restored. It will go down to 999 max HP if it tries to update the amount) CBE7-A70C B2E0-AD6C 2CE0-ADAC @@ -35873,19 +35896,19 @@ EEE6-673F - Chezni starts with 40 Power + Chezni starts with 40 Power, 42 Attack 46EB-6D3F - Chezni starts with 60 Power + Chezni starts with 60 Power, 62 Attack 7AEB-6D3F - Chezni starts with 42 Defense + Chezni starts with 42 Defense, 30 Endurance F3EB-6F3F - Chezni starts with 72 Defense + Chezni starts with 72 Defense, 60 Endurance 7AEB-6F3F @@ -36177,6 +36200,10 @@ D131-4F0D 5331-4F6D + + One hit kills + 102C-C7D3 + PGA Tour Golf (USA) @@ -36297,11 +36324,11 @@ DD63-DD04 - After losing a life automatically finish level + After losing a life automatically finish level, gain 99 lives and retain all power-ups 00D83AAD - Once power-up has been obtained + Once power-up has been obtained, it is not lost until you continue (doesn't work for weapon, only power-ups) C229-D7A4 @@ -36557,6 +36584,13 @@ Infinite lives C280-1F6F + + One hit kills + 3CAF-3DAF + 3CAF-3FDF + CBAF-3F0F + 5EAF-3F6F + 1/2 health after 1st hit (1st life only) 4D65-1FF5 @@ -38363,23 +38397,23 @@ DDB1-0F65 - Sell sturdy tires for $4 + Sell sturdy tires for $4,910 0BBA-0FA5 - Sell 4-liter high output engine for $9 + Sell 4-liter high output engine for $9,925 BBB5-0DA5 - Start new game with $9 + Start new game with $9,910 BBCB-DF61 - Start new game with $49 + Start new game with $49,104,910 62CB-D701 - Start new game with $99 + Start new game with $99,109,910 BBCB-DF61 62CB-D701 @@ -38808,7 +38842,7 @@ C98E-6FDF - Instant 255 mph speed (best to get into 6th gear before activating this code + Instant 255 mph speed (best to get into 6th gear before activating this code, then you can go 357 mph) CBC5-D70F EEC5-D7AF @@ -39384,103 +39418,103 @@ DBB0-346F - Start on level 1 + Start on level 1, sub-level 2 F3BB-3FA4 3FBB-3F64 DFBB-3FD4 - Start on level 1 + Start on level 1, sub-level 3 F3BB-3FA4 3FBB-3F64 D4BB-3FD4 - Start on level 1 + Start on level 1, sub-level 4 F3BB-3FA4 3FBB-3F64 D7BB-3FD4 - Start on level 2 + Start on level 2, sub-level 1 F3BB-3FA4 3FBB-3F64 D0BB-3FD4 - Start on level 2 + Start on level 2, sub-level 2 F3BB-3FA4 3FBB-3F64 D9BB-3FD4 - Start on level 2 + Start on level 2, sub-level 3 F3BB-3FA4 3FBB-3F64 D1BB-3FD4 - Start on level 2 + Start on level 2, sub-level 4 F3BB-3FA4 3FBB-3F64 D5BB-3FD4 - Start on level 3 + Start on level 3, sub-level 1 F3BB-3FA4 3FBB-3F64 D6BB-3FD4 - Start on level 3 + Start on level 3, sub-level 2 F3BB-3FA4 3FBB-3F64 DBBB-3FD4 - Start on level 3 + Start on level 3, sub-level 3 F3BB-3FA4 3FBB-3F64 DCBB-3FD4 - Start on level 3 + Start on level 3, sub-level 4 F3BB-3FA4 3FBB-3F64 D8BB-3FD4 - Start on level 4 + Start on level 4, sub-level 1 F3BB-3FA4 3FBB-3F64 DABB-3FD4 - Start on level 4 + Start on level 4, sub-level 3 F3BB-3FA4 3FBB-3F64 D3BB-3FD4 - Start on level 4 + Start on level 4, sub-level 4 F3BB-3FA4 3FBB-3F64 DEBB-3FD4 - Start on level 5 + Start on level 5, sub-level 1 F3BB-3FA4 3FBB-3F64 FDBB-3FD4 - Start on level 5 + Start on level 5, sub-level 2 F3BB-3FA4 3FBB-3F64 FFBB-3FD4 - Start on level 5 + Start on level 5, sub-level 3 F3BB-3FA4 3FBB-3F64 F4BB-3FD4 @@ -39743,23 +39777,23 @@ FD36-4F0D - Start with $50 + Start with $50,000 D9CF-CDD5 - Start with $100 + Start with $100,000 FDCF-CDD5 - Start with $500 + Start with $500,000 9DCF-CDD5 - Start with $990 + Start with $990,000 BBCF-CDD5 - Start with $5 + Start with $5,020,000 D9CF-CD05 @@ -40076,12 +40110,16 @@ 7E0B79FF - Last area + Last area, last level 7E0B7B03 Rocky Rodent (USA) + + Invincibility + 7E005472 + Infinite lives 3CAD-4DA7 @@ -40178,92 +40216,92 @@ Romance of the Three Kingdoms II (USA) - Start with 30 + Start with 30,000 gold pieces (scenario 1) 7DE7-A465 59E7-A4A5 - Start with 30 + Start with 30,000 rice (scenario 1) 7DE7-A765 59E7-A705 - Start with 30 + Start with 30,000 population (scenario 1) 7DE7-A765 59E7-A7A5 - Start with 30 + Start with 30,000 gold pieces (scenario 2) 7D67-A406 596D-A466 - Start with 30 + Start with 30,000 rice (scenario 2) 7D67-A4A6 596D-A7D6 - Start with 30 + Start with 30,000 population (scenario 2) 7D67-A706 596D-A766 - Start with 30 + Start with 30,000 gold pieces (scenario 3) 7D67-A7DB 5967-A70B - Start with 30 + Start with 30,000 rice (scenario 3) 7D67-A76B 5967-A7AB - Start with 30 + Start with 30,000 population (scenario 3) 7D60-ADDB 5960-AD0B - Start with 30 + Start with 30,000 gold pieces (scenario 4) 7D67-A70C 5967-A76C - Start with 30 + Start with 30,000 rice (scenario 4) 7D67-A7AC 5960-ADDC - Start with 30 + Start with 30,000 population (scenario 4) 7D60-AD0C 5960-AD6C - Start with 30 + Start with 30,000 gold pieces (scenario 5) 7DBB-D7D6 59BB-D706 - Start with 30 + Start with 30,000 rice (scenario 5) 7DBB-D766 59BB-D7A6 - Start with 30 + Start with 30,000 population (scenario 5) 7DBC-DDD6 59BC-DD06 - Start with 30 + Start with 30,000 gold pieces (scenario 6) 7DB9-6766 59B9-67A6 - Start with 30 + Start with 30,000 rice (scenario 6) 7DB1-6DD6 59B1-6D06 - Start with 30 + Start with 30,000 population (scenario 6) 7DB1-6D66 59B1-6DA6 @@ -40389,6 +40427,17 @@ DC83-AD84 + + Rushing Beat Shura (Japan) + + Invincibility + C22A-1DD7 + + + One hit kills + 1028-CDD3 + + Sailormoon (France) @@ -40472,6 +40521,10 @@ Saturday Night Slam Masters (USA) + + Infinite time + 7E1A7001 + Able to pick the same characters 1D79-EFD4 @@ -40702,7 +40755,7 @@ 7E22DBFF - Everyone is invincible + Everyone is invincible, including enemies C2A0-CD5A 826B-41DF D261-400F @@ -40717,7 +40770,7 @@ DDA9-15D5 - View Boy's stats to get 131 + View Boy's stats to get 131,074 Talons (don't use if you already have more than that) CBC4-3DE0 D4C4-3F70 DDC4-3F50 @@ -40805,7 +40858,7 @@ 9C06-85AD - Chest in elder's basement in Potos gives you 65 + Chest in elder's basement in Potos gives you 65,360 GP EE6B-8738 @@ -40871,7 +40924,7 @@ 8208-776D - Change screens to max out Strength + Change screens to max out Strength, Agility, Constitution, Intelligence and Wisdom DD03-ED04 @@ -40879,11 +40932,11 @@ EE28-EDAF - Start with 32 + Start with 32,768 GP 6D28-EFDF - Start with 65 + Start with 65,280 GP EE28-EFDF @@ -41037,7 +41090,7 @@ F3E1-1FDD - Add 65 + Add 65,000 nuyen (if less than 65,000) DFBC-17AF DEB8-1D0F 7AB8-1D6F @@ -41045,7 +41098,7 @@ 53B8-1DAF - Add about 131 + Add about 131,000 nuyen (if less than 65,000) D4BC-17AF DEB8-1D0F 7AB8-1D6F @@ -41053,7 +41106,7 @@ 53B8-1DAF - Add about 524 + Add about 524,000 nuyen (if less than 65,000) D6BC-17AF DEB8-1D0F 7AB8-1D6F @@ -41168,7 +41221,7 @@ 53B8-1DAF - Learn powerball spell + Learn powerball spell, level 6 D1BC-17AF D5B8-1D0F 7AB8-1D6F @@ -41176,7 +41229,7 @@ 53B8-1DAF - Learn heal spell + Learn heal spell, level 6 D1BC-17AF D6B8-1D0F 7AB8-1D6F @@ -41184,7 +41237,7 @@ 53B8-1DAF - Learn invisibility spell + Learn invisibility spell, level 6 D1BC-17AF DBB8-1D0F 7AB8-1D6F @@ -41192,7 +41245,7 @@ 53B8-1DAF - Learn armor spell + Learn armor spell, level 6 D1BC-17AF DCB8-1D0F 7AB8-1D6F @@ -41200,7 +41253,7 @@ 53B8-1DAF - Learn summon spirit spell + Learn summon spirit spell, level 6 D1BC-17AF D8B8-1D0F 7AB8-1D6F @@ -41208,7 +41261,7 @@ 53B8-1DAF - Learn freeze spell + Learn freeze spell, level 6 D1BC-17AF DAB8-1D0F 7AB8-1D6F @@ -41216,7 +41269,7 @@ 53B8-1DAF - Learn firearms skill + Learn firearms skill, level 5 D9BC-17AF DFB8-1D0F 7AB8-1D6F @@ -41224,7 +41277,7 @@ 53B8-1DAF - Learn firearms skill + Learn firearms skill, level 10 DCBC-17AF DFB8-1D0F 7AB8-1D6F @@ -41232,7 +41285,7 @@ 53B8-1DAF - Learn firearms skill + Learn firearms skill, level 15 DEBC-17AF DFB8-1D0F 7AB8-1D6F @@ -41240,7 +41293,7 @@ 53B8-1DAF - Learn computer skill + Learn computer skill, level 6 D1BC-17AF D0B8-1D0F 7AB8-1D6F @@ -41248,7 +41301,7 @@ 53B8-1DAF - Learn leadership skill + Learn leadership skill, level 6 D1BC-17AF D9B8-1D0F 7AB8-1D6F @@ -41256,7 +41309,7 @@ 53B8-1DAF - Learn armed combat skill + Learn armed combat skill, level 6 D1BC-17AF D7B8-1D0F 7AB8-1D6F @@ -41264,7 +41317,7 @@ 53B8-1DAF - Learn unarmed combat skill + Learn unarmed combat skill, level 6 D1BC-17AF D4B8-1D0F 7AB8-1D6F @@ -41272,7 +41325,7 @@ 53B8-1DAF - Learn negotiation skill + Learn negotiation skill, level 6 D1BC-17AF D1B8-1D0F 7AB8-1D6F @@ -41280,23 +41333,23 @@ 53B8-1DAF - Start with computer + Start with computer, firearms skills at level 2 D4BE-4DA4 - Start with computer + Start with computer, firearms skills at level 3 D7BE-4DA4 - Start with computer + Start with computer, firearms skills at level 4 D0BE-4DA4 - Start with computer + Start with computer, firearms skills at level 5 D9BE-4DA4 - Start with computer + Start with computer, firearms skills at level 6 D1BE-4DA4 @@ -41434,7 +41487,7 @@ 7E11DC0B - Play as Daiki Stage 2 + Play as Daiki Stage 2, Ryuuta Stage 3 7E11DC0C @@ -41546,17 +41599,17 @@ DE67-DFAA - Start easy game with $40 + Start easy game with $40,000 0DAB-6D02 BAAB-6D62 - Start easy game with $60 + Start easy game with $60,000 1DAB-6D02 3CAB-6D62 - Start easy game with $3 + Start easy game with $3,000 86AB-6D02 D8AB-6D62 @@ -41570,14 +41623,14 @@ SimCity 2000 (USA) - Start with $99 + Start with $99,999,999 on all the maps except the Land Of Freedom EEF3-8700 3DF3-8760 E9FE-8D60 D9FE-8DA0 - Start with $99 + Start with $99,999,999 on the Land Of Freedom EEF3-8D00 3DF3-8D60 E9F3-8F60 @@ -41695,7 +41748,7 @@ 6DCC-A4D4 - No enemies or Jemeralds (good for exploring + No enemies or Jemeralds (good for exploring, disable to advance) 8BAB-6DD9 @@ -42541,7 +42594,7 @@ DDEB-649F - Gems set to 999 + Gems set to 999,999 every time one is obtained DDE8-64BF @@ -42562,43 +42615,43 @@ D7EA-AFA1 - 600 EXP required instead of 1 + 600 EXP required instead of 1,000 for level 5 D1EA-A4A1 - 1 + 1,200 EXP required instead of 2,000 for level 6 F4EA-A7A1 - 2 + 2,400 EXP required instead of 3,200 for level 7 40E2-ADA1 - 3 + 3,500 EXP required instead of 4,500 for level 8 79E2-AFA1 - 4 + 4,800 EXP required instead of 5,800 for level 9 06E2-A4A1 - 6 + 6,600 EXP required instead of 7,600 for level 10 11E2-A7A1 - 8 + 8,600 EXP required instead of 9,600 for level 11 61E3-ADA1 - 10 + 10,000 EXP required instead of 12,400 for level 12 DDE3-AFA1 - 13 + 13,000 EXP required instead of 15,000 for level 13 7DE3-A4A1 - 15 + 15,000 EXP required instead of 19,000 for level 14 9DE3-A7A1 @@ -42667,12 +42720,12 @@ Space Megaforce (USA) - Protection against enemy hits + Protection against enemy hits, and weapon level goes to 2 when hit CB68-D4AC D168-D7DC - Protection against enemy hits + Protection against enemy hits, and weapon level goes to 6 when hit CB68-D4AC D168-D7DC D16A-D4DC @@ -43479,7 +43532,7 @@ 7E10F8FF - Infinite health - Wolverine + Infinite health - Wolverine, Cyclops, Storm 7E0B2964 @@ -43499,7 +43552,7 @@ C26D-090A - Infinite lives - Wolverine + Infinite lives - Wolverine, Cyclops, Storm C2C2-D767 @@ -43719,7 +43772,7 @@ DD1F-E465 - View status screen for max strength + View status screen for max strength, constitution, agility and stamina (These affect the base stat, making it savable. Stamina won't appear updated until you turn the codes off and re-enter that character's status screen) DD48-54CF 9843-774D 1F47-5F3D @@ -43969,7 +44022,7 @@ EDBE-0F09 - Dizziness lasts longer (on harder levels + Dizziness lasts longer (on harder levels, won't work on computer) C9BE-0DA9 @@ -44028,7 +44081,7 @@ 2AA5-DF60 - Some special moves are easier to perform (E Honda's Sumo Head Butt + Some special moves are easier to perform (E Honda's Sumo Head Butt, Blanka's Rolling Attack, Guile's Flash Kick and Sonic Boom, Chun Li's Whirlwind Kick) DD84-DD01 @@ -44054,43 +44107,43 @@ 1DB8-ADF3 - Fireballs + Fireballs, Sonic Booms and Yoga Fires always go to the right (thrown to the left, they go backwards) DDE3-DF01 - Light Fireballs + Light Fireballs, Sonic Booms and Yoga Fires are slower EEB8-A793 - Light Fireballs + Light Fireballs, Sonic Booms and Yoga Fires are faster EBB8-A793 - Light Fireballs + Light Fireballs, Sonic Booms and Yoga Fires are super fast EDB8-A793 - Medium Fireballs + Medium Fireballs, Sonic Booms and Yoga Fires are slower EEB8-A723 - Medium Fireballs + Medium Fireballs, Sonic Booms and Yoga Fires are faster EBB8-A723 - Medium Fireballs + Medium Fireballs, Sonic Booms and Yoga Fires are super fast EDB8-A723 - Hard Fireballs + Hard Fireballs, Sonic Booms and Yoga Fires are slower EEBA-AD93 - Hard Fireballs + Hard Fireballs, Sonic Booms and Yoga Fires are faster EBBA-AD93 - Hard Fireballs + Hard Fireballs, Sonic Booms and Yoga Fires are super fast EDBA-AD93 @@ -44139,15 +44192,15 @@ 32B5-DDB3 - Most special moves disabled (computer can still do them + Most special moves disabled (computer can still do them, Zangief can still do Spinning Clothesline) 6DA4-6707 - Invisible Fireballs + Invisible Fireballs, Sonic Booms, Yoga Fires and Yoga Flames CB61-07A4 - No Fireballs + No Fireballs, Sonic Booms or Yoga Fires, makes Yoga Flame invisible 1868-0D6C @@ -44369,7 +44422,7 @@ C734-7405 - 1st throws do more damage (if you have enough health) + 1st throws do more damage (if you have enough health), others do less damage F034-7405 @@ -44386,11 +44439,11 @@ Enable 10 star turbo mode - ADFC-E40D - F9FC-E46D + ADFC-E40D + F9FC-E46D - No charging required for special moves (except Balrog’s turn punch power) + No charging required for special moves (except Balrog's turn punch power) D071-E460 @@ -44764,6 +44817,14 @@ Strike Gunner S.T.G (USA) + + Invincibility after first life - P1 + 7E024E05 + + + Invincibility after first life - P2 + 7E024F05 + Infinite lives - P1 C2B4-076F @@ -44784,16 +44845,6 @@ Infinite special weapon energy - P2 C2E4-0DAD - - Max shot power on pick-up - P1 - CBAA-640A - DBAA-64AA - - - Max shot power on pick-up - P2 - CBAA-640A - DBA2-64AA - Start on stage 2 CB69-D40D @@ -44993,7 +45044,7 @@ D96A-67AF - Start in area 1 + Start in area 1, stage 2 D766-0FD7 @@ -45001,15 +45052,15 @@ D966-0FD7 - Start in area 1 + Start in area 1, stage 3 D566-0FD7 - Start in area 2 + Start in area 2, stage 1 DC66-0FD7 - Start in area 2 + Start in area 2, stage 2 DA66-0FD7 @@ -45017,27 +45068,27 @@ D366-0FD7 - Start in area 2 + Start in area 2, stage 3 FF66-0FD7 - Start in area 3 + Start in area 3, stage 1 F066-0FD7 - Start in area 3 + Start in area 3, stage 2 F666-0FD7 - Start in area 3 + Start in area 3, stage 3 FC66-0FD7 - Start in area 4 + Start in area 4, stage 1 F266-0FD7 - Start in area 4 + Start in area 4, stage 2 FE66-0FD7 @@ -45045,23 +45096,23 @@ 4D66-0FD7 - Start in area 4 + Start in area 4, stage 3 4066-0FD7 - Start in area 5 + Start in area 5, stage 1 4566-0FD7 - Start in area 5 + Start in area 5, stage 2 4B66-0FD7 - Start in area 5 + Start in area 5, stage 3 4866-0FD7 - Start in area 5 + Start in area 5, bonus round 4266-0FD7 @@ -45766,19 +45817,19 @@ 7E0E3980 - Invincibility + Invincibility, Kick Bomb, Punch Glove, Bomb Walk, Brick Walk - P1 7E0D79E3 - Invincibility + Invincibility, Kick Bomb, Punch Glove, Bomb Walk, Brick Walk - P2 7E0DB9E3 - Invincibility + Invincibility, Kick Bomb, Punch Glove, Bomb Walk, Brick Walk - P3 7E0DF9E3 - Invincibility + Invincibility, Kick Bomb, Punch Glove, Bomb Walk, Brick Walk - P4 7E0E39E3 @@ -45874,11 +45925,11 @@ 7E0E3809 - Have 9 + Have 9,000,000 points - P1 7E0D5B09 - Have 9 + Have 9,000,000 points - P2 7E0D9B09 @@ -46113,11 +46164,11 @@ 7E83F501 - Have 4 + Have 4,000,000 points - P1 7E5DEFA7 - Have 9 + Have 9,000,000 points - P2 7E0D9B09 @@ -46659,7 +46710,7 @@ Super Ghouls'n Ghosts (USA) - Invincibility (disable at end of first two stages of level 3 + Invincibility (disable at end of first two stages of level 3, so you can trigger the hidden end of stage marker) D4D5-B286 @@ -46730,7 +46781,7 @@ 7E045302 - 900 + 900,000 points 7E029509 @@ -47162,7 +47213,7 @@ D5A8-6CAA - (SMB3) After getting star + (SMB3) After getting star, invincible until end of level (may have to disable to jump) C23B-680D @@ -47857,6 +47908,10 @@ Infinite lives C222-D4DD + + Multi-jump + 6D2E-0FDF + Multi-jump and float down (disable in water and to get on Yoshi) 7E147101 @@ -48073,7 +48128,7 @@ C2EE-64BF - After using the magnifying glass + After using the magnifying glass, red coins and hidden items are always revealed C2C8-A465 @@ -48242,7 +48297,7 @@ 6DB6-6F55 - After using the magnifying glass + After using the magnifying glass, red coins and hidden items are always revealed C2C8-A465 @@ -48480,7 +48535,7 @@ 7E09A5FF - Automatically collect secret and/or special items in current room (Missiles + Automatically collect secret and/or special items in current room (Missiles, Energy Tanks, ect) 402B-3DB7 402E-3FF7 @@ -48528,6 +48583,11 @@ 7E0B2D44 7E0B2E01 + + Metroids can be killed without being frozen first + 403F-38DE + 6D34-3BAE + Infinite time to escape ship 7E094500 @@ -48711,20 +48771,12 @@ Protection from most hazards (makes some side-view enemies invincible) 822E-07B0 - - Start with 250 cash - EC81-AF69 - - - Start with 40 - 6981-A4D9 - Don't subtract money (must have enough to buy) 1DAF-D4D6 - All stats are 20 (attack + All stats are 20 (attack, defense, energy, max HP, max NP) CB2F-A70C 3C2F-A7AC F02F-A76C @@ -48803,6 +48855,14 @@ M power-ups set to 15 F930-6720 + + Start with 250 cash + EC81-AF69 + + + Start with 40,960 cash + 6981-A4D9 + Super Nova (USA) @@ -48823,46 +48883,6 @@ Infinite nitros 3CA0-CD6F - - $9 - DBB6-1FDF - - - $2 - D4B6-1FDF - - - $9 - DBB6-1F6F - - - $2 - D4B6-1F6F - - - $2 - D4B6-14DF - - - $9 - DBB6-14DF - - - $2 - D4B6-146F - - - $9 - DBB6-146F - - - $2 - D4B6-17DF - - - $4 - D0B6-17DF - Indestructible engine C283-34D7 @@ -48883,6 +48903,46 @@ Vehicle can take only about 35% damage 7D81-37D7 + + $9,000 for brakes + DBB6-1FDF + + + $2,000 for brakes + D4B6-1FDF + + + $9,000 for tires + DBB6-1F6F + + + $2,000 for tires + D4B6-1F6F + + + $2,000 for shocks + D4B6-14DF + + + $9,000 for shocks + DBB6-14DF + + + $2,000 for lights + D4B6-146F + + + $9,000 for lights + DBB6-146F + + + $2,000 for engine + D4B6-17DF + + + $4,000 for engine + D0B6-17DF + Super Off Road (USA) @@ -48900,11 +48960,11 @@ 2B84-DDDD - Start with $500 + Start with $500,000 D987-6D0F - Start with $900 + Start with $900,000 DB87-6D0F @@ -49090,7 +49150,7 @@ 7D68-6D6B - Once FORCE has been obtained + Once FORCE has been obtained, keep it forever C267-A4D9 @@ -49209,43 +49269,43 @@ D0C9-056F - Select low mode to start on level 5 (Blastris B + Select low mode to start on level 5 (Blastris B, Type B) D968-D100 - Select low mode to start on level 15 (Blastris B + Select low mode to start on level 15 (Blastris B, Type B) DE68-D100 - Select low mode to start on level 25 (Blastris B + Select low mode to start on level 25 (Blastris B, Type B) FB68-D100 - Select low mode to start on level 30 (Blastris B + Select low mode to start on level 30 (Blastris B, Type B) F368-D100 - Select low mode to start on level 35 (Blastris B + Select low mode to start on level 35 (Blastris B, Type B) 4768-D100 - Select low mode to start on level 40 (Blastris B + Select low mode to start on level 40 (Blastris B, Type B) 4668-D100 - Clear stage after 1 Molian is hit (Mole Patrol + Clear stage after 1 Molian is hit (Mole Patrol, Stage Mode) BAA6-01DD - Take no damage (LazerBlazer + Take no damage (LazerBlazer, Type A) 8262-64A1 - Take no damage (LazerBlazer Game + Take no damage (LazerBlazer Game, Type B) 3CB0-670B - Take no damage (LazerBlazer Game + Take no damage (LazerBlazer Game, Type C) C269-67DE @@ -49316,7 +49376,7 @@ 7E189A06 - Infinite credits (if continue timer runs out and player starts + Infinite credits (if continue timer runs out and player starts, a credit gets used) C223-D78B @@ -49790,7 +49850,7 @@ DDCC-1DDA - Mind control + Mind control, Slow, Deflect and Invisible don't drain force bar C22F-C7F9 @@ -50341,7 +50401,7 @@ Super Street Fighter II (USA) - Invincibility (except against throws + Invincibility (except against throws, projectiles don't work) - P1 6D9C-8D67 DF9C-8DA7 6DA1-8FD5 @@ -50442,15 +50502,15 @@ F122-E760 - Balrog - Fierce charging punch + Balrog - Fierce charging punch, does heavy damage 6E6A-EF90 - Balrog - Roundhouse charging uppercut + Balrog - Roundhouse charging uppercut, does heavy damage 6E62-E790 - Balrog - Fierce shoulder butt + Balrog - Fierce shoulder butt, does heavy damage 6E69-5799 @@ -50462,27 +50522,27 @@ DB8C-74D5 - Blanka - Fierce forward ball + Blanka - Fierce forward ball, does heavy damage 6E1C-E720 - Blanka - Beast leap + Blanka - Beast leap, does heavy damage 6E1B-7D29 - Blanka - Jab zap + Blanka - Jab zap, does heavy damage 6E15-ED20 - Cammy - Fierce spin knuckle + Cammy - Fierce spin knuckle, does heavy damage 6EB3-5F20 - Cammy - Roundhouse front kick + Cammy - Roundhouse front kick, does heavy damage 6EBB-5720 - Cammy - Roundhouse cannon drill + Cammy - Roundhouse cannon drill, does heavy damage from far away 6EBF-5420 @@ -50506,15 +50566,15 @@ D620-14FA - Chun-Li - Fierce fireball + Chun-Li - Fierce fireball, does heavy damage 6E5D-7D20 - Chun-Li - Down step + Chun-Li - Down step, does heavy damage DE10-5425 - Chun-Li - Short lightning kick + Chun-Li - Short lightning kick, does heavy damage 6E11-8425 @@ -50526,11 +50586,11 @@ DB5E-8F60 - Dee Jay - Fierce hyper fist (1st hit) + Dee Jay - Fierce hyper fist (1st hit), does heavy damage 6EC5-EF99 - Dee Jay - Fierce Max Out + Dee Jay - Fierce Max Out, does heavy damage 6ECF-7D91 @@ -50546,43 +50606,43 @@ DB23-1F9A - Dhalsim - Yoga spear + Dhalsim - Yoga spear, does heavy damage DE5E-8729 - Dhalsim - Strong yoga flame (solid hit) + Dhalsim - Strong yoga flame (solid hit), does heavy damage 6E5E-E429 - Dhalsim - Fierce yoga fire + Dhalsim - Fierce yoga fire, does heavy damage 6E58-E729 - E. Honda - Jab hundred-hand slap + E. Honda - Jab hundred-hand slap, does heavy damage 6E99-8795 - E. Honda - Fierce torpedo + E. Honda - Fierce torpedo, does heavy damage 6E96-E495 - E. Honda - Fierce sumo splash + E. Honda - Fierce sumo splash, does heavy damage 6E92-E795 - Fei Long - Fierce slide punch (1st hit) + Fei Long - Fierce slide punch (1st hit), does heavy damage 6EC7-5F20 - Fei Long - Fierce slide punch (2nd hit) + Fei Long - Fierce slide punch (2nd hit), does heavy damage 6EC0-5D20 - Fei Long - Fierce slide punch (3rd hit) + Fei Long - Fierce slide punch (3rd hit), does heavy damage 6EC0-5720 - Fei Long - Roundhouse dragon kick + Fei Long - Roundhouse dragon kick, does heavy damage 6ECE-7420 @@ -50594,27 +50654,27 @@ D627-1F2A - Guile - Fierce sonic boom + Guile - Fierce sonic boom, does heavy damage 6E16-5491 - Guile - Roundhouse sonic kick + Guile - Roundhouse sonic kick, extremely close range, does heavy damage 6E1E-7491 - Hawk - The Hawk + Hawk - The Hawk, does heavy damage 6EB3-5F91 - Ken - Fierce dragon punch + Ken - Fierce dragon punch, close to opponent, does heavy damage 6E96-8721 - Ken - Fierce fireballs + Ken - Fierce fireballs, close to opponent, does heavy damage 6E92-8F21 - Ken - Roundhouse hurricane kick while on the ground + Ken - Roundhouse hurricane kick while on the ground, does heavy damage 6E9A-5721 @@ -50642,11 +50702,11 @@ 1086-5D00 - Ryu - Jab dragon punch + Ryu - Jab dragon punch, close to opponent, does heavy damage 6E9D-8729 - Ryu - Fierce red fireballs from far away + Ryu - Fierce red fireballs from far away, does heavy damage 6E9B-E429 @@ -50670,43 +50730,43 @@ 3169-57A5 - Sagat - Roundhouse low tiger + Sagat - Roundhouse low tiger, from far away, does heavy damage 6E64-5F20 - Sagat - Fierce high tiger + Sagat - Fierce high tiger, from far away, does heavy damage 6E62-7720 - Sagat - Short tiger knee + Sagat - Short tiger knee, does heavy damage 6E53-ED25 - Sagat - Jab projectiles move slower for everyone but Sagat + Sagat - Jab projectiles move slower for everyone but Sagat, does heavy damage EE27-479E - Sagat - Jab projectiles move slower for Sagat + Sagat - Jab projectiles move slower for Sagat, does heavy damage EE20-4D2E - Sagat - Fierce projectiles move faster for everyone but Sagat + Sagat - Fierce projectiles move faster for everyone but Sagat, does heavy damage EC20-4D9E - Sagat - Fierce projectiles move faster for Sagat + Sagat - Fierce projectiles move faster for Sagat, does heavy damage E520-4F2E - Vega - Fierce claw dive + Vega - Fierce claw dive, does heavy damage AE6A-8491 - Vega - Rolling claw attack + Vega - Rolling claw attack, does heavy damage 6E62-8F91 - Vega - Claw thrust + Vega - Claw thrust, does heavy damage 6E6E-EF91 @@ -50718,7 +50778,7 @@ 1053-5760 - Zangief - Double spinning lariat (only certain hits) + Zangief - Double spinning lariat (only certain hits), does heavy damage 6E51-EF90 @@ -51555,11 +51615,11 @@ D035-C540 - You have 1 minute to complete act 1 + You have 1 minute to complete act 1, level 1 DF64-41C0 - You have 5 minutes to complete act 1 + You have 5 minutes to complete act 1, level 1 D964-41C0 @@ -51635,13 +51695,13 @@ 173F-15C0 - Start on act 1 + Start on act 1, level 2 4A36-1140 7D36-1110 DF3F-15C0 - Start on act 1 + Start on act 1, level 3 4A36-1140 7D36-1110 D43F-15C0 @@ -51652,19 +51712,19 @@ 7D36-1110 - Start on act 2 + Start on act 2, level 1 4A36-1140 7D36-1110 D03F-15C0 - Start on act 2 + Start on act 2, level 2 4A36-1140 7D36-1110 D93F-15C0 - Start on act 2 + Start on act 2, level 3 4A36-1140 7D36-1110 D13F-15C0 @@ -51676,19 +51736,19 @@ D53F-15C0 - Start on act 3 + Start on act 3, level 1 4A36-1140 7D36-1110 D63F-15C0 - Start on act 3 + Start on act 3, level 2 4A36-1140 7D36-1110 DB3F-15C0 - Start on act 3 + Start on act 3, level 3 4A36-1140 7D36-1110 DC3F-15C0 @@ -51700,19 +51760,19 @@ D83F-15C0 - Start on act 4 + Start on act 4, level 1 4A36-1140 7D36-1110 DA3F-15C0 - Start on act 4 + Start on act 4, level 2 4A36-1140 7D36-1110 D23F-15C0 - Start on act 4 + Start on act 4, level 3 4A36-1140 7D36-1110 D33F-15C0 @@ -51724,19 +51784,19 @@ DE3F-15C0 - Start on act 5 + Start on act 5, level 1 4A36-1140 7D36-1110 FD3F-15C0 - Start on act 5 + Start on act 5, level 2 4A36-1140 7D36-1110 FF3F-15C0 - Start on act 5 + Start on act 5, level 3 4A36-1140 7D36-1110 F43F-15C0 @@ -51773,11 +51833,11 @@ D035-C540 - You have 1 minute to complete act 1 + You have 1 minute to complete act 1, level 1 DF64-41C0 - You have 5 minutes to complete act 1 + You have 5 minutes to complete act 1, level 1 D964-41C0 @@ -51853,13 +51913,13 @@ 173F-15C0 - Start on act 1 + Start on act 1, level 2 4A36-1140 7D36-1110 DF3F-15C0 - Start on act 1 + Start on act 1, level 3 4A36-1140 7D36-1110 D43F-15C0 @@ -51870,19 +51930,19 @@ 7D36-1110 - Start on act 2 + Start on act 2, level 1 4A36-1140 7D36-1110 D03F-15C0 - Start on act 2 + Start on act 2, level 2 4A36-1140 7D36-1110 D93F-15C0 - Start on act 2 + Start on act 2, level 3 4A36-1140 7D36-1110 D13F-15C0 @@ -51894,19 +51954,19 @@ D53F-15C0 - Start on act 3 + Start on act 3, level 1 4A36-1140 7D36-1110 D63F-15C0 - Start on act 3 + Start on act 3, level 2 4A36-1140 7D36-1110 DB3F-15C0 - Start on act 3 + Start on act 3, level 3 4A36-1140 7D36-1110 DC3F-15C0 @@ -51918,19 +51978,19 @@ D83F-15C0 - Start on act 4 + Start on act 4, level 1 4A36-1140 7D36-1110 DA3F-15C0 - Start on act 4 + Start on act 4, level 2 4A36-1140 7D36-1110 D23F-15C0 - Start on act 4 + Start on act 4, level 3 4A36-1140 7D36-1110 D33F-15C0 @@ -51942,19 +52002,19 @@ DE3F-15C0 - Start on act 5 + Start on act 5, level 1 4A36-1140 7D36-1110 FD3F-15C0 - Start on act 5 + Start on act 5, level 2 4A36-1140 7D36-1110 FF3F-15C0 - Start on act 5 + Start on act 5, level 3 4A36-1140 7D36-1110 F43F-15C0 @@ -52258,15 +52318,15 @@ D4C1-1D03 - After doing an ultimate attack + After doing an ultimate attack, health bar goes to about 1/4 F0C3-4463 - After doing an ultimate attack + After doing an ultimate attack, health bar goes to about 1/2 46C3-4463 - After doing an ultimate attack + After doing an ultimate attack, health bar goes to about 3/4 7AC3-4463 @@ -52549,7 +52609,7 @@ 7E1E1B03 - Tetris 2 - Select any round - 1P (at round select meter + Tetris 2 - Select any round - 1P (at round select meter, keep pressing right) 9DBD-3DF4 @@ -52565,7 +52625,7 @@ DDC5-4F6C - Tetris 2 - More time to place the blocks where you want them + Tetris 2 - More time to place the blocks where you want them, even after they hit the ground (left and right only) 6DB1-346B @@ -53018,7 +53078,7 @@ 7E07D809 - Have $9 + Have $9,000,000 7E07D809 @@ -53087,7 +53147,7 @@ Tiny Toon Adventures - Buster Busts Loose! (USA) - Infinite health (when hit + Infinite health (when hit, a fake empty heart appears) 3CE9-448A @@ -53107,7 +53167,7 @@ D184-C4A1 - 1-up gives 2-up (not on mystery weight challenge level + 1-up gives 2-up (not on mystery weight challenge level, or by collecting stars) D46B-CFAF @@ -53219,11 +53279,11 @@ DFCD-4FAF - Start with 4 hearts on Children or Normal difficulty levels + Start with 4 hearts on Children or Normal difficulty levels, 2 on Challenge D0CD-4FAF - Start with 5 hearts on Children or Normal difficulty levels + Start with 5 hearts on Children or Normal difficulty levels, 3 on Challenge D9CD-4FAF @@ -53386,43 +53446,43 @@ C9BD-1F04 - 1st place gives $50 + 1st place gives $50,000 instead of $10,000 7430-398E - 2nd place gives $50 + 2nd place gives $50,000 instead of $6,000 7430-317E - 3rd place gives $50 + 3rd place gives $50,000 instead of $4,000 7430-318E - 4th place gives $50 + 4th place gives $50,000 instead of $3,000 7430-357E - 5th place gives $50 + 5th place gives $50,000 instead of $2,000 7430-358E - 6th place gives $50 + 6th place gives $50,000 instead of $1,000 7439-307E - 7th place gives $50 + 7th place gives $50,000 instead of $0 7439-308E - 8th place gives $50 + 8th place gives $50,000 instead of $0 7439-397E - 9th place gives $50 + 9th place gives $50,000 instead of $0 7439-398E - 10th place gives $50 + 10th place gives $50,000 instead of $0 7439-317E @@ -54211,6 +54271,17 @@ F066-446F + + Turbo Toons (Europe) + + Start at Final Tournament (press Select at title screen, then in the topmost menu select the trophy) + 7E1E4404 + + + Infinite Turbo - Hong Kong Phooey + 7E0C9EE0 + + Turn and Burn - No-Fly Zone (USA) @@ -54260,15 +54331,15 @@ Invincibility CEA5-34DF - - Infinite money - C260-3766 - Infinite HP 7E4CE0FF 7E4CE14F + + Infinite money + C260-3766 + Infinite money (alt) 7E0A57E7 @@ -54372,7 +54443,7 @@ DD80-0DAD - Start with $9 + Start with $9,000 BD80-0DAD @@ -54662,12 +54733,12 @@ 7E1CFC63 - 65 + 65,000 Exp 7E1D00E8 7E1D01FD - 65 + 65,000 Gold 7E1CE6E8 7E1CE7FD @@ -54683,7 +54754,7 @@ 7E09C963 - Start with 60 + Start with 60,000 score 7E09B960 7E09BAEA @@ -54811,7 +54882,7 @@ 7E201B80 - 1 D.a.s. + 1 D.a.s., No Scurvy 7E415E00 @@ -55320,19 +55391,19 @@ EC63-543D - Start a new game with $1 + Start a new game with $1,024 Gold D063-574D - Start a new game with $9 + Start a new game with $9,984 Gold 4563-574D - Start a new game with $64 + Start a new game with $64,000 Gold EC63-574D - Start a new game with $196 + Start a new game with $196,608 Gold D763-571D @@ -55343,7 +55414,7 @@ Uncharted Waters (USA) - Start with 65 + Start with 65,000 Gold E2EF-D7D5 @@ -55406,15 +55477,15 @@ Vegas Stakes (USA) - Only $34 + Only $34,464 needed for highroller status (glitchy) DDA0-A4AD - Only $38 + Only $38,527 needed to win the game instead of $10 million DDA8-640D - Only $5 + Only $5,019,263 needed to win the game 0AA8-640D @@ -55474,19 +55545,19 @@ 4183-A7A7 - Start with $132 + Start with $132,072 (highroller status) - P1 D481-A707 - Start with $132 + Start with $132,072 - P2 D48B-A467 - Start with $132 + Start with $132,072 - P3 D48A-AFA7 - Start with $132 + Start with $132,072 - P4 D48E-AFD7 @@ -56688,7 +56759,7 @@ Yoshi's Cookie (USA) - In Action mode + In Action mode, passing a stage advances to the next round 6D8F-DF3B @@ -56700,20 +56771,20 @@ 14C6-0436 - In VS mode + In VS mode, only 1 win is required instead of 3. P2 always wins the set (2P only) DF86-A71C - In VS mode + In VS mode, the fuses don't count down C2A0-DF48 - In VS mode + In VS mode, play against tougher opponents without the secret code D685-A766 DD86-AF66 - In Puzzle mode + In Puzzle mode, passing a stage advances to the next round DD3C-6738 @@ -56957,27 +57028,27 @@ A682-012E - Start with 488 Gold instead of 1 + Start with 488 Gold instead of 1,000 DF8E-00BE - Start with 2 + Start with 2,024 Gold D58E-00BE - Start with 9 + Start with 9,704 Gold 498E-00BE - Start with 20 + Start with 20,200 Gold 038E-00BE - Start with 40 + Start with 40,168 Gold BA8E-00BE - Start with 65 + Start with 65,512 Gold EE8E-00BE @@ -57264,11 +57335,11 @@ DBED-1FA4 - Only 1 victim to rescue per level (no bonus for rescuing all victims + Only 1 victim to rescue per level (no bonus for rescuing all victims, game is over if Zombie eats a victim) DF63-14DF - Can advance to next level after getting 1 victim (no bonus for rescuing all victims + Can advance to next level after getting 1 victim (no bonus for rescuing all victims, game is over if Zombie eats a victim) BAA1-44A4 diff --git a/bsnes/snes/interface/interface.hpp b/bsnes/snes/interface/interface.hpp index 8c6a2f8b..f7ee5b14 100755 --- a/bsnes/snes/interface/interface.hpp +++ b/bsnes/snes/interface/interface.hpp @@ -1,6 +1,6 @@ class Interface { public: - virtual void video_refresh(const uint16_t *data, unsigned width, unsigned height) {} + virtual void video_refresh(const uint16_t *data, bool hires, bool interlace, bool overscan) {} virtual void audio_sample(uint16_t l_sample, uint16_t r_sample) {} virtual void input_poll() {} virtual int16_t input_poll(bool port, Input::Device device, unsigned index, unsigned id) { return 0; } diff --git a/bsnes/snes/ppu/ppu.cpp b/bsnes/snes/ppu/ppu.cpp index 44352b3a..b4a8de4c 100755 --- a/bsnes/snes/ppu/ppu.cpp +++ b/bsnes/snes/ppu/ppu.cpp @@ -40,7 +40,7 @@ void PPU::enter() { scanline(); add_clocks(60); - if(vcounter() <= (!regs.overscan ? 224 : 239)) { + if(vcounter() <= 239) { for(signed pixel = -7; pixel <= 255; pixel++) { bg1.run(1); bg2.run(1); diff --git a/bsnes/snes/ppu/screen/screen.cpp b/bsnes/snes/ppu/screen/screen.cpp index 8a9f3589..04beab96 100755 --- a/bsnes/snes/ppu/screen/screen.cpp +++ b/bsnes/snes/ppu/screen/screen.cpp @@ -22,6 +22,8 @@ void PPU::Screen::run() { } uint16 PPU::Screen::get_pixel(bool swap) { + if(ppu.regs.overscan == false && ppu.vcounter() >= 225) return 0x0000; + enum source_t { BG1, BG2, BG3, BG4, OAM, BACK }; bool color_enable[] = { regs.bg1_color_enable, regs.bg2_color_enable, regs.bg3_color_enable, regs.bg4_color_enable, regs.oam_color_enable, regs.back_color_enable }; diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 1f9a0b19..8f58a792 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[] = "077.05"; + static const char Version[] = "078"; static const unsigned SerializerVersion = 19; } } diff --git a/bsnes/snes/video/video.cpp b/bsnes/snes/video/video.cpp index 1fd6879f..864d9c0c 100755 --- a/bsnes/snes/video/video.cpp +++ b/bsnes/snes/video/video.cpp @@ -56,7 +56,7 @@ void Video::update() { uint16_t *data = (uint16_t*)ppu.output; if(ppu.interlace() && ppu.field()) data += 512; - if(frame_hires) { + if(hires) { //normalize line widths for(unsigned y = 0; y < 240; y++) { if(line_width[y] == 512) continue; @@ -67,25 +67,22 @@ void Video::update() { } } - system.interface->video_refresh(ppu.output, 256 << frame_hires, 240 << frame_interlace); + system.interface->video_refresh(ppu.surface, hires, ppu.interlace(), ppu.overscan()); - frame_hires = false; - frame_interlace = false; + hires = false; } void Video::scanline() { unsigned y = cpu.vcounter(); if(y >= 240) return; - frame_hires |= ppu.hires(); - frame_interlace |= ppu.interlace(); + hires |= ppu.hires(); unsigned width = (ppu.hires() == false ? 256 : 512); line_width[y] = width; } void Video::init() { - frame_hires = false; - frame_interlace = false; + hires = false; for(unsigned i = 0; i < 240; i++) line_width[i] = 256; } diff --git a/bsnes/snes/video/video.hpp b/bsnes/snes/video/video.hpp index 733857f1..1a37e48d 100755 --- a/bsnes/snes/video/video.hpp +++ b/bsnes/snes/video/video.hpp @@ -1,7 +1,6 @@ class Video { private: - bool frame_hires; - bool frame_interlace; + bool hires; unsigned line_width[240]; void update(); diff --git a/bsnes/ui-libsnes/libsnes.cpp b/bsnes/ui-libsnes/libsnes.cpp index 6ec08f67..7962180c 100755 --- a/bsnes/ui-libsnes/libsnes.cpp +++ b/bsnes/ui-libsnes/libsnes.cpp @@ -12,7 +12,11 @@ struct Interface : public SNES::Interface { snes_input_state_t pinput_state; string basename; - void video_refresh(const uint16_t *data, unsigned width, unsigned height) { + void video_refresh(const uint16_t *data, bool hires, bool interlace, bool overscan) { + unsigned width = hires ? 512 : 256; + unsigned height = overscan ? 224 : 239; + if(interlace) height <<= 1; + data += 9 * 1024; //skip front porch if(pvideo_refresh) return pvideo_refresh(data, width, height); } diff --git a/bsnes/ui/interface.cpp b/bsnes/ui/interface.cpp index 15d14c92..b6b5debc 100755 --- a/bsnes/ui/interface.cpp +++ b/bsnes/ui/interface.cpp @@ -78,24 +78,27 @@ void Filter::render(uint32_t *output, unsigned outpitch, const uint16_t *input, } } -void Interface::video_refresh(const uint16_t *data, unsigned width, unsigned height) { - bool interlace = SNES::ppu.interlace(); - bool overscan = SNES::ppu.overscan(); +//data is a 512x512x16bpp buffer, broken in two-scanline pairs (for interlace): +// 0 - 7 = front porch +// 8 = empty scanline 0 +// 9 - 232 = standard scanlines 1 - 224 +//233 - 247 = overscan scanlines 225-239 +//248 - 255 = back porch + +void Interface::video_refresh(const uint16_t *data, bool hires, bool interlace, bool overscan) { + unsigned width = hires ? 512 : 256; + unsigned height = config.video.region == 0 ? 224 : 239; + if(interlace) height <<= 1; unsigned inpitch = interlace ? 1024 : 2048; - //always ignore blank scanline 0 - data += 1024; - height -= 1 << interlace; - if(config.video.region == 0) { - //NTSC overscan compensation - height -= 15 << interlace; - if(overscan == true ) data += 7 * 1024; + if(overscan == false) data += 9 * 1024; // 0 + 224 + 0 + if(overscan == true ) data += 16 * 1024; //-7 + 224 + -7 } if(config.video.region == 1) { - //PAL underscan compensation - if(overscan == false) data -= 7 * 1024; + if(overscan == false) data += 1 * 1024; // 8 + 224 + 7 + if(overscan == true ) data += 9 * 1024; // 0 + 239 + 0 } unsigned outwidth = width, outheight = height; diff --git a/bsnes/ui/interface.hpp b/bsnes/ui/interface.hpp index e2107a25..de3600ef 100755 --- a/bsnes/ui/interface.hpp +++ b/bsnes/ui/interface.hpp @@ -15,7 +15,7 @@ struct Filter : public library { }; struct Interface : public SNES::Interface { - void video_refresh(const uint16_t *data, unsigned width, unsigned height); + void video_refresh(const uint16_t *data, bool hires, bool interlace, bool overscan); void audio_sample(uint16_t left, uint16_t right); void input_poll(); int16_t input_poll(bool port, SNES::Input::Device device, unsigned index, unsigned id); diff --git a/snesfilter/nall/bit.hpp b/snesfilter/nall/bit.hpp index 169fc144..ca6ea29a 100755 --- a/snesfilter/nall/bit.hpp +++ b/snesfilter/nall/bit.hpp @@ -3,12 +3,12 @@ namespace nall { template inline unsigned uclamp(const unsigned x) { - enum { y = (1U << bits) - 1 }; + enum { y = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) }; return y + ((x - y) & -(x < y)); //min(x, y); } template inline unsigned uclip(const unsigned x) { - enum { m = (1U << bits) - 1 }; + enum { m = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) }; return (x & m); } diff --git a/snesfilter/nall/config.hpp b/snesfilter/nall/config.hpp index f555158e..b8381b16 100755 --- a/snesfilter/nall/config.hpp +++ b/snesfilter/nall/config.hpp @@ -45,11 +45,11 @@ namespace nall { void set(string s) { switch(type) { - case boolean_t: *(bool*)data = (s == "true"); break; - case signed_t: *(signed*)data = strsigned(s); break; - case unsigned_t: *(unsigned*)data = strunsigned(s); break; - case double_t: *(double*)data = strdouble(s); break; - case string_t: s.trim("\""); *(string*)data = s; break; + case boolean_t: *(bool*)data = (s == "true"); break; + case signed_t: *(signed*)data = integer(s); break; + case unsigned_t: *(unsigned*)data = decimal(s); break; + case double_t: *(double*)data = fp(s); break; + case string_t: s.trim("\""); *(string*)data = s; break; } } }; diff --git a/snesfilter/nall/directory.hpp b/snesfilter/nall/directory.hpp index df0bf086..c4f94c9a 100755 --- a/snesfilter/nall/directory.hpp +++ b/snesfilter/nall/directory.hpp @@ -41,14 +41,14 @@ struct directory { if(handle != INVALID_HANDLE_VALUE) { if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = utf8_t(data.cFileName); + string name = (const char*)utf8_t(data.cFileName); if(wildcard(name, pattern)) list.append(string(name, "/")); } } while(FindNextFile(handle, &data) != false) { if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = utf8_t(data.cFileName); + string name = (const char*)utf8_t(data.cFileName); if(wildcard(name, pattern)) list.append(string(name, "/")); } } @@ -70,12 +70,12 @@ struct directory { handle = FindFirstFile(utf16_t(path), &data); if(handle != INVALID_HANDLE_VALUE) { if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = utf8_t(data.cFileName); + string name = (const char*)utf8_t(data.cFileName); if(wildcard(name, pattern)) list.append(name); } while(FindNextFile(handle, &data) != false) { if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = utf8_t(data.cFileName); + string name = (const char*)utf8_t(data.cFileName); if(wildcard(name, pattern)) list.append(name); } } diff --git a/snesfilter/nall/dl.hpp b/snesfilter/nall/dl.hpp index 6fa7603f..ebfa5585 100755 --- a/snesfilter/nall/dl.hpp +++ b/snesfilter/nall/dl.hpp @@ -19,6 +19,7 @@ namespace nall { struct library { bool opened() const { return handle; } bool open(const char*, const char* = ""); + bool open_absolute(const char*); void* sym(const char*); void close(); @@ -40,6 +41,12 @@ namespace nall { return handle; } + inline bool library::open_absolute(const char *name) { + if(handle) close(); + handle = (uintptr_t)dlopen(name, RTLD_LAZY); + return handle; + } + inline void* library::sym(const char *name) { if(!handle) return 0; return dlsym((void*)handle, name); @@ -58,6 +65,12 @@ namespace nall { return handle; } + inline bool library::open_absolute(const char *name) { + if(handle) close(); + handle = (uintptr_t)dlopen(name, RTLD_LAZY); + return handle; + } + inline void* library::sym(const char *name) { if(!handle) return 0; return dlsym((void*)handle, name); @@ -76,6 +89,12 @@ namespace nall { return handle; } + inline bool library::open_absolute(const char *name) { + if(handle) close(); + handle = (uintptr_t)LoadLibraryW(utf16_t(name)); + return handle; + } + inline void* library::sym(const char *name) { if(!handle) return 0; return (void*)GetProcAddress((HMODULE)handle, name); diff --git a/snesfilter/nall/filemap.hpp b/snesfilter/nall/filemap.hpp index 52acb2fa..5e8cc059 100755 --- a/snesfilter/nall/filemap.hpp +++ b/snesfilter/nall/filemap.hpp @@ -21,7 +21,7 @@ namespace nall { public: enum class mode : unsigned { read, write, readwrite, writeread }; - bool opened() const { return p_opened(); } + bool open() const { return p_open(); } bool open(const char *filename, mode mode_) { return p_open(filename, mode_); } void close() { return p_close(); } unsigned size() const { return p_size; } @@ -42,7 +42,7 @@ namespace nall { HANDLE p_filehandle, p_maphandle; - bool p_opened() const { + bool p_open() const { return p_handle; } @@ -128,7 +128,7 @@ namespace nall { int p_fd; - bool p_opened() const { + bool p_open() const { return p_handle; } diff --git a/snesfilter/nall/foreach.hpp b/snesfilter/nall/foreach.hpp index 00a039f3..031913c8 100755 --- a/snesfilter/nall/foreach.hpp +++ b/snesfilter/nall/foreach.hpp @@ -5,8 +5,14 @@ #include #undef foreach -#define foreach(iter, object) \ + +#define foreach2(iter, object) foreach3(iter, object, foreach_counter) +#define foreach3(iter, object, foreach_counter) \ for(unsigned foreach_counter = 0, foreach_limit = container_size(object), foreach_once = 0, foreach_broken = 0; foreach_counter < foreach_limit && foreach_broken == 0; foreach_counter++, foreach_once = 0) \ for(auto &iter = object[foreach_counter]; foreach_once == 0 && (foreach_broken = 1); foreach_once++, foreach_broken = 0) +#define foreach_impl(...) foreach_decl(__VA_ARGS__, foreach3(__VA_ARGS__), foreach2(__VA_ARGS__), foreach_too_few_arguments) +#define foreach_decl(_1, _2, _3, N, ...) N +#define foreach(...) foreach_impl(__VA_ARGS__) + #endif diff --git a/snesfilter/nall/function.hpp b/snesfilter/nall/function.hpp index 645991fb..35b76881 100755 --- a/snesfilter/nall/function.hpp +++ b/snesfilter/nall/function.hpp @@ -27,7 +27,7 @@ namespace nall { }; template struct lambda : container { - L object; + mutable L object; R operator()(P... p) const { return object(std::forward

(p)...); } container* copy() const { return new lambda(object); } lambda(const L& object) : object(object) {} @@ -46,7 +46,7 @@ namespace nall { return *this; } - function(const function &source) { operator=(source); } + function(const function &source) : callback(0) { operator=(source); } function() : callback(0) {} function(void *function) : callback(0) { if(function) callback = new global((R (*)(P...))function); } function(R (*function)(P...)) { callback = new global(function); } diff --git a/snesfilter/nall/gameboy/cartridge.hpp b/snesfilter/nall/gameboy/cartridge.hpp new file mode 100755 index 00000000..0e1b28d8 --- /dev/null +++ b/snesfilter/nall/gameboy/cartridge.hpp @@ -0,0 +1,105 @@ +#ifndef NALL_GAMEBOY_CARTRIDGE_HPP +#define NALL_GAMEBOY_CARTRIDGE_HPP + +namespace nall { + +class GameBoyCartridge { +public: + string xml; + inline GameBoyCartridge(const uint8_t *data, unsigned size); + +//private: + struct Information { + string mapper; + bool ram; + bool battery; + bool rtc; + bool rumble; + + unsigned romsize; + unsigned ramsize; + } info; +}; + +GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) { + xml = "\n"; + if(romsize < 0x4000) return; + + info.mapper = "unknown"; + info.ram = false; + info.battery = false; + info.rtc = false; + info.rumble = false; + + info.romsize = 0; + info.ramsize = 0; + + switch(romdata[0x0147]) { + case 0x00: info.mapper = "none"; break; + case 0x01: info.mapper = "MBC1"; break; + case 0x02: info.mapper = "MBC1"; info.ram = true; break; + case 0x03: info.mapper = "MBC1"; info.ram = true; info.battery = true; break; + case 0x05: info.mapper = "MBC2"; info.ram = true; break; + case 0x06: info.mapper = "MBC2"; info.ram = true; info.battery = true; break; + case 0x08: info.mapper = "none"; info.ram = true; break; + case 0x09: info.mapper = "MBC0"; info.ram = true; info.battery = true; break; + case 0x0b: info.mapper = "MMM01"; break; + case 0x0c: info.mapper = "MMM01"; info.ram = true; break; + case 0x0d: info.mapper = "MMM01"; info.ram = true; info.battery = true; break; + case 0x0f: info.mapper = "MBC3"; info.rtc = true; info.battery = true; break; + case 0x10: info.mapper = "MBC3"; info.rtc = true; info.ram = true; info.battery = true; break; + case 0x11: info.mapper = "MBC3"; break; + case 0x12: info.mapper = "MBC3"; info.ram = true; break; + case 0x13: info.mapper = "MBC3"; info.ram = true; info.battery = true; break; + case 0x19: info.mapper = "MBC5"; break; + case 0x1a: info.mapper = "MBC5"; info.ram = true; break; + case 0x1b: info.mapper = "MBC5"; info.ram = true; info.battery = true; break; + case 0x1c: info.mapper = "MBC5"; info.rumble = true; break; + case 0x1d: info.mapper = "MBC5"; info.rumble = true; info.ram = true; break; + case 0x1e: info.mapper = "MBC5"; info.rumble = true; info.ram = true; info.battery = true; break; + case 0xfc: break; //Pocket Camera + case 0xfd: break; //Bandai TAMA5 + case 0xfe: info.mapper = "HuC3"; break; + case 0xff: info.mapper = "HuC1"; info.ram = true; info.battery = true; break; + } + + switch(romdata[0x0148]) { default: + case 0x00: info.romsize = 2 * 16 * 1024; break; + case 0x01: info.romsize = 4 * 16 * 1024; break; + case 0x02: info.romsize = 8 * 16 * 1024; break; + case 0x03: info.romsize = 16 * 16 * 1024; break; + case 0x04: info.romsize = 32 * 16 * 1024; break; + case 0x05: info.romsize = 64 * 16 * 1024; break; + case 0x06: info.romsize = 128 * 16 * 1024; break; + case 0x07: info.romsize = 256 * 16 * 1024; break; + case 0x52: info.romsize = 72 * 16 * 1024; break; + case 0x53: info.romsize = 80 * 16 * 1024; break; + case 0x54: info.romsize = 96 * 16 * 1024; break; + } + + switch(romdata[0x0149]) { default: + case 0x00: info.ramsize = 0 * 1024; break; + case 0x01: info.ramsize = 2 * 1024; break; + case 0x02: info.ramsize = 8 * 1024; break; + case 0x03: info.ramsize = 32 * 1024; break; + } + + if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit + + xml << "\n"; + + xml << " \n"; //TODO: trust/check info.romsize? + + if(info.ramsize > 0) + xml << " \n"; + + xml << "\n"; + xml.transform("'", "\""); +} + +} + +#endif diff --git a/snesfilter/nall/input.hpp b/snesfilter/nall/input.hpp index 28b10453..1fd680f4 100755 --- a/snesfilter/nall/input.hpp +++ b/snesfilter/nall/input.hpp @@ -92,7 +92,7 @@ struct Keyboard { string s(name); if(!strbegin(name, "KB")) return 0; s.ltrim("KB"); - unsigned id = strunsigned(s); + unsigned id = decimal(s); auto pos = strpos(s, "::"); if(!pos) return 0; s = substr(s, pos() + 2); @@ -189,7 +189,7 @@ struct Mouse { string s(name); if(!strbegin(name, "MS")) return 0; s.ltrim("MS"); - unsigned id = strunsigned(s); + unsigned id = decimal(s); auto pos = strpos(s, "::"); if(!pos) return 0; s = substr(s, pos() + 2); @@ -313,7 +313,7 @@ struct Joypad { string s(name); if(!strbegin(name, "JP")) return 0; s.ltrim("JP"); - unsigned id = strunsigned(s); + unsigned id = decimal(s); auto pos = strpos(s, "::"); if(!pos) return 0; s = substr(s, pos() + 2); diff --git a/snesfilter/nall/public_cast.hpp b/snesfilter/nall/public_cast.hpp new file mode 100755 index 00000000..331800e1 --- /dev/null +++ b/snesfilter/nall/public_cast.hpp @@ -0,0 +1,32 @@ +#ifndef NALL_PUBLIC_CAST_HPP +#define NALL_PUBLIC_CAST_HPP + +//this is a proof-of-concept-*only* C++ access-privilege elevation exploit. +//this code is 100% legal C++, per C++98 section 14.7.2 paragraph 8: +//"access checking rules do not apply to names in explicit instantiations." +//usage example: + +//struct N { typedef void (Class::*)(); }; +//template class public_cast; +//(class.*public_cast::value); + +//Class::Reference may be public, protected or private +//Class::Reference may be a function, object or variable + +namespace nall { + template struct public_cast; + + template struct public_cast { + static typename T::type value; + }; + + template typename T::type public_cast::value; + + template struct public_cast { + static typename T::type value; + }; + + template typename T::type public_cast::value = public_cast::value = P; +} + +#endif diff --git a/snesfilter/nall/random.hpp b/snesfilter/nall/random.hpp index 74ebc2d2..409c4561 100755 --- a/snesfilter/nall/random.hpp +++ b/snesfilter/nall/random.hpp @@ -8,12 +8,20 @@ namespace nall { return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320); } - struct random_cyclic { - unsigned seed; - inline unsigned operator()() { - return seed = (seed >> 1) ^ (((seed & 1) - 1) & 0xedb88320); + struct random_lfsr { + inline void seed(unsigned seed__) { + seed_ = seed__; } - random_cyclic() : seed(0) {} + + inline unsigned operator()() { + return seed_ = (seed_ >> 1) ^ (((seed_ & 1) - 1) & 0xedb88320); + } + + random_lfsr() : seed_(0) { + } + + private: + unsigned seed_; }; } diff --git a/snesfilter/nall/reference_array.hpp b/snesfilter/nall/reference_array.hpp new file mode 100755 index 00000000..ac47c32b --- /dev/null +++ b/snesfilter/nall/reference_array.hpp @@ -0,0 +1,103 @@ +#ifndef NALL_REFERENCE_ARRAY_HPP +#define NALL_REFERENCE_ARRAY_HPP + +#include +#include +#include + +namespace nall { + template struct reference_array { + protected: + typedef typename std::remove_reference::type *Tptr; + Tptr *pool; + unsigned poolsize, buffersize; + + public: + unsigned size() const { return buffersize; } + unsigned capacity() const { return poolsize; } + + void reset() { + if(pool) free(pool); + pool = 0; + poolsize = 0; + buffersize = 0; + } + + void reserve(unsigned newsize) { + if(newsize == poolsize) return; + + pool = (Tptr*)realloc(pool, newsize * sizeof(T)); + poolsize = newsize; + buffersize = min(buffersize, newsize); + } + + void resize(unsigned newsize) { + if(newsize > poolsize) reserve(bit::round(newsize)); + buffersize = newsize; + } + + void append(const T data) { + unsigned index = buffersize++; + if(index >= poolsize) resize(index + 1); + pool[index] = &data; + } + + template reference_array(Args&... args) : pool(0), poolsize(0), buffersize(0) { + construct(args...); + } + + ~reference_array() { + reset(); + } + + reference_array& operator=(const reference_array &source) { + if(pool) free(pool); + buffersize = source.buffersize; + poolsize = source.poolsize; + pool = (Tptr*)malloc(sizeof(T) * poolsize); + memcpy(pool, source.pool, sizeof(T) * buffersize); + return *this; + } + + reference_array& operator=(const reference_array &&source) { + if(pool) free(pool); + pool = source.pool; + poolsize = source.poolsize; + buffersize = source.buffersize; + source.pool = 0; + source.reset(); + return *this; + } + + inline T operator[](unsigned index) { + if(index >= buffersize) throw "reference_array[] out of bounds"; + return *pool[index]; + } + + inline const T operator[](unsigned index) const { + if(index >= buffersize) throw "reference_array[] out of bounds"; + return *pool[index]; + } + + private: + void construct() { + } + + void construct(const reference_array &source) { + operator=(source); + } + + void construct(const reference_array &&source) { + operator=(std::move(source)); + } + + template void construct(T data, Args&... args) { + append(data); + construct(args...); + } + }; + + template struct has_size> { enum { value = true }; }; +} + +#endif diff --git a/snesfilter/nall/snes/info.hpp b/snesfilter/nall/snes/cartridge.hpp similarity index 83% rename from snesfilter/nall/snes/info.hpp rename to snesfilter/nall/snes/cartridge.hpp index df8b5f59..e3c0e0c5 100755 --- a/snesfilter/nall/snes/info.hpp +++ b/snesfilter/nall/snes/cartridge.hpp @@ -1,13 +1,12 @@ -#ifndef NALL_SNES_INFO_HPP -#define NALL_SNES_INFO_HPP +#ifndef NALL_SNES_CARTRIDGE_HPP +#define NALL_SNES_CARTRIDGE_HPP namespace nall { -class snes_information { +class SNESCartridge { public: - string xml_memory_map; - - inline snes_information(const uint8_t *data, unsigned size); + string xmlMemoryMap; + inline SNESCartridge(const uint8_t *data, unsigned size); //private: inline void read_header(const uint8_t *data, unsigned size); @@ -106,30 +105,30 @@ public: bool has_st018; }; -snes_information::snes_information(const uint8_t *data, unsigned size) { +SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) { read_header(data, size); string xml = "\n"; if(type == TypeBsx) { xml << ""; - xml_memory_map = xml; + xmlMemoryMap = xml.transform("'", "\""); return; } if(type == TypeSufamiTurbo) { xml << ""; - xml_memory_map = xml; + xmlMemoryMap = xml.transform("'", "\""); return; } if(type == TypeGameBoy) { xml << "\n"; if(gameboy_ram_size(data, size) > 0) { - xml << " \n"; + xml << " \n"; } xml << "\n"; - xml_memory_map = xml; + xmlMemoryMap = xml.transform("'", "\""); return; } @@ -146,23 +145,19 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; } else if(type == TypeSuperGameBoy2Bios) { xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; } else if(has_spc7110) { xml << " \n"; xml << " \n"; @@ -172,9 +167,9 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -199,7 +194,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; if(ram_size > 0) { - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { @@ -220,7 +215,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; if(ram_size > 0) { - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { @@ -238,7 +233,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; if(ram_size > 0) { - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -253,7 +248,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; if(ram_size > 0) { - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { @@ -271,7 +266,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -284,19 +279,23 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; } else if(mapper == SA1ROM) { xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; - xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -310,7 +309,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -326,7 +325,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -339,11 +338,14 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; } else if(mapper == BSXROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -360,7 +362,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -370,7 +372,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -380,10 +382,8 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { if(has_srtc) { xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; xml << " \n"; } @@ -401,15 +401,13 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { if(has_cx4) { xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; xml << " \n"; } if(has_dsp1) { - xml << " \n"; + xml << " \n"; if(dsp1_mapper == DSP1LoROM1MB) { xml << " \n"; xml << " \n"; @@ -442,7 +440,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { } if(has_dsp2) { - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -455,7 +453,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { } if(has_dsp3) { - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -468,7 +466,7 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { } if(has_dsp4) { - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -482,46 +480,57 @@ snes_information::snes_information(const uint8_t *data, unsigned size) { if(has_obc1) { xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; xml << " \n"; } if(has_st010) { - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; } if(has_st011) { - //ST-0011 addresses not verified; chip is unsupported - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; } if(has_st018) { xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; + xml << " \n"; + xml << " \n"; xml << " \n"; } xml << "\n"; - xml_memory_map = xml; + xmlMemoryMap = xml.transform("'", "\""); } -void snes_information::read_header(const uint8_t *data, unsigned size) { +void SNESCartridge::read_header(const uint8_t *data, unsigned size) { type = TypeUnknown; mapper = LoROM; dsp1_mapper = DSP1Unmapped; @@ -749,7 +758,7 @@ void snes_information::read_header(const uint8_t *data, unsigned size) { } } -unsigned snes_information::find_header(const uint8_t *data, unsigned size) { +unsigned SNESCartridge::find_header(const uint8_t *data, unsigned size) { unsigned score_lo = score_header(data, size, 0x007fc0); unsigned score_hi = score_header(data, size, 0x00ffc0); unsigned score_ex = score_header(data, size, 0x40ffc0); @@ -764,7 +773,7 @@ unsigned snes_information::find_header(const uint8_t *data, unsigned size) { } } -unsigned snes_information::score_header(const uint8_t *data, unsigned size, unsigned addr) { +unsigned SNESCartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) { if(size < addr + 64) return 0; //image too small to contain header at this location? int score = 0; @@ -845,7 +854,7 @@ unsigned snes_information::score_header(const uint8_t *data, unsigned size, unsi return score; } -unsigned snes_information::gameboy_ram_size(const uint8_t *data, unsigned size) { +unsigned SNESCartridge::gameboy_ram_size(const uint8_t *data, unsigned size) { if(size < 512) return 0; switch(data[0x0149]) { case 0x00: return 0 * 1024; @@ -858,7 +867,7 @@ unsigned snes_information::gameboy_ram_size(const uint8_t *data, unsigned size) } } -bool snes_information::gameboy_has_rtc(const uint8_t *data, unsigned size) { +bool SNESCartridge::gameboy_has_rtc(const uint8_t *data, unsigned size) { if(size < 512) return false; if(data[0x0147] == 0x0f ||data[0x0147] == 0x10) return true; return false; diff --git a/snesfilter/nall/snes/cpu.hpp b/snesfilter/nall/snes/cpu.hpp new file mode 100755 index 00000000..28f5ddb5 --- /dev/null +++ b/snesfilter/nall/snes/cpu.hpp @@ -0,0 +1,458 @@ +#ifndef NALL_SNES_CPU_HPP +#define NALL_SNES_CPU_HPP + +namespace nall { + +struct SNESCPU { + enum : unsigned { + Implied, // + Constant, //#$00 + AccumConstant, //#$00 + IndexConstant, //#$00 + Direct, //$00 + DirectX, //$00,x + DirectY, //$00,y + IDirect, //($00) + IDirectX, //($00,x) + IDirectY, //($00),y + ILDirect, //[$00] + ILDirectY, //[$00],y + Address, //$0000 + AddressX, //$0000,x + AddressY, //$0000,y + IAddressX, //($0000,x) + ILAddress, //[$0000] + PAddress, //PBR:$0000 + PIAddress, //PBR:($0000) + Long, //$000000 + LongX, //$000000,x + Stack, //$00,s + IStackY, //($00,s),y + BlockMove, //$00,$00 + RelativeShort, //+/- $00 + RelativeLong, //+/- $0000 + }; + + struct OpcodeInfo { + char name[4]; + unsigned mode; + }; + + static const OpcodeInfo opcodeInfo[256]; + + static unsigned getOpcodeLength(bool accum, bool index, uint8_t opcode); + static string disassemble(unsigned pc, bool accum, bool index, uint8_t opcode, uint8_t pl, uint8_t ph, uint8_t pb); +}; + +const SNESCPU::OpcodeInfo SNESCPU::opcodeInfo[256] = { + //0x00 - 0x0f + { "brk", Constant }, + { "ora", IDirectX }, + { "cop", Constant }, + { "ora", Stack }, + + { "tsb", Direct }, + { "ora", Direct }, + { "asl", Direct }, + { "ora", ILDirect }, + + { "php", Implied }, + { "ora", AccumConstant }, + { "asl", Implied }, + { "phd", Implied }, + + { "tsb", Address }, + { "ora", Address }, + { "asl", Address }, + { "ora", Long }, + + //0x10 - 0x1f + { "bpl", RelativeShort }, + { "ora", IDirectY }, + { "ora", IDirect }, + { "ora", IStackY }, + + { "trb", Direct }, + { "ora", DirectX }, + { "asl", DirectX }, + { "ora", ILDirectY }, + + { "clc", Implied }, + { "ora", AddressY }, + { "inc", Implied }, + { "tcs", Implied }, + + { "trb", Address }, + { "ora", AddressX }, + { "asl", AddressX }, + { "ora", LongX }, + + //0x20 - 0x2f + { "jsr", Address }, + { "and", IDirectX }, + { "jsl", Long }, + { "and", Stack }, + + { "bit", Direct }, + { "and", Direct }, + { "rol", Direct }, + { "and", ILDirect }, + + { "plp", Implied }, + { "and", AccumConstant }, + { "rol", Implied }, + { "pld", Implied }, + + { "bit", Address }, + { "and", Address }, + { "rol", Address }, + { "and", Long }, + + //0x30 - 0x3f + { "bmi", RelativeShort }, + { "and", IDirectY }, + { "and", IDirect }, + { "and", IStackY }, + + { "bit", DirectX }, + { "and", DirectX }, + { "rol", DirectX }, + { "and", ILDirectY }, + + { "sec", Implied }, + { "and", AddressY }, + { "dec", Implied }, + { "tsc", Implied }, + + { "bit", AddressX }, + { "and", AddressX }, + { "rol", AddressX }, + { "and", LongX }, + + //0x40 - 0x4f + { "rti", Implied }, + { "eor", IDirectX }, + { "wdm", Constant }, + { "eor", Stack }, + + { "mvp", BlockMove }, + { "eor", Direct }, + { "lsr", Direct }, + { "eor", ILDirect }, + + { "pha", Implied }, + { "eor", AccumConstant }, + { "lsr", Implied }, + { "phk", Implied }, + + { "jmp", PAddress }, + { "eor", Address }, + { "lsr", Address }, + { "eor", Long }, + + //0x50 - 0x5f + { "bvc", RelativeShort }, + { "eor", IDirectY }, + { "eor", IDirect }, + { "eor", IStackY }, + + { "mvn", BlockMove }, + { "eor", DirectX }, + { "lsr", DirectX }, + { "eor", ILDirectY }, + + { "cli", Implied }, + { "eor", AddressY }, + { "phy", Implied }, + { "tcd", Implied }, + + { "jml", Long }, + { "eor", AddressX }, + { "lsr", AddressX }, + { "eor", LongX }, + + //0x60 - 0x6f + { "rts", Implied }, + { "adc", IDirectX }, + { "per", Address }, + { "adc", Stack }, + + { "stz", Direct }, + { "adc", Direct }, + { "ror", Direct }, + { "adc", ILDirect }, + + { "pla", Implied }, + { "adc", AccumConstant }, + { "ror", Implied }, + { "rtl", Implied }, + + { "jmp", PIAddress }, + { "adc", Address }, + { "ror", Address }, + { "adc", Long }, + + //0x70 - 0x7f + { "bvs", RelativeShort }, + { "adc", IDirectY }, + { "adc", IDirect }, + { "adc", IStackY }, + + { "stz", DirectX }, + { "adc", DirectX }, + { "ror", DirectX }, + { "adc", ILDirectY }, + + { "sei", Implied }, + { "adc", AddressY }, + { "ply", Implied }, + { "tdc", Implied }, + + { "jmp", IAddressX }, + { "adc", AddressX }, + { "ror", AddressX }, + { "adc", LongX }, + + //0x80 - 0x8f + { "bra", RelativeShort }, + { "sta", IDirectX }, + { "brl", RelativeLong }, + { "sta", Stack }, + + { "sty", Direct }, + { "sta", Direct }, + { "stx", Direct }, + { "sta", ILDirect }, + + { "dey", Implied }, + { "bit", AccumConstant }, + { "txa", Implied }, + { "phb", Implied }, + + { "sty", Address }, + { "sta", Address }, + { "stx", Address }, + { "sta", Long }, + + //0x90 - 0x9f + { "bcc", RelativeShort }, + { "sta", IDirectY }, + { "sta", IDirect }, + { "sta", IStackY }, + + { "sty", DirectX }, + { "sta", DirectX }, + { "stx", DirectY }, + { "sta", ILDirectY }, + + { "tya", Implied }, + { "sta", AddressY }, + { "txs", Implied }, + { "txy", Implied }, + + { "stz", Address }, + { "sta", AddressX }, + { "stz", AddressX }, + { "sta", LongX }, + + //0xa0 - 0xaf + { "ldy", IndexConstant }, + { "lda", IDirectX }, + { "ldx", IndexConstant }, + { "lda", Stack }, + + { "ldy", Direct }, + { "lda", Direct }, + { "ldx", Direct }, + { "lda", ILDirect }, + + { "tay", Implied }, + { "lda", AccumConstant }, + { "tax", Implied }, + { "plb", Implied }, + + { "ldy", Address }, + { "lda", Address }, + { "ldx", Address }, + { "lda", Long }, + + //0xb0 - 0xbf + { "bcs", RelativeShort }, + { "lda", IDirectY }, + { "lda", IDirect }, + { "lda", IStackY }, + + { "ldy", DirectX }, + { "lda", DirectX }, + { "ldx", DirectY }, + { "lda", ILDirectY }, + + { "clv", Implied }, + { "lda", AddressY }, + { "tsx", Implied }, + { "tyx", Implied }, + + { "ldy", AddressX }, + { "lda", AddressX }, + { "ldx", AddressY }, + { "lda", LongX }, + + //0xc0 - 0xcf + { "cpy", IndexConstant }, + { "cmp", IDirectX }, + { "rep", Constant }, + { "cmp", Stack }, + + { "cpy", Direct }, + { "cmp", Direct }, + { "dec", Direct }, + { "cmp", ILDirect }, + + { "iny", Implied }, + { "cmp", AccumConstant }, + { "dex", Implied }, + { "wai", Implied }, + + { "cpy", Address }, + { "cmp", Address }, + { "dec", Address }, + { "cmp", Long }, + + //0xd0 - 0xdf + { "bne", RelativeShort }, + { "cmp", IDirectY }, + { "cmp", IDirect }, + { "cmp", IStackY }, + + { "pei", IDirect }, + { "cmp", DirectX }, + { "dec", DirectX }, + { "cmp", ILDirectY }, + + { "cld", Implied }, + { "cmp", AddressY }, + { "phx", Implied }, + { "stp", Implied }, + + { "jmp", ILAddress }, + { "cmp", AddressX }, + { "dec", AddressX }, + { "cmp", LongX }, + + //0xe0 - 0xef + { "cpx", IndexConstant }, + { "sbc", IDirectX }, + { "sep", Constant }, + { "sbc", Stack }, + + { "cpx", Direct }, + { "sbc", Direct }, + { "inc", Direct }, + { "sbc", ILDirect }, + + { "inx", Implied }, + { "sbc", AccumConstant }, + { "nop", Implied }, + { "xba", Implied }, + + { "cpx", Address }, + { "sbc", Address }, + { "inc", Address }, + { "sbc", Long }, + + //0xf0 - 0xff + { "beq", RelativeShort }, + { "sbc", IDirectY }, + { "sbc", IDirect }, + { "sbc", IStackY }, + + { "pea", Address }, + { "sbc", DirectX }, + { "inc", DirectX }, + { "sbc", ILDirectY }, + + { "sed", Implied }, + { "sbc", AddressY }, + { "plx", Implied }, + { "xce", Implied }, + + { "jsr", IAddressX }, + { "sbc", AddressX }, + { "inc", AddressX }, + { "sbc", LongX }, +}; + +inline unsigned SNESCPU::getOpcodeLength(bool accum, bool index, uint8_t opcode) { + switch(opcodeInfo[opcode].mode) { default: + case Implied: return 1; + case Constant: return 2; + case AccumConstant: return 3 - accum; + case IndexConstant: return 3 - index; + case Direct: return 2; + case DirectX: return 2; + case DirectY: return 2; + case IDirect: return 2; + case IDirectX: return 2; + case IDirectY: return 2; + case ILDirect: return 2; + case ILDirectY: return 2; + case Address: return 3; + case AddressX: return 3; + case AddressY: return 3; + case IAddressX: return 3; + case ILAddress: return 3; + case PAddress: return 3; + case PIAddress: return 3; + case Long: return 4; + case LongX: return 4; + case Stack: return 2; + case IStackY: return 2; + case BlockMove: return 3; + case RelativeShort: return 2; + case RelativeLong: return 3; + } +} + +inline string SNESCPU::disassemble(unsigned pc, bool accum, bool index, uint8_t opcode, uint8_t pl, uint8_t ph, uint8_t pb) { + string name = opcodeInfo[opcode].name; + unsigned mode = opcodeInfo[opcode].mode; + + if(mode == Implied) return name; + if(mode == Constant) return { name, " #$", hex<2>(pl) }; + if(mode == AccumConstant) return { name, " #$", accum ? "" : hex<2>(ph), hex<2>(pl) }; + if(mode == IndexConstant) return { name, " #$", index ? "" : hex<2>(ph), hex<2>(pl) }; + if(mode == Direct) return { name, " $", hex<2>(pl) }; + if(mode == DirectX) return { name, " $", hex<2>(pl), ",x" }; + if(mode == DirectY) return { name, " $", hex<2>(pl), ",y" }; + if(mode == IDirect) return { name, " ($", hex<2>(pl), ")" }; + if(mode == IDirectX) return { name, " ($", hex<2>(pl), ",x)" }; + if(mode == IDirectY) return { name, " ($", hex<2>(pl), "),y" }; + if(mode == ILDirect) return { name, " [$", hex<2>(pl), "]" }; + if(mode == ILDirectY) return { name, " [$", hex<2>(pl), "],y" }; + if(mode == Address) return { name, " $", hex<2>(ph), hex<2>(pl) }; + if(mode == AddressX) return { name, " $", hex<2>(ph), hex<2>(pl), ",x" }; + if(mode == AddressY) return { name, " $", hex<2>(ph), hex<2>(pl), ",y" }; + if(mode == IAddressX) return { name, " ($", hex<2>(ph), hex<2>(pl), ",x)" }; + if(mode == ILAddress) return { name, " [$", hex<2>(ph), hex<2>(pl), "]" }; + if(mode == PAddress) return { name, " $", hex<2>(ph), hex<2>(pl) }; + if(mode == PIAddress) return { name, " ($", hex<2>(ph), hex<2>(pl), ")" }; + if(mode == Long) return { name, " $", hex<2>(pb), hex<2>(ph), hex<2>(pl) }; + if(mode == LongX) return { name, " $", hex<2>(pb), hex<2>(ph), hex<2>(pl), ",x" }; + if(mode == Stack) return { name, " $", hex<2>(pl), ",s" }; + if(mode == IStackY) return { name, " ($", hex<2>(pl), ",s),y" }; + if(mode == BlockMove) return { name, " $", hex<2>(ph), ",$", hex<2>(pl) }; + if(mode == RelativeShort) { + unsigned addr = (pc + 2) + (int8_t)(pl << 0); + return { name, " $", hex<4>(addr) }; + } + if(mode == RelativeLong) { + unsigned addr = (pc + 3) + (int16_t)((ph << 8) + (pl << 0)); + return { name, " $", hex<4>(addr) }; + } + + return ""; +} + +} + +#endif diff --git a/snesfilter/nall/snes/smp.hpp b/snesfilter/nall/snes/smp.hpp new file mode 100755 index 00000000..7a1ac47b --- /dev/null +++ b/snesfilter/nall/snes/smp.hpp @@ -0,0 +1,639 @@ +#ifndef NALL_SNES_SMP_HPP +#define NALL_SNES_SMP_HPP + +namespace nall { + +struct SNESSMP { + enum : unsigned { + Implied, // + TVector, //0 + Direct, //$00 + DirectRelative, //$00,+/-$00 + ADirect, //a,$00 + AAbsolute, //a,$0000 + AIX, //a,(x) + AIDirectX, //a,($00+x) + AConstant, //a,#$00 + DirectDirect, //$00,$00 + CAbsoluteBit, //c,$0000:0 + Absolute, //$0000 + P, //p + AbsoluteA, //$0000,a + Relative, //+/-$00 + ADirectX, //a,$00+x + AAbsoluteX, //a,$0000+x + AAbsoluteY, //a,$0000+y + AIDirectY, //a,($00)+y + DirectConstant, //$00,#$00 + IXIY, //(x),(y) + DirectX, //$00+x + A, //a + X, //x + XAbsolute, //x,$0000 + IAbsoluteX, //($0000+x) + CNAbsoluteBit, //c,!$0000:0 + XDirect, //x,$00 + PVector, //$ff00 + YaDirect, //ya,$00 + XA, //x,a + YAbsolute, //y,$0000 + Y, //y + AX, //a,x + YDirect, //y,$00 + YConstant, //y,#$00 + XSp, //x,sp + YaX, //ya,x + IXPA, //(x)+,a + SpX, //sp,x + AIXP, //a,(x)+ + DirectA, //$00,a + IXA, //(x),a + IDirectXA, //($00+x),a + XConstant, //x,#$00 + AbsoluteX, //$0000,x + AbsoluteBitC, //$0000:0,c + DirectY, //$00,y + AbsoluteY, //$0000,y + Ya, //ya + DirectXA, //$00+x,a + AbsoluteXA, //$0000+x,a + AbsoluteYA, //$0000+y,a + IDirectYA, //($00)+y,a + DirectYX, //$00+y,x + DirectYa, //$00,ya + DirectXY, //$00+x,y + AY, //a,y + DirectXRelative, //$00+x,+/-$00 + XDirectY, //x,$00+y + YDirectX, //y,$00+x + YA, //y,a + YRelative, //y,+/-$00 + }; + + struct OpcodeInfo { + char name[6]; + unsigned mode; + }; + + static const OpcodeInfo opcodeInfo[256]; + + static unsigned getOpcodeLength(uint8_t opcode); + static string disassemble(uint16_t pc, uint8_t opcode, uint8_t pl, uint8_t ph); + static string disassemble(uint16_t pc, bool p, uint8_t opcode, uint8_t pl, uint8_t ph); +}; + +const SNESSMP::OpcodeInfo SNESSMP::opcodeInfo[256] = { + //0x00 - 0x0f + { "nop ", Implied }, + { "tcall", TVector }, + { "set0 ", Direct }, + { "bbs0 ", DirectRelative }, + + { "or ", ADirect }, + { "or ", AAbsolute }, + { "or ", AIX }, + { "or ", AIDirectX }, + + { "or ", AConstant }, + { "or ", DirectDirect }, + { "or1 ", CAbsoluteBit }, + { "asl ", Direct }, + + { "asl ", Absolute }, + { "push ", P }, + { "tset ", AbsoluteA }, + { "brk ", Implied }, + + //0x10 - 0x1f + { "bpl ", Relative }, + { "tcall", TVector }, + { "clr0 ", Direct }, + { "bbc0 ", DirectRelative }, + + { "or ", ADirectX }, + { "or ", AAbsoluteX }, + { "or ", AAbsoluteY }, + { "or ", AIDirectY }, + + { "or ", DirectConstant }, + { "or ", IXIY }, + { "decw ", Direct }, + { "asl ", DirectX }, + + { "asl ", A }, + { "dec ", X }, + { "cmp ", XAbsolute }, + { "jmp ", IAbsoluteX }, + + //0x20 - 0x2f + { "clrp ", Implied }, + { "tcall", TVector }, + { "set1 ", Direct }, + { "bbs1 ", DirectRelative }, + + { "and ", ADirect }, + { "and ", AAbsolute }, + { "and ", AIX }, + { "and ", AIDirectX }, + + { "and ", AConstant }, + { "and ", DirectDirect }, + { "or1 ", CNAbsoluteBit }, + { "rol ", Direct }, + + { "rol ", Absolute }, + { "push ", A }, + { "cbne ", DirectRelative }, + { "bra ", Relative }, + + //0x30 - 0x3f + { "bmi ", Relative }, + { "tcall", TVector }, + { "clr1 ", Direct }, + { "bbc1 ", DirectRelative }, + + { "and ", ADirectX }, + { "and ", AAbsoluteX }, + { "and ", AAbsoluteY }, + { "and ", AIDirectY }, + + { "and ", DirectConstant }, + { "and ", IXIY }, + { "incw ", Direct }, + { "rol ", DirectX }, + + { "rol ", A }, + { "inc ", X }, + { "cmp ", XDirect }, + { "call ", Absolute }, + + //0x40 - 0x4f + { "setp ", Implied }, + { "tcall", TVector }, + { "set2 ", Direct }, + { "bbs2 ", DirectRelative }, + + { "eor ", ADirect }, + { "eor ", AAbsolute }, + { "eor ", AIX }, + { "eor ", AIDirectX }, + + { "eor ", AConstant }, + { "eor ", DirectDirect }, + { "and1 ", CAbsoluteBit }, + { "lsr ", Direct }, + + { "lsr ", Absolute }, + { "push ", X }, + { "tclr ", AbsoluteA }, + { "pcall", PVector }, + + //0x50 - 0x5f + { "bvc ", Relative }, + { "tcall", TVector }, + { "clr2 ", Direct }, + { "bbc2 ", DirectRelative }, + + { "eor ", ADirectX }, + { "eor ", AAbsoluteX }, + { "eor ", AAbsoluteY }, + { "eor ", AIDirectY }, + + { "eor ", DirectConstant }, + { "eor ", IXIY }, + { "cmpw ", YaDirect }, + { "lsr ", DirectX }, + + { "lsr ", A }, + { "mov ", XA }, + { "cmp ", YAbsolute }, + { "jmp ", Absolute }, + + //0x60 - 0x6f + { "clrc ", Implied }, + { "tcall", TVector }, + { "set3 ", Direct }, + { "bbs3 ", DirectRelative }, + + { "cmp ", ADirect }, + { "cmp ", AAbsolute }, + { "cmp ", AIX }, + { "cmp ", AIDirectX }, + + { "cmp ", AConstant }, + { "cmp ", DirectDirect }, + { "and1 ", CNAbsoluteBit }, + { "ror ", Direct }, + + { "ror ", Absolute }, + { "push ", Y }, + { "dbnz ", DirectRelative }, + { "ret ", Implied }, + + //0x70 - 0x7f + { "bvs ", Relative }, + { "tcall", TVector }, + { "clr3 ", Direct }, + { "bbc3 ", DirectRelative }, + + { "cmp ", ADirectX }, + { "cmp ", AAbsoluteX }, + { "cmp ", AAbsoluteY }, + { "cmp ", AIDirectY }, + + { "cmp ", DirectConstant }, + { "cmp ", IXIY }, + { "addw ", YaDirect }, + { "ror ", DirectX }, + + { "ror ", A }, + { "mov ", AX }, + { "cmp ", YDirect }, + { "reti ", Implied }, + + //0x80 - 0x8f + { "setc ", Implied }, + { "tcall", TVector }, + { "set4 ", Direct }, + { "bbs4 ", DirectRelative }, + + { "adc ", ADirect }, + { "adc ", AAbsolute }, + { "adc ", AIX }, + { "adc ", AIDirectX }, + + { "adc ", AConstant }, + { "adc ", DirectDirect }, + { "eor1 ", CAbsoluteBit }, + { "dec ", Direct }, + + { "dec ", Absolute }, + { "mov ", YConstant }, + { "pop ", P }, + { "mov ", DirectConstant }, + + //0x90 - 0x9f + { "bcc ", Relative }, + { "tcall", TVector }, + { "clr4 ", Direct }, + { "bbc4 ", DirectRelative }, + + { "adc ", ADirectX }, + { "adc ", AAbsoluteX }, + { "adc ", AAbsoluteY }, + { "adc ", AIDirectY }, + + { "adc ", DirectRelative }, + { "adc ", IXIY }, + { "subw ", YaDirect }, + { "dec ", DirectX }, + + { "dec ", A }, + { "mov ", XSp }, + { "div ", YaX }, + { "xcn ", A }, + + //0xa0 - 0xaf + { "ei ", Implied }, + { "tcall", TVector }, + { "set5 ", Direct }, + { "bbs5 ", DirectRelative }, + + { "sbc ", ADirect }, + { "sbc ", AAbsolute }, + { "sbc ", AIX }, + { "sbc ", AIDirectX }, + + { "sbc ", AConstant }, + { "sbc ", DirectDirect }, + { "mov1 ", CAbsoluteBit }, + { "inc ", Direct }, + + { "inc ", Absolute }, + { "cmp ", YConstant }, + { "pop ", A }, + { "mov ", IXPA }, + + //0xb0 - 0xbf + { "bcs ", Relative }, + { "tcall", TVector }, + { "clr5 ", Direct }, + { "bbc5 ", DirectRelative }, + + { "sbc ", ADirectX }, + { "sbc ", AAbsoluteX }, + { "sbc ", AAbsoluteY }, + { "sbc ", AIDirectY }, + + { "sbc ", DirectConstant }, + { "sbc ", IXIY }, + { "movw ", YaDirect }, + { "inc ", DirectX }, + + { "inc ", A }, + { "mov ", SpX }, + { "das ", A }, + { "mov ", AIXP }, + + //0xc0 - 0xcf + { "di ", Implied }, + { "tcall", TVector }, + { "set6 ", Direct }, + { "bbs6 ", DirectRelative }, + + { "mov ", DirectA }, + { "mov ", AbsoluteA }, + { "mov ", IXA }, + { "mov ", IDirectXA }, + + { "cmp ", XConstant }, + { "mov ", AbsoluteX }, + { "mov1 ", AbsoluteBitC }, + { "mov ", DirectY }, + + { "mov ", AbsoluteY }, + { "mov ", XConstant }, + { "pop ", X }, + { "mul ", Ya }, + + //0xd0 - 0xdf + { "bne ", Relative }, + { "tcall", TVector }, + { "clr6 ", Relative }, + { "bbc6 ", DirectRelative }, + + { "mov ", DirectXA }, + { "mov ", AbsoluteXA }, + { "mov ", AbsoluteYA }, + { "mov ", IDirectYA }, + + { "mov ", DirectX }, + { "mov ", DirectYX }, + { "movw ", DirectYa }, + { "mov ", DirectXY }, + + { "dec ", Y }, + { "mov ", AY }, + { "cbne ", DirectXRelative }, + { "daa ", A }, + + //0xe0 - 0xef + { "clrv ", Implied }, + { "tcall", TVector }, + { "set7 ", Direct }, + { "bbs7 ", DirectRelative }, + + { "mov ", ADirect }, + { "mov ", AAbsolute }, + { "mov ", AIX }, + { "mov ", AIDirectX }, + + { "mov ", AConstant }, + { "mov ", XAbsolute }, + { "not1 ", CAbsoluteBit }, + { "mov ", YDirect }, + + { "mov ", YAbsolute }, + { "notc ", Implied }, + { "pop ", Y }, + { "sleep", Implied }, + + //0xf0 - 0xff + { "beq ", Relative }, + { "tcall", TVector }, + { "clr7 ", Direct }, + { "bbc7 ", DirectRelative }, + + { "mov ", ADirectX }, + { "mov ", AAbsoluteX }, + { "mov ", AAbsoluteY }, + { "mov ", AIDirectY }, + + { "mov ", XDirect }, + { "mov ", XDirectY }, + { "mov ", DirectDirect }, + { "mov ", YDirectX }, + + { "inc ", Y }, + { "mov ", YA }, + { "dbz ", YRelative }, + { "stop ", Implied }, +}; + +inline unsigned SNESSMP::getOpcodeLength(uint8_t opcode) { + switch(opcodeInfo[opcode].mode) { default: + case Implied: return 1; // + case TVector: return 1; //0 + case Direct: return 2; //$00 + case DirectRelative: return 3; //$00,+/-$00 + case ADirect: return 2; //a,$00 + case AAbsolute: return 3; //a,$0000 + case AIX: return 1; //a,(x) + case AIDirectX: return 2; //a,($00+x) + case AConstant: return 2; //a,#$00 + case DirectDirect: return 3; //$00,$00 + case CAbsoluteBit: return 3; //c,$0000:0 + case Absolute: return 3; //$0000 + case P: return 1; //p + case AbsoluteA: return 3; //$0000,a + case Relative: return 2; //+/-$00 + case ADirectX: return 2; //a,$00+x + case AAbsoluteX: return 3; //a,$0000+x + case AAbsoluteY: return 3; //a,$0000+y + case AIDirectY: return 2; //a,($00)+y + case DirectConstant: return 3; //$00,#$00 + case IXIY: return 1; //(x),(y) + case DirectX: return 2; //$00+x + case A: return 1; //a + case X: return 1; //x + case XAbsolute: return 3; //x,$0000 + case IAbsoluteX: return 3; //($0000+x) + case CNAbsoluteBit: return 3; //c,!$0000:0 + case XDirect: return 2; //x,$00 + case PVector: return 2; //$ff00 + case YaDirect: return 2; //ya,$00 + case XA: return 1; //x,a + case YAbsolute: return 3; //y,$0000 + case Y: return 1; //y + case AX: return 1; //a,x + case YDirect: return 2; //y,$00 + case YConstant: return 2; //y,#$00 + case XSp: return 1; //x,sp + case YaX: return 1; //ya,x + case IXPA: return 1; //(x)+,a + case SpX: return 1; //sp,x + case AIXP: return 1; //a,(x)+ + case DirectA: return 2; //$00,a + case IXA: return 1; //(x),a + case IDirectXA: return 2; //($00+x),a + case XConstant: return 2; //x,#$00 + case AbsoluteX: return 3; //$0000,x + case AbsoluteBitC: return 3; //$0000:0,c + case DirectY: return 2; //$00,y + case AbsoluteY: return 3; //$0000,y + case Ya: return 1; //ya + case DirectXA: return 2; //$00+x,a + case AbsoluteXA: return 3; //$0000+x,a + case AbsoluteYA: return 3; //$0000+y,a + case IDirectYA: return 2; //($00)+y,a + case DirectYX: return 2; //$00+y,x + case DirectYa: return 2; //$00,ya + case DirectXY: return 2; //$00+x,y + case AY: return 1; //a,y + case DirectXRelative: return 3; //$00+x,+/-$00 + case XDirectY: return 2; //x,$00+y + case YDirectX: return 2; //y,$00+x + case YA: return 1; //y,a + case YRelative: return 2; //y,+/-$00 + } +} + +inline string SNESSMP::disassemble(uint16_t pc, uint8_t opcode, uint8_t pl, uint8_t ph) { + string name = opcodeInfo[opcode].name; + unsigned mode = opcodeInfo[opcode].mode; + unsigned pa = (ph << 8) + pl; + + if(mode == Implied) return name; + if(mode == TVector) return { name, " ", opcode >> 4 }; + if(mode == Direct) return { name, " $", hex<2>(pl) }; + if(mode == DirectRelative) return { name, " $", hex<2>(pl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; + if(mode == ADirect) return { name, " a,$", hex<2>(pl) }; + if(mode == AAbsolute) return { name, " a,$", hex<4>(pa) }; + if(mode == AIX) return { name, "a,(x)" }; + if(mode == AIDirectX) return { name, " a,($", hex<2>(pl), "+x)" }; + if(mode == AConstant) return { name, " a,#$", hex<2>(pl) }; + if(mode == DirectDirect) return { name, " $", hex<2>(ph), ",$", hex<2>(pl) }; + if(mode == CAbsoluteBit) return { name, " c,$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; + if(mode == Absolute) return { name, " $", hex<4>(pa) }; + if(mode == P) return { name, " p" }; + if(mode == AbsoluteA) return { name, " $", hex<4>(pa), ",a" }; + if(mode == Relative) return { name, " $", hex<4>(pc + 2 + (int8_t)pl) }; + if(mode == ADirectX) return { name, " a,$", hex<2>(pl), "+x" }; + if(mode == AAbsoluteX) return { name, " a,$", hex<4>(pa), "+x" }; + if(mode == AAbsoluteY) return { name, " a,$", hex<4>(pa), "+y" }; + if(mode == AIDirectY) return { name, " a,($", hex<2>(pl), ")+y" }; + if(mode == DirectConstant) return { name, " $", hex<2>(ph), ",#$", hex<2>(pl) }; + if(mode == IXIY) return { name, " (x),(y)" }; + if(mode == DirectX) return { name, " $", hex<2>(pl), "+x" }; + if(mode == A) return { name, " a" }; + if(mode == X) return { name, " x" }; + if(mode == XAbsolute) return { name, " x,$", hex<4>(pa) }; + if(mode == IAbsoluteX) return { name, " ($", hex<4>(pa), "+x)" }; + if(mode == CNAbsoluteBit) return { name, " c,!$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; + if(mode == XDirect) return { name, " x,$", hex<2>(pl) }; + if(mode == PVector) return { name, " $ff", hex<2>(pl) }; + if(mode == YaDirect) return { name, " ya,$", hex<2>(pl) }; + if(mode == XA) return { name, " x,a" }; + if(mode == YAbsolute) return { name, " y,$", hex<4>(pa) }; + if(mode == Y) return { name, " y" }; + if(mode == AX) return { name, " a,x" }; + if(mode == YDirect) return { name, " y,$", hex<2>(pl) }; + if(mode == YConstant) return { name, " y,#$", hex<2>(pl) }; + if(mode == XSp) return { name, " x,sp" }; + if(mode == YaX) return { name, " ya,x" }; + if(mode == IXPA) return { name, " (x)+,a" }; + if(mode == SpX) return { name, " sp,x" }; + if(mode == AIXP) return { name, " a,(x)+" }; + if(mode == DirectA) return { name, " $", hex<2>(pl), ",a" }; + if(mode == IXA) return { name, " (x),a" }; + if(mode == IDirectXA) return { name, " ($", hex<2>(pl), "+x),a" }; + if(mode == XConstant) return { name, " x,#$", hex<2>(pl) }; + if(mode == AbsoluteX) return { name, " $", hex<4>(pa), ",x" }; + if(mode == AbsoluteBitC) return { name, " $", hex<4>(pa & 0x1fff), ":", pa >> 13, ",c" }; + if(mode == DirectY) return { name, " $", hex<2>(pl), ",y" }; + if(mode == AbsoluteY) return { name, " $", hex<4>(pa), ",y" }; + if(mode == Ya) return { name, " ya" }; + if(mode == DirectXA) return { name, " $", hex<2>(pl), "+x,a" }; + if(mode == AbsoluteXA) return { name, " $", hex<4>(pa), "+x,a" }; + if(mode == AbsoluteYA) return { name, " $", hex<4>(pa), "+y,a" }; + if(mode == IDirectYA) return { name, " ($", hex<2>(pl), ")+y,a" }; + if(mode == DirectYX) return { name, " $", hex<2>(pl), "+y,x" }; + if(mode == DirectYa) return { name, " $", hex<2>(pl), ",ya" }; + if(mode == DirectXY) return { name, " $", hex<2>(pl), "+x,y" }; + if(mode == AY) return { name, " a,y" }; + if(mode == DirectXRelative) return { name, " $", hex<2>(pl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; + if(mode == XDirectY) return { name, " x,$", hex<2>(pl), "+y" }; + if(mode == YDirectX) return { name, " y,$", hex<2>(pl), "+x" }; + if(mode == YA) return { name, " y,a" }; + if(mode == YRelative) return { name, " y,$", hex<4>(pc + 2 + (int8_t)pl) }; + + return ""; +} + +inline string SNESSMP::disassemble(uint16_t pc, bool p, uint8_t opcode, uint8_t pl, uint8_t ph) { + string name = opcodeInfo[opcode].name; + unsigned mode = opcodeInfo[opcode].mode; + unsigned pdl = (p << 8) + pl; + unsigned pdh = (p << 8) + ph; + unsigned pa = (ph << 8) + pl; + + if(mode == Implied) return name; + if(mode == TVector) return { name, " ", opcode >> 4 }; + if(mode == Direct) return { name, " $", hex<3>(pdl) }; + if(mode == DirectRelative) return { name, " $", hex<3>(pdl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; + if(mode == ADirect) return { name, " a,$", hex<3>(pdl) }; + if(mode == AAbsolute) return { name, " a,$", hex<4>(pa) }; + if(mode == AIX) return { name, "a,(x)" }; + if(mode == AIDirectX) return { name, " a,($", hex<3>(pdl), "+x)" }; + if(mode == AConstant) return { name, " a,#$", hex<2>(pl) }; + if(mode == DirectDirect) return { name, " $", hex<3>(pdh), ",$", hex<3>(pdl) }; + if(mode == CAbsoluteBit) return { name, " c,$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; + if(mode == Absolute) return { name, " $", hex<4>(pa) }; + if(mode == P) return { name, " p" }; + if(mode == AbsoluteA) return { name, " $", hex<4>(pa), ",a" }; + if(mode == Relative) return { name, " $", hex<4>(pc + 2 + (int8_t)pl) }; + if(mode == ADirectX) return { name, " a,$", hex<3>(pdl), "+x" }; + if(mode == AAbsoluteX) return { name, " a,$", hex<4>(pa), "+x" }; + if(mode == AAbsoluteY) return { name, " a,$", hex<4>(pa), "+y" }; + if(mode == AIDirectY) return { name, " a,($", hex<3>(pdl), ")+y" }; + if(mode == DirectConstant) return { name, " $", hex<3>(pdh), ",#$", hex<2>(pl) }; + if(mode == IXIY) return { name, " (x),(y)" }; + if(mode == DirectX) return { name, " $", hex<3>(pdl), "+x" }; + if(mode == A) return { name, " a" }; + if(mode == X) return { name, " x" }; + if(mode == XAbsolute) return { name, " x,$", hex<4>(pa) }; + if(mode == IAbsoluteX) return { name, " ($", hex<4>(pa), "+x)" }; + if(mode == CNAbsoluteBit) return { name, " c,!$", hex<4>(pa & 0x1fff), ":", pa >> 13 }; + if(mode == XDirect) return { name, " x,$", hex<3>(pdl) }; + if(mode == PVector) return { name, " $ff", hex<2>(pl) }; + if(mode == YaDirect) return { name, " ya,$", hex<3>(pdl) }; + if(mode == XA) return { name, " x,a" }; + if(mode == YAbsolute) return { name, " y,$", hex<4>(pa) }; + if(mode == Y) return { name, " y" }; + if(mode == AX) return { name, " a,x" }; + if(mode == YDirect) return { name, " y,$", hex<3>(pdl) }; + if(mode == YConstant) return { name, " y,#$", hex<2>(pl) }; + if(mode == XSp) return { name, " x,sp" }; + if(mode == YaX) return { name, " ya,x" }; + if(mode == IXPA) return { name, " (x)+,a" }; + if(mode == SpX) return { name, " sp,x" }; + if(mode == AIXP) return { name, " a,(x)+" }; + if(mode == DirectA) return { name, " $", hex<3>(pdl), ",a" }; + if(mode == IXA) return { name, " (x),a" }; + if(mode == IDirectXA) return { name, " ($", hex<3>(pdl), "+x),a" }; + if(mode == XConstant) return { name, " x,#$", hex<2>(pl) }; + if(mode == AbsoluteX) return { name, " $", hex<4>(pa), ",x" }; + if(mode == AbsoluteBitC) return { name, " $", hex<4>(pa & 0x1fff), ":", pa >> 13, ",c" }; + if(mode == DirectY) return { name, " $", hex<3>(pdl), ",y" }; + if(mode == AbsoluteY) return { name, " $", hex<4>(pa), ",y" }; + if(mode == Ya) return { name, " ya" }; + if(mode == DirectXA) return { name, " $", hex<3>(pdl), "+x,a" }; + if(mode == AbsoluteXA) return { name, " $", hex<4>(pa), "+x,a" }; + if(mode == AbsoluteYA) return { name, " $", hex<4>(pa), "+y,a" }; + if(mode == IDirectYA) return { name, " ($", hex<3>(pdl), ")+y,a" }; + if(mode == DirectYX) return { name, " $", hex<3>(pdl), "+y,x" }; + if(mode == DirectYa) return { name, " $", hex<3>(pdl), ",ya" }; + if(mode == DirectXY) return { name, " $", hex<3>(pdl), "+x,y" }; + if(mode == AY) return { name, " a,y" }; + if(mode == DirectXRelative) return { name, " $", hex<3>(pdl), ",$", hex<4>(pc + 3 + (int8_t)ph) }; + if(mode == XDirectY) return { name, " x,$", hex<3>(pdl), "+y" }; + if(mode == YDirectX) return { name, " y,$", hex<3>(pdl), "+x" }; + if(mode == YA) return { name, " y,a" }; + if(mode == YRelative) return { name, " y,$", hex<4>(pc + 2 + (int8_t)pl) }; + + return ""; +} + +} + +#endif diff --git a/snesfilter/nall/string/base.hpp b/snesfilter/nall/string/base.hpp index 77f15e17..f6172c26 100755 --- a/snesfilter/nall/string/base.hpp +++ b/snesfilter/nall/string/base.hpp @@ -12,20 +12,18 @@ namespace nall { class string; - template inline string to_string(T); + template inline const char* to_string(T); class string { public: inline void reserve(unsigned); - inline string& assign(const char*); - inline string& append(const char*); - inline string& append(bool); - inline string& append(signed int value); - inline string& append(unsigned int value); - inline string& append(double value); + template inline string& assign(Args&&... args); + template inline string& append(Args&&... args); + inline string& assign_(const char*); + inline string& append_(const char*); - inline bool readfile(const char*); + inline bool readfile(const string&); inline string& replace (const char*, const char*); inline string& qreplace(const char*, const char*); @@ -113,11 +111,11 @@ namespace nall { inline char* strlower(char *str); inline char* strupper(char *str); inline char* strtr(char *dest, const char *before, const char *after); - inline uintmax_t strhex (const char *str); - inline intmax_t strsigned (const char *str); - inline uintmax_t strunsigned(const char *str); - inline uintmax_t strbin (const char *str); - inline double strdouble (const char *str); + inline uintmax_t hex (const char *str); + inline intmax_t integer(const char *str); + inline uintmax_t decimal(const char *str); + inline uintmax_t binary (const char *str); + inline double fp (const char *str); //math.hpp inline bool strint (const char *str, int &result); @@ -145,12 +143,17 @@ namespace nall { inline unsigned strlcpy(string &dest, const char *src, unsigned length); inline unsigned strlcat(string &dest, const char *src, unsigned length); inline string substr(const char *src, unsigned start = 0, unsigned length = 0); - template inline string strhex(uintmax_t value); - template inline string strsigned(intmax_t value); - template inline string strunsigned(uintmax_t value); - template inline string strbin(uintmax_t value); - inline unsigned strdouble(char *str, double value); - inline string strdouble(double value); + + inline string integer(intmax_t value); + template inline string linteger(intmax_t value); + template inline string rinteger(intmax_t value); + inline string decimal(uintmax_t value); + template inline string ldecimal(uintmax_t value); + template inline string rdecimal(uintmax_t value); + template inline string hex(uintmax_t value); + template inline string binary(uintmax_t value); + inline unsigned fp(char *str, double value); + inline string fp(double value); //variadic.hpp template inline void print(Args&&... args); diff --git a/snesfilter/nall/string/cast.hpp b/snesfilter/nall/string/cast.hpp index 5b17c408..14f005da 100755 --- a/snesfilter/nall/string/cast.hpp +++ b/snesfilter/nall/string/cast.hpp @@ -4,14 +4,14 @@ namespace nall { //this is needed, as C++0x does not support explicit template specialization inside classes -template<> inline string to_string (bool v) { return v ? "true" : "false"; } -template<> inline string to_string (signed int v) { return strsigned(v); } -template<> inline string to_string (unsigned int v) { return strunsigned(v); } -template<> inline string to_string (double v) { return strdouble(v); } -template<> inline string to_string (char *v) { return v; } -template<> inline string to_string (const char *v) { return v; } -template<> inline string to_string (string v) { return v; } -template<> inline string to_string(const string &v) { return v; } +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 (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; } +template<> inline const char* to_string(const string &v) { return v; } template string& string::operator= (T value) { return assign(to_string(value)); } template string& string::operator<<(T value) { return append(to_string(value)); } @@ -22,8 +22,8 @@ template lstring& lstring::operator<<(T value) { } #if defined(QSTRING_H) -template<> inline string to_string(QString v) { return v.toUtf8().constData(); } -template<> inline string to_string(const QString &v) { return v.toUtf8().constData(); } +template<> inline const char* to_string(QString v) { return v.toUtf8().constData(); } +template<> inline const char* to_string(const QString &v) { return v.toUtf8().constData(); } string::operator QString() const { return QString::fromUtf8(*this); } #endif diff --git a/snesfilter/nall/string/convert.hpp b/snesfilter/nall/string/convert.hpp index 12a6c1ff..603d2e0e 100755 --- a/snesfilter/nall/string/convert.hpp +++ b/snesfilter/nall/string/convert.hpp @@ -40,7 +40,7 @@ char* strtr(char *dest, const char *before, const char *after) { return dest; } -uintmax_t strhex(const char *str) { +uintmax_t hex(const char *str) { if(!str) return 0; uintmax_t result = 0; @@ -60,13 +60,16 @@ uintmax_t strhex(const char *str) { return result; } -intmax_t strsigned(const char *str) { +intmax_t integer(const char *str) { if(!str) return 0; intmax_t result = 0; bool negate = false; - //check for negation - if(*str == '-') { + //check for sign + if(*str == '+') { + negate = false; + str++; + } else if(*str == '-') { negate = true; str++; } @@ -81,7 +84,7 @@ intmax_t strsigned(const char *str) { return !negate ? result : -result; } -uintmax_t strunsigned(const char *str) { +uintmax_t decimal(const char *str) { if(!str) return 0; uintmax_t result = 0; @@ -95,7 +98,7 @@ uintmax_t strunsigned(const char *str) { return result; } -uintmax_t strbin(const char *str) { +uintmax_t binary(const char *str) { if(!str) return 0; uintmax_t result = 0; @@ -113,39 +116,8 @@ uintmax_t strbin(const char *str) { return result; } -double strdouble(const char *str) { - if(!str) return 0.0; - bool negate = false; - - //check for negation - if(*str == '-') { - negate = true; - str++; - } - - intmax_t result_integral = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x == '.' || x == ',') break; //break loop and read fractional part - else return (double)result_integral; //invalid value, assume no fractional part - result_integral = result_integral * 10 + x; - } - - intmax_t result_fractional = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result_fractional = result_fractional * 10 + x; - } - - //calculate fractional portion - double result = (double)result_fractional; - while((uintmax_t)result > 0) result /= 10.0; - result += (double)result_integral; - - return !negate ? result : -result; +double fp(const char *str) { + return atof(str); } } diff --git a/snesfilter/nall/string/core.hpp b/snesfilter/nall/string/core.hpp index bad29030..4ffda4ee 100755 --- a/snesfilter/nall/string/core.hpp +++ b/snesfilter/nall/string/core.hpp @@ -3,6 +3,15 @@ namespace nall { +static void istring(string &output) { +} + +template +static void istring(string &output, const T &value, Args&&... args) { + output.append_(to_string(value)); + istring(output, std::forward(args)...); +} + void string::reserve(unsigned size_) { if(size_ > size) { size = size_; @@ -11,25 +20,31 @@ void string::reserve(unsigned size_) { } } -string& string::assign(const char *s) { +template string& string::assign(Args&&... args) { + *data = 0; + istring(*this, std::forward(args)...); + return *this; +} + +template string& string::append(Args&&... args) { + istring(*this, std::forward(args)...); + return *this; +} + +string& string::assign_(const char *s) { unsigned length = strlen(s); reserve(length); strcpy(data, s); return *this; } -string& string::append(const char *s) { +string& string::append_(const char *s) { unsigned length = strlen(data) + strlen(s); reserve(length); strcat(data, s); return *this; } -string& string::append(bool value) { append(value ? "true" : "false"); return *this; } -string& string::append(signed int value) { append(strsigned(value)); return *this; } -string& string::append(unsigned int value) { append(strunsigned(value)); return *this; } -string& string::append(double value) { append(strdouble(value)); return *this; } - string::operator const char*() const { return data; } @@ -64,15 +79,6 @@ string& string::operator=(string &&source) { return *this; } -static void istring(string &output) { -} - -template -static void istring(string &output, const T &value, Args&&... args) { - output.append(value); - istring(output, std::forward(args)...); -} - template string::string(Args&&... args) { size = 64; data = (char*)malloc(size + 1); @@ -95,7 +101,7 @@ string::~string() { if(data) free(data); } -bool string::readfile(const char *filename) { +bool string::readfile(const string &filename) { assign(""); #if !defined(_WIN32) diff --git a/snesfilter/nall/string/platform.hpp b/snesfilter/nall/string/platform.hpp index 42c1a756..0deda430 100755 --- a/snesfilter/nall/string/platform.hpp +++ b/snesfilter/nall/string/platform.hpp @@ -3,15 +3,15 @@ namespace nall { -string realpath(const char *name) { +string currentpath() { char path[PATH_MAX]; - if(::realpath(name, path)) { + if(::getcwd(path)) { string result(path); result.transform("\\", "/"); if(result.endswith("/") == false) result.append("/"); return result; } - return ""; + return "./"; } string userpath() { @@ -22,18 +22,17 @@ string userpath() { if(result.endswith("/") == false) result.append("/"); return result; } - return ""; + return currentpath(); } -string currentpath() { +string realpath(const char *name) { char path[PATH_MAX]; - if(::getcwd(path)) { + if(::realpath(name, path)) { string result(path); result.transform("\\", "/"); - if(result.endswith("/") == false) result.append("/"); return result; } - return ""; + return userpath(); } } diff --git a/snesfilter/nall/string/utility.hpp b/snesfilter/nall/string/utility.hpp index d2bad881..8e6c1005 100755 --- a/snesfilter/nall/string/utility.hpp +++ b/snesfilter/nall/string/utility.hpp @@ -27,104 +27,202 @@ string substr(const char *src, unsigned start, unsigned length) { /* arithmetic <> string */ -template string strhex(uintmax_t value) { - string output; - unsigned offset = 0; - - //render string backwards, as we do not know its length yet - do { - unsigned n = value & 15; - output[offset++] = n < 10 ? '0' + n : 'a' + n - 10; - value >>= 4; - } while(value); - - while(offset < length) output[offset++] = padding; - output[offset--] = 0; - - //reverse the string in-place - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strsigned(intmax_t value) { - string output; - unsigned offset = 0; - +string integer(intmax_t value) { bool negative = value < 0; if(negative) value = abs(value); - do { - unsigned n = value % 10; - output[offset++] = '0' + n; - value /= 10; - } while(value); - - while(offset < length) output[offset++] = padding; - if(negative) output[offset++] = '-'; - output[offset--] = 0; - - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strunsigned(uintmax_t value) { - string output; - unsigned offset = 0; + char buffer[64]; + unsigned size = 0; do { unsigned n = value % 10; - output[offset++] = '0' + n; + buffer[size++] = '0' + n; value /= 10; } while(value); + buffer[size++] = negative ? '-' : '+'; + buffer[size] = 0; - while(offset < length) output[offset++] = padding; - output[offset--] = 0; + char result[size + 1]; + memset(result, '0', size); + result[size] = 0; - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; + for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) { + result[x] = buffer[y]; } - return output; + return (const char*)result; } -template string strbin(uintmax_t value) { - string output; - unsigned offset = 0; +template string linteger(intmax_t value) { + bool negative = value < 0; + if(negative) value = abs(value); + + char buffer[64]; + unsigned size = 0; + + do { + unsigned n = value % 10; + buffer[size++] = '0' + n; + value /= 10; + } while(value); + buffer[size++] = negative ? '-' : '+'; + buffer[size] = 0; + + unsigned length = (length_ == 0 ? size : length_); + char result[length + 1]; + memset(result, ' ', length); + result[length] = 0; + + for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { + result[x] = buffer[y]; + } + + return (const char*)result; +} + +template string rinteger(intmax_t value) { + bool negative = value < 0; + if(negative) value = abs(value); + + char buffer[64]; + unsigned size = 0; + + do { + unsigned n = value % 10; + buffer[size++] = '0' + n; + value /= 10; + } while(value); + buffer[size++] = negative ? '-' : '+'; + buffer[size] = 0; + + unsigned length = (length_ == 0 ? size : length_); + char result[length + 1]; + memset(result, ' ', length); + result[length] = 0; + + for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { + result[x] = buffer[y]; + } + + return (const char*)result; +} + +string decimal(uintmax_t value) { + char buffer[64]; + unsigned size = 0; + + do { + unsigned n = value % 10; + buffer[size++] = '0' + n; + value /= 10; + } while(value); + buffer[size] = 0; + + char result[size + 1]; + memset(result, '0', size); + result[size] = 0; + + for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) { + result[x] = buffer[y]; + } + + return (const char*)result; +} + +template string ldecimal(uintmax_t value) { + char buffer[64]; + unsigned size = 0; + + do { + unsigned n = value % 10; + buffer[size++] = '0' + n; + value /= 10; + } while(value); + buffer[size] = 0; + + unsigned length = (length_ == 0 ? size : length_); + char result[length + 1]; + memset(result, ' ', length); + result[length] = 0; + + for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { + result[x] = buffer[y]; + } + + return (const char*)result; +} + +template string rdecimal(uintmax_t value) { + char buffer[64]; + unsigned size = 0; + + do { + unsigned n = value % 10; + buffer[size++] = '0' + n; + value /= 10; + } while(value); + buffer[size] = 0; + + unsigned length = (length_ == 0 ? size : length_); + char result[length + 1]; + memset(result, ' ', length); + result[length] = 0; + + for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { + result[x] = buffer[y]; + } + + return (const char*)result; +} + +template string hex(uintmax_t value) { + char buffer[64]; + unsigned size = 0; + + do { + unsigned n = value & 15; + buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10; + value >>= 4; + } while(value); + + unsigned length = (length_ == 0 ? size : length_); + char result[length + 1]; + memset(result, '0', length); + result[length] = 0; + + for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { + result[x] = buffer[y]; + } + + return (const char*)result; +} + +template string binary(uintmax_t value) { + char buffer[256]; + unsigned size = 0; do { unsigned n = value & 1; - output[offset++] = '0' + n; + buffer[size++] = '0' + n; value >>= 1; } while(value); - while(offset < length) output[offset++] = padding; - output[offset--] = 0; + unsigned length = (length_ == 0 ? size : length_); + char result[length + 1]; + memset(result, '0', length); + result[length] = 0; - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; + for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { + result[x] = buffer[y]; } - return output; + return (const char*)result; } //using sprintf is certainly not the most ideal method to convert //a double to a string ... but attempting to parse a double by //hand, digit-by-digit, results in subtle rounding errors. -unsigned strdouble(char *str, double value) { +unsigned fp(char *str, double value) { char buffer[256]; sprintf(buffer, "%f", value); @@ -145,10 +243,10 @@ unsigned strdouble(char *str, double value) { return length + 1; } -string strdouble(double value) { +string fp(double value) { string temp; - temp.reserve(strdouble(0, value)); - strdouble(temp(), value); + temp.reserve(fp(0, value)); + fp(temp(), value); return temp; } diff --git a/snesfilter/nall/varint.hpp b/snesfilter/nall/varint.hpp index fe4732b1..35649896 100755 --- a/snesfilter/nall/varint.hpp +++ b/snesfilter/nall/varint.hpp @@ -8,84 +8,110 @@ namespace nall { template class uint_t { private: - enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value - typedef typename static_if< - sizeof(int) >= bytes, - unsigned int, - typename static_if< - sizeof(long) >= bytes, - unsigned long, - typename static_if< - sizeof(long long) >= bytes, - unsigned long long, - void - >::type - >::type - >::type T; - static_assert(!std::is_same::value, ""); - T data; + unsigned data; public: - inline operator T() const { return data; } - inline T operator ++(int) { T r = data; data = uclip(data + 1); return r; } - inline T operator --(int) { T r = data; data = uclip(data - 1); return r; } - inline T operator ++() { return data = uclip(data + 1); } - inline T operator --() { return data = uclip(data - 1); } - inline T operator =(const T i) { return data = uclip(i); } - inline T operator |=(const T i) { return data = uclip(data | i); } - inline T operator ^=(const T i) { return data = uclip(data ^ i); } - inline T operator &=(const T i) { return data = uclip(data & i); } - inline T operator<<=(const T i) { return data = uclip(data << i); } - inline T operator>>=(const T i) { return data = uclip(data >> i); } - inline T operator +=(const T i) { return data = uclip(data + i); } - inline T operator -=(const T i) { return data = uclip(data - i); } - inline T operator *=(const T i) { return data = uclip(data * i); } - inline T operator /=(const T i) { return data = uclip(data / i); } - inline T operator %=(const T i) { return data = uclip(data % i); } + inline operator unsigned() const { return data; } + inline unsigned operator ++(int) { unsigned r = data; data = uclip(data + 1); return r; } + inline unsigned operator --(int) { unsigned r = data; data = uclip(data - 1); return r; } + inline unsigned operator ++() { return data = uclip(data + 1); } + inline unsigned operator --() { return data = uclip(data - 1); } + inline unsigned operator =(const unsigned i) { return data = uclip(i); } + inline unsigned operator |=(const unsigned i) { return data = uclip(data | i); } + inline unsigned operator ^=(const unsigned i) { return data = uclip(data ^ i); } + inline unsigned operator &=(const unsigned i) { return data = uclip(data & i); } + inline unsigned operator<<=(const unsigned i) { return data = uclip(data << i); } + inline unsigned operator>>=(const unsigned i) { return data = uclip(data >> i); } + inline unsigned operator +=(const unsigned i) { return data = uclip(data + i); } + inline unsigned operator -=(const unsigned i) { return data = uclip(data - i); } + inline unsigned operator *=(const unsigned i) { return data = uclip(data * i); } + inline unsigned operator /=(const unsigned i) { return data = uclip(data / i); } + inline unsigned operator %=(const unsigned i) { return data = uclip(data % i); } inline uint_t() : data(0) {} - inline uint_t(const T i) : data(uclip(i)) {} + inline uint_t(const unsigned i) : data(uclip(i)) {} }; template class int_t { private: - enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value - typedef typename static_if< - sizeof(int) >= bytes, - signed int, - typename static_if< - sizeof(long) >= bytes, - signed long, - typename static_if< - sizeof(long long) >= bytes, - signed long long, - void - >::type - >::type - >::type T; - static_assert(!std::is_same::value, ""); - T data; + signed data; public: - inline operator T() const { return data; } - inline T operator ++(int) { T r = data; data = sclip(data + 1); return r; } - inline T operator --(int) { T r = data; data = sclip(data - 1); return r; } - inline T operator ++() { return data = sclip(data + 1); } - inline T operator --() { return data = sclip(data - 1); } - inline T operator =(const T i) { return data = sclip(i); } - inline T operator |=(const T i) { return data = sclip(data | i); } - inline T operator ^=(const T i) { return data = sclip(data ^ i); } - inline T operator &=(const T i) { return data = sclip(data & i); } - inline T operator<<=(const T i) { return data = sclip(data << i); } - inline T operator>>=(const T i) { return data = sclip(data >> i); } - inline T operator +=(const T i) { return data = sclip(data + i); } - inline T operator -=(const T i) { return data = sclip(data - i); } - inline T operator *=(const T i) { return data = sclip(data * i); } - inline T operator /=(const T i) { return data = sclip(data / i); } - inline T operator %=(const T i) { return data = sclip(data % i); } + inline operator signed() const { return data; } + inline signed operator ++(int) { signed r = data; data = sclip(data + 1); return r; } + inline signed operator --(int) { signed r = data; data = sclip(data - 1); return r; } + inline signed operator ++() { return data = sclip(data + 1); } + inline signed operator --() { return data = sclip(data - 1); } + inline signed operator =(const signed i) { return data = sclip(i); } + inline signed operator |=(const signed i) { return data = sclip(data | i); } + inline signed operator ^=(const signed i) { return data = sclip(data ^ i); } + inline signed operator &=(const signed i) { return data = sclip(data & i); } + inline signed operator<<=(const signed i) { return data = sclip(data << i); } + inline signed operator>>=(const signed i) { return data = sclip(data >> i); } + inline signed operator +=(const signed i) { return data = sclip(data + i); } + inline signed operator -=(const signed i) { return data = sclip(data - i); } + inline signed operator *=(const signed i) { return data = sclip(data * i); } + inline signed operator /=(const signed i) { return data = sclip(data / i); } + inline signed operator %=(const signed i) { return data = sclip(data % i); } inline int_t() : data(0) {} - inline int_t(const T i) : data(sclip(i)) {} + inline int_t(const signed i) : data(sclip(i)) {} + }; + + class varuint_t { + private: + unsigned data; + unsigned mask; + + public: + inline operator unsigned() const { return data; } + inline unsigned operator ++(int) { unsigned r = data; data = (data + 1) & mask; return r; } + inline unsigned operator --(int) { unsigned r = data; data = (data - 1) & mask; return r; } + inline unsigned operator ++() { return data = (data + 1) & mask; } + inline unsigned operator --() { return data = (data - 1) & mask; } + inline unsigned operator =(const unsigned i) { return data = (i) & mask; } + inline unsigned operator |=(const unsigned i) { return data = (data | i) & mask; } + inline unsigned operator ^=(const unsigned i) { return data = (data ^ i) & mask; } + inline unsigned operator &=(const unsigned i) { return data = (data & i) & mask; } + inline unsigned operator<<=(const unsigned i) { return data = (data << i) & mask; } + inline unsigned operator>>=(const unsigned i) { return data = (data >> i) & mask; } + inline unsigned operator +=(const unsigned i) { return data = (data + i) & mask; } + inline unsigned operator -=(const unsigned i) { return data = (data - i) & mask; } + inline unsigned operator *=(const unsigned i) { return data = (data * i) & mask; } + inline unsigned operator /=(const unsigned i) { return data = (data / i) & mask; } + inline unsigned operator %=(const unsigned i) { return data = (data % i) & mask; } + + inline void bits(unsigned bits) { mask = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1); data &= mask; } + inline varuint_t() : data(0), mask(~0U) {} + inline varuint_t(const unsigned i) : data(i), mask(~0U) {} + }; + + class varuintmax_t { + private: + uintmax_t data; + uintmax_t mask; + + public: + inline operator uintmax_t() const { return data; } + inline uintmax_t operator ++(int) { uintmax_t r = data; data = (data + 1) & mask; return r; } + inline uintmax_t operator --(int) { uintmax_t r = data; data = (data - 1) & mask; return r; } + inline uintmax_t operator ++() { return data = (data + 1) & mask; } + inline uintmax_t operator --() { return data = (data - 1) & mask; } + inline uintmax_t operator =(const uintmax_t i) { return data = (i) & mask; } + inline uintmax_t operator |=(const uintmax_t i) { return data = (data | i) & mask; } + inline uintmax_t operator ^=(const uintmax_t i) { return data = (data ^ i) & mask; } + inline uintmax_t operator &=(const uintmax_t i) { return data = (data & i) & mask; } + inline uintmax_t operator<<=(const uintmax_t i) { return data = (data << i) & mask; } + inline uintmax_t operator>>=(const uintmax_t i) { return data = (data >> i) & mask; } + inline uintmax_t operator +=(const uintmax_t i) { return data = (data + i) & mask; } + inline uintmax_t operator -=(const uintmax_t i) { return data = (data - i) & mask; } + inline uintmax_t operator *=(const uintmax_t i) { return data = (data * i) & mask; } + inline uintmax_t operator /=(const uintmax_t i) { return data = (data / i) & mask; } + inline uintmax_t operator %=(const uintmax_t i) { return data = (data % i) & mask; } + + inline void bits(unsigned bits) { mask = (1ULL << (bits - 1)) + ((1ULL << (bits - 1)) - 1); data &= mask; } + inline varuintmax_t() : data(0), mask(~0ULL) {} + inline varuintmax_t(const uintmax_t i) : data(i), mask(~0ULL) {} }; } diff --git a/snesfilter/nall/vector.hpp b/snesfilter/nall/vector.hpp index 543c7b69..c6ef24f2 100755 --- a/snesfilter/nall/vector.hpp +++ b/snesfilter/nall/vector.hpp @@ -46,7 +46,7 @@ namespace nall { void reserve(unsigned newsize) { newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - T *poolcopy = (T*)malloc(newsize * sizeof(T)); + T *poolcopy = (T*)calloc(newsize, sizeof(T)); for(unsigned i = 0; i < min(objectsize, newsize); i++) new(poolcopy + i) T(pool[i]); for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); free(pool); diff --git a/snespurify/cc-gtk.sh b/snespurify/cc-gtk.sh index 5b83e513..30b4e71a 100755 --- a/snespurify/cc-gtk.sh +++ b/snespurify/cc-gtk.sh @@ -1,4 +1,4 @@ g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp `pkg-config --cflags gtk+-2.0` -DPHOENIX_GTK g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp -DPHOENIX_GTK -g++-4.5 -s -o snespurify snespurify.o phoenix.o `pkg-config --libs gtk+-2.0` -lX11 +g++-4.5 -s -o snespurify-gtk snespurify.o phoenix.o `pkg-config --libs gtk+-2.0` -lX11 rm *.o diff --git a/snespurify/cc-qt.sh b/snespurify/cc-qt.sh index 86f34539..6a063a4f 100755 --- a/snespurify/cc-qt.sh +++ b/snespurify/cc-qt.sh @@ -1,5 +1,5 @@ moc -i -o phoenix/qt/qt.moc phoenix/qt/qt.moc.hpp g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp `pkg-config --cflags QtCore QtGui` -DPHOENIX_QT g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp -DPHOENIX_QT -g++-4.5 -s -o snespurify snespurify.o phoenix.o `pkg-config --libs QtCore QtGui` +g++-4.5 -s -o snespurify-qt snespurify.o phoenix.o `pkg-config --libs QtCore QtGui` rm *.o diff --git a/snespurify/cc-windows.bat b/snespurify/cc-windows.bat index 69c2194e..72d3af6f 100755 --- a/snespurify/cc-windows.bat +++ b/snespurify/cc-windows.bat @@ -2,6 +2,5 @@ windres phoenix/windows/phoenix.rc phoenix-resource.o g++ -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp -DPHOENIX_WINDOWS g++ -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp -DPHOENIX_WINDOWS g++ -mwindows -s -o snespurify snespurify.o phoenix.o phoenix-resource.o -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32 -upx --best snespurify.exe @pause @del *.o diff --git a/snespurify/nall/directory.hpp b/snespurify/nall/directory.hpp index df0bf086..c4f94c9a 100755 --- a/snespurify/nall/directory.hpp +++ b/snespurify/nall/directory.hpp @@ -41,14 +41,14 @@ struct directory { if(handle != INVALID_HANDLE_VALUE) { if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = utf8_t(data.cFileName); + string name = (const char*)utf8_t(data.cFileName); if(wildcard(name, pattern)) list.append(string(name, "/")); } } while(FindNextFile(handle, &data) != false) { if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = utf8_t(data.cFileName); + string name = (const char*)utf8_t(data.cFileName); if(wildcard(name, pattern)) list.append(string(name, "/")); } } @@ -70,12 +70,12 @@ struct directory { handle = FindFirstFile(utf16_t(path), &data); if(handle != INVALID_HANDLE_VALUE) { if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = utf8_t(data.cFileName); + string name = (const char*)utf8_t(data.cFileName); if(wildcard(name, pattern)) list.append(name); } while(FindNextFile(handle, &data) != false) { if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = utf8_t(data.cFileName); + string name = (const char*)utf8_t(data.cFileName); if(wildcard(name, pattern)) list.append(name); } } diff --git a/snespurify/nall/filemap.hpp b/snespurify/nall/filemap.hpp index 52acb2fa..5e8cc059 100755 --- a/snespurify/nall/filemap.hpp +++ b/snespurify/nall/filemap.hpp @@ -21,7 +21,7 @@ namespace nall { public: enum class mode : unsigned { read, write, readwrite, writeread }; - bool opened() const { return p_opened(); } + bool open() const { return p_open(); } bool open(const char *filename, mode mode_) { return p_open(filename, mode_); } void close() { return p_close(); } unsigned size() const { return p_size; } @@ -42,7 +42,7 @@ namespace nall { HANDLE p_filehandle, p_maphandle; - bool p_opened() const { + bool p_open() const { return p_handle; } @@ -128,7 +128,7 @@ namespace nall { int p_fd; - bool p_opened() const { + bool p_open() const { return p_handle; } diff --git a/snespurify/nall/random.hpp b/snespurify/nall/random.hpp index 74ebc2d2..409c4561 100755 --- a/snespurify/nall/random.hpp +++ b/snespurify/nall/random.hpp @@ -8,12 +8,20 @@ namespace nall { return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320); } - struct random_cyclic { - unsigned seed; - inline unsigned operator()() { - return seed = (seed >> 1) ^ (((seed & 1) - 1) & 0xedb88320); + struct random_lfsr { + inline void seed(unsigned seed__) { + seed_ = seed__; } - random_cyclic() : seed(0) {} + + inline unsigned operator()() { + return seed_ = (seed_ >> 1) ^ (((seed_ & 1) - 1) & 0xedb88320); + } + + random_lfsr() : seed_(0) { + } + + private: + unsigned seed_; }; } diff --git a/snespurify/nall/snes/cartridge.hpp b/snespurify/nall/snes/cartridge.hpp index 48d32720..e3c0e0c5 100755 --- a/snespurify/nall/snes/cartridge.hpp +++ b/snespurify/nall/snes/cartridge.hpp @@ -362,7 +362,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -372,7 +372,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; diff --git a/snespurify/nall/string/base.hpp b/snespurify/nall/string/base.hpp index 1bc6ca07..f6172c26 100755 --- a/snespurify/nall/string/base.hpp +++ b/snespurify/nall/string/base.hpp @@ -12,18 +12,16 @@ namespace nall { class string; - template inline string to_string(T); + template inline const char* to_string(T); class string { public: inline void reserve(unsigned); - inline string& assign(const char*); - inline string& append(const char*); - inline string& append(bool); - inline string& append(signed int value); - inline string& append(unsigned int value); - inline string& append(double value); + template inline string& assign(Args&&... args); + template inline string& append(Args&&... args); + inline string& assign_(const char*); + inline string& append_(const char*); inline bool readfile(const string&); diff --git a/snespurify/nall/string/cast.hpp b/snespurify/nall/string/cast.hpp index d8503106..14f005da 100755 --- a/snespurify/nall/string/cast.hpp +++ b/snespurify/nall/string/cast.hpp @@ -4,14 +4,14 @@ namespace nall { //this is needed, as C++0x does not support explicit template specialization inside classes -template<> inline string to_string (bool v) { return v ? "true" : "false"; } -template<> inline string to_string (signed int v) { return integer(v); } -template<> inline string to_string (unsigned int v) { return decimal(v); } -template<> inline string to_string (double v) { return fp(v); } -template<> inline string to_string (char *v) { return v; } -template<> inline string to_string (const char *v) { return v; } -template<> inline string to_string (string v) { return v; } -template<> inline string to_string(const string &v) { return v; } +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 (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; } +template<> inline const char* to_string(const string &v) { return v; } template string& string::operator= (T value) { return assign(to_string(value)); } template string& string::operator<<(T value) { return append(to_string(value)); } @@ -22,8 +22,8 @@ template lstring& lstring::operator<<(T value) { } #if defined(QSTRING_H) -template<> inline string to_string(QString v) { return v.toUtf8().constData(); } -template<> inline string to_string(const QString &v) { return v.toUtf8().constData(); } +template<> inline const char* to_string(QString v) { return v.toUtf8().constData(); } +template<> inline const char* to_string(const QString &v) { return v.toUtf8().constData(); } string::operator QString() const { return QString::fromUtf8(*this); } #endif diff --git a/snespurify/nall/string/convert.hpp b/snespurify/nall/string/convert.hpp index ca77db85..603d2e0e 100755 --- a/snespurify/nall/string/convert.hpp +++ b/snespurify/nall/string/convert.hpp @@ -117,38 +117,7 @@ uintmax_t binary(const char *str) { } double fp(const char *str) { - if(!str) return 0.0; - bool negate = false; - - //check for negation - if(*str == '-') { - negate = true; - str++; - } - - intmax_t result_integral = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x == '.' || x == ',') break; //break loop and read fractional part - else return (double)result_integral; //invalid value, assume no fractional part - result_integral = result_integral * 10 + x; - } - - intmax_t result_fractional = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result_fractional = result_fractional * 10 + x; - } - - //calculate fractional portion - double result = (double)result_fractional; - while((uintmax_t)result > 0) result /= 10.0; - result += (double)result_integral; - - return !negate ? result : -result; + return atof(str); } } diff --git a/snespurify/nall/string/core.hpp b/snespurify/nall/string/core.hpp index b04078d1..4ffda4ee 100755 --- a/snespurify/nall/string/core.hpp +++ b/snespurify/nall/string/core.hpp @@ -3,6 +3,15 @@ namespace nall { +static void istring(string &output) { +} + +template +static void istring(string &output, const T &value, Args&&... args) { + output.append_(to_string(value)); + istring(output, std::forward(args)...); +} + void string::reserve(unsigned size_) { if(size_ > size) { size = size_; @@ -11,25 +20,31 @@ void string::reserve(unsigned size_) { } } -string& string::assign(const char *s) { +template string& string::assign(Args&&... args) { + *data = 0; + istring(*this, std::forward(args)...); + return *this; +} + +template string& string::append(Args&&... args) { + istring(*this, std::forward(args)...); + return *this; +} + +string& string::assign_(const char *s) { unsigned length = strlen(s); reserve(length); strcpy(data, s); return *this; } -string& string::append(const char *s) { +string& string::append_(const char *s) { unsigned length = strlen(data) + strlen(s); reserve(length); strcat(data, s); return *this; } -string& string::append(bool value) { append(value ? "true" : "false"); return *this; } -string& string::append(signed int value) { append(integer(value)); return *this; } -string& string::append(unsigned int value) { append(decimal(value)); return *this; } -string& string::append(double value) { append(fp(value)); return *this; } - string::operator const char*() const { return data; } @@ -64,15 +79,6 @@ string& string::operator=(string &&source) { return *this; } -static void istring(string &output) { -} - -template -static void istring(string &output, const T &value, Args&&... args) { - output.append(value); - istring(output, std::forward(args)...); -} - template string::string(Args&&... args) { size = 64; data = (char*)malloc(size + 1); diff --git a/snespurify/nall/string/platform.hpp b/snespurify/nall/string/platform.hpp index 42c1a756..0deda430 100755 --- a/snespurify/nall/string/platform.hpp +++ b/snespurify/nall/string/platform.hpp @@ -3,15 +3,15 @@ namespace nall { -string realpath(const char *name) { +string currentpath() { char path[PATH_MAX]; - if(::realpath(name, path)) { + if(::getcwd(path)) { string result(path); result.transform("\\", "/"); if(result.endswith("/") == false) result.append("/"); return result; } - return ""; + return "./"; } string userpath() { @@ -22,18 +22,17 @@ string userpath() { if(result.endswith("/") == false) result.append("/"); return result; } - return ""; + return currentpath(); } -string currentpath() { +string realpath(const char *name) { char path[PATH_MAX]; - if(::getcwd(path)) { + if(::realpath(name, path)) { string result(path); result.transform("\\", "/"); - if(result.endswith("/") == false) result.append("/"); return result; } - return ""; + return userpath(); } } diff --git a/snespurify/phoenix/core/core.cpp b/snespurify/phoenix/core/core.cpp index b1f2ac68..ddb868cb 100755 --- a/snespurify/phoenix/core/core.cpp +++ b/snespurify/phoenix/core/core.cpp @@ -26,6 +26,7 @@ void OS::processEvents() { return pOS::processEvents(); } void OS::quit() { return pOS::quit(); } void OS::initialize() { static bool initialized = false; if(initialized == false) { initialized = true; return pOS::initialize(); } } +Geometry Font::geometry(const string &text) { return p.geometry(text); } void Font::setBold(bool bold) { state.bold = bold; return p.setBold(bold); } void Font::setFamily(const string &family) { state.family = family; return p.setFamily(family); } void Font::setItalic(bool italic) { state.italic = italic; return p.setItalic(italic); } @@ -80,13 +81,15 @@ void CheckItem::setChecked(bool checked) { state.checked = checked; return p.set void CheckItem::setText(const string &text) { state.text = text; return p.setText(text); } CheckItem::CheckItem() : state(*new State), base_from_member(*new pCheckItem(*this)), Action(base_from_member::value), p(base_from_member::value) { p.constructor(); } -void RadioItem::group_(const reference_array &list) { foreach(item, list) item.p.setGroup(item.state.group = list); if(list.size()) list[0].setChecked(); } +void RadioItem::group(const reference_array &list) { foreach(item, list) item.p.setGroup(item.state.group = list); if(list.size()) list[0].setChecked(); } bool RadioItem::checked() { return p.checked(); } void RadioItem::setChecked() { foreach(item, state.group) item.state.checked = false; state.checked = true; return p.setChecked(); } void RadioItem::setText(const string &text) { state.text = text; return p.setText(text); } RadioItem::RadioItem() : state(*new State), base_from_member(*new pRadioItem(*this)), Action(base_from_member::value), p(base_from_member::value) { p.constructor(); } bool Widget::enabled() { return state.enabled; } +Font& Widget::font() { return p.font(); } +Geometry Widget::minimumGeometry() { return p.minimumGeometry(); } void Widget::setEnabled(bool enabled) { state.enabled = enabled; return p.setEnabled(enabled); } void Widget::setFocused() { return p.setFocused(); } void Widget::setFont(Font &font) { state.font = &font; return p.setFont(font); } @@ -99,6 +102,10 @@ Widget::Widget(pWidget &p) : state(*new State), p(p) { p.constructor(); } void Button::setText(const string &text) { state.text = text; return p.setText(text); } Button::Button() : state(*new State), base_from_member(*new pButton(*this)), Widget(base_from_member::value), p(base_from_member::value) { p.constructor(); } +uint32_t* Canvas::buffer() { return p.buffer(); } +void Canvas::update() { return p.update(); } +Canvas::Canvas() : base_from_member(*new pCanvas(*this)), Widget(base_from_member::value), p(base_from_member::value) { p.constructor(); } + bool CheckBox::checked() { return p.checked(); } void CheckBox::setChecked(bool checked) { state.checked = checked; return p.setChecked(checked); } void CheckBox::setText(const string &text) { state.text = text; return p.setText(text); } @@ -148,7 +155,7 @@ ListView::ListView() : state(*new State), base_from_member(*new pLis void ProgressBar::setPosition(unsigned position) { state.position = position; return p.setPosition(position); } ProgressBar::ProgressBar() : state(*new State), base_from_member(*new pProgressBar(*this)), Widget(base_from_member::value), p(base_from_member::value) { p.constructor(); } -void RadioBox::group_(const reference_array &list) { foreach(item, list) item.p.setGroup(item.state.group = list); if(list.size()) list[0].setChecked(); } +void RadioBox::group(const reference_array &list) { foreach(item, list) item.p.setGroup(item.state.group = list); if(list.size()) list[0].setChecked(); } bool RadioBox::checked() { return p.checked(); } void RadioBox::setChecked() { foreach(item, state.group) item.state.checked = false; state.checked = true; return p.setChecked(); } void RadioBox::setText(const string &text) { state.text = text; return p.setText(text); } diff --git a/snespurify/phoenix/core/core.hpp b/snespurify/phoenix/core/core.hpp index d6ab585d..2f087b42 100755 --- a/snespurify/phoenix/core/core.hpp +++ b/snespurify/phoenix/core/core.hpp @@ -16,6 +16,7 @@ struct pRadioItem; struct pLayout; struct pWidget; struct pButton; +struct pCanvas; struct pCheckBox; struct pComboBox; struct pHexEdit; @@ -29,6 +30,11 @@ struct pTextEdit; struct pVerticalSlider; struct pViewport; +enum : unsigned { + MaximumSize = ~0u, + MinimumSize = 0u, +}; + struct Geometry { signed x, y; unsigned width, height; @@ -63,6 +69,7 @@ private: }; struct Font : Object { + Geometry geometry(const nall::string &text); void setBold(bool bold = true); void setFamily(const nall::string &family); void setItalic(bool italic = true); @@ -179,7 +186,8 @@ struct CheckItem : private nall::base_from_member, Action { }; struct RadioItem : private nall::base_from_member, Action { - template static void group(Args&... args) { group_({ args... }); } + template static void group(Args&... args) { group({ args... }); } + static void group(const nall::reference_array &list); nall::function onTick; @@ -191,19 +199,18 @@ struct RadioItem : private nall::base_from_member, Action { struct State; State &state; pRadioItem &p; - -private: - static void group_(const nall::reference_array &list); }; struct Layout : Object { - virtual void setGeometry(Geometry &geometry) = 0; + virtual void setGeometry(const Geometry &geometry) = 0; virtual void setParent(Window &parent) = 0; virtual void setVisible(bool visible = true) = 0; }; struct Widget : Object { bool enabled(); + Font& font(); + Geometry minimumGeometry(); void setEnabled(bool enabled = true); void setFocused(); void setFont(Font &font); @@ -229,6 +236,14 @@ struct Button : private nall::base_from_member, Widget { pButton &p; }; +struct Canvas : private nall::base_from_member, Widget { + uint32_t* buffer(); + void update(); + + Canvas(); + pCanvas &p; +}; + struct CheckBox : private nall::base_from_member, Widget { nall::function onTick; @@ -348,7 +363,8 @@ struct ProgressBar : private nall::base_from_member, Widget { }; struct RadioBox : private nall::base_from_member, Widget { - template static void group(Args&... args) { group_({ args... }); } + template static void group(Args&... args) { group({ args... }); } + static void group(const nall::reference_array &list); nall::function onTick; @@ -360,9 +376,6 @@ struct RadioBox : private nall::base_from_member, Widget { struct State; State &state; pRadioBox &p; - -private: - static void group_(const nall::reference_array &list); }; struct TextEdit : private nall::base_from_member, Widget { diff --git a/snespurify/phoenix/core/layout/fixed-layout.cpp b/snespurify/phoenix/core/layout/fixed-layout.cpp index a1c0c093..a9b9628e 100755 --- a/snespurify/phoenix/core/layout/fixed-layout.cpp +++ b/snespurify/phoenix/core/layout/fixed-layout.cpp @@ -9,7 +9,7 @@ void FixedLayout::append(Widget &widget, const Geometry &geometry) { children.append({ &widget, geometry }); } -void FixedLayout::setGeometry(Geometry &geometry) { +void FixedLayout::setGeometry(const Geometry &geometry) { } void FixedLayout::setVisible(bool visible) { diff --git a/snespurify/phoenix/core/layout/fixed-layout.hpp b/snespurify/phoenix/core/layout/fixed-layout.hpp index 14f90f76..9b4be043 100755 --- a/snespurify/phoenix/core/layout/fixed-layout.hpp +++ b/snespurify/phoenix/core/layout/fixed-layout.hpp @@ -1,6 +1,6 @@ struct FixedLayout : Layout { void append(Widget &widget, const Geometry &geometry); - void setGeometry(Geometry &geometry); + void setGeometry(const Geometry &geometry); void setParent(Window &parent); void setVisible(bool visible); FixedLayout(); diff --git a/snespurify/phoenix/core/layout/horizontal-layout.cpp b/snespurify/phoenix/core/layout/horizontal-layout.cpp index 9fa43139..7e4336f2 100755 --- a/snespurify/phoenix/core/layout/horizontal-layout.cpp +++ b/snespurify/phoenix/core/layout/horizontal-layout.cpp @@ -1,77 +1,130 @@ -void HorizontalLayout::setParent(Window &parent) { - foreach(child, children) { - if(child.layout) child.layout->setParent(parent); - if(child.widget) parent.append(*child.widget); - } -} - -void HorizontalLayout::append(VerticalLayout &layout, unsigned width, unsigned height, unsigned spacing) { - layout.width = width; - layout.height = height; - children.append({ &layout, 0, width, height, spacing }); +void HorizontalLayout::append(VerticalLayout &layout, unsigned spacing) { + children.append({ &layout, 0, MinimumSize, MinimumSize, spacing }); } void HorizontalLayout::append(Widget &widget, unsigned width, unsigned height, unsigned spacing) { children.append({ 0, &widget, width, height, spacing }); } -void HorizontalLayout::setGeometry(Geometry &geometry) { - geometry.x += margin; - geometry.y += margin; - geometry.width -= margin * 2; - geometry.height -= margin * 2; +Geometry HorizontalLayout::minimumGeometry() { + unsigned width = 0, height = 0; - unsigned geometryWidth = width ? width : geometry.width; - unsigned geometryHeight = height ? height : geometry.height; - - Geometry baseGeometry = geometry; - linear_vector children = this->children; - - unsigned minimumWidth = 0; - foreach(child, children) minimumWidth += child.width + child.spacing; - - unsigned autosizeWidgets = 0; foreach(child, children) { - if(child.width == 0) autosizeWidgets++; - } - foreach(child, children) { - if(child.width == 0) child.width = (geometryWidth - minimumWidth) / autosizeWidgets; - if(child.height == 0) child.height = geometryHeight; + width += child.spacing; + if(child.width == MinimumSize || child.width == MaximumSize) { + if(child.layout) width += child.layout->minimumGeometry().width; + if(child.widget) width += child.widget->minimumGeometry().width; + continue; + } + width += child.width; } - unsigned maxHeight = 0; foreach(child, children) { - maxHeight = max(maxHeight, child.height); + if(child.height == MinimumSize || child.height == MaximumSize) { + if(child.layout) height = max(height, child.layout->minimumGeometry().height); + if(child.widget) height = max(height, child.widget->minimumGeometry().height); + continue; + } + height = max(height, child.height); } + return { 0, 0, margin * 2 + width, margin * 2 + height }; +} + +Geometry HorizontalLayout::minimumLayoutGeometry() { + unsigned width = 0, height = 0; + bool maximumWidth = false; + bool maximumHeight = false; + + foreach(child, children) { + if(child.width == MaximumSize) { + maximumWidth = true; + break; + } + + if(child.width == MinimumSize) { + if(child.layout) width += child.layout->minimumGeometry().width; + if(child.widget) width += child.widget->minimumGeometry().width; + continue; + } + + width += child.width; + } + + foreach(child, children) { + if(child.height == MaximumSize) { + maximumHeight = true; + break; + } + + if(child.height == MinimumSize) { + if(child.layout) height = max(height, child.layout->minimumGeometry().height); + if(child.widget) height = max(height, child.widget->minimumGeometry().height); + continue; + } + + height = max(height, child.height); + } + + return { 0, 0, maximumWidth ? MaximumSize : margin * 2 + width, maximumHeight ? MaximumSize : margin * 2 + height }; +} + +void HorizontalLayout::setGeometry(const Geometry &containerGeometry) { + auto children = this->children; foreach(child, children) { if(child.layout) { - child.layout->setGeometry(geometry); - geometry.x += child.spacing; - geometry.width -= child.spacing; - geometry.y = baseGeometry.y; - geometry.height = baseGeometry.height; + child.width = child.layout->minimumLayoutGeometry().width; + child.height = child.layout->minimumLayoutGeometry().height; } if(child.widget) { - child.widget->setGeometry({ geometry.x, geometry.y, child.width, child.height }); - geometry.x += child.width + child.spacing; - geometry.width -= child.width + child.spacing; + if(child.width == MinimumSize) child.width = child.widget->minimumGeometry().width; + if(child.height == MinimumSize) child.height = child.widget->minimumGeometry().height; } } - geometry.y += maxHeight; - geometry.height -= maxHeight; + Geometry geometry = containerGeometry; + geometry.x += margin; + geometry.y += margin; + geometry.width -= margin * 2; + geometry.height -= margin * 2; + + unsigned minimumWidth = 0, maximumWidthCounter = 0; + foreach(child, children) { + if(child.width == MaximumSize) maximumWidthCounter++; + if(child.width != MaximumSize) minimumWidth += child.width; + minimumWidth += child.spacing; + } + + foreach(child, children) { + if(child.width == MaximumSize) child.width = (geometry.width - minimumWidth) / maximumWidthCounter; + if(child.height == MaximumSize) child.height = geometry.height; + } + + unsigned maximumHeight = 0; + foreach(child, children) maximumHeight = max(maximumHeight, child.height); + + foreach(child, children) { + unsigned pivot = (maximumHeight - child.height) / 2; + Geometry childGeometry = { geometry.x, geometry.y + pivot, child.width, child.height }; + + if(child.layout) child.layout->setGeometry(childGeometry); + if(child.widget) child.widget->setGeometry(childGeometry); + + geometry.x += child.width + child.spacing; + geometry.width -= child.width + child.spacing; + } } -void HorizontalLayout::setMargin(unsigned margin_) { - margin = margin_; +void HorizontalLayout::setMargin(unsigned margin) { + this->margin = margin; } -unsigned HorizontalLayout::minimumWidth() { - unsigned width = margin * 2; - foreach(child, children) width += child.width + child.spacing; - return width; +void HorizontalLayout::setParent(Window &parent) { + foreach(child, children) { + if(child.layout) child.layout->setParent(parent); + if(child.widget) parent.append(*child.widget); + } } void HorizontalLayout::setVisible(bool visible) { @@ -83,6 +136,4 @@ void HorizontalLayout::setVisible(bool visible) { HorizontalLayout::HorizontalLayout() { margin = 0; - width = 0; - height = 0; } diff --git a/snespurify/phoenix/core/layout/horizontal-layout.hpp b/snespurify/phoenix/core/layout/horizontal-layout.hpp index 2fd3c45a..d8faf3f5 100755 --- a/snespurify/phoenix/core/layout/horizontal-layout.hpp +++ b/snespurify/phoenix/core/layout/horizontal-layout.hpp @@ -1,10 +1,11 @@ struct VerticalLayout; struct HorizontalLayout : public Layout { - void append(VerticalLayout &layout, unsigned width, unsigned height, unsigned spacing = 0); + void append(VerticalLayout &layout, unsigned spacing = 0); void append(Widget &widget, unsigned width, unsigned height, unsigned spacing = 0); - unsigned minimumWidth(); - void setGeometry(Geometry &geometry); + Geometry minimumLayoutGeometry(); + Geometry minimumGeometry(); + void setGeometry(const Geometry &geometry); void setMargin(unsigned margin); void setParent(Window &parent); void setVisible(bool visible); @@ -12,8 +13,6 @@ struct HorizontalLayout : public Layout { //private: unsigned margin; - unsigned width; - unsigned height; struct Children { VerticalLayout *layout; Widget *widget; diff --git a/snespurify/phoenix/core/layout/vertical-layout.cpp b/snespurify/phoenix/core/layout/vertical-layout.cpp index 0bebb14b..373c8249 100755 --- a/snespurify/phoenix/core/layout/vertical-layout.cpp +++ b/snespurify/phoenix/core/layout/vertical-layout.cpp @@ -1,77 +1,130 @@ -void VerticalLayout::setParent(Window &parent) { - foreach(child, children) { - if(child.layout) child.layout->setParent(parent); - if(child.widget) parent.append(*child.widget); - } -} - -void VerticalLayout::append(HorizontalLayout &layout, unsigned width, unsigned height, unsigned spacing) { - layout.width = width; - layout.height = height; - children.append({ &layout, 0, width, height, spacing }); +void VerticalLayout::append(HorizontalLayout &layout, unsigned spacing) { + children.append({ &layout, 0, MinimumSize, MinimumSize, spacing }); } void VerticalLayout::append(Widget &widget, unsigned width, unsigned height, unsigned spacing) { children.append({ 0, &widget, width, height, spacing }); } -void VerticalLayout::setGeometry(Geometry &geometry) { - geometry.x += margin; - geometry.y += margin; - geometry.width -= margin * 2; - geometry.height -= margin * 2; +Geometry VerticalLayout::minimumGeometry() { + unsigned width = 0, height = 0; - unsigned geometryWidth = width ? width : geometry.width; - unsigned geometryHeight = height ? height : geometry.height; - - Geometry baseGeometry = geometry; - linear_vector children = this->children; - - unsigned minimumHeight = 0; - foreach(child, children) minimumHeight += child.height + child.spacing; - - unsigned autosizeWidgets = 0; foreach(child, children) { - if(child.height == 0) autosizeWidgets++; - } - foreach(child, children) { - if(child.width == 0) child.width = geometryWidth; - if(child.height == 0) child.height = (geometryHeight - minimumHeight) / autosizeWidgets; + if(child.width == MinimumSize || child.width == MaximumSize) { + if(child.layout) width = max(width, child.layout->minimumGeometry().width); + if(child.widget) width = max(width, child.widget->minimumGeometry().width); + continue; + } + width = max(width, child.width); } - unsigned maxWidth = 0; foreach(child, children) { - maxWidth = max(maxWidth, child.width); + height += child.spacing; + if(child.height == MinimumSize || child.height == MaximumSize) { + if(child.layout) height += child.layout->minimumGeometry().height; + if(child.widget) height += child.widget->minimumGeometry().height; + continue; + } + height += child.height; } + return { 0, 0, margin * 2 + width, margin * 2 + height }; +} + +Geometry VerticalLayout::minimumLayoutGeometry() { + unsigned width = 0, height = 0; + bool maximumWidth = false; + bool maximumHeight = false; + + foreach(child, children) { + if(child.width == MaximumSize) { + maximumWidth = true; + break; + } + + if(child.width == MinimumSize) { + if(child.layout) width = max(width, child.layout->minimumGeometry().width); + if(child.widget) width = max(width, child.widget->minimumGeometry().width); + continue; + } + + width = max(width, child.width); + } + + foreach(child, children) { + if(child.height == MaximumSize) { + maximumHeight = true; + break; + } + + if(child.height == MinimumSize) { + if(child.layout) height += child.layout->minimumGeometry().height; + if(child.widget) height += child.widget->minimumGeometry().height; + continue; + } + + height += child.height; + } + + return { 0, 0, maximumWidth ? MaximumSize : margin * 2 + width, maximumHeight ? MaximumSize : margin * 2 + height }; +} + +void VerticalLayout::setGeometry(const Geometry &containerGeometry) { + auto children = this->children; foreach(child, children) { if(child.layout) { - child.layout->setGeometry(geometry); - geometry.x = baseGeometry.x; - geometry.width = baseGeometry.width; - geometry.y += child.spacing; - geometry.height -= child.spacing; + child.width = child.layout->minimumLayoutGeometry().width; + child.height = child.layout->minimumLayoutGeometry().height; } if(child.widget) { - child.widget->setGeometry({ geometry.x, geometry.y, child.width, child.height }); - geometry.y += child.height + child.spacing; - geometry.height -= child.height + child.spacing; + if(child.width == MinimumSize) child.width = child.widget->minimumGeometry().width; + if(child.height == MinimumSize) child.height = child.widget->minimumGeometry().height; } } - geometry.x += maxWidth; - geometry.width -= maxWidth; + Geometry geometry = containerGeometry; + geometry.x += margin; + geometry.y += margin; + geometry.width -= margin * 2; + geometry.height -= margin * 2; + + unsigned minimumHeight = 0, maximumHeightCounter = 0; + foreach(child, children) { + if(child.height == MaximumSize) maximumHeightCounter++; + if(child.height != MaximumSize) minimumHeight += child.height; + minimumHeight += child.spacing; + } + + foreach(child, children) { + if(child.width == MaximumSize) child.width = geometry.width; + if(child.height == MaximumSize) child.height = (geometry.height - minimumHeight) / maximumHeightCounter; + } + + unsigned maximumWidth = 0; + foreach(child, children) maximumWidth = max(maximumWidth, child.width); + + foreach(child, children) { + unsigned pivot = 0; //(maximumWidth - child.width) / 2; + Geometry childGeometry = { geometry.x + pivot, geometry.y, child.width, child.height }; + + if(child.layout) child.layout->setGeometry(childGeometry); + if(child.widget) child.widget->setGeometry(childGeometry); + + geometry.y += child.height + child.spacing; + geometry.height -= child.height + child.spacing; + } } -void VerticalLayout::setMargin(unsigned margin_) { - margin = margin_; +void VerticalLayout::setMargin(unsigned margin) { + this->margin = margin; } -unsigned VerticalLayout::minimumHeight() { - unsigned height = margin * 2; - foreach(child, children) height += child.height + child.spacing; - return height; +void VerticalLayout::setParent(Window &parent) { + foreach(child, children) { + if(child.layout) child.layout->setParent(parent); + if(child.widget) parent.append(*child.widget); + } } void VerticalLayout::setVisible(bool visible) { @@ -83,6 +136,4 @@ void VerticalLayout::setVisible(bool visible) { VerticalLayout::VerticalLayout() { margin = 0; - width = 0; - height = 0; } diff --git a/snespurify/phoenix/core/layout/vertical-layout.hpp b/snespurify/phoenix/core/layout/vertical-layout.hpp index 28ec0f4d..a280c269 100755 --- a/snespurify/phoenix/core/layout/vertical-layout.hpp +++ b/snespurify/phoenix/core/layout/vertical-layout.hpp @@ -1,10 +1,11 @@ struct HorizontalLayout; struct VerticalLayout : public Layout { - void append(HorizontalLayout &layout, unsigned width, unsigned height, unsigned spacing = 0); + void append(HorizontalLayout &layout, unsigned spacing = 0); void append(Widget &widget, unsigned width, unsigned height, unsigned spacing = 0); - unsigned minimumHeight(); - void setGeometry(Geometry &geometry); + Geometry minimumGeometry(); + Geometry minimumLayoutGeometry(); + void setGeometry(const Geometry &geometry); void setMargin(unsigned margin); void setParent(Window &parent); void setVisible(bool visible); @@ -12,8 +13,6 @@ struct VerticalLayout : public Layout { //private: unsigned margin; - unsigned width; - unsigned height; struct Children { HorizontalLayout *layout; Widget *widget; diff --git a/snespurify/phoenix/gtk/font.cpp b/snespurify/phoenix/gtk/font.cpp index 7ece6ad8..93bc0303 100755 --- a/snespurify/phoenix/gtk/font.cpp +++ b/snespurify/phoenix/gtk/font.cpp @@ -1,3 +1,11 @@ +Geometry pFont::geometry(const string &text) { + pango_layout_set_font_description(gtkLayout, gtkFont); + pango_layout_set_text(gtkLayout, text, -1); + int width = 0, height = 0; + pango_layout_get_pixel_size(gtkLayout, &width, &height); + return { 0, 0, width, height }; +} + void pFont::setBold(bool bold) { pango_font_description_set_weight(gtkFont, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL); } @@ -19,4 +27,6 @@ void pFont::setUnderline(bool underline) { void pFont::constructor() { gtkFont = pango_font_description_new(); + PangoContext *context = gdk_pango_context_get_for_screen(gdk_screen_get_default()); + gtkLayout = pango_layout_new(context); } diff --git a/snespurify/phoenix/gtk/gtk.cpp b/snespurify/phoenix/gtk/gtk.cpp index bf83c963..c711d7a2 100755 --- a/snespurify/phoenix/gtk/gtk.cpp +++ b/snespurify/phoenix/gtk/gtk.cpp @@ -14,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" @@ -27,6 +28,8 @@ #include "widget/vertical-slider.cpp" #include "widget/viewport.cpp" +Font pOS::defaultFont; + Geometry pOS::availableGeometry() { //TODO: is there a GTK+ function for this? //should return desktopGeometry() sans panels, toolbars, docks, etc. diff --git a/snespurify/phoenix/gtk/gtk.hpp b/snespurify/phoenix/gtk/gtk.hpp index 1e5a60d4..f6abacce 100755 --- a/snespurify/phoenix/gtk/gtk.hpp +++ b/snespurify/phoenix/gtk/gtk.hpp @@ -26,6 +26,8 @@ struct pObject { }; struct pOS : public pObject { + static Font defaultFont; + static Geometry availableGeometry(); static Geometry desktopGeometry(); static string fileLoad(Window &parent, const string &path, const lstring &filter); @@ -42,7 +44,9 @@ struct pOS : public pObject { struct pFont : public pObject { Font &font; PangoFontDescription *gtkFont; + PangoLayout *gtkLayout; + Geometry geometry(const string &text); void setBold(bool bold); void setFamily(const string &family); void setItalic(bool italic); @@ -164,10 +168,12 @@ struct pWidget : public pObject { pWindow *parentWindow; bool enabled(); + Font& font(); + virtual Geometry minimumGeometry(); void setEnabled(bool enabled); virtual void setFocused(); virtual void setFont(Font &font); - void setGeometry(const Geometry &geometry); + virtual void setGeometry(const Geometry &geometry); void setVisible(bool visible); pWidget(Widget &widget) : widget(widget) {} @@ -177,16 +183,32 @@ struct pWidget : public pObject { struct pButton : public pWidget { Button &button; + Geometry minimumGeometry(); void setText(const string &text); pButton(Button &button) : pWidget(button), button(button) {} void constructor(); }; +struct pCanvas : public pWidget { + Canvas &canvas; + uint32_t *bufferRGB; + uint32_t *bufferBGR; + + uint32_t* buffer(); + void setGeometry(const Geometry &geometry); + void update(); + + pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {} + void constructor(); + void redraw(); +}; + struct pCheckBox : public pWidget { CheckBox &checkBox; bool checked(); + Geometry minimumGeometry(); void setChecked(bool checked); void setText(const string &text); @@ -199,6 +221,7 @@ struct pComboBox : public pWidget { unsigned itemCounter; void append(const string &text); + Geometry minimumGeometry(); void reset(); unsigned selection(); void setSelection(unsigned row); @@ -234,6 +257,7 @@ struct pHexEdit : public pWidget { struct pHorizontalSlider : public pWidget { HorizontalSlider &horizontalSlider; + Geometry minimumGeometry(); unsigned position(); void setLength(unsigned length); void setPosition(unsigned position); @@ -245,6 +269,7 @@ struct pHorizontalSlider : public pWidget { struct pLabel : public pWidget { Label &label; + Geometry minimumGeometry(); void setText(const string &text); pLabel(Label &label) : pWidget(label), label(label) {} @@ -254,6 +279,7 @@ struct pLabel : public pWidget { struct pLineEdit : public pWidget { LineEdit &lineEdit; + Geometry minimumGeometry(); void setEditable(bool editable); void setText(const string &text); string text(); @@ -297,6 +323,7 @@ struct pListView : public pWidget { struct pProgressBar : public pWidget { ProgressBar &progressBar; + Geometry minimumGeometry(); void setPosition(unsigned position); pProgressBar(ProgressBar &progressBar) : pWidget(progressBar), progressBar(progressBar) {} @@ -307,6 +334,7 @@ struct pRadioBox : public pWidget { RadioBox &radioBox; bool checked(); + Geometry minimumGeometry(); void setChecked(); void setGroup(const reference_array &group); void setText(const string &text); @@ -333,6 +361,7 @@ struct pTextEdit : public pWidget { struct pVerticalSlider : public pWidget { VerticalSlider &verticalSlider; + Geometry minimumGeometry(); unsigned position(); void setLength(unsigned length); void setPosition(unsigned position); diff --git a/snespurify/phoenix/gtk/widget/button.cpp b/snespurify/phoenix/gtk/widget/button.cpp index 75774ddd..360ccedf 100755 --- a/snespurify/phoenix/gtk/widget/button.cpp +++ b/snespurify/phoenix/gtk/widget/button.cpp @@ -2,6 +2,12 @@ static void Button_tick(Button *self) { if(self->onTick) self->onTick(); } +Geometry pButton::minimumGeometry() { + Font &font = pWidget::font(); + Geometry geometry = font.geometry(button.state.text); + return { 0, 0, geometry.width + 24, geometry.height + 14 }; +} + void pButton::setText(const string &text) { gtk_button_set_label(GTK_BUTTON(gtkWidget), text); } diff --git a/snespurify/phoenix/gtk/widget/canvas.cpp b/snespurify/phoenix/gtk/widget/canvas.cpp new file mode 100755 index 00000000..2a0d479b --- /dev/null +++ b/snespurify/phoenix/gtk/widget/canvas.cpp @@ -0,0 +1,59 @@ +static void Canvas_expose(pCanvas *self) { + self->redraw(); +} + +uint32_t* pCanvas::buffer() { + return bufferRGB; +} + +void pCanvas::setGeometry(const Geometry &geometry) { + delete[] bufferRGB; + delete[] bufferBGR; + + bufferRGB = new uint32_t[geometry.width * geometry.height](); + bufferBGR = new uint32_t[geometry.width * geometry.height](); + + pWidget::setGeometry(geometry); + update(); +} + +void pCanvas::update() { + if(gtk_widget_get_realized(gtkWidget) == false) return; + GdkRectangle rect; + rect.x = 0; + rect.y = 0; + rect.width = gtkWidget->allocation.width; + rect.height = gtkWidget->allocation.height; + gdk_window_invalidate_rect(gtkWidget->window, &rect, true); +} + +void pCanvas::constructor() { + bufferRGB = new uint32_t[256 * 256](); + bufferBGR = new uint32_t[256 * 256](); + + gtkWidget = gtk_drawing_area_new(); + GdkColor color; + color.pixel = color.red = color.green = color.blue = 0; + gtk_widget_modify_bg(gtkWidget, GTK_STATE_NORMAL, &color); + gtk_widget_set_double_buffered(gtkWidget, false); + gtk_widget_add_events(gtkWidget, GDK_EXPOSURE_MASK); + g_signal_connect_swapped(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this); +} + +void pCanvas::redraw() { + if(gtk_widget_get_realized(gtkWidget) == false) return; + uint32_t *rgb = bufferRGB, *bgr = bufferBGR; + for(unsigned y = gtkWidget->allocation.height; y; y--) { + for(unsigned x = gtkWidget->allocation.width; x; x--) { + uint32_t pixel = *rgb++; + *bgr++ = ((pixel << 16) & 0xff0000) | (pixel & 0x00ff00) | ((pixel >> 16) & 0x0000ff); + } + } + + gdk_draw_rgb_32_image( + gtkWidget->window, + gtkWidget->style->fg_gc[GTK_WIDGET_STATE(gtkWidget)], + 0, 0, gtkWidget->allocation.width, gtkWidget->allocation.height, + GDK_RGB_DITHER_NONE, (guchar*)bufferBGR, sizeof(uint32_t) * gtkWidget->allocation.width + ); +} diff --git a/snespurify/phoenix/gtk/widget/check-box.cpp b/snespurify/phoenix/gtk/widget/check-box.cpp index bcacb7f3..4169c68b 100755 --- a/snespurify/phoenix/gtk/widget/check-box.cpp +++ b/snespurify/phoenix/gtk/widget/check-box.cpp @@ -6,6 +6,12 @@ bool pCheckBox::checked() { return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtkWidget)); } +Geometry pCheckBox::minimumGeometry() { + Font &font = pWidget::font(); + Geometry geometry = font.geometry(checkBox.state.text); + return { 0, 0, geometry.width + 28, geometry.height + 4 }; +} + void pCheckBox::setChecked(bool checked) { locked = true; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), checked); diff --git a/snespurify/phoenix/gtk/widget/combo-box.cpp b/snespurify/phoenix/gtk/widget/combo-box.cpp index 72338cca..0ea1e200 100755 --- a/snespurify/phoenix/gtk/widget/combo-box.cpp +++ b/snespurify/phoenix/gtk/widget/combo-box.cpp @@ -7,6 +7,15 @@ void pComboBox::append(const string &text) { if(itemCounter++ == 0) setSelection(0); } +Geometry pComboBox::minimumGeometry() { + Font &font = pWidget::font(); + unsigned maximumWidth = 0; + foreach(item, comboBox.state.text) maximumWidth = max(maximumWidth, font.geometry(item).width); + + Geometry geometry = font.geometry(" "); + return { 0, 0, maximumWidth + 44, geometry.height + 10 }; +} + void pComboBox::reset() { locked = true; for(signed n = itemCounter - 1; n >= 0; n--) { diff --git a/snespurify/phoenix/gtk/widget/horizontal-slider.cpp b/snespurify/phoenix/gtk/widget/horizontal-slider.cpp index 44f6614d..89a17a8a 100755 --- a/snespurify/phoenix/gtk/widget/horizontal-slider.cpp +++ b/snespurify/phoenix/gtk/widget/horizontal-slider.cpp @@ -4,6 +4,10 @@ static void HorizontalSlider_change(HorizontalSlider *self) { if(self->onChange) self->onChange(); } +Geometry pHorizontalSlider::minimumGeometry() { + return { 0, 0, 0, 20 }; +} + unsigned pHorizontalSlider::position() { return (unsigned)gtk_range_get_value(GTK_RANGE(gtkWidget)); } diff --git a/snespurify/phoenix/gtk/widget/label.cpp b/snespurify/phoenix/gtk/widget/label.cpp index bcf38121..645abdbf 100755 --- a/snespurify/phoenix/gtk/widget/label.cpp +++ b/snespurify/phoenix/gtk/widget/label.cpp @@ -1,3 +1,9 @@ +Geometry pLabel::minimumGeometry() { + Font &font = pWidget::font(); + Geometry geometry = font.geometry(label.state.text); + return { 0, 0, geometry.width, geometry.height }; +} + void pLabel::setText(const string &text) { gtk_label_set_text(GTK_LABEL(gtkWidget), text); } diff --git a/snespurify/phoenix/gtk/widget/line-edit.cpp b/snespurify/phoenix/gtk/widget/line-edit.cpp index 65359fbd..e783b3e2 100755 --- a/snespurify/phoenix/gtk/widget/line-edit.cpp +++ b/snespurify/phoenix/gtk/widget/line-edit.cpp @@ -6,6 +6,12 @@ static void LineEdit_change(LineEdit *self) { if(self->p.locked == false && self->onChange) self->onChange(); } +Geometry pLineEdit::minimumGeometry() { + Font &font = pWidget::font(); + Geometry geometry = font.geometry(lineEdit.state.text); + return { 0, 0, geometry.width + 10, geometry.height + 10 }; +} + void pLineEdit::setEditable(bool editable) { gtk_entry_set_editable(GTK_ENTRY(gtkWidget), editable); } diff --git a/snespurify/phoenix/gtk/widget/progress-bar.cpp b/snespurify/phoenix/gtk/widget/progress-bar.cpp index 96959b62..4e7d752c 100755 --- a/snespurify/phoenix/gtk/widget/progress-bar.cpp +++ b/snespurify/phoenix/gtk/widget/progress-bar.cpp @@ -1,3 +1,7 @@ +Geometry pProgressBar::minimumGeometry() { + return { 0, 0, 0, 25 }; +} + void pProgressBar::setPosition(unsigned position) { position = position <= 100 ? position : 0; gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gtkWidget), (double)position / 100.0); diff --git a/snespurify/phoenix/gtk/widget/radio-box.cpp b/snespurify/phoenix/gtk/widget/radio-box.cpp index 2fb7d38f..67e709ae 100755 --- a/snespurify/phoenix/gtk/widget/radio-box.cpp +++ b/snespurify/phoenix/gtk/widget/radio-box.cpp @@ -6,6 +6,12 @@ bool pRadioBox::checked() { return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtkWidget)); } +Geometry pRadioBox::minimumGeometry() { + Font &font = pWidget::font(); + Geometry geometry = font.geometry(radioBox.state.text); + return { 0, 0, geometry.width + 28, geometry.height + 4 }; +} + void pRadioBox::setChecked() { locked = true; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), true); diff --git a/snespurify/phoenix/gtk/widget/vertical-slider.cpp b/snespurify/phoenix/gtk/widget/vertical-slider.cpp index dbd4347c..b19632f7 100755 --- a/snespurify/phoenix/gtk/widget/vertical-slider.cpp +++ b/snespurify/phoenix/gtk/widget/vertical-slider.cpp @@ -4,6 +4,10 @@ static void VerticalSlider_change(VerticalSlider *self) { if(self->onChange) self->onChange(); } +Geometry pVerticalSlider::minimumGeometry() { + return { 0, 0, 20, 0 }; +} + unsigned pVerticalSlider::position() { return (unsigned)gtk_range_get_value(GTK_RANGE(gtkWidget)); } diff --git a/snespurify/phoenix/gtk/widget/widget.cpp b/snespurify/phoenix/gtk/widget/widget.cpp index d26d0c6c..62bb46f4 100755 --- a/snespurify/phoenix/gtk/widget/widget.cpp +++ b/snespurify/phoenix/gtk/widget/widget.cpp @@ -6,6 +6,15 @@ static void Widget_setFont(GtkWidget *widget, gpointer font) { } } +Font& pWidget::font() { + if(widget.state.font) return *widget.state.font; + return pOS::defaultFont; +} + +Geometry pWidget::minimumGeometry() { + return { 0, 0, 0, 0 }; +} + bool pWidget::enabled() { return gtk_widget_get_sensitive(gtkWidget); } diff --git a/snespurify/phoenix/nall/snes/cartridge.hpp b/snespurify/phoenix/nall/snes/cartridge.hpp index 48d32720..e3c0e0c5 100755 --- a/snespurify/phoenix/nall/snes/cartridge.hpp +++ b/snespurify/phoenix/nall/snes/cartridge.hpp @@ -362,7 +362,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; @@ -372,7 +372,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) { xml << " \n"; xml << " \n"; xml << " \n"; - xml << " \n"; + xml << " \n"; xml << " \n"; xml << " \n"; xml << " \n"; diff --git a/snespurify/phoenix/nall/string/base.hpp b/snespurify/phoenix/nall/string/base.hpp index 1bc6ca07..f6172c26 100755 --- a/snespurify/phoenix/nall/string/base.hpp +++ b/snespurify/phoenix/nall/string/base.hpp @@ -12,18 +12,16 @@ namespace nall { class string; - template inline string to_string(T); + template inline const char* to_string(T); class string { public: inline void reserve(unsigned); - inline string& assign(const char*); - inline string& append(const char*); - inline string& append(bool); - inline string& append(signed int value); - inline string& append(unsigned int value); - inline string& append(double value); + template inline string& assign(Args&&... args); + template inline string& append(Args&&... args); + inline string& assign_(const char*); + inline string& append_(const char*); inline bool readfile(const string&); diff --git a/snespurify/phoenix/nall/string/cast.hpp b/snespurify/phoenix/nall/string/cast.hpp index d8503106..058fcdc1 100755 --- a/snespurify/phoenix/nall/string/cast.hpp +++ b/snespurify/phoenix/nall/string/cast.hpp @@ -4,14 +4,14 @@ namespace nall { //this is needed, as C++0x does not support explicit template specialization inside classes -template<> inline string to_string (bool v) { return v ? "true" : "false"; } -template<> inline string to_string (signed int v) { return integer(v); } -template<> inline string to_string (unsigned int v) { return decimal(v); } -template<> inline string to_string (double v) { return fp(v); } -template<> inline string to_string (char *v) { return v; } -template<> inline string to_string (const char *v) { return v; } -template<> inline string to_string (string v) { return v; } -template<> inline string to_string(const string &v) { return v; } +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 (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; } +template<> inline const char* to_string(const string &v) { return v; } template string& string::operator= (T value) { return assign(to_string(value)); } template string& string::operator<<(T value) { return append(to_string(value)); } @@ -22,8 +22,8 @@ template lstring& lstring::operator<<(T value) { } #if defined(QSTRING_H) -template<> inline string to_string(QString v) { return v.toUtf8().constData(); } -template<> inline string to_string(const QString &v) { return v.toUtf8().constData(); } +template<> inline const char* to_string(QString v) { return v.toUtf8().constData(); } +template<> inline const char* to_string(const QString &v) { return v.toUtf8().constData(); } string::operator QString() const { return QString::fromUtf8(*this); } #endif diff --git a/snespurify/phoenix/nall/string/convert.hpp b/snespurify/phoenix/nall/string/convert.hpp index ca77db85..603d2e0e 100755 --- a/snespurify/phoenix/nall/string/convert.hpp +++ b/snespurify/phoenix/nall/string/convert.hpp @@ -117,38 +117,7 @@ uintmax_t binary(const char *str) { } double fp(const char *str) { - if(!str) return 0.0; - bool negate = false; - - //check for negation - if(*str == '-') { - negate = true; - str++; - } - - intmax_t result_integral = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x == '.' || x == ',') break; //break loop and read fractional part - else return (double)result_integral; //invalid value, assume no fractional part - result_integral = result_integral * 10 + x; - } - - intmax_t result_fractional = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result_fractional = result_fractional * 10 + x; - } - - //calculate fractional portion - double result = (double)result_fractional; - while((uintmax_t)result > 0) result /= 10.0; - result += (double)result_integral; - - return !negate ? result : -result; + return atof(str); } } diff --git a/snespurify/phoenix/nall/string/core.hpp b/snespurify/phoenix/nall/string/core.hpp index b04078d1..4ffda4ee 100755 --- a/snespurify/phoenix/nall/string/core.hpp +++ b/snespurify/phoenix/nall/string/core.hpp @@ -3,6 +3,15 @@ namespace nall { +static void istring(string &output) { +} + +template +static void istring(string &output, const T &value, Args&&... args) { + output.append_(to_string(value)); + istring(output, std::forward(args)...); +} + void string::reserve(unsigned size_) { if(size_ > size) { size = size_; @@ -11,25 +20,31 @@ void string::reserve(unsigned size_) { } } -string& string::assign(const char *s) { +template string& string::assign(Args&&... args) { + *data = 0; + istring(*this, std::forward(args)...); + return *this; +} + +template string& string::append(Args&&... args) { + istring(*this, std::forward(args)...); + return *this; +} + +string& string::assign_(const char *s) { unsigned length = strlen(s); reserve(length); strcpy(data, s); return *this; } -string& string::append(const char *s) { +string& string::append_(const char *s) { unsigned length = strlen(data) + strlen(s); reserve(length); strcat(data, s); return *this; } -string& string::append(bool value) { append(value ? "true" : "false"); return *this; } -string& string::append(signed int value) { append(integer(value)); return *this; } -string& string::append(unsigned int value) { append(decimal(value)); return *this; } -string& string::append(double value) { append(fp(value)); return *this; } - string::operator const char*() const { return data; } @@ -64,15 +79,6 @@ string& string::operator=(string &&source) { return *this; } -static void istring(string &output) { -} - -template -static void istring(string &output, const T &value, Args&&... args) { - output.append(value); - istring(output, std::forward(args)...); -} - template string::string(Args&&... args) { size = 64; data = (char*)malloc(size + 1); diff --git a/snespurify/phoenix/nall/string/platform.hpp b/snespurify/phoenix/nall/string/platform.hpp index 42c1a756..0deda430 100755 --- a/snespurify/phoenix/nall/string/platform.hpp +++ b/snespurify/phoenix/nall/string/platform.hpp @@ -3,15 +3,15 @@ namespace nall { -string realpath(const char *name) { +string currentpath() { char path[PATH_MAX]; - if(::realpath(name, path)) { + if(::getcwd(path)) { string result(path); result.transform("\\", "/"); if(result.endswith("/") == false) result.append("/"); return result; } - return ""; + return "./"; } string userpath() { @@ -22,18 +22,17 @@ string userpath() { if(result.endswith("/") == false) result.append("/"); return result; } - return ""; + return currentpath(); } -string currentpath() { +string realpath(const char *name) { char path[PATH_MAX]; - if(::getcwd(path)) { + if(::realpath(name, path)) { string result(path); result.transform("\\", "/"); - if(result.endswith("/") == false) result.append("/"); return result; } - return ""; + return userpath(); } } diff --git a/snespurify/phoenix/qt/action/action.cpp b/snespurify/phoenix/qt/action/action.cpp index c2cbe42b..57036439 100755 --- a/snespurify/phoenix/qt/action/action.cpp +++ b/snespurify/phoenix/qt/action/action.cpp @@ -28,7 +28,7 @@ void pAction::setFont(Font &font) { void pAction::setVisible(bool visible) { if(dynamic_cast(&action)) { - ((Menu&)action).p.qtMenu->setVisible(visible); + ((Menu&)action).p.qtMenu->menuAction()->setVisible(visible); } else if(dynamic_cast(&action)) { ((Separator&)action).p.qtAction->setVisible(visible); } else if(dynamic_cast(&action)) { diff --git a/snespurify/phoenix/qt/font.cpp b/snespurify/phoenix/qt/font.cpp index c492fca1..f9c7acb7 100755 --- a/snespurify/phoenix/qt/font.cpp +++ b/snespurify/phoenix/qt/font.cpp @@ -1,3 +1,17 @@ +Geometry pFont::geometry(const string &text) { + QFontMetrics metrics(*qtFont); + + lstring lines; + lines.split("\n", text); + + unsigned maxWidth = 0; + foreach(line, lines) { + maxWidth = max(maxWidth, metrics.width(line)); + } + + return { 0, 0, maxWidth, metrics.height() * lines.size() }; +} + void pFont::setBold(bool bold) { update(); } void pFont::setFamily(const string &family) { update(); } void pFont::setItalic(bool italic) { update(); } diff --git a/snespurify/phoenix/qt/qt.cpp b/snespurify/phoenix/qt/qt.cpp index b10df857..d971d04b 100755 --- a/snespurify/phoenix/qt/qt.cpp +++ b/snespurify/phoenix/qt/qt.cpp @@ -15,6 +15,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" @@ -29,6 +30,7 @@ #include "widget/viewport.cpp" QApplication *pOS::application = 0; +Font pOS::defaultFont; Geometry pOS::availableGeometry() { QRect rect = QApplication::desktop()->availableGeometry(); diff --git a/snespurify/phoenix/qt/qt.moc b/snespurify/phoenix/qt/qt.moc index 27b6fbbb..5105ee8f 100755 --- a/snespurify/phoenix/qt/qt.moc +++ b/snespurify/phoenix/qt/qt.moc @@ -1,8 +1,8 @@ /**************************************************************************** ** Meta object code from reading C++ file 'qt.moc.hpp' ** -** Created: Fri Feb 25 04:49:31 2011 -** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2) +** Created: Tue Mar 29 11:11:59 2011 +** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0) ** ** WARNING! All changes made in this file will be lost! *****************************************************************************/ @@ -10,7 +10,7 @@ #if !defined(Q_MOC_OUTPUT_REVISION) #error "The header file 'qt.moc.hpp' doesn't include ." #elif Q_MOC_OUTPUT_REVISION != 62 -#error "This file was generated using the moc from 4.6.2. It" +#error "This file was generated using the moc from 4.7.0. It" #error "cannot be used with the include files from this version of Qt." #error "(The moc has changed too much.)" #endif @@ -19,7 +19,7 @@ QT_BEGIN_MOC_NAMESPACE static const uint qt_meta_data_pWindow[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 0, 0, // methods @@ -70,7 +70,7 @@ int pWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pItem[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods @@ -131,7 +131,7 @@ int pItem::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pCheckItem[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods @@ -192,7 +192,7 @@ int pCheckItem::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pRadioItem[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods @@ -253,7 +253,7 @@ int pRadioItem::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pButton[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods @@ -311,10 +311,61 @@ int pButton::qt_metacall(QMetaObject::Call _c, int _id, void **_a) } return _id; } +static const uint qt_meta_data_pCanvas[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_pCanvas[] = { + "pCanvas\0" +}; + +const QMetaObject pCanvas::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_pCanvas, + qt_meta_data_pCanvas, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &pCanvas::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *pCanvas::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *pCanvas::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_pCanvas)) + return static_cast(const_cast< pCanvas*>(this)); + if (!strcmp(_clname, "pWidget")) + return static_cast< pWidget*>(const_cast< pCanvas*>(this)); + return QObject::qt_metacast(_clname); +} + +int pCanvas::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} static const uint qt_meta_data_pCheckBox[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods @@ -375,7 +426,7 @@ int pCheckBox::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pComboBox[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods @@ -436,7 +487,7 @@ int pComboBox::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pHexEdit[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods @@ -497,7 +548,7 @@ int pHexEdit::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pHorizontalSlider[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods @@ -558,7 +609,7 @@ int pHorizontalSlider::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pLineEdit[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 2, 14, // methods @@ -621,7 +672,7 @@ int pLineEdit::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pListView[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 3, 14, // methods @@ -687,7 +738,7 @@ int pListView::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pRadioBox[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods @@ -748,7 +799,7 @@ int pRadioBox::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pTextEdit[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods @@ -809,7 +860,7 @@ int pTextEdit::qt_metacall(QMetaObject::Call _c, int _id, void **_a) static const uint qt_meta_data_pVerticalSlider[] = { // content: - 4, // revision + 5, // revision 0, // classname 0, 0, // classinfo 1, 14, // methods diff --git a/snespurify/phoenix/qt/qt.moc.hpp b/snespurify/phoenix/qt/qt.moc.hpp index 10f170cc..d7466d6b 100755 --- a/snespurify/phoenix/qt/qt.moc.hpp +++ b/snespurify/phoenix/qt/qt.moc.hpp @@ -25,6 +25,7 @@ struct pObject { struct pOS : public pObject { static QApplication *application; + static Font defaultFont; static Geometry availableGeometry(); static Geometry desktopGeometry(); @@ -43,6 +44,7 @@ struct pFont : public pObject { Font &font; QFont *qtFont; + Geometry geometry(const string &text); void setBold(bool bold); void setFamily(const string &family); void setItalic(bool italic); @@ -193,10 +195,12 @@ struct pWidget : public pObject { Widget &widget; QWidget *qtWidget; + Font& font(); + virtual Geometry minimumGeometry(); void setEnabled(bool enabled); void setFocused(); void setFont(Font &font); - void setGeometry(const Geometry &geometry); + virtual void setGeometry(const Geometry &geometry); void setVisible(bool visible); pWidget(Widget &widget) : widget(widget) {} @@ -210,6 +214,7 @@ public: Button &button; QPushButton *qtButton; + Geometry minimumGeometry(); void setText(const string &text); pButton(Button &button) : pWidget(button), button(button) {} @@ -219,6 +224,28 @@ public slots: void onTick(); }; +struct pCanvas : public QObject, public pWidget { + Q_OBJECT + +public: + Canvas &canvas; + QImage *qtImage; + struct QtCanvas : public QWidget { + pCanvas &self; + void paintEvent(QPaintEvent*); + QtCanvas(pCanvas &self); + } *qtCanvas; + + uint32_t* buffer(); + void setGeometry(const Geometry &geometry); + void update(); + + pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {} + void constructor(); + +public slots: +}; + struct pCheckBox : public QObject, public pWidget { Q_OBJECT @@ -227,6 +254,7 @@ public: QCheckBox *qtCheckBox; bool checked(); + Geometry minimumGeometry(); void setChecked(bool checked); void setText(const string &text); @@ -245,6 +273,7 @@ public: QComboBox *qtComboBox; void append(const string &text); + Geometry minimumGeometry(); void reset(); unsigned selection(); void setSelection(unsigned row); @@ -291,6 +320,7 @@ public: HorizontalSlider &horizontalSlider; QSlider *qtSlider; + Geometry minimumGeometry(); unsigned position(); void setLength(unsigned length); void setPosition(unsigned position); @@ -306,6 +336,7 @@ struct pLabel : public pWidget { Label &label; QLabel *qtLabel; + Geometry minimumGeometry(); void setText(const string &text); pLabel(Label &label) : pWidget(label), label(label) {} @@ -319,6 +350,7 @@ public: LineEdit &lineEdit; QLineEdit *qtLineEdit; + Geometry minimumGeometry(); void setEditable(bool editable); void setText(const string &text); string text(); @@ -365,6 +397,7 @@ struct pProgressBar : public pWidget { ProgressBar &progressBar; QProgressBar *qtProgressBar; + Geometry minimumGeometry(); void setPosition(unsigned position); pProgressBar(ProgressBar &progressBar) : pWidget(progressBar), progressBar(progressBar) {} @@ -380,6 +413,7 @@ public: QButtonGroup *qtGroup; bool checked(); + Geometry minimumGeometry(); void setChecked(); void setGroup(const reference_array &group); void setText(const string &text); @@ -418,6 +452,7 @@ public: VerticalSlider &verticalSlider; QSlider *qtSlider; + Geometry minimumGeometry(); unsigned position(); void setLength(unsigned length); void setPosition(unsigned position); diff --git a/snespurify/phoenix/qt/widget/button.cpp b/snespurify/phoenix/qt/widget/button.cpp index 0fdcd04b..e6645dce 100755 --- a/snespurify/phoenix/qt/widget/button.cpp +++ b/snespurify/phoenix/qt/widget/button.cpp @@ -1,3 +1,9 @@ +Geometry pButton::minimumGeometry() { + Font &font = this->font(); + Geometry geometry = font.geometry(button.state.text); + return { 0, 0, geometry.width + 20, geometry.height + 12 }; +} + void pButton::setText(const string &text) { qtButton->setText(QString::fromUtf8(text)); } diff --git a/snespurify/phoenix/qt/widget/canvas.cpp b/snespurify/phoenix/qt/widget/canvas.cpp new file mode 100755 index 00000000..05c661bc --- /dev/null +++ b/snespurify/phoenix/qt/widget/canvas.cpp @@ -0,0 +1,27 @@ +uint32_t* pCanvas::buffer() { + return (uint32_t*)qtImage->bits(); +} + +void pCanvas::setGeometry(const Geometry &geometry) { + qtImage = new QImage(geometry.width, geometry.height, QImage::Format_RGB32); + qtImage->fill(0); + update(); + pWidget::setGeometry(geometry); +} + +void pCanvas::update() { + qtCanvas->update(); +} + +void pCanvas::constructor() { + qtWidget = qtCanvas = new QtCanvas(*this); + qtImage = new QImage(256, 256, QImage::Format_RGB32); +} + +void pCanvas::QtCanvas::paintEvent(QPaintEvent *event) { + QPainter painter(self.qtCanvas); + painter.drawImage(0, 0, *self.qtImage); +} + +pCanvas::QtCanvas::QtCanvas(pCanvas &self) : self(self) { +} diff --git a/snespurify/phoenix/qt/widget/check-box.cpp b/snespurify/phoenix/qt/widget/check-box.cpp index ef0484b9..1cd89157 100755 --- a/snespurify/phoenix/qt/widget/check-box.cpp +++ b/snespurify/phoenix/qt/widget/check-box.cpp @@ -2,6 +2,12 @@ bool pCheckBox::checked() { return qtCheckBox->isChecked(); } +Geometry pCheckBox::minimumGeometry() { + Font &font = this->font(); + Geometry geometry = font.geometry(checkBox.state.text); + return { 0, 0, geometry.width + 26, geometry.height + 6 }; +} + void pCheckBox::setChecked(bool checked) { locked = true; qtCheckBox->setChecked(checked); diff --git a/snespurify/phoenix/qt/widget/combo-box.cpp b/snespurify/phoenix/qt/widget/combo-box.cpp index a51cd7fd..83090415 100755 --- a/snespurify/phoenix/qt/widget/combo-box.cpp +++ b/snespurify/phoenix/qt/widget/combo-box.cpp @@ -2,6 +2,14 @@ void pComboBox::append(const string &text) { qtComboBox->addItem(QString::fromUtf8(text)); } +Geometry pComboBox::minimumGeometry() { + Font &font = this->font(); + unsigned maximumWidth = 0; + foreach(text, comboBox.state.text) maximumWidth = max(maximumWidth, font.geometry(text).width); + Geometry geometry = font.geometry(" "); + return { 0, 0, maximumWidth + 32, geometry.height + 12 }; +} + void pComboBox::reset() { while(qtComboBox->count()) qtComboBox->removeItem(0); } diff --git a/snespurify/phoenix/qt/widget/horizontal-slider.cpp b/snespurify/phoenix/qt/widget/horizontal-slider.cpp index af875776..b29eab7b 100755 --- a/snespurify/phoenix/qt/widget/horizontal-slider.cpp +++ b/snespurify/phoenix/qt/widget/horizontal-slider.cpp @@ -1,3 +1,7 @@ +Geometry pHorizontalSlider::minimumGeometry() { + return { 0, 0, 0, 20 }; +} + unsigned pHorizontalSlider::position() { return qtSlider->value(); } diff --git a/snespurify/phoenix/qt/widget/label.cpp b/snespurify/phoenix/qt/widget/label.cpp index 2dc5c013..fb233fa0 100755 --- a/snespurify/phoenix/qt/widget/label.cpp +++ b/snespurify/phoenix/qt/widget/label.cpp @@ -1,3 +1,9 @@ +Geometry pLabel::minimumGeometry() { + Font &font = this->font(); + Geometry geometry = font.geometry(label.state.text); + return { 0, 0, geometry.width, geometry.height }; +} + void pLabel::setText(const string &text) { qtLabel->setText(QString::fromUtf8(text)); } diff --git a/snespurify/phoenix/qt/widget/line-edit.cpp b/snespurify/phoenix/qt/widget/line-edit.cpp index ac647251..237e658c 100755 --- a/snespurify/phoenix/qt/widget/line-edit.cpp +++ b/snespurify/phoenix/qt/widget/line-edit.cpp @@ -1,3 +1,9 @@ +Geometry pLineEdit::minimumGeometry() { + Font &font = this->font(); + Geometry geometry = font.geometry(lineEdit.state.text); + return { 0, 0, geometry.width + 12, geometry.height + 12 }; +} + void pLineEdit::setEditable(bool editable) { qtLineEdit->setReadOnly(!editable); } diff --git a/snespurify/phoenix/qt/widget/progress-bar.cpp b/snespurify/phoenix/qt/widget/progress-bar.cpp index d7c66b8f..698c587e 100755 --- a/snespurify/phoenix/qt/widget/progress-bar.cpp +++ b/snespurify/phoenix/qt/widget/progress-bar.cpp @@ -1,3 +1,7 @@ +Geometry pProgressBar::minimumGeometry() { + return { 0, 0, 0, 25 }; +} + void pProgressBar::setPosition(unsigned position) { qtProgressBar->setValue(position); } diff --git a/snespurify/phoenix/qt/widget/radio-box.cpp b/snespurify/phoenix/qt/widget/radio-box.cpp index 62a9abbc..22f0e911 100755 --- a/snespurify/phoenix/qt/widget/radio-box.cpp +++ b/snespurify/phoenix/qt/widget/radio-box.cpp @@ -2,6 +2,12 @@ bool pRadioBox::checked() { return qtRadioBox->isChecked(); } +Geometry pRadioBox::minimumGeometry() { + Font &font = this->font(); + Geometry geometry = font.geometry(radioBox.state.text); + return { 0, 0, geometry.width + 26, geometry.height + 6 }; +} + void pRadioBox::setChecked() { locked = true; foreach(item, radioBox.state.group) { diff --git a/snespurify/phoenix/qt/widget/vertical-slider.cpp b/snespurify/phoenix/qt/widget/vertical-slider.cpp index 684da804..10c05e50 100755 --- a/snespurify/phoenix/qt/widget/vertical-slider.cpp +++ b/snespurify/phoenix/qt/widget/vertical-slider.cpp @@ -1,3 +1,7 @@ +Geometry pVerticalSlider::minimumGeometry() { + return { 0, 0, 20, 0 }; +} + unsigned pVerticalSlider::position() { return qtSlider->value(); } diff --git a/snespurify/phoenix/qt/widget/widget.cpp b/snespurify/phoenix/qt/widget/widget.cpp index 99f21526..e9723fef 100755 --- a/snespurify/phoenix/qt/widget/widget.cpp +++ b/snespurify/phoenix/qt/widget/widget.cpp @@ -1,3 +1,12 @@ +Font& pWidget::font() { + if(widget.state.font) return *widget.state.font; + return pOS::defaultFont; +} + +Geometry pWidget::minimumGeometry() { + return { 0, 0, 0, 0 }; +} + void pWidget::setEnabled(bool enabled) { qtWidget->setEnabled(enabled); } diff --git a/snespurify/phoenix/windows/font.cpp b/snespurify/phoenix/windows/font.cpp index 20612be7..60d417ee 100755 --- a/snespurify/phoenix/windows/font.cpp +++ b/snespurify/phoenix/windows/font.cpp @@ -6,6 +6,19 @@ static HFONT Font_createFont(const string &family, unsigned size, bool bold, boo ); } +Geometry pFont::geometry(const string &text) { + HDC hdc = GetDC(0); + SelectObject(hdc, hfont); + RECT rc = { 0, 0, 0, 0 }; + DrawText(hdc, utf16_t(text), -1, &rc, DT_CALCRECT); + ReleaseDC(0, hdc); + return { 0, 0, rc.right, rc.bottom }; +} + +unsigned pFont::height() { + return geometry(" ").height; +} + void pFont::setBold(bool bold) { if(hfont) { DeleteObject(hfont); hfont = 0; } hfont = Font_createFont(font.state.family, font.state.size, font.state.bold, font.state.italic, font.state.underline); @@ -32,5 +45,5 @@ void pFont::setUnderline(bool underline) { } void pFont::constructor() { - hfont = 0; + hfont = Font_createFont("Tahoma", 8, false, false, false); } diff --git a/snespurify/phoenix/windows/widget/button.cpp b/snespurify/phoenix/windows/widget/button.cpp index 936877b2..46696aa3 100755 --- a/snespurify/phoenix/windows/widget/button.cpp +++ b/snespurify/phoenix/windows/widget/button.cpp @@ -1,3 +1,9 @@ +Geometry pButton::minimumGeometry() { + Font &font = this->font(); + Geometry geometry = font.geometry(button.state.text); + return { 0, 0, geometry.width + 20, font.p.height() + 10 }; +} + void pButton::setText(const string &text) { SetWindowText(hwnd, utf16_t(text)); } diff --git a/snespurify/phoenix/windows/widget/canvas.cpp b/snespurify/phoenix/windows/widget/canvas.cpp new file mode 100755 index 00000000..e5618666 --- /dev/null +++ b/snespurify/phoenix/windows/widget/canvas.cpp @@ -0,0 +1,54 @@ +static LRESULT CALLBACK Canvas_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + if(msg == WM_PAINT) { + Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if(object && dynamic_cast(object)) { + Canvas &canvas = (Canvas&)*object; + canvas.update(); + } + } + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +uint32_t* pCanvas::buffer() { + return bufferRGB; +} + +void pCanvas::setGeometry(const Geometry &geometry) { + delete[] bufferRGB; + bufferRGB = new uint32_t[geometry.width * geometry.height](); + pWidget::setGeometry(geometry); + update(); +} + +void pCanvas::update() { + RECT rc; + GetClientRect(hwnd, &rc); + unsigned width = rc.right, height = rc.bottom; + + BITMAPINFO bmi; + memset(&bmi, 0, sizeof(BITMAPINFO)); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; //GDI stores bitmaps upside now; negative height flips bitmap + bmi.bmiHeader.biSizeImage = sizeof(uint32_t) * width * height; + + PAINTSTRUCT ps; + BeginPaint(hwnd, &ps); + SetDIBitsToDevice(ps.hdc, 0, 0, width, height, 0, 0, 0, height, (void*)bufferRGB, &bmi, DIB_RGB_COLORS); + EndPaint(hwnd, &ps); + InvalidateRect(hwnd, 0, false); +} + +void pCanvas::constructor() { + bufferRGB = new uint32_t[256 * 256](); + setParent(Window::None); +} + +void pCanvas::setParent(Window &parent) { + if(hwnd) DestroyWindow(hwnd); + hwnd = CreateWindow(L"phoenix_canvas", L"", WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, parent.p.hwnd, (HMENU)id, GetModuleHandle(0), 0); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&canvas); +} diff --git a/snespurify/phoenix/windows/widget/check-box.cpp b/snespurify/phoenix/windows/widget/check-box.cpp index a20bd7be..0f21b052 100755 --- a/snespurify/phoenix/windows/widget/check-box.cpp +++ b/snespurify/phoenix/windows/widget/check-box.cpp @@ -2,6 +2,12 @@ bool pCheckBox::checked() { return SendMessage(hwnd, BM_GETCHECK, 0, 0); } +Geometry pCheckBox::minimumGeometry() { + Font &font = this->font(); + Geometry geometry = font.geometry(checkBox.state.text); + return { 0, 0, geometry.width + 20, font.p.height() + 4 }; +} + void pCheckBox::setChecked(bool checked) { SendMessage(hwnd, BM_SETCHECK, (WPARAM)checked, 0); } diff --git a/snespurify/phoenix/windows/widget/combo-box.cpp b/snespurify/phoenix/windows/widget/combo-box.cpp index ecc6e6a3..88d81264 100755 --- a/snespurify/phoenix/windows/widget/combo-box.cpp +++ b/snespurify/phoenix/windows/widget/combo-box.cpp @@ -3,6 +3,13 @@ void pComboBox::append(const string &text) { if(SendMessage(hwnd, CB_GETCOUNT, 0, 0) == 1) setSelection(0); } +Geometry pComboBox::minimumGeometry() { + Font &font = this->font(); + unsigned maximumWidth = 0; + foreach(text, comboBox.state.text) maximumWidth = max(maximumWidth, font.geometry(text).width); + return { 0, 0, maximumWidth + 24, font.p.height() + 10 }; +} + void pComboBox::reset() { SendMessage(hwnd, CB_RESETCONTENT, 0, 0); } diff --git a/snespurify/phoenix/windows/widget/horizontal-slider.cpp b/snespurify/phoenix/windows/widget/horizontal-slider.cpp index b0758a59..c660be1e 100755 --- a/snespurify/phoenix/windows/widget/horizontal-slider.cpp +++ b/snespurify/phoenix/windows/widget/horizontal-slider.cpp @@ -1,3 +1,7 @@ +Geometry pHorizontalSlider::minimumGeometry() { + return { 0, 0, 0, 25 }; +} + unsigned pHorizontalSlider::position() { return SendMessage(hwnd, TBM_GETPOS, 0, 0); } diff --git a/snespurify/phoenix/windows/widget/label.cpp b/snespurify/phoenix/windows/widget/label.cpp index 0c827952..dc40ed61 100755 --- a/snespurify/phoenix/windows/widget/label.cpp +++ b/snespurify/phoenix/windows/widget/label.cpp @@ -1,3 +1,9 @@ +Geometry pLabel::minimumGeometry() { + Font &font = this->font(); + Geometry geometry = font.geometry(label.state.text); + return { 0, 0, geometry.width, geometry.height }; +} + void pLabel::setText(const string &text) { SetWindowText(hwnd, utf16_t(text)); InvalidateRect(hwnd, 0, false); diff --git a/snespurify/phoenix/windows/widget/line-edit.cpp b/snespurify/phoenix/windows/widget/line-edit.cpp index ccde0374..de54470d 100755 --- a/snespurify/phoenix/windows/widget/line-edit.cpp +++ b/snespurify/phoenix/windows/widget/line-edit.cpp @@ -1,3 +1,9 @@ +Geometry pLineEdit::minimumGeometry() { + Font &font = this->font(); + Geometry geometry = font.geometry(lineEdit.state.text); + return { 0, 0, geometry.width + 12, font.p.height() + 10 }; +} + void pLineEdit::setEditable(bool editable) { SendMessage(hwnd, EM_SETREADONLY, editable == false, 0); } @@ -13,7 +19,7 @@ string pLineEdit::text() { wchar_t text[length + 1]; GetWindowText(hwnd, text, length + 1); text[length] = 0; - return utf8_t(text); + return (const char*)utf8_t(text); } void pLineEdit::constructor() { diff --git a/snespurify/phoenix/windows/widget/progress-bar.cpp b/snespurify/phoenix/windows/widget/progress-bar.cpp index e3b7b9d7..46e65d18 100755 --- a/snespurify/phoenix/windows/widget/progress-bar.cpp +++ b/snespurify/phoenix/windows/widget/progress-bar.cpp @@ -1,3 +1,7 @@ +Geometry pProgressBar::minimumGeometry() { + return { 0, 0, 0, 23 }; +} + void pProgressBar::setPosition(unsigned position) { SendMessage(hwnd, PBM_SETPOS, (WPARAM)position, 0); } diff --git a/snespurify/phoenix/windows/widget/radio-box.cpp b/snespurify/phoenix/windows/widget/radio-box.cpp index 8f48e4d9..b135f87e 100755 --- a/snespurify/phoenix/windows/widget/radio-box.cpp +++ b/snespurify/phoenix/windows/widget/radio-box.cpp @@ -2,6 +2,12 @@ bool pRadioBox::checked() { return SendMessage(hwnd, BM_GETCHECK, 0, 0); } +Geometry pRadioBox::minimumGeometry() { + Font &font = this->font(); + Geometry geometry = font.geometry(radioBox.state.text); + return { 0, 0, geometry.width + 20, font.p.height() + 4 }; +} + void pRadioBox::setChecked() { foreach(item, radioBox.state.group) { SendMessage(item.p.hwnd, BM_SETCHECK, (WPARAM)(&item == &radioBox), 0); diff --git a/snespurify/phoenix/windows/widget/text-edit.cpp b/snespurify/phoenix/windows/widget/text-edit.cpp index c2026dc3..a1a42fe5 100755 --- a/snespurify/phoenix/windows/widget/text-edit.cpp +++ b/snespurify/phoenix/windows/widget/text-edit.cpp @@ -29,7 +29,7 @@ string pTextEdit::text() { wchar_t buffer[length + 1]; GetWindowText(hwnd, buffer, length + 1); buffer[length] = 0; - string text = utf8_t(buffer); + string text = (const char*)utf8_t(buffer); text.replace("\r", ""); return text; } diff --git a/snespurify/phoenix/windows/widget/vertical-slider.cpp b/snespurify/phoenix/windows/widget/vertical-slider.cpp index 5db91514..8c170cdf 100755 --- a/snespurify/phoenix/windows/widget/vertical-slider.cpp +++ b/snespurify/phoenix/windows/widget/vertical-slider.cpp @@ -1,3 +1,7 @@ +Geometry pVerticalSlider::minimumGeometry() { + return { 0, 0, 25, 0 }; +} + unsigned pVerticalSlider::position() { return SendMessage(hwnd, TBM_GETPOS, 0, 0); } diff --git a/snespurify/phoenix/windows/widget/widget.cpp b/snespurify/phoenix/windows/widget/widget.cpp index 062da650..81f984f7 100755 --- a/snespurify/phoenix/windows/widget/widget.cpp +++ b/snespurify/phoenix/windows/widget/widget.cpp @@ -2,6 +2,15 @@ bool pWidget::enabled() { return IsWindowEnabled(hwnd); } +Font& pWidget::font() { + if(widget.state.font) return *widget.state.font; + return pOS::state->defaultFont; +} + +Geometry pWidget::minimumGeometry() { + return { 0, 0, 0, 0 }; +} + void pWidget::setEnabled(bool enabled) { EnableWindow(hwnd, enabled); } diff --git a/snespurify/phoenix/windows/windows.cpp b/snespurify/phoenix/windows/windows.cpp index 1c6f0c97..4c3596a4 100755 --- a/snespurify/phoenix/windows/windows.cpp +++ b/snespurify/phoenix/windows/windows.cpp @@ -14,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" @@ -80,7 +81,7 @@ static string pOS_fileDialog(bool save, Window &parent, const string &path, cons bool result = (save == false ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn)); if(result == false) return ""; - string name = utf8_t(wfilename); + string name = (const char*)utf8_t(wfilename); name.transform("\\", "/"); return name; } @@ -117,7 +118,7 @@ string pOS::folderSelect(Window &parent, const string &path) { } } if(result == false) return ""; - string name = utf8_t(wfilename); + string name = (const char*)utf8_t(wfilename); if(name == "") return ""; name.transform("\\", "/"); if(name.endswith("/") == false) name.append("/"); @@ -183,6 +184,18 @@ void pOS::initialize() { wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClass(&wc); + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0)); + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = Canvas_windowProc; + wc.lpszClassName = L"phoenix_canvas"; + wc.lpszMenuName = 0; + wc.style = CS_HREDRAW | CS_VREDRAW; + RegisterClass(&wc); + wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); diff --git a/snespurify/phoenix/windows/windows.hpp b/snespurify/phoenix/windows/windows.hpp index 2e641308..70933131 100755 --- a/snespurify/phoenix/windows/windows.hpp +++ b/snespurify/phoenix/windows/windows.hpp @@ -37,6 +37,8 @@ struct pFont : public pObject { Font &font; HFONT hfont; + Geometry geometry(const string &text); + unsigned height(); void setBold(bool bold); void setFamily(const string &family); void setItalic(bool italic); @@ -155,6 +157,8 @@ struct pWidget : public pObject { HWND hwnd; bool enabled(); + Font& font(); + virtual Geometry minimumGeometry(); void setEnabled(bool enabled); void setFocused(); void setFont(Font &font); @@ -170,6 +174,7 @@ struct pWidget : public pObject { struct pButton : public pWidget { Button &button; + Geometry minimumGeometry(); void setText(const string &text); pButton(Button &button) : pWidget(button), button(button) {} @@ -177,10 +182,24 @@ struct pButton : public pWidget { void setParent(Window &parent); }; +struct pCanvas : public pWidget { + Canvas &canvas; + uint32_t *bufferRGB; + + uint32_t* buffer(); + void setGeometry(const Geometry &geometry); + void update(); + + pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {} + void constructor(); + void setParent(Window &parent); +}; + struct pCheckBox : public pWidget { CheckBox &checkBox; bool checked(); + Geometry minimumGeometry(); void setChecked(bool checked); void setText(const string &text); @@ -193,6 +212,7 @@ struct pComboBox : public pWidget { ComboBox &comboBox; void append(const string &text); + Geometry minimumGeometry(); void reset(); unsigned selection(); void setSelection(unsigned row); @@ -222,6 +242,7 @@ struct pHexEdit : public pWidget { struct pHorizontalSlider : public pWidget { HorizontalSlider &horizontalSlider; + Geometry minimumGeometry(); unsigned position(); void setLength(unsigned length); void setPosition(unsigned position); @@ -234,6 +255,7 @@ struct pHorizontalSlider : public pWidget { struct pLabel : public pWidget { Label &label; + Geometry minimumGeometry(); void setText(const string &text); pLabel(Label &label) : pWidget(label), label(label) {} @@ -244,6 +266,7 @@ struct pLabel : public pWidget { struct pLineEdit : public pWidget { LineEdit &lineEdit; + Geometry minimumGeometry(); void setEditable(bool editable); void setText(const string &text); string text(); @@ -280,6 +303,7 @@ struct pListView : public pWidget { struct pProgressBar : public pWidget { ProgressBar &progressBar; + Geometry minimumGeometry(); void setPosition(unsigned position); pProgressBar(ProgressBar &progressBar) : pWidget(progressBar), progressBar(progressBar) {} @@ -291,6 +315,7 @@ struct pRadioBox : public pWidget { RadioBox &radioBox; bool checked(); + Geometry minimumGeometry(); void setChecked(); void setGroup(const reference_array &group); void setText(const string &text); @@ -317,6 +342,7 @@ struct pTextEdit : public pWidget { struct pVerticalSlider : public pWidget { VerticalSlider &verticalSlider; + Geometry minimumGeometry(); unsigned position(); void setLength(unsigned length); void setPosition(unsigned position); diff --git a/snespurify/snespurify.cpp b/snespurify/snespurify.cpp index c640263f..4f07d05e 100755 --- a/snespurify/snespurify.cpp +++ b/snespurify/snespurify.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include using namespace nall; @@ -12,7 +11,7 @@ using namespace nall; #include using namespace phoenix; -static const char applicationTitle[] = "snespurify v07"; +static const char applicationTitle[] = "snespurify v10"; struct Application : Window { Font font; @@ -43,7 +42,6 @@ struct Application : Window { void scan(const string &pathname); void analyze(const string &filename); void repair(); - void createPatch(const string &filename); } application; void Application::main() { @@ -69,31 +67,20 @@ void Application::main() { fixSelected.setText("Correct"); layout.setMargin(5); - pathLayout.append(pathLabel, 80, 0, 5); - pathLayout.append(pathBox, 0, 0, 5); - pathLayout.append(pathScan, 80, 0, 5); - pathLayout.append(pathBrowse, 80, 0); - layout.append(pathLayout, 0, 25, 5); - layout.append(fileList, 0, 0, 5); - controlLayout.append(selectAll, 80, 0, 5); - controlLayout.append(unselectAll, 80, 0, 5); - controlLayout.append(spacer, 0, 0, 5); - controlLayout.append(fixSelected, 80, 0); - layout.append(controlLayout, 0, 25); + pathLayout.append(pathLabel, 0, 0, 5); + pathLayout.append(pathBox, ~0, 0, 5); + pathLayout.append(pathScan, 80, 0, 5); + pathLayout.append(pathBrowse, 80, 0 ); + layout.append(pathLayout, 5); + layout.append(fileList, ~0, ~0, 5); + controlLayout.append(selectAll, 80, 0, 5); + controlLayout.append(unselectAll, 80, 0, 5); + controlLayout.append(spacer, ~0, 0, 5); + controlLayout.append(fixSelected, 80, 0 ); + layout.append(controlLayout ); append(layout); -// unsigned x = 5, y = 5, width = 600, height = 25; -// layout.append(pathLabel, x, y, 80, height); -// layout.append(pathBox, x + 85, y, 335, height); -// layout.append(pathScan, x + 425, y, 80, height); -// layout.append(pathBrowse, x + 510, y, 80, height); y += height + 5; -// layout.append(fileList, x, y, 590, 290); y += 290 + 5; -// layout.append(selectAll, x, y, 80, height); -// layout.append(unselectAll, x + 85, y, 80, height); -// layout.append(fixSelected, 595 - 80, y, 80, height); y += height + 5; -// setLayout(layout); - - onClose = []() { OS::quit(); }; + onClose = &OS::quit; pathBox.onActivate = pathScan.onTick = { &Application::scan, this }; @@ -194,10 +181,7 @@ void Application::analyze(const string &filename) { unsigned filesize = map.size(); SNESCartridge information(map.data(), filesize); - //the ordering of rules is very important: - //patches need to be created prior to removal of headers - //headers need to be removed prior to renaming files (so header removal has correct filename) - //etc. + //note: the ordering of rules is very important switch(information.type) { case SNESCartridge::TypeNormal: case SNESCartridge::TypeBsxSlotted: @@ -205,16 +189,6 @@ void Application::analyze(const string &filename) { case SNESCartridge::TypeSufamiTurboBios: case SNESCartridge::TypeSuperGameBoy1Bios: case SNESCartridge::TypeSuperGameBoy2Bios: { - string ipsName = { nall::basename(filename), ".ips" }; - string upsName = { nall::basename(filename), ".ups" }; - if(file::exists(ipsName) == true && file::exists(upsName) == false) { - FileInfo info; - info.filename = filename; - info.problem = "Unsupported patch format"; - info.solution = "Create UPS patch"; - fileInfo.append(info); - } - if((filesize & 0x7fff) == 512) { FileInfo info; info.filename = filename; @@ -255,6 +229,14 @@ void Application::analyze(const string &filename) { } case SNESCartridge::TypeSufamiTurbo: { + if((filesize & 0x7fff) == 512) { + FileInfo info; + info.filename = filename; + info.problem = "Copier header present"; + info.solution = "Remove copier header"; + fileInfo.append(info); + } + if(filename.endswith(".st") == false) { FileInfo info; info.filename = filename; @@ -290,9 +272,7 @@ void Application::repair() { OS::processEvents(); FileInfo &info = fileInfo[n]; - if(info.solution == "Create UPS patch") { - createPatch(info.filename); - } else if(info.solution == "Remove copier header") { + if(info.solution == "Remove copier header") { file fp; if(fp.open(info.filename, file::mode::read)) { unsigned size = fp.size(); @@ -332,94 +312,6 @@ void Application::repair() { enable(true); } -void Application::createPatch(const string &filename) { - string ipsName = { nall::basename(filename), ".ips" }; - string upsName = { nall::basename(filename), ".ups" }; - - file fp; - if(fp.open(filename, file::mode::read)) { - unsigned isize = fp.size(); - uint8_t *idata = new uint8_t[isize]; - fp.read(idata, isize); - fp.close(); - - fp.open(ipsName, file::mode::read); - unsigned psize = fp.size(); - uint8_t *pdata = new uint8_t[psize]; - fp.read(pdata, psize); - fp.close(); - - if(psize >= 8 - && pdata[0] == 'P' && pdata[1] == 'A' && pdata[2] == 'T' && pdata[3] == 'C' && pdata[4] == 'H' - && pdata[psize - 3] == 'E' && pdata[psize - 2] == 'O' && pdata[psize - 1] == 'F') { - unsigned osize = 0; - //no way to determine how big IPS output will be, allocate max size IPS patches support -- 16MB - uint8_t *odata = new uint8_t[16 * 1024 * 1024](); - memcpy(odata, idata, isize); - - unsigned offset = 5; - while(offset < psize - 3) { - unsigned addr; - addr = pdata[offset++] << 16; - addr |= pdata[offset++] << 8; - addr |= pdata[offset++] << 0; - - unsigned size; - size = pdata[offset++] << 8; - size |= pdata[offset++] << 0; - - if(size == 0) { - //RLE - size = pdata[offset++] << 8; - size |= pdata[offset++] << 0; - - for(unsigned n = addr; n < addr + size;) { - odata[n++] = pdata[offset]; - if(n > osize) osize = n; - } - offset++; - } else { - for(unsigned n = addr; n < addr + size;) { - odata[n++] = pdata[offset++]; - if(n > osize) osize = n; - } - } - } - - osize = max(isize, osize); - bool hasHeader = ((isize & 0x7fff) == 512); - - uint8_t *widata = idata; - unsigned wisize = isize; - if(hasHeader) { - //remove copier header for UPS patch creation - widata += 512; - wisize -= 512; - } - - uint8_t *wodata = odata; - unsigned wosize = osize; - if(hasHeader) { - //remove copier header for UPS patch creation - wodata += 512; - wosize -= 512; - } - - ups patcher; - if(patcher.create(widata, wisize, wodata, wosize, upsName) != ups::result::success) { - errors.append({ "Failed to create UPS patch: ", upsName, "\n" }); - } - - delete[] odata; - } else { - errors.append({ "IPS patch is invalid: ", ipsName, "\n" }); - } - - delete[] idata; - delete[] pdata; - } -} - int main() { application.main(); OS::main();