Advertisement
Jimmie1717

BizHawk: Jet Force Genocide Script

Jun 17th, 2016
513
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 17.39 KB | None | 0 0
  1. -- Jet Force Genocide Script
  2. -- This script will only work for the English and Japanese Versions.
  3.  
  4. -- What is Jet Force Genocide? -------------------------------------------------------------
  5. -- This is a hack that reverses how Tribals work. When a Tribal is 'saved' it is counted as
  6. -- 'killed' and vice versa. This means that in order to be able to beat the game the player
  7. -- must go through the game and kill all the Tribals instead of saving them. Reversing how
  8. -- they work is necessary to make the game beatable. This is because as far as the game is
  9. -- concerned all the Tribals must be saved to do so.
  10.  
  11. -- Emulator: -------------------------------------------------------------------------------
  12. -- Use BizHawk 1.11.6 (or higher)
  13. -- After loading the ROM use N64 -> Plugins
  14. -- For Global Plugin Settings use:
  15. --      Core Type:              DynaRec
  16. --      Rsp Plugin:             Hle
  17. --      Active Video Plugin:    Jabo 1.6.1
  18. --      Video Resolution:       640x480 (text display is setup for this resolution)
  19. -- It seems if the core type is set to interperter (pure or not) the Lurg Fight can crash the game.
  20. -- Jabo Video plugin is the best as it shows the manual targetting reticles while the others don't.
  21. -- However there are a few errors with it on the Japanese Version.
  22. -- The Lurg Boss Fight and Chasm Night Vision Sections are covered by a black screen.
  23. -- This prevents you from being able to see. So I disabled them.
  24. -- These errors don't seem to happen on the English version but I still disabled to make sure it works.
  25.  
  26. -- How to use this:
  27. -- On pastebin.com click the download button on the upper right side of the code frame to download this file as a .lua file.
  28. -- In BizHawk open the Lua Console. (Tools -> Lua Console)
  29. -- In Lua Console open the .lua file. (Script -> Open Script -> <browse to file>)
  30.  
  31. -- NOTES: ----------------------------------------------------------------------------------
  32. -- I added an check for invalid tribal counts.
  33. -- A message will pop up in the bottle left of the BizHawk window if it happens.
  34. -- If this happens the saved and killed counts will reset to 0.
  35. -- This could cause an issue with remaining tribals though if it happens in the middle of a region.
  36. -- If it happens at the very beggining of the region it should be fine.
  37. -- This error shouldn't happen anymore, but I put this in just in case.
  38.  
  39. -- I also added a Tribal Count Display (above the weapon hud).
  40. -- The format for it is as follows: <saved> <killed> <remaining> <total kill count>
  41. -- This will make it easy to tell if the counts are off some how.
  42. -- The display is setup for 480p.
  43.  
  44. -- Levitation is enabled since as a tribal you can't use the Jet Pack.
  45. -- However it is still based on Jet Fuel. You need to have Jet Fuel to be able to levitate.
  46. -- It works the exact same (for the most part). C-Up to accelerate upwards. C-Down to Hover.
  47. --      There are 2 displays. A generic one and one that looks like the digital version from in game.
  48. --      The digital one requires a specific font to work. To use it you will need "Quartz MS" Font.
  49. --      You can download Quartz MS here: https://www.dropbox.com/s/u2np0mk6xmp67u7/QuartzMS.TTF?dl=0
  50. --      On line 59 of this file there is a variable called "font", set this to true if you have Quarts MS Installed.
  51. --      Otherwise leave it false for the generic display.
  52.  
  53. -- You should be a tribal when playing as Juno or Vela.
  54. -- Sometimes this isn't applied but that't not really an issue.
  55. -- For the Mizar's Palace Race you have to be a Drone so it is disabled there.
  56.  
  57. console.clear()
  58.  
  59. local font                  = false
  60.  
  61. -- Game Hash
  62. versions                    = {
  63.     ["493CED9008DBE932D6E91179B68E8630CF23A023"]    = "E",  -- English
  64.     ["15099233760B36E7AFAD7DA36B9464DA1512C4B1"]    = "J"   -- Japanese
  65. }
  66.  
  67. -- Version Detection
  68. local v                 = versions[gameinfo.getromhash()]
  69. if (v == "E") then
  70.     gui.addmessage("Version: Jet Force Gemini (U)")
  71. elseif (v == "J") then
  72.     gui.addmessage("Version: Star Twins (J)")
  73. else
  74.     gui.addmessage("Version: Unknown")
  75.     v = nil
  76. end
  77.  
  78. local addrs                 = {
  79.     ["E"]                   = {
  80.         sceneLast           = 0x0A323C,
  81.         sceneSetter         = 0x0A3250,
  82.         entranceSetter      = 0x0A3258,
  83.         loadFlag            = 0x0A3294,
  84.         tribal              = {
  85.             saved           = 0x1E6014,
  86.             killed          = 0x1E6015,
  87.             remaining       = 0x1E6016
  88.         },
  89.         region              = 0x0A3269,
  90.         continues           = 0x0A3280,
  91.         character           = 0x1E6010,
  92.         model               = {
  93.             vela            = 0x1E6170,
  94.             juno            = 0x1E61E6
  95.         },
  96.         pointers            = {
  97.             vela            = 0x1D6BAC,
  98.             juno            = 0x1D6BB4,
  99.         },
  100.         rainbow_blood       = 0x0A5080,
  101.         paused              = 0x0A06A4,
  102.         night_vision        = 0x0A6D03,
  103.         lurg_vision         = 0x0A333B
  104.     },
  105.     ["J"]                   = {
  106.         sceneLast           = 0x0A30FC,
  107.         sceneSetter         = 0x0A3110,
  108.         entranceSetter      = 0x0A3118,
  109.         loadFlag            = 0x0A3154,
  110.         tribal              = {
  111.             saved           = 0x1E3584,
  112.             killed          = 0x1E3585,
  113.             remaining       = 0x1E3586
  114.         },
  115.         region              = 0x0A3129,
  116.         continues           = 0x0A3140,
  117.         character           = 0x1E3580,
  118.         model               = {
  119.             vela            = 0x1E36E0,
  120.             juno            = 0x1E3756
  121.         },
  122.         pointers            = {
  123.             vela            = 0x1D40FC,
  124.             juno            = 0x1D4104,
  125.         },
  126.         rainbow_blood       = 0x0A4F90,
  127.         paused              = 0x0A0564,
  128.         night_vision        = 0x0A6C13,
  129.         lurg_vision         = 0x0A31FF
  130.     },
  131.     velocity                = {
  132.         vela                = 0x0190,
  133.         juno                = 0x0170
  134.     },
  135.     jet_fuel                = {
  136.         vela                = 0x07B4,
  137.         juno                = 0x0794
  138.     },
  139.     state                   = {
  140.         vela                = 0x075A,
  141.         juno                = 0x073A
  142.     }
  143. }
  144.  
  145. local playerVelocity        = nil
  146. local playerFuel            = nil
  147. local playerState           = nil
  148.  
  149. local timer                 = 0
  150. local jetFuel               = 0
  151. local jetFuelSwitch         = false
  152.  
  153. local tribals               = {
  154.     saved                   = 0,
  155.     killed                  = 0,
  156.     remaining               = 0,
  157.     killtotal               = 0
  158. }
  159.  
  160. -- Initialize Version Dependant Variables
  161. if (v ~= nil) then
  162.     tribalRemaining         = addrs[v].tribal.remaining
  163.     tribalKilled            = addrs[v].tribal.killed
  164.     tribalSaved             = addrs[v].tribal.saved
  165.     region                  = addrs[v].region
  166.     continues               = addrs[v].continues
  167.     sceneLast               = addrs[v].sceneLast
  168.     sceneSetter             = addrs[v].sceneSetter
  169.     entranceSetter          = addrs[v].entranceSetter
  170.     loadFlag                = addrs[v].loadFlag
  171.     rainbowBlood            = addrs[v].rainbow_blood
  172.     paused                  = addrs[v].paused
  173.     nightVision             = addrs[v].night_vision
  174.     lurgVision              = addrs[v].lurg_vision
  175. end
  176.  
  177. -- Encapsulate memory.read/write into functions.
  178. function getByte(address)
  179.     if (address ~= nil) then
  180.         return memory.readbyte(address)
  181.     else
  182.         print("getByte(address): address (a nil value)")
  183.     end
  184. end
  185.  
  186. function getWord(address)
  187.     if (address ~= nil) then
  188.         return memory.read_u16_be(address)
  189.     else
  190.         print("getWord(address): address (a nil value)")
  191.     end
  192. end
  193.  
  194. function getDWord(address)
  195.     if (address ~= nil) then
  196.         return memory.read_u32_be(address)
  197.     else
  198.         print("getDWord(address): address (a nil value)")
  199.     end
  200. end
  201.  
  202. function setByte(address, value)
  203.     if (address ~= nil and value ~= nil) then
  204.         memory.writebyte(address, value)
  205.     elseif (address == nil) then
  206.         print("setByte(address, value): address (a nil value)")
  207.     elseif (value == nil) then
  208.         print("setByte(address, value): value (a nil value)")
  209.     end
  210. end
  211.  
  212. function setWord(address, value)
  213.     if (address ~= nil and value ~= nil) then
  214.         memory.write_u16_be(address, value)
  215.     elseif (address == nil) then
  216.         print("setWord(address, value): address (a nil value)")
  217.     elseif (value == nil) then
  218.         print("setWord(address, value): value (a nil value)")
  219.     end
  220. end
  221.  
  222. function setDWord(address, value)
  223.     if (address ~= nil and value ~= nil) then
  224.         memory.write_u32_be(address, value)
  225.     elseif (address == nil) then
  226.         print("setDWord(address, value): address (a nil value)")
  227.     elseif (value == nil) then
  228.         print("setDWord(address, value): value (a nil value)")
  229.     end
  230. end
  231.  
  232. -- This function handles setting up the player actor related data that moves around dynamically in memory.
  233. function setupTribal()
  234.  
  235.     playerVelocity          = nil
  236.     playerFuel              = nil
  237.     playerState             = nil
  238.  
  239.     local character         = getByte(addrs[v].character)
  240.     local model
  241.  
  242.     -- Check the character and set model to Tribal
  243.     if (character == 0x00 or character == 0x04) then
  244.         model               = getWord(addrs[v].model.vela) % 0x10
  245.         model               = getWord(addrs[v].model.vela) - model
  246.         setWord(addrs[v].model.vela, model + 0x02)
  247.     elseif (character == 0x01 or character == 0x05) then
  248.         model               = getWord(addrs[v].model.juno) % 0x10
  249.         model               = getWord(addrs[v].model.juno) - model
  250.         setWord(addrs[v].model.juno, model + 0x02)
  251.     end
  252.    
  253.     -- Give the scene time to load
  254.     for i = 0, 240, 1 do    -- 240 frames / 4 seconds.
  255.         textDisplay()
  256.         updateTribals()
  257.         storeTribals()
  258.         fixVision()
  259.         emu.frameadvance()
  260.     end
  261.    
  262.     -- Check the character and set addresses.
  263.     if ((character == 0x00 or character == 0x04) and getDWord(addrs[v].pointers.vela) ~= 0x00000000) then
  264.         playerVelocity      = getDWord(addrs[v].pointers.vela) - 0x80000000 + addrs.velocity.vela
  265.         playerState         = getDWord(addrs[v].pointers.vela) - 0x80000000 + addrs.state.vela
  266.         if (character == 0x04) then
  267.             playerFuel          = getDWord(addrs[v].pointers.vela) - 0x80000000 + addrs.jet_fuel.vela
  268.         end
  269.     elseif ((character == 0x01 or character == 0x05) and getDWord(addrs[v].pointers.juno) ~= 0x00000000) then
  270.         playerVelocity      = getDWord(addrs[v].pointers.juno) - 0x80000000 + addrs.velocity.juno
  271.         playerState         = getDWord(addrs[v].pointers.juno) - 0x80000000 + addrs.state.juno
  272.         if (character == 0x05) then
  273.             playerFuel          = getDWord(addrs[v].pointers.juno) - 0x80000000 + addrs.jet_fuel.juno
  274.         end
  275.     end
  276.  
  277. end
  278.  
  279. -- Jet Pack with C-Up/C-Down like normal.
  280. function levitate(i)
  281.  
  282.     if (playerVelocity ~= nil and playerFuel ~= nil and playerState ~= nil) then
  283.    
  284.         local fuel  = getWord(playerFuel)
  285.        
  286.         if (fuel > 0x0000 and fuel < 0x0E11 and getByte(playerState) ~= 0x01) then
  287.            
  288.             jetFuelSwitch   = true
  289.            
  290.             if (i == true) then
  291.                 setDWord(playerVelocity, 0x40A00000)        -- 5.0
  292.                 if (fuel - 0x0002 == 0xFFFF) then
  293.                     setWord(playerFuel, 0x0000)
  294.                 else
  295.                     setWord(playerFuel, fuel - 0x0002)
  296.                 end
  297.             elseif (i == false) then
  298.                 setDWord(playerVelocity, 0x3FACCCCC)        -- 1.25
  299.                 setWord(playerFuel, fuel - 0x0001)
  300.             end
  301.            
  302.         end
  303.  
  304.     end
  305.  
  306. end
  307.  
  308. -- This function handles updating the tribal counts.
  309. function updateTribals()
  310.  
  311.     -- Store current counts to check against last frame's counts.
  312.     local saved                 = getByte(tribalSaved)
  313.     local killed                = getByte(tribalKilled)
  314.     local remaining             = getByte(tribalRemaining)
  315.    
  316.     local savedDiff             = 0
  317.     local killedDiff            = 0
  318.  
  319.     -- Check if the Remaining Tribals has gone down.
  320.     if (remaining < tribals.remaining) then
  321.        
  322.         -- Killed Difference
  323.         if (killed > tribals.killed) then
  324.             killedDiff          = killed - tribals.killed
  325.         elseif (killed < tribals.killed) then
  326.             -- If the count has decreased then the player entered a new region.
  327.             tribals.killed      = 0
  328.         end
  329.        
  330.         -- Saved Difference
  331.         if (saved > tribals.saved) then
  332.             savedDiff           = saved - tribals.saved
  333.         elseif (saved < tribals.saved) then
  334.             -- If the count has decreased then the player entered a new region.
  335.             tribals.saved       = 0
  336.         end
  337.        
  338.         -- Apply Differences to opposite count.
  339.         tribals.saved       = tribals.saved + killedDiff
  340.         tribals.killed      = tribals.killed + savedDiff
  341.        
  342.         -- Update Kill Total
  343.         tribals.killtotal   = tribals.killtotal + killedDiff
  344.        
  345.         -- Validate Tribal counts. (16 is highest)
  346.         if (tribals.saved > 16 or tribals.killed > 16) then
  347.             gui.addmessage("Invalid Tribal Counts")
  348.             gui.addmessage("Reseting Counts...")
  349.             setByte(tribalSaved, 0)
  350.             setByte(tribalKilled, 0)
  351.             setByte(tribalRemaining, tribals.remaining)
  352.         else
  353.             setByte(tribalSaved, tribals.saved)
  354.             setByte(tribalKilled, tribals.killed)
  355.         end
  356.        
  357.     end
  358.  
  359. end
  360.  
  361. -- Store the tribal counts.
  362. function storeTribals()
  363.  
  364.     tribals.saved           = getByte(tribalSaved)
  365.     tribals.killed          = getByte(tribalKilled)
  366.     tribals.remaining       = getByte(tribalRemaining)
  367.    
  368. end
  369.  
  370. function jetFuelDisplayTimer()
  371.  
  372.     local fuel  = getWord(playerFuel)
  373.    
  374.     if (fuel ~= jetFuel) then
  375.         jetFuelSwitch   = true
  376.     elseif (fuel == 0x0000) then
  377.         jetFuelSwitch   = false
  378.     end
  379.    
  380.     if (jetFuelSwitch == true and timer < 455) then
  381.         timer           = timer + 2
  382.     elseif(jetFuelSwitch == false and timer > 0) then
  383.         timer           = timer - 1
  384.     end
  385.    
  386.     if (timer >= 455) then
  387.         jetFuelSwitch   = false
  388.     end
  389.    
  390.     jetFuel = fuel
  391.  
  392. end
  393.  
  394. function textDisplay()
  395.  
  396.     local x     = 45
  397.     local y     = 13
  398.     local t     = 0
  399.    
  400.     if (timer < 0xFF) then
  401.         t       = timer * 0x01000000
  402.     else
  403.         t       = 0xFF000000
  404.     end
  405.  
  406.     -- Tribal Counts
  407.     if (getByte(loadFlag) == 0x00 and getByte(region) ~= 0x00 and getByte(paused) == 0x00) then
  408.         if (getWord(sceneLast) ~= 0x0000 and
  409.             getWord(sceneLast) ~= 0x0001 and
  410.             getWord(sceneLast) ~= 0x007F and
  411.             getWord(sceneLast) ~= 0x015C and
  412.             getWord(sceneLast) ~= 0x015D and
  413.             getWord(sceneLast) ~= 0x017D and
  414.             getWord(sceneLast) ~= 0x017E and
  415.             getWord(sceneLast) ~= 0x017F and
  416.             getWord(sceneLast) ~= 0x0180 and
  417.             getWord(sceneLast) ~= 0x0181) then
  418.             gui.drawBox(x, y, x + 102, y + 15, 0xFF4FB3C9, 0x80267580)
  419.             gui.drawText(x - 2, y - 1, string.format("%02d", tribals.saved), 0x60FFFFFF, "TRANSPARENT", 16)
  420.             gui.drawText(x + 22, y - 1, string.format("%02d", tribals.killed), 0x60FFFFFF, "TRANSPARENT", 16)
  421.             gui.drawText(x + 46, y - 1, string.format("%02d", tribals.remaining), 0x60FFFFFF, "TRANSPARENT", 16)
  422.             gui.drawText(x + 70, y - 1, string.format("%03d", tribals.killtotal), 0x60FFFF00, "TRANSPARENT", 16)
  423.             gui.drawText(x - 2, y - 1, string.format("%2d", tribals.saved), 0xFFFFFFFF, "TRANSPARENT", 16)
  424.             gui.drawText(x + 22, y - 1, string.format("%2d", tribals.killed), 0xFFFFFFFF, "TRANSPARENT", 16)
  425.             gui.drawText(x + 46, y - 1, string.format("%2d", tribals.remaining), 0xFFFFFFFF, "TRANSPARENT", 16)
  426.             gui.drawText(x + 70, y - 1, string.format("%3d", tribals.killtotal), 0xFFFFFF00, "TRANSPARENT", 16)
  427.         end
  428.     end
  429.        
  430.     -- Jet Fuel
  431.     if (getByte(loadFlag) == 0x00 and getByte(paused) == 0x00 and playerFuel ~= nil and getWord(playerFuel) < 0x0E11) then
  432.        
  433.         if (font == false) then
  434.        
  435.             if (timer < 0x80) then
  436.                 gui.drawBox(x + 183, y + 424, x + 407, y + 439, t + 0x4FB3C9, t + 0x267580)
  437.             else
  438.                 gui.drawBox(x + 183, y + 424, x + 407, y + 439, t + 0x4FB3C9, 0x80267580)
  439.             end
  440.             gui.drawText(x + 230, y + 423, string.format("Jet Fuel: %3d", getWord(playerFuel) / 36), t + 0xFFFFFF, "TRANSPARENT", 16)
  441.        
  442.         elseif (font == true) then
  443.        
  444.             -- Main
  445.             if (getWord(playerFuel) / 36 == 100) then
  446.                 gui.drawText(470, 386, string.format("%3d", getWord(playerFuel) / 36), t + 0x00FF00, "Transparent", 47, "Quartz MS")
  447.             elseif (getWord(playerFuel) / 36 >= 10) then
  448.                 gui.drawText(485, 386, string.format("%3d", getWord(playerFuel) / 36), t + 0x00FF00, "Transparent", 47, "Quartz MS")
  449.             else
  450.                 gui.drawText(502, 386, string.format("%3d", getWord(playerFuel) / 36), t + 0x00FF00, "Transparent", 47, "Quartz MS")
  451.             end
  452.            
  453.             -- Background
  454.             if (timer < 0x20) then
  455.                 gui.drawText(470, 386, string.format("%3d", 888), t + 0x00FF00, "Transparent", 47, "Quartz MS")
  456.             else
  457.                 gui.drawText(470, 386, string.format("%3d", 888), 0x2000FF00, "Transparent", 47, "Quartz MS")
  458.             end
  459.            
  460.         end
  461.        
  462.     end
  463.    
  464. end
  465.  
  466. function fixVision()
  467.  
  468.     -- Disable Lurg Black Screen
  469.     if (getByte(lurgVision) == 0x01) then
  470.         setByte(lurgVision, 0x00)
  471.     end
  472.    
  473.     -- 0x0107
  474.  
  475.     -- Disable Night Vision
  476.     if (getByte(nightVision) ~= 0x00) then
  477.         setByte(nightVision, 0x00)
  478.     end
  479.    
  480.     -- By pass the Night Vision Room.
  481.     -- Since it's disabled there's no reason to get it or activate it.
  482.     if (getByte(loadFlag) ~= 0x00 and getWord(sceneSetter) == 0x013D and getWord(entranceSetter) == 0x0001) then
  483.         setWord(sceneSetter, 0x0137)
  484.     elseif (getByte(loadFlag) ~= 0x00 and getWord(sceneSetter) == 0x013C and getWord(entranceSetter) == 0x0000) then
  485.         setWord(sceneSetter, 0x013B)
  486.     end
  487.  
  488. end
  489.  
  490. -- Run this when the script is turned on. UNLESS at the title screen/game select menu.
  491. if (getWord(sceneLast) ~= 0x0000 and
  492.     getWord(sceneLast) ~= 0x0001 and
  493.     getWord(sceneLast) ~= 0x007F and
  494.     getWord(sceneLast) ~= 0x015C and
  495.     getWord(sceneLast) ~= 0x015D and
  496.     getWord(sceneLast) ~= 0x017D and
  497.     getWord(sceneLast) ~= 0x017E and
  498.     getWord(sceneLast) ~= 0x017F and
  499.     getWord(sceneLast) ~= 0x0180 and
  500.     getWord(sceneLast) ~= 0x0181) then
  501.     setupTribal()
  502.     storeTribals()
  503. end
  504.  
  505. while true do
  506.  
  507.     -- If version is not detected the script won't be able to do anything.
  508.     if (v ~= nil) then
  509.    
  510.         -- Button Activators
  511.         if joypad.get(1)['C Up'] then
  512.             levitate(true)
  513.         elseif joypad.get(1)['C Down'] then
  514.             levitate(false)
  515.         end
  516.        
  517.         -- On a load.
  518.         if (getByte(loadFlag) ~= 0x00) then
  519.        
  520.             local i = getWord(sceneSetter)
  521.             -- If the entrance is any of the below this won't run.
  522.             if (i ~= 0x0000 and     -- Game Select
  523.                 i ~= 0x0001 and     -- Game Select
  524.                 i ~= 0x007F and     -- Character Select
  525.                 i ~= 0x015C and     -- Title Screen
  526.                 i ~= 0x015D and     -- Title Screen
  527.                 i ~= 0x017D and     -- Title Screen
  528.                 i ~= 0x017E and     -- Title Screen
  529.                 i ~= 0x017F and     -- Title Screen
  530.                 i ~= 0x0180 and     -- Title Screen
  531.                 i ~= 0x0181 and     -- Title Screen
  532.                 i ~= 0x00FA and     -- Mizar's Palace Race Areas
  533.                 i ~= 0x010C and     -- Mizar's Palace Race Areas
  534.                 i ~= 0x011D and     -- Mizar's Palace Race Areas
  535.                 i ~= 0x0169 and     -- Mizar's Palace Race Areas
  536.                 i ~= 0x016B and     -- Mizar's Palace Race Areas
  537.                 i ~= 0x0197 and     -- Mizar's Palace Race Areas
  538.                 i ~= 0x018E and     -- Mizar's Palace Race Areas
  539.                 i ~= 0x018A) then   -- Mizar's Palace Race Areas
  540.                
  541.                 -- Rainbow Blood
  542.                 setDWord(rainbowBlood, 0x01000000) 
  543.                
  544.                 setupTribal()
  545.                
  546.             end
  547.         end
  548.        
  549.         if (playerFuel ~= nil) then
  550.             jetFuelDisplayTimer()
  551.         end
  552.        
  553.         textDisplay()
  554.         updateTribals()
  555.         storeTribals()
  556.         fixVision()
  557.  
  558.     end
  559.    
  560.     emu.frameadvance()
  561.        
  562. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement