[dino dinoj] hitbox viewer port
Posted: Tue Nov 21, 2017 2:51 pm
It is ported from mame-rr beat'em up hitbox viewer.
Bugfixed.
Box define methods for attack box and vulnerability box are different.
save the code as dino.json and dinoj.json. Enable in plugin cheats.
Bugfixed.
Box define methods for attack box and vulnerability box are different.
save the code as dino.json and dinoj.json. Enable in plugin cheats.
Code: Select all
[{
"space":{
"cpup":{
"type":"program",
"tag":":maincpu"
}
},
"script":{
"on":"
--[[--CPS-2 beatem up hitbox viewer]]
--[[--November 11, 2011]]
--[[--http://code.google.com/p/mame-rr/wiki/Hitboxes]]
boxes = {
[\"vulnerability\"] = {color = 0x7777FF, fill = 0x40, outline = 0xFF},
[\"attack\"] = {color = 0xFF0000, fill = 0x40, outline = 0xFF},
[\"proj. vulnerability\"] = {color = 0x00FFFF, fill = 0x40, outline = 0xFF},
[\"proj. attack\"] = {color = 0xFF66FF, fill = 0x40, outline = 0xFF},
}
globals = {
axis_color = 0xFFFFFFFF,
blank_color = 0xFFFFFFFF,
axis_size = 12,
mini_axis_size = 2,
blank_screen = false,
draw_axis = true,
draw_mini_axis = false,
no_alpha = false, --fill = 0x00, outline = 0xFF for all box types
}
--------------------------------------------------------------------------------
-- game-specific modules
--invulnerable: if > 0, don't draw blue
--alive: if == 0, don't draw blue
--hp: if < 0, don't draw blue
--harmless: never draw red
--active: if none == 0, don't draw red
game = {
gamename = \"dino\",
address = {
screen_left = 0xFF8744,
game_phase = 0xFF0A4B,
},
offset = {
flip_x = 0x24,
pos_x = 0x08,
pos_z = 0x10,
},
objects = {
{address = 0xFF8874, number = 0x18, space = 0x0C0, active = {0x14,0x16,0x4C,0xB0}, projectile = true}, --items
{address = 0xFFB274, number = 0x03, space = 0x180, alive = 0x6C, invulnerable = 0x118}, --players
{address = 0xFFB6F4, number = 0x18, space = 0x0C0, alive = 0x6C, projectile = true}, --etc
{address = 0xFFC8F4, number = 0x18, space = 0x0E0, alive = 0x6C}, --enemies
},
box = {
--radius_read = cpup:read_u16,
val_x = 0x4, val_y = 0x8, rad_x = 0x6, rad_y = 0xA,
radscale = 2,
},
box_list = {
{id_ptr = 0x48, type = \"vulnerability\", special_offset = 0x2},
{id_ptr = 0x48, type = \"vulnerability\", special_offset = 0xE},
{id_ptr = 0x49, type = \"attack\", special_offset = 0x2},
},
--id_read = cpup:read_u8,
--cpup:read_u8,
exist_val = 0x0101,
box_address = function(obj, box, box_entry)
local address = cpup:read_u32(obj.base + 0x44)
if address == 0x106000 then --dinosaurs
address = address + cpup:read_u16(address + box.id * 2)
if not box_entry.special_offset or (cpup:read_u16(address) == 0 and box_entry.special_offset > 0x2) then
return nil
end
return address + box_entry.special_offset
end
return address + box.id * 0xC --everything else
end,
}
--------------------------------------------------------------------------------
-- post-process modules
--game.box.offset_read = game.box.radius_read == cpup:read_u8 and cpup:read_i8 or cpup:read_i16
game.offset.pos_y = game.offset.pos_x + 0x4
game.exist_val = game.exist_val or 0x0100
for _, box in pairs(boxes) do
box.fill = box.color | ((globals.no_alpha and 0x00 or box.fill) << 24)
box.outline = box.color | ((globals.no_alpha and 0xFF or box.outline) << 24)
end
framebuffer = {}
DRAW_DELAY = 1
function copytable(orig)
local copy = {}
for orig_key, orig_value in pairs(orig) do
copy[orig_key] = orig_value
end
return copy
end
function max(a, b)
if a > b then
return a
end
return b
end
--------------------------------------------------------------------------------
-- prepare the hitboxes
set_box_center = {
function(obj, box)
return
obj.pos_x + box.val_x * (obj.flip_x > 0 and -1 or 1),
obj.pos_y - box.val_y
end,
function(obj, box)
if box.type==\"attack\" then
return
obj.pos_x + (box.val_x + box.rad_x) * (obj.flip_x > 0 and -1 or 1),
obj.pos_y - (box.val_y + box.rad_y)
end
return
obj.pos_x,
obj.pos_y - (box.val_y + box.rad_y)
end,
}
function define_box(obj, box_entry)
local box = {type = box_entry.type}
local base_id = box_entry.anim_ptr and cpup:read_u32(obj.base + box_entry.anim_ptr) or obj.base
box.id = cpup:read_u8(base_id + box_entry.id_ptr)
if base_id == 0 or box.id <= 0 or
(obj.invulnerable and box.type == \"vulnerability\") or
(obj.harmless and box.type == \"attack\") then
return nil
elseif obj.projectile then
box.type = (box.type == \"vulnerability\" and \"proj. vulnerability\") or box.type
box.type = (box.type == \"attack\" and \"proj. attack\") or box.type
end
box.address = game.box_address(obj, box, box_entry)
if not box.address then
return nil
end
box.rad_x = cpup:read_u16(box.address + game.box.rad_x)/game.box.radscale
box.rad_y = cpup:read_u16(box.address + game.box.rad_y)/game.box.radscale
box.val_x = cpup:read_i16(box.address + game.box.val_x)
box.val_y = cpup:read_i16(box.address + game.box.val_y)
box.val_x, box.val_y = set_box_center[game.box.radscale](obj, box)
box.left = box.val_x - box.rad_x
box.right = box.val_x + box.rad_x
box.top = box.val_y - box.rad_y
box.bottom = box.val_y + box.rad_y
return box
end
function update_object(f, obj)
obj.flip_x = cpup:read_u8(obj.base + game.offset.flip_x)
obj.pos_z = game.offset.pos_z and cpup:read_i16(obj.base + game.offset.pos_z) or 0
obj.pos_x = cpup:read_i16(obj.base + game.offset.pos_x) - f.screen_left
obj.pos_y = cpup:read_i16(obj.base + game.offset.pos_y) + obj.pos_z
obj.pos_y = screen:height() - (obj.pos_y - 0x0F) + f.screen_top
for entry in ipairs(game.box_list) do
table.insert(obj, define_box(obj, game.box_list[entry]))
end
return obj
end
function inactive(base, active)
for _, offset in ipairs(active) do
if cpup:read_u16(base + offset) > 0 then
return false
end
end
return true
end
function update_hitboxes()
if not game then
return
end
for f = 1, DRAW_DELAY do
framebuffer[f] = copytable(framebuffer[f+1])
end
framebuffer[DRAW_DELAY+1] = {game_active = cpup:read_u8(game.address.game_phase) > 0}
local f = framebuffer[DRAW_DELAY+1]
if not f.game_active then
return
end
f.screen_left = cpup:read_i16(game.address.screen_left)
f.screen_top = cpup:read_i16(game.address.screen_left + 0x4)
for _, set in ipairs(game.objects) do
for n = 1, set.number do
local obj = {base = set.address + (n-1) * set.space}
if cpup:read_i16(obj.base) >= game.exist_val then
obj.projectile = set.projectile
obj.invulnerable = (set.hp and cpup:read_i16(obj.base + set.hp) < 0) or
(set.alive and cpup:read_u16(obj.base + set.alive) == 0) or
(set.invulnerable and cpup:read_u16(obj.base + set.invulnerable) > 0)
obj.harmless = set.harmless or (set.active and inactive(obj.base, set.active))
obj.addr_table = set.addr_table
table.insert(f, update_object(f, obj))
if obj.box_count then
f.box_count = obj.box_count
end
end
end
end
end
--------------------------------------------------------------------------------
-- draw the hitboxes
function draw_hitbox(hb)
if not hb then
return
end
if globals.draw_mini_axis then
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)
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)
end
draw_box(screen,hb.left, hb.top, hb.right, hb.bottom, boxes[hb.type].fill, boxes[hb.type].outline)
--draw_text(screen,hb.left,hb.bottom,0xFFFF0000,\"%s\",hb.type)
end
function draw_axis(obj)
draw_line(screen,obj.pos_x, obj.pos_y-globals.axis_size, obj.pos_x, obj.pos_y+globals.axis_size, globals.axis_color)
draw_line(screen,obj.pos_x-globals.axis_size, obj.pos_y, obj.pos_x+globals.axis_size, obj.pos_y, globals.axis_color)
--draw_text(screen,obj.pos_x, obj.pos_y,0xFFFFFFFF, \"%06X\", obj.base) --debug
end
function render_hitboxes()
local f = framebuffer[1]
if not f.game_active then
return
end
if globals.blank_screen then
draw_box(screen,0, 0, screen:width(), screen:height(), globals.blank_color)
end
for entry = 1, f.box_count or #game.box_list do
for _, obj in ipairs(f) do
draw_hitbox(obj[entry])
end
end
if globals.draw_axis then
for _, obj in ipairs(f) do
draw_axis(obj)
end
end
end
--------------------------------------------------------------------------------
-- initialize on game startup
function initialize_fb()
framebuffer = {}
for f = 1, DRAW_DELAY + 1 do
framebuffer[f] = {}
end
end
initialize_fb()
",
"run":"update_hitboxes() render_hitboxes()"
},
"screen":{
"screen":":screen"
},
"desc":"Hitbox viewer"
}]
--[[-- Cheat file downloaded from http://www.mamecheat.co.uk, see cheat.txt for list of contributors. ]]