-- The Mafat Conspiracy - Sniping Hitbox Viewer
--
-- When in sniper mode:
-- 1. Draws the enemy's hitbox (red)
-- 2. Draws your effective targeting position after applying wind (cyan)
--
-- Tested with FCEUX 2.2.0
--
-- version 0.0:  first release

crosshairX = 125
crosshairY = 85

enemyHitboxOutlineColor = "#ff0000c0"
crosshairColor = "#00ffffc0"


-- TODO Is this right?  This is basically the first thing I found in RAM Search
-- that looked like it might work.  It seems to, anyway...
function isInSniperMode()
	return (memory.readbyte(0x03e) == 3)
end

function getEnemyHitbox()
	x = memory.readbyte(0x022e) - 16
	y = memory.readbyte(0x024e) - 16
	return {left = x - 8, right = x + 7, top = y - 8, bottom = y + 7}
end

function getGolgoX()
	return memory.readbyte(0x0220)
end

function getGolgoY()
	return memory.readbyte(0x0240)
end

function getWindComponent(magnitude, code)
	offset = magnitude + bit.band(code, 0x7f)
	if (code > 0x7f) then
		sign = -1
	elseif (code > 0) then
		sign = 1
	else
		sign = 0
	end
	-- +0x10 because I'm offended that rom.readbyte() doesn't skip the header.
	return sign * rom.readbyte(0xb1b2 + 0x10 + offset)
end

function getWindVector()
	directionFlag = memory.readbyte(0x008f)
	magnitude = memory.readbyte(0x0090)
	codes = {x = rom.readbyte(0xb1db + 0x10 + 2*directionFlag),
		y = rom.readbyte(0xb1dc + 0x10 + 2*directionFlag)}
	return {x = getWindComponent(magnitude, codes.x),
		y = getWindComponent(magnitude, codes.y)}
end


function hitboxToScreenX(x)
	return x - getGolgoX() + crosshairX
end

function hitboxToScreenY(y)
	return y - getGolgoY() + crosshairY
end


function drawEnemyHitbox()
	hitbox = getEnemyHitbox()
	gui.box(hitboxToScreenX(hitbox.left), hitboxToScreenY(hitbox.top),
		hitboxToScreenX(hitbox.right), hitboxToScreenY(hitbox.bottom),
		enemyHitboxOutlineColor)
end

function drawCrosshair()
	wind = getWindVector()
	x = crosshairX + wind.x
	y = crosshairY + wind.y
	gui.line(x - 2, y, x + 2, y, crosshairColor)
	gui.line(x, y - 2, x, y + 2, crosshairColor)
end


function draw()
	if isInSniperMode() then
		drawEnemyHitbox()
		drawCrosshair()
	end
end


gui.register(draw)
