From 4b5333077348b55cb338cb5522cec9fed640a3e7 Mon Sep 17 00:00:00 2001 From: Meep-Eep Date: Mon, 16 Apr 2007 03:48:07 +0000 Subject: [PATCH] DOS SC2 string convertor. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2738 8092fc87-c524-0410-9efc-e669fe64eaf9 --- tools/dos-str/Makefile | 9 ++ tools/dos-str/unstr | Bin 0 -> 22729 bytes tools/dos-str/unstr.c | 311 ++++++++++++++++++++++++++++++++++++++ tools/dos-str/unstrall.sh | 44 ++++++ 4 files changed, 364 insertions(+) create mode 100644 tools/dos-str/Makefile create mode 100755 tools/dos-str/unstr create mode 100644 tools/dos-str/unstr.c create mode 100755 tools/dos-str/unstrall.sh diff --git a/tools/dos-str/Makefile b/tools/dos-str/Makefile new file mode 100644 index 000000000..a2811878c --- /dev/null +++ b/tools/dos-str/Makefile @@ -0,0 +1,9 @@ +unstr: unstr.c + gcc -W -Wall -g -O0 unstr.c -o unstr + +clean: + rm unstr unstr.tgz + +tgz: unstr.c Makefile + tar -cvzf unstr.tgz unstr.c Makefile + diff --git a/tools/dos-str/unstr b/tools/dos-str/unstr new file mode 100755 index 0000000000000000000000000000000000000000..c443c571109e5d11fabf8331830db771c87935f1 GIT binary patch literal 22729 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 A3jhEB literal 0 HcmV?d00001 diff --git a/tools/dos-str/unstr.c b/tools/dos-str/unstr.c new file mode 100644 index 000000000..6e3f02e4e --- /dev/null +++ b/tools/dos-str/unstr.c @@ -0,0 +1,311 @@ +/* + * DOS SC2 string extractor. + * + * By Serge van den Boom (svdb@stack.nl), 20021027 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// The DOS strings are contained within a dynamically loaded piece of 16 +// bits x86 code. These code files also contain a table with starting +// offsets of the various strings. +// This program is very simple; it takes the filename of the resource, +// and will then search backwards from the end of the file to the start +// off the string table. It will then print the strings in a human-readable +// format. +// +// To use this program, you need to take the following steps: +// - use unpkg to extract the various conversation packages, given +// starcon.pkg, con1.pkg, and con2.pkg. (starcon.pkg contains the index; +// the actual data comes from con1.pkg and con2.pkg) +// - use unpkg on the extracted con packages. The con packages all have +// resource type 6 (the last two numbers of the resource id presented as +// a string are "06"). This produces some files; the files with resource +// id 00200007 and 00400007 are the ones we're interested in. +// - on these files, run "lz" from the "dos-ani" directory, to decompress +// them. +// - run this program, unstr, on the decompressed files. + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include + + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef int32_t int32; + +#define MAKE_WORD(x1, x2) (((x2) << 8) | (x1)) + + + +struct options { + char *infile; + off_t startOffset; + off_t endOffset; + char verbose; +}; + + +bool testStringTable(const uint8 *data, const uint8 *start, + const uint8 *end); +void findStringTable(const uint8 *data, size_t len, off_t *tableStart, + off_t *tableEnd); +void parse_arguments(int argc, char *argv[], struct options *opts); +void dumpStrings(const uint8 *data, off_t startOff, off_t endOff); + + +int +main(int argc, char *argv[]) { + int in; + struct stat sb; + uint8 *buf; + struct options opts; + + parse_arguments(argc, argv, &opts); + + in = open(opts.infile, O_RDONLY); + if (in == -1) { + fprintf(stderr, "Error: Could not open file %s: %s\n", opts.infile, + strerror(errno)); + return EXIT_FAILURE; + } + + if (fstat(in, &sb) == -1) { + perror("stat() failed"); + return EXIT_FAILURE; + } + + buf = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, in, 0); + if (buf == MAP_FAILED) { + perror("mmap() failed"); + return EXIT_FAILURE; + } + close(in); + + if (opts.startOffset == (off_t) -1) { + findStringTable(buf, sb.st_size, &opts.startOffset, + &opts.endOffset); + if (opts.verbose) { + fprintf(stderr, "String table found at offset %u " + "(0x%08x) to %u (0x%08x).\n", + (unsigned int) opts.startOffset, + (unsigned int) opts.startOffset, + (unsigned int) opts.endOffset, + (unsigned int) opts.endOffset); + } + } else { + if (opts.endOffset == (off_t) -1) + opts.endOffset = sb.st_size; + + if (opts.startOffset > opts.endOffset || + opts.endOffset > sb.st_size) { + fprintf(stderr, "Invalid offset.\n"); + exit(EXIT_FAILURE); + } + } + + dumpStrings(buf, opts.startOffset, opts.endOffset); + + munmap(buf, sb.st_size); + return EXIT_SUCCESS; +} + +void +usage() { + fprintf(stderr, "unstr [-s [-e ]] \n" + "\t-s start of the string table. If not specified, unstr tries\n" + "\t to locate it itself.\n"); +} + +void +parse_arguments(int argc, char *argv[], struct options *opts) { + char ch; + + memset(opts, '\0', sizeof (struct options)); + opts->startOffset = (off_t) -1; + opts->endOffset = (off_t) -1; + while (1) { + ch = getopt(argc, argv, "s:v"); + if (ch == -1) + break; + switch(ch) { + case 'v': + opts->verbose = 1; + break; + case 'e': { + char *strEnd; + long value; + + errno = 0; + value = strtoul(optarg, &strEnd, 0); + if (errno != 0 || *optarg == '\0' || *strEnd != '\0') { + fprintf(stderr, "Invalid argument to '-e'.\n"); + exit(EXIT_FAILURE); + } + opts->endOffset = (off_t) value; + break; + } + case 's': { + char *strEnd; + long value; + + errno = 0; + value = strtoul(optarg, &strEnd, 0); + if (errno != 0 || *optarg == '\0' || *strEnd != '\0') { + fprintf(stderr, "Invalid argument to '-s'.\n"); + exit(EXIT_FAILURE); + } + opts->startOffset = (off_t) value; + break; + } + case '?': + case 'h': + default: + usage(); + exit(EXIT_SUCCESS); + } + } + + if (opts->startOffset == (off_t) -1 && opts->endOffset != (off_t) -1) { + fprintf(stderr, "'-e' is only valid in combination with '-s'.\n"); + exit(EXIT_FAILURE); + } + + argc -= optind; + argv += optind; + if (argc != 1) { + usage(); + exit(EXIT_FAILURE); + } + opts->infile = argv[0]; +} + +// Pre: start and end are aligned on 2 bytes. +bool +testStringTable(const uint8 *data, const uint8 *start, const uint8 *end) { + const uint8 *ptr; + off_t tableStartOff = start - data; + int32 lastWord; + + lastWord = -1; + for (ptr = start; ptr < end; ptr += 2) { + uint16 word = MAKE_WORD(ptr[0], ptr[1]); + + // Check the range. + if (word >= tableStartOff) + return false; + + // Offsets must be increasing. + if (word <= lastWord) + return false; + + // XXX: I could whether the strings end where the next one starts, + // but this scanning is good enough. + + lastWord = word; + } + return true; +} + +void +findStringTable(const uint8 *data, size_t len, off_t *tableStart, + off_t *tableEnd) { + off_t i = (off_t) len; + + // Table is aligned on 2 bytes. + if (i % 2 == 1) + i--; + + while (i >= 2) { + uint16 word; + const uint8 *ptr; + i -= 2; + + // Check whether the word points to someplace before &data[i]. + word = MAKE_WORD(data[i], data[i + 1]); + if (word >= i) + continue; + + // There should be one string starting at &data[word], and ending + // just before the start of the string table. + ptr = memchr(&data[word], '\0', i - word); + if (ptr == NULL) + continue; + // If the pointer to the end of the string is an even position, + // the next byte must be '\0' too. + if (((uintptr_t) ptr % 2) == 0) { + ptr++; + if (*ptr != '\0') + continue; + } + ptr++; + // Ptr now points past the end of the string. The start of the + // string table could be here. + + if (testStringTable(data, ptr, &data[i + 2])) { + *tableStart = ptr - data; + *tableEnd = i + 2; + return; + } + } + + fprintf(stderr, "Could not find the start of the string table.\n"); + exit(EXIT_FAILURE); +} + +// Pre: startOff and endOff fall within the range of data. +void +dumpStrings(const uint8 *data, off_t startOff, off_t endOff) { + const uint8 *start = data + startOff; + const uint8 *end = data + endOff; + const uint8 *maxStr = start; + // The strings come directly before the string table. + size_t i; + + for (i = 0; start < end; start += 2, i++) { + uint16 strOff = MAKE_WORD(start[0], start[1]); + size_t maxLen; + const char *strEnd; + + if (&data[strOff] >= maxStr) { + fprintf(stderr, "Invalid string table entry on offset %u.\n", + (uint16) (start - data)); + continue; + } + + maxLen = (size_t) (maxStr - &data[strOff]); + strEnd = memchr(&data[strOff], '\0', maxLen); + if (strEnd == NULL) { + fprintf(stderr, "Invalid string table entry on offset %u.\n", + (uint16) (start - data)); + continue; + } + + printf("#%d\n%s\n", i, (const char *) &data[strOff]); + } +} + + diff --git a/tools/dos-str/unstrall.sh b/tools/dos-str/unstrall.sh new file mode 100755 index 000000000..3cfeca416 --- /dev/null +++ b/tools/dos-str/unstrall.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +UNSTR="./unstr" +INPREFIX="./" +OUTPREFIX="./dialog/" +INFORMAT='${INPREFIX}${RACE1}.con/$ID.out' +OUTFORMAT='${OUTPREFIX}${RACE2}.txt' + + +while read RACE1 ID RACE2; do + eval INFILE="$INFORMAT" + eval OUTFILE="$OUTFORMAT" + echo "Processing... $INFILE ==> $OUTFILE" + $UNSTR -v "$INFILE" > "$OUTFILE" +done << EOF + arilou 00200007 arilou + blackur 00200007 blackur + chmmr 00200007 chmmr + comandr 00200007 comandr + comandr 00400107 starbas + druuge 00200007 druuge + ilwrath 00200007 ilwrath + melnorm 00200007 melnorm + mycon 00200007 mycon + orz 00200007 orz + pkunk 00200007 pkunk + shofixt 00200007 shofixt + slyhome 00200007 slyhome + slyland 00200007 slyland + spathi 00200007 spathi + spathi 00400107 spahome + supox 00200007 supox + syreen 00200007 syreen + talkpet 00200007 talkpet + thradd 00200007 thradd + umgah 00200007 umgah + urquan 00200007 urquan + utwig 00200007 utwig + vux 00200007 vux + yehat 00200007 yehat + yehat 00400107 rebel + zoqfot 00200007 zoqfot +EOF +