fceux/output/luaScripts/FRKfunctions.lua

625 lines
20 KiB
Lua

_FRK_Fn= {}
_FRK_Fn.version= 1
--FatRatKnight
-- Various little functions for use.
-- Shortly, I will list out functions and keywords that the script provides
-- access to. But first, I feel a need to explain a few things...
-- Option keywords are simply global variables that this auxillary script looks
-- for. If they are anything other than false or nil by the time your script
-- calls requrie("FRKfunctions"), this script will react accordingly.
-- Reserved variable names are those the script uses, but allows access for
-- other scripts. Sorry about taking valuble names away from you, but I figure
-- you might want direct access to them.
-- Functions are just that. Functions that do stuff, the whole point of this
-- auxillary script. I copied down their line numbers for your convenience.
-- If the quick description isn't enough, then perhaps the more detailed
-- comments and actual code might be.
-- Options for individual functions can be changed by altering its number
-- after the require("FRKfunctions") line.
--List of option keywords:
-- _FRK_SkipRename Convenient names aren't used for these functions
-- _FRK_NoAutoReg Will not automatically fill registers
--List of reserved variable names:
-- keys For checking current keys.
-- lastkeys For checking previous keys.
--List of functions:
-- 82 UpdateKeys() Updates this script's key tables
-- 97 Press(button) Checks for a key hit
-- 109 PressRepeater(button) Like Press, but if held for long
-- 133 Release(button) Checks for when a key is released
-- 144 MouseMoved() Returns how far the mouse moved
-- 166 FBoxOldFast(x1, y1, x2, y2, color) Faster at drawing, but stupid
-- 180 FBoxOld(x1, y1, x2, y2, color) Border-only box; corners fix
-- 210 FakeBox(x1, y1, x2, y2, Fill, Border) Fill-and-Border box; corners fix
-- 230 Draw[digit](Left,Top,color) Paints tiny digit on screen
-- 354 _FRK_Fn._DN_AnyBase(right, top, Number, color, bkgnd, div)
-- Paints a right-aligned number using any base from 2 to 16.
-- 405 DrawNum(right, top, Number, color, bkgnd) Paints a beautiful number
-- 413 DrawNumx(right, top, Number, color, bkgnd) Hexidecimal version
-- 504 ProcessReg() Removes functions in registers and stores 'em
-- 521 ApplyReg() Sets registers
-- 534 AddReg(name, function)
-- 543 RemoveReg(name, pos)
-- 564 limits(value,low,high) Returns value or specified limits
-- 575 within(value,low,high) Returns T/F; Is it within range?
--List of options for individual functions:
_FRK_Fn.RepeaterDelay= 5 --How long should PressRepeater wait?
-- input.get family
--*****************************************************************************
function _FRK_Fn.UpdateKeys()
--*****************************************************************************
-- Moves keys into lastkeys, then puts fresh keyboard input into keys.
-- Meant to simplify the process of registering keyhits.
-- Stick this thing at the beginning of a gui.register function or main loop.
lastkeys= keys
keys= input.get()
end
keys= input.get() -- Sanity. Want xmouse and ymouse to exist.
lastkeys= keys -- Otherwise, MouseMoved pings an error at me.
--*****************************************************************************
function _FRK_Fn.Press(button) -- Expects a key
--*****************************************************************************
-- Returns true or false. It's true at the moment the user hits the button.
-- 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 _FRK_Fn.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.
-- It works fine if there are multiple calls to different buttons. Not so fine
-- if there's multiple calls to the same button. Only one repeater variable...
if keys[button] then
if not lastkeys[button] or repeater >= _FRK_Fn.RepeaterDelay 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 _FRK_Fn.Release(button) -- Expects a key
--*****************************************************************************
-- Returns true or false. It's true at the moment the user releases the button.
-- Might be a good idea to know when the user ain't holding it anymore.
-- Eh, I don't see any obvious application, but may as well have it.
return ((not keys[button]) and lastkeys[button])
end
--*****************************************************************************
function _FRK_Fn.MouseMoved()
--*****************************************************************************
-- Returns two values: x,y
-- This function tells you how far the mouse moved since the last update.
-- It's simply the difference of what position it is now and what it once was.
return (keys.xmouse - lastkeys.xmouse) , (keys.ymouse - lastkeys.ymouse)
end
-- Display family
-- For helping you see
--*****************************************************************************
function _FRK_Fn.FBoxOldFast(x1, y1, x2, y2, color)
--*****************************************************************************
-- Gets around FCEUX's problem of double-painting the corners.
-- This particular function doesn't make sure the x and y are good.
-- Call this instead if you need processing speed and know its fine
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
--*****************************************************************************
function _FRK_Fn.FBoxOld(x1, y1, x2, y2, color)
--*****************************************************************************
-- Gets around FCEUX's problem of double-painting the corners.
-- This has several sanity checks to ensure a properly drawn box.
-- It acts like the old-style border-only box.
if (x1 == x2) and (y1 == y2) then -- Sanity: Is it a single dot?
gui.pixel(x1,y1,color)
elseif (x1 == x2) or (y1 == y2) then -- Sanity: A straight line?
gui.line(x1,y1,x2,y2,color)
else --(x1 ~= x2) and (y1 ~= y2)
local temp
if x1 > x2 then
temp= x1; x1= x2; x2= temp -- Sanity: Without these checks,
end -- This function may end up putting
if y1 > y2 then -- two or four out-of-place pixels
temp= y1; y1= y2; y2= temp -- near the corners.
end
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 _FRK_Fn.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. Not quite perfectly...
-- One "problem" is that, if you specify Fill only, it won't successfully
-- mimic the actual gui.box fill.
if not Border then Border= Fill end
gui.box(x1,y1,x2,y2,Fill,0)
FBoxOld(x1,y1,x2,y2,Border)
end
--### # ### ### # # ### ### ### ### ### # ## # ## ### ###
--# # ## # # # # # # # # # # # # # # # # # # # # #
--# # # ### ### ### ### ### ## ### ### # # ## # # # ## ##
--# # # # # # # # # # # # # ### # # # # # # # #
--### ### ### ### # ### ### # ### ### # # ## # ## ### #
--*****************************************************************************
_FRK_Fn.Draw= {} --Draw[button]( Left , Top , color )
--*****************************************************************************
--Coordinates is the top-left pixel of the 3x5 digit.
--Used for drawing compact, colored numbers.
local d= _FRK_Fn.Draw
function d.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 d.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 d.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 d.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 d.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 d.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 d.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 d.D7(left, top, color)
gui.line(left ,top ,left+1,top ,color)
gui.line(left+2,top ,left+1,top+4,color)
end
function d.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 d.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)
end
function d.DA(left, top, color)
gui.line(left ,top+1,left ,top+4,color)
gui.line(left+2,top+1,left+2,top+4,color)
gui.pixel(left+1,top ,color)
gui.pixel(left+1,top+3,color)
end
function d.DB(left, top, color)
gui.line(left ,top ,left ,top+4,color)
gui.line(left+1,top ,left+2,top+1,color)
gui.line(left+1,top+4,left+2,top+3,color)
gui.pixel(left+1,top+2,color)
end
function d.DC(left, top, color)
gui.line(left ,top+1,left ,top+3,color)
gui.line(left+1,top ,left+2,top+1,color)
gui.line(left+1,top+4,left+2,top+3,color)
end
function d.DD(left, top, color)
gui.line(left ,top ,left ,top+4,color)
gui.line(left+2,top+1,left+2,top+3,color)
gui.pixel(left+1,top ,color)
gui.pixel(left+1,top+4,color)
end
function d.DE(left, top, color)
gui.line(left ,top ,left ,top+4,color)
gui.line(left+1,top ,left+2,top ,color)
gui.line(left+1,top+4,left+2,top+4,color)
gui.pixel(left+1,top+2,color)
end
function d.DF(left, top, color)
gui.line(left ,top ,left ,top+4,color)
gui.line(left+1,top ,left+2,top ,color)
gui.pixel(left+1,top+2,color)
end
d[0],d[1],d[2],d[3],d[4]= d.D0, d.D1, d.D2, d.D3, d.D4
d[5],d[6],d[7],d[8],d[9]= d.D5, d.D6, d.D7, d.D8, d.D9
d[10],d[11],d[12],d[13],d[14],d[15]= d.DA, d.DB, d.DC, d.DD, d.DE, d.DF
--*****************************************************************************
function _FRK_Fn._DN_AnyBase(right, top, Number, color, bkgnd, div)
--*****************************************************************************
-- Works with any base from 2 to 16. Paints the input number.
-- Returns the x position where it would paint another digit.
-- It only works with integers. Rounds fractions toward zero.
if div < 2 then return end -- Prevents the function from never returning.
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 % div
Number= math.floor(Number/div)
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 _FRK_Fn.Draw[Digit[i]] do
_FRK_Fn.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 _FRK_Fn.DrawNum(right, top, Number, color, bkgnd)
--*****************************************************************************
-- Paints the input number as right-aligned. Decimal version.
return _FRK_Fn._DN_AnyBase(right, top, Number, color, bkgnd, 10)
end
--*****************************************************************************
function _FRK_Fn.DrawNumx(right, top, Number, color, bkgnd)
--*****************************************************************************
-- Paints the input number as right-aligned. Hexadecimal version.
return _FRK_Fn._DN_AnyBase(right, top, Number, color, bkgnd, 16)
end
-- Registry family
-- For overloading the usual registers with multiple separate functions.
local RegNames= {"Before", "After", "Exit", "Gui", "Save", "Load"}
_FRK_Fn.RegList= {}
_FRK_Fn.RegList.Before={}
_FRK_Fn.RegList.After= {}
_FRK_Fn.RegList.Exit= {}
_FRK_Fn.RegList.Gui= {}
_FRK_Fn.RegList.Save= {}
_FRK_Fn.RegList.Load= {}
--*****************************************************************************
_FRK_Fn.RegFn= {} --RegFn[name]() For various registers
--*****************************************************************************
function _FRK_Fn.RegFn.Before()
local i= 1
while (_FRK_Fn.RegList.Before[i]) do
_FRK_Fn.RegList.Before[i]()
i= i+1
end
end
function _FRK_Fn.RegFn.After()
local i= 1
while (_FRK_Fn.RegList.After[i]) do
_FRK_Fn.RegList.After[i]()
i= i+1
end
end
function _FRK_Fn.RegFn.Exit()
local i= 1
while (_FRK_Fn.RegList.Exit[i]) do
_FRK_Fn.RegList.Exit[i]()
i= i+1
end
end
function _FRK_Fn.RegFn.Gui()
local i= 1
while (_FRK_Fn.RegList.Gui[i]) do
_FRK_Fn.RegList.Gui[i]()
i= i+1
end
end
function _FRK_Fn.RegFn.Save()
local i= 1
while (_FRK_Fn.RegList.Save[i]) do
_FRK_Fn.RegList.Save[i]()
i= i+1
end
end
function _FRK_Fn.RegFn.Load()
local i= 1
while (_FRK_Fn.RegList.Load[i]) do
_FRK_Fn.RegList.Load[i]()
i= i+1
end
end
local EmuRegisters={
emu.registerbefore,
emu.registerafter,
emu.registerexit,
gui.register,
savestate.registersave,
savestate.registerload
}
--*****************************************************************************
function _FRK_Fn.ProcessRegisters()
--*****************************************************************************
-- Any functions in registers, such as those that might be inserted by
-- auxillary files, are removed from their registers and inserted into my
-- table of functions to execute.
-- All registers will be empty after excecution of this function.
for i= 1, 6 do
local test= EmuRegisters[i]()
-- Make sure the function exists. Also, make sure it isn't ourselves...
if test and (test ~= _FRK_Fn.RegFn[ RegNames[i] ]) then
table.insert(_FRK_Fn.RegList[ RegNames[i] ],1,test)
end
end
end
--*****************************************************************************
function _FRK_Fn.ApplyRegisters()
--*****************************************************************************
-- Fills the registers with functions that will excecute functions stored in
-- my tables.
for i= 1, 6 do
if _FRK_Fn.RegList[ RegNames[i] ][ 1 ] then
EmuRegisters[i](_FRK_Fn.RegFn[ RegNames[i] ])
end
end
end
--*****************************************************************************
function _FRK_Fn.AddRegister(name, fn)
--*****************************************************************************
-- Name should be "Before", "After", "Exit", "Gui", "Save", or "Load".
-- Recommended for use if you plan to add functions to the register.
table.insert(_FRK_Fn.RegList[name],fn)
end
--*****************************************************************************
function _FRK_Fn.RemoveRegister(name, pos)
--*****************************************************************************
-- Name should be "Before", "After", "Exit", "Gui", "Save", or "Load".
-- You may omit pos. Doing so will remove and return the first function that's
-- been inserted into my table.
return table.remove(_FRK_Fn.RegList[name],pos)
end
-- Miscellaneous family
--*****************************************************************************
function _FRK_Fn.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.
-- Sometimes, you'd rather crop the number to some specific limits.
return math.max(math.min(value,high),low)
end
--*****************************************************************************
function _FRK_Fn.within( value , low , high ) -- Expects numbers
--*****************************************************************************
-- Returns true if value is between low and high, inclusive. False otherwise.
-- Sometimes, you just want to know if the number is within a certain range.
return ( value >= low ) and ( value <= high )
end
--=============================================================================
if not _FRK_SkipRename then
--=============================================================================
UpdateKeys= _FRK_Fn.UpdateKeys
Press= _FRK_Fn.Press
PressRepeater= _FRK_Fn.PressRepeater
Release= _FRK_Fn.Release
MouseMoved= _FRK_Fn.MouseMoved
FBoxOldFast= _FRK_Fn.FBoxOldFast
FBoxOld= _FRK_Fn.FBoxOld
FakeBox= _FRK_Fn.FakeBox
Draw= _FRK_Fn.Draw
DrawNum= _FRK_Fn.DrawNum
DrawNumx= _FRK_Fn.DrawNumx
ProcessReg= _FRK_Fn.ProcessRegisters
ApplyReg= _FRK_Fn.ApplyRegisters
AddReg= _FRK_Fn.AddRegister
RemoveReg= _FRK_Fn.RemoveRegister
limits= _FRK_Fn.limits
within= _FRK_Fn.within
end
--=============================================================================
if not _FRK_NoAutoReg then
--=============================================================================
emu.registerbefore( _FRK_Fn.RegFn.Before)
emu.registerafter( _FRK_Fn.RegFn.After )
emu.registerexit( _FRK_Fn.RegFn.Exit )
gui.register( _FRK_Fn.RegFn.Gui )
savestate.registersave(_FRK_Fn.RegFn.Save )
savestate.registerload(_FRK_Fn.RegFn.Load )
end