1340 lines
38 KiB
C++
1340 lines
38 KiB
C++
#include "mini.h"
|
|
#include "jfile.h"
|
|
#include <string.h>
|
|
#include "lua.h"
|
|
#include "gif.h"
|
|
#include "gifenc.h"
|
|
#include "jail_audio.h"
|
|
#include "jshader.h"
|
|
|
|
#define MAX_TEXTURES 100
|
|
|
|
#ifdef MACOS_BUNDLE
|
|
#include <libgen.h>
|
|
#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<gJbBBJbJP?0Zm";
|
|
uint16_t font[96];
|
|
|
|
char base64glyphs[193] = "/h/AqV/hhhh/GMYYMGz/t/eS33H477wsjjswY4IOPHEFFVVVAVAVAVIc+dJHMMM/h/qBgBgVqq+//eIUi/dJzhAAhzAAA/eM"
|
|
"AMShAAAQsjAAAwsjAAAeSzAAAcU3AAAEqRAAABVaiAAMezhAAAAAMAADH4wAASb2SAAMAttAQYcefACGOe+AAAVVAAAAbbAA";
|
|
|
|
//Uint8 keymapping[6] = { SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_Z, SDL_SCANCODE_X };
|
|
const bool *keys;
|
|
Uint8 key_just_pressed = 0;
|
|
|
|
int mouse_x, mouse_y, mouse_wheel;
|
|
Uint32 mouse_buttons;
|
|
uint8_t mouse_just_pressed = 0;
|
|
|
|
SDL_Gamepad *gamepad = NULL;
|
|
int8_t pad_just_pressed = SDL_GAMEPAD_BUTTON_INVALID;
|
|
|
|
#define MAX_SOUNDS 50
|
|
JA_Music_t *music = NULL;
|
|
JA_Sound_t *sounds[MAX_SOUNDS];
|
|
|
|
int16_t beats, num_beats = 0;
|
|
|
|
char* get_value_from_line(char* line) {
|
|
char* equal_character = strchr(line, '=');
|
|
if (equal_character == NULL) return NULL;
|
|
*equal_character = '\0';
|
|
return ++equal_character;
|
|
}
|
|
|
|
void read_ini() {
|
|
int size;
|
|
SDL_Log("Carregant 'game.ini'...");
|
|
FILE *f = file_getfilepointer("game.ini", size); // fopen("game.ini", "r");
|
|
char line[1024];
|
|
if (f == NULL) { SDL_Log("FAIL!\n"); return; }
|
|
SDL_Log("OK!\n");
|
|
while (fgets(line, sizeof(line), f)) {
|
|
char *value = get_value_from_line(line);
|
|
if (value != NULL) {
|
|
value[strlen(value)-1] = '\0';
|
|
if (strcmp(line, "title") == 0) { strcpy(window_title, value); SDL_Log("-title=%s\n", window_title); }
|
|
else if (strcmp(line, "config") == 0) { strcpy(config_folder, value); SDL_Log("-config=%s\n", config_folder); }
|
|
else if (strcmp(line, "width") == 0) { screen_width = atoi(value); SDL_Log("-screen width=%i\n", screen_width); }
|
|
else if (strcmp(line, "height") == 0) { screen_height = atoi(value); SDL_Log("-screen height=%i\n", screen_height); }
|
|
else if (strcmp(line, "zoom") == 0) { screen_zoom = atoi(value); SDL_Log("-screen zoom=%i\n", screen_zoom); }
|
|
else if (strcmp(line, "fullscreen") == 0) { screen_fullscreen = atoi(value); SDL_Log("-screen sullscreen=%i\n", screen_fullscreen); }
|
|
//else if (strcmp(line, "files") == 0) {
|
|
//lua_files = (char*)malloc(strlen(value));
|
|
// strcpy(lua_files, value);
|
|
//}
|
|
}
|
|
}
|
|
fclose(f);
|
|
SDL_Log("'game.ini' carregat!\n");
|
|
}
|
|
|
|
void pset_fast(int x, int y) {
|
|
if (ds::trans != ds::pen_color) DEST(x, y) = ds::draw_palette[ds::pen_color];
|
|
}
|
|
|
|
void pset_pattern(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) DEST(x, y) = ds::draw_palette[ds::pen_color];
|
|
} else {
|
|
if (!ds::fill_trans) DEST(x, y) = ds::draw_palette[ds::back_color];
|
|
}
|
|
}
|
|
|
|
void reinit() {
|
|
SDL_Log("REINIT\n");
|
|
do_pset = pset_fast;
|
|
ds::pen_color = 6;
|
|
ds::back_color = 0;
|
|
ds::origin[0] = ds::origin[1] = 0;
|
|
ds::clip[0] = ds::clip[1] = 0; ds::clip[2] = screen_width-1; ds::clip[3] = screen_height-1;
|
|
ds::clp[0] = ds::clp[1] = 0; ds::clp[2] = screen_width; ds::clp[3] = screen_height;
|
|
ds::trans=0;
|
|
ds::fill_pattern = 0b1111111111111111;
|
|
ds::fill_trans = false;
|
|
for (int i=1; i<MAX_TEXTURES; ++i) {
|
|
if (surfaces[i].p != NULL) free(surfaces[i].p);
|
|
surfaces[i].p = NULL;
|
|
if (surfaces[i].name != NULL) free(surfaces[i].name);
|
|
surfaces[i].name = NULL;
|
|
}
|
|
for (int i=0;i<256;++i) ds::draw_palette[i]=i;
|
|
if (file!=NULL) fclose(file);
|
|
file = NULL;
|
|
}
|
|
|
|
void initaudio() {
|
|
JA_Init(48000, SDL_AUDIO_S16, 1);
|
|
for (int i=0;i<MAX_SOUNDS;++i) sounds[i] = NULL;
|
|
}
|
|
|
|
void quitaudio() {
|
|
if (music != NULL) JA_DeleteMusic(music);
|
|
for (int i=0;i<MAX_SOUNDS;++i) if (sounds[i]!=NULL) JA_DeleteSound(sounds[i]);
|
|
JA_Quit();
|
|
}
|
|
|
|
int scrw() {
|
|
return screen_width;
|
|
}
|
|
|
|
int scrh() {
|
|
return screen_height;
|
|
}
|
|
|
|
uint8_t newsurf(int w, int h) {
|
|
int i = 0;
|
|
while (i<MAX_TEXTURES && surfaces[i].p != NULL) ++i;
|
|
//[TODO] Gestionar el cas en que no queden surfaces lliures
|
|
surfaces[i].name = nullptr;
|
|
surfaces[i].w = w;
|
|
surfaces[i].h = h;
|
|
surfaces[i].size = w*h;
|
|
surfaces[i].p = (uint8_t*)calloc(surfaces[i].size,1);
|
|
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Surface %i creada.\n", i);
|
|
return i;
|
|
}
|
|
|
|
uint8_t loadsurf(const char* filename) {
|
|
// Si el gif ja s'ha carregat en una textura, tornem eixa textura
|
|
for (int i=0; i<MAX_TEXTURES; ++i)
|
|
if (surfaces[i].name && strcmp(surfaces[i].name, filename)==0) {
|
|
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Carrega de '%s' abortada: Reusant: %i.\n", filename, i);
|
|
return i;
|
|
}
|
|
|
|
int i = 0;
|
|
while (i<MAX_TEXTURES && surfaces[i].p != NULL) ++i;
|
|
//[TODO] Gestionar el cas en que no queden surfaces lliures
|
|
|
|
int size;
|
|
uint8_t *buffer = (uint8_t*)file_getfilebuffer(filename, size);
|
|
surfaces[i].p = LoadGif(buffer, &surfaces[i].w, &surfaces[i].h);
|
|
surfaces[i].size = surfaces[i].w*surfaces[i].h;
|
|
surfaces[i].name = (char*)malloc(strlen(filename)+1);
|
|
strcpy(surfaces[i].name, filename);
|
|
free(buffer);
|
|
|
|
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Carregat '%s': Surface: %i.\n", filename, i);
|
|
return i;
|
|
}
|
|
|
|
void savesurf(uint8_t surface, const char* filename, uint8_t *pal, uint8_t colors)
|
|
{
|
|
uint8_t depth=0;
|
|
do { colors = colors >> 1; depth++; } while (colors!=0);
|
|
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<MAX_TEXTURES; ++i) if (map_surface == &surfaces[i]) return i;
|
|
return 0;
|
|
}
|
|
|
|
void shader_init(const char* vshader, const char* fshader)
|
|
{
|
|
int filesize;
|
|
char *vshaderfile = file_getfilebuffer(vshader, filesize, true);
|
|
|
|
char *fshaderfile = nullptr;
|
|
if (fshader) { fshaderfile = file_getfilebuffer(fshader, filesize, true); }
|
|
shader::init(mini_win, mini_shadertex, vshaderfile, fshaderfile);
|
|
}
|
|
|
|
void shader_enable() { shader::enable(); }
|
|
void shader_disable() { shader::disable(); }
|
|
|
|
void createDisplay() {
|
|
if (screen_zoom <= 0) screen_zoom = 1;
|
|
while (screen_width*screen_zoom > 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; i<num_joysticks; ++i) {
|
|
if (SDL_IsGamepad(joysticks[i])) {
|
|
gamepad = SDL_OpenGamepad(joysticks[i]);
|
|
if (SDL_GamepadConnected(gamepad)) {
|
|
SDL_SetGamepadEventsEnabled(true);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc,char*argv[]){
|
|
|
|
#ifdef DEBUG
|
|
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
|
#endif
|
|
|
|
if (argc>1)
|
|
{
|
|
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;
|
|
}
|
|
|
|
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) {
|
|
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;i<screen_surface->size;++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<MAX_TEXTURES;++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::origin[0]; y += ds::origin[1];
|
|
if (x < ds::clip[0] || x > 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<<i));
|
|
}
|
|
|
|
void palt(uint8_t col, bool t) {
|
|
ds::trans[col] = t;
|
|
}
|
|
*/
|
|
|
|
void pset(int x, int y) {
|
|
x += ds::origin[0]; y += ds::origin[1];
|
|
if (x < ds::clip[0] || x > 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<dy+dh;++y) {
|
|
csx = ssx;
|
|
for(int x=dx;x<dx+dw;++x) {
|
|
uint8_t color = invert ? sget(SDL_max(sy,csy),SDL_max(sx, csx)) : sget(SDL_max(sx, csx), SDL_max(sy,csy));
|
|
pset(x, y, color);
|
|
csx += sdx;
|
|
}
|
|
csy += sdy;
|
|
}
|
|
}
|
|
|
|
void blit_r(int sx, int sy, int sw, int sh, int x, int y, float a)
|
|
{
|
|
const int x0 = sw>>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<sw-1 && yy>=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;
|
|
uint8_t celw = map_surface->w;// >> 3;
|
|
uint8_t 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; y<celh; ++y) {
|
|
for (int x=0; x<celw; ++x) {
|
|
spr(mget(celx+x, cely+y), 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;
|
|
}
|
|
|
|
int mousey() {
|
|
return mouse_y;
|
|
}
|
|
|
|
int mwheel() {
|
|
return mouse_wheel;
|
|
}
|
|
|
|
bool mbtn(uint8_t i) {
|
|
return mouse_buttons & SDL_BUTTON_MASK(i);
|
|
}
|
|
|
|
bool mbtnp(uint8_t i) {
|
|
return mouse_just_pressed == i;
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
int loadsound(const char *filename) {
|
|
int size;
|
|
char *buffer = file_getfilebuffer(filename, size);
|
|
int i=0;
|
|
while (i<MAX_SOUNDS && sounds[i]!=NULL) i++;
|
|
if (i==MAX_SOUNDS) { i=0; JA_DeleteSound(sounds[i]); }
|
|
sounds[i]=JA_LoadSound((Uint8*)buffer, size);
|
|
return i;
|
|
}
|
|
|
|
void freesound(int soundfile) {
|
|
JA_DeleteSound(sounds[soundfile]);
|
|
sounds[soundfile] = NULL;
|
|
}
|
|
|
|
int playsound(int soundfile, const int volume) {
|
|
const int channel = JA_PlaySound(sounds[soundfile], 0);
|
|
JA_SetSoundVolume(128);
|
|
//Mix_Volume(channel, volume!=-1?volume:MIX_MAX_VOLUME);
|
|
return channel;
|
|
}
|
|
|
|
void stopsound(int soundchannel) {
|
|
JA_StopChannel(soundchannel);
|
|
//Mix_HaltChannel(soundchannel);
|
|
}
|
|
|
|
int getzoom() {
|
|
return screen_zoom;
|
|
}
|
|
|
|
void setzoom(const int value) {
|
|
screen_zoom = value;
|
|
destroyDisplay();
|
|
createDisplay();
|
|
char strzoom[3];
|
|
file_setconfigvalue("zoom", SDL_itoa(screen_zoom, strzoom, 10));
|
|
}
|
|
|
|
void setres(const int w, const int h) {
|
|
screen_width = w;
|
|
screen_height = h;
|
|
destroyDisplay();
|
|
createDisplay();
|
|
}
|
|
|
|
bool getfullscreen() {
|
|
return screen_fullscreen;
|
|
}
|
|
|
|
void setfullscreen(const bool value) {
|
|
screen_fullscreen=value;
|
|
destroyDisplay();
|
|
createDisplay();
|
|
file_setconfigvalue("fullscreen", screen_fullscreen?"true":"false");
|
|
}
|
|
|
|
bool getcursor() {
|
|
return screen_cursor;
|
|
}
|
|
|
|
void setcursor(const bool value) {
|
|
screen_cursor=value;
|
|
if (screen_cursor) SDL_ShowCursor(); else SDL_HideCursor();
|
|
}
|
|
|
|
const char* getconfig(const char* key) {
|
|
return file_getconfigvalue(key);
|
|
}
|
|
|
|
void setconfig(const char* key, const char* value) {
|
|
file_setconfigvalue(key, value);
|
|
}
|
|
|
|
const char *configfolder() {
|
|
return file_getconfigfolder();
|
|
}
|
|
|
|
void setupdatemode(const int value, const int t) {
|
|
update_mode = value;
|
|
timeout = t;
|
|
}
|
|
|
|
int getupdatemode() {
|
|
return update_mode;
|
|
}
|
|
|
|
void exit() {
|
|
should_exit = true;
|
|
should_quit = true;
|
|
}
|