I had received a PM asking about this script. I have salvaged some scripts from my TASing computer. As I haven't managed to get my usual TASing stuff on this new computer, I didn't test out whether these scripts work as is. It will take a while before I can get things working well again.
I recall MtEdit was basically a somewhat simplified version of Multitrack2, so that I can make changes to it better, or something.
Regardless, here are two different scripts:
The first one is
Multitrack2
The second one is
MtEdit
Whether they work is currently unknown. So are their settings. I am copying these files here as is, as the pastey link certainly isn't working now, and any access is better than nothing.
Download Multitrack2.luaLanguage: lua
-- XOR Multitrack for Snes9x by FatRatKnight
-- It simply records all input and XORs it with the user's button presses.
-- Still a few problems, but things are definitely much smoother.
--***************
local players= 1 -- You may tweak the number of players here.
--***************
--Display
local PlayerSwitch= "home" -- For viewing other players
local ListSwitch= "end" -- Should the script use or ignore its own list?
local JoypadSwitch= "delete" -- Should we allow or deny your input?
local btn={"left","up","right","down","A","B","Y","X","L","R","start","select"}
--Try to avoid changing btn. You may reorder btn's stuff if you don't
--like the default order, however.
local solid= "pageup" -- Make the display less
local clear= "pagedown" -- or more transparant.
local DispN= "numpad8"
local DispS= "numpad2" -- For moving the
local DispE= "numpad6" -- display around.
local DispW= "numpad4"
local MoreFutr= "numpad3"
local LessFutr= "numpad1" -- These will determine
local MorePast= "numpad7" -- how many frames you
local LessPast= "numpad9" -- want to display.
local ResetFP= "numpad5"
--Various colors I'm using. If you wish to bother, go ahead.
local shade= 0x00000080
local white= 0xFFFFFFFF
local red= 0xFF0000FF
local green= 0x00FF00FF
local blue= 0x0040FFFF
local orange=0xFFC000FF
--*****************************************************************************
--Please do not change the following, unless you plan to change the code:
local plmin , plmax= 1 , 1
local fc= movie.framecount()
local InputList= {}
local OptionUseList= {}
local OptionUseJoypad= {}
local keys, lastkeys= {}, {}
for pl= 1, players do
InputList[pl]= {}
OptionUseList[pl]= true
OptionUseJoypad[pl]= true
end
--*****************************************************************************
print("Running Multitrack Script made by FatRatKnight.",
"\r\nIts primary use is to preserve input after a loadstate.",
"\r\nNot as functional as what I have in FCEUX, but this works.",
"\r\nThis assumes you're using frame advance, so unpaused playerswitching",
"will toggle through the players at a rapid pace.\r\n")
print(PlayerSwitch,"- Display another player's input")
print(ListSwitch, "- Toggle whether the script uses its list")
print(JoypadSwitch,"- Toggle whether the joypad input is used\r\n")
print(solid,"- Make display more opaque.")
print(clear,"- Fade the display a bit.")
print(DispN,DispS,DispE,DispW,"- Move the display.")
print(MoreFutr,LessFutr,MorePast,LessPast,"- Adjust how much the display shows")
print(ResetFP,"- Reset display around current frame\r\n")
print("When running this script, you'll see a bunch of symbols appear.",
"This basically says what the script has recorded so far.",
"As I can't accept input while paused, you'll need to hold the",
"option key down and hit frame advance.\r\n")
print("But the script has basic, useful functionality. It works as well as",
"well as I hoped. And remember, edit the script if you don't like some",
"of the controls. The options are near the top.\r\n")
print("Players:",players)
--*****************************************************************************
function FBoxOld(x1, y1, x2, y2, color)
--*****************************************************************************
-- Gets around Snes9x's problem of double-painting the corners.
-- The double-paint is visible with non-opaque drawing.
-- It acts like the old-style border-only box.
-- Slightly messes up when x2 or y2 are less than their counterparts.
if (x1 == x2) and (y1 == y2) then
gui.pixel(x1,y1,color)
elseif (x1 == x2) or (y1 == y2) then
gui.line(x1,y1,x2,y2,color)
else --(x1 ~= x2) and (y1 ~= y2)
gui.line(x1 ,y1 ,x2-1,y1 ,color) -- top
gui.line(x2 ,y1 ,x2 ,y2-1,color) -- right
gui.line(x1+1,y2 ,x2 ,y2 ,color) -- bottom
gui.line(x1 ,y1+1,x1 ,y2 ,color) -- left
end
end
--*****************************************************************************
function FakeBox(x1, y1, x2, y2, Fill, Border)
--*****************************************************************************
-- Gets around Snes9x's problem of double-painting the corners.
-- It acts like the new-style fill-and-border box.
if not Border then Border= Fill end
gui.box(x1,y1,x2,y2,Fill,0)
FBoxOld(x1,y1,x2,y2,Border)
end
--*****************************************************************************
local Draw= {} --Draw[button]( Left , Top , color )
--*****************************************************************************
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.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.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.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) -- ###
FBoxOld(x ,y ,x+2,y+2,color) -- # #
end -- ###
function Draw.A(x,y,color) -- ###
FBoxOld(x ,y ,x+2,y+1,color) -- ###
gui.pixel(x ,y+2,color) -- # #
gui.pixel(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.X(x,y,color)
gui.line(x ,y ,x+2,y+2,color) -- # #
gui.pixel(x ,y+2,color) -- #
gui.pixel(x+2,y ,color) -- # #
end
function Draw.Y(x,y,color)
gui.line(x+1,y+1,x+1,y+2,color) -- # #
gui.pixel(x ,y ,color) -- #
gui.pixel(x+2,y ,color) -- #
end
function Draw.L(x,y,color) -- #
gui.line(x ,y+2,x+2,y+2,color) -- #
gui.line(x ,y ,x ,y+1,color) -- ###
end
function Draw.R(x,y,color)
gui.line(x ,y ,x ,y+2,color) -- ##
gui.line(x+1,y ,x+1,y+1,color) -- ##
gui.pixel(x+2,y+2,color) -- # #
end
function Draw.D0(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
function Draw.D1(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
function Draw.D2(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
function Draw.D3(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
function Draw.D4(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
function Draw.D5(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
function Draw.D6(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
function Draw.D7(left, top, color)
gui.line(left ,top ,left+1,top ,color)
gui.line(left+2,top ,left+1,top+4,color)
end
function Draw.D8(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
function Draw.D9(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)
gui.pixel(left+2,top+3,color)
end
Draw[0],Draw[1],Draw[2],Draw[3],Draw[4]=Draw.D0,Draw.D1,Draw.D2,Draw.D3,Draw.D4
Draw[5],Draw[6],Draw[7],Draw[8],Draw[9]=Draw.D5,Draw.D6,Draw.D7,Draw.D8,Draw.D9
--*****************************************************************************
function DrawNum(right, top, Number, color, bkgnd)
--*****************************************************************************
-- Paints the input number as right-aligned.
-- Returns the x position where it would paint another digit.
-- It only works with integers. Rounds fractions toward zero.
local Digit= {}
local Negative= false
if Number < 0 then
Number= -Number
Negative= true
end
Number= math.floor(Number)
if not color then color= "white" end
if not bkgnd then bkgnd= "clear" end
local i= 0
if Number < 1 then
Digit[1]= 0
i= 1
end
while (Number >= 1) do
i= i+1
Digit[i]= Number % 10
Number= math.floor(Number/10)
end
if Negative then i= i+1 end
local left= right - i*4
FakeBox(left+1, top-1, right+1, top+5,bkgnd,bkgnd)
i= 1
while Draw[Digit[i]] do
Draw[Digit[i]](right-2,top,color)
right= right-4
i=i+1
end
if Negative then
gui.line(right, top+2,right-2,top+2,color)
right= right-4
end
return right
end
--*****************************************************************************
function limits( value , low , high ) -- Expects numbers
--*****************************************************************************
-- Returns value, low, or high. high is returned if value exceeds high,
-- and low is returned if value is beneath low.
return math.max(math.min(value,high),low)
end
--*****************************************************************************
function within( value , low , high ) -- Expects numbers
--*****************************************************************************
-- Returns true if value is between low and high. False otherwise.
return ( value >= low ) and ( value <= high )
end
--*****************************************************************************
function JoyToNum(Joys) -- Expects a table containing joypad buttons
--*****************************************************************************
-- Returns a number from 0 to 4095, representing button presses.
-- These numbers are the primary storage for this version of this script.
local joynum= 0
for i= 1, 12 do
if Joys[btn[i]] then
joynum= bit.bor(joynum, bit.rshift(0x1000,i))
end
end
return joynum
end
--*****************************************************************************
function ReadJoynum(input, button) -- Expects... Certain numbers!
--*****************************************************************************
-- Returns true or false. True if the indicated button is pressed
-- according to the input. False otherwise.
return ( bit.band(input , bit.rshift( 0x1000,button )) ~= 0 )
end
--*****************************************************************************
function ShowOnePlayer(x,y,color,button,pl)
--*****************************************************************************
-- Displays an individual button.
-- Helper function for DisplayInput. Called as HighlightButton
x= x + 4*button - 3
Draw[btn[button]](x,y,color)
end
--*****************************************************************************
function ShowManyPlayers(x,y,color,button,pl)
--*****************************************************************************
-- Displays an individual button. Uses 2x3 boxes instead of button graphics.
-- Helper function for DisplayInput. Called as HighlightButton
x= x + (players + 1)*(button - 1) + pl
gui.line(x,y,x,y+2,color)
end
local DispX, DispY= 160, 70
local Past, Future= -12, 20
local Opaque= 1
--*****************************************************************************
function DisplayOptions(width) -- Expects width calculated by DisplayInput
--*****************************************************************************
-- Returns true if Opaque is 0, as a signal to don't bother painting.
-- Separated from DisplayInput to make it clear which half is doing what.
-- Change opacity?
if keys[solid] then Opaque= Opaque + 1/8 end
if keys[clear] then Opaque= Opaque - 1/8 end
Opaque= limits(Opaque,0,1)
gui.opacity(Opaque)
if Opaque == 0 then return true end
-- Don't bother processing display if there's none to see.
-- How many frames to show?
if keys[LessFutr] then
Future= Future-1
if Future < Past then Past= Future end
end
if keys[MoreFutr] then
Future= Future+1
if Future > Past+53 then Past= Future-53 end
end
if keys[MorePast] then
Past= Past-1
if Past < Future-53 then Future= Past+53 end
end
if keys[LessPast] then
Past= Past+1
if Past > Future then Future= Past end
end
if keys[ResetFP] then Past= -12; Future= 12 end
-- Move the display around?
if keys[DispS] then DispY= DispY+1 end
if keys[DispW] then DispX= DispX-1 end
if keys[DispE] then DispX= DispX+1 end
if keys[DispN] then DispY= DispY-1 end
if keys["leftclick"] and lastkeys["leftclick"] then
DispX= DispX + keys.xmouse - lastkeys.xmouse
DispY= DispY + keys.ymouse - lastkeys.ymouse
end
DispX= limits(DispX,1,254-width)
DispY= limits(DispY,3-4*Past,218-4*Future)
return nil -- Signal to display the input
end
--*****************************************************************************
function DisplayInput()
--*****************************************************************************
-- Paints on the screen the current input stored within the script's list.
-- Rather a shoddy job at loadstate, however.
--Are we showing all players or just one?
local HighlightButton= ShowOnePlayer
local width= 48
if plmin ~= plmax then
HighlightButton= ShowManyPlayers
width= 12*players + 12
end
--For both setting options and asking if we should bother displaying ourselves
if DisplayOptions(width) then return end
--Display frame offsets we're looking at.
local RtDigit= DispX + width + 22
if RtDigit > 254 then RtDigit= DispX - 4 end
local TpDigit= DispY + 4*Past - 2
DrawNum(RtDigit,TpDigit,Past,white,shade)
if Future > Past+1 then
TpDigit= DispY + 4*Future
DrawNum(RtDigit,TpDigit,Future,white,shade)
end
--Show cute little box around current frame
if Past <= 0 and Future >= 0 then
local color= green
local temp= 0
for pl= plmin, plmax do
if OptionUseJoypad[pl] then
temp= temp+1
end
end
if temp == 0 then
color= red
elseif (plmin ~= plmax) and (temp ~= players) then
color= orange
end
FBoxOld(DispX-1,DispY-2,DispX+width+1,DispY+4,color)
end
--Finally, we get to show the actual buttons!
for i= Past, Future do
local Y= DispY + 4*i
if i < 0 then Y=Y-2
elseif i > 0 then Y=Y+2 end
gui.box(DispX,Y-1,DispX+width,Y+3,shade,shade)
for pl= plmin, plmax do
local scanz= InputList[pl][fc+i]
for button= 1, 12 do
local color
if not scanz then
color= white
elseif ReadJoynum(scanz,button) then
color= green
else
color= red
end
if (not OptionUseList[pl]) and i >= 0 then
color= bit.bor(color, 0xC080C000)
end
HighlightButton(DispX,Y,color,button,pl)
end
end
end
end
--*****************************************************************************
function SetInput()
--*****************************************************************************
-- Sets the joypads. It's smart, at long last!
for pl= 1, players do
local temp= InputList[pl][fc-1]
if temp and OptionUseList[pl] then
local ThisInput= {}
if OptionUseJoypad[pl] then
ThisInput= joypad.get(pl)
end
for i= 1, 12 do
if ReadJoynum(temp,i) then
ThisInput[btn[i]]= not ThisInput[btn[i]]
end
end
joypad.set(pl, ThisInput)
end
end
end
--*****************************************************************************
function CatchInput()
--*****************************************************************************
-- For use with registerbefore. It will get the input and paste it into
-- the input list.
fc= movie.framecount()
for pl= 1, players do
InputList[pl][fc-1]= JoyToNum(joypad.get(pl))
end
end
emu.registerbefore(CatchInput)
--*****************************************************************************
function ItIsYourTurn()
--*****************************************************************************
-- Rather stripped down from FCEUX version. Only has basic functionality.
-- Mainly just there to set options and controls now.
--Ensure things are nice, shall we?
fc= movie.framecount()
lastkeys= keys
keys= input.get()
--Switch players on keypress
if keys[PlayerSwitch] then
if plmin ~= plmax then
plmax= 1
elseif plmin == players then
plmin= 1
else
plmin= plmin+1
plmax= plmax+1
end
end
--Sets controller to pick either this script or the player.
if keys[ListSwitch] then
for pl= plmin, plmax do
OptionUseList[pl]= not OptionUseList[pl]
end
end
if keys[JoypadSwitch] then
for pl= plmin, plmax do
OptionUseJoypad[pl]= not OptionUseJoypad[pl]
end
end
--Display which player we're selecting. Upperleft corner seems good.
if plmin == plmax then
gui.text(1,2,plmin)
else
gui.text(1,2,"A")
end
SetInput()
collectgarbage("collect")
end
gui.register(DisplayInput)
emu.pause()
while true do
ItIsYourTurn()
emu.frameadvance()
end
Download MtEdit.luaLanguage: lua
local PLAYERS = 1
local btn={"left","up","right","down","A","B","Y","X","L","R","start","select"}
--#############################################################################
-- 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 rs= "numpad5" --Reset display
local AutoList= true
local Insert= "insert"
local Delete= "delete"
local AutoSwitch= "end"
local Pl1Switch= "numpad+"
--#############################################################################
-- Default values
local Opq= 1
local DispX, DispY= 50, 80
local Past, Future= -12, 12
local WatermarkInterval= 12
local Pl1Control= true
--Colors
local White =-0x00000001 --0xFFFFFFFF
local Red =-0x00DFFF01 --0xFF2000FF
local Green = 0x00FF00FF
local Orange=-0x007FFF01 --0xFF8000FF
--#############################################################################
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 JoypadGetAlternate(player)
--*****************************************************************************
if Pl1Control then return joypad.get(1) end
return joypad.get(player)
end
--*****************************************************************************
local function JoypadSetFCEUXStyle(player,inputs)
--*****************************************************************************
-- Snes9x has two values: Force on, force off.
-- FCEUX has four: Force on, force off, user passthrough, and user invert.
-- I need the four, but I can at least emulate the four from lua.
-- This is only possible because Snes9x can read+modify on the immediate frame.
local TempInput= JoypadGetAlternate(player)
for btn,val in pairs(inputs) do -- This skips nil; User passthrough
if not val then -- Lua-side false; Force off
TempInput[btn]= false
elseif type(val) == "string" then -- A string, eh? User invert
TempInput[btn]= not TempInput[btn]
else -- Assume what's left is true; Force on
TempInput[btn]= true
end
end
joypad.set(player, TempInput)
end
--*****************************************************************************
local function RegBoundaryHandleJoypad()
--*****************************************************************************
for pl= 1, PLAYERS do
JoypadSetFCEUXStyle(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
function Draw.X(x,y,color)
gui.line(x ,y ,x+2,y+2,color) -- # #
gui.pixel(x ,y+2,color) -- #
gui.pixel(x+2,y ,color) -- # #
end
function Draw.Y(x,y,color)
gui.line(x+1,y+1,x+1,y+2,color) -- # #
gui.pixel(x ,y ,color) -- #
gui.pixel(x+2,y ,color) -- #
end
function Draw.L(x,y,color) -- #
gui.line(x ,y+2,x+2,y+2,color) -- #
gui.line(x ,y ,x ,y+1,color) -- ###
end
function Draw.R(x,y,color)
gui.line(x ,y ,x ,y+2,color) -- ##
gui.line(x+1,y ,x+1,y+1,color) -- ##
gui.pixel(x+2,y+2,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 Neg(n)
if n >= 0x80000000 then n= n - 0xFFFFFFFF - 1 end
return n
end
local function Pos(n)
if n < 0 then n= n + 0xFFFFFFFF + 1 end
return n
end
--*****************************************************************************
local function GetColorBasic(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 GetColor(Frame,b)
--*****************************************************************************
local c= GetColorBasic(JoypadList[PlSel][Frame],b)
if Frame%WatermarkInterval == 0 then
c= bit.bor(Neg(Pos(bit.band(c, -0x03030400))*0.75),0xFF)
end
return c
end
--*****************************************************************************
local function PaintFrame(x,y,Frame)
--*****************************************************************************
for b= 1, #btn do
Draw[btn[b]](x+4*b,y,GetColor(Frame,b))
end
end
--*****************************************************************************
local function PaintBorder(x,y)
--*****************************************************************************
local color= Green
if not AutoList then color= Orange 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 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, 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()
--*****************************************************************************
-- No "run while paused" code version.
for k,v in pairs(keys) do
if 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
KF[rs]=function() Past, Future= -12, 12 end
-------------------------------------------------------------------------------
KF[Pl1Switch]= function() Pl1Control= not Pl1Control 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(); fc= fc-1 --Snes9x acts a tad off for the UpdateFC routine.
for pl= 1, PLAYERS do LoadJoypad(pl) end
end
savestate.registerload(RegisterLoad)
--*****************************************************************************
while true do --Register boundary
--*****************************************************************************
RegBoundaryHandleJoypad()
emu.frameadvance()
end