Used in the submission http://tasvideos.org/4280S.html
-- Chrono Trigger (U) Info Display
-- Originally written by Dromiceius - Thanks!
-- =)
-- release 3
memory.usememorydomain("CARTROM")
local MONEY = 0x2c53
local TIME_FRAMES = 0x0400
local TIME_SECONDS = 0x0401
local TIME_MINUTES = 0x0402
local TIME_TENS_MINUTES = 0x0403
local TIME_HOURS = 0x0404
local CURRENT_HP = 0x2603 -- + 0x50 * char
local MAX_HP = 0x2605 -- + 0x50 * char
local CURRENT_MP = 0x2607 -- + 0x50 * char
local MAX_MP = 0x2609 -- + 0x50 * char
local LEVEL = 0x2612
local BATTLE_FLAG = 0x0117
local ENEMY_HP = 0x5fb0
local ENEMY_ATB = 0xafae
local CHAR1_ID = 0x2980
local CHAR2_ID = 0x2981
local CHAR3_ID = 0x2982
local RESERVE_CHAR1_ID = 0x2983
local RESERVE_CHAR2_ID = 0x2984
local RESERVE_CHAR3_ID = 0x2985
local RESERVE_CHAR4_ID = 0x2986
local RESERVE_CHAR5_ID = 0x2987
local RESERVE_CHAR6_ID = 0x2988
local CURRENT_SONG = 0x29AE
local SONG_NAMES = {"","Memories of Green","Wind Scene","Corridors of Time","Rhythm of Wind, Sky, and Earth","Ruined World","Guardia Millenial Fair","Far Off Promise","Secret of the Forest","Zeal Palace","Remains of Factory","Ayla's Theme","Courage and Pride","Lavos' Theme","Robo's Theme","Morning Sunlight","Manoria Cathedral","Sounds of the Ocean","Leene's Bell","Wings that Cross Time","Schala's Theme","Delightful Spekkio","A Shot of Crisis","Kingdom Trial","Chrono Trigger","Blackbird Interior","Blackbird Exterior","Fanfare 1","Fanfare 2","At the Bottom of the Night","Peaceful Day","A Strange Happening","Dungeon dripping noise","Running Water","The Hidden Truth","A Prayer to the Road that Leads","Huh?","The Day the World Revived","Robo Gang Johnny","Battle with Magus","Boss Battle 1","Frog's Theme","Goodnight","Bike Chase","People who Threw Away the Will to Live","Mystery of the Past","Underground Sewer","Presentiment","Undersea Palace","Last Battle","Lab 16's Ruins","Inside the Shell","Quake","Burn! Bobonga!","Wormhole","Primitive Mountain","World Revolution","Lavos Scream","Sealed Door","Silent Light","Fanfare 3","The Brink of Time","To Far Away Times","Confusing Melody","Hail Magus","Gonzales' Song","Underground River, Rain","Black Dream","Battle 1","Tyran Castle","Tsunami","Magus' Castle","First Festival of Stars","The Destruction of Zeal","Ocean Tide","Lavos' Breath","Epilogue - To Good Friends","Boss Battle 2","Fanfare 4","Determination","Battle 2","Singing Mountain"}
local JOIN_CHARS = 0x29AF
local ENEMY_NAME_LIST = 0x0C6500 -- Enemy names (11 bytes each), 251 strings
local ENEMY_ID = 0xAF02
-- B1BEC9CDC2CDBE = Reptite
-- 7EAF0D 01 FF Battle Enemy 03 original index 2008.07.17
-- etc.
function intToSring( c )
if c == 0xEF then
return ' '
end
if c == 0xE4 then
return '&'
end
if c < 0xBA then
return string.char(c - 0x5F)
else return string.char(c - 0x59)
end
end
local atbs_max = {0}
for i = 0, 7 do
atbs_max[i] = 18
end
function main()
drawBG()
displayTime()
if((mainmemory.readbyte(BATTLE_FLAG) % 2) == 0) then
party()
-- gui.drawText(4, 0xB5, string.format("Map: %3X %d",mainmemory.readbyte(MAP_ID) * 0x100 + mainmemory.readbyte(MAP_ID + 1),mainmemory.read_s16_le(0x172C)/3))
--gui.drawText(4, 0xB5, string.format("Map: %3d %d",mainmemory.readbyte(MAP_ID + 1),mainmemory.read_s16_le(0x172C)/3))
-- gui.drawText(4, 0xBD, string.format("X: %d\ny: %d", mainmemory.readbyte(X), mainmemory.readbyte(Y)))
else
battle()
end
end
function drawBG()
if (emu.framecount() < 238440) then
gui.drawImage('oldwin.png', 0, 0)
gui.drawImage('oldlongwin.png', 0, 80)
else
gui.drawImage('newwin.png', 0, 0)
gui.drawImage('newlongwin.png', 0, 80)
end
end
function drawShadowTextMono(x, y, str, size)
gui.drawText(x+1, y+1, str, 'black', size, 'Chrono Trigger Monospaced')
gui.drawText(x, y, str, 'white', size, 'Chrono Trigger Monospaced')
end
function drawShadowText(x, y, str, size)
gui.drawText(x+1, y+1, str, 'black', size, 'Chrono Trigger')
gui.drawText(x, y, str, 'white', size, 'Chrono Trigger')
end
function drawGrayText(x, y, str, size)
gui.drawText(x+1, y+1, str, 'black', size, 'Chrono Trigger')
gui.drawText(x, y, str, 'gray', size, 'Chrono Trigger')
end
function displayTime()
drawShadowText(5, 7,"Game Time:", 16)
drawShadowTextMono(52, 20, string.format("%01d:%02d:%05.2f",
mainmemory.read_u8(TIME_HOURS),
mainmemory.read_u8(TIME_TENS_MINUTES) * 10 + mainmemory.read_u8(TIME_MINUTES),
mainmemory.read_u8(TIME_SECONDS) + mainmemory.read_u8(TIME_FRAMES) / 60),
16
)
drawShadowText(5, 35, "Real Time:", 16)
drawShadowTextMono(52, 48, string.format("%01d:%02d:%05.2f",
(emu.framecount() + 1) / 216000,
(emu.framecount() + 1) % 216000 / 3600,
((emu.framecount() + 1) % 3600) / 60),
16
)
drawShadowText(5, 63, "Inputs:", 16)
inputs = movie.getinput(emu.framecount())
-- print('bouh')
-- for k,v in pairs(inputs) do
-- for kk,kv in pairs(v) do print(kk) end
-- end
buttons = {'P1 Up', 'P1 Left', 'P1 Right', 'P1 Down', 'P1 A', 'P1 B', 'P1 X', 'P1 Y', 'P1 L', 'P1 R', 'P1 Start', 'P1 Select'}
bdisp = {'u', 'l', 'r', 'd', 'A', 'B', 'X', 'Y', 'L', 'R', 'S', 's'}
xcoords = {48, 56, 60, 66, 74, 82, 90, 98, 106, 113, 121, 128}
for i = 1, 12 do
if inputs[buttons[i]] then
drawShadowText(xcoords[i], 63, bdisp[i], 16)
else
drawGrayText(xcoords[i], 63, bdisp[i], 16)
end
end
-- drawShadowText(5, 68, "Money:", 16)
-- drawShadowText(77, 83, string.format("%5d", mainmemory.read_u24_le(MONEY)), 16)
end
local char_icons = {'Crono - Save.gif', 'Marle - Save.gif', 'Lucca - Save.gif', 'Robo - Save.gif', 'Frog - Save.gif', 'Ayla - Save.gif'}
function party()
drawShadowText(37, 85, 'LV', 16)
drawShadowText(79, 85, 'HP', 16)
drawShadowText(109, 85, 'MP', 16)
charids = {mainmemory.read_u8(CHAR1_ID), mainmemory.read_u8(CHAR2_ID), mainmemory.read_u8(CHAR3_ID), mainmemory.read_u8(RESERVE_CHAR1_ID), mainmemory.read_u8(RESERVE_CHAR2_ID), mainmemory.read_u8(RESERVE_CHAR3_ID), mainmemory.read_u8(RESERVE_CHAR4_ID), mainmemory.read_u8(RESERVE_CHAR5_ID), mainmemory.read_u8(RESERVE_CHAR6_ID)}
pos = 0
for i = 1, 9 do
char = charids[i]
if (char < 0x06) then
hp = mainmemory.read_u16_le(CURRENT_HP+0x50*char)
maxhp = mainmemory.read_u16_le(MAX_HP+0x50*char)
mp = mainmemory.read_u16_le(CURRENT_MP+0x50*char)
maxmp = mainmemory.read_u16_le(MAX_MP+0x50*char)
level = mainmemory.read_u8(LEVEL+0x50*char)
gui.drawImage(char_icons[char+1], 7, 99 + 20*pos)
drawShadowTextMono(35, 102 + 20*pos,string.format("%2d",level), 16)
drawShadowTextMono(70, 102 + 20*pos,string.format("%3d",hp), 16)
drawShadowTextMono(110, 102 + 20*pos,string.format("%2d",mp), 16)
pos = pos + 1
end
end
end
function battle()
drawShadowText(5, 90, 'Enemy', 16)
drawShadowText(72, 90, 'ATB', 16)
drawShadowText(120, 90, 'HP', 16)
-- Display enemies information.
pos = 0
for i = 0, 7 do
local hps = mainmemory.read_u16_le(ENEMY_HP + i * 0x80)
local atb = mainmemory.read_u8(ENEMY_ATB + i)
local id = mainmemory.read_u8(ENEMY_ID + i)
if atbs_max[i] < atb then
atbs_max[i] = atb
end
-- if the enemy coords are invalid, it's probably because there's nothing to display
--Don't draw for invalid enemies
if (id ~= 0xFF) and (hps > 0) and (atb < 128) then
-- grab the enemy name and draw it
name = {}
for j = 0, 10 do
letter = memory.read_u8(ENEMY_NAME_LIST + id * 11 + j)
table.insert( name, intToSring( letter ))
end
namestring = table.concat( name, "" )
drawShadowText(5, 110 + 18 * pos, namestring, 16) -- enemy name
-- draw the HP and ATB meter.
drawShadowTextMono(78, 110 + 18 * pos, string.format("%2d",atb), 16) -- atb numeric
-- gui.drawBox(0x20, 0x50 + 4 * i - 2, 0x20 + 38, 0x50 + 4 * i + 2, 0xFF888888, 0x00000000) -- atb border
-- gui.drawBox(0x20 + 1, 0x50 + 4 * i - 1, 0x20 + barlen + 1, 0x50 + 4 * i, 0x00FFFFFF, 0xFFFFFFFF) -- atb bar
drawShadowTextMono(95, 110 + 18 * pos, string.format("%5d",hps), 16) -- hp
pos = pos + 1
else
-- if invalid enemy, reset maximum ATB size variable to common enemy value
atbs_max[i] = 18
end
end
end
while true do
main()
emu.frameadvance()
end