FILE *blorb_fp;
bb_result_t blorb_res;
-/* bb_map_t *blorb_map; */ /* Used only locally */
+bb_map_t *blorb_map;
static int isblorb(FILE *);
bb_err_t blorb_err;
- bb_map_t *blorb_map = NULL;
-
if ((fp = fopen(filename, "rb")) == NULL)
return bb_err_Read;
*/
if (isblorb(fp)) { /* Now we know to look */
f_setup.exec_in_blorb = 1; /* for zcode in the blorb */
- blorb_fp = fopen(filename, "rb");
+ blorb_fp = fp;
} else {
- len1 = strlen(filename) + strlen(EXT_BLORB);
- len2 = strlen(filename) + strlen(EXT_BLORB3);
-
- mystring = malloc(len2 * sizeof(char) + 1);
- strncpy(mystring, filename, len1 * sizeof(char));
- p = strrchr(mystring, '.');
- if (p != NULL)
- *p = '\0';
-
- strncat(mystring, EXT_BLORB, len1 * sizeof(char));
-
- /* Done monkeying with the initial file. */
fclose(fp);
- fp = NULL;
-
- /* Check if foo.blb is there. */
if (f_setup.blorb_file != NULL)
mystring = strdup(f_setup.blorb_file);
else {
- if ((blorb_fp = fopen(mystring, "rb")) == NULL) {
- p = strrchr(mystring, '.');
- if (p != NULL)
- *p = '\0';
- strncat(mystring, EXT_BLORB3, len2 * sizeof(char));
- blorb_fp = fopen(mystring, "rb");
- }
+ len1 = strlen(filename) + strlen(EXT_BLORB);
+ len2 = strlen(filename) + strlen(EXT_BLORB3);
+ mystring = malloc(len2 * sizeof(char) + 1);
+ strncpy(mystring, filename, len1 * sizeof(char));
+ p = strrchr(mystring, '.');
+ if (p != NULL) *p = '\0';
+ strncat(mystring, EXT_BLORB, len1 * sizeof(char));
}
- if (blorb_fp == NULL || !isblorb(fp)) /* No matching blorbs found. */
- return bb_err_NoBlorb;
+ /* Check if foo.blb is there. */
+ if ((fp = fopen(mystring, "rb")) == NULL) {
+ p = strrchr(mystring, '.');
+ if (p != NULL) *p = '\0';
+ strncat(mystring, EXT_BLORB3, len2 * sizeof(char));
+ if (!(fp = fopen(mystring, "rb")))
+ return bb_err_NoBlorb;
+ }
+ if (!isblorb(fp)) {
+ fclose(fp);
+ return bb_err_NoBlorb;
+ }
/* At this point we know that we're using a naked zcode file */
/* with resources in a separate Blorb file. */
+ blorb_fp = fp;
f_setup.use_blorb = 1;
}
* This will fail if the file is not a valid Blorb file.
* From this map, we can now pick out any resource we need.
*/
- blorb_err = bb_create_map(fp, &blorb_map);
+ blorb_err = bb_create_map(blorb_fp, &blorb_map);
if (blorb_err != bb_err_None)
return bb_err_Format;
f_setup.exec_in_blorb = 1;
}
- fclose(fp);
return blorb_err;
}
-/*
- * ux_blorb_stop
- *
- * Basically just close the Blorb file.
- *
- */
-void ux_blorb_stop(void)
-{
- if (blorb_fp != NULL)
- fclose(blorb_fp);
- blorb_fp = NULL;
-}
-
-/*
- **********************************************
- * These functions are internal to ux_blorb.c
- *
- **********************************************
- */
-
/*
* isblorb
*
* Returns 1 if this file is a Blorb file, 0 if not.
*
- * FIXME Is there a potential endian problem here?
*/
static int isblorb(FILE *fp)
{
*/
#include "dumb_frotz.h"
+#include "dumb_blorb.h"
f_setup_t f_setup;
#define PIC_HEADER_WIDTH 2
#define PIC_HEADER_HEIGHT 4
+bb_map_t *blorb_map;
+
static struct {
int z_num;
int width;
int height;
int orig_width;
int orig_height;
+ uint32 type;
} *pict_info;
static int num_pictures = 0;
-static unsigned char lookupb(unsigned char *p, int n) {return p[n];}
-static unsigned short lookupw(unsigned char *p, int n)
+
+static int round_div(int x, int y)
{
- return (p[n + 1] << 8) | p[n];
+ int quotient = x / y;
+ int dblremain = (x % y) << 1;
+
+ if ((dblremain > y) || ((dblremain == y) && (quotient & 1)))
+ quotient++;
+ return quotient;
}
-void dumb_init_pictures (char *filename)
+
+bool dumb_init_pictures (void)
{
- FILE *file = NULL;
- int success = FALSE;
- unsigned char gheader[16];
- unsigned char *raw_info = NULL;
- int i, entry_size, flags;
- float x_scaler, y_scaler;
-
- do {
- if ((h_version != V6)
- || !filename
- || ((file = fopen (filename, "rb")) == NULL)
- || (fread(&gheader, sizeof (gheader), 1, file) != 1))
- break;
-
- num_pictures = lookupw(gheader, PIC_FILE_HEADER_NUM_IMAGES);
- entry_size = lookupb(gheader, PIC_FILE_HEADER_ENTRY_SIZE);
- flags = lookupb(gheader, PIC_FILE_HEADER_FLAGS);
-
- raw_info = malloc(num_pictures * entry_size);
-
- if (fread(raw_info, num_pictures * entry_size, 1, file) != 1)
- break;
-
- pict_info = malloc((num_pictures + 1) * sizeof(*pict_info));
- pict_info[0].z_num = 0;
- pict_info[0].height = num_pictures;
- pict_info[0].width = lookupw(gheader, PIC_FILE_HEADER_VERSION);
-
- y_scaler = h_screen_rows / 200.0;
- x_scaler = h_screen_cols / ((flags & 0x08) ? 640.0 : 320.0);
-
- /* Copy and scale. */
- for (i = 1; i <= num_pictures; i++) {
- unsigned char *p = raw_info + entry_size * (i - 1);
- pict_info[i].z_num = lookupw(p, PIC_HEADER_NUMBER);
- pict_info[i].orig_height = lookupw(p, PIC_HEADER_HEIGHT);
- pict_info[i].orig_width = lookupw(p, PIC_HEADER_WIDTH);
- pict_info[i].height = pict_info[i].orig_height * y_scaler + .5;
- pict_info[i].width = pict_info[i].orig_width * x_scaler + .5;
- }
+ int maxlegalpic = 0;
+ int i, x_scale, y_scale;
+ bool success = FALSE;
+
+ unsigned char png_magic[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
+ unsigned char ihdr_name[] = "IHDR";
+ unsigned char jpg_magic[3] = {0xFF, 0xD8, 0xFF};
+ unsigned char jfif_name[5] = {'J', 'F', 'I', 'F', 0x00};
+
+ bb_result_t res;
+ uint32 pos;
+
+ if (blorb_map == NULL) return FALSE;
+
+ bb_count_resources(blorb_map, bb_ID_Pict, &num_pictures, NULL, &maxlegalpic);
+ pict_info = malloc((num_pictures + 1) * sizeof(*pict_info));
+ pict_info[0].z_num = 0;
+ pict_info[0].height = num_pictures;
+ pict_info[0].width = bb_get_release_num(blorb_map);
+
+ y_scale = 200;
+ x_scale = 320;
+
+ for (i = 1; i <= num_pictures; i++) {
+ if (bb_load_resource(blorb_map, bb_method_Memory, &res, bb_ID_Pict, i) == bb_err_None) {
+ pict_info[i].type = blorb_map->chunks[res.chunknum].type;
+ /* Copy and scale. */
+ pict_info[i].z_num = i;
+ /* Check to see if we're dealing with a PNG file. */
+ if (pict_info[i].type == bb_ID_PNG) {
+ if (memcmp(res.data.ptr, png_magic, 8) == 0) {
+ /* Check for IHDR chunk. If it's not there, PNG file is invalid. */
+ if (memcmp(res.data.ptr+12, ihdr_name, 4) == 0) {
+ pict_info[i].orig_width =
+ (*((unsigned char *)res.data.ptr+16) << 24) +
+ (*((unsigned char *)res.data.ptr+17) << 16) +
+ (*((unsigned char *)res.data.ptr+18) << 8) +
+ (*((unsigned char *)res.data.ptr+19) << 0);
+ pict_info[i].orig_height =
+ (*((unsigned char *)res.data.ptr+20) << 24) +
+ (*((unsigned char *)res.data.ptr+21) << 16) +
+ (*((unsigned char *)res.data.ptr+22) << 8) +
+ (*((unsigned char *)res.data.ptr+23) << 0);
+ }
+ }
+ } else if (pict_info[i].type == bb_ID_Rect) {
+ pict_info[i].orig_width =
+ (*((unsigned char *)res.data.ptr+0) << 24) +
+ (*((unsigned char *)res.data.ptr+1) << 16) +
+ (*((unsigned char *)res.data.ptr+2) << 8) +
+ (*((unsigned char *)res.data.ptr+3) << 0);
+ pict_info[i].orig_height =
+ (*((unsigned char *)res.data.ptr+4) << 24) +
+ (*((unsigned char *)res.data.ptr+5) << 16) +
+ (*((unsigned char *)res.data.ptr+6) << 8) +
+ (*((unsigned char *)res.data.ptr+7) << 0);
+ } else if (pict_info[i].type == bb_ID_JPEG) {
+ if (memcmp(res.data.ptr, jpg_magic, 3) == 0) { /* Is it JPEG? */
+ if (memcmp(res.data.ptr+6, jfif_name, 5) == 0) { /* Look for JFIF */
+ pos = 11;
+ while (pos < res.length) {
+ pos++;
+ if (pos >= res.length) break; /* Avoid segfault */
+ if (*((unsigned char *)res.data.ptr+pos) != 0xFF) continue;
+ if (*((unsigned char *)res.data.ptr+pos+1) != 0xC0) continue;
+ pict_info[i].orig_width =
+ (*((unsigned char *)res.data.ptr+pos+7)*256) +
+ *((unsigned char *)res.data.ptr+pos+8);
+ pict_info[i].orig_height =
+ (*((unsigned char *)res.data.ptr+pos+5)*256) +
+ *((unsigned char *)res.data.ptr+pos+6);
+ } /* while */
+ } /* JFIF */
+ } /* JPEG */
+ }
+ } /* for */
+
+ pict_info[i].height = round_div(pict_info[i].orig_height * h_screen_rows, y_scale);
+ pict_info[i].width = round_div(pict_info[i].orig_width * h_screen_cols, x_scale);
+
+ /* Don't let dimensions get rounded to nothing. */
+ if (pict_info[i].orig_height && !pict_info[i].height)
+ pict_info[1].height = 1;
+ if (pict_info[i].orig_width && !pict_info[i].width)
+ pict_info[i].width = 1;
+
success = TRUE;
- } while (0);
-
- if (file)
- fclose(file);
- if (raw_info)
- free(raw_info);
- if (success)
- h_config |= CONFIG_PICTURES;
- else {
- h_flags &= ~GRAPHICS_FLAG;
- if (filename)
- fprintf(stderr, "Warning: could not read graphics file %s\n", filename);
- }
+ } /* for */
+
+ if (success) h_config |= CONFIG_PICTURES;
+ else h_flags &= ~GRAPHICS_FLAG;
+
+ return success;
}
+
/* Convert a Z picture number to an index into pict_info. */
static int z_num_to_index(int n)
{