Skip to content

Commit

Permalink
Merge pull request #40 from skx/38-encryption
Browse files Browse the repository at this point in the history
Generate encrypted versions of the ZX Spectrum game
  • Loading branch information
skx authored Mar 28, 2024
2 parents 1342c8b + c1f0f8a commit e0f7076
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 34 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
game.com
lihouse.com
lihouse2.com
lighthouse
encrypt
*.tap
*.com
52 changes: 41 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ VERSION := $(or ${GITHUB_REF},${GITHUB_REF},"unreleased-git")

all: lighthouse game-cpm game-spectrum


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


# Build the encryption helper
encrypt: encrypt.c
gcc -o encrypt -Wall -Werror encrypt.c


# Format our C-code
format:
astyle --style=allman -A1 --indent=spaces=4 --break-blocks --pad-oper --pad-header --unpad-paren --max-code-length=200 *.c *.h
Expand All @@ -23,28 +30,51 @@ format:
version:
echo "DB \"$$(echo ${VERSION} | awk -F/ '{print $$NF}' )\"" > version.z80



# build the game for CP/M
game-cpm: game.z80 bios.z80 version Makefile
pasmo --equ ENTRYPOINT=100h --equ ENCRYPT_STRINGS=0 --equ SPECTRUM=0 game.z80 lihouse.com

# build the game for CP/M with encrypted strings/code
game-cpm-encrypted: game.z80 bios.z80 version Makefile encrypt
pasmo --equ ENTRYPOINT=100h --equ ENCRYPT_STRINGS=1 --equ SPECTRUM=0 game.z80 lihouse.com
./encrypt lihouse.com lihousex.com
rm lihouse.com



# build the game for the ZX Spectrum
game-spectrum: game.z80 bios.z80 version Makefile
pasmo --tapbas --equ ENTRYPOINT=32768 --equ ENCRYPT_STRINGS=0 --equ SPECTRUM=1 game.z80 lihouse.tap

# Build the encryption helper
encrypt: encrypt.c
gcc -o encrypt -Wall -Werror encrypt.c
# build the game for the ZX Spectrum with encrypted strings
game-spectrum-encrypted: game.z80 bios.z80 version Makefile encrypt
pasmo --tapbas --equ ENTRYPOINT=32768 --equ ENCRYPT_STRINGS=1 --equ SPECTRUM=1 game.z80 lihouse.tap
./encrypt -crc lihouse.tap lihousex.tap
rm lihouse.tap


# Build the game for release - with strings encrypted
release: game.z80 encrypt version
pasmo --equ ENTRYPOINT=100h --equ ENCRYPT_STRINGS=1 --equ SPECTRUM=0 game.z80 lihouse.com
./encrypt
mv lihouse2.com lihouse.com
release: version
make game-cpm-encrypted
make game-cpm
make game-spectrum-encrypted
make game-spectrum


# Run for CP/M
run-cpm: game
# Run the CP/M version via runcpm
run-cpm: game-cpm
~/cpm/cpm lihouse

run-spectrum:
xspect -quick-load -load-immed -tap *.tap
# Run the CP/M version via runcpm, with the encrypted version of the code
run-cpm-encrypted: game-cpm-encrypted
~/cpm/cpm lihouseX

# Run the spectrum version
run-spectrum: game-spectrum
xspect -quick-load -load-immed -tap lihouse.tap

# Run the spectrum version, with strings encrypted
run-spectrum-encrypted: game-spectrum-encrypted
xspect -quick-load -load-immed -tap lihousex.tap
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Quick links within this README file:
* [Bugs?](#bugs)



## Play Online

Thanks to the excellent [jsspeccy](https://github.com/gasman/jsspeccy3) ZX Spectrum emulator you can play this game with your browser here:</p>
Expand Down Expand Up @@ -88,27 +89,25 @@ defining `SPECTRUM`, and `ENTRYPOINT` as appropriate.
* 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.
* The Z80 version has more easter-eggs (Try typing "`xyzzy`" a few times).
* There are __two__ victory conditions.
* The CP/M version of the game can be built with the text-strings, and game code, protected by simple XOR encryption:
* The game can be built with the text-strings, and game code, protected by simple XOR encryption:
* This stops users from looking through the binary for hints.
* Run `make release` to build the _protected_ CP/M version.
* Run `make release` to build both "normal" and "protected" versions of the release.
* The encrypted versions of the games have an X suffix in their filenames.



## Compiling & Running It

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

Running `make` will generate the default targets:

* `make lighthouse` -> Build the game for linux.
* `make lihouse.com` -> Build the game for CP/M, without the XOR encryption.
* `make lihouse.tap` -> Build the game for the 48k ZX Spectrum.

If you wish to build only individual things then :
Running `make` will generate the default targets, if you wish to build only individual things then :

* `make game-cpm` to build a normal CP/M version.
* `make game-cpm-encrypted` to build an encrypted CP/M version.
* `make game-spectrum` to build the ZX Spectrum version.
* `make game-spectrum-encrypted` to build the encrypted ZX Spectrum version.
* `make lighthouse` will build the C-game for Linux
* `make release` will build the _protected_ CP/M version.
* `make release` will build both versions of the CP/M and ZX Spectrum release.



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

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



## Bugs?
Expand Down
131 changes: 121 additions & 10 deletions encrypt.c
Original file line number Diff line number Diff line change
@@ -1,47 +1,130 @@
/*
* Load `lihouse.com` and scramble the strings, saving to `lihouse2.com`.
* Generate an encrypted version of the specified input file.
*
* Optionally update the CRC check of the file - this is necessary
* for the .TAP version we generate for the ZX Spectrum.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

typedef unsigned char byte;


// calculate the checksum for the given region
byte crc(byte *start, int length)
{
byte tcrc = 0;

for (int i = 0; i < length; i++)
tcrc = tcrc ^ start[i];

return tcrc;
}

int main(int argc, char *argv[])
{
FILE *f = fopen("lihouse.com", "r");
// check argument count
if (argc != 3 && argc != 4)
{
printf("Usage: encrypt [-crc] input output\n");
return 1;
}

// flags / arguments
int do_crc = 0;
char *input = NULL;
char *output = NULL;

// look for flags
if (argc == 4)
{
// Should we run a CRC update?
for (int i = 1; i < argc ; i++)
{
if (strcmp(argv[i], "-crc") == 0)
{
do_crc = 1;
}
}
}

// look for input/output names.
for (int i = 1; i < argc ; i++)
{
// Ignore flags
if (strcmp(argv[i], "-crc") == 0)
{
continue;
}

// input file goes first
if (input == NULL)
{
input = argv[i];
continue;
}

// output file goes second.
if (output == NULL)
{
output = argv[i];
continue;
}
}

printf("Input file: %s\n", input);
printf("Output file: %s\n", output);

if (do_crc)
{
printf("CRC will be updated\n");
}
else
{
printf("No CRC update\n");
}

// Open the file for reading
FILE *f = fopen(input, "r");

if (f == NULL)
{
printf("Failed to open file\n");
return 0;
printf("Failed to open input file: %s\n", input);
return 1;
}

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

printf("File size is %ld bytes\n", sz);

// get back to start
fseek(f, 0L, SEEK_SET);

// allocate memory
char *buf = malloc(sz);
unsigned char *buf = malloc(sz);

if (buf == NULL)
{
printf("failed to allocate memory\n");
return 0;
return 1;
}

// read the file
int n = fread(buf, sizeof(char), sz, f);
int n = fread(buf, sizeof(unsigned char), sz, f);

if (ferror(f) != 0)
{
printf("error reading\n");
return 1;
}
if ( n != sz ) {

if (n != sz)
{
printf("short read\n");
return 1;
}
Expand All @@ -68,12 +151,40 @@ int main(int argc, char *argv[])
k++;
}

if (do_crc)
{
// Now we have to fixup the CRC
unsigned char *pos = buf;

for (int i = 1; i < sz; i++)
{
size_t blocksize = pos[0] | (pos[1] << 8);

if ((pos + blocksize + 1) < (buf + sz))
{
if (blocksize > 1)
{
char ccrc = crc(&pos[2], blocksize - 1);

if (pos[blocksize + 1] != ccrc)
{
printf("Updated CRC\n");
pos[blocksize + 1] = ccrc;
}
}
}


pos += blocksize + 2;
}
}

// Write
FILE *nw = fopen("lihouse2.com", "w");
FILE *nw = fopen(output, "w");

if (nw == NULL)
{
printf("Failed to open file for writing\n");
printf("Failed to open file for writing: %s\n", output);
}

fwrite(buf, sz, 1, nw);
Expand Down

0 comments on commit e0f7076

Please sign in to comment.