From: David Griffith Date: Mon, 27 Feb 2017 04:59:44 +0000 (-0800) Subject: Added preliminary support for Blorb loading for Dumb interface. X-Git-Url: https://scope-eye.net/git/?a=commitdiff_plain;h=3140e076eef1fb3ddbf348ee11199c9f3bd9104d;p=liskon_frotz.git Added preliminary support for Blorb loading for Dumb interface. In the interest of keeping the dumb interface as simple as possible, I want to make sure that Blorb support is optional. --- diff --git a/Makefile b/Makefile index f374df6..afa2fee 100644 --- a/Makefile +++ b/Makefile @@ -143,7 +143,8 @@ DUMB_TARGET = $(SRCDIR)/frotz_dumb.a DUMB_OBJECT = $(DUMB_DIR)/dumb_init.o \ $(DUMB_DIR)/dumb_input.o \ $(DUMB_DIR)/dumb_output.o \ - $(DUMB_DIR)/dumb_pic.o + $(DUMB_DIR)/dumb_pic.o \ + $(DUMB_DIR)/dumb_blorb.o BLORB_DIR = $(SRCDIR)/blorb BLORB_TARGET = $(SRCDIR)/blorblib.a @@ -174,8 +175,8 @@ else endif dumb: d$(NAME) -d$(NAME): hash $(COMMON_DIR)/defines.h $(COMMON_TARGET) $(DUMB_TARGET) - $(CC) -o d$(BINNAME)$(EXTENSION) $(COMMON_TARGET) $(DUMB_TARGET) $(LIB) +d$(NAME): hash $(COMMON_DIR)/defines.h $(COMMON_TARGET) $(DUMB_TARGET) $(BLORB_TARGET) + $(CC) -o d$(BINNAME)$(EXTENSION) $(COMMON_TARGET) $(DUMB_TARGET) $(BLORB_TARGET) $(LIB) all: $(NAME) d$(NAME) diff --git a/src/dumb/dumb_blorb.c b/src/dumb/dumb_blorb.c new file mode 100644 index 0000000..6f058cf --- /dev/null +++ b/src/dumb/dumb_blorb.c @@ -0,0 +1,176 @@ +/* + * dumb_blorb.c - Blorb routines + * + * This file is part of Frotz. + * + * Frotz is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Frotz is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Or visit http://www.fsf.org/ + */ + +#include +#include +#include + +#include +#include +#include + +#include "dumb_frotz.h" +#include "dumb_blorb.h" + +f_setup_t f_setup; + +FILE *blorb_fp; +bb_result_t blorb_res; +bb_map_t *blorb_map; + +static int isblorb(FILE *); + +#define UnsignedToFloat(u) (((double)((long)(u - 2147483647L - 1))) + 2147483648.0) + + +/* + * dumb_blorb_init + * + * Check if we're opening a Blorb file directly. If not, check + * to see if there's a seperate Blorb file that looks like it goes + * along with this Zcode file. If we have a Blorb file one way or the + * other, make a Blorb map. If we opened a Blorb file directly, that + * means that our executable is in that file and therefore we will look + * for a ZCOD chunk and record its location so os_load_story() can find it. + * Make sure the Blorb file is opened and with the file pointer blorb_fp. + */ +bb_err_t dumb_blorb_init(char *filename) +{ + FILE *fp; + char *p; + char *mystring; + int len1; + int len2; + + bb_err_t blorb_err; + + blorb_map = NULL; + + if ((fp = fopen(filename, "rb")) == NULL) + return bb_err_Read; + + /* Is this really a Blorb file? If not, maybe we're loading a naked + * zcode file and our resources are in a seperate blorb file. + */ + if (isblorb(fp)) { /* Now we know to look */ + f_setup.exec_in_blorb = 1; /* for zcode in the blorb */ + blorb_fp = fopen(filename, "rb"); + } 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 = rindex(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 ((blorb_fp = fopen(mystring, "rb")) == NULL) { + p = rindex(mystring, '.'); + if (p != NULL) + *p = '\0'; + strncat(mystring, EXT_BLORB3, len2 * sizeof(char)); + blorb_fp = fopen(mystring, "rb"); + } + + if (blorb_fp == NULL || !isblorb(fp)) /* No matching blorbs found. */ + return bb_err_NoBlorb; + + /* At this point we know that we're using a naked zcode file */ + /* with resources in a seperate Blorb file. */ + f_setup.use_blorb = 1; + } + + /* Create a Blorb map from this file. + * 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); + if (blorb_err != bb_err_None) + return bb_err_Format; + + /* Locate the EXEC chunk within the blorb file and record its + * location so os_load_story() can find it. + */ + if (f_setup.exec_in_blorb) { + blorb_err = bb_load_chunk_by_type(blorb_map, bb_method_FilePos, + &blorb_res, bb_make_id('Z','C','O','D'), 0); + 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) +{ + char mybuf[4]; + + if (fp == NULL) + return 0; + + fread(mybuf, 1, 4, fp); + if (strncmp(mybuf, "FORM", 4)) + return 0; + + fseek(fp, 4, SEEK_CUR); + fread(mybuf, 1, 4, fp); + + if (strncmp(mybuf, "IFRS", 4)) + return 0; + + return 1; +} diff --git a/src/dumb/dumb_blorb.h b/src/dumb/dumb_blorb.h new file mode 100644 index 0000000..0c52c55 --- /dev/null +++ b/src/dumb/dumb_blorb.h @@ -0,0 +1,34 @@ + +#include "../blorb/blorb.h" +#include "../blorb/blorblow.h" + + +typedef struct sampledata_struct { + unsigned short channels; + unsigned long samples; + unsigned short bits; + double rate; +} sampledata_t; + + +/* + * The bb_result_t struct lacks a few members that would make things a + * bit easier. The myresource struct takes encapsulates the bb_result_t + * struct and adds a type member and a filepointer. I would like to + * convince Andrew Plotkin to make a change in the reference Blorb code + * to add these members. + * + */ +typedef struct { + bb_result_t bbres; + ulong type; + FILE *fp; +} myresource; + +extern bb_err_t blorb_err; +extern bb_map_t *blorb_map; +extern bb_result_t blorb_res; +extern FILE *blorb_fp; + +bb_err_t dumb_blorb_init(char *); +void dumb_blorb_stop(void); diff --git a/src/dumb/dumb_init.c b/src/dumb/dumb_init.c index 76c7484..8b2cc7b 100644 --- a/src/dumb/dumb_init.c +++ b/src/dumb/dumb_init.c @@ -19,7 +19,9 @@ * Or visit http://www.fsf.org/ */ +#include #include "dumb_frotz.h" +#include "dumb_blorb.h" f_setup_t f_setup; @@ -208,7 +210,30 @@ void os_fatal (const char *s, ...) FILE *os_load_story(void) { - return fopen(f_setup.story_file, "rb"); + FILE *fp; + + switch (dumb_blorb_init(f_setup.story_file)) { + case bb_err_NoBlorb: +// printf("No blorb file found.\n\n"); + break; + case bb_err_Format: + printf("Blorb file loaded, but unable to build map.\n\n"); + break; + case bb_err_NotFound: + printf("Blorb file loaded, but lacks executable chunk.\n\n"); + break; + case bb_err_None: +// printf("No blorb errors.\n\n"); + break; + } + + fp = fopen(f_setup.story_file, "rb"); + + /* Is this a Blorb file containing Zcode? */ + if (f_setup.exec_in_blorb) + fseek(fp, blorb_res.data.startpos, SEEK_SET); + + return fp; } /*