home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / dskutl / diag.mac < prev    next >
Text File  |  1994-07-13  |  39KB  |  1,721 lines

  1.     subttl    comments
  2.     title    DIAG - disk diagnostics (C) 1982-1983 P.J.Blower
  3.     .comment "
  4.  
  5. DIAG Vers 2.0 July 1983 - complete rewrite of Vers 1.0
  6.     - Drv, Trk, Sec & Blk sub-commands improved
  7.     - Whole sub-command added
  8.     - Esc & ^C low level escape commands added
  9.     - force Read made optional
  10.     - BACK command added
  11.     - COPY command expanded
  12.     - Fill command added
  13.  
  14.  
  15.     Alternate    Help        O        Verify
  16.     Back        I        P        Write
  17.     Copy        J        Quit        X
  18.     Display        K        Read        Y
  19.     Edit        List        S        Z
  20.     Fill        M        Translate
  21.     G        Next        U
  22.  
  23.     "
  24.     subttl    equates
  25.     .Z80
  26.     ASEG
  27.  
  28.     ORG    0100h
  29.  
  30. WBOOT    EQU    0000h
  31. BDOS    EQU    0005h
  32. FCB    EQU    005Ch    ;default File Control Block
  33. FCBRR    EQU    FCB+33    ;random record number
  34. CPMBUF    EQU    0080h    ;CP/M command buffer
  35.  
  36. BS    EQU    08h
  37. CR    EQU    0Dh
  38. LF    EQU    0Ah
  39. ESC    EQU    1Bh
  40. LLF    EQU    8Ah    ;LF with top bit set
  41. ;-------------------------------
  42.     subttl    main program
  43.  
  44.     JP    INIT
  45.  
  46. FRC:    DB    0    ;optional forcing byte for systems with volatile CBIOSs
  47.  
  48. CURRT:    DB    0Ch    ;video cursor right
  49. CURUP:    DB    0Bh    ;video cursor up
  50.  
  51. KBD:    DB    04h    ;keyboard cursor left
  52.     DB    03h    ;keyboard cursor right
  53.     DB    01h    ;keyboard cursor up
  54.     DB    02h    ;keyboard cursor down
  55.  
  56. SIGNON:    DB    "DIAG 820 Pre-release V2.0  Copyright (c) July 1983
  57. P.J.Blower",CR,LF,LF
  58.     DB    "Note that CP/M 128 byte sectors are used throughout,",CR,LF
  59.     DC    "  these may not coincide with actual physical sectors."
  60.  
  61. ; current drive parameter table
  62. DIRBUF:    DW    0        ;addr of DIR buffer
  63. BLKSIZ:    DW    0        ;Block size = BLKSIZ *128
  64. SYSTRK:    DW    0        ;no of system tracks
  65. MAXTRK:    DW    0        ;max no of tracks
  66. BUF1:    DW    BUFF1        ;buffer..
  67. BUF2:    DW    CPMBUF        ;..addresses
  68.  
  69. PPARAM:                ;space for backup parameters
  70.     DB    0
  71.     DW    0
  72.     DW    0
  73.     DB    7
  74.     DW    0
  75.     DW    0
  76.  
  77. PRMLEN    EQU    $-PPARAM
  78.  
  79. SPARAM:            ;temporary function save area
  80. SDRIVE:    DB    0
  81. STRACK:    DW    0
  82. SSECT:    DW    0
  83. SBLKSW:    DB    0
  84. SBLOCK:    DW    0
  85. SBLCKE:    DW    0
  86.  
  87. TPARAM:    DS    PRMLEN        ;temporary function save area
  88.  
  89. CPARAM:
  90. CDRIVE:    DB    0        ;current drive
  91. CTRACK:    DW    0        ;current track
  92. CSECT:    DW    0        ;current sector
  93. CBLKSW:    DB    7        ;switch block marker
  94. CBLOCK:    DW    0        ;current block
  95. CBLCKE:    DW    0        ;current block extension
  96.  
  97. UPARAM:            ;upper limit value save area
  98. UDRIVE:    DB    0
  99. UTRACK:    DW    0
  100. USECT:    DW    0
  101. UBLKSW:    DB    0
  102. UBLOCK:    DW    0
  103. UBLCKE:    DW    0
  104.  
  105. DPARAM:            ;destination value save area
  106. DDRIVE:    DB    0
  107. DTRACK:    DW    0
  108. DSECT:    DW    0
  109. DBLKSW:    DB    0
  110. DBLOCK:    DW    0
  111. DBLCKE:    DW    0
  112.  
  113. OPARAM:            ;destination upper value
  114. ODRIVE:    DB    0
  115. OTRACK:    DW    -1        ;force almost
  116. OSECT:    DW    -1        ;..indefinate read or write
  117. OBLKSW:    DB    0
  118. OBLOCK:    DW    -1
  119. OBLCKE:    DW    -1
  120.  
  121. EPARAM:
  122. ;-------------------------------
  123.  
  124. INIT:    LD    SP,STACK
  125.     LD    HL,(WBOOT+1)    ;HL = addr CBIOS WBOOT
  126.     LD    L,06        ;put CBOIS addresses into rest of prog
  127.     LD    BC,3        ;length of JP instruction
  128.     LD    (CONST+1),HL
  129.     ADD    HL,BC
  130.     LD    (CONNIN+1),HL
  131.     ADD    HL,BC
  132.     LD    (CONOUT+1),HL
  133.     ADD    HL,BC
  134.     LD    (LISTP+1),HL
  135.     LD    L,18h
  136.     LD    (HOME+1),HL
  137.     ADD    HL,BC
  138.     LD    (SELDSK+1),HL
  139.     ADD    HL,BC
  140.     LD    (SETTRK+1),HL
  141.     ADD    HL,BC
  142.     LD    (SETSEC+1),HL
  143.     ADD    HL,BC
  144.     LD    (SETDMA+1),HL
  145.     ADD    HL,BC
  146.     LD    (READFF+1),HL
  147.     ADD    HL,BC
  148.     LD    (WRITF+1),HL
  149.     ADD    HL,BC
  150.     ADD    HL,BC
  151.     LD    (SCTRAN+1),HL
  152.  
  153.     LD    HL,KBD        ;put cursor controls into EDIT
  154.     LD    A,(HL)
  155.     LD    (EDIT12+1),A    ;left cursor
  156.     INC    HL
  157.     LD    A,(HL)
  158.     LD    (EDIT17+1),A    ;right cursor
  159.     INC    HL
  160.     LD    A,(HL)
  161.     LD    (EDIT18+1),A    ;up cursor
  162.     INC    HL
  163.     LD    A,(HL)
  164.     LD    (EDIT16+1),A    ;down cursor
  165.  
  166.     INC    HL        ;point to SIGNON
  167.     CALL    CPMSG
  168.     LD    A,(CDRIVE)
  169.     LD    C,A
  170.     CALL    CHK1        ;get disk parameters
  171.     CALL    CONIN
  172.  
  173. ;HELP menu - print everything but ignore control bytes & jumps
  174. HELP:    CALL    CPRINT
  175.     DB    LF
  176.     DC    "Single letter commands available in DIAG"
  177.     LD    HL,MENUM
  178.     LD    B,CMDS+1    ;number of avaible commands
  179. HELP1:    CALL    CPMSG        ;print msg
  180.     LD    A,(HL)        ;get control byte
  181.     AND    11111110b    ;mask
  182.     OR    A        ;test it
  183.     CALL    NZ,SUBMSG    ;print sub-commands
  184.     INC    HL        ;step over to next msg
  185.     INC    HL
  186.     INC    HL
  187.     DJNZ    HELP1
  188.  
  189. ;main command menu
  190. MENU:    LD    SP,STACK
  191.     LD    HL,COPYBK    ;point ESC & ^C to COPYBK routine
  192.     LD    (ABORT+1),HL
  193.     LD    HL,MENU        ;save return address
  194.     PUSH    HL
  195.     XOR    A
  196.     LD    (MENU7+1),A    ;kill any outstanding repeat function
  197.     LD    (MENU9+1),A    ;and CURUP calls
  198.     CALL    HOME        ;for safety
  199. ;CALL TEST
  200. MENU1:    CALL    CPRINT        ;print promt
  201.     DC    "DIAG>>"
  202. MENU2:    CALL    CONIN        ;get user response
  203.     CP    " "
  204.     JP    Z,HELP        ;jump if space
  205.     CP    CR
  206.     JR    Z,MENU1        ;go to new line
  207.  
  208.     LD    HL,MENUM    ;pointer to menu list
  209.     LD    B,CMDS        ;no. of commands available
  210. MENU3:    CP    (HL)        ;get first character
  211.     JR    Z,MENU4        ;jump if compare
  212.     CALL    DMSG        ;inc HL to end of msg
  213.     INC    HL        ;skip past control byte
  214.     INC    HL        ;.. & address
  215.     INC    HL
  216.     DJNZ    MENU3        ;search for next
  217.     JR    MENU2        ;failed, go back
  218.  
  219. ;command letter found - print command then call SCMD if necc. then jump
  220. MENU4:    LD    (MENU5+1),HL    ;save msg pointer
  221.     CALL    SMSG        ;print until space
  222.     CALL    DMSG        ;inc HL to end of msg
  223.     CALL    PRINT
  224.     DC    ">"
  225.     PUSH    HL        ;save addr
  226.     LD    A,(HL)        ;get control byte
  227.     LD    (SRPT1+1),A    ;save for SRPT
  228.     CALL    SCMD        ;get more Drv,Trk,Sec,Blk commands if necc.
  229.     POP    HL
  230.     PUSH    HL
  231.     CALL    SDEST        ;check (& act) if destination required
  232.     POP    HL
  233.     LD    A,(SCMDX+1)    ;get used control byte
  234.     CP    (HL)        ;different?
  235.     CALL    NZ,CRLF        ;yes, call CRLF
  236.     INC    HL        ;point to address
  237.     CALL    GETADR        ;get it
  238.     LD    (MENU6+1),HL    ;save addr
  239.     JR    Z,MENU6        ;not different, skip
  240. MENU5:    LD    HL,0        ;command msg pointer here
  241.     CALL    SMSG        ;print command
  242.     CALL    PRINT
  243.     DC    "-"
  244. MENU6:    LD    HL,0        ;addr pointer stored here
  245.     CALL    CALADR        ;call addr in HL
  246.  
  247. MENU7:    LD    A,0        ;repeated function indicator stored here
  248.     OR    A
  249.     RET    Z        ;ret if not required
  250.     LD    A,(UBLKSW)    ;get block switch marker
  251.     OR    A        ;clear carry
  252.     JR    Z,MENUJJ
  253.     LD    DE,TPARAM    ;copy..
  254.     CALL    COPYF1        ;Cparam to Tparam..
  255.     CALL    COPYF2        ;& Uparam to Cparam
  256.     CALL    KBLK        ;translate Blk into Trk & Sec
  257.     CALL    SRPT2        ;restore to original state
  258. MENUJJ:    LD    A,0        ;drive whole marker stored here
  259.     OR    A
  260.     JR    Z,MENU8
  261.     LD    HL,(MAXTRK)
  262.     LD    (UTRACK),HL
  263.     XOR    A
  264.     LD    (MENUJJ+1),A
  265.  
  266. MENU8:    CALL    INCSEC        ;inc next sector
  267.     CALL    UCOMP        ;compare Ctrk,Csec with Utrk,Usec
  268.     JR    Z,DECSEC    ;ret & dec sector if limit passed
  269.     JR    C,DECSEC
  270.     CALL    SCAN        ;scan for user interrupts
  271. MENU9:    LD    A,0        ;optional CURUP char stored here
  272.     CALL    POUT
  273.     JR    MENU5        ;do some more
  274. ;-------------------------------
  275. SCAN:    EXX            ;scan for any user interrupt
  276. CONST:    CALL    0        ;CONST addr stored here
  277.     EXX
  278.     INC    A        ;waiting char?
  279.     JR    NZ,SCAN1
  280.     CALL    HOME        ;safety call
  281.     CALL    CONN        ;yes, collect waiting char
  282.     CALL    CONN        ;yes, wait for any i/p or ESC
  283. SCAN1:    JP    CRLF
  284. ;-------------------------------
  285. ;Decrement sector count
  286. DECSEC:    LD    HL,(CSECT)    ;get current sector
  287.     DEC    HL
  288.     LD    (CSECT),HL
  289.     CALL    CHKSEC        ;maximum reached?
  290.     RET    C        ;no, ret
  291.     LD    HL,(CTRACK)    ;get current track
  292.     DEC    HL
  293.     LD    (CTRACK),HL    ;load current track
  294.     EX    DE,HL        ;make max no. of sectors
  295.     DEC    HL
  296.     JR    INCS1        ;save & ret
  297. ;-------------------------------
  298. ;Increment sector count
  299. INCSEC:    LD    HL,(CSECT)    ;get current sector
  300.     INC    HL
  301.     LD    (CSECT),HL
  302.     CALL    CHKSEC        ;maximum reached?
  303.     RET    C        ;no, ret
  304.     LD    HL,(CTRACK)    ;get current track
  305.     INC    HL
  306.     LD    (CTRACK),HL    ;load current track
  307.     LD    HL,0        ;make sector = 0
  308. INCS1:    LD    (CSECT),HL    ;save
  309.     RET
  310. ;-------------------------------
  311. JPADDR:    CALL    GETADR        ;get address
  312. CALADR:    JP    (HL)        ;jump to it
  313. ;-------------------------------
  314. ;examine control byte, call sub-commands upon request
  315. SCMD:    LD    (SCMDX+1),A
  316.     AND    11111110b    ;mask for Drv,Trk,Sec,Blk
  317.     RET    Z
  318.     LD    C,A
  319. SCMD0:    LD    A,0        ;last user character stored here
  320.     CP    CR
  321.     RET    Z
  322.     CP    "-"
  323.     JR    NZ,SCMD1
  324.     LD    A,"u"
  325. SCMD1:    LD    HL,SUBMM    ;msg pointer
  326.     LD    B,NSUB        ;no. of sub-commands
  327. SCMD2:    RLC    C
  328.     JR    NC,SCMD3
  329.     CP    (HL)        ;same as first char?
  330.     CALL    Z,SMSG        ;yes, print
  331. SCMD3:    CALL    DMSG        ;lose rest of msg
  332.     JR    Z,SCMDX        ;jump if match
  333.     INC    HL
  334.     INC    HL
  335.     DJNZ    SCMD2        ;loop round for more
  336.     CALL    CONIN        ;get user response
  337. SCMDX:    LD    A,0        ;save control byte here
  338.     LD    C,2        ;no. of spaces
  339.     CALL    Z,JPADDR    ;call sub-command
  340.     JR    SCMD
  341. ;-------------------------------
  342. ;get repeated function parameters
  343. SRPT:    LD    (MENU7+1),A    ;flag repeated function in MENU
  344.     LD    DE,TPARAM    ;copy Cparam to Tparam
  345.     CALL    COPYF1        ;do it
  346. SRPT1:    LD    A,0        ;copy of control byte here
  347.     AND    01110000b
  348.     CALL    SCMD        ;get upper limit track & sector values
  349. SRPT2:    LD    HL,UPARAM-1    ;point to Uparam
  350.     LD    DE,DPARAM-1    ;restore original values
  351. SRPT4:    LD    BC,2*PRMLEN    ;2x
  352.     LDDR
  353.     RET
  354.  
  355. SRPT5:    LD    HL,DPARAM-1
  356.     JR    SRPT4
  357. ;-------------------------------
  358. ;check if destination required, if so then get parameters
  359. SDEST:    LD    A,(SRPT1+1)    ;get control byte
  360.     BIT    2,A        ;destination required
  361.     RET    Z        ;no, ret
  362.     AND    11110100b    ;mask for Drv,Trk,Sec,Blk
  363.     PUSH    AF
  364.     LD    A,(SCMDX+1)    ;get used command byte
  365.     CP    (HL)        ;any change?
  366.     LD    C,15
  367.     CALL    NZ,CSPINC    ;yes, print CRLF and 15 spaces
  368.     LD    A,"t"        ;print "to" msg
  369.     LD    (SCMD0+1),A    ;..& dispose of any remaining CR
  370.     CALL    CPYWY        ;shift Dparam over the Cparam slot
  371.     LD    HL,SPARAM    ;copy original current values for safety
  372.     LD    DE,CPARAM
  373.     CALL    COPYF2
  374.     POP    AF
  375.     CALL    SCMD        ;get destination track & sector values
  376. SDESTE:    LD    DE,EPARAM-1    ;save destination values
  377.     CALL    SRPT5
  378.     JR    SRPT4        ;put back original parameters & ret
  379. ;-------------------------------
  380. ;get drive number
  381. SDRV:    AND    01111111b    ;lose next Drv command
  382.     PUSH    AF
  383.     CALL    CONIN
  384.     PUSH    AF
  385.     SUB    "A"        ;check if range A-P
  386.     JR    C,SDRV1
  387.     OR    10000000b    ;nobble last char
  388.     LD    (SCMD0+1),A
  389.     AND    01111111b
  390.     CP    "P"-"A"+1
  391.     JR    C,SDRV2        ;OK, skip
  392. SDRV1:    LD    A,(CDRIVE)
  393. SDRV2:    LD    (CDRIVE),A
  394.     ADD    A,"A"
  395.     CALL    POUT
  396.     POP    AF
  397.     CP    "W"        ;Whole command?
  398.     JR    NZ,SDRV3    ;no, skip
  399.     LD    (SCMD0+1),A    ;put "W" in for WHOLE routine
  400. SDRV3:    CALL    NZ,CONIN    ;get next char (Whole or SCMD)
  401.     CALL    WHOLE        ;was it Whole?
  402.     JR    NZ,SRETW    ;no, jump & ret
  403.     LD    (MENUJJ+1),A    ;force MENU to put in last track after CHECK
  404.     XOR    A
  405.     LD    (CBLKSW),A    ;ensure no block translation
  406.     LD    HL,0        ;zeroise track count
  407.     LD    (CTRACK),HL
  408.     LD    HL,(MAXTRK)
  409.     JR    STRK1        ;continue with sector
  410. ;-------------------------------
  411. ;get Track no. & put into CTRACK
  412. STRK:    AND    10101101b    ;lose next Trk & Blk commands
  413.     PUSH    AF
  414.     LD    HL,(CTRACK)
  415.     CALL    GETDEC
  416.     LD    (CTRACK),HL
  417.     XOR    A
  418.     LD    (CBLKSW),A    ;ensure no block translation
  419.     CALL    WHOLE        ;was there a Whole command?
  420.     JR    NZ,SRETW    ;no, jump & ret
  421.     LD    HL,(CTRACK)
  422.     INC    HL
  423. STRK1:    LD    (UTRACK),HL    ;make Utrk = Ctrk+1
  424.     POP    AF
  425.     LD    HL,0        ;zeroise sector count
  426.     LD    (CSECT),HL
  427.     LD    (USECT),HL
  428.     XOR    A        ;no more commands
  429.     LD    (UBLKSW),A    ;force Track interpretation
  430.     RET
  431. ;-------------------------------
  432. WHOLE:    CALL    SPINC
  433.     LD    A,(SCMDX+1)
  434.     AND    00000010b
  435.     XOR    00000010b
  436.     RET    NZ
  437.     LD    A,(SCMD0+1)
  438.     CP    "W"        ;was last char "W"?
  439.     RET    NZ
  440.     PUSH    AF
  441.     LD    (MENU7+1),A    ;make it a repeated function
  442.     CALL    PRINT
  443.     DC    "Whole"
  444. SRETW:    POP    AF
  445.     RET
  446. ;-------------------------------
  447. ;get Block no. & block offset
  448. SBLK:    AND    10001101b
  449.     PUSH    AF
  450.     PUSH    BC
  451.     LD    B,4        ;no. of i/p chars
  452.     XOR    A        ;clear SBLK3
  453.     LD    HL,SBLK3+2
  454.     LD    (HL),A
  455.     DEC    HL
  456.     LD    (HL),A
  457. SBLK1:    CALL    GETHEX        ;get hex i/p
  458.     JR    C,SBLK2        ;jump if non-hex
  459.     RLD            ;put into CBLOCK
  460.     INC    HL
  461.     RLD
  462.     DEC    HL
  463.     DJNZ    SBLK1
  464. SBLK2:    LD    A,4        ;test if any hex i/p
  465.     CP    B
  466. SBLK3:    LD    HL,0        ;hex i/p stored here
  467.     JR    Z,SBLK4        ;skip if no hex i/p
  468.     LD    (CBLOCK),HL
  469. SBLK4:    LD    HL,(CBLOCK)
  470.     CALL    Z,B4HEX        ;print BLK no. if no meaningful i/p
  471.     LD    A,":"
  472.     CALL    POUT
  473.     LD    A,(SCMD0+1)    ;get last char
  474.     CP    CR
  475.     JR    Z,SBLK5
  476.     CP    " "
  477.     JR    Z,SBLK5
  478.     CP    "W"
  479.     JR    Z,SBLK5
  480.     LD    HL,(CBLCKE)    ;get previous extension value
  481.     CALL    GETDEC        ;get new value
  482.     JR    SBLK6
  483.  
  484. SBLK5:    LD    A,"0"
  485.     CALL    POUT
  486.     CALL    POUT
  487.     LD    HL,0
  488. SBLK6:    LD    (CBLCKE),HL
  489.     LD    (CBLKSW),A
  490.     POP    BC        ;get space value
  491.     CALL    WHOLE        ;check for Whole command
  492.     JR    NZ,SRETW    ;no, jump & ret
  493.     LD    (UBLKSW),A    ;force examinatoin of Blk cmnd
  494.     POP    AF
  495.     LD    HL,(CBLOCK)
  496.     INC    HL
  497.     LD    (UBLOCK),HL    ;put CBLOCK+1 in UBLOCK
  498.     LD    HL,0
  499.     LD    (UBLCKE),HL    ;put in block boundary
  500.     XOR    A        ;no more commands
  501.     RET
  502. ;-------------------------------
  503. ;get Sector no. & put into CSECT
  504. SSEC:    PUSH    AF
  505.     LD    HL,(CSECT)
  506.     CALL    GETDEC
  507.     LD    (CSECT),HL
  508.     XOR    A
  509.     LD    (CBLKSW),A    ;ensure no block translation
  510.     POP    AF
  511.     AND    11001101b    ;lose next Sec & Blk commands
  512.     JP    SPINC
  513. ;-------------------------------
  514. ;put Block no. & block offset into CTRACK & CSECT
  515. KBLK:    LD    A,(CBLKSW)
  516.     OR    A
  517.     RET    Z
  518.     LD    HL,(SYSTRK)
  519.     LD    (CTRACK),HL
  520.     LD    HL,(CBLCKE)    ;start with Block extension sectors
  521.     LD    (CSECT),HL
  522.     LD    BC,(CBLOCK)
  523.     JR    KBLK2
  524. KBLK1:    LD    DE,(BLKSIZ)
  525.     INC    DE        ;DE= no. of sectors/block
  526.     CALL    ADDSEC
  527.     DEC    BC
  528. KBLK2:    LD    A,B
  529.     OR    C
  530.     JR    NZ,KBLK1
  531.     XOR    A
  532.     LD    (CBLKSW),A    ;force Trk interpretation
  533.     RET
  534. ;-------------------------------
  535. ;control byte definitions for SUBCMD
  536. ;    X000 0000    - Drive
  537. ;    0X00 0000    - Track
  538. ;    00X0 0000    - Sector
  539. ;    000X 0000    - Block
  540. ;    0000 X000    - marker to allow repeated function
  541. ;    0000 0X00    - marker to allow repeated function inc DRV
  542. ;    0000 00X0    - marker to allow "Whole" command
  543. ;    0000 000X    - no list device allowed
  544. MENUM:    
  545.     DB    "Help or",CR,LF
  546.     DC    "(space)   - prints this menu"
  547.     DB    0
  548.     DW    HELP
  549.  
  550.     DC    "Display   - display current buffer"
  551.     DB    0
  552.     DW    DISPLY
  553.  
  554.     DC    "Alternate - switch to alternate buffer"
  555.     DB    0
  556.     DW    ALT
  557.  
  558.     DC    "Edit      - edit current buffer (hex or ,ascii)"
  559.     DB    0
  560.     DW    EDIT
  561.  
  562.     DC    "Fill      - fill current buffer (hex or ,ascii)"
  563.     DB    0
  564.     DW    FILL
  565.  
  566. READM:    DC    "Read      -"
  567.     DB    11111010b
  568.     DW    READ
  569.  
  570.     DC    "Next      - read next sector"
  571.     DB    0
  572.     DW    NEXT
  573.  
  574.     DC    "Back      - read previous sector"
  575.     DB    0
  576.     DW    BACK
  577.  
  578. WRITEM:    DC    "Write     -"
  579.     DB    11111010b
  580.     DW    WRITE
  581.  
  582.     DC    "Copy      -"
  583.     DB    11111110b
  584.     DW    COPY
  585.  
  586.     DC    "Verify    -"
  587.     DB    11111010b
  588.     DW    VERIFY
  589.  
  590.     DC    "List      - list directory block usage"
  591.     DB    10000000b
  592.     DW    LIST
  593.  
  594.     DC    "Translate - displays sector translation table"
  595.     DB    10000000b
  596.     DW    TRANS
  597.  
  598.     DC    "Quit      - exit to CP/M"
  599.     DB    0
  600.     DW    0
  601.  
  602. CMDS    EQU    14        ;no. of commands available
  603.  
  604.     DB    "(HELP Key) - exit to CP/M at any time",CR,LF
  605.     DB    "(Esc)      - return to Command mode at any time",CR,LF,LF
  606.     DB    "notation   - d= decimal, h= hex",CR,LF
  607.     DB    "Whole      - is available under Drv, Trk & Blk",LLF
  608.     DB    0
  609. ;-------------------------------
  610. ;bit pattern in A organised as follows:-
  611. ;    X000 0000    Drive
  612. ;    0X00 0000    Track
  613. ;    00X0 0000    Sector
  614. ;    000X 0000    Block
  615. ;    0000 X000    Repeated functions
  616. ;    0000 0X00    Repeated functions including drive
  617. SUBMSG:
  618.     PUSH    HL        ;save MENU msg pointer
  619.     PUSH    BC
  620.     LD    B,NSUB        ;no. of messages
  621.     LD    HL,SUBMM
  622. SUBM1:    RLCA            ;rotate to carry
  623.     CALL    C,PMSG        ;print if bit set
  624.     CALL    NC,DMSG        ;else send to dummy print routine
  625.     INC    HL        ;inc past address
  626.     INC    HL
  627.     DJNZ    SUBM1
  628.     POP    BC
  629.     POP    HL
  630. SRET:    AND    11110000b    ;mask for SDEST only
  631.     RET
  632.  
  633. SUBMM:
  634. DRVM:    DC    "Drive A-P"
  635.     DW    SDRV
  636. TRKM:    DC    "Track d"
  637.     DW    STRK
  638. SECM:    DC    "Sector d"
  639.     DW    SSEC
  640. BLKM:    DC    "Block h:d"
  641.     DW    SBLK
  642. UNTLM:    DC    "until Trk Sec Blk"
  643.     DW    SRPT
  644. TOMSG:    DC    "to DvTkScBk"
  645.     DW    SRET
  646. NSUB    EQU    6        ;no. of commands
  647. ;-------------------------------
  648. LIST:    CALL    CRLF
  649.  
  650.  
  651.     RET
  652. ;-------------------------------
  653. TRANS:    CALL    CHK        ;get parameters
  654.     CALL    PRINT
  655.     DC    "decimal sectors"
  656.     LD    BC,10*256+10    ;0-9, 10 spaces
  657.     CALL    CRLLF
  658.     CALL    SPINC
  659. TRANS1:    LD    C,4        ;spaces
  660.     CALL    SPINC
  661.     LD    A,10
  662.     SUB    B
  663.     CALL    B2HEX        ;print 0 - 9
  664.     DJNZ    TRANS1
  665.     CALL    CRLF
  666.     LD    HL,0
  667.  
  668. TRANS2:    LD    BC,10*256+3    ;0-9, 3 spaces
  669.     CALL    CSPINC
  670.     LD    A," "
  671.     CALL    B2DEC1
  672.     LD    C,1        ;1 space
  673.     CALL    PRINT
  674.     DC    ":"
  675. TRANS3:    CALL    SPINC
  676.     PUSH    HL        ;CP/M sector no.
  677.     PUSH    BC
  678.     CALL    CXLT0        ;translate
  679.     CALL    B2DEC2        ;print translation
  680.     POP    BC
  681.     POP    DE        ;get sect no.
  682.     INC    DE
  683.     LD    HL,(MAXSEC+1)    ;sector maximum
  684.     SCF
  685.     SBC    HL,DE        ;limit reached?
  686.     JP    C,CRLF        ;yes, finished
  687.     EX    DE,HL        ;back to HL
  688.     DJNZ    TRANS3        ;do some more
  689.     JR    TRANS2        ;go start another 10
  690. ;-------------------------------
  691. VERIFY:    LD    A,(CURUP)
  692.     LD    (MENU9+1),A    ;do automatic CURUP in SCAN
  693.     CALL    CHECK1        ;get & display disk parameters
  694.     LD    HL,(CSECT)
  695.     JP    READF        ;high speed read
  696. ;-------------------------------
  697. ;Read previous sector
  698. BACK:    CALL    DECSEC
  699.     JR    READ
  700. ;-------------------------------
  701. ;Read Next sector
  702. NEXT:    CALL    INCSEC
  703. ;-------------------------------
  704. ; Read <block> or <track,sector>
  705. READ:    CALL    CHECK
  706.     CALL    FORCE        ;force BIOS to read every sector every time
  707.     JR    DSPLY0
  708. ;-------------------------------
  709. ;part of ^C & ESC routine, invokes EDITF in edit mode
  710. CONED:    CALL    EDITF
  711.     CALL    CRLF
  712. ;-------------------------------
  713. ;switch to alternate buffer
  714. ALT:    LD    HL,(BUF1)
  715.     EX    DE,HL
  716.     LD    HL,(BUF2)
  717.     LD    (BUF1),HL
  718.     EX    DE,HL
  719.     LD    (BUF2),HL
  720. ;-------------------------------
  721. DISPLY:    CALL    CHECK
  722. DSPLY0:    CALL    CRLF
  723.     LD    BC,16*100h+8    ;write 0-F for HEX heading & 8 spaces
  724.     CALL    CSPINC        ;CRLF followed by C spaces
  725.     XOR    A
  726. DSPLY1:    LD    C,2
  727.     CALL    SPINC        ;2 spaces
  728.     CALL    B1HEX        ;print 0-9,A-F
  729.     INC    A
  730.     DJNZ    DSPLY1
  731.     CALL    SPINC
  732.  
  733.     LD    B,16        ;write 0-F for ASCII heading
  734.     XOR    A
  735. DSPLY2:    CALL    B1HEX
  736.     INC    A
  737.     DJNZ    DSPLY2
  738.     CALL    CRLLF
  739.  
  740. ;display buffer
  741.     LD    HL,(BUF1)
  742.     LD    BC,8*100h+5    ;B= 8 rows, C= 5 spaces
  743.     LD    E,"0"        ;row address character
  744. DSPLY3:    CALL    SPINC
  745.     LD    A,E        ;char to A
  746.     CALL    POUT        ;print it
  747.     CALL    DISPHL        ;print row of HEX & ASCII
  748.     INC    E        ;next char
  749.     DJNZ    DSPLY3
  750.     RET
  751. ;-------------------------------
  752. ; display 16 characters in HEX & ASCII starting at addr in HL
  753. DISPHL:    PUSH    BC
  754.     LD    C,2        ;2 spaces
  755.     CALL    SPINC
  756.     LD    B,16        ;B= 16 values
  757.     PUSH    BC
  758.     DEC    C        ;1 space
  759.     PUSH    HL
  760. DSPHL1:    LD    A,(HL)        ;get value
  761.     CALL    SPINC        ;print 1 space
  762.     CALL    B2HEX        ;print hex display
  763.     INC    HL
  764.     DJNZ    DSPHL1
  765.     POP    HL
  766.     POP    BC
  767.     CALL    SPINC        ;2 spaces
  768. DSPHL2:    LD    A,(HL)        ;get value again
  769.     CALL    PASC        ;print ASCII only
  770.     INC    HL
  771.     DJNZ    DSPHL2
  772.     POP    BC
  773.     JP    CRLF
  774. ;-------------------------------
  775. ; force BIOS to do a sector read away from current sector,
  776. ; & hence complete a pysical read or write
  777. FORCE:    LD    HL,(MAXSEC+1)
  778.     DEC    HL
  779.     SRL    H        ;divide by 2
  780.     RR    L
  781.     EX    DE,HL
  782.     LD    HL,(CSECT)    ;get current sector
  783.     LD    A,(FRC)        ;get FRC byte
  784.     OR    A
  785.     JR    Z,READF        ;jump if special forcing not required
  786.     PUSH    HL        ;save
  787.     SBC    HL,DE        ;take away half total sectors
  788.     JR    NC,FORCE1    ;jump if still +ve
  789.     ADC    HL,DE        ;add total sectors
  790.     ADC    HL,DE
  791. FORCE1:    CALL    READF        ;do a read
  792.     POP    HL        ;now read desired sector
  793.  
  794. ; read a sector via sector translation table
  795. READF:    PUSH    HL
  796.     CALL    CXLT0        ;translate if neccessary
  797. READFF:    CALL    0        ;read sector
  798.     POP    HL
  799. ERRCHK:    OR    A
  800.     RET    Z
  801.     PUSH    HL
  802.     CALL    PRINT
  803.     DC    "*** Read Error - Sector"
  804.     POP    HL
  805.     JP    B2DEC
  806. ;-------------------------------
  807. ; write a sector via sector translation table
  808. WRITEF:    LD    BC,(BUF1)    ;write from first buffer
  809.     CALL    SETDMA
  810.     LD    HL,(CSECT)
  811.     CALL    CXLT0        ;set sector via sector trans table
  812.     LD    C,1        ;normal sector write
  813. WRITF:    CALL    0        ;write sector
  814.     JR    ERRCHK        ;check for errors
  815. ;-------------------------------
  816. WRITE:    CALL    CHECK
  817.     LD    BC,(BUF2)    ;read sector into alternate buffer
  818.     CALL    SETDMA
  819.     LD    HL,(CSECT)
  820.     CALL    CXLT0        ;set sector via translation table
  821.     CALL    READF
  822.     CALL    WRITEF        ;write sector
  823.     JP    FORCE
  824. ;-------------------------------
  825. EDIT:    LD    HL,CONED    ;addr for ESC & ^C handling
  826.     LD    (ABORT+1),HL    ;modify ESC & ^C to call EDITF
  827.     CALL    DISPLY        ;display buffer
  828.     LD    HL,(BUF1)    ;copy data buffer
  829.     LD    DE,(BUF2)    ;to alternate buffer
  830.     LD    BC,128
  831.     LDIR
  832. EDIT0:    LD    A,(CURUP)    ;bring cursor over first character
  833.     LD    B,8
  834.     CALL    CURS1
  835.     LD    HL,(BUF1)    ;first location
  836.  
  837. EDIT1:    CALL    WEDIT        ;get position in line in C
  838.     LD    A,CR
  839.     CALL    POUT
  840.     LD    A,C        ;multiply by 3
  841.     ADD    A,A
  842.     ADD    A,C
  843.     ADD    A,9        ;add 9
  844.     LD    B,A
  845.     CALL    CURS        ;bring cursor to right place
  846.  
  847. ;get value & put in buffer
  848.     CALL    GETHEX        ;get single hex digit in A (no carry if OK)
  849.     JR    C,EDIT10    ;not hex, jump 
  850.     RLCA
  851.     RLCA            ;rotate to upper nibble
  852.     RLCA
  853.     RLCA
  854.     LD    B,A        ;save in B
  855. EDIT3:    CALL    GETHEX        ;get other lo nibble
  856.     JR    C,EDIT3
  857.     ADD    A,B        ;add together
  858.     LD    (HL),A
  859.  
  860. ; update ASCII representation
  861. EDIT4:    LD    A,C        ;position in line
  862.     SUB    17
  863.     CPL
  864.     ADD    A,A
  865.     ADD    A,15
  866.     LD    B,A        ;shift cursor to ASCII position
  867.     CALL    CURS
  868.     LD    A,(HL)
  869.     CALL    PASC        ;print ASCII only
  870.  
  871. ; check if last position in line, if so goto next line
  872. EDIT5:    LD    A,C        ;get position in line
  873.     CP    15        ;last position?
  874.     JR    NZ,EDIT7
  875. EDIT6:    CALL    CRLF
  876. EDIT7:    INC    HL        ;inc buffer pointer
  877.  
  878. ; check if still in buffer space
  879. EDIT8:    CALL    WEDIT        ;get new positions
  880.     JR    NC,EDIT9    ;jump if not past beginning
  881.     INC    HL        ;inc buffer pointer
  882.     INC    DE
  883.     CALL    CRLF
  884. EDIT9:    EX    DE,HL        ;HL= distance into buffer
  885.     LD    BC,128
  886.     SBC    HL,BC        ;past end?
  887.     EX    DE,HL
  888.     JR    C,EDIT1        ;no, jump
  889.     JR    EDIT0        ;yes, start at beginning
  890. ;-------------------------------
  891. ;entry other than hex
  892. EDIT10:    CP    ","        ;ascii entry?
  893.     JR    NZ,EDIT12    ;no, jump
  894.     CALL    POUT
  895. EDIT11:    CALL    CONN        ;get full range ASCII i/p
  896.     AND    7Fh        ;remove top bit
  897.     CP    " "-1        ;cntrl char?
  898.     JR    C,EDIT11    ;yes, do again
  899.     CP    7Fh        ;DEL?
  900.     JR    Z,EDIT11    ;yes, do again
  901.     LD    (HL),A        ;put in buffer
  902.     CALL    POUT        ;print it
  903.     JR    EDIT4        ;print in ASCII representation
  904. ;---------------
  905. EDIT12:    CP    0        ;left cursor: then cursor back
  906.     JR    Z,EDIT13
  907.     CP    BS        ;backspace: then cursor back
  908.     JR    NZ,EDIT16    ;no, continue
  909. ;do backspace
  910. EDIT13:    LD    A,C        ;get position in line
  911.     OR    A        ;first position?
  912.     JR    NZ,EDIT15    ;no then skip
  913. EDIT14:    LD    A,(CURUP)    ;go up a line
  914.     CALL    POUT
  915. EDIT15:    DEC    HL
  916.     JR    EDIT8
  917. ;---------------
  918. EDIT16:    CP    0        ;down cursor
  919.     JR    NZ,EDIT17    ;no, continue
  920.     LD    DE,16
  921.     ADD    HL,DE        ;add one line
  922.     CALL    WEDIT        ;in range?
  923.     EX    DE,HL
  924.     LD    BC,128
  925.     SBC    HL,BC        ;test for end
  926.     EX    DE,HL        ;restore HL
  927.     DEC    HL        ;adjust for space
  928.     JR    C,EDIT6        ;in range, jump
  929.     LD    DE,15        ;put back as it was
  930.     SBC    HL,DE
  931. ;---------------
  932. EDIT17:    CP    0        ;right cursor
  933.     JR    Z,EDIT5
  934.     CP    " "        ;space: then cursor forward
  935.     JR    Z,EDIT5
  936. ;---------------
  937. EDIT18:    CP    0        ;up cursor
  938.     JR    NZ,EDIT19    ;no, continue
  939.     LD    DE,16
  940.     SBC    HL,DE        ;subract one line
  941.     CALL    WEDIT        ;in range?
  942.     INC    HL        ;adjust for backspace
  943.     JR    NC,EDIT14    ;in range, jump
  944.     LD    DE,15        ;put back as it was
  945.     ADD    HL,DE
  946. ;---------------
  947. EDIT19:    CP    CR        ;CR: then finish
  948.     JP    NZ,EDIT1    ;nothing valid, go back
  949.  
  950. ;finish with edit - put cursor back underneath display
  951. EDITF:    CALL    WEDIT
  952.     LD    A,E
  953.     AND    11110000b
  954.     SRL    A
  955.     SRL    A
  956.     SRL    A
  957.     SRL    A
  958.     CPL
  959.     ADD    A,9
  960.     LD    B,A
  961. EDITF1:    CALL    CRLF
  962.     DJNZ    EDITF1
  963.     RET
  964. ;-------------------------------
  965. ; get position in buffer in DE, & position in line in C
  966. WEDIT:    PUSH    HL        ;current buffer addr
  967.     OR    A        ;clear carry
  968.     EX    DE,HL
  969.     LD    HL,(BUF1)    ;get buffer start addr
  970.     EX    DE,HL
  971.     SBC    HL,DE
  972.     EX    DE,HL        ;DE= position in buffer
  973.     PUSH    AF        ;save flags
  974.     LD    A,E
  975.     AND    00001111b
  976.     LD    C,A        ;C= position in line
  977.     POP    AF
  978.     POP    HL
  979.     RET
  980. ;-------------------------------
  981. CURS:    LD    A,(CURRT)
  982. CURS1:    CALL    POUT
  983.     DJNZ    CURS1
  984.     RET
  985. ;-------------------------------
  986. FILL:    CALL    GETHEX        ;get single hex digit in A (no carry if OK)
  987.     JR    C,FILL2        ;not hex, jump 
  988.     RLCA
  989.     RLCA            ;rotate to upper nibble
  990.     RLCA
  991.     RLCA
  992.     LD    B,A        ;save in B
  993. FILL1:    CALL    GETHEX        ;get other lo nibble
  994.     JR    C,FILL1
  995.     ADD    A,B        ;add together
  996.     JR    FILL4
  997.  
  998. ;entry other than hex
  999. FILL2:    CP    ","        ;ascii entry?
  1000.     JR    NZ,FILL     ;no, jump
  1001.     CALL    POUT
  1002. FILL3:    CALL    CONN        ;get full range ASCII i/p
  1003.     AND    7Fh        ;remove top bit
  1004.     CP    " "-1        ;cntrl char?
  1005.     JR    C,FILL3        ;yes, do again
  1006.     CP    7Fh        ;DEL?
  1007.     JR    Z,FILL3        ;yes, do again
  1008.     CALL    POUT        ;print it
  1009.  
  1010. FILL4:    LD    HL,(BUF2)
  1011.     LD    (HL),A
  1012.     LD    D,H
  1013.     LD    E,L
  1014.     INC    DE
  1015.     LD    BC,127
  1016.     LDIR
  1017.     CALL    CRLLF
  1018.     JP    ALT
  1019. ;-------------------------------
  1020.  
  1021. SOD:    PUSH    HL
  1022.     PUSH    BC
  1023.     PUSH    AF
  1024.     CALL    PRINT
  1025.     DC    " SOD "
  1026.     POP    AF
  1027.     POP    BC
  1028.     POP    HL
  1029.     RET
  1030.  
  1031.  
  1032. ;Copy from CDRIVE, CTRACK, CSECT until UTRACK, USECT
  1033. ;    to DDRIVE, DTRACK, DSECT
  1034. COPY:    LD    HL,(BUF1)    ;save buffer pointer
  1035.     LD    (BUF3),HL
  1036.     CALL    CHECK        ;display options
  1037.     LD    DE,SPARAM    ;save Cparam
  1038.     CALL    COPYF1
  1039.     LD    HL,COPYE
  1040.     LD    (ABORT+1),HL    ;direct ESC & ^C routine to COPYE
  1041.     LD    A,(MENU7+1)    ;examine repeat function indicator
  1042.     OR    A
  1043.     JR    Z,COPY1A    ;jump if none
  1044.     LD    HL,UPARAM    ;copy Uparam to Cparam
  1045.     CALL    COPYE1        ;do it
  1046.     CALL    KBLK        ;now that CHECK is done- translate block
  1047.     CALL    DECSEC        ;adjust to show last physical sector
  1048.     OR    A        ;clear carry
  1049.     LD    HL,(CSECT)    ;get upper sector limit
  1050.     LD    (COPY9+1),HL
  1051.     LD    DE,(SSECT)    ;get current sector
  1052.     SBC    HL,DE        ;+ve?
  1053.     LD    BC,(MAXSEC+1)
  1054.     LD    (COPY16+1),BC    ;save max no. sectors per track
  1055.     LD    DE,(CTRACK)    ;load upper track limit
  1056.     LD    (COPY8+1),DE
  1057.     JR    NC,COPY1    ;jump if +ve
  1058.     ADD    HL,BC        ;add maxsec sectors
  1059.     DEC    DE        ;minus 1 track
  1060. COPY1:    LD    (COPY13+1),HL    ;save sector difference
  1061.     PUSH    HL
  1062.     POP    BC        ;save also in BC
  1063.     OR    A        ;clear carry
  1064.     LD    HL,(STRACK)    ;get current track
  1065.     EX    DE,HL
  1066.     SBC    HL,DE        ;legal?
  1067.     LD    (COPY14+1),HL    ;save track difference
  1068.     JR    C,COPY2        ;no, skip "until" section
  1069.     ADC    HL,BC        ;Trk+Sec=0?
  1070.     JR    NZ,COPY2    ;no, do it
  1071. COPY1A:    SCF
  1072. COPY2:    PUSH    AF
  1073.     JR    C,COPY4        ;skip if carry set
  1074.     CALL    CPRINT
  1075. COPY3:    DC    "  last"
  1076.     CALL    CHECK
  1077. COPY4:    CALL    CRLLF
  1078.     LD    C,4        ;4 spaces
  1079.     CALL    SPINC
  1080.     LD    HL,TOMSG    ;"to" msg
  1081.     CALL    SMSG
  1082.     LD    HL,DPARAM    ;copy Dparam to Cparam
  1083.     CALL    COPYE1
  1084.     CALL    CHECK
  1085.     POP    AF        ;get those flags again
  1086.     JP    C,COPY17    ;skip next bit
  1087.     LD    A,(SDRIVE)    ;get current drive
  1088.     LD    HL,UDRIVE    ;get dest drive
  1089.     CP    (HL)        ;same drive?
  1090.     JP    NZ,COPY12    ;no, go straight to routine
  1091.  
  1092. ;check that there is enough buffer to absorb the entire read
  1093.     OR    A
  1094.     LD    HL,(WBOOT+1)
  1095.     LD    L,0
  1096.     LD    DE,BUFF2
  1097.     SBC    HL,DE        ;HL= available buffer space
  1098.     LD    BC,128
  1099.     LD    DE,-1        ;allow for buffer
  1100. COPY5:    SBC    HL,BC
  1101.     INC    DE        ;sector count
  1102.     JR    NC,COPY5
  1103.     LD    HL,(COPY13+1)    ;sector difference
  1104.     EX    DE,HL        ;HL= buffer space in sectors
  1105.     LD    (COPY10+1),HL
  1106.     OR    A    
  1107.     SBC    HL,DE        ;+ve? (buffer space - difference
  1108.     JR    C,COPY7        ;no, don't bother checking track
  1109.     LD    DE,(COPY16+1)    ;sectors per track
  1110.     LD    BC,(COPY14+1)    ;track difference
  1111. COPY6:    LD    A,B
  1112.     OR    C        ;track difference exhausted?
  1113.     JR    Z,COPY12    ;yes, buffer > difference, Ok to continue
  1114.     DEC    BC
  1115.     SBC    HL,DE
  1116.     JR    NC,COPY6    ;loop if more to go
  1117.  
  1118. ;buffer is insufficient, check whether dest is outside source area
  1119. COPY7:    LD    DE,(STRACK)
  1120.     LD    HL,(SSECT)
  1121.     CALL    COMP        ;compare
  1122.     JR    NC,COPY12    ;dest < source, continue
  1123. COPY8:    LD    DE,0        ;Utrack stored here
  1124. COPY9:    LD    HL,0        ;Usect stored here
  1125.     CALL    COMP
  1126.     JR    C,COPY12    ;dest > source upper limit, continue
  1127.     CALL    CRLF
  1128.     CALL    CPRINT
  1129.     DC    "*** Source sector(s) would be overwritten (buffer holds"
  1130. COPY10:    LD    HL,0        ;buffer length stored here
  1131.     CALL    B2DEC
  1132.     CALL    PRINT
  1133.     DC    " Sectors)"
  1134. COPY11:    CALL    COPYE
  1135.     JP    MENU
  1136. ;---------------
  1137. COPY12:    LD    HL,COPY3    ;"last" msg again
  1138.     CALL    CPMSG
  1139.     LD    HL,CPARAM
  1140.     CALL    COPYE1
  1141. COPY13:    LD    DE,0        ;sector difference stored here
  1142. COPY14:    LD    BC,0        ;track difference stored here
  1143. COPY15:    CALL    ADDSEC        ;add DE sectors & adjust
  1144. COPY16:    LD    DE,0        ;previous maxsec value
  1145.     LD    A,B
  1146.     OR    C
  1147.     DEC    BC        ;lose a track
  1148.     JR    NZ,COPY15    
  1149.     CALL    CHECK
  1150.  
  1151. COPY17:    LD    HL,SPARAM    ;put back current parameters
  1152.     CALL    COPYE1
  1153.     CALL    CRLF
  1154.     CALL    CONIN        ;scan for ESC & ^C
  1155.     CP    "N"
  1156.     JR    Z,COPY11
  1157.     LD    A,(CURUP)
  1158.     LD    (MENU9+1),A    ;do automatic CURUP in SCAN
  1159.     LD    HL,COPYRD    ;ensure that COPYW routine jumps..
  1160.     LD    (COPYW2+1),HL    ;..back to COPYRD
  1161.     LD    HL,CPYWX    ;addr COPY end
  1162.     EX    (SP),HL        ;exchange ret addr & COPYE
  1163.     PUSH    HL        ;restore ret addr
  1164.  
  1165. ;Read section - adjust MENU to show Read command & jump to COPYR
  1166. COPYRD:    LD    HL,BUFF2    ;put new pointer in
  1167.     LD    (BUF1),HL
  1168.     LD    HL,READM    ;put Read msg in MENU routine
  1169.     LD    (MENU5+1),HL
  1170.     LD    HL,COPYR
  1171.     LD    (MENU6+1),HL    ;direct menu to jump to COPYR
  1172.     CALL    HOME        ;for safety
  1173.     CALL    CRLF
  1174.     POP    HL        ;lose return
  1175.     JP    MENU5
  1176. ;---------------
  1177. COPYR:    CALL    CHECK1        ;get & display disk parameters
  1178.     LD    HL,(CSECT)
  1179.     CALL    READF        ;high speed read
  1180. ;check buffer overflow
  1181.     OR    A        ;clear carry
  1182.     LD    HL,(BUF1)    ;get current DMA addr
  1183.     LD    BC,128        ;buffer length
  1184.     ADD    HL,BC        ;add
  1185.     LD    (BUF1),HL    ;save next buffer start addr
  1186.     LD    (COPYW1+1),HL    ;save hi ram
  1187.     EX    DE,HL        ;DE = next addr
  1188.     LD    HL,(WBOOT+1)    ;get RAMTOP
  1189.     LD    L,0        ;..to the nearest Kbytes
  1190.     SBC    HL,BC        ;new RAM limit
  1191.     SBC    HL,DE        ;subtract ram used so far
  1192.     RET    NC        ;get some more if ram available
  1193.  
  1194. ;Write section - adjust MENU to show Write command & jump to COPYW
  1195. COPYWR:    CALL    CRLF
  1196.     LD    HL,WRITEM    ;put Write msg in MENU routine
  1197.     LD    (MENU5+1),HL
  1198.     LD    HL,COPYW
  1199.     LD    (MENU6+1),HL    ;direct menu to jump to COPYW
  1200.     LD    HL,BUFF2    ;start again at ram base
  1201.     LD    (BUF1),HL
  1202.     CALL    HOME        ;for safety
  1203.     CALL    CPYWY        ;copy dest params into current params slot
  1204.     POP    HL        ;lose return
  1205.     JP    MENU5
  1206. ;---------------
  1207. COPYW:    CALL    CHECK1
  1208.     LD    HL,(CSECT)
  1209.     CALL    WRITEF
  1210. ;check buffer overflow
  1211.     OR    A        ;clear carry
  1212.     LD    HL,(BUF1)    ;get current DMA addr
  1213.     LD    BC,128        ;buffer length
  1214.     ADD    HL,BC        ;add
  1215.     LD    (BUF1),HL    ;save
  1216.     ADD    HL,BC
  1217.     EX    DE,HL        ;DE = next addr
  1218. COPYW1:    LD    HL,0        ;hi ram saved here
  1219.     SBC    HL,DE        ;subtract ram used so far
  1220.     RET    NC        ;not exhausted, get some more
  1221.     CALL    SDESTE        ;copy back Cparams
  1222. COPYW2:    JP    COPYRD        ;do another read
  1223. ;---------------
  1224. CPYWX:    LD    HL,CPYWGG    ;point to CPYWGG
  1225.     LD    (COPYW2+1),HL    ;make COPYW routine jump there when finished
  1226.     CALL    COPYWR        ;this is a sort of call!
  1227.  
  1228. CPYWGG:    CALL    COPYFD        ;save Cparam into Pparam
  1229. COPYE0:    LD    HL,(BUF3)
  1230.     LD    (BUF1),HL
  1231.     EX    DE,HL
  1232.     LD    HL,(COPYW1+1)
  1233.     LD    BC,128
  1234.     OR    A
  1235.     SBC    HL,BC
  1236.     LDIR            ;read into current buffer
  1237.     JP    CRLF
  1238. ;---------------
  1239. COPYE:    CALL    COPYE0
  1240.     LD    HL,SPARAM    ;put back current parameters
  1241. COPYE1:    LD    DE,CPARAM
  1242.     JP    COPYF2
  1243. ;---------------
  1244. CPYWY:    LD    DE,SPARAM    ;put dest values into current
  1245.     LD    HL,CPARAM
  1246.     LD    BC,4*PRMLEN
  1247.     LDIR
  1248.     RET
  1249. ;---------------
  1250. BUF3:    DW    0
  1251. ;****************************************
  1252. ; check validity of track, sector
  1253. CHK:    LD    BC,(BUF1)
  1254.     CALL    SETDMA        ;call    SETDMA
  1255.     LD    HL,DRVM
  1256.     CALL    SMSG
  1257.     LD    A,(CDRIVE)    ;get current drive
  1258.     LD    C,A        ;save for SELDSK
  1259.     ADD    A,"A"
  1260.     CALL    POUT
  1261.     CALL    PRINT
  1262.     DC    " "
  1263. CHK1:
  1264. SELDSK:    CALL    0        ;call SELDSK in BIOS
  1265.     LD    A,H        ;HL= addr Disk Parameter Header
  1266.     OR    L        ;..if drive exists
  1267.     JP    Z,CHKERR    ;jump if drive doesn't exist
  1268.     CALL    GETADR
  1269.     LD    (CXLT+1),HL    ;save addr of translation table
  1270.     EX    DE,HL
  1271.     LD    DE,6
  1272.     ADD    HL,DE        ;HL= pointer to addr of DIRBUF
  1273.     CALL    GETADR
  1274.     LD    (DIRBUF),HL    ;save
  1275.     EX    DE,HL
  1276.     CALL    GETADR        ;get addr of disc parameter block
  1277.     CALL    GETADR        ;get SPT
  1278.     LD    (MAXSEC+1),HL    ;HL= max no of sectors per track
  1279.     EX    DE,HL
  1280.     INC    HL
  1281.     LD    A,(HL)        ;BLM (blocksize*128
  1282.     LD    (BLKSIZ),A    ;Blocksize = BLKSIZ * 128
  1283.     LD    B,A
  1284.     INC    HL
  1285.     INC    HL
  1286.     CALL    GETADR        ;HL= value of DSM
  1287.     PUSH    DE        ;save next addr
  1288.     LD    D,H
  1289.     LD    E,L        ;DE=HL= DSM (data storage max in blocks)
  1290. CHK2:    ADD    HL,DE        ;multiply DSM by BLKSIZ
  1291.     DJNZ    CHK2
  1292.     LD    BC,0
  1293. MAXSEC:    LD    DE,0        ;max no of 128 byte sectors per track
  1294.     INC    BC
  1295.     SBC    HL,DE        ;devide DSM*BLKSIZ by MAXSEC
  1296.     JR    NC,MAXSEC
  1297.     POP    HL        ;get next addr
  1298.     LD    DE,6
  1299.     ADD    HL,DE        ;HL= addr OFF (no of sys tracks)
  1300.     CALL    GETADR
  1301.     LD    (SYSTRK),HL    ;save no of system tracks
  1302.     ADD    HL,BC        ;HL= max no of tracks
  1303.     LD    (MAXTRK),HL    ;save
  1304.     RET
  1305. ;-------------------------------
  1306. HOME:    JP    0        ;addr HOME stored here
  1307. ;-------------------------------
  1308. CHECK:    CALL    HOME
  1309. CHECK1:    CALL    CHK
  1310.     CALL    KBLK
  1311.     LD    HL,TRKM
  1312.     CALL    SMSG
  1313.     LD    HL,(CTRACK)    ;current track
  1314.     PUSH    HL        ;save
  1315.     CALL    B2DEC        ;print decimal
  1316.     LD    DE,(MAXTRK)
  1317.     OR    A        ;clear carry
  1318.     SBC    HL,DE        ;in range?
  1319.     POP    BC        ;current track
  1320.     JP    NC,CHKERR    ;no, jump
  1321. SETTRK:    CALL    0        ;call SETTRK
  1322.     CALL    PRINT
  1323.     DC    " "        ;2 spaces
  1324.     LD    HL,SECM
  1325.     CALL    SMSG
  1326.     LD    HL,(CSECT)    ;current sector
  1327.     CALL    B2DEC        ;print decimal
  1328.     CALL    CHKSEC        ;check sector in range
  1329.     JP    NC,CHKERR
  1330.     CALL    PRINT
  1331.     DC    " "        ;2 spaces
  1332.     LD    HL,BLKM
  1333.     CALL    SMSG
  1334.     LD    HL,(SYSTRK)
  1335.     EX    DE,HL
  1336.     LD    HL,(CTRACK)
  1337.     OR    A        ;clear carry
  1338.     SBC    HL,DE
  1339.     LD    (CPMTRK+1),HL    ;no. of CP/M tracks
  1340.     LD    DE,0        ;zero sector count
  1341.     LD    BC,0        ;zero block count
  1342.     JR    NC,CPMTRK
  1343.     CALL    PRINT
  1344.     DC    "-system"
  1345.     JR    COPYFD
  1346. CPMTRK:    LD    HL,0        ;current count of tracks to go
  1347.     LD    A,H
  1348.     OR    L
  1349.     JR    Z,CHECK4    ;jump if no more
  1350.     DEC    HL
  1351.     LD    (CPMTRK+1),HL
  1352.     LD    HL,(MAXSEC+1)
  1353.     DEC    HL
  1354.     ADD    HL,DE
  1355.     EX    DE,HL        ;DE= cumulative sector count
  1356.     LD    HL,(BLKSIZ)
  1357.     INC    HL
  1358.     EX    DE,HL        ;divide no. sectors this track
  1359. CHECK3:    SBC    HL,DE        ;by no. sectors per block
  1360.     INC    BC        ;increment block count
  1361.     JR    NC,CHECK3
  1362.     DEC    BC
  1363.     ADC    HL,DE        ;put straight again
  1364.     EX    DE,HL
  1365.     JR    CPMTRK
  1366. CHECK4:    LD    HL,(CSECT)
  1367.     ADD    HL,DE
  1368.     EX    DE,HL
  1369.     LD    HL,(BLKSIZ)
  1370.     INC    HL
  1371.     EX    DE,HL
  1372. CHECK5:    SBC    HL,DE
  1373.     INC    BC
  1374.     JR    NC,CHECK5
  1375.     ADC    HL,DE
  1376.     PUSH    HL
  1377.     DEC    BC
  1378.     LD    H,B
  1379.     LD    L,C
  1380.     LD    (CBLOCK),HL
  1381.     CALL    B4HEX
  1382.     LD    A,"h"
  1383.     CALL    POUT
  1384.     LD    A,":"
  1385.     CALL    POUT
  1386.     POP    HL
  1387.     DEC    HL
  1388.     LD    (CBLCKE),HL    ;save extension
  1389.     CALL    B2DEC
  1390.  
  1391. ; all done, copy CDRIVE, CBLOCK, CTRACK & CSECT to previous buffer
  1392. COPYFD:    LD    DE,PPARAM
  1393. COPYF1:    LD    HL,CPARAM
  1394. COPYF2:    LD    BC,PRMLEN
  1395.     LDIR
  1396.     RET
  1397.  
  1398. ; all wrong, copy previuos buffer back to CDRIVE, CBLOCK, CTRACK &
  1399. CSECT 
  1400. CHKERR:    CALL    PRINT
  1401.     DC    " does not exist"
  1402.     CALL    COPYBK
  1403.     JP    MENU
  1404.  
  1405. COPYBK:    LD    HL,PPARAM
  1406.     LD    DE,CPARAM
  1407.     JR    COPYF2
  1408. ;-------------------------------
  1409. CHKSEC:    LD    HL,(MAXSEC+1)
  1410.     EX    DE,HL        ;DE= MAXSEC
  1411.     LD    HL,(CSECT)    ;current sector
  1412.     OR    A        ;clear carry
  1413.     SBC    HL,DE        ;in range?
  1414.     RET            ;Ok if carry set
  1415. ;-------------------------------
  1416. ;add no. of sectors in DE then adjust sector count
  1417. ADDSEC:    LD    HL,(CSECT)    ;get current destination
  1418.     ADD    HL,DE        ;new sector total
  1419.     LD    (CSECT),HL    ;save
  1420.     CALL    CHKSEC        ;subtract maxsec & test in range
  1421.     RET    C        ;ret if in range
  1422.     LD    (CSECT),HL    ;save new sector count..
  1423.     LD    HL,(CTRACK)
  1424.     INC    HL        ;inc track count
  1425.     LD    (CTRACK),HL
  1426.     LD    DE,0        ;nil sectors
  1427.     JR    ADDSEC        ;loop round till all sectors done
  1428. ;-------------------------------
  1429. UCOMP:    LD    HL,(USECT)    ;upper sector limit
  1430.     LD    DE,(UTRACK)    ;upper track limit
  1431. ;Compare DE with CTRACK & HL with CSECT
  1432. ;return with carry if less, zero if same
  1433. COMP:    PUSH    HL        ;save sector
  1434.     OR    A        ;clear carry
  1435.     LD    HL,(CTRACK)    ;current track
  1436.     EX    DE,HL
  1437.     SBC    HL,DE        ;in range?
  1438.     POP    DE        ;restore sector
  1439.     RET    NZ        ;not same track, ret
  1440.     LD    HL,(CSECT)
  1441.     EX    DE,HL
  1442.     SBC    HL,DE        ;in range?
  1443.     RET
  1444. ;-------------------------------
  1445. SETDMA:    JP    0        ;call setdma
  1446. ;-------------------------------
  1447. ; get physical sector from BIOS and transform
  1448. CXLT0:    LD    B,H
  1449.     LD    C,L
  1450. CXLT:    LD    DE,0        ;addr of sector translation table
  1451.     LD    A,D
  1452.     OR    E
  1453.     JR    Z,SETSEC
  1454. SCTRAN:    CALL    0        ;call SECTRAN
  1455.     LD    B,H
  1456.     LD    C,L
  1457. SETSEC:    JP    0        ;call SETSEC (set sector)
  1458. ;-------------------------------
  1459. GETADR:    LD    E,(HL)        ;get contents of (HL) into HL
  1460.     INC    HL
  1461.     LD    D,(HL)
  1462.     INC    HL
  1463.     EX    DE,HL
  1464.     RET            ;DE points to next address
  1465. ;-------------------------------
  1466. TEST:    CALL    CPRINT
  1467.     DC    " Drv   Trk    Sec    Mkr    Blk    ext     PSTCUD"
  1468.     LD    B,6
  1469.     LD    HL,PPARAM
  1470.  
  1471. TEST2:    PUSH    BC
  1472.     CALL    CRLF
  1473.     LD    A,B
  1474.     ADD    A,"0"
  1475.     CALL    POUT
  1476.     LD    A,(HL)
  1477.     ADD    A,"A"
  1478.     CALL    POUT
  1479.     CALL    TEST0
  1480.     CALL    TEST1
  1481.     CALL    TEST1
  1482.     LD    A,(HL)
  1483.     CALL    B2HEX
  1484.     CALL    TEST0
  1485.     CALL    TEST1
  1486.     CALL    TEST1
  1487.     POP    BC
  1488.     DJNZ    TEST2
  1489.     RET
  1490.  
  1491. TEST1:    CALL    GETADR
  1492.     CALL    B2DEC
  1493.     EX    DE,HL
  1494.     JR    TEST3
  1495.  
  1496. TEST0:    INC    HL
  1497. TEST3:    PUSH    HL
  1498.     CALL    PRINT
  1499.     DC    "    "
  1500.     POP    HL
  1501.     RET
  1502. ;-------------------------------
  1503. ; multiply previous contents of HL by 10 then
  1504. ; get a decimal number value from GETN & add into HL
  1505. GETDEC:    LD    B,4
  1506.     PUSH    HL
  1507.     LD    HL,0
  1508. GDEC1:    CALL    GETN
  1509.     JR    C,GDEC2
  1510.     ADD    HL,HL        ;*2
  1511.     PUSH    HL
  1512.     ADD    HL,HL        ;*4
  1513.     ADD    HL,HL        ;*8
  1514.     POP    DE
  1515.     ADD    HL,DE        ;*10
  1516.     LD    D,0
  1517.     LD    E,A
  1518.     ADD    HL,DE        ;HL= previous *10 + present
  1519.     DJNZ    GDEC1
  1520. GDEC2:    POP    DE
  1521.     LD    A,4        ;check value stored here
  1522.     CP    B
  1523.     RET    NZ        ;new value returned in HL
  1524.     EX    DE,HL        ;put old value back
  1525.     CALL    B2DEC        ;print it
  1526. GDEZ:    SCF
  1527.     RET
  1528. ;-------------------------------
  1529. GETN:    CALL    CONIN
  1530. GETN1:    CP    "0"
  1531.     RET    C
  1532.     CP    "9"+1
  1533.     JR    NC,GDEZ
  1534.     CALL    POUT
  1535.     SUB    "0"
  1536.     RET
  1537. ;-------------------------------
  1538. GETHEX: CALL    CONIN
  1539.     CP    "F"+1
  1540.     JR    NC,GDEZ
  1541.     CP    "A"
  1542.     JR    C,GETN1
  1543.     CALL    POUT
  1544.     SUB    "A"-10
  1545.     RET
  1546. ;-------------------------------
  1547. CONN:    EXX
  1548. CONNIN:    CALL    0        ;console input address stored here
  1549.     EXX
  1550.     CP    1EH        ;^C
  1551.     JP    Z,ABORT0
  1552.     CP    ESC
  1553.     RET    NZ
  1554. ABORT0:    PUSH    AF        ;save flags
  1555. ABORT:    CALL    MENU        ;local abort routine addr stored here
  1556.     POP    AF
  1557.     CP    ESC
  1558.     JP    Z,MENU
  1559.     JP    WBOOT
  1560. ;-------------------------------
  1561. CONIN:    CALL    CONN
  1562.     CP    "@"
  1563.     JR    C,CON1        ;skip if number
  1564.     AND    5Fh        ;make upper case
  1565. CON1:    LD    (SCMD0+1),A    ;put in SCMD routine
  1566.     RET
  1567. ;-----------------------
  1568. ;dummy message routine
  1569. DMSG:    PUSH    AF
  1570. DMSG1:    LD    A,(HL)    ;go though string until bit 7 found
  1571.     INC    HL    ;inc address
  1572.     OR    A
  1573.     JP    P,DMSG1    ;loop if bit 7 unset
  1574.     POP    AF
  1575.     RET
  1576. ;-----------------------
  1577. ;print message until a space is found
  1578. SMSG:    PUSH    AF
  1579. SMSG1:    CALL    POUTI
  1580.     CP    " "
  1581.     JR    NZ,SMSG1
  1582.     POP    AF
  1583.     RET
  1584. ;-----------------------
  1585. CPRINT:    CALL    CRLF    ;print CRLF followed by string
  1586. PRINT:    EX    (SP),HL    ;point to message
  1587.     CALL    PMSG
  1588.     EX    (SP),HL    ;restore return addr
  1589.     RET
  1590. ;-----------------------
  1591. PASC:    AND    7Fh    ;print only ASCII chars
  1592.     CP    " "
  1593.     JR    NC,PASC1
  1594. PASC2:    LD    A,"."
  1595. PASC1:    CP    7Fh
  1596.     JR    Z,PASC2
  1597.     JR    POUT
  1598. ;-----------------------
  1599. CRLLF:    CALL    CRLF
  1600. CRLF:    LD    A,CR    ;print CRLF
  1601.     CALL    POUT
  1602.     LD    A,LF
  1603.     JR    POUT
  1604. ;-----------------------
  1605. CPMSG:    CALL    CRLF
  1606. PMSG:    PUSH    AF
  1607. PMSG1:    CALL    POUTI    ;print char
  1608.     OR    A
  1609.     JP    P,PMSG1    ;loop if bit 7 unset
  1610.     LD    A," "    ;print space
  1611.     JR    POUT1
  1612. ;-----------------------
  1613.  
  1614. POUTI:    LD    A,(HL)    ;get char
  1615.     INC    HL
  1616. POUT:    PUSH    AF
  1617. POUT1:    EXX        ;output char in A
  1618.     AND    7Fh    ;reduce to normal ASCII chars
  1619.     LD    C,A    ;char to C
  1620.     PUSH    BC
  1621. CONOUT:    CALL    0    ;address stored here
  1622.     POP    BC
  1623. LISTSW:    LD    A,1    ;print/not print switch byte 
  1624.     OR    A
  1625. LISTP:    CALL    Z,0    ;LIST address stored here
  1626.     POP    AF
  1627.     EXX
  1628.     RET
  1629. ;-----------------------
  1630. B4HEX:    LD    A,H    ;convert HL to hex
  1631.     CALL    B2HEX
  1632.     LD    A,L
  1633. B2HEX:    PUSH    AF    ;save
  1634.     RRCA        ;rotate hi nibble to low
  1635.     RRCA
  1636.     RRCA
  1637.     RRCA
  1638.     CALL    B1HEX
  1639.     POP    AF
  1640. B1HEX:    PUSH    AF
  1641.     AND    0Fh    ;low nibble only
  1642.     ADD    A,90h    ;convert
  1643.     DAA
  1644.     ADC    A,40h
  1645.     DAA
  1646.     JR    POUT1    ;print it
  1647. ;-----------------------
  1648. ; HL= binary value, print decimal ignoring leading zeros
  1649. B2DEC:    XOR    A
  1650. B2DEC1:    LD    (BDEC4+1),A    ;replace leading zero's
  1651. B2DEC2:    LD    A,0Fh
  1652.     LD    (BDEC1+1),A    ;enable leading zero detection
  1653.     PUSH    HL
  1654.     LD    DE,1000        ;divide by 1000
  1655.     XOR    A
  1656.     CALL    BDEC        ;do it & print 2 most sig chars
  1657.     LD    DE,10        ;divide by 10
  1658.     XOR    A
  1659.     CALL    BDEC        ;do it & print next 2 chars
  1660.     LD    A,L    
  1661.     POP    HL
  1662.     JR    B1HEX        ;print remainder
  1663.  
  1664. BDEC0:    INC    A        ;inc counter
  1665.     DAA            ;adjust to decimal
  1666. BDEC:    SBC    HL,DE        ;entry point to circular subtract loop
  1667.     JR    NC,BDEC0    
  1668.     ADD    HL,DE        ;undo last subtraction
  1669. BDEC1:    CP    0Fh        ;most sig non-zero bit exist? (this changes)
  1670.     CALL    NC,B2HEX    ;yes, print both digits
  1671.     JR    NC,BDEC2    ;yes, kill further leading zero replacement
  1672.     CALL    BDEC3        ;no, replace leading zero
  1673.     OR    A        ;lower digit zero?
  1674.     JR    Z,BDEC3        ;yes, jump & replace
  1675.     CALL    B1HEX        ;print lower digit
  1676. BDEC2:    XOR    A
  1677.     LD    (BDEC1+1),A    ;kill further zero replacement
  1678.     RET
  1679.  
  1680. BDEC3:    PUSH    AF
  1681. BDEC4:    LD    A," "        ;replace leading zero by char stored here
  1682.     CALL    POUT
  1683.     POP    AF
  1684.     RET
  1685. ;-----------------------
  1686. CSPINC:    CALL    CRLF
  1687. SPINC:    PUSH    AF        ;print no. of spaces defined by C
  1688.     PUSH    BC
  1689.     LD    B,C
  1690.     LD    A," "
  1691. SPINC1:    CALL    POUT
  1692.     DJNZ    SPINC1
  1693.     POP    BC
  1694.     POP    AF
  1695.     RET
  1696. ;-----------------------
  1697. $END    EQU    $
  1698. STACK    EQU    $END+78h    ;stack space
  1699. BUFF1    EQU    STACK        ;alternative buffer space
  1700. BUFF2    EQU    BUFF1+128    ;start memory buffer
  1701.  
  1702.     END
  1703.  
  1704. ;///////////////////////////////////////////////////////////////////////////
  1705.  
  1706. ;-----------------------------
  1707.     LD    HL,LISTM
  1708.     CALL    PRN
  1709.     LD    HL,DIRM
  1710.     CALL    PRINTY
  1711.     LD    HL,(SYSTRK)
  1712.     INC    HL
  1713.     LD    (CTRACK),HL
  1714.     RET
  1715.  
  1716. DIRM:    DB    " Directory",CR,LF
  1717.     DB    "Entry User     File    Ext Size    Disc Space Allocation"
  1718.     DB    CR,LF,0
  1719. DIREM:    DB    "*********** End of Directory ********",CR,LF,0
  1720. DAMM:    DB    CR,LF,LF,"           Disc Allocation Map",CR,LF,LF,"    ",0
  1721.