diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/agi-palex.py | 185 | ||||
-rw-r--r-- | tools/create_kyradat/create_kyradat.cpp | 6 | ||||
-rw-r--r-- | tools/create_kyradat/md5.cpp | 2 | ||||
-rw-r--r-- | tools/scumm-md5.txt | 7 |
4 files changed, 199 insertions, 1 deletions
diff --git a/tools/agi-palex.py b/tools/agi-palex.py new file mode 100644 index 0000000000..58306dddbe --- /dev/null +++ b/tools/agi-palex.py @@ -0,0 +1,185 @@ +#!/usr/bin/python +# Amiga AGI game palette extractor. +# Extracts palette from an Amiga AGI game's executable file. +# Initial version written during summer of 2007 by Buddha^. +# Somewhat optimized. Adding the preliminary palette test helped speed a lot. +# FIXME: Doesn't report anything about not found files when some files are found. +# An example: palex.py SQ2 PQ1 (When file SQ2 exists but PQ1 doesn't) +import struct, sys, os.path, glob + +# Constants +maxComponentValue = 0xF +colorsPerPalette = 16 +componentsPerColor = 3 +bytesPerComponent = 2 +bytesPerColor = componentsPerColor * bytesPerComponent +componentsPerPalette = colorsPerPalette * componentsPerColor +bytesPerPalette = componentsPerPalette * bytesPerComponent +encodedBlack = '\x00' * bytesPerColor +encodedWhite = (('\x00' * (bytesPerComponent - 1)) + ("%c" % maxComponentValue)) * componentsPerColor +decodedBlack = tuple([0 for x in range(componentsPerColor)]) +decodedWhite = tuple([maxComponentValue for x in range(componentsPerColor)]) +blackColorNum = 0 +whiteColorNum = colorsPerPalette - 1 +encodedBlackStart = blackColorNum * bytesPerColor +encodedBlackEnd = encodedBlackStart + bytesPerColor +encodedWhiteStart = whiteColorNum * bytesPerColor +encodedWhiteEnd = encodedWhiteStart + bytesPerColor +componentPrintFormat = "0x%1X" +arraynamePrefix = "amigaPalette" + +def isColor12Bit(color): + """Is the color 12-bit (i.e. 4 bits per color component)?""" + for component in color: + if not (0 <= component <= maxComponentValue): + return False + return True + +def printCommentLineList(lines): + """Prints list of lines inside a comment""" + if len(lines) > 0: + if len(lines) == 1: + print "// " + lines[0] + else: + print "/**" + for line in lines: + print " * " + line + print " */" + +def printColor(color, tabulate = True, printLastComma = True, newLine = True): + """Prints color with optional start tabulation, comma in the end and a newline""" + result = "" + if tabulate: + result += "\t" + for component in color[:-1]: + result += ((componentPrintFormat + ", ") % component) + result += (componentPrintFormat % color[-1]) + if printLastComma: + result += "," + if newLine: + print result + else: + print result, + +def printPalette(palette, filename, arrayname): + """Prints out palette as a C-style array""" + # Print comments about the palette + comments = ["A 16-color, 12-bit RGB palette from an Amiga AGI game."] + comments.append("Extracted from file " + os.path.basename(filename)) + printCommentLineList(comments) + + # Print the palette as a C-style array + print "static const unsigned char " + arrayname + "[] = {" + for color in palette[:-1]: + printColor(color) + printColor(palette[-1], printLastComma = False) + print("};") + +def isAmigaPalette(palette): + """Test if the given palette is an Amiga-style palette""" + # Palette must be of correct size + if len(palette) != colorsPerPalette: + return False + + # First palette color must be black and last palette color must be black + if palette[whiteColorNum] != decodedWhite or palette[blackColorNum] != decodedBlack: + return False + + # All colors must be 12-bit (i.e. 4 bits per color component) + for color in palette: + if not isColor12Bit(color): + return False + + # All colors must be unique + if len(set(palette)) != colorsPerPalette: + return False + + return True + +def preliminaryPaletteTest(data, pos): + """Preliminary test for a palette (For speed's sake).""" + # Test that palette's last color is white + if data[pos + encodedWhiteStart : pos + encodedWhiteEnd] != encodedWhite: + return False + # Test that palette's first color is black + if data[pos + encodedBlackStart : pos + encodedBlackEnd] != encodedBlack: + return False + return True + +def searchForAmigaPalettes(filename): + """Search file for Amiga AGI game palettes and return any found unique palettes""" + try: + file = None + foundPalettes = [] + # Open file and read it into memory + file = open(filename, 'rb') + data = file.read() + palette = [decodedBlack for x in range(colorsPerPalette)] + # Search through the whole file + for searchPosition in range(len(data) - bytesPerPalette + 1): + if preliminaryPaletteTest(data, searchPosition): + # Parse possible palette from byte data + for colorNum in range(colorsPerPalette): + colorStart = searchPosition + colorNum * bytesPerColor + colorEnd = colorStart + bytesPerColor + # Parse color components as unsigned 16-bit big endian integers + color = struct.unpack('>' + 'H' * componentsPerColor, data[colorStart:colorEnd]) + palette[colorNum] = color + # Save good candidates to a list + if isAmigaPalette(palette): + foundPalettes.append(tuple(palette)) + # Close source file and return unique found palettes + file.close() + return set(foundPalettes) + except IOError: + if file != None: + file.close() + return None + +# The main program starts here +if len(sys.argv) < 2 or sys.argv[1] == "-h" or sys.argv[1] == "--help": + quit("Usage: " + os.path.basename(sys.argv[0]) + " FILE [[FILE] ... [FILE]]\n" \ + " Searches all FILE parameters for Amiga AGI game palettes\n" \ + " and prints out any found candidates as C-style arrays\n" \ + " with sequentially numbered names (" + arraynamePrefix + "1, " + arraynamePrefix + "2 etc).\n" \ + " Supports wildcards.") + +# Get the list of filenames (Works with wildcards too) +filenameList = [] +for parameter in sys.argv[1:]: + filenameList.extend(glob.glob(parameter)) + +# Go through all the files and search for palettes +totalPalettesCount = 0 +if len(filenameList) > 0: + negativeFiles = [] + errorFiles = [] + for filename in filenameList: + foundPalettes = searchForAmigaPalettes(filename) + if foundPalettes == None: + errorFiles.append(filename) + elif len(foundPalettes) == 0: + negativeFiles.append(filename) + else: + # Print out the found palettes + for palette in foundPalettes: + # Print palettes with sequentially numbered array names + totalPalettesCount = totalPalettesCount + 1 + printPalette(palette, filename, arraynamePrefix + str(totalPalettesCount)) + print "" # Print an extra newline to separate things + # Print comment about files we couldn't find any palettes in + if len(negativeFiles) > 0: + comments = [] + comments.append("Couldn't find any palettes in the following files:") + comments.extend(negativeFiles) + printCommentLineList(comments) + print "" # Print an extra newline to separate things + # Print comment about errors handling files + if len(errorFiles) > 0: + comments = [] + comments.append("Error handling the following files:") + comments.extend(errorFiles) + printCommentLineList(comments) + print "" # Print an extra newline to separate things +else: + printCommentLineList(["No files found"]) diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp index ab2d8783fa..3596751ff1 100644 --- a/tools/create_kyradat/create_kyradat.cpp +++ b/tools/create_kyradat/create_kyradat.cpp @@ -39,6 +39,11 @@ enum { #include "towns.h" #include "amiga.h" +const Game kyra1FanTranslations[] = { + { kKyra1, IT_ITA, kTalkieVersion, "7a6887428c4847625db132a461cabbbf", kyra1FreCD }, + GAME_DUMMY_ENTRY +}; + bool extractRaw(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0); bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0); bool extractRooms(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0); @@ -718,6 +723,7 @@ const Game *gameDescs[] = { kyra1GerGames, kyra1TownsGames, kyra1AmigaGames, + kyra1FanTranslations, 0 }; diff --git a/tools/create_kyradat/md5.cpp b/tools/create_kyradat/md5.cpp index abdc002eb0..78af417171 100644 --- a/tools/create_kyradat/md5.cpp +++ b/tools/create_kyradat/md5.cpp @@ -226,7 +226,7 @@ bool md5_file(const char *name, uint8 digest[16], uint32 length) { f = fopen(name, "rb"); if (f == NULL) { - printf("md5_file couldn't open '%s'", name); + printf("md5_file couldn't open '%s'\n", name); return false; } diff --git a/tools/scumm-md5.txt b/tools/scumm-md5.txt index f97785cbe0..6db30d428d 100644 --- a/tools/scumm-md5.txt +++ b/tools/scumm-md5.txt @@ -204,6 +204,8 @@ monkey The Secret of Monkey Island 66fd5ff9a810dfeb6d6bdada18221140 -1 it DOS VGA VGA 4 disk Andrea Petrucci 45152f7cf2ba8f43cf8a8ea2e740ae09 8357 es DOS VGA VGA 4 disk Fingolfin + 8776caed014c321272af407c1502a2df 8955 en Mac CD - Mac v2.4 Petr Maruska (#1749232) + 2d1e891fe52df707c30185e52c50cd92 8955 en DOS CD CD CD-ROM v2.3 Fingolfin aa8a0cb65f3afbbe2c14c3f9f92775a3 8955 fr DOS CD CD CD-ROM v2.3 Fingolfin, Andrej Sinicyn, Andrea Petrucci 305d3dd57c96c65b017bc70c8c7cfb5e 8955 de DOS CD CD CD-ROM v2.3 Fingolfin @@ -212,6 +214,7 @@ monkey The Secret of Monkey Island 2ccd8891ce4d3f1a334d21bff6a88ca2 9455 en Mac CD - Mac v2.4 Fingolfin, Lars Næsbye Christensen b9ba19ce376efc69be78ef3baef8d2b9 -1 en Mac CD - alt? Grant Yeager c13225cb1bbd3bc9fe578301696d8021 -1 en SEGA SEGA - - + 057c9b456dedcc4d71b991a3072a20b3 9465 jp SEGA SEGA - - GloKidd 8eb84cee9b429314c7f0bdcf560723eb -1 en FM-TOWNS FM-TOWNS - - Paul Priest, Andrea Petrucci e17db1ddf91b39ca6bbc8ad3ed19e883 -1 jp FM-TOWNS FM-TOWNS - - Paul Priest, Andrea Petrucci @@ -390,6 +393,9 @@ SoccerMLS Backyard Soccer MLS Edition Soccer2004 Backyard Soccer 2004 c4ffae9fac495475d6bc3343ccc8faf9 -1 en All - - - Kirben, sev +brstorm Bear Stormin' + 07a1eefd8ca95d77310311446c0f53d0 5433 en All - Demo - sev + thinker1 Big Thinkers First Grade 5c21fc49aee8f46e58fef21579e614a1 -1 us All - - - Kirben @@ -427,6 +433,7 @@ fbear Fatty Bear's Birthday Surprise fbpack Fatty Bear's Fun Pack e01acc8c12ef44e8f778fe87e5f90f4e -1 en 3DO - - - sev + c9717ee6059f1e43b768b464493d2fba -1 jp 3DO - - - clone2727 f06e66fd45b2f8b0f4a2833ff4476050 -1 hb DOS - - - sev freddi Freddi Fish 1: The Case of the Missing Kelp Seeds |