--[[ Leeland Kirwan (FatRatKnight), 2013
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 z= "none"
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)
--#############################################################################
--#############################################################################
local R1u, R1s= memory.readbyte, memory.readbytesigned
--*****************************************************************************
local function R2u(a) return R1u(a) + R1u(a+1)*256 end
local function R2s(a) return R1u(a) + R1s(a+1)*256 end
--*****************************************************************************
local lastkeys, keys= input.get(), input.get()
--*****************************************************************************
local function UpdateKeys() lastkeys= keys; keys= input.get() end
--*****************************************************************************
local function Limits(V,l,h) return math.max(math.min(V,h),l) 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
local OC= {
[0]= "white",
"white",
"white",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"green",
"grey",
"grey",
"grey",
"grey",
"red",
"red",
"red",
"red",
"red",
"red",
"red",
"red",
"orange",
"orange",
"orange",
"yellow",
"yellow",
"yellow",
"yellow",
"yellow"
}
--[[
local cc,cn= 0,0
local WantedStr= {
[0]=0x9D,0xBA,0x02,0xA9,0x01,0x9D,0x36,0x03,
0x20,0xD6,0xB9,0xA9,0x80,0x9D,0x22,0x04}
--*****************************************************************************
local function EnemyCheck()
--*****************************************************************************
for i= 0, 15 do
if R1u(0xC000 + i) ~= WantedStr[i] then cn= cn+1; return end
end
cc= cc+1
end
memory.registerexec(0xC5E8,EnemyCheck)
]]--
--*****************************************************************************
local function RNGRead()
--*****************************************************************************
local rM, rS= R1u(0x005A), R1u(0x005B)*256 + R1u(0x005C)
gui.box(139,8,171,14,"blue")
gui.box(172,8,203,14,"black")
for i= 0, 15 do
local b= bit.band(1,bit.rshift(rS,i))
Draw[b](200-4*i,9,"white")
end
DrawNumx(202,16,rS,"white","black")
DrawNumx(170,16,rM,"white","black")
local b= bit.band(1,bit.bxor( bit.rshift(rM,3),bit.rshift(rM,6) ))
Draw[b](204,9,"grey")
end
--*****************************************************************************
local function ObjRadar(Factor) -- What factor to scale radar?
--*****************************************************************************
local CamX, CamY= R2u(0x004C), R2u(0x004E)
local OffX= math.floor((1-1/Factor)*128)
local OffY= math.floor((1-1/Factor)*100)
local count= 0
for i= 0, 0x1E do
if R1u(0x0317+i) ~= 0 then
count= count+1
gui.pixel(
math.floor((R1u(0x0200+i)+R1s(0x021F+i)*256-CamX)/Factor + OffX),
math.floor((R1u(0x025D+i)+R1s(0x027C+i)*256-CamY)/Factor + OffY),
OC[i]
)
end
end
-- DrawNum(90,12,count)
end
--*****************************************************************************
local function ObjCount()
--*****************************************************************************
local P, B, E, A, I, S= 0,0,0,0,0,0
for i= 0, 2 do
if R1u(0x0317+i) ~= 0 then
P= P+1
end
end
for i= 3, 10 do
if R1u(0x0317+i) ~= 0 then
B= B+1
end
end
for i= 11, 14 do
if R1u(0x0317+i) ~= 0 then
E= E+1
end
end
for i= 15, 22 do
if R1u(0x0317+i) ~= 0 then
A= A+1
end
end
for i= 23, 25 do
if R1u(0x0317+i) ~= 0 then
I= I+1
end
end
for i= 26, 30 do
if R1u(0x0317+i) ~= 0 then
S= S+1
end
end
gui.box(244,8,255,56,"black",0)
Draw[P](246,10,"white"); Draw[3](251,10,"white")
Draw[B](246,18,"white"); Draw[8](251,18,"white")
Draw[E](246,26,"white"); Draw[4](251,26,"white")
Draw[A](246,34,"white"); Draw[8](251,34,"white")
Draw[I](246,42,"white"); Draw[3](251,42,"white")
Draw[S](246,50,"white"); Draw[5](251,50,"white")
end
local DirX={
[0]= 0, 3, 6, 8, 11, 13, 14, 15,
16, 15, 14, 13, 11, 8, 6, 3,
0, -3, -6, -8,-11,-13,-14,-15,
-16,-15,-14,-13,-11, -8, -6, -3
}
local DirX2={
[0]= 0, 12, 24, 35, 45, 53, 59, 62,
64, 62, 59, 53, 45, 35, 24, 12,
0,-12,-24,-35,-45,-53,-59,-62,
-64,-62,-59,-53,-45,-35,-24,-12
}
--*****************************************************************************
local function DirPow(v)
--*****************************************************************************
return DirX[v], DirX[(v+8)%32]
end
-- 0 1 2 3 4 5 6 7 8
-- 0 3 6 8 11 13 14 15 16
--*****************************************************************************
local function Fn()
--*****************************************************************************
UpdateKeys()
--BlackBox, to see the dot radar better.
if keys.Z then gui.box(-1,7,256,200,"black",0) end
--BasicHUD
DrawNumx(254,226,R2u(0x005D),"white","black") -- Timer
DrawNumx( 20,196,R2u(0x00C6),"white","black") -- Fuel
DrawNumx( 40,196,R2u(0x00C8),"white","black") -- Weapon left
DrawNumx(254,188,R1u(0x0374),"white","black") -- Direction
-- DrawNum( 230, 10,R2u(0x004C),"white","black") -- Cam X
DrawNum( 20,189,R1u(0x0099),"white","black") -- Wall invincibility timer
--Position
local N= 1 - bit.band(R1u(0x0336),1)*2 --X
DrawNumx(254,196,(R1u(0x029B)+R1u(0x02BA)*256)*N,"white","black") --Vel
DrawNumx(228,196, R1u(0x0200)+R1u(0x021F)*256 ,"white","black") --Pos
DrawNumx(236,196, R1u(0x0197) ,"grey" ,"black") --Sub
N= -1 + bit.band(R1u(0x0355),1)*2 --Y
DrawNumx(254,204,(R1u(0x02D9)+R1u(0x02F8)*256)*N,"white","black") --Vel
DrawNumx(228,204, R1u(0x025D)+R1u(0x027C)*256 ,"white","black") --Pos
DrawNumx(236,204, R1u(0x023E) ,"grey" ,"black") --Sub
ObjRadar(3)
ObjCount()
--Tether
N= "green"
if R1u(0x0066) == 0 then N= "grey" end
DrawNumx(18, 9,R2u(0x0068),N,"black")
DrawNumx(18,16,R2u(0x006B),N,"black")
RNGRead()
-- DrawNum(20, 8,cc,"white","black")
-- DrawNum(20,16,cn,"white","black")
end
gui.register(Fn)
--*****************************************************************************
local function DumpStats()
--*****************************************************************************
for obj= 0, 0x1E do
local color= "white"
if R1u(0x0200+obj+0x1F*9) == 0 then color= "grey" end
for st= 0, 16 do
DrawNumx(9+st*10, 9+obj*7, R1u(0x0200+obj+st*0x1F),color,"black")
end
end
end
--gui.register(DumpStats)
--#############################################################################
--#############################################################################
-- 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
cc=0
cn=0
emu.frameadvance()
end