3 * Author : Robin Krens <robin@robinkrens.nl>
5 * Last Modified Date: 15.06.2022
6 * Last Modified By : Robin Krens <robin@robinkrens.nl>
19 #include <sys/types.h>
20 #include <sys/sysmacros.h>
21 #include <SDL2/SDL_image.h>
35 unsigned short outpal[8];
38 int set_info(swan_gfx_t * gfx, SDL_Surface * img)
42 gfx->bpp = img->format->BitsPerPixel;
45 fprintf(stderr, "error: %d bpp format detected\n", img->format->BitsPerPixel);
49 if (gfx->width % 8 | gfx->height % 8) {
50 fprintf(stderr, "error: image not multiple of 16x16 tiles\n \
51 width: %d\theight: %d\n", gfx->width, gfx->height);
55 gfx->row_tiles = gfx->height / 8;
56 gfx->col_tiles = gfx->width / 8;
58 /* set userdata to iterate over
61 img->userdata = img->pixels;
62 gfx->data = (unsigned char *) img->userdata;
63 gfx->palette = img->format->palette->colors;
64 SDL_UnlockSurface(img);
69 void generate_4bpp_tile(unsigned char *buf, swan_gfx_t * gfx,
72 unsigned char * ptr = gfx->data;
73 for (int i = 0; i < TILE_SZ; i+=4) {
74 for (int j = 0; j < 4; ++j) {
75 if (packed) { /* packed format */
76 //printf("%d %d ", ptr[0], ptr[1]);
77 if (ptr[0] >= 8 || ptr[1] >= 8)
78 fprintf(stdout, "warning: too many colors detected\n");
79 gfx->outpal[ptr[0]] = (gfx->palette[ptr[0]].r >> 4) << 8 |
80 (gfx->palette[ptr[0]].g >> 4) << 4 |
81 gfx->palette[ptr[0]].b >> 4;
82 buf[i+j] = ptr[0] << 4;
85 } else { /* TODO: planar format */
86 for (int x = 0; x < 8; ++x) {
88 fprintf(stdout, "warning: too many colors detected\n");
89 buf[i + j] = ptr[x] << j;
96 ptr += (8 * (gfx->col_tiles-1));
101 FILE * openstream(const char * name, const char * prefix,
102 unsigned tile_nr, bool append)
104 assert(strlen(name) < 200);
108 unsigned buf_len = 256;
110 snprintf(buf, buf_len, "%s/%s%d.%s", prefix, name, tile_nr, prefix);
112 //printf("%s\n", buf);
114 stream = fopen(buf, "w");
116 stream = fopen(buf, "a");
122 int create_dir(const char *name)
126 if (stat(name, &statbuf) == -1)
127 return mkdir(name, 0755);
129 if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
136 int main(int argc, char *argv[])
138 SDL_Surface * rawbmp;
145 const short fill = 0xFFFF;
146 bool seperate_gfx = false;
147 bool seperate_pal = false;
149 while ((opt = getopt(argc, argv, "po:sv")) != -1) {
153 printf("generate individual .pal for each tile");
156 printf("output file %s\n", optarg);
157 strcpy(outfile, optarg);
162 printf("generate .gfx for each tile\n");
168 fprintf(stderr, "Usage: %s [-s] [-o output] file \n", argv[0]);
173 if (optind >= argc) {
174 fprintf(stderr, "Expected input .bmp file!\n");
175 fprintf(stderr, "Usage: %s [-s] [-o output] [file]\n", argv[0]);
179 infile = argv[optind];
181 rawbmp = SDL_LoadBMP(infile);
183 fprintf(stderr, "can not load %s file\n", infile);
187 swan_gfx_t * gfx = calloc(1, sizeof(swan_gfx_t));
188 int ret = set_info(gfx, rawbmp);
193 unsigned char *tile_buf = calloc(TILE_SZ, sizeof(unsigned char));
196 sprintf(outfile, "out");
199 /* check for existing gfx/ and pal/ directories */
200 ret = create_dir("gfx/");
201 ret += create_dir("pal/");
204 fprintf(stderr, "error: can not create output gfx/ or pal/ location\n");
208 fprintf(stdout, "generating %d tile(s) \
210 with %d pal file(s)\n",
211 gfx->row_tiles * gfx->col_tiles,
212 seperate_gfx ? gfx->row_tiles * gfx->col_tiles : 1,
213 seperate_pal ? gfx->row_tiles * gfx->col_tiles : 1);
215 for (int i = 0, cnt = 0; i < gfx->row_tiles; ++i) {
216 for (int j = 0; j < gfx->col_tiles; ++j, ++cnt) {
218 if (i == 0 && j == 0) {
219 gfxstream = openstream(outfile, "gfx", 0, false);
220 palstream = openstream(outfile, "pal", 0, false);
223 gfxstream = openstream(outfile, "gfx", cnt, false);
226 palstream = openstream(outfile, "pal", cnt, false);
230 generate_4bpp_tile(tile_buf, gfx, true);
231 int ret = fwrite(tile_buf, sizeof(unsigned char), TILE_SZ, gfxstream);
232 if (ret != TILE_SZ) {
233 fprintf(stderr, "failed to convert, only write %d instead of %d\n", ret, TILE_SZ);
238 fwrite(gfx->outpal, sizeof(unsigned short), 8, palstream);
239 for (int i = 0; i < 8; ++i)
240 ret += fwrite(&fill, sizeof(unsigned short), 1, palstream);
242 gfx->data += 8; /* next column */
244 if (gfx->row_tiles == (i-1) && gfx->col_tiles == (j-1)) {
254 gfx->data += (gfx->col_tiles * 64) - (8 * gfx->col_tiles);
260 SDL_FreeSurface(rawbmp);