local inp_MouseUp= "i"
local inp_MouseDn= "k"
local inp_MouseLf= "j"
local inp_MouseRt= "l"
local cmd_SelectPlayer= "p"
local Tc= {
[0]= 0xFF2000, 0x00FF00,
0xFF8080, 0xA0FFA0,
0xC05040, 0x40C040,
0xFFFF00, 0xFFFF00
}
local function NullFN() end
GapVals= {top=0,bottom=0,left=0,right=0}
function RequestGap(side,value)
if not GapVals[side] then
error("Bad argument #1",2)
end
if type(value) ~= "number" then
error("Argument #2 must be number",2)
end
value= math.floor(value)
if value < 0 then value= value end
local LastGap= GapVals[side]
GapVals[side]= GapVals[side]+value
return LastGap
end
function ApplyGaps()
gui.top_gap( GapVals.top) ;GapVals.top =0
gui.bottom_gap(GapVals.bottom);GapVals.bottom=0
gui.right_gap( GapVals.right) ;GapVals.right =0
gui.left_gap( GapVals.left) ;GapVals.left =0
end
local KeyPress,KeyRelease= {},{}
local function RegisterKeyPress(key,fn)
local OldFn= KeyPress[key]
KeyPress[key]= fn
input.keyhook(key,type(fn or KeyRelease[key]) == "function")
return OldFn
end
local function RegisterKeyRelease(key,fn)
local OldFn= KeyRelease[key]
KeyRelease[key]= fn
input.keyhook(key,type(fn or KeyPress[key]) == "function")
return OldFn
end
local function AltKeyhook(s,t)
if KeyPress[s] and (t.last_rawval == 1) then
KeyPress[s](s,t)
elseif KeyRelease[s] and (t.last_rawval == 0) then
KeyRelease[s](s,t)
end
end
local PlSel= 0
local cPort= 1
local Ports= {input.port_type(1),input.port_type(2)}
local cf= movie.currentframe()
local ResX, ResY= 512,448
local MaxPlayers= {
gamepad =1,
gamepad16 =1,
multitap =4,
multitap16=4,
mouse =1,
superscope=1,
justifier =1,
justifiers=2,
none =0
}
local Immediate = {[0]=0,0,0,0,0,0,0,0}
local BtnState = {0,0}
local FrameList = {}
local SubframeList= {}
local ListRead = {}
for pl= 0, 7 do
FrameList[pl]= {}
SubframeList[pl]= {}
ListRead[pl]=0x000000FFFFFF
end
local TranslateIndex= {}
function TranslateIndex.gamepad(i) return bit.value(i) end
function TranslateIndex.mouse(i) return bit.value(i+16) end
function TranslateIndex.superscope(i) return 0 end
function TranslateIndex.justifier(i) return 0 end
function TranslateIndex.none(i) return 0 end
TranslateIndex.gamepad16 = TranslateIndex.gamepad
TranslateIndex.multitap = TranslateIndex.gamepad
TranslateIndex.multitap16= TranslateIndex.gamepad
TranslateIndex.justifiers= TranslateIndex.justifier
local function Dbmp7x7(n,clr)
local bitmap= gui.bitmap_new(7,7,true)
for i= 0, 48 do
local c= -1
if bit.extract(n,i) == 1 then c= clr end
gui.bitmap_pset(bitmap,
i%7,
math.floor(i/7),
c
)
end
return bitmap
end
local Icons7x7= {
[0]=0x0FBFE3C78FFBE,
0x1FFF98306CF1C,
0x1FF98638C73BE,
0x0FB3F079C33BE,
0x0C187FFECD9B3,
0x0FB1E07E0FFFF,
0x0FB1E77E0C1BE,
0x0186186183FFF,
0x0FB1E37D8F1BE,
0x10205EE7879BE,
0x18FFFFC78DF1C,
0x0FF1E37F8F1BF,
0x0FBF83060FFBE,
0x07D9E3C78D99F,
0x1FC1837E0C1FF,
0x00C1BF7E0FFFF,
0x000000FE00000,
0x020408FE20408,
0x060C1830F3343,
0x198CB4A484486,
0x0994A848894F6,
0x18DB3E3870408,
0x02041C38F9B63,
0x10383C3EF3840,
0x00439EF878381,
0x10F33C30F3343,
0x1FFF83060C183,
0x18F1BF7F8F1BF,
}
for x= 0, #Icons7x7 do
Icons7x7[x]= Dbmp7x7(Icons7x7[x],0xFFFFFF)
end
local EmptyIcon= gui.bitmap_new(7,7,true)
local BlankPad= gui.bitmap_new(127,7,true)
local PadIcons= {[0]=11,18,19,20,21,22,23,24,10,25,26,27, 0, 1, 2, 3}
for i= 0, 15 do
local IconIndex= PadIcons[i]
gui.bitmap_blit(
BlankPad, i*8,0,
Icons7x7[IconIndex],0 ,0, 7,7
)
PadIcons[i]= {}
for c= 0, #Tc do
PadIcons[i][c]= gui.bitmap_new(7,7,true,Tc[c])
gui.bitmap_blit(
PadIcons[i][c], 0,0,
Icons7x7[IconIndex],0,0, 7,7 , 0xFFFFFF
)
end
end
local BlankMouse= gui.bitmap_new(95,7,true)
gui.bitmap_blit(BlankMouse, 0,0 , Icons7x7[25],0,0, 7,7)
gui.bitmap_blit(BlankMouse,16,0 , Icons7x7[16],0,0, 7,7)
gui.bitmap_blit(BlankMouse,24,0 , Icons7x7[16],0,0, 7,7)
gui.bitmap_blit(BlankMouse,40,0 , Icons7x7[18],0,0, 7,7)
gui.bitmap_blit(BlankMouse,56,0 , Icons7x7[16],0,0, 7,7)
gui.bitmap_blit(BlankMouse,64,0 , Icons7x7[16],0,0, 7,7)
gui.bitmap_blit(BlankMouse,80,0 , Icons7x7[26],0,0, 7,7)
gui.bitmap_blit(BlankMouse,88,0 , Icons7x7[27],0,0, 7,7)
local MouseIcons= {}
for i= 0, 0xF do MouseIcons[i]= Icons7x7[i] end
MouseIcons[16]= PadIcons[ 9]
MouseIcons[17]= PadIcons[ 1]
MouseIcons[18]= PadIcons[10]
MouseIcons[19]= PadIcons[11]
MouseIcons[20]= gui.bitmap_new(7,7,true,0x00FFFF)
gui.bitmap_blit(MouseIcons[20],0,0 , Icons7x7[17],0,0, 7,7 , 0xFFFFFF)
MouseIcons[21]= gui.bitmap_new(7,7,true,0xFFFF00)
gui.bitmap_blit(MouseIcons[21],0,0 , Icons7x7[16],0,0, 7,7 , 0xFFFFFF)
local DisplayLength= 56
local DisplayOffset= math.floor(DisplayLength/2)
local DispList= gui.bitmap_new( 95,447,true)
local DispListEx=gui.bitmap_new(127,447,true)
local TempFrame= gui.bitmap_new(127, 7,true)
local MainList = nil
local MainListWidth= 0
local PortWidths= {
gamepad = 95,
gamepad16 =127,
multitap = 95,
multitap16=127,
mouse = 95,
[ 95]= DispList,
[127]= DispListEx
}
local function BlitGamepad(IN)
for i= 0, 15 do
local color= bit.extract(IN,i,i+16,i+32)
gui.bitmap_blit(
TempFrame,8*i,0,
PadIcons[i][color],0,0, 7,7
)
end
return TempFrame
end
local MouseTilePos= {[0]=0,40,80,88}
local function BlitMouse(IN)
gui.bitmap_blit(TempFrame,32,0, EmptyIcon,0,0, 7,7)
gui.bitmap_blit(TempFrame,72,0, EmptyIcon,0,0, 7,7)
for i= 0, 3 do
local color= bit.bor(
bit.extract(IN,i+16),
bit.extract(IN,nil,i+20),
bit.extract(IN,nil,nil,i+24)
)
gui.bitmap_blit(
TempFrame,MouseTilePos[i],0,
MouseIcons[i+16][color],0,0, 7,7
)
end
for i= 0, 1 do
local v= 8*i
local index= 20 + bit.extract(IN,7+v)
gui.bitmap_blit(
TempFrame, 8+40*i,0,
MouseIcons[index],0,0, 7,7
)
index= bit.extract(IN,4+v,5+v,6+v)
gui.bitmap_blit(
TempFrame,16+40*i,0,
MouseIcons[index],0,0, 7,7
)
index= bit.extract(IN,v,1+v,2+v,3+v)
gui.bitmap_blit(
TempFrame,24+40*i,0,
MouseIcons[index],0,0, 7,7
)
end
return TempFrame
end
local BlitFn
local BlankFr
local function ChooseList(PortType)
MainListWidth= PortWidths[PortType]
if MainListWidth then
MainList= PortWidths[MainListWidth]
if PortType == "mouse" then
BlitFn= BlitMouse
BlankFr= BlankMouse
else
BlitFn= BlitGamepad
BlankFr= BlankPad
end
return
end
MainListWidth= 0
MainList= nil
end
local function MakeListFrame(i,frame)
local IN= FrameList[PlSel][frame]
local Frame= BlankFr
if IN then Frame= BlitFn(IN) end
gui.bitmap_blit(
MainList,0,i*8 ,
Frame, 0,0 , MainListWidth,7
)
end
local function MakeListFromScratch()
if not MainList then return end
for i= 0, DisplayLength-1 do
MakeListFrame(i, cf - DisplayOffset + i)
end
end
local function AdvanceList()
if not MainList then return end
gui.bitmap_blit(
MainList,0,0,
MainList,0,8, MainListWidth,DisplayLength*8-9
)
MakeListFrame(
DisplayLength - 1,
cf - DisplayOffset + DisplayLength
)
MakeListFrame(
DisplayOffset - 1,
cf
)
end
local ReadListColors= {
[0]= 0xFF0000,
0xFFFFFF,
0x0000FF,
0x00FF00
}
local MovieReadDots= {}
function MovieReadDots.GetColor(i)
return ReadListColors[bit.extract(ListRead[PlSel],i,i+24)]
end
function MovieReadDots.gamepad(X)
for i= 0, 11 do
local x= X + i*8 + 4
gui.circle(x,ResY+4,4,0,0,MovieReadDots.GetColor(i))
end
end
MovieReadDots.multitap= MovieReadDots.gamepad
function MovieReadDots.gamepad16(X)
for i= 0, 15 do
local x= X + i*8 + 4
gui.circle(x,ResY+4,4,0,0,MovieReadDots.GetColor(i))
end
end
MovieReadDots.multitap16= MovieReadDots.gamepad16
function MovieReadDots.mouse(X)
gui.rectangle(X+ 1,ResY,31,7,0,0,MovieReadDots.GetColor(16))
gui.rectangle(X+ 41,ResY,31,7,0,0,MovieReadDots.GetColor(17))
gui.circle( X+ 84,ResY+4,4 ,0,0,MovieReadDots.GetColor(18))
gui.circle( X+ 92,ResY+4,4 ,0,0,MovieReadDots.GetColor(19))
end
local function ShowList()
if not MainList then return end
local X= RequestGap("left",MainListWidth+2)
local Y= DisplayOffset*8-1
gui.rectangle(X-MainListWidth-2,Y,MainListWidth+2,9, 1,0x00FFFF,0)
gui.bitmap_draw(- X - MainListWidth - 1,0,MainList)
MovieReadDots[Ports[cPort]](X - MainListWidth - 2)
end
local function LGui()
ShowList()
end
local x_off= {[0]=48,40,24,32, 8, 8, 0,16,56,48, 0,56,16,24,32,40}
local y_off= {[0]=16, 8, 8, 8, 0,16, 8, 8, 8, 0, 0, 0,16,16,16,16}
local function DrawPad(x,y,IN)
for i= 0, 11 do
local color= bit.extract(IN,i)
gui.bitmap_draw(x+x_off[i],y+y_off[i],PadIcons[i][color])
end
end
local function DrawPad16(x,y,IN)
for i= 0, 15 do
local color= bit.extract(IN,i)
gui.bitmap_draw(x+x_off[i],y+y_off[i],PadIcons[i][color])
end
end
local m_sign= {[0]="+","-"}
local m_XY= {[0]="X","Y"}
local function DrawMouse(x,y,IN)
gui.bitmap_draw(x+16,y,MouseIcons[18][bit.extract(IN,18)])
gui.bitmap_draw(x+40,y,MouseIcons[19][bit.extract(IN,19)])
for i=0,1 do
local b= 8*i
gui.text(x+32*i,y+8,string.format("%s%s%2X",
m_XY[i],
m_sign[bit.extract(IN,b+7)],
bit.band(bit.lrshift(IN,b),0x7F)
))
end
end
local DrawController= {}
function DrawController.gamepad(x,y,port)
DrawPad(x,y,Immediate[port*4])
end
function DrawController.gamepad16(x,y,port)
DrawPad16(x,y,Immediate[port*4])
end
function DrawController.multitap(x,y,port)
local P= port*4
for pl= 0,3 do DrawPad(x+pl*64,y,Immediate[pl+P]) end
end
function DrawController.multitap16(x,y,port)
local P= port*4
for pl= 0,3 do DrawPad16(x+pl*64,y,Immediate[pl+P]) end
end
function DrawController.mouse(x,y,port)
DrawMouse(x,y,Immediate[port*4])
end
function DrawController.superscope(x,y,port)
gui.text(x,y,"Not supported!",0xFF2000)
end
function DrawController.justifier(x,y,port)
gui.text(x,y,"Not supported!",0xFF2000)
end
function DrawController.justifiers(x,y,port)
gui.text(x,y,"Not supported!",0xFF2000)
end
function DrawController.none(x,y,port)
gui.text(x,y,"No Controller",0xFFFF00)
end
local function BGui()
local Y= ResY+RequestGap("bottom",25)
local x= PlSel*64
gui.rectangle(x,Y,63,25,0x000080,0x000080)
DrawController[Ports[1]]( 0,Y+1,0)
DrawController[Ports[2]](256,Y+1,1)
end
local MarkController= {}
function MarkController.gamepad(pl)
Immediate[pl]= bit.bor(
bit.band(Immediate[pl],0x00000000FFFF),0x0000FFFF0000
)
end
MarkController.gamepad16 = MarkController.gamepad
MarkController.multitap = MarkController.gamepad
MarkController.multitap16= MarkController.gamepad
function MarkController.mouse(pl)
Immediate[pl]= bit.bor(
bit.band(Immediate[pl],0x0000000FFFFF),0x000000F00000
)
end
MarkController.superscope= NullFN
MarkController.justifier = NullFN
MarkController.justifiers= NullFN
MarkController.none = NullFN
local function MarkImmediate()
for port= 1, 2 do
local pl= (port-1)*4
for p= 0, 3 do
MarkController[Ports[port]](pl+p)
end
end
end
local function SaveImmediate(frame)
for port= 1, 2 do
local n= MaxPlayers[Ports[cPort]]-1
local pl= (port-1)*4
for p= 0, n do
FrameList[pl+p][frame]= Immediate[pl+p]
end
end
end
local function LoadImmediate(frame)
for pl= 0, 7 do
local temp= FrameList[pl][frame] or 0
temp= bit.bor(
bit.band( temp , ListRead[pl] ),
bit.band(bit.bnot(temp),bit.lrshift(ListRead[pl],24))
)
Immediate[pl]= temp
end
Immediate[PlSel]= bit.bxor(Immediate[PlSel],BtnState[cPort])
end
RegisterKeyPress(cmd_SelectPlayer,function(s,t)
PlSel= (PlSel+1)%8
cPort= math.floor(PlSel/4)+1
if PlSel%4 >= MaxPlayers[Ports[cPort]] then
if (cPort == 1) and (Ports[cPort] ~= "none") then
PlSel= 4; cPort= 2
else
PlSel= 0; cPort= 1
end
end
ChooseList(Ports[cPort])
MakeListFromScratch()
gui.repaint()
end)
local Ptype= {gamepad=1, gamepad16=1, multitap=1, multitap16=1,
mouse=2, superscope=3, justifier=4, justifiers=4, none=0}
function on_button(p,c,i,t)
if p == 0 then return end
if t == "analog" then return end
if (t == "hold") or (t == "type") then input.veto_button() end
if (c ~= 0) then return end
if (cPort ~= p) and (Ptype[Ports[1]] ~= Ptype[Ports[2]]) then return end
local bitval= TranslateIndex[Ports[p]](i)
if (t == "hold") or (t == "unhold") then
local temp= ListRead[PlSel]
temp= bit.bxor(temp,bitval)
bitval= bit.band(bitval,temp)
ListRead[PlSel]= bit.bxor(temp,bit.lshift(bitval,24))
gui.repaint()
elseif (t == "type") or (t == "untype") then
Immediate[PlSel]= bit.bxor(Immediate[PlSel],bitval)
gui.repaint()
elseif (t == "press") == (bit.band(BtnState[cPort],bitval) == 0) then
Immediate[PlSel]= bit.bxor(Immediate[PlSel],bitval)
BtnState[cPort]= bit.bxor(BtnState[cPort] ,bitval)
gui.repaint()
end
end
local InjectInput= {}
function InjectInput.gamepad(port)
local IN= Immediate[(port-1)*4]
for i= 0, 11 do
input.set2(port,0,i,bit.extract(IN,i))
end
end
function InjectInput.gamepad16(port)
local IN= Immediate[(port-1)*4]
for i= 0, 15 do
input.set2(port,0,i,bit.extract(IN,i))
end
end
function InjectInput.multitap(port)
for c= 0, 3 do
local IN= Immediate[(port-1)*4 + c]
for i= 0, 11 do
input.set2(port,c,i,bit.extract(IN,i))
end
end
end
function InjectInput.multitap16(port)
for c= 0, 3 do
local IN= Immediate[(port-1)*4 + c]
for i= 0, 15 do
input.set2(port,c,i,bit.extract(IN,i))
end
end
end
function InjectInput.mouse(port)
local IN= Immediate[(port-1)*4]
for i= 0, 1 do
local b= i*8
local val= bit.band(bit.lrshift(IN,b),0x7F)
if bit.extract(IN,b+7) ~= 0 then val= -val end
input.set2(port,0,i,val)
end
input.set2(port,0,2,bit.extract(IN,18))
input.set2(port,0,3,bit.extract(IN,19))
end
InjectInput.superscope= NullFN
InjectInput.justifier= NullFN
InjectInput.justifiers= NullFN
InjectInput.none= NullFN
function on_input(subframe)
for port= 1, 2 do
InjectInput[Ports[port]](port)
end
if not subframe then MarkImmediate() end
end
local IndexOffsets= {
gamepad = 16, gamepad16 = 16, multitap = 16, multitap16= 16,
mouse = 4, superscope= 0, justifier = 0, justifiers= 0,
none = 0
}
local HandleAnalog= {}
function HandleAnalog.mouse(pl,i,v)
v= math.max(-127,math.min(127,v))
if v < 0 then v= bit.bor(-v,0x80) end
local mask= bit.bnot(bit.lshift(0xFF,i*8))
Immediate[pl]= bit.bor(
bit.band(Immediate[pl],mask),
bit.lshift(v,i*8)
)
end
HandleAnalog.superscope= NullFN
HandleAnalog.justifier = NullFN
HandleAnalog.justifiers= NullFN
HandleAnalog.gamepad = NullFN
HandleAnalog.gamepad16 = NullFN
HandleAnalog.multitap = NullFN
HandleAnalog.multitap16= NullFN
HandleAnalog.none = NullFN
function on_snoop2(p,c,i,v)
if p == 0 then return end
local PortType= Ports[p]
local bitval= TranslateIndex[PortType](i)
local offset= IndexOffsets[PortType]
local pl= (p-1)*4+c
local bitset= 0; if (v ~= 0) then bitset= 1 end
local temp= Immediate[pl]
local temp2= bit.lshift(bitval,offset)
temp= bit.bor(temp,bit.lshift(bit.band(bit.bnot(temp),temp2),offset))
temp= bit.band(temp,bit.bnot(temp2))
temp= bit.bor(bit.band(temp,bit.bnot(bitval)),bitset*bitval)
Immediate[pl]= temp
HandleAnalog[PortType](pl,i,v)
end
local function HandleFrameJump()
LoadImmediate(cf)
MakeListFromScratch()
for pl= 0, 7 do ListRead[pl]=0x000000FFFFFF end
gui.repaint()
end
local function Sanity_cf(non_synth)
local CurrentFrame= movie.currentframe()
if non_synth then CurrentFrame= CurrentFrame+1 end
if CurrentFrame ~= cf then
end
end
local function Sanity_Resolution()
ResX,ResY= gui.resolution()
end
local function Sanity_Controllers()
local sane= true
for i= 1,2 do
local temp= input.port_type(i)
sane= sane and (Ports[i] == temp)
Ports[i]= temp
end
if not sane then
print("MtEdit: WARNING! Controller types have changed!")
end
end
function on_frame_emulated()
cf= movie.currentframe()
SaveImmediate(cf)
AdvanceList()
LoadImmediate(cf+1)
cf= cf+1
end
function on_post_load()
cf= movie.currentframe()
HandleFrameJump()
end
function on_rewind()
cf= movie.currentframe() + 1
HandleFrameJump()
end
function on_paint(non_synth)
Sanity_cf(non_synth)
Sanity_Resolution()
BGui()
LGui()
ApplyGaps()
end
ChooseList(Ports[1])
MakeListFromScratch()
gui.repaint()