#include "core/jail/jdraw8.hpp" #include #include "core/jail/jfile.hpp" #include "core/system/fiber.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) { int filesize = 0; char* buffer = file_getfilebuffer(file, filesize); unsigned short w, h; Uint8* pixels = LoadGif((unsigned char*)buffer, &w, &h); free(buffer); 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) { int filesize = 0; char* buffer = NULL; buffer = file_getfilebuffer(file, filesize); JD8_Palette palette = (JD8_Palette)LoadPalette((unsigned char*)buffer); return palette; } 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() { 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; } } // Cedeix el control al Director. Quan Director::run() ens torne a fer // resume(), continuarem just ací i el joc continuarà amb la següent // iteració del seu loop sense bloquejos de mutex/cv. GameFiber::yield(); } 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; } void JD8_FadeOut() { JD8_FadeStartOut(); while (true) { const bool done = JD8_FadeTickStep(); JD8_Flip(); if (done) break; } } void JD8_FadeToPal(JD8_Palette pal) { JD8_FadeStartToPal(pal); while (true) { const bool done = JD8_FadeTickStep(); JD8_Flip(); if (done) break; } }