#include "mini.h" #include "jfile.h" #include #include "lua.h" #include "gif.c" #include "chirp.h" #pragma pack(1) struct surface_t { uint8_t *p; uint16_t w, h; uint32_t size; }; char window_title[256]; uint16_t screen_width = 160; uint16_t screen_height = 120; uint8_t screen_zoom = 4; uint8_t show_cursor = SDL_ENABLE; 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; FILE *file = NULL; //uint8_t file_mode = 0; bool file_ignore_comma=true; char lua_files[1024]; #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}; uint8_t trans = 0; uint16_t fill_pattern = 0b1111111111111111; bool fill_trans = false; } bool should_exit = false; bool should_quit = false; SDL_Window *mini_win; SDL_Renderer *mini_ren; SDL_Texture *mini_bak; Uint32 *pixels; int pitch; uint32_t palette[256] = { 0x001a1c2c, 0x005d275d, 0x00b13e53, 0x00ef7d57, 0x00ffcd75, 0x00a7f070, 0x0038b764, 0x00257179, 0x0029366f, 0x003b5dc9, 0x0041a6f6, 0x0073eff7, 0x00f4f4f4, 0x0094b0c2, 0x00566c86, 0x00333c57 }; const char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char base64font[241] = "00@B@]0X__OnZDYK[G10:9BTDEG5j20@1h000RB:_]OBjW?odl]Wlil9_oTT__omT@@02:DA477ADid@Z=nm]_[g9a[]oIi?;a9m]_mBjGB[M]99o_][]e]M" "_?A]c_[eiLGBZ]e]mZ]o]Z]mlW:O9IABdTdZ000hR00__H[7?iH]3Oih;1?mXm5GjhB3M]897o]H]5^Mhm1ZchM5>LhB2]eXm2]oXZ5mlh>3)+((base64font[bi+3]-48)<<3)+((base64font[bi+4]-48)<<9); bi += 5; } read_ini(); setdest(newsurf(screen_width, screen_height)); SDL_Init(SDL_INIT_EVERYTHING); mini_win = SDL_CreateWindow(window_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width*screen_zoom, screen_height*screen_zoom, SDL_WINDOW_SHOWN); mini_ren = SDL_CreateRenderer(mini_win, -1, SDL_RENDERER_PRESENTVSYNC); //SDL_CreateWindowAndRenderer(512,512,0,&mini_win,&mini_ren); SDL_RenderSetLogicalSize(mini_ren, screen_width, screen_height); SDL_ShowCursor(show_cursor); mini_bak = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height); SDL_Event mini_eve; reinit(); initaudio(); debug("MINI v%s\n",MINI_VERSION); lua_init(lua_files); lua_call_init(); while(!should_exit) { key_just_pressed = 0; mouse_wheel = 0; while(SDL_PollEvent(&mini_eve)) { if (mini_eve.type == SDL_QUIT) { should_exit=true; should_quit=true; break; } if (mini_eve.type == SDL_KEYDOWN) { if (mini_eve.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { chirp_stop(); if (lua_is_playing()) { lua_quit(); quitaudio(); reinit(); } else { should_exit=true; //initaudio(); //lua_init(lua_files); //lua_call_init(); } } else if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F5) { chirp_stop(); should_exit=true; //lua_quit(); //reinit(); //initaudio(); //lua_init(lua_files); //lua_call_init(); } else { key_just_pressed = mini_eve.key.keysym.scancode; } } if (mini_eve.type == SDL_MOUSEWHEEL) { mouse_wheel = mini_eve.wheel.y; } } keys = SDL_GetKeyboardState(NULL); mouse_buttons = SDL_GetMouseState(&mouse_x, &mouse_y); mouse_x /= screen_zoom; mouse_y /= screen_zoom; if (lua_is_playing()) { lua_call_update(); } else { loop(); } SDL_LockTexture(mini_bak, NULL, (void**)&pixels, &pitch); for (int i=0;isize;++i) pixels[i] = palette[screen_surface->p[i]]; SDL_UnlockTexture(mini_bak); SDL_RenderCopy(mini_ren, mini_bak, NULL, NULL); SDL_RenderPresent(mini_ren); } lua_quit(); quitaudio(); for (int i=0;i<10;++i) freesurf(i); SDL_DestroyTexture(mini_bak); SDL_DestroyRenderer(mini_ren); SDL_DestroyWindow(mini_win); SDL_Quit(); } return 0; } void cls(uint8_t color) { SDL_memset(dest_surface->p, color, dest_surface->size); } void color(uint8_t color) { ds::pen_color=color; } uint32_t *loadpal(const char* filename) { int size; uint8_t *buffer = (uint8_t*)file_getfilebuffer(filename, size); uint32_t *pal = LoadPalette(buffer); free(buffer); return pal; /* FILE *f = fopen(filename, "rb"); if (f) { fseek(f, 0, SEEK_END); long size = ftell(f); fseek(f, 0, SEEK_SET); uint8_t *buffer = (uint8_t*)malloc(size); fread(buffer, size, 1, f); fclose(f); uint32_t *pal = LoadPalette(buffer); free(buffer); return pal; //memcpy(palette, pal, 1024); //free(pal); } return NULL;*/ } void setpal(uint32_t *pal) { memcpy(palette, pal, 1024); } void setcolor(uint8_t index, uint32_t color) { palette[index] = color; } uint32_t getcolor(uint8_t index) { return palette[index]; } void settrans(uint8_t index) { ds::trans = index; } uint8_t gettrans() { return ds::trans; } /*void pal() { for (int i=0; i<16; ++i) { ds::draw_palette[i] = i; ds::screen_palette[i] = i; } palt(); } void pal(uint8_t c0, uint8_t c1, uint8_t p) { if (p==0) ds::draw_palette[c0] = c1; else if (p==1) ds::screen_palette[c0]=c1; } void palt() { ds::trans[0] = true; for (int i=1; i<16; ++i) ds::trans[i] = false; } void palt(uint16_t bits) { for (int i=0; i<16; ++i) ds::trans[i] = (bits & (1< ds::clp[2] || y < ds::clp[1] || y > ds::clp[3]) return; DEST(x, y) = color; } void pset(int x, int y) { 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; if (ds::trans != ds::pen_color) DEST(x, y) = ds::pen_color; } /*void pset(int x, int y) { 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; 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]) DEST(x, y) = ds::draw_palette[ds::pen_color & 0xf]; } else { if (!ds::fill_trans) DEST(x, y) = ds::draw_palette[ds::pen_color >> 4]; } }*/ void pset(int x, int y, uint8_t color) { ds::pen_color = color; pset(x, y); } uint8_t pget(int x, int y) { x -= ds::cam[0]; y -= ds::cam[1]; if (x < 0 || x > (dest_surface->w-1) || y < 0 || y > (dest_surface->h-1)) return 0; return DEST(x, y); } // Bresenham Line Algorithm void line(int x0, int y0, int x1, int y1) { int x, y; int dx, dy; int incx, incy; int balance; if (x1 >= x0) { dx = x1 - x0; incx = 1; } else { dx = x0 - x1; incx = -1; } if (y1 >= y0) { dy = y1 - y0; incy = 1; } else { dy = y0 - y1; incy = -1; } x = x0; y = y0; if (dx >= dy) { dy <<= 1; balance = dy - dx; dx <<= 1; while (x != x1) { pset(x, y); if (balance >= 0) { y += incy; balance -= dx; } balance += dy; x += incx; } pset(x, y); } else { dx <<= 1; balance = dx - dy; dy <<= 1; while (y != y1) { pset(x, y); if (balance >= 0) { x += incx; balance -= dy; } balance += dx; y += incy; } pset(x, y); } } void line(int x0, int y0, int x1, int y1, uint8_t color) { ds::pen_color = color; line(x0, y0, x1, y1); } void hline(int x0, int y, int x1) { if (x0>x1) { const int tmp=x0;x0=x1;x1=tmp; } for (int x=x0; x<=x1; ++x) pset(x, y); } void hline(int x0, int y, int x1, uint8_t color) { ds::pen_color = color; hline(x0, y, x1); } void vline(int x, int y0, int y1) { if (y0>y1) { const int tmp=y0;y0=y1;y1=tmp; } for (int y=y0; y<=y1; ++y) pset(x, y); } void vline(int x, int y0, int y1, uint8_t color) { ds::pen_color = color; vline(x, y0, y1); } void rect(int x0, int y0, int x1, int y1) { hline(x0, y0, x1); hline(x0, y1, x1); vline(x0, y0, y1); vline(x1, y0, y1); } void rect(int x0, int y0, int x1, int y1, uint8_t color) { ds::pen_color = color; rect(x0, y0, x1, y1); } void rectfill(int x0, int y0, int x1, int y1) { for (int y=y0; y<=y1; ++y) hline(x0, y, x1); } void rectfill(int x0, int y0, int x1, int y1, uint8_t color) { ds::pen_color = color; rectfill(x0, y0, x1, y1); } void fillp(uint16_t pat, bool transparent) { ds::fill_trans = transparent; ds::fill_pattern = pat; } void print_symbol(char sym, int x, int y) { switch(sym) { case 1: pset(x, y-3); pset(x+1, y-2); break; case 2: pset(x+1, y-2); pset(x+2, y-3); break; case 3: pset(x+1, y+5); break; case 4: pset(x, y-2); pset(x+1, y-2); pset(x+2, y-2); break; case 5: pset(x, y-2); pset(x+1, y-1); break; case 6: pset(x+1, y-1); pset(x+2, y-2); break; case 7: pset(x, y-1); pset(x+1, y-1); pset(x+2, y-1); break; } } void print_char(char chr, int x, int y) { int xi = 0, yi = 0; uint16_t val = 1; while(1) { if (font[chr-32] & val) pset(x+xi, y+yi); if (xi<2) xi++; else { if (yi==4) return; else { xi=0; yi++; } } val <<= 1; } } void print_char_hv(char chr, int x, int y) { int xi = 0, yi = 0; uint16_t val = 1; while(1) { if (font[chr-32] & val) pset(x+(2-xi), y+(4-yi)); if (xi<2) xi++; else { if (yi==4) return; else { xi=0; yi++; } } val <<= 1; } } const char t195_char[]={65,65,0,0,0,0,0,67,69,69,0,0,73,73,0,0,0,78,79,79,0,0,0,0,0,85,85,0,0,0,0,0,97,97,0,0,0,0,0,99,101,101,0,0,105,105,0,0,0,110,111,111,0,0,0,0,0,117,117,0,0,0,0,0}; const char t195_symbol[]={1,2,0,0,0,0,0,3,1,2,0,0,1,2,0,0,0,4,1,2,0,0,0,0,0,1,2,0,0,0,0,0,5,6,0,0,0,0,0,3,5,6,0,0,5,6,0,0,0,7,5,6,0,0,0,0,0,5,6,0,0,0,0,0}; void print(const char *str, int x, int y) { int pos=0; for (int i=0; i < SDL_strlen(str); ++i) { if ((unsigned char)str[i]==194) { i++; if ((unsigned char)str[i]==161) print_char_hv('!', x+pos*4, y); else if ((unsigned char)str[i]==191) print_char_hv('?', x+pos*4, y); } else if ((unsigned char)str[i]==195) { i++; print_char(t195_char[(unsigned char)str[i]-128], x+pos*4, y); print_symbol(t195_symbol[(unsigned char)str[i]-128], x+pos*4, y); } else { print_char(str[i], x+pos*4, y); } pos++; } } void print(const char *str, int x, int y, uint8_t color) { ds::pen_color=color; print(str, x, y); } void clip(int x, int y, int w, int h) { ds::clip[0] = x; ds::clip[1] = y; ds::clip[2] = w; ds::clip[3] = h; ds::clp[0] = x; ds::clp[1] = y; ds::clp[2] = w-x-1; ds::clp[3] = h-y-1; } void camera(int x, int y) { ds::cam[0] = x; ds::cam[1] = y; } void _drawcirc(int xc, int yc, int x, int y) { pset(xc+x, yc+y); pset(xc-x, yc+y); pset(xc+x, yc-y); pset(xc-x, yc-y); pset(xc+y, yc+x); pset(xc-y, yc+x); pset(xc+y, yc-x); pset(xc-y, yc-x); } void _fillcirc(int xc, int yc, int x, int y) { hline(xc-x, yc+y, xc+x); hline(xc-x, yc-y, xc+x); hline(xc-y, yc+x, xc+y); hline(xc-y, yc-x, xc+y); } void _anycirc(int x, int y, uint8_t r, void (*fun_ptr)(int, int, int, int)) { int xi=0, yi=r; int d=3-2*r; (*fun_ptr)(x, y, xi, yi); while (yi>=xi++) { d += d>0 ? 4*(xi-yi--)+10 : 4*xi+6; (*fun_ptr)(x, y, xi, yi); } } void circ(int x, int y, uint8_t r) { _anycirc(x, y, r, &_drawcirc); } void circ(int x, int y, uint8_t r, uint8_t color) { ds::pen_color=color; circ(x, y, r); } void circfill(int x, int y, uint8_t r) { _anycirc(x, y, r, &_fillcirc); } void circfill(int x, int y, uint8_t r, uint8_t color) { ds::pen_color=color; circfill(x, y, r); } void _drawoval(int xc, int yc, int x, int y, float xf, float yf) { pset((xc+x)*xf, (yc+y)*yf); pset((xc-x)*xf, (yc+y)*yf); pset((xc+x)*xf, (yc-y)*yf); pset((xc-x)*xf, (yc-y)*yf); pset((xc+y)*xf, (yc+x)*yf); pset((xc-y)*xf, (yc+x)*yf); pset((xc+y)*xf, (yc-x)*yf); pset((xc-y)*xf, (yc-x)*yf); } void _filloval(int xc, int yc, int x, int y, float xf, float yf) { hline((xc-x)*xf, (yc+y)*yf, (xc+x)*xf); hline((xc-x)*xf, (yc-y)*yf, (xc+x)*xf); hline((xc-y)*xf, (yc+x)*yf, (xc+y)*xf); hline((xc-y)*xf, (yc-x)*yf, (xc+y)*xf); } void _anyoval(int x0, int y0, int x1, int y1, void (*fun_ptr)(int, int, int, int, float, float)) { int rx = (x1-x0)/2; int ry = (y1-y0)/2; int r = rx; int x = x0 + rx; int y = y0 + ry; float xf = 1.0f, yf = 1.0f; if (rx>=ry) {r=rx;yf=float(ry)/float(rx);} else {r=ry;xf=float(rx)/float(ry);} int xi=0, yi=r; int d=3-2*r; (*fun_ptr)(x, y, xi, yi, xf, yf); while (yi>=xi++) { d += d>0 ? 4*(xi-yi--)+10 : 4*xi+6; (*fun_ptr)(x, y, xi, yi, xf, yf); } } void oval(int x0, int y0, int x1, int y1) { _anyoval(x0, y0, x1, y1, &_drawoval); } void oval(int x0, int y0, int x1, int y1, uint8_t color) { ds::pen_color=color; oval(x0, y0, x1, y1); } void ovalfill(int x0, int y0, int x1, int y1) { _anyoval(x0, y0, x1, y1, &_filloval); } void ovalfill(int x0, int y0, int x1, int y1, uint8_t color) { ds::pen_color=color; ovalfill(x0, y0, x1, y1); } uint8_t sget(int x, int 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 > (source_surface->w-1) || y < 0 || y > (source_surface->h-1)) return; SOURCE(x, y) = ds::pen_color; } void sset(int x, int y, uint8_t color) { ds::pen_color=color; sset(x, y); } void spr(uint8_t n, int x, int y, float w, float h, bool flip_x, bool flip_y) { 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; //int ty2 = ty1 + th; int txd = 1; int tyd = 1; if (flip_x) {tx+=tw;txd=-1;} if (flip_y) {ty+=th;tyd=-1;} for (int yi=0; yi<=th; ++yi) { int ttx = tx; for (int xi=0; xi<=tw; ++xi) { pset(x+xi, y+yi, sget(ttx, ty)); ttx += txd; } ty += tyd; } } void sspr(int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, bool flip_x, bool flip_y) { if (dw==0)dw=sw; if (dh==0)dh=sh; float sdx = float(sw)/float(dw); float sdy = float(sh)/float(dh); float ssx = sx; float ssy = sy; if (flip_x) { sdx = -sdx; ssx += sw+sdx; } if (flip_y) { sdy = -sdy; ssy += sh+sdy; } float csx = ssx; float csy = ssy; for(int y=dy;y= x0) { dx = x1 - x0; incx = 1; } else { dx = x0 - x1; incx = -1; } if (y1 >= y0) { dy = y1 - y0; incy = 1; } else { dy = y0 - y1; incy = -1; } x = x0; y = y0; if (dx >= dy) { dy <<= 1; balance = dy - dx; dx <<= 1; while (x != x1) { pset(x, y, sget(mx*8, my*8)); if (balance >= 0) { y += incy; balance -= dx; } balance += dy; x += incx; mx += mdx; my += mdy; } pset(x, y, sget(mx*8, my*8)); } else { dx <<= 1; balance = dx - dy; dy <<= 1; while (y != y1) { pset(x, y, sget(mx*8, my*8)); if (balance >= 0) { x += incx; balance -= dy; } balance += dx; y += incy; mx += mdx; my += mdy; } pset(x, y, sget(mx*8, my*8)); } } void thline(int x0, int y, int x1, float mx, float my, float mdx, float mdy) { if (x0>x1) { const int tmp=x0;x0=x1;x1=tmp; } for (int x=x0; x<=x1; ++x) { pset(x, y, sget(mx*8, my*8)); mx += mdx; my += mdy; } } void tvline(int x, int y0, int y1, float mx, float my, float mdx, float mdy) { if (y0>y1) { const int tmp=y0;y0=y1;y1=tmp; } for (int y=y0; y<=y1; ++y) { pset(x, y, sget(mx*8, my*8)); mx += mdx; my += mdy; } } void cline(int x0, int y0, int x1, int y1, uint8_t c0, uint8_t c1) { } void chline(int x0, int y, int x1, uint8_t c0, uint8_t c1) { } void cvline(int x, int y0, int y1, uint8_t c0, uint8_t c1) { } uint8_t mget(int celx, int cely) { if (celx < 0 || celx > (map_surface->w-1) || cely < 0 || cely > (map_surface->h-1)) return 0; return TILES(celx, cely); } void mset(int celx, int cely, uint8_t snum) { if (celx < 0 || celx > (map_surface->w-1) || cely < 0 || cely > (map_surface->h-1)) return; TILES(celx, cely) = snum; } void map(int celx, int cely, int sx, int sy, uint8_t celw, uint8_t celh, uint8_t layer) { //if (celw <= 0 || celh <= 0 || celw >= TILES_WIDTH || celh >= TILES_HEIGHT) return; sx -= ds::cam[0]; sy -= ds::cam[1]; if (sx+celw*8 < ds::clp[0] || sx > ds::clp[2] || sy+celh*8 < ds::clp[1] || sy > ds::clp[3]) return; if (sx<0) { int diff = -sx/8; celx += diff; celw -= diff; sx += diff*8; } if (sy<0) { int diff = -sy/8; cely += diff; celh -= diff; sy += diff*8; } sx += ds::cam[0]; sy += ds::cam[1]; for (int y=0; y= 0 ? 1 : -1; } #ifdef __WINDOWS__ float ceil(float x) { return SDL_ceilf(x); } float sin(float x) { return SDL_sinf(x); } float cos(float x) { return SDL_cosf(x); } float atan2(float dx, float dy) { return SDL_atan2f(dx, dy); } float sqrt(float x) { return SDL_sqrtf(x); } #endif float max(float x, float y) { return SDL_max(x, y); } float mid(float x, float y, float z) { return max(x, min(y, z)); } float min(float x, float y) { return SDL_min(x, y); } int utfstrlen(const char *str) { const int size_in_bytes = SDL_strlen(str); int size_in_utfchars = 0; for (int i=0;i