#include "mini.h" #include "jfile.h" #include #include "lua.h" #include "gif.c" #include "SDL2/SDL_mixer.h" #ifdef MACOS_BUNDLE #include #endif //DECLSPEC int SDLCALL (*event_handler_ptr)(SDL_Event*) = &SDL_PollEvent; #pragma pack(1) struct surface_t { uint8_t *p; uint16_t w, h; uint32_t size; }; char window_title[256]; char config_folder[256]; uint16_t screen_width = 160; uint16_t screen_height = 120; uint8_t screen_zoom = 4; bool screen_fullscreen = false; bool screen_cursor = true; int windowpos_x = SDL_WINDOWPOS_UNDEFINED; int windowpos_y = SDL_WINDOWPOS_UNDEFINED; 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 turbo_mode = true; bool should_exit = false; bool should_quit = false; SDL_Window *mini_win; SDL_Renderer *mini_ren; SDL_Texture *mini_bak; Uint32 windowID; 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=1) { for (int i=0; i> 3 ) + ( ( base64font[bi+3] - 48 ) << 3 ) + ( ( base64font[bi+4] - 48 ) << 9 ); bi += 5; } #ifdef MACOS_BUNDLE char res_file[255] = ""; strcpy(res_file, dirname(argv[0])); strcat(res_file, "/../Resources/data.jrf"); file_setresourcefilename(res_file); #endif read_ini(); file_setconfigfolder(config_folder); const char *zoom = file_getconfigvalue("zoom"); if (zoom) screen_zoom=atoi(zoom); const char *fullscreen = file_getconfigvalue("fullscreen"); if (fullscreen) screen_fullscreen=strcmp(fullscreen, "true")==0?true:false; const char *cursor = file_getconfigvalue("cursor"); if (cursor) screen_cursor=strcmp(cursor, "true")?true:false; setdest(newsurf(screen_width, screen_height)); SDL_Init(SDL_INIT_EVERYTHING); createDisplay(); initGamePad(); Mix_Init(MIX_INIT_OGG); SDL_Event mini_eve; reinit(); initaudio(); #ifdef DEBUG debug("MINI v%s\n",MINI_VERSION); #endif lua_init(); lua_call_init(); Uint32 dt=SDL_GetTicks(); key_just_pressed = 0; pad_just_pressed = SDL_CONTROLLER_BUTTON_INVALID; mouse_just_pressed = 0; while(!should_exit) { mouse_wheel = 0; if (!turbo_mode) SDL_WaitEvent(NULL); 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_F2) { screen_zoom+=2; if (screen_zoom>=10) screen_zoom=2; destroyDisplay(); createDisplay(); char strzoom[3]; file_setconfigvalue("zoom", SDL_itoa(screen_zoom, strzoom, 10)); } else if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F3) { screen_fullscreen = !screen_fullscreen; destroyDisplay(); createDisplay(); file_setconfigvalue("fullscreen", screen_fullscreen?"true":"false"); } */ #ifdef DEBUG if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F1) { if (lua_is_playing()) { lua_quit(); quitaudio(); reinit(); } else { should_exit=true; } } else if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F5) { should_exit=true; } else { key_just_pressed = mini_eve.key.keysym.scancode; } #else key_just_pressed = mini_eve.key.keysym.scancode; #endif } if (mini_eve.type == SDL_MOUSEBUTTONUP) { mouse_just_pressed = mini_eve.button.button; } if (mini_eve.type == SDL_MOUSEWHEEL) { mouse_wheel = mini_eve.wheel.y; } if (mini_eve.type == SDL_CONTROLLERBUTTONDOWN) { pad_just_pressed = mini_eve.cbutton.button; } if ( (mini_eve.type == SDL_WINDOWEVENT) && (mini_eve.window.windowID == windowID) && (mini_eve.window.event == SDL_WINDOWEVENT_MOVED) ) { windowpos_x = mini_eve.window.data1-4; windowpos_y = mini_eve.window.data2-36; //SDL_GetWindowPosition(mini_win, &windowpos_x, &windowpos_y); } } keys = SDL_GetKeyboardState(NULL); mouse_buttons = SDL_GetMouseState(&mouse_x, &mouse_y); mouse_x /= screen_zoom; mouse_y /= screen_zoom; if (SDL_GetTicks()-dt>13) { dt = SDL_GetTicks(); if (lua_is_playing()) { lua_call_update(); } else { loop(); } if (beats==0)beats=num_beats; if (beats>0)beats--; key_just_pressed = 0; mouse_just_pressed = 0; pad_just_pressed = SDL_CONTROLLER_BUTTON_INVALID; } SDL_LockTexture(mini_bak, NULL, (void**)&pixels, &pitch); for (uint32_t 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(); Mix_Quit(); for (int i=0;i<10;++i) freesurf(i); dest_surface = source_surface = map_surface = NULL; destroyDisplay(); SDL_Quit(); } return 0; } void simple_pset(int x, int y, uint8_t color) { x -= ds::cam[0]; y -= ds::cam[1]; if (x < ds::clip[0] || x >= ds::clip[2] || y < ds::clip[1] || y >= ds::clip[3]) return; DEST(x, y) = color; } void cls(uint8_t color) { for (int y=ds::clip[1]+ds::cam[1]; yp, 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::clip[2] || y < ds::clip[1] || y >= ds::clip[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; if (x < ds::clip[0] || x >= ds::clip[2] || y < ds::clip[1] || y >= ds::clip[3]) 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 (size_t 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 clip() { 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; } void camera(int x, int y) { ds::cam[0] = x; ds::cam[1] = y; } void view(int x, int y, int w, int h) { ds::cam[0] = -x; ds::cam[1] = -y; ds::clip[0] = x; ds::clip[1] = y; ds::clip[2] = w+x; ds::clip[3] = h+y; ds::clp[0] = x; ds::clp[1] = y; ds::clp[2] = w-1; ds::clp[3] = h-1; } void view() { 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; } void origin(int x, int y) { ds::cam[0] = -(ds::clip[0]+x); ds::cam[1] = -(ds::clip[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 (map_surface==NULL) return; //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