From fa64a064a1c583d75e1f64dabbe4cda83aa02c5b Mon Sep 17 00:00:00 2001 From: antoniou79 Date: Wed, 2 Jan 2019 14:00:45 +0200 Subject: DEVTOOLS: Script code cleanup All scripts got better info and debug messages. Also improved the --trace switch for all scripts and fixed some code formatting issues. --- devtools/create_bladerunner/subtitles/README.md | 2 +- .../subtitles/fontCreator/fonFileLib.py | 70 ++-- .../subtitles/fontCreator/fontCreator.py | 2 +- .../subtitles/fontCreator/grabberFromPNG17BR.py | 448 +++++++++++---------- .../mixResourceCreator/mixResourceCreator.py | 2 +- .../packBladeRunnerMIXFromPCTLKXLS04.py | 332 ++++++++------- .../quotesSpreadsheetCreator/audFileDecode.py | 28 +- .../quotesSpreadsheetCreator/audFileLib.py | 75 ++-- .../quoteSpreadsheetCreator.py | 2 +- .../sortBladeRunnerWavs02.py | 242 +++++------ .../quotesSpreadsheetCreator/treFileLib.py | 52 ++- 11 files changed, 689 insertions(+), 566 deletions(-) (limited to 'devtools') diff --git a/devtools/create_bladerunner/subtitles/README.md b/devtools/create_bladerunner/subtitles/README.md index a285756ac7..7f7651c7f6 100644 --- a/devtools/create_bladerunner/subtitles/README.md +++ b/devtools/create_bladerunner/subtitles/README.md @@ -13,7 +13,7 @@ https://docs.google.com/spreadsheets/d/17ew0YyhSwqcqZg6bXrIgz0GkA62dhgViHN15lOu5 4. Create a configureFontsTranslation.txt in the sampleInput folder. A configuration file for the MIX file creation. A sample is provided in the sampleInput folder and documentation about this is below in this document (see "text configuration file" in mixResourceCreator). 5. From the ScummVM root folder run: ``` - make devtools/create_bladerunner/subtitles +make devtools/create_bladerunner/subtitles ``` 6. Copy the output file "SUBTITLES.MIX", created in the ScummVM root folder, into your Blade Runner game directory. 7. Launch the Blade Runner game using ScummVM. diff --git a/devtools/create_bladerunner/subtitles/fontCreator/fonFileLib.py b/devtools/create_bladerunner/subtitles/fontCreator/fonFileLib.py index 0b76a1478c..d40efc6e29 100644 --- a/devtools/create_bladerunner/subtitles/fontCreator/fonFileLib.py +++ b/devtools/create_bladerunner/subtitles/fontCreator/fonFileLib.py @@ -10,31 +10,31 @@ imagePilLibFound = False try: import shutil except ImportError: - print "Error:: Shutil python library is required to be installed!" + print "[Error] Shutil python library is required to be installed!" else: shutilLibFound = True try: import struct except ImportError: - print "Error:: struct python library is required to be installed!" + print "[Error] struct python library is required to be installed!" else: structLibFound = True try: import Image except ImportError: - print "Error:: Image python library (PIL) is required to be installed!" + print "[Error] Image python library (PIL) is required to be installed!" else: imagePilLibFound = True if (not shutilLibFound) or (not structLibFound) or (not imagePilLibFound): - sys.stdout.write("Error:: Errors were found when trying to import required python libraries\n") + sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n") sys.exit(1) from struct import * -my_module_version = "0.50" +my_module_version = "0.80" my_module_name = "fonFileLib" @@ -51,26 +51,29 @@ class FonHeader: class fonFile: m_header = FonHeader() - simpleFontFileName = "GENERIC.FON" + simpleFontFileName = 'GENERIC.FON' realNumOfCharactersInImageSegment = 0 # this is used for the workaround for the corrupted TAHOME18.FON nonEmptyCharacters = 0 glyphDetailEntriesLst = [] # list of 5-value tuples. Tuple values are (X-offset, Y-offset, Width, Height, Offset in Graphics segment) glyphPixelData = None # buffer of pixel data for glyphs - def __init__(self): + m_traceModeEnabled = False + + # traceModeEnabled is bool to enable more printed debug messages + def __init__(self, traceModeEnabled = True): del self.glyphDetailEntriesLst[:] self.glyphPixelData = None # buffer of pixel data for glyphs - self.simpleFontFileName = "GENERIC.FON" + self.simpleFontFileName = 'GENERIC.FON' self.realNumOfCharactersInImageSegment = 0 # this is used for the workaround for the corrupted TAHOME18.FON self.nonEmptyCharacters = 0 + self.m_traceModeEnabled = traceModeEnabled return def loadFonFile(self, fonBytesBuff, maxLength, fonFileName): self.simpleFontFileName = fonFileName - offsInFonFile = 0 localLstOfDataOffsets = [] del localLstOfDataOffsets[:] @@ -84,7 +87,8 @@ class fonFile: if self.simpleFontFileName == 'TAHOMA18.FON': # deal with corrupted original 'TAHOMA18.FON' file self.realNumOfCharactersInImageSegment = 176 - print "SPECIAL CASE. WORKAROUND FOR CORRUPTED %s FILE. Only %d characters supported!" % (self.simpleFontFileName, self.realNumOfCharactersInImageSegment) + if self.m_traceModeEnabled: + print "[Debug] SPECIAL CASE. WORKAROUND FOR CORRUPTED %s FILE. Only %d characters supported!" % (self.simpleFontFileName, self.realNumOfCharactersInImageSegment) else: self.realNumOfCharactersInImageSegment = self.header().maxEntriesInTableOfDetails @@ -100,15 +104,16 @@ class fonFile: self.header().graphicSegmentByteSize = tmpTuple[0] offsInFonFile += 4 - print "FON Header Info: " - print "Num of entries: %d\tGlyph max-Width: %d\tGlyph max-Height: %d\tGraphic Segment size %d" % (self.header().maxEntriesInTableOfDetails, self.header().maxGlyphWidth, self.header().maxGlyphHeight, self.header().graphicSegmentByteSize) - #print "Num of entries: %d\tGlyph max-Width: %d\tGlyph max-Height: %d\tGraphic Segment size %d" % (self.realNumOfCharactersInImageSegment, self.header().maxGlyphWidth, self.header().maxGlyphHeight, self.header().graphicSegmentByteSize) + if self.m_traceModeEnabled: + print "[Debug] Font file (FON) Header Info: " + print "[Debug] Number of entries: %d, Glyph max-Width: %d, Glyph max-Height: %d, Graphic Segment size: %d" % (self.header().maxEntriesInTableOfDetails, self.header().maxGlyphWidth, self.header().maxGlyphHeight, self.header().graphicSegmentByteSize) # # Glyph details table (each entry is 5 unsigned integers == 5*4 = 20 bytes) # For most characters, their ASCII value + 1 is the index of their glyph's entry in the details table. The 0 entry of this table is reserved # #tmpXOffset, tmpYOffset, tmpWidth, tmpHeight, tmpDataOffset - print "FON glyph details table: " + if self.m_traceModeEnabled: + print "[Debug] Font file (FON) glyph details table: " for idx in range(0, self.realNumOfCharactersInImageSegment): tmpTuple = struct.unpack_from('i', fonBytesBuff, offsInFonFile) # unsigned integer 4 bytes tmpXOffset = tmpTuple[0] @@ -131,15 +136,18 @@ class fonFile: offsInFonFile += 4 if tmpWidth == 0 or tmpHeight == 0: - print "Index: %d\t UNUSED *****************************************************************" % (idx) + if self.m_traceModeEnabled: + print "Index: %d\t UNUSED *****************************************************************" % (idx) else: self.nonEmptyCharacters += 1 - print "Index: %d\txOffs: %d\tyOffs: %d\twidth: %d\theight: %d\tdataOffs: %d" % (idx, tmpXOffset, tmpYOffset, tmpWidth, tmpHeight, tmpDataOffset) + if self.m_traceModeEnabled: + print "Index: %d\txOffs: %d\tyOffs: %d\twidth: %d\theight: %d\tdataOffs: %d" % (idx, tmpXOffset, tmpYOffset, tmpWidth, tmpHeight, tmpDataOffset) if tmpDataOffset not in localLstOfDataOffsets: localLstOfDataOffsets.append(tmpDataOffset) else: # This never happens in the original files. Offsets are "re-used" but not really because it happens only for empty (height = 0) characters which all seem to point to the next non-empty character - print "Index: %d\t RE-USING ANOTHER GLYPH *****************************************************************" % (idx) + if self.m_traceModeEnabled: + print "Index: %d\t RE-USING ANOTHER GLYPH *****************************************************************" % (idx) self.glyphDetailEntriesLst.append( ( tmpXOffset, tmpYOffset, tmpWidth, tmpHeight, tmpDataOffset) ) @@ -147,11 +155,13 @@ class fonFile: self.glyphPixelData = fonBytesBuff[offsInFonFile:] return True except: - print "Loading failure!" + print "[Error] Loading Font file (FON) %s failed!" % (self.simpleFontFileName) raise return False def outputFonToPNG(self): + print "[Info] Exporting font file (FON) to PNG: %s" % (self.simpleFontFileName + ".PNG") + targWidth = 0 targHeight = 0 paddingFromTopY = 2 @@ -159,7 +169,7 @@ class fonFile: if len(self.glyphDetailEntriesLst) == 0 or (len(self.glyphDetailEntriesLst) != self.realNumOfCharactersInImageSegment and len(self.glyphDetailEntriesLst) != self.header().maxEntriesInTableOfDetails) : - print "Error. Fon file load process did not complete correctly. Missing important data in structures. Cannot output image!" + print "[Error] Font file (FON) loading process did not complete correctly. Missing important data in structures. Cannot output image!" return # TODO asdf refine this code here. the dimensions calculation is very crude for now @@ -202,7 +212,7 @@ class fonFile: glyphDataOffs += 2 # if pixelColor > 0x8000: -# print "WEIRD CASE" # NEVER HAPPENS - TRANSPARENCY IS ON/OFF. There's no grades of transparency +# print "[Debug] WEIRD CASE" # NEVER HAPPENS - TRANSPARENCY IS ON/OFF. There's no grades of transparency rgbacolour = (0,0,0,0) if pixelColor == 0x8000: rgbacolour = (0,0,0,0) # alpha: 0.0 fully transparent @@ -219,9 +229,11 @@ class fonFile: imTargetGameFont.putpixel(( (drawIdx + 1) * (self.header().maxGlyphWidth + paddingBetweenGlyphsX ) + currX, paddingFromTopY + glyphYoffs + currY), rgbacolour) currX += 1 - - imTargetGameFont.save(os.path.join('.', self.simpleFontFileName + ".PNG"), "PNG") - + try: + imTargetGameFont.save(os.path.join('.', self.simpleFontFileName + ".PNG"), "PNG") + except Exception as e: + print '[Error] Unable to write to output PNG file. ' + str(e) + def header(self): return self.m_header # @@ -229,7 +241,7 @@ class fonFile: # if __name__ == '__main__': # main() - print "Running %s as main module" % (my_module_name) + print "[Debug] Running %s as main module" % (my_module_name) # assumes a file of name TAHOMA24.FON in same directory inFONFile = None #inFONFileName = 'TAHOMA24.FON' # USED IN CREDIT END-TITLES and SCORERS BOARD AT POLICE STATION @@ -240,22 +252,22 @@ if __name__ == '__main__': errorFound = False try: - print "Opening %s" % (inFONFileName) + print "[Info] Opening %s" % (inFONFileName) inFONFile = open(os.path.join('.',inFONFileName), 'rb') except: errorFound = True - print "Unexpected error:", sys.exc_info()[0] + print "[Error] Unexpected event:", sys.exc_info()[0] raise if not errorFound: allOfFonFileInBuffer = inFONFile.read() fonFileInstance = fonFile() if (fonFileInstance.loadFonFile(allOfFonFileInBuffer, len(allOfFonFileInBuffer), inFONFileName)): - print "FON file loaded successfully!" + print "[Info] Font file (FON) was loaded successfully!" fonFileInstance.outputFonToPNG() else: - print "Error while loading FON file!" + print "[Error] Error while loading Font file (FON)!" inFONFile.close() else: #debug - #print "Running %s imported from another module" % (my_module_name) + #print "[Debug] Running %s imported from another module" % (my_module_name) pass \ No newline at end of file diff --git a/devtools/create_bladerunner/subtitles/fontCreator/fontCreator.py b/devtools/create_bladerunner/subtitles/fontCreator/fontCreator.py index 2618ec04d6..4bac040f82 100644 --- a/devtools/create_bladerunner/subtitles/fontCreator/fontCreator.py +++ b/devtools/create_bladerunner/subtitles/fontCreator/fontCreator.py @@ -2,7 +2,7 @@ # -*- coding: UTF-8 -*- import sys if not (sys.version_info[0] == 2 and sys.version_info[1] == 7): - sys.stdout.write("Error:: Blade Runner Font Creator script requires Python 2.7\n") + sys.stdout.write("[Error] Blade Runner Font Creator script requires Python 2.7\n") sys.exit(1) import grabberFromPNG17BR diff --git a/devtools/create_bladerunner/subtitles/fontCreator/grabberFromPNG17BR.py b/devtools/create_bladerunner/subtitles/fontCreator/grabberFromPNG17BR.py index 3f8a7b4bb4..4fad7f4f8a 100644 --- a/devtools/create_bladerunner/subtitles/fontCreator/grabberFromPNG17BR.py +++ b/devtools/create_bladerunner/subtitles/fontCreator/grabberFromPNG17BR.py @@ -77,51 +77,51 @@ reLibFound = False try: import shutil except ImportError: - print "Error:: Shutil python library is required to be installed!" + print "[Error] Shutil python library is required to be installed!" else: shutilLibFound = True try: import struct except ImportError: - print "Error:: struct python library is required to be installed!" + print "[Error] struct python library is required to be installed!" else: structLibFound = True try: import Image except ImportError: - print "Error:: Image python library (PIL) is required to be installed!" + print "[Error] Image python library (PIL) is required to be installed!" else: imagePilLibFound = True try: import re except ImportError: - print "Error:: re (Regular expression operations) python library is required to be installed!" + print "[Error] re (Regular expression operations) python library is required to be installed!" else: reLibFound = True if (not shutilLibFound) or (not structLibFound) or (not imagePilLibFound) or (not reLibFound): - sys.stdout.write("Error:: Errors were found when trying to import required python libraries\n") + sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n") sys.exit(1) from os import walk, errno, path from struct import * from fonFileLib import * -company_email = "classic.adventures.in.greek@gmail.com" -app_version = "0.70" -app_name = "grabberFromPNGHHBR" -app_wrapper_name = "fontCreator.py" -app_name_spaced = "Blade Runner Font Creator/Extractor" -app_short_desc = "Extract or create Font Files (.FON) for Blade Runner" +COMPANY_EMAIL = "classic.adventures.in.greek@gmail.com" +APP_VERSION = "0.80" +APP_NAME = "grabberFromPNGHHBR" +APP_WRAPPER_NAME = "fontCreator.py" +APP_NAME_SPACED = "Blade Runner Font Creator/Exporter" +APP_SHORT_DESC = "Create Font Files (.FON) or export existing FON files to PNG images." -traceModeEnabled = False - -supportedMIXInputFiles = ['STARTUP.MIX'] +SUPPORTED_MIX_INPUT_FILES = ['STARTUP.MIX'] ## 4 font files -supportedExportedFONFiles = ['10PT.FON', 'TAHOMA18.FON', 'TAHOMA24.FON', 'KIA6PT.FON'] +SUPPORTED_EXPORTED_GAME_FON_FILES = ['10PT.FON', 'TAHOMA18.FON', 'TAHOMA24.FON', 'KIA6PT.FON'] + +gTraceModeEnabled = False def calculateFoldHash(strFileName): i = 0 @@ -141,7 +141,8 @@ def calculateFoldHash(strFileName): groupSum |= 0 hash = ((hash << 1) | ((hash >> 31) & 1)) + groupSum hash &= 0xFFFFFFFF # mask here! - #print (strParam +': ' +''.join('{:08X}'.format(hash))) + #if gTraceModeEnabled: + # print '[Debug] ' + (strParam +': ' +''.join('{:08X}'.format(hash))) return hash class grabberFromPNG: @@ -167,21 +168,21 @@ class grabberFromPNG: autoTabCalculation = True reconstructEntireFont = False # TODO: TRUE!!! - minSpaceBetweenLettersInRowLeftToLeft =0 + minSpaceBetweenLettersInRowLeftToLeft = 0 minSpaceBetweenLettersInColumnTopToTop = 0 kerningForFirstDummyFontLetter = 0 yOffsetForAllGlyphsExceptFirstSpecialGamma = 0 -# deductKerningPixels = 0 + #deductKerningPixels = 0 inputFonMixPath = "" targetFONFilename = BR_DefaultFontFileName -# origFontFilename="" + #origFontFilename ="" origFontPropertiesTxt = "" -# imageOriginalPNG="" - imageRowFilePNG="" - copyFontFileName="" + #imageOriginalPNG ="" + imageRowFilePNG ="" + copyFontFileName ="" copyFontPropertiesTxt = "" - copyPNGFileName="" + copyPNGFileName ="" lettersFound = 0 listOfBaselines = [] @@ -201,7 +202,7 @@ class grabberFromPNG: listOfWidthIncrements = [] listOfOutOfOrderGlyphs = [] - targetLangOrderAndListOfForeignLettersAsciiValues= None + targetLangOrderAndListOfForeignLettersAsciiValues = None def initOverrideEncoding(self): ## @@ -215,25 +216,26 @@ class grabberFromPNG: overrideEncodingTextFile = u'overrideEncoding.txt' relPath = u'.' self.overrideEncodingPath = os.path.join(relPath,overrideEncodingTextFile) - print "Warning:: Font Creation Override Encoding file not found in arguments. Attempting to open local file %s if it exists" % (overrideEncodingTextFile) + print "[Warning] Font Creation Override Encoding file not found in arguments. Attempting to open local file %s, if it exists" % (overrideEncodingTextFile) if os.access(self.overrideEncodingPath, os.F_OK): - ## debug - #print "Override encoding file found: {0}.".format(self.overrideEncodingPath) + print "[Info] Override encoding file found: {0}.".format(self.overrideEncodingPath) overEncodFile = open(self.overrideEncodingPath, 'r') linesLst = overEncodFile.readlines() overEncodFile.close() if linesLst is None or len(linesLst) == 0: overrideFailed = True else: - print "Override Encoding Info: " + if gTraceModeEnabled: + print "[Debug] Parsing Override Encoding file info..." involvedTokensLst =[] del involvedTokensLst[:] # unneeded for readEncodLine in linesLst: tmplineTokens = re.findall("[^\t\n]+",readEncodLine ) for x in tmplineTokens: involvedTokensLst.append(x) - # print involvedTokensLst + #if gTraceModeEnabled: + # print "[Debug] ", involvedTokensLst #break #only read first line for tokenNameKeyPair in involvedTokensLst: nameKeyTupl = tokenNameKeyPair.split('=', 1) @@ -276,12 +278,12 @@ class grabberFromPNG: if not (self.targetEncoding is None or not self.targetEncoding or targetLangOrderAndListOfForeignLettersStrUnicode is None or len(targetLangOrderAndListOfForeignLettersStrUnicode) == 0 or self.originalFontName is None or not self.originalFontName): overrideFailed = False - print "Info:: Target Encoding: " , self.targetEncoding - #print "Lang Order: " , targetLangOrderAndListOfForeignLettersStrUnicode - if traceModeEnabled: - print "Explicit Kern List: " , self.listOfExplicitKerning - print "Explicit Width Increment List: " , self.listOfWidthIncrements - print "Info:: Original Font Name: " , self.originalFontName + if gTraceModeEnabled: + print "[Debug] Target Encoding: ", self.targetEncoding + #print "[Debug] Lang Order: ", targetLangOrderAndListOfForeignLettersStrUnicode + print "[Debug] Explicit Kern List: ", self.listOfExplicitKerning + print "[Debug] Explicit Width Increment List: ", self.listOfWidthIncrements + print "[Debug] Original Font Name: ", self.originalFontName if(len(self.listOfOutOfOrderGlyphs) == 0 and self.specialGlyphMode == True): # Just keep those that are needed @@ -293,51 +295,49 @@ class grabberFromPNG: elif self.originalFontName == 'TAHOMA': # treat TAHOMA18 and TAHOMA24 similarily here self.listOfOutOfOrderGlyphs.append((u'\xe9', u'\u0192')) # french e punctuated self.listOfOutOfOrderGlyphs.append((u'\xfc', u'\u2013')) # u umlaut - if traceModeEnabled: - print "Info:: Explicit Out Of Order Glyphs List: " , self.listOfOutOfOrderGlyphs + if gTraceModeEnabled: + print "[Debug] Explicit Out Of Order Glyphs List: " , self.listOfOutOfOrderGlyphs else: - ## debug - print "Error: Override encoding file not found: {0}.".format(self.overrideEncodingPath) - #print "Override encoding file not found: {0}.".format(self.overrideEncodingFileRelPath) - #print "To override the default encoding {0} use an override encoding file with two tab separated entries: encoding (ascii) and characters-list. Convert to UTF-8 without BOM and save. For example:".format(defaultTargetEncoding) - #print "windows-1252\t!!\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}" + ## error + print "[Error] Override encoding file not found: {0}.".format(self.overrideEncodingPath) pass if overrideFailed: - ## debug - print "Override encoding file FAILED-1." #" Initializing for {0}...".format(defaultTargetLang) - # self.targetEncoding = self.defaultTargetEncoding - # self.targetEncodingUnicode = self.defaultTargetEncodingUnicode - # targetLangOrderAndListOfForeignLettersStrUnicode = unicode(allOfGreekChars, 'utf-8') - # #print targetLangOrderAndListOfForeignLettersStrUnicode + ## error + print "[Error] Override encoding file parsing has failed: Error Code 1." #" Initializing for {0}...".format(defaultTargetLang) + #if gTraceModeEnabled: + # self.targetEncoding = self.defaultTargetEncoding + # self.targetEncodingUnicode = self.defaultTargetEncodingUnicode + # targetLangOrderAndListOfForeignLettersStrUnicode = unicode(allOfGreekChars, 'utf-8') + # print '[Debug] ', targetLangOrderAndListOfForeignLettersStrUnicode sys.exit() # terminate if override Failed (Blade Runner) try: targetLangOrderAndListOfForeignLettersStr = unicode.encode("%s" % targetLangOrderAndListOfForeignLettersStrUnicode, self.targetEncoding) except: - ## debug - print "Override encoding file FAILED-2." #"Initializing for {0}...".format(defaultTargetLang) - # self.targetEncoding = self.defaultTargetEncoding - # self.targetEncodingUnicode = self.defaultTargetEncodingUnicode - # targetLangOrderAndListOfForeignLettersStrUnicode = unicode(allOfGreekChars, 'utf-8') - # targetLangOrderAndListOfForeignLettersStr = unicode.encode("%s" % targetLangOrderAndListOfForeignLettersStrUnicode, self.targetEncoding) - # #print targetLangOrderAndListOfForeignLettersStrUnicode + ## error + print "[Error] Override encoding file parsing has failed: Error Code 2." #"Initializing for {0}...".format(defaultTargetLang) + #if gTraceModeEnabled: + # self.targetEncoding = self.defaultTargetEncoding + # self.targetEncodingUnicode = self.defaultTargetEncodingUnicode + # targetLangOrderAndListOfForeignLettersStrUnicode = unicode(allOfGreekChars, 'utf-8') + # targetLangOrderAndListOfForeignLettersStr = unicode.encode("%s" % targetLangOrderAndListOfForeignLettersStrUnicode, self.targetEncoding) + # print '[Debug] ' + targetLangOrderAndListOfForeignLettersStrUnicode sys.exit() # terminate if override Failed (Blade Runner) targetLangOrderAndListOfForeignLetters = list(targetLangOrderAndListOfForeignLettersStr) - if traceModeEnabled: - print targetLangOrderAndListOfForeignLetters, len(targetLangOrderAndListOfForeignLetters) # new + if gTraceModeEnabled: + print '[Debug] ', targetLangOrderAndListOfForeignLetters, len(targetLangOrderAndListOfForeignLetters) # new self.targetLangOrderAndListOfForeignLettersAsciiValues = [ord(i) for i in targetLangOrderAndListOfForeignLetters] - if traceModeEnabled: - print self.targetLangOrderAndListOfForeignLettersAsciiValues, len(self.targetLangOrderAndListOfForeignLettersAsciiValues) + if gTraceModeEnabled: + print '[Debug] ', self.targetLangOrderAndListOfForeignLettersAsciiValues, len(self.targetLangOrderAndListOfForeignLettersAsciiValues) self.maxAsciiValueInEncoding = max(self.targetLangOrderAndListOfForeignLettersAsciiValues) - -# for charAsciiValue in targetLangOrderAndListOfForeignLetters: -# print "Ord of chars: %d" % ord(charAsciiValue) - - ## - ## END OF INIT CODE - ## + #if gTraceModeEnabled: + # for charAsciiValue in targetLangOrderAndListOfForeignLetters: + # print "[Debug] Ord of chars: %d" % ord(charAsciiValue) +## +## END OF INIT CODE +## # # TODO: warning: assumes that there is a margin on top and bellow the letters @@ -350,7 +350,7 @@ class grabberFromPNG: self.kerningForFirstDummyFontLetter = 0 self.yOffsetForAllGlyphsExceptFirstSpecialGamma = 0 self.spaceWidthInPixels = self.defaultSpaceWidthInPixelsConst -# self.deductKerningPixels = 0 + #self.deductKerningPixels = 0 self.reconstructEntireFont = False # TODO : True? #self.origFontFilename=porigFontFilename self.inputFonMixPath = "" @@ -365,8 +365,7 @@ class grabberFromPNG: self.origFontPropertiesTxt = "" self.copyFontPropertiesTxt = "" self.cleanup() # for good practice (this should not be here, but it's here too due to quick/sloppy :) coding (TODO: fix it) - #debug - #self.DBinit() # TODO REMOVE? + # if pselectedEncoding == None: pselectedEncoding = self.targetEncoding @@ -374,13 +373,6 @@ class grabberFromPNG: self.activeEncoding = pselectedEncoding self.lettersInOriginalFontFile = 0 #initialization - # TODO: we should get from the DB the encoding and lettersString - # and the Empty slots for the selected Game and Calculate the rest of - # the lists/dictionaries on the fly. - # IF no lettersString or encoding has been defined... - # then issue error? or continue with hard-coded - # (insert to db as well and inform the GUI?) - #self.calcFromDB() # TODO REMOVE? return @@ -396,8 +388,8 @@ class grabberFromPNG: del self.properListOfLetterBoxes[:] del self.listOfXOffsets[:] # new for Blade Runner support del self.listOfYOffsets[:] # new for Blade Runner support -# del self.listOfExplicitKerning[:] # don't clean these up -# del self.listOfWidthIncrements[:] # don't clean these up + #del self.listOfExplicitKerning[:] # don't clean these up + #del self.listOfWidthIncrements[:] # don't clean these up self.origFontPropertiesTxt = "" self.copyFontPropertiesTxt = "" @@ -433,9 +425,9 @@ class grabberFromPNG: self.yOffsetForAllGlyphsExceptFirstSpecialGamma = pYOffsetForAllGlyphsExceptFirstSpecialGamma return -# def setDeductKerningPixels(self, pDeductKerningPixels): -# self.deductKerningPixels = pDeductKerningPixels -# return + #def setDeductKerningPixels(self, pDeductKerningPixels): + # self.deductKerningPixels = pDeductKerningPixels + # return def setSpaceWidthInPixels(self, pSpaceWidthInPixels): self.spaceWidthInPixels = pSpaceWidthInPixels @@ -475,16 +467,18 @@ class grabberFromPNG: for y in range(0, imheight): # we search all rows (for each column) r1,g1,b1,a1 = loadedImag[x, y] if a1 != 0: # if pixel not completely transparent -- this is not necessarily the *top* left pixel of a font letter though! -- the startRow is still to be determined. - # print loadedImag[x, y] + #if gTraceModeEnabled: + # print "[Debug] ", loadedImag[x, y] if prevColStartForLetter == 0: prevColStartForLetter = x prevRowStartForLetter = y startCol = x - # print "Letter found" - # print "start col:%d" % startCol - # # print "hypothe row:%d" % y - # # starting from the first row of the row-image (to do optimize), we parse by rows to find the top point (row coordinate) of the character font - # for y2 in range(0, y+1): + #if gTraceModeEnabled: + # print "[Debug] Letter found." + # print "[Debug] Start col: %d" % startCol + ## print "[Debug] hypothetical row: %d" % y + # starting from the first row of the row-image (to do optimize), we parse by rows to find the top point (row coordinate) of the character font + #for y2 in range(0, y+1): tmpSum = y + self.minSpaceBetweenLettersInColumnTopToTop scanToRow = imheight # - explicitly set this to the whole image height -- assumes only one row of character fonts if tmpSum < imheight: # TODO: WAS scanToRow < imheight but this doesn't get executed anymore due to explicitly setting scanToRow to imheight (assuming only one row of character fonts) @@ -497,13 +491,16 @@ class grabberFromPNG: scanToCol = imwidth if tmpSum < imwidth: scanToCol = tmpSum - #print (startCol, scanToCol) + #if gTraceModeEnabled: + # print "[Debug] ", (startCol, scanToCol) for x2 in range(startCol, scanToCol): # check all columns (for each row) - #print loadedImag[x2, y2] + #if gTraceModeEnabled: + # print "[Debug] ", loadedImag[x2, y2] r2,g2,b2,a2 = loadedImag[x2, y2] if a2 != 0 and startRow == 0: startRow = y2 + trimTopPixels - # print "start row: %d" % startRow + #if gTraceModeEnabled: + # print "[Debug] Start row: %d" % startRow break if startCol > 0 and startRow > 0: # WARNING: TODO NOTE: SO NEVER HAVE AN INPUT IMAGE WHERE THE FONT CHARACTERS ARE TOUCHING THE TOP OF THE IMAGE WITH NO EMPTY SPACE WHATSOEVER tmpSum = startRow + self.minSpaceBetweenLettersInColumnTopToTop @@ -521,7 +518,8 @@ class grabberFromPNG: endRow = y if endRow > 0: endRow = endRow - trimBottomPixels - # print "end row:% d" %endRow + #if gTraceModeEnabled: + # print "[Debug] End row: %d" % endRow if startCol > 0 and startRow > 0 and endRow > 0: tmpSum = startCol + self.minSpaceBetweenLettersInRowLeftToLeft @@ -534,7 +532,8 @@ class grabberFromPNG: #print loadedImag[x, y] if a1 != 0: endCol = x - # print "end col:% d" %endCol + #if gTraceModeEnabled: + # print "[Debug] End col: %d" % endCol if startCol > 0 and startRow > 0 and endRow > 0 and endCol > 0: # append deducted baseline # @@ -543,31 +542,33 @@ class grabberFromPNG: else: # firstDoubleLetterIgnore == False if self.autoTabCalculation == True: if self.tabSpaceWidth == 0: - #print "start startPre", startCol, self.startColOfPrevFontLetter + #if gTraceModeEnabled: + # print "[Debug] start startPre: ", startCol, self.startColOfPrevFontLetter self.tabSpaceWidth = startCol - self.startColOfPrevFontLetter - if traceModeEnabled: - print "Tab Space Width detected: %d " % (self.tabSpaceWidth) + if gTraceModeEnabled: + print "[Debug] Tab Space Width detected: %d " % (self.tabSpaceWidth) # new if -- don't use else here, to include the case of when we first detected the tab space width if self.tabSpaceWidth > 0: self.listOfXOffsets.append(startCol - (self.startOfAllLettersIncludingTheExtraDoubleAndWithKern + (self.lettersFound + 1) * self.tabSpaceWidth) ) # + self.deductKerningPixels ) - #print "xOffSet", startCol - (self.startOfAllLettersIncludingTheExtraDoubleAndWithKern + (self.lettersFound + 1) * self.tabSpaceWidth) + #if gTraceModeEnabled: + # print "[Debug] xOffSet: ", startCol - (self.startOfAllLettersIncludingTheExtraDoubleAndWithKern + (self.lettersFound + 1) * self.tabSpaceWidth) else: self.listOfXOffsets.append(0) - - - + + self.listOfBaselines.append(endRow) self.listOfWidths.append(endCol-startCol + 1) # includes the last col (TODO this was without the +1 for MI:SE translator -- possible bug? did we compensate?) self.listOfHeights.append(endRow - startRow + 1) # +1 includes the last row self.listOfLetterBoxes.append((startCol, startRow, endCol, endRow)) - + self.startColOfPrevFontLetter = startCol #update for next pass #delete the letter - even in the case of ignoring the first double letter for x in range(startCol, endCol+1): for y in range(startRow - trimTopPixels, endRow+1 + trimBottomPixels): loadedImag[x, y] = 0, 0, 0, 0 return 0 - else: return -1 + else: + return -1 # # # @@ -594,7 +595,7 @@ class grabberFromPNG: interLetterSpacingInPNG = 4 origGameFontSizeEqBaseLine = 0 # offset for start of PNG index table -# firstTableLineOffset = self.PNG_TABLE_STARTLINE_OFFSET + #firstTableLineOffset = self.PNG_TABLE_STARTLINE_OFFSET lettersInOriginalFontFile = self.lettersInOriginalFontFile # # detection of origGameFontSizeEqBaseLine @@ -602,9 +603,11 @@ class grabberFromPNG: #origGameFontSizeEqBaseLine = self.findDetectedBaseline() ## NEW BR REMOVED self.cleanup() # necessary after detection of baseline, because it fills up some of the lists used in the following! -## self.origFontPropertiesTxt = self.getImagePropertiesInfo(True) # "%dx%dx%s" % (im.size[0],im.size[1], im.mode) # NEW REMOVED -# print "WEEEE::: ", self.imageOriginalPNG, im.format, "%dx%d" % im.size, im.mode -# print "BASELINE DETECTED:%d " % origGameFontSizeEqBaseLine + ##self.origFontPropertiesTxt = self.getImagePropertiesInfo(True) # "%dx%dx%s" % (im.size[0],im.size[1], im.mode) # NEW REMOVED + # + #if gTraceModeEnabled: + # print "[Debug] WEEEE::: ", self.imageOriginalPNG, im.format, "%dx%d" % im.size, im.mode + # print "[Debug] BASELINE DETECTED: %d " % origGameFontSizeEqBaseLine # # OPEN THE IMAGE WITH THE ROW OF CHARACTER FONTS TO BE IMPORTED @@ -613,18 +616,19 @@ class grabberFromPNG: try: im = Image.open(self.imageRowFilePNG) except: - errMsg = "No letters were found in input png - IO exception!" + errMsg = "[Error] No letters were found in input png - IO exception!" print errMsg retVal = -2 errorFound = True else: - errMsg = "No letters were found in input png - IO fault!" + errMsg = "[Error] No letters were found in input png - IO fault!" print errMsg retVal = -2 errorFound = True if not errorFound: #debug - #print self.imageRowFilePNG, im.format, "%dx%d" % im.size, im.mode + #if gTraceModeEnabled: + # print "[Debug] ", self.imageRowFilePNG, im.format, "%dx%d" % im.size, im.mode w1, h1 = im.size trimTopPixels = 0 trimBottomPixels = 0 @@ -633,7 +637,7 @@ class grabberFromPNG: # TODO the special settings for handling italic native letters should be in the settings(?) filepathSplitTbl = os.path.split(self.imageRowFilePNG) sFilenameOnlyImageRowFilePNG = filepathSplitTbl[1] - print "Info:: Parsing input Font glyphs image %s. Please wait..." % (sFilenameOnlyImageRowFilePNG) + print "[Info] Parsing input Font glyphs image %s. Please wait..." % (sFilenameOnlyImageRowFilePNG) if sFilenameOnlyImageRowFilePNG.startswith("itcrp_") or sFilenameOnlyImageRowFilePNG.startswith("it_"): italicsMode = True @@ -641,40 +645,43 @@ class grabberFromPNG: if sFilenameOnlyImageRowFilePNG.startswith("itcrp_"): trimTopPixels = 1 trimBottomPixels = 1 - if traceModeEnabled: - print "Will trim upper line by %d pixels and bottom line by %d pixels" % (trimTopPixels, trimBottomPixels) + print "[Info] Mode Enabled: Trim upper line by %d pixels and bottom line by %d pixels." % (trimTopPixels, trimBottomPixels) pix = im.load() # pix argument is mutable (will be changed in the parseImage body) if self.parseImage(pix, w1, h1, trimTopPixels, trimBottomPixels, True) == 0: #first run, just get the start column, ignore the letter - don't store it . We need this for the tab space width calculation and eventually the kerning calc of the letters # after the first call, we got an update on self.startColOfPrevFontLetter using the dummy double firstg letter font while self.parseImage(pix, w1, h1, trimTopPixels, trimBottomPixels) == 0: self.lettersFound = self.lettersFound + 1 # == 0 means one character font was detected so +1 to the counter - # print self.listOfBaselines #debug - if traceModeEnabled: - print "Debug:: Font Glyphs Detected (not including the first double): %d" % (self.lettersFound) + #if gTraceModeEnabled: + # print "[Debug] ", self.listOfBaselines + print "[Info] Font Glyphs Detected (not including the first double): %d" % (self.lettersFound) if (self.lettersFound ) > 0 : - #print "widths: ", self.listOfWidths[0:] - #print "Plain x offsets:" - #print zip(self.targetLangOrderAndListOfForeignLettersAsciiValues[1:], self.listOfXOffsets) -# # normalize x offsets -# minXoffset = min(self.listOfXOffsets) -# if(minXoffset < 0): -# addNormalizer = minXoffset * (-1) -# self.listOfXOffsets = [ x + addNormalizer for x in self.listOfXOffsets] -# print "Normalized x offsets: " -# print self.listOfXOffsets + #if gTraceModeEnabled: + # print "[Debug] widths: ", self.listOfWidths[0:] + # print "[Debug] Plain x offsets:" + # print zip(self.targetLangOrderAndListOfForeignLettersAsciiValues[1:], self.listOfXOffsets) + # normalize x offsets + # minXoffset = min(self.listOfXOffsets) + #if(minXoffset < 0): + # addNormalizer = minXoffset * (-1) + # self.listOfXOffsets = [ x + addNormalizer for x in self.listOfXOffsets] + #if gTraceModeEnabled: + # print "[Debug] Normalized x offsets: " + # print self.listOfXOffsets # calculate y offsets (listOfStartCols, listOfStartRows, listOfEndCols, listOfEndRows) = zip(* self.listOfLetterBoxes) minTopRow = min(listOfStartRows) self.listOfYOffsets = [ x - minTopRow for x in listOfStartRows] if (self.yOffsetForAllGlyphsExceptFirstSpecialGamma != 0): self.listOfYOffsets = [ x + self.yOffsetForAllGlyphsExceptFirstSpecialGamma for x in self.listOfYOffsets] - #print "Y offsets: " - #print self.listOfYOffsets + #if gTraceModeEnabled: + # print "[Debug] Y offsets: " + # print self.listOfYOffsets + # # + # Actually explicit Width setting could affect this, so calculate a new list here with final widths and get the max on that list! # - # # actually explicit Width setting could affect this so calc a new list here with final widths and get the max on that list! # listOfCalcWidths = [] kIncIndx = 1 @@ -684,8 +691,8 @@ class grabberFromPNG: tmpOrd = self.targetLangOrderAndListOfForeignLettersAsciiValues[kIncIndx] keysOfWidthIncrements, valuesOfWidthIncrements = (zip(*self.listOfWidthIncrements)) if tmpOrd in keysOfWidthIncrements: - if traceModeEnabled: - print "Explicit width increment for %d: %d" % (tmpOrd, valuesOfWidthIncrements[keysOfWidthIncrements.index(tmpOrd)]) + #if gTraceModeEnabled: + # print "[Debug] Explicit width increment for %d: %d" % (tmpOrd, valuesOfWidthIncrements[keysOfWidthIncrements.index(tmpOrd)]) explicitWidthIncrementVal = valuesOfWidthIncrements[keysOfWidthIncrements.index(tmpOrd)] listOfCalcWidths.append(tmpWidth + explicitWidthIncrementVal ) if explicitWidthIncrementVal == 0: @@ -694,16 +701,18 @@ class grabberFromPNG: #maxFontWidth = max(self.listOfWidths) maxFontWidth = max(listOfCalcWidths) maxFontHeight = max(self.listOfHeights) - if traceModeEnabled: - print "Debug:: Max Width, Max Height (not necessarily for the same character glyph): %d, %d" % (maxFontWidth, maxFontHeight) - #print "Index\tAsciiOrd\tX Offs\tY Offs\tWidth\tHeight" - #print zip(range(1, len(self.listOfXOffsets)), self.targetLangOrderAndListOfForeignLettersAsciiValues[1:], self.listOfXOffsets, self.listOfYOffsets, listOfCalcWidths, self.listOfHeights) + if gTraceModeEnabled: + print "[Debug] Max Width: %d, Max Height: %d (not necessarily for the same character glyph)." % (maxFontWidth, maxFontHeight) + # print "Index\tAsciiOrd\tX Offs\tY Offs\tWidth\tHeight" + # print zip(range(1, len(self.listOfXOffsets)), self.targetLangOrderAndListOfForeignLettersAsciiValues[1:], self.listOfXOffsets, self.listOfYOffsets, listOfCalcWidths, self.listOfHeights) targetFontFile = None try: targetFontFile = open(self.targetFONFilename, 'wb') - except: + except Exception as e: + print '[Error] Failed to create target font (FON) file: ' + self.targetFONFilename + '::' + str(e) errorFound = True if not errorFound: + print '[Info] Creating target font (FON) file: ' + self.targetFONFilename # reopen the image with our Fonts because we deleted the letters in the in-mem copy im = None if os.access(self.imageRowFilePNG, os.F_OK) : @@ -724,8 +733,8 @@ class grabberFromPNG: # this size should be updated at the end (after filling the file with all font image data) # # pack 'I' unsigned int - if traceModeEnabled: - print "Number Of Entries In Font Table", (self.maxAsciiValueInEncoding + 1 + 1) + if gTraceModeEnabled: + print "[Debug] Number Of Entries In Font Table: ", (self.maxAsciiValueInEncoding + 1 + 1) numberOfEntriesInFontTable = self.maxAsciiValueInEncoding + 1 + 1 # 0x0100 # This is actually the max ascii value + plus one (1) to get the font index value + plus another one (1) to get the count (since we have zero based indices) # TODO ??? could be more than this if we need to keep other characters (not in our codeset) and expand the ascii table and offset the new characters numberOfEntriesInFontTableInFile = pack('I', numberOfEntriesInFontTable ) @@ -739,7 +748,7 @@ class grabberFromPNG: startOfImageSegmentAbs = 0x10 + 20 * numberOfEntriesInFontTable # header is 0x10 bytes. Then table of 20 bytes * numberOfEntriesInFontTable and then the data. lastImageSegmentOffset = 0 - # targetFontFile.close() # don't close here + #targetFontFile.close() # don't close here # # Fonts index table - properties and offset in image segment # TODO - REVISE WHEN FINISHED WITH COMPLETE TRANSCRIPT for special glyphs @@ -801,16 +810,17 @@ class grabberFromPNG: kIncIndxLst = [item for item in enumerate(self.targetLangOrderAndListOfForeignLettersAsciiValues[1:], 0) if item[1] == (i-1) ] kIncIndx = kIncIndxLst[0][0] #kIncIndx = self.targetLangOrderAndListOfForeignLettersAsciiValues.index(i-1) - #print kIncIndxLst - #print kIncIndx, i-1 - #print i, ": actual entry index of ascii char", (i-1)," width:", self.listOfWidths[kIncIndx] - #print "Self explicit kerning list: " , self.listOfExplicitKerning + #if gTraceModeEnabled: + # print "[Debug] ", kIncIndxLst + # print "[Debug] ", kIncIndx, i-1 + # print "[Debug] ", i, ": actual entry index of ascii char", (i-1)," width:", self.listOfWidths[kIncIndx] + # print "[Debug] Self explicit kerning list: ", self.listOfExplicitKerning if len(self.listOfExplicitKerning ) > 0: keysOfExplicitKerning, valuesOfExplicitKerning = (zip(*self.listOfExplicitKerning)) if (i - 1) in keysOfExplicitKerning: # found explicit kerning for this - if traceModeEnabled: - print "Explicit kerning for %d " % (i-1) + #if gTraceModeEnabled: + # print "[Debug] Explicit kerning for %d " % (i-1) self.listOfXOffsets[kIncIndx] = valuesOfExplicitKerning[keysOfExplicitKerning.index(i-1)] # explicit X offset tmpXOffsetToWrite = pack('i', self.listOfXOffsets[kIncIndx]) # x offset - from left # TODO check if ok. Changed to signed int since it can be negative sometimes! @@ -821,8 +831,8 @@ class grabberFromPNG: if len(self.listOfWidthIncrements ) > 0: keysOfWidthIncrements, valuesOfWidthIncrements = (zip(*self.listOfWidthIncrements)) if (i - 1) in keysOfWidthIncrements: - if traceModeEnabled: - print "Explicit width increment for %d " % (i-1) + #if gTraceModeEnabled: + # print "[Debug] Explicit width increment for %d " % (i-1) foundExplicitWidthIncrement = True self.listOfWidths[kIncIndx] = self.listOfWidths[kIncIndx] + valuesOfWidthIncrements[keysOfWidthIncrements.index(i-1)] @@ -840,9 +850,10 @@ class grabberFromPNG: self.properListOfLetterBoxes.append(self.listOfLetterBoxes[kIncIndx]) else: # - #print i, ": phony entry" + #if gTraceModeEnabled: + # print "[Debug] ", i, ": phony entry" # TODO in-game resource fonts don't point all to the first entry as dummy but to the last valid entry encountered - tmpXOffsetToWrite = pack('I', 0x0000) # 0 x offset + tmpXOffsetToWrite = pack('I', 0x0000) # 0 x offset targetFontFile.write(tmpXOffsetToWrite) tmpYOffsetToWrite = pack('I', 0x0000) # 0 y offset targetFontFile.write(tmpYOffsetToWrite) @@ -854,12 +865,12 @@ class grabberFromPNG: targetFontFile.write(tmpDataOffsetToWrite) # end of for loop over all possible ascii values contained in the fon file # print the corrected properties per glyph font: - if traceModeEnabled: - print "***** FINAL (Explicit Kern, width accounted) *****\nIndex\tAsciiOrd\tX Offs\tY Offs\tWidth\tHeight" + if gTraceModeEnabled: + print "***** FINAL (Explicit kerning and width accounted) *****\nIndex\tAsciiOrd\tX Offs\tY Offs\tWidth\tHeight" tmpListOfTuplesToPrintDbg = zip(range(1, len(self.listOfXOffsets)), self.targetLangOrderAndListOfForeignLettersAsciiValues[1:], self.listOfXOffsets, self.listOfYOffsets, listOfCalcWidths, self.listOfHeights) for itemDbg in tmpListOfTuplesToPrintDbg: print "%4d\t%8d\t%6d\t%6d\t%6d\t%6d" % (itemDbg[0], itemDbg[1], itemDbg[2], itemDbg[3], itemDbg[4], itemDbg[5]) - + #print "\n" # # # Now fill in the image segment @@ -878,7 +889,7 @@ class grabberFromPNG: # START of First special character image segment # for i in range(0, maxFontWidth * maxFontHeight): - if(i < maxFontWidth or i % maxFontWidth == 0): + if (i < maxFontWidth or i % maxFontWidth == 0): tmpPixelColorRGB555ToWrite = pack('H', 0x7FFF) #unsigned short - 2 bytes targetFontFile.write(tmpPixelColorRGB555ToWrite) else: @@ -896,33 +907,40 @@ class grabberFromPNG: # If we have a character with explicit width increment (y) we should add columns of transparent colored pixels at the end (so since this is done by row, we should add y number of transparent pixels at the end of each row) kIncIndx = 1 # start after the first glyph (which is DOUBLE) for (c_startCol, c_startRow, c_endCol, c_endRow) in self.properListOfLetterBoxes[0:]: - #print (c_startCol, c_startRow, c_endCol, c_endRow),'for letter ', self.targetLangOrderAndListOfForeignLettersAsciiValues[kIncIndx] + #if gTraceModeEnabled: + # print "[Debug] ", (c_startCol, c_startRow, c_endCol, c_endRow),' for letter ', self.targetLangOrderAndListOfForeignLettersAsciiValues[kIncIndx] explicitWidthIncrementVal = 0 if len(self.listOfWidthIncrements ) > 0: tmpOrd = self.targetLangOrderAndListOfForeignLettersAsciiValues[kIncIndx] keysOfWidthIncrements, valuesOfWidthIncrements = (zip(*self.listOfWidthIncrements)) if tmpOrd in keysOfWidthIncrements: - #print "Explicit width increment for %d: %d" % (tmpOrd, valuesOfWidthIncrements[keysOfWidthIncrements.index(tmpOrd)]) + #if gTraceModeEnabled: + # print "[Debug] Explicit width increment for %d: %d" % (tmpOrd, valuesOfWidthIncrements[keysOfWidthIncrements.index(tmpOrd)]) explicitWidthIncrementVal = valuesOfWidthIncrements[keysOfWidthIncrements.index(tmpOrd)] for tmpRowCur in range(c_startRow, c_endRow + 1): for tmpColCur in range(c_startCol, c_endCol +1): - #print (tmpRowCur, tmpColCur) + #if gTraceModeEnabled: + # print "[Debug] ", (tmpRowCur, tmpColCur) r1,g1,b1,a1 = pixReloaded[tmpColCur, tmpRowCur] # Index col first, row second for image pixel array. TODO asdf this pix has been modified. All pixels would be transparent? - load image again? - if(a1 == 0): -# print "with alpha 8bit:", (r1, g1, b1, a1) + if (a1 == 0): + #if gTraceModeEnabled: + # print "[Debug] With alpha 8bit: ", (r1, g1, b1, a1) #make completely transparent - write 0x8000 tmpPixelColorRGB555ToWrite = pack('H', 0x8000) targetFontFile.write(tmpPixelColorRGB555ToWrite) # unsigned short - 2 bytes else: # alpha should be 255 here really. - #print "8bit:", (r1, g1, b1) + #if gTraceModeEnabled: + # print "[Debug] 8bit:", (r1, g1, b1) tmp5bitR1 = (r1 >> 3) & 0x1f tmp5bitG1 = (g1 >> 3) & 0x1f tmp5bitB1 = (b1 >> 3) & 0x1f - #print "5bit:", (tmp5bitR1, tmp5bitG1, tmp5bitB1) + #if gTraceModeEnabled: + # print "[Debug] 5bit: ", (tmp5bitR1, tmp5bitG1, tmp5bitB1) tmpPixelColorConvertedToRGB555 = (tmp5bitR1 << 10) | (tmp5bitG1 << 5) | (tmp5bitB1) - #print "16bit:", tmpPixelColorConvertedToRGB555 + #if gTraceModeEnabled: + # print "[Debug] 16bit: ", tmpPixelColorConvertedToRGB555 tmpPixelColorRGB555ToWrite = pack('H', tmpPixelColorConvertedToRGB555) targetFontFile.write(tmpPixelColorRGB555ToWrite) # unsigned short - 2 bytes if (tmpColCur == c_endCol and explicitWidthIncrementVal > 0): @@ -951,29 +969,29 @@ class grabberFromPNG: targetFontFile.close() else: ## if (self.lettersFound ) <= 0 - errMsg = "No letters were found in input png!" + errMsg = "[Error] No letters were found in input png!" print errMsg retVal = -2 if retVal == 0: - print "Done." + print "[Info] Done." else: - print "Errors were found." + print "[Error] Errors were found during execution." return (retVal, errMsg, origGameFontSizeEqBaseLine, totalFontLetters, importedNumOfLetters) - def extractFonFilesFromMix(self): + def exportFonFilesFromMix(self): """ Generate PNG files out of FON files stores in a MIX resource """ - print "Checking in %s for MIX files to extract FON's from" % (self.inputFonMixPath) + print "[Info] Checking in %s for MIX files to export font files (FON) from..." % (self.inputFonMixPath) inputMIXFilesFound = [] # breaking after first for loop yields only the top directory files, which is what we want for (dirpath, dirnames, filenames) in walk(self.inputFonMixPath): for filename in filenames: - for mixFileName in supportedMIXInputFiles: + for mixFileName in SUPPORTED_MIX_INPUT_FILES: if filename.upper() == mixFileName: inputMIXFilesFound.append(mixFileName) break for tmpMIXfileName in inputMIXFilesFound: - print "Found MIX: %s" % ('"' + self.inputFonMixPath + tmpMIXfileName + '"') + print "[Info] Found MIX file: %s" % ('"' + tmpMIXfileName + '"') errorFound = False inMIXFile = None # @@ -981,14 +999,14 @@ class grabberFromPNG: inMIXFile = open(os.path.join(self.inputFonMixPath,tmpMIXfileName), 'rb') except: errorFound = True - print "Unexpected error:", sys.exc_info()[0] + print "[Error] Unexpected event:", sys.exc_info()[0] raise if not errorFound: totalFONs = 0 tmpBuff = inMIXFile.read(2) # H: unsigned short (2 bytes) followed by I: unsigned int (4 bytes) mixFileEntriesNumTuple = struct.unpack('H', tmpBuff) - numOfEntriesToExtract = mixFileEntriesNumTuple[0] + numOfEntriesToExport = mixFileEntriesNumTuple[0] tmpBuff = inMIXFile.read(4) mixFileDataSegmentSizeTuple = struct.unpack('I', tmpBuff) allMixFileSize = mixFileDataSegmentSizeTuple[0] @@ -998,9 +1016,10 @@ class grabberFromPNG: # 2 + 4 = 6 bytes short MIX header # 12 bytes per MIX entry in entries table # quick size validation - print "Entries: %d, data segment %d bytes" % (numOfEntriesToExtract, allMixFileSize) - if allActualBytesInMixFile != 2 + 4 + 12 * numOfEntriesToExtract + allMixFileSize: - print "Error: MIX file size mismatch with reported size in header for %s!" % (tmpMIXfileName) + if gTraceModeEnabled: + print "[Debug] MIX file entries: %d, Data segment: %d bytes" % (numOfEntriesToExport, allMixFileSize) + if allActualBytesInMixFile != 2 + 4 + 12 * numOfEntriesToExport + allMixFileSize: + print "[Error] MIX file size mismatch with reported size in header for %s!" % (tmpMIXfileName) else: # # 12 bytes per entry @@ -1008,7 +1027,10 @@ class grabberFromPNG: # 4 bytes: Offset in data segment # 4 bytes: Size of data # - for i in range(0, numOfEntriesToExtract): + if gTraceModeEnabled: + print "[Debug] Checking for supported font file (FON) entries in MIX file..." + + for i in range(0, numOfEntriesToExport): foundFONFile = False currFonFileName = 'UNKNOWN.FON' inMIXFile.seek(2 + 4 + 12*i) @@ -1022,38 +1044,41 @@ class grabberFromPNG: tmpRdTuple = struct.unpack('I', tmpBuff) sizeOfMIXEntry = tmpRdTuple[0] - for suppFONFileName in supportedExportedFONFiles: + for suppFONFileName in SUPPORTED_EXPORTED_GAME_FON_FILES: if(idOfMIXEntry == calculateFoldHash(suppFONFileName)): foundFONFile = True currFonFileName = suppFONFileName break if (foundFONFile == True): - print "Entry Name: %s, Entry ID: %s, offset %s, data segment %s bytes" % (currFonFileName, ''.join('{:08X}'.format(idOfMIXEntry)), ''.join('{:08X}'.format(offsetOfMIXEntry)),''.join('{:08X}'.format(sizeOfMIXEntry))) + if gTraceModeEnabled: + print "\n[Debug] Entry Name: %s, Entry ID: %s, Offset: %s, Data segment: %s bytes" % (currFonFileName, ''.join('{:08X}'.format(idOfMIXEntry)), ''.join('{:08X}'.format(offsetOfMIXEntry)),''.join('{:08X}'.format(sizeOfMIXEntry))) # # IF FON FILE: # put file in FON object # # - inMIXFile.seek(2 + 4 + 12*numOfEntriesToExtract + offsetOfMIXEntry) + inMIXFile.seek(2 + 4 + 12*numOfEntriesToExport + offsetOfMIXEntry) if(offsetOfMIXEntry + sizeOfMIXEntry > allMixFileSize): - print "Error: FON file size mismatch with reported size in entry header!" + print "[Error] Font file (FON) size mismatch with reported size in entry header!" else: fonFileBuffer = inMIXFile.read(sizeOfMIXEntry) if (len(fonFileBuffer) == sizeOfMIXEntry): # load FON file - thisFonFile = fonFile() + thisFonFile = fonFile(gTraceModeEnabled) if (thisFonFile.loadFonFile(fonFileBuffer, allMixFileSize, currFonFileName)): - print "FON file loaded" + if gTraceModeEnabled: + print "[Debug] Font file (FON) %s was loaded successfully!" % (currFonFileName) thisFonFile.outputFonToPNG() totalFONs = totalFONs + 1 else: - print "Error while LOADING FON file!" + print "[Error] Error while loading font file (FON) %s!" % (currFonFileName) else: - print "Error while reading FON file %s into mem buffer" % (''.join('{:08X}'.format(idOfMIXEntry))) + print "[Error] Error while reading font file (FON) %s into mem buffer" % (''.join('{:08X}'.format(idOfMIXEntry))) inMIXFile.close() - print "Total FONs: %d " % (totalFONs) + print "[Info] Total font files (FONs) processed: %d " % (totalFONs) + print "[Info] Done." return # @@ -1062,10 +1087,10 @@ class grabberFromPNG: # main def main(argsCL): # TODO parse arguments using argparse? https://docs.python.org/3/library/argparse.html#module-argparse - global traceModeEnabled - traceModeEnabled = False + global gTraceModeEnabled + gTraceModeEnabled = False invalidSyntax = False - extractFonMode = False + exportFonMode = False TMPSpecialGlyphMode = True TMPAutoTabCalculation = True @@ -1079,14 +1104,14 @@ def main(argsCL): TMPkerningForFirstDummyFontLetter = 0 TMPYOffsToApplyToAllGlyphsExceptFirstSpecialGamma = 0 TMPSpaceWidthInPixels = 10 -# TMPdeductKerningPixels = 0 + #TMPdeductKerningPixels = 0 TMPcustomBaseLineOffset = 0 - print "Running %s (%s)..." % (app_name_spaced, app_version) -# print "Len of sysargv = %s" % (len(argsCL)) + print "Running %s (%s)..." % (APP_NAME_SPACED, APP_VERSION) + #print "Len of sysargv = %s" % (len(argsCL)) if len(argsCL) == 2: if(argsCL[1] == '--help'or argsCL[1] == '-h'): - print "%s %s supports Blade Runner (English version, CD edition)." % (app_name_spaced, app_version) - print app_short_desc + print "%s %s supports Westwood's Blade Runner PC Game (1997)." % (APP_NAME_SPACED, APP_VERSION) + print APP_SHORT_DESC print "Created by Praetorian of the classic adventures in Greek team." print "Always keep backups!" print "--------------------" @@ -1094,15 +1119,15 @@ def main(argsCL): print "1. Put overrideEncoding.txt file in the same folder with this tool. (Recommended, but not obligatory step)" print "--------------------" print "Valid syntax A - export game fonts to PNG images:" - print "%s -ip folderpath_for_MIX_Files [--trace]\n" % (app_wrapper_name) + print "%s -ip folderpath_for_MIX_Files [--trace]\n" % (APP_WRAPPER_NAME) print "Valid syntax B - create subtitle font:" - print "%s -im image_Row_PNG_Filename -om output_FON_filename -pxLL minSpaceBetweenLettersInRowLeftToLeft -pxTT minSpaceBetweenLettersInColumnTopToTop -pxKn kerningForFirstDummyFontLetter -pxWS whiteSpaceWidthInPixels [--noSpecialGlyphs] [--noAutoTabCalculation] [--trace]\n" % (app_wrapper_name) # deductKerningPixels" + print "%s -im image_Row_PNG_Filename -om output_FON_filename -pxLL minSpaceBetweenLettersInRowLeftToLeft -pxTT minSpaceBetweenLettersInColumnTopToTop -pxKn kerningForFirstDummyFontLetter -pxWS whiteSpaceWidthInPixels [--noSpecialGlyphs] [--noAutoTabCalculation] [--trace]\n" % (APP_WRAPPER_NAME) # deductKerningPixels" print "The -ip switch has an argument that is the path for the input (MIX) files folder (can be the same as the Blade Runner installation folder)." print "The -oe switch has an argument that is the input overrideEncoding file to use for the particular font creation." print "The -im switch has an argument that is the input PNG image with a row of the font glyphs spaced apart." print "The -om switch has an argument that is the output FON filename." print "The -pxLL switch has an integer argument that specifies the minimum number of pixels between the left side of a glyph and the left side of the next glyph to its right in the line-row PNG." - print "The -pxTT switch has an integer argument that specifies the minimum number of pixels between the top side of a glyph and the top side of the glyph below (if there's a second row) in the row PNG. If there is only one row, this argument still should be set (as if there was another row) to define where the parser should stop checking for the limits of a glyph vertically." + print "The -pxTT switch has an integer argument that specifies the minimum number of pixels between the top side of a glyph and the top side of the glyph below (if there's a second row) in the row PNG. If there is only one row, this argument should still be set (as if there was another row) to define where the parser should stop checking for the limits of a glyph vertically." print "The -pxKn switch has an integer argument that sets kerning for the first dummy font glyph." print "The -pxYo switch has an integer argument that sets an offset to be added to all detected y offsets for the glyphs (except the special first one)." print "The -pxWS switch has an integer argument that sets the white space width in pixels for this particular font." @@ -1111,11 +1136,11 @@ def main(argsCL): print "The --trace switch enables more debug messages being printed during execution." print "--------------------" print "Thank you for using this app." - print "Please provide any feedback to: %s " % (company_email) + print "Please provide any feedback to: %s " % (COMPANY_EMAIL) sys.exit() elif(argsCL[1] == '--version' or argsCL[1] == '-v'): - print "%s %s supports Blade Runner (English version, CD edition)." % (app_name_spaced, app_version) - print "Please provide any feedback to: %s " % (company_email) + print "%s %s supports Westwood's Blade Runner PC Game (1997)." % (APP_NAME_SPACED, APP_VERSION) + print "Please provide any feedback to: %s " % (COMPANY_EMAIL) sys.exit() else: invalidSyntax = True @@ -1124,8 +1149,8 @@ def main(argsCL): if( i < (len(argsCL) - 1) and argsCL[i][:1] == '-' and argsCL[i+1][:1] != '-'): if (argsCL[i] == '-ip'): TMPinputPathForMixFiles = argsCL[i+1] - extractFonMode = True - print "Original FON file extraction mode enabled." + exportFonMode = True + print "[Info] Original font file (FON) exporting mode enabled." elif (argsCL[i] == '-oe'): TMPOverrideEncodingFilePath = argsCL[i+1] elif (argsCL[i] == '-im'): @@ -1143,19 +1168,19 @@ def main(argsCL): elif (argsCL[i] == '-pxWS'): TMPSpaceWidthInPixels = int(argsCL[i+1]) elif argsCL[i] == '--noSpecialGlyphs': - print "Info:: No special out-of-order glyphs mode enabled." + print "[Info] No special out-of-order glyphs mode enabled." TMPSpecialGlyphMode = False elif argsCL[i] == '--noAutoTabCalculation': - print "Info:: No automatic tab calculation between glyphs." + print "[Info] No automatic tab calculation between glyphs." TMPAutoTabCalculation = False elif sys.argv[i] == '--trace': - print "Info:: Trace mode enabled (more debug messages)." - traceModeEnabled = True + print "[Info] Trace mode enabled (more debug messages)." + gTraceModeEnabled = True - if (extractFonMode == False) and (not TMPTargetFONfilename or not TMPimageRowFilePNG or TMPminSpaceBetweenLettersInRowLeftToLeft <= 0 or TMPminSpaceBetweenLettersInColumnTopToTop <= 0 or TMPkerningForFirstDummyFontLetter <= 0 or TMPSpaceWidthInPixels <= 0) : # this argument is mandatory + if (exportFonMode == False) and (not TMPTargetFONfilename or not TMPimageRowFilePNG or TMPminSpaceBetweenLettersInRowLeftToLeft <= 0 or TMPminSpaceBetweenLettersInColumnTopToTop <= 0 or TMPkerningForFirstDummyFontLetter <= 0 or TMPSpaceWidthInPixels <= 0) : # this argument is mandatory invalidSyntax = True - if (extractFonMode == True) and ( (not TMPinputPathForMixFiles) ): # not needed for extraction mode -- or not TMPOverrideEncodingFilePath ): + if (exportFonMode == True) and ( (not TMPinputPathForMixFiles) ): # not needed for exporting mode -- or not TMPOverrideEncodingFilePath ): invalidSyntax = True else: invalidSyntax = True @@ -1175,9 +1200,9 @@ def main(argsCL): myGrabInstance.setSpecialGlyphMode(TMPSpecialGlyphMode) myGrabInstance.setAutoTabCalculation(TMPAutoTabCalculation) myGrabInstance.setOverrideEncodingPath(TMPOverrideEncodingFilePath) -# myGrabInstance.setDeductKerningPixels(TMPdeductKerningPixels) - if extractFonMode: - myGrabInstance.extractFonFilesFromMix() + #myGrabInstance.setDeductKerningPixels(TMPdeductKerningPixels) + if exportFonMode: + myGrabInstance.exportFonFilesFromMix() else: myGrabInstance.initOverrideEncoding() myGrabInstance.generateModFiles(TMPcustomBaseLineOffset) @@ -1185,17 +1210,18 @@ def main(argsCL): invalidSyntax = True if invalidSyntax == True: - print "Invalid syntax\n Try: \n %s --help for more info \n %s --version for version info " % (app_wrapper_name, app_wrapper_name) + print "[Error] Invalid syntax\n Try: \n %s --help for more info \n %s --version for version info " % (APP_WRAPPER_NAME, APP_WRAPPER_NAME) print "Valid syntax A - export game fonts to PNG images:" - print "%s -ip folderpath_for_MIX_Files [--trace]\n" % (app_wrapper_name) + print "%s -ip folderpath_for_MIX_Files [--trace]\n" % (APP_WRAPPER_NAME) print "Valid syntax B - create subtitle font:" - print "%s -im image_Row_PNG_Filename -om output_FON_filename -pxLL minSpaceBetweenLettersInRowLeftToLeft -pxTT minSpaceBetweenLettersInColumnTopToTop -pxKn kerningForFirstDummyFontLetter -pxWS whiteSpaceWidthInPixels [--noSpecialGlyphs] [--noAutoTabCalculation] [--trace]\n" % (app_wrapper_name) # deductKerningPixels" + print "%s -im image_Row_PNG_Filename -om output_FON_filename -pxLL minSpaceBetweenLettersInRowLeftToLeft -pxTT minSpaceBetweenLettersInColumnTopToTop -pxKn kerningForFirstDummyFontLetter -pxWS whiteSpaceWidthInPixels [--noSpecialGlyphs] [--noAutoTabCalculation] [--trace]\n" % (APP_WRAPPER_NAME) # deductKerningPixels" + print "\nDetected arguments:" tmpi = 0 for tmpArg in argsCL: if tmpi==0: #skip first argument tmpi+=1 continue - print "\nArgument: %s" % (tmpArg) + print "Argument: %s" % (tmpArg) tmpi+=1 @@ -1206,5 +1232,5 @@ if __name__ == '__main__': main(sys.argv[0:]) else: ## debug - #print 'Debug:: %s was imported from another module' % (app_name) + #print '[Debug] %s was imported from another module' % (APP_NAME) pass diff --git a/devtools/create_bladerunner/subtitles/mixResourceCreator/mixResourceCreator.py b/devtools/create_bladerunner/subtitles/mixResourceCreator/mixResourceCreator.py index b6b0e14208..7bb454ab3e 100644 --- a/devtools/create_bladerunner/subtitles/mixResourceCreator/mixResourceCreator.py +++ b/devtools/create_bladerunner/subtitles/mixResourceCreator/mixResourceCreator.py @@ -2,7 +2,7 @@ # -*- coding: UTF-8 -*- import sys if not (sys.version_info[0] == 2 and sys.version_info[1] == 7): - sys.stdout.write("Error:: Blade Runner MIX Resource Creator script requires Python 2.7\n") + sys.stdout.write("[Error] Blade Runner MIX Resource Creator script requires Python 2.7\n") sys.exit(1) import packBladeRunnerMIXFromPCTLKXLS04 diff --git a/devtools/create_bladerunner/subtitles/mixResourceCreator/packBladeRunnerMIXFromPCTLKXLS04.py b/devtools/create_bladerunner/subtitles/mixResourceCreator/packBladeRunnerMIXFromPCTLKXLS04.py index 0a5a422ffc..7fdb0d0a9b 100644 --- a/devtools/create_bladerunner/subtitles/mixResourceCreator/packBladeRunnerMIXFromPCTLKXLS04.py +++ b/devtools/create_bladerunner/subtitles/mixResourceCreator/packBladeRunnerMIXFromPCTLKXLS04.py @@ -5,8 +5,9 @@ # classic.adventures.in.greek@gmail.com # Works with Excel version outSpeech-15-06-2018-1856-TranslatingComms-080.xls and above # +# TODO Print a warning if packing a Text Resource (TRx) without the corresponding font(s) -- only a warning though +# # DONE - Support at least one translation too (ie Greek) -# Print a warning if packing a TRE without the corresponding font(s) -- only a warning though # import os, sys @@ -20,47 +21,47 @@ structLibFound = False try: import shutil except ImportError: - print "Error:: Shutil python library is required to be installed!" + print "[Error] Shutil python library is required to be installed!" else: shutilLibFound = True try: import ctypes except ImportError: - print "Error:: ctypes python library is required to be installed!" + print "[Error] ctypes python library is required to be installed!" else: ctypesLibFound = True try: import csv except ImportError: - print "Error:: csv python library is required to be installed!" + print "[Error] csv python library is required to be installed!" else: csvLibFound = True try: import xlrd except ImportError: - print "Error:: xlrd python library is required to be installed!" + print "[Error] xlrd python library is required to be installed!" else: xlrdLibFound = True try: import re except ImportError: - print "Error:: re (Regular expression operations) python library is required to be installed!" + print "[Error] re (Regular expression operations) python library is required to be installed!" else: reLibFound = True try: import struct except ImportError: - print "Error:: struct python library is required to be installed!" + print "[Error] struct python library is required to be installed!" else: structLibFound = True if (not shutilLibFound) or (not ctypesLibFound) or (not csvLibFound) or (not xlrdLibFound) or (not reLibFound) or (not structLibFound): - sys.stdout.write("Error:: Errors were found when trying to import required python libraries\n") + sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n") sys.exit(1) @@ -69,16 +70,39 @@ from xlrd import * # for pack from struct import * -company_email = "classic.adventures.in.greek@gmail.com" -app_version = "0.70" -app_name = "packBladeRunnerMIXFromPCTLKXLS" -app_wrapper_name = "mixResourceCreator.py" -app_name_spaced = "Blade Runner MIX Resource Creator" -app_short_desc = "Get a TRE file from spoken in-game quotes" -numOfSpokenQuotes = 0 +COMPANY_EMAIL = "classic.adventures.in.greek@gmail.com" +APP_VERSION = "0.80" +APP_NAME = "packBladeRunnerMIXFromPCTLKXLS" +APP_WRAPPER_NAME = "mixResourceCreator.py" +APP_NAME_SPACED = "Blade Runner MIX Resource Creator" +APP_SHORT_DESC = "Make a Text Resource file for spoken in-game quotes and pack Text Resources with Fonts into a SUBTITLES.MIX file." + +DEFAULT_SUBTITLES_FONT_NAME = 'SUBTLS_E.FON' +DEFAULT_SUBTITLES_MIX_OUTPUT_NAME = u'SUBTITLES.MIX' + +# all dialogue sheets get the SUBTLS_E.FON for translation to a Text Resource (TRx) +# In-game dialogue sheet +# TODO- maybe the '_E' part is not needed, since we use the suffix (x) of the extension (TRx) to signify the language +SUPPORTED_INGAME_DIALOGUE_SHEETS = ['INGQUO_E.TR'] +# Video cut-scenes' dialogue sheets - these need the appendix of (x) for the language code, and a suffix of '.VQA'. +SUPPORTED_VIDEO_DIALOGUE_SHEETS = ['WSTLGO_', 'BRLOGO_', 'INTRO_', 'MW_A_', 'MW_B01_', 'MW_B02_', 'MW_B03_', 'MW_B04_', 'MW_B05_', 'INTRGT_', 'MW_D_', 'MW_C01_', 'MW_C02_', 'MW_C03_', 'END04A_', 'END04B_', 'END04C_', 'END06_', 'END01A_', 'END01B_', 'END01C_', 'END01D_', 'END01E_', 'END01F_', 'END03_'] +# +# Each Text Resource (TRx) sheet gets a specific font to handle their translation to Text Resource +# TAHOMA means both TAHOMA Fonts (18 and 24)(their translation should be identical (although in the original they have minor differences but they don't affect anything) +# We use a single naming for TAHOMA here because both TAHOMA18 and TAHOMA24 are used for ENDCRED.TRx +# The TRx files that are identically named to the originals are supposed to override them (needs ScummVM compatible functionality for that) +# This is so that fan made translations are supported. +SUPPORTED_TRANSLATION_SHEETS = [('OPTIONS.TR', 'KIA6PT'), ('DLGMENU.TR', 'KIA6PT'), ('SCORERS.TR', 'TAHOMA'), ('VK.TR', 'KIA6PT'), ('CLUES.TR', 'KIA6PT'), ('CRIMES.TR', 'KIA6PT'), ('ACTORS.TR', 'KIA6PT'), ('HELP.TR', 'KIA6PT'), ('AUTOSAVE.TR', 'KIA6PT'), ('ERRORMSG.TR', 'KIA6PT'), ('SPINDEST.TR', 'KIA6PT'), ('KIA.TR', 'KIA6PT'), ('KIACRED.TR', 'KIA6PT'), ('CLUETYPE.TR', 'KIA6PT'), ('ENDCRED.TR', 'TAHOMA'), ('POGO.TR', 'KIA6PT')] +# The FON files that are identically named to the originals are supposed to override them (needs ScummVM compatible functionality for that) +SUPPORTED_OTHER_FILES_FOR_MIX = [DEFAULT_SUBTITLES_FONT_NAME, 'KIA6PT.FON', 'TAHOMA18.FON', 'TAHOMA24.FON'] # , '10PT.FON'] # we don't deal with 10PT.FON since it's not used -- TODO verify this. + +SUPPORTED_LANGUAGES_DESCRIPTION_CODE_TLIST = [('EN_ANY', 'E', 'English'), ('DE_DEU', 'G', 'German'), ('FR_FRA', 'F', 'French'), ('IT_ITA', 'I', 'Italian'), ('ES_ESP', 'S', 'Spanish'), ('RU_RUS', 'R', 'Russian')] +DEFAULT_LANG_DESC_CODE = SUPPORTED_LANGUAGES_DESCRIPTION_CODE_TLIST[0] + +gTraceModeEnabled = False +gActiveLanguageDescriptionCodeTuple = '' +gNumOfSpokenQuotes = 0 -defaultSubtitlesFontName = 'SUBTLS_E.FON' -defaultSubtitlesMixOutputName = u'SUBTITLES.MIX' origEncoding = 'windows-1252' defaultTargetEncoding = 'windows-1252' @@ -86,29 +110,12 @@ defaultTargetEncodingUnicode = unicode(defaultTargetEncoding, 'utf-8') targetEncoding = '' targetEncodingUnicode = '' -traceModeEnabled = False - -# DONE ADD ALL SHEETS NEEDED FROM THE XLS -# all dialogue sheets get the SUBTLS_E.FON for translation to TRE -# - TODO maybe merge this with TAHOMA18.FON eventually -supportedDialogueSheets = ['INGQUO_E.TRE', 'WSTLGO_E.VQA', 'BRLOGO_E.VQA', 'INTRO_E.VQA', 'MW_A_E.VQA', 'MW_B01_E.VQA', 'MW_B02_E.VQA', 'MW_B03_E.VQA', 'MW_B04_E.VQA', 'MW_B05_E.VQA', 'INTRGT_E.VQA', 'MW_D_E.VQA', 'MW_C01_E.VQA', 'MW_C02_E.VQA', 'MW_C03_E.VQA', 'END04A_E.VQA', 'END04B_E.VQA', 'END04C_E.VQA', 'END06_E.VQA', 'END01A_E.VQA', 'END01B_E.VQA', 'END01C_E.VQA', 'END01D_E.VQA', 'END01E_E.VQA', 'END01F_E.VQA', 'END03_E.VQA'] -# -# Each TRE sheet gets a specific font to handle their translation to TRE -# TAHOMA means both TAHOMA (their translation should be identical (although in the original they have minor differences but they don't affect anything) -# We use a single naming for TAHOMA here because both TAHOMA18 and TAHOMA24 are used for ENDCRED.TRE -# The TRE files that are identically named to the originals are supposed to override them (needs ScummVM compatible functionality for that) - -supportedTranslationSheets = [('OPTIONS.TRE', 'KIA6PT'), ('DLGMENU.TRE', 'KIA6PT'), ('SCORERS.TRE', 'TAHOMA'), ('VK.TRE', 'KIA6PT'), ('CLUES.TRE', 'KIA6PT'), ('CRIMES.TRE', 'KIA6PT'), ('ACTORS.TRE', 'KIA6PT'), ('HELP.TRE', 'KIA6PT'), ('AUTOSAVE.TRE', 'KIA6PT'), ('ERRORMSG.TRE', 'KIA6PT'), ('SPINDEST.TRE', 'KIA6PT'), ('KIA.TRE', 'KIA6PT'), ('KIACRED.TRE', 'KIA6PT'), ('CLUETYPE.TRE', 'KIA6PT'), ('ENDCRED.TRE', 'TAHOMA'), ('POGO.TRE', 'KIA6PT')] -# The FON files that are identically named to the originals are supposed to override them (needs ScummVM compatible functionality for that) -supportedOtherFilesForMix = [defaultSubtitlesFontName, 'KIA6PT.FON', 'TAHOMA18.FON', 'TAHOMA24.FON'] # , '10PT.FON'] # we don't deal with 10PT.FON since it's not used -- TODO verify this. - - tableOfStringIds = [] tableOfStringOffsets = [] tableOfStringEntries = [] # this list is used in order to replace the actual indices of characters with delegate font indices (ASCII indexes of the target code-page) which have been used during the font creation (or exist in in the internal TAHOMA font) -# contains tuples of two values. First value is actual Utf char, the second is a replacement ASCII char +# contains tuples of two values. First value is actual UTF char, the second is a replacement ASCII char listOfFontNamesToOutOfOrderGlyphs = [] arrangedListOfFontNamesToOutOfOrderGlyphs = [] @@ -122,7 +129,7 @@ def initOverrideEncoding(pathToConfigureFontsTranslationTxt): configureFontsTranslationTextFile = u'configureFontsTranslation.txt' relPath = u'.' pathToConfigureFontsTranslationTxt = os.path.join(relPath, configureFontsTranslationTextFile) - print "Warning:: Font Translation Configuration file not found in arguments. Attempting to open local file %s if it exists" % (configureFontsTranslationTextFile) + print "[Warning] Font Translation Configuration file not found in arguments. Attempting to open local file %s if it exists" % (configureFontsTranslationTextFile) configureTranslationFailed = True try: @@ -133,8 +140,8 @@ def initOverrideEncoding(pathToConfigureFontsTranslationTxt): if linesLst is None or len(linesLst) == 0: configureTranslationFailed = True else: - if traceModeEnabled: - print "Info:: Font Translation Configuration Info: " + if gTraceModeEnabled: + print "[Info] Font Translation Configuration Info: " involvedTokensLst =[] for readEncodLine in linesLst: tmplineTokens = re.findall("[^\t\n]+",readEncodLine ) @@ -177,28 +184,28 @@ def initOverrideEncoding(pathToConfigureFontsTranslationTxt): configureTranslationFailed = False except: - print "Error:: while trying to access file for encoding info: %s" % (pathToConfigureFontsTranslationTxt) + print "[Error] while trying to access file for encoding info: %s" % (pathToConfigureFontsTranslationTxt) raise configureTranslationFailed = True if configureTranslationFailed == True: # targetEncoding = defaultTargetEncoding - print "Error: Could not find proper override encoding info in: %s" % (pathToConfigureFontsTranslationTxt) + print "[Error] Could not find proper override encoding info in: %s" % (pathToConfigureFontsTranslationTxt) sys.exit() # terminate if override Failed (Blade Runner) # # TODO ASDF fix this!!! # if(len(listOfFontNamesToOutOfOrderGlyphs) == 0): - tmpFontType = defaultSubtitlesFontName[:-4] # remove the .FON extensionFromTheName - print "Info:: Empty list for out of order glyphs. Assuming default out of order glyphs and only for the %s font" % (tmpFontType) + tmpFontType = DEFAULT_SUBTITLES_FONT_NAME[:-4] # remove the .FON extensionFromTheName + print "[Info] Empty list for out of order glyphs. Assuming default out of order glyphs and only for the %s font" % (tmpFontType) tmplistOfOutOfOrderGlyphs = [] tmplistOfOutOfOrderGlyphs.append((u'\xed', u'\u0386')) # spanish i (si) tmplistOfOutOfOrderGlyphs.append((u'\xf1', u'\xa5')) # spanish n (senor) tmplistOfOutOfOrderGlyphs.append((u'\xe2', u'\xa6')) # a for (liver) pate tmplistOfOutOfOrderGlyphs.append((u'\xe9', u'\xa7')) # e for (liver) pate listOfFontNamesToOutOfOrderGlyphs.append( (tmpFontType, tmplistOfOutOfOrderGlyphs)) - if traceModeEnabled: - print "Info:: Explicit Out Of Order Glyphs List: " , listOfFontNamesToOutOfOrderGlyphs + if gTraceModeEnabled: + print "[Info] Explicit Out Of Order Glyphs List: " , listOfFontNamesToOutOfOrderGlyphs # arrange list properly: # check if the list contains same item as key and value (in different pairs) # if such case then the pair with the key should preceed the pair with the value matched, @@ -220,8 +227,8 @@ def initOverrideEncoding(pathToConfigureFontsTranslationTxt): if(foundMatchingPairs == False): break # the whole while loop arrangedListOfFontNamesToOutOfOrderGlyphs.append( ( itFontName, itOOOGlyphList)) - if traceModeEnabled: - print "Info:: Arranged Glyphs Delegates List: " , arrangedListOfFontNamesToOutOfOrderGlyphs + if gTraceModeEnabled: + print "[Info] Arranged Glyphs Delegates List: " , arrangedListOfFontNamesToOutOfOrderGlyphs return # @@ -230,18 +237,18 @@ def initActorPropertyEntries(thePathToActorNamesTxt): global actorPropertyEntriesWasInit global actorPropertyEntries firstLine = True -# print "opening actornames" +# print "[Debug] opening actornames" if thePathToActorNamesTxt is None or not thePathToActorNamesTxt: actorNamesTextFile = u'actornames.txt' relPath = u'.' thePathToActorNamesTxt = os.path.join(relPath, actorNamesTextFile) - print "Warning:: Actor names text file %s not found in arguments. Attempting to open local file if it exists" % (thePathToActorNamesTxt) + print "[Warning] Actor names text file %s not found in arguments. Attempting to open local file if it exists" % (thePathToActorNamesTxt) with open(thePathToActorNamesTxt) as tsv: for line in csv.reader(tsv, dialect="excel-tab"): #skip first line header if firstLine == True: -# print "skippingHeader" +# print "[Debug] skipping Header line in Excel sheet" firstLine = False else: actorPropertyEntries.append(line) @@ -306,7 +313,7 @@ def calculateFoldHash(strFileName): groupSum |= 0 hash = ((hash << 1) | ((hash >> 31) & 1)) + groupSum hash &= 0xFFFFFFFF # mask here! - if traceModeEnabled: + if gTraceModeEnabled: print (strParam +': ' +''.join('{:08X}'.format(hash))) return hash @@ -319,21 +326,23 @@ def getSortMixFilesKey(item): return signedKeyTmp # def outputMIX(): - # output file should be defaultSubtitlesMixOutputName + # output file should be DEFAULT_SUBTITLES_MIX_OUTPUT_NAME # checking with known hashes to verify calculateFoldHash #calculateFoldHash('AR01-MIN.SET') #calculateFoldHash('AR02-MIN.SET') #calculateFoldHash('CLOVDIES.AUD') #calculateFoldHash('INTRO.VQA') + print "[Info] Writing to output file %s..." % (DEFAULT_SUBTITLES_MIX_OUTPUT_NAME) errorFound = False outMIXFile = None try: relPath = u'.' - outputMixPath = os.path.join(relPath, defaultSubtitlesMixOutputName) + outputMixPath = os.path.join(relPath, DEFAULT_SUBTITLES_MIX_OUTPUT_NAME) outMIXFile = open(outputMixPath, 'wb') - except: + except Exception as e: errorFound = True + print '[Error] Unable to write to output MIX file. ' + str(e) if not errorFound: # Write header # 2 bytes: number of entries (NumFiles) @@ -358,28 +367,28 @@ def outputMIX(): # ^^ this is done manually by making sure the filenames in the sheets of the excel as compliant # Based on observations from STARTUP.MIX: # 1) the hash ids can overflow and so lower numbers seem to appear down in the index table entries list - # -- So we sort hash but we first tranlste the unsigned key to signed with ctypes + # -- So we sort hash but we first translate the unsigned key to signed with ctypes # 2) the offsets are not necessarily sorted, meaning that the first entry in the index table won't necessarily have the 0x00000000 offset i = 0 mixFileEntries = [] totalFilesDataSize = 0 currOffsetForDataSegment = 0 # we start after header and table of index entries, from 0, (but this means that when reading the offset we need to add 6 + numOfFiles * 12). This does not concern us though. - for sheetDialogueName in supportedDialogueSheets: - sheetDialogueNameTRE = sheetDialogueName[:-4] + '.TRE' - if os.path.isfile('./' + sheetDialogueNameTRE): - entryID = calculateFoldHash(sheetDialogueNameTRE) - mixEntryfileSizeBytes = os.path.getsize('./' + sheetDialogueNameTRE) - mixFileEntries.append((entryID, sheetDialogueNameTRE, mixEntryfileSizeBytes)) + for sheetDialogueName in SUPPORTED_DIALOGUE_SHEETS: + sheetDialogueNameTRx = sheetDialogueName[:-4] + '.TRE' + if os.path.isfile('./' + sheetDialogueNameTRx): + entryID = calculateFoldHash(sheetDialogueNameTRx) + mixEntryfileSizeBytes = os.path.getsize('./' + sheetDialogueNameTRx) + mixFileEntries.append((entryID, sheetDialogueNameTRx, mixEntryfileSizeBytes)) totalFilesDataSize += mixEntryfileSizeBytes - for translatedTREFileName in [ x[0] for x in supportedTranslationSheets] : + for translatedTREFileName in [ x[0] for x in SUPPORTED_TRANSLATION_SHEETS] : if os.path.isfile('./' + translatedTREFileName): entryID = calculateFoldHash(translatedTREFileName) mixEntryfileSizeBytes = os.path.getsize('./' + translatedTREFileName) mixFileEntries.append((entryID, translatedTREFileName, mixEntryfileSizeBytes)) totalFilesDataSize += mixEntryfileSizeBytes - for otherFileName in supportedOtherFilesForMix: + for otherFileName in SUPPORTED_OTHER_FILES_FOR_MIX: if os.path.isfile('./' + otherFileName): entryID = calculateFoldHash(otherFileName) mixEntryfileSizeBytes = os.path.getsize('./' + otherFileName) @@ -397,10 +406,10 @@ def outputMIX(): totalFilesDataSizeToWrite = pack('I',totalFilesDataSize) # unsigned integer 4 bytes outMIXFile.write(totalFilesDataSizeToWrite) - if traceModeEnabled: - print ("Debug:: Sorted Entries based on EntryId") + if gTraceModeEnabled: + print ("[Debug] Sorted Entries based on EntryId") for mixFileEntry in mixFileEntries: - if traceModeEnabled: + if gTraceModeEnabled: print (''.join('{:08X}'.format(mixFileEntry[0])) + ': ' + mixFileEntry[1] + ' : ' + ''.join('{:08X}'.format(mixFileEntry[2]))) entryID = mixFileEntry[0] & 0xFFFFFFFF entryIDToWrite = pack('I',entryID) # unsigned integer 4 bytes @@ -423,11 +432,12 @@ def outputMIX(): outMIXFile.write(inEntryMIXFile.read()) inEntryMIXFile.close() else: - print ("Error while reading in ENTRY file") + print ("[Error] Error while reading in ENTRY file") break outMIXFile.close() - print "Info:: Total Resource files packed in %s: %d" % (defaultSubtitlesMixOutputName, numOfFiles) + print "[Info] Total Resource files packed in %s: %d" % (DEFAULT_SUBTITLES_MIX_OUTPUT_NAME, numOfFiles) + print "[Info] Done." return # # END FOR MIX FILE @@ -451,23 +461,23 @@ def outputMIX(): def translateQuoteToAsciiProper(cellObj, pSheetName): newQuoteReplaceSpecials = cellObj.value.encode("utf-8") - #print ('Encoded to unicode: %s ' % (newQuoteReplaceSpecials)) + #print ('[Debug] Encoded to unicode: %s ' % (newQuoteReplaceSpecials)) newQuoteReplaceSpecials = newQuoteReplaceSpecials.decode("utf-8") pertinentListOfOutOfOrderGlyphs = [] #print pSheetName - #print supportedDialogueSheets - #print defaultSubtitlesFontName[:-4] + #print SUPPORTED_DIALOGUE_SHEETS + #print DEFAULT_SUBTITLES_FONT_NAME[:-4] #print [x[0] for x in listOfFontNamesToOutOfOrderGlyphs] - if pSheetName in supportedDialogueSheets and defaultSubtitlesFontName[:-4] in [x[0] for x in listOfFontNamesToOutOfOrderGlyphs]: + if pSheetName in SUPPORTED_DIALOGUE_SHEETS and DEFAULT_SUBTITLES_FONT_NAME[:-4] in [x[0] for x in listOfFontNamesToOutOfOrderGlyphs]: for (tmpFontName, tmpOOOList) in listOfFontNamesToOutOfOrderGlyphs: - if tmpFontName == defaultSubtitlesFontName[:-4]: + if tmpFontName == DEFAULT_SUBTITLES_FONT_NAME[:-4]: pertinentListOfOutOfOrderGlyphs = tmpOOOList break - elif pSheetName in [x[0] for x in supportedTranslationSheets]: + elif pSheetName in [x[0] for x in SUPPORTED_TRANSLATION_SHEETS]: pertinentFontType = '' - #[treAndFontTypeTuple for treAndFontTypeTuple in supportedTranslationSheets if treAndFontTypeTuple[0] == pSheetName] - for (tmpSheetName, tmpFontType) in supportedTranslationSheets: + #[treAndFontTypeTuple for treAndFontTypeTuple in SUPPORTED_TRANSLATION_SHEETS if treAndFontTypeTuple[0] == pSheetName] + for (tmpSheetName, tmpFontType) in SUPPORTED_TRANSLATION_SHEETS: if tmpSheetName == pSheetName: pertinentFontType = tmpFontType break @@ -522,7 +532,7 @@ def translateQuoteToAsciiProper(cellObj, pSheetName): def inputXLS(filename): - global numOfSpokenQuotes + global gNumOfSpokenQuotes global tableOfStringIds global tableOfStringOffsets global tableOfStringEntries @@ -544,16 +554,16 @@ def inputXLS(filename): # xl_sheet = xl_workbook.sheet_by_index(0) # # - mergedListOfSubtitleSheetsAndTranslatedTREs = supportedDialogueSheets + [ x[0] for x in supportedTranslationSheets ] + mergedListOfSubtitleSheetsAndTranslatedTREs = SUPPORTED_DIALOGUE_SHEETS + [ x[0] for x in SUPPORTED_TRANSLATION_SHEETS ] for sheetDialogueName in mergedListOfSubtitleSheetsAndTranslatedTREs: xl_sheet = xl_workbook.sheet_by_name(sheetDialogueName) if(xl_sheet is not None): - if traceModeEnabled: - print ('Sheet name: %s' % xl_sheet.name) - numOfSpokenQuotes = xl_sheet.nrows - 2 # all rows minus the first TWO rows with headers - if traceModeEnabled: - print ('Debug:: num of spoken quotes: %d' % numOfSpokenQuotes) + if gTraceModeEnabled: + print ('[Info] Sheet name: %s' % xl_sheet.name) + gNumOfSpokenQuotes = xl_sheet.nrows - 2 # all rows minus the first TWO rows with headers + if gTraceModeEnabled: + print ('[Debug] Number of spoken quotes: %d' % gNumOfSpokenQuotes) # stats for debug extremeQuotesList = [] longestLength = 0 @@ -563,8 +573,8 @@ def inputXLS(filename): absStartOfIndexTable = 4 - absStartOfOffsetTable = absStartOfIndexTable + (numOfSpokenQuotes * 4) # = 4 + 0x1577 * 4 = 4 + 0x55DC = 0x55E0 - absStartOfStringTable = absStartOfOffsetTable + ((numOfSpokenQuotes+1) * 4) # = 0x55E0 + (0x1578 * 4) = 0xABC0 + absStartOfOffsetTable = absStartOfIndexTable + (gNumOfSpokenQuotes * 4) # = 4 + 0x1577 * 4 = 4 + 0x55DC = 0x55E0 + absStartOfStringTable = absStartOfOffsetTable + ((gNumOfSpokenQuotes + 1) * 4) # = 0x55E0 + (0x1578 * 4) = 0xABC0 curStrStartOffset = absStartOfStringTable - 4 newQuoteReplaceSpecialsAscii = '' tmpQuoteID = 0 @@ -572,31 +582,31 @@ def inputXLS(filename): tmpStartFrame = 0 # for VQA sheets tmpEndFrame = 0 # for VQA sheets mode = 0 # init to unknown - if xl_sheet.name == supportedDialogueSheets[0]: - if traceModeEnabled: - print 'IN GAME QUOTES' + if xl_sheet.name == SUPPORTED_DIALOGUE_SHEETS[0]: + if gTraceModeEnabled: + print '[Debug] IN GAME QUOTES' mode = 1 #in-game quote - elif xl_sheet.name in supportedDialogueSheets: - if traceModeEnabled: - print 'VQA SCENE DIALOGUE' + elif xl_sheet.name in SUPPORTED_DIALOGUE_SHEETS: + if gTraceModeEnabled: + print '[Debug] VQA SCENE DIALOGUE' mode = 2 #VQA - elif xl_sheet.name in [ x[0] for x in supportedTranslationSheets ]: - if traceModeEnabled: - print 'TRANSLATED TRE' + elif xl_sheet.name in [ x[0] for x in SUPPORTED_TRANSLATION_SHEETS ]: + if gTraceModeEnabled: + print '[Debug] TRANSLATED TEXT RESOURCE' mode = 3 # Translated TRE # del tableOfStringIds[:] del tableOfStringEntries[:] del tableOfStringOffsets[:] for row_idx in range(2, xl_sheet.nrows): - #print "Line %d" % (row_idx) + #print "[Debug] Line %d" % (row_idx) for col_idx in range(0, xl_sheet.ncols): cell_obj = xl_sheet.cell(row_idx, col_idx) # # FOR IN-GAME QUOTES -- Iterate through columns starting from col 0. We need cols: 0, 2 # if mode == 1: - #print ('Column: [%s] cell_obj: [%s]' % (col_idx, cell_obj)) + #print ('[Debug] Column: [%s] cell_obj: [%s]' % (col_idx, cell_obj)) if(col_idx == 0): #switchFlagShowQuote = False twoTokensfirstColSplitAtDotXLS = cell_obj.value.split('.', 1) @@ -604,20 +614,20 @@ def inputXLS(filename): twoTokensfirstColSplitAtDashXLS = twoTokensfirstColSplitAtDotXLS[0].split('-', 1) if len(twoTokensfirstColSplitAtDashXLS) == 2: tmpQuoteID = int( twoTokensfirstColSplitAtDashXLS[0]) * 10000 + int(twoTokensfirstColSplitAtDashXLS[1]) - #print ('row_idx %d. tag %s = quoteId [%d]' % (row_idx, twoTokensfirstColSplitAtDotXLS[0], tmpQuoteID)) + #print ('[Debug] row_idx: %d. tag %s: quoteId [%d]' % (row_idx, twoTokensfirstColSplitAtDotXLS[0], tmpQuoteID)) tableOfStringIds.append(tmpQuoteID) #if(tmpQuoteID == 160110 or tmpQuoteID == 160010): # switchFlagShowQuote = True elif(col_idx == 1) : #if switchFlagShowQuote == True: - # print ('length: %d: %s' % (len(cell_obj.value), cell_obj.value)) - # print ('object: %s' % (cell_obj)) + # print ('[Debug] length: %d: %s' % (len(cell_obj.value), cell_obj.value)) + # print ('[Debug] object: %s' % (cell_obj)) # #newQuoteReplaceSpecials = cell_obj.value.decode("utf-8") # unicode(cell_obj.value, 'windows-1252') - # #print ('decoded to unicode: %s ' % (newQuoteReplaceSpecials)) # error with char xf1 + # #print ('[Debug] decoded to unicode: %s ' % (newQuoteReplaceSpecials)) # error with char xf1 newQuoteReplaceSpecialsAscii = translateQuoteToAsciiProper(cell_obj, xl_sheet.name) #if switchFlagShowQuote == True: - # print ('length: %d: %s' % (len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii)) + # print ('[Debug] length: %d: %s' % (len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii)) #print ':'.join(x.encode('hex') for x in newQuoteReplaceSpecialsAscii) # seems to work. new chars are non-printable but exist in string tableOfStringEntries.append(newQuoteReplaceSpecialsAscii) @@ -628,18 +638,18 @@ def inputXLS(filename): if ( predefinedLengthThreshold < len(newQuoteReplaceSpecialsAscii)): extremeQuotesList.append((tmpQuoteID, newQuoteReplaceSpecialsAscii)) quoteNumAboveThreshold += 1 - #print ('row_idx %d. tag %s = quoteId [%d], length: %d: %s' % (row_idx, twoTokensfirstColSplitAtDotXLS[0], tmpQuoteID, len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii)) + #print ('[Debug] row_idx: %d. tag %s: quoteId [%d], length: %d: %s' % (row_idx, twoTokensfirstColSplitAtDotXLS[0], tmpQuoteID, len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii)) # # FOR VQAs -- Iterate through columns starting from col 2. We need cols: 2, 9, 10 # elif mode == 2: if(col_idx == 2): # subtitle text newQuoteReplaceSpecialsAscii = translateQuoteToAsciiProper(cell_obj, xl_sheet.name) - #print ('length: %d: %s' % (len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii)) + #print ('[Debug] length: %d: %s' % (len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii)) #print ':'.join(x.encode('hex') for x in newQuoteReplaceSpecialsAscii) # seems to work. new chars are non-printable but exist in string # don't append to tableOfStringEntries yet elif(col_idx == 9): # startFrame - #print "cell: %s" % (cell_obj.value) + #print "[Debug] cell: %s" % (cell_obj.value) tmpStartFrame = int(cell_obj.value) elif(col_idx == 10): # endFrame tmpEndFrame = int(cell_obj.value) @@ -658,19 +668,19 @@ def inputXLS(filename): # For translated TRE sheets the id is already in first column, the text is in the next one # elif mode == 3: - #print ('Column: [%s] cell_obj: [%s]' % (col_idx, cell_obj)) + #print ('[Debug] Column: [%s] cell_obj: [%s]' % (col_idx, cell_obj)) if(col_idx == 0): tmpQuoteID = int(cell_obj.value) tableOfStringIds.append(tmpQuoteID) elif(col_idx == 1) : #if switchFlagShowQuote == True: - # print ('length: %d: %s' % (len(cell_obj.value), cell_obj.value)) - # print ('object: %s' % (cell_obj)) + # print ('[Debug] length: %d: %s' % (len(cell_obj.value), cell_obj.value)) + # print ('[Debug] object: %s' % (cell_obj)) # #newQuoteReplaceSpecials = cell_obj.value.decode("utf-8") # unicode(cell_obj.value, 'windows-1252') - # #print ('decoded to unicode: %s ' % (newQuoteReplaceSpecials)) # error with char xf1 + # #print ('[Debug] decoded to unicode: %s ' % (newQuoteReplaceSpecials)) # error with char xf1 newQuoteReplaceSpecialsAscii = translateQuoteToAsciiProper(cell_obj, xl_sheet.name) #if switchFlagShowQuote == True: - # print ('length: %d: %s' % (len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii)) + # print ('[Debug] length: %d: %s' % (len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii)) #print ':'.join(x.encode('hex') for x in newQuoteReplaceSpecialsAscii) # seems to work. new chars are non-printable but exist in string tableOfStringEntries.append(newQuoteReplaceSpecialsAscii) @@ -681,13 +691,13 @@ def inputXLS(filename): if ( predefinedLengthThreshold < len(newQuoteReplaceSpecialsAscii)): extremeQuotesList.append((tmpQuoteID, newQuoteReplaceSpecialsAscii)) quoteNumAboveThreshold += 1 - #print ('row_idx %d. tag %s = quoteId [%d], length: %d: %s' % (row_idx, twoTokensfirstColSplitAtDotXLS[0], tmpQuoteID, len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii)) + #print ('[Debug] row_idx: %d. tag %s: quoteId [%d], length: %d: %s' % (row_idx, twoTokensfirstColSplitAtDotXLS[0], tmpQuoteID, len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii)) tableOfStringOffsets.append(curStrStartOffset) # the final extra offset entry - if traceModeEnabled: - print 'Debug:: Longest Length = %d, quotes above threshold (%d): %d' % (longestLength, predefinedLengthThreshold, quoteNumAboveThreshold) + if gTraceModeEnabled: + print '[Debug] Longest Length: %d, Quotes above threshold (%d): %d' % (longestLength, predefinedLengthThreshold, quoteNumAboveThreshold) for extremQuotTuple in extremeQuotesList: - print "Id: %d, Q: %s" % (extremQuotTuple[0], extremQuotTuple[1]) + print "[Debug] Id: %d, Q: %s" % (extremQuotTuple[0], extremQuotTuple[1]) # # WRITE TO TRE FILE # @@ -696,25 +706,46 @@ def inputXLS(filename): outTREFileName = sheetDialogueName[:-4] try: outTREFile = open("./" + outTREFileName + ".TRE", 'wb') - except: + except Exception as e: errorFound = True + print '[Error] Unable to write to output TRE file. ' + str(e) if not errorFound: - numOfSpokenQuotesToWrite = pack('I',numOfSpokenQuotes) # unsigned integer 4 bytes + numOfSpokenQuotesToWrite = pack('I', gNumOfSpokenQuotes) # unsigned integer 4 bytes outTREFile.write(numOfSpokenQuotesToWrite) # write string IDs table - for idxe in range(0,len(tableOfStringIds)): - idOfStringToWrite = pack('I',tableOfStringIds[idxe]) # unsigned integer 4 bytes + for idxe in range(0, len(tableOfStringIds)): + idOfStringToWrite = pack('I', tableOfStringIds[idxe]) # unsigned integer 4 bytes outTREFile.write(idOfStringToWrite) # write string offsets table - for idxe in range(0,len(tableOfStringOffsets)): - offsetOfStringToWrite = pack('I',tableOfStringOffsets[idxe]) # unsigned integer 4 bytes + for idxe in range(0, len(tableOfStringOffsets)): + offsetOfStringToWrite = pack('I', tableOfStringOffsets[idxe]) # unsigned integer 4 bytes outTREFile.write(offsetOfStringToWrite) #write strings with null terminator - for idxe in range(0,len(tableOfStringEntries)): + for idxe in range(0, len(tableOfStringEntries)): outTREFile.write(tableOfStringEntries[idxe]) outTREFile.write('\0') outTREFile.close() return + +# +# Aux function to validate input language description +# +def getLanguageDescCodeTuple(candidateLangDescriptionStr): + if (candidateLangDescriptionStr is None or not candidateLangDescriptionStr ): + resultTuple = DEFAULT_LANG_DESC_CODE + else: + tmpMatchTuplesList = [ (x,y,z) for (x,y,z) in SUPPORTED_LANGUAGES_DESCRIPTION_CODE_TLIST if x == candidateLangDescriptionStr] + if tmpMatchTuplesList is not None and len(tmpMatchTuplesList) > 0: + resultTuple = tmpMatchTuplesList[0] + else: + resultTuple = None + return resultTuple + +def printInfoMessageForLanguageSelectionSyntax(): + tmpCSVSupportedLangDescValues = ", ".join( zip(*SUPPORTED_LANGUAGES_DESCRIPTION_CODE_TLIST)[0] ) + print "Valid values for language selection are: %s" % (tmpCSVSupportedLangDescValues) + print "Default value is: %s (%s)" % (DEFAULT_LANG_DESC_CODE[0], DEFAULT_LANG_DESC_CODE[2]) + return # # # @@ -725,41 +756,50 @@ def inputXLS(filename): # 00-8520 -- WhatDoYouKnow dupl TLK01, TLK0A def main(argsCL): # TODO parse arguments using argparse? https://docs.python.org/3/library/argparse.html#module-argparse - global traceModeEnabled - traceModeEnabled = False + global gTraceModeEnabled + global gActiveLanguageDescriptionCodeTuple + + gTraceModeEnabled = False + gActiveLanguageDescriptionCodeTuple = DEFAULT_LANG_DESC_CODE + pathToQuoteExcelFile = "" pathToActorNamesTxt = "" pathToConfigureFontsTranslationTxt = "" invalidSyntax = False - print "Running %s (%s)..." % (app_name_spaced, app_version) + print "Running %s (%s)..." % (APP_NAME_SPACED, APP_VERSION) # print "Len of sysargv = %s" % (len(argsCL)) if len(argsCL) == 2: if(argsCL[1] == '--help'or argsCL[1] == '-h'): - print "%s %s supports Blade Runner (English version, CD edition)." % (app_name_spaced, app_version) - print app_short_desc + print "%s %s supports Westwood's Blade Runner PC Game (1997)." % (APP_NAME_SPACED, APP_VERSION) + print APP_SHORT_DESC print "Created by Praetorian of the classic adventures in Greek team." print "Always keep backups!" print "--------------------" print "Preparatory steps:" - print "1. Copy the BladeRunnerPCTLK.xls file (latest version, downloaded from Google Sheets) in some folder on your PC." + print "1. Copy the transcript Excel file (eg. BladeRunnerPCTLK.xls, latest version, downloaded from Google Sheets) in some folder on your PC." print "--------------------" - print "%s takes 1 mandatory argument:" % (app_wrapper_name) + print "%s takes 1 mandatory argument:" % (APP_WRAPPER_NAME) print "Valid syntax: " - print "%s -x path_to_BladeRunnerPCTLK_xls [-ian path_to_actornames_txt] [-cft path_to_configureFontsTranslation_txt] [--trace]" % (app_wrapper_name) + print "%s -x path_to_BladeRunnerPCTLK_xls [-ian path_to_actornames_txt] [-cft path_to_configureFontsTranslation_txt] [-ld gameInputLanguageDescription] [--trace]" % (APP_WRAPPER_NAME) print "-x is followed by the path to the excel file with the subtitle quotes." print "-ian is followed by the path to actornames.txt, if it's not in the current working directory." print "-cft is followed by the path to configureFontsTranslation.txt, if it's not in the current working directory." + print "-ld is followed by the language description of the target game version that you will install the subtitles to." + printInfoMessageForLanguageSelectionSyntax() print "The --trace switch enables more debug messages being printed during execution." - print "If the app finishes successfully a " + supportedDialogueSheets[0] + " and a few other .TRE files for the VQAs " - print "in the Excel file as well as a %s file containing all of them will be created in the same folder with the app." % (defaultSubtitlesMixOutputName) + print "--------------------" + print "If the app finishes successfully, it creates a %sx file and a few other Text Resource (TRx) files " % (SUPPORTED_INGAME_DIALOGUE_SHEETS[0]) + print "for each VQAs sheet in the input Excel file respectively. Additionally, a %s file containing all " % (DEFAULT_SUBTITLES_MIX_OUTPUT_NAME) + print "of the resources in the Excel file and a few extra (subtitle font, (optional) edited fonts) is created as well." + print "All output files are written in the current working directory." print "--------------------" print "Thank you for using this app." - print "Please provide any feedback to: %s " % (company_email) + print "Please provide any feedback to: %s " % (COMPANY_EMAIL) sys.exit() elif(argsCL[1] == '--version' or argsCL[1] == '-v'): - print "%s %s supports Blade Runner (English version, CD edition)." % (app_name_spaced, app_version) - print "Please provide any feedback to: %s " % (company_email) + print "%s %s supports Westwood's Blade Runner PC Game (1997)." % (APP_NAME_SPACED, APP_VERSION) + print "Please provide any feedback to: %s " % (COMPANY_EMAIL) sys.exit() else: invalidSyntax = True @@ -773,13 +813,20 @@ def main(argsCL): elif (argsCL[i] == '-cft'): pathToConfigureFontsTranslationTxt = argsCL[i+1] elif sys.argv[i] == '--trace': - print "Info:: Trace mode enabled (more debug messages)." - traceModeEnabled = True + print "[Info] Trace mode enabled (more debug messages)." + gTraceModeEnabled = True if not pathToQuoteExcelFile: invalidSyntax = True + + gActiveLanguageDescriptionCodeTuple = getLanguageDescCodeTuple(candidateLangDescriptionTxt) + if (not invalidSyntax) and gActiveLanguageDescriptionCodeTuple is None: + print "[Error] Invalid language code was specified" + printInfoMessageForLanguageSelectionSyntax() + invalidSyntax = True if not invalidSyntax: + print "[Info] Game Language Selected: %s (%s)" % (gActiveLanguageDescriptionCodeTuple[0], gActiveLanguageDescriptionCodeTuple[2]) # parse any overrideEncoding file if exists: initOverrideEncoding(pathToConfigureFontsTranslationTxt) @@ -788,7 +835,7 @@ def main(argsCL): # parse Actors files: initActorPropertyEntries(pathToActorNamesTxt) # for actorEntryTmp in actorPropertyEntries: -# print "Found actor: %s %s %s" % (actorEntryTmp[0], actorEntryTmp[1], actorEntryTmp[2]) +# print "[Debug] Found actor: %s %s %s" % (actorEntryTmp[0], actorEntryTmp[1], actorEntryTmp[2]) inputXLS(pathToQuoteExcelFile) outputMIX() @@ -796,21 +843,16 @@ def main(argsCL): invalidSyntax = True if invalidSyntax == True: - print "Invalid syntax\n Try: \n %s --help for more info \n %s --version for version info " % (app_wrapper_name, app_wrapper_name) + print "[Error] Invalid syntax\n Try: \n %s --help for more info \n %s --version for version info " % (APP_WRAPPER_NAME, APP_WRAPPER_NAME) print "Valid syntax: " - print "%s -x path_to_BladeRunnerPCTLK_xls [-ian path_to_actornames_txt] [-cft path_to_configureFontsTranslation_txt] [--trace]" % (app_wrapper_name) - print "-x is followed by the path to the excel file with the subtitle quotes." - print "-ian is followed by the path to actornames.txt, if it's not in the current working directory." - print "-cft is followed by the path to configureFontsTranslation.txt, if it's not in the current working directory." - print "The --trace switch enabled more debug messages being printed during execution." - print "If the app finishes successfully a " + supportedDialogueSheets[0] + " and a few other .TRE files for the VQAs " - print "in the Excel file as well as a %s file containing all of them will be created in the same folder with the app." % (defaultSubtitlesMixOutputName) + print "%s -x path_to_BladeRunnerPCTLK_xls [-ian path_to_actornames_txt] [-cft path_to_configureFontsTranslation_txt] [-ld gameInputLanguageDescription] [--trace]" % (APP_WRAPPER_NAME) + print "\nDetected arguments:" tmpi = 0 for tmpArg in argsCL: if tmpi==0: #skip first argument tmpi+=1 continue - print "\nArgument: %s" % (tmpArg) + print "Argument: %s" % (tmpArg) tmpi+=1 # Total unique quotes seems to be 5495! @@ -821,5 +863,5 @@ if __name__ == "__main__": main(sys.argv[0:]) else: ## debug - #print 'Debug:: %s was imported from another module' % (app_wrapper_name) + #print '[Debug] %s was imported from another module' % (APP_WRAPPER_NAME) pass diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileDecode.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileDecode.py index 52ef7231f0..832cc7115d 100644 --- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileDecode.py +++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileDecode.py @@ -7,24 +7,24 @@ structLibFound = False try: import ctypes except ImportError: - print "Error:: ctypes python library is required to be installed!" + print "[Error] ctypes python library is required to be installed!" else: ctypesLibFound = True try: import struct except ImportError: - print "Error:: struct python library is required to be installed!" + print "[Error] struct python library is required to be installed!" else: structLibFound = True if (not ctypesLibFound) or (not structLibFound): - sys.stdout.write("Error:: Errors were found when trying to import required python libraries\n") + sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n") sys.exit(1) from struct import * -my_module_version = "0.50" +my_module_version = "0.60" my_module_name = "audFileDecode" aud_ima_index_adjust_table = [-1, -1, -1, -1, 2, 4, 6, 8] @@ -59,15 +59,16 @@ def aud_decode_ima_chunk(audioBufferIn, index, sample, cs_chunk): audioBufferOut = [] #for i in range(0, len(audioBufferIn)): - # print 'Debug:: %d= %d'%(i, int(audioBufferIn[i])) + #if self.m_traceModeEnabled: + # print '[Debug] %d: %d'%(i, int(audioBufferIn[i])) for sample_index in range (0, cs_chunk): try: code = audioBufferIn[sample_index >> 1] except: code = 0xa9 # dummy workaround because the c code is accessing an out of bounds index sometimes due to this shift here - #print "Debug:: cs_chunk %d, sample_index %d, shifted %d, code= %d" % (cs_chunk, sample_index, sample_index >> 1, int(audioBufferIn[sample_index >> 1])) - #print "Debug:: cs_chunk %s, sample_index %s, shifted %s, code= %s" % \ + #print "[Debug] cs_chunk: %d, sample_index: %d, shifted: %d, code: %d" % (cs_chunk, sample_index, sample_index >> 1, int(audioBufferIn[sample_index >> 1])) + #print "[Debug] cs_chunk: %s, sample_index: %s, shifted: %s, code: %s" % \ # (''.join('{:04X}'.format(cs_chunk)), ''.join('{:02X}'.format(sample_index)), ''.join('{:02X}'.format(sample_index >> 1)), ''.join('{:04X}'.format(int(code)))) code = code >> 4 if (sample_index & 1) else code & 0xf step = aud_ima_step_table[index] @@ -88,7 +89,8 @@ def aud_decode_ima_chunk(audioBufferIn, index, sample, cs_chunk): sample = 32767 audioBufferOut.append(ctypes.c_short( sample ).value ) #audioBufferOut.append(sample) # it's not different from above... ctypes.c_short( sample ).value - #print "Debug:: audio_out[%s]= %s" % (''.join('{:02X}'.format(sample_index)), ''.join('{:02X}'.format(audioBufferOut[sample_index]))); + #if self.m_traceModeEnabled: + # print "[Debug] audio_out[%s]: %s" % (''.join('{:02X}'.format(sample_index)), ''.join('{:02X}'.format(audioBufferOut[sample_index]))); index += aud_ima_index_adjust_table[code & 7] if (index < 0): index = 0 @@ -198,12 +200,14 @@ def aud_decode_ws_chunk(inputChunkBuffer, cb_s, cb_d): # # # - class audFileDecode: m_index = -1 m_sample = -1 + m_traceModeEnabled = False - def __init__(self, index = 0, sample = 0): + # traceModeEnabled is bool to enable more printed debug messages + def __init__(self, traceModeEnabled = True, index = 0, sample = 0): + self.m_traceModeEnabled = traceModeEnabled self.m_index = index; self.m_sample = sample; return @@ -220,11 +224,11 @@ class audFileDecode: if __name__ == '__main__': # main() - print "Debug:: Running %s as main module" % (my_module_name) + print "[Debug] Running %s as main module" % (my_module_name) decodeInstance = audFileDecode() else: #debug - #print "Debug:: Running %s imported from another module" % (my_module_name) + #print "[Debug] Running %s imported from another module" % (my_module_name) pass \ No newline at end of file diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileLib.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileLib.py index e8c5632cc5..ed42c5ef08 100644 --- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileLib.py +++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileLib.py @@ -11,39 +11,39 @@ structLibFound = False try: import shutil except ImportError: - print "Error:: Shutil python library is required to be installed!" + print "[Error] Shutil python library is required to be installed!" else: shutilLibFound = True try: import wave except ImportError: - print "Error:: Wave python library is required to be installed!" + print "[Error] Wave python library is required to be installed!" else: waveLibFound = True try: import ctypes except ImportError: - print "Error:: ctypes python library is required to be installed!" + print "[Error] ctypes python library is required to be installed!" else: ctypesLibFound = True try: import struct except ImportError: - print "Error:: struct python library is required to be installed!" + print "[Error] struct python library is required to be installed!" else: structLibFound = True if (not shutilLibFound) or (not waveLibFound) or (not ctypesLibFound) or (not structLibFound): - sys.stdout.write("Error:: Errors were found when trying to import required python libraries\n") + sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n") sys.exit(1) from struct import * from audFileDecode import * -my_module_version = "0.50" +my_module_version = "0.60" my_module_name = "audFileLib" #constants @@ -77,12 +77,18 @@ class AudChunkHeader: # class audFile: m_header = AudHeader() - def __init__(self): + m_traceModeEnabled = False + m_simpleAudioFileName = 'GENERIC.AUD' + + # traceModeEnabled is bool to enable more printed debug messages + def __init__(self, traceModeEnabled = True): + self.m_simpleAudioFileName = 'GENERIC.AUD' + self.m_traceModeEnabled = traceModeEnabled return # std::fstream& fs, AudFileNS::pos_type startAudFilepos, AudFileNS::pos_type endAudFilepos, const std::string& filename - def extract_as_wav(self, audBytesBuff, filename): - print "Info:: Saving to wav: " + filename + def export_as_wav(self, audBytesBuff, filename): + print "[Info] Exporting to wav: " + filename cvirtualBinaryD = self.decode(audBytesBuff) # TODO DEBUG REMOVED FOR NOW. TODO RESTORE THIS!!! @@ -121,7 +127,8 @@ class audFile: return 0 # TODO fix - def loadAudFile(self, audBytesBuff, maxLength): + def loadAudFile(self, audBytesBuff, maxLength, audFileName): + self.m_simpleAudioFileName = audFileName offsInAudFile = 0 tmpTuple = struct.unpack_from('h', audBytesBuff, offsInAudFile) self.header().samplerate = tmpTuple[0] @@ -138,10 +145,11 @@ class audFile: tmpTuple = struct.unpack_from('b', audBytesBuff, offsInAudFile) self.header().compression = tmpTuple[0] offsInAudFile += 1 - print "Debug:: Sample rate= %d\tsizeIn= %d\tsizeOut= %d\tflags= %d\tcompression= %d" % (self.get_samplerate(), self.header().size_in, self.header().size_out, self.header().flags, self.header().compression) + if self.m_traceModeEnabled: + print "[Debug] Sample rate: %d\tsizeIn: %d\tsizeOut: %d\tflags: %d\tcompression: %d" % (self.get_samplerate(), self.header().size_in, self.header().size_out, self.header().flags, self.header().compression) if self.get_samplerate() < 8000 or self.get_samplerate() > 48000 or self.header().size_in > (maxLength - SIZE_OF_AUD_HEADER_IN_BYTES ): - print "Error:: Bad AUD Header size::2" + print "[Error] Bad AUD Header size in file %s" % (self.m_simpleAudioFileName) return False else: if self.header().compression == 1: @@ -205,7 +213,7 @@ class audFile: def get_chunk_data(self, inAudFileBytesBuffer, startOffs, sizeToRead): #fs.read((char*)byteChunkDataPtr, sizeToRead) outChunkDataLst = [] - #print "Debug:: startOffs %d, sizeToRead %d" % (startOffs, sizeToRead) + #print "[Debug] startOffs: %d, sizeToRead: %d" % (startOffs, sizeToRead) for i in range(startOffs, startOffs + sizeToRead): #outChunkDataLst.append(ctypes.c_char(inAudFileBytesBuffer[i]).value) #outChunkDataLst.append(ctypes.c_byte(inAudFileBytesBuffer[i]).value) @@ -221,7 +229,8 @@ class audFile: def decode(self, audBytesBuff): # The * operator unpacks an argument list. It allows you to call a function with the list items as individual arguments. # binDataOut = struct.pack('i'*len(data), *data) - print "Info:: DECODING..." + if self.m_traceModeEnabled: + print "[Debug] Decoding AUD file format..." # Cvirtual_binary d; binaryDataOutLst = [] binaryDataOutBuff = None @@ -238,9 +247,9 @@ class audFile: #out_chunk_header = AudChunkHeader() (errGetChunk, bufferDataPos, out_chunk_header) = self.get_chunk_header(chunk_i, audBytesBuff, len(audBytesBuff)) if errGetChunk != 0: -# print "Warning:: Error OR End file case while getting uncompressed chunk header!" +# print "[Warning] Error OR End file case while getting uncompressed chunk header!" break - #print "Debug:: Get uncompressed chunk header returned:: %d " % (out_chunk_header.id) + #print "[Debug] Get uncompressed chunk header returned: %d " % (out_chunk_header.id) #Cvirtual_binary out_chunk_data; #AudFileNS::byte* byteChunkDataPtr = out_chunk_data.write_start(out_chunk_header.size_in); (errorGCD, byteChunkDataLst) = self.get_chunk_data(audBytesBuff, bufferDataPos, out_chunk_header.size_in) @@ -251,7 +260,7 @@ class audFile: chunk_i += 1 binaryDataOutBuff = struct.pack('b'*len(binaryDataOutLst), *binaryDataOutLst) elif self.header().compression == 0x63: - decodeInstance = audFileDecode(); + decodeInstance = audFileDecode(self.m_traceModeEnabled); #decodeInstance.init(); #AudFileNS::byte* w = d.write_start(cb_audio); errGetChunk = 0 # int errGetChunk @@ -259,26 +268,32 @@ class audFile: chunk_i = 0 wIndex = 0 while (wIndex < cb_audio): - #print("Debug:: chunkI= %d\t Windex= %d\t cb_audio= %d") % (chunk_i,wIndex,cb_audio) + #print("[Debug] chunkI: %d\t Windex: %d\t cb_audio: %d") % (chunk_i,wIndex,cb_audio) #AudChunkHeader out_chunk_header; #out_chunk_header = AudChunkHeader() #errGetChunk = self.get_chunk_header(chunk_i, fs, startAudFilepos, endAudFilepos, out_chunk_header); (errGetChunk, bufferDataPos, out_chunk_header) = self.get_chunk_header(chunk_i, audBytesBuff, len(audBytesBuff)) if errGetChunk != 0: - print "Warning:: Error OR End file case while getting COMPRESSED chunk header!" + print "[Warning] Error OR End file case while getting COMPRESSED chunk header!" break - #print "Debug:: Get COMPRESSED chunk header returned:: headerInSize: %d headerOutSize: %d id: %d" % (out_chunk_header.size_in, out_chunk_header.size_out, out_chunk_header.id) + #print "[Debug] Get COMPRESSED chunk header returned:: headerInSize: %d headerOutSize: %d id: %d" % (out_chunk_header.size_in, out_chunk_header.size_out, out_chunk_header.id) #Cvirtual_binary out_chunk_data; #AudFileNS::byte* byteChunkDataPtr = out_chunk_data.write_start(out_chunk_header.size_in); (errorGCD, byteChunkDataLst) = self.get_chunk_data(audBytesBuff, bufferDataPos, out_chunk_header.size_in) # export decoded chunk to w (output) buffer (of SHORTS) at the point where we're currently at (so append there) - #print "Debug:: byteChunkDataLst len= %d, size_in was= %d" % (len(byteChunkDataLst), out_chunk_header.size_in) + #print "[Debug] byteChunkDataLst len: %d, size_in was: %d" % (len(byteChunkDataLst), out_chunk_header.size_in) decodedAudioChunkAsLst = decodeInstance.decode_chunk(byteChunkDataLst, out_chunk_header.size_out / self.get_cb_sample()); binaryDataOutLst.extend(decodedAudioChunkAsLst) wIndex += out_chunk_header.size_out - #print("Debug:: New Windex= %d\t cb_audio= %d") % (wIndex,cb_audio) + #print("[Debug] New Windex: %d\t cb_audio: %d") % (wIndex,cb_audio) chunk_i += 1 binaryDataOutBuff = struct.pack('h'*len(binaryDataOutLst), *binaryDataOutLst) + if self.m_traceModeEnabled: + if binaryDataOutBuff is not None: + if self.m_traceModeEnabled: + print "[Debug] Decoding Done." + else: #if binaryDataOutBuff is None: + print "[Error] Decoding yielded errors (data out buffer is null)." return binaryDataOutBuff def header(self): @@ -302,23 +317,25 @@ class audFile: # if __name__ == '__main__': # main() - print "Debug:: Running %s as main module" % (my_module_name) + print "[Debug] Running %s as main module" % (my_module_name) # assumes a file of name 000000.AUD in same directory inAUDFile = None + inAUDFileName = '00000000.AUD' + errorFound = False try: - inAUDFile = open(os.path.join('.','00000000.AUD'), 'rb') + inAUDFile = open(os.path.join('.', inAUDFileName), 'rb') except: errorFound = True - print "Error:: Unexpected event:", sys.exc_info()[0] + print "[Error] Unexpected event:", sys.exc_info()[0] raise if not errorFound: allOfAudFileInBuffer = inAUDFile.read() - audFileInstance = audFile() - audFileInstance.loadAudFile(allOfAudFileInBuffer, len(allOfAudFileInBuffer)) - audFileInstance.extract_as_wav(allOfAudFileInBuffer, './tmp.wav') + audFileInstance = audFile(True) + audFileInstance.loadAudFile(allOfAudFileInBuffer, len(allOfAudFileInBuffer), inAUDFileName) + audFileInstance.export_as_wav(allOfAudFileInBuffer, './tmp.wav') inAUDFile.close() else: #debug - #print "Debug:: Running %s imported from another module" % (my_module_name) + #print "[Debug] Running %s imported from another module" % (my_module_name) pass \ No newline at end of file diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/quoteSpreadsheetCreator.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/quoteSpreadsheetCreator.py index 158d3e1b78..83c6db7e5a 100644 --- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/quoteSpreadsheetCreator.py +++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/quoteSpreadsheetCreator.py @@ -2,7 +2,7 @@ # -*- coding: UTF-8 -*- import sys if not (sys.version_info[0] == 2 and sys.version_info[1] == 7): - sys.stdout.write("Error:: Blade Runner Quotes Spreadsheet Creator script requires Python 2.7\n") + sys.stdout.write("[Error] Blade Runner Quotes Spreadsheet Creator script requires Python 2.7\n") sys.exit(1) import sortBladeRunnerWavs02 diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py index e6e7ac66d5..60094b94d8 100644 --- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py +++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py @@ -4,7 +4,7 @@ # Created by Praetorian (ShadowNate) for Classic Adventures in Greek # classic.adventures.in.greek@gmail.com # -# DONE Add code and switch option: to get the blade runner installation directory as input, then find the TLK files and extract them with proper naming +# DONE Add code and switch option: to get the blade runner installation directory as input, then find the TLK files and export them with proper naming # DONE fix proper names for sheets as per latest code changes # import os, sys @@ -16,26 +16,26 @@ csvLibFound = False try: import shutil except ImportError: - print "Error:: Shutil python library is required to be installed!" + print "[Error] Shutil python library is required to be installed!" else: shutilLibFound = True try: import xlwt except ImportError: - print "Error:: xlwt python library is required to be installed!" + print "[Error] xlwt python library is required to be installed!" else: xlwtLibFound = True try: import csv except ImportError: - print "Error:: csv python library is required to be installed!" + print "[Error] csv python library is required to be installed!" else: csvLibFound = True if (not shutilLibFound) or (not xlwtLibFound) or (not csvLibFound): - sys.stdout.write("Error:: Errors were found when trying to import required python libraries\n") + sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n") sys.exit(1) from os import walk, errno, path @@ -51,15 +51,11 @@ COMPANY_EMAIL = "classic.adventures.in.greek@gmail.com" APP_VERSION = "0.80" APP_NAME = "sortBladeRunnerWavs" APP_WRAPPER_NAME = "quotesSpreadsheetCreator.py" -APP_NAME_spaced = "Blade Runner Transcript Excel Creator (bare bones)" -APP_SHORT_DESC = "Create an Excel (.XLS) for transcribing Blade Runner. It can also extract TRx (x is the language code of the game) files and export WAV files for game's resources. " -gTraceModeEnabled = False -gActiveLanguageDescriptionCodeTuple = '' +APP_NAME_SPACED = "Blade Runner Transcript Excel Creator (bare bones)" +APP_SHORT_DESC = "* Create an Excel (.XLS) for transcribing Blade Runner.\n* (Optional) Extract TRx (x is the language code) files as additional sheets in the Excel\n* (Optional) Export speech files from the game's TLK resources to WAV format." -gStringReplacementForRootFolderWithExtractedFiles = "" -gNumReplaceStartingCharacters = 0 - -OUTPUT_XLS_FILENAME = 'out.xls' +OUTPUT_XLS_FILENAME = 'out' +OUTPUT_XLS_FILENAME_EXT = '.xls' OUTPUT_XLS_QUOTES_SHEET = 'INGQUO_E.TR' SUPPORTED_TLK_INPUT_FILES = [('1.TLK', 'TLK01'), ('2.TLK', 'TLK02'), ('3.TLK', 'TLK03'), ('A.TLK', 'TLK0A'), ('SPCHSFX.TLK', 'TLKSPCHSFX')] @@ -68,9 +64,15 @@ SUPPORTED_MIX_INPUT_FILES = ['STARTUP.MIX'] SUPPORTED_EXPORTED_TRx_FILES = ['CLUES.TR','ACTORS.TR','CRIMES.TR','CLUETYPE.TR','KIA.TR','SPINDEST.TR','VK.TR','OPTIONS.TR','DLGMENU.TR','ENDCRED.TR','HELP.TR','SCORERS.TR','KIACRED.TR','ERRORMSG.TR','AUTOSAVE.TR'] SUPPORTED_PLACEHOLDER_VQA_FILES = ['WSTLGO_', 'BRLOGO_', 'INTRO_', 'MW_A_', 'MW_B01_', 'MW_B02_', 'MW_B03_', 'MW_B04_', 'MW_B05_', 'INTRGT_', 'MW_D_', 'MW_C01_', 'MW_C02_', 'MW_C03_', 'END04A_', 'END04B_', 'END04C_', 'END06_', 'END01A_', 'END01B_', 'END01C_', 'END01D_', 'END01E_', 'END01F_', 'END03_'] -SUPPORTED_LANGUAGES_DESCRIPTION_CODE_TLIST = [('EN_ANY', 'E', 'English'), ('DE_DEU', 'G', 'German'), ('FR_FRA', 'F', 'French'), ('IT_ITA', 'I', 'Italian'), ('RU_RUS', 'R', 'Russian'), ('ES_ESP', 'S', 'Spanish')] +SUPPORTED_LANGUAGES_DESCRIPTION_CODE_TLIST = [('EN_ANY', 'E', 'English'), ('DE_DEU', 'G', 'German'), ('FR_FRA', 'F', 'French'), ('IT_ITA', 'I', 'Italian'), ('ES_ESP', 'S', 'Spanish'), ('RU_RUS', 'R', 'Russian')] DEFAULT_LANG_DESC_CODE = SUPPORTED_LANGUAGES_DESCRIPTION_CODE_TLIST[0] +gTraceModeEnabled = False +gActiveLanguageDescriptionCodeTuple = '' + +gStringReplacementForRootFolderWithExportedFiles = "" +gNumReplaceStartingCharacters = 0 + gWavFiles = [] gWavFilesNoDups = [] gActorPropertyEntries = [] #[0]:id, [1]:ShortHand Name [2]:Full Name @@ -104,18 +106,18 @@ def initActorPropertyEntries(thePathToActorNamesTxt): global gActorPropertyEntriesWasInit global gActorPropertyEntries firstLine = True -# print "opening actornames" +# print "[Debug] opening actornames" if thePathToActorNamesTxt is None or not thePathToActorNamesTxt: actorNamesTextFile = u'actornames.txt' relPath = u'.' thePathToActorNamesTxt = os.path.join(relPath, actorNamesTextFile) - print "Warning:: Actor names text file %s not found in arguments. Attempting to open local file if it exists" % (thePathToActorNamesTxt) + print "[Warning] Actor names text file %s not found in arguments. Attempting to open local file if it exists" % (thePathToActorNamesTxt) with open(thePathToActorNamesTxt) as tsv: for line in csv.reader(tsv, dialect="excel-tab"): #skip first line header if firstLine == True: -# print "skippingHeader" +# print "[Debug] Skipping Header line in Excel sheet" firstLine = False else: gActorPropertyEntries.append(line) @@ -161,7 +163,7 @@ def getActorShortNameAndLocalQuoteIdByAUDHashID(audHashId): actorShortName = '' actorLocalQuoteId = 0 if not gActorPropertyEntriesWasInit: - print "Error:: actor properties were not initialized!" + print "[Error] actor properties were not initialized!" return (actorId, actorShortName, actorLocalQuoteId) for actorEntryTmp in gActorPropertyEntries: @@ -183,7 +185,7 @@ def ensure_dir(directory): # # Reading in the INPUT TLK files and checking all the AUD file properties # -def inputTLKsExtract(inputTLKpath, outputWAVpath): +def inputTLKsExport(inputTLKpath, outputWAVpath): # try to open all TLK file entries from SUPPORTED_TLK_INPUT_FILES # then per TLK file # create an output folder in the OUTPUT PATH named TLK## for the 1, 2, 3 TLK and TLKSPCHSFX for the SPCHSFX.TLK @@ -194,7 +196,7 @@ def inputTLKsExtract(inputTLKpath, outputWAVpath): # fileID # segment offset # file size - print "Info:: Checking in %s for TLK files to extract to %s" % (inputTLKpath, outputWAVpath) + print "[Info] Checking in %s for TLK files to export to %s" % (inputTLKpath, outputWAVpath) inputTLKFilesFound = [] # breaking after first for loop yields only the top directory files, which is what we want for (dirpath, dirnames, filenames) in walk(inputTLKpath): @@ -205,7 +207,7 @@ def inputTLKsExtract(inputTLKpath, outputWAVpath): break for tmpTLKfileTuple in inputTLKFilesFound: if gTraceModeEnabled: - print "Info:: Found TLK: %s" % ('"' + inputTLKpath + tmpTLKfileTuple[0] + '"') + print "[Info] Found TLK: %s" % ('"' + inputTLKpath + tmpTLKfileTuple[0] + '"') errorFound = False inTLKFile = None # @@ -217,13 +219,13 @@ def inputTLKsExtract(inputTLKpath, outputWAVpath): inTLKFile = open(os.path.join(inputTLKpath,tmpTLKfileTuple[0]), 'rb') except: errorFound = True - print "Error:: Unexpected event:", sys.exc_info()[0] + print "[Error] Unexpected event:", sys.exc_info()[0] raise if not errorFound: tmpBuff = inTLKFile.read(2) # H: unsigned short (2 bytes) followed by I: unsigned int (4 bytes) tlkFileEntriesNumTuple = struct.unpack('H', tmpBuff) - numOfEntriesToExtract = tlkFileEntriesNumTuple[0] + numOfTREEntriesToExtract = tlkFileEntriesNumTuple[0] tmpBuff = inTLKFile.read(4) tlkFileDataSegmentSizeTuple = struct.unpack('I', tmpBuff) allTlkFileSize = tlkFileDataSegmentSizeTuple[0] @@ -234,9 +236,9 @@ def inputTLKsExtract(inputTLKpath, outputWAVpath): # 12 bytes per TLK entry in entries table # quick size validation if gTraceModeEnabled: - print "Debug:: Entries= %d, Data segment size= %d bytes" % (numOfEntriesToExtract, allTlkFileSize) - if allActualBytesInMixFile != 2 + 4 + 12 * numOfEntriesToExtract + allTlkFileSize: - print "Error:: TLK file size mismatch with reported size in header for %s!" % (tmpTLKfileTuple[0]) + print "[Debug] Entries: %d, Data segment size: %d bytes" % (numOfTREEntriesToExtract, allTlkFileSize) + if allActualBytesInMixFile != 2 + 4 + 12 * numOfTREEntriesToExtract + allTlkFileSize: + print "[Error] TLK file size mismatch with reported size in header for %s!" % (tmpTLKfileTuple[0]) else: # # 12 bytes per entry @@ -244,7 +246,7 @@ def inputTLKsExtract(inputTLKpath, outputWAVpath): # 4 bytes: Offset in data segment # 4 bytes: Size of data # - for i in range(0, numOfEntriesToExtract): + for i in range(0, numOfTREEntriesToExtract): inTLKFile.seek(2 + 4 + 12*i) tmpBuff = inTLKFile.read(4) tmpRdTuple = struct.unpack('I', tmpBuff) @@ -256,7 +258,7 @@ def inputTLKsExtract(inputTLKpath, outputWAVpath): tmpRdTuple = struct.unpack('I', tmpBuff) sizeOfAUDEntry = tmpRdTuple[0] if gTraceModeEnabled: - print "Debug:: Entry= %s, offset %s, Data segment size= %s bytes" % (''.join('{:08X}'.format(idOfAUDEntry)), ''.join('{:08X}'.format(offsetOfAUDEntry)),''.join('{:08X}'.format(sizeOfAUDEntry))) + print "[Debug] Entry: %s, offset: %s, Data segment size: %s bytes" % (''.join('{:08X}'.format(idOfAUDEntry)), ''.join('{:08X}'.format(offsetOfAUDEntry)),''.join('{:08X}'.format(sizeOfAUDEntry))) # # put file in AUD object # do we need AUD decode? @@ -266,33 +268,36 @@ def inputTLKsExtract(inputTLKpath, outputWAVpath): # then: # AudFile aud; # aud.loadAudFile(fs); (fs is file stream) - # aud.extract_as_wav(fs, offset, offset + int(sizeof(AudHeader)) + aud.header().size_in, target); + # aud.export_as_wav(fs, offset, offset + int(sizeof(AudHeader)) + aud.header().size_in, target); # # - inTLKFile.seek(2 + 4 + 12*numOfEntriesToExtract + offsetOfAUDEntry) + inTLKFile.seek(2 + 4 + 12*numOfTREEntriesToExtract + offsetOfAUDEntry) if(offsetOfAUDEntry + sizeOfAUDEntry > allTlkFileSize): - print "Error:: AUD file size mismatch with reported size in entry header!" + print "[Error] audio file (AUD) file size mismatch with reported size in entry header!" else: + targetSimpleAudFileName = ''.join('{:08X}'.format(idOfAUDEntry)).upper()+'.AUD' audFileBuffer = inTLKFile.read(sizeOfAUDEntry) if (len(audFileBuffer) == sizeOfAUDEntry): - # load Aud file - thisAudFile = audFile() - if (thisAudFile.loadAudFile(audFileBuffer, allTlkFileSize)): - # print "AUD file load successful!" + # load audio file (AUD) file + thisAudFile = audFile(gTraceModeEnabled) + if (thisAudFile.loadAudFile(audFileBuffer, allTlkFileSize, targetSimpleAudFileName)): + if gTraceModeEnabled: + print "[Debug] Audio file (AUD) file %s was loaded successfully!" % (targetSimpleAudFileName) # find - # print "Emulating Wav write to appropriate folder..." + # print "[Debug] Emulating Wav write to appropriate folder..." (actorID, actorSName, localQuoteId) = getActorShortNameAndLocalQuoteIdByAUDHashID(idOfAUDEntry) - targetSimpleFileName = actorSName + '_' + str(localQuoteId).zfill(4) + '_' + ''.join('{:08X}'.format(idOfAUDEntry)).upper()+'.WAV' - #print os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleFileName) - if not os.path.isfile(os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleFileName) ): - thisAudFile.extract_as_wav(audFileBuffer, os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleFileName) ) + targetSimpleWavFileName = actorSName + '_' + str(localQuoteId).zfill(4) + '_' + ''.join('{:08X}'.format(idOfAUDEntry)).upper()+'.WAV' + #print os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleWavFileName) + if not os.path.isfile(os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleWavFileName) ): + thisAudFile.export_as_wav(audFileBuffer, os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleWavFileName) ) else: if gTraceModeEnabled: - print "Info:: Output file %s already exists. Skipping..." % (os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleFileName)) + print "[Info] Output file %s already exists. Skipping..." % (os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleWavFileName)) else: - print "Error:: while LOADING aud file!" + print "[Error] while loading audio file (AUD) %s!" % (targetSimpleAudFileName) else: - print "Error:: while reading AUD file %s into mem buffer" % (''.join('{:08X}'.format(idOfAUDEntry))) + print "[Error] while reading audio file (AUD) file %s into mem buffer" % (targetSimpleAudFileName) + #print "[Error] while reading audio file (AUD) file %s into mem buffer" % (''.join('{:08X}'.format(idOfMIXEntry))) inTLKFile.close() @@ -301,7 +306,7 @@ def inputTLKsExtract(inputTLKpath, outputWAVpath): return def inputMIXExtractTREs(inputMIXpath, excelOutBook = None): - print "Info:: Checking in %s for MIX files to extract Text Resources (TR%ss) from..." % (inputMIXpath, gActiveLanguageDescriptionCodeTuple[1]) + print "[Info] Checking in %s for MIX files to extract Text Resources (TR%ss) from..." % (inputMIXpath, gActiveLanguageDescriptionCodeTuple[1]) inputMIXFilesFound = [] # breaking after first for loop yields only the top directory files, which is what we want for (dirpath, dirnames, filenames) in walk(inputMIXpath): @@ -312,7 +317,7 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None): break for tmpMIXfileName in inputMIXFilesFound: if gTraceModeEnabled: - print "Info:: Found MIX file: %s" % ('"' + tmpMIXfileName + '"') + print "[Info] Found MIX file: %s" % ('"' + tmpMIXfileName + '"') errorFound = False inMIXFile = None # @@ -320,14 +325,14 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None): inMIXFile = open(os.path.join(inputMIXpath,tmpMIXfileName), 'rb') except: errorFound = True - print "Error:: Unexpected event:", sys.exc_info()[0] + print "[Error] Unexpected event:", sys.exc_info()[0] raise if not errorFound: totalTREs = 0 tmpBuff = inMIXFile.read(2) # H: unsigned short (2 bytes) followed by I: unsigned int (4 bytes) mixFileEntriesNumTuple = struct.unpack('H', tmpBuff) - numOfEntriesToExtract = mixFileEntriesNumTuple[0] + numOfTREEntriesToExtract = mixFileEntriesNumTuple[0] tmpBuff = inMIXFile.read(4) mixFileDataSegmentSizeTuple = struct.unpack('I', tmpBuff) allMixFileSize = mixFileDataSegmentSizeTuple[0] @@ -338,9 +343,9 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None): # 12 bytes per MIX entry in entries table # quick size validation if gTraceModeEnabled: - print "Debug:: Entries= %d, Data segment size= %d bytes" % (numOfEntriesToExtract, allMixFileSize) - if allActualBytesInMixFile != 2 + 4 + 12 * numOfEntriesToExtract + allMixFileSize: - print "Error:: MIX file size mismatch with reported size in header for %s!" % (tmpMIXfileName) + print "[Debug] Entries: %d, Data segment size: %d bytes" % (numOfTREEntriesToExtract, allMixFileSize) + if allActualBytesInMixFile != 2 + 4 + 12 * numOfTREEntriesToExtract + allMixFileSize: + print "[Error] MIX file size mismatch with reported size in header for %s!" % (tmpMIXfileName) else: # # 12 bytes per entry @@ -348,7 +353,7 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None): # 4 bytes: Offset in data segment # 4 bytes: Size of data # - for i in range(0, numOfEntriesToExtract): + for i in range(0, numOfTREEntriesToExtract): foundTREFile = False currTreFileName = 'UNKNOWN.TR%s' % (gActiveLanguageDescriptionCodeTuple[1]) inMIXFile.seek(2 + 4 + 12*i) @@ -371,23 +376,23 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None): if (foundTREFile == True): if gTraceModeEnabled: - print "Debug:: Entry Name= %s, Entry ID= %s, offset= %s, Data segment size= %s bytes" % (currTreFileName, ''.join('{:08X}'.format(idOfMIXEntry)), ''.join('{:08X}'.format(offsetOfMIXEntry)),''.join('{:08X}'.format(sizeOfMIXEntry))) + print "[Debug] Entry Name: %s, Entry ID: %s, offset: %s, Data segment size: %s bytes" % (currTreFileName, ''.join('{:08X}'.format(idOfMIXEntry)), ''.join('{:08X}'.format(offsetOfMIXEntry)),''.join('{:08X}'.format(sizeOfMIXEntry))) # # IF TRE FILE: # put file in TRE object # # - inMIXFile.seek(2 + 4 + 12*numOfEntriesToExtract + offsetOfMIXEntry) + inMIXFile.seek(2 + 4 + 12*numOfTREEntriesToExtract + offsetOfMIXEntry) if(offsetOfMIXEntry + sizeOfMIXEntry > allMixFileSize): - print "Error:: TR%s file size mismatch with reported size in entry header!" % (gActiveLanguageDescriptionCodeTuple[1]) + print "[Error] TR%s file size mismatch with reported size in entry header!" % (gActiveLanguageDescriptionCodeTuple[1]) else: treFileBuffer = inMIXFile.read(sizeOfMIXEntry) if (len(treFileBuffer) == sizeOfMIXEntry): # load TRE file - thisTreFile = treFile() - if (thisTreFile.loadTreFile(treFileBuffer, allMixFileSize)): + thisTreFile = treFile(gTraceModeEnabled) + if (thisTreFile.loadTreFile(treFileBuffer, allMixFileSize, currTreFileName)): if gTraceModeEnabled: - print "Info:: TR%s file loaded" % (gActiveLanguageDescriptionCodeTuple[1]) + print "[Debug] TR%s file %s was loaded successfully!" % (gActiveLanguageDescriptionCodeTuple[1], currTreFileName) if excelOutBook != None: sh = excelOutBook.add_sheet(currTreFileName) n = 0 # keeps track of rows @@ -530,21 +535,22 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None): try: objUTF8Unicode = unicode(objUTF8SafeStr, 'utf-8') except Exception as e: - print 'Error:: Failed to create unicode string: ' + str(e) + print '[Error] Failed to create unicode string: ' + str(e) objUTF8Unicode = unicode("???", 'utf-8') sh.write(m, 1, objUTF8Unicode) #for tupleIdString in thisTreFile.stringEntriesLst: - # #print "Id: %d\t Text: %s" % (tupleIdString[0], tupleIdString[1]) + # #print "[Debug] Id: %d\t Text: %s" % (tupleIdString[0], tupleIdString[1]) # pass totalTREs = totalTREs + 1 else: - print "Error:: while LOADING TR%s file!" % (gActiveLanguageDescriptionCodeTuple[1]) + print "[Error] while loading TR%s %s file!" % (gActiveLanguageDescriptionCodeTuple[1], currTreFileName) else: - print "Error:: while reading TR%s file %s into mem buffer" % (gActiveLanguageDescriptionCodeTuple[1], ''.join('{:08X}'.format(idOfMIXEntry))) + print "[Error] while reading TR%s file %s into mem buffer" % (gActiveLanguageDescriptionCodeTuple[1], currTreFileName) + #print "[Error] while reading TR%s file %s into mem buffer" % (gActiveLanguageDescriptionCodeTuple[1], ''.join('{:08X}'.format(idOfMIXEntry))) inMIXFile.close() - print "Info:: Total TR%ss handled: %d " % (gActiveLanguageDescriptionCodeTuple[1], totalTREs) + print "[Info] Total TR%ss processed: %d " % (gActiveLanguageDescriptionCodeTuple[1], totalTREs) return @@ -552,7 +558,7 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None): # Creating the OUTPUT XLS file with one sheet named as the @param sheet with entries based on the list1 (wav files, without duplicates) # def outputXLS(filename, sheet, list1, parseTREResourcesAlso = False, mixInputFolderPath = ''): - global gStringReplacementForRootFolderWithExtractedFiles + global gStringReplacementForRootFolderWithExportedFiles global gNumReplaceStartingCharacters book = xlwt.Workbook() sh = book.add_sheet(sheet) @@ -620,8 +626,8 @@ def outputXLS(filename, sheet, list1, parseTREResourcesAlso = False, mixInputFol # real path of filename realPathOfFileNameToLink = twoTokensOfRelDirnameAndFilenameXLS[2] # checks if not empty - if gStringReplacementForRootFolderWithExtractedFiles and gNumReplaceStartingCharacters > 0: - realPathOfFileNameToLink = realPathOfFileNameToLink.replace(realPathOfFileNameToLink[:gNumReplaceStartingCharacters], gStringReplacementForRootFolderWithExtractedFiles) + if gStringReplacementForRootFolderWithExportedFiles and gNumReplaceStartingCharacters > 0: + realPathOfFileNameToLink = realPathOfFileNameToLink.replace(realPathOfFileNameToLink[:gNumReplaceStartingCharacters], gStringReplacementForRootFolderWithExportedFiles) #works in Linux + Libreoffice # also works in Windows + LibreOffice (run from msys) -- tried something like: @@ -651,8 +657,9 @@ def outputXLS(filename, sheet, list1, parseTREResourcesAlso = False, mixInputFol # TODO handle special string characters (to UTF-8) try: book.save(filename) - except: - print "Error:: Could not save the output Excel file (maybe it's open?)" + print "[Info] Done." + except Exception as e: + print "[Error] Could not save the output Excel file (maybe it's open?). " + str(e) # # Aux function to validate input language description @@ -681,7 +688,7 @@ def printInfoMessageForLanguageSelectionSyntax(): def main(argsCL): # TODO parse arguments using argparse? https://docs.python.org/3/library/argparse.html#module-argparse global gTraceModeEnabled - global gStringReplacementForRootFolderWithExtractedFiles + global gStringReplacementForRootFolderWithExportedFiles global gNumReplaceStartingCharacters global gActiveLanguageDescriptionCodeTuple global gWavFiles @@ -694,40 +701,41 @@ def main(argsCL): pathToActorNamesTxt = "" candidateLangDescriptionTxt = "" - TMProotFolderWithExtractedFiles = "" + TMProotFolderWithExportedFiles = "" TMProotFolderWithInputTLKFiles = "" - extractWavFilesMode = False + exportWavFilesMode = False extractTreFilesMode = False invalidSyntax = False - print "Running %s (%s)..." % (APP_NAME_spaced, APP_VERSION) + print "Running %s (%s)..." % (APP_NAME_SPACED, APP_VERSION) # print "Len of sysargv = %s" % (len(argsCL)) if len(argsCL) == 2: if(argsCL[1] == '--help'or argsCL[1] == '-h'): - print "%s %s supports Blade Runner (English version, CD edition)." % (APP_NAME_spaced, APP_VERSION) + print "%s %s supports Westwood's Blade Runner PC Game (1997)." % (APP_NAME_SPACED, APP_VERSION) print APP_SHORT_DESC print "Created by Praetorian of the classic adventures in Greek team." print "Always keep backups!" print "--------------------" - print "%s takes has one mandatory argument, the folder of the extracted WAV files:" % (APP_WRAPPER_NAME) - print "Valid syntax: %s -op folderpath_for_extracted_wav_Files [-ip folderpath_for_TLK_Files] [-ian path_to_actornames_txt] [-m stringPathToReplaceFolderpathInExcelLinks] [-ld gameInputLanguageDescription] [-xwav] [-xtre] [--trace]" % (APP_WRAPPER_NAME) - print "The -op switch has an argument that is the path for extracted WAV files folder. The -op switch is REQUIRED always." + print "%s takes has one mandatory argument, ie. the folder of the exported WAV files:" % (APP_WRAPPER_NAME) + print "Valid syntax: %s -op folderpath_for_exported_wav_Files [-ip folderpath_for_TLK_Files] [-ian path_to_actornames_txt] [-m stringPathToReplaceFolderpathInExcelLinks] [-ld gameInputLanguageDescription] [-xwav] [-xtre] [--trace]" % (APP_WRAPPER_NAME) + print "The -op switch has an argument that is the path for exported WAV files folder. The -op switch is REQUIRED always." print "The -ip switch has an argument that is the path for the input (TLK or MIX) files folder (can be the same as the Blade Runner installation folder)." print "The -ian switch is followed by the path to actornames.txt, if it's not in the current working directory." - print "The -m switch has an argument that is a replacement string for the path to the folder of extracted WAV files which will be used as a prefix for the links in the output XLS file." + print "The -m switch has an argument that is a replacement string for the path to the folder of exported WAV files which will be used as a prefix for the links in the output XLS file." print "The -ld switch has an argument that is the language description of the original game files that you use as input." printInfoMessageForLanguageSelectionSyntax() - print "The -xwav switch enables the WAV audio extract mode from the TLK files. It requires an INPUT path to be set with the -ip switch." - print "The -xtre switch enables the TR%s parsing mode from the original MIX files. It requires an INPUT path to be set with the -ip switch." % (gActiveLanguageDescriptionCodeTuple[1]) + print "The -xwav switch enables the WAV audio export mode from the TLK files. It requires an INPUT path to be set with the -ip switch." + print "The -xtre switch enables the TRx parsing mode from the original MIX files. It requires an INPUT path to be set with the -ip switch." print "The --trace switch enables more debug messages being printed during execution." - print "If the app finishes successfully a sortedWavs.xls file will be created in the same folder with the app." + print "--------------------" + print "If the app finishes successfully, a file named %s-(language)%s will be created in the current working folder." % (OUTPUT_XLS_FILENAME, OUTPUT_XLS_FILENAME_EXT) print "--------------------" print "Thank you for using this app." print "Please provide any feedback to: %s " % (COMPANY_EMAIL) sys.exit() elif(argsCL[1] == '--version' or argsCL[1] == '-v'): - print "%s %s supports Blade Runner (English version, CD edition)." % (APP_NAME_spaced, APP_VERSION) + print "%s %s supports Westwood's Blade Runner PC Game (1997)." % (APP_NAME_SPACED, APP_VERSION) print "Please provide any feedback to: %s " % (COMPANY_EMAIL) sys.exit() else: @@ -736,56 +744,56 @@ def main(argsCL): for i in range(1, len(argsCL)): if( i < (len(argsCL) - 1) and argsCL[i][:1] == '-' and argsCL[i+1][:1] != '-'): if (argsCL[i] == '-op'): - TMProotFolderWithExtractedFiles = argsCL[i+1] - gNumReplaceStartingCharacters = len(TMProotFolderWithExtractedFiles) + TMProotFolderWithExportedFiles = argsCL[i+1] + gNumReplaceStartingCharacters = len(TMProotFolderWithExportedFiles) elif (argsCL[i] == '-ip'): TMProotFolderWithInputTLKFiles = argsCL[i+1] elif (argsCL[i] == '-m'): - gStringReplacementForRootFolderWithExtractedFiles = argsCL[i+1] + gStringReplacementForRootFolderWithExportedFiles = argsCL[i+1] elif (argsCL[i] == '-ian'): pathToActorNamesTxt = argsCL[i+1] elif (argsCL[i] == '-ld'): - candidateLangDescriptionTxt = argsCL[i+1] + candidateLangDescriptionTxt = argsCL[i+1] elif (argsCL[i] == '-xwav'): - print "Info:: Extract WAVs from TLK files mode enabled." - extractWavFilesMode = True + print "[Info] Export WAVs from TLK files mode enabled." + exportWavFilesMode = True elif (argsCL[i] == '-xtre'): - print "Info:: Extract Text Resources (TR%ss) mode enabled." % (gActiveLanguageDescriptionCodeTuple[1]) + print "[Info] Extract Text Resources (TRx) mode enabled." extractTreFilesMode = True elif argsCL[i] == '--trace': - print "Info:: Trace mode enabled (more debug messages)." + print "[Info] Trace mode enabled (more debug messages)." gTraceModeEnabled = True - if not TMProotFolderWithExtractedFiles: # this argument is mandatory + if not TMProotFolderWithExportedFiles: # this argument is mandatory invalidSyntax = True - if (not invalidSyntax) and (extractWavFilesMode == True or extractTreFilesMode == True) and (TMProotFolderWithInputTLKFiles == ''): + if (not invalidSyntax) and (exportWavFilesMode == True or extractTreFilesMode == True) and (TMProotFolderWithInputTLKFiles == ''): invalidSyntax = True - gActiveLanguageDescriptionCodeTuple = getLanguageDescCodeTuple(candidateLangDescriptionTxt) + gActiveLanguageDescriptionCodeTuple = getLanguageDescCodeTuple(candidateLangDescriptionTxt) if (not invalidSyntax) and gActiveLanguageDescriptionCodeTuple is None: - print "Error:: Invalid language code was specified" + print "[Error] Invalid language code was specified" printInfoMessageForLanguageSelectionSyntax() invalidSyntax = True if not invalidSyntax: - print "Info:: Game Language Selected: %s (%s)" % (gActiveLanguageDescriptionCodeTuple[0], gActiveLanguageDescriptionCodeTuple[2]) + print "[Info] Game Language Selected: %s (%s)" % (gActiveLanguageDescriptionCodeTuple[0], gActiveLanguageDescriptionCodeTuple[2]) # parse Actors files: initActorPropertyEntries(pathToActorNamesTxt) # for actorEntryTmp in gActorPropertyEntries: -# print "Found actor: %s %s %s" % (actorEntryTmp[0], actorEntryTmp[1], actorEntryTmp[2]) +# print "[Debug] Found actor: %s %s %s" % (actorEntryTmp[0], actorEntryTmp[1], actorEntryTmp[2]) # - # Checking for the optional case of parsing the input TLK files to extract to WAV + # Checking for the optional case of parsing the input TLK files to export to WAV # if TMProotFolderWithInputTLKFiles != '': - if (extractWavFilesMode == True): - inputTLKsExtract(TMProotFolderWithInputTLKFiles, TMProotFolderWithExtractedFiles) + if (exportWavFilesMode == True): + inputTLKsExport(TMProotFolderWithInputTLKFiles, TMProotFolderWithExportedFiles) #if (extractTreFilesMode == True): # inputMIXExtractTREs(TMProotFolderWithInputTLKFiles) # - # Parsing the extracted WAV files + # Parsing the exported WAV files # - print "Info:: Parsing the extracted WAV audio files. Please wait (this could take a while)..." - for (dirpath, dirnames, filenames) in walk(TMProotFolderWithExtractedFiles): + print "[Info] Parsing the exported WAV audio files. Please wait (this could take a while)..." + for (dirpath, dirnames, filenames) in walk(TMProotFolderWithExportedFiles): for nameIdx, nameTmp in enumerate(filenames): relDirName = '' # os.path.split would Split the pathname path into a pair, (head, tail) where tail is the last pathname component and head is everything leading up to that. The tail part will never contain a slash @@ -801,19 +809,19 @@ def main(argsCL): for fileIdx, filenameTmp in enumerate(gWavFiles): twoTokensOfFilenameAndRelDirname = filenameTmp.split('&', 1) if len(twoTokensOfFilenameAndRelDirname) != 2: - print "ERROR in filename and rel dirname split: %s" % (filenameTmp) + print "[Error] in filename and rel dirname split: %s" % (filenameTmp) sys.exit(0) twoTokensOfFilenameForExt = twoTokensOfFilenameAndRelDirname[0].split('.', 1) if len(twoTokensOfFilenameForExt) == 2: if twoTokensOfFilenameForExt[1] != 'WAV' and twoTokensOfFilenameForExt[1] != 'wav': - print "ERROR in proper extension (not WAV): %s" % (twoTokensOfFilenameAndRelDirname[0]) + print "[Error] in proper extension (not WAV): %s" % (twoTokensOfFilenameAndRelDirname[0]) sys.exit(0) else: - print "ERROR in extension split: %s" % (twoTokensOfFilenameAndRelDirname[0]) + print "[Error] in extension split: %s" % (twoTokensOfFilenameAndRelDirname[0]) sys.exit(0) #remove WAV extension here # filenameTmp = twoTokensOfFilenameAndRelDirname[0] + '&' + twoTokensOfFilenameForExt[0] -# print "Found %s" % (filenameTmp) +# print "[Debug] Found %s" % (filenameTmp) threeTokensOfFilename = twoTokensOfFilenameForExt[0].split('_', 2) if len(threeTokensOfFilename) == 3: @@ -830,11 +838,11 @@ def main(argsCL): threeTokensOfFilename.append(tmpActorFullName) else: #fatal error if something cannot convert to spot it immediately - print "ERROR in actorIdMatch match: %s %s" % (tmpActorId, twoTokensOfFilenameForExt[0]) + print "[Error] in actorIdMatch match: %s %s" % (tmpActorId, twoTokensOfFilenameForExt[0]) sys.exit(0) else: #fatal error if something cannot convert to spot it immediately - print "ERROR in shorthand match: %s %s" % (threeTokensOfFilename[0], twoTokensOfFilenameForExt[0]) + print "[Error] in shorthand match: %s %s" % (threeTokensOfFilename[0], twoTokensOfFilenameForExt[0]) sys.exit(0) # # @@ -850,7 +858,7 @@ def main(argsCL): filenameTmp = twoTokensOfFilenameForExt[0] + '&' + twoTokensOfFilenameAndRelDirname[1] gWavFiles[fileIdx] = filenameTmp else: - print "ERROR in spliting tokens on _: %s" % (filenameTmp) + print "[Error] in splitting tokens on _: %s" % (filenameTmp) sys.exit(0) #sort in-place # @@ -886,7 +894,7 @@ def main(argsCL): # for filenameSrcTmp in gWavFiles: duplicateFound = False -# print "Converted %s" % (filenameSrcTmp) +# print "[Debug]Converted %s" % (filenameSrcTmp) # Weed out duplicates by copying to another table (quick and dirty) twoTokensOfRelDirnameAndFilenameSrc = filenameSrcTmp.split('&', 2) tmpRelDirNameSrc = twoTokensOfRelDirnameAndFilenameSrc[1] @@ -900,28 +908,30 @@ def main(argsCL): #concatenate actorID and quoteID for search key keyForDuplicateSearchTarg = threeTokensOfQuoteFilenameTarg[0] + threeTokensOfQuoteFilenameTarg[1] if(keyForDuplicateSearchSrc == keyForDuplicateSearchTarg): - #print "Found duplicate %s" % (filenameSrcTmp) + #print "[Debug] Found duplicate %s" % (filenameSrcTmp) duplicateFound = True gWavFilesNoDups[fileTargIdx] = twoTokensOfRelDirnameAndFilenameTarg[0] + '&' + tmpRelDirNameSrc + ',' + tmpRelDirNameTarg + '&' + twoTokensOfRelDirnameAndFilenameTarg[2] break if(duplicateFound == False): gWavFilesNoDups.append(filenameSrcTmp) # for filenameSrcTmp in gWavFilesNoDups: -# print "Unique %s" % (filenameSrcTmp) - print "Info:: Creating output excel %s file..." % (OUTPUT_XLS_FILENAME) - outputXLS(OUTPUT_XLS_FILENAME, OUTPUT_XLS_QUOTES_SHEET + gActiveLanguageDescriptionCodeTuple[1], gWavFilesNoDups, extractTreFilesMode, TMProotFolderWithInputTLKFiles) +# print "[Debug] Unique %s" % (filenameSrcTmp) + constructedOutputFilename = "%s-%s%s" % (OUTPUT_XLS_FILENAME, gActiveLanguageDescriptionCodeTuple[2], OUTPUT_XLS_FILENAME_EXT) + print "[Info] Creating output excel %s file..." % (constructedOutputFilename) + outputXLS(constructedOutputFilename, OUTPUT_XLS_QUOTES_SHEET + gActiveLanguageDescriptionCodeTuple[1], gWavFilesNoDups, extractTreFilesMode, TMProotFolderWithInputTLKFiles) else: invalidSyntax = True if invalidSyntax == True: - print "Error:: Invalid syntax!\n Try: \n %s --help for more info \n %s --version for version info " % (APP_WRAPPER_NAME, APP_WRAPPER_NAME) - print "Valid syntax: %s -op folderpath_for_extracted_wav_Files [-ip folderpath_for_TLK_Files] [-ian path_to_actornames_txt] [-m stringPathToReplaceFolderpathInExcelLinks] [-ld gameInputLanguageDescription] [-xwav] [-xtre] [--trace]" % (APP_WRAPPER_NAME) + print "[Error] Invalid syntax!\n Try: \n %s --help for more info \n %s --version for version info " % (APP_WRAPPER_NAME, APP_WRAPPER_NAME) + print "Valid syntax: %s -op folderpath_for_exported_wav_Files [-ip folderpath_for_TLK_Files] [-ian path_to_actornames_txt] [-m stringPathToReplaceFolderpathInExcelLinks] [-ld gameInputLanguageDescription] [-xwav] [-xtre] [--trace]" % (APP_WRAPPER_NAME) + print "\nDetected arguments:" tmpi = 0 for tmpArg in argsCL: if tmpi==0: #skip first argument tmpi+=1 continue - print "\nArgument: %s" % (tmpArg) + print "Argument: %s" % (tmpArg) tmpi+=1 # 00_0000 -- DealsInInsects dupl TLK01, TLK0A @@ -937,5 +947,5 @@ if __name__ == '__main__': main(sys.argv[0:]) else: ## debug - #print 'Debug:: %s was imported from another module' % (APP_WRAPPER_NAME) + #print '[Debug] %s was imported from another module' % (APP_WRAPPER_NAME) pass diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/treFileLib.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/treFileLib.py index 9c5d56b5dc..34435eb0c5 100644 --- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/treFileLib.py +++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/treFileLib.py @@ -9,19 +9,19 @@ structLibFound = False try: import shutil except ImportError: - print "Error:: Shutil python library is required to be installed!" + print "[Error] Shutil python library is required to be installed!" else: shutilLibFound = True try: import struct except ImportError: - print "Error:: struct python library is required to be installed!" + print "[Error] struct python library is required to be installed!" else: structLibFound = True if (not shutilLibFound) or (not structLibFound): - sys.stdout.write("Error:: Errors were found when trying to import required python libraries\n") + sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n") sys.exit(1) from struct import * @@ -38,14 +38,21 @@ class TreHeader: class treFile: m_header = TreHeader() + simpleTextResourceFileName = 'GENERIC.TRE' stringEntriesLst = [] # list of two-value tuples. First value is ID, second value is String content stringOffsets = [] - def __init__(self): + m_traceModeEnabled = False + + # traceModeEnabled is bool to enable more printed debug messages + def __init__(self, traceModeEnabled = True): del self.stringEntriesLst[:] del self.stringOffsets[:] + self.simpleTextResourceFileName = 'GENERIC.TRE' + self.m_traceModeEnabled = traceModeEnabled return - def loadTreFile(self, treBytesBuff, maxLength): + def loadTreFile(self, treBytesBuff, maxLength, treFileName): + self.simpleTextResourceFileName = treFileName offsInTreFile = 0 # # parse TRE file fields for header @@ -57,7 +64,8 @@ class treFile: # # string IDs table (each entry is unsigned integer 4 bytes) # - print "Info:: Total texts in Text Resource file= %d" % (self.header().numOfTextResources) + if self.m_traceModeEnabled: + print "[Info] Total texts in Text Resource file: %d" % (self.header().numOfTextResources) for idx in range(0, self.header().numOfTextResources): tmpTuple = struct.unpack_from('I', treBytesBuff, offsInTreFile) # unsigned integer 4 bytes self.stringEntriesLst.append( (tmpTuple[0], '') ) @@ -75,7 +83,7 @@ class treFile: #absStartOfOffsetTable = absStartOfIndexTable + (self.header().numOfTextResources * 4) #absStartOfStringTable = absStartOfOffsetTable + ((self.header().numOfTextResources+1) * 4) - #print "Debug:: buffer type " , type(treBytesBuff) # it is str + #print "[Debug] buffer type: " , type(treBytesBuff) # it is str for idx in range(0, self.header().numOfTextResources): currOffset = self.stringOffsets[idx] + absStartOfIndexTable @@ -86,15 +94,15 @@ class treFile: # allTextsFound = treBytesBuff[currOffset:].split('\x00') ## check "problematic" character cases: - #if currOffset == 5982 or currOffset == 6050 or currOffset == 2827 or currOffset == 2880: - # print "Debug:: Offs= %d\tFound String= %s" % ( currOffset,''.join(allTextsFound[0]) ) - # #print "Debug:: Offs: %d\tFound String= %s" % ( currOffset,''.join(allTextsFound[0]) ) + if self.m_traceModeEnabled: + if currOffset == 5982 or currOffset == 6050 or currOffset == 2827 or currOffset == 2880: + print "[Debug] Offs: %d\tFound String: %s" % ( currOffset,''.join(allTextsFound[0]) ) (theId, stringOfIdx) = self.stringEntriesLst[idx] self.stringEntriesLst[idx] = (theId, ''.join(allTextsFound[0])) - #print "Debug:: ID= %d\tFound String= %s" % ( theId,''.join(allTextsFound[0]) ) + #print "[Debug] ID: %d\tFound String: %s" % ( theId,''.join(allTextsFound[0]) ) return True except: - print "Error:: Loading Text Resource Failed!" + print "[Error] Loading Text Resource %s failed!" % (self.simpleTextResourceFileName) return False def header(self): @@ -104,25 +112,29 @@ class treFile: # if __name__ == '__main__': # main() - print "Debug:: Running %s as main module" % (my_module_name) + print "[Debug] Running %s as main module" % (my_module_name) # assumes a file of name ACTORS.TRE in same directory inTREFile = None + inTREFileName = 'ACTORS.TRE' + errorFound = False + try: - inTREFile = open(os.path.join('.','ACTORS.TRE'), 'rb') + print "[Info] Opening %s" % (inTREFileName) + inTREFile = open(os.path.join('.',inTREFileName), 'rb') except: errorFound = True - print "Error:: Unexpected event= ", sys.exc_info()[0] + print "[Error] Unexpected event: ", sys.exc_info()[0] raise if not errorFound: allOfTreFileInBuffer = inTREFile.read() - treFileInstance = treFile() - if (treFileInstance.loadTreFile(allOfTreFileInBuffer, len(allOfTreFileInBuffer))): - print "Info:: Text Resource file loaded successfully!" + treFileInstance = treFile(True) + if (treFileInstance.loadTreFile(allOfTreFileInBuffer, len(allOfTreFileInBuffer, inTREFileName))): + print "[Info] Text Resource file loaded successfully!" else: - print "Error:: Error while loading Text Resource file!" + print "[Error] Error while loading Text Resource file!" inTREFile.close() else: #debug - #print "Debug:: Running %s imported from another module" % (my_module_name) + #print "[Debug] Running %s imported from another module" % (my_module_name) pass \ No newline at end of file -- cgit v1.2.3