From d189e66b125d3ad7fce76c8bc073da4ec4eb9215 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Sat, 17 Mar 2012 23:00:18 +0100 Subject: [PATCH 01/45] Re-do of Joystick support: dynamic alloc, reset --- framebuffer.c | 2 +- framebuffer.h | 4 ++ load81.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 151 insertions(+), 3 deletions(-) diff --git a/framebuffer.c b/framebuffer.c index 65ced77..8bf5213 100644 --- a/framebuffer.c +++ b/framebuffer.c @@ -8,7 +8,7 @@ SDL_Surface *sdlInit(int width, int height, int bpp, int fullscreen) { SDL_Surface *screen; if (fullscreen) flags |= SDL_FULLSCREEN; - if (SDL_Init(SDL_INIT_VIDEO) == -1) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) == -1) { fprintf(stderr, "SDL Init error: %s\n", SDL_GetError()); return NULL; } diff --git a/framebuffer.h b/framebuffer.h index 0a20367..91e662d 100644 --- a/framebuffer.h +++ b/framebuffer.h @@ -14,10 +14,14 @@ #define FONT_HEIGHT 16 #define FONT_KERNING 10 +/* This is the maximum number of joysticks we will allow LOAD81 to deal with */ +#define MAX_JOYSTICKS 8 + typedef struct frameBuffer { int width; int height; SDL_Surface *screen; + SDL_Joystick *joysticks[MAX_JOYSTICKS]; /* Joystick handles are held per-screen */ FPSmanager fps_mgr; } frameBuffer; diff --git a/load81.c b/load81.c index 0450cdb..2f3091d 100644 --- a/load81.c +++ b/load81.c @@ -78,6 +78,72 @@ lua_Number getNumber(char *name) { return n; } + +/* update the table_name[] table, at index, by given field, to num + e.g. table_name[1].x = 100 + stack: + table_name global + [1] index + .x field + = 100 number +*/ +void setArrayFieldNumber( char *table_name, int index, char *field, int number) +{ + lua_getglobal(l81.L, table_name); + + /* Create new if needed */ + if (lua_isnil(l81.L,-1)) { + lua_pop(l81.L,1); + lua_newtable(l81.L); + lua_setglobal(l81.L, table_name); + lua_getglobal(l81.L, table_name); + } + + /* lua: table_named[index].field = value */ + if (lua_istable(l81.L, -1)) { + lua_pushnumber(l81.L, index); + /* get table for modification */ + lua_gettable(l81.L, -2); + lua_pushstring(l81.L, field); + lua_pushnumber(l81.L, number); + lua_settable(l81.L, -3); + } + + lua_pop(l81.L, 2); +} + +/* + update the table_name[] table, .name field + e.g. table_name[1].name = "nub0" + stack: + table_name global + [1] joynum + .name field + = "nub0" value +*/ +void setArrayFieldString(char *table_name, int index, char *field, const char *value) +{ + lua_getglobal(l81.L, table_name); + if (lua_isnil(l81.L,-1)) { + lua_pop(l81.L,1); + lua_newtable(l81.L); + lua_setglobal(l81.L,table_name); + lua_getglobal(l81.L,table_name); + } + + if (lua_istable(l81.L, -1)) { + lua_pushnumber(l81.L, index); + /* get table for modification */ + lua_gettable(l81.L, -2); + lua_pushstring(l81.L, field); + lua_pushstring(l81.L, value); + lua_settable(l81.L, -3); + } + + lua_pop(l81.L, 2); +} + + /* Set a Lua global table field to the value on the top of the Lua stack. */ void setTableField(char *name, char *field) { lua_getglobal(l81.L,name); /* Stack: val table */ @@ -328,6 +394,18 @@ void mouseButtonEvent(int button, int pressed) { updatePressedState("mouse",buttonname,pressed); } +void joystickXMovedEvent(int joy_num, Sint16 x) { + if (joy_num < MAX_JOYSTICKS) { + setArrayFieldNumber("joystick", joy_num, "x", x); + } +} + +void joystickYMovedEvent(int joy_num, Sint16 y) { + if (joy_num < MAX_JOYSTICKS) { + setArrayFieldNumber("joystick", joy_num, "y", y); + } +} + void resetEvents(void) { setTableFieldString("keyboard","state","none"); setTableFieldString("keyboard","key",""); @@ -372,6 +450,15 @@ int processSdlEvents(void) { case SDL_MOUSEBUTTONUP: mouseButtonEvent(event.button.button,0); break; + case SDL_JOYAXISMOTION: /* Handle Joystick Motion */ + if( event.jaxis.axis == 0) { /* x-axis */ + joystickXMovedEvent(event.jaxis.which + 1, event.jaxis.value); /* C vs. Lua offsets */ + } + if( event.jaxis.axis == 1) { /* y-axis */ + joystickYMovedEvent(event.jaxis.which + 1, event.jaxis.value); /* C vs. Lua offsets */ + } + break; + case SDL_QUIT: exit(0); break; @@ -446,10 +533,58 @@ void initScreen(void) { l81.bpp,l81.opt_full_screen); } +void initJoysticks(frameBuffer *fb) { + int cur_joy; + for(cur_joy=0; cur_joy < MAX_JOYSTICKS; cur_joy++ ) { + fb->joysticks[cur_joy] = NULL; + } +} + +void resetJoysticks(frameBuffer *fb) { + int cur_joy, sdl_joys, num_joys; + char joyscript[70]; + + /* Initialize Joysticks */ + SDL_JoystickEventState(SDL_ENABLE); + + + for(sdl_joys = SDL_NumJoysticks(), cur_joy=0, num_joys=0; cur_joy < sdl_joys; cur_joy++ ) { + + if (cur_joy == 0) { + snprintf(joyscript, sizeof(joyscript), + "for jn = 1, %d, 1 do joystick[jn]={x=0;y=0;name=nil}; end ", sdl_joys); + luaL_loadbuffer(l81.L,joyscript,strlen(joyscript),"joyscript"); + lua_pcall(l81.L,0,0,0); + } + + if (fb->joysticks[cur_joy] != NULL) + SDL_JoystickClose( fb->joysticks[cur_joy]); + + if (cur_joy < MAX_JOYSTICKS) { + fb->joysticks[cur_joy] = SDL_JoystickOpen(cur_joy); + + if (fb->joysticks[cur_joy] != NULL) { + setArrayFieldString("joystick", cur_joy + 1, "name", SDL_JoystickName(cur_joy)); + setArrayFieldNumber("joystick", cur_joy + 1, "axes", SDL_JoystickNumAxes(fb->joysticks[cur_joy])); + setArrayFieldNumber("joystick", cur_joy + 1, "trackballs", SDL_JoystickNumBalls(fb->joysticks[cur_joy])); + setArrayFieldNumber("joystick", cur_joy + 1, "hats", SDL_JoystickNumHats(fb->joysticks[cur_joy])); + setArrayFieldNumber("joystick", cur_joy + 1, "buttons", SDL_JoystickNumButtons(fb->joysticks[cur_joy])); + setArrayFieldNumber("joystick", cur_joy + 1, "x", 0); + setArrayFieldNumber("joystick", cur_joy + 1, "y", 0); + num_joys ++; + } + } + } + + setTableFieldNumber("joystick", "count", num_joys); +} + + void resetProgram(void) { char *initscript = - "keyboard={}; keyboard['pressed']={};" - "mouse={}; mouse['pressed']={};" + "keyboard={}; keyboard['pressed']={};" \ + "mouse={}; mouse['pressed']={};" \ + "joystick={}; " \ "sprites={}"; l81.epoch = 0; @@ -462,6 +597,8 @@ void resetProgram(void) { luaopen_debug(l81.L); setNumber("WIDTH",l81.width); setNumber("HEIGHT",l81.height); + + luaL_loadbuffer(l81.L,initscript,strlen(initscript),"initscript"); lua_pcall(l81.L,0,0,0); @@ -472,6 +609,10 @@ void resetProgram(void) { setTableFieldNumber("mouse","xrel",0); setTableFieldNumber("mouse","yrel",0); + + /* Reset joysticks */ + resetJoysticks(l81.fb); + /* Register API */ lua_pushcfunction(l81.L,fillBinding); lua_setglobal(l81.L,"fill"); @@ -498,6 +639,8 @@ void resetProgram(void) { /* Start with a black screen */ fillBackground(l81.fb,0,0,0); + + } /* ================================= Main ================================== */ @@ -562,6 +705,7 @@ int main(int argc, char **argv) { initConfig(); parseOptions(argc,argv); initScreen(); + initJoysticks(l81.fb); initEditor(l81.fb,30,30,30,30); editorOpen(l81.filename); while(1) { From d20ede6e88b1661ea8dc7d055060196ea9262ec7 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Sat, 17 Mar 2012 23:03:18 +0100 Subject: [PATCH 02/45] Joystick Example. --- examples/joysticks.lua | 68 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 examples/joysticks.lua diff --git a/examples/joysticks.lua b/examples/joysticks.lua new file mode 100644 index 0000000..af50e9d --- /dev/null +++ b/examples/joysticks.lua @@ -0,0 +1,68 @@ +-- +-- simple demo of joystick input +-- by torpor (seclorum@me.com) +-- +-- the joystick[] table is global, and contains .x/.y/.name fields +-- describing the joystick. the JOYSTICK global contains the +-- number of physical joysticks detected by LOAD81 at startup. +-- +-- the maximum number of joysticks available is 4. +-- + +-- each joystick will have its own color, and since there +-- a maximum of 4 joysticks available then we have 4 +-- unique colors to use +colors = {} +colors = { +{r=255,g=0,b=255,a=1}, +{r=0,g=0,b=255,a=1}, +{r=255,g=0,b=0,a=1}, +{r=0,g=255,b=0,a=1} +} + +function setup() + print("Number of joysticks", joystick.count); + background(0,0,0,0) + -- divide the screen in 4, one quad for each joystick device + joy_quad = HEIGHT / 4; +end + +-- simple map function +function map(x, in_min, in_max, out_min, out_max) + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +end + +function draw_joystick_info(joynum) + -- each joystick gets its own color + fill(colors[joynum].r,colors[joynum].g,colors[joynum].b,colors[joynum].a); + + -- text explaining joystick name and x/y values goes in a 'quarter' of the screen + text(10, joynum * joy_quad, string.format("# %d %s x:%d/y:%d", + joynum, joystick[joynum].name, + joystick[joynum].x, joystick[joynum].y)); + + -- each joystick returns x/y axes values from -32767 to 32767, so we map to + -- the screen size + dot_x, dot_y = 0; + dot_x = map(joystick[joynum].x, 32767, -32767, WIDTH, 0); + dot_y = map(joystick[joynum].y, 32767, -32767, 0, HEIGHT); + + -- draw the joystick dot + ellipse(dot_x, dot_y, 10, 10); +end + + +function draw() + -- clear the screen + background(0,0,0,0); + + if joystick.count == 0 then + fill (255,0,0,1); + text(10, joy_quad, string.format("No joysticks detected .. plug one in and try again!")); + end + + -- draw the info for each joystick + for jn = 1, joystick.count, 1 do + draw_joystick_info(jn); + end +end From adbb468bbfa0d0a0a9cec8c358972e4438c3d65f Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Sat, 17 Mar 2012 23:04:10 +0100 Subject: [PATCH 03/45] Fix for Open Pandora --bpp arg selection. --- contrib/Pandora/PND_Resources/defconf/profile.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/Pandora/PND_Resources/defconf/profile.txt b/contrib/Pandora/PND_Resources/defconf/profile.txt index 185dc0b..0183bab 100644 --- a/contrib/Pandora/PND_Resources/defconf/profile.txt +++ b/contrib/Pandora/PND_Resources/defconf/profile.txt @@ -9,6 +9,7 @@ filepath=./examples/ exepath=./load81 --full extarg=--width;0;%na%;800 extarg=--height;0;%na%;480 +extarg=--bpp;0;%na%;0 extarg=;0;%na%;%filename% # Custom Entries Settings From 6253a45e56523cd961e8584ffad2cd2c05b26515 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Sat, 17 Mar 2012 23:22:11 +0100 Subject: [PATCH 04/45] Basic button support. --- examples/joysticks.lua | 4 ++-- load81.c | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/examples/joysticks.lua b/examples/joysticks.lua index af50e9d..f6918d4 100644 --- a/examples/joysticks.lua +++ b/examples/joysticks.lua @@ -37,9 +37,9 @@ function draw_joystick_info(joynum) fill(colors[joynum].r,colors[joynum].g,colors[joynum].b,colors[joynum].a); -- text explaining joystick name and x/y values goes in a 'quarter' of the screen - text(10, joynum * joy_quad, string.format("# %d %s x:%d/y:%d", + text(10, joynum * joy_quad, string.format("# %d %s x:%d/y:%d button:%d", joynum, joystick[joynum].name, - joystick[joynum].x, joystick[joynum].y)); + joystick[joynum].x, joystick[joynum].y, joystick[joynum].button)); -- each joystick returns x/y axes values from -32767 to 32767, so we map to -- the screen size diff --git a/load81.c b/load81.c index 2f3091d..50286ba 100644 --- a/load81.c +++ b/load81.c @@ -405,6 +405,12 @@ void joystickYMovedEvent(int joy_num, Sint16 y) { setArrayFieldNumber("joystick", joy_num, "y", y); } } +void joystickButtonEvent(int joy_num, int down) +{ + if (joy_num < MAX_JOYSTICKS) { + setArrayFieldNumber("joystick", joy_num, "button", down); + } +} void resetEvents(void) { setTableFieldString("keyboard","state","none"); @@ -458,6 +464,12 @@ int processSdlEvents(void) { joystickYMovedEvent(event.jaxis.which + 1, event.jaxis.value); /* C vs. Lua offsets */ } break; + case SDL_JOYBUTTONUP: /* Handle Joystick Button Presses */ + joystickButtonEvent(event.jbutton.which + 1, 0); + break; + case SDL_JOYBUTTONDOWN: /* Handle Joystick Button Presses */ + joystickButtonEvent(event.jbutton.which + 1, 1); + break; case SDL_QUIT: exit(0); @@ -552,7 +564,7 @@ void resetJoysticks(frameBuffer *fb) { if (cur_joy == 0) { snprintf(joyscript, sizeof(joyscript), - "for jn = 1, %d, 1 do joystick[jn]={x=0;y=0;name=nil}; end ", sdl_joys); + "for jn = 1, %d, 1 do joystick[jn]={x=0;y=0;name=nil;button=0}; end ", sdl_joys); luaL_loadbuffer(l81.L,joyscript,strlen(joyscript),"joyscript"); lua_pcall(l81.L,0,0,0); } From b6990e5b056e5a9ddd71bb53620425bb945a892c Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Sat, 17 Mar 2012 23:47:24 +0100 Subject: [PATCH 05/45] Slight tweaks to the joystick demo. --- examples/joysticks.lua | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/examples/joysticks.lua b/examples/joysticks.lua index f6918d4..c5eaa71 100644 --- a/examples/joysticks.lua +++ b/examples/joysticks.lua @@ -1,17 +1,7 @@ -- -- simple demo of joystick input --- by torpor (seclorum@me.com) --- --- the joystick[] table is global, and contains .x/.y/.name fields --- describing the joystick. the JOYSTICK global contains the --- number of physical joysticks detected by LOAD81 at startup. --- --- the maximum number of joysticks available is 4. -- --- each joystick will have its own color, and since there --- a maximum of 4 joysticks available then we have 4 --- unique colors to use colors = {} colors = { {r=255,g=0,b=255,a=1}, @@ -21,47 +11,36 @@ colors = { } function setup() - print("Number of joysticks", joystick.count); background(0,0,0,0) - -- divide the screen in 4, one quad for each joystick device - joy_quad = HEIGHT / 4; + cell_size = HEIGHT / 4; end --- simple map function function map(x, in_min, in_max, out_min, out_max) return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; end function draw_joystick_info(joynum) - -- each joystick gets its own color fill(colors[joynum].r,colors[joynum].g,colors[joynum].b,colors[joynum].a); - - -- text explaining joystick name and x/y values goes in a 'quarter' of the screen - text(10, joynum * joy_quad, string.format("# %d %s x:%d/y:%d button:%d", + text(10, joynum * cell_size, string.format("# %d %s x:%d/y:%d button:%d", joynum, joystick[joynum].name, - joystick[joynum].x, joystick[joynum].y, joystick[joynum].button)); + joystick[joynum].x, joystick[joynum].y, + joystick[joynum].button)); - -- each joystick returns x/y axes values from -32767 to 32767, so we map to - -- the screen size dot_x, dot_y = 0; - dot_x = map(joystick[joynum].x, 32767, -32767, WIDTH, 0); + dot_x = map(joystick[joynum].x, 32767, -32767, HEIGHT, 0) + WIDTH / 4; dot_y = map(joystick[joynum].y, 32767, -32767, 0, HEIGHT); + ellipse(dot_x, dot_y, 30, 20); - -- draw the joystick dot - ellipse(dot_x, dot_y, 10, 10); end - function draw() - -- clear the screen + fill (0,255,0,1); background(0,0,0,0); if joystick.count == 0 then - fill (255,0,0,1); - text(10, joy_quad, string.format("No joysticks detected .. plug one in and try again!")); + text(10, cell_size, string.format("No joysticks detected .. plug one in and try again!")); end - -- draw the info for each joystick for jn = 1, joystick.count, 1 do draw_joystick_info(jn); end From c6f8656b1964275caba1b8d20181a2cd75604514 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Sun, 18 Mar 2012 00:26:44 +0100 Subject: [PATCH 06/45] Unneeded whitespace. --- load81.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/load81.c b/load81.c index 50286ba..e6a29f3 100644 --- a/load81.c +++ b/load81.c @@ -609,8 +609,6 @@ void resetProgram(void) { luaopen_debug(l81.L); setNumber("WIDTH",l81.width); setNumber("HEIGHT",l81.height); - - luaL_loadbuffer(l81.L,initscript,strlen(initscript),"initscript"); lua_pcall(l81.L,0,0,0); @@ -621,7 +619,6 @@ void resetProgram(void) { setTableFieldNumber("mouse","xrel",0); setTableFieldNumber("mouse","yrel",0); - /* Reset joysticks */ resetJoysticks(l81.fb); From e564215818e3c4d9e19abba378b28d9dd2c03314 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Sun, 18 Mar 2012 00:28:09 +0100 Subject: [PATCH 07/45] Whitepsace --- load81.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/load81.c b/load81.c index e6a29f3..60e333a 100644 --- a/load81.c +++ b/load81.c @@ -648,8 +648,6 @@ void resetProgram(void) { /* Start with a black screen */ fillBackground(l81.fb,0,0,0); - - } /* ================================= Main ================================== */ From 741a08118ea6bae36b4063b8ffe00cf83c35970e Mon Sep 17 00:00:00 2001 From: Allen Date: Wed, 21 Mar 2012 19:25:13 -0400 Subject: [PATCH 08/45] Added to support mouse scrolling, page up, page down, home, and end --- editor.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++------- editor.h | 9 ++++ 2 files changed, 148 insertions(+), 19 deletions(-) diff --git a/editor.c b/editor.c index 5bcf8bd..957988b 100644 --- a/editor.c +++ b/editor.c @@ -473,24 +473,38 @@ void editorMouseClicked(int x, int y, int button) { } else if (x >= E.margin_left && x <= E.fb->width-1-E.margin_right && y >= E.margin_bottom && y <= E.fb->height-1-E.margin_top) { - int realheight = E.fb->height - E.margin_top - E.margin_bottom; - int realy = y - E.margin_bottom; - int row = (realheight-realy)/FONT_HEIGHT; - int col = (x-E.margin_left)/FONT_KERNING; - int filerow = E.rowoff+row; - int filecol = E.coloff+col; - erow *r = (filerow >= E.numrows) ? NULL : &E.row[filerow]; - - E.cblink = 0; - if (filerow == E.numrows) { - E.cx = 0; - E.cy = filerow-E.rowoff; - } else if (r) { - if (filecol >= r->size) - E.cx = r->size-E.coloff; - else - E.cx = filecol-E.coloff; - E.cy = filerow-E.rowoff; + if (button == 4) { + if (E.rowoff) { + E.rowoff--; + if (E.cy < E.screenrows - 1) E.cy++; + } + } + else if (button == 5) { + if (E.rowoff + E.screenrows < E.numrows) { + E.rowoff++; + if (E.cy > 0) E.cy--; + } + } + else { + int realheight = E.fb->height - E.margin_top - E.margin_bottom; + int realy = y - E.margin_bottom; + int row = (realheight-realy)/FONT_HEIGHT; + int col = (x-E.margin_left)/FONT_KERNING; + int filerow = E.rowoff+row; + int filecol = E.coloff+col; + erow *r = (filerow >= E.numrows) ? NULL : &E.row[filerow]; + + E.cblink = 0; + if (filerow == E.numrows) { + E.cx = 0; + E.cy = filerow-E.rowoff; + } else if (r) { + if (filecol >= r->size) + E.cx = r->size-E.coloff; + else + E.cx = filecol-E.coloff; + E.cy = filerow-E.rowoff; + } } } } @@ -500,6 +514,7 @@ void editorMoveCursor(int key) { int filecol = E.coloff+E.cx; int rowlen; erow *row = (filerow >= E.numrows) ? NULL : &E.row[filerow]; + int temp; switch(key) { case SDLK_LEFT: @@ -534,6 +549,61 @@ void editorMoveCursor(int key) { } } break; + case SDLK_PAGEUP: + if (E.rowoff) { + E.rowoff -= E.screenrows - 1; + if (E.rowoff < 0) { + E.rowoff = 0; + E.cy = 0; + } + } + else { + if (E.cy > 0) E.cy = 0; + } + break; + case SDLK_PAGEDOWN: + if (E.rowoff + E.screenrows - 1 < E.numrows) { + E.rowoff += E.screenrows - 1; + if (E.rowoff + E.screenrows - 1 > E.numrows) E.cy = E.numrows - E.rowoff - 1; + } + else { + E.cy = E.numrows - E.rowoff - 1; + } + break; + case SDLK_HOME: + if (E.modifiers & CTRL_MASK) { + E.rowoff = E.coloff = E.cy = E.cx = 0; + } + else { + if (row && filecol != 0) { + temp = getFirstNonSpace(row); + if (temp > -1) { + if (filecol > temp) { + E.cx = temp; + E.coloff = 0; + } + else { + E.cx = E.coloff = 0; + } + } + } + } + break; + case SDLK_END: + if (E.modifiers & CTRL_MASK) { + E.rowoff = E.numrows - E.screenrows; + E.cy = E.screenrows - 1; + E.coloff = E.cx = 0; + } + else { + if (row && filecol < row->size) { + if (row->size - E.screencols + 1 > 0) { + E.coloff = row->size - E.screencols + 1; + } + E.cx = row->size - E.coloff; + } + } + break; } /* Fix cx if the current line has not enough chars. */ filerow = E.rowoff+E.cy; @@ -549,6 +619,16 @@ void editorMoveCursor(int key) { } } +int getFirstNonSpace(erow *row) { + int i; + for (i = 0; i < row->size; i++) { + if (row->chars[i] != ' ' && row->chars[i] != '\t') { + return i; + } + } + return -1; +} + int editorEvents(void) { SDL_Event event; int j, ksym; @@ -578,6 +658,24 @@ int editorEvents(void) { E.key[ksym].counter = 1; E.key[ksym].translation = (event.key.keysym.unicode & 0xff); } + switch(ksym) { + case SDLK_LSHIFT: + case SDLK_RSHIFT: + E.modifiers |= SHIFT_MASK; + break; + case SDLK_LCTRL: + case SDLK_RCTRL: + E.modifiers |= CTRL_MASK; + break; + case SDLK_LALT: + case SDLK_RALT: + E.modifiers |= ALT_MASK; + break; + case SDLK_LMETA: + case SDLK_RMETA: + E.modifiers |= META_MASK; + break; + } break; } break; @@ -586,6 +684,24 @@ int editorEvents(void) { case SDL_KEYUP: ksym = event.key.keysym.sym; if (ksym >= 0 && ksym < KEY_MAX) E.key[ksym].counter = 0; + switch(ksym) { + case SDLK_LSHIFT: + case SDLK_RSHIFT: + E.modifiers &= ~SHIFT_MASK; + break; + case SDLK_LCTRL: + case SDLK_RCTRL: + E.modifiers &= ~CTRL_MASK; + break; + case SDLK_LALT: + case SDLK_RALT: + E.modifiers &= ~ALT_MASK; + break; + case SDLK_LMETA: + case SDLK_RMETA: + E.modifiers &= ~META_MASK; + break; + } break; /* Mouse click */ case SDL_MOUSEBUTTONDOWN: @@ -610,6 +726,10 @@ int editorEvents(void) { case SDLK_RIGHT: case SDLK_UP: case SDLK_DOWN: + case SDLK_PAGEUP: + case SDLK_PAGEDOWN: + case SDLK_HOME: + case SDLK_END: editorMoveCursor(j); break; case SDLK_BACKSPACE: @@ -618,7 +738,6 @@ int editorEvents(void) { case SDLK_RETURN: editorInsertNewline(); break; - case SDLK_HOME: case SDLK_LSHIFT: case SDLK_RSHIFT: case SDLK_LCTRL: @@ -699,4 +818,5 @@ void initEditor(frameBuffer *fb, int mt, int mb, int ml, int mr) { E.dirty = 0; E.filename = NULL; memset(E.key,0,sizeof(E.key)); + E.modifiers = 0; } diff --git a/editor.h b/editor.h index cfa6fe3..739a2fb 100644 --- a/editor.h +++ b/editor.h @@ -28,6 +28,12 @@ #define HL_FUNCDEF_COLOR {255,255,255} #define HL_LIB_COLOR {255,0,255} +/* Key Held Modifier Bit Masks */ +#define CTRL_MASK (1<<0) +#define SHIFT_MASK (1<<1) +#define ALT_MASK (1<<2) +#define META_MASK (1<<3) + typedef struct erow { int size; /* Size of the row, excluding the null term. */ char *chars; /* Row content. */ @@ -56,6 +62,7 @@ struct editorConfig { erow *row; /* Rows */ time_t lastevent; /* Last event time, so we can go standby */ keyState key[KEY_MAX]; /* Remember if a key is pressed / repeated. */ + unsigned int modifiers; /* Key modifiers held. CTRL & SHIFT & ALT & META */ int dirty; /* File modified but not saved. */ char *filename; /* Currently open filename */ frameBuffer *fb; /* Framebuffer */ @@ -76,4 +83,6 @@ void editorClearError(void); int editorFileWasModified(void); void editorRun(void); +int getFirstNonSpace(erow *row); + #endif /* EDITOR_H */ From 30cedc73825d436266b8b41deddf5a51a2ccbcc3 Mon Sep 17 00:00:00 2001 From: Allen Date: Fri, 23 Mar 2012 16:31:43 -0400 Subject: [PATCH 09/45] Add support for drawing polygons --- framebuffer.c | 11 +++++++++++ framebuffer.h | 1 + load81.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/framebuffer.c b/framebuffer.c index 65ced77..c1c9d4b 100644 --- a/framebuffer.c +++ b/framebuffer.c @@ -67,6 +67,17 @@ void drawLine(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int lineRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, r, g, b, alpha); } +void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int filled, int r, int g, int b, int alpha) { + int i; + for (i=0; iheight-1-yv[i]; + if (filled) { + filledPolygonRGBA(fb->screen, xv, yv, n, r, g, b, alpha); + } + else { + polygonRGBA(fb->screen, xv, yv, n, r, g, b, alpha); + } +} + /* ============================= Bitmap font =============================== */ void bfLoadFont(char **c) { /* Set all the entries to NULL. */ diff --git a/framebuffer.h b/framebuffer.h index 0a20367..163cdd6 100644 --- a/framebuffer.h +++ b/framebuffer.h @@ -32,6 +32,7 @@ void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha); void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha); void drawLine(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha); +void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int filled, int r, int g, int b, int alpha); /* Bitmap font */ void bfLoadFont(char **c); diff --git a/load81.c b/load81.c index 0450cdb..71a5081 100644 --- a/load81.c +++ b/load81.c @@ -212,6 +212,49 @@ int backgroundBinding(lua_State *L) { return 0; } +int polygonBinding(lua_State *L) { + Sint16* polyBufferX; + Sint16* polyBufferY; + + int size=0, i=0; + int good=0; + + if (lua_gettop(L) == 2) { + if (lua_istable(L,-1)) { + size = (int)lua_objlen(L,-1); + polyBufferY = (Sint16*)malloc(size * sizeof(Sint16)); + lua_pushnil(L); + while(lua_next(L,-2) != 0) { + polyBufferY[i++] = (Sint16)lua_tonumber(L,-1); + lua_pop(L,1); + if (i > size) break; + } + good++; + lua_pop(L,1); + } + if (lua_istable(L,-1)) { + polyBufferX = (Sint16*)malloc(size * sizeof(Sint16)); + lua_pushnil(L); + i=0; + while(lua_next(L,-2) != 0) { + polyBufferX[i++] = (Sint16)lua_tonumber(L,-1); + lua_pop(L,1); + if (i > size) break; + } + good++; + } + } + if (good == 2) { + drawPolygon(l81.fb, polyBufferX, polyBufferY, size, filled, l81.r, l81.g, l81.b, l81.alpha); + free(polyBufferX); + free(polyBufferY); + } + return 0; +} + + + + int getpixelBinding(lua_State *L) { Uint32 pixel; Uint8 r, g, b; @@ -493,6 +536,8 @@ void resetProgram(void) { lua_setglobal(l81.L,"getpixel"); lua_pushcfunction(l81.L,spriteBinding); lua_setglobal(l81.L,"sprite"); + lua_pushcfunction(l81.L,polygonBinding); + lua_setglobal(l81.L,"polygon"); initSpriteEngine(l81.L); From 1b31c1713e6583ee93cfe901747347ba4c03c805 Mon Sep 17 00:00:00 2001 From: Allen Date: Fri, 23 Mar 2012 16:44:44 -0400 Subject: [PATCH 10/45] Reworked a bit, and added some error trapping --- framebuffer.c | 9 ++------ framebuffer.h | 2 +- load81.c | 62 +++++++++++++++++++++++++-------------------------- 3 files changed, 34 insertions(+), 39 deletions(-) diff --git a/framebuffer.c b/framebuffer.c index c1c9d4b..d7256aa 100644 --- a/framebuffer.c +++ b/framebuffer.c @@ -67,15 +67,10 @@ void drawLine(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int lineRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, r, g, b, alpha); } -void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int filled, int r, int g, int b, int alpha) { +void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int r, int g, int b, int alpha) { int i; for (i=0; iheight-1-yv[i]; - if (filled) { - filledPolygonRGBA(fb->screen, xv, yv, n, r, g, b, alpha); - } - else { - polygonRGBA(fb->screen, xv, yv, n, r, g, b, alpha); - } + filledPolygonRGBA(fb->screen, xv, yv, n, r, g, b, alpha); } /* ============================= Bitmap font =============================== */ diff --git a/framebuffer.h b/framebuffer.h index 163cdd6..8efce0e 100644 --- a/framebuffer.h +++ b/framebuffer.h @@ -32,7 +32,7 @@ void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha); void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha); void drawLine(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha); -void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int filled, int r, int g, int b, int alpha); +void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int r, int g, int b, int alpha); /* Bitmap font */ void bfLoadFont(char **c); diff --git a/load81.c b/load81.c index 71a5081..3475637 100644 --- a/load81.c +++ b/load81.c @@ -216,39 +216,39 @@ int polygonBinding(lua_State *L) { Sint16* polyBufferX; Sint16* polyBufferY; - int size=0, i=0; - int good=0; - - if (lua_gettop(L) == 2) { - if (lua_istable(L,-1)) { - size = (int)lua_objlen(L,-1); - polyBufferY = (Sint16*)malloc(size * sizeof(Sint16)); - lua_pushnil(L); - while(lua_next(L,-2) != 0) { - polyBufferY[i++] = (Sint16)lua_tonumber(L,-1); - lua_pop(L,1); - if (i > size) break; - } - good++; - lua_pop(L,1); - } - if (lua_istable(L,-1)) { - polyBufferX = (Sint16*)malloc(size * sizeof(Sint16)); - lua_pushnil(L); - i=0; - while(lua_next(L,-2) != 0) { - polyBufferX[i++] = (Sint16)lua_tonumber(L,-1); - lua_pop(L,1); - if (i > size) break; - } - good++; - } + if (!(lua_gettop(L) == 2 && lua_istable(L,-1) && lua_istable(L,-2))) { + programError("Invalid arguments for polygon"); + return 0; + } + + int size = (int)lua_objlen(L,-1), i=0; + polyBufferY = (Sint16*)malloc(size * sizeof(Sint16)); + lua_pushnil(L); + while(lua_next(L,-2) != 0) { + polyBufferY[i++] = (Sint16)lua_tonumber(L,-1); + lua_pop(L,1); + if (i > size) break; + } + + lua_pop(L,1); + + if (size != (int)lua_objlen(L,-1)) { + programError("Array size mismatch in call to polygon"); + return 0; } - if (good == 2) { - drawPolygon(l81.fb, polyBufferX, polyBufferY, size, filled, l81.r, l81.g, l81.b, l81.alpha); - free(polyBufferX); - free(polyBufferY); + polyBufferX = (Sint16*)malloc(size * sizeof(Sint16)); + lua_pushnil(L); + i=0; + while(lua_next(L,-2) != 0) { + polyBufferX[i++] = (Sint16)lua_tonumber(L,-1); + lua_pop(L,1); + if (i > size) break; } + + drawPolygon(l81.fb, polyBufferX, polyBufferY, size, l81.r, l81.g, l81.b, l81.alpha); + + free(polyBufferX); + free(polyBufferY); return 0; } From 63c6660f8e3b6f9b7634ddfe8426fa623f7d0e5f Mon Sep 17 00:00:00 2001 From: Allen Date: Fri, 23 Mar 2012 18:20:34 -0400 Subject: [PATCH 11/45] Added filled() binding to set the filled state --- editor.c | 20 ++++++++++---------- examples/flames.lua | 3 +++ framebuffer.c | 21 +++++++++++++++------ framebuffer.h | 6 +++--- load81.c | 16 ++++++++++++---- load81.h | 1 + 6 files changed, 44 insertions(+), 23 deletions(-) diff --git a/editor.c b/editor.c index 957988b..b1cb7eb 100644 --- a/editor.c +++ b/editor.c @@ -374,7 +374,7 @@ void editorDrawCursor(void) { y -= E.margin_top; if (!(E.cblink & 0x80)) drawBox(E.fb,x+charmargin,y, x+charmargin+FONT_KERNING-1,y+FONT_HEIGHT-1, - 165,165,255,128); + 165,165,255,128,1); E.cblink += 4; } @@ -412,25 +412,25 @@ void editorDrawChars(void) { } void editorDrawPowerOff(int x, int y) { - drawEllipse(E.fb,x,y,12,12,66,66,231,255); - drawEllipse(E.fb,x,y,7,7,165,165,255,255); - drawBox(E.fb,x-4,y,x+4,y+12,165,165,255,255); - drawBox(E.fb,x-2,y,x+2,y+14,66,66,231,255); + drawEllipse(E.fb,x,y,12,12,66,66,231,255,1); + drawEllipse(E.fb,x,y,7,7,165,165,255,255,1); + drawBox(E.fb,x-4,y,x+4,y+12,165,165,255,255,1); + drawBox(E.fb,x-2,y,x+2,y+14,66,66,231,255,1); } void editorDrawSaveIcon(int x, int y) { - drawBox(E.fb,x-12,y-12,x+12,y+12,66,66,231,255); - drawBox(E.fb,x-1,y+7,x+1,y+11,165,165,255,255); - drawEllipse(E.fb,x,y,4,4,165,165,255,255); + drawBox(E.fb,x-12,y-12,x+12,y+12,66,66,231,255,1); + drawBox(E.fb,x-1,y+7,x+1,y+11,165,165,255,255,1); + drawEllipse(E.fb,x,y,4,4,165,165,255,255,1); } void editorDraw() { - drawBox(E.fb,0,0,E.fb->width-1,E.fb->height-1,165,165,255,255); + drawBox(E.fb,0,0,E.fb->width-1,E.fb->height-1,165,165,255,255,1); drawBox(E.fb, E.margin_left, E.margin_bottom, E.fb->width-1-E.margin_right, - E.fb->height-1-E.margin_top,66,66,231,255); + E.fb->height-1-E.margin_top,66,66,231,255,1); editorDrawChars(); editorDrawCursor(); /* Show buttons */ diff --git a/examples/flames.lua b/examples/flames.lua index f2ff89c..acc1d22 100644 --- a/examples/flames.lua +++ b/examples/flames.lua @@ -10,6 +10,7 @@ function setup() refreshCount = 0 skipCount = 0 Flames = { } + filled(false) for i=1,MaxFlames do x = math.random(WIDTH/3) + (WIDTH/3) @@ -26,9 +27,11 @@ function draw() background(0,0,0) for i,f in pairs(Flames) do if f.l > 35 then + filled(true) fill(255, 255, 255, 0.9) minMove = 0 elseif f.l > 30 then + filled(false) fill(255, 255, 192, 0.8) minMove = 1 elseif f.l > 20 then diff --git a/framebuffer.c b/framebuffer.c index 65ced77..2cd2cd1 100644 --- a/framebuffer.c +++ b/framebuffer.c @@ -51,16 +51,25 @@ void drawHline(frameBuffer *fb, int x1, int x2, int y, int r, int g, int b, int hlineRGBA(fb->screen, x1, x2, fb->height-1-y, r, g, b, alpha); } -void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int g, int b, int alpha) { - filledEllipseRGBA(fb->screen, xc, fb->height-1-yc, radx, rady, r, g, b, alpha); +void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int g, int b, int alpha, char filled) { + if (filled) + filledEllipseRGBA(fb->screen, xc, fb->height-1-yc, radx, rady, r, g, b, alpha); + else + ellipseRGBA(fb->screen, xc, fb->height-1-yc, radx, rady, r, g, b, alpha); } -void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha) { - boxRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, r, g, b, alpha); +void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha, char filled) { + if (filled) + boxRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, r, g, b, alpha); + else + rectangleRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, r, g, b, alpha); } -void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha) { - filledTrigonRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, x3, fb->height-1-y3, r, g, b, alpha); +void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha, char filled) { + if (filled) + filledTrigonRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, x3, fb->height-1-y3, r, g, b, alpha); + else + trigonRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, x3, fb->height-1-y3, r, g, b, alpha); } void drawLine(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha) { diff --git a/framebuffer.h b/framebuffer.h index 0a20367..5852713 100644 --- a/framebuffer.h +++ b/framebuffer.h @@ -28,9 +28,9 @@ frameBuffer *createFrameBuffer(int width, int height, int bpp, int fullscreen); void setPixelWithAlpha(frameBuffer *fb, int x, int y, int r, int g, int b, int alpha); void fillBackground(frameBuffer *fb, int r, int g, int b); void drawHline(frameBuffer *fb, int x1, int x2, int y, int r, int g, int b, int alpha); -void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int g, int b, int alpha); -void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha); -void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha); +void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int g, int b, int alpha, char filled); +void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha, char filled); +void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha, char filled); void drawLine(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha); /* Bitmap font */ diff --git a/load81.c b/load81.c index 0450cdb..afd7979 100644 --- a/load81.c +++ b/load81.c @@ -135,6 +135,11 @@ int fillBinding(lua_State *L) { return 0; } +int filledBinding(lua_State *L) { + l81.filled = lua_toboolean(L,-1); + return 0; +} + int rectBinding(lua_State *L) { int x,y,w,h; @@ -142,7 +147,7 @@ int rectBinding(lua_State *L) { y = lua_tonumber(L,-3); w = lua_tonumber(L,-2); h = lua_tonumber(L,-1); - drawBox(l81.fb,x,y,x+(w-1),y+(h-1),l81.r,l81.g,l81.b,l81.alpha); + drawBox(l81.fb,x,y,x+(w-1),y+(h-1),l81.r,l81.g,l81.b,l81.alpha,l81.filled); return 0; } @@ -153,7 +158,7 @@ int ellipseBinding(lua_State *L) { y = lua_tonumber(L,-3); rx = lua_tonumber(L,-2); ry = lua_tonumber(L,-1); - drawEllipse(l81.fb,x,y,rx,ry,l81.r,l81.g,l81.b,l81.alpha); + drawEllipse(l81.fb,x,y,rx,ry,l81.r,l81.g,l81.b,l81.alpha,l81.filled); return 0; } @@ -166,7 +171,7 @@ int triangleBinding(lua_State *L) { y2 = lua_tonumber(L,-3); x3 = lua_tonumber(L,-2); y3 = lua_tonumber(L,-1); - drawTriangle(l81.fb,x1,y1,x2,y2,x3,y3,l81.r,l81.g,l81.b,l81.alpha); + drawTriangle(l81.fb,x1,y1,x2,y2,x3,y3,l81.r,l81.g,l81.b,l81.alpha,l81.filled); return 0; } @@ -339,7 +344,7 @@ void showFPS(void) { if (!elapsed_ms) return; snprintf(buf,sizeof(buf),"FPS: %.2f",(float)(l81.epoch*1000)/elapsed_ms); - drawBox(l81.fb,0,0,100,20,0,0,0,255); + drawBox(l81.fb,0,0,100,20,0,0,0,255,1); bfWriteString(l81.fb,0,0,buf,strlen(buf),128,128,128,255); } @@ -413,6 +418,7 @@ void initConfig(void) { l81.r = 255; l81.g = l81.b = 0; l81.alpha = 255; + l81.filled = 1; l81.L = NULL; l81.luaerr = 0; l81.opt_show_fps = 0; @@ -475,6 +481,8 @@ void resetProgram(void) { /* Register API */ lua_pushcfunction(l81.L,fillBinding); lua_setglobal(l81.L,"fill"); + lua_pushcfunction(l81.L,filledBinding); + lua_setglobal(l81.L,"filled"); lua_pushcfunction(l81.L,rectBinding); lua_setglobal(l81.L,"rect"); lua_pushcfunction(l81.L,ellipseBinding); diff --git a/load81.h b/load81.h index 7f62925..249819d 100644 --- a/load81.h +++ b/load81.h @@ -15,6 +15,7 @@ struct globalConfig { /* Runtime */ int r,g,b; int alpha; + char filled; int fps; long long start_ms; long long epoch; From c45dfabba57de047c2a3e25754737704590fcc5b Mon Sep 17 00:00:00 2001 From: Allen Date: Fri, 23 Mar 2012 20:38:20 -0400 Subject: [PATCH 12/45] Merged, added filled stuff for polygon --- framebuffer.c | 7 +++++-- framebuffer.h | 2 +- load81.c | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/framebuffer.c b/framebuffer.c index 09a6eb5..e95c4a1 100644 --- a/framebuffer.c +++ b/framebuffer.c @@ -76,10 +76,13 @@ void drawLine(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int lineRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, r, g, b, alpha); } -void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int r, int g, int b, int alpha) { +void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int r, int g, int b, int alpha, char filled) { int i; for (i=0; iheight-1-yv[i]; - filledPolygonRGBA(fb->screen, xv, yv, n, r, g, b, alpha); + if (filled) + filledPolygonRGBA(fb->screen, xv, yv, n, r, g, b, alpha); + else + polygonRGBA(fb->screen, xv, yv, n, r, g, b, alpha); } /* ============================= Bitmap font =============================== */ diff --git a/framebuffer.h b/framebuffer.h index bd4b86d..308da02 100644 --- a/framebuffer.h +++ b/framebuffer.h @@ -32,7 +32,7 @@ void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha, char filled); void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha, char filled); void drawLine(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha); -void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int r, int g, int b, int alpha); +void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int r, int g, int b, int alpha, char filled); /* Bitmap font */ void bfLoadFont(char **c); diff --git a/load81.c b/load81.c index 4805fac..c2eefb5 100644 --- a/load81.c +++ b/load81.c @@ -250,7 +250,7 @@ int polygonBinding(lua_State *L) { if (i > size) break; } - drawPolygon(l81.fb, polyBufferX, polyBufferY, size, l81.r, l81.g, l81.b, l81.alpha); + drawPolygon(l81.fb, polyBufferX, polyBufferY, size, l81.r, l81.g, l81.b, l81.alpha, l81.filled); free(polyBufferX); free(polyBufferY); From f2a8f54be0e6781ff588b58f711af64cc0690ac0 Mon Sep 17 00:00:00 2001 From: Allen Date: Fri, 23 Mar 2012 21:21:18 -0400 Subject: [PATCH 13/45] Added functions to the README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 362dfbe..0958355 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ PROGRAMMING INTERFACE Drawing functions: * fill(r,g,b,alpha): select the drawing color. +* filled(filled): set the filled state (true or false) * background(r,g,b): paint the whole background with the specified color. * rect(x,y,width,height): draw a rectangle at x,y (left-bottom corner). * ellipse(x,y,width,height): draw an ellipse centered at x,y. @@ -58,6 +59,7 @@ Drawing functions: * triangle(x1,y1,x2,y2,x3,y3): draw a triangle with the specified vertex. * getpixel(x,y): return the red,gree,blue value of the specified pixel. * sprite(file,x,y,[rotation],[antialiasing]): draw sprite at coordinates with the specified rotation (in degrees, default 0) and antialiasing (default false). +* polygon(xv, yv): draw a polygon using a table of X values and a table of Y values. Control functions: From eb1178e019d1f30cdf7570a9a130df61a8c40bac Mon Sep 17 00:00:00 2001 From: Allen Date: Sat, 24 Mar 2012 07:06:41 -0400 Subject: [PATCH 14/45] Added tiling support to sprites --- README.md | 16 +++++- framebuffer.c | 134 +++++++++++++++++++++++++++++++++++++++++++------- framebuffer.h | 16 +++++- load81.c | 9 ++-- 4 files changed, 150 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 0958355..4ba4a1d 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,23 @@ Drawing functions: * text(x,y,string): print the specified text at x,y using a bitmap font. * triangle(x1,y1,x2,y2,x3,y3): draw a triangle with the specified vertex. * getpixel(x,y): return the red,gree,blue value of the specified pixel. -* sprite(file,x,y,[rotation],[antialiasing]): draw sprite at coordinates with the specified rotation (in degrees, default 0) and antialiasing (default false). * polygon(xv, yv): draw a polygon using a table of X values and a table of Y values. +Sprite functions: + +* sprite(file,[x,y,[rotation],[antialiasing]]): draw sprite at coordinates with the specified rotation (in degrees, default 0) and antialiasing (default false). + +Returns a sprite userdata object, with the following functions + +* getHeight(): returns the height of the sprite. +* getWidth(): returns the height of the sprite. +* getTiles(): returns x,y for the number of tiles horizontally and vertically. +* setTiles(x,y): set the number of tiles horizontally and vertically. +* getTileSize(): return w,h for the size of a tile, calculated from the width and height of the image divided by the number of tiles horizontally and vertically. +* getTileNum(): returns the number of tiles. +* tile(x,y,tileNum,[rotation],[antialiasing]): draw a tile using tileNum at coordinates with the specified rotation (in degrees, default 0) and antialiasing (default: false). +* draw(x,y,[rotation],[antialiasing]): draw sprite at coordinates with the specified rotation (in degrees, default 0) and antialiasing (default: false). + Control functions: * setFPS(fps): Set the frame rate. For default it's set to 30 frames per second. diff --git a/framebuffer.c b/framebuffer.c index e95c4a1..24b6e3d 100644 --- a/framebuffer.c +++ b/framebuffer.c @@ -34,6 +34,7 @@ frameBuffer *createFrameBuffer(int width, int height, int bpp, int fullscreen) { SDL_initFramerate(&fb->fps_mgr); /* Load the bitmap font */ bfLoadFont((char**)BitmapFont); + gfb = fb; return fb; } @@ -123,7 +124,8 @@ void bfWriteString(frameBuffer *fb, int xp, int yp, const char *s, int len, int * the same interface with load81.c. */ #define SPRITE_MT "l81.sprite_mt" -void spriteBlit(frameBuffer *fb, void *sprite, int x, int y, int angle, int aa) { +/* +void spriteBlit(frameBuffer *fb, sprite *sprite, int x, int y, int angle, int aa) { SDL_Surface *s = sprite; if (s == NULL) return; if (angle) s = rotozoomSurface(s,angle,1,aa); @@ -131,24 +133,62 @@ void spriteBlit(frameBuffer *fb, void *sprite, int x, int y, int angle, int aa) SDL_BlitSurface(s, NULL, fb->screen, &dst); if (angle) SDL_FreeSurface(s); } +*/ + +void spriteBlit(frameBuffer *fb, sprite *sp, int x, int y, int tileNum, int angle, int aa) { + SDL_Surface *s = sp->surf; + if (s == NULL) return; + + if (tileNum >= 0) { + SDL_Rect dst = {x, fb->height-1-y - sp->tileH, sp->tileW, sp->tileH}; + SDL_Rect src = {(tileNum%sp->tileY) * sp->tileW, (tileNum / sp->tileY) * sp->tileH, sp->tileW, sp->tileH}; + if (angle) { + SDL_Surface *temp = SDL_CreateRGBSurface(SDL_SWSURFACE, sp->tileW, sp->tileH, fb->screen->format->BitsPerPixel, 0, 0, 0, 0); + SDL_Surface *tempRot; + SDL_BlitSurface(s, &src, temp, NULL); + tempRot = rotozoomSurface(temp,angle,1,aa); + SDL_BlitSurface(tempRot, NULL, fb->screen, &dst); + SDL_FreeSurface(tempRot); + SDL_FreeSurface(temp); + } + else { + SDL_BlitSurface(s, &src, fb->screen, &dst); + } + } + else { + SDL_Rect dst = {x, fb->height-1-y - s->h, s->w, s->h}; + if (angle) s = rotozoomSurface(s,angle,1,aa); + SDL_BlitSurface(s, NULL, fb->screen, &dst); + if (angle) SDL_FreeSurface(s); + } +} + /* Load sprite. Return surface pointer and object on top of stack */ -void *spriteLoad(lua_State *L, const char *filename) { - SDL_Surface **pps; +sprite *spriteLoad(lua_State *L, const char *filename) { + sprite *pps; /* check if image was already loaded and cached */ lua_getglobal(L, "sprites"); lua_getfield(L, -1, filename); if (lua_isnil(L, -1)) { /* load image into surface */ - SDL_Surface *ps = IMG_Load(filename); - if (ps == NULL) { + sprite ps; + ps.surf = IMG_Load(filename); + if (ps.surf == NULL) { luaL_error(L, "failed to load sprite %s", filename); return NULL; } + ps.w = ps.surf->w; + ps.h = ps.surf->h; + ps.tileX = 0; + ps.tileY = 0; + ps.tileW = ps.w; + ps.tileH = ps.h; + /* box the surface pointer in a userdata */ - pps = (SDL_Surface **)lua_newuserdata(L, sizeof(SDL_Surface *)); + pps = (sprite*)lua_newuserdata(L, sizeof(sprite)); *pps = ps; /* set sprite metatable */ @@ -160,34 +200,92 @@ void *spriteLoad(lua_State *L, const char *filename) { lua_setfield(L, -4, filename); } else { /* unbox surface pointer */ - pps = (SDL_Surface **)luaL_checkudata(L, -1, SPRITE_MT); + pps = (sprite *)luaL_checkudata(L, -1, SPRITE_MT); } - return *pps; + return pps; } int spriteGC(lua_State *L) { - SDL_Surface **pps = (SDL_Surface **)luaL_checkudata(L, 1, SPRITE_MT); - if (pps) SDL_FreeSurface(*pps); + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + if (pps) SDL_FreeSurface(pps->surf); return 0; } int spriteGetHeight(lua_State *L) { - SDL_Surface **pps = (SDL_Surface **)luaL_checkudata(L, 1, SPRITE_MT); - lua_pushnumber(L, (*pps)->h); + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + lua_pushnumber(L, pps->h); return 1; } int spriteGetWidth(lua_State *L) { - SDL_Surface **pps = (SDL_Surface **)luaL_checkudata(L, 1, SPRITE_MT); - lua_pushnumber(L, (*pps)->w); + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + lua_pushnumber(L, pps->w); + return 1; +} + +int spriteGetTiles(lua_State *L) { + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + lua_pushnumber(L, pps->tileX); + lua_pushnumber(L, pps->tileY); + return 2; +} + +int spriteSetTiles(lua_State *L) { + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + pps->tileX = lua_tonumber(L, 2); + pps->tileY = lua_tonumber(L, 3); + pps->tileW = pps->w / pps->tileX; + pps->tileH = pps->h / pps->tileY; + return 0; +} + +int spriteGetTileSize(lua_State *L) { + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + lua_pushnumber(L, pps->tileW); + lua_pushnumber(L, pps->tileH); + return 2; +} + +int spriteGetTileNum(lua_State *L) { + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + lua_pushnumber(L, pps->tileX * pps->tileY); return 1; } +int spriteDrawTile(lua_State *L) { + int x, y, tileNum, angle, antialiasing; + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + x = lua_tonumber(L, 2); + y = lua_tonumber(L, 3); + tileNum = lua_tonumber(L,4); + angle = luaL_optnumber(L,5,0); + antialiasing = lua_toboolean(L,6); + spriteBlit(gfb, pps, x, y, tileNum, angle, antialiasing); + return 0; +} + +int spriteDraw(lua_State *L) { + int x, y, angle, antialiasing; + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + x = lua_tonumber(L, 2); + y = lua_tonumber(L, 3); + angle = luaL_optnumber(L,4,0); + antialiasing = lua_toboolean(L,5); + spriteBlit(gfb, pps, x, y, -1, angle, antialiasing); + return 0; +} + static const struct luaL_Reg sprite_m[] = { - { "__gc", spriteGC }, - { "getHeight", spriteGetHeight }, - { "getWidth", spriteGetWidth }, - { NULL, NULL } + { "__gc", spriteGC }, + { "getHeight", spriteGetHeight }, + { "getWidth", spriteGetWidth }, + { "getTiles", spriteGetTiles }, + { "setTiles", spriteSetTiles }, + { "getTileSize", spriteGetTileSize }, + { "getTileNum", spriteGetTileNum }, + { "tile", spriteDrawTile }, + { "draw", spriteDraw }, + { NULL, NULL } }; void initSpriteEngine(lua_State *L) { diff --git a/framebuffer.h b/framebuffer.h index 308da02..741f515 100644 --- a/framebuffer.h +++ b/framebuffer.h @@ -21,6 +21,8 @@ typedef struct frameBuffer { FPSmanager fps_mgr; } frameBuffer; +frameBuffer *gfb; + /* Frame buffer */ frameBuffer *createFrameBuffer(int width, int height, int bpp, int fullscreen); @@ -39,9 +41,19 @@ void bfLoadFont(char **c); void bfWriteChar(frameBuffer *fb, int xp, int yp, int c, int r, int g, int b, int alpha); void bfWriteString(frameBuffer *fb, int xp, int yp, const char *s, int len, int r, int g, int b, int alpha); +typedef struct sprite { + int w; + int h; + int tileX; + int tileY; + int tileW; + int tileH; + SDL_Surface *surf; +} sprite; + /* Sprites */ -void spriteBlit(frameBuffer *fb, void *sprite, int x, int y, int angle, int aa); -void *spriteLoad(lua_State *L, const char *filename); +void spriteBlit(frameBuffer *fb, sprite *sp, int x, int y, int tileNum, int angle, int aa); +sprite *spriteLoad(lua_State *L, const char *filename); void initSpriteEngine(lua_State *L); #endif /* FRAMEBUFFER_H */ diff --git a/load81.c b/load81.c index c2eefb5..08af1bf 100644 --- a/load81.c +++ b/load81.c @@ -303,15 +303,16 @@ int getpixelBinding(lua_State *L) { int spriteBinding(lua_State *L) { const char *filename; int x, y, angle, antialiasing; - void *sprite; + sprite *sprite; filename = lua_tostring(L, 1); - x = lua_tonumber(L, 2); - y = lua_tonumber(L, 3); + x = luaL_optnumber(L, 2, -1); + y = luaL_optnumber(L, 3, -1); angle = luaL_optnumber(L,4,0); antialiasing = lua_toboolean(L,5); sprite = spriteLoad(L,filename); - spriteBlit(l81.fb, sprite, x, y, angle, antialiasing); + if (x >= 0 && y >= 0) + spriteBlit(l81.fb, sprite, x, y, -1, angle, antialiasing); return 1; } From 58b116150289c4adf9e560e9d53cdfc35b055389 Mon Sep 17 00:00:00 2001 From: seclorum Date: Sun, 1 Apr 2012 21:22:14 +0200 Subject: [PATCH 15/45] add joystick support to flames.lua --- examples/flames.lua | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/examples/flames.lua b/examples/flames.lua index acc1d22..06a7b6a 100644 --- a/examples/flames.lua +++ b/examples/flames.lua @@ -1,6 +1,7 @@ -- Flames.lua, contributed by pmprog in the OpenPandora board. -- See http://boards.openpandora.org/index.php?/topic/7405-here-is-a-pnd-for-load81/ + function setup() local x, y, l @@ -21,10 +22,26 @@ function setup() end end +-- can't find this in .math, but lets have it here for later transformation anyway .. +function map(x, in_min, in_max, out_min, out_max) + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +end + function draw() - local i, f, minMove + local i, f, minMove; + + -- user can move joystick to get different flame effects + local joy_Lengths = { 5, 15, 20, 45, 60, 95, 140, 170, 200}; + local joy_Flames = { 5, 10, 15, 30, 60, 75, 90, 150 }; background(0,0,0) + + -- ahem .. change properties of the flame according to joystick input + FlameSize = joy_Lengths[math.floor(map (joystick[1].x, 32767, -32767, 1, #joy_Lengths) + .5)] + FlameLife = joy_Flames[math.floor(map (joystick[1].y, 32767, -32767, 1, #joy_Flames) + .5)] + + ellipse(dot_x, dot_y, 30, 20); + for i,f in pairs(Flames) do if f.l > 35 then filled(true) From 2392e99884e31aadac3e0c4bfb9cb35dd53d5f35 Mon Sep 17 00:00:00 2001 From: seclorum Date: Sun, 1 Apr 2012 21:26:26 +0200 Subject: [PATCH 16/45] consistency check --- examples/flames.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/flames.lua b/examples/flames.lua index 06a7b6a..072c9e0 100644 --- a/examples/flames.lua +++ b/examples/flames.lua @@ -31,14 +31,14 @@ function draw() local i, f, minMove; -- user can move joystick to get different flame effects - local joy_Lengths = { 5, 15, 20, 45, 60, 95, 140, 170, 200}; - local joy_Flames = { 5, 10, 15, 30, 60, 75, 90, 150 }; + local joyLengths = { 5, 15, 20, 45, 60, 95, 140, 170, 200}; + local joyFlames = { 5, 10, 15, 30, 60, 75, 90, 150 }; background(0,0,0) -- ahem .. change properties of the flame according to joystick input - FlameSize = joy_Lengths[math.floor(map (joystick[1].x, 32767, -32767, 1, #joy_Lengths) + .5)] - FlameLife = joy_Flames[math.floor(map (joystick[1].y, 32767, -32767, 1, #joy_Flames) + .5)] + FlameSize = joyLengths[math.floor(map (joystick[1].x, 32767, -32767, 1, #joyLengths) + .5)] + FlameLife = joyFlames[math.floor(map (joystick[1].y, 32767, -32767, 1, #joyFlames) + .5)] ellipse(dot_x, dot_y, 30, 20); From 91759101bfa53c49e79cbe49e8d7c81b692a5d3a Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Wed, 4 Apr 2012 11:49:55 +0200 Subject: [PATCH 17/45] add joystick support to flames, include new gridify sample --- examples/flames.lua | 57 --------------- examples/gridify.lua | 168 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 57 deletions(-) create mode 100644 examples/gridify.lua diff --git a/examples/flames.lua b/examples/flames.lua index f2ff89c..e69de29 100644 --- a/examples/flames.lua +++ b/examples/flames.lua @@ -1,57 +0,0 @@ --- Flames.lua, contributed by pmprog in the OpenPandora board. --- See http://boards.openpandora.org/index.php?/topic/7405-here-is-a-pnd-for-load81/ - -function setup() - local x, y, l - - MaxFlames = 150 - FlameLife = 40 - FlameSize = 10 - refreshCount = 0 - skipCount = 0 - Flames = { } - - for i=1,MaxFlames do - x = math.random(WIDTH/3) + (WIDTH/3) - y = math.random(FlameSize) - l = math.random(FlameLife) - a = { x = x, y = y, l = l } - table.insert(Flames,a) - end -end - -function draw() - local i, f, minMove - - background(0,0,0) - for i,f in pairs(Flames) do - if f.l > 35 then - fill(255, 255, 255, 0.9) - minMove = 0 - elseif f.l > 30 then - fill(255, 255, 192, 0.8) - minMove = 1 - elseif f.l > 20 then - fill(255, 192, 128, 0.7) - minMove = 2 - elseif f.l > 10 then - fill(220, 128, 100, 0.5) - minMove = 3 - else - fill(160, 128, 80, 0.3) - minMove = 5 - end - - ellipse(f.x,f.y,FlameSize,FlameSize) - f.l = f.l - math.random(3) - if f.l <= 0 then - f.x = math.random(WIDTH/3) + (WIDTH/3) - f.y = math.random(FlameSize) - f.l = FlameLife - else - f.y = f.y + (math.random(6) + minMove) - f.x = f.x + math.random(7) - 3 - end - end -end - diff --git a/examples/gridify.lua b/examples/gridify.lua new file mode 100644 index 0000000..44a350b --- /dev/null +++ b/examples/gridify.lua @@ -0,0 +1,168 @@ + -- +-- draw some grids +-- +screen_width = WIDTH +screen_height = HEIGHT +screen_w_center = screen_width / 2 +screen_h_center = screen_height / 2 + +colors = {} +colors = { {r=255, g=0, b=255, a=1}, + {r=0, g=0, b=255, a=1}, + {r=255, g=0, b=0, a=1}, + {r=0, g=255, b=0, a=1}, + {r=27, g=73, b=100, a=1}, + {r=0, g=51, b=75, a=1}, + {r=100, g=35, b=15, a=1}, + {r=200, g=135, b=150, a=1}, + {r=100, g=0, b=0, a=1}, + {r=100, g=50, b=0, a=1}, + {r=153, g=150, b=50, a=1}, + {r=25, g=102, b=0, a=1}, + {r=25, g=102, b=0, a=1}, + {r=80, g=500, b=200, a=1} } + + +-- dunno where we should get this from .. math.?? +function map(x, in_min, in_max, out_min, out_max) + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +end + +function setup() + background(0,0,0,0) + cell_size = HEIGHT / 4 + fill (27,73,100,1) + background(0,0,0,0) + text(10, 10, string.format("gridify, by torpor")) +end + +function draw_XY_grid() + for i = 0, screen_width, 10 do + for screen_w_center = 0, screen_height do + if (((i % 50) == 0) and ((screen_w_center % 50) == 0)) then + + fill(0, 51, 75, 1) + text(i+4, screen_w_center-1, tostring(i)) + + fill(100, 35, 15, 1) + text( i+4, screen_w_center+8, tostring(i)) -- padding for y direction + rect(i, screen_w_center, 4, 4) + + end + + if ((screen_w_center % 10) == 0) then + + fill(200, 135, 150, 1) + rect(i,screen_w_center,1,1) + + end + end + end +end + +function draw_centered_grid() + + fill(100,0,0,1) + rect(screen_w_center, screen_h_center, 4, 4) + + fill (100,50,0,1) + --fill (153,150,50) + line(0, screen_h_center, screen_width, screen_h_center) + line(screen_w_center, 0, screen_w_center, screen_height) + + for z = screen_w_center, screen_width, 10 do + if (((z - screen_w_center) % 50) == 0) then + fill (25,102,0,1) + ellipse(z, screen_h_center, 6, 6) + --text(z - 8, screen_h_center + 16 ,tostring(z - screen_w_center)) -- padding + end + end + + for z = screen_w_center, 0, -10 do + if (((z - screen_w_center) % 50) == 0) then + fill (25,102,0,1) + ellipse(z, screen_h_center, 6, 6) + --text(z - 8, screen_h_center + 16, tostring(z - screen_w_center)) -- padding + end + end + + for z = screen_h_center, screen_height, 10 do + if (((z - screen_h_center) % 50) == 0) then + + ellipse(screen_w_center, z, 6, 6) + --text(screen_w_center - 8, z + 16, tostring(z - screen_h_center)) -- padding + end + end + + for z = screen_h_center, 0, -10 do + if (((z - screen_h_center) % 50) == 0) then + --text(screen_w_center - 8, z + 16, tostring(z - screen_h_center)) -- padding + end + end +end + +--[[ +// This draws the 'percentage' scale for the centered grid, using +// the largest axes as the base to determine the appropriate +// interval +]] +function draw_percentile_grid() + + biggest_axes = math.max (screen_width, screen_height) + smallest_axes = math.min (screen_width, screen_height) + difference_between_axes = ((biggest_axes - smallest_axes) / 2) + difference = 0 + + if screen_width == biggest_axes then + difference = 0 + else + difference = difference_between_axes + end + + fill(80,500,200,1) + + i=0 + for i=0, 100, 5 do + -- map along the x axis first + x_loc = map(i, 0, 100, 0, biggest_axes) - difference + rect(x_loc, screen_h_center, 5, 5) + text(x_loc -25, screen_h_center+6, tostring(i - 50)) + end + + if (screen_height == biggest_axes) then + difference = 0 + else + difference = difference_between_axes + end + + for i=0, 100, 5 do -- map along the y axis next + y_loc = map(i, 0, 100, 0, biggest_axes) - difference + rect(screen_w_center, y_loc, 5, 5) + text(screen_w_center-25, y_loc + 6, tostring(i - 50 * -1) .. "%") + end +end + + +function draw_colors_grids() + for x in screen_w_center, screen_width do + for y in screen_h_center, screen_height do + for i in colors do + fill (color[i]) + rect (x * 10, y * 10, 5, 5) + end + end + end +end + + +function draw_grids() + draw_percentile_grid() + draw_centered_grid() + draw_XY_grid() +-- draw_colors_grids() +end + +function draw() + draw_grids() +end + From 265a1bb1ddf204f329614a221d4fdab3210d1552 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Wed, 4 Apr 2012 11:59:18 +0200 Subject: [PATCH 18/45] fix for case where no joysticks are available --- examples/flames.lua | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/examples/flames.lua b/examples/flames.lua index 500b3f9..a9e752f 100644 --- a/examples/flames.lua +++ b/examples/flames.lua @@ -1,9 +1,6 @@ -<<<<<<< HEAD -======= -- Flames.lua, contributed by pmprog in the OpenPandora board. -- See http://boards.openpandora.org/index.php?/topic/7405-here-is-a-pnd-for-load81/ - function setup() local x, y, l @@ -32,15 +29,16 @@ end function draw() local i, f, minMove; - -- user can move joystick to get different flame effects - local joyLengths = { 5, 15, 20, 45, 60, 95, 140, 170, 200}; - local joyFlames = { 5, 10, 15, 30, 60, 75, 90, 150 }; - + -- user can move joystick to get different flame effects + local joyLengths = { 5, 15, 20, 45, 60, 95, 140, 170, 200}; + local joyFlames = { 5, 10, 15, 30, 60, 75, 90, 150 }; background(0,0,0) - -- ahem .. change properties of the flame according to joystick input - FlameSize = joyLengths[math.floor(map (joystick[1].x, 32767, -32767, 1, #joyLengths) + .5)] - FlameLife = joyFlames[math.floor(map (joystick[1].y, 32767, -32767, 1, #joyFlames) + .5)] + -- ahem .. change properties of the flame according to joystick input + if joystick.count ~= 0 then + FlameSize = joyLengths[math.floor(map (joystick[1].x, 32767, -32767, 1, #joyLengths) + .5)] + FlameLife = joyFlames[math.floor(map (joystick[1].y, 32767, -32767, 1, #joyFlames) + .5)] + end ellipse(dot_x, dot_y, 30, 20); @@ -77,4 +75,3 @@ function draw() end end ->>>>>>> 2392e99884e31aadac3e0c4bfb9cb35dd53d5f35 From 6879ff32a1e6dd8ce546c65920dc89d0fd5e5115 Mon Sep 17 00:00:00 2001 From: seclorum Date: Wed, 4 Apr 2012 13:03:39 +0300 Subject: [PATCH 19/45] Update README.md --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 4ba4a1d..c52ee80 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,20 @@ if a button is pressed use: Mouse buttons are called '1', '2', '3', ... and so forth. +JOYSTICK EVENTS +=== +Joystick support is available by directly accessing the joystick[] table. +e.g. joystick[1].x / joystick[1].y = X/Y position of Joystick1 +joystick[1].button = button state +joystick[1].name = "hardware name of the joystick" + +joystick.count contains the number of joysticks detected by LOAD81 on +startup, and will be 0 if no joysticks are available. Max # of Joysticks +is currently set at 8. + +See examples/joysticks.lua and examples/flames.lua for how to use the +joystick. + LICENSE === From 074639f9f0d1a491a9dc2cbe86e7bc1b3acf97cd Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Wed, 4 Apr 2012 12:04:43 +0200 Subject: [PATCH 20/45] slight edit --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c52ee80..a19f711 100644 --- a/README.md +++ b/README.md @@ -125,9 +125,10 @@ Mouse buttons are called '1', '2', '3', ... and so forth. JOYSTICK EVENTS === Joystick support is available by directly accessing the joystick[] table. -e.g. joystick[1].x / joystick[1].y = X/Y position of Joystick1 -joystick[1].button = button state -joystick[1].name = "hardware name of the joystick" +e.g. + joystick[1].x / joystick[1].y = X/Y position of Joystick1 + joystick[1].button = button state of Joystick1 + joystick[1].name = "hardware name of the Joystick1" joystick.count contains the number of joysticks detected by LOAD81 on startup, and will be 0 if no joysticks are available. Max # of Joysticks From fbe0b30fe11230ec28a6ec8ac3dc082dbbe8f0df Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Wed, 4 Apr 2012 12:05:18 +0200 Subject: [PATCH 21/45] fix for joystick note --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a19f711..ca0acba 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,8 @@ Mouse buttons are called '1', '2', '3', ... and so forth. JOYSTICK EVENTS === Joystick support is available by directly accessing the joystick[] table. -e.g. +For example: + joystick[1].x / joystick[1].y = X/Y position of Joystick1 joystick[1].button = button state of Joystick1 joystick[1].name = "hardware name of the Joystick1" From b06cf642f861f9687b8017325289ccab06d0e083 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Wed, 4 Apr 2012 12:24:24 +0200 Subject: [PATCH 22/45] Fixup of gridifuy.lua sample. --- examples/gridify.lua | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/examples/gridify.lua b/examples/gridify.lua index 44a350b..c297429 100644 --- a/examples/gridify.lua +++ b/examples/gridify.lua @@ -138,16 +138,18 @@ function draw_percentile_grid() for i=0, 100, 5 do -- map along the y axis next y_loc = map(i, 0, 100, 0, biggest_axes) - difference rect(screen_w_center, y_loc, 5, 5) - text(screen_w_center-25, y_loc + 6, tostring(i - 50 * -1) .. "%") + text(screen_w_center-25, y_loc + 6, tostring((i - 50) * -1) .. "%") end end function draw_colors_grids() - for x in screen_w_center, screen_width do - for y in screen_h_center, screen_height do - for i in colors do - fill (color[i]) +print("screen_w_center : ", screen_w_center) +print("screen_width : ", screen_width) + for i = 1, #colors do + for x = screen_w_center, screen_width do + for y = screen_h_center, screen_height do + fill (colors[i].r, colors[i].g, colors[i].b, colors[i].a) rect (x * 10, y * 10, 5, 5) end end From 20279c3fae52486eb9916648cd322466c6b233d5 Mon Sep 17 00:00:00 2001 From: seclorum Date: Wed, 11 Apr 2012 22:39:32 +0200 Subject: [PATCH 23/45] timeout demo started --- examples/timeout.lua | 140 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 examples/timeout.lua diff --git a/examples/timeout.lua b/examples/timeout.lua new file mode 100644 index 0000000..f6f6fc7 --- /dev/null +++ b/examples/timeout.lua @@ -0,0 +1,140 @@ + -- +-- display time in all its joy +-- +screen_width = WIDTH +screen_height = HEIGHT +screen_w_center = screen_width / 2 +screen_h_center = screen_height / 2 + +colors = {} +colors = { {r=255, g=0, b=255, a=1}, + {r=0, g=0, b=255, a=1}, + {r=255, g=0, b=0, a=1}, + {r=80, g=500, b=200, a=1}, + {r=87, g=133, b=160, a =1} } + +NUM_EVENTS = 20 +SLICE_MODULO = 3 + +-- present-time countdown +ptc = NUM_EVENTS + +-- current frame values only +tick = 0 +time_str = "time: " +pixlen = 0 + +-- from now until NUM_EVENTS +event_ticks = {} + +-- dunno where we should get this from .. math.?? +function map(x, in_min, in_max, out_min, out_max) + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +end + +function setup() + background(255, 0, 0, 0) + tick = tick + 1 + + cell_size = HEIGHT / 4 + fill (27,73,100,1) + background(0,0,0,0) + + text(10, 10, string.format("timeout, by torpor")) +end + +function draw_centered_grid() + fill(100,0,0,1) + rect(screen_w_center, screen_h_center, 4, 4) + + fill (100,50,0,1) + --fill (153,150,50) + line(0, screen_h_center, screen_width, screen_h_center) + line(screen_w_center, 0, screen_w_center, screen_height) + + for z = screen_w_center, screen_width, 10 do + if (((z - screen_w_center) % 50) == 0) then + fill (25,102,0,1) + ellipse(z, screen_h_center, 6, 6) + text(z - 8, screen_h_center + 16 ,tostring(z - screen_w_center)) -- padding + end + end + + for z = screen_w_center, 0, -10 do + if (((z - screen_w_center) % 50) == 0) then + fill (25,102,0,1) + ellipse(z, screen_h_center, 6, 6) + text(z - 8, screen_h_center + 16, tostring(z - screen_w_center)) -- padding + end + end + + for z = screen_h_center, screen_height, 10 do + if (((z - screen_h_center) % 50) == 0) then + + ellipse(screen_w_center, z, 6, 6) + text(screen_w_center - 8, z + 16, tostring(z - screen_h_center)) -- padding + end + end + + for z = screen_h_center, 0, -10 do + if (((z - screen_h_center) % 50) == 0) then + ellipse(screen_w_center, z, 6, 6) + text(screen_w_center - 8, z + 16, tostring(z - screen_h_center)) -- padding + end + end +end + + +function draw_colors_grids() + for x = 1, screen_width / cell_size do + for y = 1, screen_height / cell_size do + for i = #colors, 1, -1 do + fill (colors[i].r, colors[i].g, colors[i].b, colors[i].a) + --print(" colors: " .. colors[i].r .. " " .. colors[i].g .. " " .. colors[i].b .. " " .. colors[i].a) + --rect (x * (cell_size / 16), y * (cell_size / 16), 15, 15) + rect (x * 16, y * 16, i * 15, i * 15) + end + end + end +end + +function draw_event_labels(i) + text((i * 48) - 38, screen_h_center, event_ticks[i] .. " ") +end + +function draw() + -- we keep our own count of event_ticks since start + tick = tick + 1 + + -- keep a list of NUM_EVENTS records and therefore need a present counter + if ptc <= 1 then + ptc = NUM_EVENTS + end + + -- decrement + ptc = ptc - 1 + + -- time slice + if ((ptc % SLICE_MODULO) == 0) then + background(0,0,0,1) + --draw_percentile_grid() + draw_centered_grid() + --draw_XY_grid() + draw_colors_grids() + -- remember our current ptc data + table.insert(event_ticks, tick) + + fill (87,133,160,1) + + for i = #event_ticks,1,-1 do + draw_event_labels(i) + end + + -- prune our little stack + if #event_ticks > NUM_EVENTS then + table.remove(event_ticks, 1) + end + end + +end + From 8c13a7ecda1faebcb598fd5098ba6b027f1b44ae Mon Sep 17 00:00:00 2001 From: seclorum Date: Wed, 11 Apr 2012 23:11:57 +0200 Subject: [PATCH 24/45] joystick support for timeout.lua --- examples/timeout.lua | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/examples/timeout.lua b/examples/timeout.lua index f6f6fc7..162c314 100644 --- a/examples/timeout.lua +++ b/examples/timeout.lua @@ -5,6 +5,7 @@ screen_width = WIDTH screen_height = HEIGHT screen_w_center = screen_width / 2 screen_h_center = screen_height / 2 +cell_size = HEIGHT / 4 colors = {} colors = { {r=255, g=0, b=255, a=1}, @@ -14,7 +15,8 @@ colors = { {r=255, g=0, b=255, a=1}, {r=87, g=133, b=160, a =1} } NUM_EVENTS = 20 -SLICE_MODULO = 3 + +SLICE_MODULO = 1 -- present-time countdown ptc = NUM_EVENTS @@ -26,6 +28,7 @@ pixlen = 0 -- from now until NUM_EVENTS event_ticks = {} +event_joyheights = {} -- dunno where we should get this from .. math.?? function map(x, in_min, in_max, out_min, out_max) @@ -36,7 +39,6 @@ function setup() background(255, 0, 0, 0) tick = tick + 1 - cell_size = HEIGHT / 4 fill (27,73,100,1) background(0,0,0,0) @@ -99,6 +101,14 @@ function draw_colors_grids() end function draw_event_labels(i) + fill(colors[2].r, colors[2].g, colors[2].b, colors[2].a) + + rect( (i * 48) - 38, + screen_h_center, + (i * 48) - 34, + map(event_joyheights[i], -32768, 32768, cell_size * 2, -cell_size * 2)) + + fill (87,133,160,1) text((i * 48) - 38, screen_h_center, event_ticks[i] .. " ") end @@ -116,24 +126,29 @@ function draw() -- time slice if ((ptc % SLICE_MODULO) == 0) then + background(0,0,0,1) + --draw_percentile_grid() draw_centered_grid() --draw_XY_grid() - draw_colors_grids() + -- remember our current ptc data table.insert(event_ticks, tick) - - fill (87,133,160,1) + table.insert(event_joyheights, joystick[1].y) for i = #event_ticks,1,-1 do draw_event_labels(i) end + draw_colors_grids() + -- prune our little stack if #event_ticks > NUM_EVENTS then table.remove(event_ticks, 1) + table.remove(event_joyheights, 1) end + end end From c0ef3050908df85bd85882615b752126a259533c Mon Sep 17 00:00:00 2001 From: seclorum Date: Wed, 11 Apr 2012 23:29:29 +0200 Subject: [PATCH 25/45] color support in timeout.lua --- examples/timeout.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/timeout.lua b/examples/timeout.lua index 162c314..b63e917 100644 --- a/examples/timeout.lua +++ b/examples/timeout.lua @@ -103,6 +103,11 @@ end function draw_event_labels(i) fill(colors[2].r, colors[2].g, colors[2].b, colors[2].a) + + local cn = math.modf(map (joystick[1].x, -32768, 32768, 1, #colors)) + print(cn) + fill (colors[cn].r, colors[cn].g, colors[cn].b, colors[cn].a) + rect( (i * 48) - 38, screen_h_center, (i * 48) - 34, From 081392d010235579d0adfd44c2e093ffd1920218 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Thu, 12 Apr 2012 11:25:01 +0200 Subject: [PATCH 26/45] joystick check --- examples/timeout.lua | 100 +++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/examples/timeout.lua b/examples/timeout.lua index b63e917..76ed432 100644 --- a/examples/timeout.lua +++ b/examples/timeout.lua @@ -38,11 +38,6 @@ end function setup() background(255, 0, 0, 0) tick = tick + 1 - - fill (27,73,100,1) - background(0,0,0,0) - - text(10, 10, string.format("timeout, by torpor")) end function draw_centered_grid() @@ -101,59 +96,70 @@ function draw_colors_grids() end function draw_event_labels(i) - fill(colors[2].r, colors[2].g, colors[2].b, colors[2].a) - + fill(colors[2].r, colors[2].g, colors[2].b, colors[2].a) - local cn = math.modf(map (joystick[1].x, -32768, 32768, 1, #colors)) - print(cn) - fill (colors[cn].r, colors[cn].g, colors[cn].b, colors[cn].a) + if joystick.count ~= 0 then + local cn = math.modf(map (joystick[1].x, -32768, 32768, 1, #colors)) + print(cn) + fill (colors[cn].r, colors[cn].g, colors[cn].b, colors[cn].a) + end - rect( (i * 48) - 38, - screen_h_center, - (i * 48) - 34, - map(event_joyheights[i], -32768, 32768, cell_size * 2, -cell_size * 2)) + rect( (i * 48) - 38, + screen_h_center, + (i * 48) - 34, + map(event_joyheights[i], -32768, 32768, cell_size * 2, -cell_size * 2)) fill (87,133,160,1) text((i * 48) - 38, screen_h_center, event_ticks[i] .. " ") end function draw() - -- we keep our own count of event_ticks since start - tick = tick + 1 - - -- keep a list of NUM_EVENTS records and therefore need a present counter - if ptc <= 1 then - ptc = NUM_EVENTS - end - - -- decrement - ptc = ptc - 1 - - -- time slice - if ((ptc % SLICE_MODULO) == 0) then + if joystick.count == 0 then + fill (240,0,0,1) + text(250, 10, string.format("Joystick not found, but one is required!")) + else - background(0,0,0,1) + -- we keep our own count of event_ticks since start + tick = tick + 1 - --draw_percentile_grid() - draw_centered_grid() - --draw_XY_grid() - - -- remember our current ptc data - table.insert(event_ticks, tick) - table.insert(event_joyheights, joystick[1].y) - - for i = #event_ticks,1,-1 do - draw_event_labels(i) - end - - draw_colors_grids() - - -- prune our little stack - if #event_ticks > NUM_EVENTS then - table.remove(event_ticks, 1) - table.remove(event_joyheights, 1) - end + -- keep a list of NUM_EVENTS records and therefore need a present counter + if ptc <= 1 then + ptc = NUM_EVENTS + end + -- decrement + ptc = ptc - 1 + + -- time slice + if ((ptc % SLICE_MODULO) == 0) then + + background(0,0,0,1) + text(10, 10, string.format("timeout, by torpor")) + + --draw_percentile_grid() + draw_centered_grid() + --draw_XY_grid() + + -- remember our current ptc data + table.insert(event_ticks, tick) + + if joystick.count ~= 0 then + table.insert(event_joyheights, joystick[1].y) + end + + for i = #event_ticks,1,-1 do + draw_event_labels(i) + end + + draw_colors_grids() + + -- prune our little stack + if #event_ticks > NUM_EVENTS then + table.remove(event_ticks, 1) + table.remove(event_joyheights, 1) + end + + end end end From 6b2ee93a7814dd98655244f33a561099942b834c Mon Sep 17 00:00:00 2001 From: seclorum Date: Sun, 15 Apr 2012 19:48:35 +0200 Subject: [PATCH 27/45] comments --- examples/timeout.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/timeout.lua b/examples/timeout.lua index b63e917..d2c7a9d 100644 --- a/examples/timeout.lua +++ b/examples/timeout.lua @@ -1,6 +1,10 @@ -- -- display time in all its joy -- +-- setup() and draw() are start and main functions +-- grid is drawn, time is kept on the grid +-- + screen_width = WIDTH screen_height = HEIGHT screen_w_center = screen_width / 2 @@ -105,7 +109,7 @@ function draw_event_labels(i) local cn = math.modf(map (joystick[1].x, -32768, 32768, 1, #colors)) - print(cn) +-- print(cn) fill (colors[cn].r, colors[cn].g, colors[cn].b, colors[cn].a) rect( (i * 48) - 38, From a6e607407f38304e68aeb48ce58fde7d19793c2f Mon Sep 17 00:00:00 2001 From: seclorum Date: Sun, 15 Apr 2012 20:01:11 +0200 Subject: [PATCH 28/45] fix of merge hiccup --- examples/timeout.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/timeout.lua b/examples/timeout.lua index 3dff6e3..ae4a90c 100644 --- a/examples/timeout.lua +++ b/examples/timeout.lua @@ -102,17 +102,14 @@ end function draw_event_labels(i) fill(colors[2].r, colors[2].g, colors[2].b, colors[2].a) -<<<<<<< HEAD - local cn = math.modf(map (joystick[1].x, -32768, 32768, 1, #colors)) -- print(cn) fill (colors[cn].r, colors[cn].g, colors[cn].b, colors[cn].a) -======= + if joystick.count ~= 0 then local cn = math.modf(map (joystick[1].x, -32768, 32768, 1, #colors)) print(cn) fill (colors[cn].r, colors[cn].g, colors[cn].b, colors[cn].a) end ->>>>>>> 081392d010235579d0adfd44c2e093ffd1920218 rect( (i * 48) - 38, screen_h_center, From 7a338a670d4b6d0e517a79545d0fc565e0966e8f Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Wed, 2 May 2012 11:22:31 +0200 Subject: [PATCH 29/45] tweaks --- examples/lines.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lines.lua b/examples/lines.lua index a8795bb..683cb32 100644 --- a/examples/lines.lua +++ b/examples/lines.lua @@ -1,5 +1,5 @@ function setup() - background(0,0,0,0); + background(255,0,1); end function draw() From 47a35ef18b3fa9f55d329450eb5fedaa3b637471 Mon Sep 17 00:00:00 2001 From: seclorum Date: Mon, 12 Sep 2016 18:38:56 +0000 Subject: [PATCH 30/45] Adjust Makefile to use sdl-config instead of pkg-config --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a8864fc..5973f8a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PKGS=sdl SDL_gfx SDL_image -CFLAGS=-O2 -Wall -W -Ilua/src `pkg-config --cflags $(PKGS)` -LDLIBS=lua/src/liblua.a -lm `pkg-config --libs $(PKGS)` +CFLAGS=-O2 -Wall -W -Ilua/src `sdl-config --cflags` +LDLIBS=lua/src/liblua.a -lm `sdl-config --libs` -lSDL_gfx -lSDL_image all: load81 From 8b747391f4c69ad9b42452e2f61c5fb727c5d546 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Wed, 14 Sep 2016 20:17:42 +0200 Subject: [PATCH 31/45] Add Darwin-specific hooks to compile against SDL_gfx/etc. from homebrew paths... --- Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5973f8a..0bac9ea 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,13 @@ PKGS=sdl SDL_gfx SDL_image -CFLAGS=-O2 -Wall -W -Ilua/src `sdl-config --cflags` -LDLIBS=lua/src/liblua.a -lm `sdl-config --libs` -lSDL_gfx -lSDL_image +CFLAGS=-O2 -Wall -W -Ilua/src `sdl-config --cflags` +LDLIBS=lua/src/liblua.a -lm `sdl-config --libs` + +# Customizations per-OS +UNAME := $(shell uname) +ifeq ($(UNAME), Darwin) +CFLAGS+=-I/usr/local/Cellar//sdl_gfx/2.0.25/include/SDL/ -I/usr/local/Cellar//sdl_image/1.2.12_3/include/SDL/ +LDLIBS+=-lSDL_gfx -lSDL_image +endif all: load81 From 86fbc71fc6e827ee155bfa178ffee9f765aeda75 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Wed, 14 Sep 2016 20:18:04 +0200 Subject: [PATCH 32/45] Include LFS in Lua Build --- lua/src/Makefile | 4 +- lua/src/lfs.c | 946 +++++++++++++++++++++++++++++++++++++++++++++++ lua/src/lfs.h | 34 ++ 3 files changed, 982 insertions(+), 2 deletions(-) create mode 100644 lua/src/lfs.c create mode 100644 lua/src/lfs.h diff --git a/lua/src/Makefile b/lua/src/Makefile index e0d4c9f..78cd6d1 100644 --- a/lua/src/Makefile +++ b/lua/src/Makefile @@ -25,9 +25,9 @@ PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris LUA_A= liblua.a CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ - lundump.o lvm.o lzio.o + lundump.o lvm.o lzio.o LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ - lstrlib.o loadlib.o linit.o + lstrlib.o loadlib.o linit.o lfs.o LUA_T= lua LUA_O= lua.o diff --git a/lua/src/lfs.c b/lua/src/lfs.c new file mode 100644 index 0000000..8154a46 --- /dev/null +++ b/lua/src/lfs.c @@ -0,0 +1,946 @@ +/* +** LuaFileSystem +** Copyright Kepler Project 2003 - 2016 (http://keplerproject.github.io/luafilesystem) +** +** File system manipulation library. +** This library offers these functions: +** lfs.attributes (filepath [, attributename | attributetable]) +** lfs.chdir (path) +** lfs.currentdir () +** lfs.dir (path) +** lfs.link (old, new[, symlink]) +** lfs.lock (fh, mode) +** lfs.lock_dir (path) +** lfs.mkdir (path) +** lfs.rmdir (path) +** lfs.setmode (filepath, mode) +** lfs.symlinkattributes (filepath [, attributename]) +** lfs.touch (filepath [, atime [, mtime]]) +** lfs.unlock (fh) +*/ + +#ifndef LFS_DO_NOT_USE_LARGE_FILE +#ifndef _WIN32 +#ifndef _AIX +#define _FILE_OFFSET_BITS 64 /* Linux, Solaris and HP-UX */ +#else +#define _LARGE_FILES 1 /* AIX */ +#endif +#endif +#endif + +#ifndef LFS_DO_NOT_USE_LARGE_FILE +#define _LARGEFILE64_SOURCE +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#include +#ifdef __BORLANDC__ + #include +#else + #include +#endif +#include +#else +#include +#include +#include +#include +#include +#endif + +#include +#include +#include + +#include "lfs.h" + +#define LFS_VERSION "1.6.3" +#define LFS_LIBNAME "lfs" + +#if LUA_VERSION_NUM >= 503 /* Lua 5.3 */ + +#ifndef luaL_optlong +#define luaL_optlong luaL_optinteger +#endif + +#endif + +#if LUA_VERSION_NUM < 502 +# define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l)) +#endif + +/* Define 'strerror' for systems that do not implement it */ +#ifdef NO_STRERROR +#define strerror(_) "System unable to describe the error" +#endif + +/* Define 'getcwd' for systems that do not implement it */ +#ifdef NO_GETCWD +#define getcwd(p,s) NULL +#define getcwd_error "Function 'getcwd' not provided by system" +#else +#define getcwd_error strerror(errno) + #ifdef _WIN32 + /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */ + #define LFS_MAXPATHLEN MAX_PATH + #else + /* For MAXPATHLEN: */ + #include + #define LFS_MAXPATHLEN MAXPATHLEN + #endif +#endif + +#define DIR_METATABLE "directory metatable" +typedef struct dir_data { + int closed; +#ifdef _WIN32 + intptr_t hFile; + char pattern[MAX_PATH+1]; +#else + DIR *dir; +#endif +} dir_data; + +#define LOCK_METATABLE "lock metatable" + +#ifdef _WIN32 + #ifdef __BORLANDC__ + #define lfs_setmode(file, m) (setmode(_fileno(file), m)) + #define STAT_STRUCT struct stati64 + #else + #define lfs_setmode(file, m) (_setmode(_fileno(file), m)) + #define STAT_STRUCT struct _stati64 + #endif +#define STAT_FUNC _stati64 +#define LSTAT_FUNC STAT_FUNC +#else +#define _O_TEXT 0 +#define _O_BINARY 0 +#define lfs_setmode(file, m) ((void)file, (void)m, 0) +#define STAT_STRUCT struct stat +#define STAT_FUNC stat +#define LSTAT_FUNC lstat +#endif + +/* +** Utility functions +*/ +static int pusherror(lua_State *L, const char *info) +{ + lua_pushnil(L); + if (info==NULL) + lua_pushstring(L, strerror(errno)); + else + lua_pushfstring(L, "%s: %s", info, strerror(errno)); + lua_pushinteger(L, errno); + return 3; +} + +static int pushresult(lua_State *L, int i, const char *info) +{ + if (i==-1) + return pusherror(L, info); + lua_pushinteger(L, i); + return 1; +} + + +/* +** This function changes the working (current) directory +*/ +static int change_dir (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + if (chdir(path)) { + lua_pushnil (L); + lua_pushfstring (L,"Unable to change working directory to '%s'\n%s\n", + path, chdir_error); + return 2; + } else { + lua_pushboolean (L, 1); + return 1; + } +} + +/* +** This function returns the current directory +** If unable to get the current directory, it returns nil +** and a string describing the error +*/ +static int get_dir (lua_State *L) { + char *path; + /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */ + char buf[LFS_MAXPATHLEN]; + if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) { + lua_pushnil(L); + lua_pushstring(L, getcwd_error); + return 2; + } + else { + lua_pushstring(L, path); + return 1; + } +} + +/* +** Check if the given element on the stack is a file and returns it. +*/ +static FILE *check_file (lua_State *L, int idx, const char *funcname) { +#if LUA_VERSION_NUM == 501 + FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*"); + if (*fh == NULL) { + luaL_error (L, "%s: closed file", funcname); + return 0; + } else + return *fh; +#elif LUA_VERSION_NUM >= 502 && LUA_VERSION_NUM <= 503 + luaL_Stream *fh = (luaL_Stream *)luaL_checkudata (L, idx, "FILE*"); + if (fh->closef == 0 || fh->f == NULL) { + luaL_error (L, "%s: closed file", funcname); + return 0; + } else + return fh->f; +#else +#error unsupported Lua version +#endif +} + + +/* +** +*/ +static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname) { + int code; +#ifdef _WIN32 + /* lkmode valid values are: + LK_LOCK Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error. + LK_NBLCK Locks the specified bytes. If the bytes cannot be locked, the constant returns an error. + LK_NBRLCK Same as _LK_NBLCK. + LK_RLCK Same as _LK_LOCK. + LK_UNLCK Unlocks the specified bytes, which must have been previously locked. + + Regions should be locked only briefly and should be unlocked before closing a file or exiting the program. + + http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp + */ + int lkmode; + switch (*mode) { + case 'r': lkmode = LK_NBLCK; break; + case 'w': lkmode = LK_NBLCK; break; + case 'u': lkmode = LK_UNLCK; break; + default : return luaL_error (L, "%s: invalid mode", funcname); + } + if (!len) { + fseek (fh, 0L, SEEK_END); + len = ftell (fh); + } + fseek (fh, start, SEEK_SET); +#ifdef __BORLANDC__ + code = locking (fileno(fh), lkmode, len); +#else + code = _locking (fileno(fh), lkmode, len); +#endif +#else + struct flock f; + switch (*mode) { + case 'w': f.l_type = F_WRLCK; break; + case 'r': f.l_type = F_RDLCK; break; + case 'u': f.l_type = F_UNLCK; break; + default : return luaL_error (L, "%s: invalid mode", funcname); + } + f.l_whence = SEEK_SET; + f.l_start = (off_t)start; + f.l_len = (off_t)len; + code = fcntl (fileno(fh), F_SETLK, &f); +#endif + return (code != -1); +} + +#ifdef _WIN32 +typedef struct lfs_Lock { + HANDLE fd; +} lfs_Lock; +static int lfs_lock_dir(lua_State *L) { + size_t pathl; HANDLE fd; + lfs_Lock *lock; + char *ln; + const char *lockfile = "/lockfile.lfs"; + const char *path = luaL_checklstring(L, 1, &pathl); + ln = (char*)malloc(pathl + strlen(lockfile) + 1); + if(!ln) { + lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; + } + strcpy(ln, path); strcat(ln, lockfile); + if((fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL)) == INVALID_HANDLE_VALUE) { + int en = GetLastError(); + free(ln); lua_pushnil(L); + if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION) + lua_pushstring(L, "File exists"); + else + lua_pushstring(L, strerror(en)); + return 2; + } + free(ln); + lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock)); + lock->fd = fd; + luaL_getmetatable (L, LOCK_METATABLE); + lua_setmetatable (L, -2); + return 1; +} +static int lfs_unlock_dir(lua_State *L) { + lfs_Lock *lock = (lfs_Lock *)luaL_checkudata(L, 1, LOCK_METATABLE); + if(lock->fd != INVALID_HANDLE_VALUE) { + CloseHandle(lock->fd); + lock->fd=INVALID_HANDLE_VALUE; + } + return 0; +} +#else +typedef struct lfs_Lock { + char *ln; +} lfs_Lock; +static int lfs_lock_dir(lua_State *L) { + lfs_Lock *lock; + size_t pathl; + char *ln; + const char *lockfile = "/lockfile.lfs"; + const char *path = luaL_checklstring(L, 1, &pathl); + lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock)); + ln = (char*)malloc(pathl + strlen(lockfile) + 1); + if(!ln) { + lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; + } + strcpy(ln, path); strcat(ln, lockfile); + if(symlink("lock", ln) == -1) { + free(ln); lua_pushnil(L); + lua_pushstring(L, strerror(errno)); return 2; + } + lock->ln = ln; + luaL_getmetatable (L, LOCK_METATABLE); + lua_setmetatable (L, -2); + return 1; +} +static int lfs_unlock_dir(lua_State *L) { + lfs_Lock *lock = (lfs_Lock *)luaL_checkudata(L, 1, LOCK_METATABLE); + if(lock->ln) { + unlink(lock->ln); + free(lock->ln); + lock->ln = NULL; + } + return 0; +} +#endif + +static int lfs_g_setmode (lua_State *L, FILE *f, int arg) { + static const int mode[] = {_O_BINARY, _O_TEXT}; + static const char *const modenames[] = {"binary", "text", NULL}; + int op = luaL_checkoption(L, arg, NULL, modenames); + int res = lfs_setmode(f, mode[op]); + if (res != -1) { + int i; + lua_pushboolean(L, 1); + for (i = 0; modenames[i] != NULL; i++) { + if (mode[i] == res) { + lua_pushstring(L, modenames[i]); + return 2; + } + } + lua_pushnil(L); + return 2; + } else { + return pusherror(L, NULL); + } +} + +static int lfs_f_setmode(lua_State *L) { + return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2); +} + +/* +** Locks a file. +** @param #1 File handle. +** @param #2 String with lock mode ('w'rite, 'r'ead). +** @param #3 Number with start position (optional). +** @param #4 Number with length (optional). +*/ +static int file_lock (lua_State *L) { + FILE *fh = check_file (L, 1, "lock"); + const char *mode = luaL_checkstring (L, 2); + const long start = (long) luaL_optinteger (L, 3, 0); + long len = (long) luaL_optinteger (L, 4, 0); + if (_file_lock (L, fh, mode, start, len, "lock")) { + lua_pushboolean (L, 1); + return 1; + } else { + lua_pushnil (L); + lua_pushfstring (L, "%s", strerror(errno)); + return 2; + } +} + + +/* +** Unlocks a file. +** @param #1 File handle. +** @param #2 Number with start position (optional). +** @param #3 Number with length (optional). +*/ +static int file_unlock (lua_State *L) { + FILE *fh = check_file (L, 1, "unlock"); + const long start = (long) luaL_optinteger (L, 2, 0); + long len = (long) luaL_optinteger (L, 3, 0); + if (_file_lock (L, fh, "u", start, len, "unlock")) { + lua_pushboolean (L, 1); + return 1; + } else { + lua_pushnil (L); + lua_pushfstring (L, "%s", strerror(errno)); + return 2; + } +} + + +/* +** Creates a link. +** @param #1 Object to link to. +** @param #2 Name of link. +** @param #3 True if link is symbolic (optional). +*/ +static int make_link(lua_State *L) +{ +#ifndef _WIN32 + const char *oldpath = luaL_checkstring(L, 1); + const char *newpath = luaL_checkstring(L, 2); + return pushresult(L, + (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL); +#else + errno = ENOSYS; /* = "Function not implemented" */ + return pushresult(L, -1, "make_link is not supported on Windows"); +#endif +} + + +/* +** Creates a directory. +** @param #1 Directory path. +*/ +static int make_dir (lua_State *L) { + const char *path = luaL_checkstring (L, 1); + int fail; +#ifdef _WIN32 + fail = _mkdir (path); +#else + fail = mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | + S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH ); +#endif + if (fail) { + lua_pushnil (L); + lua_pushfstring (L, "%s", strerror(errno)); + return 2; + } + lua_pushboolean (L, 1); + return 1; +} + + +/* +** Removes a directory. +** @param #1 Directory path. +*/ +static int remove_dir (lua_State *L) { + const char *path = luaL_checkstring (L, 1); + int fail; + + fail = rmdir (path); + + if (fail) { + lua_pushnil (L); + lua_pushfstring (L, "%s", strerror(errno)); + return 2; + } + lua_pushboolean (L, 1); + return 1; +} + + +/* +** Directory iterator +*/ +static int dir_iter (lua_State *L) { +#ifdef _WIN32 + struct _finddata_t c_file; +#else + struct dirent *entry; +#endif + dir_data *d = (dir_data *)luaL_checkudata (L, 1, DIR_METATABLE); + luaL_argcheck (L, d->closed == 0, 1, "closed directory"); +#ifdef _WIN32 + if (d->hFile == 0L) { /* first entry */ + if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) { + lua_pushnil (L); + lua_pushstring (L, strerror (errno)); + d->closed = 1; + return 2; + } else { + lua_pushstring (L, c_file.name); + return 1; + } + } else { /* next entry */ + if (_findnext (d->hFile, &c_file) == -1L) { + /* no more entries => close directory */ + _findclose (d->hFile); + d->closed = 1; + return 0; + } else { + lua_pushstring (L, c_file.name); + return 1; + } + } +#else + if ((entry = readdir (d->dir)) != NULL) { + lua_pushstring (L, entry->d_name); + return 1; + } else { + /* no more entries => close directory */ + closedir (d->dir); + d->closed = 1; + return 0; + } +#endif +} + + +/* +** Closes directory iterators +*/ +static int dir_close (lua_State *L) { + dir_data *d = (dir_data *)lua_touserdata (L, 1); +#ifdef _WIN32 + if (!d->closed && d->hFile) { + _findclose (d->hFile); + } +#else + if (!d->closed && d->dir) { + closedir (d->dir); + } +#endif + d->closed = 1; + return 0; +} + + +/* +** Factory of directory iterators +*/ +static int dir_iter_factory (lua_State *L) { + const char *path = luaL_checkstring (L, 1); + dir_data *d; + lua_pushcfunction (L, dir_iter); + d = (dir_data *) lua_newuserdata (L, sizeof(dir_data)); + luaL_getmetatable (L, DIR_METATABLE); + lua_setmetatable (L, -2); + d->closed = 0; +#ifdef _WIN32 + d->hFile = 0L; + if (strlen(path) > MAX_PATH-2) + luaL_error (L, "path too long: %s", path); + else + sprintf (d->pattern, "%s/*", path); +#else + d->dir = opendir (path); + if (d->dir == NULL) + luaL_error (L, "cannot open %s: %s", path, strerror (errno)); +#endif + return 2; +} + + +/* +** Creates directory metatable. +*/ +static int dir_create_meta (lua_State *L) { + luaL_newmetatable (L, DIR_METATABLE); + + /* Method table */ + lua_newtable(L); + lua_pushcfunction (L, dir_iter); + lua_setfield(L, -2, "next"); + lua_pushcfunction (L, dir_close); + lua_setfield(L, -2, "close"); + + /* Metamethods */ + lua_setfield(L, -2, "__index"); + lua_pushcfunction (L, dir_close); + lua_setfield (L, -2, "__gc"); + return 1; +} + + +/* +** Creates lock metatable. +*/ +static int lock_create_meta (lua_State *L) { + luaL_newmetatable (L, LOCK_METATABLE); + + /* Method table */ + lua_newtable(L); + lua_pushcfunction(L, lfs_unlock_dir); + lua_setfield(L, -2, "free"); + + /* Metamethods */ + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, lfs_unlock_dir); + lua_setfield(L, -2, "__gc"); + return 1; +} + + +#ifdef _WIN32 + #ifndef S_ISDIR + #define S_ISDIR(mode) (mode&_S_IFDIR) + #endif + #ifndef S_ISREG + #define S_ISREG(mode) (mode&_S_IFREG) + #endif + #ifndef S_ISLNK + #define S_ISLNK(mode) (0) + #endif + #ifndef S_ISSOCK + #define S_ISSOCK(mode) (0) + #endif + #ifndef S_ISFIFO + #define S_ISFIFO(mode) (0) + #endif + #ifndef S_ISCHR + #define S_ISCHR(mode) (mode&_S_IFCHR) + #endif + #ifndef S_ISBLK + #define S_ISBLK(mode) (0) + #endif +#endif +/* +** Convert the inode protection mode to a string. +*/ +#ifdef _WIN32 +static const char *mode2string (unsigned short mode) { +#else +static const char *mode2string (mode_t mode) { +#endif + if ( S_ISREG(mode) ) + return "file"; + else if ( S_ISDIR(mode) ) + return "directory"; + else if ( S_ISLNK(mode) ) + return "link"; + else if ( S_ISSOCK(mode) ) + return "socket"; + else if ( S_ISFIFO(mode) ) + return "named pipe"; + else if ( S_ISCHR(mode) ) + return "char device"; + else if ( S_ISBLK(mode) ) + return "block device"; + else + return "other"; +} + + +/* +** Set access time and modification values for file +*/ +static int file_utime (lua_State *L) { + const char *file = luaL_checkstring (L, 1); + struct utimbuf utb, *buf; + + if (lua_gettop (L) == 1) /* set to current date/time */ + buf = NULL; + else { + utb.actime = (time_t)luaL_optnumber (L, 2, 0); + utb.modtime = (time_t) luaL_optinteger (L, 3, utb.actime); + buf = &utb; + } + if (utime (file, buf)) { + lua_pushnil (L); + lua_pushfstring (L, "%s", strerror (errno)); + return 2; + } + lua_pushboolean (L, 1); + return 1; +} + + +/* inode protection mode */ +static void push_st_mode (lua_State *L, STAT_STRUCT *info) { + lua_pushstring (L, mode2string (info->st_mode)); +} +/* device inode resides on */ +static void push_st_dev (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_dev); +} +/* inode's number */ +static void push_st_ino (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_ino); +} +/* number of hard links to the file */ +static void push_st_nlink (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_nlink); +} +/* user-id of owner */ +static void push_st_uid (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_uid); +} +/* group-id of owner */ +static void push_st_gid (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_gid); +} +/* device type, for special file inode */ +static void push_st_rdev (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_rdev); +} +/* time of last access */ +static void push_st_atime (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_atime); +} +/* time of last data modification */ +static void push_st_mtime (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_mtime); +} +/* time of last file status change */ +static void push_st_ctime (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_ctime); +} +/* file size, in bytes */ +static void push_st_size (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_size); +} +#ifndef _WIN32 +/* blocks allocated for file */ +static void push_st_blocks (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_blocks); +} +/* optimal file system I/O blocksize */ +static void push_st_blksize (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_blksize); +} +#endif + + /* +** Convert the inode protection mode to a permission list. +*/ + +#ifdef _WIN32 +static const char *perm2string (unsigned short mode) { + static char perms[10] = "---------"; + int i; + for (i=0;i<9;i++) perms[i]='-'; + if (mode & _S_IREAD) + { perms[0] = 'r'; perms[3] = 'r'; perms[6] = 'r'; } + if (mode & _S_IWRITE) + { perms[1] = 'w'; perms[4] = 'w'; perms[7] = 'w'; } + if (mode & _S_IEXEC) + { perms[2] = 'x'; perms[5] = 'x'; perms[8] = 'x'; } + return perms; +} +#else +static const char *perm2string (mode_t mode) { + static char perms[10] = "---------"; + int i; + for (i=0;i<9;i++) perms[i]='-'; + if (mode & S_IRUSR) perms[0] = 'r'; + if (mode & S_IWUSR) perms[1] = 'w'; + if (mode & S_IXUSR) perms[2] = 'x'; + if (mode & S_IRGRP) perms[3] = 'r'; + if (mode & S_IWGRP) perms[4] = 'w'; + if (mode & S_IXGRP) perms[5] = 'x'; + if (mode & S_IROTH) perms[6] = 'r'; + if (mode & S_IWOTH) perms[7] = 'w'; + if (mode & S_IXOTH) perms[8] = 'x'; + return perms; +} +#endif + +/* permssions string */ +static void push_st_perm (lua_State *L, STAT_STRUCT *info) { + lua_pushstring (L, perm2string (info->st_mode)); +} + +typedef void (*_push_function) (lua_State *L, STAT_STRUCT *info); + +struct _stat_members { + const char *name; + _push_function push; +}; + +struct _stat_members members[] = { + { "mode", push_st_mode }, + { "dev", push_st_dev }, + { "ino", push_st_ino }, + { "nlink", push_st_nlink }, + { "uid", push_st_uid }, + { "gid", push_st_gid }, + { "rdev", push_st_rdev }, + { "access", push_st_atime }, + { "modification", push_st_mtime }, + { "change", push_st_ctime }, + { "size", push_st_size }, + { "permissions", push_st_perm }, +#ifndef _WIN32 + { "blocks", push_st_blocks }, + { "blksize", push_st_blksize }, +#endif + { NULL, NULL } +}; + +/* +** Get file or symbolic link information +*/ +static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) { + STAT_STRUCT info; + const char *file = luaL_checkstring (L, 1); + int i; + + if (st(file, &info)) { + lua_pushnil(L); + lua_pushfstring(L, "cannot obtain information from file '%s': %s", file, strerror(errno)); + return 2; + } + if (lua_isstring (L, 2)) { + const char *member = lua_tostring (L, 2); + for (i = 0; members[i].name; i++) { + if (strcmp(members[i].name, member) == 0) { + /* push member value and return */ + members[i].push (L, &info); + return 1; + } + } + /* member not found */ + return luaL_error(L, "invalid attribute name '%s'", member); + } + /* creates a table if none is given, removes extra arguments */ + lua_settop(L, 2); + if (!lua_istable (L, 2)) { + lua_newtable (L); + } + /* stores all members in table on top of the stack */ + for (i = 0; members[i].name; i++) { + lua_pushstring (L, members[i].name); + members[i].push (L, &info); + lua_rawset (L, -3); + } + return 1; +} + + +/* +** Get file information using stat. +*/ +static int file_info (lua_State *L) { + return _file_info_ (L, STAT_FUNC); +} + + +/* +** Push the symlink target to the top of the stack. +** Assumes the file name is at position 1 of the stack. +** Returns 1 if successful (with the target on top of the stack), +** 0 on failure (with stack unchanged, and errno set). +*/ +static int push_link_target(lua_State *L) { +#ifdef _WIN32 + errno = ENOSYS; + return 0; +#else + const char *file = luaL_checkstring(L, 1); + char *target = NULL; + int tsize, size = 256; /* size = initial buffer capacity */ + while (1) { + target = realloc(target, size); + if (!target) /* failed to allocate */ + return 0; + tsize = readlink(file, target, size); + if (tsize < 0) { /* a readlink() error occurred */ + free(target); + return 0; + } + if (tsize < size) + break; + /* possibly truncated readlink() result, double size and retry */ + size *= 2; + } + target[tsize] = '\0'; + lua_pushlstring(L, target, tsize); + free(target); + return 1; +#endif +} + +/* +** Get symbolic link information using lstat. +*/ +static int link_info (lua_State *L) { + int ret; + if (lua_isstring (L, 2) && (strcmp(lua_tostring(L, 2), "target") == 0)) { + int ok = push_link_target(L); + return ok ? 1 : pusherror(L, "could not obtain link target"); + } + ret = _file_info_ (L, LSTAT_FUNC); + if (ret == 1 && lua_type(L, -1) == LUA_TTABLE) { + int ok = push_link_target(L); + if (ok) { + lua_setfield(L, -2, "target"); + } + } + return ret; +} + + +/* +** Assumes the table is on top of the stack. +*/ +static void set_info (lua_State *L) { + lua_pushliteral(L, "Copyright (C) 2003-2016 Kepler Project"); + lua_setfield(L, -2, "_COPYRIGHT"); + lua_pushliteral(L, "LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution"); + lua_setfield(L, -2, "_DESCRIPTION"); + lua_pushliteral(L, "LuaFileSystem " LFS_VERSION); + lua_setfield(L, -2, "_VERSION"); +} + + +static const struct luaL_Reg fslib[] = { + {"attributes", file_info}, + {"chdir", change_dir}, + {"currentdir", get_dir}, + {"dir", dir_iter_factory}, + {"link", make_link}, + {"lock", file_lock}, + {"mkdir", make_dir}, + {"rmdir", remove_dir}, + {"symlinkattributes", link_info}, + {"setmode", lfs_f_setmode}, + {"touch", file_utime}, + {"unlock", file_unlock}, + {"lock_dir", lfs_lock_dir}, + {NULL, NULL}, +}; + +LFS_EXPORT int luaopen_lfs (lua_State *L) { + dir_create_meta (L); + lock_create_meta (L); + luaL_newlib (L, fslib); + lua_pushvalue(L, -1); + lua_setglobal(L, LFS_LIBNAME); + set_info (L); + return 1; +} diff --git a/lua/src/lfs.h b/lua/src/lfs.h new file mode 100644 index 0000000..7f7d2ab --- /dev/null +++ b/lua/src/lfs.h @@ -0,0 +1,34 @@ +/* +** LuaFileSystem +** Copyright Kepler Project 2003 - 2016 (http://keplerproject.github.io/luafilesystem) +*/ + +/* Define 'chdir' for systems that do not implement it */ +#ifdef NO_CHDIR + #define chdir(p) (-1) + #define chdir_error "Function 'chdir' not provided by system" +#else + #define chdir_error strerror(errno) +#endif + +#ifdef _WIN32 + #define chdir(p) (_chdir(p)) + #define getcwd(d, s) (_getcwd(d, s)) + #define rmdir(p) (_rmdir(p)) + #define LFS_EXPORT __declspec (dllexport) + #ifndef fileno + #define fileno(f) (_fileno(f)) + #endif +#else + #define LFS_EXPORT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +LFS_EXPORT int luaopen_lfs (lua_State *L); + +#ifdef __cplusplus +} +#endif From 7e36ea5fff1ec4da6febbd09a96865f2ade73dd1 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Thu, 15 Sep 2016 12:35:07 +0200 Subject: [PATCH 33/45] add lfs hook --- load81.c | 1 + 1 file changed, 1 insertion(+) diff --git a/load81.c b/load81.c index ac0e942..8fef213 100644 --- a/load81.c +++ b/load81.c @@ -657,6 +657,7 @@ void resetProgram(void) { luaopen_string(l81.L); luaopen_math(l81.L); luaopen_debug(l81.L); + luaopen_lfs(l81.L); setNumber("WIDTH",l81.width); setNumber("HEIGHT",l81.height); luaL_loadbuffer(l81.L,initscript,strlen(initscript),"initscript"); From 29c5d9b0f3fd0bdaf38ca448cd4e55d02665a011 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Thu, 15 Sep 2016 12:36:15 +0200 Subject: [PATCH 34/45] Add LFS --- lua/src/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/src/Makefile b/lua/src/Makefile index 78cd6d1..38afec4 100644 --- a/lua/src/Makefile +++ b/lua/src/Makefile @@ -153,6 +153,7 @@ lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \ ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h +lfs.o: lfs.c lfs.h lua.h luaconf.h lualib.h lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ lfunc.h lstring.h lgc.h ltable.h From eb3927bede4336d360d966cec362d6038ebf63af Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Thu, 15 Sep 2016 12:36:39 +0200 Subject: [PATCH 35/45] localized headers instead of system headers --- lua/src/lfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lua/src/lfs.c b/lua/src/lfs.c index 8154a46..a842f17 100644 --- a/lua/src/lfs.c +++ b/lua/src/lfs.c @@ -59,9 +59,9 @@ #include #endif -#include -#include -#include +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" #include "lfs.h" From b5c9459ee7753789113160075af5df8ffac39ad8 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Thu, 15 Sep 2016 12:37:03 +0200 Subject: [PATCH 36/45] export LFS for use in LOAD81 --- lua/src/lfs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/src/lfs.h b/lua/src/lfs.h index 7f7d2ab..f445ef0 100644 --- a/lua/src/lfs.h +++ b/lua/src/lfs.h @@ -20,14 +20,14 @@ #define fileno(f) (_fileno(f)) #endif #else - #define LFS_EXPORT + #define LFS_EXPORT extern #endif #ifdef __cplusplus extern "C" { #endif -LFS_EXPORT int luaopen_lfs (lua_State *L); +LFS_EXPORT int luaopen_lfs (lua_State *L); #ifdef __cplusplus } From 3976c8eec036910a7297462826cb00f60e4c715b Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Thu, 15 Sep 2016 12:37:28 +0200 Subject: [PATCH 37/45] include lfs in lualibs[] --- lua/src/linit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/src/linit.c b/lua/src/linit.c index c1f90df..b2f9ae2 100644 --- a/lua/src/linit.c +++ b/lua/src/linit.c @@ -20,6 +20,7 @@ static const luaL_Reg lualibs[] = { {LUA_TABLIBNAME, luaopen_table}, {LUA_IOLIBNAME, luaopen_io}, {LUA_OSLIBNAME, luaopen_os}, + {LUA_LFSLIBNAME, luaopen_lfs}, {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, {LUA_DBLIBNAME, luaopen_debug}, From c08025b4c01586e86e12637a5de8e017d57d9154 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Thu, 15 Sep 2016 12:37:57 +0200 Subject: [PATCH 38/45] global luaopen_lfs export --- lua/src/lualib.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lua/src/lualib.h b/lua/src/lualib.h index 469417f..21722ba 100644 --- a/lua/src/lualib.h +++ b/lua/src/lualib.h @@ -39,6 +39,8 @@ LUALIB_API int (luaopen_debug) (lua_State *L); #define LUA_LOADLIBNAME "package" LUALIB_API int (luaopen_package) (lua_State *L); +#define LUA_LFSLIBNAME "lfs" +LUALIB_API int (luaopen_lfs) (lua_State *L); /* open all previous libraries */ LUALIB_API void (luaL_openlibs) (lua_State *L); From d632917786021bbc280cb34f3a80a6ba7b9c19d9 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Fri, 16 Sep 2016 12:27:09 +0200 Subject: [PATCH 39/45] Put libs back in place properly --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 0bac9ea..9d1b16c 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,11 @@ PKGS=sdl SDL_gfx SDL_image CFLAGS=-O2 -Wall -W -Ilua/src `sdl-config --cflags` -LDLIBS=lua/src/liblua.a -lm `sdl-config --libs` +LDLIBS=lua/src/liblua.a -lm `sdl-config --libs` -lSDL_gfx -lSDL_image # Customizations per-OS UNAME := $(shell uname) ifeq ($(UNAME), Darwin) CFLAGS+=-I/usr/local/Cellar//sdl_gfx/2.0.25/include/SDL/ -I/usr/local/Cellar//sdl_image/1.2.12_3/include/SDL/ -LDLIBS+=-lSDL_gfx -lSDL_image endif all: load81 From fae5aa35f7f089e81ae31bda89258549cdad3915 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Fri, 16 Sep 2016 12:34:51 +0200 Subject: [PATCH 40/45] Add debian package control dir --- contrib/debian_pocketchip/load81_0.0-2/DEBIAN/control | 11 +++++++++++ contrib/debian_pocketchip/makedeb.sh | 1 + 2 files changed, 12 insertions(+) create mode 100644 contrib/debian_pocketchip/load81_0.0-2/DEBIAN/control create mode 100644 contrib/debian_pocketchip/makedeb.sh diff --git a/contrib/debian_pocketchip/load81_0.0-2/DEBIAN/control b/contrib/debian_pocketchip/load81_0.0-2/DEBIAN/control new file mode 100644 index 0000000..dd3a844 --- /dev/null +++ b/contrib/debian_pocketchip/load81_0.0-2/DEBIAN/control @@ -0,0 +1,11 @@ +Package: load81 +Version: 0.1-1 +Section: base +Priority: optional +Architecture: armhf +Maintainer: seclorum +Depends: libsdl-gfx1.2-5 (>=1.2), libsdl-image1.2 (>=1.2) +Description: antirez' LOAD81 packaged for PocketCHIP. + antirez (http://github.com/antirez/load81) created the wonderful + load81 development environment, which provides an editor to + create small apps in the Lua programming language. diff --git a/contrib/debian_pocketchip/makedeb.sh b/contrib/debian_pocketchip/makedeb.sh new file mode 100644 index 0000000..656a61c --- /dev/null +++ b/contrib/debian_pocketchip/makedeb.sh @@ -0,0 +1 @@ +dpkg-deb --build load81_0.0-2/ From f5c5716135cc1ada906bf9b79f53cee2202f67f5 Mon Sep 17 00:00:00 2001 From: seclorum Date: Fri, 7 Oct 2016 18:59:50 +0200 Subject: [PATCH 41/45] clean --- Makefile | 2 ++ runner.sh | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100755 runner.sh diff --git a/Makefile b/Makefile index 9d1b16c..a8e592b 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ + PKGS=sdl SDL_gfx SDL_image CFLAGS=-O2 -Wall -W -Ilua/src `sdl-config --cflags` LDLIBS=lua/src/liblua.a -lm `sdl-config --libs` -lSDL_gfx -lSDL_image @@ -26,3 +27,4 @@ distclean: clean dep: $(CC) -MM *.c + diff --git a/runner.sh b/runner.sh new file mode 100755 index 0000000..366f631 --- /dev/null +++ b/runner.sh @@ -0,0 +1,13 @@ +# runs load81, resetting it if any file-changes occur in the +# WATCHDIR, for example, the onboard examples/ .. any changes +# to the dir will re-load load81 .. +#!/bin/bash +export DISPLAY=:0 +WATCHDIR=./examples/ +inotifywait -m -e close_write $WATCHDIR | \ +while read -r notifile event filename ; \ +do \ + echo "notifile: $notifile event: $event filename: $filename" + killall load81 ; \ + ./load81 --width 480 --height 272 $notifile/$filename & \ +done From b72f00fdacf202a86f3ba309afb216490d7f5897 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Fri, 7 Oct 2016 19:19:49 +0200 Subject: [PATCH 42/45] gridify example --- examples/gridify.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/gridify.lua b/examples/gridify.lua index c297429..8447768 100644 --- a/examples/gridify.lua +++ b/examples/gridify.lua @@ -158,10 +158,10 @@ end function draw_grids() - draw_percentile_grid() - draw_centered_grid() + -- draw_percentile_grid() + -- draw_centered_grid() draw_XY_grid() --- draw_colors_grids() + draw_colors_grids() end function draw() From c9227b14f391e93c85accb118c0dbb1f1602bf27 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Fri, 7 Oct 2016 19:20:00 +0200 Subject: [PATCH 43/45] filelist example --- examples/filelist.lua | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 examples/filelist.lua diff --git a/examples/filelist.lua b/examples/filelist.lua new file mode 100644 index 0000000..2a78878 --- /dev/null +++ b/examples/filelist.lua @@ -0,0 +1,36 @@ + +listed = false + + +function setup() + fileList = {} + print("current working dir: " .. lfs.currentdir()) + for file in lfs.dir[[./examples/]] do + if lfs.attributes(file,"mode") == "file" then + print("found file, "..file) + elseif lfs.attributes(file,"mode")== "directory" then + if (file == ".") then + print("found dir, "..file," containing:") + for l in lfs.dir("./examples/"..file) do + if (l~="." and l~="..") then + print("",l) + -- table.insert(fileList, file) + end + end + end + end + end +end + + +function draw() + if (listed == false) then + for iFile,aFile in ipairs(fileList) do + print("a File:"..iFile) + end + listed = true + else print("Listed?") + end +end + + From 41ca649c6173a97608f0fb6662a0728bccd8c574 Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Fri, 7 Oct 2016 19:22:17 +0200 Subject: [PATCH 44/45] runner to contrib --- runner.sh => contrib/PocketCHIP/runner.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename runner.sh => contrib/PocketCHIP/runner.sh (100%) diff --git a/runner.sh b/contrib/PocketCHIP/runner.sh similarity index 100% rename from runner.sh rename to contrib/PocketCHIP/runner.sh From b730212b7febfb5555fda15402e59db4f26bd34d Mon Sep 17 00:00:00 2001 From: Jay Vaughan Date: Fri, 7 Oct 2016 19:22:47 +0200 Subject: [PATCH 45/45] /usr/include for build --- lua/src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/src/Makefile b/lua/src/Makefile index 38afec4..e6c4a16 100644 --- a/lua/src/Makefile +++ b/lua/src/Makefile @@ -8,7 +8,7 @@ PLAT= none CC= gcc -CFLAGS= -O2 -Wall $(MYCFLAGS) +CFLAGS= -O2 -Wall $(MYCFLAGS) -I/usr/include AR= ar rcu RANLIB= ranlib RM= rm -f