[Scummvm-git-logs] scummvm master -> b0c26e9e6b53849b69c300e05bc9b35dfc9576af

antoniou79 noreply at scummvm.org
Mon Jun 5 17:03:46 UTC 2023


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
b0c26e9e6b DEVTOOLS: BLADERUNNER: Fixes for python 3 port of scripts


Commit: b0c26e9e6b53849b69c300e05bc9b35dfc9576af
    https://github.com/scummvm/scummvm/commit/b0c26e9e6b53849b69c300e05bc9b35dfc9576af
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-06-05T20:02:58+03:00

Commit Message:
DEVTOOLS: BLADERUNNER: Fixes for python 3 port of scripts

Also fix compatibility with Python 2, and port the quoteSpreadsheetCreator script to Python 3 too

Changed paths:
    devtools/create_bladerunner/subtitles/common/extracsTextResource.py
    devtools/create_bladerunner/subtitles/common/pythonCompat.py
    devtools/create_bladerunner/subtitles/common/subtlsVersTextResource.py
    devtools/create_bladerunner/subtitles/common/vqasTextResource.py
    devtools/create_bladerunner/subtitles/fontCreator/fonFileLib.py
    devtools/create_bladerunner/subtitles/fontCreator/grabberFromPNG17BR.py
    devtools/create_bladerunner/subtitles/mixResourceCreator/mixResourceCreator.py
    devtools/create_bladerunner/subtitles/mixResourceCreator/packBladeRunnerMIXFromPCTLKXLS04.py
    devtools/create_bladerunner/subtitles/module.mk
    devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileDecode.py
    devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileLib.py
    devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/devCommentaryText.py
    devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/pogoTextResource.py
    devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/quoteSpreadsheetCreator.py
    devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py
    devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/treFileLib.py


diff --git a/devtools/create_bladerunner/subtitles/common/extracsTextResource.py b/devtools/create_bladerunner/subtitles/common/extracsTextResource.py
index 29a5c47d306..ecbd1724065 100644
--- a/devtools/create_bladerunner/subtitles/common/extracsTextResource.py
+++ b/devtools/create_bladerunner/subtitles/common/extracsTextResource.py
@@ -2,8 +2,8 @@
 # -*- coding: utf-8 -*-
 #
 
-my_module_version = "1.60"
-my_module_name = "extracTextResource"
+MY_MODULE_VERSION = "1.70"
+MY_MODULE_NAME = "extracTextResource"
 
 # Template for EXTRA.TRE sheet's values ((row 2 and below)
 EXTRAC_TEXT_RESOURCE_TUPLE_LIST = [
@@ -43,12 +43,12 @@ class extracTextResource:
 
 if __name__ == '__main__':
 	#	 main()
-	print ("[Debug] Running %s as main module" % (my_module_name))
+	print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	traceModeEnabled = False
 	excrTRInstance = extracTextResource(traceModeEnabled)
 	excrTRInstance.printExtracTemplate()
 
 else:
 	#debug
-	#print "[Debug] Running	 %s imported from another module" % (my_module_name)
+	#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	pass
diff --git a/devtools/create_bladerunner/subtitles/common/pythonCompat.py b/devtools/create_bladerunner/subtitles/common/pythonCompat.py
index 130aa838ebc..96a0c91a495 100644
--- a/devtools/create_bladerunner/subtitles/common/pythonCompat.py
+++ b/devtools/create_bladerunner/subtitles/common/pythonCompat.py
@@ -3,9 +3,9 @@
 
 import sys
 
-def makeUnicode(inp):
+def makeUnicode(inp, enc='utf-8'):
         if sys.version_info[0] <= 2:
-                return unicode(inp, 'utf-8')
+                return unicode(inp, enc)
         else:
                 return inp
 
@@ -38,3 +38,8 @@ def makeToBytes(s):
 	if sys.version_info[0] <= 2:
 		return [ord(i) for i in s]
 	return bytes(i for i in s)
+
+def openWithUTF8Encoding(filepath, mode):
+	if sys.version_info[0] <= 2:
+		return open(filepath, mode)
+	return open(filepath, mode, encoding='utf-8')
diff --git a/devtools/create_bladerunner/subtitles/common/subtlsVersTextResource.py b/devtools/create_bladerunner/subtitles/common/subtlsVersTextResource.py
index 92d8b83604e..3ddee921cf5 100644
--- a/devtools/create_bladerunner/subtitles/common/subtlsVersTextResource.py
+++ b/devtools/create_bladerunner/subtitles/common/subtlsVersTextResource.py
@@ -2,15 +2,20 @@
 # -*- coding: utf-8 -*-
 #
 
-my_module_version = "1.60"
-my_module_name = "subtlsVersTextResource"
+MY_MODULE_VERSION = "1.70"
+MY_MODULE_NAME = "subtlsVersTextResource"
 
 # Template for SBTLVERS.TRE sheet's values ((row 2 and below)
 SBTLVERS_TEXT_RESOURCE_TUPLE_LIST = [
 	(0, "ScummVM Team", "Credits"),
-	(1, "6", "Version (an incremental number)"),
+	(1, "9", "Version (an incremental number)"),
 	(2, "##:##:## ##/##/####", "Placeholder – Date of compilation (HH:mm:ss dd/mm/yyyy)"),
-	(3, "EFIGS", "Placeholder – Language mode")
+	(3, "EFIGS", "Placeholder – Language mode"),
+	(4, "Copyright (C) 2019-2022  ScummVM team", "Copyright"),
+	(5, "", "Font type"),
+	(6, "", "Font name"),
+	(7, "", "License"),
+	(8, "", "License link")
  ]
 #
 #
@@ -32,12 +37,12 @@ class sbtlVersTextResource:
 
 if __name__ == '__main__':
 	#	 main()
-	print ("[Debug] Running %s as main module" % (my_module_name))
+	print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	traceModeEnabled = False
 	sbtlVersTRInstance = sbtlVersTextResource(traceModeEnabled)
 	sbtlVersTRInstance.printSbtlVersTemplate()
 
 else:
 	#debug
-	#print "[Debug] Running	 %s imported from another module" % (my_module_name)
+	#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	pass
diff --git a/devtools/create_bladerunner/subtitles/common/vqasTextResource.py b/devtools/create_bladerunner/subtitles/common/vqasTextResource.py
index 08d90e3919a..997537db01b 100644
--- a/devtools/create_bladerunner/subtitles/common/vqasTextResource.py
+++ b/devtools/create_bladerunner/subtitles/common/vqasTextResource.py
@@ -2,8 +2,8 @@
 # -*- coding: utf-8 -*-
 #
 
-my_module_version = "1.60"
-my_module_name = "vqasTextResource"
+MY_MODULE_VERSION = "1.70"
+MY_MODULE_NAME = "vqasTextResource"
 
 # Timestamps and placeholder cells for all supported VQAs ((row 2 and below)
 WSTLGO_VQA_TEXT_RESOURCE_TUPLE_LIST = [
@@ -471,16 +471,16 @@ class vqasTextResource(object):
 
 	def printAllVqasTextResource(self):
 		if self.m_traceModeEnabled:
-			print "[Trace] printing all VQAs Text"
+			print ("[Trace] printing all VQAs Text")
 		for (vqaKeyStr, vqaTreList) in ALL_VQA_TEXT_RESOURCES_LISTS:
-			print "VQA prefix: %s" % (vqaKeyStr)
+			print ("VQA prefix: %s" % (vqaKeyStr))
 			for (startFrameTre, endFrameTre, textTre, timeStartTre, timeEndTre, byActorTre) in vqaTreList:
-				print "%s\t%s\t%s\t%s\t%s\t%s" % (startFrameTre, endFrameTre, textTre, timeStartTre, timeEndTre, byActorTre)
+				print ("%s\t%s\t%s\t%s\t%s\t%s" % (startFrameTre, endFrameTre, textTre, timeStartTre, timeEndTre, byActorTre))
 		return
 
 	def getVqaEntriesList(self, sVQASheetPrefix):
 		if self.m_traceModeEnabled:
-			print "[Trace] getVqaEntriesList()"
+			print ("[Trace] getVqaEntriesList()")
 		for (vqaKeyStr, vqaTreList) in ALL_VQA_TEXT_RESOURCES_LISTS:
 			if (vqaKeyStr == sVQASheetPrefix.upper()):
 				return vqaTreList
@@ -490,11 +490,11 @@ class vqasTextResource(object):
 #
 if __name__ == '__main__':
 	# main()
-	print "[Debug] Running %s as main module" % (my_module_name)
+	print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	traceModeEnabled = False
 	vqaTRInstance = vqasTextResource(traceModeEnabled)
 	vqaTRInstance.printAllVqasTextResource()
 else:
 	#debug
-	#print "[Debug] Running	 %s imported from another module" % (my_module_name)
+	#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	pass
diff --git a/devtools/create_bladerunner/subtitles/fontCreator/fonFileLib.py b/devtools/create_bladerunner/subtitles/fontCreator/fonFileLib.py
index 2414bbb455e..10b3d4c9344 100644
--- a/devtools/create_bladerunner/subtitles/fontCreator/fonFileLib.py
+++ b/devtools/create_bladerunner/subtitles/fontCreator/fonFileLib.py
@@ -44,7 +44,7 @@ if 	(not osLibFound) \
 
 from struct import *
 
-MY_MODULE_VERSION = "0.80"
+MY_MODULE_VERSION = "0.90"
 MY_MODULE_NAME    = "fonFileLib"
 
 class FonHeader(object):
@@ -193,7 +193,7 @@ class fonFile(object):
 			targHeight = 480
 
 		imTargetGameFont = Image.new("RGBA",(targWidth, targHeight), (0,0,0,0))
-		#print imTargetGameFont.getbands()
+		#print (imTargetGameFont.getbands())
 		#
 		# Now fill in the image segment
 		# Fonts in image segment are stored in pixel colors from TOP to Bottom, Left to Right per GLYPH.
@@ -207,7 +207,7 @@ class fonFile(object):
 			# TODO mark glyph OUTLINES? (optional by switch)
 			(glyphXoffs, glyphYoffs, glyphWidth, glyphHeight, glyphDataOffs) = self.glyphDetailEntriesLst[idx]
 			glyphDataOffs = glyphDataOffs * 2
-			#print idx, glyphDataOffs
+			#print (idx, glyphDataOffs)
 			currX = 0
 			currY = 0
 			if (glyphWidth == 0 or glyphHeight == 0):
@@ -220,7 +220,7 @@ class fonFile(object):
 				glyphDataOffs += 2
 
 #				 if pixelColor > 0x8000:
-#					 print "[Debug] 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
@@ -238,9 +238,9 @@ class fonFile(object):
 				imTargetGameFont.putpixel(( (drawIdx + 1) * (self.header().maxGlyphWidth + paddingBetweenGlyphsX ) + currX, paddingFromTopY + glyphYoffs + currY), rgbacolour)
 				currX += 1
 		try:
-			imTargetGameFont.save(os.path.join('.', self.simpleFontFileName + ".PNG"), "PNG")
+			imTargetGameFont.save(os.path.join(u'.', self.simpleFontFileName + ".PNG"), "PNG")
 		except Exception as e:
-			print ('[Error] Unable to write to output PNG file. ' + str(e))
+			print ("[Error] Unable to write to output PNG file. " + str(e))
 
 	def header(self):
 		return self.m_header
@@ -261,12 +261,12 @@ if __name__ == '__main__':
 	inFONFileName =  'SUBTLS_E.FON'    # Subtitles font custom
 
 	if len(sys.argv[1:])  > 0 \
-		and os.path.isfile(os.path.join('.', sys.argv[1])) \
+		and os.path.isfile(os.path.join(u'.', sys.argv[1])) \
 		and len(sys.argv[1]) >= 5 \
 		and sys.argv[1][-3:].upper() == 'FON':
 		inFONFileName = sys.argv[1]
 		print ("[Info] Attempting to use %s as input FON file..." % (inFONFileName))
-	elif os.path.isfile(os.path.join('.', inFONFileName)):
+	elif os.path.isfile(os.path.join(u'.', inFONFileName)):
 		print ("[Info] Using default %s as input FON file..." % (inFONFileName))
 	else:
 		print ("[Error] No valid input file argument was specified and default input file %s is missing." % (inFONFileName))
@@ -275,7 +275,7 @@ if __name__ == '__main__':
 	if not errorFound:
 		try:
 			print ("[Info] Opening %s" % (inFONFileName))
-			inFONFile = open(os.path.join('.',inFONFileName), 'rb')
+			inFONFile = open(os.path.join(u'.', inFONFileName), 'rb')
 		except:
 			errorFound = True
 			print ("[Error] Unexpected event:", sys.exc_info()[0])
@@ -293,5 +293,5 @@ if __name__ == '__main__':
 			inFONFile.close()
 else:
 	#debug
-	#print "[Debug] Running	 %s imported from another module" % (MY_MODULE_NAME)
+	#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	pass
diff --git a/devtools/create_bladerunner/subtitles/fontCreator/grabberFromPNG17BR.py b/devtools/create_bladerunner/subtitles/fontCreator/grabberFromPNG17BR.py
index 66d1575b22e..7419d269e37 100644
--- a/devtools/create_bladerunner/subtitles/fontCreator/grabberFromPNG17BR.py
+++ b/devtools/create_bladerunner/subtitles/fontCreator/grabberFromPNG17BR.py
@@ -104,7 +104,7 @@ else:
 try:
 	from PIL import Image
 except ImportError:
-	print ("[Error] Image python library (PIL) is required to be installed!")
+	print ("[Error] Image python library (PIL or pillow) is required to be installed!")
 else:
 	imagePilLibFound = True
 
@@ -139,7 +139,7 @@ from fonFileLib import *
 from pythonCompat import *
 
 COMPANY_EMAIL = "classic.adventures.in.greek at gmail.com"
-APP_VERSION = "1.10"
+APP_VERSION = "1.20"
 APP_NAME = "grabberFromPNGHHBR"
 APP_WRAPPER_NAME = "fontCreator.py"
 APP_NAME_SPACED = "Blade Runner Font Creator/Exporter"
@@ -170,14 +170,10 @@ def calculateFoldHash(strFileName):
 		hash = ((hash << 1) | ((hash >> 31) & 1)) + groupSum
 	hash &= 0xFFFFFFFF	   # mask here!
 	#if gTraceModeEnabled:
-	#	print '[Debug] ' + (strParam +': '  +''.join('{:08X}'.format(hash)))
+	#	print ("[Debug] " + (strParam + ": "  +''.join('{:08X}'.format(hash))))
 	return hash
 
 class grabberFromPNG:
-	origEncoding = 'windows-1252'
-	defaultTargetLang = "greek"
-	defaultTargetEncoding = 'windows-1253' #greek
-
 	targetEncoding = 'windows-1253'
 
 	overrideEncodingPath = ""
@@ -240,13 +236,12 @@ class grabberFromPNG:
 		# Read from an override file if it exists. Filename should be overrideEncoding.txt (overrideEncodingTextFile)
 		if not self.overrideEncodingPath :
 			overrideEncodingTextFile = u'overrideEncoding.txt'
-			relPath = u'.'
-			self.overrideEncodingPath = os.path.join(relPath,overrideEncodingTextFile)
+			self.overrideEncodingPath = os.path.join(u'.', 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):
 			print ("[Info] Override encoding file found: {0}.".format(self.overrideEncodingPath))
-			overEncodFile = open(self.overrideEncodingPath, 'r')
+			overEncodFile = openWithUTF8Encoding(self.overrideEncodingPath, 'r')
 			linesLst = overEncodFile.readlines()
 			overEncodFile.close()
 			if linesLst is None or len(linesLst) == 0:
@@ -261,7 +256,7 @@ class grabberFromPNG:
 					for x in tmplineTokens:
 						involvedTokensLst.append(x)
 					#if gTraceModeEnabled:
-					#	print "[Debug] ", involvedTokensLst
+					#	print ("[Debug] ", involvedTokensLst)
 					#break #only read first line
 				for tokenNameKeyPair in involvedTokensLst:
 					nameKeyTupl = tokenNameKeyPair.split('=', 1)
@@ -289,8 +284,8 @@ class grabberFromPNG:
 						elif len(nameKeyTupl) == 2 and nameKeyTupl[0] == 'specialOutOfOrderGlyphsUTF8ToAsciiTargetEncoding' and nameKeyTupl[1] is not None and nameKeyTupl[1] != '-' and nameKeyTupl[1] != '':
 							# split at comma, then split at ':' and store tuples of character
 							explicitOutOfOrderGlyphsTokenUnicode = makeUnicode(nameKeyTupl[1]) # unicode(nameKeyTupl[1], 'utf-8')
-							#explicitOutOfOrderGlyphsTokenStr =  unicode.encode("%s" % explicitOutOfOrderGlyphsTokenUnicode, self.targetEncoding)
-							#explicitOutOfOrderGlyphsTokenStr =  explicitOutOfOrderGlyphsTokenUnicode.decode(self.targetEncoding) # unicode.encode("%s" % explicitOutOfOrderGlyphsTokenUnicode, 'utf-8')
+							#explicitOutOfOrderGlyphsTokenStr =  unicodeEncode("%s" % explicitOutOfOrderGlyphsTokenUnicode, self.targetEncoding)
+							#explicitOutOfOrderGlyphsTokenStr =  explicitOutOfOrderGlyphsTokenUnicode.decode(self.targetEncoding) # unicodeEncode("%s" % explicitOutOfOrderGlyphsTokenUnicode, 'utf-8')
 							tokensOfOutOfOrderGlyphsStrList = explicitOutOfOrderGlyphsTokenUnicode.split(',')
 							for tokenX in tokensOfOutOfOrderGlyphsStrList:
 								tokensOfTupleList = tokenX.split(':')
@@ -305,7 +300,7 @@ class grabberFromPNG:
 
 				if gTraceModeEnabled:
 					print ("[Debug] Target Encoding: ", self.targetEncoding)
-					#print "[Debug] Lang Order: ", targetLangOrderAndListOfForeignLettersStrUnicode
+					#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)
@@ -330,35 +325,26 @@ class grabberFromPNG:
 
 		if overrideFailed:
 			## error
-			print ("[Error] Override encoding file parsing has failed: Error Code 1.") #" Initializing for {0}...".format(self.defaultTargetLang)
-			#if gTraceModeEnabled:
-			#	self.targetEncoding = self.defaultTargetEncoding
-			#	targetLangOrderAndListOfForeignLettersStrUnicode = unicode(allOfGreekChars, 'utf-8')
-			#	print '[Debug] ', targetLangOrderAndListOfForeignLettersStrUnicode
+			print ("[Error] Override encoding file parsing has failed: Error Code 1.")
 			sys.exit(1)	# terminate if override Failed (Blade Runner)
 
 		try:
 			targetLangOrderAndListOfForeignLettersStr = unicodeEncode("%s" % targetLangOrderAndListOfForeignLettersStrUnicode, self.targetEncoding)
 		except:
 			## error
-			print ("[Error] Override encoding file parsing has failed: Error Code 2.") #"Initializing for {0}...".format(self.defaultTargetLang)
-			#if gTraceModeEnabled:
-			#	self.targetEncoding = self.defaultTargetEncoding
-			#	targetLangOrderAndListOfForeignLettersStrUnicode = unicode(allOfGreekChars, 'utf-8')
-			#	targetLangOrderAndListOfForeignLettersStr = unicode.encode("%s" % targetLangOrderAndListOfForeignLettersStrUnicode, self.targetEncoding)
-			#	print '[Debug] ' + targetLangOrderAndListOfForeignLettersStrUnicode
+			print ("[Error] Override encoding file parsing has failed: Error Code 2.")
 			sys.exit(1)	# terminate if override Failed (Blade Runner)
 
 		targetLangOrderAndListOfForeignLetters = list(targetLangOrderAndListOfForeignLettersStr)
 		if gTraceModeEnabled:
-			print ('[Debug] ', targetLangOrderAndListOfForeignLetters, len(targetLangOrderAndListOfForeignLetters))	   # new
+			print ("[Debug] ", targetLangOrderAndListOfForeignLetters, len(targetLangOrderAndListOfForeignLetters))	   # new
 		self.targetLangOrderAndListOfForeignLettersAsciiValues = makeToBytes(targetLangOrderAndListOfForeignLetters)
 		if gTraceModeEnabled:
-			print ('[Debug] ', self.targetLangOrderAndListOfForeignLettersAsciiValues, len(self.targetLangOrderAndListOfForeignLettersAsciiValues))
+			print ("[Debug] ", self.targetLangOrderAndListOfForeignLettersAsciiValues, len(self.targetLangOrderAndListOfForeignLettersAsciiValues))
 		self.maxAsciiValueInEncoding = max(self.targetLangOrderAndListOfForeignLettersAsciiValues)
 	#if gTraceModeEnabled:
 	#	for charAsciiValue in targetLangOrderAndListOfForeignLetters:
-	#		print "[Debug] Ord of chars: %d" % ord(charAsciiValue)
+	#		print ("[Debug] Ord of chars: %d" % ord(charAsciiValue))
 ##
 ## END OF INIT CODE
 ##
@@ -497,15 +483,15 @@ class grabberFromPNG:
 				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.
 					#if gTraceModeEnabled:
-					#	print "[Debug] ", loadedImag[x, y]
+					#	print ("[Debug] ", loadedImag[x, y])
 					if prevColStartForLetter == 0:
 						prevColStartForLetter = x
 						prevRowStartForLetter = y
 						startCol = x
 						#if gTraceModeEnabled:
-						#	print "[Debug] Letter found."
-						#	print "[Debug] Start col: %d" % startCol
-						##	print "[Debug] hypothetical row: %d" % y
+						#	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
@@ -521,15 +507,15 @@ class grabberFromPNG:
 							if tmpSum < imwidth:
 								scanToCol = tmpSum
 							#if gTraceModeEnabled:
-							#	print "[Debug] ", (startCol, scanToCol)
+							#	print ("[Debug] ", (startCol, scanToCol))
 							for x2 in range(startCol, scanToCol): # check all columns (for each row)
 								#if gTraceModeEnabled:
-								#	print "[Debug] ", loadedImag[x2, y2]
+								#	print ("[Debug] ", loadedImag[x2, y2])
 								r2,g2,b2,a2 = loadedImag[x2, y2]
 								if a2 != 0 and startRow == 0:
 									startRow = y2 + trimTopPixels
 									#if gTraceModeEnabled:
-									#	print "[Debug] Start row: %d" % startRow
+									#	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
@@ -548,7 +534,7 @@ class grabberFromPNG:
 			if endRow > 0:
 				endRow = endRow - trimBottomPixels
 			#if gTraceModeEnabled:
-			#	print "[Debug] End row: %d" % endRow
+			#	print ("[Debug] End row: %d" % endRow)
 
 		if startCol > 0 and startRow > 0 and endRow > 0:
 			tmpSum = startCol + self.minSpaceBetweenLettersInRowLeftToLeft
@@ -562,7 +548,7 @@ class grabberFromPNG:
 					if a1 != 0:
 						endCol = x
 			#if gTraceModeEnabled:
-			#	print "[Debug] End col: %d" % endCol
+			#	print ("[Debug] End col: %d" % endCol)
 		if startCol > 0 and startRow > 0 and endRow > 0 and endCol > 0:
 			# append deducted baseline
 			#
@@ -572,7 +558,7 @@ class grabberFromPNG:
 				if self.autoTabCalculation == True:
 					if self.tabSpaceWidth == 0:
 						#if gTraceModeEnabled:
-						#	print "[Debug] start startPre: ", startCol, self.startColOfPrevFontLetter
+						#	print ("[Debug] start startPre: ", startCol, self.startColOfPrevFontLetter)
 						self.tabSpaceWidth = startCol - self.startColOfPrevFontLetter
 						if gTraceModeEnabled:
 							print ("[Debug] Tab Space Width detected: %d " % (self.tabSpaceWidth))
@@ -580,7 +566,7 @@ class grabberFromPNG:
 					if self.tabSpaceWidth > 0:
 						self.listOfXOffsets.append(startCol - (self.startOfAllLettersIncludingTheExtraDoubleAndWithKern + (self.lettersFound + 1) * self.tabSpaceWidth) ) #	 + self.deductKerningPixels )
 						#if gTraceModeEnabled:
-						#	print "[Debug] xOffSet: ", startCol - (self.startOfAllLettersIncludingTheExtraDoubleAndWithKern + (self.lettersFound + 1) * self.tabSpaceWidth)
+						#	print ("[Debug] xOffSet: ", startCol - (self.startOfAllLettersIncludingTheExtraDoubleAndWithKern + (self.lettersFound + 1) * self.tabSpaceWidth))
 				else:
 					self.listOfXOffsets.append(0)
 
@@ -635,8 +621,8 @@ class grabberFromPNG:
 		##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
+		#	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
@@ -683,30 +669,30 @@ class grabberFromPNG:
 					self.lettersFound = self.lettersFound + 1 # == 0 means one character font was detected so +1 to the counter
 			#debug
 			#if gTraceModeEnabled:
-			#	print "[Debug] ", self.listOfBaselines
+			#	print ("[Debug] ", self.listOfBaselines)
 			print ("[Info] Font Glyphs Detected (not including the first double): %d" % (self.lettersFound))
 			if (self.lettersFound ) > 0 :
 				#if gTraceModeEnabled:
-				#	print "[Debug] widths: ", self.listOfWidths[0:]
-				#	print "[Debug] Plain x offsets:"
-				#	print zip(self.targetLangOrderAndListOfForeignLettersAsciiValues[1:], self.listOfXOffsets)
+				#	print ([Debug] widths: ", self.listOfWidths[0:])
+				#	print ("[Debug] Plain x offsets:")
+				#	print (list(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
+				#	print ("[Debug] Normalized x offsets: ")
+				#	print (self.listOfXOffsets)
 				# calculate y offsets
-				(listOfStartCols, listOfStartRows, listOfEndCols, listOfEndRows) = zip(* self.listOfLetterBoxes)
+				(listOfStartCols, listOfStartRows, listOfEndCols, listOfEndRows) = list(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]
 				#if gTraceModeEnabled:
-				#	print "[Debug] Y offsets: "
-				#	print self.listOfYOffsets
+				#	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!
@@ -718,10 +704,10 @@ class grabberFromPNG:
 					explicitWidthIncrementVal = 0
 					if len(self.listOfWidthIncrements ) > 0:
 						tmpOrd = self.targetLangOrderAndListOfForeignLettersAsciiValues[kIncIndx]
-						keysOfWidthIncrements, valuesOfWidthIncrements = (zip(*self.listOfWidthIncrements))
+						keysOfWidthIncrements, valuesOfWidthIncrements = (list(zip(*self.listOfWidthIncrements)))
 						if tmpOrd in keysOfWidthIncrements:
 							#if gTraceModeEnabled:
-							#	print "[Debug] Explicit width increment for %d: %d" % (tmpOrd, valuesOfWidthIncrements[keysOfWidthIncrements.index(tmpOrd)])
+							#	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:
@@ -732,8 +718,8 @@ class grabberFromPNG:
 				maxFontHeight =	 max(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)
+				#	print ("Index\tAsciiOrd\tX Offs\tY Offs\tWidth\tHeight")
+				#	print (list(zip(range(1, len(self.listOfXOffsets)), self.targetLangOrderAndListOfForeignLettersAsciiValues[1:], self.listOfXOffsets, self.listOfYOffsets, listOfCalcWidths, self.listOfHeights)))
 				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
 				if self.maxAsciiValueInEncoding > 254:
@@ -745,10 +731,10 @@ class grabberFromPNG:
 					try:
 						targetFontFile = open(self.targetFONFilename, 'wb')
 					except Exception as e:
-						print ('[Error] Failed to create target font (FON) file: ' + self.targetFONFilename + '::' + str(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)
+						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) :
@@ -805,9 +791,9 @@ class grabberFromPNG:
 							#kIncIndx = 0
 							## aux list because the order of the fonts in our overrideEncoding may not match the real order in the ascii table
 							#listOfWriteableEntries = [ (0,0,0,0,0) for i in range(0, numberOfEntriesInFontTable)] # create a list of placeholders for the number of entries we need to write
-							#print " *************** DBG **************"
-							#print listOfWriteableEntries
-							#print " *************** DBG **************"
+							#print (" *************** DBG **************")
+							#print (listOfWriteableEntries)
+							#print (" *************** DBG **************")
 							del self.properListOfLetterBoxes[:]
 							for i in range(0, numberOfEntriesInFontTable):	# blocks of 20 bytes
 								# 20 byte block
@@ -845,16 +831,16 @@ class grabberFromPNG:
 										kIncIndx = kIncIndxLst[0][0]
 										#kIncIndx = self.targetLangOrderAndListOfForeignLettersAsciiValues.index(i-1)
 										#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
+										#	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))
+											keysOfExplicitKerning, valuesOfExplicitKerning = (list(zip(*self.listOfExplicitKerning)))
 											if (i - 1) in keysOfExplicitKerning:
 												# found explicit kerning for this
 												#if gTraceModeEnabled:
-												#	print "[Debug] Explicit kerning for %d " % (i-1)
+												#	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!
@@ -863,10 +849,10 @@ class grabberFromPNG:
 										targetFontFile.write(tmpYOffsetToWrite)
 
 										if len(self.listOfWidthIncrements ) > 0:
-											keysOfWidthIncrements, valuesOfWidthIncrements = (zip(*self.listOfWidthIncrements))
+											keysOfWidthIncrements, valuesOfWidthIncrements = (list(zip(*self.listOfWidthIncrements)))
 											if (i - 1) in keysOfWidthIncrements:
 												#if gTraceModeEnabled:
-												#	print "[Debug] Explicit width increment for %d " % (i-1)
+												#	print ("[Debug] Explicit width increment for %d " % (i-1))
 												foundExplicitWidthIncrement = True
 												self.listOfWidths[kIncIndx] = self.listOfWidths[kIncIndx] + valuesOfWidthIncrements[keysOfWidthIncrements.index(i-1)]
 
@@ -885,7 +871,7 @@ class grabberFromPNG:
 									else:
 										#
 										#if gTraceModeEnabled:
-										#	print "[Debug] ", i, ": phony entry"
+										#	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
 										targetFontFile.write(tmpXOffsetToWrite)
@@ -901,10 +887,10 @@ class grabberFromPNG:
 							# print the corrected properties per glyph font:
 							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)
+								tmpListOfTuplesToPrintDbg = list(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"
+								#print ("\n")
 							#
 							#
 							# Now fill in the image segment
@@ -942,39 +928,39 @@ class grabberFromPNG:
 							kIncIndx = 1 # start after the first glyph (which is DOUBLE)
 							for (c_startCol, c_startRow, c_endCol, c_endRow) in self.properListOfLetterBoxes[0:]:
 								#if gTraceModeEnabled:
-								#	print "[Debug] ", (c_startCol, c_startRow, c_endCol, c_endRow),' for letter ', self.targetLangOrderAndListOfForeignLettersAsciiValues[kIncIndx]
+								#	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))
+									keysOfWidthIncrements, valuesOfWidthIncrements = (list(zip(*self.listOfWidthIncrements)))
 									if tmpOrd in keysOfWidthIncrements:
 										#if gTraceModeEnabled:
-										#	print "[Debug] Explicit width increment for %d: %d" % (tmpOrd, valuesOfWidthIncrements[keysOfWidthIncrements.index(tmpOrd)])
+										#	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):
 										#if gTraceModeEnabled:
-										#	print "[Debug] ", (tmpRowCur, tmpColCur)
+										#	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):
 											#if gTraceModeEnabled:
-											#	print "[Debug] With alpha 8bit: ", (r1, g1, b1, a1)
+											#	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.
 											#if gTraceModeEnabled:
-											#	print "[Debug] 8bit:", (r1, g1, b1)
+											#	print ("[Debug] 8bit:", (r1, g1, b1))
 											tmp5bitR1 = (r1 >> 3) & 0x1f
 											tmp5bitG1 = (g1 >> 3) & 0x1f
 											tmp5bitB1 = (b1 >> 3) & 0x1f
 											#if gTraceModeEnabled:
-											#	print "[Debug] 5bit: ", (tmp5bitR1, tmp5bitG1, tmp5bitB1)
+											#	print ("[Debug] 5bit: ", (tmp5bitR1, tmp5bitG1, tmp5bitB1))
 											tmpPixelColorConvertedToRGB555 = (tmp5bitR1 << 10) | (tmp5bitG1 << 5) | (tmp5bitB1)
 											#if gTraceModeEnabled:
-											#	print "[Debug] 16bit: ", tmpPixelColorConvertedToRGB555
+											#	print ("[Debug] 16bit: ", tmpPixelColorConvertedToRGB555)
 											tmpPixelColorRGB555ToWrite = pack('H', tmpPixelColorConvertedToRGB555)
 											targetFontFile.write(tmpPixelColorRGB555ToWrite) # unsigned short - 2 bytes
 										if (tmpColCur == c_endCol and explicitWidthIncrementVal > 0):
@@ -1035,7 +1021,7 @@ class grabberFromPNG:
 			inMIXFile = None
 			#
 			try:
-				inMIXFile = open(os.path.join(self.inputFonMixPath,tmpMIXfileName), 'rb')
+				inMIXFile = open(os.path.join(self.inputFonMixPath, tmpMIXfileName), 'rb')
 			except:
 				errorFound = True
 				print ("[Error] Unexpected event:", sys.exc_info()[0])
@@ -1146,7 +1132,7 @@ def main(argsCL):
 	#TMPdeductKerningPixels = 0
 	TMPcustomBaseLineOffset = 0
 	print ("Running %s (%s)..." % (APP_NAME_SPACED, APP_VERSION))
-	#print "Len of sysargv = %s" % (len(argsCL))
+	#print ("Len of sysargv = %s" % (len(argsCL)))
 	if len(argsCL) == 2:
 		if(argsCL[1] == '--help'or argsCL[1] == '-h'):
 			print ("%s %s supports Westwood's Blade Runner PC Game (1997)." % (APP_NAME_SPACED, APP_VERSION))
@@ -1274,5 +1260,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 371e13949de..f1b88d573a4 100755
--- a/devtools/create_bladerunner/subtitles/mixResourceCreator/mixResourceCreator.py
+++ b/devtools/create_bladerunner/subtitles/mixResourceCreator/mixResourceCreator.py
@@ -8,7 +8,7 @@ except ImportError:
 else:
 	sysLibFound = True
 
-if 	(not sysLibFound):
+if (not sysLibFound):
 	sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n")
 	sys.exit(1)
 
diff --git a/devtools/create_bladerunner/subtitles/mixResourceCreator/packBladeRunnerMIXFromPCTLKXLS04.py b/devtools/create_bladerunner/subtitles/mixResourceCreator/packBladeRunnerMIXFromPCTLKXLS04.py
index ebe50527083..c72eb5dedcc 100644
--- a/devtools/create_bladerunner/subtitles/mixResourceCreator/packBladeRunnerMIXFromPCTLKXLS04.py
+++ b/devtools/create_bladerunner/subtitles/mixResourceCreator/packBladeRunnerMIXFromPCTLKXLS04.py
@@ -15,8 +15,6 @@ shutilLibFound = False
 ctypesLibFound = False
 csvLibFound = False
 xlrdLibFound = False
-xlwtLibFound = False
-xlutilsLibFound = False
 reLibFound = False
 structLibFound = False
 datetimeLibFound = False
@@ -71,11 +69,12 @@ else:
 	xlrdLibFound = True
 
 try:
-	import xlwt
+	import openpyxl
 except ImportError:
-	print ("[Error] xlwt python library is required to be installed!")
+	print ("[Error] openpyxl python library is required to be installed!")
+	xlrdLibFound = False # openpyxl is an optional pandas dependency for reading (and writing) Excel files
 else:
-	xlwtLibFound = True
+	xlrdLibFound = True
 
 try:
 	import re
@@ -100,7 +99,6 @@ if 	(not osLibFound) \
 	or (not datetimeLibFound) \
 	or (not csvLibFound) \
 	or (not xlrdLibFound) \
-	or (not xlwtLibFound) \
 	or (not reLibFound) \
 	or (not structLibFound):
 	sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n")
@@ -111,7 +109,6 @@ pathToCommon = os.path.join(pathToParent, "common")
 sys.path.append(pathToCommon)
 
 from os import path
-from xlrd import *
 # for pack
 from struct import *
 from subtlsVersTextResource import *
@@ -119,7 +116,7 @@ from extracsTextResource import *
 from pythonCompat import *
 
 COMPANY_EMAIL = "classic.adventures.in.greek at gmail.com"
-APP_VERSION = "1.96"
+APP_VERSION = "1.99"
 APP_NAME = "packBladeRunnerMIXFromPCTLKXLS"
 APP_WRAPPER_NAME = "mixResourceCreator.py"
 APP_NAME_SPACED = "Blade Runner MIX Resource Creator"
@@ -206,19 +203,18 @@ def initOverrideEncoding(pathToConfigureFontsTranslationTxt):
 
 	if pathToConfigureFontsTranslationTxt is None or not pathToConfigureFontsTranslationTxt:
 		configureFontsTranslationTextFile = u'configureFontsTranslation.txt'
-		relPath = u'.'
-		pathToConfigureFontsTranslationTxt = os.path.join(relPath, configureFontsTranslationTextFile)
+		pathToConfigureFontsTranslationTxt = os.path.join(u'.', configureFontsTranslationTextFile)
 		print ("[Warning] Font Translation Configuration file not found in arguments. Attempting to open local file %s if it exists" % (configureFontsTranslationTextFile))
 
 	configureTranslationFailed = False
 	try:
 		if os.access(pathToConfigureFontsTranslationTxt, os.F_OK):
 			print ("[Info] Font Translation Configuration file found: {0}".format(pathToConfigureFontsTranslationTxt))
-			conFontsTranslationFile = open(pathToConfigureFontsTranslationTxt, 'r')
+			conFontsTranslationFile = openWithUTF8Encoding(pathToConfigureFontsTranslationTxt, 'r')
 			linesLst = conFontsTranslationFile.readlines()
 			conFontsTranslationFile.close()
 			if linesLst is None or len(linesLst) == 0:
-				print ('[Error] Empty configureFontsTranslation text file!')
+				print ("[Error] Empty configureFontsTranslation text file!")
 				configureTranslationFailed = True
 			else:
 				if gTraceModeEnabled:
@@ -246,8 +242,8 @@ def initOverrideEncoding(pathToConfigureFontsTranslationTxt):
 								tmpFontCateg = fontCateg_targetEnc_OOOGlyphs_Tuple[0]
 								tmpTargetEncodingForThisFont = fontCateg_targetEnc_OOOGlyphs_Tuple[1]
 								if ( tmpFontCateg not in list(zip(*DEFAULT_TARGET_ENCODING_PER_FONT))[0]):
-									print ('[Error] Invalid Font name specified in configureFontsTranslation text file!')
-									print ('        Valid values are: ', ", ".join( list(zip(*DEFAULT_TARGET_ENCODING_PER_FONT))[0] ))
+									print ("[Error] Invalid Font name specified in configureFontsTranslation text file!")
+									print ("        Valid values are: ", ", ".join( list(zip(*DEFAULT_TARGET_ENCODING_PER_FONT))[0] ))
 									configureTranslationFailed = True
 									break
 
@@ -259,15 +255,15 @@ def initOverrideEncoding(pathToConfigureFontsTranslationTxt):
 									and fontCateg_targetEnc_OOOGlyphs_Tuple[2] != ''):
 									# split at comma, then split at ':' and store tuples of character
 									explicitOutOfOrderGlyphsTokenUnicode = makeUnicode(fontCateg_targetEnc_OOOGlyphs_Tuple[2]) # unicode(fontCateg_targetEnc_OOOGlyphs_Tuple[2], 'utf-8')
-									#explicitOutOfOrderGlyphsTokenStr =  unicode.encode("%s" % explicitOutOfOrderGlyphsTokenUnicode, gTargetEncoding)
-									#explicitOutOfOrderGlyphsTokenStr =  explicitOutOfOrderGlyphsTokenUnicode.decode(gTargetEncoding) # unicode.encode("%s" % explicitOutOfOrderGlyphsTokenUnicode, 'utf-8')
+									#explicitOutOfOrderGlyphsTokenStr =  unicodeEncode("%s" % explicitOutOfOrderGlyphsTokenUnicode, gTargetEncoding)
+									#explicitOutOfOrderGlyphsTokenStr =  explicitOutOfOrderGlyphsTokenUnicode.decode(gTargetEncoding) # unicodeEncodeode("%s" % explicitOutOfOrderGlyphsTokenUnicode, 'utf-8')
 									tokensOfOutOfOrderGlyphsStrList = explicitOutOfOrderGlyphsTokenUnicode.split(',')
 									for tokenX in tokensOfOutOfOrderGlyphsStrList:
 										tokensOfTupleList = tokenX.split(':')
 										if len(tokensOfTupleList) == 2:
 											tmpListOfOutOfOrderGlyphs.append( (getUnicodeSym(tokensOfTupleList[0]), getUnicodeSym(tokensOfTupleList[1]))  )
 										else:
-											print ('[Error] Bad tuple syntax in configureFontsTranslation text file!')
+											print ("[Error] Bad tuple syntax in configureFontsTranslation text file!")
 											configureTranslationFailed = True
 
 									if not configureTranslationFailed \
@@ -276,7 +272,7 @@ def initOverrideEncoding(pathToConfigureFontsTranslationTxt):
 									elif configureTranslationFailed:
 										break
 							else:
-								print ('[Error] Bad line syntax in configureFontsTranslation text file!')
+								print ("[Error] Bad line syntax in configureFontsTranslation text file!")
 								configureTranslationFailed = True
 								break
 					except:
@@ -294,11 +290,11 @@ def initOverrideEncoding(pathToConfigureFontsTranslationTxt):
 
 					if len(gTargetEncodingPerFont) != len(DEFAULT_TARGET_ENCODING_PER_FONT):
 						# should never happen
-						print ('[Error] Failed to populate internal target encoding per font structure!')
+						print ("[Error] Failed to populate internal target encoding per font structure!")
 						configureTranslationFailed = True
 					else:
 						if gTraceModeEnabled:
-							print ('[Debug] My encodings list: ', gTargetEncodingPerFont)
+							print ("[Debug] My encodings list: ", gTargetEncodingPerFont)
 						configureTranslationFailed = False
 
 	except:
@@ -314,7 +310,7 @@ def initOverrideEncoding(pathToConfigureFontsTranslationTxt):
 	#We no longer assume default out of order list
 	#if(len(gListOfFontNamesToOutOfOrderGlyphs) == 0):
 	#	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)
+	#	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)
@@ -356,23 +352,22 @@ def initActorPropertyEntries(thePathToActorNamesTxt):
 	global gActorPropertyEntries
 	firstLine = True
 	#if gTraceModeEnabled:
-	#	print "[Debug] 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)
+		thePathToActorNamesTxt = os.path.join(u'.', actorNamesTextFile)
 		print ("[Warning] Actor names text file %s not found in arguments. Attempting to open local file if it exists" % (thePathToActorNamesTxt))
 
 	if os.access(thePathToActorNamesTxt, os.F_OK):
 		print ("[Info] Actor names text file found: {0}".format(thePathToActorNamesTxt))
 
-		with open(thePathToActorNamesTxt) as tsv:
+		with openWithUTF8Encoding(thePathToActorNamesTxt, 'r') as tsv:
 			for line in csv.reader(tsv, dialect="excel-tab"):
 				#skip first line header
 				if firstLine == True:
 					#if gTraceModeEnabled:
-					#	print "[Debug] skipping Header line in Excel sheet"
+					#	print ("[Debug] skipping Header line in Excel sheet")
 					firstLine = False
 				else:
 					gActorPropertyEntries.append(line)
@@ -436,7 +431,7 @@ def calculateFoldHash(strFileName):
 		hash = ((hash << 1) | ((hash >> 31) & 1)) + groupSum
 	hash &= 0xFFFFFFFF	   # mask here!
 	if gTraceModeEnabled:
-		print ('[Debug] ', (strParam +': '  +''.join('{:08X}'.format(hash))))
+		print ("[Debug] ", (strParam + ": "  +''.join('{:08X}'.format(hash))))
 	return hash
 
 #
@@ -490,12 +485,11 @@ def outputMIX():
 	errorFound = False
 	outMIXFile = None
 	try:
-		relPath = u'.'
-		outputMixPath = os.path.join(relPath, DEFAULT_SUBTITLES_MIX_OUTPUT_NAME)
+		outputMixPath = os.path.join(u'.', DEFAULT_SUBTITLES_MIX_OUTPUT_NAME)
 		outMIXFile = open(outputMixPath, 'wb')
 	except Exception as e:
 		errorFound = True
-		print ('[Error] Unable to write to output MIX file. ' + str(e))
+		print ("[Error] Unable to write to output MIX file. " + str(e))
 	if not errorFound:
 		# Write header
 		# 2 bytes: number of entries (NumFiles)
@@ -538,24 +532,24 @@ def outputMIX():
 			if sheetDialogueNameTRx[-4:-1] != '.TR':
 				tmpActiveLanguageTRxCode = sheetDialogueNameTRx[-5]
 				sheetDialogueNameTRx = sheetDialogueName[:-4] + ('.TR%s' %(tmpActiveLanguageTRxCode))
-			if os.path.isfile('./' + sheetDialogueNameTRx):
+			if os.path.isfile(os.path.join(u'.', sheetDialogueNameTRx)):
 				entryID = calculateFoldHash(sheetDialogueNameTRx)
-				mixEntryfileSizeBytes = os.path.getsize('./' + sheetDialogueNameTRx)
+				mixEntryfileSizeBytes = os.path.getsize(os.path.join(u'.', sheetDialogueNameTRx))
 				mixFileEntries.append((entryID, sheetDialogueNameTRx, mixEntryfileSizeBytes))
 				totalFilesDataSize += mixEntryfileSizeBytes
 
 		supportedTranslatedTrxFilenamesList = getSupportedTranslatedTrxFilenamesList()
 		for translatedTRxFileName in supportedTranslatedTrxFilenamesList:
-			if os.path.isfile('./' + translatedTRxFileName):
+			if os.path.isfile(os.path.join(u'.', translatedTRxFileName)):
 				entryID = calculateFoldHash(translatedTRxFileName)
-				mixEntryfileSizeBytes = os.path.getsize('./' + translatedTRxFileName)
+				mixEntryfileSizeBytes = os.path.getsize(os.path.join(u'.', translatedTRxFileName))
 				mixFileEntries.append((entryID, translatedTRxFileName, mixEntryfileSizeBytes))
 				totalFilesDataSize += mixEntryfileSizeBytes
 
 		for otherFileName in SUPPORTED_OTHER_FILES_FOR_MIX:
-			if os.path.isfile('./' + otherFileName):
+			if os.path.isfile(os.path.join(u'.', otherFileName)):
 				entryID = calculateFoldHash(otherFileName)
-				mixEntryfileSizeBytes = os.path.getsize('./' + otherFileName)
+				mixEntryfileSizeBytes = os.path.getsize(os.path.join(u'.', otherFileName))
 				mixFileEntries.append((entryID, otherFileName, mixEntryfileSizeBytes))
 				totalFilesDataSize += mixEntryfileSizeBytes
 		mixFileEntries.sort(key=getSortMixFilesKey)
@@ -572,9 +566,10 @@ def outputMIX():
 
 		if gTraceModeEnabled:
 			print ("[Debug] Sorted Entries based on EntryId.")
+			print ("(Entry Id) (File Name) (File Size)")
 		for mixFileEntry in mixFileEntries:
 			if gTraceModeEnabled:
-				print (''.join('{:08X}'.format(mixFileEntry[0])) + ': ' + mixFileEntry[1] + ' : ' + ''.join('{:08X}'.format(mixFileEntry[2])))
+				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
 			outMIXFile.write(entryIDToWrite)
@@ -589,7 +584,7 @@ def outputMIX():
 		errorReadingFound = False
 		for mixFileEntry in mixFileEntries:
 			try:
-				inEntryMIXFile = open("./"+ mixFileEntry[1], 'rb')
+				inEntryMIXFile = open(os.path.join(u'.', mixFileEntry[1]), 'rb')
 			except:
 				errorReadingFound = True
 			if not errorReadingFound:
@@ -622,11 +617,11 @@ def outputMIX():
 	# TODO all strings are NULL terminated in the TRE file!
 
 def translateQuoteToAsciiProper(cellObj, pSheetName):
-	if isinstance(cellObj, float):
+	if isinstance(cellObj, float): # TODO ASDF
 		return ('%.2f' % cellObj).encode('ascii')
 	newQuoteReplaceSpecials =  cellObj
 	#if gTraceModeEnabled:
-	#	print ('[Debug] Encoded to unicode: %s' % (newQuoteReplaceSpecials))
+	#	print ("[Debug] Encoded to unicode: %s" % (newQuoteReplaceSpecials))
 
 	pertinentListOfOutOfOrderGlyphs = []
 
@@ -635,10 +630,10 @@ def translateQuoteToAsciiProper(cellObj, pSheetName):
 	localTargetEncoding = ''
 
 	#if gTraceModeEnabled:
-	#	print '[Debug] ', pSheetName
-	#	print '[Debug] ', mergedListOfSupportedSubtitleSheets
-	#	print '[Debug] ', DEFAULT_SUBTITLES_FONT_NAME[:-4]
-	#	print [x[0] for x in gListOfFontNamesToOutOfOrderGlyphs]
+	#	print ("[Debug] ", pSheetName)
+	#	print ("[Debug] ", mergedListOfSupportedSubtitleSheets)
+	#	print ("[Debug] ", DEFAULT_SUBTITLES_FONT_NAME[:-4])
+	#	print ([x[0] for x in gListOfFontNamesToOutOfOrderGlyphs])
 	if pSheetName in mergedListOfSupportedSubtitleSheets:
 
 		for (tmpFontName, tmpTargetEnc) in gTargetEncodingPerFont:
@@ -682,13 +677,13 @@ def translateQuoteToAsciiProper(cellObj, pSheetName):
 	#try:
 	#	newQuoteReplaceSpecialsRetStr = newQuoteReplaceSpecials.encode(localTargetEncoding)
 	#except:
-	#	print "==============================================================================="
-	#	print "==============================================================================="
-	#	print "ERROR:"
-	#	print newQuoteReplaceSpecials
-	#	print newQuoteReplaceSpecials.encode(localTargetEncoding, errors='xmlcharrefreplace')
-	#	print "==============================================================================="
-	#	print "==============================================================================="
+	#	print ("===============================================================================")
+	#	print ("===============================================================================")
+	#	print ("ERROR:")
+	#	print (newQuoteReplaceSpecials)
+	#	print (newQuoteReplaceSpecials.encode(localTargetEncoding, errors='xmlcharrefreplace'))
+	#	print ("===============================================================================")
+	#	print ("===============================================================================")
 	#	newQuoteReplaceSpecialsRetStr = newQuoteReplaceSpecials.encode(localTargetEncoding, errors='xmlcharrefreplace')
 	return newQuoteReplaceSpecialsRetStr
 	#return newQuoteReplaceSpecialsEnStr
@@ -706,12 +701,13 @@ def parseIntCellValue(cell_obj_value, row_idx, col_idx, xl_sheet_name, xl_sheet_
 
 def addSheet(filename, book, new_sheetname, new_sheet):
 	sheet_names = book.sheet_names
-	sheets = [book.parse(i, header=None) for i in range(len(sheet_names))]
+	sheets = [book.parse(i, header=None, keep_default_na=False, na_filter=False) for i in range(len(sheet_names))]
+	# Note: Using to_excel saves the file, there's no need for extra close() (and it will produce an I/O error)
 	try:
 		with pandas.ExcelWriter(filename) as writer:
-			new_sheet.to_excel(writer, sheet_name=new_sheetname, index=False, header=False)
-			for (name, sheet) in zip(sheet_names, sheets):
-				sheet.to_excel(writer, sheet_name=name, index=False, header=False)
+			new_sheet.to_excel(writer, sheet_name=new_sheetname, index=False, header=False, na_rep="")
+			for (name, sheet) in list(zip(sheet_names, sheets)):
+				sheet.to_excel(writer, sheet_name=name, index=False, header=False, na_rep="")
 	except Exception as e:
 		print ("[Error] Giving up: Could not save to output Excel file:: " + str(e))
 		sys.exit(1) # Terminate if we couldn't write to output Excel file
@@ -736,16 +732,16 @@ def inputXLS(pathtoInputExcelFilename):
 		if xl_workbook is not None:
 			print ("[Info] Opened Excel input file: %s" % (pathtoInputExcelFilename))
 	except Exception as e:
-		print ('[Error] Could not open the Excel input file: '  + str(e))
+		print ("[Error] Could not open the Excel input file: " + str(e))
 
 	if xl_workbook is None:
-		print ('[Error] Giving up. Could not open the specified Excel input file.')
+		print ("[Error] Giving up. Could not open the specified Excel input file.")
 		sys.exit(1) # Terminate if the input Excel was not found
 	# List sheet names, and pull a sheet by name
 	#
 	#sheet_names = xl_workbook.sheet_names()
 	#if gTraceModeEnabled:
-	#	print('[Debug] Sheet Names', sheet_names)
+	#	print ("[Debug] Sheet Names", sheet_names)
 	#
 	#xl_sheet = xl_workbook.sheet_by_name(sheet_names[0])
 
@@ -760,33 +756,35 @@ def inputXLS(pathtoInputExcelFilename):
 	mergedListOfSupportedSubtitleSheets = getSupportedSubtitleSheetsList()
 	supportedTranslatedTrxFilenamesList = getSupportedTranslatedTrxFilenamesList()
 
-	#print '[Debug] mergedListOfSupportedSubtitleSheets: ', mergedListOfSupportedSubtitleSheets
-	#print '[Debug] supportedTranslatedTrxFilenamesList: ', supportedTranslatedTrxFilenamesList
+	#print ("[Debug] mergedListOfSupportedSubtitleSheets: ", mergedListOfSupportedSubtitleSheets)
+	#print ("[Debug] supportedTranslatedTrxFilenamesList: ", supportedTranslatedTrxFilenamesList)
 	mergedListOfSupportedSubtitleSheetsAndTranslatedTREs = mergedListOfSupportedSubtitleSheets + supportedTranslatedTrxFilenamesList
 
 	# Check for a version info sheet and create one if it does not exist
 	xl_sheet = None
 	try:
 		if gTraceModeEnabled:
-			print ('[Debug] Checking for existence of sheet: ' + SUPPORTED_DIALOGUE_VERSION_SHEET)
-		xl_sheet = xl_workbook.parse(SUPPORTED_DIALOGUE_VERSION_SHEET, header=None)
+			print ("[Debug] Checking for existence of sheet: " + SUPPORTED_DIALOGUE_VERSION_SHEET)
+		xl_sheet = xl_workbook.parse(SUPPORTED_DIALOGUE_VERSION_SHEET, header=None, keep_default_na=False, na_filter=False)
 	except Exception as e:
 		if gTraceModeEnabled:
-			print ('[Debug] Could not open requested sheet: ' + SUPPORTED_DIALOGUE_VERSION_SHEET + ' in Excel::' + str(e))
+			print ("[Debug] Could not open requested sheet: " + SUPPORTED_DIALOGUE_VERSION_SHEET + " in Excel::" + str(e))
 
 	if xl_sheet is None:
 		# we didn't find a sheet for version info, so we should auto-create a Sheet for it
 		if gTraceModeEnabled:
-			print ('[Debug] Sheet: %s was not found. Creating a temporary sheet for version info...' % (SUPPORTED_DIALOGUE_VERSION_SHEET))
+			print ("[Debug] Sheet: %s was not found. Creating a temporary sheet for version info..." % (SUPPORTED_DIALOGUE_VERSION_SHEET))
 		sbtlVersTRInstance = sbtlVersTextResource(gTraceModeEnabled)
 		xl_sheet = pandas.DataFrame([
 			['Subtitles Version Info'],
 			['ID', 'Value', 'Notes']
 		] + sbtlVersTRInstance.getSbtlVersEntriesList())
 		addSheet(pathtoInputExcelFilename, xl_workbook, SUPPORTED_DIALOGUE_VERSION_SHEET, xl_sheet)
+		if xl_workbook is not None:
+			xl_workbook.close()
 
 		if gTraceModeEnabled:
-			print ('[Debug] Sheet: %s was created successfully.' % (SUPPORTED_DIALOGUE_VERSION_SHEET))
+			print ("[Debug] Sheet: %s was created successfully." % (SUPPORTED_DIALOGUE_VERSION_SHEET))
 		inputXLS(pathtoInputExcelFilename)
 		return
 	# end of check for a version info sheet
@@ -795,48 +793,50 @@ def inputXLS(pathtoInputExcelFilename):
 	xl_sheet = None
 	try:
 		if gTraceModeEnabled:
-			print ('[Debug] Checking for existence of sheet: ' + SUPPORTED_EX_CR_SHEET)
-		xl_sheet = xl_workbook.parse(SUPPORTED_EX_CR_SHEET, header=None)
+			print ("[Debug] Checking for existence of sheet: " + SUPPORTED_EX_CR_SHEET)
+		xl_sheet = xl_workbook.parse(SUPPORTED_EX_CR_SHEET, header=None, keep_default_na=False, na_filter=False)
 	except Exception as e:
 		if gTraceModeEnabled:
-			print ('[Debug] Could not open requested sheet: ' + SUPPORTED_EX_CR_SHEET + ' in Excel::' + str(e))
+			print ("[Debug] Could not open requested sheet: " + SUPPORTED_EX_CR_SHEET + " in Excel::" + str(e))
 
 	if xl_sheet is None:
 		# we didn't find a sheet for extra info, so we should auto-create a Sheet for it
 		if gTraceModeEnabled:
-			print ('[Debug] Sheet: %s was not found. Creating a temporary sheet for version info...' % (SUPPORTED_EX_CR_SHEET))
+			print ("[Debug] Sheet: %s was not found. Creating a temporary sheet for version info..." % (SUPPORTED_EX_CR_SHEET))
 		excrTRInstance = extracTextResource(gTraceModeEnabled)
 		xl_sheet = pandas.DataFrame([['Extra Info'], ['ID', 'Value', 'Notes']]
 					    + excrTRInstance.getExtracEntriesList())
 
 		addSheet(pathtoInputExcelFilename, xl_workbook, SUPPORTED_EX_CR_SHEET, xl_sheet)
+		if xl_workbook is not None:
+			xl_workbook.close()
 
 		if gTraceModeEnabled:
-			print ('[Debug] Sheet: %s was created successfully.' % (SUPPORTED_EX_CR_SHEET))
+			print ("[Debug] Sheet: %s was created successfully." % (SUPPORTED_EX_CR_SHEET))
 		inputXLS(pathtoInputExcelFilename)
 		return
 	# end of check for a extra info sheet
 
 	if gTraceModeEnabled:
-		print ('[Debug] mergedListOfSupportedSubtitleSheetsAndTranslatedTREs: ', mergedListOfSupportedSubtitleSheetsAndTranslatedTREs)
+		print ("[Debug] mergedListOfSupportedSubtitleSheetsAndTranslatedTREs: ", mergedListOfSupportedSubtitleSheetsAndTranslatedTREs)
 	for sheetDialogueName in mergedListOfSupportedSubtitleSheetsAndTranslatedTREs:
 		xl_sheet = None
 		try:
-			xl_sheet = xl_workbook.parse(sheetDialogueName, header=None)
+			xl_sheet = xl_workbook.parse(sheetDialogueName, header=None, keep_default_na=False, na_filter=False)
 		except Exception as e:
 			if gTraceModeEnabled:
-				print ('[Debug] Could not open requested sheet: ' + sheetDialogueName + ' in Excel::' + str(e))
+				print ("[Debug] Could not open requested sheet: " + sheetDialogueName + " in Excel::" + str(e))
 
 		if xl_sheet is None:
 			if (not gTraceModeEnabled) and (sheetDialogueName not in supportedTranslatedTrxFilenamesList):
-				print ('[Warning] %s sheet was not found in input Excel file.' % (sheetDialogueName))
+				print ("[Warning] %s sheet was not found in input Excel file." % (sheetDialogueName))
 
 		if xl_sheet is not None:
 			if gTraceModeEnabled:
-				print ('[Debug] Sheet name: %s' % sheetDialogueName)
+				print ("[Debug] Sheet name: %s" % sheetDialogueName)
 			gNumOfSpokenQuotes = xl_sheet.shape[0] - 2 # all rows minus the first TWO rows with headers
 			if gTraceModeEnabled:
-				print ('[Debug] Number of spoken quotes: %d' % gNumOfSpokenQuotes)
+				print ("[Debug] Number of spoken quotes: %d" % gNumOfSpokenQuotes)
 			# stats for debug
 			extremeQuotesList = []
 			longestLength = 0
@@ -862,19 +862,20 @@ def inputXLS(pathtoInputExcelFilename):
 
 			if sheetDialogueName in supportedInGameQuotesSheetsList:
 				if gTraceModeEnabled:
-					print ('[Debug] IN GAME QUOTES')
+					print ("[Debug] IN GAME QUOTES")
 				mode = 1 #in-game quote
 			elif sheetDialogueName in mergedListOfSupportedSubtitleSheets:
 				if gTraceModeEnabled:
-					print ('[Debug] VQA SCENE DIALOGUE')
+					print ("[Debug] VQA SCENE DIALOGUE")
 				mode = 2 #VQA
 				# check if the VQA sheets are of the old format or the new format
 				cell_obj = xl_sheet.iat[1, 0]
-				if cell_obj is not None and isinstance(cell_obj, str) and cell_obj.lower() == 'frame start':
+				#print ("cell_obj is ", type(cell_obj)) ## unicode for python 2, srt in python 3
+				if cell_obj is not None and ((sys.version_info[0] <= 2 and isinstance(cell_obj, unicode) and cell_obj.decode('utf-8').lower() == 'frame start') or (isinstance(cell_obj, str) and cell_obj.lower() == 'frame start')):
 					vqaSheetFormatVersion = 1
 			elif sheetDialogueName in supportedTranslatedTrxFilenamesList:
 				if gTraceModeEnabled:
-					print ('[Debug] TRANSLATED TEXT RESOURCE')
+					print ("[Debug] TRANSLATED TEXT RESOURCE")
 				mode = 3 # Translated TRE
 			#
 			del gTableOfStringIds[:]
@@ -882,16 +883,16 @@ def inputXLS(pathtoInputExcelFilename):
 			del gTableOfStringOffsets[:]
 			for row_idx in range(2, xl_sheet.shape[0]):
 				#if gTraceModeEnabled:
-				#	print "[Debug] Line %d" % (row_idx)
+				#	print ("[Debug] Line %d" % (row_idx))
 				for col_idx in range(0, xl_sheet.shape[1]):
 					cell_obj = xl_sheet.iat[row_idx, col_idx]
-#					print ('[Debug] Coord: [%d, %d, %s] cell_obj: [%s]' % (col_idx, row_idx, sheetDialogueName, cell_obj))
+#					print ("[Debug] Coord: [%d, %d, %s] cell_obj: [%s]" % (col_idx, row_idx, sheetDialogueName, cell_obj))
 					#
 					# FOR IN-GAME QUOTES -- Iterate through columns starting from col 0. We need cols: 0, 2
 					#
 					if mode == 1:
 						#if gTraceModeEnabled:
-						#	print ('[Debug] 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.split('.', 1)
@@ -902,7 +903,7 @@ def inputXLS(pathtoInputExcelFilename):
 									tmpSubQuotePart = parseIntCellValue(twoTokensfirstColSplitAtDashXLS[1], row_idx, col_idx, sheetDialogueName, xl_sheet.shape[0], xl_sheet.shape[1])
 									tmpQuoteID = tmpActorPart * 10000 + tmpSubQuotePart
 									#if gTraceModeEnabled:
-									#	print ('[Debug] 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))
 									gTableOfStringIds.append(tmpQuoteID)
 									#if(tmpQuoteID == 160110 or tmpQuoteID == 160010):
 									#	switchFlagShowQuote = True
@@ -910,16 +911,16 @@ def inputXLS(pathtoInputExcelFilename):
 						elif(col_idx == 1) :
 							#if switchFlagShowQuote == True:
 								#if gTraceModeEnabled:
-								#	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 ('[Debug] decoded to unicode: %s ' % (newQuoteReplaceSpecials)) # error with char xf1
+								#	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 ("[Debug] decoded to unicode: %s " % (newQuoteReplaceSpecials)) # error with char xf1
 							newQuoteReplaceSpecialsAscii = translateQuoteToAsciiProper(cell_obj, sheetDialogueName)
 							#if switchFlagShowQuote == True:
 								#if gTraceModeEnabled:
-								#	print ('[Debug] length: %d: %s' % (len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii))
+								#	print ("[Debug] length: %d: %s" % (len(newQuoteReplaceSpecialsAscii), newQuoteReplaceSpecialsAscii))
 							#if gTraceModeEnabled:
-							#	print ':'.join(x.encode('hex') for x in newQuoteReplaceSpecialsAscii)	 # seems to work.  new chars are non-printable but exist in string
+							#	print (':'.join(x.encode('hex') for x in newQuoteReplaceSpecialsAscii))	 # seems to work.  new chars are non-printable but exist in string
 
 							gTableOfStringEntries.append(newQuoteReplaceSpecialsAscii)
 							gTableOfStringOffsets.append(curStrStartOffset)
@@ -929,7 +930,7 @@ def inputXLS(pathtoInputExcelFilename):
 							if ( predefinedLengthThreshold < len(newQuoteReplaceSpecialsAscii)):
 								extremeQuotesList.append((tmpQuoteID, newQuoteReplaceSpecialsAscii))
 								quoteNumAboveThreshold += 1
-								#print ('[Debug] 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
 					# Earlier versions (up to Jun 23): We need columns: 2, 9, 10
@@ -938,12 +939,12 @@ def inputXLS(pathtoInputExcelFilename):
 					elif mode == 2:
 						if (col_idx == 2): # subtitle text
 							newQuoteReplaceSpecialsAscii = translateQuoteToAsciiProper(cell_obj, sheetDialogueName)
-							#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
+							#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 gTableOfStringEntries yet
 						elif (vqaSheetFormatVersion == 1 and col_idx == 0) or (vqaSheetFormatVersion == 0 and col_idx == 9):
 							# startFrame
-							#print "[Debug] cell: %s" % (cell_obj.value)
+							#print ("[Debug] cell: %s" % (cell_obj.value))
 							tmpStartFrame = parseIntCellValue(cell_obj, row_idx, col_idx, sheetDialogueName, xl_sheet.shape[0], xl_sheet.shape[1])
 						elif (vqaSheetFormatVersion == 1 and col_idx == 1) or (vqaSheetFormatVersion == 0 and col_idx == 10):
 							# endFrame
@@ -964,17 +965,17 @@ def inputXLS(pathtoInputExcelFilename):
 					# For translated TRE sheets the id is already in first column, the text is in the next one
 					#
 					elif mode == 3:
-						if gTraceModeEnabled:
-							print ('[Debug] Column: [%s] cell_obj: [%s]' % (col_idx, cell_obj))
+						#if gTraceModeEnabled:
+						#	print ("[Debug] Column: [%s] cell_obj: [%s]" % (col_idx, cell_obj))
 						if(col_idx == 0):
 							tmpQuoteID = parseIntCellValue(cell_obj, row_idx, col_idx, sheetDialogueName, xl_sheet.shape[0], xl_sheet.shape[1])
 							gTableOfStringIds.append(tmpQuoteID)
 						elif(col_idx == 1) :
 							#if switchFlagShowQuote == True:
-							#	 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 ('[Debug] decoded to unicode: %s ' % (newQuoteReplaceSpecials)) # error with char xf1
+							#	 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 ("[Debug] decoded to unicode: %s " % (newQuoteReplaceSpecials)) # error with char xf1
 							newQuoteReplaceSpecialsAscii = translateQuoteToAsciiProper(cell_obj, sheetDialogueName)
 							if sheetDialogueName == SUPPORTED_DIALOGUE_VERSION_SHEET:
 								if tmpQuoteID == 2:
@@ -984,8 +985,8 @@ def inputXLS(pathtoInputExcelFilename):
 								elif tmpQuoteID == 3:
 									newQuoteReplaceSpecialsAscii = makeAscii(gActiveLanguageDescriptionCodeTuple[2])
 							#if switchFlagShowQuote == True:
-							#	 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
+							#	 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
 
 							gTableOfStringEntries.append(newQuoteReplaceSpecialsAscii)
 							gTableOfStringOffsets.append(curStrStartOffset)
@@ -995,11 +996,11 @@ def inputXLS(pathtoInputExcelFilename):
 							if ( predefinedLengthThreshold < len(newQuoteReplaceSpecialsAscii)):
 								extremeQuotesList.append((tmpQuoteID, newQuoteReplaceSpecialsAscii))
 								quoteNumAboveThreshold += 1
-								#print ('[Debug] 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))
 
 			gTableOfStringOffsets.append(curStrStartOffset) # the final extra offset entry
 			if gTraceModeEnabled:
-				print ('[Debug] Longest Length: %d, Quotes above threshold (%d): %d' % (longestLength, predefinedLengthThreshold, quoteNumAboveThreshold))
+				print ("[Debug] Longest Length: %d, Quotes above threshold (%d): %d" % (longestLength, predefinedLengthThreshold, quoteNumAboveThreshold))
 				for extremQuotTuple in extremeQuotesList:
 					print ("[Debug] Id: %d, Q: %s" % (extremQuotTuple[0], extremQuotTuple[1]))
 			#
@@ -1017,10 +1018,10 @@ def inputXLS(pathtoInputExcelFilename):
 				tmpActiveLanguageTRxCode = outTRxFileName[-5]
 				outTRxFileName = sheetDialogueName[:-4] + ('.TR%s' %(tmpActiveLanguageTRxCode))
 			try:
-				outTRxFile = open("./" + outTRxFileName, 'wb')
+				outTRxFile = open(os.path.join(u'.', outTRxFileName), 'wb')
 			except Exception as e:
 				errorFound = True
-				print ('[Error] Unable to write to output file %s:: ' %(outTRxFileName)) + str(e)
+				print ("[Error] Unable to write to output file %s:: " %(outTRxFileName)) + str(e)
 			if not errorFound:
 				numOfSpokenQuotesToWrite = pack('I', gNumOfSpokenQuotes)	# unsigned integer 4 bytes
 				outTRxFile.write(numOfSpokenQuotesToWrite)
@@ -1037,6 +1038,8 @@ def inputXLS(pathtoInputExcelFilename):
 					outTRxFile.write(gTableOfStringEntries[idxe])
 					outTRxFile.write(b'\0')
 				outTRxFile.close()
+	if xl_workbook is not None:
+		xl_workbook.close()
 	return
 
 #
@@ -1082,7 +1085,7 @@ def main(argsCL):
 
 	invalidSyntax = False
 	print ("Running %s (%s)..." % (APP_NAME_SPACED, APP_VERSION))
-	#print "Len of sysargv = %s" % (len(argsCL))
+	#print ("Len of sysargv = %s" % (len(argsCL)))
 	if len(argsCL) == 2:
 		if(argsCL[1] == '--help'or argsCL[1] == '-h'):
 			print ("%s %s supports Westwood's Blade Runner PC Game (1997)." % (APP_NAME_SPACED, APP_VERSION))
@@ -1148,8 +1151,7 @@ def main(argsCL):
 			print ("[Info] Game Language Selected: %s (%s)" % (gActiveLanguageDescriptionCodeTuple[0], gActiveLanguageDescriptionCodeTuple[2]))
 			#
 			# Early check for external subtitles font file, since we no longer support internal font
-			relPath = u'.'
-			thePathToExternalFontFileFon = os.path.join(relPath, DEFAULT_SUBTITLES_FONT_NAME)
+			thePathToExternalFontFileFon = os.path.join(u'.', DEFAULT_SUBTITLES_FONT_NAME)
 			if not os.path.isfile(thePathToExternalFontFileFon):
 				print ("[Error] Font file %s for subtitles was not found!" % (thePathToExternalFontFileFon))
 				sys.exit(1)
@@ -1192,5 +1194,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/module.mk b/devtools/create_bladerunner/subtitles/module.mk
index 28c65826590..6a02cbde89f 100644
--- a/devtools/create_bladerunner/subtitles/module.mk
+++ b/devtools/create_bladerunner/subtitles/module.mk
@@ -7,7 +7,7 @@ FONT_OUTPUT := SUBTLS_E.FON
 
 BLADERUNNER_SUBTITLES_SCRIPTS_ROOT_FOLDER := $(srcdir)/devtools/create_bladerunner/subtitles
 BLADERUNNER_SUBTITLES_SAMPLE_INPUT_FOLDER := $(srcdir)/devtools/create_bladerunner/subtitles/sampleInput
-INTERMEDIATE_RESOURCE_FILES_UI := OPTIONS.TR* DLGMENU.TR* SCORERS.TR* VK.TR* CLUES.TR* CRIMES.TR* ACTORS.TR* HELP.TR* AUTOSAVE.TR* ERRORMSG.TR* SPINDEST.TR* KIA.TR* KIACRED.TR* CLUETYPE.TR* ENDCRED.TR* POGO.TR* SBTLVERS.TR*
+INTERMEDIATE_RESOURCE_FILES_UI := OPTIONS.TR* DLGMENU.TR* SCORERS.TR* VK.TR* CLUES.TR* CRIMES.TR* ACTORS.TR* HELP.TR* EXTRA.TR* AUTOSAVE.TR* ERRORMSG.TR* SPINDEST.TR* KIA.TR* KIACRED.TR* CLUETYPE.TR* ENDCRED.TR* POGO.TR* SBTLVERS.TR*
 INTERMEDIATE_RESOURCE_FILES_SUBS := INGQUO_*.TR* WSTLGO_E.TR* BRLOGO_E.TR* INTRO_*.TR* MW_A_*.TR* MW_B01_*.TR* MW_B02_*.TR* MW_B03_*.TR* MW_B04_*.TR* MW_B05_*.TR* INTRGT_*.TR* MW_D_*.TR* MW_C01_*.TR* MW_C02_*.TR* MW_C03_*.TR* END04A_*.TR* END04B_*.TR* END04C_*.TR* END06_*.TR* END01A_*.TR* END01B_*.TR* END01C_*.TR* END01D_*.TR* END01E_*.TR* END01F_*.TR* END03_*.TR* TB_FLY_*.TR*
 INPUT_TRANSCRIPT_FILENAME := englishTranscript.xls
 INPUT_TRANSCRIPT_FILEPATH := $(BLADERUNNER_SUBTITLES_SAMPLE_INPUT_FOLDER)/$(INPUT_TRANSCRIPT_FILENAME)
@@ -37,7 +37,7 @@ $(FONT_OUTPUT): $(BLADERUNNER_SUBTITLES_SAMPLE_INPUT_FOLDER)/$(INPUT_FONT_GLYPHS
 	$(info If successful, a $(FONT_OUTPUT) file will be created in your working directory)
 	$(info This is an intermediate file. You don't need to copy this in your Blade Runner game directory)
 	$(info ---------)
-	$(BLADERUNNER_SUBTITLES_SCRIPTS_ROOT_FOLDER)/fontCreator/fontCreator.py -im $(BLADERUNNER_SUBTITLES_SAMPLE_INPUT_FOLDER)/$(INPUT_FONT_GLYPHS_PNG_FILENAME) -oe $(BLADERUNNER_SUBTITLES_SAMPLE_INPUT_FOLDER)/$(INPUT_FONT_GLYPHS_PNG_AUX_CONF_FILENAME) -om $(FONT_OUTPUT) -pxLL 42 -pxTT 30 -pxKn 1 -pxWS 7
+	$(BLADERUNNER_SUBTITLES_SCRIPTS_ROOT_FOLDER)/fontCreator/fontCreator.py -im $(BLADERUNNER_SUBTITLES_SAMPLE_INPUT_FOLDER)/$(INPUT_FONT_GLYPHS_PNG_FILENAME) -oe $(BLADERUNNER_SUBTITLES_SAMPLE_INPUT_FOLDER)/$(INPUT_FONT_GLYPHS_PNG_AUX_CONF_FILENAME) -om $(FONT_OUTPUT) -pxLL 42 -pxTT 30 -pxKn 1 -pxWS 7 --trace
 
 # Creation of final output mix file SUBTILES.MIX
 # The MIX file will pack the fonts file $(FONT_OUTPUT) as well as resources created from the transcript (EXCEL) file $(INPUT_TRANSCRIPT_FILENAME)
@@ -55,5 +55,5 @@ $(TOOL_OUTPUT): $(FONT_OUTPUT) $(INPUT_TRANSCRIPT_FILEPATH) $(BLADERUNNER_SUBTIT
 	$(info If successful, a $(TOOL_OUTPUT) file will be created in your working directory)
 	$(info Please, copy this $(TOOL_OUTPUT) into your Blade Runner game directory!)
 	$(info ---------)
-	$(BLADERUNNER_SUBTITLES_SCRIPTS_ROOT_FOLDER)/mixResourceCreator/mixResourceCreator.py -x $(INPUT_TRANSCRIPT_FILEPATH) -ian $(BLADERUNNER_SUBTITLES_SCRIPTS_ROOT_FOLDER)/common/actornames.txt -cft $(BLADERUNNER_SUBTITLES_SAMPLE_INPUT_FOLDER)/$(INPUT_TRANSCRIPT_AUX_CONF_FILENAME) -ld EFIGS
+	$(BLADERUNNER_SUBTITLES_SCRIPTS_ROOT_FOLDER)/mixResourceCreator/mixResourceCreator.py -x $(INPUT_TRANSCRIPT_FILEPATH) -ian $(BLADERUNNER_SUBTITLES_SCRIPTS_ROOT_FOLDER)/common/actornames.txt -cft $(BLADERUNNER_SUBTITLES_SAMPLE_INPUT_FOLDER)/$(INPUT_TRANSCRIPT_AUX_CONF_FILENAME) -ld EFIGS --trace
 	-$(RM) $(INTERMEDIATE_RESOURCE_FILES_UI) $(INTERMEDIATE_RESOURCE_FILES_SUBS)
diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileDecode.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileDecode.py
index b1e6a594f68..722b40a2c5b 100644
--- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileDecode.py
+++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileDecode.py
@@ -7,7 +7,7 @@ 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
 
@@ -17,7 +17,7 @@ if 	(not ctypesLibFound):
 
 from struct import *
 
-MY_MODULE_VERSION = "0.60"
+MY_MODULE_VERSION = "0.70"
 MY_MODULE_NAME = "audFileDecode"
 
 aud_ima_index_adjust_table = [-1, -1, -1, -1, 2, 4, 6, 8]
@@ -53,16 +53,16 @@ def aud_decode_ima_chunk(audioBufferIn, index, sample, cs_chunk):
 	audioBufferOut = []
 	#for i in range(0, len(audioBufferIn)):
 	#if self.m_traceModeEnabled:
-	#	print '[Debug] %d: %d'%(i, int(audioBufferIn[i]))
+	#	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" % \
-		#		(''.join('{:04X}'.format(cs_chunk)), ''.join('{:02X}'.format(sample_index)), ''.join('{:02X}'.format(sample_index >> 1)), ''.join('{:04X}'.format(int(code))))
+		#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]
 		delta = step >> 3
@@ -83,7 +83,7 @@ def aud_decode_ima_chunk(audioBufferIn, index, sample, cs_chunk):
 		audioBufferOut.append(ctypes.c_short( sample ).value )
 		#audioBufferOut.append(sample) # it's not different from above... ctypes.c_short( sample ).value
 		#if self.m_traceModeEnabled:
-		#	print "[Debug] audio_out[%s]: %s" % (''.join('{:02X}'.format(sample_index)), ''.join('{:02X}'.format(audioBufferOut[sample_index])));
+		#	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
@@ -219,9 +219,9 @@ if __name__ == '__main__':
 	#	 main()
 	decodeInstance = audFileDecode()
 	if decodeInstance.m_traceModeEnabled:
-		print "[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION)
+		print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 
 else:
 	#debug
-	#print "[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION)
+	#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	pass
diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileLib.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileLib.py
index 2e4181b1621..212da7ea642 100644
--- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileLib.py
+++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/audFileLib.py
@@ -11,28 +11,28 @@ structLibFound = False
 try:
 	import os
 except ImportError:
-	print "[Error] os python library is required to be installed!"
+	print ("[Error] os python library is required to be installed!")
 else:
 	osLibFound = True
 
 try:
 	import sys
 except ImportError:
-	print "[Error] sys python library is required to be installed!"
+	print ("[Error] sys python library is required to be installed!")
 else:
 	sysLibFound = 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 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
 
@@ -46,7 +46,7 @@ if 	(not osLibFound) \
 from struct import *
 from audFileDecode import *
 
-MY_MODULE_VERSION = "0.80"
+MY_MODULE_VERSION = "0.90"
 MY_MODULE_NAME = "audFileLib"
 
 #constants
@@ -93,10 +93,10 @@ class audFile(object):
 	# std::fstream& fs, AudFileNS::pos_type startAudFilepos, AudFileNS::pos_type endAudFilepos, const std::string& filename
 	def export_as_wav(self, audBytesBuff, filename):
 		if (not self.header().m_populated):
-			print "[Error] file was not loaded properly (header info missing): " + filename
+			print ("[Error] file was not loaded properly (header info missing): " + filename)
 			return 1
 
-		print "[Info] Exporting to wav: " + filename
+		print ("[Info] Exporting to wav: " + filename)
 
 		cvirtualBinaryD = None
 		if self.header().m_compression > 0:
@@ -104,9 +104,9 @@ class audFile(object):
 		elif self.header().m_flags == 2: # compression 0, 16bit stereo
 			cbinaryDataOutLst = []
 			offsInAudFile = SIZE_OF_AUD_HEADER_IN_BYTES
-			for i in range(0, (len(audBytesBuff) - SIZE_OF_AUD_HEADER_IN_BYTES) / 2):
+			for i in range(0, (len(audBytesBuff) - SIZE_OF_AUD_HEADER_IN_BYTES) // 2):
 				if (self.m_traceModeEnabled):
-					print "[Trace] Reading bytes %d, %d" % (2*i, 2*i + 1)
+					print ("[Trace] Reading bytes %d, %d" % (2*i, 2*i + 1))
 				tmpTupleL = struct.unpack_from('B', audBytesBuff, offsInAudFile)
 				offsInAudFile += 1
 				tmpTupleH = struct.unpack_from('B', audBytesBuff, offsInAudFile)
@@ -116,10 +116,10 @@ class audFile(object):
 			cvirtualBinaryD = struct.pack('B'*len(cbinaryDataOutLst), *cbinaryDataOutLst)
 
 		if (not cvirtualBinaryD and (len(audBytesBuff) - SIZE_OF_AUD_HEADER_IN_BYTES) > 0):
-			print "[Error] audio file could not be exported properly (0 data read): %s" % (filename)
+			print ("[Error] audio file could not be exported properly (0 data read): %s" % (filename))
 			return 1
 		elif (len(audBytesBuff) - SIZE_OF_AUD_HEADER_IN_BYTES) == 0:
-			print "[Warning] Creating empty wav file: %s" % (filename)
+			print ("[Warning] Creating empty wav file: %s" % (filename))
 
 		cb_sample = self.get_cb_sample()
 		cs_remaining = self.get_c_samples()
@@ -132,7 +132,6 @@ class audFile(object):
 		#waveWritFile.setcomptype(None, '')
 		waveWritFile.writeframesraw(cvirtualBinaryD)
 		waveWritFile.close()
-
 #		t_wav_header header;
 #		memset(&header, 0, sizeof(t_wav_header));
 #		header.file_header.id = wav_file_id; // # "RIFF"
@@ -173,10 +172,10 @@ class audFile(object):
 		offsInAudFile += 1
 
 		if self.m_traceModeEnabled:
-			print "[Debug] Sample rate: %d\tsizeIn: %d\tsizeOut: %d\tflags: %d\tcompression: %d" % (self.get_samplerate(), self.header().m_size_in, self.header().m_size_out, self.header().m_flags, self.header().m_compression)
+			print ("[Debug] Sample rate: %d\tsizeIn: %d\tsizeOut: %d\tflags: %d\tcompression: %d" % (self.get_samplerate(), self.header().m_size_in, self.header().m_size_out, self.header().m_flags, self.header().m_compression))
 
 		if self.get_samplerate() < 8000 or self.get_samplerate() > 48000 or self.header().m_size_in > (maxLength - SIZE_OF_AUD_HEADER_IN_BYTES ):
-			print "[Warning] Bad AUD Header info in file %s, size_in: %d, maxLen: %d" % (self.m_simpleAudioFileName, self.header().m_size_in, (maxLength - SIZE_OF_AUD_HEADER_IN_BYTES))
+			print ("[Warning] Bad AUD Header info in file %s, size_in: %d, maxLen: %d" % (self.m_simpleAudioFileName, self.header().m_size_in, (maxLength - SIZE_OF_AUD_HEADER_IN_BYTES)))
 			if self.header().m_size_in == 0:
 				# handle special case where only the header of the AUD file is present and the size_in is 0.
 				# fill the header with "valid" info for an empty wav file
@@ -210,7 +209,7 @@ class audFile(object):
 		rAudPos = SIZE_OF_AUD_HEADER_IN_BYTES
 
 		if (self.m_traceModeEnabled):
-			print "[Trace] Getting chunk header at %d" % (rAudPos)
+			print ("[Trace] Getting chunk header at %d" % (rAudPos))
 		#AudChunkHeader  tmpInremediateChunkheader;
 		tmpInremediateChunkheader = AudChunkHeader()
 		#while (i--) # value of i is decreased after checked by while loop
@@ -257,8 +256,8 @@ class audFile(object):
 		#fs.read((char*)byteChunkDataPtr, sizeToRead)
 		outChunkDataLst = []
 		if (self.m_traceModeEnabled):
-			print "[Trace] Getting chunk data"
-			print "[Trace] startOffs: %d, sizeToRead: %d" % (startOffs, sizeToRead)
+			print ("[Trace] Getting chunk data")
+			print ("[Trace] 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)
@@ -275,7 +274,7 @@ class audFile(object):
 		# 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)
 		if self.m_traceModeEnabled:
-			print "[Debug] Decoding AUD file format..."
+			print ("[Debug] Decoding AUD file format...")
 #		Cvirtual_binary d;
 		binaryDataOutLst = []
 		binaryDataOutBuff = None
@@ -293,11 +292,11 @@ class audFile(object):
 				(errGetChunk, bufferDataPos, out_chunk_header) = self.get_chunk_header(chunk_i, audBytesBuff, len(audBytesBuff))
 				if errGetChunk != 0:
 					if self.m_traceModeEnabled:
-						print "[Trace] Error OR End file case while getting uncompressed chunk header!"
+						print ("[Trace] Error OR End file case while getting uncompressed chunk header!")
 					break
 
 				if self.m_traceModeEnabled:
-					print "[Trace] Get uncompressed chunk header returned: %d " % (out_chunk_header.m_ch_id)
+					print ("[Trace] Get uncompressed chunk header returned: %d " % (out_chunk_header.m_ch_id))
 				#Cvirtual_binary out_chunk_data;
 				#AudFileNS::byte* byteChunkDataPtr = out_chunk_data.write_start(out_chunk_header.m_ch_size_in);
 				(errorGCD, byteChunkDataLst) = self.get_chunk_data(audBytesBuff, bufferDataPos, out_chunk_header.m_ch_size_in)
@@ -317,42 +316,44 @@ class audFile(object):
 			wIndex = 0
 			while (wIndex < cb_audio):
 				if self.m_traceModeEnabled:
-					print("[Trace] chunkI: %d\t Windex: %d\t cb_audio: %d") % (chunk_i,wIndex,cb_audio)
+					print ("[Trace] 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
 				if self.m_traceModeEnabled:
-					print "[Trace] Get COMPRESSED chunk header returned:: headerInSize: %d headerOutSize: %d id: %d" % (out_chunk_header.m_ch_size_in, out_chunk_header.m_ch_size_out,  out_chunk_header.m_ch_id)
+					print ("[Trace] Get COMPRESSED chunk header returned:: headerInSize: %d headerOutSize: %d id: %d" % (out_chunk_header.m_ch_size_in, out_chunk_header.m_ch_size_out,  out_chunk_header.m_ch_id))
 				#Cvirtual_binary out_chunk_data;
 				#AudFileNS::byte* byteChunkDataPtr = out_chunk_data.write_start(out_chunk_header.m_ch_size_in);
 				(errorGCD, byteChunkDataLst) = self.get_chunk_data(audBytesBuff, bufferDataPos, out_chunk_header.m_ch_size_in)
 				# export decoded chunk to w (output) buffer (of SHORTS) at the point where we're currently at (so append there)
 				if self.m_traceModeEnabled:
-					print "[Trace] byteChunkDataLst len: %d, m_ch_size_in was: %d" % (len(byteChunkDataLst), out_chunk_header.m_ch_size_in)
-				decodedAudioChunkAsLst = decodeInstance.decode_chunk(byteChunkDataLst, out_chunk_header.m_ch_size_out / self.get_cb_sample());
+					print ("[Trace] byteChunkDataLst len: %d, m_ch_size_in was: %d" % (len(byteChunkDataLst), out_chunk_header.m_ch_size_in))
+				# Use "//" for floor int division in decode_chunk(), since in python 3 just using "/" would result in float and that leads to error
+				decodedAudioChunkAsLst = decodeInstance.decode_chunk(byteChunkDataLst, (out_chunk_header.m_ch_size_out // self.get_cb_sample()));
 				binaryDataOutLst.extend(decodedAudioChunkAsLst)
 				wIndex += out_chunk_header.m_ch_size_out
 				if self.m_traceModeEnabled:
-					print("[Trace] New Windex: %d\t cb_audio: %d") % (wIndex,cb_audio)
+					print ("[Trace] 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 "[Trace] Decoding Done."
+					print ("[Trace] Decoding Done.")
 			else: #if binaryDataOutBuff is None:
-				print "[Error] Decoding yielded errors (data out buffer is null)."
+				print ("[Error] Decoding yielded errors (data out buffer is null).")
 		return binaryDataOutBuff
 
 	def header(self):
 		return self.m_header
 
 	def get_c_samples(self):
-		return self.m_header.m_size_out / self.get_cb_sample()
+		# Use "//" for floor int division in return value, since in python 3 just using "/" would result in float and that leads to error
+		return (self.m_header.m_size_out // self.get_cb_sample())
 
 	def get_samplerate(self):
 		return self.m_header.m_samplerate;
@@ -376,37 +377,37 @@ if __name__ == '__main__':
 	inAUDFileName = '00000000.AUD'
 
 	if len(sys.argv[1:])  > 0 \
-		and os.path.isfile(os.path.join('.', sys.argv[1])) \
+		and os.path.isfile(os.path.join(u'.', sys.argv[1])) \
 		and len(sys.argv[1]) >= 5 \
 		and sys.argv[1][-3:].upper() == 'AUD':
 		inAUDFileName = sys.argv[1]
-		print "[Info] Attempting to use %s as input AUD file..." % (inAUDFileName)
-	elif os.path.isfile(os.path.join('.', inAUDFileName)):
-		print "[Info] Using default %s as input AUD file..." % (inAUDFileName)
+		print ("[Info] Attempting to use %s as input AUD file..." % (inAUDFileName))
+	elif os.path.isfile(os.path.join(u'.', inAUDFileName)):
+		print ("[Info] Using default %s as input AUD file..." % (inAUDFileName))
 	else:
-		print "[Error] No valid input file argument was specified and default input file %s is missing." % (inAUDFileName)
+		print ("[Error] No valid input file argument was specified and default input file %s is missing." % (inAUDFileName))
 		errorFound = True
 
 	if not errorFound:
 		try:
-			print "[Info] Opening %s" % (inAUDFileName)
-			inAUDFile = open(os.path.join('.', inAUDFileName), 'rb')
+			print ("[Info] Opening %s" % (inAUDFileName))
+			inAUDFile = open(os.path.join(u'.', 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(True)
 			if audFileInstance.m_traceModeEnabled:
-				print "[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION)
+				print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 			if audFileInstance.loadAudFile(allOfAudFileInBuffer, len(allOfAudFileInBuffer), inAUDFileName):
-				print "[Info] Audio file (AUD) loaded successfully!"
+				print ("[Info] Audio file (AUD) loaded successfully!")
 				audFileInstance.export_as_wav(allOfAudFileInBuffer, './tmp.wav')
 			else:
-				print "[Error] Error while loading Audio file (AUD)!"
+				print ("[Error] Error while loading Audio file (AUD)!")
 			inAUDFile.close()
 else:
 	#debug
-	#print "[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION)
+	#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	pass
diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/devCommentaryText.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/devCommentaryText.py
index 1c94a82fdc5..4d29dcb75ab 100644
--- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/devCommentaryText.py
+++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/devCommentaryText.py
@@ -2,8 +2,8 @@
 # -*- coding: utf-8 -*-
 #
 
-my_module_version = "1.00"
-my_module_name = "devCommentaryText"
+MY_MODULE_VERSION = "1.10"
+MY_MODULE_NAME = "devCommentaryText"
 
 # All game versions should have the English text pre-filled in the POGO sheet
 DEV_AUDIO_COMMENTARY_TUPLE_LIST = [
@@ -59,46 +59,46 @@ class devCommentaryText(object):
 
 	def printTexts(self):
 		if self.m_traceModeEnabled:
-			print "[Trace] Printing all dev commentary text"
-		print "\nAUDIO COMMENTARY"
-		print "------------------"
+			print ("[Trace] Printing all dev commentary text")
+		print ("\nAUDIO COMMENTARY")
+		print ("------------------")
 		for (idTre, textTre) in DEV_AUDIO_COMMENTARY_TUPLE_LIST:
-			print "%s\t%s" % (idTre, textTre)
-		print "\nEXTRA SPEECH AUDIO"
-		print "------------------"
+			print ("%s\t%s" % (idTre, textTre))
+		print ("\nEXTRA SPEECH AUDIO")
+		print ("------------------")
 		for (idTre, textTre) in EXTRA_SPEECH_AUDIO_TUPLE_LIST:
-			print "%s\t%s" % (idTre, textTre)
-		print "\nI_SEZ QUOTES"
-		print "------------------"
+			print ("%s\t%s" % (idTre, textTre))
+		print ("\nI_SEZ QUOTES")
+		print ("------------------")
 		for (idTre, textTre) in DEV_ISEZ_QUOTES_TUPLE_LIST:
-			print "%s\t%s" % (idTre, textTre)
+			print ("%s\t%s" % (idTre, textTre))
 		return
 
 	def getAudioCommentaryTextEntriesList(self):
 		if self.m_traceModeEnabled:
-			print "[Trace] getAudioCommentaryTextEntriesList"
+			print ("[Trace] getAudioCommentaryTextEntriesList")
 		return DEV_AUDIO_COMMENTARY_TUPLE_LIST
 
 	def getISEZTextEntriesList(self):
 
 		if self.m_traceModeEnabled:
-			print "[Trace] getISEZTextEntriesList"
+			print ("[Trace] getISEZTextEntriesList")
 		return DEV_ISEZ_QUOTES_TUPLE_LIST
 
 	def getExtraSpeechAudioEntriesList(self):
 		if self.m_traceModeEnabled:
-			print "[Trace] getExtraSpeechAudioEntriesList"
+			print ("[Trace] getExtraSpeechAudioEntriesList")
 		return EXTRA_SPEECH_AUDIO_TUPLE_LIST
 #
 #
 #
 if __name__ == '__main__':
 	# main()
-	print "[Debug] Running %s as main module" % (my_module_name)
+	print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	traceModeEnabled = False
 	devCommentaryTextInstance = devCommentaryText(traceModeEnabled)
 	devCommentaryTextInstance.printTexts()
 else:
 	#debug
-	#print "[Debug] Running	 %s imported from another module" % (my_module_name)
+	#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	pass
diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/pogoTextResource.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/pogoTextResource.py
index d16f0b6f6aa..6ba29a24953 100644
--- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/pogoTextResource.py
+++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/pogoTextResource.py
@@ -2,8 +2,8 @@
 # -*- coding: utf-8 -*-
 #
 
-my_module_version = "1.00"
-my_module_name = "pogoTextResource"
+MY_MODULE_VERSION = "1.10"
+MY_MODULE_NAME = "pogoTextResource"
 
 # All game versions should have the English text pre-filled in the POGO sheet
 POGO_TEXT_RESOURCE_TUPLE_LIST = [
@@ -178,14 +178,14 @@ class pogoTextResource(object):
 
 	def printPogo(self):
 		if self.m_traceModeEnabled:
-			print "[Trace] printing Pogo..."
+			print ("[Trace] printing Pogo...")
 		for (idTre, textTre) in POGO_TEXT_RESOURCE_TUPLE_LIST:
-			print "%s\t%s" % (idTre, textTre)
+			print ("%s\t%s" % (idTre, textTre))
 		return
 
 	def getPogoEntriesList(self):
 		if self.m_traceModeEnabled:
-			print "[Trace] getPogoEntriesList()"
+			print ("[Trace] getPogoEntriesList()")
 		return POGO_TEXT_RESOURCE_TUPLE_LIST
 
 #
@@ -193,11 +193,11 @@ class pogoTextResource(object):
 #
 if __name__ == '__main__':
 	# main()
-	print "[Debug] Running %s as main module" % (my_module_name)
+	print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	traceModeEnabled = False
 	pogoTRInstance = pogoTextResource(traceModeEnabled)
 	pogoTRInstance.printPogo()
 else:
 	#debug
-	#print "[Debug] Running	 %s imported from another module" % (my_module_name)
+	#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	pass
diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/quoteSpreadsheetCreator.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/quoteSpreadsheetCreator.py
index a2c4cae2400..9791361571c 100644
--- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/quoteSpreadsheetCreator.py
+++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/quoteSpreadsheetCreator.py
@@ -12,11 +12,6 @@ if (not sysLibFound):
 	sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n")
 	sys.exit(1)
 
-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.exit(1)
-
 import sortBladeRunnerWavs02
-
 if __name__ == "__main__":
 	sortBladeRunnerWavs02.main(sys.argv[0:])
diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py
index 63f34ab6987..13a5ceedb17 100644
--- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py
+++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py
@@ -16,35 +16,35 @@ csvLibFound = False
 try:
 	import os
 except ImportError:
-	print "[Error] os python library is required to be installed!"
+	print ("[Error] os python library is required to be installed!")
 else:
 	osLibFound = True
 
 try:
 	import sys
 except ImportError:
-	print "[Error] sys python library is required to be installed!"
+	print ("[Error] sys python library is required to be installed!")
 else:
 	sysLibFound = True
 
 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
 
@@ -56,8 +56,12 @@ if 	(not osLibFound) \
 	sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n")
 	sys.exit(1)
 
+try:
+	import errno
+except ImportError:
+	from os import errno
 
-from os import walk, errno, path
+from os import walk, path
 
 pathToParent = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)
 pathToCommon = os.path.join(pathToParent, "common")
@@ -70,13 +74,14 @@ from pogoTextResource import *
 from devCommentaryText import *
 from subtlsVersTextResource import *
 from vqasTextResource import *
+from pythonCompat import *
 
 # encoding=utf8
 #reload(sys)
 #sys.setdefaultencoding('utf8')
 
 COMPANY_EMAIL = "classic.adventures.in.greek at gmail.com"
-APP_VERSION = "1.60"
+APP_VERSION = "1.70"
 APP_NAME = "sortBladeRunnerWavs"
 APP_WRAPPER_NAME = "quotesSpreadsheetCreator.py"
 APP_NAME_SPACED = "Blade Runner Transcript Excel Creator (bare bones)"
@@ -182,7 +187,7 @@ def calculateFoldHash(strFileName):
 				groupSum |= 0
 		hash = ((hash << 1) | ((hash >> 31) & 1)) + groupSum
 	hash &= 0xFFFFFFFF	   # mask here!
-	#print (strParam +': '  +''.join('{:08X}'.format(hash)))
+	#print (strParam + ": " + ''.join('{:08X}'.format(hash)))
 	return hash
 
 # Fill the gActorPropertyEntries table
@@ -191,25 +196,24 @@ def initActorPropertyEntries(thePathToActorNamesTxt):
 	global gActorPropertyEntries
 	firstLine = True
 	gActorPropertyEntriesWasInit = False
-	#print "[Debug] 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)
+		thePathToActorNamesTxt = os.path.join(u'.', actorNamesTextFile)
+		print ("[Warning] Actor names text file %s not found in arguments. Attempting to open local file if it exists" % (thePathToActorNamesTxt))
 
 	if os.access(thePathToActorNamesTxt, os.F_OK):
-		print "[Info] Actor names text file found: {0}.".format(thePathToActorNamesTxt)
+		print ("[Info] Actor names text file found: {0}.".format(thePathToActorNamesTxt))
 
-		with open(thePathToActorNamesTxt) as tsv:
+		with openWithUTF8Encoding(thePathToActorNamesTxt, 'r') as tsv:
 			if gTraceModeEnabled:
-				print "[Debug] Parsing Override Encoding file info..."
+				print ("[Debug] Parsing Override Encoding file info...")
 			for line in csv.reader(tsv, dialect="excel-tab"):
 				#skip first line header
 				if firstLine == True:
 					#if gTraceModeEnabled:
-					#	print "[Debug] Skipping Header line in Excel sheet"
+					#	print ("[Debug] Skipping Header line in Excel sheet")
 					firstLine = False
 				else:
 					gActorPropertyEntries.append(line)
@@ -217,7 +221,7 @@ def initActorPropertyEntries(thePathToActorNamesTxt):
 		tsv.close()
 	else:
 		## error
-		print "[Error] Actor names text file not found: {0}.".format(thePathToActorNamesTxt)
+		print ("[Error] Actor names text file not found: {0}.".format(thePathToActorNamesTxt))
 		sys.exit(1)	# terminate if finding actor names file failed (Blade Runner)
 
 def getActorShortNameById(lookupActorId):
@@ -253,7 +257,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:
@@ -288,7 +292,7 @@ def inputTLKsExport(inputTLKpath, outputWAVpath, pExportWavFilesMode, pExtractDe
 	#				file size
 	if not pExportWavFilesMode and not pExtractDevCommAndExtraSFXMode:
 		return # nothing to do
-	print "[Info] Checking in:\n\t%s\n\tfor TLK or MIX files containing supported speech audio (AUD) to export as WAV to:\n\t%s" % (inputTLKpath, outputWAVpath)
+	print ("[Info] Checking in:\n\t%s\n\tfor TLK or MIX files containing supported speech audio (AUD) to export as WAV to:\n\t%s" % (inputTLKpath, outputWAVpath))
 	inputTLKFilesForSpeechFound = []
 	inputMIXFilesForSpeechFound = []	# breaking after first for loop yields only the top directory files, which is what we want
 	for (dirpath, dirnames, filenames) in walk(inputTLKpath):
@@ -305,34 +309,34 @@ def inputTLKsExport(inputTLKpath, outputWAVpath, pExportWavFilesMode, pExtractDe
 
 	if pExportWavFilesMode:
 		if len(inputTLKFilesForSpeechFound) == 0:
-			print "[Error] No valid speech audio files (TLK) were found in the specified input path (-ip switch)"
+			print ("[Error] No valid speech audio files (TLK) were found in the specified input path (-ip switch)")
 			sys.exit(1)
 	if pExtractDevCommAndExtraSFXMode:
 		if len(inputMIXFilesForSpeechFound) == 0:
-			print "[Error] No valid extras speech audio files (MIX) were found in the specified input path (-ip switch)"
+			print ("[Error] No valid extras speech audio files (MIX) were found in the specified input path (-ip switch)")
 			sys.exit(1)
 
 	# get the supported AUD files from TLK or MIX archives
 	for tmpTLKorMIXFileTuple in (inputTLKFilesForSpeechFound + inputMIXFilesForSpeechFound):
 		if gTraceModeEnabled:
-			print "[Info] Found supported audio file: %s" % ('"' + inputTLKpath + tmpTLKorMIXFileTuple[0] + '"')
+			print ("[Info] Found supported audio file: %s" % ('"' + inputTLKpath + tmpTLKorMIXFileTuple[0] + '"'))
 		errorFound = False
 		inTLKorMIXFile = None
 		fileIsMIX = False
-		#print "[Trace] Type of file is: %s" % (tmpTLKorMIXFileTuple[0][-3:])
+		#print ("[Trace] Type of file is: %s" % (tmpTLKorMIXFileTuple[0][-3:]))
 		if tmpTLKorMIXFileTuple[0][-3:].upper() == 'MIX':
 			fileIsMIX = True
-			print "[Info] Checking MIX file %s for speech audio (-xdevs mode)... " % (tmpTLKorMIXFileTuple[0])
+			print ("[Info] Checking MIX file %s for speech audio (-xdevs mode)... " % (tmpTLKorMIXFileTuple[0]))
 		#
 		# Create output folder if not exists at output path
 		if gTraceModeEnabled:
-			print "[Debug] Ensuring output directory %s" % (os.path.join(outputWAVpath, tmpTLKorMIXFileTuple[1] ))
+			print ("[Debug] Ensuring output directory %s" % (os.path.join(outputWAVpath, tmpTLKorMIXFileTuple[1] )))
 		ensure_dir(os.path.join(outputWAVpath, tmpTLKorMIXFileTuple[1] ) )
 		try:
 			inTLKorMIXFile = open(os.path.join(inputTLKpath,tmpTLKorMIXFileTuple[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 = inTLKorMIXFile.read(2)
@@ -349,9 +353,9 @@ def inputTLKsExport(inputTLKpath, outputWAVpath, pExportWavFilesMode, pExtractDe
 			# 12 bytes per TLK entry in entries table
 			# quick size validation
 			if gTraceModeEnabled:
-				print "[Debug] Entries: %d, Data segment size: %d bytes" % (numOfAUDEntriesToExtract, allTlkFileSize)
+				print ("[Debug] Entries: %d, Data segment size: %d bytes" % (numOfAUDEntriesToExtract, allTlkFileSize))
 			if allActualBytesInMixFile != 2 + 4 + 12 * numOfAUDEntriesToExtract + allTlkFileSize:
-				print "[Error] Audio Archive file size mismatch with reported size in header for %s!" % (tmpTLKorMIXFileTuple[0])
+				print ("[Error] Audio Archive file size mismatch with reported size in header for %s!" % (tmpTLKorMIXFileTuple[0]))
 			else:
 				#
 				# 12 bytes per entry
@@ -374,20 +378,20 @@ def inputTLKsExport(inputTLKpath, outputWAVpath, pExportWavFilesMode, pExtractDe
 					targetSimpleAudFileName = ''.join('{:08X}'.format(idOfAUDEntry)).upper()+'.AUD'
 					foundSupportedAUDFromMIXFile = False
 					if fileIsMIX:	# MIX file like SFX.MIX which has some spoken dialogue
-						#print 'idOfEntry: %d' % (idOfAUDEntry)
-						for suppAUDFromMIXFileName in zip(*SUPPORTED_EXPORTED_AUD_FROM_MIX_FILES)[0]:
-							#print 'checked with: %d' % (calculateFoldHash(suppAUDFromMIXFileName))
+						#print ("idOfEntry: %d" % (idOfAUDEntry))
+						for suppAUDFromMIXFileName in list(zip(*SUPPORTED_EXPORTED_AUD_FROM_MIX_FILES))[0]:
+							#print ("checked with: %d" % (calculateFoldHash(suppAUDFromMIXFileName)))
 							if(idOfAUDEntry == calculateFoldHash(suppAUDFromMIXFileName)):
 								foundSupportedAUDFromMIXFile = True
 								targetSimpleAudFileName = suppAUDFromMIXFileName
 								break
 						if foundSupportedAUDFromMIXFile:
 							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] Filename: " + targetSimpleAudFileName
+								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] Filename: " + targetSimpleAudFileName)
 					else:			# TLK file
 						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?
@@ -403,7 +407,7 @@ def inputTLKsExport(inputTLKpath, outputWAVpath, pExportWavFilesMode, pExtractDe
 					if foundSupportedAUDFromMIXFile or not fileIsMIX:
 						inTLKorMIXFile.seek(2 + 4 + 12*numOfAUDEntriesToExtract + offsetOfAUDEntry)
 						if(offsetOfAUDEntry + sizeOfAUDEntry > allTlkFileSize):
-							print "[Error] audio file (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:
 							targetSimpleWavFileName = targetSimpleAudFileName[:-4] + '.WAV' # remove the .AUD before adding the .WAV
 							if not fileIsMIX: # TLK file
@@ -416,19 +420,19 @@ def inputTLKsExport(inputTLKpath, outputWAVpath, pExportWavFilesMode, pExtractDe
 								thisAudFile = audFile(gTraceModeEnabled)
 								if (thisAudFile.loadAudFile(audFileBuffer, allTlkFileSize, targetSimpleAudFileName)):
 									if gTraceModeEnabled:
-										print "[Debug] Audio file (AUD) file %s was loaded successfully!" % (targetSimpleAudFileName)
-									#print os.path.join(outputWAVpath, tmpTLKorMIXFileTuple[1], targetSimpleWavFileName)
+										print ("[Debug] Audio file (AUD) file %s was loaded successfully!" % (targetSimpleAudFileName))
+									#print (os.path.join(outputWAVpath, tmpTLKorMIXFileTuple[1], targetSimpleWavFileName))
 									# tmpTLKorMIXFileTuple[1] is the subfolder where the AUD -> WAV files for this archive are written
 									if not os.path.isfile(os.path.join(outputWAVpath, tmpTLKorMIXFileTuple[1], targetSimpleWavFileName) ):
 										thisAudFile.export_as_wav(audFileBuffer, os.path.join(outputWAVpath, tmpTLKorMIXFileTuple[1], targetSimpleWavFileName) )
 									else:
 										if gTraceModeEnabled:
-											print "[Info] Output file %s already exists. Skipping..." % (os.path.join(outputWAVpath, tmpTLKorMIXFileTuple[1], targetSimpleWavFileName))
+											print ("[Info] Output file %s already exists. Skipping..." % (os.path.join(outputWAVpath, tmpTLKorMIXFileTuple[1], targetSimpleWavFileName)))
 								else:
-									print "[Warning] Failed to load a proper audio file (AUD) %s (to export it to %s)! Size of input is: %d" % (targetSimpleAudFileName, targetSimpleWavFileName,  sizeOfAUDEntry)
+									print ("[Warning] Failed to load a proper audio file (AUD) %s (to export it to %s)! Size of input is: %d" % (targetSimpleAudFileName, targetSimpleWavFileName,  sizeOfAUDEntry))
 							else:
-								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)))
+								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))))
 			inTLKorMIXFile.close()
 
 
@@ -439,7 +443,7 @@ def inputTLKsExport(inputTLKpath, outputWAVpath, pExportWavFilesMode, pExtractDe
 
 def appendVQAPlaceHolderSheets(excelOutBook = None):
 	if excelOutBook != None:
-		print "[Info] Appending placeholder sheets for supported video cutscenes (VQA)..."
+		print ("[Info] Appending placeholder sheets for supported video cutscenes (VQA)...")
 		currVQAFileNameLclzd = None
 		for currVQAFileNameDesc in SUPPORTED_PLACEHOLDER_VQA_ENGLISH_FILES + SUPPORTED_PLACEHOLDER_VQA_LOCALIZED_FILES:
 			if currVQAFileNameDesc in SUPPORTED_PLACEHOLDER_VQA_ENGLISH_FILES:
@@ -448,7 +452,7 @@ def appendVQAPlaceHolderSheets(excelOutBook = None):
 				currVQAFileNameLclzd = currVQAFileNameDesc[0] + ('%s' % (gActiveLanguageDescriptionCodeTuple[1])) + '.VQA'
 			if 	currVQAFileNameLclzd is not None:
 				if gTraceModeEnabled:
-					print "[Debug] Creating placeholder sheet %s: %s!" % (currVQAFileNameLclzd, currVQAFileNameDesc[1])
+					print ("[Debug] Creating placeholder sheet %s: %s!" % (currVQAFileNameLclzd, currVQAFileNameDesc[1]))
 				sh = excelOutBook.add_sheet(currVQAFileNameLclzd)
 				# First Row
 				n = 0 # keeps track of rows
@@ -477,19 +481,19 @@ def appendVQAPlaceHolderSheets(excelOutBook = None):
 					for i1 in range(2,6):
 						objStr = e1[i1]
 						try:
-							objUTF8Unicode = unicode(objStr, 'utf-8')
+							objUTF8Unicode = makeUnicode(objStr)
 						except Exception as e:
-							print '[Error] Failed to create unicode string: ' + str(e)
-							objUTF8Unicode = unicode("???", 'utf-8')
+							print ("[Error] Failed to create unicode string: " + str(e))
+							objUTF8Unicode = makeUnicode("???")
 						sh.write(m, i1, objUTF8Unicode)
 	return
 
 def appendPOGOTextSheet(excelOutBook = None):
 	if excelOutBook != None:
-		print "[Info] Appending POGO sheet..."
+		print ("[Info] Appending POGO sheet...")
 		currTreFileName = '%s%s' % (SUPPORTED_SPECIAL_POGO_FILE, gActiveLanguageDescriptionCodeTuple[1]) # POGO
 		if gTraceModeEnabled:
-			print "[Debug] TR%s file %s was loaded successfully!" % (gActiveLanguageDescriptionCodeTuple[1], currTreFileName) # POGO
+			print ("[Debug] TR%s file %s was loaded successfully!" % (gActiveLanguageDescriptionCodeTuple[1], currTreFileName)) # POGO
 		sh = excelOutBook.add_sheet(currTreFileName)
 		n = 0 # keeps track of rows
 		col1_name = 'Text Resource File: %s' % (currTreFileName)
@@ -509,10 +513,10 @@ def appendPOGOTextSheet(excelOutBook = None):
 			objStr = e1[1]
 			try:
 				# We assume utf-8 charset for POGO (since we get the text from a python script)
-				objUTF8Unicode = unicode(objStr, 'utf-8')
+				objUTF8Unicode = makeUnicode(objStr)
 			except Exception as e:
-				print '[Error] Failed to create unicode string: ' + str(e)
-				objUTF8Unicode = unicode("???", 'utf-8')
+				print ("[Error] Failed to create unicode string: " + str(e))
+				objUTF8Unicode = makeUnicode("???")
 			sh.write(m, 1, objUTF8Unicode)
 
 # aux: populate a row in extra audio sheets
@@ -529,10 +533,10 @@ def auxPopulateExtraSpeechAudioRow(sh = None, n = 0, pFilenameStr = '', pTextStr
 			sh.write(n, 0, pFilenameStr)				# Filename
 			# We assume utf-8 charset for Audio Commentary and extra text entries (since we get the text from a python script)
 			try:
-				objUTF8Unicode = unicode(pTextStr, 'utf-8')
+				objUTF8Unicode = makeUnicode(pTextStr)
 			except Exception as e:
-				print '[Error] Failed to create unicode string: ' + str(e)
-				objUTF8Unicode = unicode("???", 'utf-8')
+				print ("[Error] Failed to create unicode string: " + str(e))
+				objUTF8Unicode = makeUnicode("???")
 			sh.write(n, 1, objUTF8Unicode)				# Quote
 			sh.write(n, 2, 'N/A')						# By Actor
 			sh.write(n, 3, '')							# Notes
@@ -548,7 +552,7 @@ def auxPopulateExtraSpeechAudioRow(sh = None, n = 0, pFilenameStr = '', pTextStr
 				if len(twoTokensOfRelDirnameAndFilenameXLS) == 3:
 					tokensOfFilename = twoTokensOfRelDirnameAndFilenameXLS[0].split('#', 3)
 					#ShortHandFileName
-					if (tokensOfFilename[0][:-4]+'.AUD') in zip(*SUPPORTED_EXPORTED_AUD_FROM_MIX_FILES)[0] \
+					if (tokensOfFilename[0][:-4]+'.AUD') in list(zip(*SUPPORTED_EXPORTED_AUD_FROM_MIX_FILES))[0] \
 						and (tokensOfFilename[0][:-4]+'.AUD') == dcAUDFilename:
 						shortHandFileName = tokensOfFilename[0]
 						# real path of filename
@@ -573,7 +577,7 @@ def appendDevCommentarySheet(excelOutBook = None, listOfExtraWavsForDevSheet = N
 		and len(listOfExtraWavsForDevSheet) > 0:
 
 		objUTF8Unicode = None
-		print "[Info] Appending Developer Commentary sheet..."
+		print ("[Info] Appending Developer Commentary sheet...")
 
 		sh = excelOutBook.add_sheet("DEV AUDIO")
 		devCommentaryTextInstance = devCommentaryText(gTraceModeEnabled)
@@ -644,21 +648,21 @@ def appendDevCommentarySheet(excelOutBook = None, listOfExtraWavsForDevSheet = N
 			sh.write(n, 0, idStr)
 			# We assume utf-8 charset for I_SEZ Commentary (since we get the text from a python script)
 			try:
-				objUTF8Unicode = unicode(textStr, 'utf-8')
+				objUTF8Unicode = makeUnicode(textStr)
 			except Exception as e:
-				print '[Error] Failed to create unicode string: ' + str(e)
-				objUTF8Unicode = unicode("???", 'utf-8')
+				print ("[Error] Failed to create unicode string: " + str(e))
+				objUTF8Unicode = makeUnicode("???")
 			sh.write(n, 1, objUTF8Unicode)
-			sh.write(n, 2, 'N/A')	# by actor
-			sh.write(n, 3, '')	# notes
-			sh.write(n, 4, 'N/A')	# to actor
-			sh.write(n, 5, 'N/A')	# Resources
-			sh.write(n, 6, 'N/A')	# ShortHandFilename and URL
+			sh.write(n, 2, 'N/A')   # by actor
+			sh.write(n, 3, '')      # notes
+			sh.write(n, 4, 'N/A')   # to actor
+			sh.write(n, 5, 'N/A')   # Resources
+			sh.write(n, 6, 'N/A')   # ShortHandFilename and URL
 			n+=1
 	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 = []
 	objUTF8Unicode = None
 	# breaking after first for loop yields only the top directory files, which is what we want
@@ -670,12 +674,12 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None):
 		break
 
 	if len(inputMIXFilesFound) == 0:
-		print "[Error] No supported game archive resource files (MIX) were found in the specified input path (-ip switch)"
+		print ("[Error] No supported game archive resource files (MIX) were found in the specified input path (-ip switch)")
 		sys.exit(1)
 
 	for tmpMIXfileName in inputMIXFilesFound:
 		if gTraceModeEnabled:
-			print "[Info] Found MIX file: %s" % ('"' + tmpMIXfileName + '"')
+			print ("[Info] Found MIX file: %s" % ('"' + tmpMIXfileName + '"'))
 		errorFound = False
 		inMIXFile = None
 		#
@@ -683,7 +687,7 @@ 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
@@ -701,9 +705,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" % (numOfTREEntriesToExtract, allMixFileSize)
+				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)
+				print ("[Error] MIX file size mismatch with reported size in header for %s!" % (tmpMIXfileName))
 			else:
 				#
 				# 12 bytes per entry
@@ -734,7 +738,7 @@ 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
@@ -742,7 +746,7 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None):
 						#
 						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):
@@ -750,7 +754,7 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None):
 								thisTreFile = treFile(gTraceModeEnabled)
 								if (thisTreFile.loadTreFile(treFileBuffer, allMixFileSize, currTreFileName)):
 									if gTraceModeEnabled:
-										print "[Debug] TR%s file %s was loaded successfully!" % (gActiveLanguageDescriptionCodeTuple[1], currTreFileName)
+										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
@@ -779,57 +783,96 @@ def inputMIXExtractTREs(inputMIXpath, excelOutBook = None):
 												# in ERRORMSG TRx.
 												# Eg. in Spanish version they use \xa2 (correct with IBM437) and \xf3 (correct with Latin-1) for the 'ó' character
 												#  or in French version 'è' uses both \x8a and \xe8
-												objEncodeSafeStr = ""
-												for i in range(0, len(objStr)):
-													# ENG version has no buggy character exceptions
-													# GER version has no buggy character exceptions
-													# FRA version
-													if (objStr[i] == '\x82'): # FRA - ERRORMSG.TRF
-														objEncodeSafeStr += '\xe9'	# fixing buggy character 'é'
-													elif (objStr[i] == '\x85'): # FRA - ERRORMSG.TRF (also used in ITA ERRORMSG.TRI - same glyph)
-														objEncodeSafeStr += '\xe0'	 # fixing buggy character 'à'
-													elif (objStr[i] == '\x8a'): # FRA - ERRORMSG.TRF (also used in ITA ERRORMSG.TRI - same glyph)
-														objEncodeSafeStr += '\xe8'    # fixing buggy character 'è'
-													# ITA version
-													#elif (objStr[i] == '\x85'): # ITA - ERRORMSG.TRI [commented out: already covered in FRA check above]
-													#	objEncodeSafeStr += '\xe0'	 # buggy - fixed above
-													#elif (objStr[i] == '\x8a'): # ITA - ERRORMSG.TRI [commented out: already covered in FRA check above]
-													#	objEncodeSafeStr += '\xe8'    # buggy - fixed above
-													elif (objStr[i] == '\x97'): # ITA - ERRORMSG.TRI
-														objEncodeSafeStr += '\xf9'    # fixing buggy character 'ù'
-													# ESP version
-													elif (objStr[i] == '\xa2'): # ESP - ERRORMSG.TRS
-														objEncodeSafeStr += '\xf3' 	# fixing buggy character 'ó'
-													else:
-														objEncodeSafeStr += objStr[i]
-													#
-													try:
-														objUTF8Unicode = unicode(objEncodeSafeStr, 'latin-1')
-													except Exception as e:
-														print '[Error] Failed to create unicode string: ' + str(e)
-														objUTF8Unicode = unicode("???", 'latin-1')
+												if sys.version_info[0] <= 2:
+													objEncodeSafeStr = ""
+													for i in range(0, len(objStr)):
+														# ENG version has no buggy character exceptions
+														# GER version has no buggy character exceptions
+														# FRA version
+														if (objStr[i] == '\x82'): # FRA - ERRORMSG.TRF
+															objEncodeSafeStr += '\xe9'	# fixing buggy character 'é'
+														elif (objStr[i] == '\x85'): # FRA - ERRORMSG.TRF (also used in ITA ERRORMSG.TRI - same glyph)
+															objEncodeSafeStr += '\xe0'	 # fixing buggy character 'à'
+														elif (objStr[i] == '\x8a'): # FRA - ERRORMSG.TRF (also used in ITA ERRORMSG.TRI - same glyph)
+															objEncodeSafeStr += '\xe8'    # fixing buggy character 'è'
+														# ITA version
+														#elif (objStr[i] == '\x85'): # ITA - ERRORMSG.TRI [commented out: already covered in FRA check above]
+														#	objEncodeSafeStr += '\xe0'	 # buggy - fixed above
+														#elif (objStr[i] == '\x8a'): # ITA - ERRORMSG.TRI [commented out: already covered in FRA check above]
+														#	objEncodeSafeStr += '\xe8'    # buggy - fixed above
+														elif (objStr[i] == '\x97'): # ITA - ERRORMSG.TRI
+															objEncodeSafeStr += '\xf9'    # fixing buggy character 'ù'
+														# ESP version
+														elif (objStr[i] == '\xa2'): # ESP - ERRORMSG.TRS
+															objEncodeSafeStr += '\xf3' 	# fixing buggy character 'ó'
+														else:
+															objEncodeSafeStr += objStr[i]
+														#
+														try:
+															objUTF8Unicode = unicode(objEncodeSafeStr, 'latin-1')
+														except Exception as e:
+															print ("[Error] Failed to create unicode string: " + str(e))
+															objUTF8Unicode = unicode("???", 'latin-1')
+												else:
+													#python 3 case:
+													objEncodeSafeStr = bytearray(b'')
+													for i in range(0, len(objStr)):
+														# ENG version has no buggy character exceptions
+														# GER version has no buggy character exceptions
+														# FRA version
+														if (objStr[i] == b'\x82'): # FRA - ERRORMSG.TRF
+															objEncodeSafeStr.append(b'\xe9') # fixing buggy character 'é'
+														elif (objStr[i] == b'\x85'): # FRA - ERRORMSG.TRF (also used in ITA ERRORMSG.TRI - same glyph)
+															objEncodeSafeStr.append(b'\xe0') # fixing buggy character 'à'
+														elif (objStr[i] == b'\x8a'): # FRA - ERRORMSG.TRF (also used in ITA ERRORMSG.TRI - same glyph)
+															objEncodeSafeStr.append(b'\xe8') # fixing buggy character 'è'
+														# ITA version
+														#elif (objStr[i] == b'\x85'): # ITA - ERRORMSG.TRI [commented out: already covered in FRA check above]
+														#	objEncodeSafeStr.append(b'\xe0') # buggy - fixed above
+														#elif (objStr[i] == b'\x8a'): # ITA - ERRORMSG.TRI [commented out: already covered in FRA check above]
+														#	objEncodeSafeStr.append(b'\xe8') # buggy - fixed above
+														elif (objStr[i] == b'\x97'): # ITA - ERRORMSG.TRI
+															objEncodeSafeStr.append(b'\xf9') # fixing buggy character 'ù'
+														# ESP version
+														elif (objStr[i] == b'\xa2'): # ESP - ERRORMSG.TRS
+															objEncodeSafeStr.append(b'\xf3') # fixing buggy character 'ó'
+														else:
+															objEncodeSafeStr.append(objStr[i])
+														#
+														try:
+															objUTF8Unicode = objEncodeSafeStr.decode('latin-1')
+														except Exception as e:
+															print ("[Error] Failed to create unicode string: " + str(e))
+															objUTF8Unicode = b"???".decode('latin-1')
+
 											else:
 											# all the other official game TRx use the KIA6PT.FON
 											# There could be variances of the KIA6PT.FON per Blade Runner version
 											# TODO: For now, we assume that there aren't significant variances that warrant a more elaborate approach
 											# TODO: Tested for EN, DEU, FRA, ITA, ESP. Pending testing for Russian version.
 												try:
-													objUTF8Unicode = unicode(objStr, 'cp437')
+													if sys.version_info[0] <= 2:
+														objUTF8Unicode = unicode(objStr, 'cp437')
+													else:
+														objUTF8Unicode = objStr.decode('cp437')
 												except Exception as e:
-													print '[Error] Failed to create unicode string: ' + str(e)
-													objUTF8Unicode = unicode("???", 'cp437')
+													print ("[Error] Failed to create unicode string: " + str(e))
+													if sys.version_info[0] <= 2:
+														objUTF8Unicode = unicode("???", 'cp437')
+													else:
+														objUTF8Unicode = b"???".decode('cp437')
 											sh.write(m, 1, objUTF8Unicode)
 									#for tupleIdString in thisTreFile.stringEntriesLst:
-									#	#print "[Debug] 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 %s file!" % (gActiveLanguageDescriptionCodeTuple[1], currTreFileName)
+									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], currTreFileName)
-								#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 processed: %d " % (gActiveLanguageDescriptionCodeTuple[1], totalTREs)
+			print ("[Info] Total TR%ss processed: %d " % (gActiveLanguageDescriptionCodeTuple[1], totalTREs))
 	return
 
 
@@ -869,12 +912,12 @@ def outputXLS(filename, sheet, listTlkWavs, listDevsWavs, parseTREResourcesAlso
 				# We assume utf-8 charset (since we get the text from a python script)
 				# populate row with quote ID == 3 and column B with the description of language used in the command's execution (or assumed)
 				if tmpQuoteID == 3 and i1 == 1:
-					objUTF8Unicode = unicode(gActiveLanguageDescriptionCodeTuple[2], 'utf-8')
+					objUTF8Unicode = makeUnicode(gActiveLanguageDescriptionCodeTuple[2])
 				else:
-					objUTF8Unicode = unicode(objStr, 'utf-8')
+					objUTF8Unicode = makeUnicode(objStr)
 			except Exception as e:
-				print '[Error] Failed to create unicode string: ' + str(e)
-				objUTF8Unicode = unicode("???", 'utf-8')
+				print ("[Error] Failed to create unicode string: " + str(e))
+				objUTF8Unicode = makeUnicode("???")
 			vrsn_sheet.write(m, i1, objUTF8Unicode)
 	#
 	# Add ingame quotes sheet
@@ -890,7 +933,7 @@ def outputXLS(filename, sheet, listTlkWavs, listDevsWavs, parseTREResourcesAlso
 	#
 	#
 	# You may need to group the variables together
-	#for n, (v_desc, v) in enumerate(zip(desc, variables)):
+	#for n, (v_desc, v) in enumerate(list(zip(desc, variables))):
 		#sh.write(n, 0, v_desc)
 		#sh.write(n, 1, v)
 	col1_name = 'BladeRunnerTLK In-Game dialogue / voiceover quotes'
@@ -984,22 +1027,22 @@ def outputXLS(filename, sheet, listTlkWavs, listDevsWavs, parseTREResourcesAlso
 
 	try:
 		book.save(filename)
-		print "[Info] Done."
+		print ("[Info] Done.")
 	except Exception as e:
-		print "[Error] Could not save the output Excel file:: " + str(e)
+		print ("[Error] Could not save the output Excel file:: " + str(e))
 
 #
 # Aux function to weed out duplicates from wav file lists
 # valid listTypes: 'TLKWAVS', 'EXTRAMIXWAVS'
 def wavDupsRemove(listOfWavFiles, listType):
 	if listType != 'TLKWAVS' and listType != 'EXTRAMIXWAVS':
-		print '[Error] Invalid listtype %s specified to remove duplicate wav files' % (listType)
+		print ("[Error] Invalid listtype %s specified to remove duplicate wav files" % (listType))
 		sys.exit(1)
 
 	listOfWavFilesNoDups = []
 	for filenameSrcTmp in listOfWavFiles:
 		duplicateFound = False
-		#print "[Debug]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] # eg. TLK1
@@ -1024,14 +1067,14 @@ def wavDupsRemove(listOfWavFiles, listType):
 				#concatenate actorID and quoteID for search key
 				keyForDuplicateSearchTarg =	 threeTokensOfQuoteFilenameTarg[0] + threeTokensOfQuoteFilenameTarg[1]
 			if(keyForDuplicateSearchSrc == keyForDuplicateSearchTarg):
-				#print "[Debug] Found duplicate %s" % (filenameSrcTmp)
+				#print ("[Debug] Found duplicate %s" % (filenameSrcTmp))
 				duplicateFound = True
 				listOfWavFilesNoDups[fileTargIdx] = twoTokensOfRelDirnameAndFilenameTarg[0] + '&' +  tmpRelDirNameSrc + ',' + tmpRelDirNameTarg + '&' + twoTokensOfRelDirnameAndFilenameTarg[2]
 				break
 		if(duplicateFound == False):
 			listOfWavFilesNoDups.append(filenameSrcTmp)
 	#for filenameSrcTmp in listOfWavFilesNoDups:
-	#	print "[Debug] Unique %s" % (filenameSrcTmp)
+	#	print ("[Debug] Unique %s" % (filenameSrcTmp))
 	return listOfWavFilesNoDups
 
 #
@@ -1049,9 +1092,9 @@ def getLanguageDescCodeTuple(candidateLangDescriptionStr):
 	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])
+	tmpCSVSupportedLangDescValues = ", ".join( list(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
 #
 #
@@ -1085,37 +1128,37 @@ def main(argsCL):
 	extractPOGOTextMode = False
 
 	invalidSyntax = False
-	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 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, 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] [-xdevs] [-xpogo] [--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 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."
+			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, 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] [-xdevs] [-xpogo] [--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 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 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 -xdevs switch will add a sheet for Developer Commentary text and some additional voice-overs from SFX.MIX."
-			print "The -xpogo switch will add a sheet for the POGO text."
-			print "The --trace switch enables more debug messages being printed during execution."
-			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)
+			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 -xdevs switch will add a sheet for Developer Commentary text and some additional voice-overs from SFX.MIX.")
+			print ("The -xpogo switch will add a sheet for the POGO text.")
+			print ("The --trace switch enables more debug messages being printed during execution.")
+			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 Westwood's Blade Runner PC Game (1997)." % (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
@@ -1135,61 +1178,61 @@ def main(argsCL):
 					candidateLangDescriptionTxt = argsCL[i+1]
 
 			elif (argsCL[i] == '-xwav'):
-				print "[Info] Export WAVs from TLK files mode enabled (only missing files will be exported)."
+				print ("[Info] Export WAVs from TLK files mode enabled (only missing files will be exported).")
 				exportWavFilesMode = True
 			elif (argsCL[i] == '-xtre'):
-				print "[Info] Extract Text Resources (TRx) mode enabled."
+				print ("[Info] Extract Text Resources (TRx) mode enabled.")
 				extractTreFilesMode = True
 			elif (argsCL[i] == '-xdevs'):
-				print "[Info] Additional Sheet for developer commentary and extra SFX mode enabled."
+				print ("[Info] Additional Sheet for developer commentary and extra SFX mode enabled.")
 				extractDevCommAndExtraSFXMode = True
 			elif (argsCL[i] == '-xpogo'):
-				print "[Info] Additional Sheet for POGO text mode enabled."
+				print ("[Info] Additional Sheet for POGO text mode enabled.")
 				extractPOGOTextMode = True
 			elif argsCL[i] == '--trace':
-				print "[Info] Trace mode enabled (more debug messages)."
+				print ("[Info] Trace mode enabled (more debug messages).")
 				gTraceModeEnabled = True
 			elif argsCL[i][:1] == '-':
 				invalidSyntax = True
 				break
 
 		if (not exportWavFilesMode):
-			print "[Info] Export WAVs from TLK files mode disabled."
+			print ("[Info] Export WAVs from TLK files mode disabled.")
 		if (not extractTreFilesMode):
-			print "[Info] Extract Text Resources (TRx) mode disabled."
+			print ("[Info] Extract Text Resources (TRx) mode disabled.")
 		if (not extractDevCommAndExtraSFXMode):
-			print "[Info] Additional Sheet for developer commentary and extra SFX mode disabled."
+			print ("[Info] Additional Sheet for developer commentary and extra SFX mode disabled.")
 		if (not extractPOGOTextMode):
-			print "[Info] Additional Sheet for POGO text mode disabled."
+			print ("[Info] Additional Sheet for POGO text mode disabled.")
 
 		if not TMProotFolderWithExportedFiles: # this argument is mandatory
-			print "[Error] The output path for exported files (-op switch) argument is mandatory!"
+			print ("[Error] The output path for exported files (-op switch) argument is mandatory!")
 			invalidSyntax = True
 
 		if (not invalidSyntax) \
 			and (exportWavFilesMode == True or extractDevCommAndExtraSFXMode == True or extractTreFilesMode == True) \
 			and (TMProotFolderWithInputTLKFiles == ''):
-			print "[Error] No game input path (-ip switch) specified, while any of the export audio to WAV mode (-xwav), the export extras (-xdevs) or the extract Text Resources mode (-xtre) is enabled."
+			print ("[Error] No game input path (-ip switch) specified, while any of the export audio to WAV mode (-xwav), the export extras (-xdevs) or the extract Text Resources mode (-xtre) is enabled.")
 			invalidSyntax = True
 
 		if (not invalidSyntax) \
 			and (exportWavFilesMode == False and extractDevCommAndExtraSFXMode == False and extractTreFilesMode == False) \
 			and (TMProotFolderWithInputTLKFiles != ''):
-			print "[Warning] Specified game input path (-ip switch) will be ignored, since the export audio to WAV mode (-xwav), the export extras (-xdevs) and the extract Text Resources mode (-xtre) are disabled."
+			print ("[Warning] Specified game input path (-ip switch) will be ignored, since the export audio to WAV mode (-xwav), the export extras (-xdevs) and the extract Text Resources mode (-xtre) are disabled.")
 			# not invalid syntax though
 
 		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 "[Debug] Found actor: %s %s %s" % (actorEntryTmp[0], actorEntryTmp[1], actorEntryTmp[2])
+			#	print ("[Debug] Found actor: %s %s %s" % (actorEntryTmp[0], actorEntryTmp[1], actorEntryTmp[2]))
 			#
 			# Early checks for invalid cases
 			# 1. if TMProotFolderWithInputTLKFiles is not valid and -xtre or -xwav -> error!
@@ -1198,10 +1241,10 @@ def main(argsCL):
 			# 2. if not -wav and -op path is invalid then empty INGQUOT sheet -> error
 			# 3 [We check for this further bellow, before call for outputXLS]. if not -wav and -op path is empty (has no WAVs) then empty INGQUOT sheet -> Treat as an error case!
 			if ((exportWavFilesMode == True or extractDevCommAndExtraSFXMode == True or extractTreFilesMode == True) and (not os.path.isdir(TMProotFolderWithInputTLKFiles))):
-				print "[Error] Invalid game input path (-ip switch) was specified, while the export audio to WAV mode (-xwav), export extras (-xdevs) or the extract Text Resources mode (-xtre) is enabled."
+				print ("[Error] Invalid game input path (-ip switch) was specified, while the export audio to WAV mode (-xwav), export extras (-xdevs) or the extract Text Resources mode (-xtre) is enabled.")
 				sys.exit(1)
 			if ((exportWavFilesMode == False and extractDevCommAndExtraSFXMode == False) and (not os.path.isdir(TMProotFolderWithExportedFiles))):
-				print "[Error] Invalid output path for exported files (-op switch) was specified, while the export audio to WAV mode (-xwav) and export extras (-xdevs) are disabled (if enabled, it would create the path)."
+				print ("[Error] Invalid output path for exported files (-op switch) was specified, while the export audio to WAV mode (-xwav) and export extras (-xdevs) are disabled (if enabled, it would create the path).")
 				sys.exit(1)
 			#
 			# Checking for the optional case of parsing the input TLK files to export to WAV
@@ -1213,8 +1256,8 @@ def main(argsCL):
 				#	inputMIXExtractTREs(TMProotFolderWithInputTLKFiles)
 			#
 			# Parsing the exported WAV files
-			# NO: depending on the mode don't parse the irrellevant WAVs?
-			print "[Info] Parsing the (exported) WAV audio files in the -op path.\n\tPlease wait (this could take a while)..."
+			# NO: depending on the mode don't parse the irrelevant WAVs?
+			print ("[Info] Parsing the (exported) WAV audio files in the -op path.\n\tPlease wait (this could take a while)...")
 			# The broad search here is intentional
 			for (dirpath, dirnames, filenames) in walk(TMProotFolderWithExportedFiles):
 				for nameIdx, nameTmp in enumerate(filenames):
@@ -1239,12 +1282,12 @@ def main(argsCL):
 							if (posOfTLKWithinRightmostToken != -1 \
 								or posOfSFXWithinRightmostToken != -1):
 								relDirName = pTokenTmp	# don't break, we are interested in right-most matching token in the path
-						#if (nameTmp.upper()[:-4] + '.AUD') in zip(*SUPPORTED_EXPORTED_AUD_FROM_MIX_FILES)[0]:
-						#	print '[Trace] 1 file: %s' % (nameTmp.upper())
-						#	print 'TLKss %d vs SFXss:%d ' % (idxOfLastTLKToken, idxOfLastSFXToken)
+						#if (nameTmp.upper()[:-4] + '.AUD') in list(zip(*SUPPORTED_EXPORTED_AUD_FROM_MIX_FILES))[0]:
+						#	print ("[Trace] 1 file: %s" % (nameTmp.upper()))
+						#	print ("TLKss %d vs SFXss:%d " % (idxOfLastTLKToken, idxOfLastSFXToken))
 
 						if (idxOfLastSFXToken > idxOfLastTLKToken \
-							and (nameTmp.upper()[:-4] + '.AUD') in zip(*SUPPORTED_EXPORTED_AUD_FROM_MIX_FILES)[0]):
+							and (nameTmp.upper()[:-4] + '.AUD') in list(zip(*SUPPORTED_EXPORTED_AUD_FROM_MIX_FILES))[0]):
 							gMIXWavFiles.append(filenames[nameIdx] +'&' + relDirName + '&' + os.path.join(dirpath, nameTmp))
 						else:
 							gTLKWavFiles.append(filenames[nameIdx] +'&' + relDirName + '&' + os.path.join(dirpath, nameTmp))
@@ -1252,7 +1295,7 @@ def main(argsCL):
 			for fileIdx, filenameTmp in enumerate(gTLKWavFiles):
 				twoTokensOfFilenameAndRelDirname = filenameTmp.split('&', 1)
 				if len(twoTokensOfFilenameAndRelDirname) != 2:
-					print "[Error] While attempting filename and relative dirname split: %s" % (filenameTmp)
+					print ("[Error] While attempting filename and relative dirname split: %s" % (filenameTmp))
 					sys.exit(0)
 				#
 				# Remove WAV extension here
@@ -1272,11 +1315,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, twoTokensOfFilenameAndRelDirname[0][:-4])
+							print ("[Error] in actorIdMatch match: %s %s" % (tmpActorId, twoTokensOfFilenameAndRelDirname[0][:-4]))
 							sys.exit(0)
 					else:
 					#fatal error if something cannot convert to spot it immediately
-						print "[Error] in shorthand match: %s %s" % (threeTokensOfFilename[0], twoTokensOfFilenameAndRelDirname[0][:-4])
+						print ("[Error] in shorthand match: %s %s" % (threeTokensOfFilename[0], twoTokensOfFilenameAndRelDirname[0][:-4]))
 						sys.exit(0)
 					#
 					#
@@ -1292,7 +1335,7 @@ def main(argsCL):
 					filenameTmp =  tmpHealedSimpleFilename + '&' + twoTokensOfFilenameAndRelDirname[1]
 					gTLKWavFiles[fileIdx] = filenameTmp
 				else:
-					print "[Error] in splitting tokens on _: %s" % (filenameTmp)
+					print ("[Error] in splitting tokens on _: %s" % (filenameTmp))
 					sys.exit(0)
 			#
 			# Now handle the extra speech files (-xdevs mode)
@@ -1301,11 +1344,11 @@ def main(argsCL):
 				# (we will put it in another sheet)
 				twoTokensOfFilenameAndRelDirname = filenameTmp.split('&', 1)
 				if len(twoTokensOfFilenameAndRelDirname) != 2:
-					print "[Error] While attempting filename and relative dirname split on extra speech file: %s" % (filenameTmp)
+					print ("[Error] While attempting filename and relative dirname split on extra speech file: %s" % (filenameTmp))
 					sys.exit(0)
 
 				if (gTraceModeEnabled):
-					print "[Debug] No healing action needed on: %s" % (twoTokensOfFilenameAndRelDirname[0])
+					print ("[Debug] No healing action needed on: %s" % (twoTokensOfFilenameAndRelDirname[0]))
 
 			#sort in-place
 			#
@@ -1318,32 +1361,32 @@ def main(argsCL):
 			#
 			gTLKWavFilesNoDups = wavDupsRemove(gTLKWavFiles, 'TLKWAVS')
 			if len(gTLKWavFilesNoDups) == 0:
-				print "[Error] No supported speech audio files (WAV) were found in the output folder path (-op switch)."
+				print ("[Error] No supported speech audio files (WAV) were found in the output folder path (-op switch).")
 				sys.exit(1)
 			#
 			# Remove duplicates from extra speech files (-xdevs mode)
 			#
 			gMIXWavFilesNoDups = wavDupsRemove(gMIXWavFiles, 'EXTRAMIXWAVS')
 			if extractDevCommAndExtraSFXMode and len(gMIXWavFilesNoDups) == 0:
-				print "[Error] No supported extra speech audio files (WAV) were found in the output folder path (-op switch)."
+				print ("[Error] No supported extra speech audio files (WAV) were found in the output folder path (-op switch).")
 				sys.exit(1)
 
 			constructedOutputFilename = "%s-%s%s" % (OUTPUT_XLS_FILENAME, gActiveLanguageDescriptionCodeTuple[2], OUTPUT_XLS_FILENAME_EXT)
-			print "[Info] Creating output excel %s file..." % (constructedOutputFilename)
+			print ("[Info] Creating output excel %s file..." % (constructedOutputFilename))
 			outputXLS(constructedOutputFilename, OUTPUT_XLS_QUOTES_SHEET + gActiveLanguageDescriptionCodeTuple[1] + '.TR' + gActiveLanguageDescriptionCodeTuple[1], gTLKWavFilesNoDups, gMIXWavFilesNoDups, extractTreFilesMode, extractDevCommAndExtraSFXMode, extractPOGOTextMode, 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_exported_wav_Files [-ip folderpath_for_TLK_Files] [-ian path_to_actornames_txt] [-m stringPathToReplaceFolderpathInExcelLinks] [-ld gameInputLanguageDescription] [-xwav] [-xtre] [-xdevs] [-xpogo] [--trace]" % (APP_WRAPPER_NAME)
-		print "\nDetected arguments:"
+		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] [-xdevs] [-xpogo] [--trace]" % (APP_WRAPPER_NAME))
+		print ("\nDetected arguments:")
 		tmpi = 0
 		for tmpArg in argsCL:
 			if tmpi==0: #skip first argument
 				tmpi+=1
 				continue
-			print "Argument: %s" % (tmpArg)
+			print ("Argument: %s" % (tmpArg))
 			tmpi+=1
 
 # 00_0000 -- DealsInInsects					dupl TLK01, TLK0A
@@ -1359,5 +1402,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 4c8556a6ebd..a5e51646e6e 100644
--- a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/treFileLib.py
+++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/treFileLib.py
@@ -9,21 +9,21 @@ structLibFound = False
 try:
 	import os
 except ImportError:
-	print "[Error] os python library is required to be installed!"
+	print ("[Error] os python library is required to be installed!")
 else:
 	osLibFound = True
 
 try:
 	import sys
 except ImportError:
-	print "[Error] sys python library is required to be installed!"
+	print ("[Error] sys python library is required to be installed!")
 else:
 	sysLibFound = 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
 
@@ -33,9 +33,14 @@ if 	(not osLibFound) \
 	sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n")
 	sys.exit(1)
 
+pathToParent = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)
+pathToCommon = os.path.join(pathToParent, "common")
+sys.path.append(pathToCommon)
+
 from struct import *
+from pythonCompat import *
 
-MY_MODULE_VERSION = "0.50"
+MY_MODULE_VERSION = "0.70"
 MY_MODULE_NAME = "treFileLib"
 
 
@@ -74,7 +79,7 @@ class treFile(object):
 			# string IDs table (each entry is unsigned integer 4 bytes)
 			#
 			if self.m_traceModeEnabled:
-				print "[Info] Total texts in Text Resource file: %d" % (self.header().numOfTextResources)
+				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], '') )
@@ -92,7 +97,7 @@ class treFile(object):
 			#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
@@ -101,18 +106,30 @@ class treFile(object):
 				# to split the substring starting at the indicated offset each time, at the null character, and get the first string token.
 				# This works ok.
 				#
-				allTextsFound = treBytesBuff[currOffset:].split('\x00')
+				print (treBytesBuff[currOffset:])
+				if sys.version_info[0] <= 2:
+					allTextsFound = treBytesBuff[currOffset:].split('\x00')
+				else:
+					allTextsFound = treBytesBuff[currOffset:].split(b'\0')
+				print (allTextsFound[0])
 				### check "problematic" character cases:
 				##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]) )
+				##		print ("[Debug] Offs: %d\tFound String: %s" % (currOffset, ''.join(allTextsFound[0]) ))
 				(theId, stringOfIdx) = self.stringEntriesLst[idx]
-				self.stringEntriesLst[idx] = (theId, ''.join(allTextsFound[0]))
+				if sys.version_info[0] <= 2:
+					self.stringEntriesLst[idx] = (theId, ''.join(allTextsFound[0]))
+				else:
+					self.stringEntriesLst[idx] = (theId, allTextsFound[0])
+
 				if self.m_traceModeEnabled:
-					print "[Trace] ID: %d\tFound String: %s" % ( theId,''.join(allTextsFound[0]) )
+					if sys.version_info[0] <= 2:
+						print ("[Trace] ID: %d\tFound String: %s" % (theId, ''.join(allTextsFound[0]) ))
+					else:
+						print ("[Trace] ID: %d\tFound String: %s" % (theId, allTextsFound[0] ))
 			return True
-  		except:
-			print "[Error] Loading Text Resource %s failed!" % (self.simpleTextResourceFileName)
+		except Exception as e:
+			print ("[Error] Loading Text Resource %s failed!" % (self.simpleTextResourceFileName) + " " + str(e))
 			return False
 
 	def header(self):
@@ -129,36 +146,36 @@ if __name__ == '__main__':
 	inTREFileName =  'ACTORS.TRE'
 
 	if len(sys.argv[1:])  > 0 \
-		and os.path.isfile(os.path.join('.', sys.argv[1])) \
+		and os.path.isfile(os.path.join(u'.', sys.argv[1])) \
 		and len(sys.argv[1]) >= 5 \
 		and sys.argv[1][-3:].upper() == 'TRE':
 		inTREFileName = sys.argv[1]
-		print "[Info] Attempting to use %s as input TRE file..." % (inTREFileName)
-	elif os.path.isfile(os.path.join('.', inTREFileName)):
-		print "[Info] Using default %s as input TRE file..." % (inTREFileName)
+		print ("[Info] Attempting to use %s as input TRE file..." % (inTREFileName))
+	elif os.path.isfile(os.path.join(u'.', inTREFileName)):
+		print ("[Info] Using default %s as input TRE file..." % (inTREFileName))
 	else:
-		print "[Error] No valid input file argument was specified and default input file %s is missing." % (inTREFileName)
+		print ("[Error] No valid input file argument was specified and default input file %s is missing." % (inTREFileName))
 		errorFound = True
 
 	if not errorFound:
 		try:
-			print "[Info] Opening %s" % (inTREFileName)
-			inTREFile = open(os.path.join('.',inTREFileName), 'rb')
+			print ("[Info] Opening %s" % (inTREFileName))
+			inTREFile = open(os.path.join(u'.', 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(True)
 			if treFileInstance.m_traceModeEnabled:
-				print "[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION)
+				print ("[Debug] Running %s (%s) as main module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 			if treFileInstance.loadTreFile(allOfTreFileInBuffer, len(allOfTreFileInBuffer), inTREFileName):
-				print "[Info] Text Resource file loaded successfully!"
+				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 (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION)
+	#print ("[Debug] Running %s (%s) imported from another module" % (MY_MODULE_NAME, MY_MODULE_VERSION))
 	pass




More information about the Scummvm-git-logs mailing list