Unfortunately the CGA version is more difficult. It uses a custom packer; the main game content/logic seems to be in FILECODE.SQZ; and LOADER.EXE unpacks the actual EXE in memory. Since packers are quite difficult -- at least for me 😀 -- I gave up on this. md5 for FILECODE.SQZ is FD884F7A1B214C7AEFBAB75039DCE4E8.
If anyone wants to patch the VGA version but has a different executable. After some startup routines, there is a sequence of calls
55 push bp
8B EC mov bp, sp
83 EC 06 sub sp, 6
9A 0A 00 11 0B call sub_B11A ; -> this is the protection call
9A 11 04 09 11 call sub_114A1
9A DB 03 09 11 call sub_1146B
9A 45 03 09 11 call sub_113D5
9A 10 00 09 11 call sub_110A0
9A 6A 00 09 11 call sub_110FA
noping the call out doesn't work, as there is some self-modifying code-thing going on.
The function at sub_B11A actually looks similar to this:
sub_B11A proc far
50 push ax ; 0cfe:000a // cga:0bf0:000a
53 push bx
51 push cx
52 push dx
57 push di
56 push si
1E push ds
06 push es
55 push bp
FA cli <- some interrupt magic going on
33 C0 xor ax, ax
8E D8 mov ds, ax
assume ds:seg000
C7 06 04 00 D5 01 mov word ptr loc_3+1, offset byte_B2E5
8C 0E 06 00 mov word ptr loc_3+3, cs
9C pushf
58 pop ax
0D 00 01 or ax, 100h
50 push ax
9D popf
FB sti ; <- some interrupt magic going on
It looks like this game uses TurboC, which uses fastcall convention. So we can just immediately reutrn without worrying to mess with the stack (50 -> EB, i.e. return).
But what's happening between cli and then sti (resulting in an immediate interrupt and doing mad jumps around) is beyond me; this is why I am paranoid about this not being fully cracked.
I don't have old hardware, so it's difficult for me to understand how the game actually behaves with the actual protection running.