This is the actual call into the protection check:
JSR init_aes_window
TST.W D0
BGE aes_ok
MOVEQ #-1,D0
BRA init_screen_return
aes_ok:JSR check_copy_protection
MOVE.W D0,protection_flag
CLR.W (A7)
MOVE.L #str_midimaze_d8a,-(A7)
MOVE.W #$3D,-(A7) ; Fopen("MIDIMAZE.D8A", 0)
JSR _gemdos
It is tested later and disables the multi-player game:
check protection in a different place later
TST.W protection_flag
BNE protOK
MOVE.W #-2,machines_online
MOVE.W #-2,all_players
protOK:
The protection of Midi Maze is quite simple, but effective: Track 0, Sector 0 on Side 0 is read twice and while the first 6 bytes have to contain ‘100004’, the rest of the sector has to change between these two reads. This is done via “weak” or “fuzzy” bits on the disk. Interestingly a patch of the Floprd() function could defeat the protection easily, however because there is no further checksums or encryption replacing the beginning of check_copy_protection
with ST D0; RTS
will be more efficient. This was also exactly the patch that was done on a Karstadt Public-Domain disk with an official version of MIDIMAZE on it!
check_copy_protection:
MOVEM.L A0-A6/D1-D7,-(A7)
MOVEQ #2,D6 ;test drive A and B
MOVEQ #2,D5 ;read the sector twice
MOVE.W #$19,-(A7) ;DGETDRV
TRAP #1
ADDQ.W #2,A7
MOVE.W D0,D7
CMPI.W #2,D7
BLT.S check_copy_protection_rd_loop
CLR.W D7 ;if loaded from harddisk, search drive A
check_copy_protection_rd_loop:
MOVE.W #1,-(A7) ;1 sector
CLR.W -(A7) ;Side 0
CLR.W -(A7) ;Track 0
CLR.W -(A7) ;Sector 0
MOVE.W D7,-(A7) ;drive
CLR.L -(A7) ;reserved
PEA check_copy_protection_buffer
MOVE.W #8,-(A7) ;FLOPRD
TRAP #14
ADDA.W #20,A7
TST.W D0 ;E_OK
BEQ.S check_copy_protection_verify
CMP.W #-4,D0 ;E_CRC
BEQ.S check_copy_protection_verify
check_copy_protection_rd_retry:
SUBQ.W #1,D6 ;out of tries?
BEQ.S check_copy_protection_fail ;=> protection fail
MOVEQ #2,D5 ;read the sector twice (again)
; try the potentially other floppy drive
ADDQ.W #1,D7 ;try reading drive B
CMPI.W #2,D7 ;reached C?
BNE.S check_copy_protection_rd_loop
CLR.W D7 ;then try drive A
BRA.S check_copy_protection_rd_loop
check_copy_protection_fail:
CLR.W D0 ;fail
BRA.S check_copy_protection_return
DC.B 'RMP V1.00 31-July-86'
check_copy_protection_verify:
CLR.W D0
; first: compare the first 6 bytes for identity
LEA check_copy_protection_buffer,A0
LEA check_copy_protection_magic,A1
CMPM.L (A0)+,(A1)+
BNE.S check_copy_protection_rd_retry
CMPM.W (A0)+,(A1)+
BNE.S check_copy_protection_rd_retry
; count the number of set bits in the remaining 506 bytes
MOVE.W #505,D1
check_copy_protection_byteloop:
MOVEQ #7,D2
MOVE.B (A0)+,D3
check_copy_protection_bitloop:
ASR.W #1,D3
BCC.S check_copy_protection_bitloop2
ADDQ.W #1,D0
check_copy_protection_bitloop2:
DBF D2,check_copy_protection_bitloop
DBF D1,check_copy_protection_byteloop
SUBQ.W #1,D5 ;already read twice?
BEQ.S check_copy_protection_check ;yes! => compare the bitcounter
MOVE.W D0,D4 ; save the number of bits
BRA check_copy_protection_rd_loop ;read sector again
check_copy_protection_check:
SUB.W D4,D0 ;same number of bits set?
BEQ.S check_copy_protection_rd_retry ;=> that is a fail!
ST D0 ;bitcounter change => success
check_copy_protection_return:
MOVEM.L (A7)+,A0-A6/D1-D7
RTS
check_copy_protection_buffer:
DCB.B 512,0
ALIGN 4
check_copy_protection_magic:
DC.B '100004'