-- Multitrack v2 for FCEUX by FatRatKnight --*************** local players= 2 -- You may tweak the number of players here. --*************** -- Rewind options local saveMax= 50 -- How many save states to keep? Set to 0 to disable local SaveBuf= 12 -- How many frames between saves? Don't use 0, ever. local rewind= "numpad0" -- What key do you wish to hit for rewind? --Keep in mind: Higher saveMax, more savestates, more memory needed. --Control local PlayerSwitch= "home" -- For selecting other players local opt= "end" -- For changing control options local key = {"right", "left", "down", "up", "L", "O", "J", "K"} local btn = {"right", "left", "down", "up", "start", "select", "B", "A"} --Try to avoid changing btn. You may reorder btn's stuff if you don't --like the default order, however. Line up with key for good reasons. --key is the actual keyboard control over the buttons. Change that! --Insertions and deletions local Insert= "insert" -- Inserts a frame at the frame you're at local Delete= "delete" -- Eliminates current frame --Display 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" --Control options by keyboard local OptUp= "numpad8" local OptDn= "numpad2" -- Controls for changing local OptRt= "numpad6" -- options by keyboard. local OptLf= "numpad4" local OptHit="numpad5" --Various colors I'm using. If you wish to bother, go ahead. local shade= 0x00000080 local white= "#FFFFFFFF" local red= "#FF2000FF" local green= 0x00FF00FF local blue= 0x0040FFFF local orange="#FFC000FF" --***************************************************************************** --Please do not change the following, unless you plan to change the code: local plmin , plmax= 1 , 1 local fc= movie.framecount() local LastLoad= movie.framecount() local saveCount= 0 local saveArray= {} local rewinding= false local InputList= {} local ThisInput= {} local BufInput= {} local BufLen= {} local TrueSwitch, FalseSwitch= {}, {} local ReadList= {} local ScriptEdit= {} for pl= 1, players do InputList[pl]= {} ThisInput[pl]= {} BufInput[pl]= {} BufLen[pl]= 0 TrueSwitch[pl]= {} FalseSwitch[pl]= {} ReadList[pl]= {} ScriptEdit[pl]= {} for i= 1, 8 do TrueSwitch[pl][i]= "inv" FalseSwitch[pl][i]= nil ReadList[pl][i]= true ScriptEdit[pl][i]= false end end --***************************************************************************** -- Just painting instructions here. print("Running Multitrack Script made by FatRatKnight.", "\r\nIts primary use is to preserve input after a loadstate.", "\r\nIt also gives precise control on changing this stored input.", "\r\nEdit the script if you need to change stuff. All options are near the top.", "\r\nThe script is currently set as follows:\r\n") print("Players:",players) if players > 1 then print("Player Switch key:",PlayerSwitch, "\r\nThere is an All Players view as well, beyond the last player.\r\n") else print("With only one player, the PlayerSwitch button is disabled.\r\n") end print("Maximum rewind states:",saveMax) local CalcSeconds= math.floor(saveMax*SaveBuf*100/60)/100 if saveMax > 0 then print("Frames between saves:",SaveBuf, "\r\nRewind key:",rewind, "\r\nThis can go backwards up to about",CalcSeconds,"seconds.", "\r\nRewind is a quick and easy way to back up just a few frames.", "\r\nJust hit",rewind,"and back you go!\r\n") else print("Rewind function is disabled. Cheap on memory!\r\n") end print("Hold >",opt,"< to view control options.", "\r\nYou may use the mouse or keyboard to toggle options.", "\r\nFor keyboard, use",OptUp,OptDn,OptRt,OptLf,"to choose an option and", OptHit,"to toggle the option.", "\r\nFor mouse, it's as simple at point and click.", "\r\nIf viewing All Players, changing options will affect all players.\r\n") print("For the frame display, you can drag it around with the mouse.", "\r\nTo move it by keyboard:",DispN,DispS,DispE,DispW, "\r\nTo change frames to display:",MoreFutr,LessFutr,MorePast,LessPast, "\r\nTo recenter display around current frame:",ResetFP, "\r\nLastly, hide it with >",clear,"< and show it with >",solid,"<\r\n") print("Insert frame:",Insert, "\r\nDelete frame:",Delete, "\r\nThese keys allow you to shift frames around the current frame.", "Perhaps you found an improvement to a segment and want to delete frames.", "Or this small trick you wanted to add requires shifting a few frames forward.", "These buttons let you shift frames around without forcing you to", "modify each and every one of them individually.\r\n") print("Script keys:", "\r\nJoy - Keyboard", "\r\n------------") for i= 1, 8 do print(btn[i],"-",key[i]) end print("By default, these are disabled. Enable them through the control options.", "\r\nThey are a one-tap joypad switch for precision control.", "\r\nIt will affect the currently displayed player, or all of them if", "it's displaying All Players.\r\n") print("If you want to \"load\" an fm2 into this script, run the play file", "while running this script. As the movie on read-only plays out, the", "script will pick up its input. The script does not need to start from", "frame 1 -- Load a state near the end of a movie if you so wish!", "Once input is loaded, you may continue whatever you were doing.\r\n") print("Remember, edit the script if you don't like the current options. All", "the options you should care about are near the top, clearly marked.", "Change the control keys through there, as well as number of players or rewind limits.", "\r\nThis script works with the joypad you actually set from FCEUX's config,", "and they can even cancel input stored in this script.", "\r\n\r\nAnd have fun with this script. I hope your experiments with this script goes well.", "\r\n\r\nLeeland Kirwan, the FatRatKnight.") print("Players:",players," - - ",CalcSeconds,"seconds of rewind.") --***************************************************************************** function FBoxOld(x1, y1, x2, y2, color) --***************************************************************************** -- Gets around FCEUX'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. 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 FCEUX'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.D0(left, top, color) FBoxOld(left ,top ,left+2,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) FBoxOld(left ,top+2,left+2,top+4,color) gui.line(left ,top ,left+2,top ,color) gui.pixel(left ,top+1,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) FBoxOld(left,top,left+2,top+4,color) gui.pixel(left+1,top+2,color) end function Draw.D9(left, top, color) FBoxOld(left ,top ,left+2,top+2,color) gui.line(left ,top+4,left+2,top+4,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 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 if Number < 1 then gui.box(right+1,top-1,right-2,top+5,bkgnd) Draw[0](right-2,top,color) right= right-4 end while (Number >= 1) do local digit= Number % 10 Number= math.floor(Number/10) gui.box(right+1,top-1,right-2,top+5,bkgnd) Draw[digit](right-2,top,color) right= right-4 end if Negative then gui.box(right+1,top-1,right-2,top+5,bkgnd) gui.line(right, top+2,right-2,top+2,color) right= right-4 end gui.line(right+1,top-1,right+1,top+5,bkgnd) 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 local keys, lastkeys= {}, {} --***************************************************************************** function press(button) -- Expects a key --***************************************************************************** -- Returns true or false. -- Generally, if keys is pressed, the next loop around will set lastkeys, -- and thus prevent returning true more than once if held. return (keys[button] and not lastkeys[button]) end local repeater= 0 --***************************************************************************** function pressrepeater(button) -- Expects a key --***************************************************************************** --DarkKobold & FatRatKnight -- Returns true or false. -- Acts much like press if you don't hold the key down. Once held long enough, -- it will repeatedly return true. -- Try not to call this function more than once per main loop, since I've only -- set one repeater variable. Inside a for loop is real bad. if keys[button] then if not lastkeys[button] or repeater >= 3 then return true else repeater = repeater + 1; end elseif lastkeys[button] then -- To allow more calls for other buttons repeater= 0 end; return false end --***************************************************************************** function JoyToNum(Joys) -- Expects a table containing joypad buttons --***************************************************************************** -- Returns a number from 0 to 255, representing button presses. -- These numbers are the primary storage for this version of this script. local joynum= 0 for i= 1, 8 do if Joys[btn[i]] then joynum= bit.bor(joynum, bit.rshift(0x100,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. -- Helper function return ( bit.band(input , bit.rshift( 0x100,button )) ~= 0 ) end --***************************************************************************** function RewindThis() --***************************************************************************** --DarkKobold & FatRatKnight; Original concept by Antony Lavelle if saveCount <= 0 then return false -- Failed to rewind else savestate.load(saveArray[saveCount]); saveCount = saveCount-1; end; return true -- Yay, rewind! end --***************************************************************************** function ShowOnePlayer(x,y,color,button,pl) --***************************************************************************** -- Displays an individual button. -- Helper function for DisplayInput. 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. x= x + (2*players + 1)*(button - 1) + 2*pl - 1 FBoxOld(x,y,x+1,y+2,color) end local DispX, DispY= 190, 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 pressrepeater(solid) then Opaque= Opaque + 1/8 end if pressrepeater(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 pressrepeater(LessFutr) then Future= Future-1 if Future < Past then Past= Future end end if pressrepeater(MoreFutr) then Future= Future+1 if Future > Past+53 then Past= Future-53 end end if pressrepeater(MorePast) then Past= Past-1 if Past < Future-53 then Future= Past+53 end end if pressrepeater(LessPast) then Past= Past+1 if Past > Future then Future= Past end end if press(ResetFP) then Past= -12; Future= 12 end -- Move the display around? if pressrepeater(DispS) then DispY= DispY+1 end if pressrepeater(DispW) then DispX= DispX-1 end if pressrepeater(DispE) then DispX= DispX+1 end if pressrepeater(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. --Are we showing all players or just one? local HighlightButton= ShowOnePlayer local width= 32 if plmin ~= plmax then HighlightButton= ShowManyPlayers width= 16*players + 8 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= blue for pl= plmin, plmax do local ThisFrame= InputList[pl][fc-BufLen[pl]] if BufLen[pl] > 0 then ThisFrame= BufInput[pl][1] end if ThisFrame ~= JoyToNum(ThisInput[pl]) then color= green end 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 if i < 0 then scanz= InputList[pl][fc+i] elseif i == 0 then scanz= JoyToNum(ThisInput[pl]) elseif i < BufLen[pl] then scanz= BufInput[pl][i+1] else scanz= InputList[pl][fc+i-BufLen[pl]] end for button= 1, 8 do local color if not scanz then color= white elseif ReadJoynum(scanz,button) then if (i > 0) and not (ReadList[pl][button]) then color= orange else color= green end else color= red end HighlightButton(DispX,Y,color,button,pl) end end end end --***************************************************************************** function SetInput() --***************************************************************************** -- Prepares ThisInput for joypad use. for pl= 1, players do local temp= InputList[pl][fc-BufLen[pl]] if BufLen[pl] > 0 then temp= BufInput[pl][1] end for i= 1, 8 do if temp and ReadJoynum(temp,i) and ReadList[pl][i] then ThisInput[pl][btn[i]]= TrueSwitch[pl][i] else ThisInput[pl][btn[i]]= FalseSwitch[pl][i] end end end end --***************************************************************************** function ApplyInput() --***************************************************************************** -- Shoves ThisInput into the actual emulator joypads. if movie.mode() ~= "playback" then for pl= 1, players do joypad.set(pl, ThisInput[pl]) end end end --***************************************************************************** function InputSnap() --***************************************************************************** -- Will shove the input list over. -- Might end up freezing for a moment if there's a few thousand frames to shift for pl= 1, players do if BufLen[pl] < 0 then -- Squish! local pointer= fc while InputList[pl][pointer] do InputList[pl][pointer]= InputList[pl][pointer-BufLen[pl]] pointer= pointer+1 end end if BufLen[pl] > 0 then -- Foom! local pointer= fc while InputList[pl][pointer] do pointer= pointer+1 end -- pointer is now looking at a null frame. -- Assume later frames are also null. while pointer > fc do pointer= pointer-1 InputList[pl][pointer+BufLen[pl]]= InputList[pl][pointer] end -- pointer should now match fc. -- Everything at fc and beyond should be moved over by BufLen. for i=0, BufLen[pl]-1 do InputList[pl][fc +i]= table.remove(BufInput[pl],1) end end BufLen[pl]= 0 -- If it ain't zero before, we want it zero now! end end local XStart, XDiff= 30, 25 local YStart, YDiff= 12, 15 local Status= { {},{},{},{} } local TargA= {FalseSwitch,TrueSwitch,ReadList,ScriptEdit} local TrueA= { nil , "inv" , true , true } local FalsA= { false , true , false , false } local BtnX, BtnY= 0, 0 local BasicText= { "Activate: Lets the joypad activate input.", "Remove: Allows the joypad to remove input.", "List: Should the script remember button presses?", "Keys: Allow the script-specific keys to work?"} local AdvText= { {"With both joypad options on, you have full control.", "Held buttons will toggle the script's stored input."}, -- 1 {"With this on-off set-up, auto-hold will not", "accidentally cancel input, such as from load state."}, -- 2 {"With this off-on set, you can use auto-hold to", "elegantly strip off unwanted input."}, -- 3 {"With both joypad options off, you ensure you can't", "accidentally change what's stored in the script."}, -- 4 {"List on: Script will apply input stored within.", "This is the whole point of the script, ya know."}, -- 5 {"List off: Stored input is ignored. A good idea if", "you don't want the script interfering."}, -- 6 {"Keys on: Script keys will toggle the button press", "for the current frame. Meant for precise edits."}, -- 7 {"Keys off: Script-specific keys are no longer a", "factor. Long-term control is meant for joypad!"}, -- 8 {"Apparently, you've selected 'All players'", "and they have different options set."}, -- 9 {"This is the 'All' button. Selecting this will set", "all 'Yes' or all 'No' for this particular option."} --10 } --***************************************************************************** function ControlOptions() --***************************************************************************** -- Lets the user make adjustments on the various controls of this script. -- The interface, apparently, is most of the work! -- Silly little graphics Draw.B( XStart + XDiff ,YStart,red) Draw.right(XStart + XDiff + 5,YStart,white) Draw.B( XStart + XDiff +10,YStart,green) Draw.B( XStart + XDiff*2 ,YStart,green) Draw.right(XStart + XDiff*2+ 5,YStart,white) Draw.B( XStart + XDiff*2+10,YStart,red) Draw.right(XStart + XDiff*3 ,YStart ,green) Draw.right(XStart + XDiff*3 ,YStart+4,green) Draw.left( XStart + XDiff*3+ 4,YStart ,green) Draw.left( XStart + XDiff*3+ 4,YStart+4,red) Draw.down( XStart + XDiff*3+ 8,YStart ,red) Draw.down( XStart + XDiff*3+ 8,YStart+4,green) gui.box(XStart+XDiff*4,YStart,XStart+XDiff*4+14,YStart+6,0,green) Draw.select(XStart+ XDiff*4+ 2,YStart+2,green) Draw.B( XStart + XDiff*4+ 6,YStart+2,green) Draw.A( XStart + XDiff*4+10,YStart+2,green) -- Button selection if (keys.xmouse ~= lastkeys.xmouse) or (keys.ymouse ~= lastkeys.ymouse) then BtnX= math.floor((keys.xmouse- XStart+4)/XDiff) BtnY= math.floor((keys.ymouse- YStart-6)/YDiff) else if press(OptUp) then BtnX= limits(BtnX ,1,4) BtnY= limits(BtnY-1,1,9) end if press(OptDn) then BtnX= limits(BtnX ,1,4) BtnY= limits(BtnY+1,1,9) end if press(OptRt) then BtnX= limits(BtnX+1,1,4) BtnY= limits(BtnY ,1,9) end if press(OptLf) then BtnX= limits(BtnX-1,1,4) BtnY= limits(BtnY ,1,9) end end --Did you punch something? if press("leftclick") or press(OptHit) then if within( BtnY , 1 , 9 ) then if within( BtnX , 1 , 4 ) then local LoopS, LoopF= 1, 8 if BtnY ~= 9 then LoopS, LoopF= BtnY, BtnY end local Target, TstT, TstF= TargA[BtnX], TrueA[BtnX], FalsA[BtnX] for pl= plmin, plmax do for Loop= LoopS, LoopF do if Target[plmax][LoopF] == TstT then Target[pl][Loop]= TstF else Target[pl][Loop]= TstT end end end end end end --Figure out the status for i= 1, 4 do for j= 1, 8 do Status[i][j]= TargA[i][plmin][j] local pl= plmin+1 while (pl <= plmax) do if Status[i][j] ~= TargA[i][pl][j] then Status[i][j]= "???" break end pl= pl+1 end if Status[i][j] == TrueA[i] then Status[i][j]= "Yes" elseif Status[i][j] == FalsA[i] then Status[i][j]= "No" end end end --Highlight button if within( BtnY , 1 , 9 ) then if within( BtnX , 1 , 4 ) then local LowX=BtnX*XDiff +XStart -4 local LowY=BtnY*YDiff +YStart -3 gui.box(LowX,LowY,LowX+XDiff-2,LowY+YDiff-2,blue,blue) --Handle text. Feels sort of hard-coded, however gui.text(1,160,BasicText[BtnX]) local adv if BtnY == 9 then adv= 10 elseif Status[BtnX][BtnY] == "???" then adv= 9 elseif within(BtnX,1,2) and ((Status[3-BtnX][BtnY] == "???")) then adv= 9 elseif within(BtnX,1,2) then adv= 1 if Status[2][BtnY] == "No" then adv= adv + 1 end if Status[1][BtnY] == "No" then adv= adv + 2 end else adv= 5 if BtnX == 4 then adv= adv+2 end if Status[BtnX][BtnY] == "No" then adv= adv+1 end end gui.text(1,175,AdvText[adv][1]) gui.text(1,183,AdvText[adv][2]) end end --Lines! for i= 1, 5 do local Xpos= XStart + XDiff*i -5 gui.line(Xpos,0,Xpos,YStart + YDiff*10-4,green) end for j= 1, 9 do local Ypos= YStart + YDiff*j -4 gui.line( 0, Ypos, XStart + XDiff*5-5, Ypos, green) end gui.line(XStart+XDiff-4, YStart + YDiff*10-4, XStart + XDiff*5-5, YStart + YDiff*10-4, green) --Button labels! for j= 1, 8 do local Ypos= YStart + YDiff*j gui.text( 1, Ypos, btn[j]) Draw[btn[j]](XStart + XDiff - 12, Ypos, green) for i= 1, 4 do gui.text(XStart + XDiff*i, Ypos, Status[i][j]) end end for i= 1, 4 do gui.text(XStart + XDiff*i, YStart + YDiff*9, "All") 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 if BufLen[pl] > 0 then table.remove(BufInput[pl],1) table.insert(BufInput[pl],InputList[pl][fc-1]) end InputList[pl][fc-1]= JoyToNum(joypad.get(pl)) end SetInput() end emu.registerbefore(CatchInput) --***************************************************************************** function OnLoad() --***************************************************************************** -- For use with registerload. It updates ThisInput so we're not stuck with -- junk being carried over when we load something. -- Also clears whatever rewind stuff is stored. InputSnap() fc= movie.framecount() LastLoad= fc saveCount= 0 SetInput() ApplyInput() -- Sanity versus unpaused stateload end savestate.registerload(OnLoad) --***************************************************************************** function ItIsYourTurn() --***************************************************************************** -- For use with gui.register. I need to catch input while paused! -- Needed for a half-decent interface. --Ensure things are nice, shall we? local fc_= movie.framecount() keys= input.get() if fc ~= fc_ then -- Sanity versus unusual jump (Reset cycle?) OnLoad() end --Process Rewind if saveMax > 0 then -- Don't process if Rewind is disabled if pressrepeater(rewind) or rewinding then rewinding= false if RewindThis() then InputSnap() movie.rerecordcounting(true) fc= movie.framecount() SetInput() if saveCount <= 1 then emu.pause() end end end end --Switch players on keypress if press(PlayerSwitch) then if plmin ~= plmax then plmax= 1 elseif plmin == players then plmin= 1 else plmin= plmin+1 plmax= plmax+1 end end --Display which player we're selecting. Upperleft corner seems good. if plmin == plmax then gui.text(1,2,plmin) gui.text(11,2,BufLen[plmin]) else gui.text(1,2,"A") end --Check if we want to see control options if keys[opt] then gui.opacity(1) ControlOptions() SetInput() --Otherwise, handle what we can see else --Inserts and deletes. --table functions don't work well on tables that don't connect from 1. if pressrepeater(Insert) then for pl= plmin, plmax do BufLen[pl]= BufLen[pl] + 1 if BufLen[pl] > 0 then table.insert(BufInput[pl],1,0) end end SetInput() end if pressrepeater(Delete) then for pl= plmin, plmax do if BufLen[pl] > 0 then table.remove(BufInput[pl],1) end BufLen[pl]= BufLen[pl] - 1 end SetInput() end --Script key handler for pl= plmin, plmax do for i= 1, 8 do if press(key[i]) and ScriptEdit[pl][i] then if ThisInput[pl][btn[i]] then ThisInput[pl][btn[i]]= FalseSwitch[pl][i] else ThisInput[pl][btn[i]]= TrueSwitch[pl][i] end end end end DisplayInput() end --Last bits of odds and ends ApplyInput() lastkeys= keys collectgarbage("collect") end gui.register(ItIsYourTurn) emu.pause() --***************************************************************************** while true do -- Main loop --***************************************************************************** -- Contains the saving part of the Rewind engine. -- Original by Antony Lavelle, added by DarkKobold, messed by FatRatKnight if saveMax > 0 then -- Don't process if Rewind is disabled if keys[rewind] and saveCount > 0 then rewinding= true elseif (fc - LastLoad)%SaveBuf == 0 then if saveCount >= saveMax then table.remove(saveArray,1) else saveCount= saveCount+1 end if saveArray[saveCount] == nil then saveArray[saveCount]= savestate.create(); end savestate.save(saveArray[saveCount]); movie.rerecordcounting(false) end end emu.frameadvance() end