2020-06-30 18:48:08 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
import argparse, os, re, struct, sys
|
|
|
|
|
|
|
|
def errorOut(msg):
|
|
|
|
print('ERROR: {}'.format(msg))
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
def mkParser():
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('-enc', dest = 'ENCODING', type = str, help = 'use this encoding' )
|
2022-04-04 08:12:29 +02:00
|
|
|
parser.add_argument('-tn', dest = 'DO_TABLE', action = 'store_true',
|
|
|
|
help = 'output table file' )
|
|
|
|
parser.add_argument('-oc', dest = 'DO_OTHERCOUNTS', action = 'store_true',
|
|
|
|
help = 'write extra (non-15x15 board) counts' )
|
|
|
|
parser.add_argument('-info', dest = 'INFO_KEY', type = str,
|
|
|
|
help = 'info.txt keyword to write null-terminated' )
|
2020-07-04 04:06:16 +02:00
|
|
|
|
2020-06-30 18:48:08 +02:00
|
|
|
# parser.add_argument('-tn', dest = 'UNICODE', default = False,
|
|
|
|
# action = 'store_true', help = 'assume unicode')
|
|
|
|
# parser.add_argument('-t', dest = 'UNICODE', type = str, default = True,
|
|
|
|
# action = 'store_false', help = 'DO NOT assume unicode')
|
|
|
|
parser.add_argument('-v', dest = 'DO_VALS', action = 'store_true', help = 'output values file' )
|
|
|
|
parser.add_argument('-s', dest = 'DO_SIZE', action = 'store_true', help = 'output size file')
|
|
|
|
parser.add_argument('-out', dest = 'OUTFILE', type = str, help = 'outfile path')
|
2020-07-04 04:06:16 +02:00
|
|
|
|
|
|
|
parser.add_argument('--table-file', dest = 'TABLE_FILE', type = str, help = 'write table file here')
|
|
|
|
parser.add_argument('--size-file', dest = 'SIZE_FILE', type = str, help = 'write size file here')
|
|
|
|
parser.add_argument('--vals-file', dest = 'VALS_FILE', type = str, help = 'write vals file here')
|
|
|
|
|
2020-06-30 18:48:08 +02:00
|
|
|
return parser
|
|
|
|
|
|
|
|
sPreComment = re.compile('^(.*)#.*$')
|
|
|
|
sVarAssign = re.compile('^(\w+):(.*)$')
|
|
|
|
sBeginTiles = re.compile('^<BEGIN_TILES>$')
|
|
|
|
sEndTiles = re.compile('^<END_TILES>$')
|
2020-07-07 20:54:45 +02:00
|
|
|
sSingleCharMatch = re.compile("'(.(\|.)*)'")
|
|
|
|
sSpecialsMatch = re.compile('{"(.+)"(,.+)?}')
|
2020-06-30 18:48:08 +02:00
|
|
|
|
|
|
|
def parseTileInfo(infoFile, encoding):
|
|
|
|
result = {'_TILES' : []}
|
|
|
|
with open(infoFile, 'rt') as file:
|
|
|
|
data = file.read()
|
|
|
|
# if encoding:
|
|
|
|
# data = data.decode(encoding)
|
|
|
|
data = data.split('\n')
|
|
|
|
|
|
|
|
inTiles = False
|
|
|
|
tiles = []
|
|
|
|
for line in data:
|
|
|
|
# print('line at start: {}'.format(line))
|
|
|
|
match = sPreComment.match(line)
|
|
|
|
if match:
|
|
|
|
line = match.group(1)
|
|
|
|
# print('line sans comment: {}'.format(line))
|
|
|
|
if 0 == len(line):continue
|
|
|
|
|
|
|
|
if inTiles:
|
|
|
|
if sEndTiles.match(line):
|
|
|
|
break
|
|
|
|
else:
|
2022-04-04 08:12:29 +02:00
|
|
|
(face, val, counts) = line.split(None, 2)
|
|
|
|
result['_TILES'].append({'counts': counts,
|
|
|
|
'val': val,
|
|
|
|
'face': face})
|
2020-06-30 18:48:08 +02:00
|
|
|
elif sBeginTiles.match(line):
|
|
|
|
inTiles = True
|
|
|
|
else:
|
|
|
|
match = sVarAssign.match(line)
|
|
|
|
if match:
|
|
|
|
var = match.group(1)
|
|
|
|
if not var in result: result[var] = ''
|
|
|
|
result[var] += match.group(2)
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
def printLetters( letters, outfile ):
|
|
|
|
letters = letters.split('|')
|
|
|
|
letters = ' '.join(letters)
|
|
|
|
outfile.write(letters.encode('utf8'))
|
|
|
|
|
2022-04-04 08:12:29 +02:00
|
|
|
def writeInfoFile(xlocToken, key, outfile):
|
|
|
|
val = xlocToken[key]
|
|
|
|
assert val
|
|
|
|
outfile.write(val.encode('utf8'))
|
|
|
|
outfile.write(struct.pack('B', 0 ))
|
|
|
|
|
2020-06-30 18:48:08 +02:00
|
|
|
def writeMapFile(xlocToken, outfile):
|
2022-04-04 08:12:29 +02:00
|
|
|
print('writeMapFile(out={})'.format(outfile))
|
2020-06-30 18:48:08 +02:00
|
|
|
tiles = xlocToken['_TILES']
|
|
|
|
specialCount = 0
|
|
|
|
for tile in tiles:
|
2022-04-04 08:12:29 +02:00
|
|
|
face = tile['face']
|
2020-06-30 18:48:08 +02:00
|
|
|
match = sSingleCharMatch.match(face)
|
|
|
|
if match:
|
|
|
|
printLetters( match.group(1), outfile )
|
|
|
|
continue
|
|
|
|
match = sSpecialsMatch.match(face)
|
|
|
|
if match:
|
|
|
|
print('specials char: {}'.format(match.group(1)))
|
|
|
|
outfile.write(struct.pack('B', specialCount ))
|
|
|
|
specialCount += 1
|
|
|
|
continue
|
|
|
|
|
|
|
|
print('bad/unmatched face: {}'.format(face))
|
|
|
|
assert False
|
|
|
|
|
|
|
|
def writeValuesFile(xlocToken, outfile):
|
|
|
|
header = xlocToken.get('XLOC_HEADER') or errorOut('no XLOC_HEADER found')
|
|
|
|
|
2022-04-04 08:12:29 +02:00
|
|
|
print('writeValuesFile(out={}): writing header: {}'.format(outfile, header))
|
2020-06-30 18:48:08 +02:00
|
|
|
outfile.write(struct.pack('!H', int(header, 16)))
|
|
|
|
|
2022-04-04 08:12:29 +02:00
|
|
|
cs = xlocToken.get('COUNT_SIZES', '15').split()
|
|
|
|
useOffset = cs.index('15')
|
|
|
|
|
|
|
|
nCounts = 0
|
2020-06-30 18:48:08 +02:00
|
|
|
for tile in xlocToken['_TILES']:
|
2022-04-04 08:12:29 +02:00
|
|
|
counts = tile['counts'].split()
|
|
|
|
assert nCounts == 0 or nCounts == len(counts)
|
|
|
|
nCounts = len(counts)
|
|
|
|
assert nCounts == len(cs)
|
|
|
|
outfile.write(struct.pack('B', int(counts[useOffset])))
|
|
|
|
|
|
|
|
val = int(tile['val'])
|
|
|
|
outfile.write(struct.pack('B', val))
|
|
|
|
|
|
|
|
def writeOtherCounts(xlocToken, outfile):
|
|
|
|
cs = xlocToken.get('COUNT_SIZES', '15').split()
|
|
|
|
|
|
|
|
tiles = xlocToken['_TILES']
|
|
|
|
# Write the size of the data so it can be skipped by the reader,
|
|
|
|
# which won't know how many faces the tile set has yet.
|
|
|
|
totalSiz = (len(cs) - 1) * (1 + len(tiles))
|
|
|
|
outfile.write(struct.pack('B', totalSiz))
|
|
|
|
|
|
|
|
for useOffset in range(len(cs)):
|
|
|
|
siz = int(cs[useOffset])
|
|
|
|
if siz == 15: continue
|
|
|
|
outfile.write(struct.pack('B', siz))
|
|
|
|
for tile in tiles:
|
|
|
|
count = tile['counts'].split()[useOffset]
|
|
|
|
outfile.write(struct.pack('B', int(count)))
|
2020-06-30 18:48:08 +02:00
|
|
|
|
|
|
|
def main():
|
|
|
|
print('{}.main {} called'.format(sys.argv[0], sys.argv[1:]))
|
|
|
|
args = mkParser().parse_args()
|
|
|
|
|
|
|
|
infoFile = 'info.txt'
|
|
|
|
if not os.path.exists(infoFile):
|
|
|
|
errorOut('{} not found'.format(infoFile))
|
|
|
|
xlocToken = parseTileInfo(infoFile, args.ENCODING)
|
|
|
|
|
2022-04-04 08:12:29 +02:00
|
|
|
if args.INFO_KEY and args.OUTFILE:
|
|
|
|
with open(args.OUTFILE, 'wb') as outfile:
|
|
|
|
writeInfoFile(xlocToken, args.INFO_KEY, outfile);
|
|
|
|
|
2020-07-04 04:06:16 +02:00
|
|
|
if args.DO_TABLE or args.TABLE_FILE:
|
|
|
|
path = args.TABLE_FILE or args.OUTFILE
|
|
|
|
with open(path, 'wb') as outfile:
|
2020-06-30 18:48:08 +02:00
|
|
|
writeMapFile(xlocToken, outfile);
|
2020-07-04 04:06:16 +02:00
|
|
|
|
|
|
|
if args.DO_SIZE or args.SIZE_FILE:
|
|
|
|
path = args.SIZE_FILE or args.OUTFILE
|
|
|
|
with open(path, 'wb') as outfile:
|
2020-06-30 18:48:08 +02:00
|
|
|
count = len(xlocToken['_TILES'])
|
2020-07-04 04:06:16 +02:00
|
|
|
outfile.write(struct.pack('B', count))
|
2020-06-30 18:48:08 +02:00
|
|
|
|
2020-07-04 04:06:16 +02:00
|
|
|
if args.DO_VALS or args.VALS_FILE:
|
|
|
|
path = args.VALS_FILE or args.OUTFILE
|
|
|
|
with open(path, 'wb') as outfile:
|
|
|
|
writeValuesFile( xlocToken, outfile )
|
2020-06-30 18:48:08 +02:00
|
|
|
|
2022-04-04 08:12:29 +02:00
|
|
|
if args.DO_OTHERCOUNTS and args.OUTFILE:
|
|
|
|
with open(args.OUTFILE, 'wb') as outfile:
|
|
|
|
writeOtherCounts(xlocToken, outfile)
|
|
|
|
|
2020-06-30 18:48:08 +02:00
|
|
|
##############################################################################
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|