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 / CCP / XTCPM15.LBR / XTCPM15.AQM / XTCPM15.ASM
Assembly Source File  |  2000-06-30  |  41KB  |  1,537 lines

  1. ;**********************************************************
  2. ;                              *
  3. ;              EXTENDED CPM-- 12/13/81          *
  4. ;      DESIGNED TO BE PORTABLE TO ANY CP/M 2.2      *
  5. ;       SYSTEM THAT IS IN ORIGINAL 8080 CODE FOR CCP.      *
  6. ;    (will work with others also, but you will      *
  7. ;    have to find all of the CCP equates.)          *
  8. ;             RLP                  *
  9. ;                              *
  10. ;        will assemble w/ASM.COM              *
  11. ;                              *
  12. ;    Donated 11/22/81 for the benefit of hobby      *
  13. ;    computing, but may not be sold or copied      *
  14. ;    for a profit.                      *
  15. ;                              *
  16. MSIZE    EQU    61        ;MEMORY SIZE THIS VERS      *
  17.                 ;CHANGE TO YOUR SIZE HERE *
  18. OVERLAY    EQU    OVERLAY        ;COMPUTED SYSGEN OVERLAY  *
  19. ;                              *
  20. ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  21. ;                        >>
  22. ;    *** I M P O R T A N T ***        >>
  23. ;                        >>
  24. ; You must obtain the address for CBOOT from    >>
  25. ; the argument of the first jump at the        >>
  26. ; beginning of YOUR BIOS and place it in the     >>
  27. ; conditional equate assembled for your system.    >>
  28. ; Make it relative to the beginning of the    >>
  29. ; BIOS as shown.                >>
  30. ;                        >>
  31. ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  32. ;
  33. ;**********************************************************
  34. ;
  35. ;           XTCPM.ASM  VERS 1.5
  36. ;
  37. ;    THIS PROGRAM PROVIDES FOR AN EXPANSION OF YOUR
  38. ;    SYSTEM BY EITHER ONE OR 2 KBYTES WITHOUT THE NEED
  39. ;    FOR A SPECIAL SYSGEN.  JUST ADD THIS CODE TO YOUR
  40. ;    SYSTEM BY OVERLAYING YOUR CPMxx.COM FILE USING DDT.
  41. ;    AFTER YOU HAVE OVERLAYED THE CODE INTO CPMxx.COM
  42. ;    WITH DDT, DO TWO SAVES. ONE, SAVE YOUR CPMxx.COM
  43. ;    FILE AS USUAL. TWO, DO A SAVE OF THE CODE WHICH
  44. ;    WILL BE IN THE IMAGE AT 100H. THIS WILL BE A TRAN-
  45. ;    SIENT THAT YOU MUST KEEP ON YOUR 'A' DRIVE AND CON-
  46. ;    TAINS THE ADDITIONAL CODE - SO SAVE IT WITH ENOUGH
  47. ;    SECTORS TO WRITE 1 OR 2 KB DEPENDING ON THE SIZE.
  48. ;    NAME THE TRANSIENT 'XTCPM.COM'. BE SURE THAT YOUR
  49. ;    BIOS IS SET TO DO A TURNKEY START BY HAVING IT
  50. ;    JMP TO THE FIRST ENTRY POINT (CCP+0H) AFTER BIOS
  51. ;    INITIALIZATION.  SOME PROPRIETARY BIOS'S DO THIS
  52. ;    THROUGH A MODE BYTE. FINALLY USE YOUR NORMAL 
  53. ;    'SYSGEN' TO WRITE THE CPMxx.COM TO YOUR SYSTEM
  54. ;    TRACKS. IT IS PREFERABLE THAT YOUR BIOS DO A JUMP
  55. ;    TO THE SECOND ENTRY POINT IN THE CCP (CCP+3H) ON
  56. ;    A WARM BOOT, HOWEVER THIS CODE WILL PROPERLY HANDLE
  57. ;    THE SITUATION EVEN IF YOUR BIOS IS NOT IMPLEMENTED
  58. ;    THAT WAY.
  59. ;
  60. ;    THE EXPANDED CODE SHOWN HERE PROVIDES FOR AN
  61. ;    EXTENDED CCP THAT CAN CONTAIN ADDITIONAL USER
  62. ;    DEFINED CCP COMMANDS AS WELL AS TO MAKE TRANSIENTS
  63. ;    APPEAR AS CCP-LIKE IN THAT THEY CAN BE INVOKED
  64. ;    REGARDLESS OF LOGGED DRIVE/USER AREA. THUS IT IS
  65. ;    COMPLETELY UN-NECESSARY TO PLACE THESE TRANSIENTS
  66. ;    IN MULTIPLE USER AREAS.  IT ALSO PROVIDES FOR
  67. ;    TWO LEVELS OF PASSWORD PROTECTION.  ADD A TURNKEY
  68. ;    START OF WARD'S 'BYE' W/O PASSWORD TO MAKE A VERS-
  69. ;    ATILE ON-LINE SYSTEM. JUST PUT 'BYE' AT 'FILNAM'
  70. ;    PRECEEDED BY A '3' AND ADD A TEMINATING NULL.
  71. ;    THEN PLACE 'BYE.COM' IN USER 13 ON YOUR 'A' DRIVE
  72. ;    AND SET TNKY2 EQUAL TO TRUE.
  73. ;
  74. ;    AS DISTRIBUTED HERE, ALL OF THE FEATURES ARE
  75. ;    AVAILABLE WITH LESS THAN ONE KILOBYTE OF SPACE ABOVE
  76. ;    CP/M. THE CODE REQUIRES A Z80 CPU BUT MAY BE
  77. ;    CONVERTED TO 8080 OR 8085. STUFF THE HOLES W/CARE.
  78. ;
  79. ;    TESTED OK WITH LIFEBOAT CP/M FOR NORTH STAR AND
  80. ;    NORTH STAR'S CP/M PRODUCT. IF YOU ARE USING THE
  81. ;    NORTH STAR CP/M WITH HARD DISK OR NON-STANDARD
  82. ;    PROM, BE CAREFUL NOT TO OVERWRITE THE LAST 80H
  83. ;    OF THE USER AREA CODE STARTING AT 3380H IN IMAGE.
  84. ;    ALSO BE SURE TO SAVE 54 FOR A CPMXX.COM FILE SINCE
  85. ;    THE IMAGE STARTS HIGHER THAN THE USUAL STANDARD.
  86. ;
  87. ;    ALSO TESTED WITH A STANDARD CP/M USING 8 IN DISKS
  88. ;    AND A MICROMATION DOUBLER.
  89. ;
  90. ;    YOU CAN APPEND YOUR OWN CUSTOMIZED VERSION OF 'BYE'
  91. ;    WITHOUT A MOVER INTO THE USER2 AREA IF YOU ARE CARE-
  92. ;    FUL TO AVOID LABEL CONFLICTS. IF YOU DO SO, THEN ADD
  93. ;    A COMMAND STRING AT THE 0 PASSWORD LEVEL AND POINT
  94. ;    TO THE ADDRESS OF YOUR 'BYE' ENTRY POINT. ALSO,
  95. ;    REDIRECT THE STACK IN 'BYE' TO BE THE SAME AS THE
  96. ;    STACK IN THIS CODE AND ELIMINATE THE SEPARATE STACK.
  97. ;    ALSO SEE THE NOTE AT LABEL CCPINIT.
  98. ;
  99. ;    NOTE....THIS PROGRAM DOES NOT CLOBBER ANYTHING IN THE
  100. ;    TPA EXCEPT WHEN LOADING 'BYE' AS A TRANSIENT WHICH
  101. ;    CAN BE AVOIDED AS ABOVE.
  102. ;
  103. ;    YOU CAN ELIMINATE THE USER1 CODE AREA IN ITS ENTIRETY
  104. ;    IF YOU ARE ALREADY HAPPY WITH YOUR I/O DRIVERS. THERE
  105. ;    IS A CONDITIONAL ASSEMBLY EQUATE TO ACCOMPLISH THIS.
  106. ;
  107. ;    12/13/81 Now patches the CCP to allow changing user
  108. ;    area on the command line. i.e, A: 2 or C: 12 changes
  109. ;    the user area on A to 2 or on C to 12. Logging a
  110. ;    drive with for example B: if you are already in user
  111. ;    x will log you to the B drive, user x. The USER command
  112. ;    still works also but will not give an error message
  113. ;    if there is no user number on the command line.
  114. ;
  115. ;    12/6/81 Fixed warm boot branch address in CCPINIT.
  116. ;    Added second DIR string and address so that CCP code
  117. ;    for DIR will run at 0 password level and a DIR.COM
  118. ;    transient will run above that level if it is on the
  119. ;    system disk.  See NOTE just above label DIR1.
  120. ;    Changed location of PASBYTE vector to the buffer at
  121. ;    the end of the BDOS (spare location) so that if the
  122. ;    CCP is crashed by DDT or anything else, BYE will still
  123. ;    be able to find the PASBYTE to reset it. Former loc-
  124. ;    ation of this vector was at a spare location in the CCP.
  125. ;    Clarified USER2 equate for IF STDCPM.   RLP
  126. ;
  127. ;    12/4/81 Major revision, see the DOC file. Also
  128. ;    cleaned up the code.            RLP
  129. ;
  130. ;    11/30/81 Added code to make USERs 13, 14, & 15 on 'A'
  131. ;    universal depending on password level achieved at
  132. ;    log-on time. Removed nested IF's. Cleaned up code so
  133. ;    that a warm boot will properly initialize the CCP.
  134. ;    Also removed bug that would have prevented a file
  135. ;    from being executed by a transient that loads the
  136. ;    command line, sets the buffer pointer, and jumps to
  137. ;    the beginning of the CCP.        RLP
  138. ;
  139. ;    11/25/81 Added conditional assembly equate to
  140. ;    allow removal of i/o drivers and added routines
  141. ;    to link the code in USER2 to your own customized
  142. ;    BIOS.                    RLP
  143. ;    
  144. ***********************************************************
  145. ;
  146. ;        SYSTEM EQUATES
  147. ;    IMPORTANT   You must check these system equates to
  148. ;be sure that they are valid for your system and change them
  149. ;if they are not.  You may choose to integrate the USER1 code
  150. ;with your open BIOS if you have one and thus eliminate the
  151. ;USER1 equate.  USER2 will usually be just above CP/M including
  152. ;any buffer and will usually be MSIZE*1024+32. 32 is to allow
  153. ;room for stack. Change the value of ADJUST until the values
  154. ;for CCP, BDOS and BIOS are correct for your system. The value
  155. ;0D00H for Lifeboat on North Star and for North Star CP/M is
  156. ;correct, and the value 600H is correct for standard CP/M.
  157. ;
  158. FALSE    EQU    0
  159. TRUE    EQU    NOT FALSE    ;SEE OPTIONS BLOCK
  160.                 ;TO SELECT ALL OPTIONS
  161. ;
  162. IOBYTE    EQU    0003H        ;I/O BYTE ADDRESS
  163. DRIVE    EQU    0004H        ;LOC OF CURR DRV BYTE
  164. STAKSIZ    EQU    32        ;15 LEVEL STACK + BOOT FLAG
  165.                 ;AND PASBYTE
  166. ;
  167. ;        - - - - - - - - - - - - -
  168. ;
  169. ;select only one of these true except that if Lifeboat BIOS
  170. ;then make decision on S22X
  171. ;
  172. STDCPM    EQU    FALSE    ;true if standard CP/M on IBM
  173.             ;compatible floppy disk.
  174. NSTRCPM    EQU    FALSE    ;true if North Star CP/M
  175. LIFBOAT    EQU    TRUE    ;true if Lifeboat CP/M for North
  176.             ;Star DQ.
  177. S22X    EQU    TRUE    ;TRUE FOR 2.21A & 2.22. THIS IS A
  178.             ;SPECIAL EQUATE FOR LIFEBOAT BIOS'S
  179.             ;AND ANY OTHERS THAT HAVE ADDED AN
  180.             ;ADDITIONAL JMP FOR WINIT IN THE 
  181.             ;USER1 JUMP TABLE. SET TO FALSE
  182.             ;FOR ALL OTHERS. BE SURE THAT YOUR
  183.             ;BIOS JMP TABLE IS PROPERLY LINKED
  184.             ;TO USER1 OR JUST FORGET IT IF YOU
  185.             ;INTEGRATE THIS CODE INTO YOUR 
  186.             ;OPEN BIOS.
  187. M2BIOS    EQU    FALSE    ;true if micromation bios
  188.             ;
  189. ;        - - - - - - - - - - - -
  190.             ;
  191. ;
  192. SKIP    EQU    0    ;EQUATE THIS TO SIZE OF ROM TO SKIP
  193.     ;NOTE:  This will add an additional offset to the
  194.     ;    USER2 equate if you wish to place the USER2
  195.     ;    code above any PROM or ROM areas. Thus, it
  196.     ;    will be unecessary to reserve space between
  197.     ;    the top of CP/M and ROM
  198.     ;
  199.     IF    LIFBOAT
  200.     ;
  201. ADJUST    EQU    0D00H
  202. BIOS    EQU    (MSIZE*1024)-ADJUST    ;BASE OF BIOS
  203. USER1    EQU    BIOS+0700H        ;BASE 1RST USER AREA
  204. USER2    EQU    MSIZE*1024+STAKSIZ+SKIP    ;BASE 2ND USER AREA
  205. RAMEND    EQU    0FC00H            ;CHANGE TO YOUR VALUE
  206. CBOOT    EQU    BIOS+80H        ;COLDBOOT VECTOR FOR 2.22
  207. CCPIMAGE EQU    0A00H            ;CHANGE THIS TO EQUAL THE
  208.                     ;ADDRESS OF YOUR CCP IN
  209.                     ;THE DDT/SYSGEN IMAGE.
  210. OVERLAY    EQU    2000H-BIOS        ;COMPUTED OVERLAY
  211.     ;
  212.     ENDIF
  213.     ;
  214.     IF    NSTRCPM
  215.     ;
  216. ADJUST    EQU    0D00H
  217. BIOS    EQU    (MSIZE*1024)-ADJUST    ;BASE OF BIOS
  218. USER1    EQU    BIOS+0700H        ;BASE 1RST USER AREA
  219. USER2    EQU    MSIZE*1024+STAKSIZ+SKIP    ;BASE 2ND USER AREA
  220. RAMEND    EQU    0FC00H            ;CHANGE TO YOUR VALUE
  221. CBOOT    EQU    BIOS+0xxH
  222. CCPIMAGE EQU    1500H
  223. OVERLAY    EQU    2B00H-BIOS        ;COMPUTED OVERLAY
  224.     ;
  225.     ENDIF
  226.     ;
  227.     IF    STDCPM
  228.     ;
  229. ADJUST    EQU    600H
  230. BIOS    EQU    (MSIZE*1024)-ADJUST    ;BASE OF BIOS
  231. ;USER1    EQU    BIOS + (YOUR OFFSET TO USER1 PATCH AREA) 
  232. USER2    EQU    MSIZE*1024+STAKSIZ+SKIP    ;*NOTE* IF YOUR BIOS CODE
  233.                     ;INCLUDING ITS BUFFER SPACE
  234.                     ;HAS SPACE LEFT BELOW
  235.                     ;MSIZE*1024, YOU CAN SUBTRACT
  236.                     ;THE AMOUNT OF SPACE YOU HAVE
  237.                     ;LEFT FROM THIS USER2 EQUATE.
  238.                     ;SEE THE CODE AT 'IF M2BIOS'
  239.                     ;BELOW FOR AN EXAMPLE OF THIS. 
  240. ;RAMEND    EQU    (PUT YOUR VALUE HERE)
  241. CBOOT    EQU    BIOS+0xxH
  242. CCPIMAGE EQU    980H            ;ADDR OF CCP IN DDT IMAGE
  243. OVERLAY    EQU    1F80H-BIOS        ;COMPUTED OVERLAY
  244.     ;
  245.     ENDIF
  246.     ;
  247.     IF    M2BIOS
  248.     ;This is for a particular user's CBIOS that uses a
  249.     ;Micromation Doubler and has a user code area begin-
  250.     ;ning at BIOS+23DH.  Make your own conditional ass-
  251.     ;embly equates for your values.
  252. ADJUST    EQU    600H
  253. BIOS    EQU    (MSIZE*1024)-ADJUST
  254. USER1    EQU    BIOS+23DH        ;BASE 1RST USER AREA
  255. USER2    EQU    MSIZE*1024+STAKSIZ-256+SKIP ;BASE 2ND USER AREA
  256. RAMEND    EQU    0F400H            ;CHANGE TO YOUR VALUE
  257.                     ;USED ONLY IN PARITY
  258.                     ;SETTING CODE IN 'INITIAL'
  259. CBOOT    EQU    BIOS+0ABH
  260. CCPIMAGE EQU    980H            ;ADDR OF CCP IN DDT IMAGE
  261. OVERLAY    EQU    1F80H-BIOS        ;COMPUTED OVERLAY
  262.     ;
  263.     ENDIF
  264.     ;
  265. BOOTFLG    EQU    USER2-1            ;LOC OF BOOT FLAG
  266.                     ;IF NOT 0, then a
  267.                     ;cold boot is in progress.
  268. PASBYTE    EQU    USER2-2            ;LOC OF PASBYTE
  269. STACK    EQU    USER2-2            ;TOP OF STACK
  270. CCP    EQU    BIOS-1600H        ;BASE OF CCP
  271. BDOS    EQU    CCP+800H        ;BASE OF BDOS
  272. ;
  273. ;
  274. IOBYT    EQU    00000001B    ;VALUE OF IOBYTE
  275.         ; ; ; ;---------;CONSOLE IS TTY:    00
  276.         ; ; ;        ;        CRT:    01
  277.         ; ; ;        ;        BAT:    10
  278.         ; ; ;        ;        UC1:    11
  279.         ; ; ;-----------;READER IS  TTY:    00
  280.          ; ;        ;        RDR:    01 
  281.         ; ;        ;        UR1:    10 
  282.         ; ;        ;        UR2:    11 
  283.         ; ;-------------;PUNCH IS   TTY:    00 
  284.         ;        ;        PUN:    01 
  285.         ;        ;        UP1:    10 
  286.         ;        ;        UP2:    11  
  287.         ;---------------;LIST IS    TTY:    00 
  288.                 ;        CRT:    01 
  289.                 ;        LPT:    10 
  290.                 ;-----------UL1:    11 
  291. ;
  292. DRIVERS    EQU    TRUE    ;WANT THE I/O DRIVERS? (CONTAINED
  293.             ;IN USER1 CODE AREA)
  294. BGTST    EQU    TRUE    ;WANT BACKGROUND MEMORY TEST?
  295. ;                               
  296. PARITY    EQU    TRUE    ;WANT TO SET PARITY MEMORY       
  297. ;                               
  298. TNKY2    EQU    TRUE    ;WANT 2ND TURNKEY START
  299. ;
  300. MAXUSER    EQU    2    ;FOR EXAMPLE..MAX PUBLIC USER AREA 
  301. ;
  302. MAXDRIV    EQU    4    ;FOR EXAMPLE..NUMBER OF DRIVES
  303. ;                               
  304. SGNON    EQU    FALSE    ;NEED SIGN ON MESSAGE?
  305. ;
  306. PASBYT    EQU    00100100B    ;PASSWORD BYTE       
  307.           ;  ;----------;PASSWORD 2 REQUIRED       
  308.           ;-------------;PASSWORD 1 REQUIRED       
  309. ;                               
  310. ;END OF OPTIONS BLOCK                       
  311. ;***********************************************************
  312. ;***********************************************************
  313. ;
  314. ;        PORT ASSIGNMENTS
  315. ;
  316. ;Be sure to check port assignments for your system.
  317. ;
  318. PARAL    EQU    0    ;PARALLEL I/O PORT
  319. SER1D    EQU    2    ;LEFT SERIAL PORT DATA
  320. SER1ST    EQU    3    ;LEFT SERIAL PORT STATUS
  321. SER2D    EQU    4    ;RIGHT SERIAL PORT DATA
  322. SER2ST    EQU    5    ;RIGHT SERIAL PORT STATUS
  323. MOTHER    EQU    6    ;MOTHERBOARD COMMAND/STATUS
  324. MEMORY    EQU    0C0H    ;PARITY MEMORY PORT unique to
  325.             ;North Star
  326. ;
  327. ;**********************************************************
  328. ;START OF USER1 CODE
  329. ;
  330. ;        JUMP TABLE LINKS BIOS TO XTCPM
  331. ;        The rest of the jumps are at base
  332. ;        of the BIOS.
  333. ;
  334. ;NOTICE.  The IOBYTE processor in this code saves and re-
  335. ;stores BC, DE, and HL registers.
  336. ;
  337. ;**********************************************************
  338. ;
  339.     IF    DRIVERS
  340.     ;
  341.     ORG    USER1
  342.     JMP    INITIAL        ;USER INIT ROUTINE
  343.     ;
  344.     ENDIF
  345.     ;
  346.     IF    S22X
  347.     ;
  348.     DS    3        ;SPACE FOR JMP TO WINIT
  349.                 ;USED BY 221A & HIGHER ONLY
  350.     ENDIF
  351.     ;
  352.     IF    DRIVERS AND NOT (STDCPM OR M2BIOS)
  353.     ;
  354.     JMP    CONST        ;CONSOLE STATUS ROUTINE
  355.     JMP    CONIN        ;CONSOLE INPUT
  356.     JMP    CONOUT        ;CONSOLE OUTPUT
  357.     ;
  358.     ENDIF
  359.     ;
  360.     IF    DRIVERS
  361. ;
  362. ;***********************************************************
  363. ;
  364. ;        IOBYTE PROCESSOR
  365. ;
  366. ;***********************************************************
  367. ;
  368. CONSOL:
  369.     MVI    A,CONCNT    ;SHIFT COUNTER
  370. ;
  371. DISPAT:    ;I/O DISPATCHER - TO MAP LOGICAL TO PHYSICAL
  372.     XTHL             ;GET RETURN ADDR & SAVE HL
  373.     PUSH    B        ;SAVE BC
  374.     PUSH    D        ;SAVE DE
  375.      MOV    B,A        ;PUT COUNTER VALUE IN B
  376.     LDA    IOBYTE        ;GET THE IO BYTE
  377.     ;
  378. DISPAT1:
  379.     DCR    B        ;SHIFT IOBYTE UNTIL
  380. DB    JRZ,    DISPAT2-$-1    ;COUNT IN B=0
  381.     RRC
  382.     RRC
  383. DB    JR,    DISPAT1-$-1 AND 0FFH ;SHIFT NEXT TWO BYTES
  384.     ;
  385. DISPAT2:
  386.     ANI    03H        ;MASK OUT BITS 0,1
  387.     RLC            ;DOUBLE
  388.     MVI    D,0        ;CLEAR D
  389.     MOV    E,A        ;
  390.     DAD    D        ;H,L POINTS TO ENTRY
  391.     MOV    A,M        ;GET LOW BYTE
  392.     INX    H        ;POINT TO HIGH BYTE
  393.     MOV    H,M        ;GET HIGH BYTE
  394.     MOV    L,A        ;H,L POINTS TO SUBR.
  395.     POP    D        ;RESTORE DE
  396.     POP    B        ;RESTORE BC
  397.     XTHL            ;RSTR HL & PUT RET ON STACK
  398.     RET
  399. ;
  400. CONST:    ;CONSOLE STATUS, RETURN 0FFH IF READY ,0 IF NOT
  401.     CALL    CONSOL        ;COMMON ROUTINE
  402.     DW    TTYST        ;TTY STATUS
  403.     DW    CRTST        ;CRT STATUS
  404.     DW    RDRST        ;READER STATUS 
  405.     DW    UC1ST        ;USER CONSOLE STATUS
  406. ;
  407. CONIN:
  408.     ENDIF
  409.     ;
  410.     IF    BGTST AND DRIVERS
  411.     ;
  412.     CALL    TEST        ;BACKGROUND MEMORY TEST
  413.     ;
  414.     ENDIF
  415.     ;
  416.     IF    DRIVERS
  417.     ;
  418.     CALL    CONST
  419.     ORA    A        ;SET CC
  420. DB    JRZ,    CONIN-$-1 AND 0FFH
  421.     ;CONSOLE INPUT ROUTINE
  422.     CALL    CONSOL        ;COMMON CONSOLE ROUTINE
  423.     DW    TTYIN        ;TTY INPUT
  424.     DW    CRTIN        ;CRT INPUT
  425.     DW    READER        ;READER INPUT 
  426.     DW    UC1IN        ;USER CONSOLE INPUT
  427.     ;
  428. CONOUT: ;CONSOLE OUTPUT ROUTINE
  429.     CALL    CONSOL        ;COMMON ROUTINE
  430.     DW    TTYOUT        ;TTY OUTPUT
  431.     DW    CRTOUT        ;CRT OUTPUT
  432.     DW    LIST        ;LIST OUTPUT 
  433.     DW    UC1OUT        ;USER CONSOLE OUTPUT
  434. ;
  435. READER0:
  436.     ENDIF
  437.     ;
  438.     IF    BGTST AND DRIVERS
  439.     ;
  440.     CALL TEST        ;BACKGROUND MEM TEST
  441.     ;
  442.     ENDIF
  443.     ;
  444.     IF    DRIVERS
  445.     ;
  446. READER:    ;READER INPUT ROUTINE
  447.     MVI    A,RDRCNT    ;SHIFT COUNTER
  448.     CALL    DISPAT        ;GO TO LOOKUP ROUTINE
  449.     DW    TTYRDR        ;READER IS TTY KBD.
  450.     DW    HSRIN        ;IS HIGH SPEED READER
  451.     DW    UR1IN        ;USER READER ONE
  452.     DW    UR2IN        ;USER READER TWO
  453. ;
  454. PUNCH:    ;PUNCH OUTPUT ROUTINE
  455.     MVI    A,PCHCNT    ;SHIFT COUNTER
  456.     CALL    DISPAT        ;LOOK UP ROUTINE
  457.     DW    TTYOUT        ;PUNCH IS TTY
  458.     DW    PUNOUT        ;HIGH SPEED PUNCH
  459.     DW    UP1OUT        ;USER PUNCH ONE
  460.     DW    UP2OUT        ;USER PUNCH TWO
  461. ;
  462. LIST:    ;LIST OUTPUT ROUTINE
  463.     MVI    A,LSTCNT    ;SHIFT COUNTER
  464.     CALL    DISPAT        ;GO TO DISPATCHER
  465.     DW    TTYOUT        ;LIST DEVICE IS TTY
  466.     DW    CRTOUT        ;LIST DEVICE IS CRT
  467.     DW    LPTOUT        ;LINE PRINTER
  468.     DW    UL1OUT        ;USER LIST DEVICE
  469. ;
  470. LISTST:    ;LIST DEVICE STATUS ROUTINE
  471.     MVI    A,LSTCNT    ;SHIFT COUNTER
  472.     CALL    DISPAT        ;LOOK UP ROUTINE
  473.     DW    TTYST        ;RETURN TTY STATUS
  474.     DW    CRTST        ;RETURN CRT STATUS
  475.     DW    LPTST        ;LINE PRINTER STATUS
  476.     DW    UL1ST        ;USER LIST DEVICE STATUS
  477. ;
  478. ;**********************************************************
  479. ;
  480. ;           INPUT/OUTPUT DRIVERS
  481. ;
  482. ;**********************************************************
  483. ;
  484. ;        CRT DRIVERS 
  485. ;
  486. CRTST:    ;CRT STATUS
  487.     IN     SER1ST    ;GET SERIAL ONE STATUS
  488. DB    JR,    TSTSTAT-$-1
  489. ;
  490. CRTIN:    IN    SER1D    ;GET DATA
  491. STRPRET: ANI    7FH    ;STRIP PARITY
  492.     RET
  493. ;
  494. CRTOUT:    ;CRT OUTPUT
  495.     IN    SER1ST    ;GET STATUS FOR 1RST SERIAL
  496.     ANI    OUTRDY    ;READY TO RECEIVE DATA?
  497. DB    JRZ,    CRTOUT-$-1 AND 0FFH    ;NO, LOOP TIL READY
  498.     MOV    A,C    ;GET DATA
  499.           OUT    SER1D    ;SEND TO DATA PORT
  500.     RET
  501. ;
  502. ;        TTY DRIVERS 
  503. ;
  504. TTYST:        ;TTY INPUT STATUS
  505.     IN    SER2ST    ;GET SERIAL TWO STATUS
  506. DB    JR,    TSTSTAT-$-1
  507. ;
  508. TTYRDR:    ;TTY KEYBOARD AS READER
  509.     IN    SER2ST
  510.     ANI    INRDY
  511.     JZ    READER0
  512. TTYIN:    IN    SER2D    ;GET DATA
  513. DB    JR,    STRPRET-$-1 AND 0FFH    
  514. ;
  515. TTYOUT:    ;TTY OUTPUT
  516.     IN    SER2ST    ;GET STATUS FOR SERIAL PORT 1
  517.     ANI    OUTRDY    ;READY FOR DATA?
  518. DB    JRZ,    TTYOUT-$-1 AND 0FFH    ;NO, WAIT TIL READY
  519.     MOV    A,C    ;GET DATA
  520.     OUT    SER2D    ;SEND TO SERIAL 2 DATA PORT
  521.     RET
  522. ;
  523. ;        READER DRIVER (PARALLEL INPUT PORT)
  524. ;
  525. RDRST:                ;READER STATUS
  526.     IN    MOTHER        ;GET STATUS
  527. TSTSTAT:
  528.     ANI    INRDY        ;MASK FOR READY
  529.     RRC            ;SHIFT TO LSB
  530. DCRCMA:
  531.     DCR    A        ;IF ZERO, MAKE FF
  532.     CMA            ;COMPLEMENT THE ACC.
  533.     RET
  534.  
  535. HSRIN:                ;HIGH-SPEED READER INPUT 
  536.     IN    MOTHER        ;GET STATUS
  537.     ANI    INRDY        ;READY WITH DATA?
  538.     JZ    READER0        ;LOOP UNTIL PI FLAG
  539.     IN    PARAL        ;GET PARALLEL INPUT DATA
  540.     ANI    07FH        ;STRIP PARITY
  541.     MOV    B,A        ;SAVE
  542.     MVI    A,30H        ;LOAD COMMAND BYTE TO A
  543.     OUT    MOTHER        ;RESET PI FLAG
  544.     MOV    A,B        ;RECOVER DATA
  545.     RET
  546. ;
  547. ;        PUNCH DRIVER (PARALLEL OUTPUT PORT)
  548. ;
  549. PUNOUT:                ;HIGH-SPEED PUNCH OUTPUT 
  550. LPTOUT:                ;LINE PRINTER OUT
  551.     ;PUNOUT AND LPTOUT ARE SAME ROUTINE
  552.     IN    MOTHER        ;GET STATUS
  553.     ANI    OUTRDY        ;READY FOR DATA
  554. DB    JRZ,     LPTOUT-$-1 AND 0FFH    ;NO, WAIT TIL READY
  555.     MOV    A,C        ;GET DATA
  556.     OUT    PARAL        ;SEND TO PARALLEL PORT
  557.     MVI    A,20H        ;COMMAND BYTE
  558.     OUT    MOTHER        ;RESET PO FLAG
  559.     MOV    A,C        ;GET DATA AGAIN
  560.     RET
  561. ;
  562. LPTST:                ;LINE PRINTER STATUS 
  563.     IN    MOTHER        ;GET STATUS
  564.     ANI    OUTRDY        ;READY TO RECEIVE CHAR
  565. DB    JR,    DCRCMA-$-1 AND 0FFH
  566. ;
  567. ;**********************************************************
  568. ;
  569. ;        USER DEFINED I/O DEVICE DRIVERS
  570. ;
  571. ;**********************************************************
  572. ;
  573. UC1ST:    ;USER CONSOLE 1 STATUS
  574. UL1ST:    ;USER LIST DEVICE STATUS
  575.     MVI    A,0FFH        ;ALWAYS READY
  576.     RET
  577. ;
  578. UC1OUT:    ;USER CONSOLE 1 IN (NULL)    
  579. UP1OUT:    ;USER PUNCH ONE OUT (NULL)
  580. UP2OUT:    ;USER PUNCH TWO OUTPUT "
  581. UL1OUT:    ;USER LIST OUTPUT (NULL)
  582.     MOV    A,C        ;CHARACTER INTO A
  583.     RET
  584. ;
  585. UC1IN:    ;USER CONSOLE 1 IN (NULL)
  586. UR1IN:    ;USER READER ONE INPUT
  587. UR2IN:    ;USER READER TWO INPUT
  588.     MVI    A,EOF        ;END OF FILE FOR NOW
  589.     RET
  590. ;
  591. ;**********************************************************
  592. ;THIS IS THE INIT ROUTINE....You should change this for
  593. ;your hardware.  Usually you should make it the same as
  594. ;the init routine that came with the version of CP/M that
  595. ;is customized for your system. The init routine below is
  596. ;for a North Star Horizon.
  597. ;
  598. INITIAL:
  599.     MVI    A,IOBYT        ;THE VALUE
  600.     STA    IOBYTE        ;THE LOCATION
  601. ;
  602.     XRA    A        ;SET TO CLEAR MOTHERBOARD
  603.     OUT    MOTHER
  604.     OUT    MOTHER        ;EXTRAS FOR TIMING, 
  605.     OUT    MOTHER
  606.     OUT    MOTHER        ;DON'T ASK
  607.     ;
  608. ;
  609.     MVI    A,40H        ;DISABLE PARITY LOGIC
  610.     OUT    MEMORY        ;BEFORE READING RAM
  611.     ;
  612.     ENDIF
  613.     ;
  614.     IF    PARITY    
  615.     ;
  616.     LXI    H,RAMEND    ;PARITY SETTING CODE
  617.     MOV    D,H
  618.     MOV    E,L
  619.     LXI    B,RAMEND+1    ;NUMBER OF BYTES TO CLEAR
  620. DW    LDDR            ;SET PARITY ON ALL RAM
  621.     MVI    A,41H        ;PARITY ENABLE CODE
  622.     OUT    MEMORY        ;REARM PARITY LOGIC
  623.     ;
  624.     ENDIF
  625.     ;
  626.     IF    DRIVERS
  627.     ;
  628.     MVI    A,0CEH        ;INITIALIZE UARTS
  629.                 ;2 STOPS, 16X CLOCK
  630.                 ;8 BITS, NO PARITY
  631.     OUT    SER1ST
  632.     OUT    SER2ST
  633. ;
  634.     MVI    A,37H        ;COMMAND: RTS, ER,
  635.                 ;RXF, DTR, TXEN
  636.     OUT    SER1ST
  637.     OUT    SER2ST
  638. ;
  639.     IN    PARAL
  640.     IN    SER1D
  641.     IN    SER2D
  642. ;
  643. ;
  644.     MVI    A,30H        ;RESET PI FLAG
  645.     OUT    MOTHER
  646.     ;
  647.     RET
  648.     ;
  649. ;
  650. USR1END: EQU    $        ;END OF USER1 CODE FOR NOW
  651. USR1SIZE EQU    USR1END-USER1    ;MUST NOT EXCEED SPACE 
  652.                 ;ALLOCATED IN USER1
  653.     ENDIF
  654. ;
  655. ;**********************************************************
  656. ; USER2 code starts here. Will be loaded to just above
  657. ; CP/M by the CCP.
  658. ;The following ORG statement will provide for loading of
  659. ;USER2 code just above CP/M by the specially initialized
  660. ;CCP(which this program does); AND, will provide for the
  661. ;memory image to appear at 100H when the OVERLAY offset
  662. ;is used with DDT to patch in your code to a CPMxx.COM
  663. ;file. Save your USER2 code as a transient called XTCPM.COM
  664. ;and keep it on your A drive since it will be needed for all
  665. ;cold boots.  Also save your CPMxx.COM file after patching
  666. ;with DDT and use your normal SYSGEN program to write it
  667. ;to the system tracks. Save both files to appropriate size.
  668. ;
  669. ;Any code placed in this area should have the EQU  $+OFFSET
  670. ;at each label and Z80 jump relatives should use the FR and
  671. ;BR post-fixes as shown.
  672. ;
  673. ;THIS ORG STATEMENT SHOULD CAUSE THE FOLLOWING CODE TO APPEAR
  674. ;AT 100H IN THE DDT IMAGE AFTER OFFSETTING WITH THE OVERLAY
  675. ;BIAS THAT YOU USE IN PATCHING YOUR BIOS INTO CPMxx.COM.
  676. ;
  677.     ORG    CCP-(CCPIMAGE-100H)
  678. SOURCE:    EQU    $        ;SOURCE OF USER2 CODE
  679. OFFSET:    EQU    USER2-SOURCE    ;OFFSET FOR USER2 CODE
  680. FR:    EQU    -1-OFFSET    ;FORWARD RELATIVE
  681. BR:    EQU    FR+0FFH+1    ;BACKWARD RELATIVE
  682. ;
  683.     
  684. ;**********************************************************
  685. ;This routine is the first to be called when going to the
  686. ;TPA on a coldboot turnkey start.  It simply changes the
  687. ;CCP parameters to restore the dma and address for the TPA
  688. ;back to 100H and resets the address tested for CCP overwrite.
  689. ;The turnkey start in the mean time has loaded the rest of
  690. ;the code in the USER2 area to a location just above CP/M
  691. ;and all properly linked to the code in the USER1 area.
  692. ;
  693.     RET            ;TO RET IF EXECUTED FROM
  694.                 ;THE COMMAND LINE.
  695. ;This is the entry point when called by the CCP.
  696. XTCPM:    EQU    $+OFFSET    ;ROUTINE TO RESTORE CCP DMA
  697.                 ;AND TPA ADDRESSES TO 100H
  698.     LXI    H,TPA
  699.     SHLD    CCPDMA
  700.     SHLD    TPASUB
  701.     LXI    H,CCP
  702.     SHLD    TSTOVWR
  703.     ;
  704.     MVI    A,PASBYT ;GET THE PASSWORD BYTE
  705.              ;If you use Ward's 'BYE' ,then
  706.              ;you should restore the PASBYT
  707.              ;to its initial value in the
  708.              ;HANGUP routine of 'BYE'.
  709.              ;Use the following code:
  710.              ;LHLD    0001H    ;get bios vector
  711.              ;LXI    D,-28H     ;set to subtract (SEARA+2)
  712.              ;DAD    D    ;hl pnts to PASBYTE address
  713.              ;MOV    A,M    ;load hl with address
  714.              ;INX    H
  715.              ;MOV    H,M
  716.              ;MOV    L,A
  717.              ;MVI    M,24H    ;reset PASBYTE
  718.              ;
  719.     STA    PASBYTE     ;STORE IT
  720.     ;
  721.     CALL    RSTPRMS
  722.     ;
  723.     IF    SGNON
  724.     ;
  725.     MVI    C,WRBUF        ;GIVE SYSTEM SIGNON MESSAGE
  726.     LXI    D,SIGNON
  727.     CALL    BDOSFNC
  728.     ;
  729.     ENDIF
  730.     ;
  731.     IF    NOT TNKY2
  732.     ;
  733.     RET
  734.     ;
  735.     ENDIF
  736.     ;
  737.     IF    TNKY2
  738.     ;
  739.     LXI    H,COMBUF+1
  740.     SHLD    BUFPTR
  741.     DCX    H
  742.     XCHG
  743.     LXI    H,FILNAM
  744.     LXI    B,5
  745. DW    LDIR
  746.     MVI    C,0
  747.     JMP    CCP
  748.     ;
  749. FILNAM:    EQU    $+OFFSET
  750.     DB    3,'BYE',0
  751.     ;
  752.     ENDIF
  753.     ;
  754.     IF    SGNON
  755.     ;
  756. SIGNON: EQU    $+OFFSET
  757.     DB    CR,LF
  758.     DB    MSIZE/10+30H
  759.     DB    MSIZE MOD 10 + 30H
  760.     DB    'K CP/M 2.2 - XTCPM$'
  761.     ;
  762.     ENDIF
  763. ;
  764. ;**********************************************************
  765. ;The password checking routine- uses string comparator
  766. ;that is contained in the CCP.
  767. ;
  768. CKPASS0: EQU    $+OFFSET
  769.     LXI    H,PASBYTE
  770. DW    BIT2M
  771. DB    JRZ,    OK-$+FR
  772.     LXI    H,PAS2
  773.     SHLD    STRPTR
  774.     LXI    H,PASTBL2
  775.     SHLD    CMDPTR
  776. DB    JR,    CKPASS-$+FR
  777.     ;
  778. PASSINT: EQU    $+OFFSET
  779.     CALL    LOGTST
  780. DB    JRZ,    OK-$+FR
  781.     LXI    H,PAS1
  782.     SHLD    STRPTR
  783.     LXI    H,PASTBL1
  784.     SHLD    CMDPTR
  785.     ;
  786. CKPASS:    EQU    $+OFFSET
  787.     MVI    A,1
  788.     STA    CMDCNT
  789.     MVI    A,10
  790.     STA    CMDLEN
  791.     MVI    C,4    ;GIVES 4 TRIES
  792.     PUSH    B
  793.     ;
  794. CKAGIN:    EQU    $+OFFSET
  795.     CALL    ILPRT
  796.     DB    'Password:',0
  797.     POP    B
  798.     MVI    B,14    ;TO KEEP HIM FROM CLOBBERING
  799.             ;THE CODE
  800.     LXI    H,NAME
  801. DRCON:    EQU    $+OFFSET
  802.     CALL    VCONIN
  803.     CPI    CR
  804. DB    JRNZ,    DRCN2-$+FR
  805.     MVI    A,20H
  806.     MVI    B,1
  807. DRCN2:    EQU    $+OFFSET
  808.     MOV    M,A
  809.     INX    H
  810.     DCR    B
  811. DB    JRNZ,    DRCON-$+BR    
  812.     ;
  813.     DCR    C
  814.     JZ    RELOG0
  815.     PUSH    B
  816.     JMP    SRCHCMD
  817.     ;
  818. OK:    EQU    $+OFFSET
  819.     CALL    ILPRT
  820.     DB    'Ok.',0
  821.     JMP    RETCCP
  822. ;
  823. PASTBL1: EQU    $+OFFSET
  824.     DW    OK1
  825.     DW    CKAGIN
  826. PASTBL2: EQU    $+OFFSET
  827.     DW    OK2
  828.     DW    CKAGIN
  829. ;
  830. ;**********************************************************
  831. ;This is the in-line print subroutine.
  832. ;
  833. ILPRT:    EQU    $+OFFSET
  834. DB    EXX    
  835.     CALL    CRLF
  836. DB    EXX
  837.     ;
  838. ILPRT2:    EQU    $+OFFSET
  839.     XTHL        ;SAVE HL, GET MSG
  840. ILPLP:    EQU    $+OFFSET
  841.     MOV    C,M    ;GET CHAR
  842.     CALL    VCONOUT    ;OUTPUT IT
  843.     INX    H    ;POINT TO NEXT
  844.     MOV    A,M    ;TEST
  845.     ORA    A    ;..FOR END
  846. DB    JRNZ,    ILPLP-$+BR
  847.     XTHL        ;RESTORE HL, RET ADDR
  848.     RET        ;RET PAST MSG
  849. ;
  850. ;***********************************************************
  851. ;ROUTINE TO TEST LOG IN
  852. ;
  853. LOGTST:    EQU    $+OFFSET
  854.     LXI    H,PASBYTE
  855. DW    BIT5M
  856.     RET
  857. ;
  858. ;**********************************************************
  859. ;
  860. RELOG0:    EQU    $+OFFSET
  861.     CALL    CRLF
  862. RELOG:    EQU    $+OFFSET
  863.     CALL    LOGTST
  864. DB    JRZ,    EXIT-$+FR
  865.     CALL    LGMSG
  866. EXIT:    EQU    $+OFFSET
  867.     JMP    RETCCP
  868.     ;
  869. LGMSG:    EQU    $+OFFSET
  870.     CALL    ILPRT2
  871. DB    'Login please. ',CR,LF,0
  872.     RET
  873. ;
  874. ;**********************************************************
  875. ;Routines to trap transient files if they are resident
  876. ;on drive A.  If DIR.COM not present, then the CCP code for
  877. ;the DIR command will be executed. If TYPE.COM not present,
  878. ;then the CCP code for the TYPE command will be executed.
  879. ;This trapping is useful for SD.COM and MLIST.COM re-named
  880. ;to DIR.COM and TYPE.COM respectively.
  881. ;**NOTE**  Do not use a Directory transient that scans user
  882. ;areas such as SD-21 or SD-22. KDIR is ok.  You can use SD-42
  883. ;if you set AOPT to FALSE and add an IF AOPT and ENDIF around
  884. ;the [lda,newusr; cmp m; jnz mordir] sequence at the label,
  885. ;SYSFOK. Otherwise you will defeat the universal user area
  886. ;features in this program so far as directories are concerned,
  887. ;although the universallity will still apply to execution and
  888. ;finding of files in users 13, 14, and 15.
  889. ;
  890. DIR1:    EQU    $+OFFSET
  891.     LXI    H,TRAPBYT
  892. DW    SET0M            ;SET DIR TRAP
  893.     JMP    GETRANS
  894.     ;
  895. TYPE1:    EQU    $+OFFSET
  896.     LXI    H,TRAPBYT
  897. DW    SET1M
  898.     JMP    GETRANS
  899.     ;
  900. HUH0:    EQU    $+OFFSET
  901.     LXI    H,TRAPBYT
  902. DW    BIT0M            ;SEE IF DIR TRAP SET
  903.     JNZ    DIR        ;CCP DIR CODE IF NOT
  904. DW    BIT1M            ;SEE IF TYPE TRAP SET
  905. DW    RES1M
  906.     JNZ    TYPE        ;CCP TYPE CODE IF NOT
  907.     CALL    ILPRT
  908.     DB    'No!, ',BELL,0
  909.     CALL    LOGTST
  910. DB    JRNZ,    RELOG-$+BR
  911.     JMP    HUH+3        
  912.     ;
  913. ;**********************************************************
  914. ;This is the command string which is divided into private
  915. ;and public sections. Do not use more than five letters for
  916. ;the name of any command/transient and fill out each string
  917. ;to exactly five characters by using spaces below. Strings
  918. ;must occur at 5 character intervals.  If you use some
  919. ;other string length such as 4 as in the original CCP, just
  920. ;change string lengths below and change the LENCMD equate
  921. ;from 5 to 4.  I use 5 below so that LOGIN & LOGON can fit.
  922. ;
  923. CMDSTR2: EQU    $+OFFSET
  924.     DB    'ERA  REN  SAVE '
  925. CMDSTR1: EQU    $+OFFSET
  926.     DB    'TYPE USER PASS DIR  '
  927. CMDSTR0: EQU    $+OFFSET
  928.     DB    'DIR  LOGINLOGON'
  929. ;
  930. ;**********************************************************
  931. ;This is the command address table which is divided into
  932. ;private and public areas. The address of the routine to be
  933. ;jumped to must be here for CCP-included code as well as
  934. ;any that you put in your customized BIOS.
  935. ;You can expand the table to any extent that you have space
  936. ;and the command string above must be expanded in synchronism.
  937. ;
  938. CMDTBL2: EQU    $+OFFSET
  939.     DW    ERA    ;ERA....PRIVATE COMMANDS
  940.     DW    REN    ;REN
  941.     DW    SAVE    ;SAVE
  942. CMDTBL1: EQU    $+OFFSET
  943.     DW    TYPE1    ;TYPE..In case MLIST.COM renamed
  944.             ;to 'TYPE.COM'. Put the transient
  945.             ;in USER 14 on drive A.
  946.     DW    USER    ;USER
  947.     DW    CKPASS0    ;PASS(word) to gain access to
  948.             ;private user areas. Can also
  949.             ;be set at LOGIN by entering the
  950.             ;second password.
  951.     DW    DIR1    ;DIR....If you wish to use SD or
  952.             ;KDIR as a CCP transient instead of
  953.             ;the CCP DIR code, just change the
  954.             ;name of your transient to DIR.COM
  955.             ;and put it in USER 14 on drive A.
  956.             ;The transient will run only if 1rst
  957.             ;password level has been achieved.
  958.             ;If transient not present then CCP
  959.             ;'DIR' code will run.
  960. ;These commands will be the only ones allowed until the user
  961. ;logs in to the system with LOGIN.
  962. CMDTBL0: EQU    $+OFFSET
  963.     DW    DIR    ;WILL RUN THE CCP 'DIR' CODE
  964.     DW    PASSINT    ;LOGIN
  965.     DW    PASSINT    ;LOGON
  966. GETRAN0: EQU    $+OFFSET ;This must be last entry in table.
  967.     DW    GETRANS    ;GET THE TRANSIENT AND EXECUTE OR
  968.             ;RETURN TO CCP W/HUH MESSAGE IF NOT
  969.             ;ON DISK.
  970. ;
  971. ;**********************************************************
  972. ;This patch which is called from the CCP provides for a
  973. ;report of USER number at the prompt....i.e. A2> for USER 2,
  974. ;'A' drive.
  975. ;
  976. UPATCH:    EQU    $+OFFSET
  977.     CALL    GETUSR        ;GET USER NUMBER
  978.     ANI    0FH        ;KILL UNWANTED BITS
  979. DB    JRZ,    UPA2-$+FR    ;IF USER 0, DON'T REPORT
  980.     CPI    10
  981. DB    JRC,    UPA1-$+FR    ;JIF USER NUM = 0 THRU 9
  982.     SUI    10        ;USER NUM = 10 THRU 15
  983.     PUSH    PSW
  984.     MVI    C,'1'
  985.     CALL    VCONOUT        ;PRINT A '1'
  986.     POP    PSW
  987.     ;
  988. UPA1:    EQU    $+OFFSET
  989.     ADI    '0'
  990.     MOV    C,A
  991.     CALL    VCONOUT        ;PRINT DIGIT
  992.     ;
  993. UPA2:    EQU    $+OFFSET
  994.     MVI    C,'>'
  995.     CALL    VCONOUT        ;PRINT '>', EXIT
  996.     XRA    A
  997.     STA    TRAPBYT        ;CLEAR THE TRAPS
  998.     ;FALL THROUGH TO RESET PARAMETERS & RETURN
  999. ;
  1000. ;**********************************************************
  1001. ;Routines to reset parameters for string matching and other
  1002. ;purposes.
  1003. ;
  1004. RSTPRMS: EQU    $+OFFSET
  1005.     MVI    A,0C3H        ;SET BDOS TO TREAT USERS 
  1006.     STA    BDOS+75EH    ;..13, 14 AND/ OR 15 AS
  1007.     LXI    H,UNIV        ;..UNIVERSAL DEPENDING ON
  1008.     SHLD    BDOS+75FH    ;..PASSWORD LEVEL.
  1009.     ;
  1010.     MVI    A,LENCMD
  1011.     STA    CMDLEN
  1012.     LXI    H,PASBYTE
  1013. DW    BIT5M
  1014. DB    JRNZ,    RST0-$+FR
  1015. DW    BIT2M
  1016. DB    JRNZ,    RST1-$+FR
  1017.     ;
  1018. RST2:    EQU    $+OFFSET
  1019.     LXI    H,CMDSTR2
  1020.     SHLD    STRPTR
  1021.     MVI    A,(GETRAN0-CMDTBL2)/2
  1022.     STA    CMDCNT
  1023.     LXI    H,CMDTBL2
  1024.     SHLD    CMDPTR
  1025.     MVI    A,16
  1026.     STA    TSTUSR
  1027.     RET
  1028.     ;
  1029. RST1:    EQU    $+OFFSET
  1030.     LXI    H,CMDSTR1
  1031.     SHLD    STRPTR
  1032.     MVI    A,(GETRAN0-CMDTBL1)/2
  1033.     STA    CMDCNT
  1034.     LXI    H,CMDTBL1
  1035.     SHLD    CMDPTR
  1036.     MVI    A,MAXUSER+1
  1037.     STA    TSTUSR
  1038.     RET
  1039.     ;
  1040. RST0:    EQU    $+OFFSET
  1041.     MVI    A,(GETRAN0-CMDTBL0)/2
  1042.     STA    CMDCNT
  1043.     LXI    H,CMDSTR0
  1044.     SHLD    STRPTR
  1045.     LXI    H,CMDTBL0
  1046.     SHLD    CMDPTR
  1047.     MVI    A,1
  1048.     STA    TSTUSR
  1049.     RET
  1050. ;
  1051. ;**********************************************************
  1052. ;BIOS routines called herein.
  1053. ;
  1054. VCONIN:    EQU    $+OFFSET
  1055. DB    EXX
  1056.     CALL    BIOS+9H
  1057. DB    EXX
  1058.     RET
  1059.     ;
  1060. VCONOUT: EQU    $+OFFSET
  1061.     PUSH    H
  1062.     PUSH    D
  1063.     PUSH    B
  1064.     CALL    BIOS+0CH
  1065.     POP    B
  1066.     POP    D
  1067.     POP    H    
  1068.     RET
  1069. ;
  1070. ;**********************************************************
  1071. ;This routine will make USER 13, 14, and/or 15 universal on
  1072. ;drive A only depending on password level. Files placed in
  1073. ;user 13 will be universal without any password. Files placed
  1074. ;in user 14 will additionally be universal on drive A at the
  1075. ;first password level, and files placed in user 15 will be
  1076. ;universal at the second password level in addition to those
  1077. ;in users 13 and 14.
  1078. ;    ***** WARNING! *****
  1079. ;NEVER have two files by the same name & extension on the
  1080. ;same disk (one in USER 15 and the other in some other
  1081. ;USER) because CP/M will take which ever one comes first
  1082. ;in the directory.
  1083. ;
  1084. UNIV:    EQU    $+OFFSET
  1085.     MOV    A,B        ;duplicate instruction overlayed
  1086.     ORA    A        ;check pointer for zero byte
  1087. DB    JRNZ,    UNIV1-$+FR    ;skip if not zero byte of fcb
  1088.     ;
  1089.     LDA    CURDSK    ;get current disk
  1090.     ANI    0FH        ;mask out high nibble
  1091.     CPI    0        ;is it drive A? (may be changed
  1092.                 ;to any drive. 0,1,2.. = A,B,C..)
  1093. DB    JRNZ,    UNIV1-$+FR    ;skip if not
  1094.     ;
  1095.     LDAX    D        ;get fcb first byte
  1096.     CPI    0E5H        ;check for erased
  1097. DB    JRZ,    UNIV1-$+FR    ;skip if erased
  1098.     ;
  1099.     LDA    PASBYTE
  1100. DW    BIT5A
  1101. DB    JRNZ,    DFU13-$+FR
  1102. DW    BIT2A
  1103. DB    JRNZ,    DFU14-$+FR
  1104.     ;
  1105.     MOV    A,M
  1106.     CPI    15        ;and check for user 15
  1107. DB    JRZ,    MATCH0-$+FR    ;jump if zero
  1108.     ;
  1109. DFU14:    EQU    $+OFFSET
  1110.     MOV    A,M
  1111.     CPI    14        ;check for user 14
  1112. DB    JRZ,    MATCH0-$+FR
  1113.     ;
  1114. DFU13:    EQU    $+OFFSET
  1115.     MOV    A,M
  1116.     CPI    13        ;check for user 13
  1117. MATCH0:    EQU    $+OFFSET
  1118.     JZ    MATCH
  1119.     ;
  1120. UNIV1:    EQU    $+OFFSET
  1121.     MOV    A,B        ;duplicate instuction overlayed
  1122.     CPI    0DH        ;    "    "    "
  1123.     JMP    TINUSRCH    ;and return where routine left off
  1124.     ;
  1125. ;**********************************************************
  1126. ;This is a background memory test that runs whenever the
  1127. ;current console (including remote) is waiting for an input
  1128. ;character to be typed.
  1129. ;
  1130. ;TEST ROUTINE TO CONSTANTLY TEST MEMORY
  1131. ;
  1132.     IF    BGTST AND DRIVERS
  1133. ;
  1134. TSTPT:    EQU    $+OFFSET
  1135.     DW    0
  1136. TEST:    EQU    $+OFFSET
  1137.     DI
  1138.     PUSH    H
  1139.     LHLD    TSTPT
  1140.     INX    H
  1141.     MOV    A,H
  1142.     CPI    ($+OFFSET)/100H-SKIP/100H
  1143. DB    JRNZ,    TEST1-$+FR
  1144.     LXI    H,0
  1145. ;
  1146. TEST1:    EQU    $+OFFSET
  1147.     SHLD    TSTPT
  1148.     MOV    A,M
  1149.     CMA
  1150.     MOV    M,A
  1151.     CMP    M
  1152. DB    JRZ,    TEST2-$+FR
  1153.     XRA    M
  1154.     PUSH    PSW
  1155.     PUSH    H
  1156.     CALL    CRLF
  1157.     POP    H
  1158.     POP    PSW
  1159.     PUSH    PSW
  1160.     CALL    PRTHX
  1161.     CALL    ILPRT2
  1162.     DB    'H Bits bad at: ',0
  1163.     MOV    A,H
  1164.     CALL    PRTHX
  1165.     MOV    A,L
  1166.     CALL    PRTHX
  1167.     POP    PSW
  1168. ;
  1169. TEST2:    EQU    $+OFFSET
  1170.     CMA
  1171.     MOV    M,A
  1172.     POP    H
  1173.     EI
  1174.     RET
  1175. ;
  1176. PRTHX:    EQU    $+OFFSET
  1177.     PUSH    PSW
  1178.     RRC
  1179.     RRC
  1180.     RRC
  1181.     RRC
  1182.     CALL    PRTHX1
  1183.     POP    PSW
  1184. ;
  1185. PRTHX1:    EQU    $+OFFSET
  1186.     ANI    0FH
  1187.     CPI    10
  1188. DB    JRC,    PRTHX2-$+FR
  1189.     ADI    7
  1190. ;
  1191. PRTHX2:    EQU    $+OFFSET
  1192.     ADI    '0'
  1193.     MOV    C,A
  1194. DB    JR,    VCONOUT-$+BR
  1195.     ;
  1196. ;END OF CONSTANT MEMORY TEST
  1197. ;
  1198.     ENDIF
  1199. ;
  1200. USR2END: EQU    $+OFFSET    ;END OF USER2 CODE FOR NOW
  1201. INITSIZE EQU    INITSIZE    ;
  1202. USR2SIZE EQU    USR2END-USER2    ;DO NOT EXCEED SPACE ALLOCAT-
  1203.                 ;ED ABOVE YOUR RUNNING CP/M. 
  1204. ;
  1205. ;**********************************************************
  1206. ;    EQUATES FOR CCP PATCHES
  1207. LENCMD    EQU    5        ;LENGTH OF CCP CMD STRINGS
  1208. GETUSR    EQU    CCP+113H    ;GET USER #
  1209. SETUSR    EQU    CCP+115H    ;SET USER #
  1210. TSTUSR    EQU    CCP+692H    ;TEST USER #
  1211. USRSAV    EQU    CCP+118H
  1212. UPATCH0    EQU    CCP+390H
  1213. UPATCH1    EQU    CCP+393H
  1214. HUH    EQU    CCP+209H    ;CCP HUH RESPONSE
  1215. CRLF    EQU    CCP+98H        ;CCP CR/LF FUNCTION
  1216. RCCPNL    EQU    CCP+789H    ;RSTRT CCP W/O LOG OF DFLT DRV
  1217. RETCCP  EQU    CCP+382H    ;RE-ENTRY TO CCP
  1218. GETCMD    EQU    CCP+398H    ;GET THE ENTERED COMMAND
  1219. SRCHCMD    EQU    CCP+3B1H    ;ENTRY TO SEARCH OF COMMANDS
  1220. COMBUF    EQU    CCP+7H        ;LOC OF CMD BUFFER
  1221. BUFPTR    EQU    CCP+88H        ;LOC OF CMD BUFFER POINTER
  1222. CMDPTR    EQU    CCP+3B5H    ;LOC OF CMD ADDR TBL PTR
  1223. GETRPTR    EQU    CCP+3AFH    ;LOC OF GET TRANS PTR
  1224. STRPTR    EQU    CCP+32FH    ;POINTER TO CCP CMD STRINGS
  1225. CMDCNT    EQU    CCP+335H    ;BYTE VALUE = # OF COMMANDS
  1226. CMDLEN    EQU    CCP+33BH    ;BYTE VALUE = LENGTH OF EACH
  1227.                 ;COMMAND STRING.
  1228. TSTOPN    EQU    CCP+6DCH    ;TEST FILE OPEN FUNCTION
  1229. CMDDRV    EQU    CCP+7F0H    ;BYTE INDICATES DRV IN CMD
  1230. CMDERR    EQU    CCP+76BH    ;HUH RESPONSE IF DR #
  1231. NAME    EQU    CCP+7CEH    ;LOC FOR FN IN FCB
  1232. XTNSN    EQU    CCP+7D6H    ;STORAGE LOC FOR FILE TYPE,
  1233.                 ;EXT #, AND RECORD COUNT
  1234. RELOOK    EQU    CCP+6CDH    ;RELOOK W/INDICATED DRIVE
  1235. TSTOVWR    EQU    CCP+6F5H    ;TEST OVERWRITE OF CCP
  1236. CCPDMA    EQU    CCP+6DFH    ;LOC TO SUBSTITUTE FOR
  1237.                 ;DMA ADDRESS
  1238. TPASUB    EQU    CCP+75DH    ;LOC TO SUSTITUTE BEFORE
  1239.                   ;CALLING THE TPA
  1240. CLDBOOT    EQU    CCP+35CH    ;COLDBOOT ENTRY POINT
  1241. CONTINUE EQU    CCP+75FH    ;CONTINUE AFTER CALL TO TPA
  1242. GETRANS    EQU    CCP+6A8H    ;GET TRANS OR CCP COMMAND
  1243. ERA    EQU    CCP+51FH    ;ADDR OF ERA ROUTINE
  1244. REN    EQU    CCP+610H    ;ADDR OF REN ROUTINE
  1245. SAVE    EQU    CCP+5ADH    ;ADDR OF SAVE ROUTINE
  1246. DIR    EQU    CCP+477H    ;ADDR OF DIR ROUTINE
  1247. TYPE    EQU    CCP+55DH    ;ADDR OF TYPE ROUTINE
  1248. USER    EQU    CCP+68EH    ;ADDR OF USER ROUTINE
  1249. TPA    EQU    100H        ;OR YOUR TPA ADDRESS
  1250. STKPTR1    EQU    CCP+35DH
  1251. STKPTR2    EQU    CCP+760H
  1252. STKPTR3    EQU    CCP+383H
  1253. PRNSTR1    EQU    CCP+0A7H    ;PRINT STRING WITH LEADING
  1254.                 ;CR/LF..POINT TO IT WITH BC
  1255. PRNSTR2    EQU    CCP+0ACH    ;PRINT STRING..POINT WITH HL
  1256. CCPSPARE EQU    CCP+7F2H    ;14 SPARE BYTES AT END CCP
  1257.     ;Addresses of holes left in CCP that are filled in
  1258.     ;with patches.
  1259. HOLE1    EQU    CCP+79BH    ;16 BYTES
  1260. HOLE2    EQU    CCP+310H    ;30 BYTES    
  1261. HOLE3    EQU    CCP+3C1H    ;24 BYTES
  1262. HOLE4    EQU    CCP+1F5H    ;20 BYTES
  1263. HOLE5    EQU    CCP+6A5H    ;3 BYTES
  1264. ;
  1265. ;**********************************************************
  1266. ;    CCP patches
  1267. ;**********************************************************
  1268. ;These two patches allow changing the user area on the
  1269. ;command line after X: where X is drive letter.
  1270. ;
  1271.     ORG    CCP+6C2H
  1272.     DW    USER
  1273.     ORG    CCP+69DH
  1274.     DW    RCCPNL
  1275. ;
  1276. ;**********************************************************
  1277. ;
  1278.     ORG    GETRPTR
  1279.     DW    GETRANS
  1280.     ;
  1281.     ORG    CMDCNT
  1282.     DB    0
  1283.     ;
  1284.     ORG    CMDPTR
  1285.     DW    GETR0
  1286.     ;
  1287.     ORG    HOLE5
  1288. GETR0:    DW    GETRANS
  1289.     DB    0    ;3 BYTES AT HOLE5
  1290. ;
  1291. ;Patch the turnkey start string into the CCP command buffer.
  1292.     ORG    COMBUF
  1293. TNKY:    DB    05,'XTCPM',0       
  1294. ;
  1295. ;**********************************************************
  1296. ;To trap the HUH message.
  1297. ;
  1298.     ORG    HUH
  1299.     JMP    HUH0
  1300. ;
  1301. ;**********************************************************
  1302. ;To redirect the CCP stack so a larger stack is available.
  1303. ;
  1304.     ORG    STKPTR1
  1305.     DW    STACK
  1306.     ORG    STKPTR2
  1307.     DW    STACK
  1308.     ORG    STKPTR3
  1309.     DW    STACK
  1310. ;
  1311. ;**********************************************************
  1312. ; This patch is used to restrict access to the higher user
  1313. ; areas while leaving the lower user areas public. The high-
  1314. ; est available public user area is defined by MAXUSER.
  1315. ;
  1316.     ORG    HOLE1
  1317. OK2:    LXI    H,PASBYTE
  1318. DW    RES2M
  1319.     ;
  1320. OK1:    LXI    H,PASBYTE
  1321. DW    RES5M
  1322.     JMP    OK
  1323. ;
  1324. TRAPBYT:
  1325.     DB    0
  1326.     DB    0,0    ;SPARES
  1327.             ;DO NOT EXPAND
  1328.             ;16 BYTES AT HOLE1
  1329. ;***********************************************************
  1330. ;The following sequence of statements are to patch the CCP
  1331. ;so that the transient 'XTCPM.COM' will be loaded above CP/M
  1332. ;by the CCP without the need for a special 'sysgen' routine.
  1333. ;Use the normal SYSGEN program with your system.
  1334.     ORG    CCP+1
  1335.     DW    CCPINIT
  1336.     ;
  1337.     ORG    HOLE2
  1338. CCPINIT:
  1339.     LXI    H,CCP+35CH
  1340.     SHLD    CCP+1
  1341.     ;
  1342.     LXI    H,BOOTFLG
  1343. DW    BIT1M            ;SEE IF COLD BOOT
  1344. DW    RES1M
  1345.     JZ    CCP+358H    ;ELSE GOTO WARM BOOT ENTRY 
  1346.     ;
  1347.     LXI    H,USER2+800H    ;TO MOVE OVERWRITE TEST LOC
  1348.                 ;TO TOP OF SYS MEMORY
  1349.     SHLD    TSTOVWR
  1350.     LXI    H,USER2        ;TO SUBSTITUTE DMA AND TPA
  1351.                 ;TO USER2 ADDRESS TEMPORARILY
  1352.     JMP    BRIDGE
  1353. ;
  1354.     DB    0,0        ;SPARES
  1355. ;Do not expand, 30 bytes available here.
  1356. ;
  1357. ;**********************************************************
  1358.     ORG    USRSAV
  1359.     DW    SAVUSR
  1360.     ;
  1361.     ORG    HOLE3
  1362. SAVUSR:    MOV    A,E
  1363.     CPI    0FFH
  1364.     JZ    BDOSFNC
  1365.     RLC
  1366.     RLC
  1367.     RLC
  1368.     RLC
  1369.     MOV    B,A
  1370.     LDA    DRIVE
  1371.     ANI    0FH
  1372.     ORA    B
  1373.     STA    DRIVE
  1374.     JMP    BDOSFNC
  1375.     DB    0    ;DO NOT EXPAND, 24 BYTES HERE
  1376. ;
  1377. ;**********************************************************
  1378. ;These are the passwords for entry to CP/M from BYE       
  1379. ;and to USER area and command privileges above MAXUSER       
  1380. ;repectively. Passwords may be up to 10 characters, and   
  1381. ;must be filled out to this value with spaces.           
  1382.     ORG    HOLE4
  1383. PAS1:    DB    'PASSWORD1 '
  1384. PAS2:    DB    'PASSWORD2 '           
  1385.             ;DO NOT EXPAND, EXACTLY 20 BYTES
  1386.             ;ARE AVAILABLE HERE.
  1387. ;                               
  1388. ;**********************************************************
  1389. ; This patch causes user number to be reported at the cp/m
  1390. ; prompt.....i.e. - A2>.  User 0 report is suppressed.
  1391. ;
  1392.     ORG    UPATCH0
  1393.     MVI    C,USRFNC
  1394.     ;
  1395.     ORG    UPATCH1
  1396.     DW    UPATCH
  1397.     ;the routine UPATCH is located in the USER2 area
  1398. ;**********************************************************
  1399. ; This patch causes the CCP of a cp/m 2.x system to look on
  1400. ; drive A when you are logged into a drive other than A and
  1401. ; call for a .COM file that does not exist on that drive.
  1402. ; Giving an explicit drive reference overrides this feature,
  1403. ; so that you can always force the file to be loaded from a
  1404. ; specific drive.
  1405. ;
  1406.     ORG    TSTOPN
  1407.     DW    APATCH        ;REPLACES 'CMDERR'
  1408. ;
  1409.     ORG    CCPSPARE
  1410. APATCH:    LXI    H,CMDDRV    ;GET DRIVE FROM CURRENT CMD.
  1411.     ORA    M        ;FETCHES DRIVE
  1412.     JNZ    CMDERR        ;GIVE ERR IF CMD HAS DRIVE #
  1413.     INR    M        ;FORCE TO DRIVE A
  1414.     LXI    D,XTNSN        ;UNDO WHEN...
  1415.     JMP    RELOOK        ;REENTERING
  1416.     ;DON'T EXPAND. 14 BYTES HERE.
  1417. ;
  1418. ;**********************************************************
  1419. ;    BDOS patches
  1420. ;**********************************************************
  1421. ;
  1422. BDOSPARE EQU    BDOS+0DEEH    ;18 SPARE BYTES AT END BDOS
  1423. MATCH    EQU    BDOS+077CH
  1424. CURDSK    EQU    BDOS+342H
  1425. TINUSRCH EQU    BDOS+761H
  1426. ;
  1427.     ORG    BDOS+0DDBH    ;SEARA+2
  1428.     DW    PASBYTE        ;ADDRESS OF PASS WORD BYTE
  1429. ;
  1430.     ORG    BDOSPARE
  1431. BRIDGE:    SHLD    CCPDMA
  1432.     INX    H
  1433.     SHLD    TPASUB
  1434.     JMP    CLDBOOT      ;COLDBOOT ENTRY POINT
  1435. ;end of CCP initialization
  1436. ;
  1437. CBOOT0:    LXI    H,BOOTFLG
  1438. DW    SET1M    
  1439.     JMP    CBOOT
  1440.         ;DO NOT EXPAND, EXACTLY 18 BYTES HERE
  1441. ;
  1442. ;**********************************************************
  1443. ;    BIOS patches
  1444. ;**********************************************************
  1445. ;This jump table overlays the table at the base of the BIOS
  1446. ;thus making it unecessary to have all of the jumps in the 
  1447. ;jump table at the base of the USER1 area.
  1448. ;
  1449.     ORG    BIOS
  1450.     JMP    CBOOT0
  1451.     ;
  1452.     IF    DRIVERS    AND NOT (STDCPM OR M2BIOS)
  1453.     ;
  1454.     ORG    BIOS+0FH
  1455.     JMP    LIST
  1456.     JMP    PUNCH
  1457.     JMP    READER
  1458.     ;
  1459.     ORG    BIOS+2DH
  1460.     JMP    LISTST
  1461.     ;
  1462.     ENDIF
  1463.     ;
  1464.     IF    DRIVERS AND (STDCPM OR M2BIOS)
  1465.     ;
  1466.     ORG    BIOS+6H
  1467.     JMP    CONST
  1468.     JMP    CONIN
  1469.     JMP    CONOUT
  1470.     JMP    LIST
  1471.     JMP    PUNCH
  1472.     JMP    READER
  1473.     ;
  1474.     ORG    BIOS+2DH
  1475.     JMP    LISTST
  1476.     ;
  1477.     ENDIF
  1478.     ;
  1479. ;************************************************************
  1480. ;
  1481. ;        SPECIAL ASCII CODES
  1482. ;
  1483. LF    EQU    0AH    ; LINE FEED
  1484. CR    EQU    0DH    ; CARRIAGE RETURN
  1485. EOF    EQU    1AH    ; END OF FILE
  1486. BELL    EQU    07H    ; DING
  1487. NULL    EQU    00H    ; NOTHING
  1488. ESC    EQU    1BH    ; ESCAPE - USED IN TWO CHAR COMMANDS
  1489. LIN    EQU    6CH    ; CHAR AFTER ESCAPE TO CLEAR LINE
  1490. SCRN    EQU    45H    ; CHAR AFTER ESCAPE TO CLEAR SCREEN
  1491. ;
  1492. ;        STATUS MASKS
  1493. ;
  1494. INRDY    EQU    02H    ;INPUT READY MASK
  1495. OUTRDY    EQU    01H    ;OUTPUT READY MASK
  1496. ;
  1497. ;    POSITION OF BIT PAIR IN IOBYTE
  1498. ;
  1499. CONCNT    EQU    1    ;CONSOLE BITS 0,1
  1500. RDRCNT    EQU    2    ;READER  BITS 2,3
  1501. PCHCNT    EQU    3    ;PUNCH   BITS 4,5
  1502. LSTCNT    EQU    4    ;LIST    BITS 6,7
  1503. ;
  1504. ;**********************************************************
  1505. ;
  1506. ;        Z80 EQUATES
  1507. ;
  1508. JR    EQU    18H    ;JUMP RELATIVE
  1509. JRZ    EQU    28H    ;JUMP RELATIVE ON ZERO
  1510. JRNZ    EQU    20H    ;JUMP RELATIVE ON NOT ZERO
  1511. JRC    EQU    38H    ;JUMP RELATIVE ON CARRY
  1512. JRNC    EQU    30H    ;JUMP RELATIVE IF CARRY RESET
  1513. LDIR    EQU    0B0EDH    ;MEMORY BLOCK MOVE
  1514. LDDR    EQU    0B8EDH    ;MOVE BLOCK UNTIL COUNTER=0
  1515. MOVIVA    EQU    47EDH    ;MOVE ACC TO INTERRUPT REGISTER
  1516. IM2    EQU    5EEDH    ;SET INTERRUPT MODE 2
  1517. BIT2A    EQU    57CBH    ;TEST BIT 2 IN ACC.
  1518. BIT5A    EQU    6FCBH    ;TEST BIT 5 IN ACC.
  1519. BIT0M    EQU    46CBH    ;TEST BIT 0 IN MEM
  1520. BIT1M    EQU    4ECBH    ;TEST BIT 1 IN MEM
  1521. BIT2M    EQU    56CBH    ;TEST BIT 2 IN MEM
  1522. BIT5M    EQU    6ECBH    ;TEST BIT 5 IN MEM
  1523. SET0M    EQU    0C6CBH    ;SET BIT 0 IN MEM
  1524. SET1M    EQU    0CECBH    ;SET BIT 1 IN MEM
  1525. RES1M    EQU    8ECBH    ;RESET BIT 1 IN MEM
  1526. RES2M    EQU    96CBH    ;RESET BIT 2 IN MEM
  1527. RES5M    EQU    0AECBH    ;RESET BIT 5 IN MEM
  1528. EXX    EQU    0D9H    ;EXCH REG PAIRS B, D, & H
  1529. ;
  1530. ;
  1531. ;BDOS EQUATES
  1532. ;
  1533. BDOSFNC    EQU    BDOS+6H
  1534. USRFNC    EQU    32
  1535. WRBUF    EQU    9
  1536.  
  1537.