Files
scummvm-cursorfix/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/treFileLib.py
2026-02-02 04:50:13 +01:00

182 lines
6.2 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
osLibFound = False
sysLibFound = False
shutilLibFound = False
structLibFound = False
try:
import os
except ImportError:
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!")
else:
sysLibFound = True
try:
import struct
except ImportError:
print ("[Error] struct python library is required to be installed!")
else:
structLibFound = True
if (not osLibFound) \
or (not sysLibFound) \
or (not structLibFound):
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.70"
MY_MODULE_NAME = "treFileLib"
class TreHeader(object):
numOfTextResources = -1
def __init__(self):
return
class treFile(object):
m_header = TreHeader()
simpleTextResourceFileName = 'GENERIC.TRE'
stringEntriesLst = [] # list of two-value tuples. First value is ID, second value is String content
stringOffsets = []
m_traceModeEnabled = False
# traceModeEnabled is bool to enable more printed debug messages
def __init__(self, traceModeEnabled = True):
del self.stringEntriesLst[:]
del self.stringOffsets[:]
self.simpleTextResourceFileName = 'GENERIC.TRE'
self.m_traceModeEnabled = traceModeEnabled
return
def loadTreFile(self, treBytesBuff, maxLength, treFileName):
self.simpleTextResourceFileName = treFileName
offsInTreFile = 0
#
# parse TRE file fields for header
#
try:
tmpTuple = struct.unpack_from('I', treBytesBuff, offsInTreFile) # unsigned integer 4 bytes
self.header().numOfTextResources = tmpTuple[0]
offsInTreFile += 4
#
# 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))
for idx in range(0, self.header().numOfTextResources):
tmpTuple = struct.unpack_from('I', treBytesBuff, offsInTreFile) # unsigned integer 4 bytes
self.stringEntriesLst.append( (tmpTuple[0], '') )
offsInTreFile += 4
# string offsets table (each entry is unsigned integer 4 bytes)
for idx in range(0, self.header().numOfTextResources):
tmpTuple = struct.unpack_from('I', treBytesBuff, offsInTreFile) # unsigned integer 4 bytes
self.stringOffsets.append( tmpTuple[0] )
offsInTreFile += 4
#
# strings (all entries are null terminated)
# TODO +++
absStartOfIndexTable = 4
#absStartOfOffsetTable = absStartOfIndexTable + (self.header().numOfTextResources * 4)
#absStartOfStringTable = absStartOfOffsetTable + ((self.header().numOfTextResources+1) * 4)
#print ("[Debug] buffer type: ", type(treBytesBuff)) # it is str
for idx in range(0, self.header().numOfTextResources):
currOffset = self.stringOffsets[idx] + absStartOfIndexTable
# the buffer (treBytesBuff) where we read the TRE file into, is "str" type but contains multiple null terminated strings
# the solution here (to not get out of index errors when reading the null terminator points) is
# to split the substring starting at the indicated offset each time, at the null character, and get the first string token.
# This works ok.
#
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]) ))
(theId, stringOfIdx) = self.stringEntriesLst[idx]
if sys.version_info[0] <= 2:
self.stringEntriesLst[idx] = (theId, ''.join(allTextsFound[0]))
else:
self.stringEntriesLst[idx] = (theId, allTextsFound[0])
if self.m_traceModeEnabled:
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 Exception as e:
print ("[Error] Loading Text Resource %s failed!" % (self.simpleTextResourceFileName) + " " + str(e))
return False
def header(self):
return self.m_header
#
#
#
if __name__ == '__main__':
# main()
errorFound = False
# By default assumes a file of name ACTORS.TRE in same directory
# otherwise tries to use the first command line argument as input file
inTREFile = None
inTREFileName = 'ACTORS.TRE'
if len(sys.argv[1:]) > 0 \
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(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))
errorFound = True
if not errorFound:
try:
print ("[Info] Opening %s" % (inTREFileName))
inTREFile = open(os.path.join(u'.', inTREFileName), 'rb')
except:
errorFound = True
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))
if treFileInstance.loadTreFile(allOfTreFileInBuffer, len(allOfTreFileInBuffer), inTREFileName):
print ("[Info] Text Resource file loaded successfully!")
else:
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))
pass