1 /* blorb.c Babel interface to blorb files
\r
2 * Copyright 2006 by L. Ross Raszewski
\r
4 * This code is freely usable for all purposes.
\r
6 * This work is licensed under the Creative Commons Attribution2.5 License.
\r
7 * To view a copy of this license, visit
\r
8 * http://creativecommons.org/licenses/by/2.5/ or send a letter to
\r
10 * 543 Howard Street, 5th Floor,
\r
11 * San Francisco, California, 94105, USA.
\r
13 * This file depends upon treaty_builder.h, misc.c and ifiction.c
\r
15 * Header note: to add support for new executable chunk types, see
\r
18 * This file defines a Treaty of Babel compatable module for handling blorb
\r
19 * files. However, blorb files are not themselves a babel format. This module
\r
20 * is used internally by the babel program to handle blorbs.
\r
22 * As a result, if GET_STORY_FILE_IFID_SEL returns NO_REPLY_RV,
\r
23 * you should check the story file against the babel registry before resorting
\r
24 * to the default IFID calculation.
\r
27 #define FORMAT blorb
\r
28 #define HOME_PAGE "http://eblong.com/zarf/blorb"
\r
29 #define FORMAT_EXT ".blorb,.blb,.zblorb,.zlb,.gblorb,.glb"
\r
30 #define CONTAINER_FORMAT
\r
31 #include "treaty_builder.h"
\r
35 extern TREATY treaty_registry[];
\r
36 /* The following is the translation table of Blorb chunk types to
\r
37 babel formats. it is NULL-terminated. */
\r
38 static char *TranslateExec[] = { "ZCOD", "zcode",
\r
44 void *my_malloc(int32, char *);
\r
45 int32 ifiction_get_IFID(char *, char *, int32);
\r
47 static int32 read_int(void *inp)
\r
49 unsigned char *mem=(unsigned char *)inp;
\r
54 return i1 | (i2<<8) | (i3<<16) | (i4<<24);
\r
58 static int32 blorb_get_chunk(void *blorb_file, int32 extent, char *id, int32 *begin, int32 *output_extent)
\r
63 if (memcmp(((char *)blorb_file)+i,id,4)==0)
\r
65 *output_extent=read_int((char *)blorb_file+i+4);
\r
66 if (*output_extent > extent) return NO_REPLY_RV;
\r
71 j=read_int((char *)blorb_file+i+4);
\r
78 static int32 blorb_get_resource(void *blorb_file, int32 extent, char *rid, int32 number, int32 *begin, int32 *output_extent)
\r
83 if (blorb_get_chunk(blorb_file, extent,"RIdx",&i,&ridx_len)==NO_REPLY_RV)
\r
86 ridx=(char *)blorb_file+i+4;
\r
87 ridx_len=read_int((char *)blorb_file+i);
\r
88 for(i=0;i<ridx_len;i++)
\r
90 if(memcmp((char *)ridx+(i*12),rid,4)==0 && read_int((char *)ridx+(i*12)+4)==number)
\r
93 i=read_int((char *)ridx+(j*12)+8);
\r
95 *output_extent=read_int((char *)blorb_file+i+4);
\r
101 static int32 blorb_get_story_file(void *blorb_file, int32 extent, int32 *begin, int32 *output_extent)
\r
103 return blorb_get_resource(blorb_file, extent, "Exec", 0, begin, output_extent);
\r
107 static int32 get_story_extent(void *blorb_file, int32 extent)
\r
110 if (blorb_get_resource(blorb_file, extent, "Exec", 0, &i, &j))
\r
114 return NO_REPLY_RV;
\r
117 static int32 get_story_file(void *blorb_file, int32 extent, void *output, int32 output_extent)
\r
120 if (blorb_get_resource(blorb_file, extent, "Exec", 0, &i, &j))
\r
122 ASSERT_OUTPUT_SIZE(j);
\r
123 memcpy(output,(char *)blorb_file+i,j);
\r
126 return NO_REPLY_RV;
\r
130 char *blorb_chunk_for_name(char *name)
\r
132 static char buffer[5];
\r
134 for(j=0;TranslateExec[j];j+=2)
\r
135 if (strcmp(name,TranslateExec[j+1])==0) return TranslateExec[j];
\r
136 for(j=0;j<4 && name[j];j++) buffer[j]=toupper(buffer[j]);
\r
137 while(j<4) buffer[j++]=' ';
\r
142 static char *blorb_get_story_format(void *blorb_file, int32 extent)
\r
146 for(j=0;treaty_registry[j];j++)
\r
148 static char fn[512];
\r
149 treaty_registry[j](GET_FORMAT_NAME_SEL,NULL,0,fn,512);
\r
150 if (blorb_get_chunk(blorb_file,extent,blorb_chunk_for_name(fn),&i, &i)) return fn;
\r
155 static int32 get_story_format(void *blorb_file, int32 extent, char *output, int32 output_extent)
\r
158 o=blorb_get_story_format(blorb_file, extent);
\r
159 if (!o) return NO_REPLY_RV;
\r
160 ASSERT_OUTPUT_SIZE((signed) strlen(o)+1);
\r
162 return strlen(o)+1;
\r
164 static int32 get_story_file_metadata_extent(void *blorb_file, int32 extent)
\r
167 if (blorb_get_chunk(blorb_file,extent,"IFmd",&i,&j)) return j+1;
\r
168 return NO_REPLY_RV;
\r
170 static int32 blorb_get_cover(void *blorb_file, int32 extent, int32 *begin, int32 *output_extent)
\r
173 if (blorb_get_chunk(blorb_file,extent,"Fspc",&i,&j))
\r
175 if (j<4) return NO_REPLY_RV;
\r
176 i=read_int((char *)blorb_file+i);
\r
177 if (!blorb_get_resource(blorb_file,extent,"Pict",i,&i,&j)) return NO_REPLY_RV;
\r
180 if (memcmp((char *)blorb_file+i-8,"PNG ",4)==0) return PNG_COVER_FORMAT;
\r
181 else if (memcmp((char *)blorb_file+i-8,"JPEG",4)==0) return JPEG_COVER_FORMAT;
\r
183 return NO_REPLY_RV;
\r
187 static int32 get_story_file_cover_extent(void *blorb_file, int32 extent)
\r
190 if (blorb_get_cover(blorb_file,extent,&i,&j)) return j;
\r
191 return NO_REPLY_RV;
\r
194 static int32 get_story_file_cover_format(void *blorb_file, int32 extent)
\r
197 return blorb_get_cover(blorb_file, extent, &i,&j);
\r
200 static int32 get_story_file_IFID(void *b, int32 e, char *output, int32 output_extent)
\r
204 j=get_story_file_metadata_extent(b,e);
\r
205 if (j<=0) return NO_REPLY_RV;
\r
206 md=(char *)my_malloc(j, "Metadata buffer");
\r
207 j=get_story_file_metadata(b,e,md,j);
\r
208 if (j<=0) return NO_REPLY_RV;
\r
210 j=ifiction_get_IFID(md,output,output_extent);
\r
215 static int32 get_story_file_metadata(void *blorb_file, int32 extent, char *output, int32 output_extent)
\r
218 if (!blorb_get_chunk(blorb_file, extent,"IFmd",&i,&j)) return NO_REPLY_RV;
\r
219 ASSERT_OUTPUT_SIZE(j+1);
\r
220 memcpy(output,(char *)blorb_file+i,j);
\r
224 static int32 get_story_file_cover(void *blorb_file, int32 extent, void *output, int32 output_extent)
\r
227 if (!blorb_get_cover(blorb_file, extent,&i,&j)) return NO_REPLY_RV;
\r
228 ASSERT_OUTPUT_SIZE(j);
\r
229 memcpy(output,(char *)blorb_file+i,j);
\r
233 static int32 claim_story_file(void *story_file, int32 extent)
\r
238 memcmp(story_file,"FORM",4) ||
\r
239 memcmp((char *)story_file+8,"IFRS",4)
\r
240 ) i= INVALID_STORY_FILE_RV;
\r
241 else i= NO_REPLY_RV;
\r