Merge branch 'master' into gtk3
[projects/chimara/chimara.git] / babel / zcode.c
1 /* zcode.c  Treaty of Babel module for Z-code files\r
2  * 2006 By L. Ross Raszewski\r
3  *\r
4  * This file depends on treaty_builder.h\r
5  *\r
6  * This file is public domain, but note that any changes to this file\r
7  * may render it noncompliant with the Treaty of Babel\r
8  */\r
9 \r
10 #define FORMAT zcode\r
11 #define HOME_PAGE "http://www.inform-fiction.org"\r
12 #define FORMAT_EXT ".z3,.z4,.z5,.z6,.z7,.z8"\r
13 #define NO_METADATA\r
14 #define NO_COVER\r
15 #define CUSTOM_EXTENSION\r
16 #include "treaty_builder.h"\r
17 #include <ctype.h>\r
18 #include <stdio.h>\r
19 \r
20 static int32 get_story_file_IFID(void *story_file, int32 extent, char *output, int32 output_extent)\r
21 {\r
22  int32 i,j;\r
23  char ser[7];\r
24  char buffer[32];\r
25 \r
26 \r
27  if (extent<0x1D) return INVALID_STORY_FILE_RV;\r
28  memcpy(ser, (char *) story_file+0x12, 6);\r
29  ser[6]=0;\r
30  /* Detect vintage story files */\r
31  if (!(ser[0]=='8' || ser[0]=='9' ||\r
32      (ser[0]=='0' && ser[1]>='0' && ser[1]<='5')))\r
33  {\r
34   for(i=0;i<extent;i++) if (memcmp((char *)story_file+i,"UUID://",7)==0) break;\r
35   if (i<extent) /* Found explicit IFID */\r
36   {\r
37    for(j=i+7;j<extent && ((char *)story_file)[j]!='/';j++);\r
38    if (j<extent)\r
39    {\r
40     i+=7;\r
41     ASSERT_OUTPUT_SIZE(j-i);\r
42     memcpy(output,(char *)story_file+i,j-i);\r
43     output[j-i]=0;\r
44     return 1;\r
45    }\r
46   }\r
47  }\r
48  /* Did not find intact IFID.  Build one */\r
49  i=((unsigned char *)story_file)[2] << 8 |((unsigned char *)story_file)[3];\r
50  for(j=0;j<6;j++)\r
51   if (!isalnum(ser[j])) ser[j]='-';\r
52 \r
53  j=((unsigned char *)story_file)[0x1C] << 8 |((unsigned char *)story_file)[0x1D];\r
54 \r
55  if (strcmp(ser,"000000") && isdigit(ser[0]) && ser[0]!='8')\r
56   sprintf(buffer,"ZCODE-%d-%s-%04X",i,ser,j);\r
57  else\r
58   sprintf(buffer,"ZCODE-%d-%s",i,ser);\r
59 \r
60  ASSERT_OUTPUT_SIZE((signed) strlen(buffer)+1);\r
61  strcpy((char *)output,buffer);\r
62  return 1;\r
63 \r
64 }\r
65 \r
66 static int32 read_zint(unsigned char *sf)\r
67 {\r
68  return ((int32)sf[0] << 8) | ((int32) sf[1]);\r
69 \r
70 }\r
71 static int32 claim_story_file(void *story_file, int32 extent)\r
72 {\r
73  unsigned char *sf=(unsigned char *)story_file;\r
74  int32 i,j;\r
75  if (extent<0x3c ||\r
76      sf[0] < 1 ||\r
77      sf[0] > 8\r
78     ) return INVALID_STORY_FILE_RV;\r
79  for(i=4;i<=14;i+=2)\r
80  {\r
81   j=read_zint(sf+i);\r
82   if (j>extent || j < 0x40) return INVALID_STORY_FILE_RV;\r
83  }\r
84 \r
85  return VALID_STORY_FILE_RV;\r
86 }\r
87 static int32 get_story_file_extension(void *sf, int32 extent, char *out, int32 output_extent)\r
88 {\r
89  int v;\r
90  if (!extent) return INVALID_STORY_FILE_RV;\r
91  v= ((char *) sf)[0];\r
92  if (v>9) ASSERT_OUTPUT_SIZE(5);\r
93  else ASSERT_OUTPUT_SIZE(4);\r
94  sprintf(out,".z%d",v);\r
95  return 3+(v>9);\r
96 \r
97 }\r