#include #include #include #include #include #include #include #include #include #include #include #include #include #include "pnglite.h" #include "png.h" #include "commands.h" static cammy_tile_palette palette = { .colors = { { 0, 0, 0 }, { 85, 85, 85 }, { 171, 171, 171 }, { 255, 255, 255 } } }; static void import_usage(int argc, char **argv, const char *message, ...) { if (message) { va_list args; va_start(args, message); vfprintf(stderr, message, args); va_end(args); fprintf(stderr, "\n"); } fprintf(stderr, "usage: %1$s tile-import file.sav 1..30 printer.tile\n" " %1$s tile-export file.sav 1..30 output.tile\n" " %1$s tile-convert printer.tile output.png\n", argv[0]); exit(1); } int cammy_tile_import(int argc, char **argv) { cammy_sram *sram; cammy_image dest, *src; int photo; cammy_image_point to = { 0, 0 }; cammy_image_region from = { 16, 16, CAMMY_PHOTO_WIDTH, CAMMY_PHOTO_HEIGHT }; if (argc < 2) { import_usage(argc, argv, "No camera SRAM file provided"); } else if (argc < 3) { import_usage(argc, argv, "No picture number provided"); } else if (argc < 4) { import_usage(argc, argv, "No Game Boy screen tile data file provided"); } photo = atoi(argv[3]); if (photo < 1 || photo > CAMMY_SRAM_PHOTO_COUNT) { import_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 = cammy_image_open_tile(argv[4], CAMMY_SCREEN_WIDTH, CAMMY_SCREEN_HEIGHT)) == NULL) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "cammy_image_open_tile()", argv[4], strerror(errno)); goto error_image_open_tile; } dest.format = CAMMY_IMAGE_2BPP_TILE; dest.tiles = (cammy_tile *)&sram->data->photos[photo-1].tiles; dest.width = CAMMY_PHOTO_WIDTH; dest.height = CAMMY_PHOTO_HEIGHT; cammy_image_copy(&dest, src, &to, &from); cammy_image_close(src); cammy_sram_close(sram); return 0; error_image_open_tile: cammy_sram_close(sram); error_sram_open: return 1; } static void export_usage(int argc, char **argv, const char *message, ...) { if (message) { va_list args; va_start(args, message); vfprintf(stderr, message, args); va_end(args); fprintf(stderr, "\n"); } fprintf(stderr, "usage: %1$s tile-import file.sav 1..30 printer.tile\n" " %1$s tile-export file.sav 1..30 output.tile\n" " %1$s tile-convert printer.tile output.png\n", argv[0]); exit(1); } int cammy_tile_export(int argc, char **argv) { cammy_sram *sram; cammy_image *dest, src; int photo; cammy_image_point to = { 16, 16 }; cammy_image_region from = { 0, 0, CAMMY_PHOTO_WIDTH, CAMMY_PHOTO_HEIGHT }; if (argc < 2) { export_usage(argc, argv, "No camera SRAM file provided"); } else if (argc < 3) { export_usage(argc, argv, "No picture number provided"); } else if (argc < 4) { export_usage(argc, argv, "No Game Boy screen tile data file provided"); } photo = atoi(argv[3]); if (photo < 1 || photo > CAMMY_SRAM_PHOTO_COUNT) { export_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; } src.format = CAMMY_IMAGE_2BPP_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_2BPP_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, &to, &from); 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; } cammy_image_close(dest); cammy_sram_close(sram); return 0; error_image_save_tile_dest: cammy_image_destroy(dest); error_image_new_dest: cammy_sram_close(sram); error_sram_open: return errno || 1; } static void convert_usage(int argc, char **argv, const char *message, ...) { if (message) { va_list args; va_start(args, message); vfprintf(stderr, message, args); va_end(args); fprintf(stderr, "\n"); } fprintf(stderr, "usage: %1$s tile-convert printer.tile output.png\n", argv[0]); exit(1); } int cammy_tile_convert(int argc, char **argv) { int fd; void *in, *out; if (argc < 3) { convert_usage(argc, argv, "No input Game Boy screen tile data file provided"); } else if (argc < 4) { convert_usage(argc, argv, "No output PNG filename provided"); } if ((fd = open(argv[2], O_RDONLY)) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "open()", argv[2], strerror(errno)); goto error_open; } if ((in = malloc(CAMMY_SCREEN_SIZE)) == NULL) { fprintf(stderr, "%s: %s: %s\n", argv[0], "malloc()", strerror(errno)); goto error_malloc_in; } if (read(fd, in, CAMMY_SCREEN_SIZE) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "read()", argv[2], strerror(errno)); goto error_read; } if ((out = malloc(CAMMY_SCREEN_WIDTH * CAMMY_SCREEN_HEIGHT * 3)) == NULL) { fprintf(stderr, "%s: %s: %s\n", argv[0], "malloc()", strerror(errno)); goto error_malloc_out; } cammy_image_copy_from_tile(out, in, CAMMY_SCREEN_WIDTH, CAMMY_SCREEN_HEIGHT, 3, &palette); if (cammy_png_save(argv[3], out, CAMMY_SCREEN_WIDTH, CAMMY_SCREEN_HEIGHT, 8, PNG_TRUECOLOR) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "cammy_png_save()", argv[3], strerror(errno)); goto error_png_save; } return 0; error_png_save: free(out); error_malloc_out: error_read: free(in); error_malloc_in: close(fd); error_open: return errno; }