From 8163ad0fe794278ed85b1852063778ad665ca78d Mon Sep 17 00:00:00 2001 From: David Griffith Date: Sun, 21 Jul 2019 16:28:27 -0700 Subject: [PATCH] Added Blorbified V6 semi-support to dumb interface. --- src/dumb/dumb_blorb.c | 74 ++++++------------- src/dumb/dumb_frotz.h | 2 +- src/dumb/dumb_init.c | 7 +- src/dumb/dumb_pic.c | 164 +++++++++++++++++++++++++++--------------- 4 files changed, 134 insertions(+), 113 deletions(-) diff --git a/src/dumb/dumb_blorb.c b/src/dumb/dumb_blorb.c index 4227c9c..267a4f0 100644 --- a/src/dumb/dumb_blorb.c +++ b/src/dumb/dumb_blorb.c @@ -39,7 +39,7 @@ f_setup_t f_setup; 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 *); @@ -67,8 +67,6 @@ bb_err_t dumb_blorb_init(char *filename) bb_err_t blorb_err; - bb_map_t *blorb_map = NULL; - if ((fp = fopen(filename, "rb")) == NULL) return bb_err_Read; @@ -77,41 +75,37 @@ bb_err_t dumb_blorb_init(char *filename) */ 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; } @@ -119,7 +113,7 @@ bb_err_t dumb_blorb_init(char *filename) * 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; @@ -132,37 +126,15 @@ bb_err_t dumb_blorb_init(char *filename) 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) { diff --git a/src/dumb/dumb_frotz.h b/src/dumb/dumb_frotz.h index 4da1d80..27cd681 100644 --- a/src/dumb/dumb_frotz.h +++ b/src/dumb/dumb_frotz.h @@ -41,4 +41,4 @@ void dumb_elide_more_prompt(void); void dumb_set_picture_cell(int row, int col, zchar c); /* dumb-pic.c */ -void dumb_init_pictures(char *graphics_filename); +bool dumb_init_pictures(void); diff --git a/src/dumb/dumb_init.c b/src/dumb/dumb_init.c index 08e32a0..8628969 100644 --- a/src/dumb/dumb_init.c +++ b/src/dumb/dumb_init.c @@ -88,7 +88,6 @@ static int user_screen_width = 75; static int user_screen_height = 24; static int user_random_seed = -1; static int user_tandy_bit = 0; -static char *graphics_filename = NULL; static bool plain_ascii = FALSE; /* @@ -208,7 +207,7 @@ void os_init_screen(void) dumb_init_input(); dumb_init_output(); - dumb_init_pictures(graphics_filename); + dumb_init_pictures(); } int os_random_seed (void) @@ -238,7 +237,7 @@ FILE *os_load_story(void) #ifndef NO_BLORB switch (dumb_blorb_init(f_setup.story_file)) { case bb_err_NoBlorb: -// printf("No blorb file found.\n\n"); +/* printf("No blorb file found.\n\n"); */ break; case bb_err_Format: printf("Blorb file loaded, but unable to build map.\n\n"); @@ -247,7 +246,7 @@ FILE *os_load_story(void) printf("Blorb file loaded, but lacks executable chunk.\n\n"); break; case bb_err_None: -// printf("No blorb errors.\n\n"); +/* printf("No blorb errors.\n\n"); */ break; } diff --git a/src/dumb/dumb_pic.c b/src/dumb/dumb_pic.c index ee14077..55c7dec 100644 --- a/src/dumb/dumb_pic.c +++ b/src/dumb/dumb_pic.c @@ -20,6 +20,7 @@ */ #include "dumb_frotz.h" +#include "dumb_blorb.h" f_setup_t f_setup; @@ -32,79 +33,128 @@ 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) { -- 2.34.1