From 599ae659548c27da4022623eb3561488d8e141b2 Mon Sep 17 00:00:00 2001 From: Isotarge Date: Sat, 27 Jan 2018 01:32:39 +1030 Subject: [PATCH] TFTT Module --- Beta/TFTT Mouse.lua | 18 -- README.md | 1 + ScriptHawk.lua | 276 ++++++++-------- .../Tyrants - Fight Through Time (U) [!].wch | 45 ++- Beta/TFTT Log.lua => games/tftt.lua | 300 ++++++++++++++---- lib/LibScriptHawk.lua | 18 ++ 6 files changed, 420 insertions(+), 238 deletions(-) delete mode 100644 Beta/TFTT Mouse.lua rename Beta/TFTT Log.lua => games/tftt.lua (64%) diff --git a/Beta/TFTT Mouse.lua b/Beta/TFTT Mouse.lua deleted file mode 100644 index 56687ad7..00000000 --- a/Beta/TFTT Mouse.lua +++ /dev/null @@ -1,18 +0,0 @@ -local cursorX = 0xB410; -local cursorY = 0xB412; - -local function doMouse() - -- Make game cursor follow real cursor - local mousePos = input.getmouse(); - mainmemory.write_u16_be(cursorX, mousePos.X * 2); - mainmemory.write_u16_be(cursorY, (mousePos.Y * 2) - 40); -- Minus 40 pixels to compensate for Overscan - - if mousePos.Left then - joypad.set({["B"] = true}, 1); - end - if mousePos.Right then - joypad.set({["C"] = true}, 1); - end -end - -event.onframestart(doMouse); \ No newline at end of file diff --git a/README.md b/README.md index 975b1a70..4b559c1a 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ While ScriptHawk does have basic support for OoT and MM there are people who are - Taz-Mania (SMS) - The Ninja (SMS) - Ty the Tasmanian Tiger 2: Bush Rescue (GBA) +- Tyrants - Fight Through Time (Mega Lo Mania) (Genesis) - Wonder Boy in Monster World (SMS) - Earthworm Jim 3D (N64) diff --git a/ScriptHawk.lua b/ScriptHawk.lua index 0b7662ec..5e23c8e8 100644 --- a/ScriptHawk.lua +++ b/ScriptHawk.lua @@ -309,202 +309,220 @@ end local supportedGames = { -- Alex Kidd in Miracle World -- TODO: Somehow support self contained modules with while true loops... - --["6E8E702E1D8A893EE698B93F5807972A"] = {["moduleName"] = "beta.Miracle World", ["selfContained"] = true, ["friendlyName"] = "Alex Kidd in Miracle World (J)"}, - --["3D9A8D5C2D6D3F8FF63A8F7C77FFA983"] = {["moduleName"] = "beta.Miracle World", ["selfContained"] = true, ["friendlyName"] = "Alex Kidd in Miracle World (UE)"}, - --["F43E74FFEC58DDF62F0B8667D31F22C0"] = {["moduleName"] = "beta.Miracle World", ["selfContained"] = true, ["friendlyName"] = "Alex Kidd in Miracle World (UE) (Rev 1)"}, + --["6E8E702E1D8A893EE698B93F5807972A"] = {moduleName="beta.Miracle World", selfContained=true, friendlyName="Alex Kidd in Miracle World (J)"}, + --["3D9A8D5C2D6D3F8FF63A8F7C77FFA983"] = {moduleName="beta.Miracle World", selfContained=true, friendlyName="Alex Kidd in Miracle World (UE)"}, + --["F43E74FFEC58DDF62F0B8667D31F22C0"] = {moduleName="beta.Miracle World", selfContained=true, friendlyName="Alex Kidd in Miracle World (UE) (Rev 1)"}, -- Banjo - ["90726D7E7CD5BF6CDFD38F45C9ACBF4D45BD9FD8"] = {["moduleName"] = "games.bk", ["friendlyName"] = "Banjo to Kazooie no Daibouken (Japan)"}, - ["5A5172383037D171F121790959962703BE1F373C"] = {["moduleName"] = "games.bt", ["friendlyName"] = "Banjo to Kazooie no Daibouken 2 (Japan)"}, - ["BB359A75941DF74BF7290212C89FBC6E2C5601FE"] = {["moduleName"] = "games.bk", ["friendlyName"] = "Banjo-Kazooie (Europe) (En,Fr,De)"}, - ["DED6EE166E740AD1BC810FD678A84B48E245AB80"] = {["moduleName"] = "games.bk", ["friendlyName"] = "Banjo-Kazooie (USA) (Rev A)"}, - ["1FE1632098865F639E22C11B9A81EE8F29C75D7A"] = {["moduleName"] = "games.bk", ["friendlyName"] = "Banjo-Kazooie (USA)"}, - ["4CA2D332F6E6B018777AFC6A8B7880B38B6DFB79"] = {["moduleName"] = "games.bt", ["friendlyName"] = "Banjo-Tooie (Australia)"}, - ["93BF2FAC1387320AD07251CB4B64FD36BAC1D7A6"] = {["moduleName"] = "games.bt", ["friendlyName"] = "Banjo-Tooie (Europe) (En,Fr,De,Es)"}, - ["AF1A89E12B638B8D82CC4C085C8E01D4CBA03FB3"] = {["moduleName"] = "games.bt", ["friendlyName"] = "Banjo-Tooie (USA)"}, + ["90726D7E7CD5BF6CDFD38F45C9ACBF4D45BD9FD8"] = {moduleName="games.bk", friendlyName="Banjo to Kazooie no Daibouken (Japan)"}, + ["5A5172383037D171F121790959962703BE1F373C"] = {moduleName="games.bt", friendlyName="Banjo to Kazooie no Daibouken 2 (Japan)"}, + ["BB359A75941DF74BF7290212C89FBC6E2C5601FE"] = {moduleName="games.bk", friendlyName="Banjo-Kazooie (Europe) (En,Fr,De)"}, + ["DED6EE166E740AD1BC810FD678A84B48E245AB80"] = {moduleName="games.bk", friendlyName="Banjo-Kazooie (USA) (Rev A)"}, + ["1FE1632098865F639E22C11B9A81EE8F29C75D7A"] = {moduleName="games.bk", friendlyName="Banjo-Kazooie (USA)"}, + ["4CA2D332F6E6B018777AFC6A8B7880B38B6DFB79"] = {moduleName="games.bt", friendlyName="Banjo-Tooie (Australia)"}, + ["93BF2FAC1387320AD07251CB4B64FD36BAC1D7A6"] = {moduleName="games.bt", friendlyName="Banjo-Tooie (Europe) (En,Fr,De,Es)"}, + ["AF1A89E12B638B8D82CC4C085C8E01D4CBA03FB3"] = {moduleName="games.bt", friendlyName="Banjo-Tooie (USA)"}, -- Conker's Bad Fur Day - ["EE7BC6656FD1E1D9FFB3D19ADD759F28B88DF710"] = {["moduleName"] = "games.cbfd", ["friendlyName"] = "Conker's Bad Fur Day (Europe)"}, - ["4CBADD3C4E0729DEC46AF64AD018050EADA4F47A"] = {["moduleName"] = "games.cbfd", ["friendlyName"] = "Conker's Bad Fur Day (USA)"}, + ["EE7BC6656FD1E1D9FFB3D19ADD759F28B88DF710"] = {moduleName="games.cbfd", friendlyName="Conker's Bad Fur Day (Europe)"}, + ["4CBADD3C4E0729DEC46AF64AD018050EADA4F47A"] = {moduleName="games.cbfd", friendlyName="Conker's Bad Fur Day (USA)"}, -- Crash Bandicoot - ["41B5F211"] = {["moduleName"] = "games.crash1", ["friendlyName"] = "Crash Bandicoot (USA)"}, - ["249FC147"] = {["moduleName"] = "games.crash1", ["friendlyName"] = "Crash Bandicoot (USA)"}, - ["D6172125"] = {["moduleName"] = "games.crash1", ["friendlyName"] = "Crash Bandicoot (Europe) (EDC)"}, - ["2033243A"] = {["moduleName"] = "games.crash1", ["friendlyName"] = "Crash Bandicoot (Europe) (EDC)"}, - ["FD11EB1E"] = {["moduleName"] = "games.crash1", ["friendlyName"] = "Crash Bandicoot (Europe) (No EDC)"}, - ["0B9EB02B"] = {["moduleName"] = "games.crash1", ["friendlyName"] = "Crash Bandicoot (Europe) (No EDC)"}, - ["D9BA797E"] = {["moduleName"] = "games.crash1", ["friendlyName"] = "Crash Bandicoot (Japan)"}, - ["F5B95131"] = {["moduleName"] = "games.crash1", ["friendlyName"] = "Crash Bandicoot (Japan)"}, + ["41B5F211"] = {moduleName="games.crash1", friendlyName="Crash Bandicoot (USA)"}, + ["249FC147"] = {moduleName="games.crash1", friendlyName="Crash Bandicoot (USA)"}, + ["D6172125"] = {moduleName="games.crash1", friendlyName="Crash Bandicoot (Europe) (EDC)"}, + ["2033243A"] = {moduleName="games.crash1", friendlyName="Crash Bandicoot (Europe) (EDC)"}, + ["FD11EB1E"] = {moduleName="games.crash1", friendlyName="Crash Bandicoot (Europe) (No EDC)"}, + ["0B9EB02B"] = {moduleName="games.crash1", friendlyName="Crash Bandicoot (Europe) (No EDC)"}, + ["D9BA797E"] = {moduleName="games.crash1", friendlyName="Crash Bandicoot (Japan)"}, + ["F5B95131"] = {moduleName="games.crash1", friendlyName="Crash Bandicoot (Japan)"}, -- Crash Bandicoot 2: Cortex Strikes Back - ["149A203B"] = {["moduleName"] = "games.crash2", ["friendlyName"] = "Crash Bandicoot 2 - Cortex Strikes Back (USA)"}, - ["395C0916"] = {["moduleName"] = "games.crash2", ["friendlyName"] = "Crash Bandicoot 2 - Cortex Strikes Back (USA)"}, - ["5F65CF0F"] = {["moduleName"] = "games.crash2", ["friendlyName"] = "Crash Bandicoot 2 - Cortex Strikes Back (Europe) (En,Fr,De,Es,It) (No EDC)"}, - ["F5E2EC49"] = {["moduleName"] = "games.crash2", ["friendlyName"] = "Crash Bandicoot 2 - Cortex Strikes Back (Europe) (En,Fr,De,Es,It) (No EDC)"}, - ["97395614"] = {["moduleName"] = "games.crash2", ["friendlyName"] = "Crash Bandicoot 2 - Cortex Strikes Back (Europe) (En,Fr,De,Es,It) (EDC)"}, - ["74C85B1E"] = {["moduleName"] = "games.crash2", ["friendlyName"] = "Crash Bandicoot 2 - Cortex Strikes Back (Europe) (En,Fr,De,Es,It) (EDC)"}, - ["B0A92BAF"] = {["moduleName"] = "games.crash2", ["friendlyName"] = "Crash Bandicoot 2 - Cortex no Gyakushuu! (Japan)"}, - ["14591AE9"] = {["moduleName"] = "games.crash2", ["friendlyName"] = "Crash Bandicoot 2 - Cortex no Gyakushuu! (Japan)"}, + ["149A203B"] = {moduleName="games.crash2", friendlyName="Crash Bandicoot 2 - Cortex Strikes Back (USA)"}, + ["395C0916"] = {moduleName="games.crash2", friendlyName="Crash Bandicoot 2 - Cortex Strikes Back (USA)"}, + ["5F65CF0F"] = {moduleName="games.crash2", friendlyName="Crash Bandicoot 2 - Cortex Strikes Back (Europe) (En,Fr,De,Es,It) (No EDC)"}, + ["F5E2EC49"] = {moduleName="games.crash2", friendlyName="Crash Bandicoot 2 - Cortex Strikes Back (Europe) (En,Fr,De,Es,It) (No EDC)"}, + ["97395614"] = {moduleName="games.crash2", friendlyName="Crash Bandicoot 2 - Cortex Strikes Back (Europe) (En,Fr,De,Es,It) (EDC)"}, + ["74C85B1E"] = {moduleName="games.crash2", friendlyName="Crash Bandicoot 2 - Cortex Strikes Back (Europe) (En,Fr,De,Es,It) (EDC)"}, + ["B0A92BAF"] = {moduleName="games.crash2", friendlyName="Crash Bandicoot 2 - Cortex no Gyakushuu! (Japan)"}, + ["14591AE9"] = {moduleName="games.crash2", friendlyName="Crash Bandicoot 2 - Cortex no Gyakushuu! (Japan)"}, -- Crash Bandicoot 3: Warped - ["05E3012B"] = {["moduleName"] = "games.crash3", ["friendlyName"] = "Crash Bandicoot - Warped (USA)"}, - ["9BF37B2C"] = {["moduleName"] = "games.crash3", ["friendlyName"] = "Crash Bandicoot - Warped (USA)"}, - ["39B868A1"] = {["moduleName"] = "games.crash3", ["friendlyName"] = "Crash Bandicoot 3 - Warped (Europe) (En,Fr,De,Es,It)"}, - ["A91BEA0E"] = {["moduleName"] = "games.crash3", ["friendlyName"] = "Crash Bandicoot 3 - Warped (Europe) (En,Fr,De,Es,It)"}, - ["7E59A4CE"] = {["moduleName"] = "games.crash3", ["friendlyName"] = "Crash Bandicoot 3 - Buttobi! Sekai Isshuu (Japan)"}, - ["A2E93AEC"] = {["moduleName"] = "games.crash3", ["friendlyName"] = "Crash Bandicoot 3 - Buttobi! Sekai Isshuu (Japan)"}, + ["05E3012B"] = {moduleName="games.crash3", friendlyName="Crash Bandicoot - Warped (USA)"}, + ["9BF37B2C"] = {moduleName="games.crash3", friendlyName="Crash Bandicoot - Warped (USA)"}, + ["39B868A1"] = {moduleName="games.crash3", friendlyName="Crash Bandicoot 3 - Warped (Europe) (En,Fr,De,Es,It)"}, + ["A91BEA0E"] = {moduleName="games.crash3", friendlyName="Crash Bandicoot 3 - Warped (Europe) (En,Fr,De,Es,It)"}, + ["7E59A4CE"] = {moduleName="games.crash3", friendlyName="Crash Bandicoot 3 - Buttobi! Sekai Isshuu (Japan)"}, + ["A2E93AEC"] = {moduleName="games.crash3", friendlyName="Crash Bandicoot 3 - Buttobi! Sekai Isshuu (Japan)"}, -- Diddy Kong Racing - ["B7F628073237B3D211D40406AA0884FF8FDD70D5"] = {["moduleName"] = "games.dkr", ["friendlyName"] = "Diddy Kong Racing (Europe) (En,Fr,De) (Rev A)"}, - ["DD5D64DD140CB7AA28404FA35ABDCABA33C29260"] = {["moduleName"] = "games.dkr", ["friendlyName"] = "Diddy Kong Racing (Europe) (En,Fr,De)"}, - ["23BA3D302025153D111416E751027CEF11213A19"] = {["moduleName"] = "games.dkr", ["friendlyName"] = "Diddy Kong Racing (Japan)"}, - ["6D96743D46F8C0CD0EDB0EC5600B003C89B93755"] = {["moduleName"] = "games.dkr", ["friendlyName"] = "Diddy Kong Racing (USA) (En,Fr) (Rev A)"}, - ["0CB115D8716DBBC2922FDA38E533B9FE63BB9670"] = {["moduleName"] = "games.dkr", ["friendlyName"] = "Diddy Kong Racing (USA) (En,Fr)"}, + ["B7F628073237B3D211D40406AA0884FF8FDD70D5"] = {moduleName="games.dkr", friendlyName="Diddy Kong Racing (Europe) (En,Fr,De) (Rev A)"}, + ["DD5D64DD140CB7AA28404FA35ABDCABA33C29260"] = {moduleName="games.dkr", friendlyName="Diddy Kong Racing (Europe) (En,Fr,De)"}, + ["23BA3D302025153D111416E751027CEF11213A19"] = {moduleName="games.dkr", friendlyName="Diddy Kong Racing (Japan)"}, + ["6D96743D46F8C0CD0EDB0EC5600B003C89B93755"] = {moduleName="games.dkr", friendlyName="Diddy Kong Racing (USA) (En,Fr) (Rev A)"}, + ["0CB115D8716DBBC2922FDA38E533B9FE63BB9670"] = {moduleName="games.dkr", friendlyName="Diddy Kong Racing (USA) (En,Fr)"}, -- Donkey Kong 64 - ["F96AF883845308106600D84E0618C1A066DC6676"] = {["moduleName"] = "games.dk64", ["friendlyName"] = "Donkey Kong 64 (Europe) (En,Fr,De,Es)"}, - ["F0AD2B2BBF04D574ED7AFBB1BB6A4F0511DCD87D"] = {["moduleName"] = "games.dk64", ["friendlyName"] = "Donkey Kong 64 (Japan)"}, - ["B4717E602F07CA9BE0D4822813C658CD8B99F993"] = {["moduleName"] = "games.dk64", ["friendlyName"] = "Donkey Kong 64 (USA) (Demo) (Kiosk)"}, - ["CF806FF2603640A748FCA5026DED28802F1F4A50"] = {["moduleName"] = "games.dk64", ["friendlyName"] = "Donkey Kong 64 (USA)"}, + ["F96AF883845308106600D84E0618C1A066DC6676"] = {moduleName="games.dk64", friendlyName="Donkey Kong 64 (Europe) (En,Fr,De,Es)"}, + ["F0AD2B2BBF04D574ED7AFBB1BB6A4F0511DCD87D"] = {moduleName="games.dk64", friendlyName="Donkey Kong 64 (Japan)"}, + ["B4717E602F07CA9BE0D4822813C658CD8B99F993"] = {moduleName="games.dk64", friendlyName="Donkey Kong 64 (USA) (Demo) (Kiosk)"}, + ["CF806FF2603640A748FCA5026DED28802F1F4A50"] = {moduleName="games.dk64", friendlyName="Donkey Kong 64 (USA)"}, -- Drill Dozer - ["C1058CC2482B91204100CC8515DA99AEB06773F5"] = {["moduleName"] = "games.GBA_DrillDozer", ["friendlyName"] = "Drill Dozer (USA)"}, - ["84AFA7108E4D604E7B1A6D105DF5760869A247FA"] = {["moduleName"] = "games.GBA_DrillDozer", ["friendlyName"] = "Screw Breaker Goushin Dorirurero (Japan)"}, + ["C1058CC2482B91204100CC8515DA99AEB06773F5"] = {moduleName="games.GBA_DrillDozer", friendlyName="Drill Dozer (USA)"}, + ["84AFA7108E4D604E7B1A6D105DF5760869A247FA"] = {moduleName="games.GBA_DrillDozer", friendlyName="Screw Breaker Goushin Dorirurero (Japan)"}, -- Earthworm Jim 3D - ["EAB14F23640CD6148D4888902CDCC00DD6111BF9"] = {["moduleName"] = "games.ej3d", ["friendlyName"] = "Earthworm Jim 3D (USA)"}, - ["F02C1AFD18C1CBE309472CBE5B3B3F04B22DB7EE"] = {["moduleName"] = "games.ej3d", ["friendlyName"] = "Earthworm Jim 3D (Europe) (En,Fr,De,Es,It)"}, + ["EAB14F23640CD6148D4888902CDCC00DD6111BF9"] = {moduleName="games.ej3d", friendlyName="Earthworm Jim 3D (USA)"}, + ["F02C1AFD18C1CBE309472CBE5B3B3F04B22DB7EE"] = {moduleName="games.ej3d", friendlyName="Earthworm Jim 3D (Europe) (En,Fr,De,Es,It)"}, -- Elmo - ["97777CA06F4E8AFF8F1E95033CC8D3833BE40F76"] = {["moduleName"] = "games.elmo", ["friendlyName"] = "Elmo's Letter Adventure (USA)"}, - ["7195EA96D9FE5DE065AF61F70D55C92C8EE905E6"] = {["moduleName"] = "games.elmo", ["friendlyName"] = "Elmo's Number Journey (USA)"}, + ["97777CA06F4E8AFF8F1E95033CC8D3833BE40F76"] = {moduleName="games.elmo", friendlyName="Elmo's Letter Adventure (USA)"}, + ["7195EA96D9FE5DE065AF61F70D55C92C8EE905E6"] = {moduleName="games.elmo", friendlyName="Elmo's Number Journey (USA)"}, -- Galahad - ["536E5A1FFB50D33632A9978B35DB5DF6"] = {["moduleName"] = "beta.Galahad", ["selfContained"] = true, ["friendlyName"] = "Legend of Galahad, The (UE) [!]"}, - ["FA7A34B92D06013625C2FE155A9DB5A8"] = {["moduleName"] = "beta.Galahad", ["selfContained"] = true, ["friendlyName"] = "Legend of Galahad, The (UE) [t1+C]"}, - ["3F183BD8A7360E3BE3CF65AE8FF9810C"] = {["moduleName"] = "beta.Galahad", ["selfContained"] = true, ["friendlyName"] = "Legend of Galahad, The (UE) [t1]"}, + ["536E5A1FFB50D33632A9978B35DB5DF6"] = {moduleName="beta.Galahad", selfContained=true, friendlyName="Legend of Galahad, The (UE) [!]"}, + ["FA7A34B92D06013625C2FE155A9DB5A8"] = {moduleName="beta.Galahad", selfContained=true, friendlyName="Legend of Galahad, The (UE) [t1+C]"}, + ["3F183BD8A7360E3BE3CF65AE8FF9810C"] = {moduleName="beta.Galahad", selfContained=true, friendlyName="Legend of Galahad, The (UE) [t1]"}, -- Golden Axe Warrior - ["D46E40BBB729BA233F171AD7BF6169F5"] = {["moduleName"] = "beta.Golden Axe Warrior", ["selfContained"] = true, ["friendlyName"] = "Golden Axe Warrior (UE)"}, + ["D46E40BBB729BA233F171AD7BF6169F5"] = {moduleName="beta.Golden Axe Warrior", selfContained=true, friendlyName="Golden Axe Warrior (UE)"}, -- Golvellius - ["2101295C258CB6B845BDB72BE617691D"] = {["moduleName"] = "beta.Golvellius", ["selfContained"] = true, ["friendlyName"] = "Golvellius (UE)"}, - ["6BD9879AF39E248D149761014EBF5639"] = {["moduleName"] = "beta.Golvellius", ["selfContained"] = true, ["friendlyName"] = "Golvellius (J)"}, + ["2101295C258CB6B845BDB72BE617691D"] = {moduleName="beta.Golvellius", selfContained=true, friendlyName="Golvellius (UE)"}, + ["6BD9879AF39E248D149761014EBF5639"] = {moduleName="beta.Golvellius", selfContained=true, friendlyName="Golvellius (J)"}, -- Impossible Mission - ["AF51AB03A173DEC28C9241532227CD64"] = {["moduleName"] = "games.impossible_mission", ["friendlyName"] = "Impossible Mission (E)"}, - ["A26D40B6B7646C22D1F2DB7F746F0391"] = {["moduleName"] = "games.impossible_mission", ["friendlyName"] = "Impossible Mission (E) (Beta)"}, + ["AF51AB03A173DEC28C9241532227CD64"] = {moduleName="games.impossible_mission", friendlyName="Impossible Mission (E)"}, + ["A26D40B6B7646C22D1F2DB7F746F0391"] = {moduleName="games.impossible_mission", friendlyName="Impossible Mission (E) (Beta)"}, -- Lord of the Sword - ["6A08D913FD92A213B1ECF5AA7C5630362CCCC6B4"] = {["moduleName"] = "games.lots", ["friendlyName"] = "Lord of the Sword (J)"}, - ["A5736126ED7E8569A189065EC20ADF72"] = {["moduleName"] = "games.lots", ["friendlyName"] = "Lord of the Sword (J)"}, - ["A5326A0029F7C3101ADD3335A599A01CCD7634C5"] = {["moduleName"] = "games.lots", ["friendlyName"] = "Lord of the Sword (UE)"}, - ["B80F87887881343E5705FF3CCE93C5F1"] = {["moduleName"] = "games.lots", ["friendlyName"] = "Lord of the Sword (UE)"}, + ["6A08D913FD92A213B1ECF5AA7C5630362CCCC6B4"] = {moduleName="games.lots", friendlyName="Lord of the Sword (J)"}, + ["A5736126ED7E8569A189065EC20ADF72"] = {moduleName="games.lots", friendlyName="Lord of the Sword (J)"}, + ["A5326A0029F7C3101ADD3335A599A01CCD7634C5"] = {moduleName="games.lots", friendlyName="Lord of the Sword (UE)"}, + ["B80F87887881343E5705FF3CCE93C5F1"] = {moduleName="games.lots", friendlyName="Lord of the Sword (UE)"}, -- Majora's Mask - ["B38B71D2961DFFB523020A67F4807A4B704E347A"] = {["moduleName"] = "games.mm", ["friendlyName"] = "Legend of Zelda, The - Majora's Mask (Europe) (En,Fr,De,Es) (Beta)"}, - ["BB4E4757D10727C7584C59C1F2E5F44196E9C293"] = {["moduleName"] = "games.mm", ["friendlyName"] = "Legend of Zelda, The - Majora's Mask (Europe) (En,Fr,De,Es) (Rev A)"}, - ["C04599CDAFEE1C84A7AF9A71DF68F139179ADA84"] = {["moduleName"] = "games.mm", ["friendlyName"] = "Legend of Zelda, The - Majora's Mask (Europe) (En,Fr,De,Es)"}, - ["2F0744F2422B0421697A74B305CB1EF27041AB11"] = {["moduleName"] = "games.mm", ["friendlyName"] = "Legend of Zelda, The - Majora's Mask (USA) (Demo)"}, - ["D6133ACE5AFAA0882CF214CF88DABA39E266C078"] = {["moduleName"] = "games.mm", ["friendlyName"] = "Legend of Zelda, The - Majora's Mask (USA)"}, - ["41FDB879AB422EC158B4EAFEA69087F255EA8589"] = {["moduleName"] = "games.mm", ["friendlyName"] = "Zelda no Densetsu - Mujura no Kamen (Japan) (Rev A)"}, - ["5FB2301AACBF85278AF30DCA3E4194AD48599E36"] = {["moduleName"] = "games.mm", ["friendlyName"] = "Zelda no Densetsu - Mujura no Kamen (Japan)"}, + ["B38B71D2961DFFB523020A67F4807A4B704E347A"] = {moduleName="games.mm", friendlyName="Legend of Zelda, The - Majora's Mask (Europe) (En,Fr,De,Es) (Beta)"}, + ["BB4E4757D10727C7584C59C1F2E5F44196E9C293"] = {moduleName="games.mm", friendlyName="Legend of Zelda, The - Majora's Mask (Europe) (En,Fr,De,Es) (Rev A)"}, + ["C04599CDAFEE1C84A7AF9A71DF68F139179ADA84"] = {moduleName="games.mm", friendlyName="Legend of Zelda, The - Majora's Mask (Europe) (En,Fr,De,Es)"}, + ["2F0744F2422B0421697A74B305CB1EF27041AB11"] = {moduleName="games.mm", friendlyName="Legend of Zelda, The - Majora's Mask (USA) (Demo)"}, + ["D6133ACE5AFAA0882CF214CF88DABA39E266C078"] = {moduleName="games.mm", friendlyName="Legend of Zelda, The - Majora's Mask (USA)"}, + ["41FDB879AB422EC158B4EAFEA69087F255EA8589"] = {moduleName="games.mm", friendlyName="Zelda no Densetsu - Mujura no Kamen (Japan) (Rev A)"}, + ["5FB2301AACBF85278AF30DCA3E4194AD48599E36"] = {moduleName="games.mm", friendlyName="Zelda no Densetsu - Mujura no Kamen (Japan)"}, -- Mr. Driller - ["E7009DD8418303343C4AAC2558538B8CAA28B694"] = {["moduleName"] = "beta.Drillbot", ["selfContained"] = true, ["friendlyName"] = "Mr. Driller 2 (USA)"}, + ["E7009DD8418303343C4AAC2558538B8CAA28B694"] = {moduleName="beta.Drillbot", selfContained=true, friendlyName="Mr. Driller 2 (USA)"}, -- Ocarina of Time - ["CFBB98D392E4A9D39DA8285D10CBEF3974C2F012"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Legend of Zelda, The - Ocarina of Time (Europe) (En,Fr,De) (Rev A)"}, - ["328A1F1BEBA30CE5E178F031662019EB32C5F3B5"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Legend of Zelda, The - Ocarina of Time (Europe) (En,Fr,De)"}, - ["D3ECB253776CD847A5AA63D859D8C89A2F37B364"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Legend of Zelda, The - Ocarina of Time (USA) (Rev A)"}, - ["41B3BDC48D98C48529219919015A1AF22F5057C2"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Legend of Zelda, The - Ocarina of Time (USA) (Rev B)"}, - ["AD69C91157F6705E8AB06C79FE08AAD47BB57BA7"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Legend of Zelda, The - Ocarina of Time (USA)"}, - ["50BEBEDAD9E0F10746A52B07239E47FA6C284D03"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Legend of Zelda, The - Ocarina of Time - Master Quest (USA) (Debug Edition)"}, - ["8B5D13AAC69BFBF989861CFDC50B1D840945FC1D"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Legend of Zelda, The - Ocarina of Time - Master Quest (USA) (GC)"}, - ["DBFC81F655187DC6FEFD93FA6798FACE770D579D"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Zelda no Densetsu - Toki no Ocarina (Japan) (Rev A)"}, - ["FA5F5942B27480D60243C2D52C0E93E26B9E6B86"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Zelda no Densetsu - Toki no Ocarina (Japan) (Rev B)"}, - ["C892BBDA3993E66BD0D56A10ECD30B1EE612210F"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Zelda no Densetsu - Toki no Ocarina (Japan)"}, - ["DD14E143C4275861FE93EA79D0C02E36AE8C6C2F"] = {["moduleName"] = "games.oot", ["friendlyName"] = "Zelda no Densetsu - Toki no Ocarina (Japan) (GC)"}, + ["CFBB98D392E4A9D39DA8285D10CBEF3974C2F012"] = {moduleName="games.oot", friendlyName="Legend of Zelda, The - Ocarina of Time (Europe) (En,Fr,De) (Rev A)"}, + ["328A1F1BEBA30CE5E178F031662019EB32C5F3B5"] = {moduleName="games.oot", friendlyName="Legend of Zelda, The - Ocarina of Time (Europe) (En,Fr,De)"}, + ["D3ECB253776CD847A5AA63D859D8C89A2F37B364"] = {moduleName="games.oot", friendlyName="Legend of Zelda, The - Ocarina of Time (USA) (Rev A)"}, + ["41B3BDC48D98C48529219919015A1AF22F5057C2"] = {moduleName="games.oot", friendlyName="Legend of Zelda, The - Ocarina of Time (USA) (Rev B)"}, + ["AD69C91157F6705E8AB06C79FE08AAD47BB57BA7"] = {moduleName="games.oot", friendlyName="Legend of Zelda, The - Ocarina of Time (USA)"}, + ["50BEBEDAD9E0F10746A52B07239E47FA6C284D03"] = {moduleName="games.oot", friendlyName="Legend of Zelda, The - Ocarina of Time - Master Quest (USA) (Debug Edition)"}, + ["8B5D13AAC69BFBF989861CFDC50B1D840945FC1D"] = {moduleName="games.oot", friendlyName="Legend of Zelda, The - Ocarina of Time - Master Quest (USA) (GC)"}, + ["DBFC81F655187DC6FEFD93FA6798FACE770D579D"] = {moduleName="games.oot", friendlyName="Zelda no Densetsu - Toki no Ocarina (Japan) (Rev A)"}, + ["FA5F5942B27480D60243C2D52C0E93E26B9E6B86"] = {moduleName="games.oot", friendlyName="Zelda no Densetsu - Toki no Ocarina (Japan) (Rev B)"}, + ["C892BBDA3993E66BD0D56A10ECD30B1EE612210F"] = {moduleName="games.oot", friendlyName="Zelda no Densetsu - Toki no Ocarina (Japan)"}, + ["DD14E143C4275861FE93EA79D0C02E36AE8C6C2F"] = {moduleName="games.oot", friendlyName="Zelda no Densetsu - Toki no Ocarina (Japan) (GC)"}, -- Penguin Land - ["8762239C339A084DFB8443CC38515301476BDE28"] = {["moduleName"] = "games.penguin_land", ["friendlyName"] = "Penguin Land (UE)"}, - ["8DDEC589F72CDCF2CD4CAAFB075EC8E4"] = {["moduleName"] = "games.penguin_land", ["friendlyName"] = "Penguin Land (UE)"}, - ["C01CF44EEE335D509DC20A165ADD8514E7FBB7C4"] = {["moduleName"] = "games.penguin_land", ["friendlyName"] = "Doki Doki Penguin Land - Uchuu Daibouken (J)"}, - ["FF7502DD8A717DB5ADB42C711DDBC9F5"] = {["moduleName"] = "games.penguin_land", ["friendlyName"] = "Doki Doki Penguin Land - Uchuu Daibouken (J)"}, + ["8762239C339A084DFB8443CC38515301476BDE28"] = {moduleName="games.penguin_land", friendlyName="Penguin Land (UE)"}, + ["8DDEC589F72CDCF2CD4CAAFB075EC8E4"] = {moduleName="games.penguin_land", friendlyName="Penguin Land (UE)"}, + ["C01CF44EEE335D509DC20A165ADD8514E7FBB7C4"] = {moduleName="games.penguin_land", friendlyName="Doki Doki Penguin Land - Uchuu Daibouken (J)"}, + ["FF7502DD8A717DB5ADB42C711DDBC9F5"] = {moduleName="games.penguin_land", friendlyName="Doki Doki Penguin Land - Uchuu Daibouken (J)"}, -- Psycho Fox - ["278CC3853905626138E83B6CFA39C26BA8E4F632"] = {["moduleName"] = "games.psycho_fox", ["friendlyName"] = "Psycho Fox (UE)"}, - ["A9C2FACF9EF536D095414CE2E7CE2F4F"] = {["moduleName"] = "games.psycho_fox", ["friendlyName"] = "Psycho Fox (UE)"}, + ["278CC3853905626138E83B6CFA39C26BA8E4F632"] = {moduleName="games.psycho_fox", friendlyName="Psycho Fox (UE)"}, + ["A9C2FACF9EF536D095414CE2E7CE2F4F"] = {moduleName="games.psycho_fox", friendlyName="Psycho Fox (UE)"}, -- Rats! - ["5E423DFAB8221B69A641D2E535EBFE1E3759A2E4"] = {["moduleName"] = "games.rats", ["friendlyName"] = "Rats! (USA) (En,Es)"}, + ["5E423DFAB8221B69A641D2E535EBFE1E3759A2E4"] = {moduleName="games.rats", friendlyName="Rats! (USA) (En,Es)"}, -- Rayman 2 - ["619AB27EA1645399439AD324566361D3E7FF020E"] = {["moduleName"] = "games.rayman_2", ["friendlyName"] = "Rayman 2 - The Great Escape (Europe) (En,Fr,De,Es,It)"}, - ["50558356B059AD3FBAF5FE95380512B9DCEAAF52"] = {["moduleName"] = "games.rayman_2", ["friendlyName"] = "Rayman 2 - The Great Escape (USA) (En,Fr,De,Es,It)"}, + ["619AB27EA1645399439AD324566361D3E7FF020E"] = {moduleName="games.rayman_2", friendlyName="Rayman 2 - The Great Escape (Europe) (En,Fr,De,Es,It)"}, + ["50558356B059AD3FBAF5FE95380512B9DCEAAF52"] = {moduleName="games.rayman_2", friendlyName="Rayman 2 - The Great Escape (USA) (En,Fr,De,Es,It)"}, -- San Francisco Rush 2049 - ["3F99351D7BB61656614BDB2AA1A90CFE55D1922C"] = {["moduleName"] = "games.rush_2049", ["friendlyName"] = "San Francisco Rush 2049 (USA)"}, - ["61373D4758ECA3FA831BEAC27B4D4C250845F80C"] = {["moduleName"] = "games.rush_2049", ["friendlyName"] = "San Francisco Rush 2049 (Europe) (En,Fr,De,Es,It,Nl)"}, + ["3F99351D7BB61656614BDB2AA1A90CFE55D1922C"] = {moduleName="games.rush_2049", friendlyName="San Francisco Rush 2049 (USA)"}, + ["61373D4758ECA3FA831BEAC27B4D4C250845F80C"] = {moduleName="games.rush_2049", friendlyName="San Francisco Rush 2049 (Europe) (En,Fr,De,Es,It,Nl)"}, -- Super Mario 64 - ["4AC5721683D0E0B6BBB561B58A71740845DCEEA9"] = {["moduleName"] = "games.sm64", ["friendlyName"] = "Super Mario 64 (Europe) (En,Fr,De)"}, - ["3F319AE697533A255A1003D09202379D78D5A2E0"] = {["moduleName"] = "games.sm64", ["friendlyName"] = "Super Mario 64 (Japan) (Rev A) (Shindou Edition)"}, - ["8A20A5C83D6CEB0F0506CFC9FA20D8F438CAFE51"] = {["moduleName"] = "games.sm64", ["friendlyName"] = "Super Mario 64 (Japan)"}, - ["9BEF1128717F958171A4AFAC3ED78EE2BB4E86CE"] = {["moduleName"] = "games.sm64", ["friendlyName"] = "Super Mario 64 (USA)"}, + ["4AC5721683D0E0B6BBB561B58A71740845DCEEA9"] = {moduleName="games.sm64", friendlyName="Super Mario 64 (Europe) (En,Fr,De)"}, + ["3F319AE697533A255A1003D09202379D78D5A2E0"] = {moduleName="games.sm64", friendlyName="Super Mario 64 (Japan) (Rev A) (Shindou Edition)"}, + ["8A20A5C83D6CEB0F0506CFC9FA20D8F438CAFE51"] = {moduleName="games.sm64", friendlyName="Super Mario 64 (Japan)"}, + ["9BEF1128717F958171A4AFAC3ED78EE2BB4E86CE"] = {moduleName="games.sm64", friendlyName="Super Mario 64 (USA)"}, -- Smash 64 - ["4B71F0E01878696733EEFA9C80D11C147ECB4984"] = {["moduleName"] = "games.smash64", ["friendlyName"] = "Nintendo All-Star! Dairantou Smash Brothers (Japan)"}, - ["A9BF83FE73361E8D042C33ED48B3851D7D46712C"] = {["moduleName"] = "games.smash64", ["friendlyName"] = "Super Smash Bros. (Australia)"}, - ["6EE8A41FEF66280CE3E3F0984D00B96079442FB9"] = {["moduleName"] = "games.smash64", ["friendlyName"] = "Super Smash Bros. (Europe) (En,Fr,De)"}, - ["E2929E10FCCC0AA84E5776227E798ABC07CEDABF"] = {["moduleName"] = "games.smash64", ["friendlyName"] = "Super Smash Bros. (USA)"}, - ["88C8FED5ECD5ED901CB5FC4B5BBEFFA3EA022DF7"] = {["moduleName"] = "games.smash64", ["friendlyName"] = "19XXTE 0.11"}, + ["4B71F0E01878696733EEFA9C80D11C147ECB4984"] = {moduleName="games.smash64", friendlyName="Nintendo All-Star! Dairantou Smash Brothers (Japan)"}, + ["A9BF83FE73361E8D042C33ED48B3851D7D46712C"] = {moduleName="games.smash64", friendlyName="Super Smash Bros. (Australia)"}, + ["6EE8A41FEF66280CE3E3F0984D00B96079442FB9"] = {moduleName="games.smash64", friendlyName="Super Smash Bros. (Europe) (En,Fr,De)"}, + ["E2929E10FCCC0AA84E5776227E798ABC07CEDABF"] = {moduleName="games.smash64", friendlyName="Super Smash Bros. (USA)"}, + ["88C8FED5ECD5ED901CB5FC4B5BBEFFA3EA022DF7"] = {moduleName="games.smash64", friendlyName="19XXTE 0.11"}, -- Sonic The Hedgehog (SMS) - ["6B9677E4A9ABB37765D6DB4658F4324251807E07"] = {["moduleName"] = "games.sonic1_sms", ["friendlyName"] = "Sonic The Hedgehog (UE)"}, - ["DC13A61EAFE75C13C15B5ECE419AC57B"] = {["moduleName"] = "games.sonic1_sms", ["friendlyName"] = "Sonic The Hedgehog (UE)"}, - ["6ACA0E3DFFE461BA1CB11A86CD4CAF5B97E1B8DF"] = {["moduleName"] = "games.sonic1_sms", ["friendlyName"] = "Sonic The Hedgehog (E) (BIOS)"}, - ["4187D96BEAF36385E681A3CF3BD1663D"] = {["moduleName"] = "games.sonic1_sms", ["friendlyName"] = "Sonic The Hedgehog (E) (BIOS)"}, + ["6B9677E4A9ABB37765D6DB4658F4324251807E07"] = {moduleName="games.sonic1_sms", friendlyName="Sonic The Hedgehog (UE)"}, + ["DC13A61EAFE75C13C15B5ECE419AC57B"] = {moduleName="games.sonic1_sms", friendlyName="Sonic The Hedgehog (UE)"}, + ["6ACA0E3DFFE461BA1CB11A86CD4CAF5B97E1B8DF"] = {moduleName="games.sonic1_sms", friendlyName="Sonic The Hedgehog (E) (BIOS)"}, + ["4187D96BEAF36385E681A3CF3BD1663D"] = {moduleName="games.sonic1_sms", friendlyName="Sonic The Hedgehog (E) (BIOS)"}, -- Space Station Silicon Valley - ["E5E09205AA743A9E5043A42DF72ADC379C746B0B"] = {["moduleName"] = "games.sssv", ["friendlyName"] = "Space Station Silicon Valley (USA)"}, - ["23710541BB3394072740B0F0236A7CB1A7D41531"] = {["moduleName"] = "games.sssv", ["friendlyName"] = "Space Station Silicon Valley (Europe) (En,Fr,De)"}, + ["E5E09205AA743A9E5043A42DF72ADC379C746B0B"] = {moduleName="games.sssv", friendlyName="Space Station Silicon Valley (USA)"}, + ["23710541BB3394072740B0F0236A7CB1A7D41531"] = {moduleName="games.sssv", friendlyName="Space Station Silicon Valley (Europe) (En,Fr,De)"}, -- Taz-Mania (SMS) - ["AC98F23DDC24609CB77BB13102E0386F8C2A4A76"] = {["moduleName"] = "games.taz", ["friendlyName"] = "Taz-Mania (E)"}, - ["CFC878F0163933FCFCC89E134FBEB31F"] = {["moduleName"] = "games.taz", ["friendlyName"] = "Taz-Mania (E)"}, + ["AC98F23DDC24609CB77BB13102E0386F8C2A4A76"] = {moduleName="games.taz", friendlyName="Taz-Mania (E)"}, + ["CFC878F0163933FCFCC89E134FBEB31F"] = {moduleName="games.taz", friendlyName="Taz-Mania (E)"}, -- Tetris Attack -- TODO: Support more versions of this game - ["EAD855D774C9943F7FFB5B4F429B2DD07FB6F606"] = {["moduleName"] = "Tetris Attack Bot", ["selfContained"] = true, ["friendlyName"] = "Panel de Pon (Japan)"}, -- SNES - ["B59061561A3AEAC13E46735582F29826E7310141"] = {["moduleName"] = "Tetris Attack Bot", ["selfContained"] = true, ["friendlyName"] = "Panel de Pon - Event '98 (Japan) (BS)"}, -- SNES - ["08E01F9AD5B6148E1A4355C80E2B23D8B2463443"] = {["moduleName"] = "Tetris Attack Bot", ["selfContained"] = true, ["friendlyName"] = "Tetris Attack (Europe) (En,Ja)"}, -- SNES - ["2DC56EAB3E70C0910AE47119D8B69F494E6000DF"] = {["moduleName"] = "Tetris Attack Bot", ["selfContained"] = true, ["friendlyName"] = "Tetris Attack (USA) (En,Ja)"}, -- SNES + ["EAD855D774C9943F7FFB5B4F429B2DD07FB6F606"] = {moduleName="Tetris Attack Bot", selfContained=true, friendlyName="Panel de Pon (Japan)"}, -- SNES + ["B59061561A3AEAC13E46735582F29826E7310141"] = {moduleName="Tetris Attack Bot", selfContained=true, friendlyName="Panel de Pon - Event '98 (Japan) (BS)"}, -- SNES + ["08E01F9AD5B6148E1A4355C80E2B23D8B2463443"] = {moduleName="Tetris Attack Bot", selfContained=true, friendlyName="Tetris Attack (Europe) (En,Ja)"}, -- SNES + ["2DC56EAB3E70C0910AE47119D8B69F494E6000DF"] = {moduleName="Tetris Attack Bot", selfContained=true, friendlyName="Tetris Attack (USA) (En,Ja)"}, -- SNES -- The Ninja (SMS) - ["76396A25902700E18ADF6BC5C8668E2A8BDF03A9"] = {["moduleName"] = "games.the_ninja", ["friendlyName"] = "The Ninja (UE)"}, - ["E9ACDAE112A898F7DB090FC0B8F1CE9B86637234"] = {["moduleName"] = "games.the_ninja", ["friendlyName"] = "The Ninja (J)"}, - ["2C620BA64FCAAC940B4B1566733037B3"] = {["moduleName"] = "games.the_ninja", ["friendlyName"] = "The Ninja (UE)"}, - ["41E20AFE05C2FBE45AC5F3A9C8111047"] = {["moduleName"] = "games.the_ninja", ["friendlyName"] = "The Ninja (J)"}, + ["76396A25902700E18ADF6BC5C8668E2A8BDF03A9"] = {moduleName="games.the_ninja", friendlyName="The Ninja (UE)"}, + ["E9ACDAE112A898F7DB090FC0B8F1CE9B86637234"] = {moduleName="games.the_ninja", friendlyName="The Ninja (J)"}, + ["2C620BA64FCAAC940B4B1566733037B3"] = {moduleName="games.the_ninja", friendlyName="The Ninja (UE)"}, + ["41E20AFE05C2FBE45AC5F3A9C8111047"] = {moduleName="games.the_ninja", friendlyName="The Ninja (J)"}, -- Toy Story 2 - ["A9F97E22391313095D2C2FBAF81FB33BFA2BA7C6"] = {["moduleName"] = "games.ts2", ["friendlyName"] = "Toy Story 2 - Buzz l'Eclair a la Rescousse! (France)"}, - ["92015E5254CBBAD1BC668ECB13A4B568E5F55052"] = {["moduleName"] = "games.ts2", ["friendlyName"] = "Toy Story 2 - Buzz Lightyear to the Rescue! (Europe)"}, - ["982AD2E1E44C6662C88A77367BC5DF91C51531BF"] = {["moduleName"] = "games.ts2", ["friendlyName"] = "Toy Story 2 - Buzz Lightyear to the Rescue! (USA)"}, - ["EAE83C07E2E777D8E71A5BE6120AED03D7E67782"] = {["moduleName"] = "games.ts2", ["friendlyName"] = "Toy Story 2 - Captain Buzz Lightyear auf Rettungsmission! (Germany) (Rev A)"}, - ["F8FBB100227015BE8629243F53D70F29A2A14315"] = {["moduleName"] = "games.ts2", ["friendlyName"] = "Toy Story 2 - Captain Buzz Lightyear auf Rettungsmission! (Germany)"}, + ["A9F97E22391313095D2C2FBAF81FB33BFA2BA7C6"] = {moduleName="games.ts2", friendlyName="Toy Story 2 - Buzz l'Eclair a la Rescousse! (France)"}, + ["92015E5254CBBAD1BC668ECB13A4B568E5F55052"] = {moduleName="games.ts2", friendlyName="Toy Story 2 - Buzz Lightyear to the Rescue! (Europe)"}, + ["982AD2E1E44C6662C88A77367BC5DF91C51531BF"] = {moduleName="games.ts2", friendlyName="Toy Story 2 - Buzz Lightyear to the Rescue! (USA)"}, + ["EAE83C07E2E777D8E71A5BE6120AED03D7E67782"] = {moduleName="games.ts2", friendlyName="Toy Story 2 - Captain Buzz Lightyear auf Rettungsmission! (Germany) (Rev A)"}, + ["F8FBB100227015BE8629243F53D70F29A2A14315"] = {moduleName="games.ts2", friendlyName="Toy Story 2 - Captain Buzz Lightyear auf Rettungsmission! (Germany)"}, + + -- Ty the Tasmanian Tiger 2: Bush Rescue(GBA) + ["84267CE3D86100688048A8D4F166FA1B2D50E6D5"] = {moduleName="games.GBA_Ty2", friendlyName="Ty the Tasmanian Tiger 2 - Bush Rescue (USA,Europe) (En,Fr,De)"}, + + -- Tyrants - Fight Through Time (Mega Lo Mania) + ["F8FBB100227015BE8629243F53D70F29A2A14315"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time"}, + ["B090D74241CD56820B568C319799412B"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time (U) [!]"}, + ["1F7DD4DCB076E7AF7E43F01795504C4A"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time (U) [!]"}, -- Bad dump? + ["8EBE079DB90BEC1AE3E5CBBBDDF0EC4F3164B191"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time (U) [!]"}, -- Bad dump? + ["692F7BF5446415B1B64AAA32E4F652E6"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time (U) [b1]"}, + ["C98AD9D36B1A43B7C6E687C197487C05"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time (U) [b2]"}, + ["11AA8E16CB988BFE63A18E81976DDD3E"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time (U) [b3]"}, + ["2E132458425BB780A3563611811E33E4"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time (U) [f1]"}, + ["080686B870B124F89E47AC9C83A94A73"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time (U) [hI+1C]"}, + ["21901EE9D49825953454DF458230D673"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time (U) [hI+2C]"}, + ["A5D23A84E3320CB5A0DDA78B1A435083"] = {moduleName="games.tftt", friendlyName="Tyrants - Fight Through Time (U) [hI]"}, + ["E622BC3C4A61AACC2EFC1FE4C580987F"] = {moduleName="games.tftt", friendlyName="Mega Lo Mania (E) (REV00) [c][!]"}, + ["B26A3CE67638A9A02E0CFEA97A31A2DE"] = {moduleName="games.tftt", friendlyName="Mega Lo Mania (E) (REV01) [hI+C]"}, + ["EFF87FFE2421EF0F5A5965F3B9D3F573"] = {moduleName="games.tftt", friendlyName="Mega Lo Mania (E) (REV01) [hI]"}, + ["A4561B736011C91E43C18AA8971CDEAD"] = {moduleName="games.tftt", friendlyName="Mega Lo Mania (E) (REV01)"}, + ["6D294B1A2C901AE61774754F6F533A34"] = {moduleName="games.tftt", friendlyName="Mega Lo Mania (J) [!]"}, + ["1FCFC9EE3BFFC25388735782B0CDB829A7E40507"] = {moduleName="games.tftt", friendlyName="Mega Lo Mania (F) [!]"}, - --Ty the Tasmanian Tiger 2: Bush Rescue(GBA) - ["84267CE3D86100688048A8D4F166FA1B2D50E6D5"] = {["moduleName"] = "games.GBA_Ty2", ["friendlyName"] = "Ty the Tasmanian Tiger 2 - Bush Rescue (USA,Europe) (En,Fr,De)"}, - - -- Wonder Boy III - ["E7F86C049E4BD8B26844FF62BD067D57"] = {["moduleName"] = "beta.Wonder Boy III RNG Watch", ["selfContained"] = true, ["friendlyName"] = "Wonder Boy III - The Dragon's Trap (UE)"}, + ["E7F86C049E4BD8B26844FF62BD067D57"] = {moduleName="beta.Wonder Boy III RNG Watch", selfContained=true, friendlyName="Wonder Boy III - The Dragon's Trap (UE)"}, -- Wonder Boy in Monster World (SMS) - ["DA0ACDB1B9E806AA67A0216A675CB02ED24ABF8B"] = {["moduleName"] = "games.wonder_boy_monster_world", ["friendlyName"] = "Wonder Boy in Monster World (E)"}, - ["5837764C172C8C43C8C7B21F2144CF27"] = {["moduleName"] = "games.wonder_boy_monster_world", ["friendlyName"] = "Wonder Boy in Monster World (E)"}, + ["DA0ACDB1B9E806AA67A0216A675CB02ED24ABF8B"] = {moduleName="games.wonder_boy_monster_world", friendlyName="Wonder Boy in Monster World (E)"}, + ["5837764C172C8C43C8C7B21F2144CF27"] = {moduleName="games.wonder_boy_monster_world", friendlyName="Wonder Boy in Monster World (E)"}, }; local romName = gameinfo.getromname(); diff --git a/Watch/Tyrants - Fight Through Time (U) [!].wch b/Watch/Tyrants - Fight Through Time (U) [!].wch index e19cc72d..c94a3750 100644 --- a/Watch/Tyrants - Fight Through Time (U) [!].wch +++ b/Watch/Tyrants - Fight Through Time (U) [!].wch @@ -1,26 +1,23 @@ SystemID GEN -156A w u 1 68K RAM Help Enabled -156E w u 1 68K RAM Population Available For Battle -157A w u 1 68K RAM Speech Enabled -157C w u 1 68K RAM SFX Enabled -157E w u 1 68K RAM Music Enabled -1588 w s 1 68K RAM Island Index -2300 w u 1 68K RAM Cursor Color -A754 b h 1 68K RAM Alliance -A760 b b 1 68K RAM Opponents -B364 w u 1 68K RAM Character? -B394 w u 1 68K RAM Counter Held Duration -B396 b u 1 68K RAM Counter Speed 1 -B397 b u 1 68K RAM Counter Speed 2 -B410 w u 1 68K RAM Cursor X Position -B412 w u 1 68K RAM Cursor Y Position -B50E w h 1 68K RAM RNG? -B5B4 w h 1 68K RAM Selected Sector Pointer -B5BC w u 1 68K RAM Paused -B5C0 w u 1 68K RAM Game Speed -B602 w u 1 68K RAM Men allocated to Battle -D144 w h 1 68K RAM Research -D14E w h 1 68K RAM Research -E26C w h 1 68K RAM Research -E276 w h 1 68K RAM Research +00156A w u 1 68K RAM Help Enabled +00156E w u 1 68K RAM Population Available For Battle +00157A w u 1 68K RAM Speech Enabled +00157C w u 1 68K RAM SFX Enabled +00157E w u 1 68K RAM Music Enabled +001588 w s 1 68K RAM Island Index +001590 w s 1 68K RAM Epoch Index +002300 w u 1 68K RAM Cursor Color +00A754 b h 1 68K RAM Alliance +00A760 b b 1 68K RAM Opponents +00B364 w u 1 68K RAM Character +00B394 w u 1 68K RAM Counter Held Duration +00B396 b u 1 68K RAM Counter Speed 1 +00B397 b u 1 68K RAM Counter Speed 2 +00B410 w u 1 68K RAM Cursor X Position +00B412 w u 1 68K RAM Cursor Y Position +00B50E w h 1 68K RAM RNG +00B5B4 w h 1 68K RAM Selected Sector Pointer +00B5BC w u 1 68K RAM Paused +00B5C0 w u 1 68K RAM Game Speed +00B602 w u 1 68K RAM Men allocated to Battle diff --git a/Beta/TFTT Log.lua b/games/tftt.lua similarity index 64% rename from Beta/TFTT Log.lua rename to games/tftt.lua index 63584542..31e0263f 100644 --- a/Beta/TFTT Log.lua +++ b/games/tftt.lua @@ -1,29 +1,88 @@ -local function toHexString(value, desiredLength, prefix) - value = string.format("%X", value or 0); - prefix = prefix or "0x"; - desiredLength = desiredLength or string.len(value); - while string.len(value) < desiredLength do - value = "0"..value; - end - return prefix..value; -end - ---[[ rPrint(struct, [limit], [indent]) Recursively print arbitrary data. -Set limit (default 100) to stanch infinite loops. -Indents tables as [KEY] VALUE, nested tables as [KEY] [KEY]...[KEY] VALUE -Set indent ("") to prefix each line: Mytable [KEY] [KEY]...[KEY] VALUE ---]] -local function rPrint(s, l, i) -- recursive Print (structure, limit, indent) - l = (l) or 100; i = i or ""; -- default item limit, indent string - if (l < 1) then print "ERROR: Item limit reached."; return l - 1; end - local ts = type(s); - if (ts ~= "table") then print (i, ts, s); return l - 1; end - print (i, ts); -- print "table" - for k, v in pairs(s) do -- print "[KEY] VALUE" - l = rPrint(v, l, i.."\t["..tostring(k).."]"); - if (l < 0) then break; end - end - return l; +if type(ScriptHawk) ~= "table" then + print("This script is not designed to run by itself"); + print("Please run ScriptHawk.lua from the parent directory instead"); + print("Thanks for using ScriptHawk :)"); + return; +end + +local Game = { + Memory = { + island = 0x1588, -- s16_be + epoch = 0x1590, -- s16_be + password_cursor_index = 0x1574, + password_string = 0xABD8, + character = 0xB364, + cursorX = 0xB410, + cursorY = 0xB412, + ticker_held = 0xB394, + ticker_speed = 0xB396, + tick_timer = 0xA730, + RNG = 0xB50E, + selectedSectorPointer = 0xB5B4, + suspended_men = { + scarlet = 0xB604, -- u16_be, it appears to be divided by 10 until it crosses over 0x8000 + caesar = 0xB606, -- u16_be, it appears to be divided by 10 until it crosses over 0x8000 + oberon = 0xB608, -- u16_be, it appears to be divided by 10 until it crosses over 0x8000 + madcap = 0xB60A, -- u16_be, it appears to be divided by 10 until it crosses over 0x8000 + }, + }, + maps = { + "1-1 Aloha", + "1-2 Bazooka", + "1-3 Cilla", + "2-1 Dracula", + "2-2 Etcetra", + "2-3 Formica", + "3-1 Gazza", + "3-2 Hernia", + "3-3 Ibiza", + "4-1 Junta", + "4-2 Karma", + "4-3 Lada", + "5-1 Mascara", + "5-2 Nausea", + "5-3 Ocarina", + "6-1 Pyjama", + "6-2 Quota", + "6-3 Rumbaba", + "7-1 Sinatra", + "7-2 Tapioca", + "7-3 Utopia", + "8-1 Vespa", + "8-2 Wonka", + "8-3 Xtra", + "9-1 Yoga", + "9-2 Zappa", + "9-3 Ohm", + "10-1 Megalomania", + }, +}; + +function Game.detectVersion(romName, romHash) + ScriptHawk.dpad.joypad.enabled = false; + ScriptHawk.dpad.key.enabled = false; + return true; +end + +function Game.setMap(value) + mainmemory.write_s16_be(Game.Memory.island, value - 1); + mainmemory.write_s16_be(Game.Memory.epoch, math.floor((value - 1) / 3)); +end + +function Game.getXPosition() + return mainmemory.read_u16_be(Game.Memory.cursorX); +end + +function Game.getYPosition() + return mainmemory.read_u16_be(Game.Memory.cursorY); +end + +function Game.setXPosition(value) + mainmemory.write_u16_be(Game.Memory.cursorX, value); +end + +function Game.setYPosition(value) + mainmemory.write_u16_be(Game.Memory.cursorY, value); end local displayModes = { @@ -45,14 +104,10 @@ local function toggleDisplayEmptySectors() displayEmptySectors = not displayEmptySectors; end -local selectedSectorPointer = 0xB5B4; local sectorBase = 0xB6C4; local sectorSize = 0x44A; local numSectors = 16; -local cursorX = 0xB410; -local cursorY = 0xB412; - local cursorColors = { -- Pattern repeats % 4 [0] = 0xFF66AAEE, -- Blue [1] = 0xFFEE0000, -- Red @@ -213,7 +268,7 @@ local sectorData = { owner = 0x3FE, -- u16_be population = 0x406, -- u16_be epoch = 0x418, -- u16_be - status = 0x448, -- u16_be (0x0000 unusable, 0x8000 normal, 0x4000 nuked) + status = 0x448, -- u16_be (0x0000 unusable, 0x8000 normal, 0x9000 2001AD?, 0xB000 shut down, 0x4000 nuked) }; local OSDPosition = {2, 2}; @@ -258,6 +313,25 @@ local function getArmyData(sector, army, total) end end +function clearArmyData(sector, army, total) + totalValue = mainmemory.read_u16_be(sector + total); + if totalValue > 0 then + army = sector + army; + mainmemory.write_u8(army + sectorData.army.rocks, 0); + mainmemory.write_u8(army + sectorData.army.catapaults, 0); + mainmemory.write_u8(army + sectorData.army.pikes, 0); + mainmemory.write_u8(army + sectorData.army.longbows, 0); + mainmemory.write_u8(army + sectorData.army.giant_catapaults, 0); + mainmemory.write_u8(army + sectorData.army.cannons, 0); + -- TODO + mainmemory.write_u8(army + sectorData.army.planes, 0); + mainmemory.write_u8(army + sectorData.army.jets, 0); + mainmemory.write_u8(army + sectorData.army.UFOs, 0); + mainmemory.write_u8(army + sectorData.army.unarmed, 0); + mainmemory.write_u16_be(sector + total, 0); + end +end + local function getTickerData(ticker) return { pop = mainmemory.read_u16_be(ticker + sectorData.ticker.pop), @@ -338,12 +412,17 @@ local function getElementData(sector, indexOffset) return elementData; end +function isUsable(sector) + local status = mainmemory.read_u16_be(sector + sectorData.status); + return status == 0x8000 or status == 0x9000 or status == 0xB000; +end + local function getSectorData(sector) local data = {}; data.status = mainmemory.read_u16_be(sector + sectorData.status); - if data.status ~= 0x8000 then -- Speedup: Don't get data for unusable or nuked sectors + if not displayEmptySectors and not isUsable(sector) then -- Speedup: Don't get data for unusable or nuked sectors return data; end @@ -402,7 +481,7 @@ local function getSectorData(sector) return data; end -local function printSectorData(sector) +function printSectorData(sector) rPrint(getSectorData(sector), 10000); end @@ -415,25 +494,11 @@ local function getArmyString(data) return armyString; end -local CPressed = false; -local VPressed = false; -local function draw_OSD() - local row = 0; +ScriptHawk.bindKeyRealtime("C", toggleDisplayMode, true); +ScriptHawk.bindKeyRealtime("V", toggleDisplayEmptySectors, true); - local input_table = input.get(); - if input_table["C"] and not CPressed then - CPressed = true; - toggleDisplayMode(); - elseif not input_table["C"] then - CPressed = false; - end - - if input_table["V"] and not VPressed then - VPressed = true; - toggleDisplayEmptySectors(); - elseif not input_table["V"] then - VPressed = false; - end +function Game.drawUI() + local row = 0; if displayModes[currentDisplayMode] == "Off" then return; @@ -445,7 +510,7 @@ local function draw_OSD() for i = numSectors, 1, -1 do local sector = sectorBase + (i - 1) * sectorSize; local data = getSectorData(sector); - if data.status == 0x8000 then + if isUsable(sector) then if displayEmptySectors or data.owner < 4 then gui.text(OSDPosition[1], OSDPosition[2] + row * OSDRowHeight, toHexString(sector), characterColors[data.owner], "bottomright"); local rowString = ""; @@ -456,7 +521,7 @@ local function draw_OSD() rowString = rowString..getResearchString(data).." "; rowString = rowString..data.tower_health.."/"..data.max_tower_health.."HP "; --rowString = rowString.."owner: "..data.owner.." "; - --rowString = rowString.."status: "..toHexString(data.status, 4, "").." "; + rowString = rowString.."status: "..toHexString(data.status, 4, "").." "; rowString = rowString..epochs[data.epoch].." "; end @@ -485,7 +550,7 @@ function dump() for i = 1, numSectors do local sector = sectorBase + (i - 1) * sectorSize; local data = getSectorData(sector); - if data.status == 0x8000 then + if isUsable(sector) then local rowString = toHexString(sector).." "; rowString = rowString..(i - 1).." "; @@ -499,29 +564,130 @@ function dump() end end -function buildAll() - local character = mainmemory.read_u16_be(0xB364); +function Game.buildAll() + local you = mainmemory.read_u16_be(Game.Memory.character); for i = 1, numSectors do local sector = sectorBase + (i - 1) * sectorSize; - local data = getSectorData(sector); - if data.owner == 4 then - mainmemory.write_u16_be(sector + sectorData.owner, character); + local owner = mainmemory.read_u16_be(sector + sectorData.owner); + if owner == 4 then + mainmemory.write_u16_be(sector + sectorData.owner, you); end end end ---[[ -function infiniteMen() - local character = mainmemory.read_u16_be(0xB364); +function Game.applyInfinites() + local you = mainmemory.read_u16_be(Game.Memory.character); for i = 1, numSectors do local sector = sectorBase + (i - 1) * sectorSize; - local data = getSectorData(sector); - if data.owner == character then + local owner = mainmemory.read_u16_be(sector + sectorData.owner); + if owner == you then mainmemory.write_u16_be(sector + sectorData.population, 419); end end end -event.onframestart(infiniteMen); ---]] -event.onframestart(draw_OSD); \ No newline at end of file +function Game.setPassword(password) + writeNullTerminatedString(Game.Memory.password_string, password); + mainmemory.write_u16_be(Game.Memory.password_cursor_index, 0x0B); +end + +function Game.getTickerSpeed() + if mainmemory.readbyte(Game.Memory.ticker_speed) == 0x01 then + if mainmemory.readbyte(Game.Memory.ticker_speed + 1) == 0x01 then + return 2; + end + return 1; + end + return 0; +end + +function Game.getTickerHeld() + return mainmemory.read_u16_be(Game.Memory.ticker_held); +end + +function Game.getRNG() + return toHexString(mainmemory.read_u16_be(Game.Memory.RNG), 4, ""); +end + +function Game.getTickTimer() + return mainmemory.read_u16_be(Game.Memory.tick_timer); +end + +function readSuspendedMen(address) + local value = mainmemory.read_u16_be(address); + if value < 0x8000 then + return math.floor(value / 10); + end + return value; +end + +function Game.getSuspendedMen() + local scarlet = readSuspendedMen(Game.Memory.suspended_men.scarlet); + local caesar = readSuspendedMen(Game.Memory.suspended_men.caesar); + local oberon = readSuspendedMen(Game.Memory.suspended_men.oberon); + local madcap = readSuspendedMen(Game.Memory.suspended_men.madcap); + return scarlet..","..caesar..","..oberon..","..madcap; +end + +function Game.eachFrame() + if forms.ischecked(ScriptHawk.UI.form_controls["mouse_control"]) then + -- Make game cursor follow real cursor + local mousePos = input.getmouse(); + if mousePos.X >= 0 and mousePos.X <= client.bufferwidth() and mousePos.Y >= 0 and mousePos.Y <= client.bufferheight() then + Game.setXPosition(mousePos.X * 2); + Game.setYPosition((mousePos.Y * 2) - 40); -- Minus 40 pixels to compensate for Overscan + + if mousePos.Left then + joypad.set({["B"] = true}, 1); + end + if mousePos.Right then + joypad.set({["C"] = true}, 1); + end + end + end + + if forms.ischecked(ScriptHawk.UI.form_controls["sandbox_mode"]) then + local you = mainmemory.read_u16_be(Game.Memory.character); + for i = numSectors, 1, -1 do + local sector = sectorBase + (i - 1) * sectorSize; + if isUsable(sector) then + local owner = mainmemory.read_u16_be(sector + sectorData.owner); + if owner ~= you then + mainmemory.write_u16_be(sector + sectorData.population, 0); + end + if you ~= 0 then + clearArmyData(sector, sectorData.army_bases.scarlet, sectorData.army_totals.scarlet); + end + if you ~= 1 then + clearArmyData(sector, sectorData.army_bases.caesar, sectorData.army_totals.caesar); + end + if you ~= 2 then + clearArmyData(sector, sectorData.army_bases.oberon, sectorData.army_totals.oberon); + end + if you ~= 3 then + clearArmyData(sector, sectorData.army_bases.madcap, sectorData.army_totals.madcap); + end + end + end + end +end + +function Game.initUI() + ScriptHawk.UI.form_controls["build_all"] = forms.button(ScriptHawk.UI.options_form, "Build All", Game.buildAll, ScriptHawk.UI.col(10), ScriptHawk.UI.row(4), ScriptHawk.UI.col(4) + 10, ScriptHawk.UI.button_height); + ScriptHawk.UI.form_controls["mouse_control"] = forms.checkbox(ScriptHawk.UI.options_form, "Mouse Control", ScriptHawk.UI.col(0) + ScriptHawk.UI.dropdown_offset, ScriptHawk.UI.row(6) + ScriptHawk.UI.dropdown_offset); + ScriptHawk.UI.form_controls["sandbox_mode"] = forms.checkbox(ScriptHawk.UI.options_form, "Sandbox Mode", ScriptHawk.UI.col(0) + ScriptHawk.UI.dropdown_offset, ScriptHawk.UI.row(7) + ScriptHawk.UI.dropdown_offset); +end + +Game.OSD = { + {"X", Game.getXPosition}, + {"Y", Game.getYPosition}, + {"dX"}, + {"dY"}, + {"Ticker Speed", Game.getTickerSpeed}, + {"Ticker Held", Game.getTickerHeld}, + {"Tick Timer", Game.getTickTimer}, + {"RNG", Game.getRNG}, + {"Suspended Men", Game.getSuspendedMen}, +}; + +return Game; \ No newline at end of file diff --git a/lib/LibScriptHawk.lua b/lib/LibScriptHawk.lua index 22abf832..d18fca4c 100644 --- a/lib/LibScriptHawk.lua +++ b/lib/LibScriptHawk.lua @@ -92,6 +92,24 @@ function print_deferred() __dprinted = {}; end +--[[ rPrint(struct, [limit], [indent]) Recursively print arbitrary data. +Set limit (default 100) to stanch infinite loops. +Indents tables as [KEY] VALUE, nested tables as [KEY] [KEY]...[KEY] VALUE +Set indent ("") to prefix each line: Mytable [KEY] [KEY]...[KEY] VALUE +--]] +function rPrint(s, l, i) -- recursive Print (structure, limit, indent) + l = (l) or 100; i = i or ""; -- default item limit, indent string + if (l < 1) then print "ERROR: Item limit reached."; return l - 1; end + local ts = type(s); + if (ts ~= "table") then print (i, ts, s); return l - 1; end + print (i, ts); -- print "table" + for k, v in pairs(s) do -- print "[KEY] VALUE" + l = rPrint(v, l, i.."\t["..tostring(k).."]"); + if (l < 0) then break; end + end + return l; +end + if emu.getsystemid() == "N64" then RDRAMBase = 0x80000000; RDRAMSize = 0x800000; -- Halved with no expansion pak, can be read from 0x80000318