OSDN Git Service

c465e8b205bad193f8cc4934c959385cb9fc31a7
[heavyosecpu/HeavyOSECPU.git] / tek.c
1 #include <setjmp.h>
2 #include <string.h>
3 #include <stdlib.h>
4
5 #if (!defined(NULL))
6         #define NULL            0
7 #endif
8
9 typedef unsigned char UCHAR;
10 typedef unsigned int UINT32;
11 typedef UINT32 tek_TPRB;
12
13 /* not used
14 static int tek_decode1(int siz, UCHAR *p, UCHAR *q);
15 static int tek_decode2(int siz, UCHAR *p, UCHAR *q);
16  */
17 static int tek_decode5(int siz, UCHAR *p, UCHAR *q);
18
19 static unsigned int tek_getnum_s7s(UCHAR **pp)
20 /* これは必ずbig-endian */
21 /* 下駄がないので中身をいじりやすい */
22 {
23         unsigned int s = 0;
24         UCHAR *p = *pp;
25         do {
26                 s = s << 7 | *p++;
27         } while ((s & 1) == 0);
28         s >>= 1;
29         *pp = p;
30         return s;
31 }
32
33 #if 0
34
35 int tek_getsize(unsigned char *p)
36 {
37         static char header[15] = {
38                 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x41, 0x53, 0x4b, 0x43, 0x4d, 0x50
39         };
40         int size = -1;
41         if (memcmp(p + 1, header, 15) == 0 && (*p == 0x83 || *p == 0x85 || *p == 0x89)) {
42                 p += 16;
43                 size = tek_getnum_s7s(&p);
44         }
45         return size;
46 }         /* (註)memcmpはstrncmpの仲間で、文字列中に0があっても指定された15文字まで比較する関数 */
47
48 #endif
49
50 int tek_decomp(unsigned char *p, char *q, int size)
51 {
52         int err = -1;
53 #if 0
54         if (*p == 0x83) {
55                 err = tek_decode1(size, p, q);
56         } else if (*p == 0x85) {
57                 err = tek_decode2(size, p, q);
58         } else if (*p == 0x89) {
59                 err = tek_decode5(size, p, q);
60         }
61 #else
62 if (*p == 0x89) {
63                 err = tek_decode5(size, p, (UCHAR *)q);
64         }
65 #endif
66         if (err != 0) {
67                 return -1;      /* 失敗 */
68         }
69         return 0;       /* 成功 */
70 }
71
72 #if 0
73
74 static int tek_lzrestore_stk1(int srcsiz, UCHAR *src, int outsiz, UCHAR *q)
75 {
76         int by, lz, cp, ds;
77         UCHAR *q1 = q + outsiz, *s7ptr = src, *q0 = q;
78         do {
79                 if ((by = (lz = *s7ptr++) & 0x0f) == 0)
80                         by = tek_getnum_s7s(&s7ptr);
81                 if ((lz >>= 4) == 0)
82                         lz = tek_getnum_s7s(&s7ptr);
83                 do {
84                         *q++ = *s7ptr++;
85                 } while (--by);
86                 if (q >= q1)
87                         break;
88                 do {
89                         ds = (cp = *s7ptr++) & 0x0f;
90                         if ((ds & 1) == 0) {
91                                 do {
92                                         ds = ds << 7 | *s7ptr++;
93                                 } while ((ds & 1) == 0);
94                         }
95                         ds = ‾(ds >> 1);
96                         if ((cp >>= 4) == 0) {
97                                 do {
98                                         cp = cp << 7 | *s7ptr++;
99                                 } while ((cp & 1) == 0);
100                                 cp >>= 1;
101                         } /* 0がこないことをあてにする */
102                         cp++;
103                         if (q + ds < q0)
104                                 goto err;
105                         if (q + cp > q1)
106                                 cp = q1 - q;
107                         do {
108                                 *q = *(q + ds);
109                                 q++;
110                         } while (--cp);
111                 } while (--lz);
112         } while (q < q1);
113         return 0;
114 err:
115         return 1;
116 }
117
118 static int tek_decode1(int siz, UCHAR *p, UCHAR *q)
119 {
120         int dsiz, hed, bsiz;
121         UCHAR *p1 = p + siz;
122         p += 16;
123         if ((dsiz = tek_getnum_s7s(&p)) > 0) {
124                 hed = tek_getnum_s7s(&p);
125                 bsiz = 1 << (((hed >> 1) & 0x0f) + 8);
126                 if (dsiz > bsiz || (hed & 0x21) != 0x01)
127                         return 1;
128                 if (hed & 0x40)
129                         tek_getnum_s7s(&p); /* オプション情報へのポインタを読み飛ばす */
130                 if (tek_getnum_s7s(&p) != 0)
131                         return 1; /* 補助バッファ使用 */
132                 return tek_lzrestore_stk1(p1 - p, p, dsiz, q);
133         }
134         return 0;
135 }
136
137 static unsigned int tek_getnum_s7(UCHAR **pp)
138 /* これは必ずbig-endian */
139 {
140         unsigned int s = 0, b = 0, a = 1;
141         UCHAR *p = *pp;
142         for (;;) {
143                 s = s << 7 | *p++;
144                 if (s & 1)
145                         break;
146                 a <<= 7;
147                 b += a;
148         }
149         s >>= 1;
150         *pp = p;
151         return s + b;
152 }
153
154 static int tek_lzrestore_stk2(int srcsiz, UCHAR *src, int outsiz, UCHAR *q)
155 {
156         int cp, ds, repdis[4], i, j;
157         UCHAR *q1 = q + outsiz, *s7ptr = src, *q0 = q, bylz, cbylz;
158         for (j = 0; j < 4; j++)
159                 repdis[j] = -1 - j;
160         bylz = cbylz = 0;
161         if (outsiz) {
162                 if (tek_getnum_s7s(&s7ptr))
163                         return 1;
164                 do {
165                         /* byフェーズ */
166                         j = 0;
167                         do {
168                                 j++;
169                                 if (j >= 17) {
170                                         j += tek_getnum_s7s(&s7ptr);
171                                         break;
172                                 }
173                                 if (cbylz == 0) {
174                                         cbylz = 8;
175                                         bylz = *s7ptr++;
176                                 }
177                                 cbylz--;
178                                 i = bylz & 1;
179                                 bylz >>= 1;
180                         } while (i == 0);
181                         do {
182                                 *q++ = *s7ptr++;
183                         } while (--j);
184                         if (q >= q1)
185                                 break;
186
187                         /* lzフェーズ */
188                         j = 0;
189                         do {
190                                 j++;
191                                 if (j >= 17) {
192                                         j += tek_getnum_s7s(&s7ptr);
193                                         break;
194                                 }
195                                 if (cbylz == 0) {
196                                         cbylz = 8;
197                                         bylz = *s7ptr++;
198                                 }
199                                 cbylz--;
200                                 i = bylz & 1;
201                                 bylz >>= 1;
202                         } while (i == 0);
203                         do {
204                                 i = *s7ptr++;
205                                 cp = i >> 4;
206                                 i &= 0x0f;
207                                 if ((i & 1) == 0)
208                                         i |= (tek_getnum_s7(&s7ptr) + 1) << 4;
209                                 i >>= 1;
210                                 ds = ‾(i - 6);
211                                 if (i < 4)
212                                         ds = repdis[i];
213                                 if (i == 4)
214                                         ds = repdis[0] - tek_getnum_s7(&s7ptr) - 1;
215                                 if (i == 5)
216                                         ds = repdis[0] + tek_getnum_s7(&s7ptr) + 1;
217                                 if (cp == 0)
218                                         cp = tek_getnum_s7(&s7ptr) + 16;
219                                 cp++;
220                                 if (i > 0) {
221                                         if (i > 1) {
222                                                 if (i > 2)
223                                                         repdis[3] = repdis[2];
224                                                 repdis[2] = repdis[1];
225                                         }
226                                         repdis[1] = repdis[0];
227                                         repdis[0] = ds;
228                                 }
229                                 if (q + ds < q0)
230                                         goto err;
231                                 if (q + cp > q1)
232                                         cp = q1 - q;
233                                 do {
234                                         *q = *(q + ds);
235                                         q++;
236                                 } while (--cp);
237                         } while (--j);
238                 } while (q < q1);
239         }
240         return 0;
241 err:
242         return 1;
243 }
244
245 static int tek_decode2(int siz, UCHAR *p, UCHAR *q)
246 {
247         UCHAR *p1 = p + siz;
248         int dsiz, hed, bsiz, st = 0;
249         p += 16;
250         if ((dsiz = tek_getnum_s7s(&p)) > 0) {
251                 hed = tek_getnum_s7s(&p);
252                 bsiz = 1 << (((hed >> 1) & 0x0f) + 8);
253                 if (dsiz > bsiz || (hed & 0x21) != 0x01)
254                         return 1;
255                 if (hed & 0x40)
256                         tek_getnum_s7s(&p); /* オプション情報へのポインタを読み飛ばす */
257                 st = tek_lzrestore_stk2(p1 - p, p, dsiz, q);
258         }
259         return st;
260 }
261
262 #endif
263
264 static int tek_decmain5(int *work, UCHAR *src, int osiz, UCHAR *q, int lc, int pb, int lp, int flags);
265
266 static int tek_lzrestore_tek5(int srcsiz, UCHAR *src, int outsiz, UCHAR *outbuf)
267 {
268         int wrksiz, lc, lp, pb, flags = 0, *work, prop0, fl;
269
270         if ((fl = (prop0 = *src) & 0x0f) == 0x01) /* 0001 */
271                 flags |= -1;
272         else if (fl == 0x05)
273                 flags = -2;
274         else if (fl == 0x09)
275                 flags &= 0;
276         else
277                 return 1;
278         src++;
279         prop0 >>= 4;
280         if (prop0 == 0)
281                 prop0 = *src++;
282         else {
283                 static UCHAR prop0_table[] = { 0x5d, 0x00 }, prop1_table[] = { 0x00 };
284                 if (flags == -1) {
285                         if (prop0 >= 3)
286                                 return 1;
287                         prop0 = prop0_table[prop0 - 1];
288                 } else {
289                         if (prop0 >= 2)
290                                 return 1;
291                         prop0 = prop1_table[prop0 - 1];
292                 }
293         }
294         lp = prop0 / (9 * 5);
295         prop0 %= 9 * 5;
296         pb = prop0 / 9;
297         lc = prop0 % 9;
298         if (flags == 0) /* tek5:z2 */
299                 flags = *src++;
300         if (flags == -1) { /* stk5 */
301                 wrksiz = lp;
302                 lp = pb;
303                 pb = wrksiz;
304         }
305         wrksiz = 0x180 * sizeof (UINT32) + (0x840 + (0x300 << (lc + lp))) * sizeof (tek_TPRB); /* 最低15KB, lc+lp=3なら、36KB */
306         work = (int *) malloc(wrksiz);
307         if (work == NULL)
308                 return -1;
309         flags = tek_decmain5(work, src, outsiz, outbuf, lc, pb, lp, flags);
310         free(work);
311         return flags;
312 }
313
314 struct tek_STR_BITMODEL {
315         UCHAR t, m, s, dmy;
316         UINT32 prb0, prb1, tmsk, ntm, lt, lt0, dmy4;
317 };
318
319 struct tek_STR_PRB {
320         struct tek_STR_PRB_PB {
321                 struct tek_STR_PRB_PBST {
322                         tek_TPRB mch, rep0l1;
323                 } st[12];
324                 tek_TPRB lenlow[2][8], lenmid[2][8];
325         } pb[16];
326         struct tek_STR_PRB_ST {
327                 tek_TPRB rep, repg0, repg1, repg2;
328         } st[12];
329         tek_TPRB lensel[2][2], lenhigh[2][256], pslot[4][64], algn[64];
330         tek_TPRB spdis[2][2+4+8+16+32], lenext[2+4+8+16+32];
331         tek_TPRB repg3, fchgprm[2 * 32], tbmt[16], tbmm[16], fchglt;
332         tek_TPRB lit[1];
333 };
334
335 struct tek_STR_RNGDEC {
336         UCHAR *p;
337         UINT32 range, code, rmsk;
338         jmp_buf errjmp;
339         struct tek_STR_BITMODEL bm[32], *ptbm[16];
340         struct tek_STR_PRB probs;
341 };
342
343 static void tek_setbm5(struct tek_STR_BITMODEL *bm, int t, int m)
344 {
345         bm->t = t;
346         bm->m = m;
347         bm->prb1 = -1 << (m + t);
348         bm->prb0 = ~bm->prb1;
349         bm->prb1 |= 1 << t;
350         bm->tmsk = (-1 << t) & 0xffff;
351         bm->prb0 &= bm->tmsk;
352         bm->prb1 &= bm->tmsk;
353         bm->ntm = ~bm->tmsk;
354         return;
355 }
356
357 static int tek_rdget0(struct tek_STR_RNGDEC *rd, int n, int i)
358 {
359         do {
360                 while (rd->range < (UINT32) (1 << 24)) {
361                         rd->range <<= 8;
362                         rd->code = rd->code << 8 | *rd->p++;
363                 }
364                 rd->range >>= 1;
365                 i += i;
366                 if (rd->code >= rd->range) {
367                         rd->code -= rd->range;
368                         i |= 1;
369                 }
370         } while (--n);
371         return ~i;
372 }
373
374 static int tek_rdget1(struct tek_STR_RNGDEC *rd, tek_TPRB *prob0, int n, int j, struct tek_STR_BITMODEL *bm)
375 {
376         UINT32 p, i, *prob, nm = n >> 4;
377         n &= 0x0f;
378         prob0 -= j;
379         do {
380                 p = *(prob = prob0 + j);
381                 if (bm->lt > 0) {
382                         if (--bm->lt == 0) {
383                                 /* 寿命切れ */
384                                 if (tek_rdget1(rd, &rd->probs.fchglt, 0x71, 0, &rd->bm[3]) == 0) {
385                                         /* 寿命変更はまだサポートしてない */
386 err:
387                                         longjmp(rd->errjmp, 1);
388                                 }
389                                 i = bm - rd->bm;
390                                 if ((bm->s = tek_rdget1(rd, &rd->probs.fchgprm[i * 2 + bm->s], 0x71, 0, &rd->bm[1])) == 0) {
391                                         i = tek_rdget1(rd, rd->probs.tbmt, 0x74, 1, &rd->bm[2]) & 15;
392                                         if (i == 15)
393                                                 goto err;
394                                         tek_setbm5(bm, i, ((tek_rdget1(rd, rd->probs.tbmm, 0x74, 1, &rd->bm[2]) - 1) & 15) + 1);
395                                 }
396                                 bm->lt = bm->lt0;
397                         }
398                         if (p < bm->prb0) {
399                                 p = bm->prb0;
400                                 goto fixprob;
401                         }
402                         if (p > bm->prb1) {
403                                 p = bm->prb1;
404                                 goto fixprob;
405                         }
406                         if (p & bm->ntm) {
407                                 p &= bm->tmsk;
408         fixprob:
409                                 *prob = p;
410                         }
411                 }
412
413                 while (rd->range < (UINT32) (1 << 24)) {
414                         rd->range <<= 8;
415                         rd->code = rd->code << 8 | *rd->p++;
416                 }
417                 j += j;
418                 // 64ビット幅が必要
419                 i = (unsigned int)(((unsigned long long)(rd->range & rd->rmsk) * p) >> 16);
420                 if (rd->code < i) {
421                         j |= 1;
422                         rd->range = i;
423                         *prob += ((0x10000 - p) >> bm->m) & bm->tmsk;
424                 } else {
425                         rd->range -= i;
426                         rd->code -= i;
427                         *prob -= (p >> bm->m) & bm->tmsk;
428                 }
429                 --n;
430                 if ((n & nm) == 0)
431                         bm++;
432         } while (n);
433         return j;
434 }
435
436 static UINT32 tek_revbit(UINT32 data, int len)
437 {
438         UINT32 rev = 0;
439         do {
440                 rev += rev + (data & 1);
441                 data >>= 1;
442         } while (--len);
443         return rev;
444 }
445
446 static int tek_getlen5(struct tek_STR_RNGDEC *rd, int m, int s_pos, int stk)
447 {
448         int i;
449         if (tek_rdget1(rd, &rd->probs.lensel[m][0], 0x71, 0, rd->ptbm[3]) ^ stk) /* low */
450                 i = tek_rdget1(rd, rd->probs.pb[s_pos].lenlow[m], 0x73, 1, rd->ptbm[4]) & 7;
451         else if (tek_rdget1(rd, &rd->probs.lensel[m][1], 0x71, 0, rd->ptbm[3]) ^ stk) /* mid */
452                 i = tek_rdget1(rd, rd->probs.pb[s_pos].lenmid[m], 0x73, 1, rd->ptbm[5]);
453         else {
454                 /* high */
455                 i = tek_rdget1(rd, rd->probs.lenhigh[m], 0x78, 1, rd->ptbm[6]) - (256 + 256 - 8);
456                 if (i > 0) {
457                         if (i < 6 && stk == 0)
458                                 i = tek_rdget1(rd, &rd->probs.lenext[(1 << i) - 2], i | 0x70, 1, rd->ptbm[7]) - 1;
459                         else
460                                 i = tek_rdget0(rd, i, ~1) - 1;
461                         i = tek_rdget0(rd, i, ~1) - 1;
462                 }
463                 i += 256 - 8 + 16;
464         }
465         return i;
466 }
467
468 static int tek_decmain5(int *work, UCHAR *src, int osiz, UCHAR *q, int lc, int pb, int lp, int flags)
469 {
470         static int state_table[] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };
471         int i, j, k, pmch, rep[4], s, pos, m_pos = (1 << pb) - 1, m_lp = (1 << lp) - 1;
472         int stk = (flags == -1), lcr = 8 - lc, s_pos, lit0cntmsk = 0x78;
473         UINT32 *lit1;
474         struct tek_STR_RNGDEC *rd = (struct tek_STR_RNGDEC *) work;
475         struct tek_STR_PRB *prb = &rd->probs;
476
477         rd->p = &src[4];
478         rd->range |= -1;
479         rd->code = src[0] << 24 | src[1] << 16 | src[2] << 8 | src[3];
480         for (i = 0; i < 4; i++)
481                 rep[i] = ~i;
482         if (setjmp(rd->errjmp))
483                 goto err;
484         for (i = sizeof (struct tek_STR_PRB) / sizeof (tek_TPRB) + (0x300 << (lc + lp)) - 2; i >= 0; i--)
485                 ((tek_TPRB *) prb)[i] = 1 << 15;
486         for (i = 0; i < 32; i++) {
487                 rd->bm[i].lt = (i >= 4); /* 0..3は寿命なし */
488                 rd->bm[i].lt0 = (i < 24) ? 16 * 1024 : 8 * 1024;
489                 rd->bm[i].s &= 0;
490                 rd->bm[i].t = rd->bm[i].m = 5;
491         }
492         lit1 = prb->lit + ((256 << (lc + lp)) - 2);
493         if (stk) {
494                 rd->rmsk = -1 << 11;
495                 for (i = 0; i < 32; i++)
496                         rd->bm[i].lt = 0; /* 全て寿命なし */
497                 for (i = 0; i < 14; i++)
498                         rd->ptbm[i] = &rd->bm[0];
499         } else {
500                 UCHAR pt[14];
501                 static UCHAR pt1[14] = {
502                          8,  8,  8,  8,  8,  8,  8,  8,
503                          8,  8, 18, 18, 18,  8
504                 };
505                 static UCHAR pt2[14] = {
506                          8,  8, 10, 11, 12, 12, 14, 15,
507                         16, 16, 18, 18, 20, 21
508                 };
509                 /*
510                          0- 7:mch, mch, lit1, lensel, lenlow, lenmid, lenhigh, lenext
511                          8-15:pslot, pslot, sdis, sdis, align, rep-repg2
512                 */
513                 rd->rmsk |= -1;
514                 rd->bm[1].t = 5; rd->bm[1].m = 3; /* for fchgprm */
515                 rd->bm[2].t = 9; rd->bm[2].m = 2; /* for tbmt, tbmm */
516                 if (flags & 0x40) { /* lt-flag */
517                         rd->bm[3].t = 0; rd->bm[3].m = 1;
518                         prb->fchglt = 0xffff;
519                 }
520                 rd->bm[22].t = 0; rd->bm[22].m = 1;
521                 prb->repg3 = 0xffff;
522                 if (flags == -2) { /* z1 */
523                         rd->bm[22].lt = 0; /* repg3のltを0に */
524                         for (i = 0; i < 14; i++)
525                                 pt[i] = pt1[i];
526                 } else {
527                         for (i = 0; i < 14; i++)
528                                 pt[i] = pt2[i];
529                         lit0cntmsk = (7 >> (flags & 3)) << 4 | 8;
530                         pt[ 1] =  8 + ((flags & 0x04) != 0); /* mch */
531                         pt[ 5] = 12 + ((flags & 0x08) != 0); /* llm */
532                         pt[ 9] = 16 + ((flags & 0x10) != 0); /* pst */
533                         pt[11] = 18 + ((flags & 0x20) != 0); /* sds */
534                 }
535                 for (i = 0; i < 14; i++)
536                         rd->ptbm[i] = &rd->bm[pt[i]];
537         }
538         for (i = 0; i < 32; i++)
539                 tek_setbm5(&rd->bm[i], rd->bm[i].t, rd->bm[i].m);
540
541         if ((tek_rdget1(rd, &prb->pb[0].st[0].mch, 0x71, 0, rd->ptbm[0]) ^ stk) == 0)
542                 goto err;
543         *q++ = tek_rdget1(rd, prb->lit, lit0cntmsk, 1, &rd->bm[24]) & 0xff;
544         pmch &= 0; s &= 0; pos = 1;
545         while (pos < osiz) {
546                 s_pos = pos & m_pos;
547                 if (tek_rdget1(rd, &prb->pb[s_pos].st[s].mch, 0x71, 0, rd->ptbm[s > 0]) ^ stk) { /* 非lz */
548                         i = (q[-1] >> lcr | (pos & m_lp) << lc) << 8;
549                         s = state_table[s];
550                         if (pmch == 0)
551                                 *q = tek_rdget1(rd, &prb->lit[i], lit0cntmsk, 1, &rd->bm[24]) & 0xff;
552                         else {
553                                 struct tek_STR_BITMODEL *bm = &rd->bm[24];
554                                 j = 1; /* lit1は最初から2を減じてある */
555                                 k = 8;
556                                 pmch = q[rep[0]];
557                                 do {
558                                         j += j + tek_rdget1(rd, &lit1[(i + j) << 1 | pmch >> 7], 0x71, 0, rd->ptbm[2]);
559                                         k--;
560                                         if ((k & (lit0cntmsk >> 4)) == 0)
561                                                 bm++;
562                                         if ((((pmch >> 7) ^ j) & 1) != 0 && k != 0) {
563                                                 j = tek_rdget1(rd, &prb->lit[i + j - 1], k | (lit0cntmsk & 0x70), j, bm);
564                                                 break;
565                                         }
566                                         pmch <<= 1;
567                                 } while (k);
568                                 *q = j & 0xff;
569                                 pmch &= 0;
570                         }
571                         pos++;
572                         q++;
573                 } else { /* lz */
574                         pmch |= 1;
575                         if (tek_rdget1(rd, &prb->st[s].rep, 0x71, 0, rd->ptbm[13]) ^ stk) { /* len/dis */
576                                 rep[3] = rep[2];
577                                 rep[2] = rep[1];
578                                 rep[1] = rep[0];
579                                 j = i = tek_getlen5(rd, 0, s_pos, stk);
580                                 s = s < 7 ? 7 : 10;
581                                 if (j >= 4)
582                                         j = 3;
583                                 rep[0] = j = tek_rdget1(rd, prb->pslot[j], 0x76, 1, rd->ptbm[8 + (j == 3)]) & 0x3f;
584                                 if (j >= 4) {
585                                         k = (j >> 1) - 1; /* k = [1, 30] */
586                                         rep[0] = (2 | (j & 1)) << k;
587                                         if (j < 14) /* k < 6 */
588                                                 rep[0] |= tek_revbit(tek_rdget1(rd, &prb->spdis[j & 1][(1 << k) - 2], k | 0x70, 1, rd->ptbm[10 + (k >= 4)]), k);
589                                         else {
590                                                 if (stk == 0) {
591                                                         if (k -= 6)
592                                                                 rep[0] |= tek_rdget0(rd, k, ~0) << 6;
593                                                         rep[0] |= tek_revbit(tek_rdget1(rd, prb->algn, 0x76, 1, rd->ptbm[12]), 6);
594                                                 } else {
595                                                         rep[0] |= tek_rdget0(rd, k - 4, ~0) << 4;
596                                                         rep[0] |= tek_revbit(tek_rdget1(rd, prb->algn, 0x74, 1, rd->ptbm[12]), 4);
597                                                 }
598                                         }
599                                 }
600                                 rep[0] = ~rep[0];
601                         } else { /* repeat-dis */
602                                 if (tek_rdget1(rd, &prb->st[s].repg0, 0x71, 0, rd->ptbm[13]) ^ stk) { /* rep0 */
603                                         i |= -1;
604                                         if (tek_rdget1(rd, &prb->pb[s_pos].st[s].rep0l1, 0x71, 0, rd->ptbm[13]) == 0) {
605                                                 s = s < 7 ? 9 : 11;
606                                                 goto skip;
607                                         }
608                                 } else {
609                                         if (tek_rdget1(rd, &prb->st[s].repg1, 0x71, 0, rd->ptbm[13]) ^ stk) /* rep1 */
610                                                 i = rep[1];
611                                         else {
612                                                 if (tek_rdget1(rd, &prb->st[s].repg2, 0x71, 0, rd->ptbm[13]) ^ stk) /* rep2 */
613                                                         i = rep[2];
614                                                 else {
615                                                         if (stk == 0) {
616                                                                 if  (tek_rdget1(rd, &prb->repg3, 0x71, 0, &rd->bm[22]) == 0)
617                                                                         goto err;
618                                                         }
619                                                         i = rep[3]; /* rep3 */
620                                                         rep[3] = rep[2];
621                                                 }
622                                                 rep[2] = rep[1];
623                                         }
624                                         rep[1] = rep[0];
625                                         rep[0] = i;
626                                 }
627                                 i = tek_getlen5(rd, 1, s_pos, stk);
628                                 s = s < 7 ? 8 : 11;
629                         }
630 skip:
631                         i += 2;
632                         if (pos + rep[0] < 0)
633                                 goto err;
634                         if (pos + i > osiz)
635                                 i = osiz - pos;
636                         pos += i;
637                         do {
638                                 *q = q[rep[0]];
639                                 q++;
640                         } while (--i);
641                 }
642         }
643         return 0;
644 err:
645         return 1;
646 }
647
648 static int tek_decode5(int siz, UCHAR *p, UCHAR *q)
649 {
650         UCHAR *p1 = p + siz;
651         int dsiz, hed, bsiz, st = 0;
652         p += 16;
653         if ((dsiz = tek_getnum_s7s(&p)) > 0) {
654                 hed = tek_getnum_s7s(&p);
655                 if ((hed & 1) == 0)
656                         st = tek_lzrestore_tek5(p1 - p + 1, p - 1, dsiz, q);
657                 else {
658                         bsiz = 1 << (((hed >> 1) & 0x0f) + 8);
659                         if (hed & 0x20)
660                                 return 1;
661                         if (bsiz == 256)
662                                 st = tek_lzrestore_tek5(p1 - p, p, dsiz, q);
663                         else {
664                                 if (dsiz > bsiz)
665                                         return 1;
666                                 if (hed & 0x40)
667                                         tek_getnum_s7s(&p); /* オプション情報へのポインタを読み飛ばす */
668                                 st = tek_lzrestore_tek5(p1 - p, p, dsiz, q);
669                         }
670                 }
671         }
672         return st;
673 }