From 6358fb3415cf9c2275fe8fa9dd333d9b516bf510 Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Mon, 18 May 2026 12:36:54 -0400 Subject: [PATCH] Commit code, circa 2006 --- Makefile | 69 + gcmbrowser.bakvpj | 215 +++ gcmbrowser.bakvpw | 6 + gcmbrowser.vpj | 221 +++ gcmbrowser.vpw | 10 + gcmbrowser.vpwhistu | 52 + gcmbrowser.vtg | Bin 0 -> 90112 bytes source/.svn/all-wcprops | 47 + source/.svn/entries | 269 +++ source/.svn/prop-base/Makefile.svn-base | 5 + source/.svn/prop-base/README.txt.svn-base | 5 + source/.svn/prop-base/gcmbrowser.cpp.svn-base | 5 + source/.svn/prop-base/gcminfo.cpp.svn-base | 5 + source/.svn/prop-base/gcminfo.h.svn-base | 5 + .../.svn/prop-base/sample-output.txt.svn-base | 5 + .../.svn/prop-base/std_disclaimer.h.svn-base | 5 + source/.svn/text-base/Makefile.svn-base | 94 + source/.svn/text-base/README.txt.svn-base | 26 + source/.svn/text-base/gcmbrowser.cpp.svn-base | 163 ++ source/.svn/text-base/gcminfo.cpp.svn-base | 674 +++++++ source/.svn/text-base/gcminfo.h.svn-base | 217 +++ .../.svn/text-base/sample-output.txt.svn-base | 1709 +++++++++++++++++ .../.svn/text-base/std_disclaimer.h.svn-base | 13 + source/CVS/.svn/all-wcprops | 23 + source/CVS/.svn/entries | 130 ++ source/CVS/.svn/text-base/Entries.svn-base | 8 + source/CVS/.svn/text-base/Repository.svn-base | 1 + source/CVS/.svn/text-base/Root.svn-base | 1 + source/CVS/Entries | 8 + source/CVS/Repository | 1 + source/CVS/Root | 1 + source/Makefile | 94 + source/README.txt | 26 + source/gcmbrowser.cpp | 163 ++ source/gcminfo.cpp | 674 +++++++ source/gcminfo.h | 217 +++ source/sample-output.txt | 1709 +++++++++++++++++ source/std_disclaimer.h | 13 + 38 files changed, 6889 insertions(+) create mode 100755 Makefile create mode 100755 gcmbrowser.bakvpj create mode 100755 gcmbrowser.bakvpw create mode 100755 gcmbrowser.vpj create mode 100755 gcmbrowser.vpw create mode 100755 gcmbrowser.vpwhistu create mode 100755 gcmbrowser.vtg create mode 100755 source/.svn/all-wcprops create mode 100755 source/.svn/entries create mode 100755 source/.svn/prop-base/Makefile.svn-base create mode 100755 source/.svn/prop-base/README.txt.svn-base create mode 100755 source/.svn/prop-base/gcmbrowser.cpp.svn-base create mode 100755 source/.svn/prop-base/gcminfo.cpp.svn-base create mode 100755 source/.svn/prop-base/gcminfo.h.svn-base create mode 100755 source/.svn/prop-base/sample-output.txt.svn-base create mode 100755 source/.svn/prop-base/std_disclaimer.h.svn-base create mode 100755 source/.svn/text-base/Makefile.svn-base create mode 100755 source/.svn/text-base/README.txt.svn-base create mode 100755 source/.svn/text-base/gcmbrowser.cpp.svn-base create mode 100755 source/.svn/text-base/gcminfo.cpp.svn-base create mode 100755 source/.svn/text-base/gcminfo.h.svn-base create mode 100755 source/.svn/text-base/sample-output.txt.svn-base create mode 100755 source/.svn/text-base/std_disclaimer.h.svn-base create mode 100755 source/CVS/.svn/all-wcprops create mode 100755 source/CVS/.svn/entries create mode 100755 source/CVS/.svn/text-base/Entries.svn-base create mode 100755 source/CVS/.svn/text-base/Repository.svn-base create mode 100755 source/CVS/.svn/text-base/Root.svn-base create mode 100755 source/CVS/Entries create mode 100755 source/CVS/Repository create mode 100755 source/CVS/Root create mode 100755 source/Makefile create mode 100755 source/README.txt create mode 100755 source/gcmbrowser.cpp create mode 100755 source/gcminfo.cpp create mode 100755 source/gcminfo.h create mode 100755 source/sample-output.txt create mode 100755 source/std_disclaimer.h diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..7304636 --- /dev/null +++ b/Makefile @@ -0,0 +1,69 @@ +# This makefile is a bit hackish. I wrote it early in the AM. +# Fohgiveuhness, please!! + +ifndef $(CFG) + CFG=Debug +endif + +TARGET=libgcm +PROJECTHOME=$(shell pwd) +LIBDIR=/usr/lib +HEADERDIR=/usr/include + +ifeq "$(CFG)" "Debug" + OUTDIR=Debug + LIBTARGET=$(TARGET)-dbg.so + LINKLIB=gcm-dbg +# CFLAGS really should be -Werror... + CFLAGS=-g -ggdb -gstabs -Wall -c + LDFLAGS=-shared -fPIC -o $(OUTDIR)/$(LIBTARGET) +endif + +ifeq "$(CFG)" "Release" + OUTDIR=Release + LIBTARGET=$(TARGET).so + LINKLIB=gcm + CFLAGS=-O2 -fomit-frame-pointer -pipe -c + LDFLAGS=-shared -fPIC -o $(OUTDIR)/$(LIBTARGET) +endif + +LIBSRC=source/gcminfo.cpp +TESTSRC=source/gcmbrowser.cpp + +LIBOBJ=$(OUTDIR)/gcminfo.o +TESTOBJ=$(OUTDIR)/gcmbrowser.o + +CC = gcc +CXX = g++ +LD = $(CXX) + + +$(OUTDIR)/%.o : source/%.cpp + $(CXX) $(CFLAGS) -o $@ $< + +all: lib bin + +lib: $(LIBOBJ) $(TESTOBJ) + $(LD) $(LDFLAGS) $(LIBOBJ) + +bin: + $(LD) -o $(OUTDIR)/gcmbrowser \ + $(LIBOBJ) $(TESTOBJ) + + +.PHONY: clean +clean: + rm $(OUTDIR)/*.o + rm $(OUTDIR)/gcmbrowser + rm $(OUTDIR)/$(LIBTARGET) + +.PHONY: rebuild +rebuild: + make clean + make CFG=$(CFG) + + +.PHONY: install +install: + $(INSTALL) $(OUTDIR)/$(LIBTARGET) $(LIBDIR)/$(TARGET) + $(INSTALL) source/gcminfo.h $(HEADERDIR)/libgcm.h diff --git a/gcmbrowser.bakvpj b/gcmbrowser.bakvpj new file mode 100755 index 0000000..242f865 --- /dev/null +++ b/gcmbrowser.bakvpj @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gcmbrowser.bakvpw b/gcmbrowser.bakvpw new file mode 100755 index 0000000..02a8993 --- /dev/null +++ b/gcmbrowser.bakvpw @@ -0,0 +1,6 @@ + + + + + + diff --git a/gcmbrowser.vpj b/gcmbrowser.vpj new file mode 100755 index 0000000..a151818 --- /dev/null +++ b/gcmbrowser.vpj @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gcmbrowser.vpw b/gcmbrowser.vpw new file mode 100755 index 0000000..788eb4b --- /dev/null +++ b/gcmbrowser.vpw @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/gcmbrowser.vpwhistu b/gcmbrowser.vpwhistu new file mode 100755 index 0000000..eb40ca1 --- /dev/null +++ b/gcmbrowser.vpwhistu @@ -0,0 +1,52 @@ +[Global] +CurrentProject=gcmbrowser.vpj +[ProjectDates] +gcmbrowser.vpj=20060801143843000 +[ActiveConfig] +gcmbrowser.vpj=,Debug +[TreeExpansion2] +- gcmbrowser.vpj + - Source Files + - Header Files + - Resource Files + - Bitmaps + - Other Files +scroll:0 +[State] +SCREEN: 1600 1200 73 36 1121 898 0 0 N 0 0 0 0 893 567 +CWD: ../stlini/ +BUFFER: BN="source/std_disclaimer.h" +BI: MA=1 74 1 TABS=1 5 WWS=1 IWT=1 ST=0 IN=2 BW=0 US=32000 RO=0 SE=1 SN=0 BIN=0 MN=C HM=0 MF=808 TL=0 MLL=0 ASE=0 LNL=6 LCF=0 CAPS=0 E=0 ESBU2=-1 +VIEW: LN=.0 CL=1 LE=0 CX=1 CY=0 WI=5 BI=36 HT=0 HN=0 HF=0 HC=4 +BUFFER: BN="source/gcmbrowser.cpp" +BI: MA=1 74 1 TABS=1 5 WWS=1 IWT=1 ST=0 IN=2 BW=0 US=32000 RO=0 SE=1 SN=0 BIN=0 MN=C HM=0 MF=8 TL=0 MLL=0 ASE=0 LNL=6 LCF=0 CAPS=0 E=0 ESBU2=-1 +VIEW: LN=.0 CL=1 LE=0 CX=1 CY=1 WI=5 BI=35 HT=0 HN=0 HF=0 HC=4 +BUFFER: BN="source/gcminfo.h" +BI: MA=1 74 1 TABS=1 5 WWS=1 IWT=1 ST=0 IN=2 BW=0 US=32000 RO=0 SE=1 SN=0 BIN=0 MN=C HM=0 MF=872 TL=0 MLL=0 ASE=0 LNL=6 LCF=0 CAPS=0 E=0 ESBU2=-1 +VIEW: LN=.8219 CL=15 LE=0 CX=15 CY=22 WI=5 BI=13 HT=0 HN=0 HF=0 HC=4 +BUFFER: BN="source/gcminfo.cpp" +BI: MA=1 74 1 TABS=1 5 WWS=1 IWT=1 ST=0 IN=2 BW=0 US=32000 RO=0 SE=1 SN=0 BIN=0 MN=C HM=0 MF=872 TL=0 MLL=0 ASE=0 LNL=6 LCF=0 CAPS=0 E=0 ESBU2=-1 +VIEW: LN=.14666 CL=1 LE=0 CX=1 CY=2 WI=5 BI=40 HT=0 HN=0 HF=0 HC=4 +WINDOW: 25 25 602 382 0 0 N WF=0 WT=4 "Default Fixed Font,10,0,1" +BUFFER: BN="source/gcminfo.h" +VIEW: LN=.8219 CL=15 LE=0 CX=15 CY=22 WI=278 BI=13 HT=0 HN=0 HF=0 HC=4 +WINDOW: 0 0 604 446 0 0 N WF=0 WT=2 "OEM Fixed Font,10,0,1" +BUFFER: BN="source/gcmbrowser.cpp" +VIEW: LN=.0 CL=1 LE=0 CX=1 CY=0 WI=253 BI=35 HT=0 HN=0 HF=0 HC=4 +WINDOW: 162 160 602 382 0 0 N WF=0 WT=3 "Default Fixed Font,10,0,1" +BUFFER: BN="source/std_disclaimer.h" +VIEW: LN=.0 CL=1 LE=0 CX=1 CY=0 WI=281 BI=36 HT=0 HN=0 HF=0 HC=4 +WINDOW: 0 0 604 445 0 0 N WF=0 WT=1 "OEM Fixed Font,10,0,1" +BUFFER: BN="source/gcminfo.cpp" +VIEW: LN=.15877 CL=13 LE=0 CX=13 CY=20 WI=68 BI=40 HT=0 HN=0 HF=0 HC=4 +FILEHIST: 5 +source/gcmbrowser.cpp +source/README.txt +source/gcminfo.cpp +source/gcminfo.h +source/std_disclaimer.h +DEBUG: 0 0 0 0 4 0 +printf +strcpy +std::* +######## diff --git a/gcmbrowser.vtg b/gcmbrowser.vtg new file mode 100755 index 0000000000000000000000000000000000000000..4cb024f844329adddf7fea0af974677ee40ebb56 GIT binary patch literal 90112 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 +#include + +// All the interesting stuff is in gcminfo.c|h ; gcmbrowser.cpp is just a proof +// and simple util. + +const char *usage = +"gcmbrowser V0.01 (C) 2005 Andrew Kesterson (andrew@aklabs.net) \n\ +\n\ +Usage: gcmbrowser <.gcm file> \n\ +\n\ +operations:\n\ + -h : print this help\n\ + -H : print the disk header (maker, title, etc)\n\ + -E : explode the filesystem into the current directory\n\ + -e : extract \"file\" from the gcm. With -o you\n\ + may specify an optional output filename; by default,\n\ + the file will be named the same (and reside in the\n\ + same directory tree) as in the image. You may specify\n\ + the source file by file number or by filename (full path\n\ + is necessary when specifying by filename.)\n\ + -o : specify the destination for a -e operation.\n\ + -l : list the names and file numbers of all files in the GCM.\n\ + All files are printed with full path.\n\ + -d : when extracting a file, create all needed directories for\n\ + the output file. This can, but really shouldn't, be used with\n\ + the -o option.\n\ +\n"; + +const char *shortopts = "hHEe:o:ld"; + +#define OP_PRINT_HEADER 0 +#define OP_EXPLODE 2 +#define OP_EXTRACT 4 +#define OP_LIST 8 +#define OP_CREATE_DIRS 1024 + +int main(int argc, char **argv) +{ + std::string gcmFname; + std::string outFname; + std::string extractFname; + unsigned int extractFnumber= -1; + int outIsDigit = 1; + int ctr = 0; + int op = 0; + GCM theGCM; + unsigned int opt = 0; + unsigned int ret = 0; + + if ( argc < 2 ) { + fprintf(stderr, usage); + return 1; + } + + opt = getopt(argc, argv, shortopts); + while ( opt != -1) { + switch ( opt ){ + case 'h': + fprintf(stderr, usage); + return 1; + case 'H': + op = OP_PRINT_HEADER; + break; + case 'E': + op = OP_EXPLODE; + break; + case 'e': + op = OP_EXTRACT; + for ( ctr = 0; ctr < strlen(optarg) ; ctr++ ) { + if ( isprint(optarg[ctr]) && !isdigit(optarg[ctr])) { + outIsDigit = 0; + } else { + //printf("DEBUG : extract filename character %c is a digit\n", optarg[ctr]); + continue; + } + } + if ( outIsDigit == 0 ) { + //printf("DEBUG : extract filename option is NON-DIGIT %s\n", optarg); + extractFname.reserve(strlen(optarg)); + extractFname.assign(optarg); + break; + } + else { + //printf("DEBUG : extract filename option is file number %s\n", optarg); + extractFnumber = atoi(optarg); + break; + } + case 'o': + outFname.reserve(strlen(optarg)); + outFname.assign(optarg); + break; + case 'l': + op = OP_LIST; + break; + case 'd': + op |= OP_CREATE_DIRS; + break; + default: + fprintf(stderr, "I don't understand option -%c\n", opt); + return 1; + } + opt = getopt(argc, argv, shortopts); + } + gcmFname.reserve(strlen(argv[optind])); + gcmFname.assign(argv[optind]); + + if ( gcmInit((char *)gcmFname.c_str(), &theGCM) ) { + printf("Couldn't init GCM file %s\n", argv[1]); + return 1; + } + + int top = 0; + if ( op & OP_CREATE_DIRS ) top = op ^ OP_CREATE_DIRS; + else top = op; + switch ( top ) { + case OP_EXPLODE: + ret = gcmExplode(&theGCM); + if ( ! ret ) + fprintf(stderr, "Failed to explode filesystem.\n"); + break; + case OP_EXTRACT: + if ( extractFnumber == -1 ) { + //printf("DEBUG : getting file number for %s\n", extractFname.c_str()); + extractFnumber = gcmGetFileByName(&theGCM, (char *)extractFname.c_str()); + //printf("DEBUG: got %d\n", extractFnumber); + } + if ( extractFnumber > theGCM.fst.stringtable.size() || extractFnumber == -1) { + fprintf(stderr, "File number %d requested was beyond the length of the filesystem\n", extractFnumber); + break; + } + if ( outFname.length() == 0 && ( op & OP_CREATE_DIRS ) ) { + char *outfile = (char *) new char[GCNDVD_FNAME_LENGTH]; + gcmGetFullFileName(&theGCM, extractFnumber, outfile); + std::string execstring = ""; + // this is a quick hack to ensure that the output directory exists + execstring.append("mkdir -p ."); + execstring.append("`dirname "); + execstring.append(outfile); + execstring.append("`"); + system(execstring.c_str()); + delete outfile; + } + if ( outFname.length() > 0 ) + ret = gcmExtractFile(&theGCM, extractFnumber, (char *)outFname.c_str()); + else + ret = gcmExtractFile(&theGCM, extractFnumber, NULL); + if ( ret != 0 ) + fprintf(stderr, "Failed to extract file number %d to output file %s\n", extractFnumber, outFname.length() > 0 ? (char *)outFname.c_str() : "" ); + break; + case OP_PRINT_HEADER: + ret = gcmPrint(&theGCM); + break; + case OP_LIST: + ret = gcmPrintFST(&theGCM); + break; + } + + gcmFreeStringTable(&theGCM); + + return ret; +} diff --git a/source/.svn/text-base/gcminfo.cpp.svn-base b/source/.svn/text-base/gcminfo.cpp.svn-base new file mode 100755 index 0000000..6d8d4f2 --- /dev/null +++ b/source/.svn/text-base/gcminfo.cpp.svn-base @@ -0,0 +1,674 @@ +#include "gcminfo.h" +#include +#include +#include + +int needByteSwap = 0; + +// these are functions that the user really doesn't need to see, +// so they're declared here away from the external API. They're +// used mainly for populating the internal FST data structure. +// All the user-necessary functions are listed out in gcminfo.h. + +int gcmPopulateFST(GCM *data, FILE *file); +void *gcmWhichData(int whichdata, GCM *data); +int gcmGetData(int whichdata, GCM *data, FILE *file); +int gcmGetFile(GCM *data, GCM_FSTEntry *entry, int fnum, FILE *file); +int gcmCheckMagic(FILE *file); + +// checks the magic number of the DVD file, and sets needByteSwap +// returns the final value of needByteSwap. Returns -1 if the magic +// word doesn't match either way and needByteSwap couldn't be set. +int gcmCheckMagic(FILE *file) +{ + int magic = 0; + fseek(file, GCMPieces[GCM_DHEAD_DVDMAGIC].offset, 0); + fread(&magic, GCMPieces[GCM_DHEAD_DVDMAGIC].size, 1, file); + + if ( magic == GCNDVD_MAGICNUM ) { + needByteSwap = 0; + } else { + magic = (((magic&0x000000FF)<<24)+((magic&0x0000FF00)<<8)+ + ((magic&0x00FF0000)>>8)+((magic&0xFF000000)>>24)); + if ( magic == GCNDVD_MAGICNUM ) { + needByteSwap = 1; + } + else needByteSwap = -1; + } + + return needByteSwap; +} + +// swap from big to little endian (only needed on intel machines) +// only works if needByteSwap is > -1 +int byteSwap (int nLongNumber) +{ + if ( needByteSwap ) return (((nLongNumber&0x000000FF)<<24)+((nLongNumber&0x0000FF00)<<8)+ + ((nLongNumber&0x00FF0000)>>8)+((nLongNumber&0xFF000000)>>24)); + else if ( needByteSwap == -1 ) return 0; // refuse to work +} + +// return the type (0=file 1=directory) for the given FST entry +int gcmGetFSTEntryType(GCM_FSTEntry *entry) +{ + return entry->fname_offset >> 24; +} + +// uses one of the GCM_* definitions to return a pointer to +// the appropriate point of the GCM struct to read data into. +void *gcmWhichData(int whichdata, GCM *data) +{ + void *toPrint = NULL; + + switch (whichdata) { + case GCM_DHEAD_GAMECODE: + toPrint = &data->head.gamecode; + break; + case GCM_DHEAD_GAMEMAKER: + toPrint = &data->head.gamemaker; + break; + case GCM_DHEAD_DVDMAGIC: + toPrint = &data->head.magicword; + break; + case GCM_DHEAD_GAMENAME: + toPrint = &data->head.gamename; + break; + case GCM_DHEAD_DEBUGMON: + toPrint = &data->head.debugmon; + break; + case GCM_DHEAD_DEBUGMONADDR: + toPrint = &data->head.debugmonaddr; + break; + case GCM_DHEAD_BOOTFILE: + toPrint = &data->head.bootfile; + break; + case GCM_DHEAD_FST: + toPrint = &data->fst.offset; + break; + case GCM_DHEAD_FSTSIZE: + toPrint = &data->fst.size; + break; + case GCM_DHEAD_FSTMAXSIZE: + toPrint = &data->fst.maxsize; + break; + case GCM_DHEAD_USERPOS: + toPrint = &data->head.userpos; + break; + case GCM_DHEAD_USERLEN: + toPrint = &data->head.userlen; + break; + case GCM_DHEADINF_DEBUGMONSIZE: + toPrint = &data->headInf.debugmonsize; + break; + case GCM_DHEADINF_SIMMEMSIZE: + toPrint = &data->headInf.simmemsize; + break; + case GCM_DHEADINF_ARGOFFSET: + toPrint = &data->headInf.simmemsize; + break; + case GCM_DHEADINF_DEBUGFLAG: + toPrint = &data->headInf.debugflag; + break; + case GCM_DHEADINF_TRACKLOCATION: + toPrint = &data->headInf.tracklocation; + break; + case GCM_DHEADINF_TRACKSIZE: + toPrint = &data->headInf.tracksize; + break; + case GCM_DHEADINF_COUNTRYCODE: + toPrint = &data->headInf.countrycode; + break; + case GCM_APPLOADER_VERSION: + toPrint = &data->apploader.datever; + break; + case GCM_APPLOADER_ENTRY: + toPrint = &data->apploader.entry; + break; + case GCM_APPLOADER_SIZE: + toPrint = &data->apploader.size; + break; + case GCM_APPLOADER_TRAILERSIZE: + toPrint = &data->apploader.trailersize; + break; + case GCM_APPLOADER_BINARY: + toPrint = &data->apploader.apploader; + break; + case GCM_FST_ROOT: + toPrint = (void *)"Not implemented yet"; + break; + case GCM_FST_STRINGTABLEOFF: + toPrint = &data->fst.stringtable_offset; + break; + default: + return NULL; + } + + return toPrint; +} + +// print the info in data as indicated by the GCM_* +// passed to whichdata +int gcmPrintData(int whichdata, GCM *data) +{ + void *ptr; + if ( GCMPieces[whichdata].type == 1) { + char *theData = (char *)gcmWhichData(whichdata,data); + printf("%-38s:\t %s\n", GCMPieces[whichdata].name, theData); + } + else { + int *theData = (int *)gcmWhichData(whichdata,data); + if ( theData ) { + printf("%-38s:\t %x\n", GCMPieces[whichdata].name, *theData); + } + else { + printf("%-38s:\t refusing to print NULL pointer...\n", + "(untested function/invalid data)"); // this means you're using a feature that doesn't work (yet) + } + } +} + +// print the information for a given file in data (by entry num) +int gcmPrintFile(GCM *data, int fnum) +{ + GCM_FSTEntry f; + char *fname = NULL; + + // printf("DEBUG : retrieving file data for number %d\n", fnum); + f = data->fst.entries.at(fnum); + + // see gcmPrint for how this is laid out... + if ( fnum >= data->fst.entries.size() ) + fname = "(out_of_bounds string)" ; + else + fname = (char *)data->fst.stringtable.at(fnum)->c_str(); + + printf("%-20s%-6d%-6x%-12x%-20d\n", + fname, + fnum, + gcmGetFSTEntryType(&f), + f.file_offset, + f.file_length); +} + +// reads data into dest and returns the number of bytes read +// (only used internally by the other gcm functions, this should +// be transparent outside the API guts) +int gcmGetData(int whichdata, GCM *data, FILE *file) +{ + int offset = 0; + void *dest = gcmWhichData(whichdata, data); + if ( whichdata > GCM_MAX_PIECES || dest == NULL || file == NULL) { + return 0; + } + + switch ( GCMPieces[whichdata].area ) { + case 0: + offset = GCMPieces[whichdata].offset; + break; + case 1: + offset = GCMPieces[GCM_DHEAD].offset + GCMPieces[whichdata].offset; + break; + case 2: + offset = GCMPieces[GCM_DHEADINF].offset + GCMPieces[whichdata].offset; + break; + case 3: + offset = GCMPieces[GCM_APPLOADER].offset + GCMPieces[whichdata].offset; + break; + case 4: + offset = data->fst.offset + GCMPieces[whichdata].offset; + default: + return 0; + } + + fseek(file, offset, 0); + if ( GCMPieces[whichdata].type == 1 ) { + fgets((char *)dest, GCMPieces[whichdata].size, file) == NULL; + } + else { + fread(dest, 1, GCMPieces[whichdata].size, file); + int *tmp = (int *)dest; + *tmp = byteSwap(*tmp); + } + rewind(file); + return GCMPieces[whichdata].size; +} + +// get the file at fnum from file for the GCM data and store it +// in entry +int gcmGetFile(GCM *data, GCM_FSTEntry *entry, int fnum, FILE *file) +{ + if ( fnum > -1 && file != NULL ) { + rewind(file); + fseek(file, data->fst.offset + (12 * fnum), 0); + + if ( !feof(file) ) { + fread(&entry->fname_offset, 4, 1, file); + entry->fname_offset = byteSwap(entry->fname_offset); + fread(&entry->file_offset, 4, 1, file); + entry->file_offset = byteSwap(entry->file_offset); + fread(&entry->file_length, 4, 1, file); + entry->file_length = byteSwap(entry->file_length); + data->fst.entries.push_back(*entry); + } + } + else return -1; +} + +// populate the FST of the given GCM from file +int gcmPopulateFST(GCM *data, FILE *file) +{ + GCM_FSTEntry *newEntry; + GCM_FSTEntry root; + int i = 0; + int j = 0; + int oldpos = 0; + int maxentries = 0; + char *tmpbuff = new char[GCNDVD_FNAME_LENGTH]; + std::string * strdest = new std::string(""); + char tmp = 0xFF; + int f = 0; + int *appSize = NULL; + + if ( !tmpbuff ) { + return -1; + } + + fseek(file, data->fst.offset, 0); + + // now just loop until there are no more entries... + gcmGetFile(data, &root, 0,file); + root = data->fst.entries.front(); + // this is where we inject the filesystem entries for bootloader.bin, apploader.bin, + // and game.dol ... these aren't technically part of the filesystem, but we + // do this so they can be viewed/extracted like other files. + /* + appSize = (int *)gcmWhichData(GCM_APPLOADER_SIZE, data); + newEntry = new GCM_FSTEntry; + newEntry->fname_offset = 0; + newEntry->file_offset = GCM_APPLOADER_CODE_LOC; + newEntry->file_length = *appSize; + newEntry->stringtable_off = 1; + data->fst.entries.push_back(*newEntry); + delete newEntry;*/ + for ( int i = 1; i < root.file_length ; i++) { + newEntry = new GCM_FSTEntry; + gcmGetFile(data, newEntry, i, file); + delete newEntry; + } + + + // we're past the FST proper; now the string table... + data->fst.stringtable_offset = data->fst.offset + (root.file_length * 12); + fseek(file, data->fst.stringtable_offset, 0); + //printf("FST string table offset calculated to 0x\%x...\n", data->fst.stringtable_offset); + data->fst.stringtable.clear(); + data->fst.stringtable.push_back(&std::string("/\0")); + //data->fst.stringtable.push_back(&std::string("apploader.bin\0")); + memset(tmpbuff, GCNDVD_FNAME_LENGTH, 0x00); + while ( ftell(file) < (data->fst.offset + data->fst.size) && !feof(file)) { + i = 0; + while ( 1 ) { + tmp = fgetc(file); + if ( tmp == 0x00 ) { + break; + } + tmpbuff[i] = tmp; + i++; + } + tmpbuff[i] = '\0'; + strdest->clear(); + strdest->reserve(i); + strdest->assign(tmpbuff); + data->fst.stringtable.push_back(strdest); + // printf("DEBUG : FILENAME WAS %s ... added %s\n", strdest, + // data->fst.stringtable.at(f+1)->c_str()); + memset(tmpbuff, GCNDVD_FNAME_LENGTH, 0x00); + strdest = new std::string(""); + f++; + } + delete tmpbuff; + return 0; +} + +// called inside of gcmInit to make sure everything inside is sane +// (only needed internally) +int gcmZeroOut(GCM *data) +{ + data->apploader.entry = 0; + data->apploader.size = 0; + data->apploader.trailersize = 0; + data->fst.maxsize = 0; + data->fst.offset = 0; + data->fst.size = 0; + data->head.bootfile = 0; + data->head.debugmon = 0; + data->head.debugmonaddr = 0; + data->head.gamecode = 0; + data->head.gamemaker = 0; + data->head.magicword = 0; + data->head.userlen = 0; + data->head.userpos = 0; + data->headInf.argoff = 0; + data->headInf.countrycode = 0; + data->headInf.debugflag = 0; + data->headInf.debugmonsize = 0; + data->headInf.simmemsize = 0; + data->headInf.tracklocation = 0; + data->headInf.tracksize = 0; +} + +// reads all info from the GCM in gcmname and puts it in data +int gcmInit(char *gcmname, GCM *data) +{ + FILE *gcm = fopen(gcmname, "r+b"); + int i = 0; + + if (!gcm) { + return -1; + } + + gcmZeroOut(data); + + switch ( gcmCheckMagic(gcm) ) { + case 0: + needByteSwap = 1; + break; + case 1: + break; + case -1: + //printf("DEBUG: DVD Magic number on GCM image was incorrect or couldn't be understood!\n"); + //printf("DEBUG: Aborting in GCMInit! (filename %s)\n", gcmname); + fclose(gcm); + return -1; + } + + for ( i = 3; i < GCM_MAX_PIECES ; i++) { + gcmGetData(i,data, gcm); + } + + gcmPopulateFST(data, gcm); + + fclose(gcm); + + data->fname = new char[strlen(gcmname)+1]; + if ( !data->fname ) { + printf("couldn't store GCM filename for later retrieval. Aborting.\n"); + gcmFreeStringTable(data); + exit(-1); + } + else strcpy(data->fname, gcmname); + + return 0; +} + +// print all information about the GCM in a columnar format, +// including the FST. +int gcmPrint(GCM *data) +{ + int ml = 0; + int i = 0; + + for (i = 3; i < GCM_MAX_PIECES; i++ ) { + gcmPrintData(i,data); + } + + GCM_FSTEntry root = data->fst.entries.front(); + + printf("%-38s:\t%d\n", "Total files in the FST", root.file_length); + printf("%-38s:\t%d\n", "Total entries in the FST string table", data->fst.stringtable.size()); + return 0; +} + +int gcmPrintFST(GCM *data) +{ + int ml = 0; + int i = 0; + char *tbuff = new char[GCNDVD_FNAME_LENGTH]; + if (!tbuff) { + printf("Couldn't get temporary buffer for full path printing. Aborting.\n"); + return -1; + } else { + memset(tbuff, 0x00, GCNDVD_FNAME_LENGTH); + } + + GCM_FSTEntry root = data->fst.entries.front(); + printf("%-38s:\t%d\n", "Total files in the FST", root.file_length); + printf("%-38s:\t%d\n", "Total entries in the FST string table", data->fst.stringtable.size()); + printf("\n\n\n%30s\n", "(FST CONTENTS)"); + printf("%-16s %-6s %-6s %s %-12s\n", + "(name)", "(fnum)", "(type)", "(offset)", "(length)"); + for (i = 0; i < data->fst.entries.size() - 1 ; i++) { + //printf("DEBUG: retrieving file data for number %d\n", i); + gcmPrintFile(data, i); + } + + printf("\n\t\t\t(PRINTING FILES WITH FULL PATH)\n"); + for (i = 0; i < data->fst.entries.size() - 1; i++ ) { + printf("File %d:", i); + gcmGetFullFileName(data, i, tbuff); + printf(" %s\n", tbuff); + memset(tbuff, 0x00, GCNDVD_FNAME_LENGTH); + } + + delete tbuff; + return 0; +} + +// frees memory used by the string table. MUST be called before zeroing +// the gcm for new reading (gcmInit) or quitting the application. +// This should be accompanied by clearing the entries vector, though the +// destructor in that member should take care of cleanup for you. +// Thou shalt not leak memory! + +int gcmFreeStringTable(GCM *data) +{ + std::string *string = NULL; + int i = 0; + + //printf("freeing memory used by FST string table... "); + + for (i = 0; i < (data->fst.stringtable.size()) ; i++ ) { + string = (std::string *)data->fst.stringtable.at(i); + // we create the "/" entry for 0 manually, and it's not alloc'ed + // so don't try freeing it! + if ( string != NULL && i > 0 ) { + delete string; + } + string = NULL; + } + data->fst.stringtable.clear(); + delete data->fname; + + //printf(" ...done.\n"); +} + +GCM_FSTEntry gcmGetFileByFnum(GCM *data, int fnum) +{ + return data->fst.entries.at(fnum); +} + +int gcmGetFileByOffset(GCM *data, int offset) +{ + GCM_FSTEntry curr; + bool done = false; + + for (int i = 0; i < data->fst.entries.size() -1; i++) { + curr = data->fst.entries.at(i); + if (curr.file_offset == offset) { + return i; + } + } +} + +// takes in a full pathname and retrieves the fnum +// for the appropriate file in the FST +unsigned int gcmGetFileByName(GCM *data, char *name) +{ + GCM_FSTEntry curr; + bool done = false; + int nextStart = 0; + int i = 0; + char *tmp2 = (char *) new char[GCNDVD_FNAME_LENGTH]; + if ( !tmp2 ) { + fprintf(stderr, "Failed to allocate temporary string storage\n"); + return -1; + } + for ( i = 0; i < data->fst.stringtable.size() ; i++ ) { + gcmGetFullFileName(data, i, tmp2); + //printf("DEBUG : comparing filename %s to original %s...\n", name, tmp2); + if ( !strcmp(name, tmp2) ) { + delete tmp2; + //printf("DEBUG : found filename %s at number %d", name, i); + return i; + } + } + delete tmp2; + return -1; +} + +// extracts a file into outfile from the GCM given the fnum. +// FIXME : allow the user to specify a different output filename? +unsigned int gcmExtractFile(GCM *data, int fnum, char *outfname) +{ + FILE *out = NULL; + FILE *gcm = NULL; + int pos = 0; + int endpos = 0; + int b = 0; + GCM_FSTEntry curr; + std::string execstring = ""; + char *outfile = NULL; + std::string tmpStr = ""; + + // check that the fnum is in range + + if ( fnum < data->fst.entries.size() - 1) { + curr = data->fst.entries.at(fnum); + } + else { + return -1; + } + + // if it's a file, open the outfile, open the GCM, and perform the copy - clean up and exit + if ( gcmGetFSTEntryType(&curr) == 0 ) { + if ( outfname ) { + outfile = outfname; + tmpStr = ""; + } else { + outfile = new char[GCNDVD_FNAME_LENGTH]; + if ( !outfile ) return -1; + else gcmGetFullFileName(data, fnum, outfile); + tmpStr = "."; + } + tmpStr.append(outfile); + gcm = fopen(data->fname, "rb"); + out = fopen(tmpStr.c_str(), "wb"); + if ( !gcm || !out ) { + gcm ? fclose(gcm) : printf("Couldn't read from gcm file\n"); + out ? fclose(out) : printf("Couldn't write to output file\n"); + return -1; + } + fseek(gcm, curr.file_offset, 0); + endpos = curr.file_offset + curr.file_length; + if ( ftell(gcm) != curr.file_offset || !out || !gcm) { + delete outfile; + fclose(gcm); + fclose(out); + return -1; + } + + while ( !feof(gcm) && ftell(gcm) <= endpos) { + fread(&b, 1, 1, gcm); + if ( needByteSwap == 1 ) b = byteSwap(b); // swap the bytes for the host + fwrite(&b, 1, 1, out); + } + + if ( outfile && !outfname )delete outfile; + fclose(gcm); + fclose(out); + printf("exploded %s\n", tmpStr.c_str()); + return 0; + } + // if it's a dir, construct the mkdir command, do it, clean up and exit. + else { + if ( outfname ) + outfile = outfname; + else { + outfile = new char[GCNDVD_FNAME_LENGTH]; + if (!outfile ) { + return -1; + } + } + gcmGetFullFileName(data, fnum, outfile); + if ( !outfname ) + execstring.append("mkdir -p ."); + else + execstring.append("mkdir -p "); + execstring.append(outfile); + int retcode = system(execstring.c_str()); + if ( outfile && !outfname ) delete outfile; + return 0; + } +} + + +// explodes the FST onto the host filesystem +int gcmExplode(GCM *data) +{ + for ( int i = 0; i <= (data->fst.entries.size() - 1) ; i++ ) { + if ( gcmExtractFile(data, i, NULL) < 0 ) return -1; + } + +} + +// retrieves the full filename for fnum with full path +int gcmGetFullFileName(GCM *data, int fnum, char *dest) +{ + bool finished = false; + GCM_FSTEntry curr; + std::vector fnames; + int fn = fnum; + int depth = 0; + std::string work = ""; + + curr = data->fst.entries.at(fn); + + while (!finished) { + depth++; + if ( depth > data->fst.entries.size() - 1) { + printf("went too far. aborting.\n"); + exit(-1); + } + if ( fn == 0 ) { + fnames.push_back(0); + finished = true; + break; + } + if ( gcmGetFSTEntryType(&curr) == 0 ) { + // file + fnames.push_back(fn); + while (gcmGetFSTEntryType(&curr) == 0) { + // search up for the parent directory.... + curr = data->fst.entries.at(fn - 1); + fn -= 1; + } + } + else if ( gcmGetFSTEntryType(&curr) == 1) { + // directory + fnames.push_back(fn); + fn = curr.file_offset; + curr = data->fst.entries.at(fn); + } + } + + if ( fnum != 0 ) { + for (int i = fnames.size() -1 ; i >= 0; i--) { + if ( i < fnames.size()-1 ) { + work.append("/"); + } + if ( fnames.at(i) != 0 ) work.append(data->fst.stringtable.at(fnames.at(i))->c_str()); + } + } else work = "/"; + strcpy(dest, work.c_str()); + return 0; +} diff --git a/source/.svn/text-base/gcminfo.h.svn-base b/source/.svn/text-base/gcminfo.h.svn-base new file mode 100755 index 0000000..04eadd1 --- /dev/null +++ b/source/.svn/text-base/gcminfo.h.svn-base @@ -0,0 +1,217 @@ +// thanks to groepaz and everyone else who wrote YAGCD, most of my info came from it +// also thanks to WntrMute for loaning me some source to clear things up about the FST + +// (C) 2005 Andrew K andrew@aklabs.net +// License: Take all you want, but credit for all you take. + +#include +#include +#include +#include +#include + +#define LIBGCMVERSION "libGCM Version 0.1a (build Sep 4 2005)" + +// defines for internal program control (not necessarily GCM-related) + +#define GCNDVD_MAGICNUM 0xc2339f3d // if this isn't correct in the GCM, + // the program will abort. + +#define GCNDVD_SECTORS 712880 // not really used, but left for future updates that might use it +#define GCNDVD_SECTORSIZE 2048 // " " +#define GCNDVD_FNAME_LENGTH 1024 + + +#define GCM_MAX_PIECES 29 // change this if (for whatever reason) you add a new entry in GCMPieces + +// these all define indices in the GCMPieces global array where +// information about (where to look in the GCM for) a given piece +// of data about the GCM can be found. The rationale should +// be easy enough to follow. +#define GCM_DHEAD 0 +#define GCM_DHEADINF 1 +#define GCM_APPLOADER 2 + +#define GCM_DHEAD_GAMECODE 3 +#define GCM_DHEAD_GAMEMAKER 4 +#define GCM_DHEAD_DVDMAGIC 5 +#define GCM_DHEAD_GAMENAME 6 +#define GCM_DHEAD_DEBUGMON 7 +#define GCM_DHEAD_DEBUGMONADDR 8 +#define GCM_DHEAD_BOOTFILE 9 +#define GCM_DHEAD_FST 10 +#define GCM_DHEAD_FSTSIZE 11 +#define GCM_DHEAD_FSTMAXSIZE 12 +#define GCM_DHEAD_USERPOS 13 +#define GCM_DHEAD_USERLEN 14 + +#define GCM_DHEADINF_DEBUGMONSIZE 15 +#define GCM_DHEADINF_SIMMEMSIZE 16 +#define GCM_DHEADINF_ARGOFFSET 17 +#define GCM_DHEADINF_DEBUGFLAG 18 +#define GCM_DHEADINF_TRACKLOCATION 19 +#define GCM_DHEADINF_TRACKSIZE 20 +#define GCM_DHEADINF_COUNTRYCODE 21 + +#define GCM_APPLOADER_VERSION 22 +#define GCM_APPLOADER_ENTRY 23 +#define GCM_APPLOADER_SIZE 24 +#define GCM_APPLOADER_TRAILERSIZE 25 +#define GCM_APPLOADER_BINARY 26 +#define GCM_APPLOADER_CODE_LOC 0x2450 + +#define GCM_FST_ROOT 28 +#define GCM_FST_STRINGTABLEOFF 29 + +typedef struct { + int area; // 0 = basic structure, 1 = header, 2= header info, 3 = apploader, 4 = FST + char *name; + long offset; + long size; + int type; // 1 for string, 0 for numeric value (strings aren't byteswapped) +} GCMPiece; + + // pieces with area 1 add the base of the disk header to their offset + // pieces with area 2 add the base of the disk header info to their offset + // pieces with area 3 add the base of the apploader to their offset + // pieces with area 4 add the base of the FST to their offset (garnered from the disk header) +static GCMPiece GCMPieces [] ={ + // root disc pieces + {0, "Disk Header (boot.bin)", 0x00000000, 0x0440, 0}, + {0, "Disk Header Information (bi2.bin)", 0x00000440, 0x2000, 0}, + {0, "Apploader (appldr.bin)", 0x00002440, 0x2000, 0}, // 0x2000 size is an estimate I think + // disk header + {1, "Game code", 0x0000, 0x0004, 0}, + {1, "Game maker code", 0x0004, 0x0002, 0}, + {1, "DVD Magic Word", 0x001c, 0x0004, 0}, + {1, "Game name", 0x0020, 0x03e0, 1}, + {1, "Debug monitor offset", 0x0400, 0x0004, 0}, + {1, "Debug monitor load address", 0x0404, 0x0004, 0}, + {1, "Bootfile offset", 0x0420, 0x0004, 0}, + {1, "FST offset", 0x0424, 0x0004, 0}, + {1, "FST size", 0x0428, 0x0004, 0}, + {1, "FST Max Size", 0x042c, 0x0004, 0}, + {1, "User position", 0x0430, 0x0004, 0}, + {1, "User length", 0x0434, 0x0004, 0}, + + // the disk header info is loaded to 0x800000f4 when the disc is loaded by the IPL (tho we're reading it straight + // out of the .gcm image, so YMMV) + {2, "Debug-monitor size", 0x0000, 0x0004, 0}, + {2, "Simulated memory size", 0x0004, 0x0004, 0}, + {2, "Argument offset", 0x0008, 0x0004, 0}, + {2, "Debug flag", 0x000c, 0x0004, 0}, + {2, "Track location", 0x0010, 0x0004, 0}, + {2, "Track size", 0x0014, 0x0004, 0}, + {2, "Countrycode", 0x0018, 0x0004, 0}, + + // apploader header info + {3, "Version/Date", 0x0000, 0x000F, 1}, // don't include the padding in the date + {3, "Apploader entry point", 0x0010, 0x0004, 0}, + {3, "Apploader size", 0x0014, 0x0004, 0}, + {3, "Trailer size", 0x0018, 0x0004, 0}, + {3, "Apploader binary", 0x0020, 0, 1}, // no length given - taken from the "apploader size" + + // FST info + {4, "Root directory entry", 0x00, 0x0c, 0}, + {4, "FST String table offset", 0x0008, 0x0004, 0} + +}; + +// primary GCM disk header +typedef struct GCM_DiskHeader{ + int gamecode; + int gamemaker; + int magicword; + char gamename[0x03e0]; + int debugmon; + int debugmonaddr; + int bootfile; + int userpos; + int userlen; +}; + +// the GCM disk header additional info +typedef struct GCM_DiskHeaderInfo { + int debugmonsize; + int simmemsize; + int argoff; + int debugflag; + int tracklocation; + int tracksize; + int countrycode; +}; + +// information about the apploader on the GCM +typedef struct GCM_ApploaderInfo{ + char datever[10]; + int entry; + int size; + int trailersize; + char apploader[0x200]; // actual apploader data +}; + +// information about a particular file in the FST +typedef struct GCM_FSTEntry { + int fname_offset; // offset into the FST string table for the filename + // the offset is only actually 3 bytes, but + // we're only reading, not writing so it doesn't matter + // if we're grande sized .... + // the first byte of fname_offset is actually the flags of the file; 0: file 1: dir + int file_offset; // if this is a directory, this is actually the offset of the parent + int file_length; // actually the number of entries (root) or next_offset (dir) + int stringtable_off; // offset in the string table +}; + +// information about the names and locations of files in the GCM +typedef struct GCM_FST { + int size; + int offset; + int stringtable_offset; + int maxsize; + std::vector entries; // list of entries + std::vector stringtable; // string table +}; + +// GCM image data structure +typedef struct GCM { + GCM_DiskHeader head; + GCM_DiskHeaderInfo headInf; + GCM_ApploaderInfo apploader; + GCM_FST fst; + char *fname; +}; + +// these are just the functions that the user would need beyond +// the functionality provided by gcmInit's loader; more internal +// functions can be found inside gcminfo.c + +// returns 0 for a regular file, 1 for a directory +extern int gcmGetFSTEntryType(GCM_FSTEntry *entry); +// initialises the GCM data structures with FST and such; +extern int gcmInit(char *gcmname, GCM *data); +// prints a given portion of the GCM data +// whichdata should be an indice into the GCMPieces array +extern int gcmPrintData(int whichdata, GCM *data); +// prints all the data in the GCM in a (fairly) columnar format +extern int gcmPrint(GCM *data); +// prints a comprehensive listing of all files in the GCM +extern int gcmPrintFST(GCM *data); +// retrieves a given file and puts it in the FST entries, +// given the fnum +extern int gcmGetFile(GCM *data, GCM_FSTEntry *entry, int fnum, FILE *file); +// prints information for a given fname +extern int gcmPrintFile(GCM *data, int fnum); +// frees all data in the FST stringtable +extern int gcmFreeStringTable(GCM *data); +// extracts a file, given the fnum, into the current dir, unless outfname is specified +extern unsigned int gcmExtractFile(GCM *data, int fnum, char *outfname); +// puts the full filename (with path) into dest, given fnum +extern int gcmGetFullFileName(GCM *data, int fnum, char *dest); +// returns the fnum of a given file by its offset +extern int gcmGetFileByOffset(GCM *data, int offset); +// returns the fnum of a given file by its full pathname +extern unsigned int gcmGetFileByName(GCM *data, char *name); +// returns the actual entry of a file given its fnum +extern GCM_FSTEntry gcmGetFileByFnum(GCM *data, int fnum); +// explodes the FST onto the host filesystem in the current directory +extern int gcmExplode(GCM *data); diff --git a/source/.svn/text-base/sample-output.txt.svn-base b/source/.svn/text-base/sample-output.txt.svn-base new file mode 100755 index 0000000..a2cfd4d --- /dev/null +++ b/source/.svn/text-base/sample-output.txt.svn-base @@ -0,0 +1,1709 @@ +DEBUG: turning on byte swapping... +FST string table offset calculated to 0x209e6c... +Game code : 47475345 +Game maker code : 41340000 +DVD Magic Word : c2339f3d +Game name : METAL GEAR SOLID THE TWIN SNAKES +Debug monitor offset : 1d224 +Debug monitor load address : 80280060 +Bootfile offset : 1f700 +FST offset : 205000 +FST size : 729c +FST Max Size : 729c +User position : 803f8d60 +User length : 210000 +Debug-monitor size : 0 +Simulated memory size : 0 +Argument offset : 0 +Debug flag : 0 +Track location : 0 +Track size : 0 +Countrycode : 1 +Version/Date : 2003/04/17 +Apploader entry point : 81200258 +Apploader size : 1954 +Trailer size : 1b8b0 +Apploader binary : +(untested function/invalid data) : refusing to print NULL pointer... +FST String table offset : 20746f4e +Total files in the FST : 1673 +Total entries in the FST string table : 1673 + + + + (FST CONTENTS) +(name) (fnum) (type) (offset) (length) +(root) 0 1 0 1673 +.sbas 1 1 0 1673 +Sync 2 1 0 4 +SyncLock 3 0 210000 329 +audio 4 0 21014c 0 +banks 5 1 0 89 +.sbas 6 1 4 33 +Sync 7 1 5 9 +SyncLock 8 0 21014c 2054 +bank017.spd 9 0 210954 0 +bank017.spt 10 0 210954 1531467 +bank018.spd 11 0 3867a0 19566 +bank018.spt 12 0 38b410 1404419 +bank021.spd 13 0 4e2214 18020 +bank021.spt 14 0 4e6878 2109832 +bank022.spd 15 0 6e9a00 22244 +bank022.spt 16 0 6ef0e4 2120391 +bank024.spd 17 0 8f4bac 21982 +bank024.spt 18 0 8fa18c 2273772 +bank027.spd 19 0 b25378 24108 +bank027.spt 20 0 b2b1a4 2398383 +bank032.spd 21 0 d74a54 24198 +bank032.spt 22 0 d7a8dc 1749186 +bank033.spd 23 0 f259a0 13510 +bank033.spt 24 0 f28e68 2413943 +bank034.spd 25 0 11763e0 18922 +bank034.spt 26 0 117adcc 1511074 +bank035.spd 27 0 12ebc70 18602 +bank035.spt 28 0 12f051c 1115266 +bank037.spd 29 0 14009a0 13212 +bank037.spt 30 0 1403d3c 1955346 +bank042.spd 31 0 15e1350 20640 +bank042.spt 32 0 15e63f0 2013550 +stream 33 0 17d1d60 22834 +.sbas 34 1 4 89 +Sync 35 1 21 37 +SyncLock 36 0 17d7694 3933 +0005L 37 0 17d85f4 0 +0005R 38 0 17d85f4 811392 +0006L 39 0 189e774 811392 +0006R 40 0 19648f4 811392 +0007L 41 0 1a2aa74 811392 +0007R 42 0 1af0bf4 1036896 +0008L 43 0 1bede54 1036896 +0008R 44 0 1ceb0b4 811392 +0009L 45 0 1db1234 811392 +0009R 46 0 1e773b4 786528 +0014L 47 0 1f37414 786528 +0014R 48 0 1ff7474 2991552 +0015L 49 0 22d1a34 2991552 +0015R 50 0 25abff4 2051243 +0016L 51 0 27a0ca0 2051243 +0016R 52 0 299594c 1907543 +0045L 53 0 2b674a4 1907543 +0045R 54 0 2d38ffc 1156416 +0046L 55 0 2e5353c 1156416 +0046R 56 0 2f6da7c 1008883 +0047L 57 0 3063f70 1008883 +0047R 58 0 315a464 1251687 +0048L 59 0 328bdcc 1251687 +0048R 60 0 33bd734 1119205 +0049L 61 0 34ceb1c 1119205 +0049R 62 0 35dff04 1313742 +0050L 63 0 3720ad4 1313742 +0050R 64 0 38616a4 816956 +0051L 65 0 3928de0 816956 +0051R 66 0 39f051c 1140687 +0052L 67 0 3b06cec 1140687 +0052R 68 0 3c1d4bc 1013143 +0053L 69 0 3d14a54 1013143 +0053R 70 0 3e0bfec 812108 +0055L 71 0 3ed2438 812108 +0055R 72 0 3f98884 1142278 +0069L 73 0 40af68c 1142278 +0069R 74 0 41c6494 1647860 +0092L 75 0 4358988 1647860 +0092R 76 0 44eae7c 1134096 +0093L 77 0 45ffc8c 1134096 +0093R 78 0 4714a9c 1319660 +0094L 79 0 4856d88 1319660 +0094R 80 0 4999074 1209696 +0095L 81 0 4ac05d4 1209696 +0095R 82 0 4be7b34 1134096 +0096L 83 0 4cfc944 1134096 +0096R 84 0 4e11754 1707767 +0097L 85 0 4fb264c 1707767 +0097R 86 0 5153544 901216 +0098L 87 0 522f5a4 901216 +0098R 88 0 530b604 3042839 +demo.dat 89 0 55f241c 3042839 +opening.bnr 90 0 58e0000 585379840 +stage.dat 91 0 28723000 6496 +shared 92 0 28728000 203001856 +.sbas 93 1 0 1673 +Sync 94 1 5c 96 +SyncLock 95 0 348c1000 1137 +audio 96 0 348c1474 0 +banks 97 1 5c 1661 +.sbas 98 1 60 129 +Sync 99 1 61 101 +SyncLock 100 0 348c1474 5484 +bank001.spd 101 0 348c29e0 0 +bank001.spt 102 0 348c29e0 2481256 +bank003.spd 103 0 34b20648 21606 +bank003.spt 104 0 34b25ab0 2167834 +bank006.spd 105 0 34d36ecc 26310 +bank006.spt 106 0 34d3d594 2032853 +bank008.spd 107 0 34f2da6c 21772 +bank008.spt 108 0 34f32f78 2098461 +bank013.spd 109 0 35133498 18456 +bank013.spt 110 0 35137cb0 2033464 +bank015.spd 111 0 353283e8 21044 +bank015.spt 112 0 3532d61c 1723454 +bank019.spd 113 0 354d225c 20526 +bank019.spt 114 0 354d728c 1772357 +bank020.spd 115 0 35687dd4 13284 +bank020.spt 116 0 3568b1b8 1816099 +bank023.spd 117 0 358467dc 24434 +bank023.spt 118 0 3584c750 1654605 +bank025.spd 119 0 359e06a0 17574 +bank025.spt 120 0 359e4b48 2475099 +bank026.spd 121 0 35c40fa4 17080 +bank026.spt 122 0 35c4525c 768478 +bank031.spd 123 0 35d00c3c 4642 +bank031.spt 124 0 35d01e60 1700085 +bank048.spd 125 0 35ea0f58 17916 +bank048.spt 126 0 35ea5554 1470612 +bank049.spd 127 0 3600c5e8 348 +bank049.spt 128 0 3600c744 1557407 +stream 129 0 36188ae4 20094 +.sbas 130 1 60 1661 +Sync 131 1 81 133 +SyncLock 132 0 3618d964 109211 +0001L 133 0 361a8400 0 +0001R 134 0 361a8400 1111103 +0003L 135 0 362b7840 1111103 +0003R 136 0 363c6c80 2077232 +0004L 137 0 365c1eb0 2077232 +0004R 138 0 367bd0e0 9072096 +0010L 139 0 37063ec0 9072096 +0010R 140 0 3790aca0 1895483 +0012L 141 0 37ad98dc 1895483 +0012R 142 0 37ca8518 1064426 +0013L 143 0 37dac304 1064426 +0013R 144 0 37eb00f0 908239 +0018L 145 0 37f8dcc0 908239 +0018R 146 0 3806b890 1601047 +0019L 147 0 381f26a8 1601047 +0019R 148 0 383794c0 1357627 +0021L 149 0 384c4bfc 1357627 +0021R 150 0 38610338 581006 +0022L 151 0 3869e0c8 581006 +0022R 152 0 3872be58 2977574 +0039L 153 0 38a02d80 2977574 +0039R 154 0 38cd9ca8 663524 +0041L 155 0 38d7bc8c 663524 +0041R 156 0 38e1dc70 2496360 +0044L 157 0 3907f3d8 2496360 +0044R 158 0 392e0b40 644350 +0054L 159 0 3937e040 644350 +0054R 160 0 3941b540 2301474 +0056L 161 0 3964d364 2301474 +0056R 162 0 3987f188 3144654 +0057L 163 0 39b7ed58 3144654 +0057R 164 0 39e7e928 603090 +0058L 165 0 39f11cfc 603090 +0058R 166 0 39fa50d0 655160 +0059L 167 0 3a045008 655160 +0059R 168 0 3a0e4f40 2124019 +0060L 169 0 3a2eb834 2124019 +0060R 170 0 3a4f2128 2031712 +0061L 171 0 3a6e2188 2031712 +0061R 172 0 3a8d21e8 2980611 +0065L 173 0 3aba9cec 2980611 +0065R 174 0 3ae817f0 3709712 +0071L 175 0 3b20b300 3709712 +0071R 176 0 3b594e10 1743822 +0072L 177 0 3b73e9e0 1743822 +0072R 178 0 3b8e85b0 5456703 +0073L 179 0 3be1c8f0 5456703 +0073R 180 0 3c350c30 5454150 +0074L 181 0 3c884578 5454150 +0074R 182 0 3cdb7ec0 1714831 +0075L 183 0 3cf5a950 1714831 +0075R 184 0 3d0fd3e0 1792950 +0076L 185 0 3d2b2f98 1792950 +0076R 186 0 3d468b50 1542354 +0077L 187 0 3d5e1424 1542354 +0077R 188 0 3d759cf8 1815539 +0078L 189 0 3d9150ec 1815539 +0078R 190 0 3dad04e0 3943551 +0079L 191 0 3de93160 3943551 +0079R 192 0 3e255de0 4840754 +0081L 193 0 3e6f3b14 4840754 +0081R 194 0 3eb91848 4721399 +0088L 195 0 3f012340 4721399 +0088R 196 0 3f492e38 1700167 +0089L 197 0 3f631f80 1700167 +0089R 198 0 3f7d10c8 1543711 +0090L 199 0 3f949ee8 1543711 +0090R 200 0 3fac2d08 1540725 +0091L 201 0 3fc3af80 1540725 +0091R 202 0 3fdb31f8 1540182 +0099L 203 0 3ff2b250 1540182 +0099R 204 0 400a32a8 726808 +0100L 205 0 401549c0 726808 +0100R 206 0 402060d8 1104846 +0176L 207 0 40313ca8 1104846 +0176R 208 0 40421878 196688 +0177L 209 0 404518c8 196688 +0177R 210 0 40481918 243863 +0178L 211 0 404bd1b0 243863 +0178R 212 0 404f8a48 109582 +0179 213 0 40513658 109582 +0180L 214 0 4052e268 100917 +0180R 215 0 40546ca0 67110 +0181G 216 0 405572c8 67110 +0184L 217 0 405678f0 4689496 +0184R 218 0 409e0748 804523 +0200L 219 0 40aa4df4 804523 +0200R 220 0 40b694a0 183522 +0201L 221 0 40b96184 183522 +0201R 222 0 40bc2e68 183522 +0202L 223 0 40befb4c 183522 +0202R 224 0 40c1c830 183522 +0203L 225 0 40c49514 183522 +0203R 226 0 40c761f8 183522 +0204L 227 0 40ca2edc 183522 +0204R 228 0 40ccfbc0 183522 +0205L 229 0 40cfc8a4 183522 +0205R 230 0 40d29588 183522 +0206L 231 0 40d5626c 183522 +0206R 232 0 40d82f50 183522 +0207L 233 0 40dafc34 183522 +0207R 234 0 40ddc918 183522 +0208L 235 0 40e095fc 183522 +0208R 236 0 40e362e0 183522 +0209L 237 0 40e62fc4 183522 +0209R 238 0 40e8fca8 183522 +0210L 239 0 40ebc98c 183522 +0210R 240 0 40ee9670 183522 +0211L 241 0 40f16354 183522 +0211R 242 0 40f43038 183522 +0212L 243 0 40f6fd1c 183522 +0212R 244 0 40f9ca00 183522 +0213L 245 0 40fc96e4 183522 +0213R 246 0 40ff63c8 183522 +0214L 247 0 410230ac 183522 +0214R 248 0 4104fd90 183522 +0215L 249 0 4107ca74 183522 +0215R 250 0 410a9758 183522 +0216L 251 0 410d643c 183522 +0216R 252 0 41103120 183522 +0217L 253 0 4112fe04 183522 +0217R 254 0 4115cae8 183522 +0218L 255 0 411897cc 183522 +0218R 256 0 411b64b0 183522 +0300 257 0 411e3194 183522 +0301 258 0 4120fe78 65975 +0302 259 0 41220030 126765 +0303 260 0 4123ef60 29839 +0304 261 0 412463f0 26164 +0305 262 0 4124ca24 24740 +0306 263 0 41252ac8 30594 +0307 264 0 4125a24c 58267 +0308 265 0 412685e8 12099 +0309 266 0 4126b52c 20171 +0310 267 0 412703f8 25303 +0311 268 0 412766d0 112501 +0312 269 0 41291e48 48847 +0313 270 0 4129dd18 32677 +0314 271 0 412a5cc0 9035 +0315 272 0 412a800c 6997 +0316 273 0 412a9b64 8270 +0317 274 0 412abbb4 7208 +0318 275 0 412ad7dc 7102 +0319 276 0 412af39c 6120 +0320 277 0 412b0b84 7496 +0321 278 0 412b28cc 29839 +0322 279 0 412b9d5c 21614 +0323 280 0 412bf1cc 24740 +0324 281 0 412c5270 30594 +0325 282 0 412cc9f4 58267 +0326 283 0 412dad90 12099 +0327 284 0 412ddcd4 20171 +0328 285 0 412e2ba0 25303 +0329 286 0 412e8e78 112501 +0330 287 0 413045f0 48847 +0331 288 0 413104c0 32677 +0332 289 0 41318468 41599 +0333 290 0 413226e8 28662 +0334 291 0 413296e0 38514 +0335 292 0 41332d54 32363 +0336 293 0 4133abc0 50631 +0337 294 0 41347188 40078 +0338 295 0 41350e18 23958 +0339 296 0 41356bb0 43062 +0340 297 0 413613e8 46852 +0341 298 0 4136caec 50962 +0342 299 0 41379200 25123 +0343 300 0 4137f424 34300 +0344 301 0 41387a20 46322 +0345 302 0 41392f14 26469 +0346 303 0 4139967c 65317 +0347 304 0 413a95a4 23974 +0348 305 0 413af34c 88500 +0349 306 0 413c4d00 46328 +0350 307 0 413d01f8 10230 +0351 308 0 413d29f0 22531 +0352 309 0 413d81f4 18926 +0353 310 0 413dcbe4 22548 +0354 311 0 413e23f8 29200 +0355 312 0 413e9608 24056 +0356 313 0 413ef400 20917 +0357 314 0 413f45b8 40851 +0358 315 0 413fe54c 37106 +0359 316 0 41407640 20987 +0360 317 0 4140c83c 23414 +0361 318 0 414123b4 33325 +0362 319 0 4141a5e4 18546 +0363 320 0 4141ee58 26203 +0364L 321 0 414254b4 19068 +0364R 322 0 41429f30 183522 +0398L 323 0 41456c14 183522 +0398R 324 0 414838f8 972860 +0399L 325 0 41571134 972860 +0399R 326 0 4165e970 581266 +0401 327 0 416ec804 581266 +0402 328 0 4177a698 1001766 +0403 329 0 4186efc0 10812 +0404 330 0 418719fc 32640 +0405 331 0 4187997c 12211 +0406 332 0 4187c930 17888 +0407 333 0 41880f10 20906 +0408 334 0 418860bc 9094 +0409 335 0 41888444 17100 +0410 336 0 4188c710 18866 +0411 337 0 418910c4 25472 +0412 338 0 41897444 11799 +0413 339 0 4189a25c 23776 +0414 340 0 4189ff3c 21930 +0415 341 0 418a54e8 34399 +0416 342 0 418adb48 39324 +0417 343 0 418b74e4 42410 +0418 344 0 418c1a90 16028 +0419 345 0 418c592c 21677 +0420L 346 0 418caddc 23637 +0420R 347 0 418d0a34 11386 +0421L 348 0 418d36b0 11386 +0421R 349 0 418d632c 8131 +0422L 350 0 418d82f0 8131 +0422R 351 0 418da2b4 9311 +0423L 352 0 418dc714 9311 +0423R 353 0 418deb74 10502 +0424L 354 0 418e147c 10502 +0424R 355 0 418e3d84 14510 +0425L 356 0 418e7634 14510 +0425R 357 0 418eaee4 13276 +0426L 358 0 418ee2c0 13276 +0426R 359 0 418f169c 17687 +0427L 360 0 418f5bb4 17687 +0427R 361 0 418fa0cc 9136 +0428L 362 0 418fc47c 9136 +0428R 363 0 418fe82c 9578 +0429L 364 0 41900d98 9578 +0429R 365 0 41903304 17037 +0430L 366 0 41907594 17037 +0430R 367 0 4190b824 11518 +0431L 368 0 4190e524 11518 +0431R 369 0 41911224 10483 +0432L 370 0 41913b18 10483 +0432R 371 0 4191640c 14786 +0433L 372 0 41919dd0 14786 +0433R 373 0 4191d794 22163 +0434L 374 0 41922e28 22163 +0434R 375 0 419284bc 20381 +0435L 376 0 4192d45c 20381 +0435R 377 0 419323fc 19231 +0436L 378 0 41936f1c 19231 +0436R 379 0 4193ba3c 12934 +0437L 380 0 4193ecc4 12934 +0437R 381 0 41941f4c 8432 +0438L 382 0 4194403c 8432 +0438R 383 0 4194612c 21332 +0439L 384 0 4194b480 21332 +0439R 385 0 419507d4 12295 +0440L 386 0 419537dc 12295 +0440R 387 0 419567e4 16010 +0441L 388 0 4195a670 16010 +0441R 389 0 4195e4fc 17893 +0442L 390 0 41962ae4 17893 +0442R 391 0 419670cc 10917 +0443L 392 0 41969b74 10917 +0443R 393 0 4196c61c 9560 +0444L 394 0 4196eb74 9560 +0444R 395 0 419710cc 15203 +0445L 396 0 41974c30 15203 +0445R 397 0 41978794 24724 +0446L 398 0 4197e828 24724 +0446R 399 0 419848bc 20384 +0447L 400 0 4198985c 20384 +0447R 401 0 4198e7fc 10214 +0448L 402 0 41990fe4 10214 +0448R 403 0 419937cc 16367 +0449L 404 0 419977bc 16367 +0449R 405 0 4199b7ac 25891 +0450L 406 0 419a1cd0 25891 +0450R 407 0 419a81f4 27610 +0451L 408 0 419aedd0 27610 +0451R 409 0 419b59ac 10204 +0452L 410 0 419b8188 10204 +0452R 411 0 419ba964 23686 +0453L 412 0 419c05ec 23686 +0453R 413 0 419c6274 15286 +0454L 414 0 419c9e2c 15286 +0454R 415 0 419cd9e4 30948 +0455L 416 0 419d52c8 30948 +0455R 417 0 419dcbac 22895 +0456L 418 0 419e251c 22895 +0456R 419 0 419e7e8c 23864 +0457L 420 0 419edbc4 23864 +0457R 421 0 419f38fc 18500 +0458L 422 0 419f8140 18500 +0458R 423 0 419fc984 25748 +0459L 424 0 41a02e18 25748 +0459R 425 0 41a092ac 15614 +0460L 426 0 41a0cfac 15614 +0460R 427 0 41a10cac 28422 +0461L 428 0 41a17bb4 28422 +0461R 429 0 41a1eabc 31965 +0462L 430 0 41a2679c 31965 +0462R 431 0 41a2e47c 16885 +0463L 432 0 41a32674 16885 +0463R 433 0 41a3686c 47013 +0464L 434 0 41a42014 47013 +0464R 435 0 41a4d7bc 16440 +0465L 436 0 41a517f4 16440 +0465R 437 0 41a5582c 17767 +0466L 438 0 41a59d94 17767 +0466R 439 0 41a5e2fc 26783 +0467L 440 0 41a64b9c 26783 +0467R 441 0 41a6b43c 27442 +0468L 442 0 41a71f70 27442 +0468R 443 0 41a78aa4 20384 +0469L 444 0 41a7da44 20384 +0469R 445 0 41a829e4 16026 +0470L 446 0 41a86880 16026 +0470R 447 0 41a8a71c 14351 +0471L 448 0 41a8df2c 14351 +0471R 449 0 41a9173c 19980 +0472L 450 0 41a96548 19980 +0472R 451 0 41a9b354 31226 +0473L 452 0 41aa2d50 31226 +0473R 453 0 41aaa74c 26982 +0474L 454 0 41ab10b4 26982 +0474R 455 0 41ab7a1c 32544 +0475L 456 0 41abf93c 32544 +0475R 457 0 41ac785c 33387 +0476L 458 0 41acfac8 33387 +0476R 459 0 41ad7d34 18807 +0477L 460 0 41adc6ac 18807 +0477R 461 0 41ae1024 26851 +0478L 462 0 41ae7908 26851 +0478R 463 0 41aee1ec 15645 +0479L 464 0 41af1f0c 15645 +0479R 465 0 41af5c2c 19476 +0481 466 0 41afa840 19476 +0482 467 0 41aff454 56298 +0483 468 0 41b0d040 172587 +0485L 469 0 41b3726c 61067 +0485R 470 0 41b460f8 237560 +0486L 471 0 41b800f0 237560 +0486R 472 0 41bba0e8 23423 +0487L 473 0 41bbfc68 23423 +0487R 474 0 41bc57e8 31476 +0488L 475 0 41bcd2dc 31476 +0488R 476 0 41bd4dd0 54989 +0489L 477 0 41be24a0 54989 +0489R 478 0 41befb70 50591 +0490L 479 0 41bfc110 50591 +0490R 480 0 41c086b0 23610 +0491L 481 0 41c0e2ec 23610 +0491R 482 0 41c13f28 29578 +0492L 483 0 41c1b2b4 29578 +0492R 484 0 41c22640 985152 +0493L 485 0 41d12e80 985152 +0493R 486 0 41e036c0 265146 +0494L 487 0 41e4427c 265146 +0494R 488 0 41e84e38 985152 +0495L 489 0 41f75678 985152 +0495R 490 0 42065eb8 88854 +0496L 491 0 4207b9d0 88854 +0496R 492 0 420914e8 100800 +0497L 493 0 420a9ea8 100800 +0497R 494 0 420c2868 69309 +0498L 495 0 420d3728 69309 +0498R 496 0 420e45e8 81798 +0499L 497 0 420f8570 81798 +0499R 498 0 4210c4f8 120578 +0500 499 0 42129bfc 120578 +0501 500 0 42147300 58672 +0502 501 0 42155830 58151 +0503 502 0 42163b58 58672 +0504 503 0 42172088 58151 +0505 504 0 421803b0 58151 +0506 505 0 4218e6d8 15443 +0507 506 0 4219232c 15682 +0508 507 0 42196070 13181 +0509 508 0 421993f0 92506 +0510 509 0 421afd4c 72343 +0511 510 0 421c17e4 96814 +0512 511 0 421d9214 92506 +0513 512 0 421efb70 72343 +0514 513 0 42201608 96814 +3000 514 0 42219038 6255 +3001 515 0 4221a8a8 47346 +3002 516 0 4222619c 39570 +3003 517 0 4222fc30 49178 +3004 518 0 4223bc4c 35975 +3005 519 0 422448d4 43831 +3006 520 0 4224f40c 71614 +3007 521 0 42260bcc 85710 +3008 522 0 42275a9c 62590 +3009 523 0 42284f1c 92310 +3010 524 0 4229b7b4 46668 +3011 525 0 422a6e00 45935 +3012 526 0 422b2170 48613 +3013 527 0 422bdf58 102390 +3014 528 0 422d6f50 58677 +3015 529 0 422e5488 59019 +3016 530 0 422f3b14 82221 +3017 531 0 42307c44 67316 +3018 532 0 42318338 73426 +3019 533 0 4232a20c 75043 +3020 534 0 4233c730 69002 +3021 535 0 4234d4bc 70172 +3022 536 0 4235e6d8 51711 +3023 537 0 4236b0d8 59727 +3024 538 0 42379a28 92135 +3025 539 0 42390210 94042 +3026 540 0 423a716c 96240 +3027 541 0 423be95c 107578 +3028 542 0 423d8d98 102533 +3029 543 0 423f1e20 96541 +3030 544 0 42409740 59895 +3031 545 0 42418138 62635 +3032 546 0 424275e4 74283 +3033 547 0 42439810 69892 +3034 548 0 4244a914 62880 +3035 549 0 42459eb4 62752 +3036 550 0 424693d4 72789 +3037 551 0 4247b02c 64782 +3038 552 0 4248ad3c 84140 +3039 553 0 4249f5e8 66904 +3040 554 0 424afb40 68350 +3041 555 0 424c0640 69332 +3042 556 0 424d1514 72782 +3043 557 0 424e3164 64802 +3044 558 0 424f2e88 53655 +3045 559 0 42500020 76360 +3046 560 0 42512a68 78622 +3047 561 0 42525d88 66566 +3048 562 0 42536190 57372 +3049 563 0 425441ac 79499 +3050 564 0 42557838 72911 +3051 565 0 42569508 76807 +3052 566 0 4257c110 87396 +3053 567 0 42591674 98775 +3054 568 0 425a984c 78256 +3055 569 0 425bc9fc 70354 +3056 570 0 425cdcd0 77398 +3057 571 0 425e0b28 68391 +3058 572 0 425f1650 49080 +3059 573 0 425fd608 54448 +3060 574 0 4260aab8 64755 +3061 575 0 4261a7ac 51221 +3062 576 0 42626fc4 50504 +3063 577 0 4263350c 75942 +3064 578 0 42645db4 90654 +3065 579 0 4265bfd4 119691 +3066 580 0 42679360 110942 +3067 581 0 426944c0 106523 +3068 582 0 426ae4dc 108998 +3069 583 0 426c8ea4 114087 +3070 584 0 426e4c4c 100885 +3071 585 0 426fd664 81798 +3072 586 0 427115ec 90015 +3073 587 0 4272758c 132968 +3074 588 0 42747cf4 121743 +3075 589 0 42765884 123368 +3076 590 0 42783a6c 111124 +3077 591 0 4279ec80 115304 +3078 592 0 427baee8 139670 +3079 593 0 427dd080 98205 +3080 594 0 427f5020 84154 +3081 595 0 428098dc 111856 +3082 596 0 42824dcc 94909 +3083 597 0 4283c08c 101383 +3084 598 0 42854c94 71415 +3085 599 0 4286638c 111604 +3086 600 0 42881780 112548 +3087 601 0 4289cf24 113563 +3088 602 0 428b8ac0 94251 +3089 603 0 428cfaec 83218 +3090 604 0 428e4000 96000 +3091 605 0 428fb700 100980 +3092 606 0 42914174 74998 +3093 607 0 4292666c 105563 +3094 608 0 429402c8 71597 +3095 609 0 42951a78 95468 +3096 610 0 42968f64 85367 +3097 611 0 4297dcdc 92598 +3098 612 0 42994694 86228 +3099 613 0 429a9768 102244 +3100 614 0 429c26cc 89059 +3101 615 0 429d82b0 110742 +3102 616 0 429f3348 97402 +3103 617 0 42a0afc4 95935 +3104 618 0 42a22684 103316 +3105 619 0 42a3ba18 105822 +3106 620 0 42a55778 98530 +3107 621 0 42a6d85c 70406 +3108 622 0 42a7eb64 60644 +3109 623 0 42a8d848 40095 +3110 624 0 42a974e8 40014 +3111 625 0 42aa1138 26596 +3112 626 0 42aa791c 41235 +3113 627 0 42ab1a30 41091 +3114 628 0 42abbab4 23310 +3115 629 0 42ac15c4 26011 +3116 630 0 42ac7b60 75950 +3117 631 0 42ada410 72266 +3118 632 0 42aebe5c 98728 +3119 633 0 42b04004 92943 +3120 634 0 42b1ab14 96142 +3121 635 0 42b322a4 77411 +3122 636 0 42b45108 118490 +3123 637 0 42b61fe4 119263 +3124 638 0 42b7f1c4 119507 +3125 639 0 42b9c498 77676 +3126 640 0 42baf404 90588 +3127 641 0 42bc55e0 83250 +3128 642 0 42bd9b14 91583 +3129 643 0 42bf00d4 100991 +3130 644 0 42c08b54 89838 +3131 645 0 42c1ea44 82482 +3132 646 0 42c32c78 83630 +3133 647 0 42c47328 81562 +3134 648 0 42c5b1c4 84604 +3135 649 0 42c6fc40 87533 +3136 650 0 42c85230 102620 +3137 651 0 42c9e30c 96704 +3138 652 0 42cb5ccc 92925 +3139 653 0 42ccc7cc 67520 +3140 654 0 42cdcf8c 29010 +3141 655 0 42ce40e0 22050 +3142 656 0 42ce9704 23066 +3143 657 0 42cef120 48010 +3144 658 0 42cfacac 41578 +3145 659 0 42d04f18 46311 +3146 660 0 42d10400 52527 +3147 661 0 42d1d130 58220 +3148 662 0 42d2b49c 52574 +3149 663 0 42d381fc 56923 +3150 664 0 42d46058 64436 +3151 665 0 42d55c0c 74594 +3152 666 0 42d67f70 73187 +3153 667 0 42d79d54 57523 +3154 668 0 42d87e08 53629 +3155 669 0 42d94f88 46470 +3156 670 0 42da0510 34429 +3157 671 0 42da8b90 88221 +3158 672 0 42dbe430 45333 +3159 673 0 42dc9548 48600 +3160 674 0 42dd5320 43080 +3161 675 0 42ddfb68 51892 +3162 676 0 42dec61c 33995 +3163 677 0 42df4ae8 35046 +3164 678 0 42dfd3d0 41021 +3165 679 0 42e07410 36839 +3166 680 0 42e103f8 41094 +3167 681 0 42e1a480 25608 +3168 682 0 42e20888 33667 +3169 683 0 42e28c0c 30720 +3170 684 0 42e3040c 35995 +3171 685 0 42e390a8 15117 +3172 686 0 42e3cbb8 17134 +3173 687 0 42e40ea8 12547 +3174 688 0 42e43fac 12686 +3175 689 0 42e4713c 15112 +3176 690 0 42e4ac44 17839 +3177 691 0 42e4f1f4 33003 +3178 692 0 42e572e0 39551 +3179 693 0 42e60d60 40045 +3180 694 0 42e6a9d0 45258 +3181 695 0 42e75a9c 40114 +3182 696 0 42e7f750 30764 +3183 697 0 42e86f7c 39723 +3184 698 0 42e90aa8 37359 +3185 699 0 42e99c98 41071 +3186 700 0 42ea3d08 31933 +3187 701 0 42eab9c8 67868 +3188 702 0 42ebc2e4 32178 +3189 703 0 42ec4098 26963 +3190 704 0 42eca9ec 36096 +3191 705 0 42ed36ec 43629 +3192 706 0 42ede15c 13658 +3193 707 0 42ee16b8 15290 +3194 708 0 42ee5274 9093 +3195 709 0 42ee75fc 9358 +3196 710 0 42ee9a8c 44852 +3197 711 0 42ef49c0 33726 +3198 712 0 42efcd80 24092 +3199 713 0 42f02b9c 33565 +3200 714 0 42f0aebc 6188 +3201 715 0 42f0c6e8 29511 +3202 716 0 42f13a30 42866 +3203 717 0 42f1e1a4 5554 +3204 718 0 42f1f758 32528 +3205 719 0 42f27668 32858 +3206 720 0 42f2f6c4 7109 +3207 721 0 42f3128c 20758 +3208 722 0 42f363a4 8058 +3209 723 0 42f38320 20707 +3210 724 0 42f3d404 33955 +3211 725 0 42f458a8 7733 +3212 726 0 42f476e0 18044 +3213 727 0 42f4bd5c 6282 +3214 728 0 42f4d5e8 11710 +3215 729 0 42f503a8 9632 +3216 730 0 42f52948 34410 +3217 731 0 42f5afb4 35530 +3218 732 0 42f63a80 15846 +3219 733 0 42f67868 65007 +3220 734 0 42f77658 24829 +3221 735 0 42f7d758 7424 +3222 736 0 42f7f458 21013 +3223 737 0 42f84670 7926 +3224 738 0 42f86568 9866 +3225 739 0 42f88bf4 21748 +3226 740 0 42f8e0e8 9384 +3227 741 0 42f90590 9468 +3228 742 0 42f92a8c 11701 +3229 743 0 42f95844 8749 +3230 744 0 42f97a74 11090 +3231 745 0 42f9a5c8 5472 +3232 746 0 42f9bb28 6178 +3233 747 0 42f9d34c 6624 +3234 748 0 42f9ed2c 8328 +3235 749 0 42fa0db4 12620 +3236 750 0 42fa3f00 13428 +3237 751 0 42fa7374 10258 +3238 752 0 42fa9b88 13259 +3239 753 0 42facf54 11614 +3240 754 0 42fafcb4 9418 +3241 755 0 42fb2180 14768 +3242 756 0 42fb5b30 16463 +3243 757 0 42fb9b80 22076 +3244 758 0 42fbf1bc 14925 +3245 759 0 42fc2c0c 20047 +3246 760 0 42fc7a5c 13459 +3247 761 0 42fcaef0 13158 +3248 762 0 42fce258 11423 +3249 763 0 42fd0ef8 21738 +3250 764 0 42fd63e4 11294 +3251 765 0 42fd9004 8934 +3252 766 0 42fdb2ec 12795 +3253 767 0 42fde4e8 7395 +3254 768 0 42fe01cc 21603 +3255 769 0 42fe5630 19549 +3256 770 0 42fea290 21610 +3257 771 0 42fef6fc 16669 +3258 772 0 42ff381c 13047 +3259 773 0 42ff6b14 12845 +3260 774 0 42ff9d44 23829 +3261 775 0 42fffa5c 20918 +3262 776 0 43004c14 21432 +3263 777 0 43009fcc 21967 +3264 778 0 4300f59c 20212 +3265 779 0 43014490 22378 +3266 780 0 43019bfc 27784 +3267 781 0 43020884 12669 +3268 782 0 43023a04 21645 +3269 783 0 43028e94 14387 +3270 784 0 4302c6c8 15568 +3271 785 0 43030398 12144 +3272 786 0 43033308 12699 +3273 787 0 430364a4 21978 +3274 788 0 4303ba80 22796 +3275 789 0 4304138c 15912 +3276 790 0 430451b4 21664 +3277 791 0 4304a654 16158 +3278 792 0 4304e574 20979 +3279 793 0 43053768 11879 +3280 794 0 430565d0 25287 +3281 795 0 4305c898 40155 +3282 796 0 43066574 29647 +3283 797 0 4306d944 29320 +3284 798 0 43074bcc 22733 +3285 799 0 4307a49c 13883 +3286 800 0 4307dad8 12560 +3287 801 0 43080be8 14559 +3288 802 0 430844c8 12821 +3289 803 0 430876e0 10900 +3290 804 0 4308a174 14669 +3291 805 0 4308dac4 12062 +3292 806 0 430909e4 59622 +3293 807 0 4309f2cc 39031 +3294 808 0 430a8b44 62318 +3295 809 0 430b7eb4 52256 +3296 810 0 430c4ad4 47055 +3297 811 0 430d02a4 45757 +3298 812 0 430db564 46331 +3299 813 0 430e6a60 70203 +3300 814 0 430f7c9c 35140 +3301 815 0 431005e0 41468 +3302 816 0 4310a7dc 52544 +3303 817 0 4311751c 62187 +3304 818 0 43126808 7676 +3305 819 0 43128604 17020 +3306 820 0 4312c880 18666 +3307 821 0 4313116c 10236 +3308 822 0 43133968 8203 +3309 823 0 43135974 13031 +3310 824 0 43138c5c 41125 +3311 825 0 43142d04 83491 +3312 826 0 43157328 39879 +3313 827 0 43160ef0 55247 +3314 828 0 4316e6c0 50387 +3315 829 0 4317ab94 57571 +3316 830 0 43188c78 55470 +3317 831 0 43196528 53728 +3318 832 0 431a3708 47314 +3319 833 0 431aefdc 91907 +3320 834 0 431c56e0 72948 +3321 835 0 431d73d4 50725 +3322 836 0 431e39fc 75098 +3323 837 0 431f5f58 64383 +3324 838 0 43205ad8 67826 +3325 839 0 432163cc 62984 +3326 840 0 432259d4 41064 +3327 841 0 4322fa3c 13406 +3328 842 0 43232e9c 13206 +3329 843 0 43236234 9194 +3330 844 0 43238620 10164 +3331 845 0 4323add4 53589 +3332 846 0 43247f2c 37253 +3333 847 0 432510b4 24259 +3334 848 0 43256f78 34414 +3335 849 0 4325f5e8 10416 +3336 850 0 43261e98 24522 +3337 851 0 43267e64 30023 +3338 852 0 4326f3ac 7420 +3339 853 0 432710a8 32472 +3340 854 0 43278f80 32678 +3341 855 0 43280f28 11432 +3342 856 0 43283bd0 18740 +3343 857 0 43288504 10203 +3344 858 0 4328ace0 24314 +3345 859 0 43290bdc 34874 +3346 860 0 43299418 6741 +3347 861 0 4329ae70 22839 +3348 862 0 432a07a8 8799 +3349 863 0 432a2a08 17312 +3350 864 0 432a6da8 10436 +3351 865 0 432a966c 36970 +3352 866 0 432b26d8 33677 +3353 867 0 432baa68 10189 +3354 868 0 432bd238 117612 +3355 869 0 432d9da4 36818 +3356 870 0 432e2d78 15780 +3357 871 0 432e6b1c 19907 +3358 872 0 432eb8e0 19804 +3359 873 0 432f063c 26196 +3360 874 0 432f6c90 29898 +3361 875 0 432fe15c 16118 +3362 876 0 43302054 6183 +3363 877 0 4330387c 8490 +3364 878 0 433059a8 8147 +3365 879 0 4330797c 10967 +3366 880 0 4330a454 14795 +3367 881 0 4330de20 7554 +3368 882 0 4330fba4 10739 +3369 883 0 43312598 7754 +3370 884 0 433143e4 11574 +3371 885 0 4331711c 10886 +3372 886 0 43319ba4 8380 +3373 887 0 4331bc60 11879 +3374 888 0 4331eac8 11159 +3375 889 0 43321660 10140 +3376 890 0 43323dfc 14299 +3377 891 0 433275d8 15933 +3378 892 0 4332b418 20747 +3379 893 0 43330524 15820 +3380 894 0 433342f0 18887 +3381 895 0 43338cb8 14642 +3382 896 0 4333c5ec 12828 +3383 897 0 4333f808 13718 +3384 898 0 43342da0 21206 +3385 899 0 43348078 11883 +3386 900 0 4334aee4 9213 +3387 901 0 4334d2e4 9518 +3388 902 0 4334f814 9199 +3389 903 0 43351c04 18235 +3390 904 0 43356340 16310 +3391 905 0 4335a2f8 18032 +3392 906 0 4335e968 20741 +3393 907 0 43363a70 19151 +3394 908 0 43368540 19187 +3395 909 0 4336d034 56447 +3396 910 0 4337acb4 34807 +3397 911 0 433834ac 32307 +3398 912 0 4338b2e0 22388 +3399 913 0 43390a54 54485 +3400 914 0 4339df2c 26428 +3401 915 0 433a4668 56668 +3402 916 0 433b23c4 16231 +3403 917 0 433b632c 11990 +3404 918 0 433b9204 12366 +3405 919 0 433bc254 17319 +3406 920 0 433c05fc 14808 +3407 921 0 433c3fd4 14967 +3408 922 0 433c7a4c 27172 +3409 923 0 433ce470 36864 +3410 924 0 433d7470 17511 +3411 925 0 433db8d8 18428 +3412 926 0 433e00d4 8383 +3413 927 0 433e2194 23430 +3414 928 0 433e7d1c 21883 +3415 929 0 433ed298 18430 +3416 930 0 433f1a98 17286 +3417 931 0 433f5e20 17823 +3418 932 0 433fa3c0 19071 +3419 933 0 433fee40 15940 +3420 934 0 43402c84 11560 +3421 935 0 434059ac 14646 +3422 936 0 434092e4 10420 +3423 937 0 4340bb98 14367 +3424 938 0 4340f3b8 11116 +3425 939 0 43411f24 57111 +3426 940 0 4341fe3c 39959 +3427 941 0 43429a54 34163 +3428 942 0 43431fc8 49202 +3429 943 0 4343dffc 36354 +3430 944 0 43446e00 33583 +3431 945 0 4344f130 35661 +3432 946 0 43457c80 56604 +3433 947 0 4346599c 45654 +3434 948 0 43470bf4 34602 +3435 949 0 43479320 29148 +3436 950 0 434804fc 49291 +3437 951 0 4348c588 50051 +3438 952 0 4349890c 12674 +3439 953 0 4349ba90 14398 +3440 954 0 4349f2d0 8387 +3441 955 0 434a1394 11647 +3442 956 0 434a4114 16108 +3443 957 0 434a8000 18901 +3444 958 0 434ac9d8 64472 +3445 959 0 434bc5b0 60538 +3446 960 0 434cb22c 34847 +3447 961 0 434d3a4c 34312 +3448 962 0 434dc054 40227 +3449 963 0 434e5d78 30251 +3450 964 0 434ed3a4 39325 +3451 965 0 434f6d44 36488 +3452 966 0 434ffbcc 39480 +3453 967 0 43509604 72782 +3454 968 0 4351b254 36362 +3455 969 0 43524060 29427 +3456 970 0 4352b354 35286 +3457 971 0 43533d2c 63693 +3458 972 0 435435fc 37359 +3459 973 0 4354c7ec 13525 +3460 974 0 4354fcc4 12530 +3461 975 0 43552db8 8138 +3462 976 0 43554d84 7922 +3463 977 0 43556c78 55108 +3464 978 0 435643bc 29747 +3465 979 0 4356b7f0 26822 +3466 980 0 435720b8 34880 +3467 981 0 4357a8f8 6994 +3468 982 0 4357c44c 34466 +3469 983 0 43584af0 33847 +3470 984 0 4358cf28 6307 +3471 985 0 4358e7cc 35586 +3472 986 0 435972d0 8752 +3473 987 0 43599500 8728 +3474 988 0 4359b718 16327 +3475 989 0 4359f6e0 11912 +3476 990 0 435a2568 33940 +3477 991 0 435aa9fc 29037 +3478 992 0 435b1b6c 14383 +3479 993 0 435b539c 12012 +3480 994 0 435b8288 14327 +3481 995 0 435bba80 12827 +3482 996 0 435bec9c 11772 +3483 997 0 435c1a98 35351 +3484 998 0 435ca4b0 34182 +3485 999 0 435d2a38 9469 +3486 1000 0 435d4f38 145452 +3487 1001 0 435f8764 32087 +3488 1002 0 436004bc 25294 +3489 1003 0 4360678c 39789 +3490 1004 0 436102fc 22067 +3491 1005 0 43615930 48699 +3492 1006 0 4362176c 29554 +3493 1007 0 43628ae0 23139 +3494 1008 0 4362e544 8077 +3495 1009 0 436304d4 9864 +3496 1010 0 43632b5c 9019 +3497 1011 0 43634e98 9756 +3498 1012 0 436374b4 7328 +3499 1013 0 43639154 8650 +3500 1014 0 4363b320 14189 +3501 1015 0 4363ea90 6293 +3502 1016 0 43640328 12501 +3503 1017 0 43643400 11667 +3504 1018 0 43646194 11056 +3505 1019 0 43648cc4 11773 +3506 1020 0 4364bac4 13567 +3507 1021 0 4364efc4 10844 +3508 1022 0 43651a20 16496 +3509 1023 0 43655a90 17957 +3510 1024 0 4365a0b8 18894 +3511 1025 0 4365ea88 18292 +3512 1026 0 436631fc 19290 +3513 1027 0 43667d58 14381 +3514 1028 0 4366b588 16858 +3515 1029 0 4366f764 14662 +3516 1030 0 436730ac 19621 +3517 1031 0 43677d54 12599 +3518 1032 0 4367ae8c 9902 +3519 1033 0 4367d53c 8430 +3520 1034 0 4367f62c 7979 +3521 1035 0 43681558 16796 +3522 1036 0 436856f4 14398 +3523 1037 0 43688f34 14482 +3524 1038 0 4368c7c8 15807 +3525 1039 0 43690588 30403 +3526 1040 0 43697c4c 33424 +3527 1041 0 4369fedc 26765 +3528 1042 0 436a676c 44404 +3529 1043 0 436b14e0 30888 +3530 1044 0 436b8d88 24060 +3531 1045 0 436beb84 26879 +3532 1046 0 436c5484 10739 +3533 1047 0 436c7e78 17816 +3534 1048 0 436cc410 11542 +3535 1049 0 436cf128 13982 +3536 1050 0 436d27c8 15480 +3537 1051 0 436d6440 24114 +3538 1052 0 436dc274 11930 +3539 1053 0 436df110 14268 +3540 1054 0 436e28cc 16767 +3541 1055 0 436e6a4c 22935 +3542 1056 0 436ec3e4 16399 +3543 1057 0 436f03f4 18885 +3544 1058 0 436f4dbc 9770 +3545 1059 0 436f73e8 23253 +3546 1060 0 436fcec0 29816 +3547 1061 0 43704338 26156 +3548 1062 0 4370a964 43140 +3549 1063 0 437151e8 26064 +3550 1064 0 4371b7b8 20179 +3551 1065 0 4372068c 12496 +3552 1066 0 4372375c 15306 +3553 1067 0 43727328 16248 +3554 1068 0 4372b2a0 10571 +3555 1069 0 4372dbec 14392 +3556 1070 0 43731424 11330 +3557 1071 0 43734068 51784 +3558 1072 0 43740ab0 52477 +3559 1073 0 4374d7b0 50395 +3560 1074 0 43759c8c 41962 +3561 1075 0 43764078 34605 +3562 1076 0 4376c7a8 46464 +3563 1077 0 43777d28 45098 +3564 1078 0 43782d54 36435 +3565 1079 0 4378bba8 19403 +3566 1080 0 43790774 41600 +3567 1081 0 4379a9f4 46066 +3568 1082 0 437a5de8 42587 +3569 1083 0 437b0444 11447 +3570 1084 0 437b30fc 10485 +3571 1085 0 437b59f4 14104 +3572 1086 0 437b910c 9948 +3573 1087 0 437bb7e8 20876 +3574 1088 0 437c0974 68399 +3575 1089 0 437d14a4 37752 +3576 1090 0 437da81c 48061 +3577 1091 0 437e63dc 38304 +3578 1092 0 437ef97c 53918 +3579 1093 0 437fcc1c 55182 +3580 1094 0 4380a3ac 43284 +3581 1095 0 43814cc0 64166 +3582 1096 0 43824768 58655 +3583 1097 0 43832c88 71051 +3584 1098 0 43844214 39580 +3585 1099 0 4384dcb0 76024 +3586 1100 0 438605a8 44792 +3587 1101 0 4386b4a0 34429 +3588 1102 0 43873b20 48979 +3589 1103 0 4387fa74 11295 +3590 1104 0 43882694 13584 +3591 1105 0 43885ba4 7804 +3592 1106 0 43887a20 7228 +3593 1107 0 4388965c 56183 +3594 1108 0 438971d4 25742 +3595 1109 0 4389d664 31941 +3596 1110 0 438a532c 40539 +3597 1111 0 438af188 6144 +3598 1112 0 438b0988 26237 +3599 1113 0 438b7008 32525 +3600 1114 0 438bef18 3965 +3601 1115 0 438bfe98 35378 +3602 1116 0 438c88cc 39836 +3603 1117 0 438d2468 9706 +3604 1118 0 438d4a54 17855 +3605 1119 0 438d9014 9987 +3606 1120 0 438db718 15922 +3607 1121 0 438df54c 38920 +3608 1122 0 438e8d54 51370 +3609 1123 0 438f5600 6922 +3610 1124 0 438f710c 80212 +3611 1125 0 4390aa60 9988 +3612 1126 0 4390d164 14552 +3613 1127 0 43910a3c 48600 +3614 1128 0 4391c814 42222 +3615 1129 0 43926d04 11492 +3616 1130 0 439299e8 138899 +3617 1131 0 4394b87c 45256 +3618 1132 0 43956944 15382 +3619 1133 0 4395a55c 39415 +3620 1134 0 43963f54 7414 +3621 1135 0 43965c4c 30807 +3622 1136 0 4396d4a4 13306 +3623 1137 0 439708a0 13180 +3624 1138 0 43973c1c 5787 +3625 1139 0 439752b8 8666 +3626 1140 0 43977494 8491 +3627 1141 0 439795c0 9435 +3628 1142 0 4397ba9c 5292 +3629 1143 0 4397cf48 6134 +3630 1144 0 4397e740 7342 +3631 1145 0 439803f0 6170 +3632 1146 0 43981c0c 12208 +3633 1147 0 43984bbc 10300 +3634 1148 0 439873f8 13925 +3635 1149 0 4398aa60 13339 +3636 1150 0 4398de7c 10506 +3637 1151 0 43990788 8899 +3638 1152 0 43992a4c 18334 +3639 1153 0 439971ec 16075 +3640 1154 0 4399b0b8 18902 +3641 1155 0 4399fa90 15957 +3642 1156 0 439a38e8 20510 +3643 1157 0 439a8908 12490 +3644 1158 0 439ab9d4 15261 +3645 1159 0 439af574 11461 +3646 1160 0 439b223c 18624 +3647 1161 0 439b6afc 11022 +3648 1162 0 439b960c 9571 +3649 1163 0 439bbb70 11827 +3650 1164 0 439be9a4 8005 +3651 1165 0 439c08ec 15004 +3652 1166 0 439c4388 14206 +3653 1167 0 439c7b08 13218 +3654 1168 0 439caeac 15900 +3655 1169 0 439cecc8 12411 +3656 1170 0 439d1d44 14412 +3657 1171 0 439d5590 17628 +3658 1172 0 439d9a6c 35208 +3659 1173 0 439e23f4 24100 +3660 1174 0 439e8218 24356 +3661 1175 0 439ee13c 14334 +3662 1176 0 439f193c 22653 +3663 1177 0 439f71bc 17064 +3664 1178 0 439fb464 17415 +3665 1179 0 439ff86c 12591 +3666 1180 0 43a0299c 16871 +3667 1181 0 43a06b84 16656 +3668 1182 0 43a0ac94 20183 +3669 1183 0 43a0fb6c 16317 +3670 1184 0 43a13b2c 18915 +3671 1185 0 43a18510 24264 +3672 1186 0 43a1e3d8 21983 +3673 1187 0 43a239b8 13016 +3674 1188 0 43a26c90 21432 +3675 1189 0 43a2c048 11096 +3676 1190 0 43a2eba0 25312 +3677 1191 0 43a34e80 13478 +3678 1192 0 43a38328 17196 +3679 1193 0 43a3c654 13839 +3680 1194 0 43a3fc64 17877 +3681 1195 0 43a4423c 12367 +3682 1196 0 43a4728c 10214 +3683 1197 0 43a49a74 14210 +3684 1198 0 43a4d1f8 11368 +3685 1199 0 43a4fe60 15774 +3686 1200 0 43a53c00 14701 +3687 1201 0 43a57570 11141 +5007 1202 0 43a5a0f8 46477 +5012 1203 0 43a65688 640047 +5013 1204 0 43b01ab8 23575 +5014 1205 0 43b076d0 20695 +5015 1206 0 43b0c7a8 20215 +5016 1207 0 43b116a0 38310 +5017 1208 0 43b1ac48 34419 +5018 1209 0 43b232bc 159757 +5019 1210 0 43b4a2cc 52030 +5020 1211 0 43b56e0c 9391 +5021 1212 0 43b592bc 8402 +5022 1213 0 43b5b390 22550 +5023 1214 0 43b60ba8 32140 +5024 1215 0 43b68934 14916 +5025 1216 0 43b6c378 80836 +5026 1217 0 43b7ff3c 108395 +5027 1218 0 43b9a6a8 36101 +5028 1219 0 43ba33b0 26803 +5029 1220 0 43ba9c64 39000 +5030 1221 0 43bb34bc 44566 +5031 1222 0 43bbe2d4 48923 +5032 1223 0 43bca1f0 71959 +5033 1224 0 43bdbb08 71640 +5034 1225 0 43bed2e0 30422 +5035 1226 0 43bf49b8 148274 +5036 1227 0 43c18cec 67780 +5037 1228 0 43c295b0 20662 +5038 1229 0 43c2e668 16238 +5039 1230 0 43c325d8 105980 +5040 1231 0 43c4c3d4 13413 +5041 1232 0 43c4f83c 23038 +5042 1233 0 43c5523c 30671 +5043 1234 0 43c5ca0c 15644 +5044 1235 0 43c60728 32135 +5045 1236 0 43c684b0 40408 +5046 1237 0 43c72288 64462 +5047 1238 0 43c81e58 36012 +5048 1239 0 43c8ab04 100327 +5049 1240 0 43ca32ec 124575 +5050 1241 0 43cc198c 118612 +5051 1242 0 43cde8e0 91659 +5052 1243 0 43cf4eec 56183 +5053 1244 0 43d02a64 74730 +5054 1245 0 43d14e50 100022 +5055 1246 0 43d2d508 97661 +5056 1247 0 43d45288 154875 +5057 1248 0 43d6af84 28372 +5058 1249 0 43d71e58 84919 +5059 1250 0 43d86a10 78912 +5060 1251 0 43d99e50 61212 +5061 1252 0 43da8d6c 184423 +5062 1253 0 43dd5dd4 38390 +5074 1254 0 43ddf3cc 52208 +5075 1255 0 43debfbc 15956 +5076 1256 0 43defe10 19190 +5077 1257 0 43df4908 25990 +5078 1258 0 43dfae90 10427 +5079 1259 0 43dfd74c 23940 +5080L 1260 0 43e034d0 69970 +5080R 1261 0 43e14624 87775 +5081L 1262 0 43e29d04 87775 +5081R 1263 0 43e3f3e4 87775 +5083 1264 0 43e54ac4 87775 +5084 1265 0 43e6a1a4 97204 +5085 1266 0 43e81d58 36141 +5086 1267 0 43e8aa88 31888 +5087 1268 0 43e92718 44632 +5088 1269 0 43e9d570 13856 +5089 1270 0 43ea0b90 61796 +5090 1271 0 43eafcf4 58118 +5091L 1272 0 43ebdffc 46763 +5091R 1273 0 43ec96a8 59327 +5092 1274 0 43ed7e68 59327 +5093 1275 0 43ee6628 13736 +5094 1276 0 43ee9bd0 14581 +5095 1277 0 43eed4c8 9974 +5096 1278 0 43eefbc0 9102 +5097 1279 0 43ef1f50 18036 +5098 1280 0 43ef65c4 13923 +5099 1281 0 43ef9c28 50204 +5100 1282 0 43f06044 61390 +5101 1283 0 43f15014 61842 +5102 1284 0 43f241a8 40950 +5103 1285 0 43f2e1a0 56283 +5104 1286 0 43f3bd7c 170942 +5105 1287 0 43f6593c 266150 +5106 1288 0 43fa68e4 10870 +5107 1289 0 43fa935c 10048 +5108 1290 0 43faba9c 7964 +5109 1291 0 43fad9b8 18295 +5110 1292 0 43fb2130 16221 +5111 1293 0 43fb6090 14450 +5112 1294 0 43fb9904 176608 +5113 1295 0 43fe4ae4 90615 +5114 1296 0 43ffacdc 57728 +5115 1297 0 44008e5c 375564 +5116 1298 0 44064968 338599 +5121 1299 0 440b7410 494404 +5122 1300 0 4412ff54 124874 +5123 1301 0 4414e720 380559 +5124 1302 0 441ab5b0 32339 +5125 1303 0 441b3404 21976 +5126 1304 0 441b89dc 59128 +5127 1305 0 441c70d4 56560 +5128 1306 0 441d4dc4 63612 +5129 1307 0 441e4640 61458 +5130 1308 0 441f3654 26480 +5131 1309 0 441f9dc4 40579 +5132 1310 0 44203c48 34483 +5133 1311 0 4420c2fc 27914 +5134 1312 0 44213008 80915 +5135 1313 0 44226c1c 27778 +5136 1314 0 4422d8a0 24514 +5137 1315 0 44233864 26959 +5138 1316 0 4423a1b4 59653 +5143 1317 0 44248abc 63530 +5144 1318 0 442582e8 376884 +5156 1319 0 442b431c 64926 +5161 1320 0 442c40bc 214674 +5162 1321 0 442f8750 40091 +5165 1322 0 443023ec 58147 +5166 1323 0 44310710 140955 +5167 1324 0 44332dac 125652 +5168 1325 0 44351880 106892 +5169 1326 0 4436ba0c 118386 +5170 1327 0 44388880 82543 +5172 1328 0 4439caf0 49719 +5173 1329 0 443a8d28 43936 +5174 1330 0 443b38c8 29181 +5175 1331 0 443baac8 101018 +5176 1332 0 443d3564 6538 +5177 1333 0 443d4ef0 23184 +5178 1334 0 443da980 13551 +5179 1335 0 443dde70 60004 +5180 1336 0 443ec8d4 44700 +5181 1337 0 443f7770 48951 +5191 1338 0 444036a8 11506 +5192 1339 0 4440639c 7706 +5193 1340 0 444081b8 11096 +5194 1341 0 4440ad10 37380 +5195 1342 0 44413f14 55746 +5197 1343 0 444218d8 77903 +5198 1344 0 44434928 38734 +5199 1345 0 4443e078 8333 +5200 1346 0 44440108 7554 +5201 1347 0 44441e8c 10492 +5202 1348 0 44444788 27011 +5204 1349 0 4444b10c 10659 +5205 1350 0 4444dab0 52786 +5206 1351 0 4445a8e4 25021 +5207 1352 0 44460aa4 27444 +5208 1353 0 444675d8 24988 +5209 1354 0 4446d774 46802 +5210 1355 0 44478e48 15846 +5211 1356 0 4447cc30 31264 +5212 1357 0 44484650 71885 +5213 1358 0 44495f20 17558 +5214 1359 0 4449a3b8 27850 +5215 1360 0 444a1084 19596 +5220 1361 0 444a5d10 74480 +5239 1362 0 444b8000 29132 +5240 1363 0 444bf1cc 31688 +5241 1364 0 444c6d94 43635 +5244 1365 0 444d1808 17404 +5245 1366 0 444d5c04 24630 +5246 1367 0 444dbc3c 84140 +5247 1368 0 444f04e8 101602 +5248 1369 0 445091cc 131893 +5249 1370 0 44529504 33613 +5250 1371 0 44531854 49840 +5251 1372 0 4453db04 40990 +5252 1373 0 44547b24 25267 +5253 1374 0 4454ddd8 19190 +5254 1375 0 445528d0 36738 +5255 1376 0 4455b854 11302 +5256 1377 0 4455e47c 40141 +5257 1378 0 4456814c 15170 +5258 1379 0 4456bc90 28538 +5259 1380 0 44572c0c 9272 +5260 1381 0 44575044 54757 +5261 1382 0 4458262c 35710 +5262 1383 0 4458b1ac 13126 +5263 1384 0 4458e4f4 13126 +5264 1385 0 4459183c 11555 +5265 1386 0 44594560 32724 +5266 1387 0 4459c534 36280 +5267 1388 0 445a52ec 24590 +5268 1389 0 445ab2fc 21784 +5269 1390 0 445b0814 16456 +5270 1391 0 445b485c 23920 +5271 1392 0 445ba5cc 30582 +5272 1393 0 445c1d44 13764 +5273 1394 0 445c5308 12589 +5274 1395 0 445c8438 27589 +5275 1396 0 445cf000 24279 +5276 1397 0 445d4ed8 21253 +5277 1398 0 445da1e0 30780 +5278 1399 0 445e1a1c 26972 +5279 1400 0 445e8378 64502 +5280 1401 0 445f7f70 11309 +5281 1402 0 445faba0 12861 +5282 1403 0 445fdde0 22560 +5283 1404 0 44603600 25128 +5284 1405 0 44609828 39074 +5285 1406 0 446130cc 36087 +5286 1407 0 4461bdc4 10267 +5287 1408 0 4461e5e0 11787 +5288 1409 0 446213ec 14904 +5289 1410 0 44624e24 65079 +5290 1411 0 44634c5c 13956 +5291 1412 0 446382e0 23158 +5292 1413 0 4463dd58 16988 +5293 1414 0 44641fb4 11056 +5294 1415 0 44644ae4 38181 +5295 1416 0 4464e00c 23662 +5296 1417 0 44653c7c 18461 +5297 1418 0 4465849c 18594 +5298 1419 0 4465cd40 20557 +5299 1420 0 44661d90 44679 +5300 1421 0 4466cc18 16922 +5301 1422 0 44670e34 36559 +5302 1423 0 44679d04 886966 +5303 1424 0 447525bc 713058 +5312 1425 0 44800720 330072 +5313 1426 0 44851078 28551 +5314 1427 0 44858000 15754 +5315 1428 0 4485bd8c 30034 +5316 1429 0 448632e0 24365 +5317 1430 0 44869210 35683 +5318 1431 0 44871d74 60602 +5319 1432 0 44880a30 28903 +5320 1433 0 44887b18 20093 +5321 1434 0 4488c998 14427 +5322 1435 0 448901f4 14847 +5323 1436 0 44893bf4 23082 +5324 1437 0 44899620 24086 +5325 1438 0 4489f438 33534 +5326 1439 0 448a7738 21976 +5327 1440 0 448acd10 22142 +5328 1441 0 448b2390 27669 +5329 1442 0 448b8fa8 19797 +5330 1443 0 448bdd00 34047 +5331 1444 0 448c6200 30582 +5332 1445 0 448cd978 19071 +5333 1446 0 448d23f8 40566 +5334 1447 0 448dc270 18925 +5335 1448 0 448e0c60 34708 +5336 1449 0 448e93f4 32631 +5337 1450 0 448f136c 44254 +5338 1451 0 448fc04c 81195 +5339 1452 0 4490fd78 34117 +5340 1453 0 449182c0 30959 +5341 1454 0 4491fbb0 17160 +5342 1455 0 44923eb8 14583 +5343 1456 0 449277b0 32711 +5344 1457 0 4492f778 37142 +5345 1458 0 44938890 37979 +5346 1459 0 44941cec 36054 +5347 1460 0 4494a9c4 30482 +5348 1461 0 449520d8 39372 +5349 1462 0 4495baa4 29519 +5352 1463 0 44962df4 38350 +5353 1464 0 4496c3c4 7951 +5354 1465 0 4496e2d4 7951 +5355 1466 0 449701e4 7278 +5356 1467 0 44971e54 13866 +5357 1468 0 44975480 41509 +5358 1469 0 4497f6a8 15541 +5360L 1470 0 44983360 7951 +5360R 1471 0 44985270 350174 +5361L 1472 0 449daa50 350174 +5361R 1473 0 44a30230 105333 +5362L 1474 0 44a49da8 105333 +5362R 1475 0 44a63920 108931 +5363L 1476 0 44a7e2a4 108931 +5363R 1477 0 44a98c28 106759 +5364L 1478 0 44ab2d30 106759 +5364R 1479 0 44acce38 92504 +5365L 1480 0 44ae3790 92504 +5365R 1481 0 44afa0e8 78215 +5366L 1482 0 44b0d270 78215 +5366R 1483 0 44b203f8 88301 +5367L 1484 0 44b35ce8 88301 +5367R 1485 0 44b4b5d8 88837 +5368L 1486 0 44b610e0 88837 +5368R 1487 0 44b76be8 87636 +5369L 1488 0 44b8c23c 87636 +5369R 1489 0 44ba1890 96818 +5370L 1490 0 44bb92c4 96818 +5370R 1491 0 44bd0cf8 81519 +5371L 1492 0 44be4b68 81519 +5371R 1493 0 44bf89d8 122104 +5372L 1494 0 44c166d0 122104 +5372R 1495 0 44c343c8 123187 +5373L 1496 0 44c524fc 123187 +5373R 1497 0 44c70630 152708 +5374L 1498 0 44c95ab4 152708 +5374R 1499 0 44cbaf38 98028 +5375L 1500 0 44cd2e24 98028 +5375R 1501 0 44cead10 77455 +5376L 1502 0 44cfdba0 77455 +5376R 1503 0 44d10a30 87788 +5377L 1504 0 44d2611c 87788 +5377R 1505 0 44d3b808 115101 +5378L 1506 0 44d579a8 115101 +5378R 1507 0 44d73b48 67219 +5379L 1508 0 44d841dc 67219 +5379R 1509 0 44d94870 69499 +5380L 1510 0 44da57ec 69499 +5380R 1511 0 44db6768 87702 +5381L 1512 0 44dcbe00 87702 +5381R 1513 0 44de1498 73383 +5382L 1514 0 44df3340 73383 +5382R 1515 0 44e051e8 63434 +5383L 1516 0 44e149b4 63434 +5383R 1517 0 44e24180 62638 +5384L 1518 0 44e33630 62638 +5384R 1519 0 44e42ae0 69590 +5385L 1520 0 44e53ab8 69590 +5385R 1521 0 44e64a90 80763 +5386L 1522 0 44e7860c 80763 +5386R 1523 0 44e8c188 80976 +5387L 1524 0 44e9fdd8 80976 +5387R 1525 0 44eb3a28 68343 +5388L 1526 0 44ec4520 68343 +5388R 1527 0 44ed5018 88837 +5389L 1528 0 44eeab20 88837 +5389R 1529 0 44f00628 88220 +5390 1530 0 44f15ec4 88220 +5391 1531 0 44f2b760 90535 +5392 1532 0 44f41908 134693 +5393 1533 0 44f62730 163141 +5394 1534 0 44f8a478 77830 +5395 1535 0 44f9d480 68456 +5396 1536 0 44fadfe8 63362 +5397 1537 0 44fbd76c 102092 +5398 1538 0 44fd6638 131296 +5399 1539 0 44ff6718 71640 +5400 1540 0 45007ef0 97754 +5401 1541 0 4501fccc 147855 +5402 1542 0 45043e5c 94144 +5403 1543 0 4505ae1c 81195 +5404 1544 0 4506eb48 76524 +5405 1545 0 45081634 134693 +5406 1546 0 450a245c 83954 +5407 1547 0 450b6c50 158895 +5408 1548 0 450dd900 123653 +5409 1549 0 450fbc08 98178 +5410 1550 0 45113b8c 117285 +5411 1551 0 451305b4 97754 +5412 1552 0 45148390 83264 +5413 1553 0 4515c8d0 87139 +5414 1554 0 45171d34 90110 +5415 1555 0 45187d34 61238 +5416 1556 0 45196c6c 201354 +5417 1557 0 451c7ef8 79071 +5418 1558 0 451db3d8 75462 +5419 1559 0 451edaa0 93932 +5420 1560 0 4520498c 81619 +5421 1561 0 45218860 140213 +5422 1562 0 4523ac18 128324 +5423 1563 0 4525a15c 155498 +5424 1564 0 452800c8 123229 +5425 1565 0 4529e228 310050 +5426 1566 0 452e9d4c 152101 +5427 1567 0 4530ef74 99876 +5428 1568 0 45327598 63573 +5429 1569 0 45336df0 31304 +5430 1570 0 4533e838 273535 +5431 1571 0 453814b8 99452 +5432 1572 0 45399934 80982 +5433 1573 0 453ad58c 69093 +5434 1574 0 453be374 44254 +5435 1575 0 453c9054 44043 +5436 1576 0 453d3c60 88837 +5437 1577 0 453e9768 90959 +5438 1578 0 453ffab8 53171 +5439 1579 0 4540ca6c 63998 +5440 1580 0 4541c46c 73127 +5441 1581 0 4542e214 37886 +5442 1582 0 45437614 54232 +5443 1583 0 454449ec 38310 +5444 1584 0 4544df94 40858 +5445 1585 0 45457f30 81406 +5446 1586 0 4546bd30 119630 +5447 1587 0 45489080 82314 +5448 1588 0 4549d20c 107848 +5449 1589 0 454b7754 48724 +5450 1590 0 454c35a8 35947 +5451 1591 0 454cc214 261844 +5452 1592 0 4550c0e8 142931 +5453 1593 0 4552ef3c 55852 +5454 1594 0 4553c968 35349 +5455 1595 0 45545380 46867 +5456 1596 0 45550a94 43821 +5457 1597 0 4555b5c4 43821 +5458 1598 0 455660f4 63581 +5459 1599 0 45575954 79983 +5460 1600 0 455891c4 71138 +5461 1601 0 4559a7a8 33663 +5462 1602 0 455a2b28 58783 +5463 1603 0 455b10c8 51467 +5464 1604 0 455bd9d4 30387 +5465 1605 0 455c5088 35903 +5466 1606 0 455cdcc8 30798 +5467 1607 0 455d5518 30240 +5468 1608 0 455dcb38 61966 +5469 1609 0 455ebd48 44014 +5470 1610 0 455f6938 30904 +5471 1611 0 455fe1f0 50794 +5472 1612 0 4560a85c 44902 +5473 1613 0 456157c4 77646 +5474 1614 0 45628714 42527 +5475 1615 0 45632d34 32702 +5476 1616 0 4563acf4 45716 +5477 1617 0 45645f88 40186 +5478 1618 0 4564fc84 34646 +5479 1619 0 456583dc 59830 +5480L 1620 0 45666d94 508373 +5480R 1621 0 456e2f6c 88854 +5481L 1622 0 456f8a84 88854 +5481R 1623 0 4570e59c 100800 +5482L 1624 0 45726f5c 100800 +5482R 1625 0 4573f91c 75015 +5483L 1626 0 45751e24 75015 +5483R 1627 0 4576432c 76886 +5484L 1628 0 45776f84 76886 +5484R 1629 0 45789bdc 106846 +5485L 1630 0 457a3d3c 106846 +5485R 1631 0 457bde9c 75592 +5486L 1632 0 457d05e4 75592 +5486R 1633 0 457e2d2c 71459 +5487L 1634 0 457f4450 71459 +5487R 1635 0 45805b74 69309 +5488L 1636 0 45816a34 69309 +5488R 1637 0 458278f4 83878 +5489L 1638 0 4583c09c 83878 +5489R 1639 0 45850844 84092 +5490L 1640 0 458650c0 84092 +5490R 1641 0 4587993c 68434 +5491L 1642 0 4588a490 68434 +5491R 1643 0 4589afe4 79526 +5492L 1644 0 458ae68c 79526 +5492R 1645 0 458c1d34 73709 +5493L 1646 0 458d3d24 73709 +5493R 1647 0 458e5d14 75413 +5494L 1648 0 458f83ac 75413 +5494R 1649 0 4590aa44 81798 +5495L 1650 0 4591e9cc 81798 +5495R 1651 0 45932954 136661 +5496L 1652 0 45953f2c 136661 +5496R 1653 0 45975504 99269 +5603L 1654 0 4598d8cc 99269 +5603R 1655 0 459a5c94 251260 +6010 1656 0 459e3210 251260 +6011 1657 0 45a2078c 10318 +6012 1658 0 45a22fdc 43850 +6013 1659 0 45a2db28 199019 +6014 1660 0 45a5e494 66546 +codec.dat 1661 0 45a6e888 34276 +DebugImages.tpl 1662 0 45a78000 12409824 +dummy.tpl 1663 0 4664dbe0 1835136 +face.dat 1664 0 4680dc60 256 +ip.cfg 1665 0 46810000 7034880 +mgso.rel 1666 0 46ec5800 48 +mgso.str 1667 0 46ec5830 5729024 +movie.dat 1668 0 4743c330 35 +stage 1669 0 47440000 94935040 +preview 1670 1 5c 1672 +data.cnf 1671 1 685 1672 +vox.dat 1672 0 4cec9800 175 +freeing memory used by FST string table... ...done. diff --git a/source/.svn/text-base/std_disclaimer.h.svn-base b/source/.svn/text-base/std_disclaimer.h.svn-base new file mode 100755 index 0000000..6e8827c --- /dev/null +++ b/source/.svn/text-base/std_disclaimer.h.svn-base @@ -0,0 +1,13 @@ +/* What you are seeing is a work in progress. Source and comments + it contains could be dangerous, profane, or just plain wrong. + While I generally don't publish source code unless I feel it's in + a semi-production state (or at least to the point where someone + somewhere could benefit from it), I can't guarantee anything. + + If you use this code and the genie of your computer (or your cube!) escapes in + a puff of smoke, I will not be held liable. You have been warned. + This code may be ugly, incomplete, or just plain wrong. + + No F'in warranty implied! + + Andrew K 2005 andrew@aklabs.net */ diff --git a/source/CVS/.svn/all-wcprops b/source/CVS/.svn/all-wcprops new file mode 100755 index 0000000..1d14ac4 --- /dev/null +++ b/source/CVS/.svn/all-wcprops @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/aklabs/!svn/ver/10/trunk/gcmbrowser/source/CVS +END +Repository +K 25 +svn:wc:ra_dav:version-url +V 62 +/svn/aklabs/!svn/ver/10/trunk/gcmbrowser/source/CVS/Repository +END +Root +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/aklabs/!svn/ver/10/trunk/gcmbrowser/source/CVS/Root +END +Entries +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/aklabs/!svn/ver/10/trunk/gcmbrowser/source/CVS/Entries +END diff --git a/source/CVS/.svn/entries b/source/CVS/.svn/entries new file mode 100755 index 0000000..981ec34 --- /dev/null +++ b/source/CVS/.svn/entries @@ -0,0 +1,130 @@ +10 + +dir +44 +https://127.0.0.1/svn/aklabs/trunk/gcmbrowser/source/CVS +https://127.0.0.1/svn/aklabs + + + +2007-05-26T21:39:54.335125Z +10 +andrew + + + + + + + + + + + + + + +eb184899-6090-47d4-a65b-558f62f6ea1c + +Repository +file + + + + +2010-02-05T03:38:38.432623Z +dd9ce8b79f776a0af94e6e826fafa5a5 +2007-05-26T21:39:54.335125Z +10 +andrew + + + + + + + + + + + + + + + + + + + + + +24 + +Root +file + + + + +2010-02-05T03:38:38.432623Z +7af14a164593104c1e7a07a572dd352a +2007-05-26T21:39:54.335125Z +10 +andrew + + + + + + + + + + + + + + + + + + + + + +24 + +Entries +file + + + + +2010-02-05T03:38:38.432623Z +e1a46804a276c986516219ef14fc2ee1 +2007-05-26T21:39:54.335125Z +10 +andrew + + + + + + + + + + + + + + + + + + + + + +346 + diff --git a/source/CVS/.svn/text-base/Entries.svn-base b/source/CVS/.svn/text-base/Entries.svn-base new file mode 100755 index 0000000..d8bbddb --- /dev/null +++ b/source/CVS/.svn/text-base/Entries.svn-base @@ -0,0 +1,8 @@ +/Makefile/1.1.1.1/Sun Jan 1 00:15:04 2006// +/README.txt/1.1.1.1/Sun Jan 1 00:15:04 2006// +/gcmbrowser.cpp/1.1.1.1/Sun Jan 1 00:15:04 2006// +/gcminfo.cpp/1.1.1.1/Sun Jan 1 00:15:04 2006// +/gcminfo.h/1.1.1.1/Sun Jan 1 00:15:04 2006// +/sample-output.txt/1.1.1.1/Sun Jan 1 00:15:04 2006// +/std_disclaimer.h/1.1.1.1/Sun Jan 1 00:15:04 2006// +D diff --git a/source/CVS/.svn/text-base/Repository.svn-base b/source/CVS/.svn/text-base/Repository.svn-base new file mode 100755 index 0000000..5468d98 --- /dev/null +++ b/source/CVS/.svn/text-base/Repository.svn-base @@ -0,0 +1 @@ +utils/gcmbrowser/source diff --git a/source/CVS/.svn/text-base/Root.svn-base b/source/CVS/.svn/text-base/Root.svn-base new file mode 100755 index 0000000..180ad4a --- /dev/null +++ b/source/CVS/.svn/text-base/Root.svn-base @@ -0,0 +1 @@ +andrew@gabbo:/home/cvsd diff --git a/source/CVS/Entries b/source/CVS/Entries new file mode 100755 index 0000000..d8bbddb --- /dev/null +++ b/source/CVS/Entries @@ -0,0 +1,8 @@ +/Makefile/1.1.1.1/Sun Jan 1 00:15:04 2006// +/README.txt/1.1.1.1/Sun Jan 1 00:15:04 2006// +/gcmbrowser.cpp/1.1.1.1/Sun Jan 1 00:15:04 2006// +/gcminfo.cpp/1.1.1.1/Sun Jan 1 00:15:04 2006// +/gcminfo.h/1.1.1.1/Sun Jan 1 00:15:04 2006// +/sample-output.txt/1.1.1.1/Sun Jan 1 00:15:04 2006// +/std_disclaimer.h/1.1.1.1/Sun Jan 1 00:15:04 2006// +D diff --git a/source/CVS/Repository b/source/CVS/Repository new file mode 100755 index 0000000..5468d98 --- /dev/null +++ b/source/CVS/Repository @@ -0,0 +1 @@ +utils/gcmbrowser/source diff --git a/source/CVS/Root b/source/CVS/Root new file mode 100755 index 0000000..180ad4a --- /dev/null +++ b/source/CVS/Root @@ -0,0 +1 @@ +andrew@gabbo:/home/cvsd diff --git a/source/Makefile b/source/Makefile new file mode 100755 index 0000000..0d0fbba --- /dev/null +++ b/source/Makefile @@ -0,0 +1,94 @@ +# Visual SlickEdit generated file. Do not edit this file except in designated areas. +# -----Begin user-editable area----- + +# -----End user-editable area----- + +# Make command to use for dependencies +MAKECMD=gmake + +# If no configuration is specified, "Debug" will be used +ifndef "CFG" +CFG=Debug +endif + +# +# Configuration: Debug +# +ifeq "$(CFG)" "Debug" +OUTDIR=Debug +OUTFILE=$(OUTDIR)/gcmbrowser +CFG_INC= +CFG_LIB= +CFG_OBJ= +COMMON_OBJ=$(OUTDIR)/gcmbrowser.o +OBJ=$(COMMON_OBJ) $(CFG_OBJ) + +COMPILE=g++ -c -g -o "$(OUTDIR)/$(*F).o" $(CFG_INC) "$<" +LINK=g++ -g -o "$(OUTFILE)" $(OBJ) $(CFG_LIB) + +# Pattern rules +$(OUTDIR)/%.o : source/%.cpp + $(COMPILE) + +# Build rules +all: $(OUTFILE) + +$(OUTFILE): $(OUTDIR) $(OBJ) + $(LINK) + +$(OUTDIR): + mkdir -p "$(OUTDIR)" + +# Rebuild this project +rebuild: cleanall all + +# Clean this project +clean: + rm -f source/*o + rm -f $(CFG)/*o + rm -f $(OUTFILE) + +# Clean this project and all dependencies +cleanall: clean +endif + +# +# Configuration: Release +# +ifeq "$(CFG)" "Release" +OUTDIR=Release +OUTFILE=$(OUTDIR)/gcmbrowser +CFG_INC= +CFG_LIB= +CFG_OBJ= +COMMON_OBJ=$(OUTDIR)/gcmbrowser.o +OBJ=$(COMMON_OBJ) $(CFG_OBJ) + +COMPILE=g++ -c -o "$(OUTDIR)/$(*F).o" $(CFG_INC) "$<" +LINK=g++ -o "$(OUTFILE)" $(OBJ) $(CFG_LIB) + +# Pattern rules +$(OUTDIR)/%.o : source/%.cpp + $(COMPILE) + +# Build rules +all: $(OUTFILE) + +$(OUTFILE): $(OUTDIR) $(OBJ) + $(LINK) + +$(OUTDIR): + mkdir -p "$(OUTDIR)" + +# Rebuild this project +rebuild: cleanall all + +# Clean this project +clean: + rm -f source/*o + rm -f $(CFG)/*o + rm -f $(OUTFILE) + +# Clean this project and all dependencies +cleanall: clean +endif diff --git a/source/README.txt b/source/README.txt new file mode 100755 index 0000000..67606d5 --- /dev/null +++ b/source/README.txt @@ -0,0 +1,26 @@ +This is libgcm V0.1a, an early alpha of my library for +manipulating gamecube master files. It currently has +little functionality, but you can list and extract the contents +of GCMs - the only thing I haven't got extracting correctly +yet is the apploader stuff, because I haven't even really +begun working on that yet, and don't know how to really test +the results of that extraction. + + Before this is over, I intend to have the library +ready to insert, append, and create entire new images for +burning to a GCM. My final test of this ability will be to +completely unpack a disc image onto the drive (which it can +already do, with the exception of the apploader) and re-pack +it and see if it plays. + + Maybe someone will be helped by this code. GPL applies. +This code is free as in freedom. If you have any additions you +would like to see in the next release, I'd be happy to include them, +with credit. Just email them to me or find me in #gcdev on EFNet. + + Enjoy! + Andrew K + andrew@aklabs.net + andrewk in #gcdev on EFNet + 120817314 ICQ + diff --git a/source/gcmbrowser.cpp b/source/gcmbrowser.cpp new file mode 100755 index 0000000..c31bdd7 --- /dev/null +++ b/source/gcmbrowser.cpp @@ -0,0 +1,163 @@ +#include "gcminfo.h" +#include +#include + +// All the interesting stuff is in gcminfo.c|h ; gcmbrowser.cpp is just a proof +// and simple util. + +const char *usage = +"gcmbrowser V0.01 (C) 2005 Andrew Kesterson (andrew@aklabs.net) \n\ +\n\ +Usage: gcmbrowser <.gcm file> \n\ +\n\ +operations:\n\ + -h : print this help\n\ + -H : print the disk header (maker, title, etc)\n\ + -E : explode the filesystem into the current directory\n\ + -e : extract \"file\" from the gcm. With -o you\n\ + may specify an optional output filename; by default,\n\ + the file will be named the same (and reside in the\n\ + same directory tree) as in the image. You may specify\n\ + the source file by file number or by filename (full path\n\ + is necessary when specifying by filename.)\n\ + -o : specify the destination for a -e operation.\n\ + -l : list the names and file numbers of all files in the GCM.\n\ + All files are printed with full path.\n\ + -d : when extracting a file, create all needed directories for\n\ + the output file. This can, but really shouldn't, be used with\n\ + the -o option.\n\ +\n"; + +const char *shortopts = "hHEe:o:ld"; + +#define OP_PRINT_HEADER 0 +#define OP_EXPLODE 2 +#define OP_EXTRACT 4 +#define OP_LIST 8 +#define OP_CREATE_DIRS 1024 + +int main(int argc, char **argv) +{ + std::string gcmFname; + std::string outFname; + std::string extractFname; + unsigned int extractFnumber= -1; + int outIsDigit = 1; + int ctr = 0; + int op = 0; + GCM theGCM; + unsigned int opt = 0; + unsigned int ret = 0; + + if ( argc < 2 ) { + fprintf(stderr, usage); + return 1; + } + + opt = getopt(argc, argv, shortopts); + while ( opt != -1) { + switch ( opt ){ + case 'h': + fprintf(stderr, usage); + return 1; + case 'H': + op = OP_PRINT_HEADER; + break; + case 'E': + op = OP_EXPLODE; + break; + case 'e': + op = OP_EXTRACT; + for ( ctr = 0; ctr < strlen(optarg) ; ctr++ ) { + if ( isprint(optarg[ctr]) && !isdigit(optarg[ctr])) { + outIsDigit = 0; + } else { + //printf("DEBUG : extract filename character %c is a digit\n", optarg[ctr]); + continue; + } + } + if ( outIsDigit == 0 ) { + //printf("DEBUG : extract filename option is NON-DIGIT %s\n", optarg); + extractFname.reserve(strlen(optarg)); + extractFname.assign(optarg); + break; + } + else { + //printf("DEBUG : extract filename option is file number %s\n", optarg); + extractFnumber = atoi(optarg); + break; + } + case 'o': + outFname.reserve(strlen(optarg)); + outFname.assign(optarg); + break; + case 'l': + op = OP_LIST; + break; + case 'd': + op |= OP_CREATE_DIRS; + break; + default: + fprintf(stderr, "I don't understand option -%c\n", opt); + return 1; + } + opt = getopt(argc, argv, shortopts); + } + gcmFname.reserve(strlen(argv[optind])); + gcmFname.assign(argv[optind]); + + if ( gcmInit((char *)gcmFname.c_str(), &theGCM) ) { + printf("Couldn't init GCM file %s\n", argv[1]); + return 1; + } + + int top = 0; + if ( op & OP_CREATE_DIRS ) top = op ^ OP_CREATE_DIRS; + else top = op; + switch ( top ) { + case OP_EXPLODE: + ret = gcmExplode(&theGCM); + if ( ! ret ) + fprintf(stderr, "Failed to explode filesystem.\n"); + break; + case OP_EXTRACT: + if ( extractFnumber == -1 ) { + //printf("DEBUG : getting file number for %s\n", extractFname.c_str()); + extractFnumber = gcmGetFileByName(&theGCM, (char *)extractFname.c_str()); + //printf("DEBUG: got %d\n", extractFnumber); + } + if ( extractFnumber > theGCM.fst.stringtable.size() || extractFnumber == -1) { + fprintf(stderr, "File number %d requested was beyond the length of the filesystem\n", extractFnumber); + break; + } + if ( outFname.length() == 0 && ( op & OP_CREATE_DIRS ) ) { + char *outfile = (char *) new char[GCNDVD_FNAME_LENGTH]; + gcmGetFullFileName(&theGCM, extractFnumber, outfile); + std::string execstring = ""; + // this is a quick hack to ensure that the output directory exists + execstring.append("mkdir -p ."); + execstring.append("`dirname "); + execstring.append(outfile); + execstring.append("`"); + system(execstring.c_str()); + delete outfile; + } + if ( outFname.length() > 0 ) + ret = gcmExtractFile(&theGCM, extractFnumber, (char *)outFname.c_str()); + else + ret = gcmExtractFile(&theGCM, extractFnumber, NULL); + if ( ret != 0 ) + fprintf(stderr, "Failed to extract file number %d to output file %s\n", extractFnumber, outFname.length() > 0 ? (char *)outFname.c_str() : "" ); + break; + case OP_PRINT_HEADER: + ret = gcmPrint(&theGCM); + break; + case OP_LIST: + ret = gcmPrintFST(&theGCM); + break; + } + + gcmFreeStringTable(&theGCM); + + return ret; +} diff --git a/source/gcminfo.cpp b/source/gcminfo.cpp new file mode 100755 index 0000000..6d8d4f2 --- /dev/null +++ b/source/gcminfo.cpp @@ -0,0 +1,674 @@ +#include "gcminfo.h" +#include +#include +#include + +int needByteSwap = 0; + +// these are functions that the user really doesn't need to see, +// so they're declared here away from the external API. They're +// used mainly for populating the internal FST data structure. +// All the user-necessary functions are listed out in gcminfo.h. + +int gcmPopulateFST(GCM *data, FILE *file); +void *gcmWhichData(int whichdata, GCM *data); +int gcmGetData(int whichdata, GCM *data, FILE *file); +int gcmGetFile(GCM *data, GCM_FSTEntry *entry, int fnum, FILE *file); +int gcmCheckMagic(FILE *file); + +// checks the magic number of the DVD file, and sets needByteSwap +// returns the final value of needByteSwap. Returns -1 if the magic +// word doesn't match either way and needByteSwap couldn't be set. +int gcmCheckMagic(FILE *file) +{ + int magic = 0; + fseek(file, GCMPieces[GCM_DHEAD_DVDMAGIC].offset, 0); + fread(&magic, GCMPieces[GCM_DHEAD_DVDMAGIC].size, 1, file); + + if ( magic == GCNDVD_MAGICNUM ) { + needByteSwap = 0; + } else { + magic = (((magic&0x000000FF)<<24)+((magic&0x0000FF00)<<8)+ + ((magic&0x00FF0000)>>8)+((magic&0xFF000000)>>24)); + if ( magic == GCNDVD_MAGICNUM ) { + needByteSwap = 1; + } + else needByteSwap = -1; + } + + return needByteSwap; +} + +// swap from big to little endian (only needed on intel machines) +// only works if needByteSwap is > -1 +int byteSwap (int nLongNumber) +{ + if ( needByteSwap ) return (((nLongNumber&0x000000FF)<<24)+((nLongNumber&0x0000FF00)<<8)+ + ((nLongNumber&0x00FF0000)>>8)+((nLongNumber&0xFF000000)>>24)); + else if ( needByteSwap == -1 ) return 0; // refuse to work +} + +// return the type (0=file 1=directory) for the given FST entry +int gcmGetFSTEntryType(GCM_FSTEntry *entry) +{ + return entry->fname_offset >> 24; +} + +// uses one of the GCM_* definitions to return a pointer to +// the appropriate point of the GCM struct to read data into. +void *gcmWhichData(int whichdata, GCM *data) +{ + void *toPrint = NULL; + + switch (whichdata) { + case GCM_DHEAD_GAMECODE: + toPrint = &data->head.gamecode; + break; + case GCM_DHEAD_GAMEMAKER: + toPrint = &data->head.gamemaker; + break; + case GCM_DHEAD_DVDMAGIC: + toPrint = &data->head.magicword; + break; + case GCM_DHEAD_GAMENAME: + toPrint = &data->head.gamename; + break; + case GCM_DHEAD_DEBUGMON: + toPrint = &data->head.debugmon; + break; + case GCM_DHEAD_DEBUGMONADDR: + toPrint = &data->head.debugmonaddr; + break; + case GCM_DHEAD_BOOTFILE: + toPrint = &data->head.bootfile; + break; + case GCM_DHEAD_FST: + toPrint = &data->fst.offset; + break; + case GCM_DHEAD_FSTSIZE: + toPrint = &data->fst.size; + break; + case GCM_DHEAD_FSTMAXSIZE: + toPrint = &data->fst.maxsize; + break; + case GCM_DHEAD_USERPOS: + toPrint = &data->head.userpos; + break; + case GCM_DHEAD_USERLEN: + toPrint = &data->head.userlen; + break; + case GCM_DHEADINF_DEBUGMONSIZE: + toPrint = &data->headInf.debugmonsize; + break; + case GCM_DHEADINF_SIMMEMSIZE: + toPrint = &data->headInf.simmemsize; + break; + case GCM_DHEADINF_ARGOFFSET: + toPrint = &data->headInf.simmemsize; + break; + case GCM_DHEADINF_DEBUGFLAG: + toPrint = &data->headInf.debugflag; + break; + case GCM_DHEADINF_TRACKLOCATION: + toPrint = &data->headInf.tracklocation; + break; + case GCM_DHEADINF_TRACKSIZE: + toPrint = &data->headInf.tracksize; + break; + case GCM_DHEADINF_COUNTRYCODE: + toPrint = &data->headInf.countrycode; + break; + case GCM_APPLOADER_VERSION: + toPrint = &data->apploader.datever; + break; + case GCM_APPLOADER_ENTRY: + toPrint = &data->apploader.entry; + break; + case GCM_APPLOADER_SIZE: + toPrint = &data->apploader.size; + break; + case GCM_APPLOADER_TRAILERSIZE: + toPrint = &data->apploader.trailersize; + break; + case GCM_APPLOADER_BINARY: + toPrint = &data->apploader.apploader; + break; + case GCM_FST_ROOT: + toPrint = (void *)"Not implemented yet"; + break; + case GCM_FST_STRINGTABLEOFF: + toPrint = &data->fst.stringtable_offset; + break; + default: + return NULL; + } + + return toPrint; +} + +// print the info in data as indicated by the GCM_* +// passed to whichdata +int gcmPrintData(int whichdata, GCM *data) +{ + void *ptr; + if ( GCMPieces[whichdata].type == 1) { + char *theData = (char *)gcmWhichData(whichdata,data); + printf("%-38s:\t %s\n", GCMPieces[whichdata].name, theData); + } + else { + int *theData = (int *)gcmWhichData(whichdata,data); + if ( theData ) { + printf("%-38s:\t %x\n", GCMPieces[whichdata].name, *theData); + } + else { + printf("%-38s:\t refusing to print NULL pointer...\n", + "(untested function/invalid data)"); // this means you're using a feature that doesn't work (yet) + } + } +} + +// print the information for a given file in data (by entry num) +int gcmPrintFile(GCM *data, int fnum) +{ + GCM_FSTEntry f; + char *fname = NULL; + + // printf("DEBUG : retrieving file data for number %d\n", fnum); + f = data->fst.entries.at(fnum); + + // see gcmPrint for how this is laid out... + if ( fnum >= data->fst.entries.size() ) + fname = "(out_of_bounds string)" ; + else + fname = (char *)data->fst.stringtable.at(fnum)->c_str(); + + printf("%-20s%-6d%-6x%-12x%-20d\n", + fname, + fnum, + gcmGetFSTEntryType(&f), + f.file_offset, + f.file_length); +} + +// reads data into dest and returns the number of bytes read +// (only used internally by the other gcm functions, this should +// be transparent outside the API guts) +int gcmGetData(int whichdata, GCM *data, FILE *file) +{ + int offset = 0; + void *dest = gcmWhichData(whichdata, data); + if ( whichdata > GCM_MAX_PIECES || dest == NULL || file == NULL) { + return 0; + } + + switch ( GCMPieces[whichdata].area ) { + case 0: + offset = GCMPieces[whichdata].offset; + break; + case 1: + offset = GCMPieces[GCM_DHEAD].offset + GCMPieces[whichdata].offset; + break; + case 2: + offset = GCMPieces[GCM_DHEADINF].offset + GCMPieces[whichdata].offset; + break; + case 3: + offset = GCMPieces[GCM_APPLOADER].offset + GCMPieces[whichdata].offset; + break; + case 4: + offset = data->fst.offset + GCMPieces[whichdata].offset; + default: + return 0; + } + + fseek(file, offset, 0); + if ( GCMPieces[whichdata].type == 1 ) { + fgets((char *)dest, GCMPieces[whichdata].size, file) == NULL; + } + else { + fread(dest, 1, GCMPieces[whichdata].size, file); + int *tmp = (int *)dest; + *tmp = byteSwap(*tmp); + } + rewind(file); + return GCMPieces[whichdata].size; +} + +// get the file at fnum from file for the GCM data and store it +// in entry +int gcmGetFile(GCM *data, GCM_FSTEntry *entry, int fnum, FILE *file) +{ + if ( fnum > -1 && file != NULL ) { + rewind(file); + fseek(file, data->fst.offset + (12 * fnum), 0); + + if ( !feof(file) ) { + fread(&entry->fname_offset, 4, 1, file); + entry->fname_offset = byteSwap(entry->fname_offset); + fread(&entry->file_offset, 4, 1, file); + entry->file_offset = byteSwap(entry->file_offset); + fread(&entry->file_length, 4, 1, file); + entry->file_length = byteSwap(entry->file_length); + data->fst.entries.push_back(*entry); + } + } + else return -1; +} + +// populate the FST of the given GCM from file +int gcmPopulateFST(GCM *data, FILE *file) +{ + GCM_FSTEntry *newEntry; + GCM_FSTEntry root; + int i = 0; + int j = 0; + int oldpos = 0; + int maxentries = 0; + char *tmpbuff = new char[GCNDVD_FNAME_LENGTH]; + std::string * strdest = new std::string(""); + char tmp = 0xFF; + int f = 0; + int *appSize = NULL; + + if ( !tmpbuff ) { + return -1; + } + + fseek(file, data->fst.offset, 0); + + // now just loop until there are no more entries... + gcmGetFile(data, &root, 0,file); + root = data->fst.entries.front(); + // this is where we inject the filesystem entries for bootloader.bin, apploader.bin, + // and game.dol ... these aren't technically part of the filesystem, but we + // do this so they can be viewed/extracted like other files. + /* + appSize = (int *)gcmWhichData(GCM_APPLOADER_SIZE, data); + newEntry = new GCM_FSTEntry; + newEntry->fname_offset = 0; + newEntry->file_offset = GCM_APPLOADER_CODE_LOC; + newEntry->file_length = *appSize; + newEntry->stringtable_off = 1; + data->fst.entries.push_back(*newEntry); + delete newEntry;*/ + for ( int i = 1; i < root.file_length ; i++) { + newEntry = new GCM_FSTEntry; + gcmGetFile(data, newEntry, i, file); + delete newEntry; + } + + + // we're past the FST proper; now the string table... + data->fst.stringtable_offset = data->fst.offset + (root.file_length * 12); + fseek(file, data->fst.stringtable_offset, 0); + //printf("FST string table offset calculated to 0x\%x...\n", data->fst.stringtable_offset); + data->fst.stringtable.clear(); + data->fst.stringtable.push_back(&std::string("/\0")); + //data->fst.stringtable.push_back(&std::string("apploader.bin\0")); + memset(tmpbuff, GCNDVD_FNAME_LENGTH, 0x00); + while ( ftell(file) < (data->fst.offset + data->fst.size) && !feof(file)) { + i = 0; + while ( 1 ) { + tmp = fgetc(file); + if ( tmp == 0x00 ) { + break; + } + tmpbuff[i] = tmp; + i++; + } + tmpbuff[i] = '\0'; + strdest->clear(); + strdest->reserve(i); + strdest->assign(tmpbuff); + data->fst.stringtable.push_back(strdest); + // printf("DEBUG : FILENAME WAS %s ... added %s\n", strdest, + // data->fst.stringtable.at(f+1)->c_str()); + memset(tmpbuff, GCNDVD_FNAME_LENGTH, 0x00); + strdest = new std::string(""); + f++; + } + delete tmpbuff; + return 0; +} + +// called inside of gcmInit to make sure everything inside is sane +// (only needed internally) +int gcmZeroOut(GCM *data) +{ + data->apploader.entry = 0; + data->apploader.size = 0; + data->apploader.trailersize = 0; + data->fst.maxsize = 0; + data->fst.offset = 0; + data->fst.size = 0; + data->head.bootfile = 0; + data->head.debugmon = 0; + data->head.debugmonaddr = 0; + data->head.gamecode = 0; + data->head.gamemaker = 0; + data->head.magicword = 0; + data->head.userlen = 0; + data->head.userpos = 0; + data->headInf.argoff = 0; + data->headInf.countrycode = 0; + data->headInf.debugflag = 0; + data->headInf.debugmonsize = 0; + data->headInf.simmemsize = 0; + data->headInf.tracklocation = 0; + data->headInf.tracksize = 0; +} + +// reads all info from the GCM in gcmname and puts it in data +int gcmInit(char *gcmname, GCM *data) +{ + FILE *gcm = fopen(gcmname, "r+b"); + int i = 0; + + if (!gcm) { + return -1; + } + + gcmZeroOut(data); + + switch ( gcmCheckMagic(gcm) ) { + case 0: + needByteSwap = 1; + break; + case 1: + break; + case -1: + //printf("DEBUG: DVD Magic number on GCM image was incorrect or couldn't be understood!\n"); + //printf("DEBUG: Aborting in GCMInit! (filename %s)\n", gcmname); + fclose(gcm); + return -1; + } + + for ( i = 3; i < GCM_MAX_PIECES ; i++) { + gcmGetData(i,data, gcm); + } + + gcmPopulateFST(data, gcm); + + fclose(gcm); + + data->fname = new char[strlen(gcmname)+1]; + if ( !data->fname ) { + printf("couldn't store GCM filename for later retrieval. Aborting.\n"); + gcmFreeStringTable(data); + exit(-1); + } + else strcpy(data->fname, gcmname); + + return 0; +} + +// print all information about the GCM in a columnar format, +// including the FST. +int gcmPrint(GCM *data) +{ + int ml = 0; + int i = 0; + + for (i = 3; i < GCM_MAX_PIECES; i++ ) { + gcmPrintData(i,data); + } + + GCM_FSTEntry root = data->fst.entries.front(); + + printf("%-38s:\t%d\n", "Total files in the FST", root.file_length); + printf("%-38s:\t%d\n", "Total entries in the FST string table", data->fst.stringtable.size()); + return 0; +} + +int gcmPrintFST(GCM *data) +{ + int ml = 0; + int i = 0; + char *tbuff = new char[GCNDVD_FNAME_LENGTH]; + if (!tbuff) { + printf("Couldn't get temporary buffer for full path printing. Aborting.\n"); + return -1; + } else { + memset(tbuff, 0x00, GCNDVD_FNAME_LENGTH); + } + + GCM_FSTEntry root = data->fst.entries.front(); + printf("%-38s:\t%d\n", "Total files in the FST", root.file_length); + printf("%-38s:\t%d\n", "Total entries in the FST string table", data->fst.stringtable.size()); + printf("\n\n\n%30s\n", "(FST CONTENTS)"); + printf("%-16s %-6s %-6s %s %-12s\n", + "(name)", "(fnum)", "(type)", "(offset)", "(length)"); + for (i = 0; i < data->fst.entries.size() - 1 ; i++) { + //printf("DEBUG: retrieving file data for number %d\n", i); + gcmPrintFile(data, i); + } + + printf("\n\t\t\t(PRINTING FILES WITH FULL PATH)\n"); + for (i = 0; i < data->fst.entries.size() - 1; i++ ) { + printf("File %d:", i); + gcmGetFullFileName(data, i, tbuff); + printf(" %s\n", tbuff); + memset(tbuff, 0x00, GCNDVD_FNAME_LENGTH); + } + + delete tbuff; + return 0; +} + +// frees memory used by the string table. MUST be called before zeroing +// the gcm for new reading (gcmInit) or quitting the application. +// This should be accompanied by clearing the entries vector, though the +// destructor in that member should take care of cleanup for you. +// Thou shalt not leak memory! + +int gcmFreeStringTable(GCM *data) +{ + std::string *string = NULL; + int i = 0; + + //printf("freeing memory used by FST string table... "); + + for (i = 0; i < (data->fst.stringtable.size()) ; i++ ) { + string = (std::string *)data->fst.stringtable.at(i); + // we create the "/" entry for 0 manually, and it's not alloc'ed + // so don't try freeing it! + if ( string != NULL && i > 0 ) { + delete string; + } + string = NULL; + } + data->fst.stringtable.clear(); + delete data->fname; + + //printf(" ...done.\n"); +} + +GCM_FSTEntry gcmGetFileByFnum(GCM *data, int fnum) +{ + return data->fst.entries.at(fnum); +} + +int gcmGetFileByOffset(GCM *data, int offset) +{ + GCM_FSTEntry curr; + bool done = false; + + for (int i = 0; i < data->fst.entries.size() -1; i++) { + curr = data->fst.entries.at(i); + if (curr.file_offset == offset) { + return i; + } + } +} + +// takes in a full pathname and retrieves the fnum +// for the appropriate file in the FST +unsigned int gcmGetFileByName(GCM *data, char *name) +{ + GCM_FSTEntry curr; + bool done = false; + int nextStart = 0; + int i = 0; + char *tmp2 = (char *) new char[GCNDVD_FNAME_LENGTH]; + if ( !tmp2 ) { + fprintf(stderr, "Failed to allocate temporary string storage\n"); + return -1; + } + for ( i = 0; i < data->fst.stringtable.size() ; i++ ) { + gcmGetFullFileName(data, i, tmp2); + //printf("DEBUG : comparing filename %s to original %s...\n", name, tmp2); + if ( !strcmp(name, tmp2) ) { + delete tmp2; + //printf("DEBUG : found filename %s at number %d", name, i); + return i; + } + } + delete tmp2; + return -1; +} + +// extracts a file into outfile from the GCM given the fnum. +// FIXME : allow the user to specify a different output filename? +unsigned int gcmExtractFile(GCM *data, int fnum, char *outfname) +{ + FILE *out = NULL; + FILE *gcm = NULL; + int pos = 0; + int endpos = 0; + int b = 0; + GCM_FSTEntry curr; + std::string execstring = ""; + char *outfile = NULL; + std::string tmpStr = ""; + + // check that the fnum is in range + + if ( fnum < data->fst.entries.size() - 1) { + curr = data->fst.entries.at(fnum); + } + else { + return -1; + } + + // if it's a file, open the outfile, open the GCM, and perform the copy - clean up and exit + if ( gcmGetFSTEntryType(&curr) == 0 ) { + if ( outfname ) { + outfile = outfname; + tmpStr = ""; + } else { + outfile = new char[GCNDVD_FNAME_LENGTH]; + if ( !outfile ) return -1; + else gcmGetFullFileName(data, fnum, outfile); + tmpStr = "."; + } + tmpStr.append(outfile); + gcm = fopen(data->fname, "rb"); + out = fopen(tmpStr.c_str(), "wb"); + if ( !gcm || !out ) { + gcm ? fclose(gcm) : printf("Couldn't read from gcm file\n"); + out ? fclose(out) : printf("Couldn't write to output file\n"); + return -1; + } + fseek(gcm, curr.file_offset, 0); + endpos = curr.file_offset + curr.file_length; + if ( ftell(gcm) != curr.file_offset || !out || !gcm) { + delete outfile; + fclose(gcm); + fclose(out); + return -1; + } + + while ( !feof(gcm) && ftell(gcm) <= endpos) { + fread(&b, 1, 1, gcm); + if ( needByteSwap == 1 ) b = byteSwap(b); // swap the bytes for the host + fwrite(&b, 1, 1, out); + } + + if ( outfile && !outfname )delete outfile; + fclose(gcm); + fclose(out); + printf("exploded %s\n", tmpStr.c_str()); + return 0; + } + // if it's a dir, construct the mkdir command, do it, clean up and exit. + else { + if ( outfname ) + outfile = outfname; + else { + outfile = new char[GCNDVD_FNAME_LENGTH]; + if (!outfile ) { + return -1; + } + } + gcmGetFullFileName(data, fnum, outfile); + if ( !outfname ) + execstring.append("mkdir -p ."); + else + execstring.append("mkdir -p "); + execstring.append(outfile); + int retcode = system(execstring.c_str()); + if ( outfile && !outfname ) delete outfile; + return 0; + } +} + + +// explodes the FST onto the host filesystem +int gcmExplode(GCM *data) +{ + for ( int i = 0; i <= (data->fst.entries.size() - 1) ; i++ ) { + if ( gcmExtractFile(data, i, NULL) < 0 ) return -1; + } + +} + +// retrieves the full filename for fnum with full path +int gcmGetFullFileName(GCM *data, int fnum, char *dest) +{ + bool finished = false; + GCM_FSTEntry curr; + std::vector fnames; + int fn = fnum; + int depth = 0; + std::string work = ""; + + curr = data->fst.entries.at(fn); + + while (!finished) { + depth++; + if ( depth > data->fst.entries.size() - 1) { + printf("went too far. aborting.\n"); + exit(-1); + } + if ( fn == 0 ) { + fnames.push_back(0); + finished = true; + break; + } + if ( gcmGetFSTEntryType(&curr) == 0 ) { + // file + fnames.push_back(fn); + while (gcmGetFSTEntryType(&curr) == 0) { + // search up for the parent directory.... + curr = data->fst.entries.at(fn - 1); + fn -= 1; + } + } + else if ( gcmGetFSTEntryType(&curr) == 1) { + // directory + fnames.push_back(fn); + fn = curr.file_offset; + curr = data->fst.entries.at(fn); + } + } + + if ( fnum != 0 ) { + for (int i = fnames.size() -1 ; i >= 0; i--) { + if ( i < fnames.size()-1 ) { + work.append("/"); + } + if ( fnames.at(i) != 0 ) work.append(data->fst.stringtable.at(fnames.at(i))->c_str()); + } + } else work = "/"; + strcpy(dest, work.c_str()); + return 0; +} diff --git a/source/gcminfo.h b/source/gcminfo.h new file mode 100755 index 0000000..04eadd1 --- /dev/null +++ b/source/gcminfo.h @@ -0,0 +1,217 @@ +// thanks to groepaz and everyone else who wrote YAGCD, most of my info came from it +// also thanks to WntrMute for loaning me some source to clear things up about the FST + +// (C) 2005 Andrew K andrew@aklabs.net +// License: Take all you want, but credit for all you take. + +#include +#include +#include +#include +#include + +#define LIBGCMVERSION "libGCM Version 0.1a (build Sep 4 2005)" + +// defines for internal program control (not necessarily GCM-related) + +#define GCNDVD_MAGICNUM 0xc2339f3d // if this isn't correct in the GCM, + // the program will abort. + +#define GCNDVD_SECTORS 712880 // not really used, but left for future updates that might use it +#define GCNDVD_SECTORSIZE 2048 // " " +#define GCNDVD_FNAME_LENGTH 1024 + + +#define GCM_MAX_PIECES 29 // change this if (for whatever reason) you add a new entry in GCMPieces + +// these all define indices in the GCMPieces global array where +// information about (where to look in the GCM for) a given piece +// of data about the GCM can be found. The rationale should +// be easy enough to follow. +#define GCM_DHEAD 0 +#define GCM_DHEADINF 1 +#define GCM_APPLOADER 2 + +#define GCM_DHEAD_GAMECODE 3 +#define GCM_DHEAD_GAMEMAKER 4 +#define GCM_DHEAD_DVDMAGIC 5 +#define GCM_DHEAD_GAMENAME 6 +#define GCM_DHEAD_DEBUGMON 7 +#define GCM_DHEAD_DEBUGMONADDR 8 +#define GCM_DHEAD_BOOTFILE 9 +#define GCM_DHEAD_FST 10 +#define GCM_DHEAD_FSTSIZE 11 +#define GCM_DHEAD_FSTMAXSIZE 12 +#define GCM_DHEAD_USERPOS 13 +#define GCM_DHEAD_USERLEN 14 + +#define GCM_DHEADINF_DEBUGMONSIZE 15 +#define GCM_DHEADINF_SIMMEMSIZE 16 +#define GCM_DHEADINF_ARGOFFSET 17 +#define GCM_DHEADINF_DEBUGFLAG 18 +#define GCM_DHEADINF_TRACKLOCATION 19 +#define GCM_DHEADINF_TRACKSIZE 20 +#define GCM_DHEADINF_COUNTRYCODE 21 + +#define GCM_APPLOADER_VERSION 22 +#define GCM_APPLOADER_ENTRY 23 +#define GCM_APPLOADER_SIZE 24 +#define GCM_APPLOADER_TRAILERSIZE 25 +#define GCM_APPLOADER_BINARY 26 +#define GCM_APPLOADER_CODE_LOC 0x2450 + +#define GCM_FST_ROOT 28 +#define GCM_FST_STRINGTABLEOFF 29 + +typedef struct { + int area; // 0 = basic structure, 1 = header, 2= header info, 3 = apploader, 4 = FST + char *name; + long offset; + long size; + int type; // 1 for string, 0 for numeric value (strings aren't byteswapped) +} GCMPiece; + + // pieces with area 1 add the base of the disk header to their offset + // pieces with area 2 add the base of the disk header info to their offset + // pieces with area 3 add the base of the apploader to their offset + // pieces with area 4 add the base of the FST to their offset (garnered from the disk header) +static GCMPiece GCMPieces [] ={ + // root disc pieces + {0, "Disk Header (boot.bin)", 0x00000000, 0x0440, 0}, + {0, "Disk Header Information (bi2.bin)", 0x00000440, 0x2000, 0}, + {0, "Apploader (appldr.bin)", 0x00002440, 0x2000, 0}, // 0x2000 size is an estimate I think + // disk header + {1, "Game code", 0x0000, 0x0004, 0}, + {1, "Game maker code", 0x0004, 0x0002, 0}, + {1, "DVD Magic Word", 0x001c, 0x0004, 0}, + {1, "Game name", 0x0020, 0x03e0, 1}, + {1, "Debug monitor offset", 0x0400, 0x0004, 0}, + {1, "Debug monitor load address", 0x0404, 0x0004, 0}, + {1, "Bootfile offset", 0x0420, 0x0004, 0}, + {1, "FST offset", 0x0424, 0x0004, 0}, + {1, "FST size", 0x0428, 0x0004, 0}, + {1, "FST Max Size", 0x042c, 0x0004, 0}, + {1, "User position", 0x0430, 0x0004, 0}, + {1, "User length", 0x0434, 0x0004, 0}, + + // the disk header info is loaded to 0x800000f4 when the disc is loaded by the IPL (tho we're reading it straight + // out of the .gcm image, so YMMV) + {2, "Debug-monitor size", 0x0000, 0x0004, 0}, + {2, "Simulated memory size", 0x0004, 0x0004, 0}, + {2, "Argument offset", 0x0008, 0x0004, 0}, + {2, "Debug flag", 0x000c, 0x0004, 0}, + {2, "Track location", 0x0010, 0x0004, 0}, + {2, "Track size", 0x0014, 0x0004, 0}, + {2, "Countrycode", 0x0018, 0x0004, 0}, + + // apploader header info + {3, "Version/Date", 0x0000, 0x000F, 1}, // don't include the padding in the date + {3, "Apploader entry point", 0x0010, 0x0004, 0}, + {3, "Apploader size", 0x0014, 0x0004, 0}, + {3, "Trailer size", 0x0018, 0x0004, 0}, + {3, "Apploader binary", 0x0020, 0, 1}, // no length given - taken from the "apploader size" + + // FST info + {4, "Root directory entry", 0x00, 0x0c, 0}, + {4, "FST String table offset", 0x0008, 0x0004, 0} + +}; + +// primary GCM disk header +typedef struct GCM_DiskHeader{ + int gamecode; + int gamemaker; + int magicword; + char gamename[0x03e0]; + int debugmon; + int debugmonaddr; + int bootfile; + int userpos; + int userlen; +}; + +// the GCM disk header additional info +typedef struct GCM_DiskHeaderInfo { + int debugmonsize; + int simmemsize; + int argoff; + int debugflag; + int tracklocation; + int tracksize; + int countrycode; +}; + +// information about the apploader on the GCM +typedef struct GCM_ApploaderInfo{ + char datever[10]; + int entry; + int size; + int trailersize; + char apploader[0x200]; // actual apploader data +}; + +// information about a particular file in the FST +typedef struct GCM_FSTEntry { + int fname_offset; // offset into the FST string table for the filename + // the offset is only actually 3 bytes, but + // we're only reading, not writing so it doesn't matter + // if we're grande sized .... + // the first byte of fname_offset is actually the flags of the file; 0: file 1: dir + int file_offset; // if this is a directory, this is actually the offset of the parent + int file_length; // actually the number of entries (root) or next_offset (dir) + int stringtable_off; // offset in the string table +}; + +// information about the names and locations of files in the GCM +typedef struct GCM_FST { + int size; + int offset; + int stringtable_offset; + int maxsize; + std::vector entries; // list of entries + std::vector stringtable; // string table +}; + +// GCM image data structure +typedef struct GCM { + GCM_DiskHeader head; + GCM_DiskHeaderInfo headInf; + GCM_ApploaderInfo apploader; + GCM_FST fst; + char *fname; +}; + +// these are just the functions that the user would need beyond +// the functionality provided by gcmInit's loader; more internal +// functions can be found inside gcminfo.c + +// returns 0 for a regular file, 1 for a directory +extern int gcmGetFSTEntryType(GCM_FSTEntry *entry); +// initialises the GCM data structures with FST and such; +extern int gcmInit(char *gcmname, GCM *data); +// prints a given portion of the GCM data +// whichdata should be an indice into the GCMPieces array +extern int gcmPrintData(int whichdata, GCM *data); +// prints all the data in the GCM in a (fairly) columnar format +extern int gcmPrint(GCM *data); +// prints a comprehensive listing of all files in the GCM +extern int gcmPrintFST(GCM *data); +// retrieves a given file and puts it in the FST entries, +// given the fnum +extern int gcmGetFile(GCM *data, GCM_FSTEntry *entry, int fnum, FILE *file); +// prints information for a given fname +extern int gcmPrintFile(GCM *data, int fnum); +// frees all data in the FST stringtable +extern int gcmFreeStringTable(GCM *data); +// extracts a file, given the fnum, into the current dir, unless outfname is specified +extern unsigned int gcmExtractFile(GCM *data, int fnum, char *outfname); +// puts the full filename (with path) into dest, given fnum +extern int gcmGetFullFileName(GCM *data, int fnum, char *dest); +// returns the fnum of a given file by its offset +extern int gcmGetFileByOffset(GCM *data, int offset); +// returns the fnum of a given file by its full pathname +extern unsigned int gcmGetFileByName(GCM *data, char *name); +// returns the actual entry of a file given its fnum +extern GCM_FSTEntry gcmGetFileByFnum(GCM *data, int fnum); +// explodes the FST onto the host filesystem in the current directory +extern int gcmExplode(GCM *data); diff --git a/source/sample-output.txt b/source/sample-output.txt new file mode 100755 index 0000000..a2cfd4d --- /dev/null +++ b/source/sample-output.txt @@ -0,0 +1,1709 @@ +DEBUG: turning on byte swapping... +FST string table offset calculated to 0x209e6c... +Game code : 47475345 +Game maker code : 41340000 +DVD Magic Word : c2339f3d +Game name : METAL GEAR SOLID THE TWIN SNAKES +Debug monitor offset : 1d224 +Debug monitor load address : 80280060 +Bootfile offset : 1f700 +FST offset : 205000 +FST size : 729c +FST Max Size : 729c +User position : 803f8d60 +User length : 210000 +Debug-monitor size : 0 +Simulated memory size : 0 +Argument offset : 0 +Debug flag : 0 +Track location : 0 +Track size : 0 +Countrycode : 1 +Version/Date : 2003/04/17 +Apploader entry point : 81200258 +Apploader size : 1954 +Trailer size : 1b8b0 +Apploader binary : +(untested function/invalid data) : refusing to print NULL pointer... +FST String table offset : 20746f4e +Total files in the FST : 1673 +Total entries in the FST string table : 1673 + + + + (FST CONTENTS) +(name) (fnum) (type) (offset) (length) +(root) 0 1 0 1673 +.sbas 1 1 0 1673 +Sync 2 1 0 4 +SyncLock 3 0 210000 329 +audio 4 0 21014c 0 +banks 5 1 0 89 +.sbas 6 1 4 33 +Sync 7 1 5 9 +SyncLock 8 0 21014c 2054 +bank017.spd 9 0 210954 0 +bank017.spt 10 0 210954 1531467 +bank018.spd 11 0 3867a0 19566 +bank018.spt 12 0 38b410 1404419 +bank021.spd 13 0 4e2214 18020 +bank021.spt 14 0 4e6878 2109832 +bank022.spd 15 0 6e9a00 22244 +bank022.spt 16 0 6ef0e4 2120391 +bank024.spd 17 0 8f4bac 21982 +bank024.spt 18 0 8fa18c 2273772 +bank027.spd 19 0 b25378 24108 +bank027.spt 20 0 b2b1a4 2398383 +bank032.spd 21 0 d74a54 24198 +bank032.spt 22 0 d7a8dc 1749186 +bank033.spd 23 0 f259a0 13510 +bank033.spt 24 0 f28e68 2413943 +bank034.spd 25 0 11763e0 18922 +bank034.spt 26 0 117adcc 1511074 +bank035.spd 27 0 12ebc70 18602 +bank035.spt 28 0 12f051c 1115266 +bank037.spd 29 0 14009a0 13212 +bank037.spt 30 0 1403d3c 1955346 +bank042.spd 31 0 15e1350 20640 +bank042.spt 32 0 15e63f0 2013550 +stream 33 0 17d1d60 22834 +.sbas 34 1 4 89 +Sync 35 1 21 37 +SyncLock 36 0 17d7694 3933 +0005L 37 0 17d85f4 0 +0005R 38 0 17d85f4 811392 +0006L 39 0 189e774 811392 +0006R 40 0 19648f4 811392 +0007L 41 0 1a2aa74 811392 +0007R 42 0 1af0bf4 1036896 +0008L 43 0 1bede54 1036896 +0008R 44 0 1ceb0b4 811392 +0009L 45 0 1db1234 811392 +0009R 46 0 1e773b4 786528 +0014L 47 0 1f37414 786528 +0014R 48 0 1ff7474 2991552 +0015L 49 0 22d1a34 2991552 +0015R 50 0 25abff4 2051243 +0016L 51 0 27a0ca0 2051243 +0016R 52 0 299594c 1907543 +0045L 53 0 2b674a4 1907543 +0045R 54 0 2d38ffc 1156416 +0046L 55 0 2e5353c 1156416 +0046R 56 0 2f6da7c 1008883 +0047L 57 0 3063f70 1008883 +0047R 58 0 315a464 1251687 +0048L 59 0 328bdcc 1251687 +0048R 60 0 33bd734 1119205 +0049L 61 0 34ceb1c 1119205 +0049R 62 0 35dff04 1313742 +0050L 63 0 3720ad4 1313742 +0050R 64 0 38616a4 816956 +0051L 65 0 3928de0 816956 +0051R 66 0 39f051c 1140687 +0052L 67 0 3b06cec 1140687 +0052R 68 0 3c1d4bc 1013143 +0053L 69 0 3d14a54 1013143 +0053R 70 0 3e0bfec 812108 +0055L 71 0 3ed2438 812108 +0055R 72 0 3f98884 1142278 +0069L 73 0 40af68c 1142278 +0069R 74 0 41c6494 1647860 +0092L 75 0 4358988 1647860 +0092R 76 0 44eae7c 1134096 +0093L 77 0 45ffc8c 1134096 +0093R 78 0 4714a9c 1319660 +0094L 79 0 4856d88 1319660 +0094R 80 0 4999074 1209696 +0095L 81 0 4ac05d4 1209696 +0095R 82 0 4be7b34 1134096 +0096L 83 0 4cfc944 1134096 +0096R 84 0 4e11754 1707767 +0097L 85 0 4fb264c 1707767 +0097R 86 0 5153544 901216 +0098L 87 0 522f5a4 901216 +0098R 88 0 530b604 3042839 +demo.dat 89 0 55f241c 3042839 +opening.bnr 90 0 58e0000 585379840 +stage.dat 91 0 28723000 6496 +shared 92 0 28728000 203001856 +.sbas 93 1 0 1673 +Sync 94 1 5c 96 +SyncLock 95 0 348c1000 1137 +audio 96 0 348c1474 0 +banks 97 1 5c 1661 +.sbas 98 1 60 129 +Sync 99 1 61 101 +SyncLock 100 0 348c1474 5484 +bank001.spd 101 0 348c29e0 0 +bank001.spt 102 0 348c29e0 2481256 +bank003.spd 103 0 34b20648 21606 +bank003.spt 104 0 34b25ab0 2167834 +bank006.spd 105 0 34d36ecc 26310 +bank006.spt 106 0 34d3d594 2032853 +bank008.spd 107 0 34f2da6c 21772 +bank008.spt 108 0 34f32f78 2098461 +bank013.spd 109 0 35133498 18456 +bank013.spt 110 0 35137cb0 2033464 +bank015.spd 111 0 353283e8 21044 +bank015.spt 112 0 3532d61c 1723454 +bank019.spd 113 0 354d225c 20526 +bank019.spt 114 0 354d728c 1772357 +bank020.spd 115 0 35687dd4 13284 +bank020.spt 116 0 3568b1b8 1816099 +bank023.spd 117 0 358467dc 24434 +bank023.spt 118 0 3584c750 1654605 +bank025.spd 119 0 359e06a0 17574 +bank025.spt 120 0 359e4b48 2475099 +bank026.spd 121 0 35c40fa4 17080 +bank026.spt 122 0 35c4525c 768478 +bank031.spd 123 0 35d00c3c 4642 +bank031.spt 124 0 35d01e60 1700085 +bank048.spd 125 0 35ea0f58 17916 +bank048.spt 126 0 35ea5554 1470612 +bank049.spd 127 0 3600c5e8 348 +bank049.spt 128 0 3600c744 1557407 +stream 129 0 36188ae4 20094 +.sbas 130 1 60 1661 +Sync 131 1 81 133 +SyncLock 132 0 3618d964 109211 +0001L 133 0 361a8400 0 +0001R 134 0 361a8400 1111103 +0003L 135 0 362b7840 1111103 +0003R 136 0 363c6c80 2077232 +0004L 137 0 365c1eb0 2077232 +0004R 138 0 367bd0e0 9072096 +0010L 139 0 37063ec0 9072096 +0010R 140 0 3790aca0 1895483 +0012L 141 0 37ad98dc 1895483 +0012R 142 0 37ca8518 1064426 +0013L 143 0 37dac304 1064426 +0013R 144 0 37eb00f0 908239 +0018L 145 0 37f8dcc0 908239 +0018R 146 0 3806b890 1601047 +0019L 147 0 381f26a8 1601047 +0019R 148 0 383794c0 1357627 +0021L 149 0 384c4bfc 1357627 +0021R 150 0 38610338 581006 +0022L 151 0 3869e0c8 581006 +0022R 152 0 3872be58 2977574 +0039L 153 0 38a02d80 2977574 +0039R 154 0 38cd9ca8 663524 +0041L 155 0 38d7bc8c 663524 +0041R 156 0 38e1dc70 2496360 +0044L 157 0 3907f3d8 2496360 +0044R 158 0 392e0b40 644350 +0054L 159 0 3937e040 644350 +0054R 160 0 3941b540 2301474 +0056L 161 0 3964d364 2301474 +0056R 162 0 3987f188 3144654 +0057L 163 0 39b7ed58 3144654 +0057R 164 0 39e7e928 603090 +0058L 165 0 39f11cfc 603090 +0058R 166 0 39fa50d0 655160 +0059L 167 0 3a045008 655160 +0059R 168 0 3a0e4f40 2124019 +0060L 169 0 3a2eb834 2124019 +0060R 170 0 3a4f2128 2031712 +0061L 171 0 3a6e2188 2031712 +0061R 172 0 3a8d21e8 2980611 +0065L 173 0 3aba9cec 2980611 +0065R 174 0 3ae817f0 3709712 +0071L 175 0 3b20b300 3709712 +0071R 176 0 3b594e10 1743822 +0072L 177 0 3b73e9e0 1743822 +0072R 178 0 3b8e85b0 5456703 +0073L 179 0 3be1c8f0 5456703 +0073R 180 0 3c350c30 5454150 +0074L 181 0 3c884578 5454150 +0074R 182 0 3cdb7ec0 1714831 +0075L 183 0 3cf5a950 1714831 +0075R 184 0 3d0fd3e0 1792950 +0076L 185 0 3d2b2f98 1792950 +0076R 186 0 3d468b50 1542354 +0077L 187 0 3d5e1424 1542354 +0077R 188 0 3d759cf8 1815539 +0078L 189 0 3d9150ec 1815539 +0078R 190 0 3dad04e0 3943551 +0079L 191 0 3de93160 3943551 +0079R 192 0 3e255de0 4840754 +0081L 193 0 3e6f3b14 4840754 +0081R 194 0 3eb91848 4721399 +0088L 195 0 3f012340 4721399 +0088R 196 0 3f492e38 1700167 +0089L 197 0 3f631f80 1700167 +0089R 198 0 3f7d10c8 1543711 +0090L 199 0 3f949ee8 1543711 +0090R 200 0 3fac2d08 1540725 +0091L 201 0 3fc3af80 1540725 +0091R 202 0 3fdb31f8 1540182 +0099L 203 0 3ff2b250 1540182 +0099R 204 0 400a32a8 726808 +0100L 205 0 401549c0 726808 +0100R 206 0 402060d8 1104846 +0176L 207 0 40313ca8 1104846 +0176R 208 0 40421878 196688 +0177L 209 0 404518c8 196688 +0177R 210 0 40481918 243863 +0178L 211 0 404bd1b0 243863 +0178R 212 0 404f8a48 109582 +0179 213 0 40513658 109582 +0180L 214 0 4052e268 100917 +0180R 215 0 40546ca0 67110 +0181G 216 0 405572c8 67110 +0184L 217 0 405678f0 4689496 +0184R 218 0 409e0748 804523 +0200L 219 0 40aa4df4 804523 +0200R 220 0 40b694a0 183522 +0201L 221 0 40b96184 183522 +0201R 222 0 40bc2e68 183522 +0202L 223 0 40befb4c 183522 +0202R 224 0 40c1c830 183522 +0203L 225 0 40c49514 183522 +0203R 226 0 40c761f8 183522 +0204L 227 0 40ca2edc 183522 +0204R 228 0 40ccfbc0 183522 +0205L 229 0 40cfc8a4 183522 +0205R 230 0 40d29588 183522 +0206L 231 0 40d5626c 183522 +0206R 232 0 40d82f50 183522 +0207L 233 0 40dafc34 183522 +0207R 234 0 40ddc918 183522 +0208L 235 0 40e095fc 183522 +0208R 236 0 40e362e0 183522 +0209L 237 0 40e62fc4 183522 +0209R 238 0 40e8fca8 183522 +0210L 239 0 40ebc98c 183522 +0210R 240 0 40ee9670 183522 +0211L 241 0 40f16354 183522 +0211R 242 0 40f43038 183522 +0212L 243 0 40f6fd1c 183522 +0212R 244 0 40f9ca00 183522 +0213L 245 0 40fc96e4 183522 +0213R 246 0 40ff63c8 183522 +0214L 247 0 410230ac 183522 +0214R 248 0 4104fd90 183522 +0215L 249 0 4107ca74 183522 +0215R 250 0 410a9758 183522 +0216L 251 0 410d643c 183522 +0216R 252 0 41103120 183522 +0217L 253 0 4112fe04 183522 +0217R 254 0 4115cae8 183522 +0218L 255 0 411897cc 183522 +0218R 256 0 411b64b0 183522 +0300 257 0 411e3194 183522 +0301 258 0 4120fe78 65975 +0302 259 0 41220030 126765 +0303 260 0 4123ef60 29839 +0304 261 0 412463f0 26164 +0305 262 0 4124ca24 24740 +0306 263 0 41252ac8 30594 +0307 264 0 4125a24c 58267 +0308 265 0 412685e8 12099 +0309 266 0 4126b52c 20171 +0310 267 0 412703f8 25303 +0311 268 0 412766d0 112501 +0312 269 0 41291e48 48847 +0313 270 0 4129dd18 32677 +0314 271 0 412a5cc0 9035 +0315 272 0 412a800c 6997 +0316 273 0 412a9b64 8270 +0317 274 0 412abbb4 7208 +0318 275 0 412ad7dc 7102 +0319 276 0 412af39c 6120 +0320 277 0 412b0b84 7496 +0321 278 0 412b28cc 29839 +0322 279 0 412b9d5c 21614 +0323 280 0 412bf1cc 24740 +0324 281 0 412c5270 30594 +0325 282 0 412cc9f4 58267 +0326 283 0 412dad90 12099 +0327 284 0 412ddcd4 20171 +0328 285 0 412e2ba0 25303 +0329 286 0 412e8e78 112501 +0330 287 0 413045f0 48847 +0331 288 0 413104c0 32677 +0332 289 0 41318468 41599 +0333 290 0 413226e8 28662 +0334 291 0 413296e0 38514 +0335 292 0 41332d54 32363 +0336 293 0 4133abc0 50631 +0337 294 0 41347188 40078 +0338 295 0 41350e18 23958 +0339 296 0 41356bb0 43062 +0340 297 0 413613e8 46852 +0341 298 0 4136caec 50962 +0342 299 0 41379200 25123 +0343 300 0 4137f424 34300 +0344 301 0 41387a20 46322 +0345 302 0 41392f14 26469 +0346 303 0 4139967c 65317 +0347 304 0 413a95a4 23974 +0348 305 0 413af34c 88500 +0349 306 0 413c4d00 46328 +0350 307 0 413d01f8 10230 +0351 308 0 413d29f0 22531 +0352 309 0 413d81f4 18926 +0353 310 0 413dcbe4 22548 +0354 311 0 413e23f8 29200 +0355 312 0 413e9608 24056 +0356 313 0 413ef400 20917 +0357 314 0 413f45b8 40851 +0358 315 0 413fe54c 37106 +0359 316 0 41407640 20987 +0360 317 0 4140c83c 23414 +0361 318 0 414123b4 33325 +0362 319 0 4141a5e4 18546 +0363 320 0 4141ee58 26203 +0364L 321 0 414254b4 19068 +0364R 322 0 41429f30 183522 +0398L 323 0 41456c14 183522 +0398R 324 0 414838f8 972860 +0399L 325 0 41571134 972860 +0399R 326 0 4165e970 581266 +0401 327 0 416ec804 581266 +0402 328 0 4177a698 1001766 +0403 329 0 4186efc0 10812 +0404 330 0 418719fc 32640 +0405 331 0 4187997c 12211 +0406 332 0 4187c930 17888 +0407 333 0 41880f10 20906 +0408 334 0 418860bc 9094 +0409 335 0 41888444 17100 +0410 336 0 4188c710 18866 +0411 337 0 418910c4 25472 +0412 338 0 41897444 11799 +0413 339 0 4189a25c 23776 +0414 340 0 4189ff3c 21930 +0415 341 0 418a54e8 34399 +0416 342 0 418adb48 39324 +0417 343 0 418b74e4 42410 +0418 344 0 418c1a90 16028 +0419 345 0 418c592c 21677 +0420L 346 0 418caddc 23637 +0420R 347 0 418d0a34 11386 +0421L 348 0 418d36b0 11386 +0421R 349 0 418d632c 8131 +0422L 350 0 418d82f0 8131 +0422R 351 0 418da2b4 9311 +0423L 352 0 418dc714 9311 +0423R 353 0 418deb74 10502 +0424L 354 0 418e147c 10502 +0424R 355 0 418e3d84 14510 +0425L 356 0 418e7634 14510 +0425R 357 0 418eaee4 13276 +0426L 358 0 418ee2c0 13276 +0426R 359 0 418f169c 17687 +0427L 360 0 418f5bb4 17687 +0427R 361 0 418fa0cc 9136 +0428L 362 0 418fc47c 9136 +0428R 363 0 418fe82c 9578 +0429L 364 0 41900d98 9578 +0429R 365 0 41903304 17037 +0430L 366 0 41907594 17037 +0430R 367 0 4190b824 11518 +0431L 368 0 4190e524 11518 +0431R 369 0 41911224 10483 +0432L 370 0 41913b18 10483 +0432R 371 0 4191640c 14786 +0433L 372 0 41919dd0 14786 +0433R 373 0 4191d794 22163 +0434L 374 0 41922e28 22163 +0434R 375 0 419284bc 20381 +0435L 376 0 4192d45c 20381 +0435R 377 0 419323fc 19231 +0436L 378 0 41936f1c 19231 +0436R 379 0 4193ba3c 12934 +0437L 380 0 4193ecc4 12934 +0437R 381 0 41941f4c 8432 +0438L 382 0 4194403c 8432 +0438R 383 0 4194612c 21332 +0439L 384 0 4194b480 21332 +0439R 385 0 419507d4 12295 +0440L 386 0 419537dc 12295 +0440R 387 0 419567e4 16010 +0441L 388 0 4195a670 16010 +0441R 389 0 4195e4fc 17893 +0442L 390 0 41962ae4 17893 +0442R 391 0 419670cc 10917 +0443L 392 0 41969b74 10917 +0443R 393 0 4196c61c 9560 +0444L 394 0 4196eb74 9560 +0444R 395 0 419710cc 15203 +0445L 396 0 41974c30 15203 +0445R 397 0 41978794 24724 +0446L 398 0 4197e828 24724 +0446R 399 0 419848bc 20384 +0447L 400 0 4198985c 20384 +0447R 401 0 4198e7fc 10214 +0448L 402 0 41990fe4 10214 +0448R 403 0 419937cc 16367 +0449L 404 0 419977bc 16367 +0449R 405 0 4199b7ac 25891 +0450L 406 0 419a1cd0 25891 +0450R 407 0 419a81f4 27610 +0451L 408 0 419aedd0 27610 +0451R 409 0 419b59ac 10204 +0452L 410 0 419b8188 10204 +0452R 411 0 419ba964 23686 +0453L 412 0 419c05ec 23686 +0453R 413 0 419c6274 15286 +0454L 414 0 419c9e2c 15286 +0454R 415 0 419cd9e4 30948 +0455L 416 0 419d52c8 30948 +0455R 417 0 419dcbac 22895 +0456L 418 0 419e251c 22895 +0456R 419 0 419e7e8c 23864 +0457L 420 0 419edbc4 23864 +0457R 421 0 419f38fc 18500 +0458L 422 0 419f8140 18500 +0458R 423 0 419fc984 25748 +0459L 424 0 41a02e18 25748 +0459R 425 0 41a092ac 15614 +0460L 426 0 41a0cfac 15614 +0460R 427 0 41a10cac 28422 +0461L 428 0 41a17bb4 28422 +0461R 429 0 41a1eabc 31965 +0462L 430 0 41a2679c 31965 +0462R 431 0 41a2e47c 16885 +0463L 432 0 41a32674 16885 +0463R 433 0 41a3686c 47013 +0464L 434 0 41a42014 47013 +0464R 435 0 41a4d7bc 16440 +0465L 436 0 41a517f4 16440 +0465R 437 0 41a5582c 17767 +0466L 438 0 41a59d94 17767 +0466R 439 0 41a5e2fc 26783 +0467L 440 0 41a64b9c 26783 +0467R 441 0 41a6b43c 27442 +0468L 442 0 41a71f70 27442 +0468R 443 0 41a78aa4 20384 +0469L 444 0 41a7da44 20384 +0469R 445 0 41a829e4 16026 +0470L 446 0 41a86880 16026 +0470R 447 0 41a8a71c 14351 +0471L 448 0 41a8df2c 14351 +0471R 449 0 41a9173c 19980 +0472L 450 0 41a96548 19980 +0472R 451 0 41a9b354 31226 +0473L 452 0 41aa2d50 31226 +0473R 453 0 41aaa74c 26982 +0474L 454 0 41ab10b4 26982 +0474R 455 0 41ab7a1c 32544 +0475L 456 0 41abf93c 32544 +0475R 457 0 41ac785c 33387 +0476L 458 0 41acfac8 33387 +0476R 459 0 41ad7d34 18807 +0477L 460 0 41adc6ac 18807 +0477R 461 0 41ae1024 26851 +0478L 462 0 41ae7908 26851 +0478R 463 0 41aee1ec 15645 +0479L 464 0 41af1f0c 15645 +0479R 465 0 41af5c2c 19476 +0481 466 0 41afa840 19476 +0482 467 0 41aff454 56298 +0483 468 0 41b0d040 172587 +0485L 469 0 41b3726c 61067 +0485R 470 0 41b460f8 237560 +0486L 471 0 41b800f0 237560 +0486R 472 0 41bba0e8 23423 +0487L 473 0 41bbfc68 23423 +0487R 474 0 41bc57e8 31476 +0488L 475 0 41bcd2dc 31476 +0488R 476 0 41bd4dd0 54989 +0489L 477 0 41be24a0 54989 +0489R 478 0 41befb70 50591 +0490L 479 0 41bfc110 50591 +0490R 480 0 41c086b0 23610 +0491L 481 0 41c0e2ec 23610 +0491R 482 0 41c13f28 29578 +0492L 483 0 41c1b2b4 29578 +0492R 484 0 41c22640 985152 +0493L 485 0 41d12e80 985152 +0493R 486 0 41e036c0 265146 +0494L 487 0 41e4427c 265146 +0494R 488 0 41e84e38 985152 +0495L 489 0 41f75678 985152 +0495R 490 0 42065eb8 88854 +0496L 491 0 4207b9d0 88854 +0496R 492 0 420914e8 100800 +0497L 493 0 420a9ea8 100800 +0497R 494 0 420c2868 69309 +0498L 495 0 420d3728 69309 +0498R 496 0 420e45e8 81798 +0499L 497 0 420f8570 81798 +0499R 498 0 4210c4f8 120578 +0500 499 0 42129bfc 120578 +0501 500 0 42147300 58672 +0502 501 0 42155830 58151 +0503 502 0 42163b58 58672 +0504 503 0 42172088 58151 +0505 504 0 421803b0 58151 +0506 505 0 4218e6d8 15443 +0507 506 0 4219232c 15682 +0508 507 0 42196070 13181 +0509 508 0 421993f0 92506 +0510 509 0 421afd4c 72343 +0511 510 0 421c17e4 96814 +0512 511 0 421d9214 92506 +0513 512 0 421efb70 72343 +0514 513 0 42201608 96814 +3000 514 0 42219038 6255 +3001 515 0 4221a8a8 47346 +3002 516 0 4222619c 39570 +3003 517 0 4222fc30 49178 +3004 518 0 4223bc4c 35975 +3005 519 0 422448d4 43831 +3006 520 0 4224f40c 71614 +3007 521 0 42260bcc 85710 +3008 522 0 42275a9c 62590 +3009 523 0 42284f1c 92310 +3010 524 0 4229b7b4 46668 +3011 525 0 422a6e00 45935 +3012 526 0 422b2170 48613 +3013 527 0 422bdf58 102390 +3014 528 0 422d6f50 58677 +3015 529 0 422e5488 59019 +3016 530 0 422f3b14 82221 +3017 531 0 42307c44 67316 +3018 532 0 42318338 73426 +3019 533 0 4232a20c 75043 +3020 534 0 4233c730 69002 +3021 535 0 4234d4bc 70172 +3022 536 0 4235e6d8 51711 +3023 537 0 4236b0d8 59727 +3024 538 0 42379a28 92135 +3025 539 0 42390210 94042 +3026 540 0 423a716c 96240 +3027 541 0 423be95c 107578 +3028 542 0 423d8d98 102533 +3029 543 0 423f1e20 96541 +3030 544 0 42409740 59895 +3031 545 0 42418138 62635 +3032 546 0 424275e4 74283 +3033 547 0 42439810 69892 +3034 548 0 4244a914 62880 +3035 549 0 42459eb4 62752 +3036 550 0 424693d4 72789 +3037 551 0 4247b02c 64782 +3038 552 0 4248ad3c 84140 +3039 553 0 4249f5e8 66904 +3040 554 0 424afb40 68350 +3041 555 0 424c0640 69332 +3042 556 0 424d1514 72782 +3043 557 0 424e3164 64802 +3044 558 0 424f2e88 53655 +3045 559 0 42500020 76360 +3046 560 0 42512a68 78622 +3047 561 0 42525d88 66566 +3048 562 0 42536190 57372 +3049 563 0 425441ac 79499 +3050 564 0 42557838 72911 +3051 565 0 42569508 76807 +3052 566 0 4257c110 87396 +3053 567 0 42591674 98775 +3054 568 0 425a984c 78256 +3055 569 0 425bc9fc 70354 +3056 570 0 425cdcd0 77398 +3057 571 0 425e0b28 68391 +3058 572 0 425f1650 49080 +3059 573 0 425fd608 54448 +3060 574 0 4260aab8 64755 +3061 575 0 4261a7ac 51221 +3062 576 0 42626fc4 50504 +3063 577 0 4263350c 75942 +3064 578 0 42645db4 90654 +3065 579 0 4265bfd4 119691 +3066 580 0 42679360 110942 +3067 581 0 426944c0 106523 +3068 582 0 426ae4dc 108998 +3069 583 0 426c8ea4 114087 +3070 584 0 426e4c4c 100885 +3071 585 0 426fd664 81798 +3072 586 0 427115ec 90015 +3073 587 0 4272758c 132968 +3074 588 0 42747cf4 121743 +3075 589 0 42765884 123368 +3076 590 0 42783a6c 111124 +3077 591 0 4279ec80 115304 +3078 592 0 427baee8 139670 +3079 593 0 427dd080 98205 +3080 594 0 427f5020 84154 +3081 595 0 428098dc 111856 +3082 596 0 42824dcc 94909 +3083 597 0 4283c08c 101383 +3084 598 0 42854c94 71415 +3085 599 0 4286638c 111604 +3086 600 0 42881780 112548 +3087 601 0 4289cf24 113563 +3088 602 0 428b8ac0 94251 +3089 603 0 428cfaec 83218 +3090 604 0 428e4000 96000 +3091 605 0 428fb700 100980 +3092 606 0 42914174 74998 +3093 607 0 4292666c 105563 +3094 608 0 429402c8 71597 +3095 609 0 42951a78 95468 +3096 610 0 42968f64 85367 +3097 611 0 4297dcdc 92598 +3098 612 0 42994694 86228 +3099 613 0 429a9768 102244 +3100 614 0 429c26cc 89059 +3101 615 0 429d82b0 110742 +3102 616 0 429f3348 97402 +3103 617 0 42a0afc4 95935 +3104 618 0 42a22684 103316 +3105 619 0 42a3ba18 105822 +3106 620 0 42a55778 98530 +3107 621 0 42a6d85c 70406 +3108 622 0 42a7eb64 60644 +3109 623 0 42a8d848 40095 +3110 624 0 42a974e8 40014 +3111 625 0 42aa1138 26596 +3112 626 0 42aa791c 41235 +3113 627 0 42ab1a30 41091 +3114 628 0 42abbab4 23310 +3115 629 0 42ac15c4 26011 +3116 630 0 42ac7b60 75950 +3117 631 0 42ada410 72266 +3118 632 0 42aebe5c 98728 +3119 633 0 42b04004 92943 +3120 634 0 42b1ab14 96142 +3121 635 0 42b322a4 77411 +3122 636 0 42b45108 118490 +3123 637 0 42b61fe4 119263 +3124 638 0 42b7f1c4 119507 +3125 639 0 42b9c498 77676 +3126 640 0 42baf404 90588 +3127 641 0 42bc55e0 83250 +3128 642 0 42bd9b14 91583 +3129 643 0 42bf00d4 100991 +3130 644 0 42c08b54 89838 +3131 645 0 42c1ea44 82482 +3132 646 0 42c32c78 83630 +3133 647 0 42c47328 81562 +3134 648 0 42c5b1c4 84604 +3135 649 0 42c6fc40 87533 +3136 650 0 42c85230 102620 +3137 651 0 42c9e30c 96704 +3138 652 0 42cb5ccc 92925 +3139 653 0 42ccc7cc 67520 +3140 654 0 42cdcf8c 29010 +3141 655 0 42ce40e0 22050 +3142 656 0 42ce9704 23066 +3143 657 0 42cef120 48010 +3144 658 0 42cfacac 41578 +3145 659 0 42d04f18 46311 +3146 660 0 42d10400 52527 +3147 661 0 42d1d130 58220 +3148 662 0 42d2b49c 52574 +3149 663 0 42d381fc 56923 +3150 664 0 42d46058 64436 +3151 665 0 42d55c0c 74594 +3152 666 0 42d67f70 73187 +3153 667 0 42d79d54 57523 +3154 668 0 42d87e08 53629 +3155 669 0 42d94f88 46470 +3156 670 0 42da0510 34429 +3157 671 0 42da8b90 88221 +3158 672 0 42dbe430 45333 +3159 673 0 42dc9548 48600 +3160 674 0 42dd5320 43080 +3161 675 0 42ddfb68 51892 +3162 676 0 42dec61c 33995 +3163 677 0 42df4ae8 35046 +3164 678 0 42dfd3d0 41021 +3165 679 0 42e07410 36839 +3166 680 0 42e103f8 41094 +3167 681 0 42e1a480 25608 +3168 682 0 42e20888 33667 +3169 683 0 42e28c0c 30720 +3170 684 0 42e3040c 35995 +3171 685 0 42e390a8 15117 +3172 686 0 42e3cbb8 17134 +3173 687 0 42e40ea8 12547 +3174 688 0 42e43fac 12686 +3175 689 0 42e4713c 15112 +3176 690 0 42e4ac44 17839 +3177 691 0 42e4f1f4 33003 +3178 692 0 42e572e0 39551 +3179 693 0 42e60d60 40045 +3180 694 0 42e6a9d0 45258 +3181 695 0 42e75a9c 40114 +3182 696 0 42e7f750 30764 +3183 697 0 42e86f7c 39723 +3184 698 0 42e90aa8 37359 +3185 699 0 42e99c98 41071 +3186 700 0 42ea3d08 31933 +3187 701 0 42eab9c8 67868 +3188 702 0 42ebc2e4 32178 +3189 703 0 42ec4098 26963 +3190 704 0 42eca9ec 36096 +3191 705 0 42ed36ec 43629 +3192 706 0 42ede15c 13658 +3193 707 0 42ee16b8 15290 +3194 708 0 42ee5274 9093 +3195 709 0 42ee75fc 9358 +3196 710 0 42ee9a8c 44852 +3197 711 0 42ef49c0 33726 +3198 712 0 42efcd80 24092 +3199 713 0 42f02b9c 33565 +3200 714 0 42f0aebc 6188 +3201 715 0 42f0c6e8 29511 +3202 716 0 42f13a30 42866 +3203 717 0 42f1e1a4 5554 +3204 718 0 42f1f758 32528 +3205 719 0 42f27668 32858 +3206 720 0 42f2f6c4 7109 +3207 721 0 42f3128c 20758 +3208 722 0 42f363a4 8058 +3209 723 0 42f38320 20707 +3210 724 0 42f3d404 33955 +3211 725 0 42f458a8 7733 +3212 726 0 42f476e0 18044 +3213 727 0 42f4bd5c 6282 +3214 728 0 42f4d5e8 11710 +3215 729 0 42f503a8 9632 +3216 730 0 42f52948 34410 +3217 731 0 42f5afb4 35530 +3218 732 0 42f63a80 15846 +3219 733 0 42f67868 65007 +3220 734 0 42f77658 24829 +3221 735 0 42f7d758 7424 +3222 736 0 42f7f458 21013 +3223 737 0 42f84670 7926 +3224 738 0 42f86568 9866 +3225 739 0 42f88bf4 21748 +3226 740 0 42f8e0e8 9384 +3227 741 0 42f90590 9468 +3228 742 0 42f92a8c 11701 +3229 743 0 42f95844 8749 +3230 744 0 42f97a74 11090 +3231 745 0 42f9a5c8 5472 +3232 746 0 42f9bb28 6178 +3233 747 0 42f9d34c 6624 +3234 748 0 42f9ed2c 8328 +3235 749 0 42fa0db4 12620 +3236 750 0 42fa3f00 13428 +3237 751 0 42fa7374 10258 +3238 752 0 42fa9b88 13259 +3239 753 0 42facf54 11614 +3240 754 0 42fafcb4 9418 +3241 755 0 42fb2180 14768 +3242 756 0 42fb5b30 16463 +3243 757 0 42fb9b80 22076 +3244 758 0 42fbf1bc 14925 +3245 759 0 42fc2c0c 20047 +3246 760 0 42fc7a5c 13459 +3247 761 0 42fcaef0 13158 +3248 762 0 42fce258 11423 +3249 763 0 42fd0ef8 21738 +3250 764 0 42fd63e4 11294 +3251 765 0 42fd9004 8934 +3252 766 0 42fdb2ec 12795 +3253 767 0 42fde4e8 7395 +3254 768 0 42fe01cc 21603 +3255 769 0 42fe5630 19549 +3256 770 0 42fea290 21610 +3257 771 0 42fef6fc 16669 +3258 772 0 42ff381c 13047 +3259 773 0 42ff6b14 12845 +3260 774 0 42ff9d44 23829 +3261 775 0 42fffa5c 20918 +3262 776 0 43004c14 21432 +3263 777 0 43009fcc 21967 +3264 778 0 4300f59c 20212 +3265 779 0 43014490 22378 +3266 780 0 43019bfc 27784 +3267 781 0 43020884 12669 +3268 782 0 43023a04 21645 +3269 783 0 43028e94 14387 +3270 784 0 4302c6c8 15568 +3271 785 0 43030398 12144 +3272 786 0 43033308 12699 +3273 787 0 430364a4 21978 +3274 788 0 4303ba80 22796 +3275 789 0 4304138c 15912 +3276 790 0 430451b4 21664 +3277 791 0 4304a654 16158 +3278 792 0 4304e574 20979 +3279 793 0 43053768 11879 +3280 794 0 430565d0 25287 +3281 795 0 4305c898 40155 +3282 796 0 43066574 29647 +3283 797 0 4306d944 29320 +3284 798 0 43074bcc 22733 +3285 799 0 4307a49c 13883 +3286 800 0 4307dad8 12560 +3287 801 0 43080be8 14559 +3288 802 0 430844c8 12821 +3289 803 0 430876e0 10900 +3290 804 0 4308a174 14669 +3291 805 0 4308dac4 12062 +3292 806 0 430909e4 59622 +3293 807 0 4309f2cc 39031 +3294 808 0 430a8b44 62318 +3295 809 0 430b7eb4 52256 +3296 810 0 430c4ad4 47055 +3297 811 0 430d02a4 45757 +3298 812 0 430db564 46331 +3299 813 0 430e6a60 70203 +3300 814 0 430f7c9c 35140 +3301 815 0 431005e0 41468 +3302 816 0 4310a7dc 52544 +3303 817 0 4311751c 62187 +3304 818 0 43126808 7676 +3305 819 0 43128604 17020 +3306 820 0 4312c880 18666 +3307 821 0 4313116c 10236 +3308 822 0 43133968 8203 +3309 823 0 43135974 13031 +3310 824 0 43138c5c 41125 +3311 825 0 43142d04 83491 +3312 826 0 43157328 39879 +3313 827 0 43160ef0 55247 +3314 828 0 4316e6c0 50387 +3315 829 0 4317ab94 57571 +3316 830 0 43188c78 55470 +3317 831 0 43196528 53728 +3318 832 0 431a3708 47314 +3319 833 0 431aefdc 91907 +3320 834 0 431c56e0 72948 +3321 835 0 431d73d4 50725 +3322 836 0 431e39fc 75098 +3323 837 0 431f5f58 64383 +3324 838 0 43205ad8 67826 +3325 839 0 432163cc 62984 +3326 840 0 432259d4 41064 +3327 841 0 4322fa3c 13406 +3328 842 0 43232e9c 13206 +3329 843 0 43236234 9194 +3330 844 0 43238620 10164 +3331 845 0 4323add4 53589 +3332 846 0 43247f2c 37253 +3333 847 0 432510b4 24259 +3334 848 0 43256f78 34414 +3335 849 0 4325f5e8 10416 +3336 850 0 43261e98 24522 +3337 851 0 43267e64 30023 +3338 852 0 4326f3ac 7420 +3339 853 0 432710a8 32472 +3340 854 0 43278f80 32678 +3341 855 0 43280f28 11432 +3342 856 0 43283bd0 18740 +3343 857 0 43288504 10203 +3344 858 0 4328ace0 24314 +3345 859 0 43290bdc 34874 +3346 860 0 43299418 6741 +3347 861 0 4329ae70 22839 +3348 862 0 432a07a8 8799 +3349 863 0 432a2a08 17312 +3350 864 0 432a6da8 10436 +3351 865 0 432a966c 36970 +3352 866 0 432b26d8 33677 +3353 867 0 432baa68 10189 +3354 868 0 432bd238 117612 +3355 869 0 432d9da4 36818 +3356 870 0 432e2d78 15780 +3357 871 0 432e6b1c 19907 +3358 872 0 432eb8e0 19804 +3359 873 0 432f063c 26196 +3360 874 0 432f6c90 29898 +3361 875 0 432fe15c 16118 +3362 876 0 43302054 6183 +3363 877 0 4330387c 8490 +3364 878 0 433059a8 8147 +3365 879 0 4330797c 10967 +3366 880 0 4330a454 14795 +3367 881 0 4330de20 7554 +3368 882 0 4330fba4 10739 +3369 883 0 43312598 7754 +3370 884 0 433143e4 11574 +3371 885 0 4331711c 10886 +3372 886 0 43319ba4 8380 +3373 887 0 4331bc60 11879 +3374 888 0 4331eac8 11159 +3375 889 0 43321660 10140 +3376 890 0 43323dfc 14299 +3377 891 0 433275d8 15933 +3378 892 0 4332b418 20747 +3379 893 0 43330524 15820 +3380 894 0 433342f0 18887 +3381 895 0 43338cb8 14642 +3382 896 0 4333c5ec 12828 +3383 897 0 4333f808 13718 +3384 898 0 43342da0 21206 +3385 899 0 43348078 11883 +3386 900 0 4334aee4 9213 +3387 901 0 4334d2e4 9518 +3388 902 0 4334f814 9199 +3389 903 0 43351c04 18235 +3390 904 0 43356340 16310 +3391 905 0 4335a2f8 18032 +3392 906 0 4335e968 20741 +3393 907 0 43363a70 19151 +3394 908 0 43368540 19187 +3395 909 0 4336d034 56447 +3396 910 0 4337acb4 34807 +3397 911 0 433834ac 32307 +3398 912 0 4338b2e0 22388 +3399 913 0 43390a54 54485 +3400 914 0 4339df2c 26428 +3401 915 0 433a4668 56668 +3402 916 0 433b23c4 16231 +3403 917 0 433b632c 11990 +3404 918 0 433b9204 12366 +3405 919 0 433bc254 17319 +3406 920 0 433c05fc 14808 +3407 921 0 433c3fd4 14967 +3408 922 0 433c7a4c 27172 +3409 923 0 433ce470 36864 +3410 924 0 433d7470 17511 +3411 925 0 433db8d8 18428 +3412 926 0 433e00d4 8383 +3413 927 0 433e2194 23430 +3414 928 0 433e7d1c 21883 +3415 929 0 433ed298 18430 +3416 930 0 433f1a98 17286 +3417 931 0 433f5e20 17823 +3418 932 0 433fa3c0 19071 +3419 933 0 433fee40 15940 +3420 934 0 43402c84 11560 +3421 935 0 434059ac 14646 +3422 936 0 434092e4 10420 +3423 937 0 4340bb98 14367 +3424 938 0 4340f3b8 11116 +3425 939 0 43411f24 57111 +3426 940 0 4341fe3c 39959 +3427 941 0 43429a54 34163 +3428 942 0 43431fc8 49202 +3429 943 0 4343dffc 36354 +3430 944 0 43446e00 33583 +3431 945 0 4344f130 35661 +3432 946 0 43457c80 56604 +3433 947 0 4346599c 45654 +3434 948 0 43470bf4 34602 +3435 949 0 43479320 29148 +3436 950 0 434804fc 49291 +3437 951 0 4348c588 50051 +3438 952 0 4349890c 12674 +3439 953 0 4349ba90 14398 +3440 954 0 4349f2d0 8387 +3441 955 0 434a1394 11647 +3442 956 0 434a4114 16108 +3443 957 0 434a8000 18901 +3444 958 0 434ac9d8 64472 +3445 959 0 434bc5b0 60538 +3446 960 0 434cb22c 34847 +3447 961 0 434d3a4c 34312 +3448 962 0 434dc054 40227 +3449 963 0 434e5d78 30251 +3450 964 0 434ed3a4 39325 +3451 965 0 434f6d44 36488 +3452 966 0 434ffbcc 39480 +3453 967 0 43509604 72782 +3454 968 0 4351b254 36362 +3455 969 0 43524060 29427 +3456 970 0 4352b354 35286 +3457 971 0 43533d2c 63693 +3458 972 0 435435fc 37359 +3459 973 0 4354c7ec 13525 +3460 974 0 4354fcc4 12530 +3461 975 0 43552db8 8138 +3462 976 0 43554d84 7922 +3463 977 0 43556c78 55108 +3464 978 0 435643bc 29747 +3465 979 0 4356b7f0 26822 +3466 980 0 435720b8 34880 +3467 981 0 4357a8f8 6994 +3468 982 0 4357c44c 34466 +3469 983 0 43584af0 33847 +3470 984 0 4358cf28 6307 +3471 985 0 4358e7cc 35586 +3472 986 0 435972d0 8752 +3473 987 0 43599500 8728 +3474 988 0 4359b718 16327 +3475 989 0 4359f6e0 11912 +3476 990 0 435a2568 33940 +3477 991 0 435aa9fc 29037 +3478 992 0 435b1b6c 14383 +3479 993 0 435b539c 12012 +3480 994 0 435b8288 14327 +3481 995 0 435bba80 12827 +3482 996 0 435bec9c 11772 +3483 997 0 435c1a98 35351 +3484 998 0 435ca4b0 34182 +3485 999 0 435d2a38 9469 +3486 1000 0 435d4f38 145452 +3487 1001 0 435f8764 32087 +3488 1002 0 436004bc 25294 +3489 1003 0 4360678c 39789 +3490 1004 0 436102fc 22067 +3491 1005 0 43615930 48699 +3492 1006 0 4362176c 29554 +3493 1007 0 43628ae0 23139 +3494 1008 0 4362e544 8077 +3495 1009 0 436304d4 9864 +3496 1010 0 43632b5c 9019 +3497 1011 0 43634e98 9756 +3498 1012 0 436374b4 7328 +3499 1013 0 43639154 8650 +3500 1014 0 4363b320 14189 +3501 1015 0 4363ea90 6293 +3502 1016 0 43640328 12501 +3503 1017 0 43643400 11667 +3504 1018 0 43646194 11056 +3505 1019 0 43648cc4 11773 +3506 1020 0 4364bac4 13567 +3507 1021 0 4364efc4 10844 +3508 1022 0 43651a20 16496 +3509 1023 0 43655a90 17957 +3510 1024 0 4365a0b8 18894 +3511 1025 0 4365ea88 18292 +3512 1026 0 436631fc 19290 +3513 1027 0 43667d58 14381 +3514 1028 0 4366b588 16858 +3515 1029 0 4366f764 14662 +3516 1030 0 436730ac 19621 +3517 1031 0 43677d54 12599 +3518 1032 0 4367ae8c 9902 +3519 1033 0 4367d53c 8430 +3520 1034 0 4367f62c 7979 +3521 1035 0 43681558 16796 +3522 1036 0 436856f4 14398 +3523 1037 0 43688f34 14482 +3524 1038 0 4368c7c8 15807 +3525 1039 0 43690588 30403 +3526 1040 0 43697c4c 33424 +3527 1041 0 4369fedc 26765 +3528 1042 0 436a676c 44404 +3529 1043 0 436b14e0 30888 +3530 1044 0 436b8d88 24060 +3531 1045 0 436beb84 26879 +3532 1046 0 436c5484 10739 +3533 1047 0 436c7e78 17816 +3534 1048 0 436cc410 11542 +3535 1049 0 436cf128 13982 +3536 1050 0 436d27c8 15480 +3537 1051 0 436d6440 24114 +3538 1052 0 436dc274 11930 +3539 1053 0 436df110 14268 +3540 1054 0 436e28cc 16767 +3541 1055 0 436e6a4c 22935 +3542 1056 0 436ec3e4 16399 +3543 1057 0 436f03f4 18885 +3544 1058 0 436f4dbc 9770 +3545 1059 0 436f73e8 23253 +3546 1060 0 436fcec0 29816 +3547 1061 0 43704338 26156 +3548 1062 0 4370a964 43140 +3549 1063 0 437151e8 26064 +3550 1064 0 4371b7b8 20179 +3551 1065 0 4372068c 12496 +3552 1066 0 4372375c 15306 +3553 1067 0 43727328 16248 +3554 1068 0 4372b2a0 10571 +3555 1069 0 4372dbec 14392 +3556 1070 0 43731424 11330 +3557 1071 0 43734068 51784 +3558 1072 0 43740ab0 52477 +3559 1073 0 4374d7b0 50395 +3560 1074 0 43759c8c 41962 +3561 1075 0 43764078 34605 +3562 1076 0 4376c7a8 46464 +3563 1077 0 43777d28 45098 +3564 1078 0 43782d54 36435 +3565 1079 0 4378bba8 19403 +3566 1080 0 43790774 41600 +3567 1081 0 4379a9f4 46066 +3568 1082 0 437a5de8 42587 +3569 1083 0 437b0444 11447 +3570 1084 0 437b30fc 10485 +3571 1085 0 437b59f4 14104 +3572 1086 0 437b910c 9948 +3573 1087 0 437bb7e8 20876 +3574 1088 0 437c0974 68399 +3575 1089 0 437d14a4 37752 +3576 1090 0 437da81c 48061 +3577 1091 0 437e63dc 38304 +3578 1092 0 437ef97c 53918 +3579 1093 0 437fcc1c 55182 +3580 1094 0 4380a3ac 43284 +3581 1095 0 43814cc0 64166 +3582 1096 0 43824768 58655 +3583 1097 0 43832c88 71051 +3584 1098 0 43844214 39580 +3585 1099 0 4384dcb0 76024 +3586 1100 0 438605a8 44792 +3587 1101 0 4386b4a0 34429 +3588 1102 0 43873b20 48979 +3589 1103 0 4387fa74 11295 +3590 1104 0 43882694 13584 +3591 1105 0 43885ba4 7804 +3592 1106 0 43887a20 7228 +3593 1107 0 4388965c 56183 +3594 1108 0 438971d4 25742 +3595 1109 0 4389d664 31941 +3596 1110 0 438a532c 40539 +3597 1111 0 438af188 6144 +3598 1112 0 438b0988 26237 +3599 1113 0 438b7008 32525 +3600 1114 0 438bef18 3965 +3601 1115 0 438bfe98 35378 +3602 1116 0 438c88cc 39836 +3603 1117 0 438d2468 9706 +3604 1118 0 438d4a54 17855 +3605 1119 0 438d9014 9987 +3606 1120 0 438db718 15922 +3607 1121 0 438df54c 38920 +3608 1122 0 438e8d54 51370 +3609 1123 0 438f5600 6922 +3610 1124 0 438f710c 80212 +3611 1125 0 4390aa60 9988 +3612 1126 0 4390d164 14552 +3613 1127 0 43910a3c 48600 +3614 1128 0 4391c814 42222 +3615 1129 0 43926d04 11492 +3616 1130 0 439299e8 138899 +3617 1131 0 4394b87c 45256 +3618 1132 0 43956944 15382 +3619 1133 0 4395a55c 39415 +3620 1134 0 43963f54 7414 +3621 1135 0 43965c4c 30807 +3622 1136 0 4396d4a4 13306 +3623 1137 0 439708a0 13180 +3624 1138 0 43973c1c 5787 +3625 1139 0 439752b8 8666 +3626 1140 0 43977494 8491 +3627 1141 0 439795c0 9435 +3628 1142 0 4397ba9c 5292 +3629 1143 0 4397cf48 6134 +3630 1144 0 4397e740 7342 +3631 1145 0 439803f0 6170 +3632 1146 0 43981c0c 12208 +3633 1147 0 43984bbc 10300 +3634 1148 0 439873f8 13925 +3635 1149 0 4398aa60 13339 +3636 1150 0 4398de7c 10506 +3637 1151 0 43990788 8899 +3638 1152 0 43992a4c 18334 +3639 1153 0 439971ec 16075 +3640 1154 0 4399b0b8 18902 +3641 1155 0 4399fa90 15957 +3642 1156 0 439a38e8 20510 +3643 1157 0 439a8908 12490 +3644 1158 0 439ab9d4 15261 +3645 1159 0 439af574 11461 +3646 1160 0 439b223c 18624 +3647 1161 0 439b6afc 11022 +3648 1162 0 439b960c 9571 +3649 1163 0 439bbb70 11827 +3650 1164 0 439be9a4 8005 +3651 1165 0 439c08ec 15004 +3652 1166 0 439c4388 14206 +3653 1167 0 439c7b08 13218 +3654 1168 0 439caeac 15900 +3655 1169 0 439cecc8 12411 +3656 1170 0 439d1d44 14412 +3657 1171 0 439d5590 17628 +3658 1172 0 439d9a6c 35208 +3659 1173 0 439e23f4 24100 +3660 1174 0 439e8218 24356 +3661 1175 0 439ee13c 14334 +3662 1176 0 439f193c 22653 +3663 1177 0 439f71bc 17064 +3664 1178 0 439fb464 17415 +3665 1179 0 439ff86c 12591 +3666 1180 0 43a0299c 16871 +3667 1181 0 43a06b84 16656 +3668 1182 0 43a0ac94 20183 +3669 1183 0 43a0fb6c 16317 +3670 1184 0 43a13b2c 18915 +3671 1185 0 43a18510 24264 +3672 1186 0 43a1e3d8 21983 +3673 1187 0 43a239b8 13016 +3674 1188 0 43a26c90 21432 +3675 1189 0 43a2c048 11096 +3676 1190 0 43a2eba0 25312 +3677 1191 0 43a34e80 13478 +3678 1192 0 43a38328 17196 +3679 1193 0 43a3c654 13839 +3680 1194 0 43a3fc64 17877 +3681 1195 0 43a4423c 12367 +3682 1196 0 43a4728c 10214 +3683 1197 0 43a49a74 14210 +3684 1198 0 43a4d1f8 11368 +3685 1199 0 43a4fe60 15774 +3686 1200 0 43a53c00 14701 +3687 1201 0 43a57570 11141 +5007 1202 0 43a5a0f8 46477 +5012 1203 0 43a65688 640047 +5013 1204 0 43b01ab8 23575 +5014 1205 0 43b076d0 20695 +5015 1206 0 43b0c7a8 20215 +5016 1207 0 43b116a0 38310 +5017 1208 0 43b1ac48 34419 +5018 1209 0 43b232bc 159757 +5019 1210 0 43b4a2cc 52030 +5020 1211 0 43b56e0c 9391 +5021 1212 0 43b592bc 8402 +5022 1213 0 43b5b390 22550 +5023 1214 0 43b60ba8 32140 +5024 1215 0 43b68934 14916 +5025 1216 0 43b6c378 80836 +5026 1217 0 43b7ff3c 108395 +5027 1218 0 43b9a6a8 36101 +5028 1219 0 43ba33b0 26803 +5029 1220 0 43ba9c64 39000 +5030 1221 0 43bb34bc 44566 +5031 1222 0 43bbe2d4 48923 +5032 1223 0 43bca1f0 71959 +5033 1224 0 43bdbb08 71640 +5034 1225 0 43bed2e0 30422 +5035 1226 0 43bf49b8 148274 +5036 1227 0 43c18cec 67780 +5037 1228 0 43c295b0 20662 +5038 1229 0 43c2e668 16238 +5039 1230 0 43c325d8 105980 +5040 1231 0 43c4c3d4 13413 +5041 1232 0 43c4f83c 23038 +5042 1233 0 43c5523c 30671 +5043 1234 0 43c5ca0c 15644 +5044 1235 0 43c60728 32135 +5045 1236 0 43c684b0 40408 +5046 1237 0 43c72288 64462 +5047 1238 0 43c81e58 36012 +5048 1239 0 43c8ab04 100327 +5049 1240 0 43ca32ec 124575 +5050 1241 0 43cc198c 118612 +5051 1242 0 43cde8e0 91659 +5052 1243 0 43cf4eec 56183 +5053 1244 0 43d02a64 74730 +5054 1245 0 43d14e50 100022 +5055 1246 0 43d2d508 97661 +5056 1247 0 43d45288 154875 +5057 1248 0 43d6af84 28372 +5058 1249 0 43d71e58 84919 +5059 1250 0 43d86a10 78912 +5060 1251 0 43d99e50 61212 +5061 1252 0 43da8d6c 184423 +5062 1253 0 43dd5dd4 38390 +5074 1254 0 43ddf3cc 52208 +5075 1255 0 43debfbc 15956 +5076 1256 0 43defe10 19190 +5077 1257 0 43df4908 25990 +5078 1258 0 43dfae90 10427 +5079 1259 0 43dfd74c 23940 +5080L 1260 0 43e034d0 69970 +5080R 1261 0 43e14624 87775 +5081L 1262 0 43e29d04 87775 +5081R 1263 0 43e3f3e4 87775 +5083 1264 0 43e54ac4 87775 +5084 1265 0 43e6a1a4 97204 +5085 1266 0 43e81d58 36141 +5086 1267 0 43e8aa88 31888 +5087 1268 0 43e92718 44632 +5088 1269 0 43e9d570 13856 +5089 1270 0 43ea0b90 61796 +5090 1271 0 43eafcf4 58118 +5091L 1272 0 43ebdffc 46763 +5091R 1273 0 43ec96a8 59327 +5092 1274 0 43ed7e68 59327 +5093 1275 0 43ee6628 13736 +5094 1276 0 43ee9bd0 14581 +5095 1277 0 43eed4c8 9974 +5096 1278 0 43eefbc0 9102 +5097 1279 0 43ef1f50 18036 +5098 1280 0 43ef65c4 13923 +5099 1281 0 43ef9c28 50204 +5100 1282 0 43f06044 61390 +5101 1283 0 43f15014 61842 +5102 1284 0 43f241a8 40950 +5103 1285 0 43f2e1a0 56283 +5104 1286 0 43f3bd7c 170942 +5105 1287 0 43f6593c 266150 +5106 1288 0 43fa68e4 10870 +5107 1289 0 43fa935c 10048 +5108 1290 0 43faba9c 7964 +5109 1291 0 43fad9b8 18295 +5110 1292 0 43fb2130 16221 +5111 1293 0 43fb6090 14450 +5112 1294 0 43fb9904 176608 +5113 1295 0 43fe4ae4 90615 +5114 1296 0 43ffacdc 57728 +5115 1297 0 44008e5c 375564 +5116 1298 0 44064968 338599 +5121 1299 0 440b7410 494404 +5122 1300 0 4412ff54 124874 +5123 1301 0 4414e720 380559 +5124 1302 0 441ab5b0 32339 +5125 1303 0 441b3404 21976 +5126 1304 0 441b89dc 59128 +5127 1305 0 441c70d4 56560 +5128 1306 0 441d4dc4 63612 +5129 1307 0 441e4640 61458 +5130 1308 0 441f3654 26480 +5131 1309 0 441f9dc4 40579 +5132 1310 0 44203c48 34483 +5133 1311 0 4420c2fc 27914 +5134 1312 0 44213008 80915 +5135 1313 0 44226c1c 27778 +5136 1314 0 4422d8a0 24514 +5137 1315 0 44233864 26959 +5138 1316 0 4423a1b4 59653 +5143 1317 0 44248abc 63530 +5144 1318 0 442582e8 376884 +5156 1319 0 442b431c 64926 +5161 1320 0 442c40bc 214674 +5162 1321 0 442f8750 40091 +5165 1322 0 443023ec 58147 +5166 1323 0 44310710 140955 +5167 1324 0 44332dac 125652 +5168 1325 0 44351880 106892 +5169 1326 0 4436ba0c 118386 +5170 1327 0 44388880 82543 +5172 1328 0 4439caf0 49719 +5173 1329 0 443a8d28 43936 +5174 1330 0 443b38c8 29181 +5175 1331 0 443baac8 101018 +5176 1332 0 443d3564 6538 +5177 1333 0 443d4ef0 23184 +5178 1334 0 443da980 13551 +5179 1335 0 443dde70 60004 +5180 1336 0 443ec8d4 44700 +5181 1337 0 443f7770 48951 +5191 1338 0 444036a8 11506 +5192 1339 0 4440639c 7706 +5193 1340 0 444081b8 11096 +5194 1341 0 4440ad10 37380 +5195 1342 0 44413f14 55746 +5197 1343 0 444218d8 77903 +5198 1344 0 44434928 38734 +5199 1345 0 4443e078 8333 +5200 1346 0 44440108 7554 +5201 1347 0 44441e8c 10492 +5202 1348 0 44444788 27011 +5204 1349 0 4444b10c 10659 +5205 1350 0 4444dab0 52786 +5206 1351 0 4445a8e4 25021 +5207 1352 0 44460aa4 27444 +5208 1353 0 444675d8 24988 +5209 1354 0 4446d774 46802 +5210 1355 0 44478e48 15846 +5211 1356 0 4447cc30 31264 +5212 1357 0 44484650 71885 +5213 1358 0 44495f20 17558 +5214 1359 0 4449a3b8 27850 +5215 1360 0 444a1084 19596 +5220 1361 0 444a5d10 74480 +5239 1362 0 444b8000 29132 +5240 1363 0 444bf1cc 31688 +5241 1364 0 444c6d94 43635 +5244 1365 0 444d1808 17404 +5245 1366 0 444d5c04 24630 +5246 1367 0 444dbc3c 84140 +5247 1368 0 444f04e8 101602 +5248 1369 0 445091cc 131893 +5249 1370 0 44529504 33613 +5250 1371 0 44531854 49840 +5251 1372 0 4453db04 40990 +5252 1373 0 44547b24 25267 +5253 1374 0 4454ddd8 19190 +5254 1375 0 445528d0 36738 +5255 1376 0 4455b854 11302 +5256 1377 0 4455e47c 40141 +5257 1378 0 4456814c 15170 +5258 1379 0 4456bc90 28538 +5259 1380 0 44572c0c 9272 +5260 1381 0 44575044 54757 +5261 1382 0 4458262c 35710 +5262 1383 0 4458b1ac 13126 +5263 1384 0 4458e4f4 13126 +5264 1385 0 4459183c 11555 +5265 1386 0 44594560 32724 +5266 1387 0 4459c534 36280 +5267 1388 0 445a52ec 24590 +5268 1389 0 445ab2fc 21784 +5269 1390 0 445b0814 16456 +5270 1391 0 445b485c 23920 +5271 1392 0 445ba5cc 30582 +5272 1393 0 445c1d44 13764 +5273 1394 0 445c5308 12589 +5274 1395 0 445c8438 27589 +5275 1396 0 445cf000 24279 +5276 1397 0 445d4ed8 21253 +5277 1398 0 445da1e0 30780 +5278 1399 0 445e1a1c 26972 +5279 1400 0 445e8378 64502 +5280 1401 0 445f7f70 11309 +5281 1402 0 445faba0 12861 +5282 1403 0 445fdde0 22560 +5283 1404 0 44603600 25128 +5284 1405 0 44609828 39074 +5285 1406 0 446130cc 36087 +5286 1407 0 4461bdc4 10267 +5287 1408 0 4461e5e0 11787 +5288 1409 0 446213ec 14904 +5289 1410 0 44624e24 65079 +5290 1411 0 44634c5c 13956 +5291 1412 0 446382e0 23158 +5292 1413 0 4463dd58 16988 +5293 1414 0 44641fb4 11056 +5294 1415 0 44644ae4 38181 +5295 1416 0 4464e00c 23662 +5296 1417 0 44653c7c 18461 +5297 1418 0 4465849c 18594 +5298 1419 0 4465cd40 20557 +5299 1420 0 44661d90 44679 +5300 1421 0 4466cc18 16922 +5301 1422 0 44670e34 36559 +5302 1423 0 44679d04 886966 +5303 1424 0 447525bc 713058 +5312 1425 0 44800720 330072 +5313 1426 0 44851078 28551 +5314 1427 0 44858000 15754 +5315 1428 0 4485bd8c 30034 +5316 1429 0 448632e0 24365 +5317 1430 0 44869210 35683 +5318 1431 0 44871d74 60602 +5319 1432 0 44880a30 28903 +5320 1433 0 44887b18 20093 +5321 1434 0 4488c998 14427 +5322 1435 0 448901f4 14847 +5323 1436 0 44893bf4 23082 +5324 1437 0 44899620 24086 +5325 1438 0 4489f438 33534 +5326 1439 0 448a7738 21976 +5327 1440 0 448acd10 22142 +5328 1441 0 448b2390 27669 +5329 1442 0 448b8fa8 19797 +5330 1443 0 448bdd00 34047 +5331 1444 0 448c6200 30582 +5332 1445 0 448cd978 19071 +5333 1446 0 448d23f8 40566 +5334 1447 0 448dc270 18925 +5335 1448 0 448e0c60 34708 +5336 1449 0 448e93f4 32631 +5337 1450 0 448f136c 44254 +5338 1451 0 448fc04c 81195 +5339 1452 0 4490fd78 34117 +5340 1453 0 449182c0 30959 +5341 1454 0 4491fbb0 17160 +5342 1455 0 44923eb8 14583 +5343 1456 0 449277b0 32711 +5344 1457 0 4492f778 37142 +5345 1458 0 44938890 37979 +5346 1459 0 44941cec 36054 +5347 1460 0 4494a9c4 30482 +5348 1461 0 449520d8 39372 +5349 1462 0 4495baa4 29519 +5352 1463 0 44962df4 38350 +5353 1464 0 4496c3c4 7951 +5354 1465 0 4496e2d4 7951 +5355 1466 0 449701e4 7278 +5356 1467 0 44971e54 13866 +5357 1468 0 44975480 41509 +5358 1469 0 4497f6a8 15541 +5360L 1470 0 44983360 7951 +5360R 1471 0 44985270 350174 +5361L 1472 0 449daa50 350174 +5361R 1473 0 44a30230 105333 +5362L 1474 0 44a49da8 105333 +5362R 1475 0 44a63920 108931 +5363L 1476 0 44a7e2a4 108931 +5363R 1477 0 44a98c28 106759 +5364L 1478 0 44ab2d30 106759 +5364R 1479 0 44acce38 92504 +5365L 1480 0 44ae3790 92504 +5365R 1481 0 44afa0e8 78215 +5366L 1482 0 44b0d270 78215 +5366R 1483 0 44b203f8 88301 +5367L 1484 0 44b35ce8 88301 +5367R 1485 0 44b4b5d8 88837 +5368L 1486 0 44b610e0 88837 +5368R 1487 0 44b76be8 87636 +5369L 1488 0 44b8c23c 87636 +5369R 1489 0 44ba1890 96818 +5370L 1490 0 44bb92c4 96818 +5370R 1491 0 44bd0cf8 81519 +5371L 1492 0 44be4b68 81519 +5371R 1493 0 44bf89d8 122104 +5372L 1494 0 44c166d0 122104 +5372R 1495 0 44c343c8 123187 +5373L 1496 0 44c524fc 123187 +5373R 1497 0 44c70630 152708 +5374L 1498 0 44c95ab4 152708 +5374R 1499 0 44cbaf38 98028 +5375L 1500 0 44cd2e24 98028 +5375R 1501 0 44cead10 77455 +5376L 1502 0 44cfdba0 77455 +5376R 1503 0 44d10a30 87788 +5377L 1504 0 44d2611c 87788 +5377R 1505 0 44d3b808 115101 +5378L 1506 0 44d579a8 115101 +5378R 1507 0 44d73b48 67219 +5379L 1508 0 44d841dc 67219 +5379R 1509 0 44d94870 69499 +5380L 1510 0 44da57ec 69499 +5380R 1511 0 44db6768 87702 +5381L 1512 0 44dcbe00 87702 +5381R 1513 0 44de1498 73383 +5382L 1514 0 44df3340 73383 +5382R 1515 0 44e051e8 63434 +5383L 1516 0 44e149b4 63434 +5383R 1517 0 44e24180 62638 +5384L 1518 0 44e33630 62638 +5384R 1519 0 44e42ae0 69590 +5385L 1520 0 44e53ab8 69590 +5385R 1521 0 44e64a90 80763 +5386L 1522 0 44e7860c 80763 +5386R 1523 0 44e8c188 80976 +5387L 1524 0 44e9fdd8 80976 +5387R 1525 0 44eb3a28 68343 +5388L 1526 0 44ec4520 68343 +5388R 1527 0 44ed5018 88837 +5389L 1528 0 44eeab20 88837 +5389R 1529 0 44f00628 88220 +5390 1530 0 44f15ec4 88220 +5391 1531 0 44f2b760 90535 +5392 1532 0 44f41908 134693 +5393 1533 0 44f62730 163141 +5394 1534 0 44f8a478 77830 +5395 1535 0 44f9d480 68456 +5396 1536 0 44fadfe8 63362 +5397 1537 0 44fbd76c 102092 +5398 1538 0 44fd6638 131296 +5399 1539 0 44ff6718 71640 +5400 1540 0 45007ef0 97754 +5401 1541 0 4501fccc 147855 +5402 1542 0 45043e5c 94144 +5403 1543 0 4505ae1c 81195 +5404 1544 0 4506eb48 76524 +5405 1545 0 45081634 134693 +5406 1546 0 450a245c 83954 +5407 1547 0 450b6c50 158895 +5408 1548 0 450dd900 123653 +5409 1549 0 450fbc08 98178 +5410 1550 0 45113b8c 117285 +5411 1551 0 451305b4 97754 +5412 1552 0 45148390 83264 +5413 1553 0 4515c8d0 87139 +5414 1554 0 45171d34 90110 +5415 1555 0 45187d34 61238 +5416 1556 0 45196c6c 201354 +5417 1557 0 451c7ef8 79071 +5418 1558 0 451db3d8 75462 +5419 1559 0 451edaa0 93932 +5420 1560 0 4520498c 81619 +5421 1561 0 45218860 140213 +5422 1562 0 4523ac18 128324 +5423 1563 0 4525a15c 155498 +5424 1564 0 452800c8 123229 +5425 1565 0 4529e228 310050 +5426 1566 0 452e9d4c 152101 +5427 1567 0 4530ef74 99876 +5428 1568 0 45327598 63573 +5429 1569 0 45336df0 31304 +5430 1570 0 4533e838 273535 +5431 1571 0 453814b8 99452 +5432 1572 0 45399934 80982 +5433 1573 0 453ad58c 69093 +5434 1574 0 453be374 44254 +5435 1575 0 453c9054 44043 +5436 1576 0 453d3c60 88837 +5437 1577 0 453e9768 90959 +5438 1578 0 453ffab8 53171 +5439 1579 0 4540ca6c 63998 +5440 1580 0 4541c46c 73127 +5441 1581 0 4542e214 37886 +5442 1582 0 45437614 54232 +5443 1583 0 454449ec 38310 +5444 1584 0 4544df94 40858 +5445 1585 0 45457f30 81406 +5446 1586 0 4546bd30 119630 +5447 1587 0 45489080 82314 +5448 1588 0 4549d20c 107848 +5449 1589 0 454b7754 48724 +5450 1590 0 454c35a8 35947 +5451 1591 0 454cc214 261844 +5452 1592 0 4550c0e8 142931 +5453 1593 0 4552ef3c 55852 +5454 1594 0 4553c968 35349 +5455 1595 0 45545380 46867 +5456 1596 0 45550a94 43821 +5457 1597 0 4555b5c4 43821 +5458 1598 0 455660f4 63581 +5459 1599 0 45575954 79983 +5460 1600 0 455891c4 71138 +5461 1601 0 4559a7a8 33663 +5462 1602 0 455a2b28 58783 +5463 1603 0 455b10c8 51467 +5464 1604 0 455bd9d4 30387 +5465 1605 0 455c5088 35903 +5466 1606 0 455cdcc8 30798 +5467 1607 0 455d5518 30240 +5468 1608 0 455dcb38 61966 +5469 1609 0 455ebd48 44014 +5470 1610 0 455f6938 30904 +5471 1611 0 455fe1f0 50794 +5472 1612 0 4560a85c 44902 +5473 1613 0 456157c4 77646 +5474 1614 0 45628714 42527 +5475 1615 0 45632d34 32702 +5476 1616 0 4563acf4 45716 +5477 1617 0 45645f88 40186 +5478 1618 0 4564fc84 34646 +5479 1619 0 456583dc 59830 +5480L 1620 0 45666d94 508373 +5480R 1621 0 456e2f6c 88854 +5481L 1622 0 456f8a84 88854 +5481R 1623 0 4570e59c 100800 +5482L 1624 0 45726f5c 100800 +5482R 1625 0 4573f91c 75015 +5483L 1626 0 45751e24 75015 +5483R 1627 0 4576432c 76886 +5484L 1628 0 45776f84 76886 +5484R 1629 0 45789bdc 106846 +5485L 1630 0 457a3d3c 106846 +5485R 1631 0 457bde9c 75592 +5486L 1632 0 457d05e4 75592 +5486R 1633 0 457e2d2c 71459 +5487L 1634 0 457f4450 71459 +5487R 1635 0 45805b74 69309 +5488L 1636 0 45816a34 69309 +5488R 1637 0 458278f4 83878 +5489L 1638 0 4583c09c 83878 +5489R 1639 0 45850844 84092 +5490L 1640 0 458650c0 84092 +5490R 1641 0 4587993c 68434 +5491L 1642 0 4588a490 68434 +5491R 1643 0 4589afe4 79526 +5492L 1644 0 458ae68c 79526 +5492R 1645 0 458c1d34 73709 +5493L 1646 0 458d3d24 73709 +5493R 1647 0 458e5d14 75413 +5494L 1648 0 458f83ac 75413 +5494R 1649 0 4590aa44 81798 +5495L 1650 0 4591e9cc 81798 +5495R 1651 0 45932954 136661 +5496L 1652 0 45953f2c 136661 +5496R 1653 0 45975504 99269 +5603L 1654 0 4598d8cc 99269 +5603R 1655 0 459a5c94 251260 +6010 1656 0 459e3210 251260 +6011 1657 0 45a2078c 10318 +6012 1658 0 45a22fdc 43850 +6013 1659 0 45a2db28 199019 +6014 1660 0 45a5e494 66546 +codec.dat 1661 0 45a6e888 34276 +DebugImages.tpl 1662 0 45a78000 12409824 +dummy.tpl 1663 0 4664dbe0 1835136 +face.dat 1664 0 4680dc60 256 +ip.cfg 1665 0 46810000 7034880 +mgso.rel 1666 0 46ec5800 48 +mgso.str 1667 0 46ec5830 5729024 +movie.dat 1668 0 4743c330 35 +stage 1669 0 47440000 94935040 +preview 1670 1 5c 1672 +data.cnf 1671 1 685 1672 +vox.dat 1672 0 4cec9800 175 +freeing memory used by FST string table... ...done. diff --git a/source/std_disclaimer.h b/source/std_disclaimer.h new file mode 100755 index 0000000..6e8827c --- /dev/null +++ b/source/std_disclaimer.h @@ -0,0 +1,13 @@ +/* What you are seeing is a work in progress. Source and comments + it contains could be dangerous, profane, or just plain wrong. + While I generally don't publish source code unless I feel it's in + a semi-production state (or at least to the point where someone + somewhere could benefit from it), I can't guarantee anything. + + If you use this code and the genie of your computer (or your cube!) escapes in + a puff of smoke, I will not be held liable. You have been warned. + This code may be ugly, incomplete, or just plain wrong. + + No F'in warranty implied! + + Andrew K 2005 andrew@aklabs.net */