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 / JSAGE / ZSUS / PROGPACK / SAVE15.LBR / SAV15.ZZ0 / SAV15.Z80
Text File  |  1989-11-03  |  19KB  |  639 lines

  1. ; PROGRAM:    SAVE.Z80
  2. ; AUTHOR:    Jay Sage
  3. ; DATE:     September 4, 1988
  4. ; VERSION:    1.1
  5. ; DERIVATION:    ZCPR34 resident SAVE command
  6.  
  7. vers    equ    15        ; Version number
  8.  
  9. ; Version 1.5  04 November 89  Howard Goldstein
  10. ;    Fixed several problems in the "from-till" mode including failure
  11. ;    when the range encompassed more than 255 records and failure to
  12. ;    accept FFFF as an ending address.  The full 64k can now be saved
  13. ;    in this mode, although the other mode has been changed to allow
  14. ;    a maximmum of 510 instead of 512 records.
  15. ;    Changed the banner to always display "SAVE" for the program
  16. ;    name.
  17. ;    Removed the in-line versions of PRTTYPE and PRTNAME since
  18. ;    they're now available in the standard libraries.
  19. ;    Added a public symbol, COUT, which simply jumps to BOUT.  This
  20. ;    causes all console output to be done through the DOS.  Console
  21. ;    input is now also done via DOS calls.
  22. ;    Replaced PRINT with EPRINT to shorten code.
  23.  
  24. ; Version 1.4  25 November 88  Joe Wright
  25. ;    Report error if Z34 scanner was unable to find DIR: reference.
  26.  
  27. ; Version 1.3  27 October 88  Joe Wright
  28. ;    Moved the filespec from TFCB2 to TFCB before EXTEST to get it
  29. ;    out of the way of F$EXIST (Func 17) which corrupts the default
  30. ;    DMA address (0080h) and therefore the 'tail' of TFCB2.
  31. ;    Removed RETCST calls to Z33LIB in favor of GETMSG.
  32.  
  33. ; Version 1.2  20 September 88    Joe Wright
  34. ;    Placed prttype routine inline and put prtname routine back
  35. ;    in the code so that I can assemble it here without Jay's
  36. ;    newest libraries.
  37. ;    Reduced code in RADBIN: and elsewhere.
  38.  
  39. ; Version 1.1  04 September 88    Jay Sage
  40. ;    Fixed code so that it will work in non-Z34 environment, such as
  41. ;    BGii and Z3PLUS.  Replaced code originally borrowed from ZCPR3
  42. ;    with library calls.  The number evaluation routines still need to
  43. ;    be improved; the present ones are from an old version of ZCPR33.
  44. ;    New code is much shorter and simpler.
  45.  
  46. ; Version 0.7  20 January 88
  47. ;    Place RST 0 (instead or RET) as the first byte.
  48. ;    Eliminated Type 3/4 test.  Either is OK now.
  49.  
  50. ; Version 0.6  September 1987  Joe Wright
  51. ;    Implement SAVE as a Type 4 command.
  52.  
  53. ; SYNTAX:
  54. ; Version 0.5  3 Sept 87  Joe Wright
  55. ;    SAVE FROM-TILL UFN
  56. ; where from and till are hexadecimal memory addresses.  For example
  57. ; you might save the current NDR buffer with the following:
  58. ;    'save e600-e6ff names.ndr'
  59. ;
  60. ; Version 0.4
  61. ;    SAVE NUMBER UFN [SECTOR-FLAG]
  62. ; where number is a decimal number unless followed by an 'H' (exact character
  63. ; defined by the NUMBASE equate below), in which case it is a hesadecimal
  64. ; number.  UFN is an unambiguous file specification.  The third field is
  65. ; optional.  It allows the number of units to be stored to be interpreted not
  66. ; as pages (the default, 256-byte units) but as sectors or records (128-byte
  67. ; units).  The SECTCH equate below defines the character used for this switch.
  68. ; If SECTCH is defined to be the space character, then any character (and only
  69. ; the first character matters) will select sector mode.  Otherwise the
  70. ; character must match SECTCH.
  71.  
  72.  
  73. ; REVISION HISTORY
  74. ;
  75. ; Version 0.4    Jay Sage    May 19, 1987
  76. ; Updated to use Z33LIB routines.  Added version message with load address
  77. ; information.
  78.  
  79. ; Version 0.3    Jay Sage    May 15, 1987
  80. ; Updated for latest release of Z33, which has a different entry point for
  81. ; the reparse routine.
  82. ;
  83. ; Version 0.2    Jay Sage    May 4, 1987
  84. ;
  85. ; This is a hastily constructed transient version of the SAVE command from the
  86. ; ZCPR33 command processor.  It uses a type-3 environment so that it can be
  87. ; loaded at a high address in memory, where one hopes that it will not
  88. ; interfere with the memory image to be stored.  The command will work in the
  89. ; desired way only when the memory area saved does not include the memory
  90. ; occupied by SAVE.COM, or where it does not matter that that part of memory
  91. ; has been corrupted.  I recommend linking the program to an address about
  92. ; 0.5K below the lowest system address ever used in your system (this is the
  93. ; CCP base address if you never use resident system extensions, such as print
  94. ; spoolers or XSUB, that install themselves below the CCP).  A value of A000H
  95. ; is typical.
  96. ;
  97. ; This first release is intended primarily as an example of some of the ways
  98. ; features of ZCPR33 can be used.  Of particular interest is the use of the
  99. ; parser from the command processor.  Many refinements should be added to this
  100. ; program before it is considered to be more than an instructional example.
  101. ; I would recommend the following at least:
  102. ;
  103. ;    1. Replace many of the in-line routines with calls to library
  104. ;    functions.  This will make the code more readable and easier to
  105. ;    maintain.
  106. ;    2. Add various self-checking features.  For example, a warning should
  107. ;    at least be given if the memory area saved includes any part of the
  108. ;    SAVE code itself.
  109. ;    3. Increase the flexibility of the command.  For example, the command
  110. ;    could be made to allow saving blocks of memory from arbitrary starting
  111. ;    to arbitrary ending addresses (as in the DSD debugger).
  112. ;    4. The interface to the ZCPR33 error handling facilities should be
  113. ;    developed further.
  114. ;    5. Add to the built-in help display showing the syntax allowed.  This
  115. ;    screen should adapt automatically to the actual name of the program
  116. ;    and to the definitions of SECTCH and NUMBASE.
  117. ;
  118. ;        Jay Sage, April 28, 1987
  119.  
  120.  
  121. ;=============================================================================
  122. ;
  123. ;            D E F I N I T I O N S
  124. ;
  125. ;=============================================================================
  126.  
  127. sectch    equ    ' '        ; Character used to switch to sector mode (if
  128.                 ; ..set to ' ', any character will switch)
  129. numbase    equ    'H'        ; Character to switch to hexadecimal numbers
  130.  
  131. ecbaddir equ    02        ; Specified dir: out of range or not found
  132.  
  133. ecambig    equ    08        ; Error code to return for an ambiguous file
  134.                 ; ..name specification
  135. ecbadnum equ    09        ; Error code to return for a bad number
  136.  
  137. ecfull    equ    11        ; Directory or disk full error
  138.  
  139. tfcb    equ    005ch
  140. tfcb2    equ    006ch
  141. tail    equ    0080h
  142. tpa    equ    0100h
  143. bell    equ    07h
  144. tab    equ    09h
  145. lf    equ    0ah
  146. cr    equ    0dh
  147.  
  148.     extrn        z3init,getmsg,getwhl,z3log        ; Z3LIB
  149.     extrn        prttype,prtname
  150.     extrn        phlfdc,bout                ; SYSLIB
  151.     extrn        sksp,sknsp,eprint,crlf,bin,pfn2
  152.     extrn        f$close,f$exist,f$make
  153.     extrn        f$write,setdma,initfcb
  154.  
  155. ;=============================================================================
  156. ;
  157. ;            M A I N    C O D E
  158. ;
  159. ;=============================================================================
  160.  
  161. entry:    rst    0        ; New Type 3 construct    JWW
  162.     dw    save
  163.     db    'Z3ENV'
  164. type:    db    3        ; Type 3 environment
  165. z3env:    dw    0        ; ENV address
  166. ldaddr:
  167.     dw    entry        ; Load address
  168.  
  169. ; Display version message
  170.  
  171. banner:
  172.     call    eprint
  173.     db    cr,lf,'SAVE, Version '
  174.     db    vers/10+'0','.',vers mod 10+'0',' ',0
  175.     ld    a,(type)
  176.     ld    hl,(ldaddr)
  177.     call    prttype
  178.     call    eprint
  179.     db    '  File Save Utility',cr,lf,0
  180.     ret
  181.  
  182. ; This help screen should be significantly improved.  This is just a quick and
  183. ; dirty cut at something.
  184.  
  185. help:    call    banner
  186.     call    eprint
  187.     db    cr,lf,'  Syntax:',cr,lf,cr,lf,'    ',0
  188.     call    prtname
  189.     call    eprint
  190.     db    ' nn[H] FILE.TYP ['
  191.  
  192.      if    sectch eq ' '
  193.     db    'o'
  194.      else
  195.     db    sectch
  196.      endif    ;sectch eq ' '
  197.  
  198.     db    ']',cr,lf,'      '
  199.     db    'Where nn is the decimal or [H]exadecimal length in pages.'
  200.     db    cr,lf,'      '
  201.  
  202.      if    sectch eq ' '
  203.     db    'Any character'
  204.      else
  205.     db    '''',sectch,''''
  206.      endif    ;sectch eq ' '
  207.  
  208.     db    ' in the third token switches from page mode'
  209.     db    cr,lf,'      '
  210.     db    'to sector/record mode, or..'
  211.     db    cr,lf,cr,lf,'    ',0
  212.     call    prtname
  213.     call    eprint
  214.     db    ' from-till FILE.TYP',cr,lf,'      '
  215.     db    'Where ''from'' and ''till'' are hexadecimal addresses of the'
  216.     db    cr,lf,'      '
  217.     db    'start and end of the memory block you wish to save.'
  218.     db    cr,lf,0
  219.  
  220.     ret
  221.  
  222. ; Program begins here.
  223.  
  224. save:    call    z3init        ; Z3ENV address passed in HL by Z34
  225.  
  226. ; Check for help request
  227.  
  228.     ld    a,(tfcb+1)    ; Get first character of number
  229.     cp    '/'        ; Explicit help request
  230.     jr    z,helprel
  231.     cp    '?'        ; Explicit help request
  232.     jr    z,helprel
  233.     cp    ' '        ; No command tail - implied help request
  234. helprel:
  235.     jp    z,help
  236.  
  237.     ld    hl,tfcb2+1    ; Point to first character of file name
  238.     ld    a,(hl)        ; Get it
  239.     cp    ' '        ; See if any file name specified
  240.     jr    nz,main        ; If file name, go on with save
  241.     ld    (hl),'?'    ; Otherwise, force ambiguous expression
  242.  
  243. main:    call    getwhl        ; Make sure user has wheel status
  244.     jr    nz,main1    ; Branch if OK
  245.  
  246.     call    eprint
  247.     db    bell,'  Not Wheel',0
  248.     ret
  249.  
  250. main1:
  251.     ld    (stack),sp    ; Save system stack pointer
  252. ;
  253. ; Check for Z34 scanner error.
  254. ;
  255.     ld    a,(tfcb2+15)
  256.     inc    a        ; 255 -> 0
  257.     ld    c,ecbaddir
  258.     jp    z,error        ; Quit
  259.  
  260.     ld    hl,data        ; Initialize data space
  261.     ld    de,data+1
  262.     ld    bc,datalen-1
  263.     ld    (hl),0        ; Seed first value
  264.     ldir            ; Propagate it
  265.     ld    hl,100h        ; Set default save starting address
  266.     ld    (dmaadr),hl
  267.  
  268.     call    number        ; Extract number(s) from command line
  269.  
  270.     jp    c,badnumber    ; Invoke error handler if bad number
  271.  
  272.     ex    de,hl        ; Number to HL
  273.  
  274.     ld    a,(secflag)    ; See if sector count specified
  275.     or    a
  276.     jr    nz,save0    ; If so, proceed with save
  277.  
  278.     add    hl,hl        ; Else double page count to get sector count
  279.  
  280. save0:
  281.     ld    (record),hl    ; Save record count, 512 max (64k)
  282.  
  283.     ld    a,(mode)    ; Check if 'from-till' form
  284.     or    a
  285.     jr    nz,save0a    ; Branch if so
  286.     ld    de,510+1    ; Too many records
  287.     sbc    hl,de        ; Sets carry if ok
  288.     jp    nc,badnumber    ; Too many records
  289.  
  290. save0a:
  291.     ld    hl,tfcb2    ; Point to FCB
  292.     ld    de,tfcb        ; Default FCB
  293.     push    de
  294.     ld    bc,14
  295.     ldir
  296.     pop    de
  297.     call    ambchk        ; Check for ambiguous file spec (vectors to
  298.                 ; ..error handler if so)
  299.  
  300.     call    extest        ; Test for existence of file and abort if so
  301.     call    f$make
  302.     inc    a
  303.     jr    z,loaderr    ; Branch if error in creating file
  304.  
  305.     ld    bc,(record)    
  306.     ld    hl,(dmaadr)    ; Start writing from here
  307. ;
  308. save1:
  309.     ld    a,b        ; Check for BC = 0
  310.     or    c
  311.     jr    z,save2        ; Branch if done
  312.  
  313.     dec    bc        ; Count down sectors
  314.     call    setdma        ; Set DMA address to HL for write
  315.     call    f$write
  316.     push    de        ; Save FCB pointer
  317.     ld    de,128        ; Advance address by 128 bytes
  318.     add    hl,de
  319.     pop    de        ; Restore FCB pointer
  320.     jr    z,save1        ; If write successful, go back for more
  321.     ld    b,0ffh        ; B nonzero if write failed
  322.  
  323. save2:
  324.     call    f$close        ; Close file even if last write failed
  325.     or    b        ; Combine close return code with
  326.                 ; ..write success flag
  327.     jr    nz,loaderr    ; Abort if close or write failed
  328.  
  329.     call    eprint
  330.     db    '  Saved ',0
  331.     ld    hl,(record)
  332.     call    phlfdc
  333.     call    eprint
  334.     db    ' record',0
  335.     dec    hl
  336.     ld    a,h
  337.     or    l
  338.     ld    a,'s'
  339.     call    nz,bout
  340.     call    eprint
  341.     db    ' as ',0
  342.     inc    de        ; Point to first character of file name
  343.     call    pfn2
  344.     jr    done
  345.  
  346. ;-----------------------------------------------------------------------------
  347.  
  348. ; Check the FCB pointed to by DE for the presence of a question mark.  If so,
  349. ; return via error handler.  Otherwise return to the calling code.
  350.  
  351. ambchk:
  352.     ld    h,d        ; Copy DE into HL
  353.     ld    l,e
  354.     ld    a,'?'        ; Set up for scan for question mark
  355.     ld    bc,11        ; Scan 11 characters
  356.     cpir
  357.     ret    nz        ; Return if no '?' found
  358.  
  359. amberr:
  360.     ld    c,ecambig    ; Error code for ambiguous file name
  361.     jr    error
  362.  
  363. ;-----------------------------------------------------------------------------
  364.  
  365. ; Various entries to the error handler
  366.  
  367. badnumber:
  368.     ld    c,ecbadnum    ; Error code for bad number value
  369.     jr    error
  370.  
  371. loaderr:
  372.     ld    c,ecfull
  373.  
  374. error:
  375.     call    getmsg        ; Point to Z3MSG
  376.     ld    (hl),c        ; Plug in the error code
  377.     inc    hl
  378.     inc    hl
  379.     inc    hl        ; Point to the command status flag
  380.     ld    a,(hl)        ; Get it
  381.     or    1110b        ; Error, ECP and Transient bits
  382.     ld    (hl),a        ; Put it back
  383.  
  384. done:
  385.     ld    sp,(stack)    ; Restore system stack pointer
  386.     ret
  387.  
  388. ;-----------------------------------------------------------------------------
  389.  
  390. ; Test file whose FCB is pointed to by DE to see if file exists.  Ask user
  391. ; to delete if so, and abort if he choses not to.
  392.  
  393. extest:
  394.     call    z3log        ; Log into designated directory
  395.     call    initfcb
  396.     call    f$exist        ; See if file already exists
  397.     ret    z        ; OK if not found, so return
  398.  
  399.     call    eprint
  400.     defb    bell
  401.     defb    '  Erase existing ',0
  402.     inc    de        ; Point to first character of file name
  403.     call    pfn2        ; Print it
  404.     dec    de        ; Restore FCB pointer
  405.     call    eprint        ; Add question mark
  406.     defb    ' ? ',0
  407.     call    bin        ; Get user response
  408.     and    5fh        ; Convert to upper case
  409.     cp    'Y'        ; Test for permission to erase file
  410.     jp    nz,done        ; If not, flush the entire command line
  411.     jp    crlf        ; Kick up a new line and return
  412.  
  413. ;-----------------------------------------------------------------------------
  414.  
  415. ; Define public symbol COUT so that all SYSLIB routines that call COUT
  416. ; will use BOUT instead
  417.  
  418. cout::    jp    bout
  419.  
  420. ;-----------------------------------------------------------------------------
  421.  
  422. ; The routine NUMBER evaluates a string in the first token in the command
  423. ; line tail.  It interprets the forms: ##, ##H, or ####-####.  If the form
  424. ; is the latter, the MODE flag is set.    This routine also checks to see if
  425. ; the third command-line token indicates a sector (record) count instead of
  426. ; a page count.  The SECFLAG flag is set if it does.
  427. ;
  428. ; If the number conversion is successful, the value is returned as a 16-bit
  429. ; quantity in DE.  If the number is less than 256, then the zero flag is set.
  430. ; If an invalid character is encountered in the string, the routine returns
  431. ; with the carry flag set and HL pointing to the offending character.
  432.  
  433. number:
  434.  
  435.     ld    hl,tail+1
  436.     call    sksp        ; Skip to beginning of first token
  437.     push    hl        ; Save pointer for later number parsing
  438.  
  439. ; Check for possible third token
  440.  
  441.     call    sknsp        ; Skip over first token
  442.     call    sksp        ; ..to second token
  443.     call    sknsp        ; Skip over second token
  444.     call    sksp        ; ..to third token
  445.     ld    a,(hl)        ; Get possible first character in token
  446.     or    a        ; If null
  447.     jr    z,num1        ; ..leave flag as is
  448.  
  449.      if    sectch ne ' '    ; If specific character required
  450.     cp    sectch        ; ..see if it is the sector flag character
  451.     jr    nz,num1        ; If not, leave flag as is
  452.      endif
  453.  
  454.     ld    (secflag),a    ; Set the flag
  455.  
  456. num1:
  457.     pop    hl        ; Get back pointer to first token
  458.     push    hl
  459.     call    skndel        ; Skip to next delimiter
  460.     cp    ' '        ; Is it 'space'?
  461.     pop    hl        ; Pt back to beginning of string
  462.     jr    z,numb1        ; Mode 0 syntax
  463.  
  464. ; We have encountered FROM-TILL syntax
  465.  
  466. num2:    ld    (secflag),a    ; Indicate that count is in sectors
  467.     ld    (mode),a    ; ..and that we're in from-till mode
  468.     call    hexnum1        ; Value to DE
  469.     ret    c
  470.     ld    (dmaadr),de    ; Start writing from here
  471.     call    skdel        ; First digit of TILL
  472.     call    hexnum1        ; Value in DE
  473.     ret    c
  474.  
  475.     ld    hl,(dmaadr)
  476.     ex    de,hl        ; From in de, till in hl
  477.     sbc    hl,de
  478.     ret    c        ; FROM > TILL
  479. ;
  480. ; Divide HL by 128 for record count, return in DE
  481. ;
  482.     ld    de,128        ; Fudge factor (D=0)
  483.     add    hl,de
  484.     rl    d        ; Move possible carry to d
  485.     add    hl,hl        ; Divide by 128
  486.     ld    e,h        ; Result in e
  487.     rl    d        ; CY to d
  488.     ret
  489.  
  490.  
  491. numb1:    ld    hl,tfcb+1+7    ; Set pointer to last char of number string
  492.     ld    bc,8        ; Number of characters to scan
  493.     ld    a,numbase    ; Scan for HEX identifier
  494.     cpdr            ; Do the search (decrementing)
  495.     inc    hl        ; Point to HEX marker or beginning of string
  496.     jr    nz,decimal1    ; Branch if HEX identifier not found
  497.  
  498.     ld    (hl),' '    ; Replace HEX marker with valid terminator
  499.                 ; ..and fall through to HEXNUM
  500.  
  501. ;----------------------------------------
  502.  
  503. ; At this entry point the character string in the first default FCB is
  504. ; converted as a hexadecimal number (there must NOT be a HEX marker).
  505.  
  506. hexnum:
  507.     ld    hl,tfcb+1    ; Point to string in first FCB
  508.  
  509. ; At this entry point the character string pointed to by HL is converted
  510. ; as a hexadecimal number (there must be NO HEX marker at the end).
  511.  
  512. hexnum1:
  513.     ld    c,16        ; HEX radix base
  514.     jr    radbin        ; Invoke the generalized conversion routine
  515.  
  516. ;----------------------------------------
  517.  
  518. ; This entry point performs decimal conversion of the string pointed to
  519. ; by HL.
  520.  
  521. decimal1:
  522.     ld    c,10        ; Decimal radix base
  523.                 ; Fall through to generalized
  524.                 ; ..radix conversion routine
  525.  
  526. ; This routine converts the string pointed to by the entry on the top of
  527. ; the stack using the radix passed in DE.  If the conversion is successful,
  528. ; the value is returned in BC.    HL points to the character that terminated
  529. ; the number, and A contains that character.  If an invalid character is
  530. ; encountered, the routine returns with the carry flag set and nonzero, and
  531. ; HL points to the offending character.
  532.  
  533. radbin:
  534.     ld    de,0        ; Initialize result
  535. radbin1:
  536.     or    a        ; Make sure carry is reset
  537.     call    sdelm        ; Test for delimiter (returns Z if delimiter)
  538.     ret    z        ; Return if delimiter encountered
  539.  
  540.     sub    '0'        ; See if less than '0'
  541.     ret    c        ; Return with carry set if so
  542.     cp    10        ; See if in range '0'..'9'
  543.     jr    c,radbin2    ; Branch if it is valid
  544.     cp    'A'-'0'        ; Bad character if < 'A'
  545.     ret    c        ; ..so we return with carry set
  546.     sub    7        ; Convert to range 10..15
  547. radbin2:
  548.     cp    c        ; Compare to radix in C
  549.     ccf            ; Carry should be set; this will clear it
  550.     ret    c        ; If carry now set, we have an error
  551. ;
  552. ; It's a valid digit.  Multiply DE by the radix and add it in
  553. ;
  554.     inc    hl        ; Point to next character
  555.     push    hl        ; Save it on the stack
  556.     ld    b,c        ; Radix to B
  557.     ld    hl,0        ; Clear an accumulator
  558.  
  559. mpy:    add    hl,de
  560.     djnz    mpy
  561.  
  562.     ld    e,a        ; Digit to E
  563.     ld    d,b        ; Zero to D
  564.     add    hl,de
  565.     ex    de,hl        ; New result to DE
  566.     pop    hl        ; Restore pointer
  567.     jr    radbin1
  568.  
  569. ;-----------------------------------------------------------------------------
  570.  
  571. ; SKDEL - Skip over delimiters (including spaces)
  572.  
  573. skdel:    call    sdelm
  574.     ret    nz        ; Not a delimiter
  575.     inc    hl
  576.     jr    skdel
  577.  
  578. ; SKNDEL - Skip to next delimiter (including space)
  579.  
  580. skndel:    call    sdelm
  581.     ret    z
  582.     inc    hl
  583.     jr    skndel
  584.  
  585. ;-----------------------------------------------------------------------------
  586.  
  587. ; This routine checks for a delimiter character pointed to by HL.  It returns
  588. ; with the character in A and the zero flag set if it is a delimiter.  All
  589. ; registers are preserved except A.
  590.  
  591. sdelm:
  592.     ld    a,(hl)        ; Get the character
  593.     exx            ; Use alternate register set (shorter code)
  594.     ld    hl,deldat    ; Point to delimiter list
  595.     ld    bc,delend-deldat; Length of delimiter list
  596.     cpir            ; Scan for match
  597.     exx            ; Restore registers
  598.     ret            ; Returns Z if delimiter
  599.  
  600. deldat:                ; List of delimiter characters
  601.     db    ' '
  602.     db    '='
  603.     db    '_'
  604.     db    '.'
  605.     db    ':'
  606.     db    ';'
  607.     db    '<'
  608.     db    '>'
  609.     db    ','
  610.     db    '-'
  611.     db    '/'
  612.     db    '\'
  613.     db    '|'
  614.     db    '~'
  615.     db    0        ; The ultimate delimiter
  616. delend:
  617.  
  618. ;-----------------------------------------------------------------------------
  619.  
  620.     dseg
  621.  
  622. data:                ; Beginning of area to initialize
  623. dmaadr:
  624.     ds    2
  625. mode:
  626.     ds    1
  627. secflag:
  628.     ds    1
  629. record:
  630.     ds    2
  631.  
  632. datalen    equ    $ - data    ; Size of area to initialize
  633.  
  634. stack:    defs    2        ; Place to keep system stack address
  635.  
  636.     end
  637. ;
  638. ; End of SAVE.Z80
  639.