P*******************************
*                             *
* Disk zap for Commodore 128  *
*                             *
*   Glen E. Bredon 11/15/85   *
*                             *
*     80 column mode only     *
*                             *
*******************************

          TR
          EXP OFF

INDEX     = 2             ;Byte pointer into sector buff
TEMP      = 3
CURTRK    = 4             ;Track read or specified
CURSEC    = CURTRK+1      ;Sector "
RWFLAG    = 6             ;+ = Read, - = Write
ERR       = 7             ;Save for 1st disk err char
DRIVE     = 8             ;Device used for read/write
KEY       = ERR           ;Actual key read by GETKEY rout
EDPNT     = 9             ;Pointer into buffer in EDIT
VALFLAG   = $A            ;- if CURTRK may be wrong one
MODE      = $B            ;- if in ascii edit mode
BUFPNT    = $FA           ;Pointer to current R/W buffer
TYPE      = $FE           ;Flag for undelete
BUFFER    = $1300         ;Sector buffer for read/write
BUFFER2   = BUFFER+$100   ;Save for possible ESC restore
BAMBUF    = $1500         ;Buffer for BAM
BAMBUF2   = BAMBUF+$100   ;Side 2 BAM

* Commodore stuff:

DEVICE    = $BA
CV        = $EB           ;Cursor vertical
QTSW      = $F4           ;Quote flag
BASIC     = $4003         ;BASIC warm entry

ESCAPE    = $C01E         ;Editor ESC function handler

SETBNK    = $FF68
PRIMM     = $FF7D
ACPTR     = $FFA5
CIOUT     = $FFA8
CHKIN     = $FFC6
CHKOUT    = $FFC9
CHROUT    = $FFD2
CLOSE     = $FFC3
CLRCHN    = $FFCC
GETIN     = $FFE4
OPEN      = $FFC0
PLOT      = $FFF0
SETLFS    = $FFBA
SETNAM    = $FFBD

GOXY      MAC
          LDY #]1
          LDX #]2
          CLC
          JSR PLOT
          <<<

TAB       MAC
          LUP ]1
          DFB 9
          --^
          TXT ]2
          <<<

PRINT     MAC
          JSR PRIMM
          IF '=]1
          TXT ]1
          ELSE
          HEX ]1
          TXT ]2
          FIN
          BRK
          <<<

*==========================================

          ORG $1C01

*===============
* BASIC header:
*---------------

          DA :TWOBRK      ;Link
          DA 10           ;Line number
          DFB $9E         ;SYS token
          TXT '7181'
          BRK             ;eol
:TWOBRK   DA 0            ;end of BASIC prog

          ERR *-7181

          CLI             ;Start of main prog (do this
          CLD             ; stuff just in case)
          LDA #0
          STA BUFPNT      ;Never changed
          STA VALFLAG     ;Init validity flag
          STA $FF00       ;Just in case
          STA CURTRK      ;Init invalid track
          STA CURSEC      ; to force read
          TAX
          JSR SETBNK      ;Set bank 0 forever
          LDA #1
          STA $D030       ;Set fast mode
MENU      LDX #$F8
          TXS
          LDA #>BUFFER    ;Set ptr to BUFFER
          STA BUFPNT+1
          LDA #'y'
          JSR ESCAPE      ;Set default tabs
          LDA VALFLAG     ;If flag is - then buffer is
          BPL :OK         ; from another sector than
          STX CURTRK      ; CURSEC, so require a read
:OK       JSR PRIMM
          DFB 147,14,8    ;Home, lc, defeat shift-comm
          TAB 4           ;'DISK ZAP'0d0d
          TAB 3           ;'     by Glen Bredon'0d0d
          TAB 3           ;'     (1571  drives)'0d0d
          TAB 2           ;'    '8e
          LUP 16
          HEX 7FA9
          --^
          HEX 0D0D0E
          TAB 2           ;'    Main commands:'0d0d
          TAB 2           ;'    Q: Quit'0d
          TAB 2           ;'    R: Read sector from disk'0d
          TAB 2           ;'    W: Write sector to disk'0d
          TAB 2           ;'    E: Edit current sector buffer'0d
          TAB 2           ;'    C: Read first catalog sector'0d
          TAB 2           ;'    B: Show BAM'0d
          TAB 2           ;'    H: Help'0d
          TAB 2           ;'    D: Toggle drive 8<-->9, now '00
          LDA DEVICE
          AND #%00001001
          CMP #8          ;Demand 8 or 9
          BGE :STDRV
          LDA #8
:STDRV    STA DRIVE
          STA DEVICE
          ORA #'0'
          JSR CHROUT
          JSR PRIMM
          HEX 0D0D
          TAB 2           ;'    Select: '00
          LDY #0
          STY RWFLAG      ;Precaution
          JSR GETKEY
          LDX #:CMDEND-:CMDS
:NXCMD    DEX
          BMI GOMENU
          CMP :CMDS,X
          BNE :NXCMD
          TXA
          ASL
          TAX
          LDA :CMDADRS+1,X
          PHA
          LDA :CMDADRS,X
          PHA
          RTS

:CMDS     ASC 'QRWEDBCH'
:CMDEND  

:CMDADRS  DA QUIT-1
          DA READ-1
          DA WRITE-1
          DA EDIT-1
          DA TOGGLE-1
          DA BAM-1
          DA CAT-1
          DA HELP-1

*=========================
*  QUIT & TOGGLE routines:
*-------------------------

TOGGLE    LDA DRIVE
          EOR #1
          STA DEVICE
GOMENU    JMP MENU

QUIT      JSR OPFILES     ;Reinitialize the drive
          LDX #15         ; before exiting or it may
          JSR CHKOUT      ; get mixed up by an undelete
          PRINT 'i'
          JSR CLOSEFIL    ; or any write of a BAM sector.
          JMP BASIC

*================
*  EDIT routine:
*----------------

EDIT      JSR SAVBUF      ;Save buffer for ESC
          STY MODE        ;Set hex edit mode
          STY EDPNT       ;Init buffer pointer
          JSR CHKRNG      ;Check T/S valid, abort if not
EDIT2     JSR SHOWBUF     ;Show current sector buffer
          JSR PRIMM
          HEX 0D
          TXT 'ESC to cancel changes, '
          TXT 'TAB to toggle ascii mode, '
          TXT 'STOP to go to main menu.'00
:ELUP     LDA CURTRK
          CMP #$12
          BNE :JJP        ;Skip if not directory track
          LDA CURSEC
          BEQ :JJP        ; or if BAM sector
          GOXY 0          ;24 ;Set to print/erase instruction
          LDA EDPNT
          TAY
          AND #$1F
          CMP #5          ;Erase if cursor not on 1st
          BNE :ERASE      ; char of a file name
          LDA BUFFER,Y    ; or if name does not begin
          CMP #'a'        ; with an alpha char
          BLT :ERASE
          CMP #'z'+1
          BLT :TXOPT
:ERASE    LDA #'q'
          JSR ESCAPE      ;Clear to EOL
:JJP      JMP :JP
:TXOPT    JSR PRIMM
          TXT '^T for Track-Sector list of this file, '
          TXT '^F to follow file.'00
:JP       JSR POSITION
          JSR GETKEY      ;Get 1st key
          EOR #'T'&$1F    ;If ^T then check if T/S cmd
          BEQ :TSLIST     ; is to be accepted
          EOR #'T'!'F'    ;If ^F then go to 1st file sec
          BEQ :FOLLOW
          EOR #'F'&$1F!9
          BNE :CHKMODE    ;If TAB key then
          LDA MODE        ; toggle ascii/hex mode
          EOR #$80
          STA MODE
          JMP :ELUP
:CHKMODE  EOR #9          ;Correct the key
          BIT MODE
          BMI :ASCII      ;Branch if now in ascii mode
          EOR #'0'        ;Else check if a hex digit
          CMP #10
          BLT :NXDIG
          ADC #$88
          ORA #$20
          CMP #$FA
          BGE :NXDIG      ;Branch if key is a hex digit
          JMP :MOVE
:NXDIG    ASL             ;Move 1st digit to high nibble
          ASL
          ASL
          ASL
          STA TEMP        ;Save it
          JSR GETKEY      ; and get next digit
          LDY EDPNT
          EOR #'0'
          CMP #10
          BLT :GOTIT      ;Branch if valid 2nd digit
          ADC #$88
          ORA #$20
          CMP #$FA
          BGE :GOTIT      ; "
          JSR POSITION    ;Else reprint the old byte
          LDY EDPNT
          LDA BUFFER,Y
          JSR BYTHEX
          JMP :ELUP       ; and reject whole thing

:FOLLOW   SEC
:TSLIST   ROR TEMP
          LDA CURTRK      ;Require directory track
          CMP #$12
          BNE :JP
          LDA CURSEC      ;Reject BAM sector
          BEQ :JP
          LDA EDPNT
          TAY
          AND #$1F
          CMP #5          ;Cursor must be on 1st char
          BNE :JP         ; of file name
          LDA BUFFER,Y    ;Require name to start with
          CMP #'a'        ; alpha character
          BLT :JP
          CMP #'z'+1
          BGE :JP
          BIT TEMP
          BPL :TS
          JMP FOLLOW
:TS       JMP SHOWTS      ;If condns met, show T/S list

:ASCII    LDY EDPNT
          BCC :MOVE2      ;Branch if not printed char
          LDA KEY         ;Put actual key typed in buff
          STA BUFFER,Y
          LSR MODE        ;Fake hex mode
          JSR POSITION    ; to position cursor on hex
          LDA KEY
          JSR BYTHEX      ;Update hex display
          SEC
          ROR MODE        ;Fix mode
          BMI :NXEDP      ;Update buff index and loop

:GOTIT    AND #$F         ;Valid hex byte input
          ORA TEMP        ;Pack 2nd digit with 1st
          STA BUFFER,Y    ; and keep it
          TYA             ;Calculate position in
          AND #$F         ; ascii portion
          CLC
          ADC #3*18
          TAY
          LDX CV          ;Keep present vert pos
          CLC
          JSR PLOT
          LDY EDPNT
          JSR PRNTASC     ; and print chr there (or .)
:NXEDP    INC EDPNT       ;Move cursor to next byte
          JMP :ELUP

:MOVE     JSR POSITION    ;Position cursor
          LDY EDPNT
          LDA BUFFER,Y
          JSR BYTHEX      ; and show hex representation
:MOVE2    LDA KEY
          CMP #3
          BNE :LEFT
          JMP MENU        ;Exit if STOP key
:LEFT     CMP #$9D        ;Check for cursor keys
          BNE :RIGHT      ; and act accordingly
          DEY
:RIGHT    CMP #$1D
          BNE :UP
          INY
:UP       CMP #$91
          BNE :DOWN
          PHA
          TYA
          SBC #$10
          TAY
          PLA
:DOWN     CMP #$11
          BNE :REP
          PHA
          TYA
          SBC #$F0
          TAY
          PLA
:REP      CMP #27         ;If ESC key then
          BNE :BACK       ; replace buffer as it
          JSR GETBUF      ; was on entry
          JMP EDIT2       ; and loop
:BACK     STY EDPNT       ;Set new buffer pointer
          JMP :ELUP       ; and loop (other keys ignored)

SAVBUF    LDY #0
:SV       LDA BUFFER,Y    ;Save buffer for ESC cmd
          STA BUFFER2,Y
          INY
          BNE :SV
          RTS

GETBUF    LDX #0
:RP       LDA BUFFER2,X
          STA BUFFER,X
          INX
          BNE :RP
          RTS

*=====================================================
*  Routine to read and show track sector list of file:
*-----------------------------------------------------

SHOWTS    PRINT 93        ;'Track-Sector list for '
          LDY EDPNT
          LDA BUFFER-3,Y  ;Deleted file?
          AND #$80
          STA TYPE        ;Flag if active or deleted
          BMI :ACTIVE
          PRINT 'deleted'
          JMP :OV
:ACTIVE   PRINT 'active'
:OV       PRINT ' file: '
          LDX #16
:PN       LDA BUFFER,Y    ;Show file name
          JSR CHROUT
          INY
          DEX
          BNE :PN
          JSR PRIMM
          HEX 0D0D00
          LDA CURSEC      ;Save current sector #
          PHA
          BIT TYPE
          BMI :LE         ;Branch if file is active
          LSR RWFLAG      ;Do a read
          JSR RWBAM       ;Get the BAM
:LE       LDY EDPNT       ;Point to 1st T/S pair
          LDA BUFFER-1,Y  ;Track
          STA CURSEC
          LDA BUFFER-2,Y  ;Sector
          STA CURTRK
:TSLUP    LDA CURTRK
          CMP #36         ;Make sure it is a valid T/S
          BLT :VAL
          SBC #35
:VAL      TAX
          DEX
          CPX #35         ;Check valid track
          BGE :DONE       ; and exit if not
          LDA CURSEC
          CMP MAXSECS,X   ;Check valid sector
          BGE :DONE       ; and skip if not
          LDA CURTRK
          JSR BYTHEX      ;Show track in hex
          LDA #','
          JSR CHROUT
          LDA CURSEC      ; then sector
          JSR BYTHEX
          PRINT '   '
          BIT TYPE
          BMI :ACTV       ;Branch if file active or bad
          JSR ISUSED      ;Is this sector used?
          BNE :NOTU       ;Branch if not
          LDA #$C0        ;Flag file as bad
          STA TYPE
          BNE :ACTV
:NOTU     BVS :SIDE2      ;Branch if sector on side 2
          LDA BITS,Y      ;Mark sector used now
          EOR BAMBUF+1,X
          STA BAMBUF+1,X
          LDA CURTRK
          ASL
          ASL             ;CURTRK * 4
          TAX
          DEC BAMBUF,X    ; and fix free sector count
          BVC :ACTV       ;Always taken
:SIDE2    LDA BITS,Y      ;Same for side 2
          EOR BAMBUF2,X
          STA BAMBUF2,X
          LDX CURTRK
          DEC BAMBUF+21-36,X
:ACTV     JSR OPFILES
          LDA #'1'        ;Send U1 command to read
          JSR SNDUSER     ; current sector to disk mem
          JSR CLRCHN
          JSR SETBP       ;Init buffer pointer
          LDX #2
          JSR CHKIN
          JSR ACPTR       ;Read next track #
          STA CURTRK
          JSR ACPTR       ; and sector #
          STA CURSEC
          JSR CLOSEFIL
          JMP :TSLUP      ;Loop forever
:DONE     BIT TYPE
          BPL :ASK        ;Branch if can undelete
          BVC :JD         ;Branch if active file
          JMP :CANTFIX    ;Tell user file is bad
:JD       JMP :DONTFIX    ;Skip all this stuff
:ASK      PRINT 0D0D      ;'Undelete this file?'
:GK       JSR GETKEY
          CMP #'n'
          BEQ :JD
          CMP #'y'
          BNE :GK
          LDY EDPNT
          LDA #$82
          STA RWFLAG      ;Set flag to write
          STA BUFFER-3,Y  ;Mark file as PRG
          JSR RWBAM       ;Write BAM sectors
          PLA             ;Retrieve cat sector
          STA CURSEC
          LDA #$12        ; and track
          STA CURTRK
          JSR RorWsec     ;Write the cat sector
          LSR RWFLAG      ;Reset flag to read
          JSR PRIMM
          HEX 0D0D
          TXT 'The file is undeleted and has type PRG.  '
          TXT 'Zap the directory to correct type.'0d00
          JMP :EX
:CANTFIX  JSR PRIMM
          HEX 0D0D
          TXT 'This file has been corrupted and cannot '
          TXT 'be restored.'0d00
:DONTFIX  PLA
          STA CURSEC      ;Reset to original sector
          LDA #$12
          STA CURTRK      ; and track
:EX       LDA #$D
          JSR CHROUT
          JMP HITKEY      ;Wait for key, then MENU

*=================
*  WRITE routine:
*-----------------

RESET     SEC
          ROR VALFLAG     ;Show that next specification is
          JSR GETTS       ; not a T/S read from disk.
WRITE     JSR CHKRNG      ;Check T/S valid, reject if not
          PRINT 0D0D      ;'Ok to write track $'
          LDA CURTRK
          JSR BYTHEX
          PRINT ', sector $'
          LDA CURSEC
          JSR BYTHEX
          PRINT '? '
:ANS      JSR GETKEY
          CMP #'y'
          BEQ :DOW        ;If Y then write it
          CMP #'n'
          BEQ RESET       ;If N then ask for T/S change
          LDA #20         ;Erase other keys
          JSR CHROUT
          JMP :ANS        ; and loop forever (until STOP)

:DOW      ROR RWFLAG      ;Set flag to WRITE
          JSR RorWsec     ;Operate the disk
          LSR RWFLAG      ;Just a little safety factor
:TOMENU   JMP MENU

*=============================
* FOLLOW, CAT & READ routines:
*-----------------------------

FOLLOW    LDY EDPNT
          LDA BUFFER-2,Y
          STA CURTRK
          LDA BUFFER-1,Y
          STA CURSEC
          JMP READ2

CAT       LDA #$12        ;Set track $12
          STA CURTRK
          LDA #1          ; and sector 1
          STA CURSEC
          BPL READ2       ;Always taken
READ      JSR GETTS       ;Get T/S specification
READ2     LSR VALFLAG     ;Show "was read"
          LSR RWFLAG      ;Set READ mode
          JSR RorWsec     ;Read the sector
          JSR SHOWBUF     ;Show it
          JMP READ        ;Back for more

*===============================
*  BAM read and display routine:
*-------------------------------

BAM       LSR RWFLAG      ;Set for READ
          JSR RWBAM       ;Read BAM
          LDY #0          ;Move BAM side 1 to BUFFER
:MB       LDA BAMBUF,Y    ; to support later edit
          STA BUFFER,Y
          INY
          BNE :MB
          JSR PRIMM
          DFB 147         ;Home & clear
          TXT '     Track     11111111111111112222'
          TXT '22222222222233333333333333334444444'0D
:DIGITS   TXT '123456789ABCDEF0123456789ABCDEF0123'
          TXT '456789ABCDEF0123456789ABCDEF0123456'00
          LDY #1
          STY CURTRK
          DEY
          STY CURSEC      ;Init pntr to T1,S0

:BAMLUP   LDA CURTRK
          CMP #36
          BLT :VAL
          SBC #35
:VAL      TAX
          DEX
          CPX #35         ;Check valid track
          BGE :NXT        ; and skip if not
          LDA CURSEC
          CMP MAXSECS,X   ;Check valid sector
          BGE :NXT        ; and skip if not
          LDY CURTRK      ;Use track-1 for htab
          LDX CURSEC      ; sector+3 for vtab
          INX
          INX
          INX
          DEY
          JSR PLOT
          JSR ISUSED      ;Check if sector used
          BNE :NOTUSED    ; and branch if free
          LDY CURSEC
          LDA :DIGITS+15,Y ;Use units digit of sector
          HEX 2C          ; to mark used ones
:NOTUSED  LDA #'.'        ;Else use a period
          JSR CHROUT
:NXT      INC CURSEC      ;Next sector
          LDA CURSEC
          CMP #21
          BLT :BAMLUP
          LDA #0
          STA CURSEC
          INC CURTRK      ;Next track
          LDA CURTRK
          CMP #71
          BLT :BAMLUP     ;Loop till all tested
          LDA #$12        ;Point to BAM (in BUFFER)
          STA CURTRK
          JMP HITKEY      ; and wait for a key, then MENU

*==============================================
* Routine to check if CURTRK, CURSEC is used.
* Returns Z-flag set if used, V clear if side 1
*----------------------------------------------

ISUSED    LDA CURTRK      ;Routine to check if CURSEC
          CMP #36         ; is used
          BGE :SIDE2      ;Branch if side 2
          ASL             ;Track*4
          ASL
          LDY CURSEC
          ADC BYTPNT,Y    ; + byte offset
          TAX
          LDA CURSEC
          AND #%111       ;Sector mod 8
          TAY
          LDA BITS,Y      ;Get bit corr to sector
          AND BAMBUF+1,X  ; test against BAM
          CLV             ;Show side 1
          RTS

:SIDE2    ASL
          ADC CURTRK      ;x3
          SEC
          SBC #36*3       ;Adjust so track 36 -> 0
          CLC
          LDY CURSEC
          ADC BYTPNT,Y    ;Add byte offset
          TAX
          LDA CURSEC
          AND #%111
          TAY
          LDA BITS,Y      ;Get bit corr to sector
          BIT :RET        ;Set V to show side 2
          AND BAMBUF2,X   ;Test against BAM
:RET      RTS             ;Z-flag set if used

*=====================================================
* Routine to read/write the two BAM sectors to BAMBUF:
*-----------------------------------------------------

RWBAM     LDA #$35        ;R/W BAM for side 2
          STA CURTRK
          LDA #0
          STA CURSEC
          LDA #>BAMBUF2
          STA BUFPNT+1
          JSR RorWsec
          LDA #$12
          STA CURTRK      ;R/W side 1 BAM
          DEC BUFPNT+1    ;-> BAMBUF
          JSR RorWsec
          LDA #>BUFFER    ;Reset BUFPNT to default
          STA BUFPNT+1
          RTS

*==================================
*  Routine to input track & sector:
*----------------------------------

GETTS     JSR PRIMM
          HEX 0D
          TXT 'N for next T/S, STOP for main menu,'
          TXT ' ESC to go to edit mode.'
          HEX 0D0D
          TXT 'Track: $'00
          JSR INPUTNUM
          BCS TOMENU      ;Exit C set if illegal
          CMP #27
          BEQ TOED        ;Branch on ESC key
          CMP #'n'
          BEQ :NEXT       ;Branch on N key
          CMP #$D
          BEQ :DFLT       ;Accept last value if RTN
          LDA TEMP        ;Else get the input track
          STA CURTRK
:DFLT     PRINT 0D        ;'Sector: $'
          JSR INPUTNUM
          BCS TOMENU
          CMP #$D
          BEQ CHKRNG      ;Allow 1 dig <RTN>
:ISN      CMP #'n'
          BEQ :NEXT
          LDA TEMP
          JMP :NOTNXT
:NEXT     LDA BUFFER      ;For N key, get the next T/S
          STA CURTRK      ; from 1st two bytes of this
          LDA BUFFER+1    ; sector
:NOTNXT   STA CURSEC
                          ;Fall into CHKRNG
CHKRNG    LDA CURTRK
          CMP #36
          BLT :VAL
          SBC #35
:VAL      TAX
          DEX
          CPX #35         ;Check valid track
          BGE TOMENU      ; and exit to menu if not
          LDA CURSEC
          CMP MAXSECS,X   ;Check valid sector
          BGE TOMENU      ; and exit if not
          RTS             ;All ok, got T/S in CUR...

TOED      PLA
          PLA
          JMP EDIT

TOMENU    JMP MENU

*========================================
*  Routine to print A in hex and decimal:
*----------------------------------------

PHEXDEC   PHA
          JSR BYTHEX
          PRINT ' ('
          PLA
          JSR PRBYT
          LDA #')'
          JMP CHROUT
          PAG
*==================================
*  Routine to postion edit cursor:
*----------------------------------

POSITION  LDA EDPNT       ;Position in buffer
          LSR             ; divided by $10
          LSR
          LSR
          LSR
          CLC
          ADC #4
          TAX             ; + 4 = vert tab
          LDA EDPNT
          AND #$F         ;Posn mod $10
          BIT MODE
          BPL :NOTASC     ;Branch if hex mode
          ADC #3*18       ;+ offset in ascii mode
          BCC :OV         ;Always taken
:NOTASC   TAY
          LDA HORIZ,Y     ;Use mult table in hex mode
:OV       TAY             ;Y = horiz tab, carry is clear
          JMP PLOT

*====================================
*  Routines to display sector buffer:
*------------------------------------

SHOWBUF   PRINT 93        ;'          Track = $'
          LDA CURTRK
          JSR PHEXDEC
          PRINT '          Sector = $'
          LDA CURSEC
          JSR PHEXDEC
          JSR PRIMM
          HEX 0D0D
          TXT '     0  1  2  3  4  5  6  7  8  9  '
          TXT 'A  B  C  D  E  F'0d0d00
          LDY #0
:SETPNT   STY INDEX
          TYA
          JSR BYTHEX      ;Show position of line in buff
          LDA #':'
          JSR CHROUT
          LDY INDEX
:LUP      LDA #' '
          JSR CHROUT
          LDA BUFFER,Y
          JSR BYTHEX      ;Print buffered byte in hex
          INY
          TYA
          AND #$F
          BNE :LUP        ;Loop for $10 bytes
          PRINT '   '
          LDY INDEX
:PRASC    JSR PRNTASC     ;Print corresponding ascii
          INY
          TYA
          AND #$F
          BNE :PRASC
          LDA #$D         ;Move to next line
          JSR CHROUT
          LDA INDEX       ;Update buffer pointer
          CLC             ; to next line
          ADC #$10
          TAY
          BNE :SETPNT     ;Loop till buffer all shown
          RTS

PRNTASC   LDA BUFFER,Y
          AND #$7F        ;We show only the genuine
          CMP #$60        ; printing ascii chars
          BLT :OV         ;This tests for range
          AND #%01011111
:OV       CMP #'z'+1
          BGE :NO
          CMP #' '
          BLT :NO
          LDA BUFFER,Y    ; but we print actual char
          BGE :OUT
:NO       LDA #'.'
:OUT      JSR CHROUT
          LDA #0
          STA QTSW        ;In case a quote is printed
          RTS

BYTHEX    PHA             ;Save low nibble
          LSR
          LSR
          LSR
          LSR
          JSR :PRNIB      ;Print high nibble
          PLA             ;Retrieve low nibble
          AND #$F
:PRNIB    ORA #'0'        ;Convert nibble to ascii
          CMP #'9'+1
          BLT :OUT
          ADC #'A'-'9'-2
:OUT      JMP CHROUT

*===============================
*  Read & write sector routines:
*-------------------------------

RorWsec   JSR OPFILES
          BIT RWFLAG      ;Read or Write?
          BMI WRITESEC

READSEC   LDA #'1'        ;Send U1 command to read
          JSR SNDUSER     ; current sector to disk mem
          JSR CLRCHN
          JSR SETBP       ;Init buffer pointer
          LDX #2
          JSR CHKIN
          LDY #0
:RLUP     JSR ACPTR       ;Move from disk memory
          STA (BUFPNT),Y  ; to main memory buffer
          INY
          BNE :RLUP
          JMP CLOSEFIL

WRITESEC  JSR SETBP       ;Init disk buffer pointer
          LDX #2
          JSR CHKOUT
          LDY #0
:WLUP     LDA (BUFPNT),Y  ;Move main buffer memory
          JSR CIOUT       ; to disk memory
          INY
          BNE :WLUP
          JSR CLRCHN
          LDA #'2'        ;Tell disk to write it (U2 cmd)
          JSR SNDUSER
CLOSEFIL  JSR CLRCHN
          LDA #2
          JSR CLOSE
          LDA #15
          JMP CLOSE

SNDUSER   PHA             ;Save '1' or '2'
          LDX #15
          JSR CHKOUT
          LDA #'u'        ;Send USER command
          JSR CHROUT
          PLA
          JSR CHROUT      ;'1' or '2'
          PRINT ':2,0,'
          LDA CURTRK      ;Track CURTRK
          JSR PRBYT
          LDA #','
          JSR CHROUT
          LDA CURSEC      ;Sector CURSEC
          JSR PRBYT
          JSR CLRCHN      ;Check for error on disk
          LDX #15
          JSR CHKIN
          JSR ACPTR       ;1st digit err #
          STA ERR         ;Save it
          JSR ACPTR       ;2nd digit
          CMP ERR         ;Same?
          BNE ERROR       ;Was error if not
          CMP #'0'        ;Both 0?
          BNE ERROR
          RTS

ERROR     PHA             ;Save 2nd chr
          GOXY 15         ;22
          PRINT 'Disk error:   '
          LDA ERR         ;Print 1st chr
          JSR CHROUT
          PLA             ; then 2nd
:NXCHR    JSR CHROUT
          JSR ACPTR       ;Get rest of err msg
          CMP #$D
          BNE :NXCHR
          JSR CLRCHN
          JSR CLOSEFIL
HITKEY    GOXY 20         ;24
          PRINT 'Hit a key'
          JSR GETKEY
          JMP MENU

SETBP     LDX #15
          JSR CHKOUT
          PRINT 'b-p:2,0'
          JMP CLRCHN

OPFILES   LDA #15
          JSR :DOOPN
          LDA #1
          LDX #:HASH
          LDY #>:HASH
          JSR SETNAM
          LDA #2
:DOOPN    TAY
          LDX DRIVE
          JSR SETLFS
          JMP OPEN

:HASH     TXT '#'

*===================================================
*  Routine to get a key and print it if not control:
*---------------------------------------------------

GETKEY    LDA #'f'
          JSR ESCAPE      ;Set cursor to blink
:RKY      JSR GETIN       ;Get a key
          TAX
          BEQ :RKY        ;Be patient
          STA KEY         ;Save actual key got
          AND #$7F
          LDX #$A         ;Turn cursor off
          STX $D600
:WT       BIT $D600
          BPL :WT
          LDX #$10
          STX $D601
          CMP #$20        ;Branch if control
          BLT :RET
          LDA KEY         ;Show it if not
          JSR CHROUT
          LDX #0
          STX QTSW        ;Defeat the stupid quote mode
          SEC             ;Signal that key printed
:RET      RTS

*=====================================================
*  Routine to input a hex number (for track & sector):
*-----------------------------------------------------

INPUTNUM  LDA #0
:GK       JSR GETKEY      ;Get 1st key
          CMP #27
          BEQ :CC         ;Exit with CC if ESC key
          CMP #$D
          BEQ :CC         ; or if RTN
          CMP #'n'
          BEQ :CC         ; or if N
          CMP #3
          BEQ :ERR        ;Exit with CS if STOP
          JSR MAKDIG      ;Otherwise make hex digit
          BCC :OK         ;Branch if valid digit
:BACK     LDA #20         ;DEL it
          JSR CHROUT
          JMP :GK         ;Back for 1st one again
:OK       STA TEMP        ;Save 1st digit
          JSR GETKEY      ;Get 2nd digit
          BCS :WASP       ;Branch if printing chr
          CMP #$D
          BEQ :ONED       ;Accept 1 dig & RTN
          BNE :BACK       ;DEL if non-printing
:BACK2    LDA #20         ;If not valid then DEL twice
          JSR CHROUT
          JMP :BACK
:WASP     JSR MAKDIG      ;Else assume digit
          BCS :BACK2
          LUP 4
          ASL TEMP
          --^
          ORA TEMP        ;Collect nibbles
          STA TEMP        ;Save for caller
:ONED     LDA #0          ;Signal it was numeric
:CC       CLC
:ERR      RTS

MAKDIG    EOR #'0'        ;Convert ascii A to hex digit
          CMP #10
          BLT :MADE       ;Exit if ok < 10
          ADC #$88        ;Else try A...F
          ORA #$20
          CMP #$FA
          BGE :MADE       ;Branch if valid
          SEC             ;Signal not valid
          RTS
:MADE     CLC             ;Signal valid
          AND #$F         ;Mask off part we want
          RTS

*=================================================
*  Routine to print A in decimal, assumes A < 100:
*-------------------------------------------------

PRBYT     LDX #0          ;Init tens counter
:TEN      CMP #10
          BLT :PB
          SBC #10         ;Divide by 10 using repeated
          INX             ; subtracts and counting them
          BNE :TEN
:PB       PHA             ;Save remainder
          TXA             ;Get quotient
          BEQ :PULL
          JSR :PRNIB      ;Print INT(A/10), then
:PULL     PLA             ; remainder.
:PRNIB    ORA #'0'
          JMP CHROUT

*====================
*  Help text printer:
*--------------------

HELP      JSR PRIMM
          DFB 147
          TXT 'Most of the program is self-explanatory,'
          TXT ' except for reading of T/S lists and'0d
          TXT 'undeleting files.  To read the track '
          TXT 'sector list of a file, first read the'0d
          TXT 'catalog sectors and locate the file name.'
          TXT '  Then go into edit mode with ESC and'0d
          TXT 'place the cursor on the first character '
          TXT 'of the file name.  At this point a'0d
          TXT 'message will appear at the bottom of the'
          TXT ' screen, telling you to press ^T to'0d
          TXT 'read the T/S list of the file.  If you '
          TXT 'do this on a deleted file, ZAP will'0d
          TXT 'also automatically examine the T/S list'
          TXT ' to try to determine if the file can'0d
          TXT 'be safely recovered.  If it can then you'
          TXT ' are offered that option.  If not, you'0d
          TXT 'are told.  The undelete always leaves '
          TXT 'the file as a PRG file.  If this is not'0d
          TXT 'correct you should change the file type'
          TXT ' after the undeletion process.  The'0d
          TXT 'file type is the third byte on the line'
          TXT ' containing the file name.  It should'0d
          TXT 'be changed from $82 (PRG) to $81 for a'
          TXT ' text file, to $83 for a USR file or to'0d
          TXT '$84 for a REL file.'0d0d
          TXT 'When the edit cursor is on the first '
          TXT 'character of a file name you can also'0d
          TXT 'type ^F to "follow" the file.  This will '
          TXT 'show the first sector of the file.'0d
          TXT 'After that you should use the "N" key to '
          TXT 'read subsequent sectors of the file.'0d0d
          TXT 'All input of track and sector numbers '
          TXT 'must be in hexadecimal form.  Usually'0d
          TXT 'you should type them as two digit numbers'
          TXT ' but one digit followed by a CR is also'0d
          TXT 'accepted.  Note that "N" may be typed for'
          TXT ' the track instead of a number.  This'0d
          TXT 'causes the "link" (the first two bytes) of'
          TXT ' the present sector to be used for the'0d
          TXT 'next track and sector.  If this is not a'
          TXT ' valid track and sector, you will be'0d
          TXT 'sent back to the main menu.'0d00
          JMP HITKEY

*=======================================================
* Table of horiz positions for printing bytes in buffer:
*-------------------------------------------------------

]INDEX    = 4
HORIZ    
          LUP $10
          DFB ]INDEX
]INDEX    = ]INDEX+3
          --^

*==================================
* Table of maximum # sectors/ track
*----------------------------------

MAXSECS  
          LUP 17
          DFB 21
          --^
          LUP 7
          DFB 19
          --^
          LUP 6
          DFB 18
          --^
          LUP 5
          DFB 17
          --^

BYTPNT    DFB 0,0,0,0,0,0,0,0
          DFB 1,1,1,1,1,1,1,1
          DFB 2,2,2,2,2,2,2,2

BITS      DFB %00000001
          DFB %00000010
          DFB %00000100
          DFB %00001000
          DFB %00010000
          DFB %00100000
          DFB %01000000
          DFB %10000000

          ERR ^$4000
