org &4000:limit &a400

;ATLANTIC II tape Speedlock buster
;(C) November 1990 John Girvin

nolist

.ink            defl 16   ;Ink to flash during loading
.stored_at      defl $    ;ORG address

.atlantic                 ;Enter here to start Atlantic
di

ld de,-&6eb
call e_sub_de
ld (&be88),hl

;Relocate code
ld ix,reloc_table

.reloc_loop
ld l,(ix+0)               ;HL=address of add ess to modify-1
ld h,(ix+1)

ld a,h                    ;Exit if finished (sensible, really)
or l
jr z,reloc_done

inc hl
push hl

ld e,(hl)                 ;DE=address to modify
inc hl
ld d,(hl)

ld hl,-stored_at
add hl,de
ld de,(&be88)
add hl,de
ex hl,de                  ;DE=modified address

pop hl
ld (hl),e
inc hl
ld (hl),d

inc ix
inc ix
jr reloc_loop

.reloc_done
ld hl,stored_at
ld de,(&be88)
ld bc,at_end-stored_at
ldir
.mod48:ld hl,ent
ld c,&ff
jp &bd16

;-------------------------------------------------------

.fourkeys       defb &1e,&2a,&28,&22 ;Info to load info file (?)

;-------------------------------------------------------

;The following is a (slightly patched) diassembly of the original Speedlock
;loading routine, as found after going through 3 million XOR loops (approx)

L491:   DEC   A
        JR    NZ,L491
        AND   A
L495:   INC   H
        RET   Z
        LD    B,&F5
        IN    A,(C)
        XOR   C
        AND   &80
        JR    Z,L495
        LD    B,&7F
        ld a,ink
        OUT   (C),A
        LD    A,C
        CPL   
        LD    C,A
        EXX   
        LD    A,L
        INC   A
        AND   &0F
        LD    L,A
        OR    &20
        EXX   
        RLA   
        OUT   (C),A
        SCF   
        RET   

L4B7:   DEC   A
        JR    NZ,L4B7
        AND   A

L4BB:   INC   H
        RET   Z
        LD    B,&F5
        IN    A,(C)
        XOR   C
        AND   &80
        JR    Z,L4BB
        LD    B,&7F
        ld a,ink
        OUT   (C),A
        LD    A,C
        CPL   
        LD    C,A
        RRA   
        LD    A,&2A
        RLA
        OUT   (C),A
        SCF   
        RET   

L4D7:   LD    B,&F6
        LD    A,&10      
        OUT   (C),A
        EXX   
        PUSH  HL
        LD    L,&00
        EXX   

.mod45: ld hl,L47F             ;Address of load error routine

        PUSH  HL
        LD    B,&F5
        IN    A,(C)
        AND   &80
        LD    C,A

L4ED:   call L491
        JR    NC,L4ED

        ld hl,&415
L4F5:   DJNZ  L4F5
        DEC   HL
        LD    A,H
        OR    L
        JR    NZ,L4F5
        LD    A,&0A
.mod33: call L491
        JR    NC,L4ED

L503:   LD    H,&C4
        LD    A,&1C
.mod34: call L491
        JR    NC,L4ED

        LD    A,&DA
        CP    H
        JR    C,L503

L511:   LD    H,&C4
        LD    A,&1C
.mod35: call L491
        JR    NC,L4ED
        LD    A,&DA
        CP    H
        JR    C,L503

L51F:   ld iy,fourkeys    ;Address of loading info. for info file

L523:   LD    L,(IY+&00)
L526:   LD    H,&C4
        LD    A,&1C
.mod36: call L491
        JR    NC,L4ED
        LD    A,&D7
        CP    H
        JR    NC,L511
        INC   L
        JR    NZ,L526
        LD    H,&70
        LD    A,&1C
.mod37: call L491
        JR    NC,L4ED
        LD    A,&1C
.mod38: call L491
        JR    NC,L4ED
        LD    A,H
        CP    &CD
        JR    NC,L55A
        CP    &9C
        JR    NC,L51F
        INC   IY

        defb &fd,&7d      ;LD A,YL
.fkmod  cp 0
        jr nz,L523

        JR    L51F

L55A:   LD    A,&0B
        LD    H,&80
        LD    L,&08
        LD    A,&0B
        JR    L566
L564:   LD    A,&09

L566:   call L4B7
        RET   NC
        LD    A,&0B
.mod39: call L4B7
        RET   NC
        LD    A,&9F
        CP    H
        RL    L
        LD    H,&80
.mod1:  jp nc,L564
        LD    A,&1D
        CP    L
.mod49: jp nz,loaderr            ;Load error/destruction jump
        NOP   
        XOR   A
        EX    AF,AF'
        LD    H,&A1
        LD    L,&01
.scrtab ld iy,0
        LD    A,&04
        JR    L5A6

L58F:   ld a,0
        XOR   L
.key2a  add 0
        LD    (IX+&00),A
        INC   IX
        DEC   DE
        LD    H,&A1
        LD    L,&01
        LD    L,&01
        LD    A,&01
        JR    L5A6
L5A4:   LD    A,&09

L5A6:   call L4B7
        RET   NC
L5A9:   LD    A,&0B
.mod40: call L4B7
        RET   NC
        LD    A,&C0
        CP    H
        RL    L
        LD    H,&A1
.mod2:  jp nc,L5A4

        EX    AF,AF'
        XOR   L
        EX    AF,AF'
        LD    A,D
        OR    E
        JR    NZ,L58F

L5C1:   jp L47B           ;Modyfied by the loader later on to jump to ".key1b"

.key1b  ld a,0            ;Key bytes to checksum the incoming data. These are
        XOR   L           ;usually loaded over with new values
.key2b  add 0

        LD    (IX+&00),A
        INC   IX
        DEC   DE
        LD    L,&02
        LD    A,&04
        LD    H,&B3
.mod41: call L641
        RET   NC
        LD    A,(IY+&04)
        OR    A
        JR    Z,L639

        LD    L,C
        LD    BC,&7F00
        NOP   
        NOP   
        NOP   
        LD    C,(IY+&00)
        LD    B,(IY+&01)
        ld ix,0
        ADD   IX,BC
        LD    C,L
        LD    A,&01
L5F5:   LD    L,&02
        LD    H,&B3
.mod42: call L641
        RET   NC
        ld a,&7f
        cp l
        jr z,L605
.stat1  ld (0),a
L605:   LD    L,&02
        LD    A,&08
        LD    H,&B3
.mod43: call L641
        RET   NC
        LD    E,(IY+&02)
        LD    D,(IY+&03)
        LD    L,C
        ld bc,5
        ADD   IY,BC
        LD    C,L
        LD    A,E
        OR    D
        LD    H,&A1
        LD    L,&01
        LD    A,&01
.mod3:  jp nz,L5A6

.atlan2 ld de,0           ;Redirect loader so it goes to 0 (or whatever) when
.mod47: ld (L5C1+1),de    ;the game has loaded (used to be L47B)
.mod46: ld de,L5A9
        PUSH  DE
.bm_mod ld de,(0)
.mod4:  jp L4BB

L639:   LD    A,&06
        NOP   
        NOP   
        JR    L5F5

L63F:   LD    A,&0D

L641:   call L4B7
        LD    A,&10
.mod44: call L4B7
        RET   NC
        LD    A,&DB
        CP    H
        RL    L
        LD    H,&B3
.mod5:  jp nc,L63F
        RET   

L655:   call L4D7         ;Enter here for loading bit
        LD    HL,&8000
        LD    B,&FF
L65D:   PUSH  BC
        LD    E,&00
        LD    C,E
        LD    D,&FF

L663:   LD    B,&F5
        IN    A,(C)
        AND   &80
        XOR   C
        JR    Z,L6BC
        INC   E
        LD    A,C
        CPL   
        AND   &80
        LD    C,A
L672:   DEC   D
.mod6:  jp nz,L663

        LD    (HL),E
        INC   HL
        POP   BC
        DJNZ  L65D
        ld hl,0
        LD    DE,&8032
        LD    B,&32
L683:   PUSH  BC
        LD    A,(DE)
        LD    B,&00
        LD    C,A
        ADD   HL,BC
        INC   DE
        POP   BC
        DJNZ  L683
        PUSH  HL
        ld hl,0
        LD    DE,&80CD
        LD    B,&32
L696:   PUSH  BC
        LD    A,(DE)
        LD    B,&00
        LD    C,A
        ADD   HL,BC
        INC   DE
        POP   BC
        DJNZ  L696
        POP   BC
        LD    A,H
        OR    A
        jr nz,stat2
        AND   A
        SBC   HL,BC
        ld bc,&32
        AND   A
        SBC   HL,BC
        RET   C
        ADD   HL,BC
        LD    BC,&FFCD
        AND   A
        SBC   HL,BC
        RET   NC
        inc a
.stat2  ld (0),a
        RET   

L6BC:   nop
        nop
.mod7   jp L672

L47B:   POP   DE          ;Comes here when loading is finished
        EX    AF,AF'
        cp 1
L47F:   LD    B,&7F       ;This is the load error routine
        ld a,ink
        OUT   (C),A
        LD    A,&54
        OUT   (C),A
        EXX   
        POP   HL
        EXX   
        RET   C           ;RET if no error
        EXX   
loaderr:jr loaderr        ;Inf. loop (no, really ?)

;-------------------------------------------------------

.ent                      ;The start of Atlantic itself
di
ld hl,(&be86)             ;HL=address to go to after loading (ie-addr of cheat
.mod8:ld (atlan2+1),hl    ;code)

ld de,-&10c               ;Beats me wot this address is used for, but you
.mod10:call e_sub_de      ;need it anyway !
.mod11:ld (bm_mod+2),hl

ld de,-&13e               ;Loading status store
.mod12:call e_sub_de
.mod13:ld (stat1+1),hl
.mod14:ld (stat2+1),hl

inc hl                    ;Move fourkeys
.mod15:ld (L51F+2),hl
ex hl,de
.mod16:ld hl,fourkeys
ld bc,4
ldir
ld a,e
.mod17:ld (fkmod+1),a

ld a,(&be82)              ;Key 1
.mod18:ld (L58F+1),a
.mod19:ld (key1b+1),a
ld a,(&be83)              ;Key 2
.mod20:ld (key2a+1),a
.mod21:ld (key2b+1),a

ld de,-&139
.mod22:call e_sub_de
push hl
pop ix
ld de,&c6                 ;Load information file & then patch it
.mod23:call L655

ld de,-&9f                ;Erase CALL to setinx routine
.mod24:call e_sub_de
ld (hl),0
inc hl
ld (hl),0
inc hl
ld (hl),&f3

ld de,-&91                ;Redirect loading CALL
.mod25:call e_sub_de
.mod28:ld de,key1b
ld (hl),e
inc hl
ld (hl),d

ld de,-&8e
.mod26:call e_sub_de
.mod27:ld de,L5C1+1
ld (hl),e
inc hl
ld (hl),d

ld de,-&8b
.mod29:call e_sub_de
.mod30:ld de,L4D7
ld (hl),e
inc hl
ld (hl),d

ld de,-&f1                ;Insert address for loading info. table
.mod31:call e_sub_de
ld de,(&be80)
.mod32:ld (scrtab+2),de
ld (hl),e
inc hl
ld (hl),d

dec hl                    ;Enter the loader
dec hl
dec hl
jp (hl)

.copyright
text &a4,"JWJG",&11,&90

.reloc_table
defw mod1,mod2,mod3,mod4,mod5,mod6,mod7,mod8
defw mod10,mod11,mod12,mod13,mod14,mod15,mod16,mod17,mod18,mod19
defw mod20,mod21,mod22,mod23,mod24,mod25,mod26,mod27,mod28,mod29
defw mod30,mod31,mod32+1,mod33,mod34,mod35,mod36,mod37,mod38,mod39
defw mod40,mod41,mod42,mod43,mod44,mod45,mod46,mod47+1,mod48,mod49
defw L4ED,L566,L5A6,L641,L655,L51F+1,L5C1
defw 0                    ;End marker

.e_sub_de
ld hl,(&be84)
add hl,de
ret

list
.at_end
nolist
