--[[ Copyright (c) 2013 Julius Riecke This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ]] --[[ A Compilation of general-purpose functions. -]] M_UTILS_VERSION = 0 --initialization if(FCEU) then EMU = FCEU elseif(snes9x) then EMU = snes9x elseif(gens) then EMU = gens end if(EMU == nil) then error("Unsupported environment. This script runs on Lua-capable emulators only - FCEUX, Snes9x or Gens.") end --[[ m_require "require" with version checking Similar to the approach in Xk's x_functions.lua, but supports loading and automatic version checking of "compatible" modules, too. A central version checking function does have its advantages. A compatible module looks like this: if(REQUIRED_MODULE_VERSION==0) then --global variable = the second parameter of m_require error("This module isn't backwards compatible to version 0.") end module("modulename") MODULE_VERSION = 3 function test() end return _M using it in your code: m_require("modulefile.lua",3) --second parameter being > MODULE_VERSION would raise an error modulename.test() -]] function m_require(module,requiredver) if(module==nil or module=="m_utils") then if(M_UTILS_VERSION>=requiredver) then return true else error("\n\nThis script requires m_utils version "..requiredver..".\n".. "Your m_utils.lua is version "..M_UTILS_VERSION.."\n".. "Check http://morphcat.de/lua/ for a newer version.") end else --give the module the possibility to be backwards compatible --not very elegant, but there seems to be no other way using require REQUIRED_MODULE_VERSION = requiredver local ret = require(module) if(requiredver==nil) then --got no version checking to do return ret elseif(ret==nil or ret==false) then error("Could not load module "..module.." or module invalid.") elseif(type(ret)~="table") then error("Invalid module "..module..", doesn't return itself.") elseif(ret.MODULE_VERSION==nil) then error("Invalid module "..module..", missing version information.") elseif(ret.MODULE_VERSION < requiredver) then error("\n\nThis script requires "..module.." version "..requiredver..".\n".. "Your "..module.." module is version "..ret.MODULE_VERSION..".\n".. "If it's one of miau's Lua modules check\n".. "http://morphcat.de/lua/ for a newer version.\n") else return ret end end end --drawing functions with bounds checking function bcbox(x1,y1,x2,y2,color1) if(x1>=0 and y1>=0 and x2<=255 and y2<=255) then gui.drawbox(x1, y1, x2, y2, color1, 0) end end function bcpixel(x,y,color) if(x>=0 and y>=0 and x<=255 and y<=255) then gui.drawpixel(x,y,color) end end function bcline(x1,y1,x2,y2,color) if(x1>=0 and y1>=0 and x2<=255 and y2<=255 and x2>=0 and y2>=0 and x1<=255 and y1<=255) then gui.drawline(x1, y1, x2, y2, color) end end --bc + clipping, just make sure x2,y2 is the point that will most likely leave the screen first function bcline2(x1,y1,x2,y2,color) if(x1>=0 and y1>=0 and x1<=255 and y1<=255) then if(x2>255 or y2>255 or x2<0 or y2<0) then local vx,vy=getvdir(x1,y1,x2,y2) --TODO: replace brute force-y method with line intersection formula if(math.abs(vx)==1 or math.abs(vy)==1) then local x=x1 local y=y1 while(x<254 and x>1 and y<254 and y>1) do x = x + vx y = y + vy end x = math.floor(x) y = math.floor(y) --logf(" ("..x1..","..y1..")-("..x..","..y..")\r\n") gui.drawline(x1,y1,x,y,color) end else gui.drawline(x1,y1,x2,y2,color) end end end function bctext(x,y,text) if(x>=0 and y>=0 and x<=255 and y<=255) then --make sure the text is always visible or else... possible memory leaks(?) and crashes on FCEUX <= 2.0.3 local len=string.len(text)*8+1 if(x+len > 255) then x = 255-len end if(x < 0) then x = 0 end if(y > 222) then --NTSC y=222 end gui.text(x, y, text) end end function getdistance(x1,y1,x2,y2) return math.floor(math.sqrt((x1-x2)^2+(y1-y2)^2)) end --returns direction vector of a line function getvdir(srcx,srcy,destx,desty) local x1 = srcx local x2 = destx local y1 = srcy local y2 = desty local xc = x2-x1 local yc = y2-y1 if(math.abs(xc)>math.abs(yc)) then yc = yc/math.abs(xc) xc = xc/math.abs(xc) elseif(math.abs(yc)>math.abs(xc)) then xc = xc/math.abs(yc) yc = yc/math.abs(yc) else if(xc<0) then xc=-1 elseif(xc>0) then xc=1 else xc=0 end if(yc<0) then yc=-1 elseif(yc>0) then yc=1 else yc=0 end end return xc,yc end local m_cursor = { {1,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0}, {1,2,1,0,0,0,0,0}, {1,2,2,1,0,0,0,0}, {1,2,2,2,1,0,0,0}, {1,2,2,2,2,1,0,0}, {1,2,2,2,2,2,1,0}, {1,2,1,1,1,1,1,1}, {1,1,0,0,0,0,0,0}, {1,0,0,0,0,0,0,0}, } function drawcursor(px,py,col1,col2) if(px>0 and py>0 and px<256-8 and py<256-10) then for y=1,10 do if(m_cursor[y]) then for x=1,8 do if(m_cursor[y][x]==1) then gui.drawpixel(px+x,py+y,col1) elseif(m_cursor[y][x]==2) then gui.drawpixel(px+x,py+y,col2) end end end end end end --debug functions function logf(s) local fo = io.open("E:/emu/nes/fceux-2.0.4.win32-unofficial/lua/log.txt", "ab") if(fo~=nil) then fo:write(s) fo:close() return true end end function logtable(a) for i,v in pairs(a) do if(type(v)=="table") then printarrrec(v) else if(v==false) then v="false" elseif(v==true) then v="true" end logf(i.." = "..v.."\r\n") end end end