-- Configuration
local config = {
display_sprite_hitbox = true,
display_sprite_info = true,
}
local colors = {
"red", -- Donkey Kong
"magenta" -- Diddy
}
-- Some utility functions
local u8 = mainmemory.read_u8
local s8 = mainmemory.read_s8
local u16 = mainmemory.read_u16_le
local s16 = mainmemory.read_s16_le
local function rectangle(x, y, w, h, ...)
-- Draw from top-left to bottom-right
if w < 0 then
x, w = x + w, -w
end
if h < 0 then
y, h = y + h, -h
end
gui.drawRectangle(x, y, w, h, ...)
end
-- Definitions
local WRAM = {
game_mode_ptr = 0x1c,
camera_vertical_offset = 0x4a,
-- 0xbe --> camera distance from level origin
-- 0xc0 --> camera y mirror
xcam_effective = 0x1a62,
sprite_type = 0x0d45,
xspeed = 0xe8b,
xpos_camera = 0x88b,
ypos_camera = 0x895,
left_border_pos = 0x1b23,
xpos_offset = 0x0b19,
ypos_offset = 0x0bc1,
}
-- This table'll be used differently in the future
-- some sprites have completely different hitboxes depending on context
local odd_hitbox = {
-- [sprite type] = offset,
[0x15] = 0x08,
[0x16] = 0x08,
[0x23] = false, -- 0x0d,
}
local game = {}
local sprite = {}
-- Game functions
local function load_game_info()
game.game_mode_ptr = u16(WRAM.game_mode_ptr)
game.is_level_mode = game.game_mode_ptr == 0x80a9 or game.game_mode_ptr == 0xa98e
game.camera_vertical_offset = u16(WRAM.camera_vertical_offset)
game.xpos_camera = u16(WRAM.xpos_camera)
game.ypos_camera = u16(WRAM.ypos_camera)
end
local function draw_hitbox(xscreen, yscreen, slot, hitbox_offset, color)
-- flip
local do_flip = u16(0x0c69 + 2*slot)
local xflip = bit.check(do_flip, 14) and -1 or 1
local yflip = bit.check(do_flip, 15) and -1 or 1 -- not sure about that
local xoff = xflip * memory.read_s16_le(hitbox_offset + 0, "System Bus")
local yoff = yflip * memory.read_s16_le(hitbox_offset + 2, "System Bus")
local width = xflip * memory.read_s16_le(hitbox_offset + 4, "System Bus")
local height = yflip * memory.read_s16_le(hitbox_offset + 6, "System Bus")
-- draw
rectangle(xscreen + xoff, yscreen + yoff, width, height, color)
end
-- bba4d5 , bba4c8: get sprite clipping values (normal / special)
-- bba594: check for collision
-- b2 a6/ aa ae / b0 ac / a8 b4
local function sprite_hitbox(slot)
local spr_type = u16(WRAM.sprite_type + 2*slot)
local index = math.floor(u16(0xd11 + 2*slot)/2)
-- position
local xpos = u16(WRAM.xpos_offset + 2*slot)
local ypos = u16(WRAM.ypos_offset + 2*slot)
local xscreen = xpos - game.xpos_camera
local yscreen = game.camera_vertical_offset - ypos - game.ypos_camera
local color
if slot <= 2 then
color = colors[slot]
elseif odd_hitbox[spr_type] then
color = 0xff00ff00
else
color = "yellow"
end
local hitbox_offset
if odd_hitbox[spr_type] then
hitbox_offset = 8*odd_hitbox[spr_type] + 0xa428
else
hitbox_offset = memory.read_u16_le(0xbb8000 + index, "System Bus")
end
hitbox_offset = hitbox_offset + 0xbb0000
draw_hitbox(xscreen, yscreen, slot, hitbox_offset, color)
end
local function draw_sprite_info()
local xpos_camera = game.xpos_camera
local ypos_camera = game.ypos_camera
local camera_vertical_offset = game.camera_vertical_offset
-- gui.text(0, 0, string.format("Cam: %d, %d", xpos_camera, ypos_camera))
for slot = 1, 25 do
local spr_type = u16(WRAM.sprite_type + 2*slot)
local is_normal_sprite = slot <= 14
if spr_type ~= 0 then
local xpos = u16(WRAM.xpos_offset + 2*slot)
local ypos = u16(WRAM.ypos_offset + 2*slot)
local xscreen = xpos - xpos_camera
local yscreen = camera_vertical_offset - ypos - ypos_camera
local xspeed = s8(WRAM.xspeed + slot) -- todo
-- draw position pixel
if config.display_sprite_info then
gui.drawPixel(xscreen, yscreen, 0xc0ffffff)
gui.drawText(xscreen, yscreen, "#" .. slot, 0x80ffffff)
local mytext = string.format("#%d[%.2x] (%d, %d)", slot, spr_type, xpos, ypos)
gui.text(client.screenwidth() - 10 * #mytext, 15*slot, mytext, is_normal_sprite and 0xffffffff or 0xff808080)
end
-- draw hitbox
if is_normal_sprite then
sprite_hitbox(slot)
end
end
end
end
-- Callbacks and startup
print("DKC Lua script has started.")
while true do
load_game_info()
if game.is_level_mode then
draw_sprite_info()
else
gui.text(0, 0, "Outside level", 0xffffffff)
end
emu.frameadvance()
end