- [NEW] Afegit clipboard al backend

- [NEW] surfaces ara usa un vector dinàmic
- [FIX] Ajustades dereferenciacions per a arreglar la caiguda de rendiment
This commit is contained in:
2026-04-17 06:52:31 +02:00
parent 52d2fcf0d3
commit 9c4c94093c
10 changed files with 129 additions and 101 deletions

View File

@@ -83,6 +83,14 @@ namespace backend
return current_state; return current_state;
} }
char *clipboard() {
return SDL_GetClipboardText();
}
void clipboard(const char* value) {
SDL_SetClipboardText(value);
}
} }
#endif #endif

View File

@@ -65,7 +65,9 @@ namespace backend
uint32_t *pixels; uint32_t *pixels;
int pitch; int pitch;
SDL_LockTexture(tex_back, NULL, (void**)&pixels, &pitch); SDL_LockTexture(tex_back, NULL, (void**)&pixels, &pitch);
for (uint32_t i=0;i<mini::surf::state.screen_surface->size;++i) pixels[i] = mini::pal::palette[mini::surf::state.screen_surface->p[i]]; auto &s = mini::surf::state.surfaces[SCREEN];
uint8_t *p = s.p;
for (uint32_t i=0;i<s.size;++i) pixels[i] = mini::pal::palette[p[i]];
SDL_UnlockTexture(tex_back); SDL_UnlockTexture(tex_back);
SDL_RenderTexture(renderer, tex_back, NULL, NULL); //NEW SDL_RenderTexture(renderer, tex_back, NULL, NULL); //NEW

View File

@@ -21,6 +21,8 @@ namespace backend
const state_t& state(); const state_t& state();
void exit(); void exit();
uint64_t get_time_ms(); uint64_t get_time_ms();
char* clipboard();
void clipboard(const char* value);
namespace video namespace video
{ {

View File

@@ -5,9 +5,6 @@
#include <math.h> #include <math.h>
#define DEST(x, y) surf::state.dest_surface->p[x+y*surf::state.dest_surface->w]
#define SOURCE(x, y) surf::state.source_surface->p[x+y*surf::state.source_surface->w]
namespace mini namespace mini
{ {
namespace draw namespace draw
@@ -26,23 +23,27 @@ namespace mini
namespace pixel { namespace pixel {
static inline void pset_fast(int x, int y, uint8_t color) { static inline void pset_fast(int x, int y, uint8_t color) {
if (state.trans != color) DEST(x, y) = color; auto &s = surf::state.surfaces[surf::state.dest_surface];
uint8_t *p = s.p;
if (state.trans != color) p[x+y*s.w] = color;
} }
static inline void pset_bool(int x, int y, uint8_t color) { static inline void pset_bool(int x, int y, uint8_t color) {
if (state.trans != color) { if (state.trans != color) {
auto &s = surf::state.surfaces[surf::state.dest_surface];
uint8_t *p = s.p;
switch (state.mode) { switch (state.mode) {
case DRAWMODE_AND: case DRAWMODE_AND:
DEST(x, y) = DEST(x, y) & color; p[x+y*s.w] &= color;
break; break;
case DRAWMODE_OR: case DRAWMODE_OR:
DEST(x, y) = DEST(x, y) | color; p[x+y*s.w] |= color;
break; break;
case DRAWMODE_XOR: case DRAWMODE_XOR:
DEST(x, y) = DEST(x, y) ^ color; p[x+y*s.w] ^= color;
break; break;
case DRAWMODE_NOT: case DRAWMODE_NOT:
DEST(x, y) = ~DEST(x, y); p[x+y*s.w] = ~p[x+y*s.w];
break; break;
} }
} }
@@ -51,13 +52,19 @@ namespace mini
static inline void pset_pattern(int x, int y, uint8_t color) { static inline void pset_pattern(int x, int y, uint8_t color) {
int pbx = x % 4, pby = y % 4; int pbx = x % 4, pby = y % 4;
int pb = pbx+pby*4; int pb = pbx+pby*4;
if (state.fill_pattern & (1 << pb)) if (state.trans != color) DEST(x, y) = color; if (state.fill_pattern & (1 << pb))
if (state.trans != color) {
auto &s = surf::state.surfaces[surf::state.dest_surface];
uint8_t *p = s.p;
p[x+y*s.w] = color;
}
} }
// Per a les funcions que pinten tot del mateix color // Per a les funcions que pinten tot del mateix color
static inline void direct_pset(int x, int y, uint8_t color) { static inline void direct_pset(int x, int y, uint8_t color) {
auto &s = surf::state.surfaces[surf::state.dest_surface];
x += view::state.origin[0]; y += view::state.origin[1]; x += view::state.origin[0]; y += view::state.origin[1];
if (x < surf::state.dest_surface->clip[0] || x > surf::state.dest_surface->clip[2] || y < surf::state.dest_surface->clip[1] || y > surf::state.dest_surface->clip[3]) return; if (x < s.clip[0] || x > s.clip[2] || y < s.clip[1] || y > s.clip[3]) return;
switch (state.mode) { switch (state.mode) {
case DRAWMODE_NORMAL: pset_fast(x,y,color); break; case DRAWMODE_NORMAL: pset_fast(x,y,color); break;
case DRAWMODE_PATTERN: pset_pattern(x,y,color); break; case DRAWMODE_PATTERN: pset_pattern(x,y,color); break;
@@ -75,9 +82,10 @@ namespace mini
} }
uint8_t get(int x, int y) { uint8_t get(int x, int y) {
if (!surf::state.source_surface) return 0; if (surf::state.source_surface==-1) return 0;
if (x < 0 || x > (surf::state.source_surface->w-1) || y < 0 || y > (surf::state.source_surface->h-1)) return 0; auto &s = surf::state.surfaces[surf::state.source_surface];
return SOURCE(x, y); if (x < 0 || x > (s.w-1) || y < 0 || y > (s.h-1)) return 0;
return s.p[x+y*s.w];
} }
} }
@@ -417,7 +425,7 @@ namespace mini
//const int tw = tile_width; //const int tw = tile_width;
//const int th = tile_height; //const int th = tile_height;
const int tiles_per_row = mini::surf::state.source_surface->w / tw; const int tiles_per_row = mini::surf::state.surfaces[mini::surf::state.source_surface].w / tw;
// Coordenadas del tile dentro del spritesheet // Coordenadas del tile dentro del spritesheet
int tx = (n % tiles_per_row) * tw; int tx = (n % tiles_per_row) * tw;

View File

@@ -2,7 +2,6 @@
#include "external/lua/lua.hpp" #include "external/lua/lua.hpp"
#include "mini/win/win.h" #include "mini/win/win.h"
//#include <SDL3/SDL.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <stack> #include <stack>

View File

@@ -18,7 +18,7 @@
#include "mini/version.h" #include "mini/version.h"
#include <SDL3/SDL.h> #include "backends/backend.h"
#include <filesystem> #include <filesystem>
#include <vector> #include <vector>
@@ -693,10 +693,10 @@ namespace mini
static uint32_t chrono_time = 0; static uint32_t chrono_time = 0;
static int chrono(lua_State *L) { static int chrono(lua_State *L) {
if (lua_gettop(L) == 0) { if (lua_gettop(L) == 0) {
lua_pushnumber(L, float(SDL_GetTicks()-chrono_time)/1000.0f); lua_pushnumber(L, float(backend::get_time_ms()-chrono_time)/1000.0f);
return 1; return 1;
} else { } else {
chrono_time = SDL_GetTicks(); chrono_time = backend::get_time_ms();
return 0; return 0;
} }
} }
@@ -785,11 +785,11 @@ namespace mini
static int clipboard(lua_State *L) { static int clipboard(lua_State *L) {
if (lua_gettop(L) == 0) { if (lua_gettop(L) == 0) {
lua_pushstring(L, SDL_GetClipboardText()); lua_pushstring(L, backend::clipboard());
return 1; return 1;
} else { } else {
const char* value = luaL_checkstring(L, 1); const char* value = luaL_checkstring(L, 1);
SDL_SetClipboardText(value); backend::clipboard(value);
return 0; return 0;
} }
} }

View File

@@ -3,44 +3,43 @@
#include "mini/view/view.h" #include "mini/view/view.h"
#include "mini/draw/draw.h" #include "mini/draw/draw.h"
#define TILES(x, y) map_surface->p[x+y*map_surface->w]
namespace mini namespace mini
{ {
namespace map namespace map
{ {
uint8_t tile_width = 8; uint8_t tile_width = 8;
uint8_t tile_height = 8; uint8_t tile_height = 8;
mini::surf::surface_t* map_surface = nullptr; int map_surface = -1;
void init() { void init() {
} }
void quit() { void quit() {
map_surface = nullptr; map_surface = -1;
} }
namespace surf { namespace surf {
void set(uint8_t surface) { void set(uint8_t surface) {
map_surface = &mini::surf::state.surfaces[surface]; map_surface = surface;
} }
uint8_t get() uint8_t get()
{ {
for (unsigned int i=0; i<MAX_SURFACES; ++i) if (map_surface == &mini::surf::state.surfaces[i]) return i; return map_surface;
return 0;
} }
} }
void draw() { void draw() {
if (!map_surface || !mini::surf::state.source_surface) return; if (map_surface==-1 || mini::surf::state.source_surface==-1) return;
const int tw = tile_width; const int tw = tile_width;
const int th = tile_height; const int th = tile_height;
int celw = map_surface->w; auto &m = mini::surf::state.surfaces[map_surface];
int celh = map_surface->h;
int celw = m.w;
int celh = m.h;
int celx = 0; int celx = 0;
int cely = 0; int cely = 0;
@@ -51,35 +50,37 @@ namespace mini
int sx = ox; int sx = ox;
int sy = oy; int sy = oy;
auto &s = mini::surf::state.surfaces[mini::surf::state.dest_surface];
// Clipping global rápido // Clipping global rápido
if (sx + celw * tw < mini::surf::state.dest_surface->clip[0] || if (sx + celw * tw < s.clip[0] ||
sy + celh * th < mini::surf::state.dest_surface->clip[1] || sy + celh * th < s.clip[1] ||
sx > mini::surf::state.dest_surface->clip[2] || sx > s.clip[2] ||
sy > mini::surf::state.dest_surface->clip[3]) sy > s.clip[3])
return; return;
// Recorte por izquierda // Recorte por izquierda
if (sx < mini::surf::state.dest_surface->clip[0]) { if (sx < s.clip[0]) {
int diff = (mini::surf::state.dest_surface->clip[0] - sx) / tw; int diff = (s.clip[0] - sx) / tw;
celx += diff; celx += diff;
celw -= diff; celw -= diff;
sx += diff * tw; sx += diff * tw;
} }
// Recorte por arriba // Recorte por arriba
if (sy < mini::surf::state.dest_surface->clip[1]) { if (sy < s.clip[1]) {
int diff = (mini::surf::state.dest_surface->clip[1] - sy) / th; int diff = (s.clip[1] - sy) / th;
cely += diff; cely += diff;
celh -= diff; celh -= diff;
sy += diff * th; sy += diff * th;
} }
// Recorte por derecha // Recorte por derecha
int max_x = mini::surf::state.dest_surface->clip[2] - sx; int max_x = s.clip[2] - sx;
if (max_x < celw * tw) celw = max_x / tw + 1; if (max_x < celw * tw) celw = max_x / tw + 1;
// Recorte por abajo // Recorte por abajo
int max_y = mini::surf::state.dest_surface->clip[3] - sy; int max_y = s.clip[3] - sy;
if (max_y < celh * th) celh = max_y / th + 1; if (max_y < celh * th) celh = max_y / th + 1;
// Ahora sx, sy son relativos al origen y ya están recortados // Ahora sx, sy son relativos al origen y ya están recortados
@@ -96,15 +97,17 @@ namespace mini
namespace tile { namespace tile {
uint8_t get(int celx, int cely) { uint8_t get(int celx, int cely) {
if (!map_surface) return 0; if (map_surface==-1) return 0;
if (celx < 0 || celx > (map_surface->w-1) || cely < 0 || cely > (map_surface->h-1)) return 0; auto &m = mini::surf::state.surfaces[map_surface];
return TILES(celx, cely); if (celx < 0 || celx > (m.w-1) || cely < 0 || cely > (m.h-1)) return 0;
return m.p[celx+cely*m.w];
} }
void set(int celx, int cely, uint8_t snum) { void set(int celx, int cely, uint8_t snum) {
if (!map_surface) return; if (map_surface==-1) return;
if (celx < 0 || celx > (map_surface->w-1) || cely < 0 || cely > (map_surface->h-1)) return; auto &m = mini::surf::state.surfaces[map_surface];
TILES(celx, cely) = snum; if (celx < 0 || celx > (m.w-1) || cely < 0 || cely > (m.h-1)) return;
m.p[celx+cely*m.w] = snum;
} }
} }

View File

@@ -18,7 +18,6 @@
#include "lua/lua.h" #include "lua/lua.h"
#include "aux/log.h" #include "aux/log.h"
//#include <SDL3/SDL.h>
#include "backends/backend.h" #include "backends/backend.h"
#include <string.h> #include <string.h>

View File

@@ -18,24 +18,27 @@ namespace mini
void init() { void init() {
target::set(create(win::state.width, win::state.height)); target::set(create(win::state.width, win::state.height));
state.dest_surface = state.screen_surface; state.dest_surface = SCREEN;
} }
void quit() { void quit() {
for (unsigned int i=0;i<MAX_SURFACES;++i) surf::destroy(i); for (unsigned int i=0;i<state.surfaces.size();++i) surf::destroy(i);
state.dest_surface = state.source_surface = NULL; state.surfaces.clear();
state.dest_surface = state.source_surface = -1;
} }
uint8_t create(int w, int h) { uint8_t create(int w, int h) {
unsigned int i = 0; unsigned int i = 0;
while (i<MAX_SURFACES && state.surfaces[i].p != NULL) ++i; while (i<state.surfaces.size() && state.surfaces[i].p != NULL) ++i;
if (i==MAX_SURFACES) return 255; if (i==state.surfaces.size()) state.surfaces.emplace_back();
state.surfaces[i].name = nullptr;
state.surfaces[i].w = w; surface_t &s = state.surfaces[i];
state.surfaces[i].h = h; s.name = nullptr;
state.surfaces[i].size = w*h; s.w = w;
state.surfaces[i].p = (uint8_t*)calloc(state.surfaces[i].size,1); s.h = h;
state.surfaces[i].flags = SURF_GENERATED; s.size = w*h;
s.p = (uint8_t*)calloc(s.size,1);
s.flags = SURF_GENERATED;
clip::reset(i); clip::reset(i);
log_msg(LOG_INFO, "Surface %i creada.\n", i); log_msg(LOG_INFO, "Surface %i creada.\n", i);
return i; return i;
@@ -44,15 +47,16 @@ namespace mini
uint8_t load(uint8_t* buffer, const char* name) { uint8_t load(uint8_t* buffer, const char* name) {
// Agafar la pròxima textura lliure // Agafar la pròxima textura lliure
unsigned int i = 0; unsigned int i = 0;
while (i<MAX_SURFACES && state.surfaces[i].p != NULL) ++i; while (i<state.surfaces.size() && state.surfaces[i].p != NULL) ++i;
if (i==MAX_SURFACES) return 255; if (i==state.surfaces.size()) state.surfaces.emplace_back();
state.surfaces[i].p = LoadGif(buffer, &state.surfaces[i].w, &state.surfaces[i].h); surface_t &s = state.surfaces[i];
state.surfaces[i].size = state.surfaces[i].w * state.surfaces[i].h; s.p = LoadGif(buffer, &s.w, &s.h);
state.surfaces[i].name = (char*)malloc(strlen(name)+1); s.size = s.w * s.h;
state.surfaces[i].flags = SURF_GENERATED; s.name = (char*)malloc(strlen(name)+1);
strcpy(s.name, name);
s.flags = SURF_GENERATED;
clip::reset(i); clip::reset(i);
strcpy(state.surfaces[i].name, name);
log_msg(LOG_INFO, "Buffer '%s' carregat en surface: %i.\n", name, i); log_msg(LOG_INFO, "Buffer '%s' carregat en surface: %i.\n", name, i);
@@ -61,7 +65,7 @@ namespace mini
uint8_t load(const char* filename, const bool external) { uint8_t load(const char* filename, const bool external) {
// Si el gif ja s'ha carregat en una textura, tornem eixa textura // Si el gif ja s'ha carregat en una textura, tornem eixa textura
for (unsigned int i=0; i<MAX_SURFACES; ++i) for (unsigned int i=0; i<state.surfaces.size(); ++i)
if (state.surfaces[i].name && strcmp(state.surfaces[i].name, filename)==0) { if (state.surfaces[i].name && strcmp(state.surfaces[i].name, filename)==0) {
log_msg(LOG_INFO, "Carrega de '%s' abortada: Reusant: %i.\n", filename, i); log_msg(LOG_INFO, "Carrega de '%s' abortada: Reusant: %i.\n", filename, i);
return i; return i;
@@ -69,16 +73,18 @@ namespace mini
// Agafar la pròxima textura lliure // Agafar la pròxima textura lliure
unsigned int i = 0; unsigned int i = 0;
while (i<MAX_SURFACES && state.surfaces[i].p != NULL) ++i; while (i<state.surfaces.size() && state.surfaces[i].p != NULL) ++i;
if (i==MAX_SURFACES) return 255; if (i==state.surfaces.size()) state.surfaces.emplace_back();
state.surfaces[i].flags = SURF_NOTHING; surface_t &s = state.surfaces[i];
s.flags = SURF_NOTHING;
// Carregar l'arxiu de disc // Carregar l'arxiu de disc
int size; int size;
uint8_t *buffer; uint8_t *buffer;
if (external) { if (external) {
buffer = (uint8_t*)file::getfilebufferex(filename, size); buffer = (uint8_t*)file::getfilebufferex(filename, size);
state.surfaces[i].flags |= SURF_EXTERNAL; s.flags |= SURF_EXTERNAL;
} else { } else {
buffer = (uint8_t*)file::getfilebuffer(filename, size); buffer = (uint8_t*)file::getfilebuffer(filename, size);
} }
@@ -91,11 +97,11 @@ namespace mini
} }
// Finalment, carregar el gif en la surface // Finalment, carregar el gif en la surface
state.surfaces[i].p = LoadGif(buffer, &state.surfaces[i].w, &state.surfaces[i].h); s.p = LoadGif(buffer, &s.w, &s.h);
state.surfaces[i].size = state.surfaces[i].w * state.surfaces[i].h; s.size = s.w * s.h;
state.surfaces[i].name = (char*)malloc(strlen(filename)+1); s.name = (char*)malloc(strlen(filename)+1);
clip::reset(i); clip::reset(i);
strcpy(state.surfaces[i].name, filename); strcpy(s.name, filename);
free(buffer); free(buffer);
log_msg(LOG_INFO, "Arxiu '%s' carregat en surface: %i.\n", filename, i); log_msg(LOG_INFO, "Arxiu '%s' carregat en surface: %i.\n", filename, i);
@@ -103,7 +109,7 @@ namespace mini
} }
void reloadsurfs() { void reloadsurfs() {
for (unsigned int i=0; i<MAX_SURFACES; ++i) for (unsigned int i=0; i<state.surfaces.size(); ++i)
if (state.surfaces[i].name) { if (state.surfaces[i].name) {
if (state.surfaces[i].flags & SURF_GENERATED) { if (state.surfaces[i].flags & SURF_GENERATED) {
log_msg(LOG_INFO, "Ignorant surface generada %i.\n", i); log_msg(LOG_INFO, "Ignorant surface generada %i.\n", i);
@@ -159,52 +165,52 @@ namespace mini
void cls(uint8_t color) { void cls(uint8_t color) {
const uint8_t col = draw::state.draw_palette[color]; const uint8_t col = draw::state.draw_palette[color];
memset(state.dest_surface->p, col, state.dest_surface->size); memset(state.surfaces[state.dest_surface].p, col, state.surfaces[state.dest_surface].size);
} }
namespace target { namespace target {
void set(uint8_t surface) { void set(uint8_t surface) {
state.dest_surface = &state.surfaces[surface]; state.dest_surface = surface;
surf::clip::recalculate(); surf::clip::recalculate();
} }
uint8_t get() { uint8_t get() {
for (unsigned int i=0; i<MAX_SURFACES; ++i) if (state.dest_surface == &state.surfaces[i]) return i; return state.dest_surface;
return 0;
} }
} }
namespace source { namespace source {
void set(uint8_t surface) { void set(uint8_t surface) {
state.source_surface = &state.surfaces[surface]; state.source_surface = surface;
} }
uint8_t get() { uint8_t get() {
for (unsigned int i=0; i<MAX_SURFACES; ++i) if (state.source_surface == &state.surfaces[i]) return i; return state.source_surface;
return 0;
} }
} }
namespace clip { namespace clip {
void set(int x, int y, int w, int h) { void set(int x, int y, int w, int h) {
state.dest_surface->clip[0]=x; auto &s = state.surfaces[state.dest_surface];
state.dest_surface->clip[1]=y; s.clip[0]=x;
state.dest_surface->clip[2]=x+(w-1); s.clip[1]=y;
state.dest_surface->clip[3]=y+(h-1); s.clip[2]=x+(w-1);
s.clip[3]=y+(h-1);
recalculate(); recalculate();
} }
void reset(int surface) { void reset(int surface) {
surface_t *s = surface==-1 ? state.dest_surface : &state.surfaces[surface]; auto &s = surface==-1 ? state.surfaces[state.dest_surface] : state.surfaces[surface];
s->clip[0]=0; s.clip[0]=0;
s->clip[1]=0; s.clip[1]=0;
s->clip[2]=s->w-1; s.clip[2]=s.w-1;
s->clip[3]=s->h-1; s.clip[3]=s.h-1;
//recalculate(); //recalculate();
} }
void recalculate() { void recalculate() {
if (state.dest_surface->clip[0] < 0) state.dest_surface->clip[0] = 0; auto &s = state.surfaces[state.dest_surface];
if (state.dest_surface->clip[1] < 0) state.dest_surface->clip[1] = 0; if (s.clip[0] < 0) s.clip[0] = 0;
if (state.dest_surface->clip[2] >= state.dest_surface->w) state.dest_surface->clip[2] = state.dest_surface->w-1; if (s.clip[1] < 0) s.clip[1] = 0;
if (state.dest_surface->clip[3] >= state.dest_surface->h) state.dest_surface->clip[3] = state.dest_surface->h-1; if (s.clip[2] >= s.w) s.clip[2] = s.w-1;
if (s.clip[3] >= s.h) s.clip[3] = s.h-1;
} }
} }

View File

@@ -1,12 +1,14 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <vector>
namespace mini namespace mini
{ {
namespace surf namespace surf
{ {
#define MAX_SURFACES 100 #define SCREEN 0
//#define MAX_SURFACES 100
#define SURF_NOTHING 0 #define SURF_NOTHING 0
#define SURF_EXTERNAL 1 #define SURF_EXTERNAL 1
@@ -22,10 +24,9 @@ namespace mini
}; };
struct state_t { struct state_t {
surface_t surfaces[MAX_SURFACES]; std::vector<surface_t> surfaces;
surface_t* screen_surface = &surfaces[0]; int dest_surface = -1;
surface_t* dest_surface = screen_surface; int source_surface = -1;
surface_t* source_surface = nullptr;
}; };
extern state_t state; extern state_t state;