home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / KAYPRO / IOCAPKP.LBR / I_OCAPKP.AQM / I_OCAPKP.ASM
Assembly Source File  |  2000-06-30  |  21KB  |  827 lines

  1. ;       I/O-CAP.ASM Version 1.0 as of September 13, 1981
  2. ;                  By: Kelly Smith, CP/M-Net
  3. ;
  4. ; Version 1.0: Initial release by Kelly Smith
  5. ; Version 1.1: modified size for LF
  6. ;               added Apple ][ equates
  7. ; by Bill McGee (613-828-9130)  
  8. ; Version for Kaypros: Added code for Kaypros to intercept the
  9. ;             control-Z that clears screen, and change it to
  10. ;        1Eh (HOME cursor) followed by 17h (Clear to end
  11. ;        of screen) on the disk output.  Also moved the
  12. ;        QUIT check to the conin routine so that option
  13. ;        would still work.          02/13/86
  14. ;         by Dave Shuman (317-778-2810)
  15. ;      Note:  Please  append  any  changes to I/O-CAP  with  a 
  16. ; 'Version  Log' and change comments (your name would be  nice 
  17. ; too) top-down from the initial Version 1.0 release.
  18. ;  
  19. ;      Running  I/O-CAP  (the  first time) will  relocate  the 
  20. ; CONIN,  and CONOUT jump vectors to high memory and then  ALL 
  21. ; subsequent   input  or  output  (depending  on   conditional 
  22. ; assembly  switches)  will  be  buffered  (16  sectors)   for  
  23. ; eventual  output  to  disk with a filename and type   called  
  24. ; USER.LOG.  This file will then be updated as long as I/O-CAP 
  25. ; is   active  in  the system.   Note:   I/O-CAP may  be  made 
  26. ; inactive  by just type I/O-CAP again,  to toggle it off  (or 
  27. ; on).
  28. ;      I/O-CAP   requires   an  unusually  LARGE   amount   of 
  29. ; relocation  memory,  because it must buffer the entire  CP/M 
  30. ; system image to high memory to save and restore all CCP  and 
  31. ; BDOS pointers as it captures each 16 sector block of console 
  32. ; input or output...crude,  but the ONLY other wait to do this 
  33. ; would  be to  'hot-patch' the CCP and BDOS 'on-the-fly'  and 
  34. ; that  get's  just   a   bit  gruesome  from   a    UNIVERSAL   
  35. ; applications  standpoint...It's much easier to just SYSGEN a 
  36. ; smaller   CP/M  system  than your actual  maximum  available 
  37. ; memory,   and  then have I/O-CAP relocate itself above  your 
  38. ; BIOS.  If  anyone has a better way to do this  WITHOUT  this 
  39. ; relocation  crap,  I  would be eager to see it...I just  got 
  40. ; frustrated  with  trying to figure out what CP/M  was  doing 
  41. ; internally  to pursue it further...local  stacks,  pointers, 
  42. ; etc.,...ARGH...so I took the easy way out.
  43. ;      Thanks  to  Mike Karas for discovering  the  BDOS  CALL 
  44. ; contention  problems  when the BDOS stack was not saved  and 
  45. ; restored when saving the console buffer to disk.
  46. ;                       - Applications -
  47. ; (1)   Don't have a printer,  and want 'Hard Copy' of a  user 
  48. ; dialog  with the system?  Use I/O-CAP to creat it as a  disk 
  49. ; file...for  instance,  when making patches into  'uncertain' 
  50. ; areas of the system with DDT (or SID,  or whatever) you  can 
  51. ; keep  a  running  history on disk of the patches  AND  their 
  52. ; effects.
  53. ; (2)   Need to show example of console dialog for an  article 
  54. ; or book and you don't want to 'hand type' it in? Use I/O-CAP 
  55. ; to creat the examples for you,  and edit the dialog to  suit 
  56. ; your needs.
  57. ; (3)   Need to know all the events in 'history form'  leading 
  58. ; to  some bizarre system blow-up?  Use I/O-CAP to record that 
  59. ; history  for you (but only if the blow-up is recoverable  by 
  60. ; NOT COLD BOOTING the system).
  61. ; (4)   Want  to  (secretly) monitor the activities  of  other 
  62. ; users  of  the system?  Use I/O-CAP to record  user  console 
  63. ; input,  and check in from time-to-time to look at the system 
  64. ; activity.  Used  in  conjunction with BYE on a  remote  CP/M 
  65. ; system,  you can finally figure-out how that 'twit' clobbers 
  66. ; your  system from 3000 miles away...and NOT fill a room full 
  67. ; of  paper by logging all input to your  printer.  Note:  Run 
  68. ; I/O-CAP first,  then BYE.COM to 'grab' the vectors set-up by 
  69. ; the I/O-CAP program.The capture of incoming data will appear 
  70. ; to be transparent to the user,  with a slight pause when  it 
  71. ; updates the USER.LOG file...but this only happens every 2048 
  72. ; character entrys, so it should generally go un-noticed.
  73. ;                      - Using I/O-CAP -
  74. ;      Examine  the various conditional assembly switches  and 
  75. ; set  TRUE or FALSE depending on your requirements with  your 
  76. ; editor  (ED.COM).  Then assemble with ASM.COM (or  MAC.COM), 
  77. ; load it to creat a .COM file and then run.  The  conditional 
  78. ; assembly switches allow the following options:
  79. ; (1)   DEBUG  -  I/O-CAP runs at 8000 Hex...about  right  for 
  80. ; most small applications programs that use memory from 100 to 
  81. ; 7FFF Hex in a 56K CP/M system.  If FALSE, I/O-CAP runs above 
  82. ; a  48K  CP/M  system (C800 Hex),  with  no  restrictions  on 
  83. ; applications programs.
  84. ; (2)  QUIET - If FALSE, rings the console bell just before it 
  85. ; writes 2048 bytes of captured console INPUT or OUTPUT.
  86. ; (3)   ERRDISP - If TRUE,  I/O-CAP will display an  'OOPS...' 
  87. ; message on the console if the disk or directory is full.
  88. ; (4)   INPUT  - If  TRUE,  only  console  keyboard  INPUT  is 
  89. ; captured. Note: OUTPUT must be FALSE if INPUT is TRUE.
  90. ; (5)   OUTPUT  - If  TRUE,  both console keyboard  INPUT  and 
  91. ; OUTPUT will be captured...uses 'gobs' of disk storage if you 
  92. ; let I/O-CAP run for any length of time.  Note: INPUT must be 
  93. ; FALSE if OUTPUT is TRUE.
  94. ; (6) QUIT - If TRUE, when a Control-Z and Carriage Return are 
  95. ; entered  at  the console keyboard,  I/O-CAP will append  the 
  96. ; USER.LOG file with a physical end-of-file (i.e.,  no further 
  97. ; data  will  be  displayed in USER.LOG  although  it  may  be 
  98. ; physically appended to it)...Note: You must type I/O-CAP<cr> 
  99. ; to CLOSE the current USER.LOG,  and reset the disk to normal 
  100. ; R/W  status.  Failure  to  do so will result in a  R/O  BDOS 
  101. ; Error  on  any subsequent attempt to write to  the  disk  by 
  102. ; means other than I/O-CAP.
  103. ; (7) SYSLOG - If TRUE,  creates USER.LOG as a $SYS (invisible 
  104. ; to  directory)  file,  so that 'secrecy' is maintained  when 
  105. ; capturing  user input...be sure and rename USER.LOG to  your 
  106. ; 'private' name, or replace the TYPE command with MLIST.COM.
  107. ;      Please  send any changes,  'bug' reports,  suggestions, 
  108. ; comments,  gripes or bitches to the CP/M-Net  system,  (805) 
  109. ; 527-9321...have  fun with this program.  It's in the  public 
  110. ; domain, but NOT TO BE USED for COMMERCIAL BENEFIT.
  111. ;                                    Best regards,
  112. ;                                    Kelly Smith, CP/M-Net
  113. ;
  114. ;
  115. ; define TRUE/FALSE assembly parameters
  116. ;
  117. true    equ    -1    ; define TRUE
  118. false    equ    not true; define FALSE
  119. debug    equ    true    ; define DEBUG
  120. quiet    equ    false    ; define QUIET (ring BELL, if not true)
  121. errdisp    equ    true    ; define ERRDISP (display errors, if true)
  122. quit    equ    true    ; define QUIT (EOF, if Control-Z found)
  123. syslog    equ    false    ; define SYSLOG (make USER.LOG a $SYS file)
  124. KAYPRO    equ    true    ; for Kaypro with ^Z for clear screen
  125. APPLE    equ    false    ; for Apple ][ with 56K Softcard CP/M
  126. ; >>> Note: only one of the following two assembly switches may be true <<<
  127. ;
  128. input    equ    false    ; define INPUT (I/O-CAP console input)
  129. output    equ    true    ; define OUTPUT (I/O-CAP console output)
  130. ;
  131.     if    DEBUG
  132. dest    equ    08000h    ; running location of code, was 08000h KayPro
  133. ;                         LOCATED FOR KAYPRO II BELOW EX1.4 IN TPA
  134.     endif        ; DEBUG
  135.  
  136.     if    not DEBUG
  137. dest    equ    0c800h    ; running location of code
  138.     endif        ; DEBUG
  139. ;
  140. ; BDOS entry point and function codes
  141. base    equ    0    ; <<-- set to offset of CP/M for your
  142.             ; system, standard systems are 0, some
  143.             ; 'alternate' systems are 4200H
  144. bdos    equ    base+5
  145. resdsk    equ    13    ; reset disk system
  146. offc    equ    15    ; open file
  147. cffc    equ    16    ; close file
  148. dffc    equ    19    ; delete file
  149. rrfc    equ    20    ; read record
  150. wrfc    equ    21    ; write record
  151. mffc    equ    22    ; make file
  152. sdma    equ    26    ; set dma address
  153. ; secondary FCB field definitions
  154. fn    equ    1    ; file name field (rel)
  155. ft    equ    9    ; file type field (rel)
  156. ex    equ    12    ; file extent field (rel)
  157. frc    equ    15    ; file record count (rel)
  158. nr    equ    32    ; next record field (rel)
  159. ; ASCII control characters
  160. cr    equ    0dh    ; carriage return
  161. lf    equ    0ah    ; line feed
  162. bel    equ    07h    ; bell signal
  163. ;
  164. ; This  program runs up in high ram.  It gets there,  by being 
  165. ; moved  there  when 'I/O-CAP'  is typed. Change the following 
  166. ; equate to an area in your high memory where this program may 
  167. ; patch itself in.  Approximate memory requirements:  2k bytes 
  168. ; or more,  depending upon the options selected.  a marker has 
  169. ; been  placed  at  the  end to deliberately  print  an  error 
  170. ; message  during  assembly in order to determine  the  actual 
  171. ; ending  address of the program.  The error message will  not 
  172. ; affect the assembly.  make sure you have memory available up 
  173. ; to the address shown.
  174. ;
  175.     org    base+100h
  176. ;
  177. ; Move 'I/O-CAP' program up to high ram and jump to it
  178. ;
  179.     lxi    h,0    ; save old stack pointer
  180.     dad    sp
  181.     shld    oldstk
  182.     lxi    sp,stack; make a new stack pointer
  183.     lxi    h,tbuf    ; set pointer to tbuf
  184.     shld    ptr
  185.     lxi    h,0    ; set size = 0
  186.     shld    size
  187.     lhld    base+1    ; get BIOS pointer
  188.     lxi    d,5    ; add bias to console status address
  189.     dad    d
  190.     mov    d,m    ; save in [d]
  191.     lhld    newjtbl+1    ; see if vector addresses active
  192.     mov    a,h    ; been patched by previous execution?
  193.     cmp    d
  194.     jz    unpatch    ; un-patch, if so
  195.     lxi    b,pend-start+1        ; number of bytes to move
  196.     lxi    h,dest+pend-start+1    ; end of moved code
  197.     lxi    d,source+pend-start    ; end of source code
  198. ;
  199. mvlp    ldax    d    ; get byte
  200.     dcx    h    ; bump pointers
  201.     mov    m,a    ; new home
  202.     dcx    d
  203.     dcx    b    ; bump byte count
  204.     mov    a,b    ; check if zero
  205.     ora    c
  206.     jnz    mvlp    ; if not, do some more
  207.     pchl        ; do it, to it...
  208. ;
  209. source    equ    $    ; boundary memory marker
  210. ;
  211. offset    equ    dest-source ; relocation amount
  212. ;
  213. ; The following code gets moved to high ram located at "dest", 
  214. ; where it is executed. C A U T I O N :  if modifying anything 
  215. ; in this program from here on: ALL labels must be of the form:
  216. ;
  217. ; label    equ    $+offset        
  218. ;
  219. ; ...in   order   that  the  relocation  to  high   ram   work 
  220. ; successfully.   Forgetting  to specify '$+offset' will cause 
  221. ; the program to jmp into whatever is currently in low memory, 
  222. ; with unpredictable results.  Be careful....        
  223. ;
  224. start    equ    $+offset
  225. ;
  226. ; patch in the new jump table (saving the old)
  227. ;
  228. patch    equ    $+offset
  229.     call    tbladdr        ; calc [hl] =  CP/M jmp table
  230.     lxi    d,vcstat    ; point to save location
  231.     call    move        ; move it
  232. ;
  233. ; now move new jump table to CP/M
  234. ;
  235.     call    tbladdr        ; calc [hl] = CP/M's jmp table
  236.     xchg            ; move to de
  237.     lxi    h,newjtbl    ; point to new
  238.     call    move        ; move it
  239.     lxi    h,active$message
  240.     call    msgout
  241.     lhld    oldstk        ; get old CP/M stack pointer
  242.     sphl
  243.     ret
  244. ;
  245. unpatch equ    $+offset
  246.     call    reset    ; reset disk in case it's R/O
  247.     lxi    h,inactive$message
  248.     call    msgout
  249.     call    tbladdr        ; [hl] = CP/M's jmp table
  250.     xchg            ; move to de
  251.     lxi    h,vcstat    ; get saved table
  252.     call    move        ; move orig back
  253.     lhld    oldstk        ; get old CP/M stack pointer
  254.     sphl
  255.     ret            
  256. ;
  257. ; calculate [hl] = CP/M's jump table, [b] = length
  258. ;
  259. tbladdr equ    $+offset
  260.     lhld    base+1        ; get BIOS pointer
  261.     inx    h        ; ..skip
  262.     inx    h        ; ..to
  263.     inx    h        ; ..console status
  264.     mvi    b,9        ; move console jump vectors
  265.     ret
  266. ;
  267. ; move [hl] to [de], length in [b]
  268. ;
  269. move    equ    $+offset
  270.     mov    a,m        ; get a byte
  271.     stax    d        ; put at new home
  272.     inx    d        ; bump pointers
  273.     inx    h
  274.     dcr    b        ; decrement byte count
  275.     jnz    move        ; if more, do it
  276.     ret            ; if not, return
  277. ;
  278. ; move [hl] to [de], length in [bc]
  279. ;
  280. movecpm    equ    $+offset
  281.     mov    a,m        ; get a byte
  282.     stax    d        ; put at new home
  283.     inx    d        ; bump pointers
  284.     inx    h
  285.     dcx    b        ; decrement byte count
  286.     mov    a,b
  287.     ora    c
  288.     jnz    movecpm        ; if more, do it
  289.     ret            ; if not, return
  290. ;
  291. msgout    equ    $+offset
  292.     mov    a,m        ; get character from message string
  293.     ora    a        ; all of string displayed?
  294.     rz            ; return, if so
  295.     inx    h        ; no, bump pointer for next character
  296.     mov    c,a        ; pass character to 'old' BIOS vector
  297.     call    conout
  298.     jmp    msgout        ; display next character in message string
  299. ;
  300. ; This area is used for vectoring calls to the user's CBIOS, 
  301. ; but saving the registers first in case they are destroyed.
  302. ;
  303. constat equ    $+offset
  304.     push    b
  305.     push    d
  306.     push    h
  307.     call    vcstat
  308.     pop    h
  309.     pop    d
  310.     pop    b
  311.     ret
  312. ;
  313. conin    equ    $+offset
  314.     push    b
  315.     push    d
  316.     push    h
  317.     call    vcin
  318.  
  319.     if    QUIT
  320.     cpi    'Z'-40h    ; control-Z?
  321.     jnz    quitin    ; go ahead if not
  322.     lxi    h,0    ; save old stack pointer
  323.     dad    sp
  324.     shld    oldstk
  325.     lxi    sp,stack; make a new stack pointer
  326.     push    psw    ; save [a] on stack
  327.     call    wtb    ; now write buffer and close it
  328.     pop    psw    ; retrieve console input from stack
  329.     lhld    oldstk    ; get old CP/M stack pointer
  330.     sphl
  331. quitin:    equ    $+offset
  332.     endif        ; QUIT
  333.  
  334.     pop    h
  335.     pop    d
  336.     pop    b
  337.     ret
  338. ;
  339. conout    equ    $+offset
  340.     push    b
  341.     push    d
  342.     push    h
  343.     call    vcout
  344.     pop    h
  345.     pop    d
  346.     pop    b
  347.     ret
  348. ;
  349. ; This  is  the jump table which is copied on top of  the  one 
  350. ; pointed to by location 1 in CP/M
  351. ;
  352. newjtbl equ    $+offset
  353.     jmp    constat    ; console status test
  354.  
  355.     if    INPUT
  356.     jmp    capture    ; console input I/O-CAP routine
  357.     endif        ; INPUT
  358.  
  359.     if    OUTPUT
  360.     jmp    conin    ; console input routine
  361.     endif        ; OUTPUT
  362.  
  363.     if    INPUT
  364.     jmp    conout    ; console output routine
  365.     endif        ; INPUT
  366.  
  367.     if    OUTPUT
  368.     jmp    capture    ; console I/O-CAP output routine
  369.     endif        ; OUTPUT
  370.  
  371. ;
  372. capture    equ    $+offset
  373.     push    h
  374.     push    d
  375.     push    b
  376.     lxi    h,0    ; save old stack pointer
  377.     dad    sp
  378.     shld    oldstk
  379.     lxi    sp,stack; make a new stack pointer
  380.  
  381.     if    INPUT
  382.     call    vcin    ; get console input
  383.     mov    c,a    ; save in [c] for 'save'
  384.     push    psw    ; and save on the stack
  385.     endif        ; INPUT
  386.  
  387.     call    save    ; save characters in buffer
  388.  
  389.     if    INPUT
  390.     pop    psw    ; get console input of the stack
  391.     endif        ; INPUT
  392.  
  393.     lhld    oldstk    ; get old CP/M stack pointer
  394.     sphl
  395.     pop    b
  396.     pop    d
  397.     pop    h
  398.  
  399.     if    OUTPUT
  400.     jmp    vcout
  401.     endif        ; OUTPUT
  402.  
  403.     if    INPUT
  404.     ret
  405.     endif        ; INPUT
  406.  
  407. save:    equ    $+offset
  408.  
  409.     if    KAYPRO
  410.     mov    a,c
  411.     cpi    'Z'-40h    ; control-Z?   (clear screen)
  412.     jnz    save2    ; if not, use this character
  413.     push    h
  414.     push    d
  415.     push    b
  416.     push    psw    ; save real character
  417.     mvi    c,1eh    ; home cursor
  418.     call    save    ; save it
  419.     mvi    c,17h    ; clear to end of screen
  420.     call    save    ; save it
  421.     pop    psw    ; restore real character
  422.     pop    b
  423.     pop    d
  424.     pop    h
  425.     ret        ; now skip the control-z
  426. save2:    equ    $+offset
  427.     endif        ; KAYPRO
  428.  
  429.     lhld    size    ; size = size + 1
  430.     inx    h
  431.     shld    size
  432.     lhld    ptr
  433.     mov    m,c
  434.     inx    h
  435.  
  436. saved:    equ    $+offset
  437.     if    INPUT
  438.     mov    a,c
  439.     cpi    cr    ; carriage return?
  440.     jnz    notcr
  441.     mvi    m,lf    ; yes, so add line feed because CP/M does not
  442.     inx    h    ; bump pointer, for next time thru
  443.     shld    ptr    ; added for 1.1 to
  444.     lhld    size    ;        /
  445.     inx    h    ;       /
  446.     shld    size    ;      /
  447.     lhld    ptr    ; here
  448.     endif        ; INPUT
  449.  
  450. notcr    equ    $+offset; make label for next instruction...
  451.  
  452.     shld    ptr
  453.     lxi    d,endmark    ; get 'endmark' for buffer top address
  454.     mov    a,d
  455.     cmp    h    ; getting near the end of buffer yet?
  456.     rnz        ; if not, just return
  457.     mov    a,e    ; very near the top now, final address loaded?
  458.     cmp    l
  459.     rnz        ; if not, just return
  460.  
  461.     if    not QUIET
  462.     mvi    c,bel    ; warn user that we need to write to disk
  463.     call    conout
  464.     endif        ; QUIET
  465.  
  466. ; wtb - write text buffer to disk
  467. wtb:    equ    $+offset
  468.     IF NOT APPLE
  469.     lhld    base+6    ; get warm boot address for next bias to CCP
  470.     lxi    d,0fffah; make bias to CCP
  471.     dad    d    ; add bias to [hl]
  472.     lxi    b,1600h    ; make quantity to move
  473.     lxi    d,cpmbuf; buffer all of CP/M system
  474.     call    movecpm    ; move it...
  475.     ENDIF
  476.     IF APPLE
  477.     lxi    h,0CC00h
  478.     lxi    b,1400h
  479.     lxi    d,cpmbuf
  480.     call    movecpm
  481.     lxi    h,0F000h
  482.     lxi    b,1000h
  483.     lxi    d,cpmbuf1
  484.     call    movecpm
  485.     ENDIF    ; APPLE
  486.     call    reset    ; reset disk in case it's R/O
  487.     call    open    ; attempt to open USER.LOG
  488.     inr    a    ; check CP/M return code
  489.     jnz    makeok    ; USER.LOG already exist?
  490. ;
  491. nolog:    equ    $+offset
  492. ;
  493.     call    make    ; make new file
  494.     inr    a    ; check CP/M return code
  495.     jnz    makeok
  496.  
  497.     if    ERRDISP
  498.     lxi    h,dirful; oops...can't make file, return to CP/M
  499.     call    msgout
  500.     endif        ; ERRDISP
  501.  
  502.     jmp    base
  503. ;
  504. ; USER.LOG exists, so set the FCB entry for next append to file
  505. ;
  506. makeok:    equ    $+offset
  507. ;
  508.     lda    fcb+frc    ; get record count
  509.     sta    fcb+nr    ; make next record
  510.     lhld    size    ; [de] = tbuf size
  511.     xchg
  512.     lxi    h,dbuf    ; top of stack points to dbuf
  513.     push    h
  514.     lxi    h,tbuf    ; [hl] points to tbuf
  515. wtb1:    equ    $+offset
  516.     mvi    c,128    ; disk buffer size
  517. wtb2:    equ    $+offset
  518.     mov    a,m    ; fetch next byte of tbuf
  519.     inx    h
  520.     xthl
  521.     mov    m,a    ; store in dbuf
  522.     inx    h
  523.     xthl
  524.     dcx    d    ; size = size - 1
  525.     mov    a,d    ; exit loop if size = 0
  526.     ora    e
  527.     jz    wtb3
  528.     dcr    c    ; loop until dbuf full
  529.     jnz    wtb2
  530.     call    setdma    ; set dma to dbuf
  531.     call    write    ; write full dbuf to disk
  532.     push    psw    ; save possible error code
  533.     lda    fcb+frc    ; get record count
  534.     sta    fcb+nr    ; make next record
  535.     pop    psw    ; get possible error code
  536.     ora    a    ; check CP/M return code
  537.     jz    nextbuf
  538.  
  539.     if    ERRDISP
  540.     lxi    h,dskful; oops...disk is full
  541.     call    msgout
  542.     endif        ; ERRDISP
  543.  
  544.     jmp    base
  545. ;
  546. nextbuf    equ    $+offset
  547. ;
  548.     xthl        ; top of stack points to dbuf
  549.     lxi    h,dbuf
  550.     xthl
  551.     jmp    wtb1    ; loop until end of tbuf
  552. wtb3:    equ    $+offset
  553.     pop    h    ; [hl] points to current place in dbuf
  554. wtb4:    equ    $+offset
  555.     mvi    m,20h ; store eof code
  556.     inx    h
  557.     dcr    c    ; loop thru rest if dbuf
  558.     jnz    wtb4
  559.     call    setdma    ; set dma to dbuf
  560.     call    write    ; write last sector to disk
  561.     push    psw    ; save possible error code
  562.     lda    fcb+frc    ; get record count
  563.     sta    fcb+nr    ; make next record
  564.     pop    psw    ; get possible error code
  565.     ora    a    ; check CP/M return code
  566.     jz    closeup
  567.  
  568.     if    ERRDISP
  569.     lxi    h,dskful; oops...disk is full
  570.     call    msgout
  571.     endif        ; ERRDISP
  572.  
  573.     jmp    base
  574. ;
  575. closeup    equ    $+offset
  576. ;
  577.     call    close    ; clean up act and go home
  578.     lxi    h,tbuf    ; clear text buffer
  579.     shld    ptr
  580.     lxi    h,0
  581.     shld    size
  582. wtb5:    equ    $+offset
  583.     IF NOT APPLE
  584.     lhld    base+6    ; get warm boot address for next bias to CCP
  585.     lxi    d,0fffah; make bias to CCP
  586.     dad    d    ; add bias to [hl]
  587.     lxi    b,1600h    ; make quantity to move
  588.     lxi    d,cpmbuf; buffer all of CP/M system
  589.     xchg        ; swap
  590.     call    movecpm    ; move it...
  591.     ENDIF
  592.     IF APPLE
  593.     lxi    h,0CC00h
  594.     lxi    b,1400h
  595.     lxi    d,cpmbuf
  596.     xchg
  597.     call    movecpm
  598.     lxi    h,0F000h
  599.     lxi    b,1000h
  600.     lxi    d,cpmbuf1
  601.     xchg
  602.     call    movecpm
  603.     ENDIF    ; APPLE
  604.     ret
  605. ;  reset - reset disk
  606. ;
  607. reset:    equ    $+offset
  608.     push    h
  609.     push    d
  610.     push    b
  611.     mvi    c,resdsk
  612.     call    bdos
  613.     pop    b
  614.     pop    d
  615.     pop    h
  616.     ret
  617. ; open - open disk file
  618. open:    equ    $+offset
  619.     push    h
  620.     push    d
  621.     push    b
  622.     lxi    d,fcb
  623.     mvi    c,offc
  624.     call    bdos
  625.     pop    b
  626.     pop    d
  627.     pop    h
  628.     ret
  629. ; read - read record from disk file
  630. read:    equ    $+offset
  631.     push    h
  632.     push    d
  633.     push    b
  634.     lxi    d,fcb
  635.     mvi    c,rrfc
  636.     call    bdos
  637.     pop    b
  638.     pop    d
  639.     pop    h
  640.     ret
  641. ; close - close disk file
  642. close:    equ    $+offset
  643.     push    h
  644.     push    d
  645.     push    b
  646.     lxi    d,fcb
  647.     mvi    c,cffc
  648.     call    bdos
  649.     pop    b
  650.     pop    d
  651.     pop    h
  652.     ret
  653. ; delt - delete disk file
  654. delt:    equ    $+offset
  655.     push    h
  656.     push    d
  657.     push    b
  658.     lxi    d,fcb
  659.     mvi    c,dffc
  660.     call    bdos
  661.     pop    b
  662.     pop    d
  663.     pop    h
  664.     ret
  665. ; write - write record to disk
  666. write:    equ    $+offset
  667.     push    h
  668.     push    d
  669.     push    b
  670.     lxi    d,fcb
  671.     mvi    c,wrfc
  672.     call    bdos
  673.     pop    b
  674.     pop    d
  675.     pop    h
  676.     ret
  677. ; make - make new disk file
  678. make:    equ    $+offset
  679.     push    h
  680.     push    d
  681.     push    b
  682.     lxi    d,fcb
  683.     mvi    c,mffc
  684.     call    bdos
  685.     pop    b
  686.     pop    d
  687.     pop    h
  688.     ret
  689. ; setdma - set dma address for disk file
  690. setdma:    equ    $+offset
  691.     push    h
  692.     push    d
  693.     push    b
  694.     lxi    d,dbuf
  695.     mvi    c,sdma
  696.     call    bdos
  697.     pop    b
  698.     pop    d
  699.     pop    h
  700.     ret
  701. ;
  702.  
  703.     if    ERRDISP
  704. dskful:    equ    $+offset
  705.     db    cr,lf,bel,'OOPS...disk is full!',0
  706. ;
  707. dirful:    equ    $+offset
  708.     db    cr,lf,bel,'OOPS...directory is full!',0
  709.     endif        ; ERRDISP
  710.  
  711. ;
  712. active$message    equ    $+offset
  713.     db    '  (Active)',0
  714. ;
  715. inactive$message    equ    $+offset
  716.     db    '  (Inactive)',0
  717. ;
  718. fcb    equ    $+offset
  719.     db    0    ; default drive specifier
  720.  
  721.     if    SYSLOG
  722.     db    'USER    L','O'+80h,'G'
  723.     endif        ; SYSLOG
  724.  
  725.     if    not SYSLOG
  726.     db    'USER    LOG'
  727.     endif        ; SYSLOG
  728.  
  729.     db    0,0,0,0,0,0,0,0,0,0
  730. ;
  731. pend    equ    $+offset; end of relocated code
  732. ;
  733. ; data area
  734.     ds    128    ; 64 level stack
  735. stack    equ    $+offset;local stack
  736. ;
  737. ptr:    equ    $+offset
  738.     ds    2    ; text buffer pointer
  739. ;
  740. size:    equ    $+offset
  741.     ds    2    ; text buffer size
  742. ;
  743. ; Save the CP/M jump table here
  744. ;
  745. vcstat    equ    $+offset
  746.     ds    3
  747. ;
  748. vcin    equ    $+offset
  749.     ds    3
  750. ;
  751. vcout    equ    $+offset
  752.     ds    3
  753. ;
  754. oldstk    equ    $+offset
  755.     ds    2    ; storage for old CP/M stack pointer
  756. ;
  757.     IF NOT APPLE
  758.     cpmbuf    equ    $+offset
  759.     ds    1600h    ; storage CP/M system image
  760.     ENDIF
  761.     IF APPLE
  762.     cpmbuf    equ    $+offset
  763.     ds    1400h
  764.     cpmbuf1    equ    $+offset
  765.     ds    1000h
  766.     ENDIF    ;APPLE
  767. ;
  768. dbuf    equ    $+offset
  769.     ds    128    ; secondary disk buffer address
  770. ;
  771. tbuf:    equ    $+offset
  772.     ds    16*128    ; I/O-CAP storage for 16 sectors (2048 bytes)
  773. ;
  774. endmark    equ    $+offset;! ignore error - this marks end of program
  775. ;
  776.     end
  777. 28    ; I/O-CAP storage for 16 sectors (2048 bytes