LST OFF ORG $1F00 USE EDD.PAGE0 USE EDD.ROM ******************************** * * * ESSENTIAL DATA DUPLICATOR * * VERSION 4.8 STANDARD/PLUS * * 6502 ASSEMBLY SOURCE CODE * * COPYRIGHT (C) 1987 * * ALL RIGHTS RESERVED * * UTILICO MICROWARE * * DONALD ANTHONY SCHNAPP * * PRINTED OCTOBER 28, 1987 * * * ******************************** * 2008/02/10 - Deckard * Steps of the anti-Wildcard protection scheme: * * (1) During the boot 2 process of the original disk, call * a routine (H1F0F) which captures computer informations * (disk II cards mapping, computer model, slot 3 and ram). * These datas are stored in memory and are used as * reference. * * (2) A pirate uses his copy board and takes a snapshot * of EDD when the program is loaded and the menu * displayed on the screen. * He creates a bootable resurrect disk also called * a wildcard bootstrap disk (to have a 16 sectors disk * he can easily copy with tools such as Locksmith Fast * Copy, Disk Muncher, ...) * And he gives copies to his friends. Copies don't * have anymore the original boot 2 (which is lost). * * (3) A friend boots up one copy. And he has a different * apple II configuration. * * (4) EDD has traps: it checks (comparaison) that the * current computer informations are equal to the * stored datas (boot 2 references). If 1 difference * is found, EDD knows that the running program isn't * an original disk and a crash occurs. * The entry point of the check routine is H1F0C and * is called CHECKMEM. *------------------------------- ZEROPAGE_PGM EQU $0080 ; location of program in zero page BEGPAGE2 EQU $0800 ; beginning of text page 2 BEGSPRSE EQU $0C00 ; byte after text page 2 (sparse) *------------------------------- H1F00 LDA $72 ; code not used??? LDY #$34 JSR H2036 LDY $18 JSR GET_MACH_INFO *------------------------------- * Check the current computer *------------------------------- H1F0C CHECKMEM JMP DO_CHECKMEM *------------------------------- * Capture computer informations * (called by EDD's boot2) *------------------------------- EDD_CCI H1F0F JSR SEARCH_DISKII ; get disk II map STA H1F0F+1 ; NOW KILL THE JSR (=hide the call) with the ; retrieved value ; after that: H1F0F JSR $1F40 ; ($1F10) = $40 <=> slot 6 STA DISKII_MAP ; store disk II mapping H1F18 JSR GET_MI_IN_ZP ; put the GET_MACH_INFO routine in zero page STY H1F18+1 ; NOW KILL THE JSR (=hide the call) ; after that: H1F18 JSR $1F80 JSR ZEROPAGE_PGM ; exec GET_MACH_INFO (store ref values) STX $90 STX H2036+1 ; hide the BOOT_ROM_ID location RTS *------------------------------- * Exec check memory routine *------------------------------- DO_CHECKMEM JSR SEARCH_DISKII ; get disk II mapping CMP DISKII_MAP ; same as boot process? BNE PIRATE ; no => pirate!!! ; Y=$80 JSR CMP_MI_IN_ZP ; copy check routine in zero page JSR ZEROPAGE_PGM ; exec check routine and get flag result BCS PIRATE ; not the same values => pirate!!! * Kill 1st page of bank 2 * WHY TO DO THAT HERE???? Not clear... * Is it really the original code??? LDA $C083 ; read/write bank 2 LDA $C083 LDY #0 H1F3F TYA STA $D000,Y ; $D000-$D0FF filled with increasing values INY BNE H1F3F LDA $C082 ; rom only RTS RTS H1F4B PIRATE LDA $C082 ; rom only NOP ; was DFB $02 <=> CRASH (EDD 4.2 crack only) ; replaced by NOP in cracked version (=no crash but ; run the SEARCH_DISK II again) *------------------------------- * Slotscan : search for disk II * controller *------------------------------- * Out: acc = disk II map (0, 1 or more cards) * 00000000 = no card * If only 1 card (otherwise ORA values) * 00000010 = slot 1 * 00000100 = slot 2 * 00001000 = slot 3 * 00010000 = slot 4 * 00100000 = slot 5 * 01000000 = slot 6 * 10000000 = slot 7 * Y = $80 H1F4F SEARCH_DISKII LDA #>$C700 ; high : begin with slot 7 STA W1H LDA #<$C700 ; low ($00) STA W1L STA DISKII_ROMID ; init map * Search for a disk II interface card * <=> check 4 bytes id H1F5A LDY #7 ; Y=[7,5,3,1] H1F5C LDA (W1L),Y CMP DISKII_ROMID,Y ; check rom byte BNE H1F7A ; not a disk II controller ; byte ok DEY ; check another 1 DEY BPL H1F5C ; continue checking... ; ok disk II controller found LDA W1H ; $Cslot AND #%00000111 ; get slot [1,7] TAY ; in Y register LDA #1 ; init mask BNE H1F71 ; always H1F70 ASL ; shift byte according to Y reg H1F71 DEY BPL H1F70 ; >=0 ORA DISKII_ROMID ; if more than 1 disk II card STA DISKII_ROMID ; set map *------------------------------- H1F7A DEC W1H ; previous slot LDA W1H CMP #$C0 ; is it slot 0? H1F80 BNE H1F5A ; no, do this slot ; no disk II controller in slot 0!!! ; end of scan LDA DISKII_ROMID ; retrieve disk II map RTS *------------------------------- * Disk II controller rom id *------------------------------- H1F86 DISKII_ROMID HEX 40 HEX 20 ; $Cn01 (LDX #$20) HEX FF HEX 00 ; $Cn03 (LDY #$00) DISKII_MAP DFB %01000000 ; =disk II in slot 6 HEX 03 ; $Cn05 (LDX #$03) HEX FF HEX 3C ; $Cn07 (STX $3C) *------------------------------- * Machine Id *------------------------------- * Contains the values when an ORIGINAL * EDD is booted. * EDD 4.2 crack: values= $77 $77 $77 * EDD 4.9 crack: values= $EA $77 $00 * SST : values= $06 $00 $81 BOOT_ROM_ID HEX 06 ; initial ROM_VERSION ; $06 = apple IIe or //c or IIGS ; $38 = apple ][ ; $EA = ][+ or /// (emulation) BOOT_SC3ROM HEX 00 ; initial SLOTC3ROM BOOT_RAM HEX 81 ; initial ram status ; bit 0 [0=48k, 1=64k] ; bit 7 [0=no aux, 1=aux] ; $81 = aux ram & 64k (or more) *------------------------------- * Put GET_MACH_INFO in zero page *------------------------------- GET_MI_IN_ZP LDA #>GET_MACH_INFO LDX #CMP_MACH_INFO LDX # pirate!!! CMP #$06 ; rom version $06 (IIe or //c or IIGS)? BNE H1FFE ; no: ][, ][+ or /// (emulation) ; default for these machines is "no aux ram" * IIe or //c or IIGS * * Check card in auxiliary slot * LDA $C017 ; read SLOTC3ROM AND #%10000000 ; keep bit 7 CMP BOOT_SC3ROM ; check original SLOTC3ROM BNE SET_PIRATE ; no=> pirate!!! TAY BMI H1FFE ; bit 7=1 => card in slot 3 (use it, no aux) ; bit 7=0 => use card in aux slot * Aux mem or not? ; main(BEGSPRSE) LDA BEGSPRSE ; same content in princ and aux mem? STA AUXREAD STA AUXWRT CMP BEGSPRSE ; compare with value written by GET_MACH_INFO!!! * Aux : main(BEGSPRSE)=aux(BEGSPRSE) IF ORIGINAL DISK * or 128k resurrect disk BEQ H1FEF ; aux memory * >> No aux mem << TAY ; save it EOR #$FF CMP BEGSPRSE ; try the eored value BNE SET_PIRATE ; ha ha ha, got you CMP BEGPAGE2 * No aux: BEGPAGE2 = BEGSPRSE BNE SET_PIRATE ; you're dead man!!! STY BEGPAGE2 CPY BEGSPRSE * No aux: test mirror effect BNE SET_PIRATE ; doesn't work -> killed!! STA BEGPAGE2 SEC BCS H1FF8 ; always * >> Aux mem << H1FEF EOR #$FF CMP BEGPAGE2 * Aux: main(BEGSPRSE) = aux(BEGPAGE2) EOR #$FF BNE SET_PIRATE LDX #$80 ; prepare mask for comparaison (aux set in flag) H1FF8 STA MAINREAD ; R/W main STA MAINWRT * * Check language card * * Compare page filled with increasing values written by * boot 2 process H1FFE LDA $C080 ; read bank 2 LDY #$00 H2003 TYA CMP $D000,Y BNE H200C ; no language card -> acc=0 INY BNE H2003 ; beq H200C PHP ; save result LDA $C082 ; rom TXA ; retrieve bit 7 (flag) PLP ; retrieve result BNE H2016 ; no language card ORA #$01 ; 64k H2016 CMP BOOT_RAM ; compare with ref BNE SET_PIRATE ; no wildcard allowed with different config!!! CLC ; original disk! RTS SET_PIRATE SEC ; PIRATE!!! STA MAINREAD STA MAINWRT RTS *------------------------------- * Get apple II informations * (boot 2, original EDD disk) *------------------------------- ; ORG $0080 GET_MACH_INFO STA MAINREAD ; R/W main STA MAINWRT LDA $C082 ; rom only LDA #$00 ; default=48k STA BOOT_RAM LDA ROM_VERSION ; get apple II model H2036 STA BOOT_ROM_ID ; after killing STX: STA H1F80 CMP #$06 ; apple IIe or //c or IIGS? BNE H206D ; no: ][ or ][+ or /// (emulation). No aux ram. * IIe or //c or IIGS LDA $C017 ; read SLOTC3ROM AND #%10000000 ; keep only bit 7 STA BOOT_SC3ROM ; save reference BMI H206D ; bit 7=1 : a card located in slot 3 (use it, no aux) * * Check the ram card in auxiliary slot. * * Run in the safe aera not affected by bank-switching * the main and aux ram (=zero page). * * Read Apple II Technical Notes MISC#2: * * "Stores a value at $0800 and sees if the same value * appears at $0C00. If so, no auxiliary memory is * present (the non-extended 80-column card has sparse * memory mapping which causes $0800 and $0C00 to be the * same location". * * TESTS: * ===== * * >>>>> If no aux mem (mirror $0800/$0C00) *
* BEGSPRSE = acc * BEGPAGE2 = acc * BEGPAGE2 = acc EOR #$FF (mirror=>BEGSPRSE=acc EOR #$FF) * and BEGSPRSE = BEGPAGE2 * * >>>>> If aux mem *
* BEGSPRSE = acc * BEGPAGE2 = acc * BEGSPRSE = acc * BEGPAGE2 = acc EOR #$FF * and BEGSPRSE <> BEGPAGE2 in aux * * Summary: * * => No aux mem * BEGPAGE2 = BEGSPRSE * * => Aux mem * main(BEGSPRSE) = main(BEGPAGE2) * aux (BEGSPRSE) <> aux (BEGPAGE2) * main(BEGSPRSE) = aux (BEGSPRSE) * main(BEGPAGE2) = aux (BEGPAGE2) EOR #$FF LDA BEGSPRSE STA BEGPAGE2 STA AUXREAD ; switch on if there is an aux memory STA AUXWRT STA BEGSPRSE LDX #%10000000 ; init aux flag EOR #$FF ; alter value STA BEGPAGE2 CMP BEGSPRSE STA MAINREAD ; R/W main STA MAINWRT BNE H206A ; aux mem detected LDX #$00 ; no aux H206A STX BOOT_RAM * * Test for presence of language card (48k=no, 64k=yes) * H206D LDA $C083 ; force in language card LDA $C083 ; bank 2 LDY #0 ; fill a page with increasing values H2075 TYA STA $D000,Y ; $D000=$00, $D001=$01, ..., $D0FF=$FF INY BNE H2075 ; Y=0 ; and now compare that the value are always here H207C TYA CMP $D000,Y BNE H2085 ; not same value => 48k INY ; continue: test the full page BNE H207C ; beq H2085 PHP ; save result LDA $C082 ; rom PLP ; retrieve result BNE H2094 ; read and write different => no language card LDA #%00000001 ; 64k ORA BOOT_RAM ; mix with aux bit STA BOOT_RAM ; store result H2094 RTS DS \,0 SAV OBJ/DECKARD/EDD.CHECKMEM