--Zelda II, hustle script
--Currently does way too many things. I'll figure out a better description.
--[[ Leeland Kirwan (FatRatKnight), 2014
Allows user input to "mix" with TAS Editor using XOR logic.
If Recording is checked, this script will do its intended job.
Tap a P1 key to toggle input. If "All" is selected, will use other player keys
for related player. If an individual player is selected, uses P1 controls. You
can hold down a key to affect multiple frames, toggling the key on each frame.
For reference, Superimpose uses OR logic, and does not allow user input to
clear stored input. A great inconvience for those wishing to use the keyboard
to toggle individual input rather than mouse.
]]--
local btnstr= {A = "A", B = "B", select= "S", start= "T",
up= "U", down= "D", left = "L", right= "R"}
local btnval= {A = 0x01, B = 0x02, select= 0x04, start= 0x08,
up= 0x10, down= 0x20, left = 0x40, right= 0x80}
local plval= {["1P"]= 1, ["2P"]= 2, ["3P"]= 3, ["4P"]= 4}
local OldJoy= {{},{},{},{}}
--*****************************************************************************
local function InputToggle()
--*****************************************************************************
--Needs readonly mode to work, but won't interfere too much otherwise.
--Toggles inputs recorded in TAS Editor.
if not taseditor.engaged() then return end -- Escape
taseditor.clearinputchanges() -- Guessing something horrible w/o this.
local frame= emu.framecount()
local plSel= plval[taseditor.getrecordermode()]
local plLow = plSel or 1 -- Get the for loop range!
local plHigh= plSel or 4 -- Hardcoded 4 doesn't appear harmful...
local P1joy= nil -- If one player, get P1.
if plSel then P1joy= joypad.getimmediate(1) end -- Otherwise, get all.
local changed= false -- Flag, so I don't interfere too much
local History= "" -- Information for TASer in History list
for pl= plLow, plHigh do
local pad= taseditor.getinput(frame,pl)
local joy= P1joy or joypad.getimmediate(pl) -- Pick out the joypad
local mask= 0 -- Convert messy table to numbers
for btn,pressed in pairs(joy) do
if pressed and not OldJoy[pl][btn] then
mask= bit.bor(mask,btnval[btn])
History= History .. pl .. btnstr[btn]
end
end
taseditor.submitinputchange(frame,pl,bit.bxor(pad,mask))
OldJoy[pl]= joy -- To avoid repeated triggers
changed= changed or (mask ~= 0) -- If the bitmask did something, apply!
end
if changed then taseditor.applyinputchanges(History) end
end
taseditor.registerauto(InputToggle)
--#############################################################################
--#############################################################################
--My own functions for number display. FCEUX default text isn't liked by me.
local Keys, LastKeys= {}, {}
local function UpdateKeys() LastKeys= Keys; Keys= input.get() end
local function Press(k) return Keys[k] and not LastKeys[k] end
--*****************************************************************************
local Draw= {}
--*****************************************************************************
--Coordinates is the top-left pixel of the 3x5 digit.
--Used for drawing compact, colored numbers.
local Px,Li= gui.pixel, gui.line
Draw[0]= function(x,y,c) -- ###
Li(x ,y ,x ,y+4,c)-- # #
Li(x+2,y ,x+2,y+4,c)-- # #
Px(x+1,y ,c) -- # #
Px(x+1,y+4,c) -- ###
end
Draw[1]= function(x,y,c) -- #
Li(x ,y+4,x+2,y+4,c)-- ##
Li(x+1,y ,x+1,y+3,c)-- #
Px(x ,y+1,c) -- #
end -- ###
Draw[2]= function(x,y,c) -- ###
Li(x ,y ,x+2,y ,c)-- #
Li(x ,y+3,x+2,y+1,c)-- ###
Li(x ,y+4,x+2,y+4,c)-- #
Px(x ,y+2,c) -- ###
Px(x+2,y+2,c)
end
Draw[3]= function(x,y,c) -- ###
Li(x ,y ,x+1,y ,c)-- #
Li(x ,y+2,x+1,y+2,c)-- ###
Li(x ,y+4,x+1,y+4,c)-- #
Li(x+2,y ,x+2,y+4,c)-- ###
end
Draw[4]= function(x,y,c) -- # #
Li(x ,y ,x ,y+2,c)-- # #
Li(x+2,y ,x+2,y+4,c)-- ###
Px(x+1,y+2,c) -- #
end -- #
Draw[5]= function(x,y,c) -- ###
Li(x ,y ,x+2,y ,c)-- #
Li(x ,y+1,x+2,y+3,c)-- ###
Li(x ,y+4,x+2,y+4,c)-- #
Px(x ,y+2,c) -- ###
Px(x+2,y+2,c)
end
Draw[6]= function(x,y,c) -- ###
Li(x ,y ,x+2,y ,c)-- #
Li(x ,y+1,x ,y+4,c)-- ###
Li(x+2,y+2,x+2,y+4,c)-- # #
Px(x+1,y+2,c) -- ###
Px(x+1,y+4,c)
end
-- ###
Draw[7]= function(x,y,c) -- #
Li(x ,y ,x+1,y ,c)-- ##
Li(x+2,y ,x+1,y+4,c)-- #
end -- #
Draw[8]= function(x,y,c) -- ###
Li(x ,y ,x ,y+4,c)-- # #
Li(x+2,y ,x+2,y+4,c)-- ###
Px(x+1,y ,c) -- # #
Px(x+1,y+2,c) -- ###
Px(x+1,y+4,c)
end
Draw[9]= function(x,y,c) -- ###
Li(x ,y ,x ,y+2,c)-- # #
Li(x+2,y ,x+2,y+3,c)-- ###
Li(x ,y+4,x+2,y+4,c)-- #
Px(x+1,y ,c) -- ###
Px(x+1,y+2,c)
end
Draw[10]=function(x,y,c) -- #
Li(x ,y+1,x ,y+4,c)-- # #
Li(x+2,y+1,x+2,y+4,c)-- # #
Px(x+1,y ,c) -- ###
Px(x+1,y+3,c) -- # #
end
Draw[11]=function(x,y,c) -- ##
Li(x ,y ,x ,y+4,c)-- # #
Li(x+1,y ,x+2,y+1,c)-- ##
Li(x+1,y+4,x+2,y+3,c)-- # #
Px(x+1,y+2,c) -- ##
end
Draw[12]=function(x,y,c) -- #
Li(x ,y+1,x ,y+3,c)-- # #
Li(x+1,y ,x+2,y+1,c)-- #
Li(x+1,y+4,x+2,y+3,c)-- # #
end -- #
Draw[13]=function(x,y,c) -- ##
Li(x ,y ,x ,y+4,c)-- # #
Li(x+2,y+1,x+2,y+3,c)-- # #
Px(x+1,y ,c) -- # #
Px(x+1,y+4,c) -- ##
end
Draw[14]=function(x,y,c) -- ###
Li(x ,y ,x ,y+4,c)-- #
Li(x+1,y ,x+2,y ,c)-- ##
Li(x+1,y+4,x+2,y+4,c)-- #
Px(x+1,y+2,c) -- ###
end
Draw[15]=function(x,y,c) -- ###
Li(x ,y ,x ,y+4,c)-- #
Li(x+1,y ,x+2,y ,c)-- ##
Px(x+1,y+2,c) -- #
end -- #
--*****************************************************************************
local function __DN_AnyBase(right, y, Number, c, bkgnd, div)
--*****************************************************************************
-- Works with any base from 2 to 16. Paints the input number.
-- Returns the x position where it would paint another digit.
-- It only works with integers. Rounds fractions toward zero.
if div < 2 then return end -- Prevents the function from never returning.
local Digit= {}
local Negative= false
if Number < 0 then
Number= -Number
Negative= true
end
Number= math.floor(Number)
c= c or "white"
bkgnd= bkgnd or "clear"
local i= 0
if Number < 1 then
Digit[1]= 0
i= 1
end
while (Number >= 1) do
i= i+1
Digit[i]= Number % div
Number= math.floor(Number/div)
end
if Negative then i= i+1 end
local x= right - i*4
gui.box(x+1, y-1, right+1, y+5,bkgnd,bkgnd)
i= 1
while Draw[Digit[i]] do
Draw[Digit[i]](right-2,y,c)
right= right-4
i=i+1
end
if Negative then
gui.line(right, y+2,right-2,y+2,c)
right= right-4
end
return right
end
--*****************************************************************************
local function DrawNum(right, y, Number, c, bkgnd)
--*****************************************************************************
-- Paints the input number as right-aligned. Decimal version.
return __DN_AnyBase(right, y, Number, c, bkgnd, 10)
end
--*****************************************************************************
local function DrawNumx(right, y, Number, c, bkgnd)
--*****************************************************************************
-- Paints the input number as right-aligned. Hexadecimal version.
return __DN_AnyBase(right, y, Number, c, bkgnd, 16)
end
--#############################################################################
--#############################################################################
--Renaming things to my desires
local R1u= memory.readbyte
local R1s= memory.readbytesigned
local R2u= memory.readword
local R2s= memory.readwordsigned
local R1U= rom.readbyte
--#############################################################################
--#############################################################################
--ASM mimic
--*****************************************************************************
local function ROR(A,c)
--*****************************************************************************
return math.floor(A/2)+c*0x80,A%2
end
--#############################################################################
--#############################################################################
--Debug registry
--*****************************************************************************
local function RNGResetCheck()
--*****************************************************************************
--
--May wish to confirm the bank, so that 8D5E == 8D 1A 05 (STA $051A)
if (R1u(0x8D5E) ~= 0x8D) or (R1u(0x8D5F) ~= 0x1A) or (R1u(0x8D60) ~= 0x05) then print("False hit"); return end
print(string.format("f%06d RNG Reset: r[2]=%3d gTimer=%2d",
emu.framecount(),
math.floor(R1u(0x051B)/2),
R1u(0x0500)
))
end
memory.registerexec(0x8D5E,RNGResetCheck)
--*****************************************************************************
local function DetectChange()
--*****************************************************************************
--For when the game shifts to another "world".
--Like going into a town or a palace, or a different part of the continent.
print("Changed at frame " .. emu.framecount())
end
--memory.registerwrite(0x0748,DetectChange)
--*****************************************************************************
local function FnHit()
--*****************************************************************************
print(string.format("%02X %02X %02X:%02X - Zone",
R1u(0x0706),
R1u(0x0707),
R1u(0x070A),
R1u(0x056C)
))
end
--memory.registerexec(0xCD40,FnHit)
--C2E6 is called every frame. Arr...
--CD40 is exclusive to "world" shifting. So, what calls it?
--#############################################################################
--#############################################################################
--Keyhook functions
--*****************************************************************************
local function PrintExits()
--*****************************************************************************
for i= 0, 0x3E do
print(string.format("%02X: %3d %3d . %3d %3d : %02X.%d %02X.%d %02X.%d %02X.%d",
i,
R1u(0x6A00+i),
R1u(0x6A3F+i),
R1u(0x6A7E+i),
R1u(0x6ABD+i),
math.floor(R1u(0x6AFC+i*4)/4),R1u(0x6AFC+i*4)%4,
math.floor(R1u(0x6AFD+i*4)/4),R1u(0x6AFD+i*4)%4,
math.floor(R1u(0x6AFE+i*4)/4),R1u(0x6AFE+i*4)%4,
math.floor(R1u(0x6AFF+i*4)/4),R1u(0x6AFF+i*4)%4
))
end
end
--#############################################################################
--#############################################################################
--RNG
--*****************************************************************************
local function Roll(T,count)
--*****************************************************************************
--Expects a table with at least two elements.
--T[1] should correspond to the RNG value at $051A.
--An optional count parameter for rolling more than once, as desired
for i= 1, (count or 1) do
local c= bit.band(0x02,bit.bxor(T[1],T[2]))/2
for b= 1, #T do
T[b],c= ROR(T[b],c)
end
end
end
local XYspawn= {
{5,0},{0,5},{5,10},{10,5}
}
--*****************************************************************************
local function PredictEncounter()
--*****************************************************************************
--Anticipates what secrets the next encounter holds.
local Timer= {
math.max((R1u(0x0516)-1)*21 + R1u(0x0500),0), --Global clock
(256 - R1u(0x0026))%256 --Spawn timer
}
for i= 1, 2 do
local X= 100 + 50*i
local t= Timer[i]
local R= {R1u(0x051A),R1u(0x051B),R1u(0x051C)}
Roll(R,t+1)
DrawNumx(X+10,9,R[2],"orange","black")
local PosOmit= R[3]%4
DrawNum(X,9,t,"cyan","black")
for pos= 1, 4 do
if (pos-1) ~= PosOmit then
local s= XYspawn[pos]
local x= X+s[1]
local y= 15+s[2]
gui.box(x,y,x+2,y+2,"black","white")
end
end
end
-- DrawNum(200, 9,v,"cyan","black")
-- DrawNum(200, 15,SpawnT,"orange","black")
end
--#############################################################################
--#############################################################################
--Main
local RoomsPosX= {[0]=190,200,200,210}
local RoomsPosY= {[0]= 12, 16, 9, 12}
local WorldExit= {[0]=0x00461F+0x10,0x0060FC+0x10,0x00861F+0x10}
--*****************************************************************************
local function StatusHUD()
--*****************************************************************************
--Player info. Magic, health, position, velocity, you know.
local v, clr
--Coordinates
DrawNum( 16, 9,R2s(0x004D,0x003B),"white","black")
DrawNumx(24, 9,R1u(0x03D6),"grey","black")
DrawNumx(36, 9,R1s(0x0070),"cyan","black")
DrawNum( 16, 15,R2s(0x0029,0x0019),"white","black")
DrawNumx(24, 15,R1u(0x03E6),"grey","black")
DrawNumx(36, 15,R1s(0x057D),"cyan","black")
--Rooms
v= R1u(0x0561)
DrawNumx(180, 9,v,"cyan","black")
v= 0x6AFC + v*4
for i= 0, 3 do
local X= RoomsPosX[i]
local Y= RoomsPosY[i]
local room= R1u(v+i)
if math.floor(room/4) == 0x3F then
DrawNum(X,Y,room%4,"black","white")
else
DrawNum(X,Y,room/4,"white","black")
end
end
--List of exits
v= R1u(0x0748)
DrawNumx(254,194,v,"orange","black")
v= WorldExit[R1u(0x0706)] + v
for i= 0, 3 do
local Y= 204+7*i
local CoordY= R1U(v+i)
local fClr, bClr= "white","black"
if CoordY == 0 then fClr,bClr= bClr,fClr end
DrawNum(254,Y,R1U(v+0x00+i)%128,fClr,bClr)
DrawNum(240,Y,R1U(v+0x3F+i)% 64,fClr,bClr)
end
--Attack
v= R1u(0x0777)
v= R1U(0x01E66C + 0x10 + v)
DrawNum( 8, 23,v,"orange","black")
--Magic
DrawNum( 44,28,math.floor((R1u(0x0773)+1)/2),"white","black")
v= R1u(0x070C)
if v ~= 0 then DrawNum( 44,34,v,"cyan","black") end
v= R1u(0x0749)*8 + R1u(0x0778) --Spell Selection and Magic Level
v= R1U(0x000D7A + 0x10 + v)/2 --Spell cost table
clr= "orange"
if bit.band(R1u(0x074A),0x04) ~= 0 then clr= "grey" end
DrawNum( 46,18,v,clr,"black")
DrawNum( 54,9,R1u(0x0749),"white","black")
DrawNum( 44,9,R1u(0x074A),"white","black")
--Life
DrawNum(116,28,math.floor((R1u(0x0774)+1)/2),"white","black")
v= R1u(0x070D)
if v ~= 0 then DrawNum(116,34,v,"cyan","black") end
--EXP
end
--*****************************************************************************
local function BoxHUD()
--*****************************************************************************
local CamX= R2u(0x072C,0x072A)
--Link
local AtkPow= R1U(0x01E66C + 0x10 + R1u(0x0777))
local LifeLv= R1u(0x0779)
local Life = R1u(0x0774)
local X= R2u(0x004D,0x003B) - CamX
local Y= R2u(0x0029,0x0019) - 0x100
gui.box(X,Y,X+3,Y+3)
--Baddies
for i= 0, 5 do
if R1u(0x00B6+i) == 1 then
X= R2u(0x004E+i,0x003C+i) - CamX
Y= R2u(0x002A+i,0x001A+i) - 0x100
-- gui.box(X,Y,X+3,Y+3,nil,"cyan")
local hits= math.ceil(R1u(0x00C2+i)/AtkPow)
DrawNum(X,Y,hits,"cyan","black")
local dmg= R1u(0x6DF9 + R1u(0x00A1+i))%8
dmg= R1U(0x01E2AE + 0x10 + dmg*8 + LifeLv)
DrawNum(X,Y+6,dmg/2,"orange","black")
end
end
--Projectiles
for i= 0, 5 do
if R1u(0x0087+i) ~= 0 then
X= R2u(0x0054+i,0x0042+i) - CamX
Y= R2u(0x0030+i,0x0020+i) - 0x100
local dmg= R1u(0x6D17 + R1u(0x0087+i))%8
dmg= R1U(0x01E2AE + 0x10 + dmg*8 + LifeLv)
DrawNum(X,Y,dmg/2,"orange","black")
end
end
--Sword beam
end
--*****************************************************************************
local DrawDir= {
--*****************************************************************************
[0x00]= function(x,y,c) --Down
gui.pixel(x ,y+1,c)
gui.pixel(x+1,y+2,c)
gui.pixel(x+2,y+1,c)
end,
[0x04]= function(x,y,c) --Right
gui.pixel(x+1,y ,c)
gui.pixel(x+2,y+1,c)
gui.pixel(x+1,y+2,c)
end,
[0x80]= function(x,y,c) --Up
gui.pixel(x+2,y+1,c)
gui.pixel(x+1,y ,c)
gui.pixel(x ,y+1,c)
end,
[0x84]= function(x,y,c) --Left
gui.pixel(x+1,y+2,c)
gui.pixel(x ,y+1,c)
gui.pixel(x+1,y ,c)
end
}
--*****************************************************************************
local function WorldHUD()
--*****************************************************************************
--Useful stuff
local CamX, CamY= R1u(0x00FD),R1u(0x007F)
local AreaTimer= R1u(0x0012)
local RNG= {}; for i= 1, 9 do RNG[i]= R1u(0x051A+i) end
--Coordinates
DrawNum( 13, 9,R1u(0x0073),"white","black")
DrawNum( 13, 15,R1u(0x0074),"white","black")
PredictEncounter()
--[[
--Spawn Prediction
local GlbTmr= R1u(0x0500)
local SpawnC= R1u(0x0516)
local SpawnT= 255-R1u(0x0026)
local v= math.max((SpawnC-1)*21 + GlbTmr,0)
DrawNum(200, 9,v,"cyan","black")
DrawNum(200, 15,SpawnT,"orange","black")
]]--
--Prediction Tables
local Directions= {}
Roll(RNG,(15-AreaTimer)%16+1)
Directions[1]= {unpack(RNG)}
for i= 2, 5 do
Roll(RNG,16)
Directions[i]= {unpack(RNG)}
end
--Enemies
for i= 0, 7 do
local ID= R1u(0x0082+i)
if ID ~= 0 then
local x,y= (R1u(0x004E+i)-CamX)%256, (R1u(0x002A+i)-CamY)%256
gui.box(x,y,x+4,y+4*#Directions,"black","black")
for Dir= 1, #Directions do
local clr= "orange"
if ID == 3 then clr= "green" end
if (AreaTimer+0x10*Dir)%0x100 < 0x40 then clr= "green" end
local Fn= DrawDir[bit.band(Directions[Dir][i+1],0x84)]
Fn(x+1,y+1+4*(Dir-1),clr)
-- DrawNumx(x,y+6*(Dir-1),bit.band(Directions[Dir][i+1],0x84),"white","black")
end
end
--[[
local Y= 26 + 6*i
DrawNumx(13,Y,R1u(0x002A+i),"white","black") --Y
DrawNumx(23,Y,R1u(0x004E+i),"white","black") --X
DrawNumx(33,Y,R1u(0x0082+i),"white","black") --ID
DrawNumx(43,Y,R1u(0x050E+i),"white","black") --Life time
DrawNumx(53,Y,R1u(0x051B+i),"white","black") --RNG address used
DrawNumx(63,Y,R1u(0x056D+i),"white","black") --
DrawNumx(73,Y,R1u(0x0575+i),"white","black")
]]--
end
end
--*****************************************************************************
local function BasicHUD()
--*****************************************************************************
UpdateKeys()
-- if Press("space") then PrintExits() end
local mode= R1u(0x0768)
DrawNumx(9,202,mode,"white","black")
if mode == 6 then
StatusHUD()
BoxHUD()
gui.text(2,210,"Side")
elseif mode == 0 then
WorldHUD()
gui.text(2,210,"World")
else
gui.text(2,210,"What?")
end
DrawNumx(254, 9,R1u(0x0706),"white","black")
DrawNumx(254, 15,R1u(0x0707),"white","black")
DrawNumx(254, 21,R1u(0x070A),"white","black")
DrawNumx(254, 27,R1u(0x056C),"white","black")
DrawNumx(254, 33,R1u(0x0748),"orange","black")
DrawNumx(254, 39,R1u(0x0561),"cyan","black")
DrawNumx(254, 45,R1u(0x0500),"white","black")
DrawNumx(254, 51,R1u(0x0012),"white","black")
DrawNumx(254, 57,R1u(0x0203),"green","black")
DrawNumx(254, 67,R1u(0x007F),"green","black")
DrawNumx(254, 73,R1u(0x00FD),"green","black")
--[[
local LifeLv= R1u(0x0779)
--Link
DrawNumx( 24,43,R2u(0x0029,0x0019),"cyan","black") --Y pos
DrawNumx( 40,43,R2u(0x004D,0x003B),"cyan","black") --X pos
DrawNumx( 50,43,R1u(0x03D6),"cyan","black") --X sub
DrawNumx( 60,43,R1u(0x03E6),"cyan","black") --Y ??
DrawNumx( 70,43,R1u(0x005F),"cyan","black") --Facing
DrawNumx( 80,43,R1u(0x0070),"cyan","black") --?
DrawNumx( 90,43,R1u(0x0080),"cyan","black") --?
--Baddie
for y= 0, 5 do
local Y= y*7+50
local clr= "grey"
local state= R1u(0x00B6+y)
if state ~= 0 then clr= "white" end
DrawNumx( 8,Y,R1u(0x00A1+y),clr,"black")
DrawNumx( 24,Y,R2u(0x002A+y,0x001A+y),clr,"black") --Y pos
DrawNumx( 40,Y,R2u(0x004E+y,0x003C+y),clr,"black") --X pos
DrawNumx( 50,Y,R1u(0x03D7+y),clr,"black") --X sub
DrawNumx( 60,Y,R1u(0x03E7+y),clr,"black") --Y ??
DrawNumx( 70,Y,R1u(0x0060+y),clr,"black") --Facing
DrawNumx( 80,Y,R1u(0x0071+y),clr,"black") --?
DrawNumx( 90,Y,R1u(0x0081+y),clr,"black") --?
DrawNumx(100,Y,R1u(0x00C2+y),clr,"black") --
DrawNumx(110,Y,R1u(0x00BC+y),clr,"black") --
DrawNumx(120,Y,state,clr,"black") --
-- DmgCalc
local v= R1u(0x00A1+y)
v= R1u(0x6DF9 + v)%8
v= R1U(0x01E2AE + 0x10 + v*8 + LifeLv)
DrawNum(134,Y,v/2,clr,"black")
end
--Projectile
for y= 0, 5 do
local Y= y*7+92
local clr= "orange"
-- local state= R1u(0x00B6+y)
-- if state ~= 0 then clr= "white" end
DrawNumx( 8,Y,R1u(0x0087+y),clr,"black")
DrawNumx( 24,Y,R2u(0x0030+y,0x0020+y),clr,"black") --Y pos
DrawNumx( 40,Y,R2u(0x0054+y,0x0042+y),clr,"black") --X pos
DrawNumx( 50,Y,R1u(0x03DD+y),clr,"black") --X sub
DrawNumx( 60,Y,R1u(0x03ED+y),clr,"black") --Y ??
DrawNumx( 70,Y,R1u(0x0066+y),clr,"black") --Facing
DrawNumx( 80,Y,R1u(0x0077+y),clr,"black") --?
-- DmgCalc
local v= R1u(0x0087+y)
v= R1u(0x6D17 + v)%8
v= R1U(0x01E2AE + 0x10 + v*8 + LifeLv)
DrawNum(134,Y,v/2,clr,"black")
end
]]--
--[[
for y= 0, 0x0F do
local Y= y*7+50
local clr= "white"
-- if R1u(0x0019 + y) == 0 then clr= "grey" end
DrawNumx(16,Y,R2u(0x0029+y,0x0019+y),clr,"black") --Y pos
DrawNumx(32,Y,R2u(0x004D+y,0x003B+y),clr,"black") --X pos
DrawNumx(42,Y,R1u(0x005F+y),clr,"black") --Facing
DrawNumx(52,Y,R1u(0x0070+y),clr,"black") --?
DrawNumx(62,Y,R1u(0x0080+y),clr,"black") --?
DrawNumx(72,Y,R1u(0x03D6+y),clr,"black") --X sub
DrawNumx(82,Y,R1u(0x03E6+y),clr,"black") --Y ??
DrawNumx(92,Y,R1u(0x00C1+y),clr,"black") --
DrawNumx(102,Y,R1u(0x00A0+y),clr,"black") --
end
]]--
end
gui.register(BasicHUD)
--for spell= 0, 7 do
-- local s= ""
-- for lv= 1, 8 do
-- if s ~= "" then s= s .. " " end
-- s= string.format("%s%3d",
-- s,
-- R1U(0x000D7A + 0x10 + spell*8 + lv)/2
-- )
-- end
-- print(s)
--end
--#############################################################################
--#############################################################################
--Immediate (That is, run-once code)
--for k,v in pairs(memory) do print(k) end
--*****************************************************************************
local function ExtractTable(addr)
--*****************************************************************************
for i= 0, 0x3E do
print(string.format("%02X: %d.%3d %d.%2d . %3d %3d : %02X.%d %02X.%d %02X.%d %02X.%d",
i,
math.floor(R1U(addr+0x0000+i)/128),R1U(addr+0x0000+i)%128,
math.floor(R1U(addr+0x003F+i)/ 64),R1U(addr+0x003F+i)%64,
math.floor(R1U(addr+0x007E+i)/ 1),
math.floor(R1U(addr+0x00BD+i)/ 1),
math.floor(R1U(addr+0x00FC+i*4)/4),R1U(addr+0x00FC+i*4)%4,
math.floor(R1U(addr+0x00FD+i*4)/4),R1U(addr+0x00FD+i*4)%4,
math.floor(R1U(addr+0x00FE+i*4)/4),R1U(addr+0x00FE+i*4)%4,
math.floor(R1U(addr+0x00FF+i*4)/4),R1U(addr+0x00FF+i*4)%4
))
end
end
--ExtractTable(0x0060FC + 0x10)
--*****************************************************************************
local function ScanFairies()
--*****************************************************************************
for r= 0, 127 do
print("==== " .. r)
RNG= {0xA5,r*2,0}
Roll(RNG,258)
for frame= 258, 500 do
if RNG[2] >= 0xFF then print(frame, frame%21) end
Roll(RNG)
end
end
print("done")
end
--ScanFairies()
--#############################################################################
--#############################################################################
-- Ugh, need this loop on the very bottom...
--*****************************************************************************
while true do
--*****************************************************************************
-- Exists to detect frame advances, and thus clear the OldJoy array.
for i= 1, 4 do OldJoy[i]= {} end -- Retrigger keys
-- Any code that needs this loop can go here.
emu.frameadvance()
end
--[[
00DE - ((important for spells to have this zero))
0487 - Timer for selection repetition
0501 - An array of something?
051A - RNG (9 bytes), looks like a standard shifting RNG.
0524 - ((important for spells to have this zero))
0564 - Magic (mirror)
0565 - Life (mirror)
057D - Vertical velocity
070D - Life restore
0743 - vertical related?
0744 - vertical related?
0749 - Spell selection
074A - Spell related
074C - (())
0768 - Mode?
0773 - Magic
0774 - Life
0775 - EXP (hi) ?
0776 - EXP (lo)
0777 - Attack level
0778 - Magic level
0779 - Life level
ROM locations do not include .nes header (+000010)
:000229[8] - 58 76 98 7A 38 74 B8 7C
:000231[7] - 00 05 04 06 07 08 0A List of terrain IDs
:000238[7] - 00 01 01 00 01 00 00 Short distance or long distance?
:00023F[7] - 00 20 18 18 20 09 03 Timer reset
:000246[7] - 00 0A 0A 18 18 30 30
:00024D[4][6] -
00 60 B0 D0 60 50 20 30 Grass
00 60 D0 F0 60 70 20 10 Desert
00 60 C0 E0 60 60 20 20 Forest
00 50 BB F0 50 6B 35 10 Swamp
00 57 D7 F8 57 80 21 08 Grave
00 57 D7 FF 57 80 28 01 Lava
:000265[4][4] - 01 02 01 01
01 01 01 02
02 01 02 01
01 03 01 03
:0002A3 - Function (call monster)
00:82BA(0002BA) - Call monsters (051C:RNG)
00:82D9 (051B:RNG)
00:8D5E(000D5E) - RNG stuff during load?
07:C182(01C182) - Begin RNG roll function
]]--