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 / CPM / BDSC / BDSC-1 / DEFF2.CSM < prev    next >
Text File  |  2000-06-30  |  22KB  |  1,259 lines

  1. ;
  2. ; BD Software C Standard Library Machine Language Functions
  3. ; Written by Leor Zolman
  4. ; v1.46,    3/15/82
  5. ;
  6. ; This file is in "CSM" format; to convert to CRL format,
  7. ; use CASM.SUB in conjunction with CASM.COM, ASM.COM and DDT.COM.
  8. ; Functions appearing in this file:
  9. ;
  10. ;     getchar    kbhit    ungetch    putchar    putch    gets    rand    srand
  11. ;    srand1    nrand    csw    setmem    movmem    call    calla    inp
  12. ;    outp    peek    poke    sleep    pause    setfcb    read    write
  13. ;    open    close    creat    unlink    seek    tell    rename    fabort
  14. ;    fcbaddr    exit    bdos    bios    codend    externs    endext    topofmem
  15. ;    exec    execl    execv    sbrk    rsvstk
  16. ;
  17.  
  18.     maclib bds
  19.  
  20.     FUNCTION    getchar
  21.     lda    ungetl    ;any character pushed back?
  22.     ora    a
  23.     mov    l,a
  24.     jz    gch2
  25.     xra    a    ;yes. return it and clear the pushback
  26.     sta    ungetl    ;byte in C.CCC.
  27.     mvi    h,0
  28.     ret
  29.  
  30. gch2:    push    b
  31.     mvi    c,conin
  32.     call    bdos
  33.     pop    b
  34.     cpi    cntrlc    ;control-C ?
  35.     jz    base    ;if so, reboot.
  36.     cpi    1ah    ;control-Z ?
  37.     lxi    h,-1    ;if so, return -1.
  38.     rz
  39.     mov    l,a
  40.     cpi    cr    ;carriage return?
  41.     jnz    gch3
  42.     push    b
  43.     mvi    c,conout    ;if so, also echo linefeed
  44.     mvi    e,lf
  45.     call    bdos
  46.     pop    b
  47.     mvi    l,newlin    ;and return newline (linefeed)..
  48.  
  49. gch3:    mvi    h,0
  50.     ret
  51.     ENDFUNC
  52.  
  53.     FUNCTION    kbhit
  54.     lda    ungetl    ;any character ungotten?
  55.     mvi    h,0
  56.     mov    l,a
  57.     ora    a
  58.     rnz        ;if so, return true
  59.  
  60.     push    b
  61.     mvi    c,cstat    ;else interrogate console status
  62.     call    bdos
  63.     pop    b
  64.  
  65.     ora    a    ;0 returned by BDOS if no character ready
  66.     lxi    h,0
  67.     rz        ;return 0 in HL if no character ready
  68.     inr    l    ;otherwise return 1 in HL
  69.     ret
  70.     ENDFUNC kbhit
  71.  
  72.     FUNCTION    ungetch
  73.     lda    ungetl
  74.     mov    l,a
  75.     push    h
  76.     call    ma2toh
  77.     sta    ungetl
  78.     pop    h
  79.     mvi    h,0
  80.     ret
  81.     ENDFUNC ungetch
  82.  
  83.     FUNCTION    putchar
  84.     call    ma1toh    ;get character in A
  85.     push    b
  86.     mvi    c,conout
  87.     cpi    newlin    ;newline?
  88.     jnz    put1    ;if not, just go put out the character
  89.     mvi    e,cr    ;else...put out CR-LF
  90.     call    bdos
  91.     mvi    c,conout
  92.     mvi    a,lf
  93.  
  94. put1:    mov    e,a
  95.     call    bdos
  96.  
  97. put2:    mvi    c,cstat    ;now, is input present at the console?
  98.     call    bdos
  99.     ora    a
  100.     jnz    put3
  101.     pop    b    ;no...all done.
  102.     ret
  103.  
  104. put3:    mvi    c,conin    ;yes. sample it (this will always echo the
  105.     call    bdos    ;    character to the screen, alas)
  106.     cpi    cntrlc    ;is it control-C?
  107.     jz    base    ;if so, abort and reboot
  108.     pop    b    ;else ignore it.
  109.     ret
  110.     ENDFUNC
  111.  
  112.     FUNCTION    putch
  113.     call    ma1toh
  114.     push    b
  115.     mvi    c,conout
  116.     mov    e,a
  117.     cpi    newlin
  118.     jnz    putch1    ;if not newline, just put it out
  119.     mvi    e,cr    ;else put out CR-LF
  120.     call    bdos
  121.     mvi    c,conout
  122.     mvi    e,lf
  123. putch1:    call    bdos
  124.     pop    b
  125.     ret
  126.     ENDFUNC
  127.  
  128.     FUNCTION    gets
  129.     call    ma1toh    ;get destination address
  130.     push    b    ;save BC
  131.     push    h
  132.     push    h
  133.     lxi    h,-150    ;use space below stack for reading line
  134.     dad    sp
  135.     push    h    ;save buffer address
  136.     mvi    m,88h    ;Allow a max of about 135 characters
  137.     mvi    c,getlin
  138.     xchg        ;put buffer addr in DE
  139.     call    bdos    ;get the input line
  140.     mvi    c,conout
  141.     mvi    e,lf    ;put out a LF
  142.     call    bdos
  143.     pop    h    ;get back buffer address
  144.     inx    h    ;point to returned char count
  145.     mov    b,m    ;set B equal to char count
  146.     inx    h    ;HL points to first char of line
  147.     pop    d    ;DE points to start destination area
  148. copyl:    mov    a,b    ;copy line to start of buffer
  149.     ora    a
  150.     jz    gets2
  151.     mov    a,m
  152.     stax    d
  153.     inx    h
  154.     inx    d
  155.     dcr    b
  156.     jmp    copyl
  157.     
  158. gets2:    xra    a    ;store terminating null
  159.     stax    d
  160.     pop    h    ;return buffer address in HL
  161.     pop    b
  162.     ret
  163.     ENDFUNC
  164.  
  165.  
  166.     FUNCTION    rand
  167.     lhld    rseed
  168.     xchg
  169.     mvi    a,48h
  170.     ana    e
  171.     jz    rand1
  172.     jpe    rand1
  173.     stc
  174. rand1:    lhld    rseed+2
  175.     mov    a,h
  176.     ral
  177.     mov    h,a
  178.     mov    a,l
  179.     ral
  180.     mov    l,a
  181.     shld    rseed+2
  182.     mov    a,d
  183.     ral
  184.     mov    h,a
  185.     mov    a,e
  186.     ral
  187.     mov    l,a
  188.     shld    rseed
  189.     mov    a,h
  190.     ani    7fh
  191.     mov    h,a
  192.     ret
  193.     ENDFUNC
  194.  
  195.     FUNCTION    srand
  196.     call    ma1toh
  197.     mov    a,h
  198.     ora    l
  199.     jz    srand2
  200.     shld    rseed
  201.     shld    rseed+2
  202.     ret
  203.  
  204. srand2:    lxi    d,stg1
  205.     push    b
  206.     mvi    c,9
  207.     call    bdos
  208.     lxi    h,0bdbdh
  209. srand3:    push    h
  210.     mvi    c,11
  211.     call    bdos
  212.     pop    h
  213.     inx    h
  214.     inx    h
  215.     inx    h
  216.     ani    1
  217.     jz    srand3
  218.     shld    rseed
  219.     shld    rseed+2
  220.     mvi    c,conout
  221.     mvi    e,cr
  222.     call    bdos
  223.     mvi    c,conout
  224.     mvi    e,lf
  225.     call    bdos
  226.     mvi    c,conin    ;clear the character
  227.     call    bdos
  228.     pop    b
  229.     ret
  230. stg1:    db 'Wait a few seconds, and type a CR: $'
  231.     ENDFUNC
  232.  
  233.  
  234.     FUNCTION    srand1
  235.     EXTERNAL    puts
  236.     call    ma1toh
  237.     push    h
  238.     call    puts    ;print prompt string
  239.     pop    h
  240.     push    b
  241.     lxi    h,5678h
  242. sr1a:    push    h
  243.     mvi    c,cstat
  244.     call    bdos
  245.     pop    h
  246.     inx    h
  247.     inx    h
  248.     inx    h
  249.     ora    a
  250.     jz    sr1a
  251.     shld    rseed
  252.     shld    rseed+2
  253.     pop    b
  254.     ret
  255.     ENDFUNC
  256.  
  257.     FUNCTION    nrand
  258.     EXTERNAL    puts
  259.     call    arghak
  260.     lhld    arg1    ;get n (1st arg)
  261.     mov    a,h
  262.     ana    l
  263.     cpi    255    ;was it -1 (set seed) ?
  264.     jnz    nrand1
  265.     lhld    arg2    ;copy seed
  266.     shld    seed
  267.     lhld    arg3
  268.     shld    seed+2
  269.     lhld    arg4
  270.     shld    seed+4    
  271.     ret        ;all done
  272.  
  273. nrand1:    push    b
  274.     mov    a,h    ;look at first arg again
  275.     ora    l
  276.     jnz    nrand3    ;is it 0 (randomize)?
  277.     lhld    arg2
  278.     push    h    ;yes. print out string
  279.     call    puts    ;call    puts
  280.     pop    d
  281.     lxi    h,5a97h    ;yes. start w/something odd
  282. nrand2:    push    h
  283.     mvi    c,cstat    ;interrogate console status
  284.     call    bdos
  285.     pop    h
  286.     inx    h    ;and keep it odd
  287.     inx    h    ;and growing
  288.     ora    a
  289.     jz    nrand2    ;until user types something.
  290.     shld    seed    ;then plaster the value all over the
  291.     shld    seed+2    ;seed.
  292.     shld    seed+4
  293.     pop    b
  294.     ret
  295.  
  296. nrand3:    lda    seed    ;now compute next random number. from this
  297.     ori    1    ; point on, the code is that of Prof. Paul Gans
  298.     sta    seed    ;lsb of SEED must be 1
  299.     
  300.     mvi    b,6    ;clear 6 PROD bytes to 0
  301.     lxi    h,prod
  302. randm1:    mvi    m,0
  303.     inx    h
  304.     dcr    b
  305.     jnz    randm1
  306.  
  307.     lxi    b,6    ;set byte counter
  308. randm2:    lxi    h,plier-1
  309.     dad    b    ;make addr of lsb of PLIER
  310.     mov    a,m    ;PLIER byte
  311.     push    b    ;save byte counter
  312.     mvi    b,8    ;set bit counter
  313.  
  314. randm3:    mov    d,a    ;save PLIER byte
  315.     lxi    h,prod    ;shift whole PROD left one bit
  316.     mvi    c,6
  317.     xra    a
  318. randm4:    mov    a,m    ;get byte    
  319.     ral        ;shift left
  320.     mov    m,a    ;put byte
  321.     inx    h
  322.     dcr    c
  323.     jnz    randm4
  324.  
  325.     mov    a,d    ;recover PLIER byte
  326.     ral        ;look at current high bit
  327.     jnc    randm6    ;0 means no add cycle
  328.  
  329.     push    psw    ;add SEED to PROD
  330.     xra    a
  331.     mvi    c,6
  332.     lxi    h,prod
  333.     lxi    d,seed
  334. randm5:    ldax    d
  335.     adc    m
  336.     mov    m,a
  337.     inx    h
  338.     inx    d
  339.     dcr    c
  340.     jnz    randm5
  341.     pop    psw
  342.  
  343. randm6:    dcr    b    ;test bit counter
  344.     jnz    randm3    ;go cycle more bits
  345.     pop    b    ;recover byte counter
  346.     dcr    c    ;test it
  347.     jnz    randm2    ;go process more bytes
  348.  
  349.     mvi    b,6    ;complement PROD, add 1 to it,
  350.     lxi    h,seed    ;and transfer it to SEED.
  351.     lxi    d,prod
  352.     xra    a
  353.     cmc
  354. randm7:    ldax    d
  355.     cma
  356.     aci    0
  357.     mov    m,a
  358.     inx    h
  359.     inx    d
  360.     dcr    b
  361.     jnz    randm7
  362.  
  363.     dcx    h    ;put the two high order bytes
  364.     mov    a,m    ;into HL for return to C, not
  365.     ani    7fh    ;neglecting to zero the high
  366.     mov    h,a    ;order bit so a positive int
  367.     lda    seed+4    ;is returned
  368.     mov    l,a
  369.     pop    b
  370.     ret
  371.  
  372. plier:    db    0c5h,87h,1
  373.     db    0eh,9ah,0e0h    
  374.  
  375. seed:    db    1,0,0,0,0,0
  376.  
  377. prod:    db    0,0,0,0,0,0
  378.     ENDFUNC
  379.  
  380.     FUNCTION    csw
  381.     in    255
  382.     mov    l,a
  383.     mvi    h,0
  384.     ret
  385.     ENDFUNC
  386.  
  387.     FUNCTION    setmem
  388.     call    arghak
  389.     push    b
  390.     lhld    arg2
  391.     xchg
  392.     lhld    arg1
  393.     lda    arg3
  394.     mov    c,a
  395.     inx    d
  396. setm2:    dcx    d
  397.     mov    a,d
  398.     ora    e
  399.     jnz    setm3
  400.     pop    b
  401.     ret
  402.  
  403. setm3:    mov    m,c
  404.     inx    h
  405.     jmp    setm2
  406.     ENDFUNC
  407.  
  408.     FUNCTION    movmem
  409.     call    arghak
  410.     lhld    arg3    ;get block length
  411.     mov    a,h
  412.     ora    l
  413.     rz        ;do nothing if zero length
  414.     push    b
  415.     mov    b,h
  416.     mov    c,l    ;set BC to length
  417.     lhld    arg2    ;get dest addr
  418.     xchg        ;put in DE
  419.     lhld    arg1    ;get source addr in HL
  420.     call    cmphd    ;if source < dest, do tail-first
  421.     jc    tailf    ;else do head-first
  422.  
  423. headf:    mvi    a,2    ;test for Z-80
  424.     inr    a
  425.     jpe    m8080h    ;Z80?
  426.     db    0edh,0b0h    ;yes. do block move.
  427.     pop    b
  428.     ret        ;and done.
  429.  
  430. m8080h:    mov    a,m
  431.     stax    d
  432.     inx    h
  433.     inx    d
  434.     dcx    b
  435.     mov    a,b
  436.     ora    c
  437.     jnz    m8080h
  438.     pop    b
  439.     ret
  440.  
  441. tailf:    dcx    b    ;tail first. Compute new source
  442.     dad    b    ;and destination addresses
  443.     xchg
  444.     dad    b
  445.     xchg
  446.     inx    b
  447.     mvi    a,2    ;test for Z80
  448.     inr    a
  449.     jpe    m8080t    ;Z80?
  450.     db    0edh,0b8h    ;yes. do block move.
  451.     pop    b
  452.     ret
  453.  
  454. m8080t:    mov    a,m
  455.     stax    d
  456.     dcx    h
  457.     dcx    d
  458.     dcx    b
  459.     mov    a,b
  460.     ora    c
  461.     jnz    m8080t
  462.     pop    b
  463.     ret
  464.  
  465. cmphd:    mov    a,h
  466.     cmp    d
  467.     rnz
  468.     mov    a,l
  469.     cmp    e
  470.     ret
  471.     ENDFUNC
  472.  
  473.     FUNCTION    call
  474.     call    arghak
  475.     push    b
  476.     lhld    arg5
  477.     xchg
  478.     lhld    arg4
  479.     mov    b,h
  480.     mov    c,l
  481.     lda    arg2
  482.     lxi    h,call2
  483.     push    h
  484.     lhld    arg1
  485.     push    h
  486.     lhld    arg3
  487.     ret
  488.  
  489. call2:    pop    b
  490.     ret
  491.     ENDFUNC
  492.  
  493.     FUNCTION    calla
  494.     call    arghak
  495.     push    b
  496.     lhld    arg5    ;get de value
  497.     xchg
  498.     lhld    arg4    ;get bc value
  499.     mov    b,h
  500.     mov    c,l
  501.     lda    arg2    ;get a value
  502.     lxi    h,calla2  ;get return address
  503.     push    h    ;push    it
  504.     lhld    arg1    ;get address of routine
  505.     push    h
  506.     lhld    arg3    ;get hl value    
  507.     ret        ;call    routine
  508.     
  509. calla2:    mov    l,a    ;put A value in HL
  510.     mvi    h,0    ;clear high byte
  511.     pop    b
  512.     ret
  513.     ENDFUNC
  514.  
  515.     FUNCTION    inp
  516.     call    ma1toh
  517.     sta    iohack+1    ;store as arg to ram area input subroutine
  518.     call    iohack        ;call the subroutine to get value
  519.     mov    l,a        ;and put into HL
  520.     mvi    h,0
  521.     ret
  522.     ENDFUNC
  523.  
  524.     FUNCTION    outp
  525.     call    ma1toh        ;get port number
  526.     sta    iohack+4    ;store as arg to ram area output subroutine
  527.     call    ma2toh        ;get data byte
  528.     call    iohack+3    ;output it
  529.     ret
  530.     ENDFUNC
  531.  
  532.     FUNCTION    peek
  533. peek:    call    ma1toh
  534.     mov    l,m
  535.     mvi    h,0
  536.     ret
  537.     ENDFUNC peek
  538.  
  539.  
  540.     FUNCTION    poke
  541.     call    arghak
  542.     lhld    arg1
  543.     lda    arg2
  544.     mov    m,a
  545.     ret
  546.     ENDFUNC
  547.  
  548.     FUNCTION    sleep
  549.     call    ma1toh
  550.     push    b
  551.     inx    h
  552. sl1:    dcx    h
  553.     mov    a,h
  554.     ora    l
  555.     jnz    sl1a
  556.     pop    b
  557.     ret
  558.  
  559. sl1a:    lxi    d,10000
  560. sl2:    dcx    d
  561.     mov    a,d
  562.     ora    e
  563.     jnz    sl2
  564.     push    h
  565.     mvi    c,cstat
  566.     call    bdos
  567.     ora    a
  568.     pop    h
  569.     jz    sl1
  570.     push    h
  571.     mvi    c,conin
  572.     call    bdos
  573.     cpi    cntrlc
  574.     jz    base
  575.     pop    h
  576.     jmp    sl1
  577.     ENDFUNC
  578.  
  579.     FUNCTION    pause
  580.     push    b
  581. paus1:    mvi    c,cstat
  582.     call    bdos
  583.     ora    a
  584.     jz    paus1
  585.     pop    b
  586.     ret
  587.     ENDFUNC
  588.  
  589.  
  590.     FUNCTION    setfcb
  591.     call    arghak
  592.     push    b
  593.     lhld    arg2    ;get pointer to name text
  594. igsp:    mov    a,m
  595.     inx    h
  596.     cpi    ' '
  597.     jz    igsp
  598.     cpi    tab
  599.     jz    igsp
  600.     dcx    h
  601.     xchg        ;set DE pointing to 1st non-space char
  602.     lhld    arg1    ;get --> fcb area
  603.     call    setfcb    ; do it
  604.     lxi    h,0    ;all OK.
  605.     pop    b
  606.     ret
  607.     ENDFUNC
  608.  
  609.     FUNCTION    read
  610.     call    arghak
  611.     lda    arg1
  612.     call    fgfd
  613.     jc    error    ;error if illegal fd
  614.     mov    a,m
  615.     ani    2    ;open for read?
  616.     jz    error    ;error if not
  617.     push    b
  618.     lda    arg1
  619.     call    fgfcb
  620.     shld    tmp2    ;tmp2 will hold dma addr
  621.     lxi    h,0    ;count of # of successful sectors read
  622.     shld    tmp2a    ; will be kept at tmp2a
  623. read2:    lhld    arg3    ;done?
  624.     mov    a,h
  625.     ora    l
  626.     jz    read4
  627.  
  628. read2a:    lhld    arg2    ;else read another sector
  629.     xchg        ;DE is dma addr
  630.     mvi    c,sdma
  631.     call    bdos    ;set DMA
  632.     lhld    tmp2
  633.     xchg        ;DE is fcb addr
  634.     mvi    c,reads
  635.     push    d    ;save de so we can fudge nr field if
  636.     call    bdos    ;we stop reading on extent boundary...
  637.     pop    d    ; CP/M is a pain.
  638.     cpi    2
  639.     pop    b
  640.     jz    error    ;if error, abort
  641.     push    b
  642.     cpi    1
  643.     jnz    read6    ;EOF?
  644.  
  645. read3:    lxi    h,32    ;yes. are we on extent boundary?
  646.     dad    d    ;if so, adjust for CP/M's stupidity here
  647.     mov    a,m    ;by turning an 80h sector count into 00h.
  648.     cpi    80h
  649.     jnz    read4
  650.     mvi    m,0    ;yes. reset nr to 0...CP/M leaves it at 80h!
  651. read4:    lhld    tmp2a
  652. read5:    pop    b
  653.     ret
  654.  
  655. read6:    lhld    arg3
  656.     dcx    h
  657.     shld    arg3
  658.     lhld    arg2
  659.     lxi    d,128
  660.     dad    d
  661.     shld    arg2
  662.     lhld    tmp2a
  663.     inx    h
  664.     shld    tmp2a
  665.     jmp    read2
  666.     ENDFUNC
  667.  
  668.     FUNCTION    write
  669.     call    arghak
  670.     lda    arg1
  671.     call    fgfd
  672.     jc    error
  673.     mov    a,m
  674.     ani    4
  675.     jz    error
  676.     push    b
  677.     lda    arg1
  678.     call    fgfcb
  679.     shld    tmp2
  680.     lxi    h,0
  681.     shld    tmp2a
  682.     lxi    d,tbuff     ;80 for normal CP/M, else 4280
  683.     mvi    c,sdma
  684.     call    bdos
  685.  
  686. writ1:    lhld    arg3    ;done yet?
  687.     mov    a,h
  688.     ora    l
  689.     lhld    tmp2a    ;if so, return count
  690.     jz    writ3
  691.     lhld    arg2    ;else copy next 128 bytes down to tbuff
  692.     lxi    d,tbuff    ;80 for normal CP/M, else 4280
  693.     mvi    b,128
  694. writ2:    mov    a,m
  695.     stax    d
  696.     inx    h
  697.     inx    d
  698.     dcr    b
  699.     jnz    writ2
  700.     shld    arg2    ;save -> to next 128 bytes
  701.     lhld    tmp2    ;get addr of fcb
  702.     xchg
  703.     mvi    c,writs    ;go write
  704.     call    bdos
  705.     ora    a    ;error?
  706.     lhld    tmp2a    ;if so, return # of successfully written
  707.     jnz    writ3    ;  sectors.
  708.         
  709.     inx    h    ; else bump successful sector count,
  710.     shld    tmp2a
  711.     lhld    arg3    ; debump countdown,
  712.     dcx    h
  713.     shld    arg3
  714.     jmp    writ1    ; and go try next sector
  715. writ3:    pop    b
  716.     ret
  717.     ENDFUNC
  718.  
  719.     FUNCTION    open
  720.     call    arghak
  721.     xra    a
  722.     call    fgfcb    ;any fcb's free?
  723.     jc    error    ;if not, error
  724.     sta    tmp
  725.     xchg
  726.     lhld    arg1
  727.     xchg
  728.     push    b
  729.     call    setfcb
  730.     mvi    c,openc
  731.     call    bdos
  732.     cpi    errorv    ;successful open?
  733.     pop    b
  734.     jz    error    ;if not, error
  735.     lda    tmp
  736.     call    fgfd    ;get HL pointing to fd table entry
  737.     lda    arg2
  738.     ora    a    ;open for read?
  739.     mvi    d,3
  740.     jz    open1
  741.     dcr    a
  742.     mvi    d,5
  743.     jz    open1    ;write?
  744.     dcr    a
  745.     jnz    error    ;else must be both or bad mode.
  746.     mvi    d,7
  747. open1:    mov    m,d
  748.     lda    tmp
  749.     mov    l,a
  750.     mvi    h,0
  751.     ret
  752.     ENDFUNC
  753.  
  754.     FUNCTION    close
  755.     jmp    close    ;jump to the close routine in C.CCC
  756.     ENDFUNC
  757.  
  758.  
  759.  
  760.     FUNCTION    creat
  761.     EXTERNAL    unlink,open
  762.     call    arghak
  763.     lhld    arg1
  764.     push    b
  765.     push    h
  766.     call    unlink    ;erase any old versions of file
  767.     pop    d
  768.     mvi    c,creatc
  769.     lxi    d,fcb
  770.     call    bdos
  771.     cpi    errorv
  772.     pop    b
  773.     jz    error
  774.     lxi    h,2
  775.     push    h
  776.     lhld    arg1
  777.     push    h
  778.     call    open
  779.     pop    d
  780.     pop    d
  781.     ret
  782.     ENDFUNC creat
  783.  
  784.  
  785.     FUNCTION    unlink
  786.     call    ma1toh
  787.     push    b
  788.     xchg    
  789.     lxi    h,fcb
  790.     call    setfcb
  791.     mvi    c,delc
  792.     call    bdos
  793.     lxi    h,0
  794.     pop    b
  795.     ret
  796.     ENDFUNC
  797.  
  798.  
  799.     FUNCTION    seek
  800.     EXTERNAL    tell
  801.     call    arghak    ;copy arguments to args area
  802.     lda    arg1
  803.     call    fgfcb
  804.     jc    error    ;error if file not open
  805.     push    b
  806.     push    h    ;save fcb address
  807.  
  808.     lhld    arg1
  809.     push    h
  810.     call    tell    ;get r/w pointer position for the file
  811.     pop    d
  812.  
  813.     xchg        ;put present pos in DE
  814.     lda    arg3
  815.     lhld    arg2    ;get offset in HL
  816.     ora    a    ;absolute offset?
  817.     jz    seek2    ;if so, offset is new position
  818.     dad    d    ;else add offset to current position
  819. seek2:    mov    a,l    ;convert to extent and sector values
  820.     rlc
  821.     mov    a,h
  822.     ral
  823.     ani    7fh
  824.     sta    tmp
  825.     xthl
  826.     lxi    d,12
  827.     push    h
  828.     dad    d
  829.     cmp    m    ;jumping over extent boundary?
  830.     jz    seek5
  831.     xthl        ;yes.
  832.     xchg
  833.     mvi    c,closec    ;close old extent
  834.     push    d
  835.     call    bdos
  836.     pop    d
  837.     pop    h
  838.     cpi    errorv
  839.     jnz    seek4
  840. seek3:    pop    d
  841.     pop    b
  842.     jmp    error
  843.  
  844. seek4:    lda    tmp
  845.     mov    m,a
  846.     push    d
  847.     mvi    c,openc    ;and open new one.
  848.     call    bdos
  849. seek5:    pop    d
  850.     cpi    errorv
  851.     jz    seek3
  852.     lxi    h,32    ;and set nr field
  853.     dad    d
  854.     pop    d
  855.     mov    a,e
  856.     ani    7fh
  857.     mov    m,a
  858.     xchg        ;return new sector # in HL
  859.     pop    b
  860.     ret
  861.     ENDFUNC
  862.  
  863.     FUNCTION    tell
  864.     call    ma1toh    ;get fd value in A
  865.     call    fgfcb
  866.     jc    error
  867.     push    b
  868.     lxi    d,12
  869.     dad    d
  870.     mov    b,m    ;put extent # in B
  871.     lxi    d,20
  872.     dad    d
  873.     mov    c,m    ;put sector # in C
  874.     xra    a    ;rotate extent right one bit, old b0 --> Carry
  875.     mov    a,b
  876.     rar
  877.     mov    h,a    ;rotated value becomes high byte of tell position
  878.     mvi    a,0    ;rotate b0 of extent into A
  879.     rar
  880.     mov    b,a    ;save rotated extent number in B
  881.     add    c    ;add rotated extent number to sector number
  882.     mov    l,a    ;and result becomes low byte of tell position
  883.     mov    a,c    ;if both rotated extent # and sector # has bit 7 hi,
  884.     ana    b    ;then the sum had an overflow, so...
  885.     jp    tell2
  886.     inr    h    ;bump position number by 256
  887. tell2:    pop    b    ;and all done.
  888.     ret
  889.     ENDFUNC
  890.  
  891.     FUNCTION    rename
  892.     call    arghak
  893.     push    b
  894. renam:    lhld    arg1
  895.     xchg
  896.     lxi    h,wfcb
  897.     call    setfcb
  898.     lhld    arg2
  899.     xchg
  900.     lxi    h,wfcb+16
  901.     call    setfcb
  902.     lxi    d,wfcb
  903.     mvi    c,renc
  904.     call    bdos
  905.     pop    b
  906.     cpi    errorv
  907.     jz    error
  908.     lxi    h,0
  909.     ret
  910. wfcb:    ds 53
  911.     ENDFUNC
  912.  
  913.     FUNCTION    fabort
  914.     call    ma1toh
  915.     call    fgfd
  916.     jc    error
  917.     mvi    m,0    ;clear entry in fd table
  918.     lxi    h,0
  919.     ret
  920.     ENDFUNC
  921.  
  922.     FUNCTION    fcbaddr
  923.     call    ma1toh
  924.     call    fgfd    ;is it an open file?
  925.     jc    error
  926.     call    ma1toh
  927.     call    fgfcb    ;get fcb addr in HL
  928.     ret
  929.     ENDFUNC
  930.  
  931.     FUNCTION    exit
  932.     jmp    exit
  933.     ENDFUNC
  934.  
  935.     FUNCTION    bdos
  936.     call    arghak    
  937.     push    b
  938.     lda    arg1    ;get C value
  939.     mov    c,a
  940.     lhld    arg2    ;get DE value
  941.     xchg        ;put in DE
  942.     call    bdos    ;make the bdos call
  943.     pop    b
  944.     ret        ;and return to caller
  945.     ENDFUNC
  946.  
  947.     FUNCTION    bios
  948.     call    arghak    
  949.     push    b
  950.     lhld    base+1    ;get addr of jump table + 3
  951.     dcx    h    ;set to addr of first jump
  952.     dcx    h
  953.     dcx    h
  954.     lda    arg1    ;get function number (1-85)
  955.     mov    b,a    ;multiply by 3
  956.     add    a
  957.     add    b
  958.     mov    e,a    ;put in DE
  959.     mvi    d,0
  960.     dad    d    ;add to base of jump table
  961.     push    h    ;and save for later
  962.     lhld    arg2    ;get value to be put in BC
  963.     mov    b,h    ;and put it there
  964.     mov    c,l
  965.     lxi    h,retadd    ;where call to bios will return to
  966.     xthl        ;get address of vector in HL
  967.     pchl        ;and go to it...
  968. retadd:    mov    l,a    ;all done. now put return value in HL
  969.     mvi    h,0
  970.     pop    b
  971.     ret        ;and return to caller
  972.     ENDFUNC
  973.  
  974.     FUNCTION    codend
  975.     lhld    codend
  976.     ret
  977.     ENDFUNC
  978.  
  979.     FUNCTION    externs
  980.     lhld    extrns
  981.     ret
  982.     ENDFUNC
  983.  
  984.     FUNCTION    endext
  985.     lhld    freram
  986.     ret
  987.     ENDFUNC
  988.  
  989.     FUNCTION    topofmem  
  990.     lhld    base+6
  991.     lda    tpa    ;check for "NOBOOT" hackery
  992.     cpi    21h    ; "lxi h" at start of C.CCC (as inserted by NOBOOT)?
  993.     dcx    h    ;if CCC doesn't begin with "lxi h," then top of
  994.     rnz        ;memory is just below the base of the bdos
  995.     lxi    d,-2100    ;else subtract CCP size (plus little more for good
  996.     dad    d    ;measure) and return that as top of memory.
  997.     ret
  998.     ENDFUNC
  999.  
  1000.     FUNCTION    exec
  1001.     EXTERNAL    execl
  1002.     call ma1toh    ;get filename
  1003.     lxi d,0        ;load null parameter in DE
  1004.     push d        ;push null parameter
  1005.     push h        ;push filename
  1006.     call execl    ;do an execl
  1007.     pop d        ;clean up stack
  1008.     pop d
  1009.     ret
  1010.     ENDFUNC        
  1011.  
  1012.     FUNCTION    execl
  1013.     call    arghak
  1014.     push    b
  1015.     lhld    arg1
  1016.     xchg
  1017.     lxi    h,-60    ;compute &nfcb for use here
  1018.     dad    sp
  1019.     push    h    ; save for much later (will pop    into BC)
  1020.       push    h    ;make a few copies for local use below
  1021.     push    h
  1022.     call    setfcb    ;set up COM file for execl-ing
  1023.     pop    h    ;get new fcb addr
  1024.     lxi    b,9    ;set extension to COM
  1025.     dad    b
  1026.     mvi    m,'C'
  1027.     inx    h
  1028.     mvi    m,'O'
  1029.     inx    h
  1030.     mvi    m,'M'
  1031.     pop    d    ;get new fcb addr again
  1032.     mvi    c,openc    ;open the file for reading
  1033.     call    bdos
  1034.     cpi    errorv
  1035.     jnz    noerrr
  1036. err:    pop    h
  1037.     pop    b
  1038.     jmp    error
  1039.  
  1040. noerrr:    lhld    arg2    ;any first parameter?
  1041.     mov    a,h
  1042.     ora    l
  1043.     jnz    excl0
  1044.     lxi    d,arg2    ;no...null out first default fcb slot
  1045.     push    d
  1046.     lxi    h,fcb
  1047.     call    setfcb
  1048.     pop    h
  1049.     jmp    excl0a    ;and go null out 2nd fcb slot
  1050.  
  1051. excl0:    xchg        ;yes.. place into first default fcb slot
  1052.     lxi    h,fcb
  1053.     call    setfcb
  1054.     lhld    arg3    ;any second parameter given?
  1055.     mov    a,h
  1056.     ora    l
  1057.     jnz    excl0a
  1058.     lxi    h,arg3
  1059.  
  1060. excl0a:    xchg        ;yes: stick it into second default fcb slot
  1061.     lxi    h,fcb+16
  1062.     call    setfcb    
  1063.     lxi    d,tbuff+1   ;now construct command line:
  1064.     xra    a    ;  zero tbuff+1 just in case there
  1065.     stax    d    ;  are no arg strings
  1066.     lxi    h,8    ;get pointer to 1st arg string in HL
  1067.     dad    sp    ;   by offsetting 4 objects from the current SP
  1068.     mvi    b,0    ;char count for com. line buf.
  1069. excl1:    push    h    ;and construct command line
  1070.     mov    a,m    ;get addr of next arg string pointer
  1071.     inx    h
  1072.     mov    h,m
  1073.     mov    l,a    ;0000 indicates end of list.
  1074.     ora    h    ;end of list?
  1075.     jz    excl3
  1076.  
  1077.     mvi    a,' '    ;no. install next string
  1078.     dcx    h
  1079. excl2:    call    mpuc    ;convert to upper case for command line buffer
  1080.     stax    d
  1081.     inx    d
  1082.     inr    b
  1083.     inx    h
  1084.     mov    a,m
  1085.     ora    a    ;end of string?
  1086.     jnz    excl2
  1087.     pop    h    ;yes.
  1088.     inx    h    ;bump param pointer
  1089.     inx    h    
  1090.     jmp    excl1    ;and go do next string
  1091.  
  1092. excl3:    pop    h    ;clean up stack
  1093.     mov    a,b    ;check for command buffer overflow
  1094.     cpi    53h
  1095.     jc    excl30    ;if no overflow, go load file
  1096.     lxi    d,errmsg
  1097.     mvi    c,9    ;else comlain and abort...
  1098.     call    bdos
  1099.     jmp    err
  1100.  
  1101. errmsg:    db    7,'EXECL: Too much text',cr,lf,'$'
  1102.  
  1103. excl30:    lxi    h,tbuff    ;set length of command line
  1104.     mov    m,b    ;at location tbuff
  1105.  
  1106. excl3a:    lxi    d,code0    ;copy loader down to end of tbuff
  1107.     lxi    h,tpa-42
  1108.     mvi    b,42    ;length of loader
  1109. excl4:    ldax    d
  1110.     mov    m,a
  1111.     inx    d
  1112.     inx    h
  1113.     dcr    b
  1114.     jnz    excl4
  1115.  
  1116.     pop    b    ;get fcb pointer in BC
  1117.             ;reset the SP:
  1118.     lhld    base+6    ;get BDOS pointer in HL
  1119.     lda    tpa    ;look at first op byte of run-time pkg
  1120.     cpi    31h    ;begin with "lxi sp,"?
  1121.     jnz    go0    ;if so, use the same value now...
  1122.     lhld    tpa+1    ;else get special SP value
  1123.     jmp    go1
  1124.  
  1125. go0:    cpi    21h    ;begin with "lxi h" (the NOBOOT sequence?)
  1126.     jnz    go1    ;if not, just use the BDOS addr as top of memory
  1127.     lxi    d,-2050    ;for NOBOOT, subtract 2100 from BDOS addr
  1128.     dad    d    ;and make that the new SP
  1129. go1:    sphl
  1130.  
  1131.     lxi    h,base
  1132.     push    h    ;set base of ram as return addr
  1133.     jmp    tpa-42    ;(go to `code0:')
  1134.  
  1135. mpuc:    cpi    61h    ;convert character in A to upper case
  1136.     rc
  1137.     cpi    7bh
  1138.     rnc
  1139.     sui    32
  1140.     ret
  1141.  
  1142. ;
  1143. ; This loader code is now: 42 bytes long.
  1144. ;
  1145.  
  1146. code0:    lxi    d,tpa    ;destination address of new program
  1147. code1:    push    d    ;push    dma addr
  1148.     push    b    ;push    fcb pointer
  1149.     mvi    c,sdma    ;set DMA address for new sector
  1150.     call    bdos
  1151.     pop    d    ;get pointer to working fcb in DE
  1152.     push    d    ;and re-push    it
  1153.     mvi    c,reads    ;read a sector
  1154.     call    bdos
  1155.     pop    b    ;restore fcb pointer into BC
  1156.     pop    d    ;and dma address into DE
  1157.     ora    a    ;end of file?
  1158.     jz    tpa-8    ;if not, get next sector (goto `code2:')
  1159.     mvi    c,sdma    ;reset DMA pointer
  1160.     lxi    d,tbuff
  1161.     call    bdos
  1162.     jmp    tpa    ;and go invoke the program
  1163.  
  1164. code2:    lxi    h,80h    ;bump dma address
  1165.     dad d
  1166.     xchg
  1167.     jmp    tpa-39     ;and go loop (at code1)
  1168.     ENDFUNC
  1169.  
  1170.     FUNCTION    execv
  1171.     EXTERNAL    execl
  1172.     call    arghak
  1173.     lhld    arg2    ;get -> arg list
  1174.     mvi    b,0    ;clear arg count
  1175. execv1:    inr    b    ;bump arg count
  1176.     mov    e,m
  1177.     inx    h
  1178.     mov    d,m
  1179.     inx    h
  1180.     mov    a,d
  1181.     ora    e    ;last arg?
  1182.     jnz    execv1    ;if not, keep looking for last one
  1183.  
  1184.     mov    a,b    ;save arg count in case of error
  1185.     sta    savcnt
  1186.  
  1187.     dcx    h    ;HL -> next to last arg
  1188. execv2:    mov    d,m    ;now push args on stack
  1189.     dcx    h
  1190.     mov    e,m
  1191.     dcx    h
  1192.     dcr     b
  1193.     push    d
  1194.     jnz    execv2
  1195.  
  1196. execv3:    lhld    arg1    ;get program name
  1197.     push    h    ;save as first arg to execl
  1198.     call    execl    ;go do it; shouldn't come back.
  1199.     lda    savcnt    ;woops, we're back. Must've been an error...
  1200.     add     a
  1201.     mov    l,a    ;put size of passed parameter list
  1202.     mvi    h,0    ;into HL, and adjust stack
  1203.     dad    sp
  1204.     sphl
  1205.     lxi    h,-1    ;return error value
  1206.     ret
  1207.  
  1208. savcnt:    ds     1    ;save arg count here
  1209.     ENDFUNC
  1210.  
  1211.  
  1212.  
  1213.     FUNCTION    sbrk
  1214.     call    ma1toh    ;get # of bytes needed in HL
  1215.     xchg        ;put into DE
  1216.     lhld    allocp    ;get current allocation pointer
  1217.     push    h    ;save it
  1218.     dad    d    ;get tentative last address of new segment
  1219.     jc    brkerr    ;better not allow it to go over the top!
  1220.     dcx    h
  1221.     xchg        ; now last addr is in DE
  1222.     lhld    alocmx    ;get safety factor
  1223.     mov    a,h    ;negate
  1224.     cma
  1225.     mov    h,a
  1226.     mov    a,l
  1227.     cma 
  1228.     mov    l,a        
  1229.     inx    h
  1230.     dad    sp    ;get HL = (SP - alocmx)
  1231.  
  1232.     call    cmpdh    ;is DE less than HL?
  1233.     jnc    brkerr    ;if not, can't provide the needed memory.
  1234.     xchg        ;else OK.
  1235.     inx    h
  1236.     shld    allocp    ;save start of next area to be allocated
  1237.     pop    h    ;get pointer to this area
  1238.     ret        ;and return with it.
  1239.  
  1240. brkerr:    pop    h    ;clean up stack
  1241.     jmp    error    ;and return with -1 to indicate can't allocate.
  1242.  
  1243. cmpdh:    mov    a,d
  1244.     cmp    h
  1245.     rc
  1246.     rnz
  1247.     mov    a,e
  1248.     cmp    l
  1249.     ret
  1250.     ENDFUNC
  1251.  
  1252.     FUNCTION    rsvstk
  1253.     call    ma1toh    ;get the value to reserve
  1254.     shld    alocmx    ;and set new safety factor
  1255.     ret
  1256.     ENDFUNC
  1257.  
  1258.