Made a new subtitle script. Feel free to download.
This is an auxiliary script. I recommend making a new lua file that includes a dofile("SubtitleDisplayer.lua") somewhere near the beginning. This way, all the subtitling you want is in one file and the actual code that does the work doesn't clutter your subtitle file.
It now allows out-of-order subtitling. That is, you don't need to worry about keeping all the start frames of the subtitles in ascending order in your subtitles file.
Download SubtitleDisplayer.luaLanguage: lua
--Aids in displaying lua-based subtitles
--FatRatKnight
--S(start,end,left,top,line1, line2, ..., lineN)
--Subtitle. Displays text
--B(start,end,left,top,right,bottom,FillColor,BorderColor)
--Box. Paints a colored box at selected area.
--R1U(start,end,left,top,text,address)
--ReadAddress. Displays one line of text and displays value at address.
--Full list of related functions: R1U, R2U, R4U, R1S, R2S, R4S
--A(start,end,left,top,FillColor,BorderColor, line1, line2, ..., lineN)
--Auto Box&Subtitle. Displays text and a text-fitting box around it.
--Additionally, I provide a lowercase letter version of each function.
--The end parameter for lowercase is relative to start, so inserting 300 there
--means that the subtitle will last 300 frames. Additionally, lowercase also
--makes the box routine ask for width and height instead of right-side and
--bottom-side.
--The R#U and R#S functions need to be fully lowercase. r1U will fail.
--But r1u will work just fine.
local Subbies= {}
local WID= 6 -- Width of each character. DeSmuME uses 6.
local HGT= 9 -- Height. I'm arbitrarily using 9 here.
if stylus then --DeSmuME. Platform: DS
WID= 6; HGT= 9
elseif snes9x then --Snes9x. Platform: SNES
WID= 4; HGT= 8
elseif vba then --VisualBoy Advance. Platforms: GBA, GB, GBC, SGB
WID= 4; HGT= 8
elseif FCEU then --FCE Ultra / FCEUX. Platform: NES.
WID= 2; HGT= 9
end
-- Array based functions.
--#############################################################################
--*****************************************************************************
local function DispMsg(T)
--*****************************************************************************
for i= 1, #T do
gui.text(T.x,T.y+HGT*(i-1),T[i],T.c1,T.c2)
end
end
--*****************************************************************************
local function DispAddr(T)
--*****************************************************************************
gui.text(T.x,T.y, string.format(T.txt, T.rv(T.v)) , T.c1,T.c2)
end
--*****************************************************************************
local function DispBox(T)
--*****************************************************************************
gui.box(T.x,T.y,T.x2,T.y2 , T.c1,T.c2)
end
--#############################################################################
local CurrentIndex= 1
local ActiveSubs= {}
--*****************************************************************************
local function HandleArray()
--*****************************************************************************
-- I'll leave the intelligence of add/removal here.
--Add
while Subbies[CurrentIndex] and (Subbies[CurrentIndex].t <= movie.framecount()) do
table.insert(ActiveSubs,Subbies[CurrentIndex])
CurrentIndex= CurrentIndex+1
end
--Execute/remove
local i= 1
while ActiveSubs[i] do
if ActiveSubs[i].e >= movie.framecount() then
ActiveSubs[i]:fn()
i= i+1
else
table.remove(ActiveSubs,i)
end
end
end
--*****************************************************************************
local function ResetArray()
--*****************************************************************************
CurrentIndex= 1
ActiveSubs= {}
end
--*****************************************************************************
local function AddToSubbies(T)
--*****************************************************************************
for i= #Subbies, 1, -1 do
if T.t >= Subbies[i].t then
table.insert(Subbies,i+1,T)
return -- Escape, as we have inserted it!
end
end
table.insert(Subbies,1,T) -- If we go here, the loop failed to insert.
end
--#############################################################################
--#############################################################################
-- [S]ubtitle
-- Can take an arbitrary number of lines
-- Its name is one letter long to save bytes. Lots of them.
--*****************************************************************************
function S(start,End , left,top , ...)
--*****************************************************************************
-- This is a CAPITAL S. Use absolutes.
if arg.n <= 0 then return end -- Sanity; Must have text!
local NewSub= {
fn= DispMsg,
t= start, e= End,
x= left, y= top
}
for i= 1, arg.n do
NewSub[i]= arg[i]
end
AddToSubbies(NewSub)
end
--*****************************************************************************
function s(start,length , left,top , ...)
--*****************************************************************************
-- Lowercase s. Use relatives where it makes sense (frame end is it).
if arg.n <= 0 then return end -- Sanity; Must have text!
local NewSub= {
fn= DispMsg,
t= start, e= start+length,
x= left, y= top
}
for i= 1, arg.n do NewSub[i]= arg[i] end
AddToSubbies(NewSub)
end
--*****************************************************************************
local function ReadMem(start,End , left,top , str,addr , NewFn)
--*****************************************************************************
-- Not for end-user; Call the R#U/S series instead!
-- The usual start,end,left,top applies
AddToSubbies{
fn= DispAddr,
t= start, e= End,
x= left, y= top,
txt= str, v= addr,
rv= NewFn
}
end
--=============================================================================
function R1U(start,End , x1,y1 , str,addr)
ReadMem(start,End , x1,y1 , str,addr , memory.readbyteunsigned)
end
function R2U(start,End , x1,y1 , str,addr)
ReadMem(start,End , x1,y1 , str,addr , memory.readwordunsigned)
end
function R4U(start,End , x1,y1 , str,addr)
ReadMem(start,End , x1,y1 , str,addr , memory.readdwordunsigned)
end
function R1S(start,End , x1,y1 , str,addr)
ReadMem(start,End , x1,y1 , str,addr , memory.readbytesigned)
end
function R2S(start,End , x1,y1 , str,addr)
ReadMem(start,End , x1,y1 , str,addr , memory.readwordsigned)
end
function R4S(start,End , x1,y1 , str,addr)
ReadMem(start,End , x1,y1 , str,addr , memory.readdwordsigned)
end
function r1u(start,length , x1,y1 , str,addr)
ReadMem(start,start+length , x1,y1 , str,addr , memory.readbyteunsigned)
end
function r2u(start,length , x1,y1 , str,addr)
ReadMem(start,start+length , x1,y1 , str,addr , memory.readwordunsigned)
end
function r4u(start,length , x1,y1 , str,addr)
ReadMem(start,start+length , x1,y1 , str,addr , memory.readdwordunsigned)
end
function r1s(start,length , x1,y1 , str,addr)
ReadMem(start,start+length , x1,y1 , str,addr , memory.readbytesigned)
end
function r2s(start,length , x1,y1 , str,addr)
ReadMem(start,start+length , x1,y1 , str,addr , memory.readwordsigned)
end
function r4s(start,length , x1,y1 , str,addr)
ReadMem(start,start+length , x1,y1 , str,addr , memory.readdwordsigned)
end
--=============================================================================
-- [B]ox
--*****************************************************************************
function B(start,End , left,top , right,bottom , cf,cb)
--*****************************************************************************
AddToSubbies{
fn= DispBox,
t= start, e= End,
x= left, y= top,
x2= right, y2= bottom,
c1= cf, c2= cb
}
end
--*****************************************************************************
function b(start,length , left,top , width,height , cf,cb)
--*****************************************************************************
AddToSubbies{
fn= DispBox,
t= start, e= start+length,
x= left, y= top,
x2= left+width, y2= top+height,
c1= cf, c2= cb
}
end
-- [A]uto
-- Boxes and subtitles, wrapped in one.
-- Calculates the box size for you!
--*****************************************************************************
function A(start,End , left,top , cf,cb , ...)
--*****************************************************************************
if arg.n <= 0 then return end -- Sanity
local NewSub= {
fn= DispMsg,
t= start, e= End,
x= left, y= top
}
local len= 0
for i= 1, arg.n do
NewSub[i]= arg[i]
len= math.max(len, string.len(arg[i]))
end
B(start,End , left-1,top-1 , left+len*WID,top+arg.n*HGT, cf,cb)
AddToSubbies(NewSub)
end
--*****************************************************************************
function a(start,length , left,top , cf,cb , ...)
--*****************************************************************************
if arg.n <= 0 then return end -- Sanity
local NewSub= {
fn= DispMsg,
t= start, e= start+length,
x= left, y= top
}
local len= 0
for i= 1, arg.n do
NewSub[i]= arg[i]
len= math.max(len, string.len(arg[i]))
end
B(start,start+length , left-1,top-1 , left+len*WID,top+arg.n*HGT, cf,cb)
AddToSubbies(NewSub)
end
--#############################################################################
--#############################################################################
local LastFC= 0
--*****************************************************************************
local function FrameCountSanity()
--*****************************************************************************
local FC= movie.framecount()
if FC < LastFC then ResetArray() end
LastFC= FC
end
--*****************************************************************************
local function HandleSubs()
--*****************************************************************************
FrameCountSanity()
HandleArray()
end
gui.register(HandleSubs)