Skip to content

Commit ba0f8e3

Browse files
authored
Update to 1.2
1 parent 45d42a4 commit ba0f8e3

File tree

4 files changed

+134
-39
lines changed

4 files changed

+134
-39
lines changed

decoder.py

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,10 @@ def processPointers4Bytes(data, header):
153153
# Read four bytes as a quartet
154154
quartet = data[i:i + 4]
155155

156-
# Get last two byte of the quartet
157-
get2Bytes = quartet[2:]
158-
159156
# Convert the final triplet to an integer
160-
value = int.from_bytes(get2Bytes, byteorder='big') + header
157+
value = int.from_bytes(quartet, byteorder='big') + header
161158
result.append(value)
159+
162160
return result
163161

164162
def extractTexts(romData, addressesList, lineBreakers, charTable):
@@ -187,13 +185,14 @@ def extractTexts(romData, addressesList, lineBreakers, charTable):
187185
# Loop over each starting address in the list
188186
for addr in addressesList:
189187
text = bytearray()
188+
decodedValidCharacter = False
190189

191190
while True:
192191
byte = romData[addr]
193192
bytesLineCounter += 1
194193

195194
# If the byte is a line-breaker, stop extracting
196-
if byte in lineBreakers:
195+
if byte in lineBreakers and decodedValidCharacter:
197196
breakerByte = byte
198197
break
199198

@@ -203,10 +202,12 @@ def extractTexts(romData, addressesList, lineBreakers, charTable):
203202
# If single character
204203
if len(char) == 1:
205204
text.append(ord(char))
205+
decodedValidCharacter = True
206206
# If multiple characters (DTE/MTE)
207207
else:
208208
for c in char:
209209
text.append(ord(c))
210+
decodedValidCharacter = True
210211
# If byte is not in charTable, print in format ~hex~
211212
else:
212213
hexValue = format(byte, '02X')
@@ -243,6 +244,76 @@ def extractTexts(romData, addressesList, lineBreakers, charTable):
243244

244245
return texts, totalBytesRead, linesLength
245246

247+
def extractTextsNoLineBreakers(romData, addressesList, endOffset, charTable):
248+
"""
249+
Extracts texts from the ROM data at specified addresses based on the lengths in linesLength.
250+
251+
Parameters:
252+
romData (bytes): The complete ROM data.
253+
addressesList (list): A list of addresses to read the texts from.
254+
endOffset (set): The final offset after the last address.
255+
charTable (dict): A dictionary mapping byte values to characters or sequences.
256+
257+
Returns:
258+
tuple: Containing:
259+
- texts (list): Extracted script text.
260+
- totalBytesRead (int): Total text block size.
261+
- linesLength (list): Length of each line in bytes.
262+
"""
263+
texts = []
264+
linesLength = []
265+
total = 0
266+
267+
# Add final offset to the addressesList
268+
addressesList.append(int(endOffset.pop()))
269+
270+
# Calculate lines lenght of each segment is the difference between consecutive addresses
271+
for i in range(len(addressesList) - 1):
272+
length = int(addressesList[i + 1]) - int(addressesList[i])
273+
linesLength.append(length)
274+
275+
# Loop over each starting address in the list and use linesLength for determining byte ranges
276+
for i in range(len(addressesList) - 1):
277+
startAddr = addressesList[i]
278+
length = linesLength[i] # Get the length for this segment
279+
endAddr = startAddr + length
280+
281+
text = bytearray()
282+
decodedValidCharacter = False
283+
284+
# Read bytes from the starting address to the end address (using the specified length)
285+
for addr in range(startAddr, endAddr):
286+
byte = romData[addr]
287+
288+
# Map the byte using charTable to get the character
289+
char = charTable.get(byte, None)
290+
if char:
291+
# If single character
292+
if len(char) == 1:
293+
text.append(ord(char))
294+
decodedValidCharacter = True
295+
# If multiple characters (DTE/MTE)
296+
else:
297+
for c in char:
298+
text.append(ord(c))
299+
decodedValidCharacter = True
300+
# If byte is not in charTable, print in format ~hex~
301+
else:
302+
hexValue = format(byte, '02X')
303+
text.extend(f"~{hexValue}~".encode('UTF-8'))
304+
305+
# Convert byte array to string
306+
decodedText = text.decode('iso-8859-1', errors='replace')
307+
308+
# Append the decoded text to the list
309+
texts.append(decodedText)
310+
total += length
311+
312+
# Calculate total bytes read (this will be the sum of all lengths in linesLength)
313+
totalBytesRead = total
314+
315+
return texts, totalBytesRead, linesLength
316+
246317
def parseLineBreakers(string):
247318
"""
248319
Parse a string of comma-separated hexadecimal values into a set of integers.
@@ -257,8 +328,11 @@ def parseLineBreakers(string):
257328
for byte in string.split(','):
258329
byte = byte.strip()
259330
lineBreakers.add(int(byte, 16))
331+
332+
# If the lineBreaker are the final text offset
333+
is_offset = any(value > 255 for value in lineBreakers)
260334

261-
return lineBreakers
335+
return lineBreakers, is_offset
262336

263337
def formatHexString(hexString):
264338
"""

dist/HexString.exe

1.33 KB
Binary file not shown.

encoder.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def readScriptFile(file):
3030

3131
# Process text (excluding comments)
3232
textData = [
33-
line.rstrip() for line in f.readlines()
33+
line.rstrip('\n') for line in f.readlines()
3434
if not (line.startswith(";") or line.startswith("@") or line.startswith("|"))
3535
]
3636
return textData, hexData[0], hexData[1], hexData[2], lineBreakers
@@ -282,7 +282,7 @@ def calculatePointer4Bytes(listCumulativeLength, firstPointer, headerSize=None):
282282
pointersData.append(ptr & 0xFF) # Least significant byte
283283
return pointersData
284284

285-
def writeROM(romFile, startOffset, data):
285+
def writePointers(romFile, startOffset, data):
286286
"""
287287
Writes data to the ROM at the specified offset.
288288
@@ -294,3 +294,28 @@ def writeROM(romFile, startOffset, data):
294294
with open(romFile, "r+b") as f:
295295
f.seek(startOffset)
296296
f.write(data)
297+
298+
def writeText(romFile, startOffset, maxSize, data):
299+
"""
300+
Writes data to the ROM at the specified offset.
301+
302+
Parameters:
303+
romFile (str): The path to the ROM file.
304+
startOffset (int): The offset in the ROM file where data should be written.
305+
data (bytes or bytearray): The data to write to the ROM.
306+
"""
307+
# Check that the size of the data does not exceed the maximum allowed
308+
if len(data) > int(maxSize):
309+
excess = len(data) - int(maxSize)
310+
return False
311+
312+
# Check free space
313+
freeSpace = int(maxSize) - len(data)
314+
315+
# Fill free space
316+
filledData = data + b'\xFF' * freeSpace
317+
318+
with open(romFile, "r+b") as f:
319+
f.seek(startOffset)
320+
f.write(filledData)
321+
return True

main.py

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## HexString
22
## Source code by koda
3-
## release 03/12/2024 --version 1.1
3+
## release 03/01/2025 --version 1.2 (no space)
44

55
import sys
66
import os
@@ -51,7 +51,7 @@ def main():
5151
except ValueError:
5252
print("Error: Incorrect hex value.")
5353
sys.exit(1)
54-
lineBreaker = sys.argv[7] # Line breaker input (comma-separated)
54+
lineBreaker = sys.argv[7] # Line breaker input
5555
outFile = sys.argv[8] # Output file for the extracted text
5656
tblFile = sys.argv[9] # Tbl file argument
5757

@@ -64,7 +64,7 @@ def main():
6464

6565
# Parse line breakers.
6666
try:
67-
parseLineBreakers = de.parseLineBreakers(lineBreaker)
67+
parseLineBreakers, isOffset = de.parseLineBreakers(lineBreaker)
6868
except ValueError:
6969
print("Error: Incorrect hex value.")
7070
sys.exit(1)
@@ -86,7 +86,10 @@ def main():
8686

8787
# Extract the texts
8888
try:
89-
texts, totalBytesRead, linesLenght = de.extractTexts(romData, lineStartAddress, parseLineBreakers, charTable)
89+
if not isOffset:
90+
texts, totalBytesRead, linesLenght = de.extractTexts(romData, lineStartAddress, parseLineBreakers, charTable)
91+
else:
92+
texts, totalBytesRead, linesLenght = de.extractTextsNoLineBreakers(romData, lineStartAddress, parseLineBreakers, charTable)
9093
except IndexError:
9194
print(f"Error: Start address is bigger than the ROM size.")
9295
sys.exit(1)
@@ -166,33 +169,29 @@ def main():
166169

167170
# Format pointers
168171
encodedPointers = pointersFormat(pointersList, textStartAddress, headerSize)
169-
170-
# Check that the size of the data does not exceed the maximum allowed
171-
if len(encodedText) > int(textSize):
172-
excess = len(encodedText) - int(textSize)
173-
sys.stdout.write("Error: The number of bytes read exceeds the maximum block limit.\n")
174-
sys.stdout.write(f"Remove {excess} bytes from {scriptFile} file.\n")
175-
sys.exit(1)
176-
177-
# Check free bytes
178-
freeBytes = int(textSize) - len(encodedText)
179-
172+
180173
# Write the text to the ROM
181174
try:
182-
en.writeROM(romFile, textStartAddress, encodedText)
175+
if en.writeText(romFile, textStartAddress, textSize, encodedText):
176+
# Write the pointers to the ROM
177+
en.writePointers(romFile, pointersStartAddress, encodedPointers)
178+
freeSpace = int(textSize) - len(encodedText)
179+
print(f"Text written at offset {hex(textStartAddress)}.")
180+
print(f"Pointers table written at offset {hex(pointersStartAddress)} with {len(pointersList)} pointers.")
181+
print(f"Free space: {freeSpace} bytes.")
182+
print(f"Data written to {romFile}")
183+
print("Encoding complete.\n")
184+
sys.exit(1)
185+
186+
else:
187+
excess = len(encodedText) - int(textSize)
188+
sys.stdout.write("Error: The number of bytes read exceeds the maximum block limit.\n")
189+
sys.stdout.write(f"Remove {excess} bytes from {scriptFile} file.\n")
190+
sys.exit(1)
191+
183192
except FileNotFoundError:
184193
print(f"Error: File {romFile} not found in directory.")
185194
sys.exit(1)
186-
187-
# Write the pointers to the ROM
188-
en.writeROM(romFile, pointersStartAddress, encodedPointers)
189-
190-
print(f"Text written at offset {hex(textStartAddress)}.")
191-
print(f"Pointers table written at offset {hex(pointersStartAddress)} with {len(pointersList)} pointers.")
192-
print(f"Free space: {freeBytes} bytes.")
193-
print(f"Data written to {romFile}")
194-
print("Encoding complete.\n")
195-
sys.exit(1)
196195

197196
elif sys.argv[1] == '-h':
198197
print("\nUsage: HexString [-d|e] [input_file output_file]")
@@ -209,14 +208,11 @@ def main():
209208
sys.exit(1)
210209

211210
elif sys.argv[1] == '-v':
212-
sys.stdout.write("\nHexSring created by koda, version 1.1.0")
211+
sys.stdout.write("\nHexSring created by koda, version 1.2")
213212
sys.exit(1)
214213

215214
else:
216-
sys.stdout.write("Usage: -d <pointersFormat> <romFile> <PointersStartAddress> <PointerTableSize> <HeaderSize> <LineBreaker> <outFile> <tblFile>\n")
217-
sys.stdout.write(" -e <pointersFormat> <TextFile> <TextStartAddress> <TextSize> <PointersStartAddress> <HeaderSize> <romFile> <tblFile>\n")
218-
sys.stdout.write(" -h show help.\n")
219-
sys.stdout.write(" -v show version.\n")
215+
showHelp()
220216
sys.exit(1)
221217

222218
if __name__ == '__main__':

0 commit comments

Comments
 (0)