diff --git a/lua.cpp b/lua.cpp index 68b192f..5bb3024 100644 --- a/lua.cpp +++ b/lua.cpp @@ -3,6 +3,43 @@ #include "mini.h" extern "C" { + static int cpp_newsurf(lua_State *L) { + int w = luaL_checknumber(L, 1); + int h = luaL_checknumber(L, 2); + lua_pushinteger(L, newsurf(w, h)); + return 1; + } + + static int cpp_loadsurf(lua_State *L) { + const char* str = luaL_checkstring(L, 1); + lua_pushinteger(L, loadsurf(str)); + return 1; + } + + static int cpp_freesurf(lua_State *L) { + uint8_t surface = luaL_checkinteger(L, 1); + freesurf(surface); + return 0; + } + + static int cpp_setdest(lua_State *L) { + uint8_t surface = luaL_checkinteger(L, 1); + setdest(surface); + return 0; + } + + static int cpp_setsource(lua_State *L) { + uint8_t surface = luaL_checkinteger(L, 1); + setsource(surface); + return 0; + } + + static int cpp_setmap(lua_State *L) { + uint8_t surface = luaL_checkinteger(L, 1); + setmap(surface); + return 0; + } + static int cpp_cls(lua_State *L) { uint8_t color = luaL_optinteger(L, 1, 0); cls(color); @@ -461,6 +498,13 @@ void lua_init() { return; } + lua_pushcfunction(L,cpp_newsurf); lua_setglobal(L, "newsurf"); + lua_pushcfunction(L,cpp_loadsurf); lua_setglobal(L, "loadsurf"); + lua_pushcfunction(L,cpp_freesurf); lua_setglobal(L, "freesurf"); + lua_pushcfunction(L,cpp_setdest); lua_setglobal(L, "setdest"); + lua_pushcfunction(L,cpp_setsource); lua_setglobal(L, "setsource"); + lua_pushcfunction(L,cpp_setmap); lua_setglobal(L, "setmap"); + lua_pushcfunction(L,cpp_cls); lua_setglobal(L, "cls"); lua_pushcfunction(L,cpp_color); lua_setglobal(L, "color"); lua_pushcfunction(L,cpp_pal); lua_setglobal(L, "pal"); diff --git a/mini.cpp b/mini.cpp index 0f0fb11..711c4e5 100644 --- a/mini.cpp +++ b/mini.cpp @@ -3,36 +3,36 @@ #include #include "lua.h" +#pragma pack(1) + struct surface_t { - uint8_t *pointer; + uint8_t *p; uint16_t w, h; - uint32_t size_in_bytes; + uint32_t size; }; #define swap(a, b) {auto tmp=a;a=b;b=tmp;} char window_title[256]; -#define SCREEN_WIDTH 160 -#define SCREEN_HEIGHT 120 -#define SCREEN_SIZE_BYTES SCREEN_WIDTH*SCREEN_HEIGHT -#define SPRITES_WIDTH 128 -#define SPRITES_HEIGHT 128 -#define SPRITES_SIZE_BYTES SPRITES_WIDTH*SPRITES_HEIGHT -#define SPRITES_PER_LINE SPRITES_WIDTH/8 -#define SPRITES_PER_ROW SPRITES_HEIGHT/8 -#define TILES_WIDTH 128 -#define TILES_HEIGHT 128 -#define TILES_SIZE_BYTES TILES_WIDTH*TILES_HEIGHT +uint16_t screen_width = 160; +uint16_t screen_height = 120; +uint8_t screen_zoom = 4; +surface_t surfaces[10]; +surface_t *screen_surface = &surfaces[0]; +surface_t *dest_surface = screen_surface; +surface_t *source_surface = NULL; +surface_t *map_surface = NULL; -#define SCREEN(x, y) screen[x+(y)*SCREEN_WIDTH] -#define SPRITES(x, y) sprites[x+(y)*SPRITES_WIDTH] -#define TILES(x, y) tiles[x+(y)*TILES_WIDTH] +#define DEST(x, y) dest_surface->p[x+y*dest_surface->w] +#define SOURCE(x, y) source_surface->p[x+y*source_surface->w] +#define TILES(x, y) map_surface->p[x+y*map_surface->w] +#define CURRENT(x, y) surfaces[i].p[(x)+(y)*surfaces[i].w] namespace ds { uint8_t pen_color = 6; int cam[2] = {0, 0}; - int clip[4] = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; - int clp[4] = {0, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1}; + int clip[4] = {0, 0, screen_width, screen_height}; + int clp[4] = {0, 0, screen_width-1, screen_height-1}; uint8_t draw_palette[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; uint8_t screen_palette[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; bool trans[16] = {true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}; @@ -45,12 +45,9 @@ SDL_Renderer *mini_ren; SDL_Texture *mini_bak; Uint32 *pixels; int pitch; -uint8_t screen[SCREEN_SIZE_BYTES]; -uint8_t sprites[SPRITES_SIZE_BYTES]; -uint8_t tiles[TILES_SIZE_BYTES]; -uint32_t palette[16] = { 0x1a1c2c00, 0x5d275d00, 0xb13e5300, 0xef7d5700, 0xffcd7500, 0xa7f07000, 0x38b76400, 0x25717900, - 0x29366f00, 0x3b5dc900, 0x41a6f600, 0x73eff700, 0xf4f4f400, 0x94b0c200, 0x566c8600, 0x333c5700 }; +uint32_t palette[16] = { 0x001a1c2c, 0x005d275d, 0x00b13e53, 0x00ef7d57, 0x00ffcd75, 0x00a7f070, 0x0038b764, 0x00257179, + 0x0029366f, 0x003b5dc9, 0x0041a6f6, 0x0073eff7, 0x00f4f4f4, 0x0094b0c2, 0x00566c86, 0x00333c57 }; const char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -61,10 +58,10 @@ uint16_t font[96]; char base64glyphs[193] = "/h/AqV/hhhh/GMYYMGz/t/eS33H477wsjjswY4IOPHEFFVVVAVAVAVIc+dJHMMM/h/qBgBgVqq+//eIUi/dJzhAAhzAAA/eM" "AMShAAAQsjAAAwsjAAAeSzAAAcU3AAAEqRAAABVaiAAMezhAAAAAMAADH4wAASb2SAAMAttAQYcefACGOe+AAAVVAAAAbbAA"; -const int debug_line_size = (SCREEN_WIDTH/4); -const int debug_num_lines = (SCREEN_HEIGHT/6); -const int debug_total_size = debug_line_size*debug_num_lines; -char debug_text[debug_total_size]; +int debug_line_size = (screen_width/4); +int debug_num_lines = (screen_height/6); +int debug_total_size = debug_line_size*debug_num_lines; +char *debug_text = NULL; int debug_cursor = 0; //Uint8 keymapping[6] = { SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_Z, SDL_SCANCODE_X }; @@ -74,7 +71,25 @@ Uint8 key_just_pressed = 0; int mouse_x, mouse_y, mouse_wheel; Uint32 mouse_buttons; -char* get_value(char* line) { +struct bmp_header_t { + uint16_t header; // 'BM' 0x4D42 + uint32_t file_size; + uint32_t reserved; // ignore + uint32_t bmp_offset; // This is where the bmp data starts + uint32_t header_size; // Must be 40 + int32_t bmp_width; + int32_t bmp_height; + uint16_t num_color_planes; // Must be 1 + uint16_t bpp; + uint32_t compression; // expected 0 + uint32_t image_size; // warning, can be 0. Do not trust. Only useful for compressed BMPs (in my experience, it's always the size in bytes (not pixels) of the bmp) + int32_t hres; // ignore + int32_t vres; // ignore + uint32_t num_colors; // warning, can be 0. if 0, num_colors = 2^bpp + uint32_t num_important_colors; // ignore +}; + +char* get_value_from_line(char* line) { char* equal_character = strchr(line, '='); if (equal_character == NULL) return NULL; *equal_character = '\0'; @@ -84,12 +99,15 @@ char* get_value(char* line) { void read_ini() { FILE *f = fopen("game.ini", "r"); char line[256]; - if (f == NULL) return; while (fgets(line, sizeof(line), f)) { - char *value = get_value(line); + char *value = get_value_from_line(line); if (value != NULL) { - //if (strcmp(value, "title") == 0) + value[strlen(value)-1] = '\0'; + if (strcmp(line, "title") == 0) strcpy(window_title, value); + else if (strcmp(line, "width") == 0) screen_width = atoi(value); + else if (strcmp(line, "height") == 0) screen_height = atoi(value); + else if (strcmp(line, "zoom") == 0) screen_zoom = atoi(value); } } fclose(f); @@ -98,25 +116,116 @@ void read_ini() { void reinit() { ds::pen_color = 6; ds::cam[0] = ds::cam[1] = 0; - ds::clip[0] = ds::clip[1] = 0; ds::clip[2] = SCREEN_WIDTH; ds::clip[3] = SCREEN_HEIGHT; - ds::clp[0] = ds::clp[1] = 0; ds::clp[2] = SCREEN_WIDTH-1; ds::clp[3] = SCREEN_HEIGHT-1; + ds::clip[0] = ds::clip[1] = 0; ds::clip[2] = screen_width; ds::clip[3] = screen_height; + ds::clp[0] = ds::clp[1] = 0; ds::clp[2] = screen_width-1; ds::clp[3] = screen_height-1; for(int i=0;i<16;++i)ds::draw_palette[i]=i; for(int i=0;i<16;++i)ds::screen_palette[i]=i; ds::trans[0]=true;for(int i=1;i<16;++i)ds::trans[i]=false; ds::fill_pattern = 0b1111111111111111; ds::fill_trans = false; + for (int i=1; i<10; ++i) { + if (surfaces[i].p != NULL) free(surfaces[i].p); + surfaces[i].p = NULL; + } +} + +uint8_t newsurf(int w, int h) { + int i = 0; + while (i<10 && surfaces[i].p != NULL) ++i; + //[TODO] Gestionar el cas en que no queden surfaces lliures + surfaces[i].w = w; + surfaces[i].h = h; + surfaces[i].size = w*h; + surfaces[i].p = (uint8_t*)malloc(surfaces[i].size); + return i; +} + +uint8_t loadsurf(const char* filename) { + int i = 0; + while (i<10 && surfaces[i].p != NULL) ++i; + //[TODO] Gestionar el cas en que no queden surfaces lliures + + FILE *f = fopen(filename, "rb"); + if (f) { + bmp_header_t header; + fread(&header, 54, 1, f); + if (header.num_colors == 0) header.num_colors = 1 << header.bpp; + header.image_size = (header.bmp_width*header.bmp_height) * (8/header.bpp); + fseek(f, header.num_colors*4, SEEK_CUR); + uint8_t buffer[header.image_size]; + fread(buffer, header.image_size, 1, f); + fclose(f); + + surfaces[i].w = header.bmp_width; + surfaces[i].h = header.bmp_height; + surfaces[i].size = surfaces[i].w*surfaces[i].h; + surfaces[i].p = (uint8_t*)malloc(surfaces[i].size); + + for (int y=0; y> 7; + CURRENT(x*8+1, surfaces[i].w-1-y) = ( buffer[x+y*(surfaces[i].w/8)] >> 6 ) & 0x1; + CURRENT(x*8+2, surfaces[i].w-1-y) = ( buffer[x+y*(surfaces[i].w/8)] >> 5 ) & 0x1; + CURRENT(x*8+3, surfaces[i].w-1-y) = ( buffer[x+y*(surfaces[i].w/8)] >> 4 ) & 0x1; + CURRENT(x*8+4, surfaces[i].w-1-y) = ( buffer[x+y*(surfaces[i].w/8)] >> 3 ) & 0x1; + CURRENT(x*8+5, surfaces[i].w-1-y) = ( buffer[x+y*(surfaces[i].w/8)] >> 2 ) & 0x1; + CURRENT(x*8+6, surfaces[i].w-1-y) = ( buffer[x+y*(surfaces[i].w/8)] >> 1 ) & 0x1; + CURRENT(x*8+7, surfaces[i].w-1-y) = buffer[x+y*(surfaces[i].w/8)] & 0x1; + } + break; + case 2: + for (int x=0; x<(surfaces[i].w/4); ++x) { + CURRENT(x*4 , surfaces[i].w-1-y) = buffer[x+y*(surfaces[i].w/4)] >> 6; + CURRENT(x*4+1, surfaces[i].w-1-y) = ( buffer[x+y*(surfaces[i].w/4)] >> 4 ) & 0x3; + CURRENT(x*4+2, surfaces[i].w-1-y) = ( buffer[x+y*(surfaces[i].w/4)] >> 2 ) & 0x3; + CURRENT(x*4+3, surfaces[i].w-1-y) = buffer[x+y*(surfaces[i].w/4)] & 0x3; + } + break; + case 4: + for (int x=0; x<(surfaces[i].w/2); ++x) { + CURRENT(x*2, surfaces[i].w-1-y) = buffer[x+y*(surfaces[i].w/2)] >> 4; + CURRENT(x*2+1, surfaces[i].w-1-y) = buffer[x+y*(surfaces[i].w/2)] & 0xf; + } + break; + case 8: + for (int x=0; x<(surfaces[i].w); ++x) { + CURRENT(x, surfaces[i].w-1-y) = buffer[x+y*(surfaces[i].w)]; + } + break; + } + } + } + return i; +} + +void freesurf(uint8_t surface) { + if (surfaces[surface].p != NULL) free(surfaces[surface].p); + surfaces[surface].p = NULL; +} + +void setdest(uint8_t surface) { + dest_surface = &surfaces[surface]; +} + +void setsource(uint8_t surface) { + source_surface = &surfaces[surface]; +} + +void setmap(uint8_t surface) { + map_surface = &surfaces[surface]; } int main(int argc,char*argv[]){ - for (int i=0; i>3)+(base64font[bi+3]-48<<3)+(base64font[bi+4]-48<<9); bi += 5; } - FILE *f = fopen("sprites.bmp", "rb"); + + /*FILE *f = fopen("sprites.bmp", "rb"); if (f) { uint8_t buffer[SPRITES_SIZE_BYTES/2]; fseek(f, 118, SEEK_SET); @@ -128,17 +237,28 @@ int main(int argc,char*argv[]){ SPRITES(x*2+1, SPRITES_WIDTH-1-y) = buffer[x+y*(SPRITES_WIDTH/2)] & 0xf; } } - } + }*/ + + read_ini(); + setdest(newsurf(screen_width, screen_height)); + + debug_line_size = (screen_width/4); + debug_num_lines = (screen_height/6); + debug_total_size = debug_line_size*debug_num_lines; + if (debug_text != NULL) free(debug_text); + debug_text = (char*)malloc(debug_total_size); + for (int i=0; isize;++i) pixels[i] = palette[ds::screen_palette[screen_surface->p[i]]]; SDL_UnlockTexture(mini_bak); SDL_RenderCopy(mini_ren, mini_bak, NULL, NULL); SDL_RenderPresent(mini_ren); @@ -191,7 +311,7 @@ int main(int argc,char*argv[]){ } void cls(uint8_t color) { - SDL_memset(screen, color, SCREEN_SIZE_BYTES); + SDL_memset(dest_surface->p, color, dest_surface->size); } void color(uint8_t color) { @@ -226,7 +346,7 @@ void palt(uint8_t col, bool t) { void simple_pset(int x, int y, uint8_t color) { x -= ds::cam[0]; y -= ds::cam[1]; if (x < ds::clp[0] || x > ds::clp[2] || y < ds::clp[1] || y > ds::clp[3]) return; - SCREEN(x, y) = color; + DEST(x, y) = color; } void pset(int x, int y) { @@ -235,9 +355,9 @@ void pset(int x, int y) { int pbx = x % 4, pby = y % 4; int pb = pbx+pby*4; if (ds::fill_pattern & (1 << pb)) { - if (!ds::trans[ds::pen_color & 0xf]) SCREEN(x, y) = ds::draw_palette[ds::pen_color & 0xf]; + if (!ds::trans[ds::pen_color & 0xf]) DEST(x, y) = ds::draw_palette[ds::pen_color & 0xf]; } else { - if (!ds::fill_trans) SCREEN(x, y) = ds::draw_palette[ds::pen_color >> 4]; + if (!ds::fill_trans) DEST(x, y) = ds::draw_palette[ds::pen_color >> 4]; } } @@ -248,8 +368,8 @@ void pset(int x, int y, uint8_t color) { uint8_t pget(int x, int y) { x -= ds::cam[0]; y -= ds::cam[1]; - if (x < 0 || x > (SCREEN_WIDTH-1) || y < 0 || y > (SCREEN_HEIGHT-1)) return 0; - return SCREEN(x, y); + if (x < 0 || x > (dest_surface->w-1) || y < 0 || y > (dest_surface->h-1)) return 0; + return DEST(x, y); } // Bresenham Line Algorithm @@ -470,13 +590,13 @@ void ovalfill(int x0, int y0, int x1, int y1, uint8_t color) { } uint8_t sget(int x, int y) { - if (x < 0 || x > (SPRITES_WIDTH-1) || y < 0 || y > (SPRITES_HEIGHT-1)) return 0; - return SPRITES(x, y); + if (x < 0 || x > (source_surface->w-1) || y < 0 || y > (source_surface->h-1)) return 0; + return SOURCE(x, y); } void sset(int x, int y) { - if (x < 0 || x > (SPRITES_WIDTH-1) || y < 0 || y > (SPRITES_HEIGHT-1)) return; - SPRITES(x, y) = ds::draw_palette[ds::pen_color & 0xf]; + if (x < 0 || x > (source_surface->w-1) || y < 0 || y > (source_surface->h-1)) return; + SOURCE(x, y) = ds::draw_palette[ds::pen_color & 0xf]; } void sset(int x, int y, uint8_t color) { @@ -485,8 +605,8 @@ void sset(int x, int y, uint8_t color) { } void spr(uint8_t n, int x, int y, float w, float h, bool flip_x, bool flip_y) { - int tx = (n%(SPRITES_PER_LINE))<<3; - int ty = (n/(SPRITES_PER_LINE))<<3; + int tx = (n%(source_surface->w >> 3))<<3; + int ty = (n/(source_surface->w >> 3))<<3; int tw = w*8 - 1; int th = h*8 - 1; //int tx2 = tx1 + tw; @@ -597,12 +717,12 @@ void cvline(int x, int y0, int y1, uint8_t c0, uint8_t c1) { } uint8_t mget(uint8_t celx, uint8_t cely) { - if (celx < 0 || celx > (TILES_WIDTH-1) || cely < 0 || cely > (TILES_HEIGHT-1)) return 0; + if (celx < 0 || celx > (map_surface->w-1) || cely < 0 || cely > (map_surface->h-1)) return 0; return TILES(celx, cely); } void mset(uint8_t celx, uint8_t cely, uint8_t snum) { - if (celx < 0 || celx > (TILES_WIDTH-1) || cely < 0 || cely > (TILES_HEIGHT-1)) return; + if (celx < 0 || celx > (map_surface->w-1) || cely < 0 || cely > (map_surface->h-1)) return; TILES(celx, cely) = snum; } diff --git a/mini.h b/mini.h index fbb889c..2e95286 100644 --- a/mini.h +++ b/mini.h @@ -111,6 +111,14 @@ #define KEY_RGUI 231 void loop(); + +uint8_t newsurf(int w, int h); +uint8_t loadsurf(const char* filename); +void freesurf(uint8_t surface); +void setdest(uint8_t surface); +void setsource(uint8_t surface); +void setmap(uint8_t surface); + void cls(uint8_t color=0); void color(uint8_t color=6); void pal();