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