Files
mini/source/mini/surf/surf.cpp
T
JailDoctor 4c0eabcc5c - [NEW] Funcions per a apilar i desapilar surfaces target i source:
surf.source.push(surface)
surf.source.pop()
surf.target.push(surface)
surf.target.pop()
2026-05-29 20:37:15 +02:00

238 lines
8.1 KiB
C++

#include "surf.h"
#include "other/gif.h"
#include "other/gifenc.h"
#include "other/log.h"
#include "mini/file/file.h"
#include "mini/draw/draw.h"
#include "mini/win/win.h"
#include <stdlib.h>
namespace mini
{
namespace surf
{
state_t state;
void init() {
target::set(create(win::state.width, win::state.height));
state.dest_surface = SCREEN;
}
void quit() {
for (unsigned int i=0;i<state.surfaces.size();++i) surf::destroy(i);
state.surfaces.clear();
state.dest_surface = state.source_surface = -1;
}
uint8_t create(int w, int h) {
unsigned int i = 0;
while (i<state.surfaces.size() && state.surfaces[i].p != NULL) ++i;
if (i==state.surfaces.size()) state.surfaces.emplace_back();
surface_t &s = state.surfaces[i];
s.name = nullptr;
s.w = w;
s.h = h;
s.size = w*h;
s.p = (uint8_t*)calloc(s.size,1);
s.flags = SURF_GENERATED;
clip::reset(i);
log_msg(LOG_INFO, "Surface %i creada.\n", i);
return i;
}
uint8_t load(uint8_t* buffer, const char* name) {
// Agafar la pròxima textura lliure
unsigned int i = 0;
while (i<state.surfaces.size() && state.surfaces[i].p != NULL) ++i;
if (i==state.surfaces.size()) state.surfaces.emplace_back();
surface_t &s = state.surfaces[i];
s.p = LoadGif(buffer, &s.w, &s.h);
s.size = s.w * s.h;
s.name = (char*)malloc(strlen(name)+1);
strcpy(s.name, name);
s.flags = SURF_GENERATED;
clip::reset(i);
log_msg(LOG_INFO, "Buffer '%s' carregat en surface: %i.\n", name, i);
return i;
}
uint8_t load(const char* filename, const bool external) {
// Si el gif ja s'ha carregat en una textura, tornem eixa textura
for (unsigned int i=0; i<state.surfaces.size(); ++i)
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);
return i;
}
// Agafar la pròxima textura lliure
unsigned int i = 0;
while (i<state.surfaces.size() && state.surfaces[i].p != NULL) ++i;
if (i==state.surfaces.size()) state.surfaces.emplace_back();
surface_t &s = state.surfaces[i];
s.flags = SURF_NOTHING;
// Carregar l'arxiu de disc
int size;
uint8_t *buffer;
if (external) {
buffer = (uint8_t*)file::getfilebufferex(filename, size);
s.flags |= SURF_EXTERNAL;
} else {
buffer = (uint8_t*)file::getfilebuffer(filename, size);
}
// Si no s'ha pogut, petar
if (!buffer) {
log_msg(LOG_FAIL, "Error al intentar obrir l'arxiu '%s'\n", filename);
exit(-1);
return 255;
}
// Finalment, carregar el gif en la surface
s.p = LoadGif(buffer, &s.w, &s.h);
s.size = s.w * s.h;
s.name = (char*)malloc(strlen(filename)+1);
clip::reset(i);
strcpy(s.name, filename);
free(buffer);
log_msg(LOG_INFO, "Arxiu '%s' carregat en surface: %i.\n", filename, i);
return i;
}
void reloadsurfs() {
for (unsigned int i=0; i<state.surfaces.size(); ++i)
if (state.surfaces[i].name) {
if (state.surfaces[i].flags & SURF_GENERATED) {
log_msg(LOG_INFO, "Ignorant surface generada %i.\n", i);
} else {
log_msg(LOG_INFO, "Recarregant de disc surface %i:'%s'.\n", i, state.surfaces[i].name);
int size;
uint8_t *buffer;
if (state.surfaces[i].flags & SURF_EXTERNAL) {
buffer = (uint8_t*)file::getfilebufferex(state.surfaces[i].name, size);
} else {
buffer = (uint8_t*)file::getfilebuffer(state.surfaces[i].name, size);
}
// Si no s'ha pogut, petar
if (!buffer) {
log_msg(LOG_FAIL, "Error al intentar obrir l'arxiu '%s'\n", state.surfaces[i].name);
exit(-1);
}
state.surfaces[i].p = LoadGif(buffer, &state.surfaces[i].w, &state.surfaces[i].h);
state.surfaces[i].size = state.surfaces[i].w * state.surfaces[i].h;
clip::reset(i);
free(buffer);
}
}
}
void save(uint8_t surface, const char* filename, uint8_t *pal, uint8_t colors)
{
gif::write_gif(filename, state.surfaces[surface].p, state.surfaces[surface].w, state.surfaces[surface].h, pal, colors);
}
void destroy(uint8_t surface) {
if (state.surfaces[surface].name != NULL) free(state.surfaces[surface].name);
state.surfaces[surface].name = NULL;
if (state.surfaces[surface].p != NULL) {
free(state.surfaces[surface].p);
log_msg(LOG_INFO, "Surface %i alliberada.\n", surface);
}
state.surfaces[surface].p = NULL;
state.surfaces[surface].flags = SURF_NOTHING;
}
int width(uint8_t surface) {
return state.surfaces[surface].w;
}
int height(uint8_t surface) {
return state.surfaces[surface].h;
}
void cls(uint8_t color) {
const uint8_t col = draw::state.draw_palette[color];
memset(state.surfaces[state.dest_surface].p, col, state.surfaces[state.dest_surface].size);
}
namespace target {
void set(uint8_t surface) {
state.dest_surface = surface;
surf::clip::recalculate();
}
uint8_t get() {
return state.dest_surface;
}
void push(uint8_t surface) {
state.dest_stack.push(state.dest_surface);
state.dest_surface = surface;
}
void pop() {
state.dest_surface = state.dest_stack.top();
state.dest_stack.pop();
}
}
namespace source {
void set(uint8_t surface) {
state.source_surface = surface;
}
uint8_t get() {
return state.source_surface;
}
void push(uint8_t surface) {
state.source_stack.push(state.source_surface);
state.source_surface = surface;
}
void pop() {
state.source_surface = state.source_stack.top();
state.source_stack.pop();
}
}
namespace clip {
void set(int x, int y, int w, int h) {
auto &s = state.surfaces[state.dest_surface];
s.clip[0]=x;
s.clip[1]=y;
s.clip[2]=x+(w-1);
s.clip[3]=y+(h-1);
recalculate();
}
void reset(int surface) {
auto &s = surface==-1 ? state.surfaces[state.dest_surface] : state.surfaces[surface];
s.clip[0]=0;
s.clip[1]=0;
s.clip[2]=s.w-1;
s.clip[3]=s.h-1;
//recalculate();
}
void recalculate() {
auto &s = state.surfaces[state.dest_surface];
if (s.clip[0] < 0) s.clip[0] = 0;
if (s.clip[1] < 0) s.clip[1] = 0;
if (s.clip[2] >= s.w) s.clip[2] = s.w-1;
if (s.clip[3] >= s.h) s.clip[3] = s.h-1;
}
}
}
}