2015-08-16 16:00:39 +00:00
|
|
|
--[[
|
|
|
|
Implementation of PICO8 API for LOVE
|
2015-08-17 03:05:08 +00:00
|
|
|
|
|
|
|
What it is:
|
|
|
|
|
|
|
|
* An implementation of pico-8's api in love
|
|
|
|
|
|
|
|
Why:
|
|
|
|
|
|
|
|
* For a fun challenge!
|
|
|
|
* Allow standalone publishing of pico-8 games on other platforms
|
|
|
|
* should work on mobile devices
|
|
|
|
* Configurable controls
|
2015-08-18 12:14:35 +00:00
|
|
|
* Extendable
|
2015-08-17 03:05:08 +00:00
|
|
|
* No arbitrary cpu or memory limitations
|
|
|
|
* No arbitrary code size limitations
|
|
|
|
* Betting debugging tools available
|
|
|
|
* Open source
|
|
|
|
|
|
|
|
What it isn't:
|
|
|
|
|
|
|
|
* A replacement for Pico-8
|
|
|
|
* A perfect replica
|
|
|
|
* No dev tools, no image editor, map editor, sfx editor, music editor
|
|
|
|
* No modifying or saving carts
|
|
|
|
|
|
|
|
Not Yet Implemented:
|
|
|
|
|
|
|
|
* Memory modification/reading
|
|
|
|
* Sound/music
|
|
|
|
* if (foo) bar=1 shorthand
|
2015-08-18 12:14:35 +00:00
|
|
|
* stat() probably unnecessary
|
2015-08-17 03:05:08 +00:00
|
|
|
|
|
|
|
Not working:
|
|
|
|
|
|
|
|
Differences:
|
|
|
|
|
|
|
|
* Uses floating point numbers not fixed point
|
|
|
|
* sqrt doesn't freeze
|
|
|
|
* Uses luajit not lua 5.2
|
|
|
|
|
|
|
|
Extra features:
|
|
|
|
|
|
|
|
* log(...) function prints to console for debugging
|
|
|
|
* assert(expr,message) if expr is not true then errors with message
|
|
|
|
* error(message) bluescreens with an error message
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
]]
|
|
|
|
|
|
|
|
local scale = 4
|
2015-08-17 14:47:42 +00:00
|
|
|
local xpadding = 8.5
|
|
|
|
local ypadding = 3.5
|
2015-08-16 16:00:39 +00:00
|
|
|
local __accum = 0
|
|
|
|
|
|
|
|
local __pico_pal_transparent = {
|
|
|
|
}
|
|
|
|
|
|
|
|
local __pico_palette = {
|
2015-08-18 09:45:04 +00:00
|
|
|
{0,0,0,255},
|
2015-08-16 16:00:39 +00:00
|
|
|
{29,43,83,255},
|
|
|
|
{126,37,83,255},
|
|
|
|
{0,135,81,255},
|
|
|
|
{171,82,54,255},
|
|
|
|
{95,87,79,255},
|
|
|
|
{194,195,199,255},
|
|
|
|
{255,241,232,255},
|
|
|
|
{255,0,77,255},
|
|
|
|
{255,163,0,255},
|
|
|
|
{255,255,39,255},
|
|
|
|
{0,231,86,255},
|
|
|
|
{41,173,255,255},
|
|
|
|
{131,118,156,255},
|
|
|
|
{255,119,168,255},
|
|
|
|
{255,204,170,255}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local __pico_camera_x = 0
|
|
|
|
local __pico_camera_y = 0
|
|
|
|
|
2015-08-17 14:47:42 +00:00
|
|
|
local host_time = 0
|
|
|
|
|
|
|
|
local retro_mode = false
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
function love.load(argv)
|
|
|
|
love_args = argv
|
2015-08-17 14:47:42 +00:00
|
|
|
if love.system.getOS() == "Android" then
|
|
|
|
--love.window.setMode(128*scale+xpadding*scale*2,128*scale+ypadding*scale*2)
|
|
|
|
love.resize(love.window.getDimensions())
|
|
|
|
else
|
|
|
|
love.window.setMode(128*scale+xpadding*scale*2,128*scale+ypadding*scale*2)
|
|
|
|
end
|
2015-08-18 09:45:04 +00:00
|
|
|
love.graphics.clear()
|
2015-08-16 16:00:39 +00:00
|
|
|
love.graphics.setDefaultFilter('nearest','nearest')
|
|
|
|
__screen = love.graphics.newCanvas(128,128)
|
2015-08-17 14:47:42 +00:00
|
|
|
__screen:setFilter('linear','nearest')
|
2015-08-16 16:00:39 +00:00
|
|
|
|
2015-08-17 16:36:58 +00:00
|
|
|
local font = love.graphics.newImageFont("font.png","abcdefghijklmnopqrstuvwxyz\"'`-_/1234567890!?[](){}.,;:<>+ ")
|
2015-08-16 16:00:39 +00:00
|
|
|
love.graphics.setFont(font)
|
|
|
|
font:setFilter('nearest','nearest')
|
|
|
|
|
|
|
|
love.mouse.setVisible(false)
|
|
|
|
love.window.setTitle("pico-8-emu")
|
|
|
|
love.graphics.setLineStyle('rough')
|
|
|
|
love.graphics.setPointStyle('rough')
|
|
|
|
love.graphics.setPointSize(1)
|
|
|
|
love.graphics.setLineWidth(1)
|
|
|
|
|
|
|
|
love.graphics.origin()
|
|
|
|
love.graphics.setCanvas(__screen)
|
2015-08-18 12:00:57 +00:00
|
|
|
restore_clip()
|
2015-08-16 16:00:39 +00:00
|
|
|
|
2015-08-18 09:45:04 +00:00
|
|
|
__draw_palette = {}
|
|
|
|
__display_palette = {}
|
|
|
|
__pico_pal_transparent = {}
|
|
|
|
for i=1,16 do
|
|
|
|
__draw_palette[i] = i
|
|
|
|
__pico_pal_transparent[i] = i == 1 and 0 or 1
|
|
|
|
__display_palette[i] = __pico_palette[i]
|
|
|
|
end
|
2015-08-17 14:47:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
__draw_shader = love.graphics.newShader([[
|
2015-08-18 09:45:04 +00:00
|
|
|
extern float palette[16];
|
2015-08-17 14:47:42 +00:00
|
|
|
|
|
|
|
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
|
2015-08-17 16:36:58 +00:00
|
|
|
int index = int(color.r*16.0);
|
2015-08-18 09:45:04 +00:00
|
|
|
return vec4(vec3(palette[index]/16.0),1.0);
|
2015-08-17 14:47:42 +00:00
|
|
|
}]])
|
2015-08-18 09:45:04 +00:00
|
|
|
__draw_shader:send('palette',unpack(__draw_palette))
|
2015-08-16 16:00:39 +00:00
|
|
|
|
|
|
|
__sprite_shader = love.graphics.newShader([[
|
2015-08-18 09:45:04 +00:00
|
|
|
extern float palette[16];
|
|
|
|
extern float transparent[16];
|
2015-08-17 14:47:42 +00:00
|
|
|
|
|
|
|
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
|
2015-08-18 09:45:04 +00:00
|
|
|
int index = int(floor(Texel(texture, texture_coords).r*16.0));
|
|
|
|
float alpha = transparent[index];
|
|
|
|
return vec4(vec3(palette[index]/16.0),alpha);
|
2015-08-17 14:47:42 +00:00
|
|
|
}]])
|
2015-08-18 09:45:04 +00:00
|
|
|
__sprite_shader:send('palette',unpack(__draw_palette))
|
|
|
|
__sprite_shader:send('transparent',unpack(__pico_pal_transparent))
|
2015-08-17 14:47:42 +00:00
|
|
|
|
|
|
|
__text_shader = love.graphics.newShader([[
|
2015-08-18 09:45:04 +00:00
|
|
|
extern float palette[16];
|
2015-08-16 16:00:39 +00:00
|
|
|
|
|
|
|
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
|
|
|
|
vec4 texcolor = Texel(texture, texture_coords);
|
2015-08-17 14:47:42 +00:00
|
|
|
if(texcolor.a == 0) {
|
|
|
|
return vec4(0.0,0.0,0.0,0.0);
|
2015-08-16 16:00:39 +00:00
|
|
|
}
|
2015-08-17 14:47:42 +00:00
|
|
|
int index = int(color.r*16.0);
|
|
|
|
// lookup the colour in the palette by index
|
2015-08-18 09:45:04 +00:00
|
|
|
return vec4(vec3(palette[index]/16.0),1.0);
|
2015-08-16 16:00:39 +00:00
|
|
|
}]])
|
2015-08-18 09:45:04 +00:00
|
|
|
__text_shader:send('palette',unpack(__draw_palette))
|
2015-08-16 16:00:39 +00:00
|
|
|
|
2015-08-17 14:47:42 +00:00
|
|
|
__display_shader = love.graphics.newShader([[
|
2015-08-18 09:45:04 +00:00
|
|
|
|
|
|
|
extern vec4 palette[16];
|
2015-08-16 16:00:39 +00:00
|
|
|
|
2015-08-17 14:47:42 +00:00
|
|
|
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
|
2015-08-18 09:45:04 +00:00
|
|
|
int index = int(Texel(texture, texture_coords).r*15.0);
|
2015-08-17 14:47:42 +00:00
|
|
|
// lookup the colour in the palette by index
|
2015-08-18 09:45:04 +00:00
|
|
|
return palette[index]/256.0;
|
2015-08-17 14:47:42 +00:00
|
|
|
}]])
|
2015-08-18 09:45:04 +00:00
|
|
|
__display_shader:send('palette',unpack(__display_palette))
|
2015-08-17 14:47:42 +00:00
|
|
|
|
|
|
|
pal()
|
2015-08-16 16:00:39 +00:00
|
|
|
|
|
|
|
-- load the cart
|
2015-08-17 09:11:50 +00:00
|
|
|
clip()
|
|
|
|
camera()
|
|
|
|
pal()
|
|
|
|
color(0)
|
2015-08-17 14:47:42 +00:00
|
|
|
load(argv[2] or 'picopout.p8')
|
2015-08-17 11:14:08 +00:00
|
|
|
run()
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function load_p8(filename)
|
2015-08-17 03:05:08 +00:00
|
|
|
log("Opening",filename)
|
2015-08-16 16:00:39 +00:00
|
|
|
local f = love.filesystem.newFile(filename,'r')
|
|
|
|
if not f then
|
|
|
|
error("Unable to open",filename)
|
|
|
|
end
|
|
|
|
local data,size = f:read()
|
|
|
|
f:close()
|
|
|
|
|
|
|
|
if not data then
|
|
|
|
error("invalid cart")
|
|
|
|
end
|
|
|
|
|
|
|
|
--local start = data:find("pico-8 cartridge // http://www.pico-8.com\nversion ")
|
|
|
|
local header = "pico-8 cartridge // http://www.pico-8.com\nversion "
|
|
|
|
local start = data:find("pico%-8 cartridge // http://www.pico%-8.com\nversion ")
|
|
|
|
if start == nil then
|
|
|
|
error("invalid cart")
|
|
|
|
end
|
|
|
|
local next_line = data:find("\n",start+#header)
|
|
|
|
local version_str = data:sub(start+#header,next_line-1)
|
|
|
|
local version = tonumber(version_str)
|
2015-08-17 03:05:08 +00:00
|
|
|
log("version",version)
|
2015-08-16 16:00:39 +00:00
|
|
|
-- extract the lua
|
|
|
|
local lua_start = data:find("__lua__") + 8
|
|
|
|
local lua_end = data:find("__gfx__") - 1
|
|
|
|
|
|
|
|
local lua = data:sub(lua_start,lua_end)
|
|
|
|
|
|
|
|
-- patch the lua
|
|
|
|
lua = lua:gsub("!=","~=")
|
|
|
|
-- rewrite assignment operators
|
|
|
|
lua = lua:gsub("(%S+)%s*([%+-%*/])=","%1 = %1 %2 ")
|
|
|
|
-- rewrite shorthand if statements eg. if (not b) i=1 j=2
|
|
|
|
--lua = lua:gsub("if%s*%(([^\n]+)%)%s+([^\n]+)\n",function(a,b)
|
|
|
|
-- local c = b:sub(1,5)
|
2015-08-17 03:05:08 +00:00
|
|
|
-- log("'"..c.."'")
|
2015-08-16 16:00:39 +00:00
|
|
|
-- if c == "then " or c == "then" or c == "then\t" then
|
|
|
|
-- return "if "..a.." "..b.."\n"
|
|
|
|
-- else
|
|
|
|
-- return "if "..a.." then "..b.." end\n"
|
|
|
|
-- end
|
|
|
|
--end)
|
|
|
|
|
2015-08-17 04:25:08 +00:00
|
|
|
local cart_G = {
|
2015-08-17 09:11:50 +00:00
|
|
|
-- extra functions provided by picolove
|
2015-08-17 04:25:08 +00:00
|
|
|
assert=assert,
|
|
|
|
error=error,
|
|
|
|
log=log,
|
|
|
|
-- pico8 api functions go here
|
|
|
|
clip=clip,
|
|
|
|
pget=pget,
|
|
|
|
pset=pset,
|
|
|
|
sget=sget,
|
|
|
|
sset=sset,
|
|
|
|
fget=fget,
|
|
|
|
fset=fset,
|
|
|
|
flip=flip,
|
|
|
|
print=print,
|
|
|
|
cursor=cursor,
|
|
|
|
color=color,
|
|
|
|
cls=cls,
|
|
|
|
camera=camera,
|
|
|
|
circ=circ,
|
|
|
|
circfill=circfill,
|
|
|
|
line=line,
|
2015-08-17 09:11:50 +00:00
|
|
|
load=load,
|
2015-08-17 04:25:08 +00:00
|
|
|
rect=rect,
|
|
|
|
rectfill=rectfill,
|
|
|
|
run=run,
|
|
|
|
reload=reload,
|
|
|
|
pal=pal,
|
|
|
|
palt=palt,
|
|
|
|
spr=spr,
|
|
|
|
sspr=sspr,
|
|
|
|
add=add,
|
|
|
|
del=del,
|
|
|
|
foreach=foreach,
|
|
|
|
count=count,
|
|
|
|
all=all,
|
|
|
|
btn=btn,
|
|
|
|
btnp=btnp,
|
|
|
|
sfx=sfx,
|
|
|
|
music=music,
|
|
|
|
mget=mget,
|
|
|
|
mset=mset,
|
|
|
|
map=map,
|
|
|
|
memcpy=memcpy,
|
|
|
|
peek=peek,
|
|
|
|
poke=poke,
|
|
|
|
max=max,
|
|
|
|
min=min,
|
|
|
|
mid=mid,
|
|
|
|
flr=flr,
|
|
|
|
cos=cos,
|
|
|
|
sin=sin,
|
|
|
|
atan2=atan2,
|
|
|
|
sqrt=sqrt,
|
|
|
|
abs=abs,
|
|
|
|
rnd=rnd,
|
|
|
|
srand=srand,
|
|
|
|
sgn=sgn,
|
|
|
|
band=band,
|
|
|
|
bor=bor,
|
|
|
|
bxor=bxor,
|
|
|
|
bnot=bnot,
|
|
|
|
shl=shl,
|
|
|
|
shr=shr,
|
|
|
|
sub=sub,
|
2015-08-18 12:14:35 +00:00
|
|
|
stat=stat,
|
2015-08-17 04:25:08 +00:00
|
|
|
-- deprecated pico-8 function aliases
|
|
|
|
mapdraw=map
|
|
|
|
}
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
-- load the sprites into an imagedata
|
|
|
|
-- generate a quad for each sprite index
|
|
|
|
local gfx_start = data:find("__gfx__") + 8
|
|
|
|
local gfx_end = data:find("__gff__") - 1
|
|
|
|
local gfxdata = data:sub(gfx_start,gfx_end)
|
|
|
|
|
|
|
|
local row = 0
|
|
|
|
local tile_row = 32
|
|
|
|
local tile_col = 0
|
|
|
|
local col = 0
|
|
|
|
local sprite = 0
|
|
|
|
local tiles = 0
|
|
|
|
local shared = 0
|
|
|
|
|
|
|
|
__pico_map = {}
|
|
|
|
__pico_quads = {}
|
|
|
|
for y=0,63 do
|
|
|
|
__pico_map[y] = {}
|
2015-08-17 16:36:58 +00:00
|
|
|
for x=0,127 do
|
|
|
|
__pico_map[y][x] = 0
|
|
|
|
end
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
__pico_spritesheet_data = love.image.newImageData(128,128)
|
|
|
|
|
|
|
|
local next_line = 1
|
|
|
|
while next_line do
|
|
|
|
local end_of_line = gfxdata:find("\n",next_line)
|
|
|
|
if end_of_line == nil then break end
|
|
|
|
end_of_line = end_of_line - 1
|
|
|
|
local line = gfxdata:sub(next_line,end_of_line)
|
|
|
|
for i=1,#line do
|
|
|
|
local v = line:sub(i,i)
|
|
|
|
v = tonumber(v,16)
|
2015-08-17 16:36:58 +00:00
|
|
|
__pico_spritesheet_data:setPixel(col,row,v*16,v*16,v*16,255)
|
2015-08-16 16:00:39 +00:00
|
|
|
|
|
|
|
col = col + 1
|
|
|
|
if col == 128 then
|
|
|
|
col = 0
|
|
|
|
row = row + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
next_line = gfxdata:find("\n",end_of_line)+1
|
|
|
|
end
|
|
|
|
|
2015-08-17 16:36:58 +00:00
|
|
|
local tx,ty = 0,32
|
|
|
|
for sy=64,127 do
|
|
|
|
for sx=0,127,2 do
|
|
|
|
-- get the two pixel values and merge them
|
|
|
|
local lo = flr(__pico_spritesheet_data:getPixel(sx,sy)/16)
|
|
|
|
local hi = flr(__pico_spritesheet_data:getPixel(sx+1,sy)/16)
|
|
|
|
local v = bor(shl(hi,4),lo)
|
|
|
|
__pico_map[ty][tx] = v
|
|
|
|
shared = shared + 1
|
|
|
|
tx = tx + 1
|
|
|
|
if tx == 128 then
|
|
|
|
tx = 0
|
|
|
|
ty = ty + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
for y=0,15 do
|
|
|
|
for x=0,15 do
|
|
|
|
__pico_quads[sprite] = love.graphics.newQuad(8*x,8*y,8,8,128,128)
|
|
|
|
sprite = sprite + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assert(shared == 128 * 32,shared)
|
|
|
|
assert(sprite == 256,sprite)
|
|
|
|
|
|
|
|
__pico_spritesheet = love.graphics.newImage(__pico_spritesheet_data)
|
|
|
|
__pico_spritesheet_data:encode('spritesheet.png')
|
|
|
|
|
|
|
|
-- load the sprite flags
|
|
|
|
__pico_spriteflags = {}
|
|
|
|
|
|
|
|
local gff_start = data:find("__gff__") + 8
|
|
|
|
local gff_end = data:find("__map__") - 1
|
|
|
|
local gffdata = data:sub(gff_start,gff_end)
|
|
|
|
|
|
|
|
local sprite = 0
|
|
|
|
|
|
|
|
local next_line = 1
|
|
|
|
while next_line do
|
|
|
|
local end_of_line = gffdata:find("\n",next_line)
|
|
|
|
if end_of_line == nil then break end
|
|
|
|
end_of_line = end_of_line - 1
|
|
|
|
local line = gffdata:sub(next_line,end_of_line)
|
|
|
|
if version <= 2 then
|
|
|
|
for i=1,#line do
|
|
|
|
local v = line:sub(i)
|
|
|
|
v = tonumber(v,16)
|
|
|
|
__pico_spriteflags[sprite] = v
|
|
|
|
sprite = sprite + 1
|
|
|
|
end
|
|
|
|
else
|
|
|
|
for i=1,#line,2 do
|
|
|
|
local v = line:sub(i,i+1)
|
|
|
|
v = tonumber(v,16)
|
|
|
|
__pico_spriteflags[sprite] = v
|
|
|
|
sprite = sprite + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
next_line = gfxdata:find("\n",end_of_line)+1
|
|
|
|
end
|
|
|
|
|
|
|
|
assert(sprite == 256,"wrong number of spriteflags:"..sprite)
|
|
|
|
|
|
|
|
-- convert the tile data to a table
|
|
|
|
|
|
|
|
local map_start = data:find("__map__") + 8
|
|
|
|
local map_end = data:find("__sfx__") - 1
|
|
|
|
local mapdata = data:sub(map_start,map_end)
|
|
|
|
|
|
|
|
local row = 0
|
|
|
|
local col = 0
|
|
|
|
|
|
|
|
local next_line = 1
|
|
|
|
while next_line do
|
|
|
|
local end_of_line = mapdata:find("\n",next_line)
|
|
|
|
if end_of_line == nil then
|
2015-08-17 03:05:08 +00:00
|
|
|
log("reached end of map data")
|
2015-08-16 16:00:39 +00:00
|
|
|
break
|
|
|
|
end
|
|
|
|
end_of_line = end_of_line - 1
|
|
|
|
local line = mapdata:sub(next_line,end_of_line)
|
|
|
|
for i=1,#line,2 do
|
|
|
|
local v = line:sub(i,i+1)
|
|
|
|
v = tonumber(v,16)
|
|
|
|
if col == 0 then
|
|
|
|
end
|
|
|
|
__pico_map[row][col] = v
|
|
|
|
col = col + 1
|
|
|
|
tiles = tiles + 1
|
|
|
|
if col == 128 then
|
|
|
|
col = 0
|
|
|
|
row = row + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
next_line = mapdata:find("\n",end_of_line)+1
|
|
|
|
end
|
|
|
|
assert(tiles + shared == 128 * 64,string.format("%d + %d != %d",tiles,shared,128*64))
|
|
|
|
|
|
|
|
-- check all the data is there
|
2015-08-17 16:36:58 +00:00
|
|
|
love.graphics.setScissor()
|
|
|
|
mapimage = love.graphics.newCanvas(1024,512)
|
|
|
|
mapimage:clear(0,0,0,255)
|
|
|
|
love.graphics.setCanvas(mapimage)
|
|
|
|
love.graphics.setShader(__display_shader)
|
2015-08-16 16:00:39 +00:00
|
|
|
for y=0,63 do
|
|
|
|
for x=0,127 do
|
|
|
|
assert(__pico_map[y][x],string.format("missing map data: %d,%d",x,y))
|
2015-08-17 16:36:58 +00:00
|
|
|
local n = mget(x,y)
|
|
|
|
love.graphics.draw(__pico_spritesheet,__pico_quads[n],x*8,y*8)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
end
|
2015-08-17 16:36:58 +00:00
|
|
|
love.graphics.setShader()
|
|
|
|
love.graphics.setCanvas()
|
|
|
|
mapimage:getImageData():encode('map.png')
|
2015-08-17 04:25:08 +00:00
|
|
|
|
|
|
|
log("finished loading cart",filename)
|
|
|
|
|
2015-08-18 12:00:57 +00:00
|
|
|
local ok,f,e = pcall(loadstring,lua)
|
|
|
|
if not ok or f==nil then
|
|
|
|
error("Error loading lua: "..tostring(e))
|
|
|
|
else
|
|
|
|
local result
|
|
|
|
setfenv(f,cart_G)
|
|
|
|
love.graphics.setShader(__draw_shader)
|
|
|
|
love.graphics.setCanvas(__screen)
|
|
|
|
love.graphics.origin()
|
|
|
|
restore_clip()
|
|
|
|
ok,result = pcall(f)
|
|
|
|
if not ok then
|
|
|
|
error("Error running lua: "..tostring(result))
|
|
|
|
else
|
|
|
|
log("Ran lua")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-08-17 04:25:08 +00:00
|
|
|
return cart_G
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function love.update(dt)
|
2015-08-17 14:47:42 +00:00
|
|
|
host_time = host_time + dt
|
2015-08-17 04:25:08 +00:00
|
|
|
if cart._update then cart._update() end
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
2015-08-17 14:47:42 +00:00
|
|
|
function love.resize(w,h)
|
2015-08-17 16:36:58 +00:00
|
|
|
love.graphics.clear()
|
2015-08-17 14:47:42 +00:00
|
|
|
-- adjust stuff to fit the screen
|
|
|
|
if w > h then
|
|
|
|
scale = h/(128+ypadding*2)
|
|
|
|
else
|
|
|
|
scale = w/(128+xpadding*2)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
function love.run()
|
|
|
|
if love.math then
|
|
|
|
love.math.setRandomSeed(os.time())
|
|
|
|
for i=1,3 do love.math.random() end
|
|
|
|
end
|
|
|
|
|
|
|
|
if love.event then
|
|
|
|
love.event.pump()
|
|
|
|
end
|
|
|
|
|
|
|
|
if love.load then love.load(arg) end
|
|
|
|
|
|
|
|
-- We don't want the first frame's dt to include time taken by love.load.
|
|
|
|
if love.timer then love.timer.step() end
|
|
|
|
|
|
|
|
local dt = 0
|
|
|
|
|
|
|
|
-- Main loop time.
|
|
|
|
while true do
|
|
|
|
-- Process events.
|
|
|
|
if love.event then
|
|
|
|
love.event.pump()
|
|
|
|
for e,a,b,c,d in love.event.poll() do
|
|
|
|
if e == "quit" then
|
|
|
|
if not love.quit or not love.quit() then
|
|
|
|
if love.audio then
|
|
|
|
love.audio.stop()
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
love.handlers[e](a,b,c,d)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Update dt, as we'll be passing it to update
|
|
|
|
if love.timer then
|
|
|
|
love.timer.step()
|
|
|
|
dt = dt + love.timer.getDelta()
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Call update and draw
|
|
|
|
local render = false
|
|
|
|
while dt > 1/30 do
|
|
|
|
if love.update then love.update(1/30) end -- will pass 0 if love.timer is disabled
|
|
|
|
dt = dt - 1/30
|
|
|
|
render = true
|
|
|
|
end
|
|
|
|
|
|
|
|
if render and love.window and love.graphics and love.window.isCreated() then
|
|
|
|
love.graphics.origin()
|
|
|
|
if love.draw then love.draw() end
|
|
|
|
end
|
|
|
|
|
|
|
|
if love.timer then love.timer.sleep(0.001) end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-08-18 12:00:57 +00:00
|
|
|
function flip_screen()
|
|
|
|
--love.graphics.setShader(__display_shader)
|
2015-08-17 14:47:42 +00:00
|
|
|
love.graphics.setShader(__display_shader)
|
2015-08-18 09:45:04 +00:00
|
|
|
__display_shader:send('palette',unpack(__display_palette))
|
2015-08-16 16:00:39 +00:00
|
|
|
love.graphics.setCanvas()
|
|
|
|
love.graphics.origin()
|
2015-08-17 16:36:58 +00:00
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
love.graphics.setColor(255,255,255,255)
|
|
|
|
love.graphics.setScissor()
|
2015-08-17 14:47:42 +00:00
|
|
|
|
2015-08-18 09:45:04 +00:00
|
|
|
love.graphics.clear()
|
|
|
|
|
2015-08-17 16:36:58 +00:00
|
|
|
local screen_w,screen_h = love.graphics.getDimensions()
|
2015-08-17 14:47:42 +00:00
|
|
|
if screen_w > screen_h then
|
|
|
|
love.graphics.draw(__screen,screen_w/2-64*scale,ypadding*scale,0,scale,scale)
|
|
|
|
else
|
|
|
|
love.graphics.draw(__screen,xpadding*scale,screen_h/2-64*scale,0,scale,scale)
|
|
|
|
end
|
2015-08-17 16:36:58 +00:00
|
|
|
|
2015-08-18 12:00:57 +00:00
|
|
|
love.graphics.present()
|
2015-08-17 16:36:58 +00:00
|
|
|
-- get ready for next time
|
|
|
|
love.graphics.setShader(__draw_shader)
|
2015-08-17 11:14:08 +00:00
|
|
|
love.graphics.setCanvas(__screen)
|
2015-08-18 12:00:57 +00:00
|
|
|
restore_clip()
|
|
|
|
restore_camera()
|
|
|
|
end
|
|
|
|
|
|
|
|
function love.draw()
|
|
|
|
love.graphics.setCanvas(__screen)
|
|
|
|
restore_clip()
|
|
|
|
restore_camera()
|
|
|
|
|
|
|
|
love.graphics.setShader(__draw_shader)
|
|
|
|
|
|
|
|
-- run the cart's draw function
|
|
|
|
if cart._draw then cart._draw() end
|
|
|
|
|
|
|
|
-- draw the contents of pico screen to our screen
|
|
|
|
flip_screen()
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function love.keypressed(key)
|
|
|
|
if key == 'r' and love.keyboard.isDown('lctrl') then
|
2015-08-17 14:47:42 +00:00
|
|
|
reload()
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function music()
|
|
|
|
-- STUB
|
|
|
|
end
|
|
|
|
|
|
|
|
function sfx()
|
|
|
|
-- STUB
|
|
|
|
end
|
|
|
|
|
|
|
|
function clip(x,y,w,h)
|
|
|
|
if x then
|
|
|
|
love.graphics.setScissor(x,y,w,h)
|
2015-08-18 12:00:57 +00:00
|
|
|
__pico_clip = {x,y,w,h}
|
|
|
|
else
|
|
|
|
love.graphics.setScissor(0,0,128,128)
|
|
|
|
__pico_clip = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function restore_clip()
|
|
|
|
if __pico_clip then
|
|
|
|
love.graphics.setScissor(unpack(__pico_clip))
|
2015-08-16 16:00:39 +00:00
|
|
|
else
|
2015-08-17 11:14:08 +00:00
|
|
|
love.graphics.setScissor(0,0,128,128)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function pget(x,y)
|
|
|
|
if x >= 0 and x < 128 and y >= 0 and y < 128 then
|
2015-08-18 12:00:57 +00:00
|
|
|
local r,g,b,a = __screen:getPixel(flr(x),flr(y))
|
|
|
|
return flr(r/17.0)
|
2015-08-16 16:00:39 +00:00
|
|
|
else
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function pset(x,y,c)
|
|
|
|
if not c then return end
|
|
|
|
color(c)
|
2015-08-18 12:00:57 +00:00
|
|
|
love.graphics.point(flr(x),flr(y),c*16,0,0,255)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function sget(x,y)
|
|
|
|
-- return the color from the spritesheet
|
2015-08-17 14:47:42 +00:00
|
|
|
x = flr(x)
|
|
|
|
y = flr(y)
|
|
|
|
local r,g,b,a = __pico_spritesheet_data:getPixel(x,y)
|
|
|
|
return flr(r/16)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function sset(x,y,c)
|
2015-08-17 14:47:42 +00:00
|
|
|
x = flr(x)
|
|
|
|
y = flr(y)
|
|
|
|
__pico_spritesheet_data:setPixel(x,y,c*16,0,0,255)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function fget(n,f)
|
|
|
|
if n == nil then return nil end
|
|
|
|
if f ~= nil then
|
|
|
|
-- return just that bit as a boolean
|
2015-08-17 09:11:50 +00:00
|
|
|
return band(__pico_spriteflags[flr(n)],shl(1,flr(f))) ~= 0
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
2015-08-17 09:11:50 +00:00
|
|
|
return __pico_spriteflags[flr(n)]
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
2015-08-17 09:11:50 +00:00
|
|
|
assert(bit.band(0x01,bit.lshift(1,0)) ~= 0)
|
|
|
|
assert(bit.band(0x02,bit.lshift(1,1)) ~= 0)
|
|
|
|
assert(bit.band(0x04,bit.lshift(1,2)) ~= 0)
|
|
|
|
|
|
|
|
assert(bit.band(0x05,bit.lshift(1,2)) ~= 0)
|
|
|
|
assert(bit.band(0x05,bit.lshift(1,0)) ~= 0)
|
|
|
|
assert(bit.band(0x05,bit.lshift(1,3)) == 0)
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
function fset(n,f,v)
|
2015-08-18 12:00:57 +00:00
|
|
|
-- fset n [f] v
|
|
|
|
-- f is the flag index 0..7
|
|
|
|
-- v is boolean
|
2015-08-16 16:00:39 +00:00
|
|
|
if v == nil then
|
|
|
|
v,f = f,nil
|
|
|
|
end
|
|
|
|
if f then
|
2015-08-18 12:00:57 +00:00
|
|
|
-- set specific bit to v (true or false)
|
|
|
|
if f then
|
|
|
|
__pico_spriteflags[n] = bor(__pico_spriteflags[n],shl(1,f))
|
|
|
|
else
|
|
|
|
__pico_spriteflags[n] = band(bnot(__pico_spriteflags[n],shl(1,f)))
|
|
|
|
end
|
2015-08-16 16:00:39 +00:00
|
|
|
else
|
2015-08-18 12:00:57 +00:00
|
|
|
-- set bitfield to v (number)
|
2015-08-16 16:00:39 +00:00
|
|
|
__pico_spriteflags[n] = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function flip()
|
2015-08-18 12:00:57 +00:00
|
|
|
flip_screen()
|
2015-08-17 03:05:08 +00:00
|
|
|
love.timer.sleep(1/30)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
2015-08-17 03:05:08 +00:00
|
|
|
log = print
|
2015-08-16 16:00:39 +00:00
|
|
|
function print(str,x,y,col)
|
|
|
|
if col then color(col) end
|
2015-08-18 12:00:57 +00:00
|
|
|
if y==nil then
|
|
|
|
y = __pico_cursor[2]
|
|
|
|
__pico_cursor[2] = __pico_cursor[2] + 7
|
|
|
|
end
|
|
|
|
if x==nil then
|
|
|
|
x = __pico_cursor[1]
|
|
|
|
end
|
2015-08-17 14:47:42 +00:00
|
|
|
love.graphics.setShader(__text_shader)
|
2015-08-16 16:00:39 +00:00
|
|
|
love.graphics.print(str,flr(x),flr(y))
|
2015-08-17 14:47:42 +00:00
|
|
|
love.graphics.setShader(__text_shader)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
2015-08-18 12:00:57 +00:00
|
|
|
__pico_cursor = {0,0}
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
function cursor(x,y)
|
|
|
|
__pico_cursor = {x,y}
|
|
|
|
end
|
|
|
|
|
|
|
|
function color(c)
|
|
|
|
c = flr(c)
|
2015-08-18 12:14:35 +00:00
|
|
|
assert(c >= 0 and c <= 16,string.format("c is %s",c))
|
2015-08-16 16:00:39 +00:00
|
|
|
__pico_color = c
|
2015-08-17 14:47:42 +00:00
|
|
|
love.graphics.setColor(c*16,0,0,255)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function cls()
|
|
|
|
__screen:clear(0,0,0,255)
|
|
|
|
end
|
|
|
|
|
2015-08-17 17:04:45 +00:00
|
|
|
__pico_camera_x = 0
|
|
|
|
__pico_camera_y = 0
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
function camera(x,y)
|
|
|
|
if x ~= nil then
|
|
|
|
__pico_camera_x = flr(x)
|
|
|
|
__pico_camera_y = flr(y)
|
2015-08-17 09:11:50 +00:00
|
|
|
else
|
2015-08-16 16:00:39 +00:00
|
|
|
__pico_camera_x = 0
|
|
|
|
__pico_camera_y = 0
|
|
|
|
end
|
2015-08-18 12:00:57 +00:00
|
|
|
restore_camera()
|
|
|
|
end
|
|
|
|
|
|
|
|
function restore_camera()
|
|
|
|
love.graphics.origin()
|
|
|
|
love.graphics.translate(-__pico_camera_x,-__pico_camera_y)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function circ(x,y,r,col)
|
|
|
|
col = col or __pico_color
|
|
|
|
color(col)
|
2015-08-18 12:00:57 +00:00
|
|
|
x = flr(x)
|
|
|
|
y = flr(y)
|
|
|
|
r = flr(r)
|
2015-08-16 16:00:39 +00:00
|
|
|
love.graphics.circle("line",x,y,r,32)
|
|
|
|
end
|
|
|
|
|
|
|
|
function circfill(ox,oy,r,col)
|
|
|
|
col = col or __pico_color
|
|
|
|
color(col)
|
2015-08-17 14:47:42 +00:00
|
|
|
ox = flr(ox)
|
|
|
|
oy = flr(oy)
|
|
|
|
r = flr(r)
|
|
|
|
love.graphics.circle("fill",ox,oy,r,32)
|
|
|
|
--local r2 = r*r
|
|
|
|
--for y=-r,r do
|
|
|
|
-- for x=-r,r do
|
|
|
|
-- if x*x+y*y <= r2 + r*0.8 then
|
|
|
|
-- love.graphics.point(ox+x,oy+y)
|
|
|
|
-- end
|
|
|
|
-- end
|
|
|
|
--end
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
2015-08-17 14:47:42 +00:00
|
|
|
local lineMesh = love.graphics.newMesh(128,nil,"points")
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
function line(x0,y0,x1,y1,col)
|
|
|
|
col = col or __pico_color
|
|
|
|
color(col)
|
|
|
|
|
|
|
|
x0 = flr(x0)
|
|
|
|
y0 = flr(y0)
|
|
|
|
x1 = flr(x1)
|
|
|
|
y1 = flr(y1)
|
|
|
|
|
|
|
|
local dx = x1 - x0
|
|
|
|
local dy = y1 - y0
|
|
|
|
local stepx, stepy
|
|
|
|
|
|
|
|
if dy < 0 then
|
|
|
|
dy = -dy
|
|
|
|
stepy = -1
|
|
|
|
else
|
|
|
|
stepy = 1
|
|
|
|
end
|
2015-08-17 09:11:50 +00:00
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
if dx < 0 then
|
|
|
|
dx = -dx
|
|
|
|
stepx = -1
|
|
|
|
else
|
|
|
|
stepx = 1
|
|
|
|
end
|
2015-08-17 09:11:50 +00:00
|
|
|
|
2015-08-17 14:47:42 +00:00
|
|
|
local points = {{x0,y0}}
|
|
|
|
--love.graphics.point(x0,y0)
|
2015-08-16 16:00:39 +00:00
|
|
|
if dx > dy then
|
|
|
|
local fraction = dy - bit.rshift(dx, 1)
|
|
|
|
while x0 ~= x1 do
|
|
|
|
if fraction >= 0 then
|
|
|
|
y0 = y0 + stepy
|
|
|
|
fraction = fraction - dx
|
|
|
|
end
|
|
|
|
x0 = x0 + stepx
|
|
|
|
fraction = fraction + dy
|
2015-08-17 14:47:42 +00:00
|
|
|
--love.graphics.point(flr(x0),flr(y0))
|
|
|
|
table.insert(points,{flr(x0),flr(y0)})
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
else
|
|
|
|
local fraction = dx - bit.rshift(dy, 1)
|
|
|
|
while y0 ~= y1 do
|
|
|
|
if fraction >= 0 then
|
|
|
|
x0 = x0 + stepx
|
|
|
|
fraction = fraction - dy
|
|
|
|
end
|
|
|
|
y0 = y0 + stepy
|
|
|
|
fraction = fraction + dx
|
2015-08-17 14:47:42 +00:00
|
|
|
--love.graphics.point(flr(x0),flr(y0))
|
|
|
|
table.insert(points,{flr(x0),flr(y0)})
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
end
|
2015-08-17 14:47:42 +00:00
|
|
|
lineMesh:setVertices(points)
|
|
|
|
lineMesh:setDrawRange(1,#points)
|
|
|
|
love.graphics.draw(lineMesh)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
2015-08-17 14:47:42 +00:00
|
|
|
function load(_cartname)
|
2015-08-18 12:00:57 +00:00
|
|
|
love.graphics.setShader(__draw_shader)
|
|
|
|
love.graphics.setCanvas(__screen)
|
|
|
|
love.graphics.origin()
|
|
|
|
restore_clip()
|
2015-08-17 14:47:42 +00:00
|
|
|
cartname = _cartname
|
2015-08-17 11:14:08 +00:00
|
|
|
cart = load_p8(cartname)
|
2015-08-17 09:11:50 +00:00
|
|
|
end
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
function rect(x0,y0,x1,y1,col)
|
|
|
|
col = col or __pico_color
|
|
|
|
color(col)
|
2015-08-18 12:00:57 +00:00
|
|
|
love.graphics.rectangle("line",flr(x0)+1,flr(y0)+1,flr(x1-x0),flr(y1-y0))
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function rectfill(x0,y0,x1,y1,col)
|
|
|
|
col = col or __pico_color
|
|
|
|
color(col)
|
2015-08-18 12:00:57 +00:00
|
|
|
local w = math.abs(x1-x0)+1
|
|
|
|
local h = math.abs(y1-y0)+1
|
|
|
|
love.graphics.rectangle("fill",flr(x0),flr(y0),w,h)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function run()
|
2015-08-17 16:36:58 +00:00
|
|
|
love.graphics.setCanvas(__screen)
|
|
|
|
love.graphics.setShader(__draw_shader)
|
2015-08-18 12:00:57 +00:00
|
|
|
restore_clip()
|
|
|
|
love.graphics.origin()
|
|
|
|
pal()
|
|
|
|
palt()
|
|
|
|
camera()
|
2015-08-17 11:14:08 +00:00
|
|
|
if cart._init then cart._init() end
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function reload()
|
2015-08-17 14:47:42 +00:00
|
|
|
load(cartname)
|
|
|
|
run()
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
2015-08-17 17:04:45 +00:00
|
|
|
local __palette_modified = true
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
function pal(c0,c1,p)
|
|
|
|
if c0 == nil then
|
2015-08-17 17:04:45 +00:00
|
|
|
if __palette_modified == false then return end
|
2015-08-18 09:45:04 +00:00
|
|
|
for i=1,16 do
|
|
|
|
__draw_palette[i] = i
|
|
|
|
__display_palette[i] = __pico_palette[i]
|
2015-08-17 14:47:42 +00:00
|
|
|
end
|
2015-08-18 09:45:04 +00:00
|
|
|
__draw_shader:send('palette',unpack(__draw_palette))
|
|
|
|
__sprite_shader:send('palette',unpack(__draw_palette))
|
|
|
|
__text_shader:send('palette',unpack(__draw_palette))
|
|
|
|
__display_shader:send('palette',unpack(__display_palette))
|
2015-08-17 17:04:45 +00:00
|
|
|
__palette_modified = false
|
2015-08-17 17:08:55 +00:00
|
|
|
elseif p == 1 and c1 ~= nil then
|
2015-08-18 09:45:04 +00:00
|
|
|
c1 = c1+1
|
|
|
|
c0 = c0+1
|
|
|
|
__display_palette[c0] = __pico_palette[c1]
|
|
|
|
__display_shader:send('palette',unpack(__display_palette))
|
2015-08-17 17:04:45 +00:00
|
|
|
__palette_modified = true
|
2015-08-17 17:08:55 +00:00
|
|
|
elseif c1 ~= nil then
|
2015-08-18 09:45:04 +00:00
|
|
|
c1 = c1+1
|
|
|
|
c0 = c0+1
|
|
|
|
__draw_palette[c0] = c1
|
|
|
|
__draw_shader:send('palette',unpack(__draw_palette))
|
|
|
|
__sprite_shader:send('palette',unpack(__draw_palette))
|
|
|
|
__text_shader:send('palette',unpack(__draw_palette))
|
2015-08-17 17:04:45 +00:00
|
|
|
__palette_modified = true
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function palt(c,t)
|
|
|
|
if c == nil then
|
2015-08-18 09:45:04 +00:00
|
|
|
for i=1,16 do
|
|
|
|
__pico_pal_transparent[i] = i == 1 and 0 or 1
|
|
|
|
end
|
2015-08-16 16:00:39 +00:00
|
|
|
else
|
|
|
|
if t == false then
|
2015-08-18 09:45:04 +00:00
|
|
|
__pico_pal_transparent[c+1] = 1
|
2015-08-18 12:00:57 +00:00
|
|
|
elseif t == true then
|
2015-08-18 09:45:04 +00:00
|
|
|
__pico_pal_transparent[c+1] = 0
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
end
|
2015-08-18 09:45:04 +00:00
|
|
|
__sprite_shader:send('transparent',unpack(__pico_pal_transparent))
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function spr(n,x,y,w,h,flip_x,flip_y)
|
|
|
|
love.graphics.setShader(__sprite_shader)
|
2015-08-18 12:00:57 +00:00
|
|
|
__sprite_shader:send('transparent',unpack(__pico_pal_transparent))
|
|
|
|
love.graphics.draw(__pico_spritesheet,__pico_quads[flr(n)],flr(x)+(flip_x and 8 or 0),flr(y),0,flip_x and -1 or 1,flip_y and -1 or 1)
|
2015-08-17 14:47:42 +00:00
|
|
|
love.graphics.setShader(__draw_shader)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function sspr(sx,sy,sw,sh,dx,dy,dw,dh,flip_x,flip_y)
|
2015-08-18 12:00:57 +00:00
|
|
|
-- Stretch rectangle from sprite sheet (sx, sy, sw, sh) // given in pixels
|
|
|
|
-- and draw in rectangle (dx, dy, dw, dh)
|
|
|
|
-- Colour 0 drawn as transparent by default (see palt())
|
|
|
|
-- dw, dh defaults to sw, sh
|
|
|
|
-- flip_x=true to flip horizontally
|
|
|
|
-- flip_y=true to flip vertically
|
2015-08-16 16:00:39 +00:00
|
|
|
dw = dw or sw
|
|
|
|
dh = dh or sh
|
2015-08-17 14:47:42 +00:00
|
|
|
-- FIXME: cache this quad
|
2015-08-18 12:00:57 +00:00
|
|
|
-- FIXME handle flipping
|
|
|
|
local q = love.graphics.newQuad(sx,sy,sw,sh,__pico_spritesheet:getDimensions())
|
2015-08-16 16:00:39 +00:00
|
|
|
love.graphics.setShader(__sprite_shader)
|
2015-08-18 12:00:57 +00:00
|
|
|
__sprite_shader:send('transparent',unpack(__pico_pal_transparent))
|
2015-08-16 16:00:39 +00:00
|
|
|
love.graphics.draw(__pico_spritesheet,q,flr(dx),flr(dy),0,dw/sw,dh/sh)
|
2015-08-17 14:47:42 +00:00
|
|
|
love.graphics.setShader(__draw_shader)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function add(a,v)
|
|
|
|
table.insert(a,v)
|
|
|
|
end
|
|
|
|
|
|
|
|
function del(a,dv)
|
|
|
|
for i,v in ipairs(a) do
|
|
|
|
if v==dv then
|
|
|
|
table.remove(a,i)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function foreach(a,f)
|
|
|
|
for i,v in ipairs(a) do
|
|
|
|
f(v)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function count(a)
|
|
|
|
return #a
|
|
|
|
end
|
|
|
|
|
|
|
|
function all(a)
|
|
|
|
local i = 0
|
|
|
|
local n = table.getn(a)
|
|
|
|
return function()
|
|
|
|
i = i + 1
|
|
|
|
if i <= n then return a[i] end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local __pico_keypressed = {
|
|
|
|
[0] = {},
|
|
|
|
[1] = {}
|
|
|
|
}
|
|
|
|
|
|
|
|
local __keymap = {
|
|
|
|
[0] = {
|
|
|
|
[0] = 'left',
|
|
|
|
[1] = 'right',
|
|
|
|
[2] = 'up',
|
|
|
|
[3] = 'down',
|
|
|
|
[4] = 'z',
|
|
|
|
[5] = 'x',
|
|
|
|
},
|
|
|
|
[1] = {
|
|
|
|
[4] = 'escape',
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function btn(i,p)
|
|
|
|
p = p or 0
|
|
|
|
if __keymap[p][i] then
|
|
|
|
return love.keyboard.isDown(__keymap[p][i])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function btnp(i,p)
|
|
|
|
p = p or 0
|
|
|
|
if __keymap[p][i] then
|
|
|
|
local id = love.keyboard.isDown(__keymap[p][i])
|
|
|
|
if __pico_keypressed[p][i] and __pico_keypressed[p][i] > 0 then
|
|
|
|
__pico_keypressed[p][i] = __pico_keypressed[p][i] - 1
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
if id then
|
|
|
|
__pico_keypressed[p][i] = 12
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function sfx(n,channel,offset)
|
|
|
|
end
|
|
|
|
|
|
|
|
function music(n,fade_len,channel_mask)
|
|
|
|
end
|
|
|
|
|
|
|
|
function mget(x,y)
|
|
|
|
if x == nil or y == nil then return nil end
|
|
|
|
if y > 63 or x > 127 or x < 0 or y < 0 then return nil end
|
|
|
|
return __pico_map[flr(y)][flr(x)]
|
|
|
|
end
|
|
|
|
|
|
|
|
function mset(x,y,v)
|
|
|
|
if x >= 0 and x < 128 and y >= 0 and y < 64 then
|
|
|
|
__pico_map[flr(y)][flr(x)] = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function map(cel_x,cel_y,sx,sy,cel_w,cel_h,bitmask)
|
|
|
|
love.graphics.setShader(__sprite_shader)
|
|
|
|
love.graphics.setColor(255,255,255,255)
|
2015-08-17 09:11:50 +00:00
|
|
|
cel_x = flr(cel_x)
|
|
|
|
cel_y = flr(cel_y)
|
|
|
|
sx = flr(sx)
|
|
|
|
sy = flr(sy)
|
|
|
|
cel_w = flr(cel_w)
|
|
|
|
cel_h = flr(cel_h)
|
2015-08-18 12:00:57 +00:00
|
|
|
for y=0,cel_h-1 do
|
|
|
|
--if y < 64 and y >= 0 then
|
|
|
|
for x=0,cel_w-1 do
|
|
|
|
--if x < 128 and x >= 0 then
|
|
|
|
local v = __pico_map[flr(cel_y+y)][flr(cel_x+x)]
|
2015-08-17 11:14:08 +00:00
|
|
|
if v > 0 then
|
2015-08-18 12:00:57 +00:00
|
|
|
if bitmask == nil or bitmask == 0 then
|
2015-08-17 11:14:08 +00:00
|
|
|
love.graphics.draw(__pico_spritesheet,__pico_quads[v],sx+8*x,sy+8*y)
|
|
|
|
else
|
|
|
|
if band(__pico_spriteflags[v],bitmask) ~= 0 then
|
|
|
|
love.graphics.draw(__pico_spritesheet,__pico_quads[v],sx+8*x,sy+8*y)
|
|
|
|
else
|
|
|
|
end
|
|
|
|
end
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
2015-08-18 12:00:57 +00:00
|
|
|
--end
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
2015-08-18 12:00:57 +00:00
|
|
|
--end
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
2015-08-18 09:45:04 +00:00
|
|
|
love.graphics.setShader(__draw_shader)
|
2015-08-16 16:00:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- memory functions excluded
|
|
|
|
|
|
|
|
function memcpy(dest_addr,source_addr,len)
|
|
|
|
-- only for range 0x6000+0x8000
|
|
|
|
if source_addr >= 0x6000 and dest_addr >= 0x6000 then
|
|
|
|
if source_addr + len >= 0x8000 then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
if dest_addr + len >= 0x8000 then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local img = __screen:getImageData()
|
|
|
|
for i=1,len do
|
|
|
|
local x = flr(source_addr-0x6000+i)%128
|
|
|
|
local y = flr((source_addr-0x6000+i)/64)
|
2015-08-17 14:47:42 +00:00
|
|
|
local c = flr(img:getPixel(x,y)/16)
|
2015-08-16 16:00:39 +00:00
|
|
|
|
|
|
|
local dx = flr(dest_addr-0x6000+i)%128
|
|
|
|
local dy = flr((dest_addr-0x6000+i)/64)
|
|
|
|
pset(dx,dy,c)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function peek(...)
|
|
|
|
end
|
|
|
|
|
|
|
|
function poke(...)
|
|
|
|
end
|
|
|
|
|
|
|
|
max = math.max
|
|
|
|
min = math.min
|
|
|
|
function mid(x,y,z)
|
|
|
|
return x > y and x or y > z and z or y
|
|
|
|
end
|
|
|
|
|
|
|
|
assert(mid(1,5,6) == 5)
|
|
|
|
assert(mid(3,2,6) == 3)
|
|
|
|
assert(mid(3,9,6) == 6)
|
|
|
|
|
|
|
|
function __pico_angle(a)
|
|
|
|
-- FIXME: why does this work?
|
|
|
|
return (((a - math.pi) / (math.pi*2)) + 0.25) % 1.0
|
|
|
|
end
|
|
|
|
|
|
|
|
flr = math.floor
|
2015-08-18 12:14:35 +00:00
|
|
|
cos = function(x) return math.cos((x or 0)*(math.pi*2)) end
|
|
|
|
sin = function(x) return math.sin(-(x or 0)*(math.pi*2)) end
|
2015-08-16 16:00:39 +00:00
|
|
|
atan2 = function(y,x) return __pico_angle(math.atan2(y,x)) end
|
|
|
|
|
|
|
|
sqrt = math.sqrt
|
|
|
|
abs = math.abs
|
|
|
|
rnd = function(x) return love.math.random()*x end
|
|
|
|
srand = love.math.randomseed
|
|
|
|
sgn = function(x)
|
|
|
|
if x < 0 then
|
|
|
|
return -1
|
|
|
|
elseif x > 0 then
|
|
|
|
return 1
|
|
|
|
else
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-08-17 11:14:08 +00:00
|
|
|
assert(sgn(-10) == -1)
|
|
|
|
assert(sgn(10) == 1)
|
|
|
|
assert(sgn(0) == 0)
|
|
|
|
|
2015-08-16 16:00:39 +00:00
|
|
|
local bit = require("bit")
|
|
|
|
|
|
|
|
band = bit.band
|
|
|
|
bor = bit.bor
|
|
|
|
bxor = bit.bxor
|
|
|
|
bnot = bit.bnot
|
|
|
|
shl = bit.lshift
|
|
|
|
shr = bit.rshift
|
|
|
|
|
|
|
|
sub = string.sub
|
2015-08-17 14:47:42 +00:00
|
|
|
|
2015-08-18 12:14:35 +00:00
|
|
|
function stat(x)
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
|
2015-08-17 14:47:42 +00:00
|
|
|
love.graphics.point = function(x,y)
|
|
|
|
love.graphics.rectangle('fill',x,y,1,1)
|
|
|
|
end
|