I now have the ability to export images from a Game Boy Camera SRAM file to printable 160x144 tile files

This commit is contained in:
XANTRONIX Development 2016-06-07 22:45:13 -05:00
parent 26196ab925
commit 6a5fc83ede
4 changed files with 201 additions and 22 deletions

View file

@ -40,7 +40,7 @@ static void usage(int argc, char **argv, const char *message, ...) {
" %1$s split file.sav rn gn bn input.png\n"
" %1$s merge file.sav rn gn bn output.png\n"
" %1$s import-tile file.sav 1..30 printer.tile\n"
" %1$s export-tile file.sav 1..30 output.png\n"
" %1$s export-tile file.sav 1..30 output.tile\n"
" %1$s convert-tile printer.tile output.png\n",
argv[0]);
@ -587,6 +587,87 @@ error_sram_open:
return 1;
}
static int export_tile(int argc, char **argv) {
cammy_sram *sram;
cammy_image *dest, *src;
int photo;
if (argc < 2) {
usage(argc, argv, "No camera SRAM file provided");
} else if (argc < 3) {
usage(argc, argv, "No picture number provided");
} else if (argc < 4) {
usage(argc, argv, "No Game Boy screen tile data file provided");
}
photo = atoi(argv[3]);
if (photo < 1 || photo > CAMMY_SRAM_PHOTO_COUNT) {
usage(argc, argv, "Invalid photo number");
}
if ((sram = cammy_sram_open(argv[2])) == NULL) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "cammy_sram_open()", argv[2], strerror(errno));
goto error_sram_open;
}
if ((src = malloc(sizeof(*src))) == NULL) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "malloc()", strerror(errno));
goto error_malloc_src;
}
src->format = CAMMY_IMAGE_TILE;
src->size = CAMMY_PHOTO_SIZE;
src->width = CAMMY_PHOTO_WIDTH;
src->height = CAMMY_PHOTO_HEIGHT;
src->tiles = (cammy_tile *)&sram->data->photos[photo-1].tiles;
if ((dest = cammy_image_new(CAMMY_IMAGE_TILE,
CAMMY_SCREEN_WIDTH,
CAMMY_SCREEN_HEIGHT)) == NULL) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "cammy_image_new()", strerror(errno));
goto error_image_new_dest;
}
memset(dest->buf, '\0', dest->size);
cammy_image_copy(dest, src,
16, 16, 0, 0, CAMMY_PHOTO_WIDTH, CAMMY_PHOTO_HEIGHT);
if (cammy_image_save_tile(dest, argv[4]) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "cammy_image_save_tile()", argv[4], strerror(errno));
goto error_image_save_tile_dest;
}
free(dest);
cammy_image_close(src);
cammy_sram_close(sram);
return 0;
error_image_save_tile_dest:
cammy_image_destroy(dest);
error_image_new_dest:
free(src);
error_malloc_src:
cammy_sram_close(sram);
error_sram_open:
return errno || 1;
}
static int convert_tile(int argc, char **argv) {
int fd;
void *in, *out;
@ -664,6 +745,7 @@ static struct {
{ "split", split },
{ "merge", merge },
{ "import-tile", import_tile },
{ "export-tile", export_tile },
{ "convert-tile", convert_tile },
{ NULL, NULL }
};

View file

@ -21,7 +21,8 @@ typedef enum {
typedef struct _cammy_image {
cammy_image_format format;
size_t width,
size_t size,
width,
height;
union {
@ -30,12 +31,20 @@ typedef struct _cammy_image {
};
} cammy_image;
cammy_image *cammy_image_new(cammy_image_format format,
size_t width,
size_t height);
cammy_image *cammy_image_open_tile(const char *filename,
size_t width,
size_t height);
int cammy_image_save_tile(cammy_image *image, const char *filename);
void cammy_image_close(cammy_image *image);
void cammy_image_destroy(cammy_image *image);
int cammy_image_save(cammy_image *image, const char *filename);
void cammy_image_dither(uint8_t *dest,

View file

@ -8,6 +8,9 @@
#define CAMMY_PHOTO_TILES_WIDTH 16
#define CAMMY_PHOTO_TILES_HEIGHT 14
#define CAMMY_PHOTO_SIZE \
(CAMMY_TILE_SIZE * CAMMY_PHOTO_TILES_WIDTH * CAMMY_PHOTO_TILES_HEIGHT)
#define CAMMY_PHOTO_WIDTH \
(CAMMY_TILE_WIDTH * CAMMY_PHOTO_TILES_WIDTH)

View file

@ -2,6 +2,7 @@
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <cammy/image.h>
@ -140,28 +141,81 @@ static inline void buf_write(uint8_t *buf,
buf[depth*stride*y + depth*x + 2] = b;
}
cammy_image *cammy_image_open_tile(const char *filename,
cammy_image *cammy_image_new(cammy_image_format format,
size_t width,
size_t height) {
cammy_image *image;
int fd;
size_t size;
size_t size = (width * height) >> 2,
off;
switch (format) {
case CAMMY_IMAGE_TILE: {
size_t tiles_width = width >> 3,
tiles_height = height >> 3;
if ((fd = open(filename, O_RDONLY)) < 0) {
goto error_open;
if (width & 7) tiles_width++;
if (height & 7) tiles_height++;
size = CAMMY_TILE_SIZE * tiles_width * tiles_height;
break;
}
case CAMMY_IMAGE_RGB: {
size = 3 * width * height;
break;
}
case CAMMY_IMAGE_RGBA: {
size = 4 * width * height;
break;
}
default: {
errno = EINVAL;
goto error_invalid_format;
}
}
if ((image = malloc(sizeof(*image))) == NULL) {
goto error_malloc_image;
}
if ((image->tiles = malloc(size)) == NULL) {
goto error_malloc_tiles;
if ((image->buf = malloc(size)) == NULL) {
goto error_malloc_buf;
}
for (off=0; off<size;) {
image->format = format;
image->size = size;
image->width = width;
image->height = height;
return image;
error_malloc_buf:
free(image);
error_malloc_image:
error_invalid_format:
return NULL;
}
cammy_image *cammy_image_open_tile(const char *filename,
size_t width,
size_t height) {
cammy_image *image;
int fd;
size_t off;
if ((fd = open(filename, O_RDONLY)) < 0) {
goto error_open;
}
if ((image = cammy_image_new(CAMMY_IMAGE_TILE, width, height)) == NULL) {
goto error_image_new;
}
for (off=0; off<image->size;) {
ssize_t len;
if ((len = read(fd, &image->buf[off], CAMMY_IMAGE_CHUNK_SIZE)) < 0) {
@ -173,19 +227,12 @@ cammy_image *cammy_image_open_tile(const char *filename,
close(fd);
image->format = CAMMY_IMAGE_TILE;
image->width = width;
image->height = height;
return image;
error_read:
free(image->tiles);
cammy_image_destroy(image);
error_malloc_tiles:
free(image);
error_malloc_image:
error_image_new:
close(fd);
error_open:
@ -193,10 +240,48 @@ error_open:
}
void cammy_image_close(cammy_image *image) {
free(image);
}
void cammy_image_destroy(cammy_image *image) {
free(image->buf);
free(image);
}
int cammy_image_save_tile(cammy_image *image, const char *filename) {
size_t off,
rest = image->size;
int fd;
if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) {
goto error_open;
}
for (off=0; off<image->size; off+=CAMMY_IMAGE_CHUNK_SIZE) {
size_t chunk = rest > CAMMY_IMAGE_CHUNK_SIZE?
CAMMY_IMAGE_CHUNK_SIZE: rest;
ssize_t len;
if ((len = write(fd, image->buf + off, chunk)) < 0) {
goto error_write;
}
rest -= len;
}
close(fd);
return 0;
error_write:
close(fd);
error_open:
return -1;
}
void cammy_image_dither(uint8_t *dest,
uint8_t *src,
size_t width,