home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / bbs / emx-util.lbr / PROT.MZC / PROT.MAC
Text File  |  1988-01-30  |  16KB  |  572 lines

  1. ;
  2. ;
  3. ; ==>>    THIS CODE WILL ONLY RUN ON A Z80 CPU
  4. ; ==>>    IT MUST BE COMPILED WITH M80 AND LINKED WITH L80
  5. ;
  6. ; PROTECT.MAC by Simon Ewins, Sysop EMX RCPM, Toronto, Ontario
  7. ;
  8. ; Based on:  PASSWORD.ASM v3.0 by Bo McCormick 08/06/81
  9. ;
  10. ;-----------------------------------------------------------------------
  11. ;
  12. ;     - The command line allows an ASCII value (^A through the upper
  13. ;    case letter Z) to be passed as the level of protection for the
  14. ;    .COM file.  If a code or level that is less than an ASCII
  15. ;    'space' is desired, you may use a caret (^) before the ASCII
  16. ;    character that is desired to turn it into a 'control' character.
  17. ;    One character value is reserved as an 'unprotect' switch.  In
  18. ;    the example below, ^Z is such a value.    The caret '^' may be
  19. ;    used as in ^^ but a space or @ may NOT.  If you enter a single
  20. ;    ^ as an argument an error will occur.
  21. ;
  22. ;     -  syntax is:
  23. ;
  24. ;        PROTECT FILENAME[.COM] ^Z   <-- to 'unprotect' the file
  25. ;        PROTECT FILENAME[.COM] 5    <-- set level to (ASCII)
  26. ;                             5 (35 hex)
  27. ;        PROTECT FILENAME[.COM] Q    <-- set level to (ascii)
  28. ;                            Q (51 hex)
  29. ;        PROTECT FILENAME[.COM] ^I   <-- set to (ASCII) CRL-I
  30. ;                            (9 hex)
  31. ;
  32. ;     - The .COM filetype is optional as .COM will be assumed and any
  33. ;    other filetype will generate an error exit
  34. ;
  35. ;     - This file, when run, relocates itself under the CCP and then
  36. ;    loads the .COM file requested.    The first record is moved to the
  37. ;    end of the file and replaced with a jump at 100h to the next
  38. ;    record at the end of the file.    There a little routine reads the
  39. ;    byte in memory that is your 'control' byte and tries to match
  40. ;    the protection level of the file.  If there is no match, a warm
  41. ;    boot is done.  If there is a match, or the level of protection
  42. ;    is less than the level of the file, then the last record is
  43. ;    moved back to 100h and the file is executed.
  44. ;
  45. ;     - Alternately you can set EXACT to YES and then the file will run
  46. ;    only if the levels match (no 'less than' stuff).
  47. ;
  48. ;     - If you update this file, first, be careful since the stack is
  49. ;    used to pass arguments to the program once it has relocated to
  50. ;    high memory.  If you do update please send a copy to:
  51. ;
  52. ;        EMX RCPM, Toronto, Ontario ... 416 484-9663
  53. ;
  54. ;-----------------------------------------------------------------------
  55. ;
  56. ; Equates
  57. ;
  58. NO    EQU    0
  59. YES    EQU    NOT NOT
  60. ;
  61. RDCHAR    EQU    1
  62. MSGOUT    EQU    9        ; BDOS functions
  63. INCON    EQU    10
  64. OPEN    EQU    15
  65. CLOSE    EQU    16
  66. DELETE    EQU    19
  67. READ    EQU    20
  68. BWRITE    EQU    21
  69. SETDMA    EQU    26
  70. ;
  71. CR    EQU    0DH        ; ASCII values
  72. LF    EQU    0AH
  73. EOS    EQU    '$'
  74. ;
  75. BOOT    EQU    0        ; 0 for standard CP/M
  76. BDOS    EQU    5
  77. FCB    EQU    5CH
  78. DEFBUF    EQU    80H
  79. TPA    EQU    100H
  80. ;
  81. ;-----------------------------------------------------------------------
  82. ;
  83. ; This is the address of the start of your CCP.  It can be determined by
  84. ; either using CPMLOOK, SHOW or TELL or with:
  85. ;
  86. ;
  87. ;    Under DDT or ZSID examine location 0001h take the value
  88. ;    at loation 0002h and subtract 16h from it.  Take the re-
  89. ;    sult and assume it to be the msb of a two byte value the
  90. ;    LBS of which is 0...  This is the value for the next
  91. ;    equate.  Example:
  92. ;              00Hh = 0C3H
  93. ;              01H  = 03H    ; Warm boot is 3 above BIOS
  94. ;              02H  = 0CEH    ; Page address is BIOS start
  95. ;
  96. ;            subtract 16H from 0CEH to get 0B8H
  97. ;            therefore CCP = 0B800H
  98. ;
  99. CCP    EQU    0A700H        ; Address of CCP
  100. ;
  101. ;-----------------------------------------------------------------------
  102. ;
  103. ; This is the address of the byte in memory to check against the one
  104. ; that the file is locked with..
  105. ;
  106. PROBYT    EQU    0003FH        ; Access level byte location
  107. ;
  108. ;-----------------------------------------------------------------------
  109. ;
  110. ; Id EXACT is YES, then the byte in memory and the level of the file
  111. ; must match exactly... If it is NO, then the value in memory must be
  112. ; equal to or greater than the level of the file
  113. ;
  114. EXACT    EQU    YES        ; True if bytes must match exactly
  115. ;
  116. ;-----------------------------------------------------------------------
  117. ;
  118. ; This is the character that you wish to use as the 'unprotect' key.  It
  119. ; cannot be used as a protection level as well.  if you select a control
  120. ; character, remember that you must use '^' in the command line followed
  121. ; by the ASCII character.
  122. ;
  123. UKEY    EQU    'Z'-40H        ; Use CTL-z as unprotect key
  124. ;                ;   (use ^Z on command line)
  125. ;
  126. ;-----------------------------------------------------------------------
  127. ;
  128. MOVLEN    EQU    (CODEND-CODBEG)+1 ; Length of relocated code
  129. RELLOC    EQU    CCP-MOVLEN-1    ; Start address of relocated code
  130. OFF    EQU    RELLOC-CODBEG    ; Dif between reloc code and assem code
  131. ;
  132. ;
  133.     .Z80
  134.     ASEG
  135.     ORG    100H
  136. ;
  137.     JP    START
  138. ;
  139. KEYCOD::DB    UKEY        ; Store unprotect key as a byte at 103h so
  140.                 ; That it may be easily patched
  141. ;
  142. ; Start of program
  143. ;
  144. START::    LD    A,(FCB+1)    ; See if help needed
  145.     CP    '?'
  146.     JP    Z,HELP        ; Yes
  147.     CP    '/'
  148.     JP    Z,HELP        ; Yes
  149.     CP    ' '
  150.     JP    Z,HELP        ; For sure!
  151.     LD    A,(FCB+9)    ; Get first char of extension
  152.     CP    ' '        ; If ' ' then change to .COM
  153.     JP    Z,NOTYPE
  154.     CP    'C'        ; If there is an extension,
  155.     JP    NZ,HELP        ; Make sure it's .COM
  156.     LD    A,(FCB+10)    ; Check second letter
  157.     CP    'O'
  158.     JP    NZ,HELP
  159.     LD    A,(FCB+11)
  160.     CP    'M'        ; Last letter
  161.     JP    Z,ISCOM0    ; If it is a .COM, then continue
  162.     JP    HELP        ; Wrong type
  163. ;
  164. NOTYPE::LD    A,'C'        ; Force filetype to .COM
  165.     LD    (FCB+9),A
  166.     LD    A,'O'
  167.     LD    (FCB+10),A
  168.     LD    A,'M'
  169.     LD    (FCB+11),A
  170. ;
  171. ISCOM0::LD    A,(FCB+17)    ; Get argument, if any
  172.     CP    ' '        ; None?
  173.     JP    Z,HELP        ; Explain this program
  174.     CP    '^'        ; Is it a control character?
  175.     JP    NZ,NOTCTL    ; No so no conversion needed
  176.     LD    A,(FCB+18)    ; Get next character
  177.     CP    ' '        ; If space then explain program
  178.     JP    Z,HELP
  179.     CP    'A'        ; Less than 'A' not allowed
  180.     JP    C,HELP
  181.     SUB    40H        ; Convert to control character
  182. ;
  183. NOTCTL::LD    HL,KEYCOD    ; Point to UKEY
  184.     CP    (HL)        ; Is it 'unprotect' code?
  185.     JR    Z,UNPSET    ; Yes, go set flag
  186.     LD    (PBYTE),A    ; No, so assume we want to protect file
  187.     JR    REL
  188. ;
  189. UNPSET::LD    (UBYTE),A    ; Store unprotect flag with value
  190. ;
  191. ; Now relocate the needed code up high and then jump to it...
  192. ;
  193. REL::    LD    DE,VERSIO
  194.     LD    C,MSGOUT
  195.     CALL    BDOS
  196.     LD    BC,MOVLEN    ; Number of bytes to move
  197.     LD    DE,RELLOC    ; Where to and ...
  198.     LD    HL,CODBEG    ; Where from
  199.     LDIR            ; Move code into place
  200.     JP    RELLOC        ; And go to it
  201. ;
  202. VERSIO::DB    CR,LF,'PROTECT  v1.0  --  (c)1984 Simon Ewins',CR,LF,EOS
  203. ;
  204. HELP::    LD    DE,HLPMSG
  205.     LD    C,MSGOUT
  206.     CALL    BDOS
  207.     JP    0
  208. ;
  209. HLPMSG::DB    CR,LF,LF
  210.     DB    'PROTECT  v1.0  --  (c)1984 Simon Ewins'
  211.     DB    CR,LF,LF
  212.     DB    '- the command line allows an ASCII value '
  213.     DB    '(^A through the upper case'
  214.     DB    CR,LF
  215.     DB    '  letter Z)  to be passed as the level '
  216.     DB    'of protection for the .COM file.'
  217.     DB    CR,LF
  218.     DB    '  If a code or level that is less than '
  219.     DB    'an ASCII ''space'' is desired you'
  220.     DB    CR,LF
  221.     DB    '  may use a caret (^) before the ASCII '
  222.     DB    'character that is desired to'
  223.     DB    CR,LF
  224.     DB    '  turn it into a ''control'' character.  '
  225.     DB    'One character value is reserved'
  226.     DB    CR,LF
  227.     DB    '  as an ''unprotect'' switch.  in the '
  228.     DB    'example below ^Z is such a value.'
  229.     DB    CR,LF
  230.     DB    '  the character ''^'' may be used as '
  231.     DB    'in ^^ but a space or ''@'' may NOT.'
  232.     DB    CR,LF
  233.     DB    '  id est: if you enter a single ^ as '
  234.     DB    'an argument an error will occur.'
  235.     DB    CR,LF,LF
  236.     DB    '-  syntax is:'
  237.     DB    CR,LF
  238.     DB    '        PROTECT FILENAME[.COM] ^Z   '
  239.     DB    '<-- to ''unprotect'' the file'
  240.     DB    CR,LF
  241.     DB    '        PROTECT FILENAME[.COM] 5    '
  242.     DB    '<-- set level to (ASCII) 5 (35 hex)'
  243.     DB    CR,LF
  244.     DB    '        PROTECT FILENAME[.COM] Q    '
  245.     DB    '<-- set level to (ASCII) Q (51 hex)'
  246.     DB    CR,LF
  247.     DB    '        protect filename[.com] ^I   '
  248.     DB    '<-- set to (ASCII) CRT-I (9 hex)'
  249.     DB    CR,LF,LF
  250.     DB    '- the .COM filetype is optional as '
  251.     DB    '.COM will be assumed and any'
  252.     DB    CR,LF
  253.     DB    '  other filetype will generate an error exit'
  254.     DB    CR,LF,EOS
  255. ;
  256. ; This code gets relocated to high memory where it loads, modifies and
  257. ; then saves the .COM file that is being protected...
  258. ;
  259. ; NOTE: All jumps from here to the end of the program should be rela-
  260. ;    tive.  If the JR label is out of range, use 'stepping-stones' as
  261. ;    intermediate jump locations. reference to labels for loading
  262. ;     registers etc., should be of the form: LABEL+off
  263. ;
  264. CODBEG    EQU    $        ; Mark start of code to relocate
  265. ;
  266.     LD    DE,OFF+RDMSG
  267.     LD    C,MSGOUT
  268.     CALL    BDOS
  269.     LD    DE,TPA        ; Point to where program goes
  270.     LD    C,SETDMA    ; Set DMA command
  271.     PUSH    DE        ; Save it
  272.     CALL    BDOS        ; And tell CP/M
  273.     LD    A,0        ; Zero record count
  274.     LD    (FCB+32),A
  275.     LD    (FCB+17),A    ; And any arguments
  276.     LD    (FCB+18),A
  277.     LD    C,OPEN        ; Open file command
  278.     LD    DE,FCB        ; Load address of FCB in DE
  279.     CALL    BDOS        ; Open file
  280.     INC    A        ; Successful?
  281.     JR    NZ,OPENOK    ; If so, then continue
  282.     LD    DE,OFF+ERR0
  283.     LD    C,MSGOUT
  284.     CALL    BDOS
  285.     JP    0        ; Error
  286. ;
  287. OPENOK::POP    DE        ; Get starting DMA back
  288. ;
  289. RLOOP::    LD    C,SETDMA    ; And set it in loop
  290.     PUSH    DE        ; Save it
  291.     CALL    BDOS
  292.     LD    DE,FCB        ; Point to FCB
  293.     LD    C,READ        ; Read sector command
  294.     CALL    BDOS        ; Do it
  295.     POP    DE        ; Get DMA address back
  296.     AND    A        ; Eof?
  297.     JR    NZ,RDDONE    ; If so, then go to work
  298.     PUSH    DE        ; Save dma
  299.     LD    HL,RELLOC    ; Check for overload of tpa
  300.     DEC    H        ; Page for safety
  301.     INC    D        ; Rest of page
  302.     AND    A        ; Clear carry
  303.     SBC    HL,DE        ; Top of tpa - current dma
  304.     JR    NC,DMAOK    ; Hl still greater
  305.     POP    DE        ; Unjunk stack
  306.     LD    DE,OFF+TPAMSG
  307.     LD    C,MSGOUT
  308.     CALL    BDOS
  309. ;
  310.     JP    0000H        ; Reboot
  311. ;
  312. TPAMSG::DB    CR,LF,'++ tpa too small ++',CR,LF,EOS
  313. DMAOK:
  314.     POP    DE        ; Get dma back
  315.     LD    HL,80H        ; Length of sector
  316.     ADD    HL,DE        ; Bump dma
  317.     EX    DE,HL        ; Put new address in de
  318.     JR    RLOOP        ; And read some more
  319. RDDONE:
  320.     LD    (OFF+ENDADD),DE    ; Save end of file
  321.     LD    A,(OFF+UBYTE)    ; Was code valid for unprotecting?
  322.     OR    A
  323.     JR    NZ,UNPRO    ; Knew the code so go do it
  324. ;
  325. ; Else falls through to protect routine...  Since if UBYTE is 0 then
  326. ; PBYTE must have a value and vice versa.  Further, the only way that
  327. ; UBYTE can have a by the time we reach here is if it was a valid match
  328. ; to the unprotect code.
  329. ;
  330. ; Protect the file
  331. ;
  332. PRO::    CALL    OFF+PROCHK    ; Check if file is protected now
  333.     OR    A
  334.     JR    Z,PROT        ; 1=yes, 0=no
  335.     LD    DE,OFF+ERR1
  336.     LD    C,MSGOUT
  337.     CALL    BDOS
  338.     JP    0
  339. ;
  340. PROT::    EX    DE,HL        ; Got to make sure this file has not been
  341.     LD    DE,128        ; Protected before, else the file will grow
  342.     AND    A        ; By one sector each time it is protected!
  343.     SBC    HL,DE        ; Hl->start of last sector
  344.     LD    DE,TPA        ; Now we compare it to the first sector
  345.     CALL    OFF+MATCH
  346.     CP    0        ; If 0 then sectors are the same
  347.     JR    Z,NOMOVE    ; So don't adjust pointers
  348.     LD    DE,(OFF+ENDADD)    ; Get back end of file
  349.     LD    (OFF+OLDEND),DE    ; Set pointer for runtime load of sector 1
  350.     LD    A,(OFF+PBYTE)    ; Get protection level requested
  351.     LD    (OFF+LEVEL),A    ; Store protection level for this program
  352.     LD    HL,TPA        ; And save original data at end of file
  353.     LD    BC,128        ; De already has address of end of program
  354.     LDIR            ; Move first sector to end of program
  355.     LD    HL,OFF+PRODAT    ; Get protect routine
  356.     LD    DE,TPA        ; And move it to start of file
  357.     LD    BC,128
  358.     LDIR            ; Move it
  359.     LD    HL,(OFF+ENDADD)    ; Need to save one more sector than original
  360.     LD    DE,128        ; So bump marker
  361.     ADD    HL,DE
  362.     LD    (OFF+ENDADD),HL    ; And store it in write routine
  363.     JR    WRITE
  364. ;
  365. NOMOVE::LD    HL,(OFF+ENDADD)    ; Set runtime sector load address
  366.     LD    DE,128        ; Since it was here already we must point
  367.     AND    A        ; To the second last sector
  368.     SBC    HL,DE
  369.     LD    (OFF+OLDEND),HL    ; Store adjusted pointer
  370.     LD    A,(OFF+PBYTE)    ; Not moving sector but must set new level
  371.     LD    (OFF+LEVEL),A    ; Set level
  372.     LD    HL,OFF+PRODAT    ; Move protect routine to tpa
  373.     LD    DE,TPA
  374.     LD    BC,128
  375.     LDIR
  376.     JR    WRITE        ; No need to adjust end address
  377. ;
  378. ; Unprotect the file
  379. ;
  380. UNPRO::    CALL    OFF+PROCHK    ; See if already protected
  381.     OR    A
  382.     JR    NZ,UNPROT    ; 1=yes, 0=no
  383.     LD    DE,OFF+ERR2
  384.     LD    C,MSGOUT
  385.     CALL    BDOS
  386. ;
  387.     JP    0000H        ; Reboot
  388. ;
  389. ERR2::    DB    CR,LF,'++ file not protected ++',CR,LF,EOS
  390. ;
  391. UNPROT::EX    DE,HL        ; End of program in hl now
  392.     LD    DE,128        ; Less the sector for protecting
  393.     AND    A        ; Clear carry
  394.     SBC    HL,DE        ; HL->old last sector of file
  395.     LD    DE,TPA        ; Start of file
  396.     LD    BC,128        ; Move one sector
  397.     LDIR            ; Back in place
  398.  
  399. ;
  400. ; This writes either the full file, if we just protected it, plus one
  401. ; record or the full file less the last record, if we unprotected it...
  402. ;
  403. WRITE::    LD    DE,OFF+WRMSG
  404.     LD    C,MSGOUT
  405.     CALL    BDOS
  406.     XOR    A        ; Zero A
  407.     LD    (FCB+12),A    ; Zero bytes in FCB
  408.     LD    (FCB+14),A
  409.     LD    (FCB+32),A
  410.     LD    C,OPEN        ; Open file command
  411.     LD    DE,FCB        ; Point to FCB
  412.     CALL    BDOS        ; Open the file
  413.     LD    DE,TPA        ; Point to program start
  414.     PUSH    DE
  415. ;
  416. WLOOP1:;POP    DE        ; Get DMA
  417.     PUSH    DE        ; Put it back on stack
  418.     LD    C,SETDMA    ; Set DMA command
  419.     CALL    BDOS        ; Tell CP/M
  420.     LD    DE,FCB        ; Point to FCB
  421.     LD    C,BWRITE    ; Write sector command
  422.     CALL    BDOS        ; Do it
  423.     POP    HL        ; Get dma address from stack
  424.     LD    DE,80H        ; Length of sector
  425.     ADD    HL,DE        ; HL has new DMA
  426.     PUSH    HL        ; Put it on stack
  427. ;
  428. ;
  429.     .8080
  430. ;
  431. ;
  432.     DB    (LXI D)
  433. ;
  434. ;
  435.     .Z80
  436. ;
  437. ;
  438. ENDADD::DW    0000H        ; Get ending address
  439.     AND    A        ; Clear carry
  440.     SBC    HL,DE        ; See if current dma is less
  441.     JR    C,WLOOP1    ; Still more to write
  442. ;
  443.     LD    C,CLOSE        ; That's it. Close the file
  444.     LD    DE,FCB        ; Point to FCB
  445.     CALL    BDOS        ; Do it
  446.     LD    DE,OFF+DNMSG    ; Say we done
  447.     LD    C,MSGOUT
  448.     CALL    BDOS
  449.     JP    0000H        ; Reboot
  450. ;
  451. ; This data gets moved down to the start of the TPA where it is executed
  452. ; each time the protected file is run. it is the code that checks the
  453. ; values that determine if the file may be run or not...  if it can be
  454. ; run, then this code replaces itself with the code that was in the
  455. ; first reecord of the file originally.... control is then passed back
  456. ; to the start of the TPA...
  457. ;
  458. TPAOFF    EQU    $
  459. ;
  460. PRODAT::JR    PROT0        ; Jump around ff marker stuff
  461.     DW    0FFFFH
  462.     DW    0FFFFH
  463.     DW    0FFFFH
  464.     DW    0FFFFH        ; To mark protected file
  465. ;
  466. PROEXT::LD    DE,TPA+PROMSG-TPAOFF
  467.     LD    C,MSGOUT
  468.     CALL    BDOS
  469.     JP    00000H
  470. ;
  471. PROMSG::DB    CR,LF,'Restricted access...',EOS
  472. ;
  473. ;
  474.     .8080
  475. ;
  476. ;
  477. PROT0::    DB    (MVI B)
  478. ;
  479. ;
  480.     .Z80
  481. ;
  482. ;
  483. LEVEL::    DB    0        ; (0 is set to code earlier)
  484.     LD    HL,PROBYT    ; Get current user's level
  485.     LD    A,(HL)
  486.     CP    B        ; Match to file's level
  487. ;
  488.      IF    EXACT
  489.     JR    NZ,PROEXT    ; No match so drop out
  490.      ENDIF            ; End EXACT test
  491. ;
  492.      IF    NOT EXACT
  493.     JR    C,PROEXT    ; Current level less than protect level
  494.      ENDIF            ; End not exact test
  495. ;
  496. ;
  497.     .8080
  498. ;
  499. ;
  500.     DB    (LXI H)
  501. ;
  502. ;
  503.     .Z80
  504. ;
  505. ;
  506. OLDEND::DW    0000H        ; Filled with data at protect time
  507.     PUSH    HL        ; Save for after move
  508.     LD    DE,129        ; Point to end of current program + 1
  509.     ADD    HL,DE
  510.     PUSH    HL        ; Hl=address to move to
  511.     EX    DE,HL        ; De now=where we are going
  512.     LD    HL,TPA+START1-TPAOFF ; Where we move from
  513.     LD    BC,END1-START1    ; Move this much
  514.     LDIR
  515.     POP    HL        ; Relocated code
  516.     JP    (HL)        ; Go finish running file
  517. ;
  518. START1::POP    HL        ; Get back address of real program start
  519.     LD    DE,TPA        ; Move to start of tpa
  520.     LD    BC,128
  521.     LDIR
  522.     JP    TPA        ; Go run file
  523. ;
  524. END1::    DB    0
  525. ;
  526. ; End of the control code section
  527. ;
  528. ; This routine tests to see if the file loaded is protected or not
  529. ;
  530. PROCHK::LD    HL,TPA+2    ; Point to start of file + 2 for jump relative
  531.     LD    C,8        ; Testing next 8 bytes in a row for 0ffh
  532. ;
  533. TESTIT::LD    A,(HL)
  534.     CP    0FFH
  535.     JR    NZ,NPRO        ; Not protected
  536.     INC    HL
  537.     DEC    C
  538.     JR    NZ,TESTIT    ; Check all 8 bytes
  539. ;
  540. YPRO::    LD    A,1        ; Indicate protected file
  541.     RET
  542. ;
  543. NPRO::    LD    A,0        ; Indicate unprotected file
  544.     RET
  545. ;.....
  546. ;
  547. ; Compare 2 records, return with A=0 if equal
  548. ;
  549. MATCH::    LD    B,128        ; Number of bytes to check
  550. ;
  551. MLOP::    LD    A,(DE)
  552.     SUB    (HL)
  553.     RET    NZ
  554.     INC    DE
  555.     INC    HL
  556.     DJNZ    MLOP        ; Do all 128 bytes
  557.     RET            ; A=0
  558. ;.....
  559. ;
  560. ERR0::    DB    CR,LF,'++ Can''t open file ++',CR,LF,EOS
  561. ERR1::    DB    CR,LF,'++ already protected ++',CR,LF,EOS
  562. RDMSG::    DB    CR,LF,'Reading....',EOS
  563. WRMSG::    DB    CR,LF,'Writing....',EOS
  564. DNMSG::    DB    CR,LF,'Done.......',CR,LF,EOS
  565. ;
  566. PBYTE::    DB    0        ; Flags protect wanted
  567. UBYTE::    DB    0        ; Flags unprotect wanted
  568. ;
  569. CODEND    EQU    $
  570. ;
  571.     END
  572.