home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / jsage / znode3 / uploads / con20.lbr / CON20.MZC / CON20.MAC
Encoding:
Text File  |  1993-06-07  |  16.8 KB  |  725 lines

  1.  
  2. ; Program:  CON.MAC
  3. ; Author:   Joe Wright
  4. ; Date:     23 June 90
  5. ;
  6. vers    equ    20        ; Release  23 June 90
  7. ;
  8. ; A simple file concatenation program to combine two files to a third.
  9. ;
  10. ;    Syntax:  CON <[DU:]FILE3>=<[DU:]FILE1>,<[DU:]FILE2>[ /]
  11. ;
  12. ; There must be three valid filespecs on the command line.  The files
  13. ; are assumed to be ^Z terminated ASCII unless the '/' option is used.
  14. ; In that case, ^Z is ignored and the files are read until their end.
  15. ;
  16. ; Method:
  17. ; 1. Create FILE3 and copy FILE1 to it.
  18. ; 2. Append FILE2 to FILE3.
  19. ; 3. Close FILE3.
  20. ;
  21. ; We will read ASCII input files one character at a time and transfer
  22. ; them to a Write buffer.  The Write buffer will be written to FILE3
  23. ; as it fills and/or when the input file(s) are exhausted.  With the
  24. ; Binary option selected, Input files are read record at a time directly
  25. ; to the Output buffer.
  26.  
  27. ; No attempt is made to make this particularly fancy.  The interested
  28. ; hacker may want to make it a Z utility, treat NDIR, etc.
  29.  
  30. ; Assemble with any of:
  31. ;    M80 =CON
  32. ;    SLRMAC CON
  33. ;    SLRMAC CON/A        Direct .COM file
  34. ; or rename to CON.ASM and:
  35. ;    RMAC CON $-SPZ        Suppress .SYM and .PRN
  36. ;
  37. ; Link potential (MicroSoft) .REL to .COM with any of:
  38. ;    SLRNK /P:100,CON,CON/N/E
  39. ;    SLRNKP CON/N,/A:100,CON,/E
  40. ;    ZML CON
  41. ;    L80 /P:100,CON,CON/N/E
  42. ;    LINK CON[NR]        Suppress .SYM
  43.  
  44. ; Declare the Z80 macro library.  M80 needs the full filespec in
  45. ; upper case.  RMAC expects only MACLIB Z80 without the .LIB extent
  46. ; and will complain about it but will assemble correctly.  SLRMAC
  47. ; uses MACLIB Z80[.LIB] as a pseudop to select internal Z80 opcodes
  48. ; and does not actually read Z80.LIB.
  49.  
  50.     maclib    Z80.LIB        ; Upper case for M80
  51.  
  52. fcb1    equ    5ch
  53. tbuf    equ    80h
  54.  
  55. cr    equ    13
  56. lf    equ    10
  57. ctlz    equ    'Z'-40h
  58.  
  59. bufsiz    equ    16        ; Output buffer size (1..32k)
  60. tim    equ    8        ; Print 'Propeller' every 8 SETDMA's (1k)
  61.  
  62.     jmp    start        ; Jump over the patches
  63.  
  64. bin:    db    0        ; Default to ASCII mode (Patchable)
  65. buf:    db    bufsiz        ; In kilobytes (1024 bytes)
  66.  
  67. start:    sspd    stack        ; Save CCP stack pointer
  68.     lxi    sp,stack    ; Set local stack
  69. ;
  70. ; Sign us up.
  71. ;
  72.     call    print
  73.     db    ' CONcatenate v',vers/10+'0','.',vers mod 10+'0'
  74.     db    '  (',0
  75.  
  76.     lda    fcb1+1        ; Get first character of command line
  77.     cpi    ' '        ; Space?
  78.     jrz    help
  79.     cpi    '/'        ; Explicit Help?
  80.     jnz    go        ; Get over Help screen
  81.  
  82. help:    call    mode        ; Print 'Ascii' or 'Binary' modes
  83.     call    print
  84.     db    '  Syntax:  CON '
  85.     db    '[du:]outfile=[du:]infil1[,[du:]infil2][ /]',cr,lf
  86.     db    '    where [ /] option denotes Binary/Ascii toggle.',0
  87.     jmp    exit
  88. ;
  89. mode:    lda    bin        ; Get Mode byte
  90.     ora    a        ; Test it
  91.     jrz    defa        ; Ascii
  92.  
  93.     call    print
  94.     db    'Binary',0
  95.     jr    defx        ; Close it up
  96.  
  97. defa:    call    print
  98.     db    'Ascii',0
  99.  
  100. defx:    call    print
  101.     db    ')',cr,lf,0
  102.     ret
  103. ;
  104. ; Setup our pointers..
  105. ;
  106. go:    lxi    h,codend+255    ; Next page after stack
  107.     mvi    l,0        ; Round down to even page
  108.     shld    otbuf        ; Output buffer start
  109.     shld    otptr        ; Output pointer
  110. ;
  111. ; Check for valid Output buffer size
  112. ;
  113.     lda    buf        ; Output buffer size (1..32)
  114.     dcr    a        ; Rel 0..31
  115.     cpi    32        ; 32k is maximum
  116.     jnc    help        ; Quit through HELP
  117. ;
  118. ; Calculate and set Output buffer end address
  119. ;
  120.     inr    a        ; Restore A
  121.     add    a        ; X2
  122.     add    a        ; X4
  123.     add    h
  124.     mov    h,a        ; L is already 0 from above
  125.     shld    otend        ; Output buffer end
  126.     inr    h        ; Next page
  127.     shld    inplst        ; Input file list
  128.     shld    inpptr        ; Initialize pointer
  129. ;
  130. ; Get Default Drive and User
  131. ;
  132.     mvi    c,25
  133.     call    bdos        ; Current Drive
  134.     inr    a        ; Rel 1
  135.     mov    h,a        ; To H
  136.     mvi    e,255        ; Get User
  137.     call    gsusr
  138.     mov    l,a        ; User to L
  139.     shld    defdu        ; Save it
  140. ;
  141. ; Parse the command line and Open input file(s)
  142. ;
  143.     call    parser        ; Parse to OUTFCB and INPLST
  144.     call    newin        ; First input file
  145.     jz    synerr        ; Syntax error, no input file specified
  146. ;
  147. ; Open all the input files.
  148. ;
  149. opnfil:    call    open        ; Open the New file
  150.     jm    nofil        ; Not found
  151.     call    newin        ; Next input file
  152.     jrnz    opnfil        ; Again..
  153. ;
  154.     call    iniptr        ; Reset the input file pointer
  155. ;
  156. ; Input file(s) open, attempt making output file.
  157. ;
  158.     lxi    d,outfcb    ; Output file
  159.     call    make        ; Delete and Make it
  160.     jm    dirful        ; Directory full, quit
  161. ;
  162. ; Setup is OK, get on with business.
  163. ;
  164.     lda    bin        ; Binary option flag
  165.     ora    a
  166.     jrz    ascii        ; Ascii treatment
  167.     jr    binary        ; Binary treatment
  168. ;
  169. ; Binary option selected.  Fast record by record action.
  170. ;
  171. binar:    call    getr        ; Copy input to output
  172. binary:    call    newin        ; Set up INPFCB, return Z if no more
  173.     jrnz    binar        ; Next file..
  174.     jr    fin        ; No more files
  175. ;
  176. ; This is the top of the GETR/PUTR routine.  See GETR.
  177. ;
  178. putr:    lded    otend        ; End of Output buffer
  179.     dsbc    de        ; Compare with otptr
  180.     jrnz    getr        ; Buffer not full
  181.     call    wrbuf        ; Write the buffer
  182.     shld    otptr        ; New Output pointer
  183. ;
  184. ; This is the entry to GETR/PUTR.  We read the input file until its
  185. ; physical end, looping throuth PUTR to write the buffer as it fills.
  186. ;
  187. getr:    lhld    otptr        ; Output pointer is DMA address
  188.     call    fread        ; Read a record
  189.     rnz            ; End of File, Bail out..
  190.     call    ad128        ; Bump HL 128 bytes
  191.     shld    otptr        ; New Output pointer
  192.     jr    putr        ; Keep it up
  193. ;
  194. ; ASCII file(s), terminated with first ^Z.
  195. ;
  196. asci:    call    geta        ; Copy input to output
  197. ascii:    call    newin        ; Next Input file
  198.     jrnz    asci        ; Do it again..
  199. ;
  200. filz:    lhld    otptr        ; Output pointer
  201. fil:    mvi    m,ctlz        ; Fill remainder of 128 bytes with ^Z
  202.     inx    h        ; Increment pointer
  203.     mov    a,l        ; Check Lo order
  204.     ani    127        ; Modulus 128
  205.     jrnz    fil        ; Again..
  206.     shld    otptr        ; New output pointer
  207. ;
  208. fin:    call    wrbuf        ; Write partial Output buffer
  209.     lxi    d,outfcb
  210.     call    close        ; Fall through to EXIT
  211. ;
  212. exit:    lspd    stack        ; Get the CCP stack pointer
  213.     ret            ; That's all folks..
  214. ;
  215. ; Top of GETA/PUTA routine.  See GETA.
  216. ;
  217. puta:    lded    otend        ; End of buffer
  218.     dsbc    de        ; Difference to HL
  219. ;
  220. ; The following check ensures that the output buffer overflows
  221. ; by at least one and up to 128 bytes.
  222. ;
  223.     jrc    geta        ; Not full yet
  224.     jrz    geta        ; Full.  Get one more anyway
  225. ;
  226. ; Output buffer has overflowed.  Take care of it.
  227. ;
  228.     sded    otptr        ; otend to otptr for WRBUF routine
  229.     push    d        ; Save it on the stack
  230.     push    h        ; Characters beyond otend on the stack
  231.     call    wrbuf        ; Write the buffer
  232. ;
  233. ; As we have forced overflow, copy the excess to OTBUF and
  234. ; set OTPTR to the next byte.
  235. ;
  236.     pop    b        ; Length of overflow to BC
  237.     xchg            ; otbuf to DE
  238.     pop    h        ; otend to HL
  239.     ldir            ; Move overflow to otbuf
  240.     sded    otptr        ; New pointer, fall through to GETA
  241. ;
  242. ; This is the entry to the GETA/PUTA routine.  Read records from the
  243. ; input file to the output buffer until End of File.  Loop through
  244. ; PUTA to write the buffer as it fills.  Each character is tested
  245. ; for ^Z to ensure that we catch the 'first' one in a file.
  246. ;
  247. geta:    lhld    otptr        ; Out pointer
  248.     call    fread        ; Read a record
  249.     rnz            ; End of File
  250. ;
  251. ; A new record was read into the buffer.  Check it for ^Z and
  252. ; advance HL while doing so.
  253. ;
  254.     lxi    b,128        ; Check 128 bytes
  255.     mvi    a,ctlz        ; For ^Z
  256.     ccir            ; Z80 CPIR instruction
  257.     jrnz    notz        ; Not found
  258.     dcx    h        ; Back up to ^Z
  259. notz:    shld    otptr        ; New output pointer (+0..128)
  260.     jrnz    puta        ; If ^Z not found
  261.     ret
  262. ;
  263. ; WRBUF - Called from PUTA and PUTR when buffer fills and from CLOSE
  264. ;
  265. wrbuf:    lhld    otptr        ; Current pointer
  266.     lded    otbuf        ; Output buffer start
  267.     dsbc    de        ; Bytes in the buffer to HL
  268.     rz            ; Buffer empty
  269. ;
  270. ; HL is the number of bytes in the buffer.  Calculate the number
  271. ; of records to write.
  272. ;
  273.     mvi    a,127        ; Balance of one record
  274.     call    addhl        ; Add it to HL
  275.     dad    h        ; Shift HL left
  276.     mov    b,h        ; Number of records to write in B
  277. ;
  278. ; Setup for WRIT routine.
  279. ;
  280.     xchg            ; Buffer start to HL
  281.     push    h        ; Save it on the stack
  282.     lxi    d,outfcb    ; Output file
  283.     call    logusr        ; Log its user
  284. ;
  285. ; Write B records to the output file.
  286. ;
  287. writ:    call    setdma
  288.     call    fwrit        ; Write one record
  289.     jrnz    dskful
  290.     call    ad128        ; Add 128 to HL
  291.     djnz    writ        ; Decrement record count, Again..
  292. ;
  293. ; Buffer written.  Restore buffer start address and quit.
  294. ;
  295.     pop    h        ; Buffer start to HL
  296.     ret
  297. ;
  298. dskful:    call    close        ; FCB still set from above
  299.     call    print
  300.     db    ' Disk Full',0
  301.     jmp    exit
  302. ;
  303. ; Specified Input file cannot be found.
  304. ;
  305. nofil:    call    print
  306.     db    ' Can''t open input file',0
  307.     jmp    exit
  308. ;
  309. ; No directory space.
  310. ;
  311. dirful:    call    print
  312.     db    ' Directory Full',0
  313.     jmp    exit
  314. ;
  315. ; Parse any number of filespecs from the command tail into their
  316. ; associated FCB's.
  317. ;
  318. parser:    lxi    h,tbuf+1    ; Command tail
  319.     call    check        ; Check for ambiguity and Option
  320.     lxi    d,outfcb
  321.     call    fname        ; Parse the Output filespec
  322.     jr    parse
  323. ;
  324. ; Now the Input filespecs..
  325. ;
  326. pars:    call    same        ; Identity check
  327. parse:    call    newin        ; Point DE to next infcb in the list
  328.     call    inifcb        ; Initialize the FCB
  329.     call    fname        ; Parse the filespec to it
  330.     jrnz    pars        ; Until FNAME returns Zero
  331. ;
  332. ; Initialize the Input file list pointer
  333. ;
  334. iniptr:    lhld    inplst        ; Beginning of the list
  335.     shld    inpptr        ; Set the pointer
  336.     ret
  337. ;
  338. ; Initialize potential FCB at DE
  339. ;
  340. inifcb:    push    h        ; Command tail pointer
  341.     xra    a        ; Get a null
  342.     stax    d        ; Clear Drive byte
  343.     lxi    h,12        ; Extent
  344.     dad    d        ; Point HL to it
  345.     mov    m,a        ; Clear it
  346.     lxi    h,32        ; Current record byte
  347.     dad    d        ; Point HL to it
  348.     mov    m,a        ; Clear it
  349.     pop    h        ; Command tail pointer
  350.     ret
  351. ;
  352. ; NEWIN - Return DE (and INPFCB) pointing to the next Input FCB.
  353. ;    Return Z flag if new FCB is blank.
  354. ;
  355. newin:    push    h        ; Save HL
  356.     lded    inpptr        ; Point to 34-byte FCB
  357.     lxi    h,34        ; Length of it
  358.     dad    d        ; Point to next one
  359.     shld    inpptr        ; New pointer to next FCB
  360.     inx    d        ; Point to Drive byte of this one
  361.     sded    inpfcb        ; New FCB pointer for FREAD
  362.     ldax    d        ; Get drive byte
  363.     ora    a        ; Test for Zero
  364.     pop    h        ; Restore HL
  365.     ret
  366.  
  367. ; FNAME - File Spec Parser
  368. ; Enter with HL pointing to a filespec and DE pointing to an FCB.
  369. ; Return Z flag if no more files.
  370.  
  371. fname:    call    sksp        ; Skip spaces and delimiters
  372.     ora    a
  373.     rz            ; Nothing to do if Null
  374.     cpi    '/'        ; Option, not a filespec
  375.     rz
  376. ;
  377. ; Ok, we're on.  Parse it.
  378. ;
  379.     lbcd    defdu        ; Default Drive/User to BC
  380.     push    h        ; Command tail pointer
  381.     call    skdel        ; Find first delimiter (in A)
  382.     pop    h        ; Restore pointer
  383.     cpi    ':'        ; Check for DU spec
  384.     jrnz    fnam        ; None
  385. ;
  386. ; Resolve D:, U:, or DU:
  387. ;
  388.     mov    a,m        ; Drive letter?
  389.     sui    'A'        ; Remove ascii bias
  390.     cpi    16        ; Cy if A..P
  391.     jrnc    usr        ; No Drive spec
  392.  
  393.     inr    a        ; Rel 1 Drive
  394.     mov    b,a        ; To B
  395.     inx    h        ; Next character in tail
  396. ;
  397. ; Evaluate potential user number (0..31)
  398. ;
  399. usr:    push    d        ; Free up the E register
  400.     mvi    e,0        ; Clear it
  401.  
  402. ulp:    mov    a,m        ; Get the 'next' character
  403.     cpi    ':'        ; End of User spec?
  404.     jrz    uex        ; Yes.
  405. ;
  406.     mov    a,e        ; Previous digit
  407.     add    a        ; X2
  408.     add    a        ; X4
  409.     add    e        ; X5
  410.     add    a        ; X10
  411.     mov    e,a        ; Save it
  412.     mov    a,m        ; Current digit
  413.     ani    0fh        ; Strip ASCII
  414.     add    e        ; Add it to the Last one
  415.     mov    e,a        ; Save it again
  416.     mov    c,a        ; Maybe this time..
  417.     inx    h        ; Point to next character
  418.     jr    ulp        ; Try again
  419.  
  420. uex:    mov    a,c        ; User number
  421.     cpi    32
  422.     jrnc    synerr        ; Too Big
  423.  
  424.     inx    h        ; Skip past the ':'
  425.     pop    d        ; Restore DE
  426. ;
  427. fnam:    push    d        ; Save FCB pointer on stack
  428.     xchg            ; FCB pointer to HL
  429.     dcx    h        ; User
  430.     mov    m,c        ; Put User
  431.     inx    h
  432.     mov    m,b        ; Put Drive
  433.     xchg            ; BC is now 'scratch'
  434.     inx    d        ; Point to FCB Name
  435. ;
  436.     mov    a,m        ; First character of filename
  437.     call    isdel        ; Maybe not specified
  438.     jrz    outin        ; If not specified
  439. ;
  440.     mvi    b,8        ; Eight chars in name
  441. nam:    mov    a,m
  442.     call    isdel        ; Check for delimiter
  443.     jrz    snam        ; Space fill if so
  444.     inx    h        ; Bump the pointer
  445.     cpi    '.'        ; Check for '.'
  446.     jrz    snam        ; Fill name with Spaces if so
  447.  
  448.     stax    d        ; Put character in FCB
  449.     inx    d        ; Bump pointer
  450.     djnz    nam        ; Next..
  451.  
  452.     mov    a,m        ; Ninth character
  453.     call    isdel        ; Check for delimiter
  454.     jrz    ftyp        ; Do type if so
  455.  
  456.     inx    h        ; Past potential '.'
  457.     cpi    '.'
  458.     jrz    ftyp        ; Was '.', do type
  459.  
  460. synerr:    call    print
  461.     db    ' Syntax Error',0
  462.     jmp    exit
  463.  
  464. snam:    call    spaco        ; Space fill balance of filename
  465.  
  466. ftyp:    mvi    b,3        ; Three characters in 'type'
  467. typ:    mov    a,m
  468.     call    isdel        ; Zero if delimiter
  469.  
  470.     cz    spaco        ; Space out the filetype..
  471.     jrz    fnamx        ; ..and Quit
  472.  
  473.     inx    h        ; Bump pointer
  474.     stax    d        ; Put char in FCB
  475.     inx    d        ; Bump pointer
  476.     djnz    typ        ; Next..
  477.  
  478.     mov    a,m        ; Fourth character of type
  479.     call    isdel        ; Check for delimiter
  480.     jrnz    synerr        ; If not
  481.  
  482. fnamx:    pop    d        ; Restore FCB pointer
  483.     ori    255        ; NZ
  484.     ret
  485.  
  486. ; OUTIN - Input filespec is blank except perhaps for DU:
  487. ;  Copy Output filename and type to Input FCB.  
  488.  
  489. outin:    push    h        ; Command tail pointer
  490.     lxi    h,outfcb+1    ; Output FILENAME.TYP
  491.     lxi    b,11        ; Eleven bytes
  492.     ldir            ; Move them to Input FCB
  493.     pop    h        ; Command tail pointer
  494.     jr    fnamx        ; Restore FCB pointer and quit
  495.  
  496. ; SPACO - Fill the remainder (B) of Name or Typ with Spaces.
  497. ; Note that DJNZ does not change any flags.
  498.  
  499. spaco:    mvi    a,' '        ; Get a Space
  500. filla:    stax    d        ; Put it in the FCB
  501.     inx    d        ; Bump pointer
  502.     djnz    filla        ; B times..
  503.     ret
  504. ;
  505. ; Add 128 to HL.
  506. ;
  507. ad128:    mvi    a,128        ; Fall through to ADDHL
  508. ;
  509. ; Add A to HL.  Uses only AF.  Flags have no real meaning.
  510. ;
  511. addhl:    add    l        ; Add low order
  512.     mov    l,a        ; Back to L
  513.     rnc            ; If LT 256
  514.     inr    h        ; Overflow to H
  515.     ora    a        ; Clear Cy
  516.     ret
  517. ;
  518. ; PRINT - Ye Olde Inline console output routine
  519. ;
  520. print:    xthl            ; Return address to HL
  521.     call    pstr        ; Print string at return address
  522.     xthl            ; New return address on the stack
  523.     ret
  524. ;
  525. pstr:    mov    a,m        ; Get a character
  526.     inx    h        ; Bump pointer
  527.     ora    a        ; Test for Null
  528.     rz            ; Quit if so
  529.     call    cout        ; Ship the character to the console
  530.     jr    pstr        ; Next..
  531.  
  532. cout:    mov    e,a
  533.     mvi    c,2        ; Conout
  534.     jr    bdos
  535.  
  536. setdma:    xchg
  537.     mvi    c,26        ; Set DMA address
  538.     call    bdos
  539.     xchg
  540.     jmp    spin        ; Spin the Propeller
  541.  
  542. delete:    call    logusr
  543.     mvi    c,19        ; Delete
  544.     jr    bdos
  545.  
  546. make:    call    delete
  547.     mvi    c,22        ; Make
  548.     jr    bdos
  549.  
  550. open:    call    logusr
  551.     mvi    c,15        ; Open
  552.     jr    bdos
  553.  
  554. close:    call    logusr
  555.     mvi    c,16        ; Close
  556.     jr    bdos
  557.  
  558. fwrit:    mvi    c,21        ; Write
  559.     jr    bdos
  560.  
  561. fread:    call    setdma
  562.     lded    inpfcb
  563.     call    logusr
  564.     mvi    c,20        ; Read sequential
  565. ;
  566. bdos:    push    h
  567.     push    d
  568.     push    b        ; Save the registers
  569.     call    5        ; Call the operating system
  570.     ora    a        ; Note Minus flag set if A = 0FFh
  571.     pop    b
  572.     pop    d
  573.     pop    h        ; Restore the registers
  574.     ret
  575. ;
  576. logusr:    push    d        ; Save FCB pointer
  577.     dcx    d        ; Point to user
  578.     ldax    d        ; Get user number
  579.     mov    e,a        ; To E
  580.     call    gsusr        ; Log the User
  581.     pop    d        ; Restore FCB pointer
  582.     ret
  583. ;
  584. gsusr:    mvi    c,32        ; Get or Set User
  585.     jr    bdos
  586.  
  587. ; Skip spaces and delimiters
  588.  
  589. sksp:    mov    a,m
  590.     ora    a
  591.     rz            ; End of string
  592.     call    isdel
  593.     rnz            ; Non-delimiter in A
  594.     inx    h
  595.     jr    sksp
  596. ;
  597. ckerr:    call    mode
  598.     jmp    synerr
  599.  
  600. ; Check for any of '?' or '*'.    None allowed.
  601.  
  602. check:    push    h        ; Save Command tail pointer
  603. ;
  604. chek:    mov    a,m
  605.     inx    h
  606.     ora    a
  607.     jrz    chekx        ; End of command tail
  608.  
  609.     cpi    '?'
  610.     jrz    ckerr
  611.     cpi    '*'
  612.     jrz    ckerr
  613.     cpi    '/'
  614.     jrnz    chek
  615. ;
  616.     lxi    h,bin        ; Point to Option byte
  617.     mov    a,m        ; Get it
  618.     cma            ; Complement it
  619.     mov    m,a        ; Put it back
  620.  
  621. chekx:    pop    h        ; Command tail pointer
  622.     jmp    mode        ; Return through MODE routine
  623. ;
  624. ; SAME - Called by PARSER to ensure unique Output file.
  625. ;
  626. same:    push    h
  627.     push    d        ; Save FCB pointer
  628.  
  629.     dcx    d        ; Point to User
  630.     lxi    h,outusr
  631.     mvi    b,13        ; Check 13 bytes
  632.  
  633. sam:    ldax    d
  634.     cmp    m
  635.     jrnz    samx        ; Not the same
  636.     inx    d
  637.     inx    h
  638.     djnz    sam
  639.  
  640.     call    print
  641.     db    ' Output=Input error',0
  642.     jmp    exit
  643.  
  644. samx:    pop    d        ; Restore FCB pointer
  645.     pop    h
  646.     ret
  647.  
  648. ; Skip past any of Space, Equal, Comma, Colon or Null.    Return in A.
  649.  
  650. skdel:    mov    a,m
  651.     inx    h
  652.     call    isdel
  653.     jrnz    skdel
  654.     ret
  655.  
  656. isdel:    ora    a
  657.     rz            ; Null
  658.     cpi    ' '
  659.     rz            ; Space
  660.     cpi    ','
  661.     rz            ; Comma
  662.     cpi    ':'
  663.     rz            ; Colon
  664.     cpi    '='
  665.     ret            ; Equal?
  666. ;
  667. ; This is my implementation of Al Hawley's Propeller to show
  668. ; activity on the screen while CON is otherwise occupied.
  669. ; It is called for each SETDMA and will print a 'blade' on
  670. ; the screen each time TIME goes to zero.
  671. ;
  672. spin:    push    h        ; Save HL
  673.     lxi    h,time        ; Time constant
  674.     dcr    m        ; Count it down
  675.     jrnz    timx        ; Quit if not zero
  676.  
  677.     mvi    m,tim        ; Preset the timer
  678.     lxi    h,cntr        ; Blade counter
  679.     mov    a,m
  680.     ani    3        ; Modulus 4
  681.     inr    m        ; Advance the counter
  682.     lxi    h,blad        ; Blade list
  683.     call    addhl        ; Point to next blade (+0..3)
  684.     mov    a,m        ; Get it
  685.     sta    char        ; Put it in the prop string
  686.     lxi    h,prop        ; Point to the string
  687.     push    d        ; Save DE
  688.     call    pstr        ; Print the string
  689.     pop    d        ; Restore DE
  690.  
  691. timx:    pop    h        ; Restore HL
  692.     ret
  693.  
  694. prop:    db    cr,' '
  695. char:    db    '  ',0
  696. cntr:    db    0
  697. blad:    db    '|/-\'
  698. time:    db    tim
  699. ;
  700. ; The File Control Blocks are preceded by one byte which
  701. ; holds the User Number associated with the file. 34 bytes.
  702. ;
  703. outusr:    db    0
  704. outfcb:    db    0,'           ',0,0,0,0
  705.     ds    16
  706.     db    0
  707. ;
  708. ; Uninitialized data starts here.
  709. ;
  710. otbuf:    ds    2        ; Output buffer start
  711. otptr:    ds    2        ; Current pointer into OTBUF
  712. otend:    ds    2        ; End of output buffer
  713. defdu:    ds    2        ; Default Drive/User
  714. inplst:    ds    2        ; Input file list
  715. inpptr:    ds    2        ; Pointer to next input FCB user
  716. inpfcb:    ds    2        ; Pointer to current input FCB
  717. ;
  718.     ds    48        ; Local stack space
  719. stack:    ds    2        ; CCP stack pointer
  720.  
  721. codend:
  722.     end
  723. ;
  724. ; End of CON.MAC
  725.