Skip to content

Commit e0f7076

Browse files
authored
Merge pull request #40 from skx/38-encryption
Generate encrypted versions of the ZX Spectrum game
2 parents 1342c8b + c1f0f8a commit e0f7076

File tree

4 files changed

+175
-34
lines changed

4 files changed

+175
-34
lines changed

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
game.com
2-
lihouse.com
3-
lihouse2.com
41
lighthouse
52
encrypt
63
*.tap
4+
*.com

Makefile

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ VERSION := $(or ${GITHUB_REF},${GITHUB_REF},"unreleased-git")
55

66
all: lighthouse game-cpm game-spectrum
77

8+
89
# Build the C version
910
lighthouse: handlers.c inventory.c items.c main.c world.c util.c
1011
gcc -o lighthouse -Os -Wall -Wextra -Werror handlers.c inventory.c items.c main.c world.c util.c
@@ -14,6 +15,12 @@ lighthouse: handlers.c inventory.c items.c main.c world.c util.c
1415
clean:
1516
rm -f lighthouse *.com *.tap encrypt || true
1617

18+
19+
# Build the encryption helper
20+
encrypt: encrypt.c
21+
gcc -o encrypt -Wall -Werror encrypt.c
22+
23+
1724
# Format our C-code
1825
format:
1926
astyle --style=allman -A1 --indent=spaces=4 --break-blocks --pad-oper --pad-header --unpad-paren --max-code-length=200 *.c *.h
@@ -23,28 +30,51 @@ format:
2330
version:
2431
echo "DB \"$$(echo ${VERSION} | awk -F/ '{print $$NF}' )\"" > version.z80
2532

33+
34+
2635
# build the game for CP/M
2736
game-cpm: game.z80 bios.z80 version Makefile
2837
pasmo --equ ENTRYPOINT=100h --equ ENCRYPT_STRINGS=0 --equ SPECTRUM=0 game.z80 lihouse.com
2938

39+
# build the game for CP/M with encrypted strings/code
40+
game-cpm-encrypted: game.z80 bios.z80 version Makefile encrypt
41+
pasmo --equ ENTRYPOINT=100h --equ ENCRYPT_STRINGS=1 --equ SPECTRUM=0 game.z80 lihouse.com
42+
./encrypt lihouse.com lihousex.com
43+
rm lihouse.com
44+
45+
46+
3047
# build the game for the ZX Spectrum
3148
game-spectrum: game.z80 bios.z80 version Makefile
3249
pasmo --tapbas --equ ENTRYPOINT=32768 --equ ENCRYPT_STRINGS=0 --equ SPECTRUM=1 game.z80 lihouse.tap
3350

34-
# Build the encryption helper
35-
encrypt: encrypt.c
36-
gcc -o encrypt -Wall -Werror encrypt.c
51+
# build the game for the ZX Spectrum with encrypted strings
52+
game-spectrum-encrypted: game.z80 bios.z80 version Makefile encrypt
53+
pasmo --tapbas --equ ENTRYPOINT=32768 --equ ENCRYPT_STRINGS=1 --equ SPECTRUM=1 game.z80 lihouse.tap
54+
./encrypt -crc lihouse.tap lihousex.tap
55+
rm lihouse.tap
56+
3757

3858
# Build the game for release - with strings encrypted
39-
release: game.z80 encrypt version
40-
pasmo --equ ENTRYPOINT=100h --equ ENCRYPT_STRINGS=1 --equ SPECTRUM=0 game.z80 lihouse.com
41-
./encrypt
42-
mv lihouse2.com lihouse.com
59+
release: version
60+
make game-cpm-encrypted
61+
make game-cpm
62+
make game-spectrum-encrypted
63+
make game-spectrum
4364

4465

45-
# Run for CP/M
46-
run-cpm: game
66+
# Run the CP/M version via runcpm
67+
run-cpm: game-cpm
4768
~/cpm/cpm lihouse
4869

49-
run-spectrum:
50-
xspect -quick-load -load-immed -tap *.tap
70+
# Run the CP/M version via runcpm, with the encrypted version of the code
71+
run-cpm-encrypted: game-cpm-encrypted
72+
~/cpm/cpm lihouseX
73+
74+
# Run the spectrum version
75+
run-spectrum: game-spectrum
76+
xspect -quick-load -load-immed -tap lihouse.tap
77+
78+
# Run the spectrum version, with strings encrypted
79+
run-spectrum-encrypted: game-spectrum-encrypted
80+
xspect -quick-load -load-immed -tap lihousex.tap

README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Quick links within this README file:
1919
* [Bugs?](#bugs)
2020

2121

22+
2223
## Play Online
2324

2425
Thanks to the excellent [jsspeccy](https://github.com/gasman/jsspeccy3) ZX Spectrum emulator you can play this game with your browser here:</p>
@@ -88,27 +89,25 @@ defining `SPECTRUM`, and `ENTRYPOINT` as appropriate.
8889
* Along the way I realized that having fixed inventory slots made the coding more of a challenge, so I made the location of each object a property of the object itself.
8990
* The Z80 version has more easter-eggs (Try typing "`xyzzy`" a few times).
9091
* There are __two__ victory conditions.
91-
* The CP/M version of the game can be built with the text-strings, and game code, protected by simple XOR encryption:
92+
* The game can be built with the text-strings, and game code, protected by simple XOR encryption:
9293
* This stops users from looking through the binary for hints.
93-
* Run `make release` to build the _protected_ CP/M version.
94+
* Run `make release` to build both "normal" and "protected" versions of the release.
95+
* The encrypted versions of the games have an X suffix in their filenames.
96+
9497

9598

9699
## Compiling & Running It
97100

98101
Ensure you have the `pasmo` assembler installed, and then use the supplied Makefile to compile the game.
99102

100-
Running `make` will generate the default targets:
101-
102-
* `make lighthouse` -> Build the game for linux.
103-
* `make lihouse.com` -> Build the game for CP/M, without the XOR encryption.
104-
* `make lihouse.tap` -> Build the game for the 48k ZX Spectrum.
105-
106-
If you wish to build only individual things then :
103+
Running `make` will generate the default targets, if you wish to build only individual things then :
107104

108105
* `make game-cpm` to build a normal CP/M version.
106+
* `make game-cpm-encrypted` to build an encrypted CP/M version.
109107
* `make game-spectrum` to build the ZX Spectrum version.
108+
* `make game-spectrum-encrypted` to build the encrypted ZX Spectrum version.
110109
* `make lighthouse` will build the C-game for Linux
111-
* `make release` will build the _protected_ CP/M version.
110+
* `make release` will build both versions of the CP/M and ZX Spectrum release.
112111

113112

114113

@@ -117,7 +116,10 @@ If you wish to build only individual things then :
117116
If you look on our [release page](https://github.com/skx/lighthouse-of-doom/releases/) you can find the latest stable build.
118117

119118
* For CP/M download `lihouse.com` to your system, and then run `LIHOUSE` to launch it.
119+
* `lihousex.com` is the encrypted version.
120120
* For the ZX Spectrum download `lihouse.tap` to your system, and then launch in your favourite emulator.
121+
* `lihousex.tap` is the encrypted version.
122+
121123

122124

123125
## Bugs?

encrypt.c

Lines changed: 121 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,130 @@
11
/*
2-
* Load `lihouse.com` and scramble the strings, saving to `lihouse2.com`.
2+
* Generate an encrypted version of the specified input file.
3+
*
4+
* Optionally update the CRC check of the file - this is necessary
5+
* for the .TAP version we generate for the ZX Spectrum.
36
*/
47

58
#include <stdio.h>
69
#include <stdlib.h>
710
#include <string.h>
811
#include <malloc.h>
912

13+
typedef unsigned char byte;
14+
15+
16+
// calculate the checksum for the given region
17+
byte crc(byte *start, int length)
18+
{
19+
byte tcrc = 0;
20+
21+
for (int i = 0; i < length; i++)
22+
tcrc = tcrc ^ start[i];
23+
24+
return tcrc;
25+
}
26+
1027
int main(int argc, char *argv[])
1128
{
12-
FILE *f = fopen("lihouse.com", "r");
29+
// check argument count
30+
if (argc != 3 && argc != 4)
31+
{
32+
printf("Usage: encrypt [-crc] input output\n");
33+
return 1;
34+
}
35+
36+
// flags / arguments
37+
int do_crc = 0;
38+
char *input = NULL;
39+
char *output = NULL;
40+
41+
// look for flags
42+
if (argc == 4)
43+
{
44+
// Should we run a CRC update?
45+
for (int i = 1; i < argc ; i++)
46+
{
47+
if (strcmp(argv[i], "-crc") == 0)
48+
{
49+
do_crc = 1;
50+
}
51+
}
52+
}
53+
54+
// look for input/output names.
55+
for (int i = 1; i < argc ; i++)
56+
{
57+
// Ignore flags
58+
if (strcmp(argv[i], "-crc") == 0)
59+
{
60+
continue;
61+
}
62+
63+
// input file goes first
64+
if (input == NULL)
65+
{
66+
input = argv[i];
67+
continue;
68+
}
69+
70+
// output file goes second.
71+
if (output == NULL)
72+
{
73+
output = argv[i];
74+
continue;
75+
}
76+
}
77+
78+
printf("Input file: %s\n", input);
79+
printf("Output file: %s\n", output);
80+
81+
if (do_crc)
82+
{
83+
printf("CRC will be updated\n");
84+
}
85+
else
86+
{
87+
printf("No CRC update\n");
88+
}
89+
90+
// Open the file for reading
91+
FILE *f = fopen(input, "r");
1392

1493
if (f == NULL)
1594
{
16-
printf("Failed to open file\n");
17-
return 0;
95+
printf("Failed to open input file: %s\n", input);
96+
return 1;
1897
}
1998

2099
// get file size
21100
fseek(f, 0L, SEEK_END);
22101
size_t sz = ftell(f);
23102

103+
printf("File size is %ld bytes\n", sz);
104+
24105
// get back to start
25106
fseek(f, 0L, SEEK_SET);
26107

27108
// allocate memory
28-
char *buf = malloc(sz);
109+
unsigned char *buf = malloc(sz);
29110

30111
if (buf == NULL)
31112
{
32113
printf("failed to allocate memory\n");
33-
return 0;
114+
return 1;
34115
}
35116

36117
// read the file
37-
int n = fread(buf, sizeof(char), sz, f);
118+
int n = fread(buf, sizeof(unsigned char), sz, f);
38119

39120
if (ferror(f) != 0)
40121
{
41122
printf("error reading\n");
42123
return 1;
43124
}
44-
if ( n != sz ) {
125+
126+
if (n != sz)
127+
{
45128
printf("short read\n");
46129
return 1;
47130
}
@@ -68,12 +151,40 @@ int main(int argc, char *argv[])
68151
k++;
69152
}
70153

154+
if (do_crc)
155+
{
156+
// Now we have to fixup the CRC
157+
unsigned char *pos = buf;
158+
159+
for (int i = 1; i < sz; i++)
160+
{
161+
size_t blocksize = pos[0] | (pos[1] << 8);
162+
163+
if ((pos + blocksize + 1) < (buf + sz))
164+
{
165+
if (blocksize > 1)
166+
{
167+
char ccrc = crc(&pos[2], blocksize - 1);
168+
169+
if (pos[blocksize + 1] != ccrc)
170+
{
171+
printf("Updated CRC\n");
172+
pos[blocksize + 1] = ccrc;
173+
}
174+
}
175+
}
176+
177+
178+
pos += blocksize + 2;
179+
}
180+
}
181+
71182
// Write
72-
FILE *nw = fopen("lihouse2.com", "w");
183+
FILE *nw = fopen(output, "w");
73184

74185
if (nw == NULL)
75186
{
76-
printf("Failed to open file for writing\n");
187+
printf("Failed to open file for writing: %s\n", output);
77188
}
78189

79190
fwrite(buf, sz, 1, nw);

0 commit comments

Comments
 (0)