Files
aee/source/core/jail/jdraw8.cpp
Sergio Valor fe41919e1e clang-format
mogudes coses de config.yaml a debug.yaml
2026-04-16 16:46:18 +02:00

262 lines
8.0 KiB
C++

#include "core/jail/jdraw8.hpp"
#include <fstream>
#include "core/resources/resource_helper.hpp"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#endif
#include "external/gif.h"
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
JD8_Surface screen = NULL;
JD8_Palette main_palette = NULL;
Uint32* pixel_data = NULL;
void JD8_Init() {
screen = (JD8_Surface)calloc(1, 64000);
main_palette = (JD8_Palette)calloc(1, 768);
pixel_data = (Uint32*)calloc(1, 320 * 200 * 4);
}
void JD8_Quit() {
if (screen != NULL) free(screen);
if (main_palette != NULL) free(main_palette);
if (pixel_data != NULL) free(pixel_data);
}
void JD8_ClearScreen(Uint8 color) {
memset(screen, color, 64000);
}
JD8_Surface JD8_NewSurface() {
JD8_Surface surface = (JD8_Surface)malloc(64000);
memset(surface, 0, 64000);
return surface;
}
JD8_Surface JD8_LoadSurface(const char* file) {
auto buffer = ResourceHelper::loadFile(file);
unsigned short w, h;
Uint8* pixels = LoadGif(buffer.data(), &w, &h);
if (pixels == NULL) {
printf("Unable to load bitmap: %s\n", SDL_GetError());
exit(1);
}
JD8_Surface image = JD8_NewSurface();
memcpy(image, pixels, 64000);
free(pixels);
return image;
}
JD8_Palette JD8_LoadPalette(const char* file) {
auto buffer = ResourceHelper::loadFile(file);
return (JD8_Palette)LoadPalette(buffer.data());
}
void JD8_SetScreenPalette(JD8_Palette palette) {
if (main_palette == palette) return;
if (main_palette != NULL) free(main_palette);
main_palette = palette;
}
void JD8_FillSquare(int ini, int height, Uint8 color) {
const int offset = ini * 320;
const int size = height * 320;
memset(&screen[offset], color, size);
}
void JD8_Blit(JD8_Surface surface) {
memcpy(screen, surface, 64000);
}
void JD8_Blit(int x, int y, JD8_Surface surface, int sx, int sy, int sw, int sh) {
int src_pointer = sx + (sy * 320);
int dst_pointer = x + (y * 320);
for (int i = 0; i < sh; i++) {
memcpy(&screen[dst_pointer], &surface[src_pointer], sw);
src_pointer += 320;
dst_pointer += 320;
}
}
void JD8_BlitToSurface(int x, int y, JD8_Surface surface, int sx, int sy, int sw, int sh, JD8_Surface dest) {
int src_pointer = sx + (sy * 320);
int dst_pointer = x + (y * 320);
for (int i = 0; i < sh; i++) {
memcpy(&dest[dst_pointer], &surface[src_pointer], sw);
src_pointer += 320;
dst_pointer += 320;
}
}
void JD8_BlitCK(int x, int y, JD8_Surface surface, int sx, int sy, int sw, int sh, Uint8 colorkey) {
int src_pointer = sx + (sy * 320);
int dst_pointer = x + (y * 320);
for (int j = 0; j < sh; j++) {
for (int i = 0; i < sw; i++) {
if (surface[src_pointer + i] != colorkey) screen[dst_pointer + i] = surface[src_pointer + i];
}
src_pointer += 320;
dst_pointer += 320;
}
}
void JD8_BlitCKCut(int x, int y, JD8_Surface surface, int sx, int sy, int sw, int sh, Uint8 colorkey) {
int src_pointer = sx + (sy * 320);
int dst_pointer = x + (y * 320);
for (int j = 0; j < sh; j++) {
for (int i = 0; i < sw; i++) {
if (surface[src_pointer + i] != colorkey && (x + i >= 0) && (y + j >= 0) && (x + i < 320) && (y + j < 200)) screen[dst_pointer + i] = surface[src_pointer + i];
}
src_pointer += 320;
dst_pointer += 320;
}
}
void JD8_BlitCKScroll(int y, JD8_Surface surface, int sx, int sy, int sh, Uint8 colorkey) {
int dst_pointer = y * 320;
for (int j = sy; j < sy + sh; j++) {
for (int i = 0; i < 320; i++) {
int x = (i + sx) % 320;
if (surface[x + j * 320] != colorkey) screen[dst_pointer] = surface[x + j * 320];
dst_pointer++;
}
}
}
void JD8_BlitCKToSurface(int x, int y, JD8_Surface surface, int sx, int sy, int sw, int sh, JD8_Surface dest, Uint8 colorkey) {
int src_pointer = sx + (sy * 320);
int dst_pointer = x + (y * 320);
for (int j = 0; j < sh; j++) {
for (int i = 0; i < sw; i++) {
if (surface[src_pointer + i] != colorkey) dest[dst_pointer + i] = surface[src_pointer + i];
}
src_pointer += 320;
dst_pointer += 320;
}
}
void JD8_Flip() {
// Converteix el framebuffer indexat (paletted) a ARGB (pixel_data).
// El Director crida aquesta funció després del tick de cada escena
// per preparar el frame abans de presentar-lo. Ja no fa yield —
// tot corre en un sol thread sense fibers des de Phase B.2.
for (int x = 0; x < 320; x++) {
for (int y = 0; y < 200; y++) {
Uint32 color = 0xFF000000 + main_palette[screen[x + (y * 320)]].r + (main_palette[screen[x + (y * 320)]].g << 8) + (main_palette[screen[x + (y * 320)]].b << 16);
pixel_data[x + (y * 320)] = color;
}
}
}
Uint32* JD8_GetFramebuffer() {
return pixel_data;
}
void JD8_FreeSurface(JD8_Surface surface) {
free(surface);
}
Uint8 JD8_GetPixel(JD8_Surface surface, int x, int y) {
return surface[x + (y * 320)];
}
void JD8_PutPixel(JD8_Surface surface, int x, int y, Uint8 pixel) {
surface[x + (y * 320)] = pixel;
}
void JD8_SetPaletteColor(Uint8 index, Uint8 r, Uint8 g, Uint8 b) {
main_palette[index].r = r << 2;
main_palette[index].g = g << 2;
main_palette[index].b = b << 2;
}
// Màquina d'estats del fade. Evita que JD8_FadeOut/JD8_FadeToPal hagen de
// mantindre whiles interns. Cada pas aplica un delta a la paleta activa i
// el caller decideix quan fer Flip.
namespace {
enum FadeType {
FADE_NONE = 0,
FADE_OUT,
FADE_TO_PAL,
};
constexpr int FADE_STEPS = 32;
FadeType fade_type = FADE_NONE;
Color fade_target[256];
int fade_step = 0;
void apply_fade_step() {
if (fade_type == FADE_OUT) {
for (int i = 0; i < 256; i++) {
main_palette[i].r = main_palette[i].r >= 8 ? main_palette[i].r - 8 : 0;
main_palette[i].g = main_palette[i].g >= 8 ? main_palette[i].g - 8 : 0;
main_palette[i].b = main_palette[i].b >= 8 ? main_palette[i].b - 8 : 0;
}
} else if (fade_type == FADE_TO_PAL) {
for (int i = 0; i < 256; i++) {
main_palette[i].r = main_palette[i].r <= int(fade_target[i].r) - 8
? main_palette[i].r + 8
: fade_target[i].r;
main_palette[i].g = main_palette[i].g <= int(fade_target[i].g) - 8
? main_palette[i].g + 8
: fade_target[i].g;
main_palette[i].b = main_palette[i].b <= int(fade_target[i].b) - 8
? main_palette[i].b + 8
: fade_target[i].b;
}
}
}
} // namespace
void JD8_FadeStartOut() {
fade_type = FADE_OUT;
fade_step = 0;
}
void JD8_FadeStartToPal(JD8_Palette pal) {
fade_type = FADE_TO_PAL;
memcpy(fade_target, pal, sizeof(Color) * 256);
fade_step = 0;
}
bool JD8_FadeIsActive() {
return fade_type != FADE_NONE;
}
bool JD8_FadeTickStep() {
if (fade_type == FADE_NONE) return true;
apply_fade_step();
fade_step++;
if (fade_step >= FADE_STEPS) {
fade_type = FADE_NONE;
return true;
}
return false;
}
// Els shims bloquejants `JD8_FadeOut` i `JD8_FadeToPal` han estat
// eliminats a Phase B.2: feien un bucle de 32 iteracions amb `JD8_Flip`
// entre cada una que només funcionava mentre l'entorn tenia fibers i
// `JD8_Flip` cedia el control al Director. Ara tot fade es fa tick a
// tick via `scenes::PaletteFade` (que encapsula `JD8_FadeStartOut` /
// `JD8_FadeStartToPal` + `JD8_FadeTickStep`).