Just making an attempt at simplifying the code. I've actually stripped out a lot of its intelligence (
by rewriting the code from scratch, again) and making it as simple as I know how.
Use the mouse to move the display (
drag the display around).
Switch players with the Home key.
Insert a frame with Insert key.
Delete a frame with Delete key.
Toggle between "ignore stored input" and "mix user/stored input" modes with End key.
Show more or less frames with Numpad keys, specifically 1 3 7 or 9.
The script is compelled to block user input on undisplayed players. The script always allows user input on the currently displayed player, but may XOR it with the stored input or leave it untouched. The script shows a basic display of user input.
The script leaves the emulator's controls alone for individual players -- That is, the player 1 controls only affects player 1, player 2 controls affects player 2, and so forth. The reason being the emulator's implementation as of 2.1.4a actually locks me out from doing the proper modifications.
Specifically, "Boundary" lets me modify the joypad immediately, but "Before" lets me read the joypad immediately. Unfortunately, the order does not allow the immediate read prior to the immediate write, ergo, it is impossible to update player 2 controls using player 1 controls, without it being one frame late.
Download MtEdit.luaLanguage: lua
local PLAYERS = 2
local btn = {"right","left","down","up","start","select","B","A"} --Joypad
--#############################################################################
-- Keyboard Control mapping
local PlayerSwitch= "home"
local solid= "pageup" -- Make the display less
local clear= "pagedown" -- or more transparant.
local mp= "numpad7" --More past. Tweak display to see further back!
local lp= "numpad1" --Less past. You'll see less of the input stream.
local mf= "numpad3" --More future.
local lf= "numpad9" --Less future.
local AutoList= true
local Insert= "insert"
local Delete= "delete"
local AutoSwitch= "end"
--#############################################################################
-- Default values
local Opq= 1
local DispX, DispY= 50, 80
--#############################################################################
local PlSel= 1
local ThisJoypad= {}
local JoypadList= {}
local UserControl= {}
local ListControl= {}
for pl= 1, PLAYERS do
ThisJoypad[pl]= {}
JoypadList[pl]= {}
UserControl[pl]= "inv"
ListControl[pl]= true
end
local fc , Lastfc= 0 , 0
--*****************************************************************************
local function UpdateFC() Lastfc= fc; fc= movie.framecount() end
--*****************************************************************************
--*****************************************************************************
local function Within(V,l,h) return (V >= l) and (V <= h) end
local function Limits(V,l,h) return math.max(math.min(V,h),l) end
local function NullFN() return end
--*****************************************************************************
--#############################################################################
--#############################################################################
--Joypad
--*****************************************************************************
local function JoyToNum(Joys) -- Expects a table containing joypad buttons
--*****************************************************************************
-- Returns a number representing button presses.
-- These numbers are the primary storage for this version of this script.
local joynum= 0
for i= 1, #btn do
if Joys[btn[i]] then joynum= bit.bor(joynum, bit.lshift(1,i)) end
end
return joynum
end
--*****************************************************************************
local function ReadJoynum(Jn, button) -- Expects... Certain numbers!
--*****************************************************************************
-- Returns true or false. True if the indicated button is pressed
-- according to the input. False otherwise.
return ( bit.band(Jn , bit.lshift( 1, button )) ~= 0 )
end
--*****************************************************************************
local function LoadJoypad(pl)
--*****************************************************************************
-- Sets up the joypad to inject into the emulation.
local joys= JoypadList[pl][fc]
if ListControl[pl] then
for b= 1, #btn do
if joys and ReadJoynum(joys, b) then
ThisJoypad[pl][btn[b]]= (UserControl[pl] or true)
else
ThisJoypad[pl][btn[b]]= (UserControl[pl] and nil)
end
end
else
for b= 1, #btn do ThisJoypad[pl][btn[b]]= (UserControl[pl] and nil) end
end
--UserControl is "inv" or false. I abuse the shortcutting of or & and.
end
--*****************************************************************************
local function RegBoundaryHandleJoypad()
--*****************************************************************************
for pl= 1, PLAYERS do joypad.set(pl, ThisJoypad[pl]) end
end
--*****************************************************************************
local function RegAfterHandleJoypad()
--*****************************************************************************
for pl= 1, PLAYERS do
JoypadList[pl][Lastfc]= JoyToNum(joypad.get(pl))
LoadJoypad(pl)
end
end
--#############################################################################
--#############################################################################
--Display (Joypad)
--*****************************************************************************
local Draw= {}
--*****************************************************************************
function Draw.left(x,y,color) -- ##
gui.line(x+1,y ,x+2,y ,color) -- #
gui.line(x+1,y+2,x+2,y+2,color) -- ##
gui.pixel(x ,y+1,color)
end
function Draw.up(x,y,color) -- #
gui.line(x ,y+1,x ,y+2,color) -- # #
gui.line(x+2,y+1,x+2,y+2,color) -- # #
gui.pixel(x+1,y ,color)
end
function Draw.right(x,y,color) -- ##
gui.line(x ,y ,x+1,y ,color) -- #
gui.line(x ,y+2,x+1,y+2,color) -- ##
gui.pixel(x+2,y+1,color)
end
function Draw.down(x,y,color) -- # #
gui.line(x ,y ,x ,y+1,color) -- # #
gui.line(x+2,y ,x+2,y+1,color) -- #
gui.pixel(x+1,y+2,color)
end
function Draw.A(x,y,color) -- ###
gui.line(x ,y ,x ,y+2,color) -- ###
gui.line(x+1,y ,x+1,y+1,color) -- # #
gui.line(x+2,y ,x+2,y+2,color)
end
function Draw.B(x,y,color) -- # #
gui.line(x ,y ,x ,y+2,color) -- ##
gui.line(x+1,y+1,x+2,y+2,color) -- # #
gui.pixel(x+2,y ,color)
end
function Draw.start(x,y,color) -- #
gui.line(x+1,y ,x+1,y+2,color) -- ###
gui.pixel(x ,y+1,color) -- #
gui.pixel(x+2,y+1,color)
end
function Draw.select(x,y,color) -- ###
gui.line(x ,y ,x+2,y ,color) -- # #
gui.line(x ,y+2,x+2,y+2,color) -- ###
gui.pixel(x ,y+1,color)
gui.pixel(x+2,y+1,color)
end
Draw[0]= function(left, top, color) -- ###
gui.line(left ,top ,left ,top+4,color)-- # #
gui.line(left+2,top ,left+2,top+4,color)-- # #
gui.pixel(left+1,top ,color) -- # #
gui.pixel(left+1,top+4,color) -- ###
end
Draw[1]= function(left, top, color) -- #
gui.line(left ,top+4,left+2,top+4,color)-- ##
gui.line(left+1,top ,left+1,top+3,color)-- #
gui.pixel(left ,top+1,color) -- #
end -- ###
Draw[2]= function(left, top, color) -- ###
gui.line(left ,top ,left+2,top ,color)-- #
gui.line(left ,top+3,left+2,top+1,color)-- ###
gui.line(left ,top+4,left+2,top+4,color)-- #
gui.pixel(left ,top+2,color) -- ###
gui.pixel(left+2,top+2,color)
end
Draw[3]= function(left, top, color) -- ###
gui.line(left ,top ,left+1,top ,color)-- #
gui.line(left ,top+2,left+1,top+2,color)-- ###
gui.line(left ,top+4,left+1,top+4,color)-- #
gui.line(left+2,top ,left+2,top+4,color)-- ###
end
Draw[4]= function(left, top, color) -- # #
gui.line(left ,top ,left ,top+2,color)-- # #
gui.line(left+2,top ,left+2,top+4,color)-- ###
gui.pixel(left+1,top+2,color) -- #
end -- #
Draw[5]= function(left, top, color) -- ###
gui.line(left ,top ,left+2,top ,color)-- #
gui.line(left ,top+1,left+2,top+3,color)-- ###
gui.line(left ,top+4,left+2,top+4,color)-- #
gui.pixel(left ,top+2,color) -- ###
gui.pixel(left+2,top+2,color)
end
Draw[6]= function(left, top, color) -- ###
gui.line(left ,top ,left+2,top ,color)-- #
gui.line(left ,top+1,left ,top+4,color)-- ###
gui.line(left+2,top+2,left+2,top+4,color)-- # #
gui.pixel(left+1,top+2,color) -- ###
gui.pixel(left+1,top+4,color)
end
-- ###
Draw[7]= function(left, top, color) -- #
gui.line(left ,top ,left+1,top ,color)-- ##
gui.line(left+2,top ,left+1,top+4,color)-- #
end -- #
Draw[8]= function(left, top, color) -- ###
gui.line(left ,top ,left ,top+4,color)-- # #
gui.line(left+2,top ,left+2,top+4,color)-- ###
gui.pixel(left+1,top ,color) -- # #
gui.pixel(left+1,top+2,color) -- ###
gui.pixel(left+1,top+4,color)
end
Draw[9]= function(left, top, color) -- ###
gui.line(left ,top ,left ,top+2,color)-- # #
gui.line(left+2,top ,left+2,top+3,color)-- ###
gui.line(left ,top+4,left+2,top+4,color)-- #
gui.pixel(left+1,top ,color) -- ###
gui.pixel(left+1,top+2,color)
end
--*****************************************************************************
local function GetColor(Jn,b)
--*****************************************************************************
if not Jn then return "white" end --Does not exist
if not ReadJoynum(Jn,b) then return "red" end --Not pressed
return "green" --Button pressed
end
--*****************************************************************************
local function PaintFrame(x,y,Jn)
--*****************************************************************************
for b= 1, #btn do
Draw[btn[b]](x+4*b,y,GetColor(Jn,b))
end
end
--*****************************************************************************
local function PaintBorder(x,y)
--*****************************************************************************
local color= "green"
if not AutoList then color= -0x003FFF01 end
gui.line(x, y,x, y+4,color)
gui.line(x+2+4*#btn,y,x+2+4*#btn,y+4,color)
gui.pixel(x+1 ,y ,color)
gui.pixel(x+1 ,y+4,color)
gui.pixel(x+1+4*#btn,y ,color)
gui.pixel(x+1+4*#btn,y+4,color)
if PLAYERS > 1 then Draw[PlSel](x-4,y,color) end
end
local Past, Future= -5, 5
--*****************************************************************************
local function PaintJoypadList(x,y)
--*****************************************************************************
gui.box(x+3,y+4*Past-1,x+4*#btn+3,y+4*Future+3,0x00000080)
for i= Past, Future do
PaintFrame(x,y+4*i, JoypadList[PlSel][fc+i])
end
if Past <= 0 and Future >= 0 then
PaintBorder(x+2,y-1)
end
end
--#############################################################################
--#############################################################################
--User
local lastkeys, keys= input.get(), input.get()
--*****************************************************************************
local function UpdateKeys() lastkeys= keys; keys= input.get() end
local function Press(k) return keys[k] and (not lastkeys[k]) end
--*****************************************************************************
local KF= {}
--*****************************************************************************
local function KeyReader()
--*****************************************************************************
for k,v in pairs(keys) do
if (not lastkeys[k]) and KF[k] then KF[k]() end
end
end
local HandleMouse
--*****************************************************************************
local function HandleMouse_Main()
--*****************************************************************************
if keys.leftclick and lastkeys.leftclick then
DispX= DispX + keys.xmouse - lastkeys.xmouse
DispY= DispY + keys.ymouse - lastkeys.ymouse
end
end
--*****************************************************************************
local function HandleMouse_Option()
--*****************************************************************************
end
HandleMouse= HandleMouse_Main
local MaxRange= 54
-------------------------------------------------------------------------------
KF[solid]= function() Opq= math.min(Opq+0.125 , 1); gui.opacity(Opq) end
KF[clear]= function() Opq= math.max(Opq-0.125 , 0); gui.opacity(Opq) end
-------------------------------------------------------------------------------
KF[mp]=function() Past = Past -1; Future= math.min(Future,Past+MaxRange) end
KF[lp]=function() Past = Past +1; Future= math.max(Future,Past) end
KF[mf]=function() Future= Future+1; Past= math.max(Past,Future-MaxRange) end
KF[lf]=function() Future= Future-1; Past= math.min(Past,Future) end
local PlSwitch
--*****************************************************************************
local function PlSw()
--*****************************************************************************
for pl= 1, PLAYERS do
UserControl[pl]= false
ListControl[pl]= true
end
UserControl[PlSel]= "inv"
ListControl[PlSel]= AutoList
for pl= 1, PLAYERS do LoadJoypad(pl) end
end
PlSwitch= PlSw
PlSw()
-------------------------------------------------------------------------------
KF[PlayerSwitch]= function()
-------------------------------------------------------------------------------
PlSel= (PlSel%PLAYERS)+1
PlSwitch()
end
-------------------------------------------------------------------------------
KF[Insert]= function()
-------------------------------------------------------------------------------
local frame= fc
while JoypadList[PlSel][frame] do frame=frame+1 end
for i= frame, (fc+1), -1 do
JoypadList[PlSel][i]= JoypadList[PlSel][i-1]
end
JoypadList[PlSel][fc]= 0
LoadJoypad(PlSel)
end
-------------------------------------------------------------------------------
KF[Delete]= function()
-------------------------------------------------------------------------------
local i= fc
while JoypadList[PlSel][i] do
JoypadList[PlSel][i]= JoypadList[PlSel][i+1]
i=i+1
end
LoadJoypad(PlSel)
end
-------------------------------------------------------------------------------
KF[AutoSwitch]= function()
-------------------------------------------------------------------------------
AutoList= not AutoList
ListControl[PlSel]= AutoList
end
--#############################################################################
--#############################################################################
--Registry
--*****************************************************************************
local function RegisterAfter()
--*****************************************************************************
UpdateFC()
RegAfterHandleJoypad()
end
emu.registerafter(RegisterAfter)
--*****************************************************************************
local function RegisterGui()
--*****************************************************************************
UpdateKeys()
KeyReader()
HandleMouse()
DispX= Limits(DispX,-2,251-#btn*4)
DispY= Limits(DispY,1+-4*Past,220-4*Future)
PaintJoypadList(DispX, DispY)
gui.pixel(0,0,0)
end
gui.register(RegisterGui)
--*****************************************************************************
local function RegisterLoad()
--*****************************************************************************
UpdateFC()
for pl= 1, PLAYERS do LoadJoypad(pl) end
end
savestate.registerload(RegisterLoad)
--*****************************************************************************
while true do --Register boundary
--*****************************************************************************
RegBoundaryHandleJoypad()
emu.frameadvance()
end