de855b0ab641b935e46e55e0226a8094bc84e40c
[projects/chimara/chimara.git] / babel / level9.c
1 /* level9.c  Treaty of Babel module for Level 9 files\r
2  * 2006 By L. Ross Raszewski\r
3  *\r
4  * Note that this module will handle both bare Level 9 A-Code and\r
5  * Spectrum .SNA snapshots.  It will not handle compressed .Z80 images.\r
6  *\r
7  * The Level 9 identification algorithm is based in part on the algorithm\r
8  * used by Paul David Doherty's l9cut program.\r
9  *\r
10  * This file depends on treaty_builder.h\r
11  *\r
12  * This file is public domain, but note that any changes to this file\r
13  * may render it noncompliant with the Treaty of Babel\r
14  */\r
15 \r
16 #define FORMAT level9\r
17 #define HOME_PAGE "http://www.if-legends.org/~l9memorial/html/home.html"\r
18 #define FORMAT_EXT ".l9,.sna"\r
19 #define NO_METADATA\r
20 #define NO_COVER\r
21 \r
22 #include "treaty_builder.h"\r
23 #include <ctype.h>\r
24 #include <stdio.h>\r
25 #include <string.h>\r
26 \r
27 struct l9rec {\r
28                 int32 length;\r
29                 unsigned char chk;\r
30                 char *ifid;\r
31 };\r
32 \r
33 \r
34 static struct l9rec l9_registry[] = {\r
35       { 0x3a31, 0xe5, "LEVEL9-001-1" },\r
36       { 0x8333, 0xb7, "LEVEL9-001-1" },\r
37       { 0x7c6f, 0x0f, "LEVEL9-001-1" },\r
38       { 0x72fa, 0x8b, "LEVEL9-001-1" },\r
39       { 0x38dd, 0x31, "LEVEL9-001-A" },\r
40       { 0x39c0, 0x44, "LEVEL9-001-B" },\r
41       { 0x3a12, 0x8f, "LEVEL9-001-C" },\r
42       { 0x37f1, 0x77, "LEVEL9-001-2" },\r
43       { 0x844d, 0x50, "LEVEL9-001-2" },\r
44       { 0x738e, 0x5b, "LEVEL9-001-2" },\r
45       { 0x3900, 0x1c, "LEVEL9-001-3" },\r
46       { 0x8251, 0x5f, "LEVEL9-001-3" },\r
47       { 0x7375, 0xe5, "LEVEL9-001-3" },\r
48       { 0x3910, 0xac, "LEVEL9-001-4" },\r
49       { 0x7a78, 0x5e, "LEVEL9-001-4" },\r
50       { 0x78d5, 0xe3, "LEVEL9-001-4" },\r
51       { 0x3ad6, 0xa7, "LEVEL9-001-5" },\r
52       { 0x38a5, 0x0f, "LEVEL9-001-6" },\r
53       { 0x361e, 0x7e, "LEVEL9-001-7" },\r
54       { 0x3934, 0x75, "LEVEL9-001-8" },\r
55       { 0x3511, 0xcc, "LEVEL9-001-9" },\r
56       { 0x593a, 0xaf, "LEVEL9-002-1" },\r
57       { 0x7931, 0xb9, "LEVEL9-002-1" },\r
58       { 0x6841, 0x4a, "LEVEL9-002-1" },\r
59       { 0x57e6, 0x8a, "LEVEL9-002-2" },\r
60       { 0x7cdf, 0xa5, "LEVEL9-002-2" },\r
61       { 0x6bc0, 0x62, "LEVEL9-002-2" },\r
62       { 0x5819, 0xcd, "LEVEL9-002-3" },\r
63       { 0x7a0c, 0x97, "LEVEL9-002-3" },\r
64       { 0x692c, 0x21, "LEVEL9-002-3" },\r
65       { 0x579b, 0xad, "LEVEL9-002-4" },\r
66       { 0x7883, 0xe2, "LEVEL9-002-4" },\r
67       { 0x670a, 0x94, "LEVEL9-002-4" },\r
68       { 0x5323, 0xb7, "LEVEL9-003" },\r
69       { 0x6e60, 0x83, "LEVEL9-003" },\r
70       { 0x5b58, 0x50, "LEVEL9-003" },\r
71       { 0x63b6, 0x2e, "LEVEL9-003" },\r
72       { 0x6968, 0x32, "LEVEL9-003" },\r
73       { 0x5b50, 0x66, "LEVEL9-003" },\r
74       { 0x6970, 0xd6, "LEVEL9-003" },\r
75       { 0x5ace, 0x11, "LEVEL9-003" },\r
76       { 0x6e5c, 0xf6, "LEVEL9-003" },\r
77       { 0x1929, 0x00, "LEVEL9-004-DEMO" },\r
78       { 0x40e0, 0x02, "LEVEL9-004-DEMO" },\r
79       { 0x3ebb, 0x00, "LEVEL9-004-en" },\r
80       { 0x3e4f, 0x00, "LEVEL9-004-en" },\r
81       { 0x3e8f, 0x00, "LEVEL9-004-en" },\r
82       { 0x0fd8, 0x00, "LEVEL9-004-en" },\r
83       { 0x14a3, 0x00, "LEVEL9-004-en" },\r
84       { 0x110f, 0x00, "LEVEL9-004-fr" },\r
85       { 0x4872, 0x00, "LEVEL9-004-de" },\r
86       { 0x4846, 0x00, "LEVEL9-004-de" },\r
87       { 0x11f5, 0x00, "LEVEL9-004-de" },\r
88       { 0x11f5, 0x00, "LEVEL9-004-de" },\r
89       { 0x76f4, 0x5e, "LEVEL9-005" },\r
90       { 0x5b16, 0x3b, "LEVEL9-005" },\r
91       { 0x6c8e, 0xb6, "LEVEL9-005" },\r
92       { 0x6f4d, 0xcb, "LEVEL9-005" },\r
93       { 0x6f6a, 0xa5, "LEVEL9-005" },\r
94       { 0x5e31, 0x7c, "LEVEL9-005" },\r
95       { 0x6f70, 0x40, "LEVEL9-005" },\r
96       { 0x6f6e, 0x78, "LEVEL9-005" },\r
97       { 0x5a8e, 0xf2, "LEVEL9-005" },\r
98       { 0x76f4, 0x5a, "LEVEL9-005" },\r
99       { 0x630e, 0x8d, "LEVEL9-006" },\r
100       { 0x630e, 0xbe, "LEVEL9-006" },\r
101       { 0x6f0c, 0x95, "LEVEL9-006" },\r
102       { 0x593a, 0x80, "LEVEL9-006" },\r
103       { 0x6bd2, 0x65, "LEVEL9-006" },\r
104       { 0x6dc0, 0x63, "LEVEL9-006" },\r
105       { 0x58a6, 0x24, "LEVEL9-006" },\r
106       { 0x6de8, 0x4c, "LEVEL9-006" },\r
107       { 0x58a3, 0x38, "LEVEL9-006" },\r
108       { 0x63be, 0xd6, "LEVEL9-007" },\r
109       { 0x378c, 0x8d, "LEVEL9-007" },\r
110       { 0x63be, 0x0a, "LEVEL9-007" },\r
111       { 0x34b3, 0x20, "LEVEL9-008" },\r
112       { 0x34b3, 0xc7, "LEVEL9-008" },\r
113       { 0x34b3, 0x53, "LEVEL9-008" },\r
114       { 0xb1a9, 0x80, "LEVEL9-009-1" },\r
115       { 0x908e, 0x0d, "LEVEL9-009-1" },\r
116       { 0xad41, 0xa8, "LEVEL9-009-1" },\r
117       { 0xb1aa, 0xad, "LEVEL9-009-1" },\r
118       { 0x8aab, 0xc0, "LEVEL9-009-1" },\r
119       { 0xb0ec, 0xc2, "LEVEL9-009-1" },\r
120       { 0xb19e, 0x92, "LEVEL9-009-1" },\r
121       { 0x5ff0, 0xf8, "LEVEL9-009-1" },\r
122       { 0x52aa, 0xdf, "LEVEL9-009-1" },\r
123       { 0xab9d, 0x31, "LEVEL9-009-2" },\r
124       { 0x8f6f, 0x0a, "LEVEL9-009-2" },\r
125       { 0xa735, 0xf7, "LEVEL9-009-2" },\r
126       { 0xab8b, 0xbf, "LEVEL9-009-2" },\r
127       { 0x8ac8, 0x9a, "LEVEL9-009-2" },\r
128       { 0xaf82, 0x83, "LEVEL9-009-2" },\r
129       { 0x6024, 0x01, "LEVEL9-009-2" },\r
130       { 0x6ffa, 0xdb, "LEVEL9-009-2" },\r
131       { 0xae28, 0x87, "LEVEL9-009-3" },\r
132       { 0x9060, 0xbb, "LEVEL9-009-3" },\r
133       { 0xa9c0, 0x9e, "LEVEL9-009-3" },\r
134       { 0xae16, 0x81, "LEVEL9-009-3" },\r
135       { 0x8a93, 0x4f, "LEVEL9-009-3" },\r
136       { 0xb3e6, 0xab, "LEVEL9-009-3" },\r
137       { 0x6036, 0x3d, "LEVEL9-009-3" },\r
138       { 0x723a, 0x69, "LEVEL9-009-3" },\r
139       { 0xd188, 0x13, "LEVEL9-010-1" },\r
140       { 0x9089, 0xce, "LEVEL9-010-1" },\r
141       { 0xb770, 0x03, "LEVEL9-010-1" },\r
142       { 0xd19b, 0xad, "LEVEL9-010-1" },\r
143       { 0x8ab7, 0x68, "LEVEL9-010-1" },\r
144       { 0xd183, 0x83, "LEVEL9-010-1" },\r
145       { 0x5a38, 0xf7, "LEVEL9-010-1" },\r
146       { 0x76a0, 0x3a, "LEVEL9-010-1" },\r
147       { 0xc594, 0x03, "LEVEL9-010-2" },\r
148       { 0x908d, 0x80, "LEVEL9-010-2" },\r
149       { 0xb741, 0xb6, "LEVEL9-010-2" },\r
150       { 0xc5a5, 0xfe, "LEVEL9-010-2" },\r
151       { 0x8b1e, 0x84, "LEVEL9-010-2" },\r
152       { 0xc58f, 0x65, "LEVEL9-010-2" },\r
153       { 0x531a, 0xed, "LEVEL9-010-2" },\r
154       { 0x7674, 0x0b, "LEVEL9-010-2" },\r
155       { 0xd79f, 0xb5, "LEVEL9-010-3" },\r
156       { 0x909e, 0x9f, "LEVEL9-010-3" },\r
157       { 0xb791, 0xa1, "LEVEL9-010-3" },\r
158       { 0xd7ae, 0x9e, "LEVEL9-010-3" },\r
159       { 0x8b1c, 0xa8, "LEVEL9-010-3" },\r
160       { 0xd79a, 0x57, "LEVEL9-010-3" },\r
161       { 0x57e4, 0x19, "LEVEL9-010-3" },\r
162       { 0x765e, 0xba, "LEVEL9-010-3" },\r
163       { 0xbb93, 0x36, "LEVEL9-011-1" },\r
164       { 0x898a, 0x43, "LEVEL9-011-1" },\r
165       { 0x8970, 0x6b, "LEVEL9-011-1" },\r
166       { 0xbb6e, 0xa6, "LEVEL9-011-1" },\r
167       { 0x86d0, 0xb7, "LEVEL9-011-1" },\r
168       { 0xbb6e, 0xad, "LEVEL9-011-1" },\r
169       { 0x46ec, 0x64, "LEVEL9-011-1" },\r
170       { 0x74e0, 0x92, "LEVEL9-011-1" },\r
171       { 0xc58e, 0x4a, "LEVEL9-011-2" },\r
172       { 0x8b9f, 0x61, "LEVEL9-011-2" },\r
173       { 0x8b90, 0x4e, "LEVEL9-011-2" },\r
174       { 0xc58e, 0x43, "LEVEL9-011-2" },\r
175       { 0x8885, 0x22, "LEVEL9-011-2" },\r
176       { 0x6140, 0x18, "LEVEL9-011-2" },\r
177       { 0x6dbc, 0x97, "LEVEL9-011-2" },\r
178       { 0xcb9a, 0x0f, "LEVEL9-011-3" },\r
179       { 0x8af9, 0x61, "LEVEL9-011-3" },\r
180       { 0x8aea, 0x4e, "LEVEL9-011-3" },\r
181       { 0xcb9a, 0x08, "LEVEL9-011-3" },\r
182       { 0x87e5, 0x0e, "LEVEL9-011-3" },\r
183       { 0x640e, 0xc1, "LEVEL9-011-3" },\r
184       { 0x7402, 0x07, "LEVEL9-011-3" },\r
185       { 0xbba4, 0x94, "LEVEL9-012-1" },\r
186       { 0xc0cf, 0x4e, "LEVEL9-012-1" },\r
187       { 0x8afc, 0x07, "LEVEL9-012-1" },\r
188       { 0x8feb, 0xba, "LEVEL9-012-1" },\r
189       { 0xb4c9, 0x94, "LEVEL9-012-1" },\r
190       { 0xc0bd, 0x57, "LEVEL9-012-1" },\r
191       { 0x8ade, 0xf2, "LEVEL9-012-1" },\r
192       { 0x4fd2, 0x9d, "LEVEL9-012-1" },\r
193       { 0x5c7a, 0x44, "LEVEL9-012-1" },\r
194       { 0x768c, 0xe8, "LEVEL9-012-1" },\r
195       { 0xd0c0, 0x56, "LEVEL9-012-2" },\r
196       { 0xd5e9, 0x6a, "LEVEL9-012-2" },\r
197       { 0x8aec, 0x13, "LEVEL9-012-2" },\r
198       { 0x8f6b, 0xfa, "LEVEL9-012-2" },\r
199       { 0xb729, 0x51, "LEVEL9-012-2" },\r
200       { 0xd5d7, 0x99, "LEVEL9-012-2" },\r
201       { 0x8b0e, 0xfb, "LEVEL9-012-2" },\r
202       { 0x4dac, 0xa8, "LEVEL9-012-2" },\r
203       { 0x53a2, 0x1e, "LEVEL9-012-2" },\r
204       { 0x76b0, 0x1d, "LEVEL9-012-2" },\r
205       { 0xb6ac, 0xc6, "LEVEL9-012-3" },\r
206       { 0xbb8f, 0x1a, "LEVEL9-012-3" },\r
207       { 0x8aba, 0x0d, "LEVEL9-012-3" },\r
208       { 0x8f71, 0x2f, "LEVEL9-012-3" },\r
209       { 0xb702, 0xe4, "LEVEL9-012-3" },\r
210       { 0xbb7d, 0x17, "LEVEL9-012-3" },\r
211       { 0x8ab3, 0xc1, "LEVEL9-012-3" },\r
212       { 0x4f96, 0x22, "LEVEL9-012-3" },\r
213       { 0x5914, 0x22, "LEVEL9-012-3" },\r
214       { 0x765e, 0x4f, "LEVEL9-012-3" },\r
215       { 0x5eb9, 0x30, "LEVEL9-013" },\r
216       { 0x5eb9, 0x5d, "LEVEL9-013" },\r
217       { 0x5eb9, 0x6e, "LEVEL9-013" },\r
218       { 0xb257, 0xf8, "LEVEL9-013" },\r
219       { 0xb576, 0x2a, "LEVEL9-013" },\r
220       { 0x8d78, 0x3a, "LEVEL9-013" },\r
221       { 0x9070, 0x43, "LEVEL9-013" },\r
222       { 0xb38c, 0x37, "LEVEL9-013" },\r
223       { 0xb563, 0x6a, "LEVEL9-013" },\r
224       { 0xb57c, 0x44, "LEVEL9-013" },\r
225       { 0xb260, 0xe5, "LEVEL9-013" },\r
226       { 0x8950, 0xa1, "LEVEL9-013" },\r
227       { 0xb579, 0x89, "LEVEL9-013" },\r
228       { 0x579e, 0x97, "LEVEL9-013" },\r
229       { 0x69fe, 0x56, "LEVEL9-013" },\r
230       { 0x6f1e, 0xda, "LEVEL9-013" },\r
231       { 0x5671, 0xbc, "LEVEL9-014" },\r
232       { 0x6fc6, 0x14, "LEVEL9-014" },\r
233       { 0x5aa4, 0xc1, "LEVEL9-014" },\r
234       { 0x7410, 0x5e, "LEVEL9-014" },\r
235       { 0x5aa4, 0xc1, "LEVEL9-014" },\r
236       { 0x5aa4, 0xc1, "LEVEL9-014" },\r
237       { 0xb797, 0x1f, "LEVEL9-014" },\r
238       { 0xbaca, 0x3a, "LEVEL9-014" },\r
239       { 0x8c46, 0xf0, "LEVEL9-014" },\r
240       { 0x8f51, 0xb2, "LEVEL9-014" },\r
241       { 0xb451, 0xa8, "LEVEL9-014" },\r
242       { 0xbab2, 0x87, "LEVEL9-014" },\r
243       { 0xbac7, 0x7f, "LEVEL9-014" },\r
244       { 0xb7a0, 0x7e, "LEVEL9-014" },\r
245       { 0x8a60, 0x2a, "LEVEL9-014" },\r
246       { 0xbac4, 0x80, "LEVEL9-014" },\r
247       { 0x579a, 0x2a, "LEVEL9-014" },\r
248       { 0x5a50, 0xa9, "LEVEL9-014" },\r
249       { 0x6108, 0xdd, "LEVEL9-014" },\r
250       { 0x506c, 0xf0, "LEVEL9-015" },\r
251       { 0x505d, 0x32, "LEVEL9-015" },\r
252       { 0xa398, 0x82, "LEVEL9-015" },\r
253       { 0xa692, 0xd1, "LEVEL9-015" },\r
254       { 0x8d56, 0xd3, "LEVEL9-015" },\r
255       { 0x903f, 0x6b, "LEVEL9-015" },\r
256       { 0xa4e2, 0xa6, "LEVEL9-015" },\r
257       { 0xa67c, 0xb8, "LEVEL9-015" },\r
258       { 0xa69e, 0x6c, "LEVEL9-015" },\r
259       { 0xa3a4, 0xdf, "LEVEL9-015" },\r
260       { 0x8813, 0x11, "LEVEL9-015" },\r
261       { 0xa698, 0x41, "LEVEL9-015" },\r
262       { 0x5500, 0x50, "LEVEL9-015" },\r
263       { 0x6888, 0x8d, "LEVEL9-015" },\r
264       { 0x6da0, 0xb8, "LEVEL9-015" },\r
265       { 0x6064, 0xbd, "LEVEL9-016" },\r
266       { 0x6064, 0x01, "LEVEL9-016" },\r
267       { 0x6047, 0x6c, "LEVEL9-016" },\r
268       { 0x6064, 0xda, "LEVEL9-016" },\r
269       { 0x6064, 0x95, "LEVEL9-016" },\r
270       { 0x60c4, 0x28, "LEVEL9-016" },\r
271       { 0x5cb7, 0xfe, "LEVEL9-016" },\r
272       { 0x5ca1, 0x33, "LEVEL9-016" },\r
273       { 0x5cb7, 0x64, "LEVEL9-016" },\r
274       { 0x7d16, 0xe6, "LEVEL9-016" },\r
275       { 0x639c, 0x8b, "LEVEL9-016" },\r
276       { 0x60f7, 0x68, "LEVEL9-016" },\r
277       { 0x772f, 0xca, "LEVEL9-016" },\r
278       { 0x7cff, 0xf8, "LEVEL9-016" },\r
279       { 0x7cf8, 0x24, "LEVEL9-016" },\r
280       { 0x7d14, 0xe8, "LEVEL9-016" },\r
281       { 0x7c55, 0x18, "LEVEL9-016" },\r
282       { 0x5f43, 0xca, "LEVEL9-016" },\r
283       { 0xc132, 0x14, "LEVEL9-017-1" },\r
284       { 0xbeab, 0x2d, "LEVEL9-017-1" },\r
285       { 0x9058, 0xcf, "LEVEL9-017-1" },\r
286       { 0xbe94, 0xcc, "LEVEL9-017-1" },\r
287       { 0x8a21, 0xf4, "LEVEL9-017-1" },\r
288       { 0x55ce, 0xa1, "LEVEL9-017-1" },\r
289       { 0x5cbc, 0xa5, "LEVEL9-017-1" },\r
290       { 0x762e, 0x82, "LEVEL9-017-1" },\r
291       { 0x99bd, 0x65, "LEVEL9-017-2" },\r
292       { 0x8f43, 0xc9, "LEVEL9-017-2" },\r
293       { 0x8a12, 0xe3, "LEVEL9-017-2" },\r
294       { 0x54a6, 0xa9, "LEVEL9-017-2" },\r
295       { 0x5932, 0x4e, "LEVEL9-017-2" },\r
296       { 0x5bd6, 0x35, "LEVEL9-017-2" },\r
297       { 0xbcb6, 0x7a, "LEVEL9-017-3 (Amiga/PC/ST)" },\r
298       { 0x90ac, 0x68, "LEVEL9-017-3" },\r
299       { 0x8a16, 0xcc, "LEVEL9-017-3" },\r
300       { 0x51bc, 0xe3, "LEVEL9-017-3" },\r
301       { 0x5860, 0x95, "LEVEL9-017-3" },\r
302       { 0x6fa8, 0xa4, "LEVEL9-017-3" },\r
303       { 0x5fab, 0x5c, "LEVEL9-018" },\r
304       { 0x5fab, 0x2f, "LEVEL9-018" },\r
305       { 0x7b31, 0x6e, "LEVEL9-018" },\r
306       { 0x67a3, 0x9d, "LEVEL9-018" },\r
307       { 0x6bf8, 0x3f, "LEVEL9-018" },\r
308       { 0x7363, 0x65, "LEVEL9-018" },\r
309       { 0x7b2f, 0x70, "LEVEL9-018" },\r
310       { 0x7b2f, 0x70, "LEVEL9-018" },\r
311       { 0x6541, 0x02, "LEVEL9-018" },\r
312       { 0x5834, 0x42, "LEVEL9-019-1" },\r
313       { 0x765d, 0xcd, "LEVEL9-019-1" },\r
314       { 0x6ce5, 0x58, "LEVEL9-019-1" },\r
315       { 0x56dd, 0x51, "LEVEL9-019-2" },\r
316       { 0x6e58, 0x07, "LEVEL9-019-2" },\r
317       { 0x68da, 0xc1, "LEVEL9-019-2" },\r
318       { 0x5801, 0x53, "LEVEL9-019-3" },\r
319       { 0x7e98, 0x6a, "LEVEL9-019-3" },\r
320       { 0x6c67, 0x9a, "LEVEL9-019-3" },\r
321       { 0x54a4, 0x01, "LEVEL9-019-4" },\r
322       { 0x81e2, 0xd5, "LEVEL9-019-4" },\r
323       { 0x6d91, 0xb9, "LEVEL9-019-4" },\r
324       { 0x5828, 0xbd, "LEVEL9-020" },\r
325       { 0x6d84, 0xf9, "LEVEL9-020" },\r
326       { 0x6d84, 0xc8, "LEVEL9-020" },\r
327       { 0x6030, 0x47, "LEVEL9-020" },\r
328       { 0x772b, 0xcd, "LEVEL9-020" },\r
329       { 0x546c, 0xb7, "LEVEL9-020" },\r
330       { 0x7cd9, 0x0c, "LEVEL9-020" },\r
331       { 0x60dd, 0xf2, "LEVEL9-020" },\r
332       { 0x6161, 0xf3, "LEVEL9-020" },\r
333       { 0x788d, 0x72, "LEVEL9-020" },\r
334       { 0x7cd7, 0x0e, "LEVEL9-020" },\r
335       { 0x5ebb, 0xf1, "LEVEL9-020" },\r
336 \r
337       { 0, 0, NULL }\r
338 };\r
339 \r
340 \r
341 \r
342 static int32 read_l9_int(unsigned char *sf)\r
343 {\r
344  return ((int32) sf[1]) << 8 | sf[0];\r
345 \r
346 }\r
347 static int v2_recognition (unsigned char *sf, int32 extent, int32 *l, unsigned char *c)\r
348 {\r
349   int32 i, j;\r
350   for (i=0;i<extent-20;i++)\r
351     if ((read_l9_int(sf+i+4) == 0x0020) &&\r
352         (read_l9_int(sf+i+0x0a) == 0x8000) &&\r
353         (read_l9_int(sf+i+0x14) == read_l9_int(sf+i+0x16)))\r
354     {\r
355       *l=read_l9_int(sf+i+0x1c);\r
356       if (*l && *l+i <=extent)\r
357        {\r
358          *c=0;\r
359          for(j=0;j<=*l;j++)\r
360           *c+=sf[i+j];\r
361          return 2;\r
362        }\r
363     }\r
364  return 0;\r
365 }\r
366 static int v1_recognition(unsigned char *sf, int32 extent, char **ifid)\r
367 {\r
368   int32 i;\r
369   unsigned char a = 0xff, b = 0xff;\r
370 \r
371   for (i=0;i<extent-20;i++)\r
372    if (memcmp(sf+i,"ATTAC",5)==0 && sf[i+5]==0xcb)\r
373    {   \r
374     a = sf[i+6];\r
375     break;\r
376    }\r
377   for (;i<(extent-20);i++)\r
378    if (memcmp(sf+i,"BUNC",4)==0 && sf[i+4]==0xc8)\r
379    {\r
380     b = sf[i + 5];\r
381     break;\r
382    }\r
383   if (a == 0xff && b == 0xff)\r
384    return 0;\r
385   if (a == 0x14 && b == 0xff) *ifid="LEVEL9-006";\r
386   else if (a == 0x15 && b == 0x5d) *ifid="LEVEL9-013";\r
387   else if (a == 0x1a && b == 0x24) *ifid="LEVEL9-005";\r
388   else if (a == 0x20 && b == 0x3b) *ifid="LEVEL9-003";\r
389   else *ifid=NULL;\r
390   return 1;\r
391 }\r
392 static int v3_recognition_phase (int phase,unsigned char *sf, int32 extent, int32 *l, unsigned char *c)\r
393 {\r
394   int32 end, i, j, ll;\r
395   ll=0;\r
396   for (i=0;i<extent-20;i++)\r
397   {\r
398     if (ll) break;\r
399     *l = read_l9_int(sf+i);\r
400     end=*l+i;\r
401     if (phase!=3)\r
402     {\r
403     if (end <= (extent - 2) &&\r
404        (\r
405         ((phase == 2) ||\r
406         (((sf[end-1] == 0) &&\r
407          (sf[end-2] == 0)) ||\r
408         ((sf[end+1] == 0) &&\r
409          (sf[end+2] == 0))))\r
410         && (*l>0x4000) && (*l<=0xdb00)))\r
411       if ((*l!=0) && (sf[i+0x0d] == 0))\r
412        for (j=i;j<i+16;j+=2)\r
413         if (((read_l9_int(sf+j)+read_l9_int(sf+j+2))==read_l9_int(sf+j+4))\r
414             && ((read_l9_int(sf+j)+read_l9_int(sf+j+2))))\r
415         ll++;\r
416      }\r
417      else\r
418      {\r
419       if ((extent>0x0fd0) && (end <= (extent - 2)) &&\r
420          (((read_l9_int(sf+i+2) + read_l9_int(sf+i+4))==read_l9_int(sf+i+6))\r
421                     && (read_l9_int(sf+i+2) != 0) && (read_l9_int(sf+i+4)) != 0) &&\r
422          (((read_l9_int(sf+i+6) + read_l9_int(sf+i+8)) == read_l9_int(sf+i+10))\r
423           && ((sf[i + 18] == 0x2a) || (sf[i + 18] == 0x2c))\r
424           && (sf[i + 19] == 0) && (sf[i + 20] == 0) && (sf[i + 21] == 0)))\r
425         ll = 2;\r
426      }\r
427     if (ll>1)\r
428     {\r
429      *c=0;\r
430      if (phase==3) ll=1;\r
431      else\r
432      { char checksum=0;\r
433       *c = sf[end];\r
434       for (j=i;j<=end;j++)\r
435        checksum += sf[j];\r
436       if (!checksum) ll=1;\r
437       else ll=0;\r
438      }\r
439      } else ll=0;\r
440    }\r
441 \r
442   if (ll) return *l < 0x8500 ? 3:4;\r
443   return 0;\r
444 }\r
445 static char *get_l9_ifid(int32 length, unsigned char chk)\r
446 {\r
447  int i;\r
448  for(i=0;l9_registry[i].length;i++)\r
449   if (length==l9_registry[i].length && chk==l9_registry[i].chk) return l9_registry[i].ifid;\r
450  return NULL;\r
451 }\r
452 static int get_l9_version(unsigned char *sf, int32 extent, char **ifid)\r
453 {\r
454  int i;\r
455  int32 l;\r
456  unsigned char c;\r
457  if (v2_recognition(sf,extent, &l, &c)) { *ifid=get_l9_ifid(l,c); return 2; }\r
458  l=0; c=0;\r
459  i=v3_recognition_phase(1,sf,extent, &l, &c);\r
460  if (i) { *ifid=get_l9_ifid(l,c); return i; }\r
461  if (v1_recognition(sf,extent, ifid)) return 1;\r
462  l=0; c=0;\r
463  i=v3_recognition_phase(2,sf,extent, &l, &c);\r
464  if (i) { *ifid=get_l9_ifid(l,c); return i; }\r
465  i=v3_recognition_phase(3,sf,extent, &l, &c);\r
466  *ifid=NULL;\r
467  return i;\r
468 }\r
469 \r
470 static int32 claim_story_file(void *story, int32 extent)\r
471 {\r
472  char *ifid=NULL;\r
473  if (get_l9_version((unsigned char *) story,extent, &ifid))\r
474   if (ifid) return VALID_STORY_FILE_RV;\r
475   else return NO_REPLY_RV;\r
476  return INVALID_STORY_FILE_RV; \r
477 }\r
478 \r
479 \r
480 \r
481 static int32 get_story_file_IFID(void *story_file, int32 extent, char *output, int32 output_extent)\r
482 {\r
483  char *ifid=NULL;\r
484  int i=get_l9_version((unsigned char *)story_file, extent, &ifid);\r
485  if (!i) return INVALID_STORY_FILE_RV;\r
486  if (ifid)\r
487  {\r
488    ASSERT_OUTPUT_SIZE((signed) strlen(ifid)+1);\r
489    strcpy(output,ifid);\r
490    return 1;\r
491  }\r
492  ASSERT_OUTPUT_SIZE(10);\r
493  sprintf(output,"LEVEL9-%d-",i);\r
494  return INCOMPLETE_REPLY_RV;\r
495 }\r