Atari ST Book: ROM disk listing

Commented assembly listing for the ROM disk in an Atari ST-Book. Also available on GitHub.

***
*  Half the ST Book ROM contains a ROM disk, which is mapped as drive 'P' into GEMDOS
***
$e40000 : abcd ef42                STBOOK_EXTROM:DC.L    $abcdef42

$e40004 : 00e4 0200                CA_NEXT:    DC.L      CA2_NEXT                   ; pointer to next application
$e40008 : 08e4 0026                CA_INIT:    DC.L      ROMDISK_CODE
$e4000c : 00e4 0026                CA_RUN:     DC.L      ROMDISK_CODE
$e40010 : 1776                     CA_TIME:    DC.W      $1776
$e40012 : 69b6                     CA_DATE:    DC.W      $69b6
$e40014 : 0000 016c                CA_SIZE:    DC.L      $0000016c
$e40018 : 424f 4f4b 524f 4d2e 5052+CA_NAME:    DC.B      'BOOKROM.PRG',0
$e40024 : ffff                                 DC.W      $ffff

$e40026 : 601a                     ROMDISK_CODE:bra.s    ROMDISK_INIT              ; PRG_magic
$e40028 : 0000 014c                            DC.L      $0000014c                 ; PRG_tsize
$e4002c : 0000 0000                            DC.L      $00000000                 ; PRG_dsize
$e40030 : 0000 0000                            DC.L      $00000000                 ; PRG_bsize
$e40034 : 0000 0000                            DC.L      $00000000                 ; PRG_ssize
$e40038 : 0000 0000                            DC.L      $00000000                 ; PRG_res1
$e4003c : 0000 0000                            DC.L      $00000000                 ; PRGFLAGS
$e40040 : 0000                                 DC.W      $0000                     ; ABSFLAG

$e40042 : 303c 00fc                ROMDISK_INIT:move.w   #252,d0                   ; 252kb ROMDISK
$e40046 : 31fc 0200 0800                       move.w    #512,(ROMDISK_BPB).w      ; 512 bytes per sector
$e4004c : 31fc 0001 0802                       move.w    #1,(ROMDISK_BPB+2).w      ; 1 sector per cluster
$e40052 : 31fc 0200 0804                       move.w    #512,(ROMDISK_BPB+4).w    ; 512 bytes per cluster
$e40058 : 31fc 0001 0806                       move.w    #1,(ROMDISK_BPB+6).w      ; sector length of root directory
$e4005e : 31fc 0001 0810                       move.w    #1,(ROMDISK_BPB+16).w     ; 16 bit FAT
$e40064 : e340                                 asl.w     #1,d0
$e40066 : 3200                                 move.w    d0,d1
$e40068 : 31c1 080e                            move.w    d1,(ROMDISK_BPB+14).w     ; 504 clusters per disk
$e4006c : d27c 00ff                            add.w     #$ff,d1
$e40070 : e041                                 asr.w     #8,d1
$e40072 : 31c1 0808                            move.w    d1,(ROMDISK_BPB+8).w      ; 2 sectors per FAT
$e40076 : 31c1 080a                            move.w    d1,(ROMDISK_BPB+10).w     ; starting sector of second FAT = 2
$e4007a : 31c1 080c                            move.w    d1,(ROMDISK_BPB+12).w     ; starting sector of data = 2*2+1 = 5
$e4007e : d378 080c                            add.w     d1,(ROMDISK_BPB+12).w
$e40082 : 0678 0001 080c                       addi.w    #1,(ROMDISK_BPB+12).w

$e40088 : 303c 000f                            move.w    #15,d0                    ; ROMDISK is drive P
$e4008c : 7e01                                 moveq     #1,d7
$e4008e : e1af                                 lsl.l     d0,d7
$e40090 : 8fb8 04c2                            or.l      d7,(_drvbits).w           ; enable drive

$e40094 : 21f8 0472 0816                       move.l    (hdv_bpb).w,(ROMDISK_HDV_BPB).w
$e4009a : 21f8 0476 081a                       move.l    (hdv_rw).w,(ROMDISK_HDV_RW).w
$e400a0 : 21f8 047e 081e                       move.l    (hdv_mediach).w,(ROMDISK_HDV_MEDIACH).w

$e400a6 : 41fa 0024                            lea       ROMDISK_BPB(pc),a0
$e400aa : 21c8 0472                            move.l    a0,(hdv_bpb).w
$e400ae : 41fa 002c                            lea       ROMDISK_RW(pc),a0
$e400b2 : 21c8 0476                            move.l    a0,(hdv_rw).w
$e400b6 : 41fa 0034                            lea       ROMDISK_MEDIACH(pc),a0
$e400ba : 21c8 047e                            move.l    a0,(hdv_mediach).w

$e400be : 487a 00ae                            pea       ROMDISK_insttext(pc)
$e400c2 : 3f3c 0009                            move.w    #9,-(sp)
$e400c6 : 4e41                                 trap      #1
$e400c8 : 5c4f                                 addq.w    #6,sp
$e400ca : 4e75                                 rts

$e400cc : 302f 0004                ROMDISK_BPB:move.w    4(sp),d0
$e400d0 : 2078 0816                            movea.l   (ROMDISK_HDV_BPB).w,a0
$e400d4 : 43fa 002e                            lea       ROMDISK_BPB_IMP(pc),a1
$e400d8 : 6000 001e                            bra       ROMDISK_CHKDRV
$e400dc : 302f 000e                ROMDISK_RW: move.w    $e(sp),d0
$e400e0 : 2078 081a                            movea.l   (ROMDISK_HDV_RW).w,a0
$e400e4 : 43fa 0026                            lea       ROMDISK_RW_IMP(pc),a1
$e400e8 : 6000 000e                            bra       ROMDISK_CHKDRV
$e400ec : 302f 0004                ROMDISK_MEDIACH:move.w 4(sp),d0
$e400f0 : 2078 081e                            movea.l   (ROMDISK_HDV_MEDIACH).w,a0
$e400f4 : 43fa 0074                            lea       ROMDISK_MEDIACH_IMP(pc),a1
$e400f8 : b07c 000f                ROMDISK_CHKDRV:cmp.w  #15,d0                    ; ROMDISK is drive P
$e400fc : 6600 0004                            bne       ROMDISK_CHKDRVx
$e40100 : 2049                                 movea.l   a1,a0
$e40102 : 4ed0                     ROMDISK_CHKDRVx:jmp   (a0)

$e40104 : 203c 0000 0800           ROMDISK_BPB_IMP:move.l #ROMDISK_BPB,d0          ; return ROMDISK_BPB
$e4010a : 4e75                                 rts

$e4010c : 207c 00e4 0222           ROMDISK_RW_IMP:movea.l #ROMDISK_BASE,a0
$e40112 : 7000                                 moveq     #0,d0
$e40114 : 302f 000c                            move.w    $c(sp),d0                 ; start sector number
$e40118 : e188                                 lsl.l     #8,d0
$e4011a : e388                                 lsl.l     #1,d0
$e4011c : d1c0                                 adda.l    d0,a0
$e4011e : 7400                                 moveq     #0,d2
$e40120 : 342f 000a                            move.w    $a(sp),d2                 ; number of sectors
$e40124 : e98a                                 lsl.l     #4,d2
$e40126 : 226f 0006                            movea.l   6(sp),a1                  ; destination buffer
$e4012a : 2009                                 move.l    a1,d0
$e4012c : 082f 0000 0005                       btst      #0,5(sp)                  ; write access? That will fail!
$e40132 : 6704                                 beq.s     ROMDISK_RW_IMP2
$e40134 : 70f3                                 moveq     #-13,d0
$e40136 : 4e75                                 rts

$e40138 : 0800 0000                ROMDISK_RW_IMP2:btst  #0,d0                     ; the destination has to be an even address for fast copying
$e4013c : 6618                                 bne.s     ROMDISK_RW_IMP4
$e4013e : 22d8                     ROMDISK_RW_IMP3:move.l (a0)+,(a1)+
$e40140 : 22d8                                 move.l    (a0)+,(a1)+
$e40142 : 22d8                                 move.l    (a0)+,(a1)+
$e40144 : 22d8                                 move.l    (a0)+,(a1)+               ; copy 32 bytes
$e40146 : 22d8                                 move.l    (a0)+,(a1)+
$e40148 : 22d8                                 move.l    (a0)+,(a1)+
$e4014a : 22d8                                 move.l    (a0)+,(a1)+
$e4014c : 22d8                                 move.l    (a0)+,(a1)+
$e4014e : 5382                                 subq.l    #1,d2
$e40150 : 6b14                                 bmi.s     ROMDISK_RW_IMP6
$e40152 : 66ea                                 bne.s     ROMDISK_RW_IMP3
$e40154 : 6010                                 bra.s     ROMDISK_RW_IMP6
$e40156 : e74a                     ROMDISK_RW_IMP4:lsl.w #3,d2
$e40158 : 12d8                     ROMDISK_RW_IMP5:move.b (a0)+,(a1)+
$e4015a : 12d8                                 move.b    (a0)+,(a1)+
$e4015c : 12d8                                 move.b    (a0)+,(a1)+
$e4015e : 12d8                                 move.b    (a0)+,(a1)+
$e40160 : 5382                                 subq.l    #1,d2
$e40162 : 6b02                                 bmi.s     ROMDISK_RW_IMP6
$e40164 : 66f2                                 bne.s     ROMDISK_RW_IMP5
$e40166 : 4280                     ROMDISK_RW_IMP6:clr.l d0                     ; no error
$e40168 : 4e75                                 rts

$e4016a : 4280                     ROMDISK_MEDIACH_IMP:clr.l d0                 ; no error
$e4016c : 4e75                                 rts

$e4016e : 3032 3533 4b20 524f 4d44+ROMDISK_insttext:DC.B '0253K ROMDISK installed as P:\r\n',0
$e4018e : 0000 0000 ffff ffff                  DC.L      0          ; no relocation table
$e40196 : ffff ffff ffff ffff                  DCB.B     110,$ff    ; fill the 512-page to the end with $FF

$e40200 : 0000 0000                CA2_NEXT:   DC.L      $000000
$e40204 : 00e4 0222                CA2_INIT:   DC.L      ROMDISK_BASE
$e40208 : 00e4 0222                CA2_RUN:    DC.L      ROMDISK_BASE
$e4020c : 1869                     CA2_TIME:   DC.W      $1869
$e4020e : 99c6                     CA2_DATE:   DC.W      $99c6
$e40210 : 0003 fa00                CA2_SIZE:   DC.L      509 * 512
$e40214 : 4341 5254 524f 4d2e 494d+CA2_NAME:   DC.B      'CARTROM.IMG',0
$e40220 : ffff                                 DC.W      $ffff

$e40222 : 0000 0000 ffff 0400      ROMDISK_BASE:DC.B     $00,$00,$00,$00,$ff,$ff,$04,$00 ;509 * 512-byte sectors
$e4022a : 0500 0600 0700 0800                  DC.B      $05,$00,$06,$00,$07,$00,$08,$00
$e40232 : 0900 0a00 0b00 ffff                  DC.B      $09,$00,$0a,$00,$0b,$00,$ff,$ff
$e4023a : 0d00 0e00 0f00 1000                  DC.B      $0d,$00,$0e,$00,$0f,$00,$10,$00
$e40242 : 1100 1200 1300 1400                  DC.B      $11,$00,$12,$00,$13,$00,$14,$00
$e4024a : 1500 1600 1700 1800                  DC.B      $15,$00,$16,$00,$17,$00,$18,$00
$e40252 : 1900 1a00 1b00 1c00                  DC.B      $19,$00,$1a,$00,$1b,$00,$1c,$00
$e4025a : 1d00 1e00 1f00 2000                  DC.B      $1d,$00,$1e,$00,$1f,$00,$20,$00
$e40262 : 2100 2200 2300 2400                  DC.B      $21,$00,$22,$00,$23,$00,$24,$00
$e4026a : 2500 2600 2700 2800                  DC.B      $25,$00,$26,$00,$27,$00,$28,$00
...

Atari ST Book: Internal Registers

By looking at the ROM code, available software and the hardware layout I can now document most specialty registers in the ST Book from Atari. I hope it is useful to you. Also available at GitHub.

The main ROM for the ST Book starts at $e0000 and ends at $e3ffff (256kb large). At $e40000 starts the ROM-Disk (also 256kb large), which is automatically activated as drive P.

YM Port A

Bit Description
0 Side Select (S0SEL)
1 Disk 0 Select (D0SEL)
2 Disk 1 Select (D1SEL)
3 MAX241 Pin 20 (TI3) – RS232 RTS (/MFPRTS)
4 MAX241 Pin 6 (TI2) – RS232 DTR (/MFPDTR)
5 Centronics Strobe (STROBE)
6 IDE Reset (IDERESET)
7 FDD Dense Selection (FDD_DENSE_SEL)

Autovector Interrupt Level 7 /POWER FAIL (NMI)

MFP Input Pins

Bit Description
7 Power Alarms (Power Alarms) (POWER_ALARMS-) = (/SRCLOW /RTC_ALARM /POWERON)
6 MAX241 Pin 22 (RD4) – RS232 CD (/MFPRI)
5 XDISKINT
4 KTDK (VBL) (KTOK)
3 XBLTINT
2 MAX241 Pin 26 (RD3) – RS232 CTS (/MFPCTS)
1 MAX241 Pin 5 (RD2) – RS232 DCD (/MFPCD)
0 Centronics Busy (BUSY)

$D0000 – Unknown $D0004 – Unknown

$FF820B

Bit Description
0 0: enable combo -> shadow controller video transfer, 1: disable combo -> shadow controller video transfer

$FF827E

Bit Description
0 0: Shadow Chip OFF
1 0: /SHIFTER_OFF output (Unused in STBook)
2 0: POWER_OFF (Turns off main VCC when high)
3 0: /22ON output (turns off LCD Bias when HIGH)
4 0: REFRESH_MACHINE output (turns on refresh controller)
5 0: RS–232_OFF output (turns off +/- 10 generator)
6 0: (Unused in STBook)
7 0: MTR_POWER_ON (turns on IDE drive motor supply)

$FF9200 (Configuration/Signal register)

Bit Description
0 0: Power Button pressed /(POWER_SWITCH)
1 0: Top is closed /(TOP_CLOSED)
2 0: RTC Alarm triggered /(RTC_ALARM)
3 0: “Common Source” voltage level below 7.2V /(SOURCE_DEAD) – triggers an NMI
4 0: “Common Source” voltage level below 8.8V /(SOURCE_LOW)
5 0: External Modem (Pin 10 on J204) /(MODEM_WAKE)
6 Reserved (always 1)
7 0: Triggered from the Expansion Port /(EXPANSION_WAKE)
8 Reserved
9 Reserved
10 Reserved
11 Reserved
12 Reserved
13 SELF TEST (?)
14 LOW SPEED FLOPPY
15 DMA AVAILABLE

$FF9210 8-bit Common Power Voltage Level in 100mV steps

$FF9214 8-bit Reference Voltage Level in 100mV steps

Atari ST Book: POWER.PRG listing

Commented assembly listing for the POWER.PRG in an Atari ST-Book. Also available on GitHub.

main:       pea       ($0000).w
            move.l    #'_PWR',-(sp)
            jsr       (_getcookie).l            ; _PWR cookie installed?
            addq.l    #8,sp
            tst.w     d0
            beq       install                   ; (no -> install app)
_term:      clr.w     -(sp)
            trap      #1                        ; Pterm0()
            illegal

install:    move.l    #infoText,-(sp)
            move.w    #9,-(sp)
            trap      #1                        ; Cconws()
            addq.w    #6,sp

            pea       (cookiePtr).l
            pea       ($0000).w
            jsr       (_getcookie).l
            addq.l    #8,sp
            addq.l    #8,(cookiePtr).l

            movea.l   4(sp),a0                  ; BASEPAGE
            move.l    (cookiePtr).l,d0
            lsl.l     #3,d0
            move.l    $18(a0),d1                ; Pointer to beginning of BSS segment
            add.l     $1c(a0),d1                ; + BSS segment size
            sub.l     a0,d1                     ; - BASEPAGE address = size of the app memory
            add.l     d1,d0
            move.l    (cookiePtr).l,-(sp)
            move.l    d0,(cookiePtr).l
            move.l    a0,-(sp)
            move.l    #cookie_blankScreenTimer,-(sp)
            move.l    #'_PWR',-(sp)
            jsr       (setCookie).l
            adda.l    #$10,sp
            tst.l     d0
            bmi.s     _term
            bpl       install2
            subi.l    #$40,(cookiePtr).l
            clr.b     (v_opnwk_called).l

install2:   clr.l     -(sp)
            move.w    #$20,-(sp)
            trap      #1                        ; oldval = Super(0L)
            addq.w    #6,sp
            move.l    d0,-(sp)
            move.w    #$20,-(sp)                ; Super(oldval)

            jsr       (setupVectors).l

            move.b    #0,(ahdiDetected).l       ; AHDI check
            movea.l   (pun_ptr).w,a0
            cmpi.l    #'AHDI',$52(a0)           ; P_cookie in PUN_INFO in the AHDI driver
            bne       install3
            lea       $52(a0),a1
            cmpa.l    $56(a0),a1                ; check P_cookptr in the AHDI driver
            bne       install3
            cmpi.w    #$500,$5a(a0)             ; check P_version in the AHDI driver
            blt       install3
            move.b    #1,(ahdiDetected).l
            move.b    $63(a0),(ahdiStandbyTime).l ;idle time limit to spin down IDE unit 0

install3:   move.l    #powerAlarm,(mfp_MonochromeDetect).w ;power alarm
            bclr      #7,(aer).w                ; clear pending "Monochrome Monitor Detect"
            bset      #7,(iera).w               ; enable "Monochrome Monitor Detect" interrupt
            bset      #7,(imra).w               ; enable "Monochrome Monitor Detect" interrupt mask
            move.l    #powerAlarm,(Level7IRQ).w ; power fail

            move.w    #3,(countdownVBLTimer).l  ; reset VBL timer
            bclr      #0,(synmod+1).l           ; enable combo -> shadow controller video transfer
            move.l    (cookie_blankScreenTimer).l,(blankScreenTimerCounter).l
            bclr      #3,(lcdPowerControlShadow).w ;LCD on
            move.b    (lcdPowerControlShadow).w,(lcdPowerControl).l
            move.l    (cookie_sleepTimer).l,(sleepTimerCounter).l

            trap      #1                        ; Super(oldval)
            addq.w    #6,sp
            clr.w     -(sp)
            move.l    (cookiePtr).l,-(sp)
            move.w    #$31,-(sp)
            trap      #1                        ; Ptermres()
            illegal

***************************************************************************
*
***************************************************************************
_getcookie: movem.l   d6-d7/a6,-(sp)
            move.l    $10(sp),d6                ; cookie
            movea.l   $14(sp),a6                ; ptr to the cookie value, if found
            clr.l     d7
            move.l    #1,-(sp)
            move.w    #$20,-(sp)
            trap      #1
            tst.l     d0
            bne       _getcookies
            move.l    #0,2(sp)
            move.w    #$20,(sp)
            trap      #1
            move.l    d0,d7
_getcookies:addq.l    #6,sp
            movea.l   (_p_cookies).w,a0
            move.l    a0,d0
            beq       _getcookiee
_getcookiel:move.l    (a0),d0
            cmp.l     d0,d6
            beq       _getcookie2
            tst.l     d0
            beq       _getcookiee
            addq.l    #8,a0
            bra.s     _getcookiel
_getcookie2:move.l    a6,d0
            beq       _getcookie3
            move.l    4(a0),(a6)
_getcookie3:moveq     #1,d0
_getcookiee:move.l    d0,d6
            tst.l     d7
            beq       _getcookiex
            move.l    d7,-(sp)
            move.w    #$20,-(sp)
            trap      #1
            addq.l    #6,sp
_getcookiex:move.l    d6,d0
            movem.l   (sp)+,d6-d7/a6
            rts

***************************************************************************
*
***************************************************************************
setCookie:  link      a6,#0
            move.l    d7,-(sp)
            moveq     #0,d7
            move.l    #1,-(sp)
            move.w    #$20,-(sp)
            trap      #1
            tst.l     d0
            bne       setCookies
            move.l    #0,2(sp)
            move.w    #$20,(sp)
            trap      #1
            move.l    d0,d7
setCookies: addq.l    #6,sp
            movea.l   (_p_cookies).w,a0
            move.l    a0,d0
            beq       setCookiee
            moveq     #0,d0
setCookiel: addq.l    #1,d0
            tst.l     (a0)
            beq       setCookie2
            addq.l    #8,a0
            bra.s     setCookiel
setCookie2: cmp.l     4(a0),d0
            beq       setCookiee2
            move.l    4(a0),$c(a0)
            clr.l     8(a0)
            move.l    8(a6),(a0)
            move.l    $c(a6),4(a0)
            moveq     #0,d0
            bra       setCookiee5
setCookiee: cmpi.l    #2,$14(a6)
            blt       setCookiee4
            move.l    (resvector).w,(oldcookieresvector).l
            move.l    (resvalid).w,(oldcookieresvalid).l
            move.l    #cookieResetVector,(resvector).w
            move.l    #$31415926,(resvalid).w
            movea.l   $10(a6),a0
            move.l    a0,(_p_cookies).w
            move.l    8(a6),(a0)+
            move.l    $c(a6),(a0)+
            clr.l     (a0)+
            move.l    $14(a6),(a0)
            moveq     #1,d0
            bra       setCookiee5
cookieResetVector:clr.l (_p_cookies).w
            move.l    (oldcookieresvalid).l,(resvalid).w
            move.l    (oldcookieresvector).l,(resvector).w
            jmp       (a6)

setCookiee2:cmp.l     $14(a6),d0
            ble       setCookiee4
            move.l    d0,d1
            subq.l    #2,d1
            movea.l   (_p_cookies).w,a0
            movea.l   $10(a6),a1
            move.l    a1,(_p_cookies).w
setCookiee3:move.l    (a0)+,(a1)+
            move.l    (a0)+,(a1)+
            dbra      d1,setCookiee3
            move.l    8(a6),(a1)+
            move.l    $c(a6),(a1)+
            clr.l     (a1)+
            move.l    $14(a6),(a1)
            moveq     #1,d0
            bra       setCookiee5
setCookiee4:moveq     #$ff,d0
setCookiee5:tst.l     d7
            beq       setCookiex
            move.l    d0,8(a6)
            move.l    d7,-(sp)
            move.w    #$20,-(sp)
            trap      #1
            addq.l    #6,sp
            move.l    8(a6),d0
setCookiex: move.l    (sp)+,d7
            unlk      a6
            rts

***************************************************************************
*       reset vector - used to wake up the machine back                   *
***************************************************************************
resetVector:move.l    (oldresvalid).l,(resvalid).w
            move.l    (oldresvector).l,(resvector).w
            bclr      #2,(lcdPowerControlShadow).w ;power is on
            bclr      #3,(lcdPowerControlShadow).w ;LCD on
            move.b    (lcdPowerControlShadow).w,(lcdPowerControl).l
            movea.l   (oldUSP).l,a0
            move      a0,usp
            movea.l   (oldSSP).l,sp
            clr.w     (saveOrRestoreFlag).l     ; Restore chip registers

            subi.l    #$2e,(savptr).w
            bsr       saveState_video
            bsr       saveState_halftone
            bsr       saveState_MFP
            bsr       saveState_MIDI
            bsr       saveState_PSG
            bsr       saveState_time
            bsr       saveState_Keyboard
            bsr       saveState_AHDI
            move.l    #0,-(sp)
            move.w    #$2f,-(sp)
            trap      #$e                       ; Waketime(0L) - clear Waketime
            addq.w    #6,sp
            addi.l    #$2e,(savptr).w

            bset      #7,(imra).w
            andi.b    #$f,(tcdcr).w
            move.b    #$df,(iprb).w
            movea.l   (etv_timer).w,a6
            subq.l    #2,sp
            move.w    #511-1,d7
resetVector2:clr.w    (sp)
            jsr       (a6)
            dbra      d7,resetVector2
            addq.l    #2,sp
            ori.b     #$50,(tcdcr).w

resetVector3:move.w   #30,d1
resetVector4:move.b   (STConfig+1).l,d0
            cmp.b     #$fe,d0                   ; Power button still pressed?
            beq.s     resetVector3              ; yes -> continue to wait
            cmp.b     #$ff,d0                   ; no pressed?
            bne       resetVector5              ; -> done
            btst      #7,(gpip).w               ; power alarm IRQ pending?
            beq.s     resetVector3              ; -> continue to wait
            btst      #5,(iprb).w
            beq.s     resetVector4
            move.b    #$df,(iprb).w
            dbra      d1,resetVector4

resetVector5:move.b   #$7f,(ipra).w
            movem.l   (saveRegs).l,d0-d7/a0-a6
            rte

***************************************************************************
*       NMI or MFP IRQ #15                                                *
***************************************************************************
powerAlarm: btst      #2,(STConfig+1).l         ; wait for RTC alarm to be off
            bne       powerAlarm2
            bclr      #2,(rtc_mode+1).l         ; disable RTC alarm
            bra.s     powerAlarm

powerAlarm2:movem.l   d0-d2,(saveRegs).l
            move.b    (STConfig+1).l,d0         ; IRQ source
            move.b    d0,d1
            and.b     #$a4,d1
            cmp.b     #$a4,d1                   ; _only_ expansion wake, modem wake or RTC wake?
            bne       powerAlarmExit            ; these are always ignored ->
            btst      #3,d0                     ; power dead?
            beq       gotoSleep                 ; -> force sleep
            btst      #0,d0                     ; power switch?
            beq       gotoSleep                 ; -> force sleep
            btst      #1,d0                     ; top closed?
            beq       gotoSleep                 ; -> force sleep
            cmp.b     #$ff,d0                   ; anything else?
            bne       powerAlarmExit            ; -> ignore it

* we got no IRQ source, wait for a bit to see if that changes
            move.w    #$1e,d1                   ; 31 scan lines
            move      sr,d2
            move      #$2700,sr
powerAlarml:move.b    (STConfig+1).l,d0         ; read the IRQ source
            cmp.b     #$ff,d0                   ; anything changed?
            bne       gotoSleep                 ; -> force sleep
            btst      #5,(iprb).w               ; scan line IRQ?
            beq.s     powerAlarml               ; no -> continue waiting
            move.b    #$df,(iprb).w             ; confirm IRQ
            dbra      d1,powerAlarml            ; wait 31 scan lines ->
            move      d2,sr
powerAlarmExit:movem.l (saveRegs).l,d0-d2
            move.b    #$7f,(isra).w             ; re-enable MFP IRQ #15
            rte                                 ; continue normally

***************************************************************************
*       let the system go to sleep                                        *
***************************************************************************
gotoSleep:  move      #$2700,sr                 ; stop all interrupts
            movem.l   d3-d7/a0-a6,(saveRegs+4*3).l ;save all remaining registers
            btst      #3,(STConfig+1).l         ; power dead?
            beq       shutdownPower             ; -> force shutdown

            subi.l    #$2e,(savptr).w           ; decrement re-entrancy stack for xbios
            move.l    #1,-(sp)
            move.w    #$2f,-(sp)
            trap      #$e                       ; Waketime(1L) - enable Waketime
            addq.w    #6,sp
            addi.l    #$2e,(savptr).w           ; re-increment re-entrancy stack for xbios
            tst.l     d0
            beq       shutdownPower

            move.b    #$c,(ide_seccn).l
            move.b    #$e2,(ide_comst).l        ; IDE standby command
            addi.l    #11*50,(blankScreenTimerCounter).l    ; wait for 11s
            addi.l    #11*50,(sleepTimerCounter).l
            movea.l   (etv_timer).w,a6
            subq.l    #2,sp
            move.w    #511-1,d7
gotoSleep2: clr.w     (sp)                      ; calling etv_timer as ~10s have passed
            jsr       (a6)
            dbra      d7,gotoSleep2
            addq.l    #2,sp

gotoSleep3: move.b    #30,d0
gotoSleep4: btst      #7,(gpip).w
            beq.s     gotoSleep3
            btst      #5,(iprb).w
            beq.s     gotoSleep4
            move.b    #$df,(iprb).w
            dbra      d0,gotoSleep4
            move.b    #$7f,(isra).w
            movem.l   (saveRegs).l,d0-d7/a0-a6
            rte

***************************************************************************
*       shut the system down because of a power failure                   *
***************************************************************************
shutdownPower:move    usp,a0
            move.l    a0,(oldUSP).l
            move.l    sp,(oldSSP).l
            move.w    #1,(saveOrRestoreFlag).l  ; Save chip registers
            bclr      #7,(imra).w
            bset      #3,(lcdPowerControlShadow).w ;LCD off
            move.b    (lcdPowerControlShadow).w,(lcdPowerControl).l
            subi.l    #$2e,(savptr).w
            bsr       saveState_video
            bsr       saveState_halftone
            bsr       saveState_FDC
            bsr       saveState_bios_rwabs
            bsr       saveState_AHDI
            bsr       saveState_PSG
            bsr       saveState_MFP
            addi.l    #$2e,(savptr).w
            move.l    (resvalid).w,(oldresvalid).l
            move.l    (resvector).w,(oldresvector).l
            move.l    #$31415926,(resvalid).w
            move.l    #resetVector,(resvector).w
            move.b    (lcdPowerControlShadow).w,d0
            bset      #4,d0                     ; REFRESH_MACHINE output
            move.b    d0,(lcdPowerControl).l
            bset      #0,(synmod+1).l           ; disable combo -> shadow controller video transfer
debouncel:  move.w    #100,d0                   ; wait for up to 500ms for the power button to be released
            clr.b     (tacr).w                  ; stop timer a
            bclr      #5,(iera).w               ; disable timer a
            bclr      #5,(imra).w               ; clear pending timer a interrupts
            bset      #5,(iera).w               ; enable timer a
            move.b    #$c0,(tadr).w
            move.b    #5,(tacr).w               ; timer a at 5ms
debouncel2: cmpi.b    #$fe,(STConfig+1).l       ; Power button still pressed?
            beq.s     debouncel
            btst      #5,(ipra).w               ; timer a not triggered
            beq.s     debouncel2
            move.b    #$df,(ipra).w             ; clear timer a interrupt
            dbra      d0,debouncel2             ; continue waiting
            bset      #2,(lcdPowerControlShadow).w ;power off
            move.b    (lcdPowerControlShadow).w,d0
            bset      #4,d0                     ; REFRESH_MACHINE output
            move.b    d0,(lcdPowerControl).l
* The following opcode is pre-fetched, the CPU doesn't need to touch this memory after the previous opcode anymore
endlessLoop:bra.s     endlessLoop               ; wakeup via reset!
            trap      #1                        ; this is useless stuff...
            addq.w    #6,sp
            illegal

***************************************************************************
*   save/restore the XBIOS time
*   Force reading the time from the RTC to update the GEMDOS time after sleep
***************************************************************************
saveState_time:tst.w  (saveOrRestoreFlag).l
            bne       saveState_timee
            move.w    #$17,-(sp)
            trap      #$e                       ; Gettime()
            addq.w    #2,sp
saveState_timee:rts

***************************************************************************
*   save/restore the MFP state
***************************************************************************
saveState_MFP:lea     (sav_MFP).l,a0
            tst.w     (saveOrRestoreFlag).l
            beq       saveState_MFPe
            move.b    (aer).w,(a0)+
            move.b    (ddr).w,(a0)+
            move.b    (iera).w,(a0)+
            move.b    (ierb).w,(a0)+
            move.b    (imra).w,(a0)+
            move.b    (imrb).w,(a0)+
            move.b    (vr).w,(a0)+
            move.b    (tacr).w,(a0)+
            move.b    (tbcr).w,(a0)+
            move.b    (tcdcr).w,(a0)+
            move.b    (scr).w,(a0)+
            move.b    (ucr).w,(a0)+
            move.b    (rsr).w,(a0)+
            move.b    (tsr).w,(a0)+
            move.b    #$c0,(sav_MFP+16).l
            lea       (tadr).w,a0
            lea       (tacr).w,a1
            bsr       saveState_MFPsave
            move.b    d0,(sav_MFP+14).l
            lea       (tbdr).w,a0
            lea       (tbcr).w,a1
            bsr       saveState_MFPsave
            move.b    d0,(sav_MFP+15).l
            lea       (tddr).w,a0
            lea       (tcdcr).w,a1
            bsr       saveState_MFPsave
            move.b    d0,(sav_MFP+17).l
            rts

saveState_MFPe:move.b (a0)+,(aer).w
            move.b    (a0)+,(ddr).w
            move.b    (a0)+,(iera).w
            move.b    (a0)+,(ierb).w
            move.b    (a0)+,(imra).w
            move.b    (a0)+,(imrb).w
            move.b    (a0)+,(vr).w
            move.b    (a0)+,(tacr).w
            move.b    (a0)+,(tbcr).w
            move.b    (a0)+,(tcdcr).w
            move.b    (a0)+,(scr).w
            move.b    (a0)+,(ucr).w
            move.b    (a0)+,(rsr).w
            move.b    (a0)+,(tsr).w
            move.b    (sav_MFP+14).l,(tadr).w
            move.b    (sav_MFP+15).l,(tbdr).w
            move.b    (sav_MFP+16).l,(tcdr).w
            move.b    (sav_MFP+17).l,(tddr).w
            move.b    (gpip).w,d0
            move.b    (aer).w,d1
            eor.b     d1,d0
            btst      #7,d0
            bne       saveState_MFP2
            btst      #7,(ipra).w
            bne       saveState_MFP2
            bchg      #7,(aer).w
            bchg      #7,(aer).w
saveState_MFP2:btst   #6,d0
            bne       saveState_MFP3
            btst      #6,(ipra).w
            bne       saveState_MFP3
            bchg      #6,(aer).w
            bchg      #6,(aer).w
saveState_MFP3:btst   #5,d0
            bne       saveState_MFP4
            btst      #7,(iprb).w
            bne       saveState_MFP4
            bchg      #5,(aer).w
            bchg      #5,(aer).w
saveState_MFP4:btst   #4,d0
            bne       saveState_MFP5
            btst      #6,(iprb).w
            bne       saveState_MFP5
            bchg      #4,(aer).w
            bchg      #4,(aer).w
saveState_MFP5:btst   #3,d0
            bne       saveState_MFP6
            btst      #3,(iprb).w
            bne       saveState_MFP6
            bchg      #3,(aer).w
            bchg      #3,(aer).w
saveState_MFP6:btst   #2,d0
            bne       saveState_MFP7
            btst      #2,(iprb).w
            bne       saveState_MFP7
            bchg      #2,(aer).w
            bchg      #2,(aer).w
saveState_MFP7:btst   #1,d0
            bne       saveState_MFP8
            btst      #1,(iprb).w
            bne       saveState_MFP8
            bchg      #1,(aer).w
            bchg      #1,(aer).w
saveState_MFP8:btst   #0,d0
            bne       saveState_MFP9
            btst      #0,(iprb).w
            bne       saveState_MFP9
            bchg      #0,(aer).w
            bchg      #0,(aer).w
saveState_MFP9:rts

saveState_MFPsave:move.b (tcdcr).w,d0
            and.b     #7,d0
            move.b    d0,(tcdcr).w
            move.b    #4,(tcdr).w
            or.b      #$70,d0
            move.b    (a1),d2
            or.b      #7,d2
            move.b    d2,(a1)
            moveq     #1,d1
            lea       (tcdr).w,a1
            lea       (tcdcr).w,a2
            cmp.b     (a0),d1
            bne.s     $107f8
            move.b    d0,(a2)
saveState_MFPsavel:cmp.b (a0),d1
            bne       saveState_MFPsavee
            cmp.b     (a1),d1
            bne.s     saveState_MFPsavel
saveState_MFPsavee:move.b (a0),d0
            rts

***************************************************************************
*   save/restore the keyboard state
*   Reset IKBD on restore, and reset keyboard tables
***************************************************************************
saveState_Keyboard:tst.w (saveOrRestoreFlag).l
            bne       saveState_Keyboarde
            move.b    #3,(keyctl).w
            move.b    #$96,(keyctl).w
            move.l    #ikbdResetCommand,-(sp)
            move.w    #2,-(sp)
            move.w    #$19,-(sp)
            trap      #$e                       ; Ikbdws(2, ikbdResetCommand)
            addq.w    #8,sp
            move.l    #-1,-(sp)
            move.l    #-1,-(sp)
            move.l    #-1,-(sp)
            move.w    #$10,-(sp)
            trap      #$e                       ; Keytbl(-1L, -1L, -1L)
            adda.w    #$e,sp
            movea.l   d0,a0
            movea.l   (a0)+,a3
            movea.l   (a0)+,a4
            movea.l   (a0)+,a5
            move.w    #$18,-(sp)
            trap      #$e                       ; Bioskeys()
            addq.w    #2,sp
            move.l    a5,-(sp)
            move.l    a4,-(sp)
            move.l    a3,-(sp)
            move.w    #$10,-(sp)
            trap      #$e                       ; Keytbl(,,)
            adda.w    #$e,sp
saveState_Keyboarde:rts

ikbdResetCommand:DC.B $80,$01

***************************************************************************
*   save/restore the MIDI port state
*   Just reset MIDI on restore
***************************************************************************
saveState_MIDI:tst.w  (saveOrRestoreFlag).l
            bne       saveState_MIDIe
            move.b    #3,(midictl).w
            move.b    #$95,(midictl).w
saveState_MIDIe:rts

***************************************************************************
*   save/restore the sound chip state
***************************************************************************
saveState_PSG:movem.l d3-d4/a3,-(sp)
            moveq     #$f,d3
            lea       (save_psg).l,a3
            tst.w     (saveOrRestoreFlag).l
            beq       saveState_PSGe
            moveq     #$ff,d4
saveState_PSGl:addq.w #1,d4
            move.w    d4,-(sp)
            move.w    #0,-(sp)
            move.w    #$1c,-(sp)
            trap      #$e                       ; Giaccess()
            addq.w    #6,sp
            move.b    d0,(a3)+
            dbra      d3,saveState_PSGl
            ori.b     #$37,(save_psg+7).l
            movem.l   (sp)+,d3-d4/a3
            rts

saveState_PSGe:moveq  #$7f,d4
saveState_PSGel:addq.w #1,d4
            move.b    (a3)+,d0
            move.w    d4,-(sp)
            move.w    d0,-(sp)
            move.w    #$1c,-(sp)
            trap      #$e                       ; Giaccess()
            addq.w    #6,sp
            dbra      d3,saveState_PSGel
            movem.l   (sp)+,d3-d4/a3
            rts

***************************************************************************
*   save/restore the shifter state
***************************************************************************
saveState_video:tst.w (saveOrRestoreFlag).l
            beq       saveState_videoe
            move.b    (v_bas_h).w,(sav_v_bas_h).l
            move.b    (v_bas_m).w,(sav_v_bas_m).l
            move.b    (v_bas_l).w,(sav_v_bas_l).l
            move.b    (synmod+1).w,(sav_synmod).l
            move.w    (palette).w,(sav_palette0).l
            move.b    (v_shf_mod+1).w,(sav_v_shf_mod).l
            rts
saveState_videoe:move.b (sav_v_bas_h).l,(v_bas_h).w
            move.b    (sav_v_bas_m).l,(v_bas_m).w
            move.b    (sav_v_bas_l).l,(v_bas_l).w
            move.b    (sav_synmod).l,(synmod+1).w
            move.w    (sav_palette0).l,(palette).w
            move.b    (sav_v_shf_mod).l,(v_shf_mod+1).w
            move.b    #0,(v_pixscroll+1).w
            rts

***************************************************************************
*   save/restore the blitter halftone data
***************************************************************************
saveState_halftone:move.w #$1e,d0
            lea       (Halftone).w,a0
            lea       (sav_halftone).l,a1
            tst.w     (saveOrRestoreFlag).l
            beq       saveState_halftonee
saveState_halftonel1:move.w (a0)+,(a1)+
            dbra      d0,saveState_halftonel1
            rts
saveState_halftonee:move.w (a1)+,(a0)+
            dbra      d0,saveState_halftonee
            rts

***************************************************************************
*   save/restore the BIOS device driver state
*   Read the boot sector to detect disk change and update BIOS disk status
***************************************************************************
saveState_bios_rwabs:tst.w (saveOrRestoreFlag).l
            beq       saveState_bios_rwabsl
            move.w    #0,-(sp)
            move.w    #0,-(sp)
            move.w    #1,-(sp)
            move.l    #0,-(sp)
            move.w    #0,-(sp)
            move.w    #4,-(sp)
            trap      #$d                       ; Rwabs(0, 0L, 1, 0, 0)
            adda.w    #$e,sp
            move.w    #1,-(sp)
            move.w    #0,-(sp)
            move.w    #1,-(sp)
            move.l    #0,-(sp)
            move.w    #0,-(sp)
            move.w    #4,-(sp)
            trap      #$d                       ; Rwabs(0, 0L, 1, 0, 1)
            adda.w    #$e,sp
saveState_bios_rwabsl:rts

***************************************************************************
*   save/restore the FDC state
***************************************************************************
saveState_FDC:tst.w   (saveOrRestoreFlag).l
            beq.s     saveState_bios_rwabsl
            move.w    #$190,(diskctl).w
            move.w    #$90,(diskctl).w
            rts

***************************************************************************
*   save/restore the AHDI state
*   Send harddrive to sleep/wakeup
***************************************************************************
saveState_AHDI:tst.b  (ahdiDetected).l
            bne       saveState_AHDIe
saveState_AHDI6:rts

saveState_AHDIe:moveq #0,d0
            andi.w    #7,d0
            lsl.w     #4,d0
            move.b    d0,(ide_headn).l
            tst.w     (saveOrRestoreFlag).l
            beq       saveState_AHDIe2
            move.b    #$e0,(ide_comst).l        ; IDE standby immediate
saveState_AHDI7:move.l #10*200,d0
            add.l     (_hz_200).w,d0
saveState_AHDIl:btst  #5,(gpip).w
            beq.s     saveState_AHDI3
            btst      #7,(ide_stat2).l
            beq.s     saveState_AHDI3
            cmp.l     (_hz_200).w,d0
            bhi.s     saveState_AHDIl
            moveq     #-1,d0
            bra.s     saveState_AHDIr
saveState_AHDI3:move.b (ide_comst).l,d0         ; IDE status register
            btst      #0,d0
            bne.s     saveState_AHDI5
            btst      #3,d0
            bne.s     saveState_AHDIr
            moveq     #0,d0
            bra.s     saveState_AHDIr
saveState_AHDI5:move.b (ide_param).l,d0
saveState_AHDIr:rts

saveState_AHDIe2:bsr  saveState_AHDIs
            tst.w     d0
            beq.s     saveState_AHDI6
            moveq     #0,d0
            andi.w    #7,d0
            lsl.w     #4,d0
            move.b    d0,(ide_headn).l
            move.b    (ahdiStandbyTime).l,(ide_seccn).l
            move.b    #$e2,(ide_comst).l        ; IDE standby command
            bra.s     saveState_AHDI7
saveState_AHDIs:andi.b #7,d0
            lsl.b     #4,d0
            move.b    d0,(ide_headn).l
            move.l    #5*200,d0
            add.l     (_hz_200).w,d0
            move.b    #$50,d1
saveState_AHDIs2:cmp.b (ide_stat2).l,d1
            beq.s     saveState_AHDIs3
            cmp.l     (_hz_200).w,d0
            bcc.s     saveState_AHDIs2
            moveq     #0,d0
            rts
saveState_AHDIs3:moveq #1,d0
            rts

***************************************************************************
*   patch all vectors to monitor image updates and/or keyboard/mouse input
*   as well as timeouts for sleep
***************************************************************************
setupVectors:
            * patch AES/VDI trap
            moveq    #$ff,d0
            trap      #2
            move.l    d0,(sav_screendrvfuncptr).l
            move.l    (trap_aesvdi).w,(oldtrap_aesvdi).l
            move.l    #new_trap2,(trap_aesvdi).w

            * patch BIOS trap
            move.l    (trap_bios).w,(oldtrap_bios).l
            move.l    #new_bios,(trap_bios).w

            * patch XBIOS trap
            move.l    (trap_xbios).w,(oldtrap_xbios).l
            move.l    #new_xbios,(trap_xbios).w

            * patch line A
            linea     #0                        ; Line-A Initialization
            move.l    d0,(lineA_variables).l
            move.l    a1,(lineA_fontHeaders).l
            move.w    #15,d0
            lea       (sav_lineA).l,a3
setupVectorsl:move.l  (a2)+,(a3)+
            dbra      d0,setupVectorsl
            move.l    (lineAexception).w,(old_lineA).l
            move.l    #new_lineA,(lineAexception).w

            * patch IKBD vectors (keyboard, joystick, MIDI, mouse)
            move.w    #$22,-(sp)
            trap      #$e                       ; Kbdvbase()
            addq.w    #2,sp
            movea.l   d0,a1
            lea       $10(a1),a1
            move.l    a1,(old_mousevecAddr).l
            move.l    (a1),(old_mousevec).l
            move.l    #new_mousevec,(a1)
            movea.l   d0,a1
            lea       -4(a1),a1
            move.l    (a1),(old_ikbd_neg4).l
            move.l    #new_ikbd_neg4,(a1)
            movea.l   d0,a1
            lea       $18(a1),a1
            move.l    (a1),(old_joyvec).l
            move.l    #new_joyvec,(a1)
            movea.l   d0,a1
            lea       $1c(a1),a1
            move.l    (a1),(old_midisysvec).l
            move.l    #new_midisysvec,(a1)

            * patch 50Hz timer
            move.l    (etv_timer).w,(old_evt_timer).l
            move.l    #new_etv_timer,(etv_timer).w

            * insert code into VBL queue
            movea.l   (_vblqueue).w,a0
            addq.l    #4,a0
setupVectorsl2:tst.l  (a0)+
            bne.s     setupVectorsl2
            move.l    #new_vbl,-4(a0)
            rts

***************************************************************************
*   Called 50 times per second
*   - if serial port monitoring is active, re-enable LCD
*   - if screen saver is active and timeout is reached, disable LCD
*   - if sleep timeout is active and reached, sleep machine
***************************************************************************
new_etv_timer:btst    #2,(rsr).w                ; serial port active?
            beq       new_etv_timer2            ; (no)
            move.l    (cookie_sleepTimer).l,(sleepTimerCounter).l
            tst.w     (cookie_watchSerialPortFlag).l ;monitor the RS232?
            beq       new_etv_timer2            ; (no)
            move.l    (cookie_blankScreenTimer).l,(blankScreenTimerCounter).l
            bclr      #3,(lcdPowerControlShadow).w ;LCD on
            move.b    (lcdPowerControlShadow).w,(lcdPowerControl).l

new_etv_timer2:tst.l  (cookie_blankScreenTimer).l
            beq       new_etv_timer3
            subq.l    #1,(blankScreenTimerCounter).l
            bne       new_etv_timer3
            move.l    (cookie_blankScreenTimer).l,(blankScreenTimerCounter).l
            bset      #3,(lcdPowerControlShadow).w ;LCD off
            move.b    (lcdPowerControlShadow).w,(lcdPowerControl).l

new_etv_timer3:tst.l  (cookie_sleepTimer).l
            beq       new_etv_timer4
            subq.l    #1,(sleepTimerCounter).l
            bne       new_etv_timer4
            move.l    (cookie_sleepTimer).l,(sleepTimerCounter).l
            pea       new_etv_timer4(pc)
            move      sr,-(sp)
            movem.l   d0-d2,(saveRegs).l
            jmp       (gotoSleep).l

new_etv_timer4:move.l (old_evt_timer).l,-(sp)
            rts

***************************************************************************
*   VBL vector patch
*   - After 3 VBLs disable the combo -> shadow controller video transfer
***************************************************************************
new_vbl:    tst.w     (cookie_videoPowerSaverFlag).l    ; disable the LCD after timeout?
            beq       new_vbl2                  ; (no)
            subq.w    #1,(countdownVBLTimer).l
            bne       new_vbl2
            bset      #4,(lcdPowerControlShadow).w ;REFRESH_MACHINE output
            move.b    (lcdPowerControlShadow).w,(lcdPowerControl).l
            bset      #0,(synmod+1).l           ; disable combo -> shadow controller video transfer
new_vbl2:   nop
            rts

***************************************************************************
*   mouse vector patch
*   Any mouse activity:
*   - enables the transfer to the shadow controller for at least 3 VBL.
*   - reset screen saver, enable LCD
*   - re-trigger the sleep timer.
***************************************************************************
new_mousevec:move.w   #3,(countdownVBLTimer).l  ; reset VBL timer
            bclr      #0,(synmod+1).l           ; enable combo -> shadow controller video transfer
            move.l    (cookie_blankScreenTimer).l,(blankScreenTimerCounter).l
            bclr      #3,(lcdPowerControlShadow).w ;LCD on
            move.b    (lcdPowerControlShadow).w,(lcdPowerControl).l
            move.l    (cookie_sleepTimer).l,(sleepTimerCounter).l

            move.l    (old_mousevec).l,-(sp)
            rts

***************************************************************************
*   joystick vector patch
*   Any joystick activity:
*   - enables the transfer to the shadow controller for at least 3 VBL.
*   - reset screen saver, enable LCD
*   - re-trigger the sleep timer.
***************************************************************************
new_joyvec: move.w    #3,(countdownVBLTimer).l  ; reset VBL timer
            bclr      #0,(synmod+1).l           ; enable combo -> shadow controller video transfer
            move.l    (cookie_blankScreenTimer).l,(blankScreenTimerCounter).l
            bclr      #3,(lcdPowerControlShadow).w ;LCD on
            move.b    (lcdPowerControlShadow).w,(lcdPowerControl).l
            move.l    (cookie_sleepTimer).l,(sleepTimerCounter).l

            move.l    (old_joyvec).l,-(sp)
            rts

***************************************************************************
*   keyboard driver patch
*   Any keyboard activity:
*   - enables the transfer to the shadow controller for at least 3 VBL.
*   - reset screen saver, enable LCD
*   - re-trigger the sleep timer.
***************************************************************************
new_ikbd_neg4:move.w  #3,(countdownVBLTimer).l  ; reset VBL timer
            bclr      #0,(synmod+1).l           ; enable combo -> shadow controller video transfer
            move.l    (cookie_blankScreenTimer).l,(blankScreenTimerCounter).l
            bclr      #3,(lcdPowerControlShadow).w ;LCD on
            move.b    (lcdPowerControlShadow).w,(lcdPowerControl).l
            move.l    (cookie_sleepTimer).l,(sleepTimerCounter).l

            move.l    (old_ikbd_neg4).l,-(sp)
            rts

***************************************************************************
*   MIDI vector patch
*   - any MIDI activity re-triggers the sleep timer.
***************************************************************************
new_midisysvec:move.l (cookie_sleepTimer).l,(sleepTimerCounter).l
            move.l    (old_midisysvec).l,-(sp)
            rts

***************************************************************************
*   AES/VDI patch
*   - #-1 enables the transfer to the shadow controller for at least 3 VBL.
*   - VDI calls except calls waiting for keyboard input also enable the
*     transfer to the shadow controller for at least 3 VBL.
*   - VDI v_opnwk() patches the mouse vector on the first call.
***************************************************************************
new_trap2:  cmp.w     #$73,d0                   ; VDI?
            bne       new_trap2b                ; (no)
            move.l    a0,-(sp)
            movea.l   d1,a0
            movea.l   (a0),a0
            move.w    (a0),(vdi_functionCode).l
            movea.l   (sp)+,a0
            cmpi.w    #$21,(vdi_functionCode).l ; vsin_mode() - Set input mode
            beq       new_trap2out
            cmpi.w    #$1f,(vdi_functionCode).l ; vrq_string() / vsm_string() - keyboard string input
            beq       new_trap2out
            cmpi.w    #$80,(vdi_functionCode).l ; vq_key_s() - Get shift key status
            beq       new_trap2out
            move.l    #trap_vdi_tailPatch,-(sp)
            move.w    4(sp),-(sp)
            ori.w     #$2000,(sp)
            move.l    (oldtrap_aesvdi).l,-(sp)
            rts

new_trap2b: cmp.w     #$ffff,d0
            bne       new_trap2out
            move.l    #trap_aesvdi_m1,d0
            rte

new_trap2out:move.l   (oldtrap_aesvdi).l,-(sp)
            rts

trap_vdi_tailPatch:move.w #3,(countdownVBLTimer).l ;reset VBL timer
            bclr      #0,(synmod+1).l           ; enable combo -> shadow controller video transfer
            cmpi.w    #1,(vdi_functionCode).l   ; v_opnwk()
            beq       trap_aesvdi_tailPatch2
            rte

trap_aesvdi_tailPatch2:bset #0,(v_opnwk_called).l
            bne       trap_aesvdi_tailPatch3
            move.l    a1,-(sp)
            movea.l   (old_mousevecAddr).l,a1
            move.l    (a1),(old_mousevec).l
            move.l    #new_mousevec,(a1)
            movea.l   (sp)+,a1
trap_aesvdi_tailPatch3:rte

trap_aesvdi_m1:movea.l (sav_screendrvfuncptr).l,a0
            jsr       (a0)
            move.w    #3,(countdownVBLTimer).l  ; reset VBL timer
            bclr      #0,(synmod+1).l           ; enable combo -> shadow controller video transfer
            rts

***************************************************************************
*   BIOS patch
*   - Bconout() enables the transfer to the shadow controller
*     for at least 3 VBL.
*   - Bconin(), Rwabs() and Getbpb() re-trigger the sleep timer.
***************************************************************************
new_bios:   move      usp,a0                    ; USP stack is active
            btst      #5,(sp)                   ; called from user mode?
            beq       new_bios2                 ; yes ->
            movea.l   sp,a0                     ; SSP stack is active
            addq.l    #6,a0
new_bios2:  move.w    (a0),d0                   ; bios function number
            cmp.w     #3,d0                     ; Bconout()
            beq       new_bios_bconout
            cmp.w     #2,d0                     ; Bconin()
            beq       new_bios_updatetimer
            cmp.w     #4,d0                     ; Rwabs()
            beq       new_bios_updatetimer
            cmp.w     #7,d0                     ; Getbpb()
            beq       new_bios_updatetimer
new_bios_old:movea.l  (oldtrap_bios).l,a0
            jmp       (a0)

new_bios_updatetimer:move.l (cookie_sleepTimer).l,(sleepTimerCounter).l
            bra.s     new_bios_old

new_bios_bconout:move.l (cookie_sleepTimer).l,(sleepTimerCounter).l
            move.l    2(a0),-(sp)
            move.w    #3,-(sp)                  ; Bconout()
            pea       new_bios_tailPatch(pc)
            move.w    $a(sp),-(sp)
            ori.w     #$2000,(sp)
            movea.l   (oldtrap_bios).l,a0
            jmp       (a0)

new_bios_tailPatch:move.w #3,(countdownVBLTimer).l ;reset VBL timer
            bclr      #0,(synmod+1).l           ; enable combo -> shadow controller video transfer
            addq.l    #6,sp
            rte

***************************************************************************
*   XBIOS patch
*   - Setscreen() and Vsync() enable the transfer to the shadow controller
*     for at least 3 VBL.
*   - Midiws(), Flopver() and DMAread()/DMAwrite() re-trigger the
*     sleep timer.
***************************************************************************
new_xbios:  move      usp,a0                    ; USP stack is active
            btst      #5,(sp)                   ; called from user mode?
            beq       new_xbios2                ; yes ->
            lea       6(sp),a0                  ; SSP stack is active
new_xbios2: move.w    (a0),d0                   ; xbios function number
            cmp.w     #5,d0                     ; Setscreen()
            beq       new_xbios_setscreen
            cmp.w     #$25,d0                   ; Vsync()
            beq       new_xbios4
            cmp.w     #8,d0                     ; Floprd()
            blt       new_xbios_old
            cmp.w     #$c,d0                    ; Midiws()
            ble       new_xbios_updatetimer
            cmp.w     #$13,d0                   ; Flopver()
            beq       new_xbios_updatetimer
            cmp.w     #$2a,d0                   ; DMAread()
            beq       new_xbios_updatetimer
            cmp.w     #$2b,d0                   ; DMAwrite()
            beq       new_xbios_updatetimer
new_xbios_old:movea.l (oldtrap_xbios).l,a0
            jmp       (a0)

new_xbios_updatetimer:move.l (cookie_sleepTimer).l,(sleepTimerCounter).l
            bra.s     new_xbios_old

new_xbios_setscreen:move.w $a(a0),-(sp)         ; mode
            move.l    6(a0),-(sp)               ; physbase
            move.l    2(a0),-(sp)               ; logbase
            move.w    #5,-(sp)                  ; # Setscreen()
            pea       new_xbios_tailPatch(pc)
            move.w    $10(sp),-(sp)
            ori.w     #$2000,(sp)
            movea.l   (oldtrap_xbios).l,a0
            jmp       (a0)

new_xbios_tailPatch:move.w #3,(countdownVBLTimer).l ;reset VBL timer
            bclr      #0,(synmod+1).l           ; enable combo -> shadow controller video transfer
            adda.l    #$c,sp                    ; remove parameters and function number from the stack
            rte

new_xbios4: move.w    #3,-(sp)                  ; # Logbase()
            pea       new_xbios7(pc)            ; push return address onto stack
            move.w    6(sp),-(sp)               ; push SR onto stack (for a rte)
            ori.w     #$2000,(sp)               ; set supervisor mode bit
            movea.l   (oldtrap_xbios).l,a0
            jmp       (a0)

new_xbios7: move.w    #3,(countdownVBLTimer).l  ; reset VBL timer
            bclr      #0,(synmod+1).l           ; enable combo -> shadow controller video transfer
            addq.l    #2,sp                     ; remove function number from the stack
            rte

***************************************************************************
*   line A patch
*   After every line A operation the video transfer to the shadow controller
*   is enabled and kept on for at least 3 VBLs. Without this the video
*   changes would not be visible to the user.
***************************************************************************
new_lineA:  movea.l   2(sp),a1                  ; PC which points to the current opcode
            move.w    (a1),d2                   ; actual line-A opcode
            and.w     #$fff,d2                  ; mask our the upper 4 bit ($Axxx)
            addq.l    #2,a1                     ; increment PC by 2 (behind the lineA opcode)
            move.l    a1,2(sp)                  ; write back new PC
            cmp.w     #$f,d2                    ; lineA range 0..15
            bhi       new_lineA2                ; out of range...punt
            lsl.w     #2,d2                     ; pointer into lineA jump table
            movea.l   new_lineA_FuncPtr(pc,d2.w),a1
            movem.l   d3-d7/a3-a5,-(sp)         ; save all registers
            jsr       (a1)                      ; call our lineA handler
            movem.l   (sp)+,d3-d7/a3-a5         ; restore all registers
new_lineA2: rte                                 ; return from interrupt

new_lineA_FuncPtr:
            DC.L lineA_0,lineA_1,lineA_2,lineA_3,lineA_4,lineA_5,lineA_6,lineA_7
            DC.L lineA_8,lineA_9,lineA_a,lineA_b,lineA_c,lineA_d,lineA_e,lineA_f

lineA_0:    movea.l   (lineA_variables).l,a0
            move.l    a0,d0
            movea.l   (lineA_fontHeaders).l,a1
            lea       (new_lineA_FuncPtr).l,a2
            rts

lineA_1:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4).l,-(sp)
            rts

lineA_2:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*2).l,-(sp)
            rts

lineA_3:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*3).l,-(sp)
            rts

lineA_4:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*4).l,-(sp)
            rts

lineA_5:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*5).l,-(sp)
            rts

lineA_6:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*6).l,-(sp)
            rts

lineA_7:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*7).l,-(sp)
            rts

lineA_8:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*8).l,-(sp)
            rts

lineA_9:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*9).l,-(sp)
            rts

lineA_a:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*10).l,-(sp)
            rts

lineA_b:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*11).l,-(sp)
            rts

lineA_c:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*12).l,-(sp)
            rts

lineA_d:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*13).l,-(sp)
            rts

lineA_e:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*14).l,-(sp)
            rts

lineA_f:    pea       lineA_tailPatch(pc)
            move.l    (sav_lineA+4*15).l,-(sp)
            rts

lineA_tailPatch:move.w #3,(countdownVBLTimer).l ; reset VBL timer
            bclr      #0,(synmod+1).l           ; enable combo -> shadow controller video transfer
            rts

***************************************************************************
*
***************************************************************************
infoText:           DC.B '**********************************\r\n'
                    DC.B 'Shutdown   version 1.0   Oct 17 91\r\n'
                    DC.B 'Copyright  1991 Atari Corporation\r\n'
                    DC.B 'All Rights Reserved\r\n'
                    DC.B '**********************************\r\n'
                    DC.B 0
oldcookieresvector: DS.L 1
oldcookieresvalid:  DS.L 1
saveOrRestoreFlag:  DS.B 1
oldresvalid:        DS.L 1
oldresvector:       DS.L 1
sav_v_bas_h:        DS.B 1
sav_v_bas_m:        DS.B 1
sav_v_bas_l:        DS.B 1
sav_synmod:         DS.B 1
sav_palette0:       DS.W 1
sav_v_shf_mod:      DS.B 1
save_psg:           DS.B 16
saveRegs:           DS.L 16
oldSSP:             DS.L 1
oldUSP:             DS.L 1
sav_MFP:            DS.B 18
sav_halftone:       DS.W 31
sav_screendrvfuncptr:DS.L 1
cookiePtr:          DS.L 1
old_mousevec:       DS.L 1
old_mousevecAddr:   DS.L 1
old_joyvec:         DS.L 1
old_ikbd_neg4:      DS.L 1
old_midisysvec:     DS.L 1
lineA_variables:    DS.L 1
lineA_fontHeaders:  DS.L 1
countdownVBLTimer:  DS.W 1
vdi_functionCode:   DS.W 1
ahdiDetected:       DS.B 1
ahdiStandbyTime:    DS.B 1
blankScreenTimerCounter:DS.L 1
sleepTimerCounter:  DS.L 1
cookie_blankScreenTimer:DS.L 1
cookie_sleepTimer:  DS.L 1
cookie_videoPowerSaverFlag:DS.W 1
cookie_watchSerialPortFlag:DS.W 1
old_evt_timer:      DS.L 1
oldtrap_aesvdi:     DS.L 1
oldtrap_bios:       DS.L 1
oldtrap_xbios:      DS.L 1
old_lineA:          DS.L 1
sav_lineA:          DS.L 16
v_opnwk_called:     DS.B 1

Atari ST Protection: Speedball

SpeedBall protection is almost identical in the code to Garfield. Track 79 has to be shorter than normal (e.g. 5979 bytes, about 5% shorter than normal)

02BDA8  48E77F7E            L0434:MOVEM.L   A1-A6/D1-D7,-(A7)
02BDAC  23C80002C1D0              MOVE.L    A0,$0002C1D0         L0465
02BDB2  13FC00000002C1D4          MOVE.B    #0,$0002C1D4         L0466
02BDBA  263C00000001              MOVE.L    #1,D3
02BDC0  23C30002C1D6        L0435:MOVE.L    D3,$0002C1D6         L0467
02BDC6  4EB90002BE38              JSR       EnterSuper
02BDCC  4EB90002C19E              JSR       InitProtBuffer
02BDD2  50F90000043E              ST        $43E.L
02BDD8  4EB90002BE90              JSR       YMPortDeselect
02BDDE  4EB90002BECE              JSR       FDCForceInterrupt
02BDE4  4EB90002BEF2              JSR       FDCSeekTrack79
02BDEA  4EB90002BF48              JSR       FDCReadTrack
02BDF0  4EB90002BF48              JSR       FDCReadTrack
02BDF6  4EB90002BECE              JSR       FDCForceInterrupt
02BDFC  4EB90002C050              JSR       YMDeselectFloppy
02BE02  51F90000043E              SF        $43E.L
02BE08  4EB90002C06A              JSR       ExitSuper
02BE0E  4EB90002C14E              JSR       CheckProtBuffer
02BE14  10390002C1BE              MOVE.B    $0002C1BE,D0         L045C
02BE1A  B03C0000                  CMP.B     #0,D0
02BE1E  67000012                  BEQ       18(PC)               L0436
02BE22  26390002C1D6              MOVE.L    $0002C1D6,D3         L0467
02BE28  51CBFF96                  DBF       D3,-106(PC)          L0435
02BE2C  4EF900025290              JMP       $25290
02BE32  4CDF7EFE            L0436:MOVEM.L   (A7)+,A1-A6/D1-D7
02BE36  4E75                      RTS

EnterSuper
02BE38  2F3C00000001              MOVE.L    #1,-(A7)
02BE3E  3F3C0020                  MOVE.W    #$20,-(A7)
02BE42  4E41                      TRAP      #1
02BE44  DFFC00000006              ADDA.L    #6,A7
02BE4A  4A40                      TST.W     D0
02BE4C  6600002C                  BNE       44(PC)               L0438
02BE50  42A7                      CLR.L     -(A7)
02BE52  3F3C0020                  MOVE.W    #$20,-(A7)
02BE56  4E41                      TRAP      #1
02BE58  DFFC00000006              ADDA.L    #6,A7
02BE5E  23C00002C1C0              MOVE.L    D0,$0002C1C0         L045D
02BE64  12390002C1D4              MOVE.B    $0002C1D4,D1         L0466
02BE6A  4A01                      TST.B     D1
02BE6C  66000020                  BNE       32(PC)               L0439
02BE70  13FC00020002C1D4          MOVE.B    #2,$0002C1D4         L0466
02BE78  4E75                      RTS
02BE7A  12390002C1D4        L0438:MOVE.B    $0002C1D4,D1         L0466
02BE80  4A01                      TST.B     D1
02BE82  6600000A                  BNE       10(PC)               L0439
02BE86  13FC00010002C1D4          MOVE.B    #1,$0002C1D4         L0466
02BE8E  4E75                L0439:RTS

YMPortDeselect
02BE90  4EB90002BE38              JSR       EnterSuper
02BE96  303C0000                  MOVE.W    #0,D0
02BE9A  5200                      ADDQ.B    #1,D0
02BE9C  E308                      LSL.B     #1,D0
02BE9E  00400000                  ORI.W     #0,D0
02BEA2  0A000007                  EORI.B    #7,D0
02BEA6  02000007                  ANDI.B    #7,D0
02BEAA  40E7                L043B:MOVE      SR,-(A7)
02BEAC  007C0700                  ORI.W     #$700,SR
02BEB0  13FC000E00FF8800          MOVE.B    #$E,$FF8800.L
02BEB8  123900FF8800              MOVE.B    $FF8800.L,D1
02BEBE  020100F8                  ANDI.B    #$F8,D1
02BEC2  8200                      OR.B      D0,D1
02BEC4  13C100FF8802              MOVE.B    D1,$FF8802.L
02BECA  46DF                      MOVE      (A7)+,SR
02BECC  4E75                      RTS

FDCForceInterrupt
02BECE  4EB90002BE38              JSR       EnterSuper
02BED4  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02BEDC  3C3C00D0                  MOVE.W    #$D0,D6
02BEE0  4EB90002C0B2              JSR       FDCWriteReg
02BEE6  3E3C0028                  MOVE.W    #$28,D7
02BEEA  4EB90002C0AC              JSR       DelayD7
02BEF0  4E75                      RTS

FDCSeekTrack79
02BEF2  4EB90002BE38              JSR       EnterSuper
02BEF8  4EB90002C0F0              JSR       $0002C0F0            L044E
02BEFE  33FC008600FF8606          MOVE.W    #$86,$FF8606.L
02BF06  3C3C004F                  MOVE.W    #$4F,D6
02BF0A  4EB90002C0B2              JSR       FDCWriteReg
02BF10  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02BF18  3C3C001B                  MOVE.W    #$1B,D6
02BF1C  4EB90002C0B2              JSR       FDCWriteReg
02BF22  2E3C00060000              MOVE.L    #$60000,D7
02BF28  5387                L043E:SUBQ.L    #1,D7
02BF2A  67000010                  BEQ       16(PC)               L043F
02BF2E  0839000500FFFA01          BTST      #5,$FFFA01.L
02BF36  6600FFF0                  BNE       -16(PC)              L043E
02BF3A  4E75                      RTS
02BF3C  3F3CFFF9            L043F:MOVE.W    #$FFF9,-(A7)
02BF40  4EB90002C14C              JSR       $0002C14C            L0452
02BF46  4E75                      RTS

FDCReadTrack
02BF48  4EB90002BE38              JSR       EnterSuper
02BF4E  42B90002C1C8              CLR.L     $0002C1C8            L045F
02BF54  40F90002C1B8              MOVE      SR,$0002C1B8         L0459
02BF5A  46FC2700                  MOVE      #$2700,SR
02BF5E  33FC009000FF8606          MOVE.W    #$90,$FF8606.L
02BF66  33FC019000FF8606          MOVE.W    #$190,$FF8606.L
02BF6E  33FC009000FF8606          MOVE.W    #$90,$FF8606.L
02BF76  3C3C0016                  MOVE.W    #$16,D6
02BF7A  343C0200                  MOVE.W    #$200,D2
02BF7E  C4C6                      MULU      D6,D2
02BF80  33C20002C1BA              MOVE.W    D2,$0002C1BA         L045A
02BF86  26390002C1D0              MOVE.L    $0002C1D0,D3         L0465
02BF8C  D483                      ADD.L     D3,D2
02BF8E  23C20002C1C4              MOVE.L    D2,$0002C1C4         L045E
02BF94  4EB90002C0B2              JSR       FDCWriteReg
02BF9A  20390002C1D0              MOVE.L    $0002C1D0,D0         L0465
02BFA0  13C000FF860D              MOVE.B    D0,$FF860D.L
02BFA6  E088                      LSR.L     #8,D0
02BFA8  13C000FF860B              MOVE.B    D0,$FF860B.L
02BFAE  E088                      LSR.L     #8,D0
02BFB0  13C000FF8609              MOVE.B    D0,$FF8609.L
02BFB6  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02BFBE  3C3C00E8                  MOVE.W    #$E8,D6
02BFC2  4EB90002C0B2              JSR       FDCWriteReg
02BFC8  2E3C00050000              MOVE.L    #$50000,D7
02BFCE  2A790002C1C4              MOVEA.L   $0002C1C4,A5         L045E
02BFD4  303C0200                  MOVE.W    #$200,D0
02BFD8  51C8FFFE            L0441:DBF       D0,-2(PC)            L0441
02BFDC  0839000500FFFA01    L0442:BTST      #5,$FFFA01.L
02BFE4  67000030                  BEQ       48(PC)               L0443
02BFE8  5387                      SUBQ.L    #1,D7
02BFEA  67000060                  BEQ       96(PC)               L0446
02BFEE  13F900FF86090002C1C9      MOVE.B    $FF8609.L,$0002C1C9  L0460
02BFF8  13F900FF860B0002C1CA      MOVE.B    $FF860B.L,$0002C1CA  L0461
02C002  13F900FF860D0002C1CB      MOVE.B    $FF860D.L,$0002C1CB  L0462
02C00C  BBF90002C1C8              CMPA.L    $0002C1C8,A5         L045F
02C012  6E00FFC8                  BGT       -56(PC)              L0442
02C016  33FC009000FF8606    L0443:MOVE.W    #$90,$FF8606.L
02C01E  3A3900FF8606              MOVE.W    $FF8606.L,D5
02C024  33C50002C1BC              MOVE.W    D5,$0002C1BC         L045B
02C02A  08050000                  BTST      #0,D5
02C02E  67000018                  BEQ       24(PC)               L0445
02C032  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02C03A  4EB90002C12E              JSR       $0002C12E            FDCReadRegB
02C040  46F90002C1B8        L0444:MOVE      $0002C1B8,SR         L0459
02C046  4E75                      RTS
02C048  6000FFF6            L0445:BRA       -10(PC)              L0444
02C04C  6000FFF2            L0446:BRA       -14(PC)              L0444

YMDeselectFloppy
02C050  4EB90002BE38              JSR       EnterSuper
02C056  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02C05E  103C0007                  MOVE.B    #7,D0
02C062  4EB90002BEAA              JSR       $0002BEAA            L043B
02C068  4E75                      RTS

ExitSuper
02C06A  10390002C1D4              MOVE.B    $0002C1D4,D0         L0466
02C070  5300                      SUBQ.B    #1,D0
02C072  4A00                      TST.B     D0
02C074  6700002C                  BEQ       44(PC)               L0449
02C078  2F3C00000001              MOVE.L    #1,-(A7)
02C07E  3F3C0020                  MOVE.W    #$20,-(A7)
02C082  4E41                      TRAP      #1
02C084  DFFC00000006              ADDA.L    #6,A7
02C08A  4A40                      TST.W     D0
02C08C  67000014                  BEQ       20(PC)               L0449
02C090  2F390002C1C0              MOVE.L    $0002C1C0,-(A7)      L045D
02C096  3F3C0020                  MOVE.W    #$20,-(A7)
02C09A  4E41                      TRAP      #1
02C09C  DFFC00000006              ADDA.L    #6,A7
02C0A2  33FC4E7100029B08    L0449:MOVE.W    #$4E71,$29B08       ;(#"Nq")
02C0AA  4E75                      RTS

DelayD7
02C0AC  51CFFFFE                  DBF       D7,-2(PC)            DelayD7
02C0B0  4E75                      RTS

FDCWriteReg
02C0B2  4EB90002BE38              JSR       EnterSuper
02C0B8  4EB90002C0DE              JSR       fdcDelay
02C0BE  33C600FF8604              MOVE.W    D6,$FF8604.L
02C0C4  4EB90002C0DE              JSR       fdcDelay
02C0CA  4E75                      RTS

FDCReadReg
02C0CC  4EB90002BE38              JSR       EnterSuper
02C0D2  363900FF8604              MOVE.W    $FF8604.L,D3
02C0D8  4EB90002C0DE              JSR       fdcDelay

fdcDelay
02C0DE  40E7                      MOVE      SR,-(A7)
02C0E0  3F07                      MOVE.W    D7,-(A7)
02C0E2  3E3C0028                  MOVE.W    #$28,D7             ;(#"(")
02C0E6  51CFFFFE            L044D:DBF       D7,-2(PC)            L044D
02C0EA  3E1F                      MOVE.W    (A7)+,D7
02C0EC  46DF                      MOVE      (A7)+,SR
02C0EE  4E75                      RTS

02C0F0  3C390002C1CC        L044E:MOVE.W    $0002C1CC,D6         L0463
02C0F6  02460003                  ANDI.W    #3,D6
02C0FA  2E3C00050000              MOVE.L    #$50000,D7
02C100  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
02C108  4EB90002C0B2              JSR       FDCWriteReg
02C10E  5387                L044F:SUBQ.L    #1,D7
02C110  67000010                  BEQ       16(PC)               L0450
02C114  0839000500FFFA01          BTST      #5,$FFFA01.L
02C11C  6600FFF0                  BNE       -16(PC)              L044F
02C120  4E75                      RTS
02C122  3F3CFFF9            L0450:MOVE.W    #$FFF9,-(A7)
02C126  4EB90002C14C              JSR       $0002C14C            L0452
02C12C  4E75                      RTS

FDCReadRegB
02C12E  4EB90002BE38              JSR       EnterSuper
02C134  4EB90002C0DE              JSR       fdcDelay
02C13A  33F900FF86040002C1CE      MOVE.W    $FF8604.L,$0002C1CE  L0464
02C144  4EB90002C0DE              JSR       fdcDelay
02C14A  4E75                      RTS

02C14C  4E75                L0452:RTS

CheckProtBuffer
02C14E  33FC4E750002BDA8          MOVE.W    #$4E75,$0002BDA8    ;(#"Nu") L0434
02C156  22390002C1D0              MOVE.L    $0002C1D0,D1         L0465
02C15C  068100002EE0              ADDI.L    #6000*2,D1
02C162  2041                      MOVEA.L   D1,A0
02C164  263C00000DAC              MOVE.L    #3500,D3
02C16A  243C00000000              MOVE.L    #0,D2
02C170  3A20                      MOVE.W    -(A0),D5
02C172  3020                L0454:MOVE.W    -(A0),D0
02C174  BA40                      CMP.W     D0,D5
02C176  660A                      BNE.S     10(PC)               L0455
02C178  5482                      ADDQ.L    #2,D2
02C17A  51CBFFF6                  DBF       D3,-10(PC)           L0454
02C17E  60000014                  BRA       20(PC)               L0456
02C182  04820000170C        L0455:SUBI.L    #5900,D2
02C188  6B0A                      BMI.S     10(PC)               L0456
02C18A  13FC00000002C1BE          MOVE.B    #0,$0002C1BE         L045C
02C192  4E75                      RTS
02C194  13FC00010002C1BE    L0456:MOVE.B    #1,$0002C1BE         L045C
02C19C  4E75                      RTS

InitProtBuffer
02C19E  243C0000176F              MOVE.L    #5999,D2
02C1A4  20790002C1D0              MOVEA.L   $0002C1D0,A0         L0465
02C1AA  2639000004BA              MOVE.L    $4BA.L,D3
02C1B0  30C3                L0458:MOVE.W    D3,(A0)+
02C1B2  51CAFFFC                  DBF       D2,-4(PC)            L0458
02C1B6  4E75                      RTS

02C1B8  2304                L0459:DC.W      $2304
02C1BA  2C00                L045A:DC.W      $2C00
02C1BC  0000                L045B:DC.W      $0000
02C1BE  0000                L045C:DC.W      $0000
02C1C0  00000000            L045D:DC.L      $00000000
02C1C4  00017EFA            L045E:DC.L      $00017EFA
02C1C8  00                  L045F:DC.B      $00
02C1C9  00                  L0460:DC.B      $00
02C1CA  00                  L0461:DC.B      $00
02C1CB  00                  L0462:DC.B      $00
02C1CC  0003                L0463:DC.W      $0003
02C1CE  0000                L0464:DC.W      $0000
02C1D0  000152FA            L0465:DC.L      $000152FA
02C1D4  0100                L0466:DC.B      $01,$00
02C1D6  00000001            L0467:DC.L      $00000001

Atari ST Protection: Silent Service, F15 Strike Eagle

This is a more interesting protection! For one it decrypts the track testing code only while it is executed (not really a problem with an Atari ST emulator) and encrypts it afterwards.

It reads track 79 and takes the very FIRST byte from the track and searches for the first position where this byte changes. Usually this is the first GAP before the first sector header and without a SYNC it can be shifted by even 1/2 bit by the FDC. However the code has a lookup table for all 16 possible bit-shift combinations and tests if this first byte plus the following 5 are in this table. This way even without a correct SYNC the protection test still succeeds!

But there is more! It skips sector 1..9 with their headers and data blocks and then stores the sector number of the first sector after these 9 sector (e.g. 0x13). This sector extends over the index mark and has to have random data at the end, because read track stops at the index mark. However up to 496 bytes at the beginning have to be identical. If there are no garbage data at the end of the sector, the protection fails, because the sector didn’t extend over the index!

As a last test the sector is read normally via XBIOS Floprd() and this call should return NO error (read sector doesn’t stop at the index mark, if it already started reading before the index mark). The whole 512 byte sector should have identical byte in it.

If all this succeeds, the copy protection test was successfull, too.

A very nice protection indeed!

silentServiceProtection:
    move.l  a6,$148d6
    lea     $1491a,a6
    movem.l d1-7/a0-5,-(a6)
    move.l  a6,$148da

    move.w  #$22,-(a7)
    trap    #14                 ;Kbdvbase()
    addq.w  #2,a7
    movea.l d0,a0
    move.l  16(a0),$148ae       ;->kb_mousevec

    move.l  $148ae,-(a7)
    lea     $13cd4,a0
    move.l  a0,-(a7)
    clr.w   -(a7)
    clr.w   -(a7)
    trap    #14                 ;Initmouse(0,...)
    adda.l  #12,a7

    move    sr,d0
    btst    #13,d0
    bne.s   L0102F4
    clr.l   -(a7)
    move.w  #$20,-(a7)
    trap    #1
    addq.w  #6,a7
    move.l  d0,$148ce
    move.l  #-1,$148c2
    bra.s   L0102FA
L0102F4
    clr.l   $148c2

L0102FA
    move.b  #$ff,$43e           ;set flock

    move    sr,-(a7)
    ori.w   #$700,sr
    clr.l   d0
    clr.l   d7
    move    (a7)+,sr

    move.w  #$19,-(a7)
    trap    #1                  ;Dgetdrv()
    addq.w  #2,a7
    cmpi.b  #1,d0
    bne.s   L01032A
    move.w  $4a6,d5
    cmpi.w  #2,d5
    beq.s   L01032A
    clr.l   d0
L01032A
    move.w  d0,$148ac

    addq.b  #1,d0               ;drive = 1/2
    lsl.b   #1,d0               ;drive = 2/4
    or.w    #0,d0               ;side 1
    eori.b  #7,d0
    and.b   #7,d0
    moveq   #2,d4               ;3 retries
    bsr     fdcSelect

    move.w  #$82,$ff8606        ;Track Register
    bsr     fdcReadD0
    move.w  d0,$148b4           ;save track register

cpRetry
    bsr     fdcRestore
    btst    #0,d6
    bne.l   cpFailed

    bsr     fdcSeek79
    btst    #0,d6
    bne.l   cpFailed

    clr.l   d3
    moveq   #2,d5
cpNextTrack:
    bsr     fdcReadTrack
    btst    #0,d6
    bne.l   cpFailed
    bsr     decryptCode

    lea     $1491e,a0       ;track buffer
    move.l  #$1f0,d0
    move.b  (a0)+,d7
cpSearch
    move.b  (a0)+,d6        ;find first changed byte
    cmp.b   d6,d7
    bne.s   cpNext
    dbra    d0,cpSearch
    bra.l   cpFailed
cpNext
    subq.l  #2,a0           ;back to the last byte from the block
    lea     $13c72,a2

    ;a possible bit shift mask
        $01,$03,$3F,$0F,$FF,$FF,
        $02,$06,$7C,$1F,$FF,$FF,
        $04,$0C,$F8,$3F,$FF,$FF,
        $08,$19,$F0,$7F,$FF,$FF,
        $10,$33,$E0,$FF,$FF,$FF,
        $20,$67,$C1,$FF,$FF,$FF,
        $40,$CF,$83,$FF,$FF,$FF,
        $80,$81,$9F,$07,$FF,$FF,

        $5E,$5C,$40,$B0,$00,$00,
        $BC,$B8,$81,$60,$00,$00,
        $97,$10,$2C,$00,$00,$00,
        $2F,$2E,$20,$58,$00,$00,
        $E5,$C4,$0B,$00,$00,$00,
        $CB,$88,$16,$00,$00,$00,
        $79,$71,$02,$C0,$00,$00,
        $F2,$E2,$05,$80,$00,$00,

        $55,$55

    move.b  (a0)+,d6        ;byte at the track beginning that was repeated
cpLoop
    move.b  (a2)+,d7        ;find the repeated byte
    cmp.b   #$55,d7
    beq.l   cpFailed
    cmp.b   d6,d7
    beq.s   cpNextB
    addq.w  #5,a2
    bra.s   cpLoop
cpNextB

    moveq   #4,d0
cpLoopB
    move.b  (a0)+,d6        ;the following 5 bytes have to be the same
    cmp.b   (a2)+,d6
    bne.l   cpFailed
    dbra    d0,cpLoopB

    ; skip 9 sectors 1..9 in the current track
    clr.b   d0
cpLoopC
    bsr     cpSearchSync    ;search for $A1,$A1
    addq.b  #1,d0           ;sector + 1
    move.b  (a0)+,d6
    cmp.b   #$fe,d6         ;Address Mark Header
    bne.l   cpFailed
    move.b  (a0)+,d6
    cmp.b   #$4f,d6         ;Track 79
    bne.l   cpFailed
    move.b  (a0)+,d6
    cmp.b   #0,d6           ;Side == 0
    bne.l   cpFailed
    move.b  (a0)+,d6
    cmp.b   d0,d6           ;Sector correct?
    bne.l   cpFailed

    bsr     cpSearchSync    ;search for $A1,$A1
    move.b  (a0)+,d6
    cmp.b   #$fb,d6         ;Data Header
    bne.l   cpFailed
    adda.l  #$200,a0        ;Skip Sector
    cmp.b   #9,d0
    bne.s   cpLoopC

    bsr     cpSearchSync    ;search for $A1,$A1
    move.b  (a0)+,d6
    cmp.b   #$fe,d6         ;Addres Mark Header
    bne.s   cpFailed
    move.b  (a0)+,d6
    movea.l #10,a6
    cmp.b   #$4f,d6         ;Track 79
    bne.s   cpFailed
    move.b  (a0)+,d6
    cmp.b   #0,d6           ;Side == 0
    bne.s   cpFailed
    clr.w   d6
    move.b  (a0)+,d6        ;Sector >= 10
    cmp.b   #10,d6
    blt.s   cpFailed
    move.w  d6,$13c6e       ;save found sector number ($0D)

    bsr     cpSearchSync    ;search for $A1,$A1
    move.b  (a0)+,d6
    cmp.b   #$fb,d6         ;Data Header
    bne.s   cpFailed

    clr.w   d0
    clr.w   d6
    move.b  (a0)+,d6
    move.w  d6,$13c70       ;first byte in the sector ($E5)
cpLoopD
    addq.w  #1,d0
    move.b  (a0)+,d6
    cmp.w   $13c70,d6       ;skip same bytes (first byte in the sector ($E5))
    bne.s   cpNextC
    cmp.w   #$1f0,d0        ;too many bytes?
    beq.s   cpFailed
    bra.s   cpLoopD
cpNextC

    cmp.b   #0,d6           ;end of track reached before end of sector?
    beq.s   cpOut

cpFailed
    clr.w   $13c6e          ;save found sector number = illegal

    bsr     encryptCode
    dbra    d5,cpNextTrack
    dbra    d4,cpRetry

    bsr     fdcDone
    move.b  d0,d6
    cmpi.l  #$0,$148c2
    beq.s   L0104A8
    move.l  $148ce,-(a7)
    move.w  #$20,-(a7)
    trap    #1
    addq.w  #6,a7
L0104A8
    bsr     cpCreateReturncode
    bsr     cpRestoreRegister
    rts

cpOut
    bsr     encryptCode
    bsr     fdcDone

    cmpi.l  #$0,$148c2
    beq.s   L0104D4
    move.l  $148ce,-(a7)
    move.w  #$20,-(a7)
    trap    #1
    addq.w  #6,a7

L0104D4
    move.w  #1,-(a7)            ;count
    move.w  #0,-(a7)            ;sideno
    move.w  #$4f,-(a7)          ;trackno
    move.w  $13c6e,-(a7)        ;sectno = saved found sector number ($0D)
    move.w  $148ac,-(a7)        ;devno
    clr.l   -(a7)               ;filler
    lea     $1491e,a0           ;track buffer
    move.l  a0,-(a7)
    move.w  #8,-(a7)
    trap    #14                 ;int16_t Floprd( void *buf, int32_t filler, int16_t devno, int16_t sectno, int16_t trackno, int16_t sideno, int16_t count )
    adda.l  #20,a7
    cmp.l   #0,d0
    beq.s   L010512             ;should be 0! =>
    andi.l  #$ffffff,d0
L010510
    rts

L010512
    ori.l   #$37000000,d0

    ;the sector has to have all the same byte
    move.l  #511,d7
    lea     $1491e,a0           ;track buffer
    clr.w   d6
L010526
    move.b  (a0)+,d6
    cmp.w   $13c70,d6           ;first byte in the sector ($E5)
    bne.s   L010510
    dbra    d7,L010526

    ori.l   #$4f,d0
    bsr     cpCreateReturncode
    bsr     cpRestoreRegister
    rts

fdcReadTrack:
    move.l  d7,$148ca
    lea     $1491e,a0           ;track buffer
    move.l  a0,$148d2
    move.b  $148d5,$ff860d
    move.b  $148d4,$ff860b
    move.b  $148d3,$ff8609
    move.l  #$680,d7
fdcReadTrackLoopA
    clr.l   (a0)+
    dbra    d7,fdcReadTrackLoopA
    move.w  #$90,$ff8606
    move.w  #$190,$ff8606
    move.w  #$90,$ff8606
    move.w  #31,d7
    bsr     fdcWriteD7          ;31 DMA sectors (31*512 bytes)
    move.w  #$80,$ff8606
    move.w  #$e4,d7
    bsr     fdcWriteD7          ;Read Track
    move.l  #$40000,d7
    move.b  #255,d6             ;Failed flag
fdcReadTrackLoopB
    btst    #5,$fffa01
    beq.s   fdcReadTrackDone
    subq.l  #1,d7
    bne.s   fdcReadTrackLoopB
    bsr     fdcForceInterrupt
    rts
fdcReadTrackDone
    move.w  #$90,$ff8606
    move.w  $ff8606,d0
    btst    #0,d0               ;DMA ok?
    beq.s   fdcReadTrackFailed
    clr.b   d6                  ;success
fdcReadTrackFailed
    rts

cpRestoreRegister:
    movea.l $148da,a6
    movem.l (a6)+,d1-7/a0-5
    movea.l $148d6,a6
    rts

cpSearchSync:
    move.l  #$1f0,d7
cpSearchSyncLoop
    move.b  (a0)+,d6
    cmp.b   #$a1,d6
    bne.s   cpSearchSyncCheck
    move.b  (a0)+,d6
    cmp.b   #$a1,d6
    bne.s   cpSearchSyncCheck
    rts
cpSearchSyncCheck
    dbra    d7,cpSearchSyncLoop
    suba.l  a6,a6
    addq.w  #4,a7
    bra.l   cpFailed

cpCreateReturncode:             ;$3700004F
    andi.l  #$ff0000ff,d0
    clr.l   d7
    move.w  $13c70,d7           ;first byte in the sector ($E5)
    rol.w   #8,d7
    or.w    $13c6e,d7           ;save found sector number ($0D)
    rol.w   #4,d7
    rol.l   #8,d7
    or.l    d7,d0               ;== $3750DE4F (Silent Service) / $37512E4F (F15 Strike Eagle)
    rts

Calculation after return:
0 == ($0062EB61 ^ $3750DE4F) - $3732352E


fdcDone
    movea.l $148c6,a5
    move.w  $148b4,d7           ;save track register
    bsr     fdcSeekD7
fdcDoneLoop
    move.w  #$80,$ff8606
    bsr     fdcReadD0           ;wait for the motor off
    btst    #7,d0
    bne.s   fdcDoneLoop
    move.b  d2,d0
    move.b  #$0,$43e            ;reset flock
    bsr     fdcSelect           ;deselect floppy

    move.l  $148ae,-(a7)
    lea     $13cd4,a0
    move.l  a0,-(a7)
    move.w  #1,-(a7)
    clr.w   -(a7)
    trap    #14                 ;Initmouse(1,...)
    adda.l  #12,a7
    rts

CryptRetA0Plus_16
    addq.l  #1,a0
    bsr CryptRetA0Plus_10
CryptRetA0Plus_5
    subq.l  #1,a0
    bsr CryptRetA0Plus_5B
CryptRetA0Plus_1
    subq.l  #1,a0
    bsr CryptRetA0Plus_2
CryptRetA0Plus_0
    rts


fdcWriteD7
    bsr.s   fdcDelay
    move.w  d7,$ff8604

fdcDelay
    move    sr,-(a7)
    move.w  d7,-(a7)
    move.w  #32,d7
fdcDelayLoop
    dbra    d7,fdcDelayLoop
    move.w  (a7)+,d7
    move    (a7)+,sr
    rts

encryptCode:
    bsr.s   CryptBlock
    move    $148b2,sr
    rts

decryptCode:
    move    sr,$148b2
    ori.w   #$700,sr
    bsr.s   CryptBlock
    rts

CryptBlock
    move    sr,d7
    lsr.w   #8,d7
    bset    #6,d7
    bclr    #4,d7
    bclr    #3,d7

    lea     $13ce1,a0
    lea     $1038a,a2
    bsr.s   CryptRetA0Plus_16
    addq.l  #1,a0               ;A0 = $13CF2
    moveq   #8,d0
    bsr.s   CryptBlockSub

    lea     $13ce1,a0
    lea     $103a8,a2
    bsr     CryptRetA0Plus_10   ;A0 = $13CF5
    moveq   #34,d0
    bsr.s   CryptBlockSub

    lea     $13ce1,a0
    lea     $103fe,a2
    bsr     CryptRetA0Plus_5B   ;A0 = $13CE6
    moveq   #26,d0
    bsr.s   CryptBlockSub

    addq.l  #5,a0               ;A0 = $13D06
    lea     $10444,a2
    moveq   #4,d0
    bsr.s   CryptBlockSub

    lea     $13ce1,a6
    lea     $10466,a2
    bsr     CryptRetA0Plus_1
    bsr     CryptRetA0Plus_2    ;A0 = $13D0E
    moveq   #4,d0
    bsr.s   CryptBlockSub
    rts

CryptBlockSub
    clr.l   d6
    move.b  (a0)+,d6
    adda.l  d6,a2
    eor.b   d7,(a2)
    dbra    d0,CryptBlockSub
    rts


fdcSelect:
    move    sr,-(a7)
    ori.w   #$700,sr
    move.b  #$e,$ff8800
    move.b  $ff8800,d1
    move.b  d1,d2
    and.b   #$f8,d1
    or.b    d0,d1
    move.b  d1,$ff8802
    move    (a7)+,sr
    rts


fdcReadD0
    bsr     fdcDelay
    move.w  $ff8604,d0
    bra.l   fdcDelay


fdcRestore
    move.w  #$03,d7
    bsr.s   fdcCommandAndWait
fdcRestoreLoop
    subq.l  #1,d6
    beq.s   fdcRestoreTimeout
    btst    #5,$fffa01
    bne.s   fdcRestoreLoop
    clr.l   d6
    move.w  #$80,$ff8606
    bsr.s   fdcReadD0
    btst    #2,d0           ;Track 0?
    bne.s   fdcRestoreSuccess
fdcRestoreTimeout
    bsr.s   fdcForceInterrupt
    moveq   #1,d6
fdcRestoreSuccess
    rts


fdcForceInterrupt
    move.w  #$80,$ff8606
    move.w  #$d0,d7
    bsr     fdcWriteD7
    bsr     fdcDelay
    rts


fdcSeek79
    move.w  #$4f,d7
fdcSeekD7
    move.w  #$86,$ff8606
    bsr     fdcWriteD7
    move.w  #$13,d7
    bsr.s   fdcCommandAndWait
fdcSeek79Loop
    subq.l  #1,d6
    beq.s   fdcSeek79Done
    btst    #5,$fffa01
    bne.s   fdcSeek79Loop
fdcSeek79Done
    clr.l   d6
    rts


fdcCommandAndWait
    move.l  #$40000,d6
    move.w  #$80,$ff8606
    bsr     fdcReadD0
    btst    #7,d0
    bne.s   fdcCommandAndWait2
    move.l  #$60000,d6
fdcCommandAndWait2
    bsr     fdcWriteD7
    rts


CryptRetA0Plus_10
    bsr     CryptRetA0Plus_5
CryptRetA0Plus_5B
    addq.l  #2,a0
    bsr     CryptRetA0Plus_1
CryptRetA0Plus_2
    addq.l  #2,a0
    bsr     CryptRetA0Plus_0
    rts

Atari ST Protection: Mighty Bombjack

Finally an interesting protection!

The boot sector is executable and simply loads the code into memory plus reading the boot sector (moving the head back to track 0). After loading the code the fun begins (skip further down…)

    TEXT
    BRA.S     L0000

    DC.B      $00,$00,$00,$00,$00,$00,$00,$00
    DC.B      $00,$00,$02,$02,$01,$00,$02,$70
    DC.B      $00,$20,$03,$00,$05,$00,$0A,$00
    DC.B      $01,$00,$00,$00,$00,$00

L0000:MOVE.L    #$230,D0        ;track 56, sector 1
    MOVE.L    #101,D1         ;$CA00 bytes
    MOVEA.L   $432.L,A0       ;_membot = Start of TPA (user memory)
    BSR       LoadSectors
    BNE.S     L0000
    LSL.L     #8,D1
    ADD.L     D1,D1           ;buf += 512 * sectors
    ADDA.L    D1,A0
    MOVEQ     #1,D1           ;$200 bytes
    BSR       LoadSectors     ;Track 1, Sector 1
    MOVE.L    $432.L,-(A7)    ;_membot = Start of TPA (user memory)
    RTS

LoadSectors:
    MOVEM.L   A0-A2/D1-D5,-(A7)
    MOVE.L    D0,D3           ;startsector
    MOVE.L    D1,D4           ;number of sectors
    MOVEQ     #-1,D0
LoadSectorsLoop:
    MOVE.L    D3,D0
    DIVU      #10,D0          ;10 sectors per track
    SWAP      D0
    MOVEQ     #0,D1
    MOVE.W    D0,D1
    ADDQ.W    #1,D1           ;sectno
    SWAP      D0
    ANDI.L    #$FF,D0         ;trackno
    MOVE.L    D0,D5
    MOVEQ     #11,D2
    SUB.L     D1,D2           ;number of sectors
    CMP.L     D2,D4
    BGE.S     LoadSectorsR    ;< remaining sectors
    MOVE.L    D4,D2           ;then read the remaining sectors
LoadSectorsR:
    BSR       Floprd
    BNE.S     LoadSectorsError
    ADD.L     D2,D3           ;sector += read sectors
    SUB.L     D2,D4           ;number of sectors -= read sectors
    LSL.L     #8,D2
    LSL.L     #1,D2           ;buf += read sectors * 512
    ADDA.L    D2,A0
    TST.L     D4              ;remaining sectors left?
    BGT.S     LoadSectorsLoop
    MOVEQ     #0,D0
LoadSectorsError:
    MOVEM.L   (A7)+,A0-A2/D1-D5
    TST.L     D0
    RTS

Floprd:MOVEM.L   A0/D1-D2,-(A7)
    MOVE.W    D2,-(A7)        ;count
    CLR.W     -(A7)           ;sideno
    MOVE.W    D0,-(A7)        ;trackno
    MOVE.W    D1,-(A7)        ;sectno
    CLR.W     -(A7)           ;devno = 'A'
    CLR.L     -(A7)           ;filler
    MOVE.L    A0,-(A7)        ;buf
    MOVE.W    #8,-(A7)  ;FLOPRD
    TRAP      #14             ;Floprd( void *buf, int32_t filler, int16_t devno, int16_t sectno, int16_t trackno, int16_t sideno, int16_t count )
    LEA       20(A7),A7
    TST.L     D0
    MOVEM.L   (A7)+,A0/D1-D2
    RTS

    DS.W      3
    DC.B      'Copylock ST (c)1988-90 Rob Northen Computing, U.K. All Rights Reserved.',0
    DS.W      123
    DC.W      $027F
    END

Ok, the code starts by entering supervisor mode via an illegal instruction, then pushing a trace exception handler onto the stack, which decrypts code on the fly. A *lot* of code. All this code is just there to annoy people trying to trace it by hand. Later it reaches the actual protection, which I'll publish here. It again uses trace to decrypt the next opcode (actually 8 bytes) and encrypting the last one again. As a little bonus it executes a subroutine if the "EXG D7,D7" opcode is executed. Fun, but useless: if you made it that far, this is not doing anything... Another thing: LINE-A, all interrupts and traps have to point to ROM, so does GPI7 and printer code (used to enter the debugger). If not, they point to a memory erase routine and a call into the reset of the ROM.

But now to the actual thing: the protection. 3 Parts:

- Via "read track" the first 450 bytes are read and the first sector address header is searched. It has to be a 512 byte sector on the first side and the first sector has to be equal to "(11 + (track % 5) * -2) % 10". If the routine fails, it returns -1, otherwise the current track. Funny thing: on track 0, sector 1 is just fine and because the boot sector was read at the end of the loading code, that's where the floppy head is located. 3 tries to get it done.
- Via Read Sector it reads sector 5 and sector 6 of track 0. It simply times the time it takes to read the sector and expects sector 6 to be at least >1% slower than sector 5. On the floppy it seems to be more than 3%, so 1% is safe.
- The first 16 bytes of sector 6 have to contain the string "Rob Northen Comp". A checksum over this string plus the following 8 bytes results in the serial number of the disk, which is specific for the application.

Yes, that's it for the protection. It continues with trace decoding and then launches the app. The following code is the heart of the protection, cleaned up and decoded.



018CAE  48E7C0C0                  MOVEM.L   A0-A1/D0-D1,-(A7)
018CB2  43F90000015C              LEA       $15C.L,A1
018CB8  233C00044ED0              MOVE.L    #$44ED0,-(A1)
018CBE  233CFFFA2078              MOVE.L    #$FFFA2078,-(A1)
018CC4  233CFFFF51C8              MOVE.L    #$FFFF51C8,-(A1)
018CCA  233C3FF948E0              MOVE.L    #$3FF948E0,-(A1)
018CD0  233C0000303C              MOVE.L    #$303C,-(A1)
018CD6  233C41F90010              MOVE.L    #$41F90010,-(A1)
018CDC  233C46FC2700              MOVE.L    #$46FC2700,-(A1)

        ;erase all memory and call reset
        000140: 46fc 2700                 MOVE      #$2700,SR
        000144: 41f9 0010 0000            LEA       $100000,A0
        00014a: 303c 3ff9                 MOVE.W    #$3FF9,D0
        00014e: 48e0 ffff                 MOVEM.L   D0-D7/A0-A7,-(A0)
        000152: 51c8 fffa                 DBF       D0,*-$4 [$14E]
        000156: 2078 0004                 MOVEA.L   $4.w,A0
        00015a: 4ed0                      JMP       (A0)

018CE2  23C90000042A              MOVE.L    A1,$42A.L
018CE8  23FC3141592600000426      MOVE.L    #$31415926,$426.L

018CF2  41F900000028              LEA       $28.L,A0            ;Line 1010 Emulator (LineA)
018CF8  61000038                  BSR       56(PC)               resetIfNotInROM
018CFC  41F900000060              LEA       $60.L,A0            ;all interrupts and traps!
018D02  6100002E            L0000:BSR       46(PC)               resetIfNotInROM
018D06  B1FC000000C0              CMPA.L    #$C0,A0
018D0C  66F4                      BNE.S     -12(PC)              L0000
018D0E  41F90000013C              LEA       $13C.L,A0           ;GPI7 - Monochrome Detect
018D14  6100001C                  BSR       28(PC)               resetIfNotInROM
018D18  41F90000050A              LEA       $50A.L,A0           ;prv_lst
018D1E  61000012                  BSR       18(PC)               resetIfNotInROM
018D22  41F900000512              LEA       $512.L,A0           ;prv_aux
018D28  61000008                  BSR       8(PC)                resetIfNotInROM
018D2C  4CDF0303                  MOVEM.L   (A7)+,A0-A1/D0-D1
018D30  6018                      BRA.S     24(PC)               L0003

resetIfNotInROM
018D32  2018                      MOVE.L    (A0)+,D0
018D34  6712                      BEQ.S     18(PC)               L0002
018D36  028000FFFFFF              ANDI.L    #$FFFFFF,D0
018D3C  B0BC00400000              CMP.L     #$400000,D0
018D42  6C04                      BGE.S     4(PC)                L0002
018D44  2149FFFC                  MOVE.L    A1,-4(A0)
018D48  4E75                L0002:RTS

018D4A  7000                L0003:MOVEQ     #0,D0
018D4C  7201                      MOVEQ     #1,D1
018D4E  48E73FF0                  MOVEM.L   A0-A3/D2-D7,-(A7)
018D52  7400                      MOVEQ     #0,D2
018D54  E690                      ROXR.L    #3,D0
018D56  E292                      ROXR.L    #1,D2
018D58  E790                      ROXL.L    #3,D0
018D5A  1400                      MOVE.B    D0,D2
018D5C  2601                      MOVE.L    D1,D3
018D5E  7E01                      MOVEQ     #1,D7
018D60  7C00                      MOVEQ     #0,D6
018D62  47FA03A6                  LEA       934(PC),A3           buffer512Bytes
018D66  3F390000043E              MOVE.W    $43E.L,-(A7)
018D6C  50F90000043E              ST        $43E.L
018D72  610000A0            L0004:BSR       160(PC)              doCheckDiskInterleave
018D76  6B0C                      BMI.S     12(PC)               L0005
018D78  61000036                  BSR       54(PC)               checkSectorsReturnMagic
018D7C  4A86                      TST.L     D6                   ;fail? 2nd try!
018D7E  6604                      BNE.S     4(PC)                L0005
018D80  6100002E                  BSR       46(PC)               checkSectorsReturnMagic
018D84  610000A0            L0005:BSR       160(PC)              seekToPreviousTrack
018D88  4A86                      TST.L     D6
018D8A  660E                      BNE.S     14(PC)               L0006
018D8C  4A82                      TST.L     D2
018D8E  6A0A                      BPL.S     10(PC)               L0006
018D90  5202                      ADDQ.B    #1,D2
018D92  02020001                  ANDI.B    #1,D2
018D96  51CFFFDA                  DBF       D7,-38(PC)           L0004
018D9A  6100005E            L0006:BSR       94(PC)               eraseBuffer
018D9E  33DF0000043E              MOVE.W    (A7)+,$43E.L
018DA4  3202                      MOVE.W    D2,D1               ;d1.w = drive no. key disk was found in
018DA6  2006                      MOVE.L    D6,D0               ;d0.l = serial no. 0=key disk not found
018DA8  4CDF0FFC                  MOVEM.L   (A7)+,A0-A3/D2-D7
018DAC  60000560                  BRA       1376(PC)             L002D

checkSectorsReturnMagic:
018DB0  598F                      SUBQ.L    #4,A7
018DB2  303C0005                  MOVE.W    #5,D0               ;Sector 5 in Track 0 (normal sector)
018DB6  610000AC                  BSR       172(PC)              fdcMeasureSectorTiming
018DBA  2E80                      MOVE.L    D0,(A7)
018DBC  303C0006                  MOVE.W    #6,D0               ;Sector 6 in Track 0 (slower sector, ~3%)
018DC0  610000A2                  BSR       162(PC)              fdcMeasureSectorTiming
018DC4  2217                      MOVE.L    (A7),D1
018DC6  9081                      SUB.L     D1,D0               ;delta between 5 and 6
018DC8  6B2C                      BMI.S     44(PC)               L000A
018DCA  C0FC0064                  MULU      #100,D0
018DCE  80C1                      DIVU      D1,D0               ;convert delta into percent
018DD0  B03C0001                  CMP.B     #1,D0               ;1 percent or less is not good enough!
018DD4  6D20                      BLT.S     32(PC)               L000A

018DD6  7000                      MOVEQ     #0,D0
018DD8  7203                      MOVEQ     #3,D1
018DDA  204B                      MOVEA.L   A3,A0
018DDC  9098                L0008:SUB.L     (A0)+,D0            ;checksum over first 16 bytes of sector 6 = "Rob Northen Comp"
018DDE  51C9FFFC                  DBF       D1,-4(PC)            L0008
018DE2  B0BCB34C4FDC              CMP.L     #$B34C4FDC,D0       ;has to be a specific value!
018DE8  660C                      BNE.S     12(PC)               L000A
018DEA  2C00                      MOVE.L    D0,D6
018DEC  7201                      MOVEQ     #1,D1
018DEE  DC98                L0009:ADD.L     (A0)+,D6            ;secret ID over the next 8 bytes
018DF0  4846                      SWAP      D6
018DF2  51C9FFFA                  DBF       D1,-6(PC)            L0009

018DF6  588F                L000A:ADDQ.L    #4,A7
018DF8  4E75                      RTS

eraseBuffer
018DFA  204B                      MOVEA.L   A3,A0
018DFC  323C00FF                  MOVE.W    #$FF,D1
018E00  203C00D4C742              MOVE.L    #$D4C742,D0
018E06  C0FC0011            L000C:MULU      #$11,D0
018E0A  5280                      ADDQ.L    #1,D0
018E0C  30C0                      MOVE.W    D0,(A0)+
018E0E  51C9FFF6                  DBF       D1,-10(PC)           L000C
018E12  4E75                      RTS

doCheckDiskInterleave:
018E14  61000028                  BSR       40(PC)               selectFloppy
018E18  610000D0                  BSR       208(PC)              checkDiskSectorInterleave
018E1C  3A00                      MOVE.W    D0,D5                => current track number
018E1E  6B04                      BMI.S     4(PC)                L000E
018E20  61000234                  BSR       564(PC)              fdcRestore
018E24  4E75                L000E:RTS

seekToPreviousTrack:
018E26  3005                      MOVE.W    D5,D0                current track number set?
018E28  6B0E                      BMI.S     14(PC)               L0010
018E2A  61000210                  BSR       528(PC)              fdcSeekD0
018E2E  4A86                      TST.L     D6
018E30  6722                      BEQ.S     34(PC)               deselectFloppy
018E32  4A03                      TST.B     D3
018E34  671E                      BEQ.S     30(PC)               deselectFloppy
018E36  4E75                      RTS
018E38  61000250            L0010:BSR       592(PC)              fdcFloppyDeselect
018E3C  4E75                      RTS

selectFloppy:
018E3E  1002                      MOVE.B    D2,D0
018E40  5200                      ADDQ.B    #1,D0
018E42  E308                      LSL.B     #1,D0
018E44  0A000007                  EORI.B    #7,D0
018E48  02000007                  ANDI.B    #7,D0
018E4C  7201                      MOVEQ     #1,D1
018E4E  61000244                  BSR       580(PC)              fdcFloppySelect
018E52  4E75                      RTS

deselectFloppy:
018E54  223C00005949              MOVE.L    #$5949,D1
018E5A  103C0007                  MOVE.B    #7,D0
018E5E  61000234                  BSR       564(PC)              fdcFloppySelect
018E62  4E75                      RTS

fdcMeasureSectorTiming:
018E64  48E72000                  MOVEM.L   D2,-(A7)
018E68  33FC008400FF8606          MOVE.W    #$84,$FF8606.L
018E70  6100027C                  BSR       636(PC)              fdcWriteD0
018E74  610000EE                  BSR       238(PC)              fdcDMAReadAddress
018E78  303C0001                  MOVE.W    #1,D0
018E7C  61000270                  BSR       624(PC)              fdcWriteD0
018E80  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
018E88  43F900FF860B              LEA       $FF860B.L,A1
018E8E  7200                      MOVEQ     #0,D1
018E90  240B                      MOVE.L    A3,D2
018E92  2F3C66F64E75              MOVE.L    #$66F64E75,-(A7)
018E98  2F3C00FFFA01              MOVE.L    #$FFFA01,-(A7)
018E9E  2F3C08390005              MOVE.L    #$8390005,-(A7)
018EA4  2F3CB44066F6              MOVE.L    #$B44066F6,-(A7)
018EAA  2F3C01090000              MOVE.L    #$1090000,-(A7)
018EB0  2F3C02005281              MOVE.L    #$2005281,-(A7)
018EB6  2F3C06820000              MOVE.L    #$6820000,-(A7)
018EBC  2F3CB44067F8              MOVE.L    #$B44067F8,-(A7)
018EC2  2F3C01090000              MOVE.L    #$1090000,-(A7)
018EC8  2F3C00FF8604              MOVE.L    #$FF8604,-(A7)
018ECE  2F3C33FC0080              MOVE.L    #$33FC0080,-(A7)
018ED4  2F3C007C0700              MOVE.L    #$7C0700,-(A7)
018EDA  244F                      MOVEA.L   A7,A2
018EDC  CF47                      EXG       D7,D7

A2 =>
        05BC8C  007C0700                  ORI.W     #$700,SR
        05BC90  33FC008000FF8604          MOVE.W    #$80,$FF8604.L
        05BC98  01090000            L0000:MOVEP.W   0(A1),D0
        05BC9C  B440                      CMP.W     D0,D2
        05BC9E  67F8                      BEQ.S     -8(PC)               L0000
        05BCA0  068200000200              ADDI.L    #$200,D2
        05BCA6  5281                L0001:ADDQ.L    #1,D1
        05BCA8  01090000                  MOVEP.W   0(A1),D0
        05BCAC  B440                      CMP.W     D0,D2
        05BCAE  66F6                      BNE.S     -10(PC)              L0001
        05BCB0  0839000500FFFA01    L0002:BTST      #5,$FFFA01.L
        05BCB8  66F6                      BNE.S     -10(PC)              L0002
        05BCBA  4E75                      RTS

018EDE  4FEF0030                  LEA       48(A7),A7
018EE2  2001                      MOVE.L    D1,D0
018EE4  4CDF0004                  MOVEM.L   (A7)+,D2
018EE8  4E75                      RTS

checkDiskSectorInterleave:
018EEA  61000044                  BSR       68(PC)               L0016
018EEE  6B3C                      BMI.S     60(PC)               L0015
018EF0  B03C0002                  CMP.B     #2,D0               ;512 bytes sector?
018EF4  6636                      BNE.S     54(PC)               L0015 ;no => error
018EF6  2200                      MOVE.L    D0,D1
018EF8  E199                      ROL.L     #8,D1
018EFA  0281000000FF              ANDI.L    #$FF,D1             ;track number
018F00  E088                      LSR.L     #8,D0               ;sector number
018F02  82FC0005                  DIVU      #5,D1
018F06  4241                      CLR.W     D1
018F08  4841                      SWAP      D1
018F0A  C2FCFFFE                  MULU      #$FFFE,D1
018F0E  02810000FFFF              ANDI.L    #$FFFF,D1
018F14  0641000B                  ADDI.W    #11,D1
018F18  82FC000A                  DIVU      #10,D1
018F1C  4841                      SWAP      D1                  ;d1 = (11 + (track % 5) * -2) % 10
018F1E  B200                      CMP.B     D0,D1               ;sector number == track
018F20  660A                      BNE.S     10(PC)               L0015
018F22  E088                      LSR.L     #8,D0               ;side
018F24  4A00                      TST.B     D0
018F26  6604                      BNE.S     4(PC)                L0015 ;Side 2? => error
018F28  E088                      LSR.L     #8,D0               ;return the track number
018F2A  4E75                      RTS
018F2C  70FF                L0015:MOVEQ     #-1,D0
018F2E  4E75                      RTS

; read track 0, load 4 bytes of the address block of first sector into D0 (Track,Side,Sector,Length)
; == 0x00000002
018F30  7202                L0016:MOVEQ     #2,D1               ; 3 tries
018F32  61000062            L0017:BSR       98(PC)               fdcReadTrack
018F36  6B2A                      BMI.S     42(PC)               L001B
018F38  204B                      MOVEA.L   A3,A0
018F3A  303C01C1                  MOVE.W    #450-1,D0
018F3E  0C1800FE            L0018:CMPI.B    #$FE,(A0)+
018F42  6614                      BNE.S     20(PC)               L001A
018F44  0C2800A1FFFE              CMPI.B    #$A1,-2(A0)
018F4A  660C                      BNE.S     12(PC)               L001A
018F4C  7203                      MOVEQ     #3,D1
018F4E  E188                L0019:LSL.L     #8,D0
018F50  1018                      MOVE.B    (A0)+,D0
018F52  51C9FFFA                  DBF       D1,-6(PC)            L0019
018F56  4E75                      RTS
018F58  51C8FFE4            L001A:DBF       D0,-28(PC)           L0018
018F5C  51C9FFD4                  DBF       D1,-44(PC)           L0017
018F60  70FF                      MOVEQ     #-1,D0
018F62  4E75                L001B:RTS

fdcDMAReadAddress:
018F64  200B                      MOVE.L    A3,D0
018F66  13C000FF860D              MOVE.B    D0,$FF860D.L
018F6C  E088                      LSR.L     #8,D0
018F6E  13C000FF860B              MOVE.B    D0,$FF860B.L
018F74  E088                      LSR.L     #8,D0
018F76  13C000FF8609              MOVE.B    D0,$FF8609.L
018F7C  33FC009000FF8606          MOVE.W    #$90,$FF8606.L
018F84  33FC019000FF8606          MOVE.W    #$190,$FF8606.L
018F8C  33FC009000FF8606          MOVE.W    #$90,$FF8606.L
018F94  4E75                      RTS

fdcReadTrack:
018F96  48A74000                  MOVEM.W   D1,-(A7)
018F9A  6100FFC8                  BSR       -56(PC)              fdcDMAReadAddress
018F9E  303C001F                  MOVE.W    #$1F,D0
018FA2  6100014A                  BSR       330(PC)              fdcWriteD0
018FA6  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
018FAE  223C00040000              MOVE.L    #$40000,D1
018FB4  43EB01C2                  LEA       450(A3),A1
018FB8  40E7                      MOVE      SR,-(A7)
018FBA  007C0700                  ORI.W     #$700,SR
018FBE  2F3C584F4E75              MOVE.L    #$584F4E75,-(A7)
018FC4  2F3C00FF8604              MOVE.L    #$FF8604,-(A7)
018FCA  2F3C33FC00D0              MOVE.L    #$33FC00D0,-(A7)
018FD0  2F3C00FF8606              MOVE.L    #$FF8606,-(A7)
018FD6  2F3C33FC0080              MOVE.L    #$33FC0080,-(A7)
018FDC  2F3CB3D76ED6              MOVE.L    #$B3D76ED6,-(A7)
018FE2  2F3C860D0003              MOVE.L    #$860D0003,-(A7)
018FE8  2F3C1F7900FF              MOVE.L    #$1F7900FF,-(A7)
018FEE  2F3C860B0002              MOVE.L    #$860B0002,-(A7)
018FF4  2F3C1F7900FF              MOVE.L    #$1F7900FF,-(A7)
018FFA  2F3C86090001              MOVE.L    #$86090001,-(A7)
019000  2F3C1F7900FF              MOVE.L    #$1F7900FF,-(A7)
019006  2F3C53816B1C              MOVE.L    #$53816B1C,-(A7)
01900C  2F3CFA016720              MOVE.L    #$FA016720,-(A7)
019012  2F3C000500FF              MOVE.L    #$500FF,-(A7)
019018  2F3C42A70839              MOVE.L    #$42A70839,-(A7)
01901E  2F3C00FF8604              MOVE.L    #$FF8604,-(A7)
019024  2F3C33FC00E0              MOVE.L    #$33FC00E0,-(A7)
01902A  244F                      MOVEA.L   A7,A2
01902C  CF47                      EXG       D7,D7

A2 =>
        05BC8C  33FC00E000FF8604          MOVE.W    #$E0,$FF8604.L      ; Read Track
        05BC94  42A7                      CLR.L     -(A7)
        05BC96  0839000500FFFA01    L0000:BTST      #5,$FFFA01.L
        05BC9E  6720                      BEQ.S     32(PC)               L0001
        05BCA0  5381                      SUBQ.L    #1,D1
        05BCA2  6B1C                      BMI.S     28(PC)               L0001
        05BCA4  1F7900FF86090001          MOVE.B    $FF8609.L,1(A7)
        05BCAC  1F7900FF860B0002          MOVE.B    $FF860B.L,2(A7)
        05BCB4  1F7900FF860D0003          MOVE.B    $FF860D.L,3(A7)
        05BCBC  B3D7                      CMPA.L    (A7),A1             ; end address reached?
        05BCBE  6ED6                      BGT.S     -42(PC)              L0000
        05BCC0  33FC008000FF8606    L0001:MOVE.W    #$80,$FF8606.L
        05BCC8  33FC00D000FF8604          MOVE.W    #$D0,$FF8604.L      ; Force Interrupt
        05BCD0  584F                      ADDQ.W    #4,A7
        05BCD2  4E75                      RTS

01902E  4FEF0048                  LEA       72(A7),A7
019032  46DF                      MOVE      (A7)+,SR
019034  2001                      MOVE.L    D1,D0
019036  4C9F0002                  MOVEM.W   (A7)+,D1
01903A  4E75                      RTS

fdcSeekD0:
01903C  33FC008600FF8606          MOVE.W    #$86,$FF8606.L
019044  610000A8                  BSR       168(PC)              fdcWriteD0
019048  303C0014                  MOVE.W    #$14,D0
01904C  6100000A                  BSR       10(PC)               fdcCommand
019050  6B02                      BMI.S     2(PC)                L001F
019052  7000                      MOVEQ     #0,D0
019054  4E75                L001F:RTS

fdcRestore:
019056  7004                      MOVEQ     #4,D0

fdcCommand:
019058  B03C0080                  CMP.B     #$80,D0             ;Type I command?
01905C  6404                      BCC.S     4(PC)                L0022
01905E  00000003                  ORI.B     #3,D0               ;=> seek rate = 3ms
019062  33FC008000FF8606    L0022:MOVE.W    #$80,$FF8606.L
01906A  61000082                  BSR       130(PC)              fdcWriteD0
01906E  203C00004000              MOVE.L    #$4000,D0
019074  0839000500FFFA01    L0023:BTST      #5,$FFFA01.L
01907C  6756                      BEQ.S     86(PC)               fdcReadStatus
01907E  5380                      SUBQ.L    #1,D0
019080  66F2                      BNE.S     -14(PC)              L0023
019082  61000038                  BSR       56(PC)               fdcForceInterrupt
019086  70FF                      MOVEQ     #-1,D0
019088  4E75                      RTS


fdcFloppyDeselect:
01908A  223C0000004B              MOVE.L    #$4B,D1
019090  103C0007                  MOVE.B    #7,D0

fdcFloppySelect:
019094  5381                      SUBQ.L    #1,D1
019096  66FC                      BNE.S     -4(PC)               fdcFloppySelect
019098  40E7                      MOVE      SR,-(A7)
01909A  007C0700                  ORI.W     #$700,SR
01909E  13FC000E00FF8800          MOVE.B    #$E,$FF8800.L
0190A6  123900FF8800              MOVE.B    $FF8800.L,D1
0190AC  020100F8                  ANDI.B    #$F8,D1
0190B0  8200                      OR.B      D0,D1
0190B2  13C100FF8802              MOVE.B    D1,$FF8802.L
0190B8  46DF                      MOVE      (A7)+,SR
0190BA  4E75                      RTS

fdcForceInterrupt:
0190BC  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
0190C4  303C00D0                  MOVE.W    #$D0,D0
0190C8  61000024                  BSR       36(PC)               fdcWriteD0
0190CC  303C000F                  MOVE.W    #$F,D0
0190D0  51C8FFFE            L0027:DBF       D0,-2(PC)            L0027

fdcReadStatus
0190D4  33FC008000FF8606          MOVE.W    #$80,$FF8606.L
0190DC  6100001A                  BSR       26(PC)               fdcDelay
0190E0  303900FF8604              MOVE.W    $FF8604.L,D0
0190E6  02800000001F              ANDI.L    #$1F,D0
0190EC  600A                      BRA.S     10(PC)               fdcDelay

fdcWriteD0
0190EE  61000008                  BSR       8(PC)                fdcDelay
0190F2  33C000FF8604              MOVE.W    D0,$FF8604.L

fdcDelay:
0190F8  40E7                      MOVE      SR,-(A7)
0190FA  3F00                      MOVE.W    D0,-(A7)
0190FC  303C0001                  MOVE.W    #1,D0
019100  51C8FFFE            L002B:DBF       D0,-2(PC)            L002B
019104  301F                      MOVE.W    (A7)+,D0
019106  46DF                      MOVE      (A7)+,SR
019108  4E75                      RTS

buffer512Bytes: DS.B 512

Atari ST Protection: Midi-Maze

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'

Atari ST Protection: Maupiti Island

This game has a custom disk format, which I’ll describe here:

The two disks are 80 tracks, two sided.

Track 1, Side 1: 9 Sectors, no file system. The boot sector loads remaining 8 sectors in the track, which contains the “custom BIOS”. Interestingly the developer did an off-by–1 error and tries to load 9 sectors starting at sector 2. Therefore the Floprd() call actually fails… But this is not part of the protection.

Track 79, Side 2 on Disk B contains also 9 sectors, which are used to save the current game state.

The rest of these disk doesn’t contain any sector. The tracks are read with the read track command and each track has the following format:

  • 24 * $4E
  • 12 * $00
  • 3 * $A1
  • $FE
  • $07
  • track number
  • $07
  • checksum high byte
  • $07
  • checksum low byte
  • $07
  • 5842 data bytes
  • $4E repeated till the index mark

The code just searches for two $A1 at the beginning of the track, followed by $FE. It also tests the track number (it has to match the position of the head, bit 7 is set for side 2). The checksum is an unsigned word, which is calculated by adding all 5842 (unsigned) data bytes together. The checksum is also tested.

Because the data bytes can contain any byte $00..$FF it can’t be written with a standard FDC, which can’t write bytes like $F5 or $F7.

However the FDC has a bug in read track, which tries to sync all the time and certain bytes can trigger the sync, which will destroy the bytes after that. To avoid that a very simple yet efficient method was used: an $07 byte is prefixed any byte that would resync the FDC (Claus Brod wrote a wonderful article about this). This is also the reason to have these bytes in the track header!

Well, that is it. Efficient, very large payload in the track and not possible to copy.

Atari ST Protection: Indiana Jones and the Last Crusade

Another protection that measures the length of track 79, which has to be smaller than 6020 byte. The copy station created them bit a lower bitrate, on a standard floppy these tracks can not be written.

0001885a: 6100 0068                      BSR      fdcSelect
0001885e: 6100 0082                      BSR      fdcRestore

00018862: 303c 004e                      MOVE.W   #$4E,D0
00018866: 6100 0092                      BSR      fdcSeek
0001886a: 6100 0132                      BSR      fdcReadTrack
0001886e: 6100 010c                      BSR      dmaReadByteOffset
00018872: 23c0 0001 89f6                 MOVE.L   D0,$189F6         ;0x186d bytes long (unused?)

00018878: 303c 004f                      MOVE.W   #$4F,D0
0001887c: 6100 007c                      BSR      fdcSeek
00018880: 6100 011c                      BSR      fdcReadTrack
00018884: 6100 0020                      BSR      fdcDone
00018888: 6100 00f2                      BSR      dmaReadByteOffset ;0x175d bytes long
0001888c: b0bc 0000 1784                 CMP.L    #$1784,D0         ;6020 bytes
00018892: 6e00 000a                      BGT      *+$C [$1889E]
00018896: 203c 0000 0000                 MOVE.L   #0,D0             ;success
0001889c: 4e75                           RTS
0001889e: 203c 0000 0001                 MOVE.L   #1,D0             ;fail
000188a4: 4e75                           RTS


fdcDone
000188a6: 33fc 0080 ffff 8606            MOVE.W   #$80,$FFFF8606
000188ae: 3039 ffff 8604                 MOVE.W   $FFFF8604,D0
000188b4: 0800 0000                      BTST     #0,D0
000188b8: 6600 fff4                      BNE      *-$A [$188AE]
000188bc: 7007                           MOVEQ    #7,D0
000188be: 6100 0006                      BSR      *+$8 [$188C6]
000188c2: 4e75                           RTS

fdcSelect
000188c4: 7005                           MOVEQ    #5,D0
000188c6: 13fc 000e ffff 8800            MOVE.B   #$E,$FFFF8800
000188ce: 1239 ffff 8800                 MOVE.B   $FFFF8800,D1
000188d4: 0201 00f8                      ANDI.B   #$F8,D1
000188d8: 8200                           OR.B     D0,D1
000188da: 13c1 ffff 8802                 MOVE.B   D1,$FFFF8802
000188e0: 4e75                           RTS

fdcRestore
000188e2: 33fc 0080 ffff 8606            MOVE.W   #$80,$FFFF8606
000188ea: 6100 0056                      BSR      fdcDelay
000188ee: 33fc 0000 ffff 8604            MOVE.W   #$00,$FFFF8604
000188f6: 6000 005c                      BRA      fdcWait

fdcSeek
000188fa: 33fc 0086 ffff 8606            MOVE.W   #$86,$FFFF8606
00018902: 6100 003e                      BSR      fdcDelay
00018906: 33c0 ffff 8604                 MOVE.W   D0,$FFFF8604
0001890c: 6100 0046                      BSR      fdcWait
00018910: 33fc 0080 ffff 8606            MOVE.W   #$80,$FFFF8606
00018918: 6100 0028                      BSR      fdcDelay
0001891c: 33fc 0015 ffff 8604            MOVE.W   #$15,$FFFF8604
00018924: 6100 002e                      BSR      fdcWait
00018928: 4e75                           RTS

0001892a: 33fc 0080 ffff 8606            MOVE.W   #$80,$FFFF8606
00018932: 6100 000e                      BSR      fdcDelay
00018936: 33fc 0050 ffff 8604            MOVE.W   #$50,$FFFF8604
0001893e: 6000 0014                      BRA      fdcWait

fdcDelay
00018942: 40e7                           MOVE     SR,-(A7)
00018944: 3f07                           MOVE.W   D7,-(A7)
00018946: 3e3c 0020                      MOVE.W   #$20,D7
0001894a: 51cf fffe                      DBF      D7,*-$0 [$1894A]
0001894e: 3e1f                           MOVE.W   (A7)+,D7
00018950: 46df                           MOVE     (A7)+,SR
00018952: 4e75                           RTS

fdcWait
00018954: 0839 0005 ffff fa01            BTST     #5,$FFFFFA01
0001895c: 6600 fff6                      BNE      fdcWait
00018960: 4e75                           RTS

dmaSetAddress
00018962: 2008                           MOVE.L   A0,D0
00018964: 13c0 ffff 860d                 MOVE.B   D0,$FFFF860D
0001896a: e088                           LSR.L    #8,D0
0001896c: 13c0 ffff 860b                 MOVE.B   D0,$FFFF860B
00018972: e088                           LSR.L    #8,D0
00018974: 13c0 ffff 8609                 MOVE.B   D0,$FFFF8609
0001897a: 4e75                           RTS

dmaReadByteOffset
0001897c: 223c 0001 89fa                 MOVE.L   #$189FA,D1
00018982: 4280                           CLR.L    D0
00018984: 1039 00ff 8609                 MOVE.B   $FF8609,D0
0001898a: e188                           LSL.L    #8,D0
0001898c: 1039 00ff 860b                 MOVE.B   $FF860B,D0
00018992: e188                           LSL.L    #8,D0
00018994: 1039 00ff 860d                 MOVE.B   $FF860D,D0
0001899a: 9081                           SUB.L    D1,D0
0001899c: 4e75                           RTS

fdcReadTrack
0001899e: 303c 2710                      MOVE.W   #10000,D0
000189a2: 51c8 fffe                      DBF      D0,*-$0 [$189A2]
000189a6: 41f9 0001 89fa                 LEA      $189FA,A0
000189ac: 6100 ffb4                      BSR      dmaSetAddress
000189b0: 33fc 0090 ffff 8606            MOVE.W   #$90,$FFFF8606
000189b8: 33fc 0190 ffff 8606            MOVE.W   #$190,$FFFF8606
000189c0: 33fc 0090 ffff 8606            MOVE.W   #$90,$FFFF8606
000189c8: 6100 ff78                      BSR      fdcDelay
000189cc: 33fc 001f ffff 8604            MOVE.W   #$1F,$FFFF8604
000189d4: 6100 ff6c                      BSR      fdcDelay
000189d8: 33fc 0080 ffff 8606            MOVE.W   #$80,$FFFF8606
000189e0: 6100 ff60                      BSR      fdcDelay
000189e4: 33fc 00e4 ffff 8604            MOVE.W   #$E4,$FFFF8604
000189ec: 6100 ff54                      BSR      fdcDelay
000189f0: 6100 ff62                      BSR      fdcWait
000189f4: 4e75                           RTS

000189F6: DC.L 0
000189FA: DS.B buffersize

Atari ST Protection: HLS

This was used in many games, like: – Roadrunner – OutRun from Sega – Music Construction Set – Metrocross from Epyx – Skyfox – The Bards Tale – Pinball Wizard

It varies with the checksum in $24.w/$26.w (the trace vector) and for Skyfox with the sector numbers that are tested.

Track 79 has 12 sectors in it. 4 are part of the actual protection: Sector 9 and $F7, $F5 and $F6, which are impossible to write into the sector header. The 3 “weird” sectors are semi-defect. The header of sector $F7 is written right before sector 9. After 9, comes 5 (which is empty, filled with 0xE6) and then 0xF5 (also empty with 0xE6 and no read error!), 0xF6 (which continues over the index mark). Sector $F7 has a CRC error, because it contains sector 9. And Sector $F6 has a CRC error, because it continues over the index mark and therefore has garbage at the end.

The protection tests the following things: Sector 1–9 are read and should return no read-error. They also can’t contain the following bytes $A1,$A1,$A1,$FE or $FB (which is a sector header or data header with sync) and they also have to be 512 bytes long. These tests avoid that somebody creates a different – copyable – track 79 with shorter sectors, etc.

The other 3 sectors either return no error or a CRC error (error code –4). The software calculates a checksum over these 3 sectors plus sector 9 as well as a checksum (based on the seed in $24.w/$26.w) over the protection code. This checksum is then used to decrypt the main application. If any of the above tests fail, the memory is cleared of the code and the app is terminated.

Interestingly the protection can be defeated with a simple Floprd() patch which returns the right buffer for the 4 sectors…

L0000 DC.W $000,$F7
    DC.W $400,$F5
    DC.W $600,$f6

for Skyfox for values are:

L0000 DC.W $000,$43
    DC.W $400,$21
    DC.W $600,$09
05BC94  48790001FFFC        L0001:PEA       $1FFFC
05BC9A  3F3C0020                  MOVE.W    #$20,-(A7)
05BC9E  4E41                      TRAP      #1
05BCA0  61000FA0                  BSR       4000(PC)             L0025
05BCA4  4240                      CLR.W     D0
05BCA6  6100                      BSR       ...
05BCAA  7000                SuperOn: MOVEQ     #0,D0
05BCAA  2F00                SuperOff:MOVE.L    D0,-(A7)
05BCAC  3F3C0020                  MOVE.W    #$20,-(A7)
05BCB0  4E41                      TRAP      #1
05BCB2  5C8F                      ADDQ.L    #6,A7
05BCB4  4E75                      RTS

05BCB6  204F                      MOVEA.L   A7,A0
05BCB8  48E7FF7E                  MOVEM.L   A1-A6/D0-D7,-(A7)
05BCBC  2C48                      MOVEA.L   A0,A6
05BCBE  61E8                      BSR.S     -24(PC)              SuperOn
05BCC0  40C6                      MOVE      SR,D6
05BCC2  2E00                      MOVE.L    D0,D7
05BCC4  007C0700                  ORI.W     #$700,SR
05BCC8  43FAFFBE                  LEA       -66(PC),A1           L0000
05BCCC  45FA000C                  LEA       12(PC),A2            decryptBlock
05BCD0  323C0105                  MOVE.W    #$105,D1
05BCD4  3019                decryptBlockLoop:MOVE.W    (A1)+,D0
05BCD6  B15A                      EOR.W     D0,(A2)+
05BCD8  51C9FFFA                  DBF       D1,-6(PC)            decryptBlockLoop
05BCDC                      decryptBlock EQU       *-2
05BCDC  46C6                      MOVE      D6,SR
05BCDE  2C6E0004                  MOVEA.L   4(A6),A6
05BCE2  2A6E0018                  MOVEA.L   24(A6),A5
05BCE6  91C8                      SUBA.L    A0,A0
05BCE8  317C40650024              MOVE.W    #$4065,36(A0)       ;$24
05BCEE  317C32070026              MOVE.W    #$3207,38(A0)       ;$26
05BCF4  2007                      MOVE.L    D7,D0
05BCF6  61B2                      BSR.S     -78(PC)              SuperOff

05BCF8  7800                      MOVEQ     #0,D4               ;drive = A
05BCFA  61000080            L0006:BSR       128(PC)              flush9Buffers

05BCFE  7401                      MOVEQ     #1,D2               ;start at setor 1
05BD00  7609                      MOVEQ     #9,D3               ;9 sectors
05BD02  204D                      MOVEA.L   A5,A0               ;$1200 bytes
05BD04  6100008C                  BSR       140(PC)              readSectors
05BD08  6666                      BNE.S     102(PC)              L000D => read error

;check that all 9 sectors don't contain 0xA1,0xA1,0xA1 + sync header
;_and_ that all were 512 bytes long.
05BD0A  204D                      MOVEA.L   A5,A0               ;sector buffer start
05BD0C  7408                      MOVEQ     #8,D2               ;9 sectors
05BD0E  303CA1A1                  MOVE.W    #$A1A1,D0
05BD12  323C00FF            L0007:MOVE.W    #$FF,D1
05BD16  B058                L0008:CMP.W     (A0)+,D0            ;search for first sync inside the sector
05BD18  57C9FFFC                  DBEQ      D1,-4(PC)            L0008
05BD1C  6624                      BNE.S     36(PC)               L000A
05BD1E  16280001                  MOVE.B    1(A0),D3            ;0xFE = address header
05BD22  B010                      CMP.B     (A0),D0             ;another sync?
05BD24  6708                      BEQ.S     8(PC)                L0009
05BD26  1610                      MOVE.B    (A0),D3             ;address header
05BD28  B029FFFD                  CMP.B     -3(A1),D0           ;sync before?
05BD2C  66E8                      BNE.S     -24(PC)              L0008 => continue searching
05BD2E  B63C00FE            L0009:CMP.B     #$FE,D3             ;address header found?
05BD32  670001A0                  BEQ       416(PC)              eraseAndTerminate
05BD36  B63C00FB                  CMP.B     #$FB,D3             ;data header found?
05BD3A  67000198                  BEQ       408(PC)              eraseAndTerminate
05BD3E  5341                      SUBQ.W    #1,D1
05BD40  6AD4                      BPL.S     -44(PC)              L0008
05BD42  0CA8484C5320FFFC    L000A:CMPI.L    #$484C5320,-4(A0)   ;last long in the sector is "HLS "?
05BD4A  57CAFFC6                  DBEQ      D2,-58(PC)           L0007
05BD4E  67000184                  BEQ       388(PC)              eraseAndTerminate

The header of sector 0xF7 is written right before sector 0x09.
After 0x09, comes 0x05 (which is empty, filled with 0xE6) and then 0xF5 (also empty with 0xE6 and no read error!), 0xF6 (which continues over the index mark)

TrackLength:0x0018d0, fuzzySectorLength:0x000000, SectorCount:12 Flags:0x0001 TrackBytes:0x187f Track:0x4f
SectorOffset:0x0000, PosTiming:  592, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0x01 SectorSize:0x02 CRC:0x701d=OK] FDCStatus:0x00 Flags:0x00
SectorOffset:0x0200, PosTiming: 5248, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0x06 SectorSize:0x02 CRC:0xe98a=OK] FDCStatus:0x00 Flags:0x00
SectorOffset:0x0400, PosTiming: 9904, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0x02 SectorSize:0x02 CRC:0x254e=OK] FDCStatus:0x00 Flags:0x00
SectorOffset:0x0600, PosTiming:14561, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0x07 SectorSize:0x02 CRC:0xdabb=OK] FDCStatus:0x00 Flags:0x00
SectorOffset:0x0800, PosTiming:19217, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0x03 SectorSize:0x02 CRC:0x167f=OK] FDCStatus:0x00 Flags:0x00
SectorOffset:0x0a00, PosTiming:23873, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0x08 SectorSize:0x02 CRC:0xca85=OK] FDCStatus:0x00 Flags:0x00
SectorOffset:0x0c00, PosTiming:28530, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0x04 SectorSize:0x02 CRC:0x8fe8=OK] FDCStatus:0x00 Flags:0x00
SectorOffset:0x0e00, PosTiming:33186, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0xf7 SectorSize:0x02 CRC:0xc97a=OK] FDCStatus:0x08 Flags:0x00
SectorOffset:0x1000, PosTiming:33904, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0x09 SectorSize:0x02 CRC:0xf9b4=OK] FDCStatus:0x00 Flags:0x00
SectorOffset:0x1200, PosTiming:38560, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0x05 SectorSize:0x02 CRC:0xbcd9=OK] FDCStatus:0x00 Flags:0x00
SectorOffset:0x1400, PosTiming:43216, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0xf5 SectorSize:0x02 CRC:0xaf18=OK] FDCStatus:0x00 Flags:0x00
SectorOffset:0x1600, PosTiming:47873, ReadTiming:    0 [Address Block: Track:0x4f Side:0x00 Sector:0xf6 SectorSize:0x02 CRC:0xfa4b=OK] FDCStatus:0x08 Flags:0x00

;now read the 3 other sectors
05BD52  47FAFF34                  LEA       -204(PC),A3          L0000
05BD56  7E02                      MOVEQ     #2,D7
05BD58  301B                L000B:MOVE.W    (A3)+,D0            ;buffer offset
05BD5A  341B                      MOVE.W    (A3)+,D2            ;sector number
05BD5C  41F50000                  LEA       0(A5,D0.W),A0
05BD60  7601                      MOVEQ     #1,D3               ;1 sector
05BD62  612E                      BSR.S     46(PC)               readSectors
05BD64  6704                      BEQ.S     4(PC)                L000C
05BD66  B07CFFFC                  CMP.W     #-4,D0              ;CRC error
05BD6A  56CFFFEC            L000C:DBNE      D7,-20(PC)           L000B
05BD6E  6742                      BEQ.S     66(PC)               L0011 => protection OK!
05BD70  5244                L000D:ADDQ.W    #1,D4               ;drive + 1
05BD72  B87C0002                  CMP.W     #2,D4               ;drive = B?
05BD76  6D82                      BLT.S     -126(PC)             L0006
05BD78  6000015A                  BRA       346(PC)              eraseAndTerminate

05BD7C  204D                flush9Buffers:MOVEA.L   A5,A0
05BD7E  7208                      MOVEQ     #8,D1
05BD80  203C484C5320              MOVE.L    #$484C5320,D0       ;(#"HLS ")
05BD86  D0FC01FC            L000F:ADDA.W    #512-sizeof(long),A0
05BD8A  20C0                      MOVE.L    D0,(A0)+
05BD8C  51C9FFF8                  DBF       D1,-8(PC)            L000F
05BD90  4E75                      RTS

05BD92  704F                readSectors:MOVEQ     #$4F,D0        ;track = 79
05BD94  7200                      MOVEQ     #0,D1               ;side = 0
05BD96  3F03                      MOVE.W    D3,-(A7)            ;int16_t count
05BD98  3F01                      MOVE.W    D1,-(A7)            ;int16_t sideno
05BD9A  3F00                      MOVE.W    D0,-(A7)            ;int16_t trackno
05BD9C  3F02                      MOVE.W    D2,-(A7)            ;int16_t sectno
05BD9E  3F04                      MOVE.W    D4,-(A7)            ;int16_t devno
05BDA0  42A7                      CLR.L     -(A7)               ;int32_t filler
05BDA2  2F08                      MOVE.L    A0,-(A7)            ;void *buf
05BDA4  3F3C0008                  MOVE.W    #8,-(A7)
05BDA8  4E4E                      TRAP      #14
05BDAA  DEFC0014                  ADDA.W    #20,A7
05BDAE  4A80                      TST.L     D0
05BDB0  4E75                      RTS


05BDB2  41ED1000            L0011:LEA       $1000(A5),A0
05BDB6  43ED0200                  LEA       $200(A5),A1
05BDBA  303C007F                  MOVE.W    #$7F,D0
05BDBE  22D8                L0012:MOVE.L    (A0)+,(A1)+         ;Copy Sector 9 onto Sector 2
05BDC0  51C8FFFC                  DBF       D0,-4(PC)            L0012

Buffer after the reading:
A5: 0x0000..0x01FF Sector 0xF7
    0x0200..0x03FF Sector 9     (was sector 2)
    0x0400..0x05FF Sector 0xF5
    0x0600..0x07FF Sector 0xF6
    ;the following sectors are not used for the checksum:
    0x0800..0x09FF Sector 5
    0x0A00..0x0BFF Sector 6
    0x0C00..0x0DFF Sector 7
    0x0E00..0x0FFF Sector 8
    0x1000..0x11FF Sector 9

05BDC4  6100FEE2                  BSR       -286(PC)             SuperOn
05BDC8  2F00                      MOVE.L    D0,-(A7)

05BDCA  43F9FFFFEBAC              LEA       $FFFFEBAC.L,A1
05BDD0  204D                      MOVEA.L   A5,A0
05BDD2  3A3C0349                  MOVE.W    #$349,D5            ;842 words (3 sectors and 148/$94 bytes of the last ~60 bytes before index impulse triggers)
05BDD6  30291478                  MOVE.W    5240(A1),D0         ;$24 = $4065
05BDDA  5345                      SUBQ.W    #1,D5
05BDDC  3218                L0013:MOVE.W    (A0)+,D1
05BDDE  780F                      MOVEQ     #15,D4              ;16 bits per word
05BDE0  7400                L0014:MOVEQ     #0,D2
05BDE2  E349                      LSL.W     #1,D1
05BDE4  E252                      ROXR.W    #1,D2
05BDE6  B540                      EOR.W     D2,D0
05BDE8  E348                      LSL.W     #1,D0
05BDEA  6406                      BCC.S     6(PC)                L0015
05BDEC  3629147A                  MOVE.W    5242(A1),D3          ;$26 = $3207
05BDF0  B740                      EOR.W     D3,D0
05BDF2  51CCFFEC            L0015:DBF       D4,-20(PC)           L0014
05BDF6  51CDFFE4                  DBF       D5,-28(PC)           L0013
;checksum in D0

;Calculate the checksum over the protection code
05BDFA  41FAFE8C                  LEA       -372(PC),A0          L0000
05BDFE  3A3A00FE                  MOVE.W    254(PC),D5           L0024
05BE02  3340147A                  MOVE.W    D0,5242(A1)          ;$26 = contains last checksum
05BE06  3003                      MOVE.W    D3,D0
05BE08  5345                      SUBQ.W    #1,D5
05BE0A  3218                L0016:MOVE.W    (A0)+,D1
05BE0C  780F                      MOVEQ     #15,D4
05BE0E  7400                L0017:MOVEQ     #0,D2
05BE10  E349                      LSL.W     #1,D1
05BE12  E252                      ROXR.W    #1,D2
05BE14  B540                      EOR.W     D2,D0
05BE16  E348                      LSL.W     #1,D0
05BE18  6406                      BCC.S     6(PC)                L0018
05BE1A  3629147A                  MOVE.W    5242(A1),D3          ;$26 = $3207
05BE1E  B740                      EOR.W     D3,D0
05BE20  51CCFFEC            L0018:DBF       D4,-20(PC)           L0017
05BE24  51CDFFE4                  DBF       D5,-28(PC)           L0016
05BE28  3600                      MOVE.W    D0,D3                ;new checksum in D3


;copy code fragment to our function parameter
05BE2A  41FAFE68                  LEA       -408(PC),A0          L0001
05BE2E  226E0008                  MOVEA.L   8(A6),A1
05BE32  7209                      MOVEQ     #9,D1
05BE34  32D8                L0019:MOVE.W    (A0)+,(A1)+
05BE36  51C9FFFC                  DBF       D1,-4(PC)            L0019

;decrypt code with the checksum in D3
05BE3A  243C000045D2              MOVE.L    #$45D2,D2
05BE40  2802                      MOVE.L    D2,D4
05BE42  4844                      SWAP      D4
05BE44  023C0000                  ANDI.B    #0,CCR
05BE48  600C                      BRA.S     12(PC)               L001B
05BE4A  3019                L001A:MOVE.W    (A1)+,D0
05BE4C  40C1                      MOVE      SR,D1
05BE4E  B340                      EOR.W     D1,D0
05BE50  B740                      EOR.W     D3,D0
05BE52  B151                      EOR.W     D0,(A1)
05BE54  E253                      ROXR.W    #1,D3
05BE56  51CAFFF2            L001B:DBF       D2,-14(PC)           L001A
05BE5A  51CCFFEE                  DBF       D4,-18(PC)           L001A

05BE5E  201F                      MOVE.L    (A7)+,D0
05BE60  6100FE48                  BSR       -440(PC)             SuperOff

;relocate binary
05BE64  2A3C00000630              MOVE.L    #$630,D5
05BE6A  9BAE0014                  SUB.L     D5,20(A6)
05BE6E  9BAE0018                  SUB.L     D5,24(A6)
05BE72  203C00000000              MOVE.L    #0,D0
05BE78  2D40001C                  MOVE.L    D0,28(A6)
05BE7C  206E0008                  MOVEA.L   8(A6),A0
05BE80  226E0018                  MOVEA.L   24(A6),A1
05BE84  2008                      MOVE.L    A0,D0
05BE86  D1D9                      ADDA.L    (A1)+,A0
05BE88  B1C0                      CMPA.L    D0,A0
05BE8A  671C                      BEQ.S     28(PC)               L001F
05BE8C  7200                      MOVEQ     #0,D1
05BE8E  D190                L001C:ADD.L     D0,(A0)
05BE90  1219                L001D:MOVE.B    (A1)+,D1
05BE92  B27C0002                  CMP.W     #2,D1
05BE96  6504                      BCS.S     4(PC)                L001E
05BE98  D0C1                      ADDA.W    D1,A0
05BE9A  60F2                      BRA.S     -14(PC)              L001C
05BE9C  B27C0000            L001E:CMP.W     #0,D1
05BEA0  6706                      BEQ.S     6(PC)                L001F
05BEA2  D0FC00FE                  ADDA.W    #254,A0
05BEA6  60E8                      BRA.S     -24(PC)              L001D

05BEA8  43FA002A            L001F:LEA       42(PC),A1            eraseAndTerminate
05BEAC  244F                      MOVEA.L   A7,A2
05BEAE  7206                      MOVEQ     #6,D1
05BEB0  3F21                L0020:MOVE.W    -(A1),-(A7)
05BEB2  51C9FFFC                  DBF       D1,-4(PC)            L0020
05BEB6  DABC00001208              ADD.L     #$1208,D5
05BEBC  E48D                      LSR.L     #2,D5
05BEBE  2040                      MOVEA.L   D0,A0               ;A0 = 0xCEBA
05BEC0  226E0018                  MOVEA.L   24(A6),A1
05BEC4  4ED7                      JMP       (A7)

05BEC6  4299                L0021:CLR.L     (A1)+
05BEC8  51CDFFFC                  DBF       D5,-4(PC)            L0021
05BECC  2E4A                      MOVEA.L   A2,A7
05BECE  4CDF7EFF                  MOVEM.L   (A7)+,A1-A6/D0-D7
05BED2  4ED0                      JMP       (A0)

05BED4  323C0095            eraseAndTerminate:MOVE.W    #$95,D1
05BED8  43FAFDAE                  LEA       -594(PC),A1          L0000
05BEDC  4299                L0023:CLR.L     (A1)+
05BEDE  51C9FFFC                  DBF       D1,-4(PC)            L0023
05BEE2  42A7                      CLR.L     -(A7)
05BEE4  4E41                      TRAP      #1
05BEE6  23F974105542465951CA      MOVE.L    $74105542.L,$465951CA.L
05BEF0  FFFC                      DC.B      $FF,$FC
05BEF2  43FAFD94                  LEA       -620(PC),A1          L0000
05BEF6  32BC0000                  MOVE.W    #0,(A1)
05BEFA  6000FDD8                  BRA       -552(PC)             decryptBlockLoop
05BEFE  013BF7F7F7F7F7F7    L0024:DC.B      $01,$3B,$F7,$F7,$F7,$F7,$F7,$F7
05BF06  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BF0E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BF16  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BF1E  0000000000000000          DC.B      $00,$00,$00,$00,$00,$00,$00,$00
05BF26  00000000A1A1A1FE          DC.B      $00,$00,$00,$00,$A1,$A1,$A1,$FE
05BF2E  4F000902F9B4F7F7          DC.B      $4F,$00,$09,$02,$F9,$B4,$F7,$F7
05BF36  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BF3E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BF46  F7F7F7F700000000          DC.B      $F7,$F7,$F7,$F7,$00,$00,$00,$00
05BF4E  0000000000000000          DC.B      $00,$00,$00,$00,$00,$00,$00,$00
05BF56  A1A1A1FBF0F1F2F3          DC.B      $A1,$A1,$A1,$FB,$F0,$F1,$F2,$F3
05BF5E  F4F5F6F7F8F9FAFB          DC.B      $F4,$F5,$F6,$F7,$F8,$F9,$FA,$FB
05BF66  FCFDFEFF484C5320          DC.B      $FC,$FD,$FE,$FF,$48,$4C,$53,$20
05BF6E  4455504C49434154          DC.B      $44,$55,$50,$4C,$49,$43,$41,$54
05BF76  494F4EF7F7F7F7F7          DC.B      $49,$4F,$4E,$F7,$F7,$F7,$F7,$F7
05BF7E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BF86  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BF8E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BF96  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BF9E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFA6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFAE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFB6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFBE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFC6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFCE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFD6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFDE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFE6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFEE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFF6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05BFFE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C006  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C00E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C016  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C01E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C026  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C02E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C036  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C03E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C046  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C04E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C056  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C05E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C066  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C06E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C076  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C07E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C086  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C08E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C096  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C09E  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0A6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0AE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0B6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0BE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0C6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0CE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0D6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0DE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0E6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0EE  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0F6  F7F7F7F7F7F7F7F7          DC.B      $F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7
05C0FE  F7F79EFC24F42A3C          DC.B      $F7,$F7,$9E,$FC,$24,$F4,$2A,$3C
05C106  1208E2BDBBEE227A          DC.B      $12,$08,$E2,$BD,$BB,$EE,$22,$7A
05C10E  9BB64ECF62A551CD          DC.B      $9B,$B6,$4E,$CF,$62,$A5,$51,$CD
05C116  FFFC030A4CC35E91          DC.B      $FF,$FC,$03,$0A,$4C,$C3,$5E,$91
05C11E  4ED81052008D63F2          DC.B      $4E,$D8,$10,$52,$00,$8D,$63,$F2
05C126  2C77F35936D58DFC          DC.B      $2C,$77,$F3,$59,$36,$D5,$8D,$FC
05C12E  93375C5823F97410          DC.B      $93,$37,$5C,$58,$23,$F9,$74,$10
05C136  5542465951CAFFFC          DC.B      $55,$42,$46,$59,$51,$CA,$FF,$FC
05C13E  43FAFD9432BC0000          DC.B      $43,$FA,$FD,$94,$32,$BC,$00,$00
05C146  6000FDD8013B0000          DC.B      $60,$00,$FD,$D8,$01,$3B,$00,$00
05C14E  00100000013FE6E6          DC.B      $00,$10,$00,$00,$01,$3F,$E6,$E6
05C156  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C15E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C166  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C16E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C176  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C17E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C186  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C18E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C196  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C19E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1A6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1AE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1B6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1BE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1C6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1CE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1D6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1DE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1E6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1EE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1F6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C1FE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C206  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C20E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C216  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C21E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C226  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C22E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C236  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C23E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C246  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C24E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C256  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C25E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C266  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C26E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C276  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C27E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C286  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C28E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C296  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C29E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2A6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2AE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2B6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2BE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2C6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2CE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2D6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2DE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2E6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2EE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2F6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C2FE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C306  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C30E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C316  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C31E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C326  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C32E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C336  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C33E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C346  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C34E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C356  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C35E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C366  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C36E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C376  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C37E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C386  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C38E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C396  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C39E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3A6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3AE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3B6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3BE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3C6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3CE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3D6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3DE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3E6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3EE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3F6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C3FE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C406  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C40E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C416  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C41E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C426  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C42E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C436  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C43E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C446  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C44E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C456  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C45E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C466  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C46E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C476  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C47E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C486  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C48E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C496  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C49E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4A6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4AE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4B6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4BE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4C6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4CE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4D6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4DE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4E6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4EE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4F6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C4FE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C506  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C50E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C516  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C51E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C526  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C52E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C536  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C53E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C546  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C54E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C556  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C55E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C566  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C56E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C576  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C57E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C586  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C58E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C596  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C59E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5A6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5AE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5B6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5BE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5C6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5CE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5D6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5DE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5E6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5EE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5F6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C5FE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C606  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C60E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C616  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C61E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C626  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C62E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C636  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C63E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C646  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C64E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C656  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C65E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C666  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C66E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C676  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C67E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C686  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C68E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C696  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C69E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6A6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6AE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6B6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6BE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6C6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6CE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6D6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6DE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6E6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6EE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6F6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C6FE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C706  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C70E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C716  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C71E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C726  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C72E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C736  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C73E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C746  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C74E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C756  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C75E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C766  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C76E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C776  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C77E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C786  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C78E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C796  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C79E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7A6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7AE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7B6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7BE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7C6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7CE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7D6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7DE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7E6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7EE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7F6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C7FE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C806  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C80E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C816  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C81E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C826  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C82E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C836  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C83E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C846  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C84E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C856  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C85E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C866  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C86E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C876  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C87E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C886  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C88E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C896  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C89E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8A6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8AE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8B6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8BE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8C6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8CE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8D6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8DE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8E6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8EE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8F6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C8FE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C906  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C90E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C916  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C91E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C926  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C92E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C936  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C93E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C946  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C94E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C956  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C95E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C966  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C96E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C976  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C97E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C986  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C98E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C996  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C99E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9A6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9AE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9B6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9BE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9C6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9CE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9D6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9DE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9E6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9EE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9F6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05C9FE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA06  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA0E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA16  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA1E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA26  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA2E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA36  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA3E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA46  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA4E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA56  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA5E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA66  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA6E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA76  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA7E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA86  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA8E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA96  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CA9E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CAA6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CAAE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CAB6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CABE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CAC6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CACE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CAD6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CADE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CAE6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CAEE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CAF6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CAFE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB06  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB0E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB16  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB1E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB26  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB2E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB36  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB3E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB46  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB4E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB56  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB5E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB66  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB6E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB76  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB7E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB86  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB8E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB96  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CB9E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBA6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBAE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBB6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBBE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBC6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBCE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBD6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBDE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBE6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBEE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBF6  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CBFE  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CC06  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CC0E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CC16  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CC1E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CC26  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CC2E  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CC36  E6E6E6E6E6E6E6E6          DC.B      $E6,$E6,$E6,$E6,$E6,$E6,$E6,$E6
05CC3E  E6E6E6E6                  DC.B      $E6,$E6,$E6,$E6