home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / enterprs / cpm / utils / f / format.lzh / format.asm
Encoding:
Assembly Source File  |  1993-05-29  |  42.7 KB  |  2,369 lines

  1.     title    'C128 Format Program  08 June 1987'
  2.  
  3. ; modified  08June87  by V.Ertwine & F.Bowen:    add 1581 support
  4. ; modified  07May86   by V.Ertwine:        add more MFM formats
  5. ; original  15May85   by V.Ertwine:        original release
  6.  
  7.         maclib    z80
  8.     maclib    cxequ
  9.     maclib    x6502
  10.  
  11. format$1581    equ    true
  12.  
  13. $*MACRO
  14.  
  15. boot$code$02    equ    00B00h
  16. boot$code$80    equ    0E000h
  17.  
  18. ;
  19. ;    RAM loader equates
  20. ;
  21. rownum    macro    row,col
  22.     db    row+80h,col
  23.     endm
  24.  
  25. sys$name    equ    000EDh        ;
  26. cmp$hl$de    equ    000FAh        ;
  27. read$sector    equ    0044Fh        ;
  28. ext$error    equ    00480h        ;
  29. tell$user    equ    004FFh        ;
  30. table$error    equ    0051Bh        ;
  31. prt$msg$both    equ     00526h        ;
  32. prt$HL$both    equ    00534h        ;
  33. install$ASCII    equ    005BDh        ;
  34. wait        equ    00945h        ;
  35.  
  36. ;BIOS$65$code    equ    00D22h        ;
  37. ;BIOS$size    equ    001C3h        ;
  38. ;F$rd$count    equ    031BDh        ;
  39.  
  40. swap$code    equ    00EE5h        ;
  41. swap$size    equ    0001Fh        ;
  42.  
  43. MMU$init$data    equ    00FAAh        ;
  44.  
  45.     page
  46. ;"""""""""""""
  47. ;E Q U A T E S
  48. ;"""""""""""""
  49.  
  50. cret:        equ    01    ; matrix position of return key
  51. disk$ready$key:    equ    11    ; matrix position of $
  52. ctrlc:        equ    20    ; matrix position of c key
  53. yes$key:    equ    25    ; yes - matrix position of 'y' key
  54. no$key:        equ    39    ; 'no' - matrix position of n key
  55. cursor$up$key:    equ    53h    ; matrix position of up arrow
  56. cursor$dn$key:    equ    54h    ; matrix position of down arrow
  57.  
  58. top$line:    equ    0    ; screen top row for signon message
  59. use$line:    equ    2    ; screen row for "using source" message
  60. keynam$line:    equ    4    ; screen row for showing keyname
  61. lots$line:    equ    6    ; screen row for showing big messages
  62. prompt$line:    equ    10    ; screen row for showing menus
  63. spec$line:    equ    23    ; status line row for special messages
  64.  
  65. crlf:        equ    0ffh    ; code to do cr,lf    
  66. do$6502$fun:    equ    4
  67. scrsz40:    equ    20h    ; flag value that this is a 40 column screen
  68. scrsz80:    equ    40h    ; flag value that this is an 80 column screen 
  69. both:        equ    scrsz40+scrsz80        ; both of the above
  70. user$offset:    equ    3*(30-1)
  71.  
  72.     page
  73. ;"""""""""""""""""""
  74. ;CP/M function calls
  75. ;"""""""""""""""""""
  76. bdos:        equ    05    ;bdos call entry point
  77. conin:        equ    01    ;char returned in a
  78. conout:        equ    02    ;char sent in e
  79. constat:    equ    11    ;console status    
  80. cur$dsk:    equ    25    ;get current disk to A
  81. getscb:        equ    49    ;get system control block
  82.  
  83. ;"""""""""""""""""""""""""
  84. ;     1581 Drive equates
  85. ;"""""""""""""""""""""""""
  86. ;    constants
  87. buf$alc        equ    081h    ; allocate buffer 0 (no buf 7)
  88.  
  89. ;    memory location
  90. jobs        equ    002h    ; list of jobs to be done
  91. hdrs        equ    00Bh    ; header info (track and sector)
  92. buf$use        equ    06Dh    ; bit X set allocates buffer X
  93. next$job    equ    083h    ; pointer to next job to be done
  94. hdrjob        equ    099h
  95. vtrans$ts    equ    1B8h    ; sector x-lat vector
  96. drv$buf        equ    300h    ; buffer 0 start adr
  97. ;boot$ret    equ    0d35Ah    ; will change with next ROM
  98. boot$ret    equ    0FF5Ah    ; return from drive boot code
  99.  
  100.     page
  101. ;
  102. pointer    equ    20h        ; DMA pointer used by 8502
  103. cmdchn    equ    15        ; use comand channel #15
  104. ;
  105. ;    KERNAL EQUATES
  106. ;
  107. serial        equ    00A1Ch
  108. D2PRA        equ    0DD00h
  109. D1SDR        equ    0DC0Ch
  110. D1ICR        equ    0DC0Dh
  111. clk$bit        equ    10h
  112.  
  113. K$set$bnk    equ    0FF68h    ;
  114. K$setlfs    equ    0FFBAh    ; setup a logical file
  115. K$setnam    equ    0FFBDh    ; set up file name for OPEN
  116. K$open        equ    0FFC0h    ; open a logical file (after SETLFS & SETNAM)
  117. K$chkout    equ    0FFC9h    ; open a channel for output
  118. K$clrchn    equ    0FFCCh    ; clears ALL I/O channel 
  119. K$chkin        equ    0FFC6h    ; open a channel for input
  120. K$chrin        equ    0FFCFh    ; get a character from input channel
  121. K$chrout    equ    0FFD2h    ; output a character to output channel
  122. K$clall        equ    0FFE7h    ; close all open files
  123. K$close        equ    0FFC3h    ; close a logical file
  124. K$readst    equ    0FFB7h    ; read status byte
  125.  
  126.     page
  127. ;""""""""""""""""""""""""""""""""""
  128. ;m a c r o    d e f i n i t i o n s
  129. ;""""""""""""""""""""""""""""""""""
  130. define    macro    label,for
  131.     org    ramalc
  132. label    equ    $
  133. ramalc    set    ramalc+for
  134.     endm
  135.  
  136. save$top$bottom    macro    toprow,number
  137.     mvi    a,toprow+number-1
  138.     sta    bottom$choice
  139.     mvi    a,toprow
  140.     sta    top$choice
  141.     endm
  142.  
  143. skip$and$destroy$hl    macro
  144.     db    21h
  145.     endm
  146.  
  147. zero?    macro    r1,r2
  148.     mov    a,r1
  149.     ora    r2
  150.     endm
  151.  
  152. fmt    macro    fmtdef1,fmtdef2
  153.     DW    fmtdef1
  154.     IF    NOT NUL fmtdef2
  155.     DW    fmtdef2
  156.     ELSE
  157.     DW    0
  158.     ENDIF
  159.     ENDM
  160.  
  161. wrdef    macro    ?trk,?sect,?pointer
  162.     db    ?trk,?sect
  163.     dw    ?pointer
  164.     endm
  165.  
  166. defstart    macro    fillbyte
  167.     IF    NOT NUL fillbyte
  168.     db    fillbyte
  169.     ELSE
  170.     db    0
  171.     ENDIF
  172.     ENDM
  173.  
  174. defbuf    macro    ?count,?offset,?pointer
  175.     dw    ?count
  176.     dw    ?offset
  177.     dw    ?pointer
  178.     endm
  179.  
  180. definline    macro    ?count,?offset
  181.     db    ?count,-1
  182.     dw    ?offset
  183.     endm
  184.  
  185. defexec    macro    ?adr
  186.     db    0,-1
  187.     dw    ?adr
  188.     endm
  189.  
  190. defend    macro
  191.     dw    -1
  192.     endm
  193.  
  194.     page
  195. ;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  196. ;S T A R T        H E R E
  197. ;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  198.  
  199.     org    100h
  200. ;""""""""""""""
  201. ;initialization
  202. ;""""""""""""""
  203.     lxi    sp,stack    ;set up stack    
  204.     lhld    0001        ;read jump vector for i/o
  205.     lxi    d,user$offset    ;..add this
  206.     dad    d
  207.     shld    go$user$fun+1    ;install vector to user BIOS functions
  208.     
  209.     lxi    d,scbpbrd    ;point to my parameter block
  210.     mvi    c,getscb    ;..CP/M function to determine screen size
  211.     call    bdos
  212.     mov    a,h
  213.     ani    both        ;..save whether 40,80 or both
  214.     sta    scrsiz
  215.                 ;NOW  we are ready to start
  216.  
  217. ;"""""""""
  218. ;SAY$HELLO:
  219. ;"""""""""
  220.     call    clear$screen        ;set up to
  221.     call    posit$top        ;..print signon message    
  222.     call    print$msg
  223.     db    'C128 CP/M FORMAT PROGRAM' 
  224.     db    crlf
  225.     db    '     08 JUNE 1987'
  226.     db    eom
  227.  
  228.     page
  229.     mvi    c,cur$dsk        ; RETURN CURRENT DISK
  230.     call    bdos            ; ..in A
  231.     cpi    4
  232.     jrc    select$new
  233.     xra    a            ; if not A,B,C or D set A
  234.  
  235.     page
  236.  
  237. ;----------
  238. select$new:
  239. ;----------
  240.     mov    b,a        ; save in B for later
  241.     mov    c,a        ; A=B=C= selection # (0-3)
  242.     inr    c        ; (1-4)
  243.     mvi    a,80h        ; rlc will give 01
  244. select$next:
  245.     rlc            ; drive byte  0000dcba binary
  246.     dcr    c
  247.     jrnz    select$next
  248.  
  249.     sta    fmt$drv
  250.     sta    vic$drv
  251.     mov    a,b        ; get current drive select (0-3)
  252.     sta    sel$drv
  253.     adi    'A'
  254.     sta    dsp$drv$1
  255.     sta    dsp$drv$2
  256.     sta    dsp$drv$3
  257. ;
  258. ;*****    login requested drive
  259. ;
  260.     call    get$disk$info
  261.  
  262.     ani    0Eh
  263.     cpi    0Eh
  264.     jz    select$drv
  265.     page
  266. ;--------------
  267. ;show$disk$type:
  268. ;--------------
  269.     lda    fast            ;first tell user what type disk
  270.     lxi    h,fmt$drv        ;point to format drive
  271.     ana    m            ;..drive a= lst bit
  272.     lxi    h,3134h            ; 0=1541
  273.     jrz    show$slow$fast        ;
  274.  
  275. ;
  276. ;*****    test for 1581 or 1571
  277. ;
  278. ;
  279.   if    format$1581
  280.     mvi    l,'8'            ;assume 1581
  281.     lda    vic$data
  282.     cpi    0A3h            ;horrible hack for *blank* disks!
  283.     jrz    show$slow$fast        ; it is an empty 3.5" drive
  284.     cpi    0A9h
  285.     jrz    show$slow$fast        ; it is a virgin 3.5" diskette
  286.     ani    0B0h            ; 
  287.     cpi    020h            ;Resident fmt with 512 byte sectors?
  288.     jrz    show$slow$fast        ; yes, gotta be a 1581
  289.   endif
  290.  
  291.     mvi    l,'7'            ;none of the above, set as a 1571
  292.  
  293. show$slow$fast:
  294.     shld    a$15xx            ;..store the type in message
  295.     call    clear$lots        ;
  296.     call    posit$using
  297.     call    print$msg
  298.     db    'Drive '
  299. dsp$drv$1:
  300.     db    'A is a 15'
  301. a$15xx:    db    'x1',eom
  302.     mvi    a,use$line
  303.     call    highlight$line
  304.  
  305.  
  306. re$start:
  307.     lxi    sp,stack    ; set up stack    
  308.     lda    a$15xx
  309.     cpi    '4'
  310.     jz    get$1541$choices
  311.   if    format$1581
  312.     cpi    '7'
  313.     jz    get$1571$choices
  314. ;    cpi    '8'
  315. ;    jz    get$1581$choices
  316. ;
  317.     page
  318. ;---------------
  319. ;get$1581$choices:
  320. ;---------------
  321.     call    show$prompt        ;
  322.     db    'Please select disk type to format'
  323.     db    crlf,'Commodore 1581 (Double Sided)'
  324.     db    crlf,'Write system track only'
  325.     db    crlf,'Select Different Drive'
  326.     db    eom
  327.  
  328.     save$top$bottom    promptline+1,3
  329.     call    menu$response
  330.     dw    c128$ds$81
  331.     dw    c128$sys$81
  332.     dw    select$drv
  333.  
  334.   endif
  335.     page
  336. ;---------------
  337. get$1571choices:
  338. ;---------------
  339.     call    show$prompt
  340.     db    'Please select disk type to format'
  341.     db    crlf,'C128 Double sided'
  342.     db    crlf,'C128 Single sided'
  343.     db    crlf,'C64 Single sided'
  344.     db    crlf,'IBM Single Sided'
  345.     db    crlf,'IBM Double Sided'
  346.     db    crlf,'KAYPRO II'
  347.     db    crlf,'KAYPRO IV'
  348.     db    crlf,'EPSON QX10'
  349.     db    crlf,'OSBORNE DD'
  350.     db    crlf,'Select Different Drive'
  351.     db    eom
  352.  
  353.     save$top$bottom    promptline+1,10
  354.     call    menu$response
  355.     dw    c128$ds
  356.     dw    c128$ss
  357.     dw    c64$ss            ;
  358.     dw    c1571$ibm$ss        ;
  359.     dw    c1571$ibm$ds        ;
  360.     dw    c1571$kp$2        ;
  361.     dw    c1571$kp$4        ;
  362.     dw    c1571$epson        ;
  363.     dw    c1571$osborne        ;
  364.     dw    select$drv        ;
  365.  
  366.     page
  367. ;----------------
  368. get$1541$choices:
  369. ;----------------
  370.     call    show$prompt        ;
  371.     db    'Please select disk type to format'
  372.     db    crlf,'C128 single sided'
  373.     db    crlf,'C64 single sided'
  374.     db    crlf,'Select Different Drive'
  375.     db    eom
  376.  
  377.     save$top$bottom promptline+1,3
  378.     call    menu$response
  379.     dw    c128$ss
  380.     dw    c64$ss
  381.     dw    select$drv
  382.  
  383. ;----------
  384. select$drv:
  385. ;----------
  386.     call    show$prompt        ;
  387.     db    'Please select drive you wish to format with'
  388.     db    crlf,'Drive A'
  389.     db    crlf,'Drive B'
  390.     db    crlf,'Drive C'
  391.     db    crlf,'Drive D'
  392.     db    eom
  393.  
  394.     save$top$bottom    promptline+1,4
  395.     call    menu$response
  396.     dw    0            ; continue execute inline
  397.     jmp    select$new
  398.  
  399.     page
  400. ;
  401. ;
  402.   if    format$1581
  403. c128$ds$81:
  404.     lxi    h,c1581$dsk$def
  405.     jr    format$str
  406. c128$sys$81:
  407.     lxi    h,c1581$sys$def
  408.     jr    format$str
  409.   endif
  410. ;
  411. ;
  412. c128$ds:
  413.     lxi    h,c128$ds$dsk$def
  414.     jr    format$str
  415. ;
  416. ;
  417. c128$ss:
  418.     lxi    h,c128$ss$dsk$def
  419.     jr    format$str
  420. ;
  421. ;
  422. c64$ss:
  423.     lxi    h,c64$ss$dsk$def
  424.     jr    format$str
  425. ;
  426. ;
  427. c1571$epson:
  428.     lxi    h,epson$dsk$def
  429.     jr    format$str
  430. ;
  431. ;
  432. c1571$osborne:
  433.     lxi    h,osborne$dsk$def
  434.     jr    format$str
  435. ;
  436. ;
  437. c1571$kp$2:
  438.     lxi    h,kp$2$dsk$def
  439.     jr    format$str
  440. ;
  441. ;
  442. c1571$kp$4:
  443.     lxi    h,kp$4$dsk$def
  444.     jr    format$str
  445. ;
  446. ;
  447. c1571$ibm$ss:
  448.     lxi    h,ibm$dsk$def$ss
  449.     jr    format$str
  450. ;
  451. ;
  452. C1571$ibm$ds:
  453.     lxi    h,ibm$dsk$def$ds
  454. ;    jr    format$str
  455.  
  456.     page
  457. ;
  458. ;
  459. ;
  460. format$str:
  461. ;    call    print$msg
  462. ;    db    'Formatting',crlf,eom
  463.     call    print$what
  464.     shld    fmt$tbl$ptr
  465.     call    clear$prompt
  466.     call    print$msg
  467.     db    'Insert diskette TO BE FORMATTED'
  468.     db    crlf,'in drive '
  469. dsp$drv$2:
  470.     db    'A.  Type $ when ready,'
  471.     db    crlf,'any other key to abort ',eom
  472.     call    scan$for$key
  473.     mov    a,b
  474.     cpi    disk$ready$key
  475.     jnz    user$panics
  476.     call    clear$prompt
  477.     call    print$msg
  478.     db    '..formatting diskette in drive '
  479. dsp$drv$3:
  480.     db    'A',crlf,eom
  481.  
  482.     lhld    fmt$tbl$ptr
  483. ; do the format
  484.     call    get$DE$from$HL    ; get format table pointer (side 1)
  485.     cnz    format$DE$tbl
  486.     call    get$DE$from$HL    ; get format table pointer (side 2)
  487.     cnz    format$DE$tbl
  488.     call    set$dsk$type
  489.  
  490.     page
  491. ;
  492. ;
  493. ;
  494. format$1:
  495.     call    get$DE$from$HL    ; get track & sect
  496.     mov    a,d        ; DE=-1 ?
  497.     ana    e
  498.     inr    a
  499.     jz    format$another?
  500.     mov    a,e
  501.     sta    trk
  502.     mov    a,d
  503.     sta    sect
  504.  
  505.     call    print$msg
  506.     db    '..writing sector',cr,eom
  507.  
  508.     call    get$DE$from$HL    ; get DEF pointer
  509.     xchg            ; HL=DEF pointer,  DE=MAIN pointer
  510.     push    d        ; save MAIN pointer
  511. ;
  512. ;
  513. ;
  514.     mov    a,m        ; get fill byte
  515.     inx    h
  516.     call    init$buf$with$A    ; (HL saved)
  517. next$fill:
  518.     call    get$DE$from$HL    ; get word count to DE
  519.     jm    count$minus
  520.     mov    b,d        ; save count in BC
  521.     mov    c,e
  522.     call    get$DE$from$HL    ; get offset in buffer
  523.     push    d
  524.     call    get$DE$from$HL    ; get pointer to data
  525.     xthl            ; save DEF pointer get offset
  526.     push    d        ; save DATA pointer
  527.     lxi    d,sect$buf
  528.     dad    d        ; HL= buffer+offset
  529.     pop    d        ; DE= DATA pointer
  530.     xchg            ; HL= DATA ptr, DE= buffer+offset
  531.     ldir            ; move data to buffer
  532.     pop    h        ; recover DEF pointer
  533.     jr    next$fill
  534.  
  535.     page
  536. ;
  537. ;
  538. ;
  539. count$minus:
  540.     inr    e        ; test for -1
  541.     jrnz    cnt$not$minus$1
  542.  
  543.     call    write$data
  544.     pop    h        ; recover MAIN pointer
  545.     jmp    format$1
  546.  
  547. cnt$not$minus$1:
  548.     dcr    e        ; test for 0
  549.     jrnz    data$inline
  550.  
  551.     call    get$DE$from$HL
  552.     xchg            ; HL=code adr,  DE=DEF pointer
  553.     push    d        ; save DEF pointer
  554.     call    ipchl
  555.     pop    h        ; recover DEF pointer
  556.     jmp    next$fill
  557.  
  558. data$inline:
  559.     mvi    b,0
  560.     mov    c,e        ; BC=number of bytes to move
  561.     call    get$DE$from$HL    ; get offset
  562.     push    h        ; save DEF pointer
  563.     lxi    h,sect$buf
  564.     dad    d        ; HL=buffer+offset
  565.     xchg            ; DE=buffer+offset
  566.     pop    h        ; recover DEF pointer
  567.     ldir
  568.     jmp    next$fill
  569.  
  570.     page
  571. ;
  572. ;
  573. ;
  574. format$DE$tbl:
  575.     push    h        ; save MAIN pointer
  576.     xchg            ; HL=format table pointer
  577.     mov    c,m        ; get count
  578.     mvi    b,0        ; count will be 1 to 255
  579.     inr    c        ; move count also
  580.     lxi    d,@buffer    ; point to command buffer area
  581.     ldir            ; move format data to buffer
  582.     lda    fmt$drv        ;..bit 0==drive a, MSB=unit 0
  583.     sta    vic$drv
  584.     mvi    a,do$6502$fun
  585.     mvi    l,vic$frmt
  586.     call    go$user$fun    ;call,ret
  587.     ora    a
  588.     jrnz    format$error
  589.     pop    h
  590.     ret
  591.  
  592.     page
  593. ;------------
  594. format$error:
  595. ;------------
  596.     call    print$msg
  597.     db    '    format error',cr,lf,eom
  598. user$panics:
  599.     pop    h
  600.  
  601. ;---------------
  602. format$another?:
  603. ;---------------
  604.     call    print$msg
  605.     db    crlf,lf,lf
  606.     db    'Do you want to format another disk?'
  607.     db    eom
  608.     call    get$yes$or$no
  609.     jc    re$start
  610.  
  611. ;-----------
  612. exit$format:
  613. ;-----------
  614.     call    clear$screen
  615.     call    posit$prompt
  616.     call    print$msg
  617.     db    '.....exiting format program',cr,lf,lf,eom
  618. exit$clean:
  619.     mvi    c,13
  620.     call    bdos            ; reset disk system
  621.     mvi    c,constat
  622.     call    bdos
  623.     ana    a
  624.     jz    0
  625.     mvi    c,conin
  626.     call    bdos
  627.     jmp    0
  628.  
  629. ;---------
  630. quit$prog:
  631. ;---------
  632.     push    psw
  633.     push    b
  634.     push    d
  635.     push    h
  636.     call    posit$spec        ;for special messages 
  637.     call    print$msg
  638.     db    'Are you sure? [ ]',bs,bs,eom
  639.     call    get$yes$or$no
  640.     jrc    exit$clean
  641.     call    posit$spec
  642.     call    clear$eol
  643.     pop    h
  644.     pop    d
  645.     pop    b
  646.     pop    psw
  647.     ret
  648.  
  649.     page
  650. ;--------------
  651. get$DE$from$HL:
  652. ;--------------
  653.     mov    e,m
  654.     inx    h
  655.     mov    d,m
  656.     inx    h
  657.     mov    a,d
  658.     ora    e
  659.     rz
  660.     mov    a,d
  661.     ana    a
  662.     ret
  663.  
  664. ipchl:
  665.     pchl
  666.  
  667. ;---------------
  668. init$buf$with$A:
  669. ;---------------
  670.     push    h
  671.     lxi    h,sect$buf
  672.     shld    dma
  673.     mov    m,a
  674.     lxi    d,sect$buf+1
  675.     lxi    b,1024
  676.     ldir
  677.     pop    h
  678.     ret
  679. ;
  680. ;    set disk type to TYPE 0  (GCR direct sector I/O)
  681. ;------------
  682. set$dsk$type:
  683. ;------------
  684.     push    h
  685.     mvi    c,13
  686.     call    bdos            ; reset disk system
  687.     lxi    d,sel$pb
  688.     call    BIOS$ind
  689.     dcx    h
  690.     call    get$disk$info
  691.     bit    a,7            ; MFM disk?
  692.     jrnz    size$ok            ; yes, then size is ok
  693.     ani    30h            ; no,  1571 GCR reports
  694.     jrnz    size$ok            ; ...128 byte sectors
  695.     mvi    a,10h            ; set 256 byte sectors
  696. size$ok:
  697.     ani    00110000b         ; set disk type to DSK$none
  698.     mov    m,a            ; this will allow direct sector access
  699.     pop    h
  700.     ret
  701.  
  702. ;-------------
  703. get$disk$info:
  704. ;-------------
  705.     push    h
  706.     mvi    a,do$6502$fun
  707.     mvi    l,vic$test
  708.     call    go$user$fun    ;call,ret
  709.     mov    b,a        ;save status from drive in B also
  710.     pop    h
  711.     ret
  712.  
  713.     page
  714. ;----------
  715. write$data:
  716. ;----------
  717.     lxi    d,dma$bnk$pb
  718.     call    BIOS$ind
  719.     lxi    d,dma$pb
  720.     call    BIOS$ind
  721.     lxi    d,trk$pb
  722.     call    BIOS$ind
  723.     lxi    d,sect$pb
  724.     call    BIOS$ind
  725.     lxi    d,wr$pb
  726.     call    BIOS$ind
  727.     ana    a
  728.     rz
  729.     pop    h
  730.     call    posit$spec
  731.     call    print$msg
  732.     db    'Disk write error',crlf,eom
  733.     jmp    exit$format
  734.  
  735.     page
  736. ;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  737. ;M I S C E L L A N E O U S   U S E F U L   U T I L I T I E S                            
  738. ;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  739. beep:
  740.     mvi    e,7
  741.     jr    do$con$out
  742.  
  743. do$cr$lf:
  744.     mvi    e,cr
  745.     call    do$con$out
  746.     mvi    e,lf
  747. do$con$out:
  748.     mvi    c,conout
  749.     jmp    bdos
  750.  
  751. BIOS$ind:
  752.     mvi    c,50
  753.     jmp    bdos
  754.  
  755. print$what:
  756.     push    h
  757.     call    clear$lots
  758.     pop    h
  759.     call    print$hl
  760.     push    h
  761.     mvi    a,lots$line
  762.     call    highlight$line
  763.     pop    h
  764.     ret
  765.  
  766. show$prompt:
  767.     call    clear$lots        ;
  768.     call    posit$prompt
  769. ;-----------------------------------------------------
  770. print$msg:        ;print a message on the screen
  771. ;-----------------------------------------------------
  772.     xthl
  773.     call    print$hl
  774.     xthl
  775.     ret
  776.  
  777. print$hl:
  778.     push    h
  779. print$lp:
  780.     pop    h
  781.     mov    a,m        ;..get the message
  782.     mov    e,a        ;in a for call to bdos
  783.     inx    h        ;..update pointer
  784.     ana    a        ;if char was 0, pointer = return address
  785.     rz            ;..end message
  786.     push    h        ;..restore pointer
  787.     inr    a        ;..FF==cr,lf
  788.     jrz    char$eq$cr$lf    
  789.     call    do$con$out
  790.     jr    print$lp    ;..loop
  791.  
  792. char$eq$cr$lf:
  793.     call    do$cr$lf
  794.     jr    print$lp
  795.  
  796. clear$prompt:
  797.     call    posit$prompt
  798.     call    clear$eos
  799. posit$prompt:
  800.     lxi    d,prompt$line*256+0        ; B=row C=col
  801.     jr    set$fx$cp$cmd
  802.  
  803. clear$edit:
  804.     call    posit$editing
  805.     call    clear$eos
  806. posit$editing:
  807.     lxi    d,keynam$line*256+0
  808.     jr    set$fx$cp$cmd
  809.  
  810. posit$top:
  811.     lxi    d,top$line*256
  812.     jr    set$fx$cp$cmd
  813.  
  814. posit$using:
  815.     lxi    d,use$line*256        ; B=row C=col
  816.     jr    set$fx$cp$cmd
  817.  
  818. clear$lots:
  819.     call    posit$lots
  820.     call    clear$eos
  821. posit$lots:
  822.     lxi    d,lots$line*256
  823.     jr    set$fx$cp$cmd
  824.  
  825. posit$spec:        
  826.     lxi    d,spec$line*256
  827. set$fx$cp$cmd:                ;set up to position cursor
  828.     mvi    l,FR$cursor$pos
  829.     jr    go$screen$fun
  830.  
  831. clear$eos:
  832.     mvi    l,FR$CES
  833.     jr    go$screen$fun
  834.  
  835. clear$eol:
  836.     mvi    l,FR$CEL
  837. go$screen$fun:
  838.     push    b
  839.     lda    scr$siz
  840.     mvi    c,FR$40
  841.     cpi    scrsz40
  842.     jrnz    set$fx$eighty
  843. set$fx$forty:
  844.     mov    a,l
  845.     add    c
  846.     mov    l,a
  847. set$fx$eighty:
  848.     mvi    a,3        ; direct to screen fun #
  849.     pop    b
  850. go$user$fun:
  851.     jmp    0000        ; address filled in
  852.  
  853.     page
  854. ;"""""""""""""""""""""""""""""""""""""""""""""""""
  855. ;s c a n   f o r   y e s   o r   n o   a n s w e r
  856. ;"""""""""""""""""""""""""""""""""""""""""""""""""
  857. get$yes$or$no:
  858.     call    scan$for$key
  859.     mov    a,b
  860.     cpi    yes$key
  861.     stc
  862.     rz
  863.     sui    no$key
  864.     ana    a        ;clear carry for no
  865.     rz
  866.     call    beep
  867.     jr    get$yes$or$no
  868.  
  869. ;"""""""""""""""""""""""""""""""""""""""""""""
  870. ;s c a n   f o r   k e y b o a r d   i n p u t
  871. ;""""""""""""""""""""""""""""""""""""""""""""" 
  872. scan$for$key:
  873.     mvi    a,2
  874.     call    go$user$fun
  875.     inr    b
  876.     jrz    scan$for$key
  877.     dcr    b
  878.     ret
  879.  
  880.     page
  881. ;"""""""""""""""""""""""""""""""
  882. ;c l e a r   t h e   s c r e e n
  883. ;"""""""""""""""""""""""""""""""
  884. clear$screen:
  885.     call    print$msg
  886.     db    1ah,eom
  887.     ret
  888.  
  889. ;"""""""""""""""""""""""""""""""""""""""""
  890. ;g e t    r e s p o n s e   t o    m e n u
  891. ;""""""""""""""""""""""""""""""""""""""""" 
  892. menu$response:
  893.     sta    current$choice
  894.     call    highlight$line
  895. wait$ans:
  896.     call    scan$for$key
  897.     mov    a,b
  898.     cpi    cret
  899.     jz    made$selection
  900.     cpi    ctrlc
  901.     cz    quit$prog
  902.     call    up$or$down?
  903.     cz    scroll$values
  904.     jr    wait$ans     
  905.  
  906. made$selection:
  907.     lda    top$choice
  908.     mov    b,a
  909.     lda    current$choice        
  910.     sub    b            ;a=0-x for choices
  911.     mov    b,a            ;..save it
  912.     pop    d
  913.     mov    l,a
  914.     mvi    h,0
  915.                 ;first test if de is pointing to a 00
  916.     dad    h        ;*2
  917.     xchg            ;(00--> just return)
  918.     mov    a,m
  919.     inx    h
  920.     ora    m
  921.     inx    h
  922.     jrz    back$to$??
  923.     dcx    h
  924.     dcx    h
  925.     dad    d        ;+ beginning of jump table
  926.     mov    a,m
  927.     inx    h
  928.     mov    h,m
  929.     mov    l,a    
  930. back$to$??:
  931.     mov    a,b        ;a=0-x
  932.     pchl    
  933.  
  934.     page
  935. ;"""""""""""""""""""""""""""""""""""""""""""""""""""""
  936. ;s c r o l l  u p  &  d o w n   t h r o u g h  m e n u
  937. ;"""""""""""""""""""""""""""""""""""""""""""""""""""""
  938. scroll$values:
  939.     push    psw
  940.     lda    current$choice
  941.                 ;unhighlight the current menu line
  942.     mvi    h,0        ;..dont set any additional attributes
  943.     call    write$hi$line    ;..common routine for writing current line
  944.     pop    psw        ;get flags back
  945.     jrc    scroll$up
  946.     lda    bottom$choice
  947.     mov    b,a
  948.     lda    current$choice
  949.     cmp    b        ;current==bottom && scrolldown??
  950.     jrz    force$top
  951.     inr    a            
  952.     sta    current$choice
  953.     jr    highlight$line    ;call,ret
  954.  
  955. scroll$up:
  956.     lda    top$choice
  957.     mov    b,a
  958.     lda    current$choice
  959.     cmp    b        ;current==top && scroll up??
  960.     jrz    force$bottom
  961.     dcr    a
  962.     sta    current$choice
  963.     jr    highlight$line        ;call,ret
  964.  
  965. force$top:
  966.     lda    top$choice        ;to scroll down from bottom==top
  967.     sta    current$choice
  968.     jr    highlight$line        ;call,ret
  969.  
  970. force$bottom:
  971.     lda    bottom$choice        ;to scroll up from top==bottom
  972.     sta    current$choice
  973. highlight$line:                ;a=row # to be highlighted 
  974.     call    read$this$row        ;to highlight, read current row and
  975.     mvi    h,40h            ;..write it out with rev vid attribute
  976.     jr    write$hi$line
  977.  
  978.     page
  979.  
  980. read$this$row:
  981.     push    psw        ;save the row number for others
  982.     mov    d,a        ;d=row
  983.     mvi    e,0        ;column (e) = 0
  984.     lxi    h,save$buffer    ;a place to read into
  985.     shld    temp$ptr    ;save a pointer
  986.     xra    a        ;..initialize count to 0
  987.     sta    read$count
  988. read$row$lp:    
  989.     push    d        ;..save it to loop
  990.     mvi    l,FR$rd$chr$atr    ;read char and attribute from (de)
  991.     call    go$screen$fun    ;go read a character
  992.     lhld    temp$ptr    ;get buffer pointer
  993.     mov    m,b        ;buffer the character 
  994.     inx    h
  995.     mov    m,c        ;..and the attribute
  996.     inx    h        ;to next character
  997.     shld    temp$ptr    ;save the pointer
  998.     pop    d        ;current row,column
  999.     inx    d        ;next row,column
  1000.     mov    a,e        ;when count(column)=, we have read maximum
  1001.     cpi    40
  1002.     jrnz    read$row$lp
  1003.     dcx    h        ;point to last character written
  1004.     mov    b,e        ;# of characters to scan for trailing spaces
  1005.     mvi    a,' '        ;..space character to scan for
  1006. scan$space$lp:
  1007.     dcx    h        ;char, not attribute
  1008.     cmp    m        ;..is char a space??
  1009.     jrnz    end$scan    ;if not, we are done
  1010.     dcx    h        ;..else decrement to previous attribute
  1011.     djnz    scan$space$lp    ;keep looking
  1012. end$scan:
  1013.     mov    a,b    
  1014.     inr    a
  1015.     sta    read$count    ;store # of non-white chars to restore
  1016.     pop    psw        ;restore a=row #
  1017.     ret
  1018.  
  1019.     page
  1020.  
  1021. write$hi$line:
  1022.     mov    d,a        ;current row passed in a
  1023.     mvi    e,0        ;..start at column 0
  1024.     mov    a,h        ;..additional attribute bits passed in h
  1025.     sta    temp        ;save attribute value to be ored
  1026.     lxi    h,save$buffer    ;where the current line was read into
  1027.     shld    temp$ptr    ;..save pointer to it 
  1028.     lda    read$count    ;number of bytes actually in line (no trailing spaces)
  1029.  
  1030.     mov    b,a        ;..count in b
  1031. wr$hi$li$loop:
  1032.     push    b        ;save the counter
  1033.     push    d        ;save the cursor position
  1034.     lhld    temp$ptr    ;get pointer
  1035.     mov    b,m        ;get char in b
  1036.     inx    h        ;point to attribute
  1037.     mov    a,m        ;..get attribute
  1038.     inx    h        ;update to next character
  1039.     shld    temp$ptr    ;..save the pointer
  1040.     mov    h,a        ;..put attribute here for a moment
  1041.     lda    temp        ;get the attribute passed (either rev vid or none)
  1042.     ora    h        ;..set it
  1043.     mov    c,a        ;..attribute must be passed in c
  1044.     mvi    l,FR$wr$chr$atr    ;write character and attribute functions
  1045.     call    go$screen$fun    ;go do it
  1046.     pop    d        ;cursor position back
  1047.     inx    d        ;..next
  1048.     pop    b        ;get counter back
  1049.     djnz    wr$hi$li$loop    ;..loop    
  1050.     ret            ;...line is rewritten
  1051.  
  1052. up$or$down?:
  1053.     mov    a,b        ;get matrix row in a    
  1054.     cpi    cursor$up$key    ;is it cursor up?
  1055.     stc
  1056.     rz            ;..return if cursor up
  1057.     sui    cursor$dn$key
  1058.     ana    a        ;clear carry flag
  1059.     ret            ;return something to caller
  1060.  
  1061.     page
  1062. ;-------------------------------
  1063. ;p a r a m e t e r   b l o c k s
  1064. ;-------------------------------
  1065. scbpbrd:
  1066.     db    24h        ;set offset for conout
  1067.     db    0        ;..get (read)scb (hl =returnedword,a=byte)
  1068.     dw    0        ;just for the hell of it
  1069.  
  1070. wr$pb:            ;write parameter block    
  1071.     db    14        ;write sector
  1072.     db    0
  1073.     dw    0
  1074.     dw    0
  1075.     dw    0
  1076.  
  1077. sel$pb:            ;select parameter block
  1078.     db    9        ; select drive function
  1079.     db    0        ; a  
  1080. sel$drv:
  1081.     dw    0        ; bc drive #
  1082.     dw    1        ; de lsb=0 means 1st time select
  1083.     dw    0        ; hl
  1084.  
  1085. trk$pb:            ;track parameter block
  1086.     db    10        ; set track
  1087.     db    0
  1088. trk:    dw    0001h        ; track #
  1089.     dw    0
  1090.     dw    0
  1091.  
  1092. sect$pb:        ;sector parameter block    
  1093.     db    11        ; set sector #
  1094.     db    0
  1095. sect:    dw    0001h        ; sector #
  1096.     dw    0
  1097.     dw    0
  1098.  
  1099. dma$pb:            ;dma parameter block
  1100.     db    12
  1101.     db    0
  1102. dma:    dw    4000h        ; dma pointer
  1103.     dw    0
  1104.     dw    0
  1105.  
  1106. dma$bnk$pb:        ;dma bank parameter block
  1107.     db    28
  1108.     db    1        ; dma bank 1
  1109.     dw    0
  1110.     dw    0
  1111.     dw    0
  1112.  
  1113.     page
  1114. ;
  1115. ;     39-1    |     39-2    |     39-3    |
  1116. ;"""""""""""""""|"""""""""""""""|"""""""""""""""|
  1117. ; disk    | BAM    | BAM    | disk    | DRV    | SYS    |
  1118. ; lable    |  1    |  2    | DIR    | boot    | boot    |
  1119. ;"""""""|"""""""|"""""""|"""""""|"""""""|"""""""|
  1120. ; 40-0    | 40-1    | 40-2    | 40-3    | 40-4    | 40-5    |
  1121. ;
  1122. ;
  1123. ;     39-4    |     39-5    |
  1124. ;"""""""""""""""|"""""""""""""""|
  1125. ;  LDR    |  LDR    |  LDR    |    |
  1126. ;  #1    |  #2    |  #3    |    |
  1127. ;"""""""|"""""""|"""""""|"""""""|
  1128. ; 40-6    | 40-7    | 40-8    | 40-9    |
  1129. ;
  1130.   if    format$1581
  1131. c1581$dsk$def:
  1132.     db    'Formatting C128 CP/M on C1581',eom
  1133.     fmt    fmt$tbl$c1581
  1134.     wrdef    39,1,ST$sect$39$1
  1135.     wrdef    39,2,ST$sect$39$2
  1136.     wrdef    39,3,ST$sect$39$3
  1137.     wrdef    39,4,ST$loader$start$1
  1138.     wrdef    39,5,ST$loader$start$2
  1139.     defend
  1140.  
  1141. c1581$sys$def:
  1142.     db    'Formatting C128 CP/M on C1581',eom
  1143.     fmt    0
  1144.     wrdef    39,1,ST$sect$39$1
  1145.     wrdef    39,2,ST$sect$39$2
  1146.     wrdef    39,3,ST$sect$39$3
  1147.     wrdef    39,4,ST$loader$start$1
  1148.     wrdef    39,5,ST$loader$start$2
  1149.     defend
  1150.   endif
  1151.     page
  1152. ;
  1153. ;
  1154. ;
  1155. c64$ss$dsk$def:
  1156.     db    'C64 single sided',eom
  1157.     fmt    fmt$tbl$c64$ss
  1158.     wrdef    1,0,ST$c64$1$0        ; track, sector, DEF
  1159.     wrdef    3,0,ST$E5s        ; track, sector, DEF
  1160.     wrdef    3,1,ST$E5s        ; track, sector, DEF
  1161.     wrdef    3,2,ST$E5s        ; track, sector, DEF
  1162.     wrdef    3,3,ST$E5s        ; track, sector, DEF
  1163.     wrdef    3,4,ST$E5s        ; track, sector, DEF
  1164.     wrdef    3,5,ST$E5s        ; track, sector, DEF
  1165.     wrdef    3,6,ST$E5s        ; track, sector, DEF
  1166.     wrdef    3,7,ST$E5s        ; track, sector, DEF
  1167.     defend
  1168.  
  1169.     page
  1170. ;
  1171. ;
  1172. ;
  1173. c128$ss$dsk$def:
  1174.     db    'C128 Single Sided',eom
  1175.     fmt    fmt$tbl$c64$ss
  1176.     wrdef    1,0,ST$c128$1$0$ss    ; track, sector, DEF
  1177.     wrdef    1,3,ST$E5s
  1178.     wrdef    1,4,ST$E5s
  1179.     wrdef    1,9,ST$E5s
  1180.     wrdef    1,10,ST$E5s
  1181.     wrdef    1,14,ST$E5s
  1182.     wrdef    1,15,ST$E5s
  1183.     wrdef    1,19,ST$E5s
  1184.     wrdef    1,20,ST$E5s
  1185.     wrdef    18,0,ST$sect$18$0
  1186.     defend
  1187.  
  1188.     page
  1189. ;
  1190. ;
  1191. ;
  1192. c128$ds$dsk$def:
  1193.     db    'C128 Double Sided',eom
  1194.     fmt    fmt$tbl$c64$ss
  1195.     wrdef    1,0,ST$c128$1$0$ds    ; track, sector, DEF
  1196.     wrdef    1,1,ST$E5s
  1197.     wrdef    1,2,ST$E5s
  1198.     wrdef    1,3,ST$E5s
  1199.     wrdef    1,4,ST$E5s
  1200.     wrdef    1,7,ST$E5s
  1201.     wrdef    1,8,ST$E5s
  1202.     wrdef    1,9,ST$E5s
  1203.     wrdef    1,10,ST$E5s
  1204.     wrdef    1,12,ST$E5s
  1205.     wrdef    1,13,ST$E5s
  1206.     wrdef    1,14,ST$E5s
  1207.     wrdef    1,15,ST$E5s
  1208.     wrdef    1,17,ST$E5s
  1209.     wrdef    1,18,ST$E5s
  1210.     wrdef    1,19,ST$E5s
  1211.     wrdef    1,20,ST$E5s
  1212.     wrdef    18,0,ST$sect$18$0
  1213.     wrdef    53,0,ST$sect$18$0
  1214.     defend
  1215.  
  1216.     page
  1217. ;
  1218. ;
  1219. ;
  1220. epson$dsk$def:
  1221.     db    'EPSON QX10 512 byte sectors',eom
  1222.     fmt    fmt$tbl$epson
  1223.     defend
  1224. ;
  1225. ;    no sector to be set-up
  1226. ;
  1227. osborne$dsk$def:
  1228.     db    'OSBORNE Double Density',eom
  1229.     fmt    fmt$tbl$osborne
  1230.     defend
  1231. ;
  1232. ;
  1233. ;
  1234. kp$2$dsk$def:
  1235.     db    'KAYPRO II',eom
  1236.     fmt    fmt$tbl$kp$2
  1237.     defend
  1238.  
  1239. kp$4$dsk$def:
  1240.     db    'KAYPRO IV',eom
  1241.     fmt    fmt$tbl$kp$2,fmt$tbl$kp$4
  1242.     defend
  1243.  
  1244.     page
  1245. ;
  1246. ;    IBM -- single sided disk definition
  1247. ;
  1248. ibm$dsk$def$ss:
  1249.     db    'IBM SS',eom
  1250.     fmt    fmt$tbl$ibm$ss
  1251.     wrdef    0,1,ST$ibm$ss        ; track, sector, DEF
  1252.     defend
  1253. ;
  1254. ;
  1255. ;
  1256. ibm$dsk$def$ds:
  1257.     db    'IBM DS',eom
  1258.     fmt    fmt$tbl$ibm$ds
  1259.     wrdef    0,1,ST$ibm$ds        ; track, sector, DEF
  1260.     defend
  1261.  
  1262.     page
  1263. ;
  1264. ;
  1265. ;
  1266.   if    format$1581
  1267. fmt$tbl$c1581:
  1268.     db    1
  1269.     db    10000110b    ;parameter N   (cmd 4)
  1270.     db    2        ; sector size =512
  1271.     db    79        ; last track # 79
  1272.     db    10        ; number sectors/track
  1273.     db    0        ; starting track #
  1274.     db    0E5h        ; fill byte
  1275.     db    38        ; gap 3
  1276.   endif
  1277. ;
  1278. ;    GCR Format parameters
  1279. ;
  1280. fmt$tbl$c64$ss:
  1281. table$ds:    
  1282.     db    4
  1283.     db    00000110b    ;parameter N   (cmd 4)
  1284.     db    00000000b    ;parameter MD  (Mode GCR)
  1285.     db    '8'        ;parameter ID low
  1286.     db    '0'        ;parameter ID high
  1287.  
  1288. ;
  1289. ;
  1290. ;
  1291. fmt$tbl$epson:
  1292.     db    6
  1293.     db    01100110b    ; N    cmd 4
  1294.     db    10000001b    ; MD    Mode MFM (start sector 1)
  1295.     db    0        ; CP    interleave of 0
  1296.     db    2        ; SZ    512 byte sectors
  1297.     db    39        ; LT    last track 39
  1298.     db    10        ; NS    10 sectors/track
  1299.                 ; ST    Starting track logical (def 0)
  1300.                 ; S    Starting Offset Physical (def 0)
  1301.                 ; FL    Fill byte (def E5)
  1302.  
  1303. ;
  1304. ;
  1305. ;
  1306. fmt$tbl$osborne:
  1307.     db    6
  1308.     db    01000110b    ; N    cmd 4
  1309.     db    10000001b    ; MD    Mode MFM (start sector 1)
  1310.     db    0        ; CP    interleave of 0
  1311.     db    3        ; SZ    1024 byte sectors
  1312.     db    39        ; LT    last track 39
  1313.     db    5        ; NS    5 sectors/track
  1314.                 ; ST    Starting track logical (def 0)
  1315.                 ; S    Starting Offset Physical (def 0)
  1316.                 ; FL    Fill byte (def E5)
  1317.     page
  1318. ;
  1319. ;    KAYPRO II (single sided)
  1320. ;    -- uses this format data to format the top and
  1321. ;    -- bottom of KAYPRO II and KAYPRO IV disk
  1322. ;
  1323. fmt$tbl$kp$2:
  1324.     db    6
  1325.     db    01000110b    ; N    cmd 4
  1326.     db    10000000b    ; MD    Mode MFM (start sector 0)
  1327.     db    0        ; CP    interleave of 0
  1328.     db    2        ; SZ    512 byte sectors
  1329.     db    39        ; LT    last track 39
  1330.     db    10        ; NS    10 sectors/track
  1331.                 ; ST    Starting track logical (def 0)
  1332.                 ; S    Starting Offset Physical (def 0)
  1333.                 ; FL    Fill byte (def E5)
  1334. ;
  1335. ;    KAYPRO IV (double sided)
  1336. ;    -- uses this format data to format the top of the disk (side 1)
  1337. ;
  1338. fmt$tbl$kp$4:
  1339.     db    6
  1340.     db    01010110b    ; N    cmd 4
  1341.     db    10001010b    ; MD    Mode MFM (start sector 10)
  1342.     db    0        ; CP    interleave of 0
  1343.     db    2        ; SZ    512 byte sectors
  1344.     db    39        ; LT    last track 39
  1345.     db    10        ; NS    10 sectors/track
  1346.                 ; ST    Starting track logical (def 0)
  1347.                 ; S    Starting Offset Physical (def 0)
  1348.                 ; FL    Fill byte (def E5)
  1349.     page
  1350. ;
  1351. ;
  1352. ;
  1353. fmt$tbl$ibm$ss:
  1354.     db    6
  1355.     db    01000110b    ; N    cmd 4
  1356.     db    10000001b    ; MD    Mode MFM (start sector 1)
  1357.     db    0        ; CP    interleave of 0
  1358.     db    2        ; SZ    512 byte sectors
  1359.     db    39        ; LT    last track 39
  1360.     db    8        ; NS    8 sectors/track
  1361.                 ; ST    Starting track logical (def 0)
  1362.                 ; S    Starting Offset Physical (def 0)
  1363.                 ; FL    Fill byte (def E5)
  1364. ;
  1365. ;
  1366. ;
  1367. fmt$tbl$ibm$ds:
  1368.     db    6
  1369.     db    01100110b    ; N    cmd 4 format DS
  1370.     db    10000001b    ; MD    Mode MFM (start sector 1)
  1371.     db    0        ; CP    interleave of 0
  1372.     db    2        ; SZ    512 byte sectors
  1373.     db    39        ; LT    last track 39
  1374.     db    8        ; NS    8 sectors/track
  1375.                 ; ST    Starting track logical (def 0)
  1376.                 ; S    Starting Offset Physical (def 0)
  1377.                 ; FL    Fill byte (def E5)
  1378.     page
  1379. ;
  1380. ;
  1381. ;
  1382.   if    format$1581
  1383. ST$sect$39$1:
  1384.     defstart    0
  1385.     defbuf        29,0,sect$39$1
  1386.     definline    8,100h
  1387.     db    40,2            ; next BAM track and sector
  1388.     db    44h,not(44h)        ; DISK version #
  1389.     db    '80'            ; Disk ID
  1390.     db    40h            ; verify off, check header ID on
  1391.     db    80h            ; enable auto load
  1392.     defend
  1393. ;
  1394. ;
  1395. ;
  1396. ST$sect$39$2:
  1397.     defstart    0
  1398.     definline    7,1
  1399.     db    -1        ; mark end of BAM
  1400.     db    44h,not(44h)    ; Disk Version #
  1401.     db    '80'        ; ID
  1402.     db    40h        ; verify off, check header ID on
  1403.     db    80h        ; enable auto load
  1404.     definline    20,101h
  1405.     db    -1        ; next track sector (end)
  1406.     db    83h        ; type USR
  1407.     db    40,4        ; logical trk 40 sector 4
  1408.     db    'COPYRIGHT CBM 86'
  1409.     definline    1,11Eh
  1410.     db    1
  1411.     defend
  1412.  
  1413.     page
  1414. ;
  1415. ;
  1416. ;
  1417. ST$sect$39$3:
  1418.     defstart    0
  1419.     definline    5,0
  1420.     db        0,lng$drv$cd+5
  1421.     dw        drv$buf            ; exec adr in drv
  1422.     db        lng$drv$cd
  1423.     defbuf        lng$drv$cd,5,drv$code$1581
  1424.     defexec        boot$check$sum        ; compute Check SUM
  1425.     defbuf        0c9h,100h,boot$1581$sector
  1426.     defend
  1427. ;
  1428. ;
  1429. ;
  1430. ST$loader$start$1:
  1431.     defstart    0
  1432.     defbuf        512,0,loader$start
  1433.     defend
  1434. ;
  1435. ;
  1436. ;
  1437. ST$loader$start$2:
  1438.     defstart    0
  1439.     defbuf        loader$size-512,0,loader$start+512
  1440.     defend
  1441.   endif
  1442.  
  1443.     page
  1444. ;
  1445. ;
  1446. ;
  1447. ST$c64$1$0:
  1448.     defstart    0E5h
  1449.     definline    4,0
  1450.     db        'KMBE'
  1451.     defend
  1452. ;
  1453. ;
  1454. ;
  1455. ST$c128$1$0$ss:
  1456.     defstart    0
  1457.     defbuf        24h,0,sect$1$0
  1458.     defend
  1459. ;
  1460. ;
  1461. ;
  1462. ST$c128$1$0$ds:
  1463.     defstart    0
  1464.     defbuf        24h,0,sect$1$0
  1465.     definline    1,255
  1466.     db        -1
  1467.     defend
  1468.  
  1469.     page
  1470. ;
  1471. ;
  1472. ;
  1473. ST$sect$18$0:
  1474.     defstart    0
  1475.     definline    4,0
  1476.     db    1,5,41h,80h
  1477.     definline    4,48h
  1478.     db    11h,0fch,-1,7
  1479.     definline    27,90h
  1480.     db    'CP/M PLUS'
  1481.     db    0a0h,0a0h,0a0h
  1482.     db    0a0h,0a0h,0a0h
  1483.     db    0a0h,0a0h,0a0h
  1484.     db    '65',0a0h,'2A'
  1485.     db    0a0h,0a0h
  1486.     db    0a0h,0a0h
  1487.     defend
  1488. ;
  1489. ;
  1490. ;
  1491. ST$E5s:
  1492.     defstart    0E5h
  1493.     defend
  1494. ;
  1495. ;    IBM single sided
  1496. ;    -- Track 0, Sector 1 last byte =0 
  1497. ;
  1498. ST$ibm$ss:
  1499.     defstart    0E5h
  1500.     definline    1,512-1        ; last byte=0 for IBM single sided
  1501.     db    0
  1502.     defend
  1503.  
  1504. ;
  1505. ;    IBM double sided
  1506. ;    -- Track 0, Sector 1 last byte =1
  1507. ;
  1508. ST$ibm$ds:
  1509.     defstart    0E5h
  1510.     definline    1,512-1        ; last byte=0 for IBM single sided
  1511.     db    1
  1512.     defend
  1513.  
  1514.     page
  1515. ;
  1516. ;    Computes and sets the check SUM for the 1581 Drive Boot sector
  1517. ;
  1518.   if    format$1581
  1519. boot$check$sum:
  1520.     lxi    h,sect$buf+2
  1521.     lxi    d,sect$buf+2+lng$drv$cd+3
  1522.     mvi    b,0        ; start SUM =0
  1523. sum$next:
  1524.     mov    a,m
  1525.     add    b
  1526.     aci    0        ; add carry to LSB
  1527.     mov    b,a        ; return sum to B
  1528.     inx    h
  1529.     mov    a,l
  1530.     cmp    e
  1531.     jrnz    sum$next
  1532.     mov    a,h
  1533.     cmp    d
  1534.     jrnz    sum$next
  1535.     mov    m,b        ; save sum to end of buffer
  1536.     ret
  1537.   endif
  1538.  
  1539.     page
  1540. ;
  1541. ;        1541 and 1571 BOOT sector
  1542. ;    track 1 sector 0 sector definition (256 bytes)
  1543. ;
  1544. sect$1$0:
  1545.     db    'CBM',0,0,0,0,0,0    ; bytes 0 to 8
  1546.  
  1547.     @sei                ; byte 9
  1548.     @jsr    0ff84h
  1549.     @lda    3eh,#            ; set MMU to bank 0
  1550.     @sta    0ff00h            ; .. RAM and IO only
  1551.     @lda    0c3h,#
  1552.     @sta    0FFEEh
  1553.     @lda    08,#
  1554.     @sta    0FFEFh
  1555.     @lda    0,#
  1556.     @sta    0FFF0h
  1557.     @jmp    0ffd0h            ; swap to Z80 (RST1 location)
  1558.  
  1559.     page
  1560.  
  1561.   if    format$1581
  1562. CV        equ    drv$buf-$
  1563. my$trans$hi    set    high(my$trans+CV)
  1564. my$trans$low    set    low(my$trans+CV)
  1565. ;
  1566. ;
  1567. drv$code$1581:
  1568.     @sei
  1569.     @lda    VTRANS$TS        ; get old vector and save it
  1570.     @sta    CV+code$exit$2+1
  1571.     @lda    VTRANS$TS+1
  1572.     @sta    CV+code$exit$2+2
  1573.  
  1574.     @lda    my$trans$low,#        ; install new vector
  1575.     @sta    VTRANS$TS
  1576.     @lda    my$trans$hi,#
  1577.     @sta    VTRANS$TS+1
  1578.     @lda    buf$alc,#
  1579.     @sta    buf$use            ; protect this code
  1580.     @jmp    boot$ret
  1581.  
  1582. my$trans:
  1583.     @ldx    next$job
  1584.     @lda    jobs,x            ; get current job
  1585.     @cmp    80h,#            ; is it a READ
  1586.     @bne    code$exit$1
  1587.  
  1588.     @ldy    hdrjob            ; get index
  1589.  
  1590.     @ldx    hdrs+1,y        ; get logical sector
  1591.     @bne    code$exit$1
  1592.  
  1593.     @ldx    hdrs,y            ; get logical track
  1594.     @dex                ; was it one
  1595.     @bne    code$exit$1
  1596.  
  1597.     @ldx    40,#
  1598.     @stx    hdrs,y            ; change to logical TRK=40
  1599.     @ldx    5,#
  1600.     @stx    hdrs+1,y        ; change to logical SECT=5
  1601. code$exit$1:
  1602.     @lda    CV+code$exit$2+1
  1603.     @sta    VTRANS$TS        ; get old vector and save it
  1604.     @lda    CV+code$exit$2+2
  1605.     @sta    VTRANS$TS+1
  1606. code$exit$2:
  1607.     @jmp    0000
  1608.  
  1609. lng$drv$cd    equ    $-drv$code$1581
  1610.  
  1611.     page
  1612. ;
  1613. ;        1581 Directory Sector
  1614. ;
  1615. sect$39$1:
  1616.     db    40,3        ; directory track & sector (logical)
  1617.     db    44h,0        ; Disk versions and null flag
  1618.     db    'CP/M PLUS',0a0h,0a0h,0a0h
  1619.     db    0a0h,0a0h,0a0h,0a0h,0a0h,0a0h
  1620.     db    '80',0a0h,'3D',0a0h,0a0h
  1621.  
  1622.     page
  1623. ;        1581 Boot sector
  1624. ;    track 1 sector 0 sector definition (256 bytes)
  1625. ;
  1626. BB    equ    boot$code$02-$
  1627. ;
  1628. boot$1581$sector:
  1629.     db    'CBM',0,0,0,0,0,0    ; bytes 0 to 8
  1630.     @sei                ; (9)
  1631.     @jsr    0ff84h            ; (A-C)  reset I/O
  1632. ;
  1633. ;    Clear Bank 0 memory
  1634. ;
  1635.     @lda    3Fh,#            ; (D,E)   Enable RAM 0
  1636.     @sta    0FF00h            ; (F-11)
  1637.     @lda    10h,#            ; (12,13)   high byte of page pointer
  1638.     @sta    21h            ; (14,15)  save hiagh byte of pointer
  1639.     @lda    0,#            ; (16,17) low byte of page pointer
  1640.     @sta    20h            ; (18,19) save low byte of pointer
  1641.     @ldx    0EFh,#            ; (1A,1B) from 1000h to FEFFh
  1642.     @tay                ; (1Ch)   start at 0
  1643. era$loop:
  1644.     @sta    (20h),y            ; (1D,1E)
  1645.     @iny                ; (1Fh)
  1646.     @bne    era$loop        ; (20,21)
  1647.     @inc    21h            ; (22,23) point to next page
  1648.     @dex                ; (24)
  1649.     @bne    era$loop        ; (25,26)
  1650.     @sta    0FF00h            ; (27-29) re-enable kernal and I/O
  1651. ;
  1652. ;  load sectors that contain CP/M boot code (RAM version)
  1653. ;
  1654. ;    open command chanel to drive 8
  1655. ;
  1656.     @lda    15,#            ; (2A,2B)
  1657.     @ldx    8,#            ; (2C,2D)
  1658.     @tay                ; (2Eh)
  1659.     @jsr    0FFBAh            ; (2F-31) SETLFS
  1660.     @lda    0,#            ; (32,33)
  1661.     @tax                ; (34)
  1662.     @jsr    0FF68h            ; (35-37) SETBNK
  1663.     @lda    4,#            ; (38,39)
  1664.     @ldx    low(u0point+BB),#    ; (3A,3B)
  1665.     @ldy    high(u0point+BB),#    ; (3C,3D)
  1666. ;;;***
  1667.     @jsr    0FFBDh            ; (3E-40) SETNAM
  1668.     @jsr    0FFC0h            ; (41-43) OPEN
  1669. ;
  1670. ;    read sector 39-4
  1671. ;
  1672. dma0    equ    high(boot$code$80)
  1673.  
  1674.     @lda    39,#
  1675.     @ldx    4,#
  1676.     @ldy    dma0,#
  1677.     @jsr    rd$sector+BB
  1678. ;
  1679. ;    read sector 39-5
  1680. ;
  1681.     @lda    39,#
  1682.     @ldx    5,#
  1683.     @jsr    rd$sect$buf+BB
  1684. ;
  1685. ;    install JMP BOOT$CP/M
  1686. ;
  1687. low$start    equ    low(boot$code$80)
  1688. hi$start    equ    high(boot$code$80)
  1689.  
  1690.     @lda    0c3h,#
  1691.     @sta    0FFEEh
  1692.     @lda    low$start,#
  1693.     @sta    0FFEFh
  1694.     @lda    hi$start,#
  1695.     @sta    0FFF0h
  1696.     @lda    3eh,#            ; set MMU to bank 0 
  1697.     @sta    0ff00h            ; .. RAM and IO only
  1698.     @jmp    0FFD0h            ; swap to Z80 (RST1 location)
  1699.  
  1700. rd$sector:
  1701.     @sty    21h            ; hi byte of DMA adr
  1702. rd$sect$buf:
  1703.     @sta    trk02+BB
  1704.     @stx    sect02+BB
  1705.  
  1706.     @ldx    15,#            ; CMD chan #
  1707.     @jsr    0FFC9h            ; CHKOUT
  1708.     @ldy    6,#
  1709. sendf:
  1710.     @lda    R$cmd+BB,y
  1711.     @jsr    0FFD2h            ; CHROUT
  1712.     @dey
  1713.     @bne    sendf
  1714.  
  1715.     @jsr    0FFCCh            ; CLRCHN
  1716.     @bit    0DC0Dh            ; D1ICR
  1717.     @jsr    read$byte+BB        ; read status
  1718.     @ldx    2,#            ; 2 256 byte blocks/sector
  1719.     @ldy    0,#
  1720.     @sty    20h            ; low byte of DMA adr
  1721. rd$buff:
  1722.     @jsr    read$byte+BB
  1723.     @sta    (20h),y            ; at dma adr
  1724.     @iny
  1725.     @bne    rd$buff
  1726.     @inc    21h            ; advance DMA pointer
  1727.     @dex
  1728.     @bne    rd$buff
  1729.  
  1730.     @lda    0DD00h            ; D2PRA
  1731.     @and    0EFh,#            ;
  1732.     @sta    0DD00h            ; set clk hi
  1733.     @rts                ;
  1734.  
  1735. read$byte:
  1736.     @sei                ; disable interrupts
  1737.     @lda    0DD00h            ; D2PRA
  1738.     @eor    10h,#            ; clock bit
  1739.     @sta    0DD00h
  1740.     @lda    8,#
  1741. in$1:
  1742.     @bit    0DC0Dh            ; D1ICR
  1743.     @beq    in$1
  1744.     @lda    0DC0Ch            ; D1SDR
  1745.     @rts
  1746.  
  1747. R$cmd    equ    $-1
  1748.     db    1            ; count
  1749. sect02:    db    0            ; sector #
  1750. trk02:    db    0            ; track #
  1751.     db    0,'0'            ; read comand =00h
  1752.  
  1753. u0point:
  1754.     db    'U0',4Ch,0        ; Inquire Status
  1755.  
  1756.     page
  1757. ;
  1758. ZZ    equ    boot$code$80-$
  1759. LOADER$START:
  1760. ;
  1761. ;    setup the MMU for booting CP/M
  1762. ;
  1763.     lxi    sp,boot$stack
  1764.     mvi    a,3Fh
  1765.     sta    force$map
  1766. ;
  1767. ;    move bios and swap code into ram
  1768. ;
  1769.     lxi    h,bios$65$code+ZZ
  1770.     lxi    d,bios$02
  1771.     lxi    b,bios$size
  1772.     ldir
  1773.  
  1774.     lxi    h,swap$code
  1775.     lxi    d,enable$z80
  1776.     lxi    b,swap$size
  1777.     ldir
  1778.  
  1779.     mvi    a,RET            ; get z80 return adr
  1780.     sta    return$6502        ; store the RET
  1781. ;
  1782. ;    initilize the 8502 bios
  1783. ;
  1784.     xra    a                ; cleared by memory fill
  1785.     sta    vic$cmd
  1786.     call    enable$6502
  1787.  
  1788.     page
  1789. ;
  1790. ;    set MMU registers to a known state (for CP/M to use)
  1791. ;
  1792.     lxi    h,mmu$init$data+11-1    ; start at the End
  1793.     lxi    b,mmu$start+11-1    ; and work forward
  1794.     mvi    d,11            ; for all 11 bytes
  1795.  
  1796. INIT$MMU$CPM:
  1797.     mov    a,m            ; get table value
  1798.     outp    a            ; send to MMU
  1799.     dcx    h
  1800.     dcr    c
  1801.     dcr    d
  1802.     jrnz    INIT$MMU$CPM
  1803.                     ; re-enabled RAM bank 0 (no I/O)
  1804. ;
  1805. ;    set 80 column colors and set up Video memory with ASCII char set
  1806. ;
  1807.     mvi    a,26
  1808.     call    wait
  1809.     mvi    a,90h            ; foreground red background black
  1810.     outp    a
  1811.     mvi    a,85h            ; set attr and color
  1812.     sta    current$atr        ; ..for 80 column display
  1813.     mvi    a,green            ; set color
  1814.     sta    attr$40            ; ..for 40 column display
  1815.     call    install$ASCII        ; convert char set to true ASCII
  1816.  
  1817.  mvi    a,25            ; number of lines on the 40 col display
  1818.  sta    paint$size
  1819.  
  1820.     page
  1821. ;
  1822. ;    Let the user know we are booting CP/M
  1823. ;
  1824.     call    prt$msg$both
  1825.     db    -1            ; clear both screens
  1826.     rownum    1,10
  1827.     db    'BOOTING CP/M PLUS',0
  1828. ;
  1829. ;    point 40 column screen to CP/M screen area
  1830. ;
  1831.     lxi    b,VIC+24
  1832.     mvi    a,vic$screen*4/256+6    ; upper and lower case set (+6)
  1833.     outp    a
  1834. ;
  1835. ;
  1836. ;
  1837.     mvi    a,64
  1838.     sta    block$size        ; 64 dir entries/2K allocation
  1839.  
  1840.     lxi    h,DIR$PTRS+ZZ
  1841.     shld    ld$blk$ptr
  1842.     call    SCAN$DIR+ZZ        ; check 1st block
  1843.     call    SCAN$DIR+ZZ        ; check 2nd block (1K or 2K)
  1844.  
  1845.     lhld    block$ptrs        ; 1st pointer <>0 if file
  1846.     mov    a,h            ; name exist
  1847.     ora    l            ; pointer = 0
  1848.     jz    tell$user        ; yes, inform user there is a error
  1849.                     ; no, file FOUND, process it
  1850.     page
  1851. ;----------------------------
  1852. ; load 1st group to 1K buffer
  1853. ;----------------------------
  1854. FILE$FOUND:
  1855.     lxi    h,block$ptrs
  1856.     shld    ld$blk$ptr
  1857.     call    UPDATE$BUFFER+ZZ
  1858.  
  1859. ;--------------
  1860. ;GET$BOOT$INFO:
  1861. ;--------------
  1862.     lxi    h,block$buffer
  1863.     lxi    d,info$buffer
  1864.     lxi    b,12
  1865.     ldir
  1866.  
  1867.     call    prt$msg$both
  1868.     rownum    10,0
  1869.     db    0            ; end of string marker
  1870.     lxi    h,block$buffer+80h
  1871.     call    prt$hl$both
  1872.  
  1873.     lxi    h,block$buffer+256    ; set scan pointer
  1874.     shld    blk$unld$ptr
  1875.  
  1876.     page
  1877. ;---------------------------------
  1878. ; load keyboard data to system RAM
  1879. ;---------------------------------
  1880.     call    prt$msg$both
  1881.     rownum    3,12
  1882.     db    'DATA TABLES',0
  1883.     lhld    info$buffer+10
  1884.     shld    key$tbl            ; install keyboard translation pointer
  1885.  
  1886.     lxi    h,info$buffer+9
  1887.     call    GET$SIZE$ADR+ZZ        ; HL=adr DE=# (128 btye) records 
  1888.     shld    fun$tbl
  1889.  
  1890. LOAD$NEXT$FORWARD:
  1891.     call    LOAD$RECORD+ZZ        ; HL =load address (in and out)
  1892.     lxi    d,128            ; move pointer back to buf start
  1893.     dad    d
  1894.     jrnz    LOAD$NEXT$FORWARD
  1895.  
  1896.     page
  1897. ;-----------------------------------
  1898. ; transfer CP/M code to load address
  1899. ;-----------------------------------
  1900.     call    prt$msg$both
  1901.     rownum    4,12
  1902.     db    'COMMON CODE',0
  1903.     lxi    h,info$buffer+1        ; load common code
  1904.     call    LOAD$REVERSE+ZZ
  1905.  
  1906.     call    prt$msg$both
  1907.     rownum    5,12
  1908.     db    'BANKED CODE',0
  1909.     lxi    h,info$buffer+3        ; load banked code
  1910.     call    LOAD$REVERSE+ZZ
  1911.  
  1912.     page
  1913. ;---------------------------
  1914. ; now load the bios8502 code
  1915. ;---------------------------
  1916.     call    prt$msg$both
  1917.     rownum    6,12
  1918.     db    'BIOS8502 CODE',0
  1919.     lxi    h,info$buffer+7        ; load banked code
  1920.     call    LOAD$REVERSE+ZZ
  1921.  
  1922.     lda    info$buffer+7        ; get code size (in 256 byte blocks)
  1923.     mov    b,a
  1924.     lda    info$buffer+6        ; get page pointer (pointer to end)
  1925.     sub    b            ; find the start
  1926.                     ; install jmp adr to BIOS02
  1927.     sta    return$z80+2        ; (jmp) (low) (high)
  1928.     xra    a
  1929.     sta    return$z80+1        ; (jmp) (low) (high)
  1930. ;------------------------------------
  1931. ; now let's start executing CP/M Plus
  1932. ;------------------------------------
  1933.     lhld    info$buffer+4        ; get start address
  1934.     pchl                ; transfer control to CP/M
  1935.  
  1936.     page
  1937. ;-------------;
  1938. ; SUBROUTINES ;
  1939. ;-------------;
  1940. ;    scan buffer for CPM+.SYS file
  1941. ;
  1942. SCAN$DIR:
  1943.     call    UPDATE$BUFFER+ZZ    ; returns HL=block$buffer
  1944.     mvi    a,64            ; 64 for 2K block
  1945.                     ; ..number director entries/sector
  1946. CHECK$NEXT:
  1947.     shld    @dma
  1948.     lxi    d,sys$name        ; point to system name
  1949.     push    psw
  1950.     call    name$match+ZZ
  1951.     cz    FOUND+ZZ
  1952.     pop    psw
  1953.     lhld    @dma            ; get current buffer pointer
  1954.     lxi    d,32
  1955.     dad    d
  1956.     dcr    a
  1957.     jrnz    CHECK$NEXT
  1958.     ret
  1959.  
  1960.     page
  1961. ;
  1962. ;
  1963. ;
  1964. name$match:
  1965.     mvi    b,12
  1966.     xchg
  1967. match$next:
  1968.     ldax    d
  1969.     ani    7fh
  1970.     cmp    m
  1971.     rnz
  1972.     inx    h
  1973.     inx    d
  1974.     djnz    match$next
  1975.     ldax    d
  1976.     sta    ext$num
  1977.     xra    a
  1978.     ret
  1979.  
  1980.     page
  1981. ;----------------------------
  1982. ; save CPM+.SYS group numbers
  1983. ;----------------------------
  1984. ;    found a dir entry that has the right name
  1985. ;    add block pointers to list
  1986. ;
  1987. FOUND:
  1988.     lxi    d,block$ptrs        ; point to start of block pointers
  1989.     lda    ext$num
  1990.     ora    a
  1991.     jrz    EXT$NUM$0
  1992.  
  1993.     lxi    d,block$ptrs+16
  1994.     dcr    a
  1995.     jnz    ext$error
  1996.  
  1997. EXT$NUM$0:
  1998.     lhld    @dma            ; get current pointer
  1999.  
  2000.     lxi    b,16            ; number of bytes to move
  2001.     dad    b            ; also advance to block pointers
  2002.     ldir
  2003.  
  2004.     lhld    block$ptrs
  2005.     mov    a,h
  2006.     ora    l            ; 1st block present ?
  2007.     rz                ; no, read more dir.
  2008.  
  2009.     lhld    block$ptrs+14        ; extent full?
  2010.     mov    a,h
  2011.     ora    l
  2012.     jrz    GO$BOOT$IT        ; no, this is it then
  2013.  
  2014.     lhld    block$ptrs+16        ; 2nd block present ?
  2015.     mov    a,h
  2016.     ora    l
  2017.     rz                ; no, read more dir.
  2018.  
  2019. GO$BOOT$IT:
  2020.     jmp    FILE$FOUND+ZZ        ; two parms are still on the stack
  2021.                     ; but at this point who cares
  2022.     page
  2023. ;
  2024. ;
  2025. ;
  2026. LOAD$REVERSE:
  2027.     call    GET$SIZE$ADR+ZZ        ; HL=adr DE=# records (128 byte)
  2028.  
  2029. LOAD$NEXT:
  2030.     lxi    d,-128            ; move pointer back to buf start
  2031.     dad    d
  2032.     call    LOAD$RECORD+ZZ
  2033.     jrnz    LOAD$NEXT
  2034.     ret
  2035. ;
  2036. ;
  2037. ;
  2038. GET$SIZE$ADR:
  2039.     mov    e,m
  2040.     mvi    d,0            ; get buffer size (#256 byte)
  2041.     mov    a,e            ; get size to A
  2042.     ora    a
  2043.     jz    table$error        ; exit if count=0
  2044.  
  2045.     xchg
  2046.     dad    h            ; HL=#128 byte blocks
  2047.     shld    load$count
  2048.     xchg
  2049.     dcx    h
  2050.     mov    h,m
  2051.     mvi    l,0
  2052.     ret
  2053.  
  2054.     page
  2055. ;
  2056. ;
  2057. ;
  2058. LOAD$RECORD:
  2059.     push    h            ; save to address
  2060.     lxi    h,block$buffer+2048
  2061.     xchg
  2062.     lhld    blk$unld$ptr
  2063.     call    cmp$hl$de
  2064.     cz    UPDATE$BUFFER+ZZ
  2065.     xchg
  2066.     lxi    h,128
  2067.     dad    d
  2068.     shld    blk$unld$ptr
  2069.     pop    h            ; recover save address
  2070.     push    h
  2071.     xchg                ; HL=source  DE=dest.
  2072.     lxi    b,128            ; size of move
  2073.     ldir
  2074.     lhld    load$count
  2075.     dcx    h
  2076.     shld    load$count
  2077.     mov    a,l
  2078.     ora    h
  2079.     pop    h
  2080.     ret
  2081.  
  2082.     page
  2083. ;
  2084. ;
  2085. ;
  2086. UPDATE$BUFFER:
  2087.     lxi    h,block$buffer
  2088.     shld    @dma
  2089.     push    h            ; save block buffer adr for ret
  2090.     lhld    ld$blk$ptr        ; get the current block pointer
  2091.     mov    e,m            ; get LSB of block pointer
  2092.     inx    h            ; advance pointer
  2093.     mov    d,m            ; zero MSB of block pointer
  2094.     inx    h
  2095.     shld    ld$blk$ptr
  2096.     xchg                ; get block number to HL
  2097. ;
  2098. ;    read the block pointed to by the HL
  2099. ;    into the data buffer
  2100. ;
  2101.     dad    h            ; 2X (1k blocks)
  2102.     dad    h            ; 4x (512 byte blocks)
  2103.     push    h
  2104.     call    read$1K+ZZ        ; read 1st 1K block
  2105.     lda    @dma+1
  2106.     adi    4
  2107.     sta    @dma+1
  2108.     pop    h
  2109.     inx    h
  2110.     inx    h
  2111.     call    read$1K+ZZ        ; read 2nd 1K block
  2112.     pop    h            ; recover block buffer adr
  2113.     ret
  2114. ;
  2115. ;    convert block number (in HL) to sector and track
  2116. ;
  2117. read$1K:
  2118.     mvi    a,2
  2119.     sta    F$rd$count+BZ        ; 
  2120.     lxi    d,10            ; 10 sectors per side
  2121.     lxi    b,-1
  2122. compute$trk:
  2123.     inx    b
  2124.     ora    a            ; clear the carry
  2125.     dsbc    d            ; negative if <10
  2126.     jrnc    compute$trk        ; jump if still positive >=10
  2127.     dad    d            ; add it back
  2128.     mov    a,c            ; get trk # (0 to 159)
  2129.     cpi    39*2
  2130.     jrc    bump$trk
  2131.     inr    a
  2132.     inr    c
  2133. bump$trk:
  2134.     rrc                ; move bit 0 to carry
  2135.     mvi    a,1            ; sector numbers are 1 to 10
  2136.     jrnc    side$0
  2137.     mvi    a,11            ; or 11 to 20
  2138. side$0:
  2139.     add    l            ; get sector # (0-9)
  2140.     sta    VIC$sect
  2141.     mov    a,c            ; get trk # (0 to 159)
  2142.     rar                ; divide by 2 (carry was cleared)
  2143.     sta    VIC$trk
  2144.     jmp    read$sector        ; read the sector to the buffer
  2145.  
  2146. DIR$PTRS:
  2147.     dw    0,1
  2148.  
  2149.     page
  2150. ;
  2151. ;
  2152. ; **** THIS IS THE COMMAND LOOP ****
  2153. ;
  2154. BZ    equ    bios$02-$    ; BIOS BIAS
  2155.  
  2156. ;
  2157. bios$65$code:
  2158.     @sei
  2159.     @lda    0,#        ;-K
  2160.     @sta    vic$data    ;-K
  2161.     @JSR    VICIO+BZ    ;-K  go find and do requested operation
  2162. CMDLP:
  2163.     @sei
  2164.     @lda    3eh,#        ;?K  set up Z80 memory map as required
  2165.     @sta    force$map    ;-K
  2166.     @jmp    enable$z80    ;-K
  2167.  
  2168. ;
  2169. ; **** IO COMMAND DISPATCH ROUTINE ****
  2170. ;
  2171. VICIO:
  2172.     @CLD            ;-K  clear to binary mode
  2173.     @LDA    vic$cmd        ;-K  get the command
  2174.     @bne    read        ;-K   0=initialize
  2175.                 ;     1=read
  2176.     page
  2177. ;
  2178. ;
  2179. ;
  2180. initilize:            ;   initialize the 8502
  2181.     @ldx    0,#        ;-K
  2182.     @stx    force$map    ;-K  enable the kernal
  2183.     @stx    VIC+26        ;+K  turn off VIC interrupts
  2184.  
  2185.     @ldx    low(irqs+BZ),#
  2186.     @ldy    high(irqs+BZ),#
  2187.     @stx    314h        ;+K  IRQ vector
  2188.     @sty    315h
  2189.     @stx    316h        ;+K  BRK vector
  2190.     @sty    317h
  2191.     @stx    318h        ;+K  NMI vector
  2192.     @sty    319h
  2193. ;
  2194. ; **** OPEN DISK COMMAND CHANNEL ****
  2195. ;
  2196.     @LDA    cmdchn,#    ;+K
  2197.     @CLC            ;+K
  2198.     @JSR    K$close        ;+K
  2199.     @LDA    cmdchn,#    ;+K
  2200.     @LDX    8,#        ;+K
  2201.     @TAY            ;+K
  2202.     @JSR    K$setlfs    ;+K
  2203.  
  2204.     @LDA    0,#        ;+K
  2205.     @TAX            ;+K
  2206.     @JSR    K$set$bnk    ;+K
  2207.  
  2208.     @LDA    4,#            ;+K
  2209.     @LDX    low(U0PT+BZ),#        ;+K
  2210.     @LDY    high(U0PT+BZ),#        ;+K
  2211.     @JSR    K$setnam        ;+K
  2212.     @JSR    K$open            ;+K
  2213.     @bcs    misdsk
  2214.  
  2215.     @jsr    K$readst
  2216.     @ROL    A        ;+K  GET MSB TO CARRY
  2217.     @BCS    MISDSK        ;+K  DEVICE MISSING IF CARRY SET
  2218.     @rts
  2219.  
  2220. ;
  2221. ;  * DEVICE MISSING, CLEAN UP ERROR *
  2222. ;
  2223. MISDSK:
  2224.     @LDA    00fh,#        ;+K  SET ERROR CODE
  2225.     @skip2
  2226.  
  2227. fst$error:
  2228.     @lda    0dh,#        ;?K
  2229.     @skip2
  2230.  
  2231. DISK$CHANGED:
  2232.     @lda    0FFh,#        ;?K
  2233.     @STA    vic$data    ;?K  writes to RAM under ROM
  2234.     @JMP    CMDLP+BZ    ;?K
  2235.  
  2236.     PAGE
  2237. ;
  2238. ; **** DISK SECTOR READ ****
  2239. ;
  2240. READ:
  2241.     @ldx    0,#        ;-K get read command (side 0)
  2242.     @lda    VIC$sect
  2243.     @cmp    11,#
  2244.     @bmi    on$side$0
  2245.     @ldx    10h,#        ; get read command (side 1)
  2246.     @sbc    10,#        ; remove bias of 10
  2247. on$side$0:
  2248.     @stx    F$cmd+BZ
  2249.     @sta    F$rd$sect+BZ
  2250.     @lda    VIC$trk
  2251.     @sta    F$rd$trk+BZ
  2252.  
  2253.     @lda    @dma        ;-K
  2254.     @sta    pointer        ;-K
  2255.     @lda    @dma+1        ;-K
  2256.     @sta    pointer+1    ;-K
  2257.     @lda    0,#        ;-K
  2258.     @sta    force$map    ;-K
  2259.     @ldx    cmdchn,#    ;+K
  2260.     @jsr    K$chkout    ;+K
  2261.     @bcs    fst$error    ;+K
  2262.     @ldy    Fcmd$lng,#    ;+K
  2263. sendf$rd:
  2264.     @lda    Fcmd$buf+BZ-1,y    ;+K
  2265.     @jsr    K$chrout    ;+K
  2266.     @dey            ;+K
  2267.     @bne    sendf$rd    ;+K
  2268.     @jsr    K$clrchn    ;+K
  2269.     @bit    D1ICR        ;+K
  2270.     @ldx    F$rd$count+BZ    ;+K
  2271. rd$sect:
  2272.     @sei            ;+K
  2273.     @jsr    rd$byte+BZ    ;+K
  2274.     @and    0eh,#        ;+K  mask off error bits
  2275.     @bne    fst$error    ;+K
  2276.     @ldy    0,#        ;+K start index at buffer start
  2277.     @jsr    read$256+BZ    ;+K read 1st 256 byte block
  2278.     @jsr    read$256+BZ    ;+K read 2nd 256 byte block
  2279.     @dex            ;+K
  2280.     @bne    rd$sect        ;+K
  2281. clk$hi:
  2282.     @lda    d2pra        ;+K
  2283.     @and    0ffh-clk$bit,#    ;+K
  2284.     @sta    d2pra        ;+K
  2285.     @rts            ;+K
  2286.  
  2287.     PAGE
  2288. ;
  2289. ;
  2290. read$256:
  2291.     @jsr    rd$byte+BZ    ;+K
  2292.     @sta    (pointer),y    ;+K
  2293.     @iny            ;+K
  2294.     @bne    read$256    ;+K
  2295.     @inc    pointer+1    ;+K
  2296.     @rts
  2297. ;
  2298. rd$byte:
  2299.     @lda    d2pra
  2300.     @eor    clk$bit,#
  2301.     @sta    d2pra
  2302.     @lda    8,#
  2303. rd$1:
  2304.     @bit    d1icr
  2305.     @beq    rd$1
  2306.     @lda    d1sdr
  2307.     @rts
  2308.  
  2309.     page
  2310. ;
  2311. ;    handle all interrupts in BIOS 8502 (throw them away)
  2312. ;
  2313. irqs:
  2314.     @lda    CIA$1+int$ctrl
  2315.     @lda    CIA$2+int$ctrl
  2316.     @lda    0fh,#
  2317.     @sta    VIC+25
  2318. ;
  2319. ;    system saved memory config, Y, X and A before getting here
  2320. ;
  2321.     @pla
  2322.     @sta    force$map
  2323.     @pla
  2324.     @tay
  2325.     @pla
  2326.     @tax
  2327.     @pla
  2328.     @rti
  2329.  
  2330.     PAGE
  2331.  
  2332. F$cmd$buf:
  2333. F$rd$count:    db    2        ; 5
  2334. F$rd$sect:    db    0        ; 4 filled in
  2335. F$rd$trk:    db    0        ; 3 filled in
  2336. F$cmd:        db    0        ; 2 read=0
  2337.         db    '0'
  2338. U0PT:        db    'U'        ; 1
  2339. Fcmd$lng    equ    $-F$cmd$buf
  2340.         db    '0',4Ch,0    ; reset disk change status (open)
  2341. bios$size    equ    $-bios$65$code
  2342. loader$size    equ    $-loader$start
  2343.   if    loader$size > 2048
  2344.     ' loader size error'
  2345.   endif
  2346.   endif
  2347.  
  2348.     page
  2349.  
  2350. endofcode:
  2351. ramalc    set    endofcode
  2352.  
  2353. define    top$choice,1        ; top row of these choices
  2354. define    bottom$choice,1        ; bottom row of these choices
  2355. define    current$choice,1    ; current row of these choices
  2356. define    fmt$drv,1        ; drive to do format on
  2357. define    fmt$tbl$ptr,2        ; pointer to current format table
  2358. define    save$buffer,80*2    ; save a row here
  2359. define    scrsiz,1        ; current screen size flag
  2360. define    temp,1            ; miscellaneous            
  2361. define    temp$ptr,2        ; temporary ptr for moving tables
  2362. define    read$count,1        ; # of characters in saved line
  2363.  
  2364. define    top$of$stack,300
  2365. define    stack,0
  2366. define    sect$buf,1024        ; largest sector is 1024
  2367.  
  2368.     end
  2369.