home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol048 / unspool.asm < prev    next >
Assembly Source File  |  1984-04-29  |  13KB  |  678 lines

  1.  TITLE 'UNSPOOL Disk to device background process'
  2. ;
  3. ;    Gary P. Novosielski
  4. ;
  5. ;NOTE:    This source file requires MAC for assembly.
  6. ; Due to the complexity of operations performed by
  7. ; the macros which generate the relocation table, the
  8. ; assembly process will be significantly longer than
  9. ; normal for a program of this size.  Be prepared for
  10. ; a long period of no disk activity on each pass before
  11. ; pressing the panic button.
  12. ;
  13. ;Revisions:        (in LIFO order)
  14. ;
  15. ;2.3    81-11-07
  16. ;    Tab expansion for printers which don't
  17. ;        respond to the TAB character.
  18. ;        Include MACLIB code in source file.
  19. ;2.2    81-10-15
  20. ;    Add message to inform operator when the spool
  21. ;        writer de-installs itself.
  22. ;2.1    81-10-05
  23. ;    Add disk reset at BOOTREQ to more closely
  24. ;        simulate true warm boot.
  25. ;
  26. ;Version 2
  27. ;    Copy BIOS table so application programs will
  28. ;    still have BIOS access by using word at BOOT+1.
  29. ;    Preserve USER and IOBYTE values as of startup.
  30. ;
  31. ; BDOS Functions:
  32. ;
  33. @SYS    SET    0
  34. @KEY    SET    1
  35. @CON    SET    2
  36. @RDR    SET    3
  37. @PUN    SET    4
  38. @LST    SET    5
  39. @DIO    SET    6
  40. @RIO    SET    7
  41. @SIO    SET    8
  42. @MSG    SET    9
  43. @INP    SET    10
  44. @RDY    SET    11
  45. @VER    SET    12
  46. @LOG    SET    13
  47. @DSK    SET    14
  48. @OPN    SET    15
  49. @CLS    SET    16
  50. @DIR    SET    17
  51. @NXT    SET    18
  52. @DEL    SET    19
  53. @FRD    SET    20
  54. @FWR    SET    21
  55. @MAK    SET    22
  56. @REN    SET    23
  57. @CUR    SET    25
  58. @DMA    SET    26
  59. @CHG    SET    30
  60. @USR    SET    32
  61. @RRD    SET    33
  62. @RWR    SET    34
  63. @SIZ    SET    35
  64. @REC    SET    36
  65. ;
  66. ;System equates:
  67. CPMBASE    EQU    0
  68. BOOT    SET    CPMBASE
  69. BDOS    SET    BOOT+5
  70. TFCB    EQU    BOOT+5CH
  71. TFCB1    EQU    TFCB
  72. TFCB2    EQU    TFCB+16
  73. TBUFF    EQU    BOOT+80H
  74. TPA    EQU    BOOT+100H
  75. CTRL    EQU    ' '-1        ;CTRL CHAR MASK
  76. CR    SET    CTRL AND 'M'
  77. LF    SET    CTRL AND 'J'
  78. TAB    SET    CTRL AND 'I'
  79. FF    SET    CTRL AND 'L'
  80. BS    SET    CTRL AND 'H'
  81. EOF    SET    CTRL AND 'Z'
  82. FALSE    EQU    0
  83. TRUE    EQU    NOT FALSE
  84. ?    EQU    -1
  85. NVECTS    EQU    16        ;NUMBER OF BIOS VECTORS
  86. ;
  87. ; Assembly options
  88. EXPAND    SET    TRUE    ;True to expand tabs
  89.     IF    EXPAND
  90. PHYSBS    SET    TRUE    ;True to recognize backspace
  91.     ENDIF
  92. ;The flag SAVECCP should be made true if
  93. ;the program segment should load below the CCP.
  94. ;If false the segment will load in the extreme
  95. ;top of the Transient Program Area, overlaying
  96. ;the Console Command Processor.
  97. ;
  98. SAVECCP    SET    TRUE    ;MUST remain true for UNSPOOL
  99. OVERLAY    SET    FALSE    ;(initially)
  100. ; Macro Definitions
  101. ;
  102. ;     Perform a standard BIOS function:
  103. CPM    MACRO    FUNC,OPERAND
  104.     IF    NOT NUL OPERAND
  105.     LXI    D,OPERAND
  106.     ENDIF    ;not nul operand
  107.     IF    NOT NUL FUNC
  108.     MVI    C,@&FUNC
  109.     ENDIF    ;not nul func
  110.     CALL    BDOS
  111.     ENDM
  112. ;
  113. ;    Generate a label of the form ??Rnn to tag an
  114. ;    address requiring relocation:
  115. RTAG    MACRO    LBL,VAL
  116. ??R&LBL EQU    VAL
  117.     ENDM
  118. ;
  119. ;    Flag <INST> as a relocatable instruction
  120. ;    <INST> is of the form: <MNE    OP1[,OP2]>
  121. R    MACRO    INST
  122. @RLBL    SET    @RLBL+1
  123.     RTAG    %@RLBL,%2+$-@BASE
  124.     INST-@BASE
  125.     ENDM
  126. ;
  127. ; During bit map construction, get the next R-tagged
  128. ; address value:
  129. NXTRLD    MACRO    NN
  130. @RLD    SET    ??R&NN
  131. @NXTRLD    SET    @NXTRLD + 1
  132.     ENDM
  133. ;
  134. ;
  135. ; Enter here from Console Command Processor (CCP)
  136. ;
  137. CCPIN    ORG    TPA
  138.     JMP    INTRO
  139. ;
  140. SIGNON:
  141.     DB    'UNSPOOL',TAB,TAB,TAB
  142.     DB    'Ver 2.3'
  143.     IF    EXPAND
  144.     DB    '/T'
  145.     ENDIF    ;expand
  146.     DB    '$'
  147. ;
  148. INTRO:
  149.     CPM    MSG,SIGNON
  150.     CALL    SETUP        ;initialize.
  151.     LXI    H,BDOS+2    ;find top of memory
  152.     MOV    A,M        ;page address
  153.                 ;Form destination...
  154.     SUI    PAGES+1        ;...address in
  155.     MOV    D,A        ;DE pair.
  156.     MVI    E,0
  157.     PUSH    D        ;save on stack
  158.     LXI    H,@BASE        ;source address
  159.     LXI    B,SEGLEN
  160. ;
  161. MOVLOOP:
  162. ;Move (HL) to (DE) for (BC) bytes
  163.     MOV    A,B
  164.     ORA    C        ;test for (BC) = 0
  165.     JZ    MOVDONE
  166.     DCX    B        ;count down
  167.     MOV    A,M        ;move a byte
  168.     STAX    D
  169.     INX    D        ;bump the pointers
  170.     INX    H
  171.     JMP    MOVLOOP
  172. ;
  173. MOVDONE:
  174. ;The segment is now moved to high memory, but not
  175. ;properly relocated.  The bit table which specifies
  176. ;which addresses need to be adjusted is located
  177. ;just after the last byte of the source segment,
  178. ;so (HL) is now pointing at it.
  179.     POP    D    ;beginning of newly moved code.
  180.     LXI    B,SEGLEN;length of segment
  181.     PUSH    H    ;save pointer to reloc info
  182.     MOV    H,D    ;offset page address
  183. ;
  184. FIXLOOP:
  185. ;Scan through the newly moved code, and adjust any
  186. ;page addresses by adding (H) to them.  The word on
  187. ;top of the stack points to the next byte of the
  188. ;relocation bit table.  Each bit in the table
  189. ;corresponds to one byte in the destination code.
  190. ;A value of 1 indicates the byte is to be adjusted.
  191. ;A value of 0 indicates the byte is to be unchanged.
  192. ;
  193. ;Thus one byte of relocation information serves to
  194. ;mark 8 bytes of object code.  The bits which have
  195. ;not been used yet are saved in L until all 8
  196. ;are used.
  197. ;
  198.     MOV    A,B
  199.     ORA    C        ;test if finished
  200.     JZ    FIXDONE
  201.     DCX    B        ;count down
  202.     MOV    A,E
  203.     ANI    07H        ;on 8-byte boundry?
  204.     JNZ    NEXTBIT
  205. ;
  206. NEXTBYT:
  207. ;Get another byte of relocation bits
  208.     XTHL
  209.     MOV    A,M
  210.     INX    H
  211.     XTHL
  212.     MOV    L,A        ;save in register L
  213. ;
  214. NEXTBIT    MOV    A,L        ;remaining bits from L
  215.     RAL            ;next bit to CARRY
  216.     MOV    L,A        ;save the rest
  217.     JNC    NEXTADR
  218. ;
  219. ;CARRY was = 1.  Fix this byte.
  220.     LDAX    D
  221.     ADD    H        ;(H) is the page offset
  222.     STAX    D
  223. ;
  224. NEXTADR    INX    D
  225.     JMP    FIXLOOP
  226. ;
  227. FIXDONE:
  228. ;Finished.  Jump to the first address in the new
  229. ;segment in high memory.
  230. ;
  231. ;First adjust the stack.  One garbage word was
  232. ;left by fixloop.
  233.     INX    SP
  234.     INX    SP
  235. ;
  236. ;(HL) still has the page address
  237.     MOV    L,A    ;move zero to l
  238.     PCHL        ;Top-of-stack is CCP return
  239. SETUP:
  240. ;First, check environment to see if BIOS vectors
  241. ;are accessible.
  242.     LDA    BOOT        ;Location BOOT should
  243.     CPI    ( JMP )        ;have a JMP instruction
  244.     JNZ    VECTERR
  245.     LHLD    BOOT+1        ;Location one has a
  246.     MOV    A,L        ;low byte of
  247.     CPI    3        ; 03H
  248.     JNZ    VECTERR
  249.     MVI    C,NVECTS    ;which is the origin
  250.                 ;of a table of jumps
  251.                 ;which we move into
  252.                 ;the code.
  253.     LXI    D,BIOSV
  254.     XCHG
  255. VLOOP:
  256.     LDAX    D
  257.     CMP    M        ;another JMP
  258.     JNZ    VECTERR
  259.     INX    D
  260.     INX    H
  261.     LDAX    D
  262.     MOV    M,A
  263.     INX    D
  264.     INX    H
  265.     LDAX    D
  266.     MOV    M,A
  267.     INX    H
  268.     INX    D
  269.     DCR    C
  270.     JNZ    VLOOP
  271. ; Save old vectors and CCP return address
  272.     LHLD    BOOT+1
  273.     SHLD    OLDBOOT
  274. ;
  275.     LXI    H,2
  276.     DAD    SP
  277.     MOV    A,M
  278.     INX    H
  279.     MOV    H,M
  280.     MOV    L,A
  281.     SHLD    CCPRET+1
  282. ;
  283.     LHLD    BDOS+1
  284.     SHLD    GOBDOS+1
  285. SETUPDEV:
  286.     LXI    D,TFCB2+1
  287.     LDAX    D
  288.     CPI    ' '
  289.     JZ    SETUPFIL
  290. ;
  291.     LXI    H,LSTLIT
  292.     MVI    B,4
  293.     CALL    SCOMP
  294.     JZ    SETUPFIL;    Use default
  295. ;
  296.     LXI    D,TFCB2+1
  297.     LXI    H,PUNLIT
  298.     MVI    B,4
  299.     CALL    SCOMP
  300.     JNZ    DEVERR
  301.     MVI    A,@PUN
  302.     STA    DEVICE
  303. SETUPFIL:
  304.     LDA    TFCB1
  305.     ORA    A
  306.     JNZ    OPENIT
  307. ;The drive has been defaulted.  Make it explicit
  308. ;in case the default drive is changed while the
  309. ;file is being unspooled.
  310.     CPM    CUR;    Returns A: as 00
  311.     INR    A;    Open needs A: as 01
  312.     STA    TFCB1
  313. OPENIT:
  314.     CPM    OPN,TFCB1
  315.     INR    A
  316.     JNZ    COPYFCB
  317. ;Error.  Can't open input file.
  318.     LXI    H,TBUFF
  319.     MOV    A,M
  320.     ADD    L
  321.     MOV    L,A
  322.     ADC    H
  323.     SUB    L
  324.     MOV    H,A
  325.     INX    H
  326.     MVI    M,'?'
  327.     INX    H
  328.     MVI    M,'$'
  329.     CPM    CON,CR
  330.     CPM    CON,LF
  331.     CPM    MSG,TBUFF+1
  332.     POP    H;    Adjust stack
  333.     RET;        Exit to CCP
  334. ;
  335. COPYFCB:
  336.     LXI    H,TFCB1
  337.     LXI    D,FCB
  338.     MVI    C,33
  339. COPY1    MOV    A,M
  340.     STAX    D
  341.     INX    H
  342.     INX    D
  343.     DCR    C
  344.     JNZ    COPY1
  345. ;
  346. SETUPUSR:
  347. ;    Save user number in effect at time of entry
  348.     CPM    USR,?
  349.     STA    ENTUSR
  350. ;
  351. SETUPIOB:
  352. ;    Save IOBYTE in effect at time of entry
  353.     CPM    RIO
  354.     STA    ENTIOB
  355. ;
  356.     RET
  357. ;
  358. SCOMP:
  359.     LDAX    D
  360.     CMP    M
  361.     RNZ
  362.     INX    D
  363.     INX    H
  364.     DCR    B
  365.     JNZ    SCOMP
  366.     RET
  367. ;
  368. DEVERR:
  369.     CPM    MSG,DEVERRMSG
  370.     POP    H;    Adjust stack
  371.     RET;        Exit to CCP
  372. VECTERR:
  373.     CPM    MSG,VCTERRMSG
  374.     JMP    BOOT    ;try re-booting.
  375. ;
  376. LSTLIT:
  377.     DB    'LST '        ;Note trailing blank
  378. PUNLIT:
  379.     DB    'PUN '        ;Note trailing blank
  380. DEVERRMSG:
  381.     DB    CR,LF,'Invalid device.$'
  382. VCTERRMSG:
  383.     DB    CR,LF,'Error in system table.  '
  384.     DB    'Attempting re-boot.$'
  385.     PAGE
  386. ;Align location counter to next page boundry
  387. @BASE    ORG    ($ + 0FFH) AND 0FF00H
  388. @RLBL    SET    0
  389. ;
  390. ; The segment to be relocated goes here.
  391. ; Any position dependent (3-byte) instructions
  392. ; are handled by the "R" macro.
  393. ; For readability, the macro name "R" is placed in
  394. ; column 2.  The preceding blank must be present to
  395. ; distinguish it from a label.
  396. ;*************************************************
  397. BDOSV:
  398. ;After the first pass, this location will point
  399. ;to INTERCEPT: and is pointed to by BDOS.
  400. ;It must be the lowest address
  401. ;in the protected segment of code.
  402.  R    <JMP    BOOTREQ>    ;complete installation
  403. BIOSV:
  404.     REPT    NVECTS
  405.     JMP    ?
  406.     ENDM
  407. LSTSTAT    EQU    BIOSV + (14*3)
  408. ;
  409. INTERCEPT:
  410.     MOV    A,C;        Get function
  411.     CPI    @KEY;    Is it single key input?
  412.  R    <JZ    WAITING>
  413.     CPI    @INP;    or buffered input?
  414.  R    <JNZ    CKDMA>
  415. WAITING:
  416. ;Wait for actual keypress before honoring input
  417. ;request.  Unspool characters in the meantime.
  418.  R    <LDA    ACTIVE>
  419.     ORA    A;    See if finished.
  420.  R    <CNZ    PROCESS>
  421.  R    <JMP    GOBDOS>;    Honor the input request
  422. ;
  423. CKDMA    CPI    @DMA;    If the DMA address is being
  424.         ;    changed, we have to know.
  425.  R    <JNZ    GOBDOS>
  426.     XCHG
  427.  R    <SHLD    DMAHOLD>
  428.     XCHG
  429. ;
  430. GOBDOS    JMP    ?;        Patched on entry
  431.         ;    points to "real" BDOS routine.
  432. ;
  433. ;
  434. PROCESS:
  435. ;The application program is now waiting for a key
  436. ;to be input.  We will use this opportunity to print
  437. ;some characters to the device until a key is
  438. ;actually pressed.
  439.     LXI    H,0
  440.     DAD    SP
  441.  R    <LXI    SP,LCLSTACK>
  442.     PUSH    H;    Save old SP
  443.     PUSH    B
  444.     PUSH    D;    Save entry parameters
  445.     MVI    C,@RIO;    Save old IOBYTE
  446.  R    <CALL    GOBDOS>
  447.  R    <STA    IOBHOLD>
  448. PROC1:
  449.  R    <CALL    CKKEY>;    Check for keypress.
  450.  R    <JNZ    PROCEXIT>
  451.  R    <LDA    DEVICE>        ;Check device being used
  452.     CPI    @LST
  453.  R    <JNZ    PROC2>        ;If it is LST:
  454.  R    <CALL    LSTSTAT>
  455.     ORA    A
  456.  R    <JZ    PROC1>        ;Loop if not ready
  457. ;
  458. PROC2:
  459.     IF    EXPAND
  460.  R    <LDA    TABFLAG>;    In a tab sequence?
  461.      ORA    A
  462.  R    <JNZ    TABSEQ>
  463.     ENDIF    ;EXPAND
  464. ;
  465.  R    <LXI    H,BUFFER>
  466.     MOV    A,M
  467.     ORA    A
  468.  R    <CM    FILLBUFF>
  469.  R    <JC    ENDFILE>
  470.     INR    A
  471.     MOV    M,A
  472.     MOV    C,A
  473.     MVI    B,0
  474.     DAD    B;    Point to the buffered char.
  475.     MOV    A,M
  476.     CPI    EOF
  477.  R    <JZ    ENDFILE>
  478.     IF    EXPAND
  479.  R    <LXI    H,LINEPOS>;    Print head position.
  480. ;
  481.     CPI    TAB;        Is this a tab?
  482.  R    <JZ    HNDTAB>;    Process it.
  483. ;
  484.     IF    PHYSBS
  485.     CPI    BS;        Backspace?
  486.  R    <JNZ    PROC3>
  487.     DCR    M;        Back up 1 column
  488.  R    <JMP    PROC9>
  489. PROC3:
  490.     ENDIF    ;PHYSBS
  491.     CPI    CR;        End of line?
  492.  R    <JNZ    PROC4>
  493.     MVI    M,0;        Reset column count.
  494.  R    <JMP    PROC9>
  495. PROC4:
  496.     CPI    ' ';        Other ctrl char?
  497.  R    <JC    PROC9>;        Dont change column.
  498. PROC5:
  499.     INR    M;        Increase column.
  500. PROC9:
  501.     ENDIF    ;EXPAND
  502.     MOV    E,A
  503.     PUSH    D    ;SAVE CHARACTER
  504. ;Set the IOBYTE as it was when UNSPOOL was
  505. ;started.
  506.  R    <LDA    ENTIOB>
  507.     MOV    E,A
  508.     MVI    C,@SIO
  509.  R    <CALL    GOBDOS>
  510.     POP    D    ;RESTORE CHARACTER
  511.     MVI    C,@LST;        Default
  512. DEVICE    EQU    $-1;        Device code patch
  513.  R    <CALL    GOBDOS>
  514.  R    <LDA    IOBHOLD>;    Restore active IOBYTE
  515.     MOV    E,A
  516.     MVI    C,@SIO
  517.  R    <CALL    GOBDOS>
  518.  R    <JMP    PROC1>
  519. ;
  520.     IF    EXPAND
  521. HNDTAB:
  522.  R    <STA    TABFLAG>;    Set the flag
  523. SPCOUT:
  524.     MVI    A,' '
  525.  R    <JMP    PROC5>
  526. ;
  527. TABSEQ:
  528.  R    <LXI    H,LINEPOS>
  529.     MVI    A,7
  530.     ANA    M;    Check if more blanks needed
  531.  R    <JNZ    SPCOUT>
  532.  R    <STA    TABFLAG>;    Clear the flag
  533.  R    <JMP    PROC1>
  534.     ENDIF    ;EXPAND
  535. ENDFILE:
  536.     XRA    A
  537.  R    <STA    ACTIVE>
  538. ;
  539. PROCEXIT:
  540.     POP    D
  541.     POP    B
  542.     POP    H;    Restore SP
  543.     SPHL
  544.     RET
  545. ;
  546. ;
  547. FILLBUFF:
  548. ;Fill the buffer from the file
  549.     PUSH    H
  550.     INX    H
  551.     XCHG;        Buffer address to DE
  552.      MVI    C,@DMA;    Set DMA address
  553.  R    <CALL    GOBDOS>
  554.     MVI    E,?
  555.     MVI    C,@USR
  556.  R    <CALL    GOBDOS>;    Get current user
  557.  R    <STA    USRHOLD>;    Save it
  558.  R    <LDA    ENTUSR>;    Change to user at entry
  559.     MOV    E,A
  560.     MVI    C,@USR
  561.  R    <CALL    GOBDOS>
  562.  R    <LXI    D,FCB>
  563.     MVI    C,@FRD;        Read a sector
  564.  R    <CALL    GOBDOS>
  565.     PUSH    PSW;    Save read return code
  566.  R    <LHLD    DMAHOLD>
  567.     XCHG;        Restore DMA address
  568.     MVI    C,@DMA;    to old value.
  569.  R    <CALL    GOBDOS>
  570.  R    <LDA    USRHOLD>
  571.     MOV    E,A;    Restore User number
  572.     MVI    C,@USR;    to old value
  573.  R    <CALL    GOBDOS>
  574.     POP    PSW;    Read return code
  575.     POP    H;    Buffer pointer
  576.     ORA    A;    How went the read?
  577.     RZ;        Fine
  578.     STC;        No good. Set CARRY for EOF
  579.     RET
  580. ;
  581. CKKEY:
  582. ;Return zero flag if key not pressed
  583.     MVI    C,@RDY
  584.  R    <CALL    GOBDOS>
  585.     ORA    A
  586.     RET
  587. ;
  588. ;
  589. BOOTREQ:
  590. ;The application process has requested a reboot
  591. ;by jumping to location 0.  If we are no longer
  592. ;active, we will honor the request by executing
  593. ;the address found in the BOOT vector at entry.
  594. ;Otherwise return to CCP without rebooting.
  595.     LXI    SP,CCPIN    ;set up a valid stack
  596.  R    <LDA    ACTIVE>
  597.     ORA    A
  598.  R    <JNZ    NOTYET>
  599. ;Jump to old boot address as read from memory
  600. ;word 1 before we changed it.
  601.  R    <LXI    D,DONEMSG>
  602.     MVI    C,@MSG
  603.  R    <CALL    GOBDOS>
  604.  R    <LHLD    OLDBOOT>
  605.     PCHL
  606. ;
  607. NOTYET    LXI    H,TBUFF
  608.  R    <SHLD    DMAHOLD>
  609.     MVI    C,@LOG
  610.  R    <CALL    GOBDOS>
  611.  R    <LXI    D,ACTMSG>
  612.     MVI    C,@MSG
  613.  R    <CALL    GOBDOS>
  614.  R    <LXI    H,INTERCEPT>
  615.  R    <SHLD    BDOSV+1>
  616.  R    <LXI    H,BDOSV>
  617.     SHLD    BDOS+1
  618.  R    <LXI    H,BOOTREQ>
  619.  R    <SHLD    BIOSV+1>
  620.  R    <LXI    H,BIOSV>
  621.     SHLD    BOOT+1
  622. CCPRET:
  623.     JMP    ?;    Patched on startup
  624. ;
  625. ACTMSG:    DB    CR,LF
  626.     DB    'Unspooling in progress.'
  627.     DB    '$'
  628. DONEMSG:
  629.     DB    CR,LF,'UNSPOOL Completed.'
  630.     DB    '$'
  631. OLDBOOT    DW    ?
  632. DMAHOLD    DW    TBUFF
  633. ACTIVE    DB    TRUE
  634.     IF    EXPAND
  635. TABFLAG    DB    FALSE
  636. LINEPOS    DB    0
  637.     ENDIF    ;EXPAND
  638. USRHOLD    DB    ?
  639. ENTUSR    DB    ?
  640. IOBHOLD    DB    ?
  641. ENTIOB    DB    ?
  642. FCB    DS    33
  643. BUFFER    DB    ?
  644. OVERLAY    SET    $    ;Bit table may start here
  645.     DS    128
  646.     DS    32;    LOCAL STACK AT LEAST 16 WORDS
  647. ;            PLUS WHATEVER'S LEFT OVER
  648. LCLSTACK EQU    ($+0FFH) AND 0FF00H
  649. ;*************************************************
  650. ;End of segment to be relocated.
  651.     IF    SAVECCP
  652. PAGES    EQU    ($-@BASE)/256+8
  653.     ELSE
  654. PAGES    EQU    ($-@BASE)/256
  655.     ENDIF    ;saveccp
  656. ;
  657.     IF    OVERLAY NE FALSE
  658.     ;cause relocation map to slide down into
  659.     ;unused DS area:
  660. SEGLEN    EQU    OVERLAY-@BASE
  661.     ORG    @BASE+SEGLEN
  662.     ELSE
  663.     ;relocation bit map starts here:
  664. SEGLEN    EQU    $-@BASE
  665.     ENDIF    ;overlay
  666.     PAGE
  667. ;    Build the relocation information into a
  668. ; bit map following the code.
  669. ;
  670. @X    SET    0
  671. @BITCNT    SET    0
  672. @RLD    SET    ??R1
  673. @NXTRLD SET    2
  674.     RTAG    %@RLBL+1,0FFFFH    ;define one more symbol
  675. ;
  676.     REPT    SEGLEN+8
  677.     IF    @BITCNT>@RLD
  678.