aboutsummaryrefslogtreecommitdiff
path: root/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/treFileLib.py
blob: 18a23ba5f05fc271d2fe82d586c5b8d397112030 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/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 shutil 
except ImportError:
	print "[Error] Shutil python library is required to be installed!" 
else:
	shutilLibFound = True

try:
	import struct 
except ImportError:
	print "[Error] struct python library is required to be installed!" 
else:
	structLibFound = True

if 	(not osLibFound) \
	or (not sysLibFound) \
	or (not shutilLibFound) \
	or (not structLibFound):
	sys.stdout.write("[Error] Errors were found when trying to import required python libraries\n")
	sys.exit(1)
	
from struct import *

MY_MODULE_VERSION = "0.50"
MY_MODULE_NAME = "treFileLib"


class TreHeader:
	numOfTextResources = -1
	def __init__(self):
		return


class treFile:
	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.
				#
				allTextsFound = treBytesBuff[currOffset:].split('\x00')
				## 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]
				self.stringEntriesLst[idx] = (theId, ''.join(allTextsFound[0]))
				#print "[Debug] ID: %d\tFound String: %s" % ( theId,''.join(allTextsFound[0]) )
			return True
  		except:
			print "[Error] Loading Text Resource %s failed!" % (self.simpleTextResourceFileName)
			return False

	def header(self):
		return self.m_header
#
#
#
if __name__ == '__main__':
	#	 main()
	# (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('.', sys.argv[1])) \
		and len(sys.argv[1]) > 5 \
		and sys.argv[1][-3:] == 'TRE':
		inTREFileName = sys.argv[1]
	print "[Info] Using %s as input TRE file..." % (inTREFileName)	

	errorFound = False
	
	try:
		print "[Info] Opening %s" % (inTREFileName)
		inTREFile = open(os.path.join('.',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