#include "mini.h" #include "jfile.h" #include #include "lua.h" #include "gif.h" #include "gifenc.h" #include "jail_audio.h" #include "jshader.h" #define MAX_TEXTURES 100 #ifdef MACOS_BUNDLE #include #endif //DECLSPEC int SDLCALL (*event_handler_ptr)(SDL_Event*) = &SDL_PollEvent; #pragma pack(1) struct surface_t { char *name {nullptr}; uint8_t *p {nullptr}; uint16_t w, h; uint32_t size; }; int fps=0; int fps_counter=0; uint32_t fps_timer=0; 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 desktop_width = 0; int desktop_height = 0; surface_t surfaces[MAX_TEXTURES]; 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 main_lua_file[200] = "main.lua"; bool override_ini = false; //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] void (*do_pset)(int,int); namespace ds { uint8_t pen_color = 6; uint8_t back_color = 0; int origin[2] = {0, 0}; int clip[4] = {0, 0, screen_width-1, screen_height-1}; // clip (x1,y1,x2,y2) calculat intersectat amb el tamany de la surface 'dest' int clp[4] = {0, 0, screen_width, screen_height}; // clip (x1,y1,w,h) que ha especificat l'usuari uint8_t trans = 0; uint16_t fill_pattern = 0b1111111111111111; bool fill_trans = false; uint8_t draw_palette[256]; } int update_mode = UPDATE_ALWAYS; int timeout = 0; bool should_exit = false; bool should_quit = false; SDL_Window *mini_win; SDL_Renderer *mini_ren; SDL_Texture *mini_bak; SDL_Texture *mini_shadertex; 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; depth++; } while (colors!=0); printf("pal depth: %i\n", depth); gif::gif_t *file = gif::create(filename, surfaces[surface].w, surfaces[surface].h, pal, (pal?depth:8), -1, -1); memcpy(file->frame, surfaces[surface].p, surfaces[surface].w*surfaces[surface].h); gif::addFrame(file, 0); gif::close(file);*/ } void freesurf(uint8_t surface) { if (surfaces[surface].name != NULL) free(surfaces[surface].name); surfaces[surface].name = NULL; if (surfaces[surface].p != NULL) { free(surfaces[surface].p); SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Surface %i alliberada.\n", surface); } surfaces[surface].p = NULL; } int surfw(uint8_t surface) { return surfaces[surface].w; } int surfh(uint8_t surface) { return surfaces[surface].h; } void recalculate_clip() { ds::clip[0] = ds::clp[0]; ds::clip[1] = ds::clp[1]; ds::clip[2] = ds::clp[2]+ds::clp[0]-1; ds::clip[3] = ds::clp[3]+ds::clp[1]-1; if (ds::clip[0]<0) ds::clip[0]=0; if (ds::clip[1]<0) ds::clip[1]=0; if (ds::clip[2]>=dest_surface->w) ds::clip[2]=dest_surface->w-1; if (ds::clip[3]>=dest_surface->h) ds::clip[3]=dest_surface->h-1; } void setdest(uint8_t surface) { dest_surface = &surfaces[surface]; recalculate_clip(); } void setsource(uint8_t surface) { source_surface = &surfaces[surface]; } void setmap(uint8_t surface) { map_surface = &surfaces[surface]; } uint8_t getmap() { for (int i=0; i desktop_width || screen_height*screen_zoom > desktop_height) screen_zoom--; mini_win = SDL_CreateWindow(window_title, screen_width*screen_zoom, screen_height*screen_zoom, SDL_WINDOW_OPENGL|(screen_fullscreen?SDL_WINDOW_FULLSCREEN:0)); windowID = SDL_GetWindowID(mini_win); SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); mini_ren = SDL_CreateRenderer(mini_win, NULL); //SDL_CreateWindowAndRenderer(512,512,0,&mini_win,&mini_ren); //SDL_SetRenderLogicalPresentation(mini_ren, screen_width, screen_height); if (screen_cursor) SDL_ShowCursor(); else SDL_HideCursor(); mini_bak = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height); SDL_SetTextureScaleMode(mini_bak, SDL_SCALEMODE_NEAREST); SDL_PropertiesID props = SDL_GetTextureProperties(mini_bak); int real_pixelformat = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_FORMAT_NUMBER, -1); if (real_pixelformat != SDL_PIXELFORMAT_ARGB8888) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Pixelformat incorrecte: %i\n", real_pixelformat); exit(1); } mini_shadertex = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, screen_width*screen_zoom, screen_height*screen_zoom); SDL_SetTextureScaleMode(mini_shadertex, SDL_SCALEMODE_NEAREST); //int filesize; //char *shaderfile = file_getfilebuffer("lynx.glsl", filesize); shader::init(mini_win, mini_shadertex, nullptr); //SDL_GetWindowPosition(mini_win, &windowpos_x, &windowpos_y); } void destroyDisplay() { SDL_DestroyTexture(mini_bak); SDL_DestroyRenderer(mini_ren); SDL_DestroyWindow(mini_win); } void initGamePad() { int num_joysticks; SDL_JoystickID *joysticks = SDL_GetJoysticks(&num_joysticks); if (joysticks) { for (int i=0; i1) { if (strstr(argv[1], ".lua")!=nullptr) { file_setresourcefolder("./"); file_setsource(SOURCE_FOLDER); strcpy(main_lua_file, argv[1]); strcpy(window_title, argv[1]); override_ini = true; } else { char path[256] = "./"; strcat(path, argv[1]); file_setresourcefolder(path); } } while (!should_quit) { should_exit=false; // initfont() int bi = 0; for (int ci=0; ci<96; ci+=2) { font[ci] = base64font[bi] - 48 + ( ( base64font[bi+1] - 48 ) << 6) + ( ( ( base64font[bi+2] - 48 ) & 7 ) << 12 ); font[ci+1] = ( ( base64font[bi+2] - 48 ) >> 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 if (!override_ini) { 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; const char *music_enabled = file_getconfigvalue("music"); if (music_enabled) JA_EnableMusic(strcmp(music_enabled, "true")==0?true:false); const char *sound_enabled = file_getconfigvalue("sound"); if (sound_enabled) JA_EnableSound(strcmp(sound_enabled, "true")==0?true:false); } setdest(newsurf(screen_width, screen_height)); SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD); const SDL_DisplayMode *dm = SDL_GetDesktopDisplayMode(SDL_GetPrimaryDisplay()); if (!dm) { SDL_Log("SDL_GetDesktopDisplayMode failed: %s", SDL_GetError()); return 1; } desktop_width = dm->w; desktop_height = dm->h; 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(main_lua_file); lua_call_init(); Uint32 dt=SDL_GetTicks(); key_just_pressed = 0; pad_just_pressed = SDL_GAMEPAD_BUTTON_INVALID; mouse_just_pressed = 0; while(!should_exit) { mouse_wheel = 0; if (update_mode==UPDATE_WAIT) SDL_WaitEvent(NULL); else if (update_mode==UPDATE_TIMEOUT) SDL_WaitEventTimeout(NULL, timeout); while(SDL_PollEvent(&mini_eve)) { if (mini_eve.type == SDL_EVENT_QUIT) { should_exit=true; should_quit=true; break; } if (mini_eve.type == SDL_EVENT_KEY_DOWN) { /* 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.scancode == SDL_SCANCODE_F12) { if (lua_is_playing()) { lua_quit(); quitaudio(); reinit(); } else { should_exit=true; } } else if (mini_eve.key.scancode == SDL_SCANCODE_F5) { should_exit=true; } else { key_just_pressed = mini_eve.key.scancode; } #else key_just_pressed = mini_eve.key.scancode; #endif } if (mini_eve.type == SDL_EVENT_MOUSE_BUTTON_UP) { if (mouse_discard) mouse_discard = false; else mouse_just_pressed = mini_eve.button.button; } if (mini_eve.type == SDL_EVENT_MOUSE_WHEEL) { mouse_wheel = mini_eve.wheel.y; } if (mini_eve.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) { pad_just_pressed = mini_eve.gbutton.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); float real_mouse_x, real_mouse_y; mouse_buttons = SDL_GetMouseState(&real_mouse_x, &real_mouse_y); float mx, my; SDL_RenderCoordinatesFromWindow(mini_ren, real_mouse_x, real_mouse_y, &mx, &my); mouse_x = int(mx/screen_zoom); mouse_y = int(my/screen_zoom); //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_GAMEPAD_BUTTON_INVALID; } SDL_SetRenderTarget(mini_ren, mini_shadertex); SDL_SetRenderDrawColor(mini_ren, 0, 0, 0, 255); SDL_RenderClear(mini_ren); 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_RenderTexture(mini_ren, mini_bak, NULL, NULL); //NEW shader::render(); //SDL_RenderTexture(mini_ren, mini_bak, NULL, NULL); //SDL_RenderPresent(mini_ren); fps_counter++; if (SDL_GetTicks()>=(fps_timer+1000)) { fps = fps_counter; fps_counter=0; fps_timer = SDL_GetTicks(); } } lua_quit(); quitaudio(); //Mix_Quit(); for (int i=0;i ds::clip[2] || y < ds::clip[1] || y > ds::clip[3]) return; if (x < 0 || x >= dest_surface->w || y < 0 || y >= dest_surface->h) return; DEST(x, y) = color; } void cls(uint8_t color) { const uint8_t col = ds::draw_palette[color]; /*for (int y=ds::clip[1]; y<=ds::clip[3];++y) { for (int x=ds::clip[0]; x<=ds::clip[2];++x) { simple_pset(x,y,col); } }*/ SDL_memset(dest_surface->p, col, dest_surface->size); } void color(uint8_t color) { ds::pen_color=color; } void bcolor(uint8_t color) { ds::back_color=color; } uint32_t *loadpal(const char* filename, uint16_t *palsize) { int size; uint8_t *buffer = (uint8_t*)file_getfilebuffer(filename, size); uint32_t *pal = LoadPalette(buffer, palsize); 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) { for (int i=0; i<256; ++i) palette[i] = pal[i] | 0xff000000; //memcpy(palette, pal, 1024); } void setcolor(uint8_t index, uint32_t color) { palette[index] = color | 0xff000000; } uint32_t getcolor(uint8_t index) { return palette[index]; } void settrans(uint8_t index) { ds::trans = index; } uint8_t gettrans() { return ds::trans; } void subpal(uint8_t index, uint8_t color) { ds::draw_palette[index] = color; } void reset_subpal() { for (int i=0;i<256;++i) ds::draw_palette[i]=i; } /*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; do_pset(x,y); } 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::origin[0]; y += ds::origin[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 x, int y, int w, int h) { int x1 = w+x-1; int y1 = h+y-1; hline(x, y, x1); hline(x, y1, x1); vline(x, y, y1); vline(x1, y, y1); } void rect(int x, int y, int w, int h, uint8_t color) { ds::pen_color = color; rect(x, y, w, h); } void rectfill(int x, int y, int w, int h) { int x1 = w+x-1; int y1 = h+y-1; for (int i=y; i<=y1; ++i) hline(x, i, x1); } void rectfill(int x, int y, int w, int h, uint8_t color) { ds::pen_color = color; rectfill(x, y, w, h); } void fillp(uint16_t pat, bool transparent) { ds::fill_trans = true; //transparent; ds::fill_pattern = pat; do_pset=(pat==0xffff?pset_fast:pset_pattern); } 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::clp[0] = x; ds::clp[1] = y; ds::clp[2] = w; ds::clp[3] = h; recalculate_clip(); } void clip() { ds::clp[0] = ds::clp[1] = 0; ds::clp[2] = dest_surface->w; ds::clp[3] = dest_surface->h; recalculate_clip(); } void origin(int x, int y) { ds::origin[0] = x; ds::origin[1] = y; } int camx() { return ds::origin[0]; } int camy() { return ds::origin[1]; } 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 blit(int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, bool flip_x, bool flip_y, bool invert) { 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>1; const int y0 = sh>>1; const float sa = SDL_sinf(a); const float ca = SDL_cosf(a); for (int ix=0; ix<=sw; ++ix) { for (int iy=0; iy<=sh; ++iy) { const float dx = ix-x0; const float dy = iy-y0; const float xx = dx*ca - dy*sa + float(x0); const float yy = dx*sa + dy*ca + float(y0); if (xx>=0 && xx=0 && yy<=sh-1) pset(x+ix, y+iy, sget(sx+xx, sy+yy)); } } } void tline(int x0, int y0, int x1, int y1, float mx, float my, float mdx, float mdy) { 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, 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; } } uint8_t mget(int celx, int cely) { if (!map_surface) 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(int celx, int cely, uint8_t snum) { if (!map_surface) return; 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; int celw = map_surface->w;// >> 3; int celh = map_surface->h;// >> 3; int celx = 0; int cely = 0; //if (celw <= 0 || celh <= 0 || celw >= TILES_WIDTH || celh >= TILES_HEIGHT) return; int sx = ds::origin[0]; int sy = ds::origin[1]; if (sx+celw*8 < ds::clip[0] || sx > ds::clip[2] || sy+celh*8 < ds::clip[1] || sy > ds::clip[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::origin[0]; sy -= ds::origin[1]; for (int y=0; yds::clip[2]) || (fy>ds::clip[3]) ) continue; spr(tile, sx+x*8, sy+y*8); } } } bool btn(uint8_t i) { return keys[i]; } int wbtnp() { return key_just_pressed; } bool btnp(uint8_t i) { if (key_just_pressed == i) { key_just_pressed=0; return true; } else { return false; } } bool anykey() { const bool something_pressed = (key_just_pressed != 0) || (pad_just_pressed != -1); key_just_pressed=0; pad_just_pressed=-1; return something_pressed; } bool pad(int8_t i) { if (!gamepad) return false; return SDL_GetGamepadButton(gamepad, SDL_GamepadButton(i)) == 1; } bool padp(int8_t i) { if (pad_just_pressed == i) { pad_just_pressed=-1; return true; } else { return false; } } int wpad() { return pad_just_pressed; } int mousex() { return mouse_x-ds::origin[0]; } int mousey() { return mouse_y-ds::origin[1]; } int mwheel() { return mouse_wheel; } bool mbtn(uint8_t i) { if (mouse_discard) return false; return mouse_buttons & SDL_BUTTON_MASK(i); } bool mbtnp(uint8_t i) { return mouse_just_pressed == i; } void mdiscard() { mouse_discard = true; } float time() { return float(SDL_GetTicks())/1000.0f; } bool beat(int16_t i) { if (i<0) { return beats==0; } else { beats=num_beats=i; return false; } } int rnd(int x) { return rand()%x; } int getfps() { return fps; } void playmusic(const char *filename, const int loop) { int size; char *buffer = file_getfilebuffer(filename, size); if (music != NULL) JA_DeleteMusic(music); music = JA_LoadMusic((Uint8*)buffer, size); JA_PlayMusic(music, loop); } void pausemusic() { JA_PauseMusic(); } void resumemusic() { JA_ResumeMusic(); } void stopmusic(const int t) { JA_StopMusic(); } void musicpos(float value) { JA_SetMusicPosition(value); } float musicpos() { return JA_GetMusicPosition(); } void enablemusic(const bool value) { JA_EnableMusic(value); file_setconfigvalue("music", value?"true":"false"); } const bool ismusicenabled() { return JA_IsMusicEnabled(); } int loadsound(const char *filename) { int size; char *buffer = file_getfilebuffer(filename, size); int i=0; while (i