287 lines
7 KiB
C
287 lines
7 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
|
|
#include <cammy/image.h>
|
|
#include <cammy/screen.h>
|
|
#include <cammy/photo.h>
|
|
#include <cammy/sram.h>
|
|
|
|
#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;
|
|
}
|