-
Notifications
You must be signed in to change notification settings - Fork 1
/
elite-checksum.py
154 lines (129 loc) · 4.15 KB
/
elite-checksum.py
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
#!/usr/bin/env python
#
# ******************************************************************************
#
# 6502 SECOND PROCESSOR ELITE CHECKSUM SCRIPT
#
# Written by Mark Moxon, and inspired by Kieran Connell's version for the
# cassette version of Elite
#
# This script applies encryption and checksums to the compiled binary for the
# main parasite game code. It reads the unencrypted "P.CODE.unprot.bin" binary
# and generates an encrypted version as "P.CODE", based on the code in the
# original "S.PCODES" BASIC source program
#
# ******************************************************************************
from __future__ import print_function
import sys
argv = sys.argv
encrypt = True
release = 2
for arg in argv[1:]:
if arg == "-u":
encrypt = False
if arg == "-rel1":
release = 1
if arg == "-rel2":
release = 2
if arg == "-rel3":
release = 3
print("6502SP Elite Checksum")
print("Encryption = ", encrypt)
# Configuration variables for scrambling code and calculating checksums
#
# Values must match those in 3-assembled-output/compile.txt
#
# If you alter the source code, then you should extract the correct values for
# the following variables and plug them into the following, otherwise the game
# will fail the checksum process and will hang on loading
#
# You can find the correct values for these variables by building your updated
# source, and then searching compile.txt for "elite-checksum.py", where the new
# values will be listed
if release == 1:
# Source disc variant
s = 0x106A # S%
g = 0x10D1 # G%
f = 0x81B0 # F%
elif release == 2:
# SNG45 variant
s = 0x106A # S%
g = 0x10D1 # G%
f = 0x818F # F%
elif release == 3:
# Executive variant
s = 0x106C # S%
g = 0x10D3 # G%
f = 0x82E7 # F%
# Load assembled code file for P.CODE
data_block = bytearray()
elite_file = open("3-assembled-output/P.CODE.unprot.bin", "rb")
data_block.extend(elite_file.read())
elite_file.close()
# Commander data checksum
if release == 1:
# Source disc
commander_start = 12 + 5
elif release == 2:
# SNG45
commander_start = 12 + 5
elif release == 3:
# Executive
commander_start = 14 + 5
commander_offset = 0x52
CH = 0x4B - 2
CY = 0
for i in range(CH, 0, -1):
CH = CH + CY + data_block[commander_start + i + 7]
CY = (CH > 255) & 1
CH = CH % 256
CH = CH ^ data_block[commander_start + i + 8]
print("Commander checksum = ", hex(CH))
data_block[commander_start + commander_offset] = CH ^ 0xA9
data_block[commander_start + commander_offset + 1] = CH
# First part: ZP routine, which sets the checksum byte at S%-1
s_checksum = 0x10
carry = 1
for x in range(0x10, 0xA0):
for y in [0] + list(range(255, 0, -1)):
i = x * 256 + y
s_checksum += data_block[i - 0x1000] + carry
if s_checksum > 255:
carry = 1
else:
carry = 0
s_checksum = s_checksum % 256
s_checksum ^= y
s_checksum = s_checksum % 256
sub = x + (1 - carry)
if sub > s_checksum:
s_checksum = s_checksum + 256 - sub
carry = 0
else:
s_checksum -= sub
carry = 1
s_checksum = s_checksum % 256
carry = 0
s_checksum = s_checksum % 256
s_checksum = s_checksum % 256
print("S%-1 checksum = ", s_checksum)
if encrypt:
data_block[s - 0x1000 - 1] = s_checksum % 256
# Second part: SC routine, which EORs bytes between &1300 and &9FFF
if encrypt:
for n in range(0x1300, 0xA000):
data_block[n - 0x1000] = data_block[n - 0x1000] ^ (n % 256) ^ 0x75
# Third part: V, which reverses the order of bytes between G% and F%-1
if encrypt:
f -= 1
while g < f:
tmp = data_block[g - 0x1000]
data_block[g - 0x1000] = data_block[f - 0x1000]
data_block[f - 0x1000] = tmp
g += 1
f -= 1
# Write output file for P.CODE
output_file = open("3-assembled-output/P.CODE.bin", "wb")
output_file.write(data_block)
output_file.close()
print("3-assembled-output/P.CODE.bin file saved")