diff --git a/api.lua b/api.lua index 1342ac7..c0036cb 100644 --- a/api.lua +++ b/api.lua @@ -344,10 +344,10 @@ function api.line(x0, y0, x1, y1, col) end function api.pal(c0, c1, p) + local __palette_modified=false + local __display_modified=false + local __alpha_modified=false if c0==nil then - local __palette_modified=false - local __display_modified=false - local __alpha_modified=false for i=0, 15 do if pico8.draw_palette[i]~=i then pico8.draw_palette[i]=i @@ -363,34 +363,45 @@ function api.pal(c0, c1, p) __alpha_modified=true end end - if __palette_modified then - pico8.draw_shader:send('palette', shdr_unpack(pico8.draw_palette)) - pico8.sprite_shader:send('palette', shdr_unpack(pico8.draw_palette)) - pico8.text_shader:send('palette', shdr_unpack(pico8.draw_palette)) - end - if __display_modified then - pico8.display_shader:send('palette', shdr_unpack(pico8.display_palette)) - end - if __alpha_modified then - pico8.sprite_shader:send('transparent', shdr_unpack(pico8.pal_transparent)) + elseif type(c0)=="table" then + if not c1 or c1==0 then + __palette_modified=true + for i,v in pairs(c0) do + pico8.draw_palette[i]=v or i + end + elseif c1==1 then + __display_modified = true + for i,v in pairs(c0) do + pico8.display_palette[i]=v and pico8.palette[v+1] or pico8.palette[i+1] + end end elseif p==1 and c1~=nil then c0=flr(c0)%16 c1=flr(c1)%16 if pico8.draw_palette[c0]~=pico8.palette[c1+1] then pico8.display_palette[c0]=pico8.palette[c1+1] - pico8.display_shader:send('palette', shdr_unpack(pico8.display_palette)) + __display_modified = true end elseif c1~=nil then c0=flr(c0)%16 c1=flr(c1)%16 if pico8.draw_palette[c0]~=c1 then pico8.draw_palette[c0]=c1 - pico8.draw_shader:send('palette', shdr_unpack(pico8.draw_palette)) - pico8.sprite_shader:send('palette', shdr_unpack(pico8.draw_palette)) - pico8.text_shader:send('palette', shdr_unpack(pico8.draw_palette)) + __palette_modified = true end end + + if __palette_modified then + pico8.draw_shader:send('palette', shdr_unpack(pico8.draw_palette)) + pico8.sprite_shader:send('palette', shdr_unpack(pico8.draw_palette)) + pico8.text_shader:send('palette', shdr_unpack(pico8.draw_palette)) + end + if __display_modified then + pico8.display_shader:send('palette', shdr_unpack(pico8.display_palette)) + end + if __alpha_modified then + pico8.sprite_shader:send('transparent', shdr_unpack(pico8.pal_transparent)) + end end function api.palt(c, t) @@ -405,8 +416,28 @@ function api.palt(c, t) pico8.sprite_shader:send('transparent', shdr_unpack(pico8.pal_transparent)) end -function api.fillp(p) - -- TODO: oh jeez +local function convertFillp(n) + local t = {} + for i = 31, 0, -1 do + n = bit.rol(n, 1) + if (i>15) then + t[16+31-i] = 1-bit.band(n, 1) + else + t[15-i] = 1-bit.band(n, 1) + end + end + return t +end + +function api.fillp(p) --@todo: implement colors bits/transparency and all the new stuff + p=p or 0 + if math.fmod(p, 1)~=0 then + pico8.draw_shader:send('opaque', 0) + else + pico8.draw_shader:send('opaque', 1) + end + pico8.fillp = convertFillp(flr(p)) + pico8.draw_shader:send('fillp', shdr_unpack(pico8.fillp)) end function api.map(cel_x, cel_y, sx, sy, cel_w, cel_h, bitmask) @@ -642,6 +673,8 @@ function api.peek(addr) local val=api.dget(math.floor((addr-0x5e00)/4))*0x10000 local shift=(addr%4)*8 return bit.rshift(bit.band(val, bit.lshift(0xFF, shift)), shift) + elseif addr<0x5f40 then + -- TODO: Draw state elseif addr<0x5f80 then -- TODO: Hardware state if addr==0x5f26 then @@ -729,8 +762,10 @@ function api.poke(addr, val) local oval=api.dget(ind)*0x10000 local shift=(addr%4)*8 api.dset(ind, bit.bor(bit.band(oval, bit.bnot(bit.lshift(0xFF, shift))), bit.lshift(val, shift))/0x10000) - elseif addr<0x5f80 then - -- FIXME: Draw state + elseif addr<0x5f40 then + -- TODO: Draw state + elseif addr<0x5f80 then + -- TODO: Hardware state elseif addr<0x5fc0 then -- FIXME: Persistence data elseif addr<0x6000 then @@ -1141,7 +1176,19 @@ function api.holdframe() -- TODO: Implement this end -function api.menuitem() +function api.menuitem(index,label,callback) + if not index or index<1 or index >5 then return end + if label==nil or callback==nil then + pico8.custom_menu[index] = nil + else + pico8.custom_menu[index] = {string.sub(label,1,16), callback} + end + + local tot=0 + for i=1,5 do + if pico8.custom_menu[i]~=nil then tot=tot+1 end + end + pico8.custom_menu[0] = tot end api.sub=string.sub diff --git a/main.lua b/main.lua index eee9e14..15f49ca 100644 --- a/main.lua +++ b/main.lua @@ -2,18 +2,18 @@ pico8={ fps=30, resolution={128, 128}, palette={ - {0, 0, 0, 255}, + {0, 0, 0, 255}, {29, 43, 83, 255}, {126,37, 83, 255}, - {0, 135,81, 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, 0, 77, 255}, + {255,163,0, 255}, {255,240,36, 255}, - {0, 231,86, 255}, + {0, 231, 86, 255}, {41, 173,255,255}, {131,118,156,255}, {255,119,168,255}, @@ -66,6 +66,8 @@ pico8={ draw_palette={}, display_palette={}, pal_transparent={}, + fillp = {[0]=1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + custom_menu={[0]=0,nil,nil,nil,nil,nil} } require("strict") @@ -311,14 +313,36 @@ function love.load(argv) end pico8.draw_shader=love.graphics.newShader(pishaderfix([[ - extern float palette[16]; + extern float palette[16]; + extern float fillp[16]; + extern float opaque; - vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) { - int index=int(color.r*15.0+0.5); - ifblock(palette); - return vec4(palette[index]/15.0, 0.0, 0.0, 1.0); - }]])) + vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) { + int index=int(color.r*15.0+0.5); + ifblock(palette); + ifblock(fillp); + ifblock(opaque); + + int i = int(mod(screen_coords.y,4))*4+int(mod(screen_coords.x,4)); + + float alpha = fillp[i]; + + if (opaque == 0) { + return vec4(palette[index]/15.0, 0.0, 0.0, alpha); + } + else if (alpha == 1) { + return vec4(palette[index]/15.0, 0.0, 0.0, 1); + } + else { + return vec4(0,0,0,1); + } + + return vec4(palette[index]/15.0, 0.0, opaque, alpha); + + }]])) pico8.draw_shader:send('palette', shdr_unpack(pico8.draw_palette)) + pico8.draw_shader:send('fillp', shdr_unpack(pico8.fillp)) + pico8.draw_shader:send('opaque', 1) pico8.sprite_shader=love.graphics.newShader(pishaderfix([[ extern float palette[16]; @@ -487,21 +511,32 @@ function flip_screen() love.graphics.draw(pico8.screen, xpadding, ypadding, 0, scale, scale) end - if paused then --draw pico8 paused menu bypassing any userdefined palette - love.graphics.setShader() - love.graphics.scale(scale,scale) - love.graphics.setColor(0, 0, 0, 1) - love.graphics.rectangle("fill", 24, 44, 130-48, 118-76) - love.graphics.setColor(1, 1, 1, 1) - love.graphics.rectangle("fill", 25, 45, 128-48, 116-76) - love.graphics.setColor(0, 0, 0, 1) - love.graphics.rectangle("fill", 26, 46, 126-48, 114-76) - love.graphics.setColor(1, 1, 1, 1) - for l=0,3 do - if l==paused_selected then menu_print(">", 28, 50+8*l) end - menu_print(paused_menu[l+1][1], 35, 50+8*l) - end - end + if paused then --draw pico8 paused menu bypassing any userdefined palette + local height = 118-76+pico8.custom_menu[0]*8 + local pad_y = flr((128-height)/2) + love.graphics.setShader() + love.graphics.scale(scale,scale) + love.graphics.setColor(0, 0, 0, 1) + love.graphics.rectangle("fill", 23, pad_y, 130-48, height) + love.graphics.setColor(1, 1, 1, 1) + love.graphics.rectangle("fill", 24, pad_y+1, 128-48, height-2) + love.graphics.setColor(0, 0, 0, 1) + love.graphics.rectangle("fill", 25, pad_y+2, 126-48, height-4) + love.graphics.setColor(1, 1, 1, 1) + pad_y = pad_y+6 + for l=0,3 do + if l==paused_selected then menu_print(">", 27, pad_y+8*l) end + menu_print(paused_menu[l+1][1], 34, pad_y+8*l) + end + local pos=1 + for l=1,5 do + if l+3==paused_selected then menu_print(">", 27, pad_y+8*(l+3)) end + if pico8.custom_menu[l] then + menu_print(pico8.custom_menu[l][1], 34, pad_y+8*(pos+3)) + pos=pos+1 + end + end + end if gif_recording then love.graphics.setCanvas(gif_canvas) @@ -686,18 +721,38 @@ local function isCtrlOrGuiDown() end function love.keypressed(key) - log(key) - if paused then - if key=='z' or key=='x' or key=='c' or key=='v' or key=='return' then - local handler = paused_menu[paused_selected+1][2] - if handler then handler() end - elseif key=='up' then - paused_selected=(paused_selected-1)%4 - elseif key=='down' then - paused_selected=(paused_selected+1)%4 - elseif key=='pause' or key=='p' then - paused=false - end + if paused then + if key=='z' or key=='x' or key=='c' or key=='v' or key=='return' then + local handler + if paused_selected<4 then + handler = paused_menu[paused_selected+1][2] + else + local pos=1 + for l=1,5 do + if pos+3==paused_selected then + if pico8.custom_menu[l] then + handler = pico8.custom_menu[l][2] + break + end + else + pos=pos+1 + end + end + end + if handler then + local b = 0 --@todo: The callback takes a single parameter that is a bitfield of L,R,X button presses + if handler(b)==true then + else + paused=false + end + end + elseif key=='up' then + paused_selected=(paused_selected-1)%(4+pico8.custom_menu[0]) + elseif key=='down' then + paused_selected=(paused_selected+1)%(4+pico8.custom_menu[0]) + elseif key=='pause' or key=='p' then + paused=false + end else if key=='r' and isCtrlOrGuiDown() then api.music()