Skip to content

Commit 3ec8f15

Browse files
committed
Add gcipack
1 parent fdd6833 commit 3ec8f15

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

ttyd-tools/gcipack/gcipack.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import sys
2+
import os
3+
import struct
4+
import ctypes
5+
import math
6+
7+
inputFilename = sys.argv[1]
8+
inputFile = open(inputFilename, "rb")
9+
inputBuffer = ctypes.create_string_buffer(inputFile.read())[:-1]
10+
inputFile.close()
11+
12+
blockCount = math.ceil((0x2040 + len(inputBuffer)) / 0x2000)
13+
14+
# Create header
15+
headerBuffer = ctypes.create_string_buffer(0x40)
16+
struct.pack_into(">L", headerBuffer, 0x00, 0x47384D45) # game code
17+
struct.pack_into(">H", headerBuffer, 0x04, 0x3031) # maker code
18+
struct.pack_into(">B", headerBuffer, 0x06, 0xFF) # unused
19+
struct.pack_into(">B", headerBuffer, 0x07, 2) # banner flags (RGB5A3)
20+
struct.pack_into("32s", headerBuffer, 0x08, sys.argv[2].encode()) # filename
21+
struct.pack_into(">L", headerBuffer, 0x28, 0) # modified time
22+
struct.pack_into(">L", headerBuffer, 0x2C, 0) # image offset
23+
struct.pack_into(">H", headerBuffer, 0x30, 2) # icon format
24+
struct.pack_into(">H", headerBuffer, 0x32, 3) # animation speed (1 icon for 12 frames)
25+
struct.pack_into(">B", headerBuffer, 0x34, 4) # permissions
26+
struct.pack_into(">B", headerBuffer, 0x35, 0) # copy counter
27+
struct.pack_into(">H", headerBuffer, 0x36, 0) # first block number
28+
struct.pack_into(">H", headerBuffer, 0x38, blockCount) # block count
29+
struct.pack_into(">H", headerBuffer, 0x3A, 0xFF) # unused
30+
struct.pack_into(">L", headerBuffer, 0x3C, 0x2000) # comment address
31+
32+
# Load banner and icon
33+
bannerFile = open(sys.argv[5], "rb")
34+
bannerBuffer = ctypes.create_string_buffer(bannerFile.read())[:-1]
35+
if len(bannerBuffer) != 0x1800:
36+
print("Warning: banner size mismatch (should be 96x32 RGB5A3)")
37+
bannerFile.close()
38+
39+
iconFile = open(sys.argv[6], "rb")
40+
iconBuffer = ctypes.create_string_buffer(iconFile.read())[:-1]
41+
if len(iconBuffer) != 0x800:
42+
print("Warning: icon size mismatch %d (should be 32x32 RGB5A3)" % len(iconBuffer))
43+
iconFile.close()
44+
45+
# Comment
46+
commentBuffer = ctypes.create_string_buffer(0x40)
47+
struct.pack_into("32s", commentBuffer, 0x00, sys.argv[3].encode())
48+
struct.pack_into("32s", commentBuffer, 0x20, sys.argv[4].encode())
49+
50+
# Pad to block boundary
51+
paddingLength = blockCount * 0x2000 - (len(bannerBuffer) + len(iconBuffer) + len(commentBuffer) + len(inputBuffer))
52+
paddingBuffer = ctypes.create_string_buffer(paddingLength)
53+
54+
outputFilename = os.path.splitext(os.path.splitext(inputFilename)[0])[0] + ".gci"
55+
outputFile = open(outputFilename, "wb")
56+
outputFile.write(bytearray(headerBuffer))
57+
outputFile.write(bytearray(bannerBuffer))
58+
outputFile.write(bytearray(iconBuffer))
59+
outputFile.write(bytearray(commentBuffer))
60+
outputFile.write(bytearray(inputBuffer))
61+
outputFile.write(bytearray(paddingBuffer))
62+
outputFile.close()

0 commit comments

Comments
 (0)