Skip to content

Instantly share code, notes, and snippets.

@cracyc
Last active February 21, 2024 21:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cracyc/01b6d1c93b3b9937eb500dff157fc832 to your computer and use it in GitHub Desktop.
Save cracyc/01b6d1c93b3b9937eb500dff157fc832 to your computer and use it in GitHub Desktop.
sf2 lua cheats
[{
"space":{
"cpup":{
"type":"program",
"tag":":maincpu"
}
},
"script":{
"on":" --[[--Street Fighter II hitbox viewer]]\n --[[--February 20, 2012]]\n --[[--http://code.google.com/p/mame-rr/wiki/Hitboxes]]\n \n boxes = {\n [\"vulnerability\"] = {color = 0x7777FF, fill = 0x40, outline = 0xFF},\n [\"attack\"] = {color = 0xFF0000, fill = 0x40, outline = 0xFF},\n [\"proj. vulnerability\"] = {color = 0x00FFFF, fill = 0x40, outline = 0xFF},\n [\"proj. attack\"] = {color = 0xFF66FF, fill = 0x40, outline = 0xFF},\n [\"push\"] = {color = 0x00FF00, fill = 0x20, outline = 0xFF},\n [\"weak\"] = {color = 0xFFFF00, fill = 0x40, outline = 0xFF},\n [\"throw\"] = {color = 0xFFFF00, fill = 0x40, outline = 0xFF},\n [\"throwable\"] = {color = 0xF0F0F0, fill = 0x20, outline = 0xFF},\n [\"air throwable\"] = {color = 0x202020, fill = 0x20, outline = 0xFF},\n }\n \n globals = {\n axis_color = 0xFFFFFFFF,\n blank_color = 0xFFFFFFFF,\n axis_size = 12,\n mini_axis_size = 2,\n blank_screen = false,\n draw_axis = true,\n draw_mini_axis = false,\n draw_pushboxes = true,\n draw_throwable_boxes = false,\n no_alpha = false, --[[--fill = 0x00, outline = 0xFF for all box types]]\n }\n \n profile = \n {\tgames = {\"sf2\"},\n address = {\n player = 0xFF83C6,\n projectile = 0xFF938A,\n screen_left = 0xFF8BD8,\n },\n player_space = 0x300,\n box_parameter_size = 1,\n box_list = {\n {addr_table = 0xA, id_ptr = 0xD, id_space = 0x04, type = \"push\"},\n {addr_table = 0x0, id_ptr = 0x8, id_space = 0x04, type = \"vulnerability\"},\n {addr_table = 0x2, id_ptr = 0x9, id_space = 0x04, type = \"vulnerability\"},\n {addr_table = 0x4, id_ptr = 0xA, id_space = 0x04, type = \"vulnerability\"},\n {addr_table = 0x6, id_ptr = 0xB, id_space = 0x04, type = \"weak\"},\n {addr_table = 0x8, id_ptr = 0xC, id_space = 0x0C, type = \"attack\"},\n },\n }\n \n profile.match_active = function() return (cpup:read_u16(0xFF8008) & 0x08) > 0 end\n \n for _, box in pairs(boxes) do\n box.fill = box.color | ((globals.no_alpha and 0x00 or box.fill) << 24)\n box.outline = box.color | ((globals.no_alpha and 0xFF or box.outline) << 24)\n end\n \n NUMBER_OF_PLAYERS = 2\n MAX_PROJECTILES = 8\n MAX_BONUS_OBJECTS = 16\n DRAW_DELAY = 1\n \n \n initialize_fb = function()\n frame_buffer = {}\n for f = 1, DRAW_DELAY + 3 do\n frame_buffer[f] = {}\n end\n end\n \n \n initialize_throw_buffer = function()\n throw_buffer = {}\n for p = 1, NUMBER_OF_PLAYERS do\n throw_buffer[game.address.player + (p-1) * game.player_space] = {}\n end\n end\n \n \n whatgame = function()\n initialize_fb()\n game = profile\n initialize_throw_buffer()\n end\n \n --[[--------------------------------------------------------------------------------]]\n --[[-- prepare the hitboxes]]\n \n get_box_parameters = {\n [1] = function(box)\n box.val_x = cpup:read_i8(box.address + 0)\n box.val_x2 = cpup:read_u8(box.address + 5)\n if box.val_x2 >= 0x80 and box.type == \"attack\" then\n box.val_x = -box.val_x2\n end\n box.val_y = cpup:read_i8(box.address + 1)\n box.rad_x = cpup:read_u8(box.address + 2)\n box.rad_y = cpup:read_u8(box.address + 3)\n end,\n \n [2] = function(box)\n box.val_x = cpup:read_i16(box.address + 0)\n box.val_y = cpup:read_i16(box.address + 2)\n box.rad_x = cpup:read_u16(box.address + 4)\n box.rad_y = cpup:read_u16(box.address + 6)\n end,\n }\n \n \n process_box_type = {\n [\"vulnerability\"] = function(obj, box)\n end,\n \n [\"attack\"] = function(obj, box)\n if obj.projectile then\n box.type = \"proj. attack\"\n elseif cpup:read_u8(obj.base + 0x03) == 0 then\n return false\n end\n end,\n \n [\"push\"] = function(obj, box)\n if obj.projectile then\n box.type = \"proj. vulnerability\"\n end\n end,\n \n [\"weak\"] = function(obj, box)\n if (game.char_mode and cpup:read_u8(obj.base + game.char_mode) ~= 0x4)\n or cpup:read_u8(obj.animation_ptr + 0x15) ~= 2 then\n return false\n end\n end,\n \n [\"throw\"] = function(obj, box)\n get_box_parameters[2](box)\n if box.val_x == 0 and box.val_y == 0 and box.rad_x == 0 and box.rad_y == 0 then\n return false\n end\n \n if box.clear then\n for offset = 0, 6, 2 do\n cpup:write_u32(box.address + offset, 0) --[[--bad]]\n end\n end\n \n box.val_x = obj.pos_x + box.val_x * (obj.flip_x == 1 and -1 or 1)\n box.val_y = obj.pos_y - box.val_y\n box.left = box.val_x - box.rad_x\n box.right = box.val_x + box.rad_x\n box.top = box.val_y - box.rad_y\n box.bottom = box.val_y + box.rad_y\n end,\n \n [\"throwable\"] = function(obj, box)\n if (cpup:read_u8(obj.animation_ptr + 0x8) == 0 and\n cpup:read_u8(obj.animation_ptr + 0x9) == 0 and\n cpup:read_u8(obj.animation_ptr + 0xA) == 0) or\n cpup:read_u8(obj.base + 0x3) == 0x0E or\n cpup:read_u8(obj.base + 0x3) == 0x14 or\n cpup:read_u8(obj.base + 0x143) > 0 or\n cpup:read_u8(obj.base + 0x1BF) > 0 or\n cpup:read_u8(obj.base + 0x1A1) > 0 then\n return false\n elseif cpup:read_u8(obj.base + 0x181) > 0 then\n box.type = \"air throwable\"\n end\n \n box.rad_x = cpup:read_u16(box.address + 0)\n box.rad_y = cpup:read_u16(box.address + 2)\n box.val_x = obj.pos_x\n box.val_y = obj.pos_y - box.rad_y/2\n box.left = box.val_x - box.rad_x\n box.right = box.val_x + box.rad_x\n box.top = obj.pos_y - box.rad_y\n box.bottom = obj.pos_y\n end,\n }\n \n \n define_box = function(obj, box_entry)\n local box = {\n type = box_entry.type,\n id = cpup:read_u8(obj.animation_ptr + box_entry.id_ptr),\n }\n \n if box.id == 0 or process_box_type[box.type](obj, box) == false then\n return nil\n end\n \n local addr_table = obj.hitbox_ptr + cpup:read_i16(obj.hitbox_ptr + box_entry.addr_table)\n box.address = addr_table + box.id * box_entry.id_space\n get_box_parameters[game.box_parameter_size](box)\n \n box.val_x = obj.pos_x + box.val_x * (obj.flip_x == 1 and -1 or 1)\n box.val_y = obj.pos_y - box.val_y\n box.left = box.val_x - box.rad_x\n box.right = box.val_x + box.rad_x\n box.top = box.val_y - box.rad_y\n box.bottom = box.val_y + box.rad_y\n \n return box\n end\n \n \n define_throw_box = function(obj, box_entry)\n local box = {\n type = box_entry.type,\n address = obj.base + box_entry.param_offset,\n clear = box_entry.clear,\n }\n \n if process_box_type[box.type](obj, box) == false then\n return nil\n end\n \n return box\n end\n \n \n update_object = function(f, obj)\n obj.pos_x = cpup:read_i16(obj.base + 0x06) - f.screen_left\n obj.pos_y = cpup:read_i16(obj.base + 0x0A)\n obj.pos_y = screen:height() - (obj.pos_y - 0x0F) + f.screen_top\n obj.flip_x = cpup:read_u8(obj.base + 0x12)\n obj.animation_ptr = cpup:read_u32(obj.base + 0x1A)\n obj.hitbox_ptr = cpup:read_u32(obj.base + 0x34)\n \n for _, box_entry in ipairs(game.box_list) do\n table.insert(obj, define_box(obj, box_entry))\n end\n return obj\n end\n \n \n read_projectiles = function(f)\n for i = 1, MAX_PROJECTILES do\n local obj = {base = game.address.projectile + (i-1) * 0xC0}\n if cpup:read_u16(obj.base) == 0x0101 then\n obj.projectile = true\n table.insert(f, update_object(f, obj))\n end\n end\n \n for i = 1, MAX_BONUS_OBJECTS do\n local obj = {base = game.address.projectile + (MAX_PROJECTILES + i-1) * 0xC0}\n if (0xFF00 & cpup:read_u16(obj.base)) == 0x0100 then\n obj.bonus = true\n table.insert(f, update_object(f, obj))\n end\n end\n end\n \n \n adjust_delay = function(stage_address)\n if not stage_address then\n return 0\n end\n local stage_lag = {\n [0x0] = 0, --[[--Ryu]]\n [0x1] = 0, --[[--E.Honda]]\n [0x2] = 0, --[[--Blanka]]\n [0x3] = 0, --[[--Guile]]\n [0x4] = 0, --[[--Ken]]\n [0x5] = 0, --[[--Chun Li]]\n [0x6] = 0, --[[--Zangief]]\n [0x7] = 0, --[[--Dhalsim]]\n [0x8] = 0, --[[--Dictator]]\n [0x9] = 0, --[[--Sagat]]\n [0xA] = 1, --[[--Boxer*]]\n [0xB] = 0, --[[--Claw]]\n [0xC] = 1, --[[--Cammy*]]\n [0xD] = 1, --[[--T.Hawk*]]\n [0xE] = 0, --[[--Fei Long]]\n [0xF] = 1, --[[--Dee Jay*]]\n }\n return stage_lag[cpup:read_u16(stage_address) & 0xF]\n end\n \n local function copytable(orig)\n local copy = {}\n for orig_key, orig_value in pairs(orig) do\n copy[orig_key] = orig_value\n end\n return copy\n end\n function max(a, b)\n if a > b then\n return a\nend\nreturn b\n end\n\nupdate_hitboxes = function()\n if not game then\n return\n end\n local effective_delay = DRAW_DELAY + adjust_delay(game.address.stage)\n for f = 1, effective_delay do\n frame_buffer[f] = copytable(frame_buffer[f+1])\n end\n \n frame_buffer[effective_delay+1] = {match_active = game.match_active()}\n local f = frame_buffer[effective_delay+1]\n \n f.screen_left = cpup:read_i16(game.address.screen_left)\n f.screen_top = cpup:read_i16(game.address.screen_left + 0x4)\n \n for p = 1, NUMBER_OF_PLAYERS do\n local player = {base = game.address.player + (p-1) * game.player_space}\n if cpup:read_u8(player.base) > 0 then\n table.insert(f, update_object(f, player))\n local tb = throw_buffer[player.base]\n table.insert(player, tb[1])\n for frame = 1, #tb-1 do\n tb[frame] = tb[frame+1]\n end\n table.remove(tb)\n end\n end\n read_projectiles(f)\n \n --[[--f = frame_buffer[effective_delay] ]]\n for _, obj in ipairs(f or {}) do\n if obj.projectile or obj.bonus then\n break\n end\n table.insert(obj, define_throw_box(obj, {param_offset = 0x6C, type = \"throwable\"}))\n table.insert(obj, define_throw_box(obj, {param_offset = 0x64, type = \"throw\", clear = true}))\n end\n \n f.max_boxes = 0\n for _, obj in ipairs(f or {}) do\n f.max_boxes = max(f.max_boxes, #obj)\n end\n end\n \n --[[--------------------------------------------------------------------------------]]\n --[[-- draw the hitboxes]]\n \n draw_hitbox = function(hb)\n if not hb or\n (not globals.draw_pushboxes and hb.type == \"push\") or\n (not globals.draw_throwable_boxes and (hb.type == \"throwable\" or hb.type == \"air throwable\")) then\n return\n end\n \n if globals.draw_mini_axis then\n draw_line(screen, hb.val_x, hb.val_y-globals.mini_axis_size, hb.val_x, hb.val_y+globals.mini_axis_size, boxes[hb.type].outline)\n draw_line(screen, hb.val_x-globals.mini_axis_size, hb.val_y, hb.val_x+globals.mini_axis_size, hb.val_y, boxes[hb.type].outline)\n end\n \n draw_box(screen, hb.left, hb.top, hb.right, hb.bottom, boxes[hb.type].fill, boxes[hb.type].outline)\n end\n \n \n draw_axis = function(obj)\n draw_line(screen, obj.pos_x, obj.pos_y-globals.axis_size, obj.pos_x, obj.pos_y+globals.axis_size, globals.axis_color)\n draw_line(screen, obj.pos_x-globals.axis_size, obj.pos_y, obj.pos_x+globals.axis_size, obj.pos_y, globals.axis_color)\n --[[--gui.text(obj.pos_x, obj.pos_y, string.format(\"%06X\", obj.base)) --debug]]\n end\n \n \n render_hitboxes = function()\n local f = frame_buffer[1]\n if not f.match_active then\n return\n end\n \n for entry = 1, f.max_boxes or 0 do\n for _, obj in ipairs(f) do\n draw_hitbox(obj[entry])\n end\n end\n \n if globals.draw_axis then\n for _, obj in ipairs(f) do\n draw_axis(obj)\n end\n end\n end\n \n whatgame()\n",
"run":"update_hitboxes() render_hitboxes()"
},
"screen":{
"screen":":screen"
},
"desc":"Hitbox viewer"
}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment