Subversion Repositories SvarDOS

Rev

Rev 2095 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2095 Rev 2102
Line 9... Line 9...
9
 * OUT.LNG -> contains all language resources.
9
 * OUT.LNG -> contains all language resources.
10
 * OUTC.LNG -> same as OUT.LNG but with compressed strings (slower to load).
10
 * OUTC.LNG -> same as OUT.LNG but with compressed strings (slower to load).
11
 *
11
 *
12
 * === COMPRESSION ===========================================================
12
 * === COMPRESSION ===========================================================
13
 * The compression scheme is very simple. It is applied only to strings (ie.
13
 * The compression scheme is very simple. It is applied only to strings (ie.
14
 * not the dictionnary) and it is basically a stream of 16-bit values (WORDs),
14
 * not the dictionnary) and it is basically a stream of 16-bit words (tokens).
-
 
15
 *
-
 
16
 * Token format is LLLL OOOO OOOO OOOO, where:
-
 
17
 * OOOO OOOO OOOO is the back reference offset (number of bytes-1 to rewind)
-
 
18
 * LLLL is the number of bytes (-1) that have to be copied from the offset.
-
 
19
 *
-
 
20
 * However, if LLLL is zero then the token's format is different:
-
 
21
 * 0000 RRRR BBBB BBBB
-
 
22
 *
-
 
23
 * The above form occurs when uncompressible data is encountered:
-
 
24
 * BBBB BBBB is the literal value of a byte to be copied
-
 
25
 * RRRR is the number of RAW (uncompressible) WORDS that follow (possibly 0)
-
 
26
 *
15
 * where each WORD value contains the following bits "LLLL OOOO OOOO OOOO":
27
 * where each WORD value contains the following bits "LLLL OOOO OOOO OOOO":
16
 *
28
 *
17
 * OOOO OOOO OOOO = a backreference offset ("look that many bytes back")
29
 * OOOO OOOO OOOO = a backreference offset ("look that many bytes back")
18
 * LLLL = the number of bytes to copy from the backreference
30
 * LLLL = the number of bytes to copy from the backreference
19
 *
31
 *
20
 * Special case: a WORD that is smaller than 256 represents a single literal
-
 
21
 * byte.
-
 
22
 *
-
 
23
 * To recognize a compressed lang block one has to look at the id of the block
32
 * To recognize a compressed lang block one has to look at the id of the block
24
 * (16-bit language id). If its highest bit is set (0x8000) then the lang block
33
 * (16-bit language id). If its highest bit is set (0x8000) then the lang block
25
 * is compressed.
34
 * is compressed.
26
 */
35
 */
27
 
36
 
Line 348... Line 357...
348
static int svl_write_header(unsigned short num_strings, FILE *fd) {
357
static int svl_write_header(unsigned short num_strings, FILE *fd) {
349
  return((fwrite("SvL\x1a", 1, 4, fd) == 4) && (fwrite(&num_strings, 1, 2, fd) == 2));
358
  return((fwrite("SvL\x1a", 1, 4, fd) == 4) && (fwrite(&num_strings, 1, 2, fd) == 2));
350
}
359
}
351
 
360
 
352
 
361
 
-
 
362
 
-
 
363
/* write qlen literal bytes into dst, returns amount of "compressed" bytes */
-
 
364
static unsigned short mvcomp_litqueue_dump(unsigned short **dst, const unsigned char *q, unsigned short qlen) {
-
 
365
  unsigned short complen = 0;
-
 
366
 
-
 
367
  AGAIN:
-
 
368
 
-
 
369
  /* are we done? (also take care of guys calling me in for jokes) */
-
 
370
  if (qlen == 0) return(complen);
-
 
371
 
-
 
372
  qlen--; /* now it's between 0 and 30 */
-
 
373
  /* write the length and first char */
-
 
374
  **dst = ((qlen / 2) << 8) | q[0];
-
 
375
  *dst += 1;
-
 
376
  q++;
-
 
377
  complen += 2;
-
 
378
 
-
 
379
  /* anything left? */
-
 
380
  if (qlen == 0) return(complen);
-
 
381
 
-
 
382
  /* write the pending words */
-
 
383
  if (qlen > 1) {
-
 
384
    memcpy(*dst, q, (qlen/2)*2);
-
 
385
    *dst += qlen / 2;
-
 
386
    q += (qlen / 2) * 2;
-
 
387
    complen += (qlen / 2) * 2;
-
 
388
    qlen -= (qlen / 2) * 2;
-
 
389
  }
-
 
390
 
-
 
391
  /* one byte might still be left if it did not fit inside a word */
-
 
392
  goto AGAIN;
-
 
393
}
-
 
394
 
-
 
395
 
353
/* mvcomp applies the MV-COMPRESSION algorithm to data and returns the compressed size */
396
/* mvcomp applies the MV-COMPRESSION algorithm to data and returns the compressed size */
354
static unsigned short mvcomp(char *dstbuf, const char *src, unsigned short len) {
397
static unsigned short mvcomp(char *dstbuf, const char *src, unsigned short len) {
355
  unsigned short complen = 0;
398
  unsigned short complen = 0;
356
  unsigned short *dst = (void *)dstbuf;
399
  unsigned short *dst = (void *)dstbuf;
357
  unsigned short bytesprocessed = 0;
400
  unsigned short bytesprocessed = 0;
-
 
401
  unsigned char litqueue[32];
-
 
402
  unsigned char litqueuelen = 0;
358
 
403
 
359
  /* read src byte by byte, len times, each time look for a match of 15,14,13..2 chars in the back buffer */
404
  /* read src byte by byte, len times, each time look for a match of 15,14,13..2 chars in the back buffer */
360
  while (len > 0) {
405
  while (len > 0) {
361
    unsigned short matchlen;
406
    unsigned short matchlen;
362
    unsigned short offset;
407
    unsigned short offset;
Line 374... Line 419...
374
          goto FOUND;
419
          goto FOUND;
375
        }
420
        }
376
      }
421
      }
377
    }
422
    }
378
 
423
 
379
    /* if here: no match found, write a literal byte */
424
    /* if here: no match found, write a literal byte to queue */
380
    *dst = *src;
425
    litqueue[litqueuelen++] = *src;
381
    dst++;
-
 
382
    src++;
426
    src++;
383
    bytesprocessed++;
427
    bytesprocessed++;
384
    len--;
428
    len--;
-
 
429
 
-
 
430
    /* dump literal queue to dst if max length reached */
-
 
431
    if (litqueuelen == 31) {
-
 
432
      complen += mvcomp_litqueue_dump(&dst, litqueue, litqueuelen);
385
    complen += 2;
433
      litqueuelen = 0;
-
 
434
    }
386
    continue;
435
    continue;
387
 
436
 
388
    FOUND: /* found a match of matchlen bytes at -offset */
437
    FOUND: /* found a match of matchlen bytes at -offset */
-
 
438
 
-
 
439
    /* dump awaiting literal queue to dst first */
-
 
440
    if (litqueuelen != 0) {
-
 
441
      complen += mvcomp_litqueue_dump(&dst, litqueue, litqueuelen);
-
 
442
      litqueuelen = 0;
-
 
443
    }
-
 
444
 
389
    *dst = ((matchlen - 1) << 12) | (offset - 1);
445
    *dst = ((matchlen - 1) << 12) | (offset - 1);
390
    dst++;
446
    dst++;
391
    src += matchlen;
447
    src += matchlen;
392
    bytesprocessed += matchlen;
448
    bytesprocessed += matchlen;
393
    len -= matchlen;
449
    len -= matchlen;
394
    complen += 2;
450
    complen += 2;
395
  }
451
  }
396
 
452
 
-
 
453
  /* dump awaiting literal queue to dst first */
-
 
454
  if (litqueuelen != 0) {
-
 
455
    complen += mvcomp_litqueue_dump(&dst, litqueue, litqueuelen);
-
 
456
    litqueuelen = 0;
-
 
457
  }
-
 
458
 
397
  return(complen);
459
  return(complen);
398
}
460
}
399
 
461
 
400
 
462
 
401
/* write the language block (id, dict, strings) into the LNG file.
463
/* write the language block (id, dict, strings) into the LNG file.