#include "palette.h" #include "gif.c" #include #include #include #include "defines.h" namespace Palette { struct SurfaceData { Uint8 *data; Uint16 w, h; }; static SDL_Window *window = nullptr; static SDL_Renderer *renderer = nullptr; static SDL_Texture *texture = nullptr; static Surface screen; static Surface dst_surface; static Surface src_surface = nullptr; static Uint32 palette[256]; static int width = 0; static int height = 0; static int zoom = 0; static int transparent_color = 14; static int palette_number = 0; Surface newSurface(int w, int h) { Surface surf = (Surface)malloc(sizeof(SurfaceData)); surf->w = w; surf->h = h; surf->data = (Uint8 *)malloc(w * h); return surf; } void deleteSurface(Surface surf) { if (surf) { free(surf->data); free(surf); } } void setDst(Surface surf) { dst_surface = (surf == nullptr) ? screen : surf; } void setSrc(Surface surf) { src_surface = surf; } void blit(int dx, int dy, int sx, int sy, int w, int h) { if (src_surface == nullptr) { return; } for (int iy = 0; iy < h; ++iy) { for (int ix = 0; ix < w; ++ix) { putPixel(dx + ix, dy + iy, getPixel(sx + ix, sy + iy)); } } } Surface loadSurface(const char *filename) { FILE *f = fopen(filename, "rb"); if (!f) { return nullptr; } fseek(f, 0, SEEK_END); long size = ftell(f); fseek(f, 0, SEEK_SET); Uint8 *buffer = (Uint8 *)malloc(size); fread(buffer, size, 1, f); fclose(f); Uint16 w, h; Uint8 *pixels = GIF::LoadGif(buffer, &w, &h); if (pixels == nullptr) { return nullptr; } Surface surf = (Surface)malloc(sizeof(SurfaceData)); surf->w = w; surf->h = h; surf->data = pixels; free(buffer); return surf; } void loadPalette(const char *filename) { FILE *f = fopen(filename, "rb"); if (!f) { return; } fseek(f, 0, SEEK_END); long size = ftell(f); fseek(f, 0, SEEK_SET); Uint8 *buffer = (Uint8 *)malloc(size); fread(buffer, size, 1, f); fclose(f); Uint32 *pal = GIF::LoadPalette(buffer); if (pal == nullptr) { return; } free(buffer); for (int i = 0; i < 256; ++i) { palette[i] = pal[i]; } } void init(const char *titol, int w, int h, int z) { SDL_Init(SDL_INIT_VIDEO); width = w; height = h; zoom = z; window = SDL_CreateWindow(titol, w * z, h * z, 0); renderer = SDL_CreateRenderer(window, nullptr); SDL_SetRenderLogicalPresentation(renderer, w, h, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h); SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST); screen = newSurface(w, h); dst_surface = screen; } void setPalette(int index, Uint32 color) { palette[index] = color; } void clear(Uint8 color) { for (int i = 0; i < dst_surface->w * dst_surface->h; ++i) { dst_surface->data[i] = color; } } void flip() { Uint32 *pixels; int pitch; SDL_LockTexture(texture, nullptr, (void **)&pixels, &pitch); for (int i = 0; i < width * height; ++i) { pixels[i] = palette[screen->data[i]]; } SDL_UnlockTexture(texture); SDL_RenderTexture(renderer, texture, nullptr, nullptr); SDL_RenderPresent(renderer); } void putPixel(int x, int y, Uint8 color) { if (x < 0 || y < 0 || x >= dst_surface->w || y >= dst_surface->h || color == transparent_color) { return; } dst_surface->data[x + y * dst_surface->w] = color; } Uint8 getPixel(int x, int y) { return src_surface->data[x + y * src_surface->w]; } void switchPalette() { palette_number = (palette_number + 1) % NUM_PALETTES; std::array palettes{"resources/pal01.gif", "resources/pal02.gif"}; loadPalette(palettes.at(palette_number).c_str()); } }