Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Jet Force Genocide Script
- -- This script will only work for the English and Japanese Versions.
- -- What is Jet Force Genocide? -------------------------------------------------------------
- -- This is a hack that reverses how Tribals work. When a Tribal is 'saved' it is counted as
- -- 'killed' and vice versa. This means that in order to be able to beat the game the player
- -- must go through the game and kill all the Tribals instead of saving them. Reversing how
- -- they work is necessary to make the game beatable. This is because as far as the game is
- -- concerned all the Tribals must be saved to do so.
- -- Emulator: -------------------------------------------------------------------------------
- -- Use BizHawk 1.11.6 (or higher)
- -- After loading the ROM use N64 -> Plugins
- -- For Global Plugin Settings use:
- -- Core Type: DynaRec
- -- Rsp Plugin: Hle
- -- Active Video Plugin: Jabo 1.6.1
- -- Video Resolution: 640x480 (text display is setup for this resolution)
- -- It seems if the core type is set to interperter (pure or not) the Lurg Fight can crash the game.
- -- Jabo Video plugin is the best as it shows the manual targetting reticles while the others don't.
- -- However there are a few errors with it on the Japanese Version.
- -- The Lurg Boss Fight and Chasm Night Vision Sections are covered by a black screen.
- -- This prevents you from being able to see. So I disabled them.
- -- These errors don't seem to happen on the English version but I still disabled to make sure it works.
- -- How to use this:
- -- On pastebin.com click the download button on the upper right side of the code frame to download this file as a .lua file.
- -- In BizHawk open the Lua Console. (Tools -> Lua Console)
- -- In Lua Console open the .lua file. (Script -> Open Script -> <browse to file>)
- -- NOTES: ----------------------------------------------------------------------------------
- -- I added an check for invalid tribal counts.
- -- A message will pop up in the bottle left of the BizHawk window if it happens.
- -- If this happens the saved and killed counts will reset to 0.
- -- This could cause an issue with remaining tribals though if it happens in the middle of a region.
- -- If it happens at the very beggining of the region it should be fine.
- -- This error shouldn't happen anymore, but I put this in just in case.
- -- I also added a Tribal Count Display (above the weapon hud).
- -- The format for it is as follows: <saved> <killed> <remaining> <total kill count>
- -- This will make it easy to tell if the counts are off some how.
- -- The display is setup for 480p.
- -- Levitation is enabled since as a tribal you can't use the Jet Pack.
- -- However it is still based on Jet Fuel. You need to have Jet Fuel to be able to levitate.
- -- It works the exact same (for the most part). C-Up to accelerate upwards. C-Down to Hover.
- -- There are 2 displays. A generic one and one that looks like the digital version from in game.
- -- The digital one requires a specific font to work. To use it you will need "Quartz MS" Font.
- -- You can download Quartz MS here: https://www.dropbox.com/s/u2np0mk6xmp67u7/QuartzMS.TTF?dl=0
- -- On line 59 of this file there is a variable called "font", set this to true if you have Quarts MS Installed.
- -- Otherwise leave it false for the generic display.
- -- You should be a tribal when playing as Juno or Vela.
- -- Sometimes this isn't applied but that't not really an issue.
- -- For the Mizar's Palace Race you have to be a Drone so it is disabled there.
- console.clear()
- local font = false
- -- Game Hash
- versions = {
- ["493CED9008DBE932D6E91179B68E8630CF23A023"] = "E", -- English
- ["15099233760B36E7AFAD7DA36B9464DA1512C4B1"] = "J" -- Japanese
- }
- -- Version Detection
- local v = versions[gameinfo.getromhash()]
- if (v == "E") then
- gui.addmessage("Version: Jet Force Gemini (U)")
- elseif (v == "J") then
- gui.addmessage("Version: Star Twins (J)")
- else
- gui.addmessage("Version: Unknown")
- v = nil
- end
- local addrs = {
- ["E"] = {
- sceneLast = 0x0A323C,
- sceneSetter = 0x0A3250,
- entranceSetter = 0x0A3258,
- loadFlag = 0x0A3294,
- tribal = {
- saved = 0x1E6014,
- killed = 0x1E6015,
- remaining = 0x1E6016
- },
- region = 0x0A3269,
- continues = 0x0A3280,
- character = 0x1E6010,
- model = {
- vela = 0x1E6170,
- juno = 0x1E61E6
- },
- pointers = {
- vela = 0x1D6BAC,
- juno = 0x1D6BB4,
- },
- rainbow_blood = 0x0A5080,
- paused = 0x0A06A4,
- night_vision = 0x0A6D03,
- lurg_vision = 0x0A333B
- },
- ["J"] = {
- sceneLast = 0x0A30FC,
- sceneSetter = 0x0A3110,
- entranceSetter = 0x0A3118,
- loadFlag = 0x0A3154,
- tribal = {
- saved = 0x1E3584,
- killed = 0x1E3585,
- remaining = 0x1E3586
- },
- region = 0x0A3129,
- continues = 0x0A3140,
- character = 0x1E3580,
- model = {
- vela = 0x1E36E0,
- juno = 0x1E3756
- },
- pointers = {
- vela = 0x1D40FC,
- juno = 0x1D4104,
- },
- rainbow_blood = 0x0A4F90,
- paused = 0x0A0564,
- night_vision = 0x0A6C13,
- lurg_vision = 0x0A31FF
- },
- velocity = {
- vela = 0x0190,
- juno = 0x0170
- },
- jet_fuel = {
- vela = 0x07B4,
- juno = 0x0794
- },
- state = {
- vela = 0x075A,
- juno = 0x073A
- }
- }
- local playerVelocity = nil
- local playerFuel = nil
- local playerState = nil
- local timer = 0
- local jetFuel = 0
- local jetFuelSwitch = false
- local tribals = {
- saved = 0,
- killed = 0,
- remaining = 0,
- killtotal = 0
- }
- -- Initialize Version Dependant Variables
- if (v ~= nil) then
- tribalRemaining = addrs[v].tribal.remaining
- tribalKilled = addrs[v].tribal.killed
- tribalSaved = addrs[v].tribal.saved
- region = addrs[v].region
- continues = addrs[v].continues
- sceneLast = addrs[v].sceneLast
- sceneSetter = addrs[v].sceneSetter
- entranceSetter = addrs[v].entranceSetter
- loadFlag = addrs[v].loadFlag
- rainbowBlood = addrs[v].rainbow_blood
- paused = addrs[v].paused
- nightVision = addrs[v].night_vision
- lurgVision = addrs[v].lurg_vision
- end
- -- Encapsulate memory.read/write into functions.
- function getByte(address)
- if (address ~= nil) then
- return memory.readbyte(address)
- else
- print("getByte(address): address (a nil value)")
- end
- end
- function getWord(address)
- if (address ~= nil) then
- return memory.read_u16_be(address)
- else
- print("getWord(address): address (a nil value)")
- end
- end
- function getDWord(address)
- if (address ~= nil) then
- return memory.read_u32_be(address)
- else
- print("getDWord(address): address (a nil value)")
- end
- end
- function setByte(address, value)
- if (address ~= nil and value ~= nil) then
- memory.writebyte(address, value)
- elseif (address == nil) then
- print("setByte(address, value): address (a nil value)")
- elseif (value == nil) then
- print("setByte(address, value): value (a nil value)")
- end
- end
- function setWord(address, value)
- if (address ~= nil and value ~= nil) then
- memory.write_u16_be(address, value)
- elseif (address == nil) then
- print("setWord(address, value): address (a nil value)")
- elseif (value == nil) then
- print("setWord(address, value): value (a nil value)")
- end
- end
- function setDWord(address, value)
- if (address ~= nil and value ~= nil) then
- memory.write_u32_be(address, value)
- elseif (address == nil) then
- print("setDWord(address, value): address (a nil value)")
- elseif (value == nil) then
- print("setDWord(address, value): value (a nil value)")
- end
- end
- -- This function handles setting up the player actor related data that moves around dynamically in memory.
- function setupTribal()
- playerVelocity = nil
- playerFuel = nil
- playerState = nil
- local character = getByte(addrs[v].character)
- local model
- -- Check the character and set model to Tribal
- if (character == 0x00 or character == 0x04) then
- model = getWord(addrs[v].model.vela) % 0x10
- model = getWord(addrs[v].model.vela) - model
- setWord(addrs[v].model.vela, model + 0x02)
- elseif (character == 0x01 or character == 0x05) then
- model = getWord(addrs[v].model.juno) % 0x10
- model = getWord(addrs[v].model.juno) - model
- setWord(addrs[v].model.juno, model + 0x02)
- end
- -- Give the scene time to load
- for i = 0, 240, 1 do -- 240 frames / 4 seconds.
- textDisplay()
- updateTribals()
- storeTribals()
- fixVision()
- emu.frameadvance()
- end
- -- Check the character and set addresses.
- if ((character == 0x00 or character == 0x04) and getDWord(addrs[v].pointers.vela) ~= 0x00000000) then
- playerVelocity = getDWord(addrs[v].pointers.vela) - 0x80000000 + addrs.velocity.vela
- playerState = getDWord(addrs[v].pointers.vela) - 0x80000000 + addrs.state.vela
- if (character == 0x04) then
- playerFuel = getDWord(addrs[v].pointers.vela) - 0x80000000 + addrs.jet_fuel.vela
- end
- elseif ((character == 0x01 or character == 0x05) and getDWord(addrs[v].pointers.juno) ~= 0x00000000) then
- playerVelocity = getDWord(addrs[v].pointers.juno) - 0x80000000 + addrs.velocity.juno
- playerState = getDWord(addrs[v].pointers.juno) - 0x80000000 + addrs.state.juno
- if (character == 0x05) then
- playerFuel = getDWord(addrs[v].pointers.juno) - 0x80000000 + addrs.jet_fuel.juno
- end
- end
- end
- -- Jet Pack with C-Up/C-Down like normal.
- function levitate(i)
- if (playerVelocity ~= nil and playerFuel ~= nil and playerState ~= nil) then
- local fuel = getWord(playerFuel)
- if (fuel > 0x0000 and fuel < 0x0E11 and getByte(playerState) ~= 0x01) then
- jetFuelSwitch = true
- if (i == true) then
- setDWord(playerVelocity, 0x40A00000) -- 5.0
- if (fuel - 0x0002 == 0xFFFF) then
- setWord(playerFuel, 0x0000)
- else
- setWord(playerFuel, fuel - 0x0002)
- end
- elseif (i == false) then
- setDWord(playerVelocity, 0x3FACCCCC) -- 1.25
- setWord(playerFuel, fuel - 0x0001)
- end
- end
- end
- end
- -- This function handles updating the tribal counts.
- function updateTribals()
- -- Store current counts to check against last frame's counts.
- local saved = getByte(tribalSaved)
- local killed = getByte(tribalKilled)
- local remaining = getByte(tribalRemaining)
- local savedDiff = 0
- local killedDiff = 0
- -- Check if the Remaining Tribals has gone down.
- if (remaining < tribals.remaining) then
- -- Killed Difference
- if (killed > tribals.killed) then
- killedDiff = killed - tribals.killed
- elseif (killed < tribals.killed) then
- -- If the count has decreased then the player entered a new region.
- tribals.killed = 0
- end
- -- Saved Difference
- if (saved > tribals.saved) then
- savedDiff = saved - tribals.saved
- elseif (saved < tribals.saved) then
- -- If the count has decreased then the player entered a new region.
- tribals.saved = 0
- end
- -- Apply Differences to opposite count.
- tribals.saved = tribals.saved + killedDiff
- tribals.killed = tribals.killed + savedDiff
- -- Update Kill Total
- tribals.killtotal = tribals.killtotal + killedDiff
- -- Validate Tribal counts. (16 is highest)
- if (tribals.saved > 16 or tribals.killed > 16) then
- gui.addmessage("Invalid Tribal Counts")
- gui.addmessage("Reseting Counts...")
- setByte(tribalSaved, 0)
- setByte(tribalKilled, 0)
- setByte(tribalRemaining, tribals.remaining)
- else
- setByte(tribalSaved, tribals.saved)
- setByte(tribalKilled, tribals.killed)
- end
- end
- end
- -- Store the tribal counts.
- function storeTribals()
- tribals.saved = getByte(tribalSaved)
- tribals.killed = getByte(tribalKilled)
- tribals.remaining = getByte(tribalRemaining)
- end
- function jetFuelDisplayTimer()
- local fuel = getWord(playerFuel)
- if (fuel ~= jetFuel) then
- jetFuelSwitch = true
- elseif (fuel == 0x0000) then
- jetFuelSwitch = false
- end
- if (jetFuelSwitch == true and timer < 455) then
- timer = timer + 2
- elseif(jetFuelSwitch == false and timer > 0) then
- timer = timer - 1
- end
- if (timer >= 455) then
- jetFuelSwitch = false
- end
- jetFuel = fuel
- end
- function textDisplay()
- local x = 45
- local y = 13
- local t = 0
- if (timer < 0xFF) then
- t = timer * 0x01000000
- else
- t = 0xFF000000
- end
- -- Tribal Counts
- if (getByte(loadFlag) == 0x00 and getByte(region) ~= 0x00 and getByte(paused) == 0x00) then
- if (getWord(sceneLast) ~= 0x0000 and
- getWord(sceneLast) ~= 0x0001 and
- getWord(sceneLast) ~= 0x007F and
- getWord(sceneLast) ~= 0x015C and
- getWord(sceneLast) ~= 0x015D and
- getWord(sceneLast) ~= 0x017D and
- getWord(sceneLast) ~= 0x017E and
- getWord(sceneLast) ~= 0x017F and
- getWord(sceneLast) ~= 0x0180 and
- getWord(sceneLast) ~= 0x0181) then
- gui.drawBox(x, y, x + 102, y + 15, 0xFF4FB3C9, 0x80267580)
- gui.drawText(x - 2, y - 1, string.format("%02d", tribals.saved), 0x60FFFFFF, "TRANSPARENT", 16)
- gui.drawText(x + 22, y - 1, string.format("%02d", tribals.killed), 0x60FFFFFF, "TRANSPARENT", 16)
- gui.drawText(x + 46, y - 1, string.format("%02d", tribals.remaining), 0x60FFFFFF, "TRANSPARENT", 16)
- gui.drawText(x + 70, y - 1, string.format("%03d", tribals.killtotal), 0x60FFFF00, "TRANSPARENT", 16)
- gui.drawText(x - 2, y - 1, string.format("%2d", tribals.saved), 0xFFFFFFFF, "TRANSPARENT", 16)
- gui.drawText(x + 22, y - 1, string.format("%2d", tribals.killed), 0xFFFFFFFF, "TRANSPARENT", 16)
- gui.drawText(x + 46, y - 1, string.format("%2d", tribals.remaining), 0xFFFFFFFF, "TRANSPARENT", 16)
- gui.drawText(x + 70, y - 1, string.format("%3d", tribals.killtotal), 0xFFFFFF00, "TRANSPARENT", 16)
- end
- end
- -- Jet Fuel
- if (getByte(loadFlag) == 0x00 and getByte(paused) == 0x00 and playerFuel ~= nil and getWord(playerFuel) < 0x0E11) then
- if (font == false) then
- if (timer < 0x80) then
- gui.drawBox(x + 183, y + 424, x + 407, y + 439, t + 0x4FB3C9, t + 0x267580)
- else
- gui.drawBox(x + 183, y + 424, x + 407, y + 439, t + 0x4FB3C9, 0x80267580)
- end
- gui.drawText(x + 230, y + 423, string.format("Jet Fuel: %3d", getWord(playerFuel) / 36), t + 0xFFFFFF, "TRANSPARENT", 16)
- elseif (font == true) then
- -- Main
- if (getWord(playerFuel) / 36 == 100) then
- gui.drawText(470, 386, string.format("%3d", getWord(playerFuel) / 36), t + 0x00FF00, "Transparent", 47, "Quartz MS")
- elseif (getWord(playerFuel) / 36 >= 10) then
- gui.drawText(485, 386, string.format("%3d", getWord(playerFuel) / 36), t + 0x00FF00, "Transparent", 47, "Quartz MS")
- else
- gui.drawText(502, 386, string.format("%3d", getWord(playerFuel) / 36), t + 0x00FF00, "Transparent", 47, "Quartz MS")
- end
- -- Background
- if (timer < 0x20) then
- gui.drawText(470, 386, string.format("%3d", 888), t + 0x00FF00, "Transparent", 47, "Quartz MS")
- else
- gui.drawText(470, 386, string.format("%3d", 888), 0x2000FF00, "Transparent", 47, "Quartz MS")
- end
- end
- end
- end
- function fixVision()
- -- Disable Lurg Black Screen
- if (getByte(lurgVision) == 0x01) then
- setByte(lurgVision, 0x00)
- end
- -- 0x0107
- -- Disable Night Vision
- if (getByte(nightVision) ~= 0x00) then
- setByte(nightVision, 0x00)
- end
- -- By pass the Night Vision Room.
- -- Since it's disabled there's no reason to get it or activate it.
- if (getByte(loadFlag) ~= 0x00 and getWord(sceneSetter) == 0x013D and getWord(entranceSetter) == 0x0001) then
- setWord(sceneSetter, 0x0137)
- elseif (getByte(loadFlag) ~= 0x00 and getWord(sceneSetter) == 0x013C and getWord(entranceSetter) == 0x0000) then
- setWord(sceneSetter, 0x013B)
- end
- end
- -- Run this when the script is turned on. UNLESS at the title screen/game select menu.
- if (getWord(sceneLast) ~= 0x0000 and
- getWord(sceneLast) ~= 0x0001 and
- getWord(sceneLast) ~= 0x007F and
- getWord(sceneLast) ~= 0x015C and
- getWord(sceneLast) ~= 0x015D and
- getWord(sceneLast) ~= 0x017D and
- getWord(sceneLast) ~= 0x017E and
- getWord(sceneLast) ~= 0x017F and
- getWord(sceneLast) ~= 0x0180 and
- getWord(sceneLast) ~= 0x0181) then
- setupTribal()
- storeTribals()
- end
- while true do
- -- If version is not detected the script won't be able to do anything.
- if (v ~= nil) then
- -- Button Activators
- if joypad.get(1)['C Up'] then
- levitate(true)
- elseif joypad.get(1)['C Down'] then
- levitate(false)
- end
- -- On a load.
- if (getByte(loadFlag) ~= 0x00) then
- local i = getWord(sceneSetter)
- -- If the entrance is any of the below this won't run.
- if (i ~= 0x0000 and -- Game Select
- i ~= 0x0001 and -- Game Select
- i ~= 0x007F and -- Character Select
- i ~= 0x015C and -- Title Screen
- i ~= 0x015D and -- Title Screen
- i ~= 0x017D and -- Title Screen
- i ~= 0x017E and -- Title Screen
- i ~= 0x017F and -- Title Screen
- i ~= 0x0180 and -- Title Screen
- i ~= 0x0181 and -- Title Screen
- i ~= 0x00FA and -- Mizar's Palace Race Areas
- i ~= 0x010C and -- Mizar's Palace Race Areas
- i ~= 0x011D and -- Mizar's Palace Race Areas
- i ~= 0x0169 and -- Mizar's Palace Race Areas
- i ~= 0x016B and -- Mizar's Palace Race Areas
- i ~= 0x0197 and -- Mizar's Palace Race Areas
- i ~= 0x018E and -- Mizar's Palace Race Areas
- i ~= 0x018A) then -- Mizar's Palace Race Areas
- -- Rainbow Blood
- setDWord(rainbowBlood, 0x01000000)
- setupTribal()
- end
- end
- if (playerFuel ~= nil) then
- jetFuelDisplayTimer()
- end
- textDisplay()
- updateTribals()
- storeTribals()
- fixVision()
- end
- emu.frameadvance()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement