/* FredyGames: ver sdl1shim.h. Copyright (C) 2026 FredyGames, GPL-3.0-or-later. */ #include #include #include #include #include /* Os macros do sdl1shim.h (-include) valem aqui tambem; o que e do SDL2 de verdade chama-se pelo nome original. */ #undef SDL_SetVideoMode #undef SDL_UpdateRect #undef SDL_SetPalette #undef SDL_PollEvent static SDL_Window *window = NULL; static SDL_Surface *screen_surface = NULL; /* a "tela" do jogo: INDEX8 640x480, paleta logica */ static SDL_Color phys_pal[256]; /* paleta fisica: o que aparece na janela */ static char img_error[256] = ""; SDL_Surface *SDL1_SetVideoMode(int width, int height, int bpp, Uint32 flags) { (void)bpp; (void)flags; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS) != 0) return NULL; window = SDL_CreateWindow("Meritous", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN); if (!window) return NULL; screen_surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 8, SDL_PIXELFORMAT_INDEX8); for (int i = 0; i < 256; i++) { phys_pal[i].r = phys_pal[i].g = phys_pal[i].b = i; phys_pal[i].a = 255; } return screen_surface; } void SDL1_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h) { (void)x; (void)y; (void)w; (void)h; if (!window || screen != screen_surface) return; SDL_Surface *win = SDL_GetWindowSurface(window); if (!win) return; Uint32 map[256]; for (int i = 0; i < 256; i++) map[i] = SDL_MapRGB(win->format, phys_pal[i].r, phys_pal[i].g, phys_pal[i].b); if (win->format->BytesPerPixel != 4) return; int rows = screen->h < win->h ? screen->h : win->h; int cols = screen->w < win->w ? screen->w : win->w; for (int row = 0; row < rows; row++) { const Uint8 *src = (const Uint8 *)screen->pixels + (size_t)row * screen->pitch; Uint32 *dst = (Uint32 *)((Uint8 *)win->pixels + (size_t)row * win->pitch); for (int col = 0; col < cols; col++) dst[col] = map[src[col]]; } SDL_UpdateWindowSurface(window); } int SDL1_SetPalette(SDL_Surface *surface, int flags, const SDL_Color *colors, int firstcolor, int ncolors) { SDL_Color tmp[256]; if (ncolors > 256 - firstcolor) ncolors = 256 - firstcolor; for (int i = 0; i < ncolors; i++) { tmp[i].r = colors[i].r; tmp[i].g = colors[i].g; tmp[i].b = colors[i].b; tmp[i].a = 255; } if (surface == screen_surface && (flags & SDL_PHYSPAL)) { for (int i = 0; i < ncolors; i++) phys_pal[firstcolor + i] = tmp[i]; } if (flags & SDL_LOGPAL) return SDL_SetPaletteColors(surface->format->palette, tmp, firstcolor, ncolors) == 0; return 1; } /* SDL 1.2 nao repete teclas (a menos que se peca): descarta as repeticoes do SDL2. */ int SDL1_PollEvent(SDL_Event *event) { while (SDL_PollEvent(event)) { if (event->type == SDL_KEYDOWN && event->key.repeat) continue; return 1; } return 0; } /* IMG_Load: PNG em tons de cinza ou com paleta (8 bits ou menos) vira superficie INDEX8, que e o que o SDL_image 1.2 devolvia e o jogo usa como indices; o resto (RGB, RGBA) vira RGB24. */ const char *IMG_GetError(void) { return img_error; } SDL_Surface *IMG_Load(const char *file) { FILE *fp = fopen(file, "rb"); if (!fp) { snprintf(img_error, sizeof img_error, "Couldn't open %s", file); return NULL; } png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info = png ? png_create_info_struct(png) : NULL; SDL_Surface *surf = NULL; png_bytep *rows = NULL; if (!png || !info || setjmp(png_jmpbuf(png))) { snprintf(img_error, sizeof img_error, "PNG error in %s", file); if (surf) SDL_FreeSurface(surf); free(rows); if (png) png_destroy_read_struct(&png, &info, NULL); fclose(fp); return NULL; } png_init_io(png, fp); png_read_info(png, info); png_uint_32 w, h; int depth, ctype; png_get_IHDR(png, info, &w, &h, &depth, &ctype, NULL, NULL, NULL); if (depth == 16) png_set_strip_16(png); int indexed = (ctype == PNG_COLOR_TYPE_GRAY || ctype == PNG_COLOR_TYPE_PALETTE); if (indexed) { if (depth < 8) png_set_packing(png); surf = SDL_CreateRGBSurfaceWithFormat(0, w, h, 8, SDL_PIXELFORMAT_INDEX8); SDL_Color pal[256]; memset(pal, 0, sizeof pal); if (ctype == PNG_COLOR_TYPE_PALETTE) { png_colorp p; int n = 0; png_get_PLTE(png, info, &p, &n); for (int i = 0; i < n && i < 256; i++) { pal[i].r = p[i].red; pal[i].g = p[i].green; pal[i].b = p[i].blue; pal[i].a = 255; } } else { int n = 1 << (depth > 8 ? 8 : depth); for (int i = 0; i < 256; i++) { int v = (i < n) ? i * 255 / (n - 1) : 0; pal[i].r = pal[i].g = pal[i].b = v; pal[i].a = 255; } } SDL_SetPaletteColors(surf->format->palette, pal, 0, 256); } else { png_set_strip_alpha(png); if (ctype == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); surf = SDL_CreateRGBSurfaceWithFormat(0, w, h, 24, SDL_PIXELFORMAT_RGB24); } png_read_update_info(png, info); rows = malloc(sizeof(png_bytep) * h); for (png_uint_32 y = 0; y < h; y++) rows[y] = (png_bytep)surf->pixels + (size_t)y * surf->pitch; png_read_image(png, rows); png_read_end(png, NULL); free(rows); png_destroy_read_struct(&png, &info, NULL); fclose(fp); return surf; }