Subversion Repositories SvarDOS

Rev

Rev 2117 | Rev 2143 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2117 Rev 2123
Line 402... Line 402...
402
}
402
}
403
 
403
 
404
 
404
 
405
/* mvcomp applies the MV-COMPRESSION algorithm to data and returns the compressed size
405
/* mvcomp applies the MV-COMPRESSION algorithm to data and returns the compressed size
406
 * updates len with the number of input bytes left unprocessed */
406
 * updates len with the number of input bytes left unprocessed */
407
static unsigned short mvcomp(void *dstbuf, size_t dstbufsz, const unsigned char *src, size_t *len) {
407
static unsigned short mvcomp(void *dstbuf, size_t dstbufsz, const unsigned char *src, size_t *len, unsigned short *maxbytesahead) {
408
  unsigned short complen = 0;
408
  unsigned short complen = 0;
409
  unsigned short *dst = dstbuf;
409
  unsigned short *dst = dstbuf;
410
  unsigned short bytesprocessed = 0;
410
  unsigned short bytesprocessed = 0;
411
  unsigned char litqueue[32];
411
  unsigned char litqueue[32];
412
  unsigned char litqueuelen = 0;
412
  unsigned char litqueuelen = 0;
413
 
413
 
-
 
414
  *maxbytesahead = 0;
-
 
415
 
414
  /* read src byte by byte, len times, each time look for a match of 15,14,13..2 chars in the back buffer */
416
  /* read src byte by byte, len times, each time look for a match of 15,14,13..2 chars in the back buffer */
415
  while (*len > 0) {
417
  while (*len > 0) {
416
    unsigned short matchlen;
418
    unsigned short matchlen;
417
    unsigned short minmatch;
419
    unsigned short minmatch;
418
    unsigned short offset;
420
    unsigned short offset;
419
    matchlen = 16;
421
    matchlen = 16;
420
    if (*len < matchlen) matchlen = (unsigned short)(*len);
422
    if (*len < matchlen) matchlen = (unsigned short)(*len);
421
 
423
 
-
 
424
    /* monitor the amount of bytes that the compressed stream is "ahead" of
-
 
425
     * uncompressed data, this is an information used later to size a proper
-
 
426
     * buffer for in-place depacking */
-
 
427
    if (complen + litqueuelen + 2 > bytesprocessed) {
-
 
428
      unsigned short mvstreamlen = complen + litqueuelen + 2;
-
 
429
      if (*maxbytesahead < (mvstreamlen - bytesprocessed)) *maxbytesahead = mvstreamlen - bytesprocessed;
-
 
430
    }
-
 
431
 
422
    /* abort if no space in output buffer, but do NOT break a literal queue */
432
    /* abort if no space in output buffer, but do NOT break a literal queue */
423
    if ((complen >= dstbufsz - 32) && (litqueuelen == 0)) return(complen);
433
    if ((complen >= dstbufsz - 32) && (litqueuelen == 0)) return(complen);
424
 
434
 
425
    /* look for a minimum match of 2 bytes, unless I have some pending literal bytes
435
    /* look for a minimum match of 2 bytes, unless I have some pending literal bytes
426
     * awaiting, in which case I am going through a new data pattern and it is more
436
     * awaiting, in which case I am going through a new data pattern and it is more
Line 506... Line 516...
506
}
516
}
507
 
517
 
508
 
518
 
509
/* write the language block (id, dict, strings) into the LNG file.
519
/* write the language block (id, dict, strings) into the LNG file.
510
 * strings are compressed if compflag != 0 */
520
 * strings are compressed if compflag != 0 */
511
static int svl_write_lang(const struct svl_lang *l, FILE *fd, int compflag) {
521
static int svl_write_lang(const struct svl_lang *l, FILE *fd, int compflag, unsigned short *buffrequired) {
512
  unsigned short strings_bytes = svl_strings_bytes(l);
522
  unsigned short strings_bytes = svl_strings_bytes(l);
513
  unsigned short langid = *((unsigned short *)(&l->id));
523
  unsigned short langid = *((unsigned short *)(&l->id));
514
  const char *stringsptr = l->strings;
524
  const char *stringsptr = l->strings;
515
 
525
 
516
  /* if compressed then do the magic */
526
  /* if compressed then do the magic */
517
  if (compflag) {
527
  if (compflag) {
518
    static char compstrings[65000];
528
    static char compstrings[65000];
519
    unsigned short comp_bytes;
529
    unsigned short comp_bytes;
520
    size_t stringslen = strings_bytes;
530
    size_t stringslen = strings_bytes;
-
 
531
    unsigned short mvcompbytesahead;
521
    comp_bytes = mvcomp(compstrings, sizeof(compstrings), l->strings, &stringslen);
532
    comp_bytes = mvcomp(compstrings, sizeof(compstrings), l->strings, &stringslen, &mvcompbytesahead);
-
 
533
    if (mvcompbytesahead + stringslen > *buffrequired) {
-
 
534
      *buffrequired = mvcompbytesahead + stringslen;
-
 
535
    }
522
    if (comp_bytes < strings_bytes) {
536
    if (comp_bytes < strings_bytes) {
523
      printf("lang %c%c mvcomp-ressed (%u bytes -> %u bytes)\n", l->id[0], l->id[1], strings_bytes, comp_bytes);
537
      printf("lang %c%c mvcomp-ressed (%u bytes -> %u bytes) mvcomp stream at most %u bytes ahead of raw data (%u bytes needed for in-place decomp)\n", l->id[0], l->id[1], strings_bytes, comp_bytes, mvcompbytesahead, strings_bytes + mvcompbytesahead);
524
      langid |= 0x8000; /* LNG langblock flag that means "this lang is compressed" */
538
      langid |= 0x8000; /* LNG langblock flag that means "this lang is compressed" */
525
      strings_bytes = comp_bytes;
539
      strings_bytes = comp_bytes;
526
      stringsptr = compstrings;
540
      stringsptr = compstrings;
527
    } else {
541
    } else {
528
      printf("lang %c%c left UNCOMPRESSED (uncomp=%u bytes ; mvcomp=%u bytes)\n", l->id[0], l->id[1], strings_bytes, comp_bytes);
542
      printf("lang %c%c left UNCOMPRESSED (uncomp=%u bytes ; mvcomp=%u bytes)\n", l->id[0], l->id[1], strings_bytes, comp_bytes);
Line 546... Line 560...
546
  fd = fopen(fn, "wb");
560
  fd = fopen(fn, "wb");
547
  if (fd == NULL) {
561
  if (fd == NULL) {
548
    return(0);
562
    return(0);
549
  }
563
  }
550
 
564
 
551
  /* the maximum mvcomp overhead is 3.23% (ie. an increase of 1 byte for every
-
 
552
   * 31 bytes of source, because 31 source bytes are encoded as a 32 bytes
-
 
553
   * sequence). The necessary buffer for in-place decompression is therefore
-
 
554
   * FILESIZE + (FILESIZE / 31) + 1 */
-
 
555
  allocsz = biggest_langsz + (biggest_langsz / 31) + 1;
565
  allocsz = biggest_langsz + (biggest_langsz / 20);
556
  printf("biggest lang block is %u bytes -> allocating a %u bytes buffer (3.23%% margin for inplace mvcomp decompression)\n", biggest_langsz, allocsz);
566
  printf("biggest lang block is %u bytes -> allocating a %u bytes buffer (5%% safety margin)\n", biggest_langsz, allocsz);
557
  fprintf(fd, "/* THIS FILE HAS BEEN GENERATED BY TLUMACZ (PART OF THE SVARLANG LIBRARY) */\r\n");
567
  fprintf(fd, "/* THIS FILE HAS BEEN GENERATED BY TLUMACZ (PART OF THE SVARLANG LIBRARY) */\r\n");
558
  fprintf(fd, "const unsigned short svarlang_memsz = %uu;\r\n", allocsz);
568
  fprintf(fd, "const unsigned short svarlang_memsz = %uu;\r\n", allocsz);
559
  fprintf(fd, "const unsigned short svarlang_string_count = %uu;\r\n\r\n", l->num_strings);
569
  fprintf(fd, "const unsigned short svarlang_string_count = %uu;\r\n\r\n", l->num_strings);
560
  fprintf(fd, "char svarlang_mem[%u] = {\r\n", allocsz);
570
  fprintf(fd, "char svarlang_mem[%u] = {\r\n", allocsz);
561
 
571
 
Line 744... Line 754...
744
 
754
 
745
    /* write lang ID to file, followed string table size, and then
755
    /* write lang ID to file, followed string table size, and then
746
       the dictionary and string table for current language
756
       the dictionary and string table for current language
747
       skip this for reference language if /excref given */
757
       skip this for reference language if /excref given */
748
    if ((reflang != NULL) || (excref == 0)) {
758
    if ((reflang != NULL) || (excref == 0)) {
-
 
759
      /* also updates the biggest_langsz variable to accomodate enough space
-
 
760
       * for in-place decompression of mvcomp-compressed lang blocks */
749
      if (!svl_write_lang(lang, fd, mvcomp_enabled)) {
761
      if (!svl_write_lang(lang, fd, mvcomp_enabled, &biggest_langsz)) {
750
        fprintf(stderr, "ERROR WRITING TO OUTPUT FILE\r\n");
762
        fprintf(stderr, "ERROR WRITING TO OUTPUT FILE\r\n");
751
        ecode = 1;
763
        ecode = 1;
752
        goto exit_main;
764
        goto exit_main;
753
      }
765
      }
754
    } else {
766
    } else {