home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / cpm86 / fmacs86.ark / CCPMINT.A86 < prev    next >
Text File  |  1989-02-09  |  23KB  |  827 lines

  1.     pagesize    86
  2.     title     'CCPM interface for FREEMACS'
  3.  
  4. v30    equ    0
  5. files    equ    8        ;max. number of files that can be opened
  6.  
  7.     if v30
  8. ;macros for NEC V20/V30 or Intel 80186/286
  9.     codemacro SHLW parm:ew,count:db        ;shift word left by
  10.         db 0c1h                ;immediate count
  11.         modrm 4,parm
  12.         db count
  13.         endm
  14.     codemacro SHRW parm:ew,count:db        ;shift word right by
  15.         db 0c1h                ;immediate count
  16.         modrm 5,parm
  17.         db count
  18.         endm
  19.     endif
  20.  
  21. ;CCPM function EQUs
  22. c_attach    equ    92h
  23. c_detach    equ    93h
  24. drv_get        equ    19h
  25. f_close        equ    10h
  26. f_delete    equ    13h
  27. f_dmaoff    equ    1Ah
  28. f_dmaseg    equ    33h
  29. f_make        equ    16h
  30. f_multisec    equ    2Ch
  31. f_open        equ    0Fh
  32. f_parse        equ    98h
  33. f_readrand    equ    21h
  34. f_rename    equ    17h
  35. f_sfirst    equ    11h
  36. f_size        equ    23h
  37. f_snext        equ    12h
  38. f_usernum    equ    20h
  39. f_writerand    equ    22h
  40. p_cli        equ    96h
  41. p_pdadr        equ    9Ch
  42. p_priority    equ    91h
  43. t_seconds    equ    9Bh
  44.     codemacro CCPM parm:db            ;call CCPM
  45.         db 0b1h ! db parm            ;mov cl,parm
  46.         db 0cdh ! db 0e0h            ;int 0E0H
  47.         endm
  48.  
  49. data    dseg    word public
  50. our_ds        rs    0
  51.  
  52. pfcb        rw    2        ;F_PARSE parameter block
  53.  
  54. flesize        equ    48        ;length of file_list element
  55. file_list    rb    files*flesize    ;IO buffers and FCBs
  56. file_list_end    rs    0
  57. ;file list element structure
  58. ;        +-------------------------------+
  59. ;    0    |    FLAGS    |   USER CODE    |
  60. ;        +-------------------------------+
  61. ;    2    |           (reserved)        |
  62. ;        +-------------------------------+
  63. ;    4    |        RWPOINTER        |
  64. ;        |         4 bytes        |
  65. ;        +-------------------------------+
  66. ;    8    |        FILELENGTH        |
  67. ;        |         4 bytes        |
  68. ;        +-------------------------------+
  69. ;    12    |         CCPM        |
  70. ;        /    File Control Block    /
  71. ;        |        36 bytes        |
  72. ;        +-------------------------------+
  73. flags        equ    byte ptr 0    ;buffer flags          1 byte
  74. usercode    equ    byte ptr 1    ;user code          1 byte
  75. reserved    equ    byte ptr 2    ;              2 bytes
  76. rwpointer    equ    word ptr 4    ;read/write pointer      4 bytes
  77. filelength    equ    word ptr 8    ;file length          4 bytes
  78. fcb        equ    byte ptr 12    ;File Control Block     36 bytes
  79. fcb_f6        equ    byte ptr fcb+6    ;read only open flag
  80. fcb_r01        equ    word ptr fcb+33    ;random record number
  81. fcb_r2        equ    byte ptr fcb+35
  82. ;
  83. open_mask    equ    80h
  84. modf_mask    equ    40h
  85. ro_mask        equ    20h
  86. ;
  87. search_fle    rb    flesize
  88. search_fle_fcb    equ    byte ptr search_fle+12
  89. help_fle    rb    flesize
  90. help_fle_fcb    equ    byte ptr help_fle+12
  91. help_buffer    rb    130
  92.  
  93. tod        rb    5
  94.  
  95. dft_user    rb    1
  96. ;
  97. ;data    end
  98.  
  99. ;stack    sseg    word
  100. callers_bp    equ    word ptr 0[bp]
  101. callers_di    equ    word ptr 2[bp]
  102. callers_es    equ    word ptr 4[bp]
  103. callers_si    equ    word ptr 6[bp]
  104. callers_ds    equ    word ptr 8[bp]
  105. callers_dx    equ    word ptr 10[bp]
  106. callers_cx    equ    word ptr 12[bp]
  107. callers_bx    equ    word ptr 14[bp]
  108. callers_ax    equ    word ptr 16[bp]
  109. handle_nbr    equ    callers_bx        ;handle #
  110. iob_count    equ    word ptr (-2)[bp]    ;number of bytes to transfer
  111. iodma_seg    equ    word ptr (-4)[bp]    ;DMA segment
  112. iodma_off    equ    word ptr (-6)[bp]    ;DMA offset
  113. iodma_adr    equ    dword ptr (-6)[bp]
  114. iotrf_count    equ    word ptr (-8)[bp]    ;transfer count
  115. ;stack    ends
  116.  
  117.  
  118. code    cseg    byte public
  119.     ;*** assume cs:code,ds:data,es:data,ss:stack
  120.  
  121.     public    ccpm_init
  122. ccpm_init:
  123.     push ds ! mov ds,own_ds
  124.     mov dl,0FFh ! ccpm f_usernum
  125.     inc al ! mov dft_user,al
  126.     pop ds ! ret
  127.  
  128. own_ds    dw    seg our_ds
  129. pe_ret    dw    return
  130.  
  131. prolog:    pop pe_ret
  132.     push ax ! push bx ! push cx ! push dx
  133.     push ds ! push si ! push es ! push di
  134.     push bp ! mov bp,sp
  135.     jmp pe_ret
  136.  
  137. epilog:    pop pe_ret
  138.     mov sp,bp ! pop bp
  139.     pop di ! pop es ! pop si ! pop ds
  140.     pop dx ! pop cx ! pop bx ! pop ax
  141.     jmp pe_ret
  142.  
  143.     public    ccpm_create_file
  144. ccpm_create_file:        ;MS-DOS function 3CH
  145. ;enter with DS:DX -> ASCIIZ of file name
  146.     call prolog
  147.     mov ds,own_ds
  148.     call inithandle        ;init file list element
  149.     mov bx,di ! call set_user    ;set user code
  150.     lea dx,fcb[di]        ;point to fcb
  151.     ccpm f_make        ;call ccpm to create the file
  152.     or al,al        ;test for error
  153.     jz ccpm_open_file_2    ;creation secceeded
  154.     cmp ah,8h        ;test extended error
  155.     je ccpm_open_file_1    ;file exists already -- try to open
  156.     jmp err_return        ;error
  157.  
  158.     public    ccpm_open_file
  159. ccpm_open_file:            ;MS-DOS function 3DH
  160. ;enter with DS:DX -> ASCIIZ of file name
  161.     call prolog
  162.     mov ds,own_ds
  163.     call inithandle        ;init file list element
  164.     mov bx,di ! call set_user
  165. ccpm_open_file_1:
  166.     lea dx,fcb[di]
  167.     ccpm f_close        ;perhaps we reopen
  168.     lea dx,fcb[di]
  169.     ccpm f_open        ;try to open the file
  170.     inc al ! jnz ccpm_open_file_2
  171.     jmp err_return        ;file opening did not succeeded
  172. ccpm_open_file_2:
  173.     mov bx,di ! call file_size_1    ;determine the file size
  174.     or flags[bx],open_mask    ;set file open flag
  175.     mov callers_ax,bx    ;return file handle in AX
  176.     jmp return
  177.  
  178.     public    ccpm_close_file
  179. ccpm_close_file:        ;MS-DOS function 3EH
  180. ;enter with BX = File handle number
  181.     call prolog
  182.     call check_handle
  183.     mov ds,own_ds
  184.     mov di,bx ! call set_user
  185.     test flags[di],modf_mask    ;test if file has been modified
  186.     jz ccpm_close_file_1        ;jump if not
  187.     mov ax,filelength[di]
  188.     test al,7fh            ;is there a partial last record
  189.     jz ccpm_close_file_1        ;jump if not
  190.     mov rwpointer[di],ax
  191.     mov ax,filelength+2[di]
  192.     mov rwpointer+2[di],ax
  193.     mov dx,offset help_buffer
  194.     mov al,1 ! call set_dma
  195.     call rw_to_recptr
  196.     lea dx,fcb[di]            ;read last record
  197.     ccpm f_readrand ! mov bx,di
  198.     mov di,rwpointer[bx] ! and di,7fh    ;offset to EOF
  199.     mov cx,80h ! sub cx,di            ;no. of bytes till EOR
  200.     add di,offset help_buffer
  201.     push ds ! pop es
  202.     mov al,1ah ! rep stosb        ;pad with EOF chars (^Z)
  203.     lea dx,fcb[bx] ! mov di,bx
  204.     ccpm f_writerand        ;rewrite last record
  205. ccpm_close_file_1:
  206.     lea dx,fcb[di]
  207.     ccpm f_close            ;close the file
  208.     inc al ! jnz $+5
  209.     jmp err_return
  210.     mov flags[di],0
  211.     jmp return
  212.  
  213. set_user:    ;set user number
  214.     mov dl,usercode[bx]
  215.     or dl,dl ! jnz $+6
  216.     mov dl,dft_user ! dec dl
  217.     push bx ! ccpm f_usernum
  218.     pop bx ! ret
  219.  
  220. inithandle:
  221.     mov cx,files            ;number of file list elements
  222.     mov bx,offset file_list
  223. inithandle_1:                ;look for an empty file handle entry
  224.     cmp flags[bx],0
  225.     jz inithandle_2            ;element found
  226.     add bx,flesize
  227.     loop inithandle_1
  228.     jmp err_return            ;no element found -- return carry
  229.     ;
  230. inithandle_2:                ;entry found -- clear it
  231.     push ds ! pop es
  232.     xor ax,ax ! mov cx,flesize/2    ;clear file list element
  233.     mov di,bx ! rep stosw
  234.     push ds ! mov ds,callers_ds
  235.     mov si,callers_dx
  236.     mov di,offset help_buffer
  237.     mov cx,128 ! lodsb ! stosb    ;copy ASCIIZ filename to help buffer
  238.     or al,al ! loopne $-4
  239.     pop ds ! jcxz err_return    ;error -- no ASCIIZ filename
  240.     ;
  241.     mov pfcb,offset help_buffer
  242.     push bx ! lea ax,fcb[bx]    ;parse the file name
  243.     mov pfcb+2,ax
  244.     mov dx,offset pfcb
  245.     ccpm f_parse
  246.     pop di ! inc ax
  247.     jz err_return            ;error -- invalid filename
  248.     dec ax ! jz inithandle_ret
  249.     mov si,ax ! lodsb ! cmp al,'['    ;test for options
  250.     je inithandle_3            ;options follow
  251. inithandle_ret:
  252.     ret
  253. inithandle_3:
  254.     lodsb ! or al,al ! jz err_return    ;End of string
  255.     cmp al,']' ! je inithandle_ret        ;End of options
  256.     and al,5Fh            ;option char. to uppercase
  257.     mov bx,offset optiontab
  258. inithandle_4:
  259.     cmp cs:byte ptr [bx],0
  260.     jz err_return            ;end of table --- invalid option
  261.     cmp al,cs:[bx] ! je inithandle_5
  262.     lea bx,3[bx] ! jmps inithandle_4
  263. inithandle_5:
  264.     call cs:word ptr 1[bx]        ;call option routine
  265.     jmps inithandle_3
  266.  
  267. optiontab    db 'G' ! dw inithandle_uc    ;user code
  268.         db 'R' ! dw inithandle_r    ;read only
  269.         db 0
  270. cb10        db 10
  271.  
  272. inithandle_uc:                ;"G"-option -- set user code
  273.     lodsb ! cmp al,'9' ! ja err_return
  274.     cmp al,'0' ! jb err_return
  275.     and al,0Fh ! mov dl,al
  276.     lodsb ! cmp al,'5' ! ja inithandle_uc1
  277.     cmp al,'0' ! jb inithandle_uc1
  278.     and al,0Fh ! xchg al,dl
  279.     mul cs:cb10 ! add dl,al ! inc si
  280. inithandle_uc1:
  281.     inc dl ! mov usercode[di],dl    ;save user code
  282.     dec si ! ret
  283.  
  284. inithandle_r:                ;"R"-Option -- read only file
  285.     or flags[di],ro_mask ! ret
  286.  
  287. err_return:
  288.     stc ! call epilog ! ret
  289.  
  290. ret_trf:mov ax,iotrf_count
  291.     mov callers_ax,ax
  292.  
  293. return:    clc ! call epilog ! ret
  294.  
  295. check_handle:
  296.     cmp bx,offset file_list
  297.     jb err_return
  298.     cmp bx,offset file_list_end
  299.     jnb err_return
  300.     ret
  301.  
  302.     public    ccpm_write_file
  303. ccpm_write_file:        ;MS-DOS function 40H
  304. ;enter with DS:DX -> data to write
  305. ;    CX = number of bytes to write
  306. ;    BX = handle number
  307.     call prolog ! call check_handle
  308.     sub sp,8            ;scratch space
  309.     mov iotrf_count,0
  310.     jcxz ret_trf            ;nothing to do
  311.     call calc_dma            ;preset DMA address
  312.     mov ds,own_ds
  313.     push cx ! call set_user ! pop cx
  314.     mov iob_count,cx        ;save # of bytes to transfer
  315.     test rwpointer[bx],7fh        ;test for broken record io
  316.     jz ccpm_write_file_1        ;direct write possible
  317.  
  318.     mov dx,offset help_buffer
  319.     mov al,1 ! call set_dma        ;set DMA parameters to help buffer
  320.     call rw_to_recptr        ;get record ptr
  321.     lea dx,fcb[bx]
  322.     ccpm f_readrand            ;read record to be partially updated
  323.     mov bx,handle_nbr
  324.     mov di,rwpointer[bx] ! and di,7fh    ;partial record offset
  325.     mov cx,80h ! sub cx,di
  326.     cmp iob_count,cx ! ja $+5
  327.     mov cx,iob_count ! push cx        ;partial record length
  328.     add di,offset help_buffer    ;point to partial record
  329.     push ds ! pop es ! push ds
  330.     lds si,iodma_adr ! rep movsb    ;copy partial record
  331.     pop ds ! mov iodma_off,si
  332.     lea dx,fcb[bx] ! push bx
  333.     ccpm f_writerand        ;rewrite record
  334.     or al,al ! jz $+5
  335.     jmp err_return            ;error
  336.     pop bx ! pop ax            ;# of bytes transfered
  337.     add iotrf_count,ax        ;update transfer count
  338.     add rwpointer[bx],ax        ;update R/W pointer
  339.     adc rwpointer+2[bx],0
  340.     sub iob_count,ax
  341.     mov cx,iob_count
  342.  
  343. ccpm_write_file_1:
  344.     if v30
  345.     mov ax,cx ! shrw cx,7        ;cx = sector count
  346.     else
  347.     push cx ! mov ax,cx
  348.     mov cl,7 ! shr ax,cl
  349.     mov cx,ax ! pop ax
  350.     endif
  351.     and ax,7fh ! mov iob_count,ax    ;ax = rest byte count
  352. ccpm_write_file_2:
  353.     jcxz ccpm_write_file_3
  354.     push cx                ;save total sector count
  355.     cmp cx,80h ! jbe $+5
  356.     mov cx,80h ! push cx        ;save max. sector count
  357.     push ds ! lds dx,iodma_adr
  358.     call calc_dma            ;form DMA address
  359.     mov ds,ax ! mov al,cl
  360.     call set_dma            ;set DMA parameters
  361.     pop ds
  362.     call rw_to_recptr        ;form record ptr
  363.     lea dx,fcb[bx]
  364.     ccpm f_writerand        ;perform IO
  365.     or al,al ! jz $+5
  366.     jmp err_return            ;IO error
  367.     mov bx,handle_nbr
  368.     pop ax ! pop cx            ;retrieve record counts
  369.     sub cx,ax            ;update total record count
  370.     if v30
  371.     shlw ax,7            ;# of bytes transfered
  372.     else
  373.     push cx ! mov cl,7 ! shl ax,cl ! pop cx
  374.     endif
  375.     add iotrf_count,ax        ;update transfer count
  376.     add rwpointer[bx],ax        ;update R/W pointer
  377.     adc rwpointer+2[bx],0
  378.     add iodma_off,ax        ;update DMA address
  379.     jmps ccpm_write_file_2
  380.  
  381. ccpm_write_file_3:
  382.     mov cx,iob_count        ;get rest length
  383.     jcxz ccpm_write_file_4        ;all done
  384.     mov dx,offset help_buffer    ; not yet -- there's a little rest
  385.     mov al,1 ! call set_dma
  386.     call rw_to_recptr        ;form record pointer
  387.     lea dx,fcb[bx] ! ccpm f_readrand    ;read record
  388.     push ds ! pop es ! push ds
  389.     lds dx,iodma_adr ! call calc_dma
  390.     mov si,dx ! mov ds,ax
  391.     mov di,offset help_buffer
  392.     mov cx,iob_count ! rep movsb    ;copy partial record
  393.     pop ds
  394.     mov bx,handle_nbr
  395.     lea dx,fcb[bx] ! ccpm f_writerand    ;rewrite record
  396.     or ax,ax ! jz $+5
  397.     jmp err_return            ;error
  398.     mov ax,iob_count        ;# if bytes written
  399.     mov bx,handle_nbr
  400.     add rwpointer[bx],ax        ;update R/W pointer
  401.     adc rwpointer+2[bx],0
  402.     add iotrf_count,ax
  403. ccpm_write_file_4:
  404.     or flags[bx],modf_mask        ;signal that file has been modified
  405.     mov dx,rwpointer+2[bx]
  406.     cmp dx,filelength+2[bx]        ;has file been extended ?
  407.     jb ret_trf1
  408.     mov ax,rwpointer[bx]
  409.     cmp ax,filelength[bx]
  410.     jbe ret_trf1
  411.     mov filelength[bx],ax        ;yes -- update file length
  412.     mov filelength+2[bx],dx
  413. ret_trf1:
  414.     jmp ret_trf
  415.  
  416.     public    ccpm_read_file
  417. ccpm_read_file:        ;MS-DOS function 3FH
  418. ;enter with DS:DX -> buffer to read into
  419. ;    CX = number of bytes to read
  420. ;    BX = handle number
  421.     call prolog ! call check_handle
  422.     sub sp,8            ;scratch space
  423.     mov iotrf_count,0
  424.     jcxz ret_trf1            ;nothing to do
  425.     call calc_dma            ;preset DMA address
  426.     mov ds,own_ds
  427.     push cx ! call set_user ! pop cx
  428.     mov ax,rwpointer[bx]
  429.     mov dx,rwpointer+2[bx]
  430.     add ax,cx ! adc dx,0
  431.     cmp dx,filelength+2[bx]    ! ja $+7;shall we read past the EOF ?
  432.     cmp ax,filelength[bx] ! jbe $+9
  433.     sub ax,filelength[bx]        ;yes -- truncate CX to file length
  434.     sub cx,ax ! jcxz ret_trf1        ;that's EOF
  435.     mov iob_count,cx        ;save # of bytes to transfer
  436.     test rwpointer[bx],7fh        ;test for broken record io
  437.     jz ccpm_read_file_1        ;direct write possible
  438.  
  439.     mov dx,offset help_buffer
  440.     mov al,1 ! call set_dma        ;set DMA parameters to help buffer
  441.     call rw_to_recptr        ;get record ptr
  442.     lea dx,fcb[bx]
  443.     ccpm f_readrand            ;read record
  444.     or al,al ! jz $+5
  445.     jmp err_return
  446.     mov bx,handle_nbr
  447.     mov si,rwpointer[bx] ! and si,7fh    ;partial record offset
  448.     mov cx,80h ! sub cx,si
  449.     cmp iob_count,cx ! ja $+5
  450.     mov cx,iob_count ! push cx        ;partial record length
  451.     add si,offset help_buffer    ;point to partial record
  452.     les di,iodma_adr ! rep movsb    ;copy partial record
  453.     mov iodma_off,di
  454.     pop ax                ;# of bytes transfered
  455.     add iotrf_count,ax        ;update transfer count
  456.     add rwpointer[bx],ax        ;update R/W pointer
  457.     adc rwpointer+2[bx],0
  458.     sub iob_count,ax
  459.     mov cx,iob_count
  460. ;
  461. ccpm_read_file_1:
  462.     if v30
  463.     mov ax,cx ! shrw cx,7        ;cx = sector count
  464.     else
  465.     push cx ! mov ax,cx
  466.     mov cl,7 ! shr ax,cl
  467.     mov cx,ax ! pop ax
  468.     endif
  469.     and ax,7fh ! mov iob_count,ax    ;ax = rest byte count
  470. ccpm_read_file_2:
  471.     jcxz ccpm_read_file_3
  472.     push cx                ;save total sector count
  473.     cmp cx,80h ! jbe $+5
  474.     mov cx,80h ! push cx        ;save max. sector count
  475.     push ds ! lds dx,iodma_adr
  476.     call calc_dma            ;form DMA address
  477.     mov ds,ax ! mov al,cl
  478.     call set_dma            ;set DMA parameters
  479.     pop ds
  480.     call rw_to_recptr        ;form record ptr
  481.     lea dx,fcb[bx]
  482.     ccpm f_readrand            ;perform IO
  483.     mov bx,handle_nbr
  484.     or al,al ! jz ccpm_read_file_2a
  485.     dec al ! jz $+5            ;EOF ?
  486.     jmp err_return            ;no - IO error
  487.     shr ax,1 ! add iotrf_count,ax    ;number of bytes transfered
  488.     add rwpointer[bx],ax
  489.     adc rwpointer+2[bx],0
  490.     ; *** pop ax ! pop cx
  491.     jmp ret_trf2
  492. ccpm_read_file_2a:
  493.     pop ax ! pop cx            ;retrieve record counts
  494.     sub cx,ax            ;update total record count
  495.     if v30
  496.     shlw ax,7            ;# of bytes transfered
  497.     else
  498.     push cx ! mov cl,7
  499.     shl ax,cl ! pop cx
  500.     endif
  501.     add iotrf_count,ax        ;update transfer count
  502.     add rwpointer[bx],ax        ;update R/W pointer
  503.     adc rwpointer+2[bx],0
  504.     add iodma_off,ax        ;update DMA address
  505.     jmps ccpm_read_file_2
  506.  
  507. ccpm_read_file_3:
  508.     mov cx,iob_count        ;get rest length
  509.     jcxz ret_trf2            ;all done
  510.     mov dx,offset help_buffer    ; not yet -- there's a little rest
  511.     mov al,1 ! call set_dma
  512.     call rw_to_recptr        ;form record pointer
  513.     lea dx,fcb[bx] ! ccpm f_readrand    ;read record
  514.     or al,al ! jz $+5
  515.     jmp err_return
  516.     push ds ! lds dx,iodma_adr
  517.     call calc_dma ! pop ds
  518.     les di,iodma_adr
  519.     mov si,offset help_buffer
  520.     mov cx,iob_count
  521.     push cx ! rep movsb ! pop cx    ;copy partial record
  522.     mov bx,handle_nbr
  523.     add rwpointer[bx],cx        ;update R/W pointer
  524.     adc rwpointer+2[bx],0
  525.     add iotrf_count,cx
  526. ret_trf2:
  527.     jmp ret_trf
  528.  
  529.  
  530. calc_dma:    ;recalc. DMA address
  531.     ;enter with DS:DX = current DMA address
  532.     ;exit with DX and IODMA_OFF = new DMA offset
  533.     ;       AX and IODMA_SEG = new DMA segment
  534.     mov ax,ds ! push dx
  535.     if v30
  536.     shrw dx,4 ! add ax,dx        ;AX = new DMA segment
  537.     else
  538.     push cx ! mov cl,4
  539.     shr dx,cl ! pop cx ! add ax,dx
  540.     endif 
  541.     mov iodma_seg,ax
  542.     pop dx ! and dx,0fh        ;DX = new DMA offset
  543.     mov iodma_off,dx
  544.     ret
  545.  
  546. set_dma:    ;set new DMA segment, offset, and sector count
  547.     ;enter with DS = DMA segment
  548.     ;        DX = DMA offset
  549.     ;        AL = sector count
  550.     push ax ! ccpm f_dmaoff        ;set DMA offset
  551.     mov dx,ds ! ccpm f_dmaseg    ;set DMA segment
  552.     pop dx ! ccpm f_multisec    ;set sector count
  553.     ret
  554.  
  555. rw_to_recptr:    ;convert R/W pointer to record pointer
  556.     mov bx,handle_nbr
  557.     mov ax,rwpointer[bx]        ;get file pointer
  558.     mov dx,rwpointer+2[bx]
  559.     mov cl,7
  560.     sar dx,1 ! rcr ax,1        ;form record pointer
  561.     loop $-4
  562.     mov fcb_r01[bx],ax        ;record pointer -- low word
  563.     mov fcb_r2[bx],dl        ;record pointer -- high byte
  564.     ret
  565.  
  566.     public    ccpm_delete_file
  567. ccpm_delete_file:        ;MS-DOS function 41H
  568. ;enter with DS:DX -> ASCIIZ filename
  569.     call prolog
  570.     mov ds,own_ds
  571.     mov bx,offset help_fle
  572.     call inithandle_2
  573.     mov bx,di ! call set_user
  574.     mov flags[di],0
  575.     lea dx,fcb[di]
  576.     ccpm f_delete
  577.     or al,al ! jz $+5
  578.     jmp err_return
  579.     jmp return
  580.  
  581.     public    ccpm_lseek_file
  582. ccpm_lseek_file:        ;MS-DOS function 42H
  583. ;enter with  CX:DX - Distance to move
  584. ;        AL - Method of moving
  585. ;        BX - Handle
  586. ;exit with   DX:AX - New pointer location
  587.  
  588. ; >>>>> CAUTION <<<<<
  589. ;MS-DOS maintains the file length in BYTES, but CCPM in RECORDS of 128 bytes.
  590. ;Therefore, if we position to the end of a file (AL=2), we have to look in
  591. ;in last record for the last non-EOF-mark (^Z) and position after it. This
  592. ;procedure may cause TRUBBLES IN CASE OF BINARY FILES if there is an EOF-mark
  593. ;pertaining to data in the last record !!!!!
  594.  
  595.     call prolog ! call check_handle
  596.     mov ds,own_ds
  597.     or al,al ! jnz ccpm_lseek_file_1
  598.     mov rwpointer[bx],dx
  599.     mov rwpointer+2[bx],cx
  600. ccpm_lseek_file_ret:
  601.     mov callers_ax,dx
  602.     mov callers_dx,cx
  603.     jmp return
  604. ccpm_lseek_file_1:
  605.     cmp al,1 ! jne ccpm_lseek_file_2
  606.     add dx,rwpointer[bx]
  607.     adc cx,rwpointer+2[bx]
  608.     mov rwpointer[bx],dx
  609.     mov rwpointer+2[bx],cx
  610.     jmps ccpm_lseek_file_ret
  611. ccpm_lseek_file_err:
  612.     jmp err_return
  613. ccpm_lseek_file_2:
  614.     cmp al,2 ! jne ccpm_lseek_file_err
  615.     call file_size
  616.     jc ccpm_lseek_file_err
  617.     mov rwpointer[bx],ax
  618.     mov rwpointer+2[bx],dx
  619.     mov callers_ax,ax
  620.     mov callers_dx,dx
  621.     jmp return
  622.  
  623. file_size:
  624.     call set_user
  625.     push bx ! lea dx,fcb[bx]    ;to determine the file size correctly
  626.     ccpm f_close ! pop bx        ;      the file nust first be closed.
  627.     push bx ! lea dx,fcb[bx]
  628.     ccpm f_open ! pop bx
  629.     inc al ! jnz $+4 ! stc ! ret    ;cannot reopen
  630. file_size_1:
  631.     push bx ! lea dx,fcb[bx]    ;compute the virt. file size
  632.     ccpm f_size ! pop bx
  633.     sub fcb_r01[bx],1        ;position to last record
  634.     sbb fcb_r2[bx],0
  635.     jnc file_size_2
  636.     xor ax,ax ! mov dx,ax        ;file is empty
  637.     jmps file_size_3
  638. file_size_2:
  639.     mov dx,offset help_buffer
  640.     push bx ! mov al,1        ;set our own DMA
  641.     call set_dma ! pop bx
  642.     push bx ! lea dx,fcb[bx]    ;read the last record
  643.     ccpm f_readrand ! pop bx
  644.     mov di,offset help_buffer+127    ;point to end of our buffer
  645.     push ds ! pop es
  646.     mov cx,128 ! mov al,1ah        ;and search for first non EOF char
  647.     std ! rep scasb ! cld
  648.     sub di,offset help_buffer-2    ;build buffer rel. offset
  649.     mov ax,fcb_r01[bx]
  650.     xor dx,dx ! mov dl,fcb_r2[bx]
  651.     mov cx,7 ! clc
  652.     rcl ax,1 ! rcl dx,1 ! loop $-4    ;point to first byte of last record
  653.     add ax,di ! adc dx,0        ;point to EOF mark
  654. file_size_3:
  655.     mov filelength[bx],ax
  656.     mov filelength+2[bx],dx
  657.     ret
  658.  
  659.  
  660.     public    ccpm_find_file
  661. ccpm_find_file:
  662. ;enter with AH = 0    To find first entry (MS-DOS function 4EH)
  663. ;        DS:DX        pointer to ASCIIZ filename
  664. ;        ES:DI        where to put the resultant ASCIIZ filename
  665. ;        AH <> 0    To find the next entry (MS-DOS function 4F)
  666. ;        ES:DI        where to put the resultant ASCIIZ filename
  667. ; >>>>>>> CAUTION: not MS-DOS compatible (yet) !!! <<<<<<<
  668.     call prolog
  669.     mov ds,own_ds
  670.     mov dx,offset help_buffer
  671.     mov al,1 ! call set_dma            ;set DMA address
  672.     mov ax,callers_ax
  673.     or ah,ah ! jnz ccpm_find_file_1
  674.  
  675.     mov bx,offset search_fle
  676.     call inithandle_2
  677.  
  678.     cmp fcb[di],0 ! jne ccpm_file_0
  679.     ccpm drv_get ! inc al ! mov fcb[di],al    ;set drive to default
  680. ccpm_file_0:
  681.     mov bx,di ! call set_user
  682.     lea dx,fcb[di] ! ccpm f_sfirst        ;find first entry
  683.     cmp al,0ffh ! jnz ccpm_find_file_2
  684.     jmp err_return
  685.  
  686. ccpm_find_file_1:
  687.     mov bx,offset search_fle
  688.     call set_user
  689.     mov dx,offset search_fle_fcb
  690.     ccpm f_snext                ;find next entry
  691.     cmp al,0ffh ! jne ccpm_find_file_2
  692.     jmp err_return
  693.  
  694. ccpm_find_file_2:            ;copy back the filename
  695.     les di,dword ptr callers_di    ;load destination
  696.     if v30
  697.     xor ah,ah ! shlw ax,5        ;source offset rel. to DMA buffer
  698.     else
  699.     xor ah,ah ! mov cl,5 ! shl ax,cl
  700.     endif
  701.     mov si,ax ! lea si,help_buffer[si]    ;point to DIR entry
  702.     lodsb ! and al,0fh ! push ax    ;save user code from DIR
  703.     mov al,search_fle_fcb        ;drive code from fcb
  704.     add al,'@' ! mov ah,':' ! stosw    ;store drive specification
  705.     push si ! mov cx,8 ! lodsb    ;copy file name
  706.     and al,7Fh ! cmp al,32 ! je $+5    ;    blank=exit loop
  707.     stosb ! loop $-8
  708.     pop si ! lea si,8[si]        ;point to extention
  709.     cmp byte ptr [si],32        ;is there an extention ?
  710.     je ccpm_find_file_3        ;jump if not
  711.     mov al,'.' ! stosb        ;else append '.'
  712.     mov cx,3 ! lodsb
  713.     and al,7Fh ! cmp al,20h        ;and copy file extention
  714.     je $+5 ! stosb ! loop $-8
  715. ccpm_find_file_3:            ;form user specification
  716.     mov ax,'G[' ! stosw ! pop ax    ;restore user from DIR entry
  717.     aaa ! or ax,3030h        ;form ASCII user number
  718.     cmp ah,30h ! je $+7
  719.     xchg al,ah ! stosb        ;store high digit
  720.     xchg al,ah ! stosb        ;store low digit
  721.     mov ax,']' ! stosw        ;store final delimiter
  722.     jmp return
  723.  
  724.     public ccpm_rename_file
  725. ccpm_rename_file:        ;MS-DOS function 56h
  726. ;enter with    DS:DX    - old ASCIIZ file name
  727. ;        ES:DI    - new ASCIIZ file name
  728. ;exit with CARRY in error
  729.     call prolog
  730.     mov ds,own_ds ! mov bx,offset help_fle
  731.     call inithandle_2
  732.     mov bx,di ! call set_user
  733.     mov es,own_ds
  734.     mov di,offset help_fle_fcb+17
  735.     mov al,' ' ! mov cx,11
  736.     rep stosb            ;preset new file name with blanks
  737.     mov si,callers_di
  738.     mov ds,callers_es        ;copy new file name
  739.     mov di,offset help_fle_fcb+17    ;into FCB
  740.     mov cl,9
  741. ccpm_rename_file_1:
  742.     lodsb ! cmp al,'.'
  743.     je ccpm_rename_file_2        ;extension follow
  744.     or al,al ! jz ccpm_rename_file_4
  745.     call to_upper ! stosb
  746.     loop ccpm_rename_file_1
  747.     jmp err_return            ;new file name to long
  748. ccpm_rename_file_2:
  749.     mov di,offset help_fle_fcb+17+8
  750.     mov cl,4            ;copy new extension
  751. ccpm_rename_file_3:
  752.     lodsb ! or al,al
  753.     jz ccpm_rename_file_4
  754.     call to_upper ! stosb
  755.     loop ccpm_rename_file_3
  756.     jmp err_return            ;new extention is to long
  757. ccpm_rename_file_4:
  758.     mov ds,own_ds
  759.     mov dx,offset help_fle_fcb
  760.     ccpm f_rename            ;rename the file
  761.     inc al ! jz $+5
  762.     jmp return
  763.     jmp err_return            ;error -- cannot rename the file
  764.  
  765. to_upper:
  766.     and al,7fh            ;remove status bits
  767.     cmp al,'a' ! jb to_upper_exit
  768.     cmp al,'z' ! ja to_upper_exit
  769.     and al,5fh
  770. to_upper_exit:
  771.     ret
  772.  
  773.     public ccpm_get_time
  774. ccpm_get_time:        ;MS-DOS function 2CH
  775. ;exit with    CH - Hour (0-23)
  776. ;        CL - Minutes (0-59)
  777. ;        DH - Seconds (0-59)
  778. ;        DL - Hundredths (0-99)  >>>>>>> currently 0 !!!! <<<<<<<
  779.     call prolog
  780.     mov ds,own_ds
  781.     mov dx,offset tod
  782.     ccpm t_seconds            ;get current time and day
  783.     mov cl,4 ! xor dl,dl        ;>>>>>>>> clear hundredths <<<<<<<
  784.     xor ah,ah ! mov al,tod+4    ;get seconds
  785.     shl ax,cl ! shr al,cl
  786.     aad ! mov dh,al
  787.     mov al,tod+3            ;get minutes
  788.     shl ax,cl ! shr al,cl
  789.     aad ! mov bl,al
  790.     mov al,tod+2            ;get hour
  791.     shl ax,cl ! shr al,cl
  792.     aad ! mov bh,al
  793.     mov callers_dx,dx
  794.     mov callers_cx,bx
  795.     jmp return
  796.  
  797.     public ccpm_execute_program
  798. ;enter with ds:si,cx = P_CLI string
  799. ;exit with ax = Error code
  800. ccpm_execute_program:
  801.     call prolog
  802.     mov es,own_ds
  803.     mov di,offset help_buffer
  804.     lds si,dword ptr callers_si
  805.     xor al,al ! stosb
  806.     and cx,7fh ! rep movsb
  807.     stosb ! mov ds,own_ds
  808.     ccpm p_pdadr            ;get our PD address
  809.     mov al,es:byte ptr 5[bx]    ;get our priority
  810.     push ax ! push es ! push bx    ;save all
  811.     mov si,es:word ptr 1eh[bx]    ;get parent's PD
  812.     or si,si ! jz execute_program_0    ;I'm alone
  813.     mov al,es:byte ptr 5[si]    ;get parent's prio
  814.     dec al ! mov es:byte ptr 5[bx],al    ;I'm one better
  815. execute_program_0:
  816.     mov dx,offset help_buffer
  817.     ccpm p_cli
  818.     or ax,ax ! jz execute_program_1
  819.     mov ax,cx
  820. execute_program_1:
  821.     mov callers_ax,ax
  822.     ccpm c_attach
  823.     pop bx ! pop es ! pop ax
  824.     mov es:byte ptr 5[bx],al    ;reset our priority
  825.     jmp return
  826.     end
  827.