diff options
| author | Pixel <Pixel> | 2002-07-19 12:52:47 +0000 | 
|---|---|---|
| committer | Pixel <Pixel> | 2002-07-19 12:52:47 +0000 | 
| commit | 492ca575941d0e30b3725bf7a9966cab8df7e238 (patch) | |
| tree | 5cd34563c530988291691bd0a2a671e1a416b0e2 /lib/dteutils.cpp | |
| parent | 2d5f7c1052fb4206cc46fffe236ebfcac4ee316f (diff) | |
Moved everything in the right place. Cleaner now.
Diffstat (limited to 'lib/dteutils.cpp')
| -rw-r--r-- | lib/dteutils.cpp | 342 | 
1 files changed, 342 insertions, 0 deletions
| diff --git a/lib/dteutils.cpp b/lib/dteutils.cpp new file mode 100644 index 0000000..4ae8668 --- /dev/null +++ b/lib/dteutils.cpp @@ -0,0 +1,342 @@ +/* + *  PSX-Tools Bundle Pack + *  Copyright (C) 2002 Nicolas "Pixel" Noble + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include "fileutils.h" +#include "generic.h" + +class thingtree { +  public: +    static void addstring(const char *, long); +    static long look(const char *); +    static void destroy(); +  private: +      thingtree(); +      thingtree(char, bool, thingtree *, long); +      ~thingtree(); +    char thischar; +    bool terminal; +    thingtree * father, * child, * brother; +    long thingentry; +    static thingtree * root; +}; + +thingtree * thingtree::root = 0; + +thingtree::thingtree(char gchar, bool gterm, thingtree * gfather, long gthingentry) : thischar(gchar), terminal(gterm), thingentry(gthingentry) { +    if (!gfather) { +	if (!root) { +	    root = new thingtree(); +	} +	father = root; +    } else { +	father = gfather;	 +    } +    brother = father->child; +    father->child = this; +} + +thingtree::thingtree() : thischar(0), terminal(false), father(0), child(0), brother(0) { } + +long thingtree::look(const char * s) { +    const char * p; +    long currentthing = -1; +    thingtree * ptr = root; +     +    if (!ptr) { +	printm(M_ERROR, "Error: thingtree not initialised\n"); +	exit(-1); +    } +     +    for (p = s; *p; p++) { +//	printm(M_INFO, "Looking for '%c'\n", *p); +	for (ptr = ptr->child; ptr; ptr = ptr->brother) { +//	    printm(M_INFO, "Looking in %p: %c\n", ptr, ptr->thischar); +	    if (ptr->thischar == *p) { +		if (ptr->terminal) { +		    currentthing = ptr->thingentry; +		} +		break; +	    } +	} +	if (!ptr) { +//	    printm(M_INFO, "Not found.\n"); +	    break; +	} +    } +     +    if (currentthing == -1) { +	printm(M_ERROR, "Error, can't find any entry for string '%s'\n", s); +    } +     +    return currentthing; +} + +void thingtree::addstring(const char * s, long thingentry) { +    const char * p; +    thingtree * ptr, * fptr; +     +    if (!root) { +	root = new thingtree(); +    } +     +//    printm(M_INFO, "Creating new thingtree entry: %li='%s'\n", thingentry, s); +     +    ptr = root; +    for (p = s; *p; p++) { +	fptr = ptr; +//	printm(M_INFO, "Finding entry for '%c'\n", *p); +	for (ptr = ptr->child; ptr; ptr = ptr->brother) { +//	    printm(M_INFO, "Browsing childs: %p = %c\n", ptr, ptr->thischar); +	    if (ptr->thischar == *p) +		break; +	} +	 +	if (!ptr) { +//	    printm(M_INFO, "Creating new branch for %c\n", *p); +	    ptr = new thingtree(*p, *(p + 1) == 0, fptr, thingentry); +//	    printm(M_INFO, "Created branch %p\n", ptr); +	} else { +	    if (*(p + 1) == 0) { +		ptr->terminal = true; +		ptr->thingentry = thingentry; +	    } +	} +    } +} + +void thingtree::destroy() { +    delete root; +    root = 0; +} + +thingtree::~thingtree() { +    if (father->child == this) +	father->child = brother; +     +    while (child) +	delete child; +} + +char * things[256]; + +char * dte_text; +char dte_flags[256 * 256]; +long dte_counters[256 * 256]; +long dte_entries[256]; +char alloweds[256]; +long dte_usage[256]; + +long dte_most; +long dte_counter; +long dte_text_size; +int dte_size; +long gain; +long nb_dte = 0; +long tnb_dte = 0; + +void dte_reset(void) { +    memset(dte_counters, 0, 0x40000); +    dte_most = 0; +    dte_counter = 0; +} + +void build_dte(void) { +    int i; +    unsigned short t, t2; +    unsigned short p = 0; +     +    for (i = 0; i < dte_text_size; i++) { +	t = *((unsigned short *) (dte_text + i)); +	t2 = *((unsigned short *) (dte_text + i + 1)); +	if (t == p) { +	    p = 0; +	    continue; +	} +	p = t; +	if (!dte_flags[t]) { +//	if ((!dte_flags[t]) && (dte_flags[t2] != 3)) { +	    if ((dte_counters[t]++) == 0) { +		nb_dte++; +	    } +	    if (dte_counters[t] > dte_counter) { +		dte_most = t; +		dte_counter = dte_counters[t]; +	    } +//	} else if (dte_flags[t] == 3) { +//	    i++; +	} +    } +} + +void push_entry(long entry) { +    int i; +    char t[3], c1, c2; +    t[2] = 0; +     +    c1 = dte_most & 0xff; +    c2 = dte_most >> 8; +    t[0] = things[c1][0]; +    t[1] = things[c2][0]; + +    for (i = 0; i < 256; i++) { +	if (!dte_entries[i]) { +	    dte_entries[i] = entry; +	    things[i] = strdup(t); +	    thingtree::addstring(t, i); +	    break; +	} +    } +} + +char * read_line(FILE * f, char * b) { +    int r, pos = 0; + +    while (!feof(f)) { +	if ((r = fgetc(f)) == EOF) +	    break; +	if (r == 0x0d) { +	    if ((r = fgetc(f)) == EOF) +		break; +	} +	if (r == 0x0a) { +	    b[pos] = 0; +	    return b; +	} +	b[pos++] = r; +    } +     +    b[pos] = 0; +     +    return b; +} + +void dte_compress() { +    int i, j; +    char c1, c2; +     +    for (i = 0; i < 256; i++) { +	for (j = 0; j < 256; j++) { +	    dte_flags[i * 256 + j] = alloweds[i] ? alloweds[j] ? 0 : 1 : 1; +	} +    } +     +    gain = 0; +     +    printm(M_STATUS, "Going for it: dte_size = %i\n", dte_size); +    for (i = 0; i < dte_size; i++) { +	dte_reset(); +	build_dte(); +	if (!tnb_dte) +	    tnb_dte = nb_dte; +	c1 = dte_most & 0xff; +	c2 = dte_most >> 8; +	c1 = things[c1][0]; +	c2 = things[c2][0]; +	printm(M_INFO, "Entry #%i, most count: %li, couple = 0x%04x = (%c %c)\n", i, dte_counter, (int) dte_most, c1, c2); +	dte_flags[dte_most] = 3; +	gain += dte_counter; +	push_entry(dte_most); +    } +     +    printm(M_STATUS, "Estimated gain: %li bytes, new file size = %li\n", gain, dte_text_size - gain); +} + +void read_thingy(FILE * f) { +    char line[256], * st, * thing; +    long code; +    int i; +     +    st = line + 2; +    thing = line + 5; +    line[0] = '0'; +    line[1] = 'x'; +     +    dte_size = 0; +     +    for (i = 0; i < 256; i++) { +	dte_entries[i] = -1; +    } +     +    while (!feof(f)) { +	if (strlen(read_line(f, st))) { +	    line[4] = 0; +	    sscanf(line, "%li", &code); +	    switch (strlen(thing)) { +	    case 0: +		dte_size++; +		dte_entries[code] = 0; +		break; +	    case 1: +		alloweds[code] = 1; +	    default: +		things[code] = strdup(thing); +		thingtree::addstring(thing, code); +	    } +	} +    } +} + +void read_thingy_file(FILE * f) { +    char line[10240], * p, * c, trans[5]; +    long code; +    int ptr = 0, i; +     +    for (i = 0; i < 256; i++) { +	dte_usage[i] = 0; +    } +     +    while (!feof(f)) { +	if (!strlen(p = read_line(f, line))) +	    continue; +	while (*p) { +	    if (*p == '<') { +		if (!(c = strchr(p, '>'))) { +		    printm(M_ERROR, "Error in file: '<' not closed.\n"); +		    exit(-1); +		} +		p++; +		if ((c - p) == 2) { +		    *c = 0; +		    sprintf(trans, "0x%s", p); +		    sscanf(trans, "%li", &code); +		    dte_text[ptr++] = code; +		    printm(M_BARE, "0x%02x-", code); +		} else { +		    printm(M_BARE, "Unknow %s-", p); +		} +		p = c + 1; +	    } else { +		if ((code = thingtree::look(p)) == -1) +		    exit(-1); +		dte_text[ptr++] = code; +		p += strlen(things[code]); +		printm(M_BARE, "%s-", things[code]); +		dte_usage[code]++; +	    } +	} +	printm(M_BARE, "\n"); +    } +     +    dte_text[ptr] = dte_text[ptr + 1] = dte_text[ptr + 2] = dte_text[ptr + 3] = 0; +    dte_text_size = ptr; +} | 
