        CASE ON         ; Enable case sensitivity for labels

;   Imported addresses
        IMPORT  G3958_
        IMPORT  G3979_
        IMPORT  _IMUL
        IMPORT  _LADD
        IMPORT  F0070_          ; F0070_MOUSE_ProcessCommands125To128_ClickOnChampionIcon
        IMPORT  F0302_CHAMPION_ProcessCommands28To65_ClickOnSlotBox
        IMPORT  F0355_          ; F0355_INVENTORY_Toggle_CPSE
        IMPORT  F0360_          ; F0360_COMMAND_ProcessPendingClick
        IMPORT  F0365_          ; F0365_COMMAND_ProcessTypes1To2_TurnParty
        IMPORT  F0366_          ; F0366_COMMAND_ProcessTypes3To6_MoveParty
        IMPORT  F0367_          ; F0367_COMMAND_ProcessTypes12To27_ClickInChampionStatusBox
        IMPORT  F0433_          ; F0433_STARTEND_ProcessCommand140_SaveGame_CPSCDF
        IMPORT  F0464_          ; F0464_CPSC_GetChecksumSub
        IMPORT  F2151_01234567890123456789      ; F2151_
        IMPORT  F2152_
        IMPORT  F2155_

;   Forward addresses and entries
        ENTRY   F2206_CPSX
        ENTRY   L021144_Subroutine
        ENTRY   L02115C_Subroutine
        ENTRY   L0211AD_Subroutine
        ENTRY   L0211F7_Subroutine
        ENTRY   L02126F
        ENTRY   L021272
        ENTRY   L021277
        ENTRY   L02127C
        ENTRY   L02127F
        ENTRY   L021285
        ENTRY   L0214D1
        ENTRY   L021596_Subroutine
        ENTRY   L0215E7_Subroutine

        ENTRY   L021495_Subroutine
        ENTRY   L0214F9
        ENTRY   L021502
        ENTRY   L021507
        ENTRY   L02150E
        ENTRY   L021510
        ENTRY   L021512
        ENTRY   L02151B
        ENTRY   L02157E_Subroutine
        ENTRY   L021631_Subroutine
        ENTRY   L02165E
        ENTRY   L021661
        ENTRY   L021666
        ENTRY   L02166B
        ENTRY   L021849_Subroutine
        ENTRY   L021885
        ENTRY   L0218AD
        ENTRY   L0218B6
        ENTRY   L0218BB
        ENTRY   L0218C2
        ENTRY   L0218C4
        ENTRY   L0218C6
        ENTRY   L0218CF


; Regular sector (described only for comparison with the copy protection sector)
; 709 bytes total
;   3 bytes $D5 $AA $AD Sector data field prologue
;   1 byte  sector number
; 699 bytes data bytes (consists of 12 tag bytes + 512 data bytes, encoded with GCR 6 and 2)
;   4 bytes checksum (3 checksum bytes encoded with GRC 6 and 2)
;   2 bytes $DE $AA Sector data field epilogue

; Copy protection sector content
; 709 bytes total
;   3 bytes $D5 $AA $AD Sector data field prologue. Checked by the copy protection code
;   6 bytes unknown values. Never checked by the game. Different values on each copy of the game similar to the serial number in the Atari ST / Amiga copy protected sector. If the sector was a regular sector, the first byte should be the sector number. As its value does not match the sector number in the preceding sector address field, a read attempt using the sector number will fail.
;   4 bytes $FF $FF $FF $FF     Checked by the copy protection code
; 690 bytes 345 pairs of bytes: one containing fuzzy bits (resulting value $A9 or $AA or $B2) and one normal byte $EF. Checked by the copy protection code (alternating values of $EF and one of the three possible values of $A9, $AA and $B2)
;   4 bytes $FF $FF $FF $FF     Checked by the copy protection code
;   2 bytes $DE $AA Sector data field epilogue. Checked by the copy protection code


; 10dc
        EXPORT  F2206_CPSX
        SEG 'main'
F2206_CPSX  PROC
; ----------- This part is not in F2207_CPSX
        PHP
        SEP     #$20
        LONGA OFF
        LDA     $c031   ; DISKREG Disk Interface register
        ORA     #$80    ; Select head 1 on 3.5" disk drive
        STA     $c031   ; DISKREG Disk Interface register
        PLP
; ----------- The next part until the end is identical to F2207_CPSX
        PHP
        REP     #$30
        LONGA ON
        LONGI ON
        PHD
        LDA     >G3958_
        TCD
        PHB
        PHK
        PLB
        JSR     |L0211AD_Subroutine
        BCS     L021138
; Loop to ensure that the next 11 sectors on the track do not have an identical address field (this could be used to trick the copy protection by having two sectors with the
; same identification and two different content so that the game would randomly get data from each sector and still believe the disk is original)
        LDA     #$0b
        STA     $2c
L0210FE JSR     |L02115C_Subroutine
        BCS     L02110B
        JSR     |L0211AD_Subroutine
        JSR     |L021144_Subroutine
        BCC     L021138
L02110B DEC     $2c
        BNE     L0210FE
; All sectors on the track have been read once, read again the 12th sector which is the same as the very first one that was read but this time keep the data in the buffer
        JSR     |L02115C_Subroutine
        BCS     L021138
        JSR     |L0211F7_Subroutine
        BCS     L021138
        JSR     |L021144_Subroutine
        BCS     L021138
        SEP     #$30
        LONGA OFF
        LONGI OFF
        LDA     $c0e3
        LDA     $c0e4
        LDA     $c0ed
        LDA     $c0ee
        STA     $c0ec
        BMI     L021138
        REP     #$30
        LONGA ON
        LONGI ON
        PLB
        PLD
        PLP
        CLC
        RTL
L021138 REP     #$30
        LONGA ON
        LONGI ON
        LDA     #$00
        STA     [$21]
        PLB
        PLD
        PLP
        SEC
        RTL
        ENDP

; Compare read address field values with expected values
        EXPORT    L021144_Subroutine
L021144_Subroutine      PROC      ; Routine identical to L02157E_Subroutine
        SEP     #$20
        LONGA OFF
        LDX     #$04
L021149 LDA     |L021277,X      ; Read values
        CMP     |L021272,X      ; Expected values
        BNE     L021158
        DEX
        BPL     L021149         ; Loop to compare 5 bytes of sector address field
        REP     #$20            ; Return with Carry clear = no error (identical)
        LONGA ON
        CLC
        RTS
L021158 REP     #$20            ; Return with Carry set = error (not identical)
        LONGA ON
        SEC
        RTS
        ENDP

        EXPORT    L02115C_Subroutine
L02115C_Subroutine      PROC      ; Routine identical to L021596_Subroutine
        SEP     #$30
        LONGA OFF
        LONGI OFF
        LDA     #$07
        STA     $2b
        LDY     #$9e
L021164 LDX     #$02
L021166 DEY
        BNE     L02116D
        DEC     $2b
        BMI     L0211A9
L02116D LDA     $c0ec
        BPL     L02116D
        CMP     |L02126F,X
        BNE     L021164
        DEX
        BPL     L021166
; Loop to read and convert (using 256 bytes table) 5 bytes and store decoded bytes in buffer at
        LDY     #$04
        STZ     $2b
L02117E LDX     $c0ec
        BPL     L02117E
        LDA     |L021285,X
        STA     |L021277,Y
        EOR     $2b
        STA     $2b
        DEY
        BPL     L02117E
; Read trailing marks
        TAY
        BNE     L0211A9
L021193 LDA     $c0ec
        BPL     L021193
        CMP     #$de
        BNE     L0211A9
L02119C LDA     $c0ec
        BPL     L02119C
        CMP     #$aa
        BNE     L0211A9
        REP     #$30
        LONGA ON
        LONGI ON
        CLC
        RTS
L0211A9 REP     #$30
        LONGA ON
        LONGI ON
        SEC
        RTS
        ENDP

        EXPORT    L0211AD_Subroutine
L0211AD_Subroutine      PROC      ; Routine identical to L0215E7_Subroutine
        SEP     #$20
        LONGA OFF
        REP     #$10
        LONGI ON
        LDX     #$19
L0211B4 DEX
        BEQ     L0211F3
L0211B7 LDA     $c0ec
        BPL     L0211B7
        CMP     #$d5
        BNE     L0211B4
L0211C0 LDA     $c0ec
        BPL     L0211C0
        CMP     #$aa
        BNE     L0211B4
L0211C9 LDA     $c0ec
        BPL     L0211C9
        CMP     #$ad
        BNE     L0211B4
; Pattern D5, AA, AD (Data marks) was found, marking start of sector data
        LDX     #$2c0
L0211D5 LDA     $c0ec
        BPL     L0211D5
        DEX
        BNE     L0211D5
L0211DD LDA     $c0ec
        BPL     L0211DD
        CMP     #$de
        BNE     L0211F3
L0211E6 LDA     $c0ec
        BPL     L0211E6
        CMP     #$aa
        BNE     L0211F3
        REP     #$30
        LONGA ON
        LONGI ON
        CLC
        RTS
L0211F3 REP     #$30
        LONGA ON
        LONGI ON
        SEC
        RTS
        ENDP

; Read data field data and store only 690 bytes in buffer (instead of the full 709 bytes)
        EXPORT    L0211F7_Subroutine
L0211F7_Subroutine      PROC      ; Routine NOT identical to L021631_Subroutine
        SEP     #$20
        LONGA OFF
        REP     #$10
        LONGI ON
; Search for $D5 $AA $AD marks in the first 25 bytes
        LDY     #$19
L0211FE LDX     #$02
L021201 DEY
        BEQ     L02126B
L021204 LDA     $c0ec
        BPL     L021204
        CMP     |L02127C,X
        BNE     L0211FE
        DEX
        BPL     L021201
; Loop to read and ignore the first 6 bytes after the marks
        LDX     #$06
L021214 LDA     $c0ec
        BPL     L021214
        DEX
        BNE     L021214
; Loop to read and check values of the next 4 bytes, but do not store them
        LDX     #$04
L02121F LDA     $c0ec
        BPL     L02121F
        CMP     #$ff
        BNE     L02126B
        DEX
        BNE     L02121F
; Loop to read, check the values and store the next 690 bytes in the buffer
        LDY     #$00
L02122E TYA
        AND     #$01
        BNE     L021246
L021233 LDA     $c0ec
        BPL     L021233
        CMP     #$a9            ; First possible value for byte containing fuzzy bits
        BEQ     L02124F
        CMP     #$aa            ; Second possible value for byte containing fuzzy bits
        BEQ     L02124F
        CMP     #$b2            ; Third possible value for byte containing fuzzy bits
        BEQ     L02124F
        BRA     L02126B
L021246 LDA     $c0ec
        BPL     L021246
        CMP     #$ef            ; Constant byte value (alternating with byte containing fuzzy bits)
        BNE     L02126B
L02124F STA     [$21],Y         ; Store read byte in the buffer
        INY
        CPY     #$2b2           ; Store 690 bytes (data field prologue, checksum and epilogue are not stored)
        BCC     L02122E
; Loop to read and check values of the next 6 bytes, but do not store them
        LDX     #$05
L02125A LDA     $c0ec
        BPL     L02125A
        CMP     |L02127F,X
        BNE     L02126B
        DEX
        BPL     L02125A
        REP     #$30            ; Return with Carry clear = no error
        LONGA ON
        LONGI ON
        CLC
        RTS
L02126B REP     #$30            ; Return with Carry set = error
        LONGA ON
        LONGI ON
        SEC
        RTS
        ENDP

        EXPORT    L02126F
L02126F PROC
        DC.B    $96,$AA,$D5     ; Identical to bytes at L02165E
        EXPORT    L021272
L021272
        DC.B    $09,$22,$20,$0B,$00     ; Identical to bytes at L021661
        EXPORT    L021277
L021277
        DC.B    $00,$00,$00,$00,$00     ; Identical to bytes at L021666
        EXPORT    L02127C
L02127C
        DC.B    $AD,$AA,$D5     ; Sector data field prologue (in reverse order)
        EXPORT    L02127F
L02127F
        DC.B    $AA,$DE,$FF,$FF,$FF,$FF
; 256 bytes, identical to other similar block below
; This table is a 'reverse' '6 and 2 write translation table'
; For each 8-bit byte read from disk, it will give the corresponding 6-bit byte value.
; 192 values are not used because there are only 64 valid 8-bit byte values that can be read from disk
        EXPORT    L021285
L021285
        DC.B    $20,$AF,$5D,$9C,$51,$0F,$A9,$A5,$CD,$B6,$0F,$F0,$23,$8D,$B6,$0F
        DC.B    $A9,$03,$20,$AE,$5F,$20,$52,$56,$38,$6E,$56,$0F,$A9,$FA,$8D,$26
        DC.B    $0F,$8D,$27,$0F,$20,$5D,$56,$20,$6B,$56,$20,$E0,$5D,$20,$AB,$64
        DC.B    $2C,$56,$0F,$30,$0C,$AE,$56,$0F,$8E,$28,$0F,$20,$16,$5E,$20,$CC
        DC.B    $5E,$20,$58,$58,$2C,$E8,$C0,$9C,$31,$C0,$18,$AD,$4B,$0F,$F0,$01
        DC.B    $38,$60,$A9,$04,$8D,$4F,$0F,$A9,$80,$8D,$50,$0F,$60,$A2,$41,$BF
        DC.B    $00,$58,$FF,$9F,$6D,$0F,$E1,$CA,$10,$F5,$60,$A2,$15,$BF,$42,$58
        DC.B    $FF,$9D,$57,$0F,$CA,$10,$F6,$60,$A9,$28,$38,$8D,$4B,$0F,$60,$20
        DC.B    $A4,$5C,$A9,$01,$85,$45,$A9,$FF,$8D,$51,$0F,$20,$7A,$59,$B0,$00
        DC.B    $60,$96,$19,$19,$19,$19,$00,$01,$98,$99,$02,$03,$9C,$04,$05,$06
        DC.B    $A0,$A1,$A2,$A3,$A4,$A5,$07,$08,$A8,$A9,$AA,$09,$0A,$0B,$0C,$0D
        DC.B    $B0,$B1,$0E,$0F,$10,$11,$12,$13,$B8,$14,$15,$16,$17,$18,$19,$1A
        DC.B    $C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7,$C8,$C9,$CA,$1B,$CC,$1C,$1D,$1E
        DC.B    $D0,$D1,$D2,$1F,$D4,$D5,$20,$21,$D8,$22,$23,$24,$25,$26,$27,$28
        DC.B    $E0,$E1,$E2,$E3,$E4,$29,$2A,$2B,$E8,$2C,$2D,$2E,$2F,$30,$31,$32
        DC.B    $F0,$F1,$33,$34,$35,$36,$37,$38,$F8,$39,$3A,$3B,$3C,$3D,$3E,$3F
        ENDP

; 1385
        EXPORT    F2150_CPSX
F2150_CPSX  PROC      ; Read twice the fuzzy bits sector and compare them to check for fuzzy bits
        PHD
        LDA     >G3958_
        TCD
        PHB
        PHK
        PLB
        SEP     #$30
        LONGA OFF
        LONGI OFF
        LDX     #$20
L021392 LDA     |L0214D1,X
        STA     $0,X
        DEX
        BPL     L021392
        CLC
        LDA     >$c5ff
        ADC     #$03            ; SmartPort Entry point = value at $c5ff + 3 + $C500
        STA     $2
        STA     $d
        STA     $18
        LDA     #$44
        STA     $4
        STA     $f
        LDA     #$41
        STA     $1a

; Remove hooks
        LDA     #$04
        STA     |L021502
        REP     #$30
        LONGA ON
        LONGI ON
        LDA     #L021507
        STA     $10
        LDA     #^L021507
        STA     $12
L0213C2 CLC
        TDC
        ADC     #$0b
        JSR     |L021495_Subroutine
        SEP     #$20
        LONGA OFF
        LDA     |L021502
        DEC     A
        STA     |L021502
        REP     #$20
        LONGA ON
        BNE     L0213C2

; Reset marks
        LDA     #L02151B
        STA     $10
        LDA     #^L02151B
        STA     $12
        CLC
        TDC
        ADC     #$0b
        JSR     |L021495_Subroutine

; Set hook to F2206_CPSX
        LDA     #L0214F9
        STA     $5
        LDA     #^L0214F9
        STA     $7
        LDA     #L021507
        STA     $10
        LDA     #^L021507
        STA     $12
        LDA     #L02150E
        STA     $1b
        LDA     #^L02150E
        STA     $1d
        CLC
        TDC
        ADC     #$00
        JSR     |L021495_Subroutine

; ---------- Read block. This is not identical to F0527_FLOPPY_ReadFuzzySector_CPSX anymore
        CLC
        LDA     >G3979_
        STA     $21
        STA     $27
        ADC     #$564           ; 1380 = 690 * 2
        STA     |L021510        ; Address of data buffer for 'ReadBlock'
        LDA     >G3979_+2
        STA     $23
        STA     $29
        ADC     #$00
        STA     |L021512        ; Address of data buffer for 'ReadBlock'
        LDA     #$00            ; Write 0 in the first byte of the buffer. If will be $D5 if the reading is successful
        STA     [$21]
        CLC
        TDC
        ADC     #$16            ; Address of third routine to call SmartPort command
        JSR     |L021495_Subroutine        ; Call third routine (ReadBlock). First sector reading
        CLC
        LDA     $21             ; Update target address to store a second sector reading
        ADC     #$2b2           ; 690
        STA     $21
        BCC     L021445
        INC     $23
L021445 LDA     #$00            ; Write 0 in the first byte of the buffer. If will be $D5 if the reading is successful
        STA     [$21]
        CLC
        TDC
        ADC     #$16            ; Address of third routine to call SmartPort command
        JSR     |L021495_Subroutine        ; Call third routine (ReadBlock). Second sector reading

; Reset hook
        SEP     #$20
        LONGA OFF
        LDA     #$02
        STA     |L021502
        REP     #$20
        LONGA ON
        CLC
        TDC
        ADC     #$0b
        JSR     |L021495_Subroutine
; Compare the two sector readings
        LDA     [$21]
        BEQ     L021491         ; Check if first byte is still 0
        LDA     [$27]
        BEQ     L021491         ; Check if first byte is still 0
        LDY     #$2b0           ; 688
        LDX     #$00            ; Count of differences between readings
L021471 LDA     [$21],Y
        EOR     [$27],Y
        STA     $25
        AND     #$e4e4          ; e4 (complement of 1b) is mask to get non fuzzy bits
        BNE     L021491         ; Fail if any non fuzzy bits are not identical in both readings
        LDA     $25
        AND     #$1b1b          ; 1b is mask to get fuzzy bits
        BEQ     L021484         ; Check for differences in fuzzy bits between readings
        INX                     ; One more difference found
L021484 DEY
        DEY
        BPL     L021471         ; Loop 345 times (= 690 / 2)
        CPX     #$00
        BEQ     L021491         ; Fail if no difference was found between both readings of fuzzy bits
        CLC                     ; Return with Carry clear = no error
        PLB
        PLD
        RTL
L021491 SEC                     ; Return with Carry set = error
        PLB
        PLD
        RTL
        ENDP

; Routine to call a routine to call a SmartPort command (identical to L021849_Subroutine)
        EXPORT  L021495_Subroutine
L021495_Subroutine PROC
        SEI
        REP     #$30
        LONGA ON
        LONGI ON
        STA     |L0214C2
        SEP     #$20
        LONGA OFF
        LDA     #$00
        STA     |L0214C4
        REP     #$20
        LONGA ON
        TSC
        TAX
        SEP     #$20
        LONGA OFF
        LDA     #$01
        XBA
        LDA     $10100
        TCS
        PHX
        PHB
        LDA     #$00
        PHA
        PLB
        REP     #$20
        LONGA ON
        PHD
        LDA     #$00
        TCD
        SEP     #$30
        LONGA OFF
        LONGI OFF
        SEC
        XCE
;                JSL   $ff0000
; JMP opcode
        DC.B    $22
        EXPORT L0214C2
L0214C2 DC.B    $00,$00
        EXPORT L0214C4
L0214C4 DC.B    $FF
        PHP
        CLC
        XCE
        PLP
        REP     #$30
        LONGA ON
        LONGI ON
        PLD
        PLB
        PLX
        TXS
        CLI
        RTS
        EXPORT L0214D1
L0214D1 CLI                             ; 58            11 bytes long routine to call SmartPort a command
        JSR     $c500                   ; 20 00 C5
        DC.B    $00,$00,$00,$00,$00
        SEI                             ; 78
        RTL                             ; 6B
        CLI                             ; 58            11 bytes long routine to call SmartPort a command
        JSR     $c500                   ; 20 00 C5
        DC.B    $00,$00,$00,$00,$00
        SEI                             ; 78
        RTL                             ; 6B
        CLI                             ; 58            11 bytes long routine to call SmartPort a command
        JSR     $c500                   ; 20 00 C5
        DC.B    $00,$00,$00,$00,$00
        SEI                             ; 78
        RTL                             ; 6B

        EXPORT L0214F2
L0214F2 DC.B    $04,$00 ; Control list
        DC.B    $82     ; Hook reference number
        DC.L    F2206_CPSX  ; DC 10 00 00
        EXPORT L0214F9
L0214F9 DC.B    $03     ; Parameter list for first 'Control'. Parameter count = 3
        DC.B    $01     ; Unit number = 1
        DC.L    L0214F2 ; F2 14 00 00 Control list pointer
        DC.B    $05     ; Control code (device specific) = SetHook

        EXPORT L021500
L021500 DC.B    $04,$00 ; Control list
        EXPORT L021502
L021502 DC.B    $00,$00,$00,$00,$00     ; Hook reference is set in a loop to disable hooks from #4 down to #1
        EXPORT L021507
L021507 DC.B    $03     ; Parameter list for second 'Control'. Parameter count = 3
        DC.B    $01     ; Unit number = 1
        DC.L    L021500 ; 00 15 00 00
        DC.B    $06     ; Control code (device specific) = ResetHook

        EXPORT L02150E
L02150E DC.B    $03     ; Parameter list for 'ReadBlock'. Parameter count = 3
        DC.B    $01     ; Unit number = 1
        EXPORT L021510
L021510 DC.B    $00,$00 ; Address of data buffer
        EXPORT L021512
L021512 DC.B    $00,$00 ; Address of data buffer
        DC.B    $17,$00,$00,$00 ; Block number = 23

        EXPORT L021518
L021518 DC.B    $16,$00,$00     ; Control list. Reset 21 bytes in the Mark table starting at offset 0 in the table (that's the whole table)
        EXPORT L02151B
L02151B DC.B    $03     ; Parameter list for second 'Control'. Parameter count = 3
        DC.B    $01     ; Unit number = 1
        DC.L    L021518 ; 18 15 00 00
        DC.B    $08     ; Control code (device specific) = ResetMark
        ENDP

; Apple 800K floppy disk use a variable speed and variable number of sectors per track
; Tracks  Revolution per minute  Sectors per track
; ------  ---------------------- -----------------
; 00-15   394                    12
; 16-31   429                    11
; 32-47   472                    10
; 48-63   525                    9
; 64-79   590                    8

; 1522
        EXPORT    F2207_CPSX
F2207_CPSX  PROC              ; Routine used as hook for Read Data Field, replaces the default OS routine to read a data field from the floppy disk
; 157e
; 1596
; 15e7
; 1631
; This routine is called by the OS when the call to ReadBlock is performed by F0527_FLOPPY_ReadFuzzySector_CPSX to read block #23
; The OS has already located the address field and this routine starts right when reading of the data field should start
        PHP
        REP     #$30
        LONGA ON
        LONGI ON
        PHD                     ; Push caller Direct Page to the stack
        LDA     >G3958_         ; Read Direct Page from global variable
        TCD                     ; Restore Direct Page
        PHB                     ; Push data bank register to the stack
        PHK                     ; Push program bank register to the stack
        PLB                     ; Pull data bank register from the stack (the data bank is now the same as the program bank), allowing access to the data stored along with the code
        JSR     |L0215E7_Subroutine        ; Read and skip data field
        BCS     L021572         ; Branch if an error occured
; Loop to ensure that the next 11 sectors on the track do not have and identical address field (this could be used to trick the copy protection by having two sectors
; with the same identification and two different content so that the game would randomly get data from each sector and still believe the disk is original)
        LDA     #$0b            ; Loop
        STA     $2c
L021538 JSR     |L021596_Subroutine        ; Read address field
        BCS     L021545         ; If an error occured while reading address field
        JSR     |L0215E7_Subroutine        ; Read and skip data field
        JSR     |L02157E_Subroutine        ; Compare read address field values with expected values
        BCC     L021572         ; Branch if identical (sector is the one being searched). This cannot occur on the original floppy disk where the 11 sectors otherthan the copy protection one have different values in their address fields
L021545 DEC     $2c
        BNE     L021538         ; Loop 11 times (there are 11 sectors on track 0)
; All sectors on the track have been read once, read again the 12th sector which is the same as the very first one that was read but this time keep the data in the buffer
        JSR     |L021596_Subroutine        ; Read address field
        BCS     L021572         ; Branch if an error occured while reading address field
        JSR     |L021631_Subroutine        ; Read data field and store in buffer
        BCS     L021572         ; Branch if an error occured while reading data field
        JSR     |L02157E_Subroutine        ; Compare read address field values with expected values
        BCS     L021572         ; Branch if not identical (sector is not the one being searched)
        SEP     #$30
        LONGA OFF
        LONGI OFF
; ???
; The IWM chip in the Apple IIGS is configured to reside in internal slot 6. Its I/O locations are the same as the original Disk ][ interface in slot 6:
;       CA0     EQU $C0E0       stepper phase 0 / control line 0
;       CA1     EQU $C0E2       stepper phase 1 / control line 1
;       CA2     EQU $C0E4       stepper phase 2 / control line 2
;       LSTRB   EQU $C0E6       stepper phase 3 / control strobe
;       ENABLE  EQU $C0E8       disk drive off/on
;       SELECT  EQU $C0EA       select drive 1/2
;       Q6      EQU $C0EC
;       Q7      EQU $C0EE
; Each of these I/O locations represents a two-way switch; accessing location X turns off the switch; accessing location X+1 turns it on.

        LDA     $c0e3   ; Turn on CA1
        LDA     $c0e4   ; Turn off CA2
        LDA     $c0ed   ; Turn on Q6    -+
        LDA     $c0ee   ; Turn off Q7   -+- This combination of Q6 and Q7 mean 'Read status register'
        STA     $c0ec   ; STA is not a read operation... confusing
        BMI     L021572
        REP     #$30            ; Return with Carry clear = no error
        LONGA ON
        LONGI ON
        PLB
        PLD
        PLP
        CLC
        RTL
L021572 REP     #$30            ; Return with Carry set = error
        LONGA ON
        LONGI ON
        LDA     #$00
        STA     [$21]           ; Write 0 in the first byte of the buffer. If will be $D5 if the reading is successful
        PLB
        PLD
        PLP
        SEC
        RTL
        ENDP

; Compare read address field values with expected values
        EXPORT L02157E_Subroutine
L02157E_Subroutine PROC
        SEP     #$20
        LONGA OFF
        LDX     #$04
L021583 LDA     |L021666,X      ; Read values
        CMP     |L021661,X      ; Expected values
        BNE     L021592
        DEX
        BPL     L021583         ; Loop to compare 5 bytes of sector address field
        REP     #$20            ; Return with Carry clear = no error (identical)
        LONGA ON
        CLC
        RTS
L021592 REP     #$20            ; Return with Carry set = error (not identical)
        LONGA ON
        SEC
        RTS
        ENDP

; Read address field
; Address field format: $D5, $AA, $96, track, sector, sides, format, checksum, $DE, $AA
; The address fields of a 3.5-inch disk are encoded 6&2 (sort of)
;        Each datum in the address field is a 6-bit number. Their meanings are as follows:
;        track           The low-order six bits of the track number
;        sector          The sector number
;        sides           Bit 0 is the high-order bit of the track number
;                        Bit 5 is the side number (0 for side 1, 1 for side 2)
;                        All other bits are zero (i.e. the number looks like 's0000t')
;        format          The low four bits are the interleave (usually 2, unless the disk was formatted on a Unidisk 3.5)
;                        The high bit is the number of sides (0=single, 1=double)
;                        Bit 4 is always 0 (the number looks like 's0iiii')
;        checksum        A checksum of the previous four values (EOR)
        EXPORT L021596_Subroutine
L021596_Subroutine PROC
        SEP     #$30
        LONGA OFF
        LONGI OFF
        LDA     #$07
        STA     $2b
        LDY     #$9e            ; Loop to find the address marks in the next 8 * 256 + 158 bytes = 2206 bytes
L02159E LDX     #$02
L0215A0 DEY
        BNE     L0215A7         ; Fail if more than 158 bytes have been read without finding the address marks
        DEC     $2b
        BMI     L0215E3
L0215A7 LDA     $c0ec
        BPL     L0215A7
        CMP     |L02165E,X      ; Compare leading address marks
        BNE     L02159E
        DEX
        BPL     L0215A0         ; Loop to compare the 3 address mark bytes: D5 AA 96 (in reverse order)
; Loop to read and convert (using 256 bytes table) 5 bytes and store decoded bytes in buffer at L021666
        LDY     #$04
        STZ     $2b
L0215B8 LDX     $c0ec
        BPL     L0215B8
        LDA     |L02166B,X      ; Convert 8-bit disk byte read from disk to a 6-bit byte value
        STA     |L021666,Y      ; and store it in a buffer
        EOR     $2b             ; Checksum computed from read bytes (included checksum byte read from disk). Resulting value should be 0 when the last of the 5 bytes (which is the stored checksum value) is EORed.
        STA     $2b
        DEY
        BPL     L0215B8
; Read trailing marks
        TAY
        BNE     L0215E3         ; If checksum is not 0 then error
L0215CD LDA     $c0ec
        BPL     L0215CD
        CMP     #$de            ; First EOB mark
        BNE     L0215E3
L0215D6 LDA     $c0ec
        BPL     L0215D6
        CMP     #$aa            ; Second EOB mark
        BNE     L0215E3
        REP     #$30            ; Return with Carry clear = no error
        LONGA ON
        LONGI ON
        CLC
        RTS
L0215E3 REP     #$30            ; Return with Carry set = timeout, checksum, or bit-slip error
        LONGA ON
        LONGI ON
        SEC
        RTS
        ENDP

; Read and skip data field: read marks and data but do not store anywhere and do not validate checksum
; Data field format: $D5, $AA, $AD, track, 699 data bytes, 4 checksum bytes, $DE, $AA
; The 'track' number is identical to the 'track' number from the address field.
        EXPORT L0215E7_Subroutine
L0215E7_Subroutine PROC
        SEP     #$20
        LONGA OFF
        REP     #$10
        LONGI ON
        LDX     #$19            ; 25
L0215EE DEX
        BEQ     L02162D         ; If the pattern D5, AA, AD is not found in the 25 first bytes then error
L0215F1 LDA     $c0ec
        BPL     L0215F1
        CMP     #$d5            ; First data mark
        BNE     L0215EE
L0215FA LDA     $c0ec
        BPL     L0215FA
        CMP     #$aa            ; Second data mark
        BNE     L0215EE
L021603 LDA     $c0ec
        BPL     L021603
        CMP     #$ad            ; Third data mark
        BNE     L0215EE
; Pattern D5, AA, AD (Data marks) was found
        LDX     #$2c0           ; 704
L02160F LDA     $c0ec
        BPL     L02160F
        DEX
        BNE     L02160F         ; Loop to read 704 bytes
L021617 LDA     $c0ec
        BPL     L021617
        CMP     #$de            ; First EOB mark
        BNE     L02162D
L021620 LDA     $c0ec
        BPL     L021620
        CMP     #$aa            ; Second EOB mark
        BNE     L02162D
        REP     #$30            ; Return with Carry clear = no error, successfully read the 3 data marks, followed by 704 bytes and then the 2 EOB marks
        LONGA ON
        LONGI ON
        CLC
        RTS
L02162D REP     #$30            ; Return with Carry set = timeout, checksum, or bit-slip error
        LONGA ON
        LONGI ON
        SEC
        RTS
        ENDP

; Read data field data and store it all in buffer
        EXPORT L021631_Subroutine
L021631_Subroutine PROC
        SEP     #$20
        LONGA OFF
        REP     #$10
        LONGI ON
; Search for $D5 mark in the first 25 bytes
        LDX     #$19
        LDY     #$00
L02163B LDA     $c0ec
        BPL     L02163B
        CMP     #$d5
        BEQ     L02164E
        DEX
        BNE     L02163B
        BRA     L02165A
; Loop to read the 709 bytes of the sector data field
L021649 LDA     $c0ec
        BPL     L021649
L02164E STA     [$21],Y         ; Store byte in buffer
        INY
        CPY     #$2c5           ; 709
        BCC     L021649         ; Loop to read 708 bytes after the $D5 byte
        REP     #$30            ; Return with Carry clear = no error, successfully read the 3 data marks, followed by 704 bytes and then the 2 EOB marks
        LONGA ON
        LONGI ON
        CLC
        RTS
L02165A REP     #$30            ; Return with Carry set = timeout, checksum, or bit-slip error
        LONGA ON
        LONGI ON
        SEC
        RTS

        EXPORT L02165E
L02165E DC.B    $96,$AA,$D5     ; Identical to bytes at L02126F. Address marks (in reverse order)
        EXPORT L021661
L021661 DC.B    $09,$22,$20,$0B,$00     ; Identical to bytes at L021272. Expected sector address field (in reverse order) for track 0, side 2, sector 11 containing the fuzzy bits:
; Each of the 5 bytes only contains 6 bits of significant data (the two high order bits are 0):
; Byte  Bits    Description
; value
; 00    tttttt  Low order 6 bits of track number = 0
; 0B            Sector number = 11 (= logical block 23 because it is on side 2 and track 0/side 0 contains 12 sectors, 12 + 11 = 23)
; 20    s0000t  s is side 2 (0=side 1, 1=side 2). t is high-order bit of track number = 0
; 22    n0iiii  n is number of sides = double-sided (0=single, 1=double). iiii is the interleave = 2
; 09            Checksum of 4 previous bytes: (((00 EOR 0B) EOR 20) EOR 22) = 09

;  09 22 20 0B 00       6-bit bytes as 'decoded' using the table below
;  AB D9 D6 AD 96       8-bit bytes as directly read from disk

        EXPORT L021666
L021666 DC.B    $00,$00,$00,$00,$00     ; Identical to bytes at L021277. Buffer to store the contents of a sector address field (except marks)
; 256 bytes, identical to other similar block above
; This table is a 'reverse' '6 and 2 write translation table'
; For each 8-bit byte read from disk, it will give the corresponding 6-bit byte value.
; 192 values are not used because there are only 64 valid 8-bit byte values that can be read from disk
        EXPORT L02166B
L02166B DC.B    $20,$AF,$5D,$9C,$51,$0F,$A9,$A5,$CD,$B6,$0F,$F0,$23,$8D,$B6,$0F
        DC.B    $A9,$03,$20,$AE,$5F,$20,$52,$56,$38,$6E,$56,$0F,$A9,$FA,$8D,$26
        DC.B    $0F,$8D,$27,$0F,$20,$5D,$56,$20,$6B,$56,$20,$E0,$5D,$20,$AB,$64
        DC.B    $2C,$56,$0F,$30,$0C,$AE,$56,$0F,$8E,$28,$0F,$20,$16,$5E,$20,$CC
        DC.B    $5E,$20,$58,$58,$2C,$E8,$C0,$9C,$31,$C0,$18,$AD,$4B,$0F,$F0,$01
        DC.B    $38,$60,$A9,$04,$8D,$4F,$0F,$A9,$80,$8D,$50,$0F,$60,$A2,$41,$BF
        DC.B    $00,$58,$FF,$9F,$6D,$0F,$E1,$CA,$10,$F5,$60,$A2,$15,$BF,$42,$58
        DC.B    $FF,$9D,$57,$0F,$CA,$10,$F6,$60,$A9,$28,$38,$8D,$4B,$0F,$60,$20
        DC.B    $A4,$5C,$A9,$01,$85,$45,$A9,$FF,$8D,$51,$0F,$20,$7A,$59,$B0,$00
        DC.B    $60,$96,$19,$19,$19,$19,$00,$01,$98,$99,$02,$03,$9C,$04,$05,$06
        DC.B    $A0,$A1,$A2,$A3,$A4,$A5,$07,$08,$A8,$A9,$AA,$09,$0A,$0B,$0C,$0D
        DC.B    $B0,$B1,$0E,$0F,$10,$11,$12,$13,$B8,$14,$15,$16,$17,$18,$19,$1A
        DC.B    $C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7,$C8,$C9,$CA,$1B,$CC,$1C,$1D,$1E
        DC.B    $D0,$D1,$D2,$1F,$D4,$D5,$20,$21,$D8,$22,$23,$24,$25,$26,$27,$28
        DC.B    $E0,$E1,$E2,$E3,$E4,$29,$2A,$2B,$E8,$2C,$2D,$2E,$2F,$30,$31,$32
        DC.B    $F0,$F1,$33,$34,$35,$36,$37,$38,$F8,$39,$3A,$3B,$3C,$3D,$3E,$3F
        ENDP

; 176b
        EXPORT    F0527_FLOPPY_ReadFuzzySector_CPSX
F0527_FLOPPY_ReadFuzzySector_CPSX    PROC      ; Reads the full fuzzy bits sector once and store it in specified buffer
        PHD                     ; Push caller Direct Page to the stack
        LDA     >G3958_         ; Read Direct Page from global variable
        TCD                     ; Restore Direct Page
; ---------- This part is not in F2150_CPSX
        PLA                     ; Pull caller Direct Page from stack
        STA     $29             ; Store caller Direct Page
        PLA                     ; Pull JSL target 16 bit address from stack
        STA     $25             ; Store JSL target 16 bit address
        SEP     #$20
        LONGA OFF
        PLA                     ; Pull JSL target program bank register K from stack
        STA     $27             ; Store JSL target program bank register K
        REP     #$20
        LONGA ON
        PLA                     ; Pull address of buffer (function parameter)
        STA     $21             ; Store address of buffer
        PLA                     ; Pull address of buffer (function parameter)
        STA     $23             ; Store address of buffer
; ---------- This part is in F2150_CPSX
        PHB                     ; Push data bank register to the stack
        PHK                     ; Push program bank register to the stack
        PLB                     ; Pull data bank register from the stack (the data bank is now the same as the program bank, allowing to modify the program itself using Direct Page addressing mode)

; Prepare routines in memory to call SmartPort commands: copy template and customize entry point addresses and command numbers
        SEP     #$30
        LONGA OFF
        LONGI OFF
        LDX     #$20            ; Loop to copy 33 bytes (3 routines of 11 bytes to call SmartPort commands)
L02178B LDA     |L021885,X      ; Read one byte at L021885
        STA     $0,X            ; Write one byte at direct page
        DEX
        BPL     L02178B         ; Loop
        CLC
        LDA     >$c5ff
        ADC     #$03            ; SmartPort slot 5 entry point address = $C500 + value at $c5ff + 3
        STA     $2              ; Update byte at offset 2 to complete the entry point address (the other byte $C5 was already copied)
        STA     $d              ; Update byte at offset 13 to complete the entry point address (the other byte $C5 is already copied)
        STA     $18             ; Update byte at offset 24 to complete the entry point address (the other byte $C5 is already copied)
        LDA     #$44            ; Command number $44 = Extended call to 'Control'
        STA     $4              ; Write command number at offset 4
        STA     $f              ; Write command number at offset 15
        LDA     #$41            ; Command number $41 = Extended call to 'ReadBlock'
        STA     $1a             ; Write command number at offset 26

; Remove hooks
        LDA     #$04            ; Hook reference
        STA     |L0218B6
        REP     #$30
        LONGA ON
        LONGI ON
        LDA     #L0218BB
        STA     $10             ; Address of parameter list pointer (ResetHook) for second routine (Control)
        LDA     #^L0218BB
        STA     $12             ; Address of parameter list pointer (ResetHook) for second routine (Control)
L0217BB CLC                     ; Loop to call ResetHook for hooks #4 (Seek), #3 (Write Data Field), #2 (Read Data Field) and #1 (Read Address Field). The purpose is to disable custom hooks that would be used to circumvent the copy protection.
        TDC
        ADC     #$0b            ; Address of second routine to call SmartPort command
        JSR     |L021849_Subroutine
        SEP     #$20
        LONGA OFF
        LDA     |L0218B6
        DEC     A
        STA     |L0218B6        ; Decrement hook reference value
        REP     #$20
        LONGA ON
        BNE     L0217BB         ; Loop

; Reset marks
        LDA     #L0218CF
        STA     $10             ; Address of parameter list pointer (ResetMark) for second routine (Control)
        LDA     #^L0218CF
        STA     $12             ; Address of parameter list pointer (ResetMark) for second routine (Control)
        CLC
        TDC
        ADC     #$0b            ; Address of second routine to call SmartPort command
        JSR     |L021849_Subroutine

; Set hook to F2207_CPSX
        LDA     #L0218AD
        STA     $5              ; Address of parameter list pointer (SetHook) for first routine (Control)
        LDA     #^L0218AD
        STA     $7              ; Address of parameter list pointer (SetHook) for first routine (Control)
        LDA     #L0218BB
        STA     $10             ; Address of parameter list pointer (ResetHook) for second routine (Control)
        LDA     #^L0218BB
        STA     $12             ; Address of parameter list pointer (ResetHook) for second routine (Control)
        LDA     #L0218C2
        STA     $1b             ; Address of parameter list pointer (ReadBlock) for third routine (ReadBlock)
        LDA     #^L0218C2
        STA     $1d             ; Address of parameter list pointer (ReadBlock) for third routine (ReadBlock)
        CLC
        TDC
        ADC     #$00            ; Address of first routine to call SmartPort command
        JSR     |L021849_Subroutine        ; Call first routine (SetHook)

; Read block
        LDA     >G3979_
        STA     |L0218C4        ; Address of data buffer for 'ReadBlock'
        LDA     >G3979_+2
        STA     |L0218C6        ; Address of data buffer for 'ReadBlock'
        LDA     #$00
        STA     [$21]           ; Write 0 in the first byte of the buffer. If will be $D5 if the reading is successful
        CLC
        TDC
        ADC     #$16            ; Address of third routine to call SmartPort command
        JSR     |L021849_Subroutine        ; Call third routine (ReadBlock)

; Reset hook
        SEP     #$20
        LONGA OFF
        LDA     #$02
        STA     |L0218B6        ; Set hook reference to 2 (Read data field) in the ResetHook control list
        REP     #$20
        LONGA ON
        CLC
        TDC
        ADC     #$0b            ; Address of second routine to call SmartPort command
        JSR     |L021849_Subroutine        ; Call second routine (ResetHook)

; Restore stack and registers before return
        PLB
        TSC
        SEC
        SBC     #$04
        TCS
        SEP     #$20
        LONGA OFF
        LDA     $27             ; Restore JSL target program bank register K
        PHA
        REP     #$20
        LONGA ON
        LDA     $25             ; Restore JSL target 16 bit address
        PHA
        LDA     $29             ; Restore caller Direct Page
        TCD
        RTL
        ENDP

; Routine to call a routine to call a SmartPort command
        EXPORT L021849_Subroutine
L021849_Subroutine PROC
        SEI                     ; Enable interrupts. Subroutine to call a customized routine to call a SmartPort command
        REP     #$30
        LONGA ON
        LONGI ON
        STA     |L021876        ; Write address of customized routine to call a SmartPort command into the JSL instruction
        SEP     #$20
        LONGA OFF
        LDA     #$00
        STA     |L021878        ; Write bank 0 into the JSL instruction
        REP     #$20
        LONGA ON
        TSC
        TAX
        SEP     #$20
        LONGA OFF
        LDA     #$01
        XBA
        LDA     $10100
        TCS
        PHX
        PHB
        LDA     #$00
        PHA
        PLB
        REP     #$20
        LONGA ON
        PHD
        LDA     #$00
        TCD
        SEP     #$30
        LONGA OFF
        LONGI OFF
        SEC
        XCE
;       JSL   $ff0000
; JMP opcode
        DC.B    $22
        EXPORT L021876
L021876 DC.B    $00,$00
        EXPORT L021878
L021878 DC.B    $FF
        PHP
        CLC
        XCE
        PLP
        REP     #$30
        LONGA ON
        LONGI ON
        PLD
        PLB
        PLX
        TXS
        CLI
        RTS
        EXPORT L021885
L021885 CLI                             ; 58            11 bytes long routine to call SmartPort a command
        JSR     $c500                   ; 20 00 C5
        DC.B    $00,$00,$00,$00,$00
        SEI                             ; 78
        RTL                             ; 6B
        CLI                             ; 58            11 bytes long routine to call SmartPort a command
        JSR     $c500                   ; 20 00 C5
        DC.B    $00,$00,$00,$00,$00
        SEI                             ; 78
        RTL                             ; 6B
        CLI                             ; 58            11 bytes long routine to call SmartPort a command
        JSR     $c500                   ; 20 00 C5
        DC.B    $00,$00,$00,$00,$00
        SEI                             ; 78
        RTL                             ; 6B

        EXPORT L0218A6
L0218A6 DC.B    $04,$00 ; Control list
        DC.B    $82     ; Hook reference number
        DC.L    F2207_CPSX  ; 22 15 00 00
        EXPORT L0218AD
L0218AD        DC.B    $03      ; Parameter list for first 'Control'. Parameter count = 3
        DC.B    $01     ; Unit number = 1
        DC.L    L0218A6 ; A6 18 00 00 Control list pointer
        DC.B    $05     ; Control code (device specific) = SetHook

        EXPORT L0218B4
L0218B4 DC.B    $04,$00 ; Control list
        EXPORT L0218B6
L0218B6 DC.B    $00,$00,$00,$00,$00     ; Hook reference is set in a loop to disable hooks from #4 down to #1
        EXPORT L0218BB
L0218BB DC.B    $03     ; Parameter list for second 'Control'. Parameter count = 3
        DC.B    $01     ; Unit number = 1
        DC.L    L0218B4 ; B4 18 00 00
        DC.B    $06     ; Control code (device specific) = ResetHook

        EXPORT L0218C2
L0218C2 DC.B    $03     ; Parameter list for 'ReadBlock'. Parameter count = 3
        DC.B    $01     ; Unit number = 1
        EXPORT L0218C4
L0218C4 DC.B    $00,$00 ; Address of data buffer
        EXPORT L0218C6
L0218C6 DC.B    $00,$00 ; Address of data buffer
        DC.B    $17,$00,$00,$00 ; Block number = 23

        EXPORT L0218CC
L0218CC DC.B    $16,$00,$00     ; Control list. Reset 21 bytes in the Mark table starting at offset 0 in the table (that's the whole table)
        EXPORT L0218CF
L0218CF DC.B    $03     ; Parameter list for second 'Control'. Parameter count = 3
        DC.B    $01     ; Unit number = 1
        DC.L    L0218CC ; CC 18 00 00
        DC.B    $08     ; Control code (device specific) = ResetMark
        ENDP

; All data below is used by functions that check code integrity.
; Some data is used by functions that compute checksums over code to ensure the program was not tampered with (cracking attempts): the data defines bytes to ignore becauce their value is always changed by relocation at load time.
; Some data defines which function calls should be present at specific locations within the code being checked, also taking relocation into account
; 18d6    144 bytes      F0413_  F0079_  F0464_
        EXPORT    F2191_CPSX
F2191_CPSX PROC       ; For F0433_STARTEND_ProcessCommand140_SaveGame_CPSCDF
        DC.B    $D3,$01
        DC.B    $0E,$00,$03,$00
        DC.B    $1D,$00,$03,$00
        DC.B    $28,$00,$03,$00
        DC.B    $2E,$00,$03,$00
        DC.B    $3F,$00,$03,$00
        DC.B    $4D,$00,$02,$00
        DC.B    $50,$00,$02,$00
        DC.B    $5E,$00,$03,$00
        DC.B    $6A,$00,$02,$00
        DC.B    $6D,$00,$02,$00
        DC.B    $7B,$00,$03,$00
        DC.B    $9F,$00,$03,$00
        DC.B    $AD,$00,$02,$00
        DC.B    $B0,$00,$02,$00
        DC.B    $B5,$00,$02,$00
        DC.B    $B8,$00,$02,$00
        DC.B    $BD,$00,$02,$00
        DC.B    $C0,$00,$02,$00
        DC.B    $C5,$00,$02,$00
        DC.B    $C8,$00,$02,$00
        DC.B    $DA,$00,$03,$00
        DC.B    $F2,$00,$03,$00
        DC.B    $03,$01,$03,$00
        DC.B    $2F,$01,$03,$00
        DC.B    $43,$01,$02,$00
        DC.B    $49,$01,$02,$00
        DC.B    $4C,$01,$02,$00
        DC.B    $56,$01,$02,$00
        DC.B    $59,$01,$02,$00
        DC.B    $72,$01,$02,$00
        DC.B    $75,$01,$02,$00
        DC.B    $81,$01,$0C,$00
        DC.B    $98,$01,$02,$00
        DC.B    $C6,$01,$02,$00
        DC.B    $C9,$01,$02,$00
        DC.B    $FF,$FF
        ENDP

; 1966   12 bytes        F2152_
        EXPORT    F2192_CPSX
F2192_CPSX PROC       ; For F0433_STARTEND_ProcessCommand140_SaveGame_CPSCDF
        DC.B    $28,$00,$00,$00 ; 8513 0000
        DC.L    F2150_CPSX
        DC.B    $FF,$FF,$FF,$FF
        ENDP

; 1972   44 bytes        F0413_  F0079_  F0464_
        EXPORT    F2193_CPSX
F2193_CPSX PROC       ; For F2206_CPSX
; This data defines a list of bytes to skip from checksum computations on function F2206_CPSX
        DC.B    $A9,$02 ; Final offset where checksum computation stops
        DC.B    $11,$00,$03,$00 ; At offset 0011 in function F2206_CPSX, skip 3 bytes from the checksum computation
        DC.B    $19,$00,$02,$00 ; At offset 0019 in function F2206_CPSX, skip 2 bytes from the checksum computation
        DC.B    $23,$00,$02,$00
        DC.B    $28,$00,$02,$00
        DC.B    $2B,$00,$02,$00
        DC.B    $34,$00,$02,$00
        DC.B    $39,$00,$02,$00
        DC.B    $3E,$00,$02,$00
        DC.B    $6E,$00,$02,$00
        DC.B    $71,$00,$02,$00
        DC.B    $97,$00,$02,$00
        DC.B    $A8,$00,$02,$00
        DC.B    $AB,$00,$02,$00
        DC.B    $2E,$01,$02,$00
        DC.B    $84,$01,$02,$00
        DC.B    $9B,$01,$05,$00
        DC.B    $FF,$FF
        ENDP

; 19b6   58 bytes        F2151_
        EXPORT    F2194_CPSX
F2194_CPSX PROC       ; For F2206_CPSX
        DC.B    $19,$00 ; AD11
        DC.W    L0211AD_Subroutine
        DC.B    $23,$00 ; 5C11
        DC.W    L02115C_Subroutine
        DC.B    $28,$00 ; AD11
        DC.W    L0211AD_Subroutine
        DC.B    $2B,$00 ; 4411
        DC.W    L021144_Subroutine
        DC.B    $34,$00 ; 5C11
        DC.W    L02115C_Subroutine
        DC.B    $39,$00 ; F711
        DC.W    L0211F7_Subroutine
        DC.B    $3E,$00 ; 4411
        DC.W    L021144_Subroutine
        DC.B    $6E,$00 ; 7712
        DC.W    L021277
        DC.B    $71,$00 ; 7212
        DC.W    L021272
        DC.B    $97,$00 ; 6F12
        DC.W    L02126F
        DC.B    $A8,$00 ; 8512
        DC.W    L021285
        DC.B    $AB,$00 ; 7712
        DC.W    L021277
        DC.B    $2E,$01 ; 7C12
        DC.W    L02127C
        DC.B    $84,$01 ; 7F12
        DC.W    L02127F
        DC.B    $FF,$FF
        ENDP

; 19f0   144 bytes       F0413_  F0079_  F0464_
        EXPORT    F2195_CPSX
F2195_CPSX PROC       ; For F2150_CPSX
        DC.B    $9D,$01
        DC.B    $02,$00,$03,$00
        DC.B    $0E,$00,$02,$00
        DC.B    $2F,$00,$02,$00
        DC.B    $34,$00,$02,$00
        DC.B    $39,$00,$02,$00
        DC.B    $43,$00,$02,$00
        DC.B    $48,$00,$02,$00
        DC.B    $4C,$00,$02,$00
        DC.B    $53,$00,$02,$00
        DC.B    $58,$00,$02,$00
        DC.B    $62,$00,$02,$00
        DC.B    $65,$00,$02,$00
        DC.B    $6A,$00,$02,$00
        DC.B    $6F,$00,$02,$00
        DC.B    $74,$00,$02,$00
        DC.B    $79,$00,$02,$00
        DC.B    $7E,$00,$02,$00
        DC.B    $88,$00,$02,$00
        DC.B    $8C,$00,$03,$00
        DC.B    $97,$00,$02,$00
        DC.B    $9A,$00,$03,$00
        DC.B    $A5,$00,$02,$00
        DC.B    $B2,$00,$02,$00
        DC.B    $CB,$00,$02,$00
        DC.B    $D2,$00,$02,$00
        DC.B    $DC,$00,$02,$00
        DC.B    $14,$01,$02,$00
        DC.B    $1B,$01,$02,$00
        DC.B    $3D,$01,$03,$00
        DC.B    $70,$01,$04,$00
        DC.B    $76,$01,$04,$00
        DC.B    $7D,$01,$01,$00
        DC.B    $84,$01,$04,$00
        DC.B    $8B,$01,$04,$00
        DC.B    $98,$01,$04,$00
        DC.B    $FF,$FF
        ENDP

; 1a80   36 bytes        F2152_
        EXPORT    F2196_CPSX
F2196_CPSX PROC       ; For F2150_CPSX
        DC.B    $70,$01,$00,$00 ; DC10 0000
        DC.L    F2206_CPSX
        DC.B    $76,$01,$00,$00 ; F214 0000
        DC.L    L0214F2
        DC.B    $84,$01,$00,$00 ; 0015 0000
        DC.L    L021500
        DC.B    $98,$01,$00,$00 ; 1815 0000
        DC.L    L021518
        DC.B    $FF,$FF,$FF,$FF
        ENDP

; 1aa4   82 bytes        F2151_
        EXPORT    F2197_CPSX
F2197_CPSX PROC       ; For F2150_CPSX
        DC.B    $0E,$00 ; D114
        DC.W    L0214D1
        DC.B    $2F,$00 ; 0215
        DC.W    L021502
        DC.B    $34,$00 ; 0715
        DC.W    L021507
        DC.B    $43,$00 ; 9514
        DC.W    L021495_Subroutine
        DC.B    $48,$00 ; 0215
        DC.W    L021502
        DC.B    $4C,$00 ; 0215
        DC.W    L021502
        DC.B    $53,$00 ; 1B15
        DC.W    L02151B
        DC.B    $62,$00 ; 9514
        DC.W    L021495_Subroutine
        DC.B    $65,$00 ; F914
        DC.W    L0214F9
        DC.B    $6F,$00 ; 0715
        DC.W    L021507
        DC.B    $79,$00 ; 0E15
        DC.W    L02150E
        DC.B    $88,$00 ; 9514
        DC.W    L021495_Subroutine
        DC.B    $97,$00 ; 1015
        DC.W    L021510
        DC.B    $A5,$00 ; 1215
        DC.W    L021512
        DC.B    $B2,$00 ; 9514
        DC.W    L021495_Subroutine
        DC.B    $CB,$00 ; 9514
        DC.W    L021495_Subroutine
        DC.B    $D2,$00 ; 0215
        DC.W    L021502
        DC.B    $DC,$00 ; 9514
        DC.W    L021495_Subroutine
        DC.B    $14,$01 ; C214
        DC.W    L0214C2
        DC.B    $1B,$01 ; C414
        DC.W    L0214C4
        DC.B    $FF,$FF
        ENDP

; 1af6   60 bytes        F0413_  F0079_  F0464_
        EXPORT    F2198_CPSX
F2198_CPSX PROC       ; For F2207_CPSX
        DC.B    $49,$02
        DC.B    $05,$00,$03,$00
        DC.B    $0D,$00,$02,$00
        DC.B    $17,$00,$02,$00
        DC.B    $1C,$00,$02,$00
        DC.B    $1F,$00,$02,$00
        DC.B    $28,$00,$02,$00
        DC.B    $2D,$00,$02,$00
        DC.B    $32,$00,$02,$00
        DC.B    $62,$00,$02,$00
        DC.B    $65,$00,$02,$00
        DC.B    $8B,$00,$02,$00
        DC.B    $9C,$00,$02,$00
        DC.B    $9F,$00,$02,$00
        DC.B    $44,$01,$05,$00
        DC.B    $FF,$FF
        ENDP

; 1b32   50 bytes        F2151_
        EXPORT    F2199_CPSX
F2199_CPSX PROC       ; For F2207_CPSX
        DC.B    $0D,$00 ; E715
        DC.W    L0215E7_Subroutine
        DC.B    $17,$00 ; 9615
        DC.W    L021596_Subroutine
        DC.B    $1C,$00 ; E715
        DC.W    L0215E7_Subroutine
        DC.B    $1F,$00 ; 7E15
        DC.W    L02157E_Subroutine
        DC.B    $28,$00 ; 9615
        DC.W    L021596_Subroutine
        DC.B    $2D,$00 ; 3116
        DC.W    L021631_Subroutine
        DC.B    $32,$00 ; 7E15
        DC.W    L02157E_Subroutine
        DC.B    $62,$00 ; 6616
        DC.W    L021666
        DC.B    $65,$00 ; 6116
        DC.W    L021661
        DC.B    $8B,$00 ; 5E16
        DC.W    L02165E
        DC.B    $9C,$00 ; 6B16
        DC.W    L02166B
        DC.B    $9F,$00 ; 6616
        DC.W    L021666
        DC.B    $FF,$FF
        ENDP

; 1b64   140 bytes       F0413_  F0079_  F0464_
        EXPORT    F2200_CPSX
F2200_CPSX PROC       ; For F0527_FLOPPY_ReadFuzzySector_CPSX
        DC.B    $6B,$01
        DC.B    $02,$00,$03,$00
        DC.B    $21,$00,$02,$00
        DC.B    $42,$00,$02,$00
        DC.B    $47,$00,$02,$00
        DC.B    $4C,$00,$02,$00
        DC.B    $56,$00,$02,$00
        DC.B    $5B,$00,$02,$00
        DC.B    $5F,$00,$02,$00
        DC.B    $66,$00,$02,$00
        DC.B    $6B,$00,$02,$00
        DC.B    $75,$00,$02,$00
        DC.B    $78,$00,$02,$00
        DC.B    $7D,$00,$02,$00
        DC.B    $82,$00,$02,$00
        DC.B    $87,$00,$02,$00
        DC.B    $8C,$00,$02,$00
        DC.B    $91,$00,$02,$00
        DC.B    $9B,$00,$02,$00
        DC.B    $9E,$00,$03,$00
        DC.B    $A2,$00,$02,$00
        DC.B    $A5,$00,$03,$00
        DC.B    $A9,$00,$02,$00
        DC.B    $B6,$00,$02,$00
        DC.B    $BD,$00,$02,$00
        DC.B    $C7,$00,$02,$00
        DC.B    $E2,$00,$02,$00
        DC.B    $E9,$00,$02,$00
        DC.B    $0B,$01,$03,$00
        DC.B    $3E,$01,$04,$00
        DC.B    $44,$01,$04,$00
        DC.B    $4B,$01,$01,$00
        DC.B    $52,$01,$04,$00
        DC.B    $59,$01,$04,$00
        DC.B    $66,$01,$04,$00
        DC.B    $FF,$FF
        ENDP

; 1bf0   36 bytes        F2152_
        EXPORT    F2201_CPSX
F2201_CPSX PROC       ; For F0527_FLOPPY_ReadFuzzySector_CPSX
        DC.B    $3E,$01,$00,$00 ; 2215 0000
        DC.L    F2207_CPSX
        DC.B    $44,$01,$00,$00 ; A618 0000
        DC.L    L0218A6
        DC.B    $52,$01,$00,$00 ; B418 0000
        DC.L    L0218B4
        DC.B    $66,$01,$00,$00 ; CC18 0000
        DC.L    L0218CC
        DC.B    $FF,$FF,$FF,$FF
        ENDP

; 1c14   78 bytes        F2151_
        EXPORT    F2202_CPSX
F2202_CPSX PROC       ; For F0527_FLOPPY_ReadFuzzySector_CPSX
        DC.B    $21,$00 ; 8518
        DC.W    L021885
        DC.B    $42,$00 ; B618
        DC.W    L0218B6
        DC.B    $47,$00 ; BB18
        DC.W    L0218BB
        DC.B    $56,$00 ; 4918
        DC.W    L021849_Subroutine
        DC.B    $5B,$00 ; B618
        DC.W    L0218B6
        DC.B    $5F,$00 ; B618
        DC.W    L0218B6
        DC.B    $66,$00 ; CF18
        DC.W    L0218CF
        DC.B    $75,$00 ; 4918
        DC.W    L021849_Subroutine
        DC.B    $78,$00 ; AD18
        DC.W    L0218AD
        DC.B    $82,$00 ; BB18
        DC.W    L0218BB
        DC.B    $8C,$00 ; C218
        DC.W    L0218C2
        DC.B    $9B,$00 ; 4918
        DC.W    L021849_Subroutine
        DC.B    $A2,$00 ; C418
        DC.W    L0218C4
        DC.B    $A9,$00 ; C618
        DC.W    L0218C6
        DC.B    $B6,$00 ; 4918
        DC.W    L021849_Subroutine
        DC.B    $BD,$00 ; B618
        DC.W    L0218B6
        DC.B    $C7,$00 ; 4918
        DC.W    L021849_Subroutine
        DC.B    $E2,$00 ; 7618
        DC.W    L021876
        DC.B    $E9,$00 ; 7818
        DC.W    L021878
        DC.B    $FF,$FF
        ENDP

; 1c62   368 bytes       F0413_  F0079_  F0464_
        EXPORT    F2203_CPSX
F2203_CPSX PROC       ; Byte to skip for F0380_COMMAND_ProcessQueue_CPSC
        DC.B    $95,$03
        DC.B    $0C,$00,$03,$00
        DC.B    $13,$00,$02,$00
        DC.B    $16,$00,$02,$00
        DC.B    $30,$00,$02,$00
        DC.B    $35,$00,$02,$00
        DC.B    $38,$00,$03,$00
        DC.B    $3F,$00,$02,$00
        DC.B    $47,$00,$03,$00
        DC.B    $51,$00,$02,$00
        DC.B    $54,$00,$02,$00
        DC.B    $57,$00,$03,$00
        DC.B    $84,$00,$02,$00
        DC.B    $89,$00,$02,$00
        DC.B    $8E,$00,$02,$00
        DC.B    $9B,$00,$02,$00
        DC.B    $A0,$00,$02,$00
        DC.B    $A3,$00,$03,$00
        DC.B    $AA,$00,$02,$00
        DC.B    $B2,$00,$03,$00
        DC.B    $BC,$00,$02,$00
        DC.B    $BF,$00,$02,$00
        DC.B    $C2,$00,$03,$00
        DC.B    $D0,$00,$02,$00
        DC.B    $D8,$00,$03,$00
        DC.B    $E2,$00,$02,$00
        DC.B    $E5,$00,$02,$00
        DC.B    $E8,$00,$03,$00
        DC.B    $F9,$00,$02,$00
        DC.B    $FD,$00,$02,$00
        DC.B    $0D,$01,$02,$00
        DC.B    $10,$01,$02,$00
        DC.B    $13,$01,$03,$00
        DC.B    $27,$01,$03,$00
        DC.B    $4D,$01,$03,$00
        DC.B    $79,$01,$02,$00
        DC.B    $7E,$01,$02,$00
        DC.B    $89,$01,$03,$00
        DC.B    $B6,$01,$03,$00
        DC.B    $D8,$01,$02,$00
        DC.B    $E7,$01,$03,$00
        DC.B    $1A,$02,$02,$00
        DC.B    $1F,$02,$02,$00
        DC.B    $26,$02,$03,$00
        DC.B    $35,$02,$02,$00
        DC.B    $38,$02,$02,$00
        DC.B    $3B,$02,$02,$00
        DC.B    $3E,$02,$02,$00
        DC.B    $41,$02,$03,$00
        DC.B    $51,$02,$03,$00
        DC.B    $60,$02,$02,$00
        DC.B    $63,$02,$02,$00
        DC.B    $66,$02,$02,$00
        DC.B    $69,$02,$02,$00
        DC.B    $6C,$02,$03,$00
        DC.B    $7A,$02,$03,$00
        DC.B    $89,$02,$02,$00
        DC.B    $8C,$02,$02,$00
        DC.B    $8F,$02,$02,$00
        DC.B    $92,$02,$02,$00
        DC.B    $95,$02,$03,$00
        DC.B    $A5,$02,$03,$00
        DC.B    $B4,$02,$02,$00
        DC.B    $B7,$02,$02,$00
        DC.B    $BA,$02,$02,$00
        DC.B    $BD,$02,$02,$00
        DC.B    $C0,$02,$03,$00
        DC.B    $CE,$02,$03,$00
        DC.B    $DD,$02,$02,$00
        DC.B    $E0,$02,$02,$00
        DC.B    $E3,$02,$02,$00
        DC.B    $E6,$02,$02,$00
        DC.B    $E9,$02,$03,$00
        DC.B    $F9,$02,$03,$00
        DC.B    $08,$03,$02,$00
        DC.B    $0B,$03,$02,$00
        DC.B    $0E,$03,$02,$00
        DC.B    $11,$03,$02,$00
        DC.B    $14,$03,$03,$00
        DC.B    $22,$03,$03,$00
        DC.B    $31,$03,$02,$00
        DC.B    $34,$03,$02,$00
        DC.B    $37,$03,$02,$00
        DC.B    $3A,$03,$02,$00
        DC.B    $3D,$03,$03,$00
        DC.B    $4B,$03,$03,$00
        DC.B    $5A,$03,$02,$00
        DC.B    $62,$03,$02,$00
        DC.B    $66,$03,$03,$00
        DC.B    $75,$03,$02,$00
        DC.B    $7A,$03,$02,$00
        DC.B    $86,$03,$03,$00
        DC.B    $FF,$FF
        ENDP

; 1dd2   244 bytes       F2152_
        EXPORT    F2204_CPSX
F2204_CPSX PROC       ; 3 bytes addresses to check in F0380_COMMAND_ProcessQueue_CPSC
; Many addresses are set to 0 and are replaced at load time with actual references to functions using relocation records in the executable file
        DC.B    $0C,$00,$00,$00 ; 0000 0000
        DC.L    F2155_
        DC.B    $38,$00,$00,$00 ; 0000 0000
        DC.L    F0360_          ; F0360_COMMAND_ProcessPendingClick
        DC.B    $47,$00,$00,$00 ; A520 0000
        DC.L    _IMUL
        DC.B    $57,$00,$00,$00 ; 001F 0000
        DC.L    _LADD
        DC.B    $A3,$00,$00,$00 ; 0000 0000
        DC.L    F0360_          ; F0360_COMMAND_ProcessPendingClick
        DC.B    $B2,$00,$00,$00 ; A520 0000
        DC.L    _IMUL
        DC.B    $C2,$00,$00,$00 ; 001F 0000
        DC.L    _LADD
        DC.B    $D8,$00,$00,$00 ; A520 0000
        DC.L    _IMUL
        DC.B    $E8,$00,$00,$00 ; 001F 0000
        DC.L    _LADD
        DC.B    $13,$01,$00,$00 ; 0000 0000
        DC.L    F0360_          ; F0360_COMMAND_ProcessPendingClick
        DC.B    $27,$01,$00,$00 ; 0000 0000
        DC.L    F0365_          ; F0365_COMMAND_ProcessTypes1To2_TurnParty
        DC.B    $4D,$01,$00,$00 ; 0000 0000
        DC.L    F0366_          ; F0366_COMMAND_ProcessTypes3To6_MoveParty
        DC.B    $89,$01,$00,$00 ; 0000 0000
        DC.L    F0367_          ; F0367_COMMAND_ProcessTypes12To27_ClickInChampionStatusBox
        DC.B    $B6,$01,$00,$00 ; 0000 0000
        DC.L    F0070_          ; F0070_MOUSE_ProcessCommands125To128_ClickOnChampionIcon
        DC.B    $E7,$01,$00,$00 ; 0000 0000
        DC.L    F0302_CHAMPION_ProcessCommands28To65_ClickOnSlotBox
        DC.B    $26,$02,$00,$00 ; 0000 0000
        DC.L    F0355_          ; F0355_INVENTORY_Toggle_CPSE
        DC.B    $41,$02,$00,$00 ; 0000 0000
        DC.L    F0464_          ; F0464_CPSC_GetChecksumSub
        DC.B    $51,$02,$00,$00 ; 0000 0000
        DC.L    F0355_          ; F0355_INVENTORY_Toggle_CPSE
        DC.B    $6C,$02,$00,$00 ; 0000 0000
        DC.L    F2152_
        DC.B    $7A,$02,$00,$00 ; 0000 0000
        DC.L    F0355_          ; F0355_INVENTORY_Toggle_CPSE
        DC.B    $95,$02,$00,$00 ; 0000 0000
        DC.L    F0464_          ; F0464_CPSC_GetChecksumSub
        DC.B    $A5,$02,$00,$00 ; 0000 0000
        DC.L    F0355_          ; F0355_INVENTORY_Toggle_CPSE
        DC.B    $C0,$02,$00,$00 ; 0000 0000
        DC.L    F2151_01234567890123456789      ; F2151_
        DC.B    $CE,$02,$00,$00 ; 0000 0000
        DC.L    F0355_          ; F0355_INVENTORY_Toggle_CPSE
        DC.B    $E9,$02,$00,$00 ; 0000 0000
        DC.L    F0464_          ; F0464_CPSC_GetChecksumSub
        DC.B    $F9,$02,$00,$00 ; 0000 0000
        DC.L    F0355_          ; F0355_INVENTORY_Toggle_CPSE
        DC.B    $14,$03,$00,$00 ; 0000 0000
        DC.L    F2152_
        DC.B    $22,$03,$00,$00 ; 0000 0000
        DC.L    F0355_          ; F0355_INVENTORY_Toggle_CPSE
        DC.B    $3D,$03,$00,$00 ; 0000 0000
        DC.L    F2151_01234567890123456789      ; F2151_
        DC.B    $4B,$03,$00,$00 ; 0000 0000
        DC.L    F0355_          ; F0355_INVENTORY_Toggle_CPSE
        DC.B    $FF,$FF,$FF,$FF
        ENDP

; 1ec6   58 bytes        F2151_
        EXPORT    F2205_CPSX
F2205_CPSX PROC
; 2 bytes addresses to check in F0380_COMMAND_ProcessQueue_CPSC
; Array of words terminated by 0xFFFF value: Offset in F0380_COMMAND_ProcessQueue_CPSC / expected word value at this offset
        DC.B    $38,$02 ; D618    ; At offset 0238 in function F0380_COMMAND_ProcessQueue_CPSC, expected value is 18D6 = Address of F2191_CPSX = a parameter of a call to F0464_CPSC_GetChecksumSub
        DC.W    F2191_CPSX
        DC.B    $3E,$02 ; 0000
        DC.W    F0433_  ; F0433_STARTEND_ProcessCommand140_SaveGame_CPSCDF
        DC.B    $63,$02 ; 6619
        DC.W    F2192_CPSX
        DC.B    $69,$02 ; 0000
        DC.W    F0433_  ; F0433_STARTEND_ProcessCommand140_SaveGame_CPSCDF
        DC.B    $8C,$02 ; 7219
        DC.W    F2193_CPSX
        DC.B    $92,$02 ; DC10
        DC.W    F2206_CPSX
        DC.B    $B7,$02 ; B619
        DC.W    F2194_CPSX
        DC.B    $BD,$02 ; DC10
        DC.W    F2206_CPSX
        DC.B    $E0,$02 ; F019
        DC.W    F2195_CPSX
        DC.B    $E6,$02 ; 8513
        DC.W    F2150_CPSX
        DC.B    $0B,$03 ; 801A
        DC.W    F2196_CPSX
        DC.B    $11,$03 ; 8513
        DC.W    F2150_CPSX
        DC.B    $34,$03 ; A41A
        DC.W    F2197_CPSX
        DC.B    $3A,$03 ; 8513
        DC.W    F2150_CPSX
        DC.B    $FF,$FF
        ENDP

        END

; 1f00 _LADD (Start of C library functions)
