@@ 0,0 1,158 @@
+"""
+Functions for generating TRN (turn) files.
+"""
+
+import struct
+import random
+from common import SIGNATURE, SUBVERSION, get_checksum
+
+CLIENT = 'VGA Planets v3.x library for Python'
+URL = 'http://github.com/ghdpro/planets'
+
+# VPH35.DLL magic numbers, taken from PCC v2's "trn.cc" source file
+VPH_MAGIC = (1585242373,
+ 458484639, 1702713875, 2131768570, 943874411, 1531045611,
+ 622829488, 660770929, 473301358, 1868910709, 439267666, 1259778247,
+ 187160419, 205520992, 1162432602, 2048525217, 663275107, 1945076761,
+ 1912495862, 372583676, 2110506768, 972564220, 1627953855, 1696231547,
+ 1825551059, 690525357, 1425805634, 1273009202, 1643106825, 1033503714,
+ 1773067018, 1444056607, 841306782, 1311137219, 472310692, 1658228604,
+ 214806212, 1638334074, 870981249, 1438230436, 1722981495, 383237037,
+ 1014208183, 1950729749, 1381216466, 1149684732, 1475271197, 990158844,
+ 659846975, 131158828, 1269952134, 1929873739, 149943298, 94038386,
+ 1639179540, 519578396, 649680371, 2139806121, 48126387, 1820750093,
+ 2002158429, 834011058, 127330762, 1341047341, 45011247, 1210785240,
+ 102394054, 1033444233, 1452787209, 1636216880, 2001004855, 196571844,
+ 768753436, 1715639759, 9036553, 550413001, 1195957868, 566073290,
+ 1386247611, 725117880, 637842515, 782679024, 614960412, 1259473924,
+ 710893647, 137748852, 808495109, 1174108532, 2141228605, 1298353301,
+ 1989952843, 607318838, 1868217839, 2046567417, 1297732528, 886928938,
+ 533473933, 667670866, 1241783877, 1634258231, 1529167548, 1048674755,
+ 108553737, 442206379, 1427828321, 178793040, 57025576, 1886069810,
+ 1452681265, 392872129, 1749094387, 1931946557, 610131601, 497923660,
+ 800378618, 833787008, 1047995126, 867114247, 108316439, 1889137816,
+ 1566927898, 1606954817, 2129997452, 176508207, 1504084876, 781656333,
+ 1575411145, 952282888, 1920012969, 725392878, 442033280, 2055008888,
+ 125996860, 648896510, 1271579722, 734745843, 457213090, 101154514,
+ 1253209494, 649313503, 665663012, 1284757233, 526008074, 1128559135,
+ 708376521, 1888247159, 637430572, 1297014774, 84473586, 1938406737,
+ 278055502, 2082329430, 784004382, 886858342, 487519681, 979889529,
+ 2118032563, 376523135, 2037399162, 494383465, 1744352698, 533745717,
+ 752066469, 1518627158, 347571084, 1270232880, 460005993, 1754379254,
+ 1431354806, 103810045, 676346171, 948969734, 1270441550, 562587328,
+ 305781542, 48494333, 263492952, 1020466270, 190108896, 1009887493,
+ 1263640424, 2136294797, 951195719, 1154885409, 533815976, 707619918,
+ 1293089160, 1565561820, 1424862457, 2024541688, 1849356050, 804648133,
+ 1041775421, 1752468846, 2051572786, 749910457, 1708669854, 1592915884,
+ 1123095599, 1460717743, 1948843781, 1082061162, 1152635918,
+ 1881839283, 760734026, 1910315568, 1258782923, 2051380841, 1725205147,
+ 585278536, 1106219491, 444629203, 1099824661, 734821072, 2025557656,
+ 657473172, 255537853, 291983710, 286553905, 42517818, 670349676,
+ 870581336, 1127381655, 1839475352, 632654867, 547547534, 1471914002,
+ 1512583684, 890892484, 1857789058, 1587065657, 709203658, 1447182906,
+ 950862839, 1854232374, 1589606089, 18301536, 700074959, 415606342,
+ 1405416566, 1289157530, 1227135268, 340764183, 419122630, 1884968096,
+ 326246210, 540566661, 853062096, 1975701318, 1492562570, 1963382636,
+ 1075710563, 758982437, 2060895641, 1152739182, 1371354866, 800770398,
+ 1598945131, 79563287, 694771023, 1704620086, 248109047, 95128540,
+ 1062172273, 810095152, 2013227291, 1998220334, 1498632230, 1836447618,
+ 217773428, 986641406, 603013591, 1230144401, 1075426659, 1746848829,
+ 817629711, 186988432, 1484074762, 843442591, 776096924, 1024866700,
+ 2027642148, 1049701698, 247896996, 387855251, 857506062, 165410039,
+ 1748384075, 1958279260, 1593211160, 1998805368, 1633675306,
+ 2048559498, 1569149953, 1404385053, 784606841, 1589733669, 373455454,
+ 909199500, 1312922206, 408034973, 997233876, 963117498, 742951874,
+ 10752697, 574771227, 794412355, 92609016, 392712605, 964282276,
+ 1732686549)
+
+def make_turn(general, reginfo, commands):
+ """Generate complete TRN (turn) file"""
+ result = ''
+ # Player
+ result += struct.pack('< h', general['player'])
+ # No. of commands
+ result += struct.pack('< i', len(commands))
+ # Timestamp
+ result += general['timestamp_date'] + general['timestamp_time']
+ # Unused
+ result += struct.pack('< h', 0)
+ # Timestamp checksum
+ checksum_timestamp = get_checksum(general['timestamp_date'] +
+ general['timestamp_time'])
+ result += struct.pack('< h', checksum_timestamp)
+ # Include commands (if any)
+ if len(commands):
+ # Unused
+ result += '\x00'
+ # Build pointer + command blocks
+ pointers = ''
+ data = ''
+ for command in commands:
+ pointers += struct.pack('< i', len(data))
+ data += command
+ result += pointers + data
+ # Win-Plan style TRN trailer
+ result += _get_winplan_trailer(general['turn'], reginfo)
+ # DOS style TRN trailer follows
+ checksum_x = get_checksum(result) + (checksum_timestamp * 3) + 13
+ result += struct.pack('< i i', checksum_x, 0)
+ checksum = 0
+ for i in range(0, 25):
+ value = (ord(reginfo[0][i]) * (i+1) * 13)
+ result += struct.pack('< i', value)
+ checksum += value
+ for i in range(0, 25):
+ value = (ord(reginfo[1][i]) * (i+1) * 13)
+ result += struct.pack('< i', value)
+ checksum += value
+ result += struct.pack('< i', checksum + 668)
+ # ID block (checksum from TRN file for specific player)
+ for i in range(0, 11):
+ if i+1 == general['player']:
+ result += struct.pack('< i', checksum_x)
+ elif i+1 == 11: # Oddity when player isn't player 11
+ result += struct.pack('< i', int('0x0F31', 0))
+ else:
+ result += struct.pack('< i', 0)
+ return result
+
+def get_registration(serial=None, date=None):
+ """Returns registration data"""
+ if serial is None:
+ # Set shareware string
+ serial = 'VGA Planets shareware'
+ date = 'V3.5 for windows'
+ else:
+ serial = serial.encode('latin1')
+ date = date.encode('latin1')
+ return (serial.ljust(25), date.ljust(25),
+ CLIENT.ljust(50), URL.ljust(50))
+
+def _get_winplan_trailer(turn, reginfo):
+ """Assembles WinPlan-style TRN (turn) file trailer"""
+ result = SIGNATURE + SUBVERSION[1]
+ # VPH35.DLL values (encoded similarly as in PCC v2's GTurnfile::setRegInfo)
+ random.seed()
+ vph1 = VPH_MAGIC[turn % len(VPH_MAGIC)]
+ vph2 = random.randint(0, 65535)
+ vph2 |= random.randint(0, 65535)
+ vph1 ^= vph2
+ vph1 &= int('0x7FFFFFFF', 0)
+ vph2 &= int('0x7FFFFFFF', 0)
+ result += struct.pack('< i i', vph1, vph2)
+ # Registration info
+ serial_partb = ''
+ date_partb = ''
+ for i in range(0, 25):
+ serial_partb += chr(random.randint(0, 255))
+ date_partb += chr(random.randint(0, 255))
+ serial_parta = ''
+ date_parta = ''
+ for i in range(0, 25):
+ serial_parta += chr(ord(reginfo[0][i]) ^ ord(serial_partb[i]))
+ date_parta += chr(ord(reginfo[1][i]) ^ ord(date_partb[i]))
+ result += serial_parta + serial_partb + date_parta + date_partb
+ result += reginfo[2] + reginfo[3]
+ # Unused buffer of 100 bytes
+ result += '\x00'*100
+ return result
No newline at end of file