Created
June 19, 2011 16:50
-
-
Save giannitedesco/1034469 to your computer and use it in GitHub Desktop.
Rip syndicate graphics tiles in to TGA files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <errno.h> | |
#include <assert.h> | |
#include <ctype.h> | |
#include <stdint.h> | |
#include <endian.h> | |
#include <inttypes.h> | |
#define SYND_NUM_TILES 256 | |
#define SYND_NUM_SUBTILES 6 | |
#define SYND_HBLK_MIN_OFS (SYND_NUM_TILES * \ | |
SYND_NUM_SUBTILES * \ | |
sizeof(uint32_t)) | |
#define SYND_SUBTILE_X 32 | |
#define SYND_SUBTILE_Y 16 | |
#define SYND_SUBTILE_SZ (20 * SYND_SUBTILE_Y) | |
struct tga { | |
uint8_t tga_identsize; | |
uint8_t tga_colormap_type; | |
uint8_t tga_image_type; | |
uint16_t tga_color_map_start; | |
uint16_t tga_color_map_len; | |
uint8_t tga_color_map_bits; | |
uint16_t tga_xstart; | |
uint16_t tga_ystart; | |
uint16_t tga_width; | |
uint16_t tga_height; | |
uint8_t tga_bpp; | |
uint8_t tga_descriptor; | |
} __attribute__((packed)); | |
struct subtile { | |
struct tga hdr; | |
uint8_t pix[SYND_SUBTILE_X * SYND_SUBTILE_Y * 4]; | |
} __attribute__((packed)); | |
static unsigned int palette_nr; | |
static uint8_t *palette; | |
static const uint8_t *mapfile(int fd, size_t *len) | |
{ | |
struct stat st; | |
const uint8_t *map; | |
*len = 0; | |
if ( fstat(fd, &st) ) | |
return NULL; | |
map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); | |
if ( map == MAP_FAILED ) | |
return NULL; | |
*len = st.st_size; | |
return map; | |
} | |
static int load_palette(const char *fn) | |
{ | |
const uint8_t *map; | |
unsigned int i; | |
size_t sz; | |
int fd; | |
fd = open(fn, O_RDONLY); | |
if ( fd < 0 ) | |
return 0; | |
map = mapfile(fd, &sz); | |
if ( NULL == map ) { | |
close(fd); | |
return 0; | |
} | |
palette = malloc(4 * (sz / 3)); | |
if ( NULL == palette ) { | |
munmap((void *)map, sz); | |
close(fd); | |
return 0; | |
} | |
palette_nr = sz / 3; | |
for(i = 0; i < palette_nr; i++) { | |
uint8_t r, g, b; | |
r = map[3 * i + 0]; | |
g = map[3 * i + 1]; | |
b = map[3 * i + 2]; | |
#if 0 | |
palette[4 * i + 0] = r; | |
palette[4 * i + 1] = g; | |
palette[4 * i + 2] = b; | |
#else | |
palette[4 * i + 0] = (r << 2) | (r >> 4); | |
palette[4 * i + 1] = (g << 2) | (g >> 4); | |
palette[4 * i + 2] = (b << 2) | (b >> 4); | |
#endif | |
palette[4 * i + 3] = 0xff; | |
} | |
printf("Palette: %u colours\n", sz / 3); | |
munmap((void *)map, sz); | |
close(fd); | |
return 1; | |
} | |
static void unpack_row(uint8_t *dst, const uint8_t *src, unsigned int row_num) | |
{ | |
uint8_t idx[SYND_SUBTILE_X]; | |
unsigned int x, j, i; | |
const uint8_t *in; | |
uint8_t *out; | |
in = src + 20 * (SYND_SUBTILE_Y - (row_num + 1)); | |
for(j = 0; j < 4; j++) { | |
for (i = 0; i < 8; i++) { | |
unsigned int pos; | |
pos = 7 - i; | |
x = j * 8 + i; | |
idx[x] = | |
(((in[j] & (1 << pos)) >> pos) << 4) | | |
(((in[4 + j] & (1 << pos)) >> pos) << 3) | | |
(((in[8 + j] & (1 << pos)) >> pos) << 2) | | |
(((in[12 + j] & (1 << pos)) >> pos) << 1) | | |
(((in[16 + j] & (1 << pos)) >> pos) << 0); | |
assert(0 == (idx[x] & ~0x1f)); | |
} | |
} | |
out = dst + (4 * row_num * SYND_SUBTILE_X); | |
for(x = 0; x < SYND_SUBTILE_X; x++, out += 4) { | |
#if 1 | |
out[2] = palette[4 * (idx[x] & 0xf) + 0]; | |
out[1] = palette[4 * (idx[x] & 0xf) + 1]; | |
out[0] = palette[4 * (idx[x] & 0xf) + 2]; | |
out[3] = (idx[x] & (1 << 4)) ? 0x00 : 0xff; | |
#else | |
out[2] = palette[4 * row_num] + 0; | |
out[1] = palette[4 * row_num] + 1; | |
out[0] = palette[4 * row_num] + 2; | |
out[3] = 0xff; | |
#endif | |
} | |
} | |
static int load_tile(unsigned int tnum, unsigned int snum, const uint8_t *ptr) | |
{ | |
struct subtile *tile; | |
unsigned int y; | |
char fnbuf[64]; | |
int fd; | |
tile = calloc(1, sizeof(*tile)); | |
if ( NULL == tile ) | |
return 0; | |
tile->hdr.tga_image_type = 2; /* pixmap */ | |
tile->hdr.tga_bpp = 32; /* bgra */ | |
tile->hdr.tga_width = htole16(SYND_SUBTILE_X); | |
tile->hdr.tga_height = htole16(SYND_SUBTILE_Y); | |
for(y = 0; y < SYND_SUBTILE_Y; y++) { | |
unpack_row(tile->pix, ptr, (SYND_SUBTILE_Y - (y + 1))); | |
} | |
snprintf(fnbuf, sizeof(fnbuf), "tile%u.%u.tga", tnum, snum); | |
fd = open(fnbuf, O_WRONLY|O_CREAT|O_TRUNC, 0600); | |
if ( fd < 0 ) { | |
free(tile); | |
return 0; | |
} | |
if ( write(fd, tile, sizeof(*tile)) != sizeof(*tile) ) { | |
close(fd); | |
free(tile); | |
return 0; | |
} | |
close(fd); | |
free(tile); | |
printf("wrote: %s\n", fnbuf); | |
return 1; | |
} | |
static int load_tiles(const uint8_t *map, size_t sz) | |
{ | |
const uint32_t *otbl; | |
unsigned int i, j; | |
if ( sz < SYND_HBLK_MIN_OFS ) { | |
fprintf(stderr, "hblk: file to small: %zu < %zu\n", | |
sz, SYND_HBLK_MIN_OFS); | |
return 0; | |
} | |
otbl = (uint32_t *)map; | |
for(i = 0; i < SYND_NUM_TILES; i++) { | |
for(j = 0; j < SYND_NUM_SUBTILES; j++) { | |
if ( *otbl < SYND_HBLK_MIN_OFS || | |
(*otbl + SYND_SUBTILE_SZ) >= sz ) { | |
fprintf(stderr, "tile %u.%u: BLANK\n", i, j); | |
}else{ | |
load_tile(i, j, map + *otbl); | |
} | |
otbl++; | |
} | |
} | |
assert((uint8_t *)otbl == (map + SYND_HBLK_MIN_OFS)); | |
return 0; | |
} | |
int main(int argc, char **argv) | |
{ | |
const uint8_t *map; | |
size_t sz; | |
if ( argc < 2 ) | |
return EXIT_FAILURE; | |
if ( !load_palette(argv[1]) ) | |
return EXIT_FAILURE; | |
map = mapfile(STDIN_FILENO, &sz); | |
if ( NULL == map ) | |
return EXIT_FAILURE; | |
if ( load_tiles(map, sz) ) | |
return EXIT_FAILURE; | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment