mirror of
https://github.com/g012/l65.git
synced 2024-12-22 01:29:59 +00:00
Added image importers for VCS.
This commit is contained in:
parent
def316e982
commit
ae256b8e2c
@ -63,7 +63,7 @@ else ()
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
|
||||
add_compile_options(-fno-strict-aliasing -fomit-frame-pointer -ffast-math -fvisibility=hidden)
|
||||
add_compile_options(-Wsign-compare -Wno-missing-braces -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-parentheses)
|
||||
add_compile_options(-Wsign-compare -Wno-missing-braces -Wno-unused-result -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-parentheses)
|
||||
|
||||
endif()
|
||||
|
||||
@ -75,6 +75,7 @@ set(L65_SOURCES
|
||||
set(L65_HEADERS
|
||||
${L65_SOURCE_DIR}/lua.h
|
||||
${L65_BINARY_DIR}/scripts.h
|
||||
${L65_SOURCE_DIR}/stb_image.h
|
||||
)
|
||||
set(L65_RESOURCES
|
||||
${L65_SOURCE_DIR}/6502.lua
|
||||
|
@ -52,10 +52,11 @@ make
|
||||
## Credits
|
||||
|
||||
Developed by g012, using:
|
||||
* [Lua 5.3.4](https://www.lua.org/)
|
||||
* [Lua 5.3.4](https://www.lua.org)
|
||||
* [LuaMinify](https://github.com/stravant/LuaMinify)
|
||||
* Lua syntax file shipping with [vim](http://www.vim.org)
|
||||
* Lua indent file from [vim-lua](https://github.com/tbastos/vim-lua)
|
||||
* [stb_image](https://github.com/nothings/stb)
|
||||
|
||||
Not using, but integrated for end-user convenience:
|
||||
* [LuaFileSystem](https://keplerproject.github.io/luafilesystem)
|
||||
|
3
l65.lua
3
l65.lua
@ -2526,7 +2526,7 @@ if #dirl65 > 0 then
|
||||
searchl65 = string.format(";%s?;%s?.l65", dirl65, dirl65)
|
||||
package.path = package.path .. string.format(";%s?.lua", dirl65)
|
||||
end
|
||||
l65 = {
|
||||
l65_def = {
|
||||
parse = ParseLua,
|
||||
format = Format65,
|
||||
searcher_index = 2,
|
||||
@ -2535,6 +2535,7 @@ l65 = {
|
||||
loadfile_org = loadfile,
|
||||
dofile_org = dofile,
|
||||
}
|
||||
if not l65 then l65 = l65_def else for k,v in pairs(l65_def) do l65[k]=v end end
|
||||
l65.report = function(success, ...)
|
||||
if success then return success,... end
|
||||
local message=... io.stderr:write(message..'\n')
|
||||
|
135
main.c
135
main.c
@ -1,3 +1,12 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_ONLY_PNG
|
||||
#define STBI_NO_FAILURE_STRINGS
|
||||
#include "stb_image.h"
|
||||
|
||||
#define LUA_IMPLEMENTATION
|
||||
#include "lua.h"
|
||||
#include "scripts.h"
|
||||
@ -5,6 +14,131 @@
|
||||
extern int luaopen_lpeg(lua_State *L);
|
||||
extern int luaopen_lfs(lua_State *L);
|
||||
|
||||
// l65 lib
|
||||
static int r_s32be(uint8_t **b) { uint8_t *p = *b; int v = ((int)(p[0]))<<24 | ((int)(p[1]))<<16 | ((int)p[2])<<8 | p[3]; *b += 4; return v; }
|
||||
typedef struct { int len, nam; } chunk_s;
|
||||
static chunk_s r_chunk(uint8_t **b) { int len = r_s32be(b), nam = r_s32be(b); chunk_s c = { len, nam }; return c; }
|
||||
static int open_image(lua_State *L)
|
||||
{
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
FILE *file = fopen(filename, "rb");
|
||||
if (!file)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "failed to open file %s", filename);
|
||||
return 2;
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
size_t sz = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
uint8_t *png = malloc(sz);
|
||||
fread(png, sz, 1, file);
|
||||
fclose(file);
|
||||
static uint8_t png_sig[8] = { 137,80,78,71,13,10,26,10 };
|
||||
if (memcmp(png, png_sig, 8) != 0)
|
||||
{
|
||||
free(png);
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "file %s is not a PNG", filename);
|
||||
return 2;
|
||||
}
|
||||
uint8_t *b = png + 8;
|
||||
int w, h;
|
||||
uint8_t *d = 0; long d_sz = 0;
|
||||
#define CHUNK_NAM(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
|
||||
for (;;)
|
||||
{
|
||||
chunk_s chunk = r_chunk(&b);
|
||||
switch (chunk.nam)
|
||||
{
|
||||
case CHUNK_NAM('I','H','D','R'): {
|
||||
w = r_s32be(&b); h = r_s32be(&b);
|
||||
if (b[0] != 8 || b[1] != 3)
|
||||
{
|
||||
free(png);
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "PNG file %s must be 8b indexed", filename);
|
||||
return 2;
|
||||
}
|
||||
b += 9;
|
||||
} break;
|
||||
case CHUNK_NAM('I','D','A','T'): {
|
||||
d = realloc(d, d_sz + chunk.len);
|
||||
memcpy(d + d_sz, b, chunk.len);
|
||||
d_sz += chunk.len;
|
||||
b += chunk.len+4;
|
||||
} break;
|
||||
case CHUNK_NAM('I','E','N','D'): {
|
||||
free(png);
|
||||
if (!d)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "invalid PNG file %s", filename);
|
||||
return 2;
|
||||
}
|
||||
int px_sz;
|
||||
uint8_t *px_raw = (uint8_t*)stbi_zlib_decode_malloc_guesssize_headerflag((void*)d, d_sz, (w+1) * h, &px_sz, 1);
|
||||
free(d);
|
||||
uint8_t *px = calloc(w,h);
|
||||
uint8_t *px0 = px, *px_raw0 = px_raw;
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
int filter = *px_raw++;
|
||||
#define prev (x==0 ? 0 : px[x-1])
|
||||
#define up (px[x-w])
|
||||
#define prevup (x==0 ? 0 : px[x-w-1])
|
||||
switch (filter)
|
||||
{
|
||||
case 0: memcpy(px, px_raw, w); break;
|
||||
case 1: for (int x = 0; x < w; ++x) { px[x] = px_raw[x] + prev; } break;
|
||||
case 2: for (int x = 0; x < w; ++x) { px[x] = px_raw[x] + up; } break;
|
||||
case 3: for (int x = 0; x < w; ++x) { px[x] = px_raw[x] + ((prev+up)>>1); } break;
|
||||
case 4: for (int x = 0; x < w; ++x) { px[x] = px_raw[x] + stbi__paeth(prev,up,prevup); } break;
|
||||
}
|
||||
#undef prev
|
||||
#undef up
|
||||
#undef prevup
|
||||
px += w;
|
||||
px_raw += w;
|
||||
}
|
||||
STBI_FREE(px_raw0);
|
||||
|
||||
lua_createtable(L, w*h, 3);
|
||||
lua_pushstring(L, filename);
|
||||
lua_setfield(L, -2, "filename");
|
||||
lua_pushinteger(L, w);
|
||||
lua_setfield(L, -2, "width");
|
||||
lua_pushinteger(L, h);
|
||||
lua_setfield(L, -2, "height");
|
||||
for (int i = 0; i < w*h; ++i)
|
||||
{
|
||||
lua_pushinteger(L, px0[i]);
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
free(px0);
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
b += chunk.len+4;
|
||||
}
|
||||
}
|
||||
#undef CHUNK_NAM
|
||||
if (d) free(d);
|
||||
free(png);
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "invalid PNG file %s", filename);
|
||||
return 2;
|
||||
}
|
||||
static const struct luaL_Reg l65lib[] = {
|
||||
{"image", open_image},
|
||||
{NULL, NULL},
|
||||
};
|
||||
static int luaopen_l65(lua_State *L)
|
||||
{
|
||||
luaL_newlib(L, l65lib);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct script { const char *name; int t; const char *data; size_t sz; } embedded[] = {
|
||||
{ "l65cfg", 0, script_l65cfg_lua, sizeof(script_l65cfg_lua) },
|
||||
{ "vcs", 1, script_vcs_l65, sizeof(script_vcs_l65) },
|
||||
@ -44,6 +178,7 @@ int main(int argc, char *argv[])
|
||||
luaL_openlibs(L);
|
||||
luaL_requiref(L, "lpeg", luaopen_lpeg, 1); lua_pop(L, 1);
|
||||
luaL_requiref(L, "lfs", luaopen_lfs, 1); lua_pop(L, 1);
|
||||
luaL_requiref(L, "l65", luaopen_l65, 1); lua_pop(L, 1);
|
||||
|
||||
// preload embedded lua scripts
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
||||
|
7187
stb_image.h
Normal file
7187
stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
81
vcs.l65
81
vcs.l65
@ -372,3 +372,84 @@ mappers.X07 = function()
|
||||
section{"vectors"..bi, org=o+0xffc} dc.w start if mappers.irq then dc.w start end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Image converters
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
image_scan = function(img, opt)
|
||||
local r, b, flipx, flipy, xinc, yinc, x0, y0, x1, y1, width, height = {}, {}
|
||||
xinc=opt.xinc or 1 x0=opt.x0 or 0 x1=opt.x1 or img.width-1
|
||||
yinc=opt.yinc or 1 y0=opt.y0 or 0 y1=opt.y1 or img.height-1
|
||||
if x1<x0 and xinc<0 then x0,x1=x1,x0 xinc=-xinc flipx=true end
|
||||
if y1<y0 and yinc<0 then y0,y1=y1,y0 yinc=-yinc flipy=true end
|
||||
assert(y1>=y0 and x1>=x0 and x1<img.width and y1<img.height, "invalid dimensions")
|
||||
width = 1 + (x1 - x0) // xinc
|
||||
height = 1 + (y1 - y0) // yinc
|
||||
for y=y0,y1,yinc do for x=x0,x1,xinc do b[#b+1] = img[y*img.width+x] end end
|
||||
if flipx then for y=0,height-1 do for x=0,width//2-1 do
|
||||
local i0, i1 = y*width+x, y*height+width-1
|
||||
b[i0], b[i1] = b[i1], b[i0]
|
||||
end end end
|
||||
if flipy then for y=0,height//2-1 do for x=0,width-1 do
|
||||
local i0, i1 = y*width+x, (height-1-y)*width+x
|
||||
b[i0], b[i1] = b[i1], b[i0]
|
||||
end end end
|
||||
return b, width, height
|
||||
end
|
||||
|
||||
linecol = function(opt)
|
||||
if type(opt) ~= 'table' then opt = { opt } end
|
||||
local image = opt.image or assert(l65.image(opt.filename or opt[1]))
|
||||
local b,w,h = image_scan(image, opt)
|
||||
local lc = {}
|
||||
for y=0,h-1 do
|
||||
lc[#lc+1] = 0
|
||||
for x=0,w-1 do
|
||||
local col = b[y*w + x]
|
||||
if col ~= 0 then lc[#lc]=col break end
|
||||
end
|
||||
end
|
||||
return lc
|
||||
end
|
||||
|
||||
playfield = function(opt)
|
||||
if type(opt) ~= 'table' then opt = { opt } end
|
||||
local image = opt.image or assert(l65.image(opt.filename or opt[1]))
|
||||
local b,w,h = image_scan(image, opt)
|
||||
local pf={} for i=1,6 do pf[i]={} end
|
||||
for y=1,h do
|
||||
local x = \o,s((b[(y-1)*w+o]==0 and 0 or 1)<<s)
|
||||
pf[1][y] = x( 0,4)|x( 1,5)|x( 2,6)|x( 3,7)
|
||||
pf[2][y] = x( 4,7)|x( 5,6)|x( 6,5)|x( 7,4)|x( 8,3)|x( 9,2)|x(10,1)|x(11,0)
|
||||
pf[3][y] = x(12,0)|x(13,1)|x(14,2)|x(15,3)|x(16,4)|x(17,5)|x(18,6)|x(19,7)
|
||||
pf[4][y] = x(20,4)|x(21,5)|x(22,6)|x(23,7)
|
||||
pf[5][y] = x(24,7)|x(25,6)|x(26,5)|x(27,4)|x(28,3)|x(29,2)|x(30,1)|x(31,0)
|
||||
pf[6][y] = x(32,0)|x(33,1)|x(34,2)|x(35,3)|x(36,4)|x(37,5)|x(38,6)|x(39,7)
|
||||
end
|
||||
if opt.reverse then
|
||||
for _,col in ipairs(pf) do for y=1,h do col[y] = col[y] ~ 0xff end end
|
||||
end
|
||||
return pf
|
||||
end
|
||||
|
||||
sprite = function(opt)
|
||||
if type(opt) ~= 'table' then opt = { opt } end
|
||||
local image = opt.image or assert(l65.image(opt.filename or opt[1]))
|
||||
local b,w,h = image_scan(image, opt)
|
||||
local sp={}
|
||||
for c=0,((w+7)//8-1) do
|
||||
local s={} sp[#sp+1]=s
|
||||
for y=0,h-1 do
|
||||
local o=c*8
|
||||
local e=o+7 > w and w-1 or o+7
|
||||
local i,color = 7,0
|
||||
for x=o,e do
|
||||
if b[y*w+x] ~= 0 then color = color | 1<<i end
|
||||
i = i-1
|
||||
end
|
||||
s[#s+1] = color
|
||||
end
|
||||
end
|
||||
return sp
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user