home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d528 / cpublit.lha / CpuBlit / src / scroll.s < prev    next >
Text File  |  1991-08-05  |  43KB  |  1,167 lines

  1. ***************************************************************** :ts=8 *****
  2. *
  3. *    SCROLL.S
  4. *
  5. *    (C) Copyright Eddy Carroll, January 1991.
  6. *
  7. *    Replaces BltBitMap with a routine that uses the CPU (preferably
  8. *    68030). This increases speed by a factor of about 2.8 on the A3000
  9. *    when the cache is enabled or 2.0 when the cache is disabled.
  10. *
  11. *****************************************************************************
  12.  
  13.     include "exec/types.i"
  14.     include "exec/execbase.i"
  15.     include "exec/nodes.i"
  16.     include "graphics/gfx.i"
  17.  
  18.     XDEF    _NewBltBitMap
  19.     XDEF    _BltBitMapAddress
  20.     XDEF    _OnlySingle
  21.     XDEF    _UsageCount
  22.     XDEF    _Broken
  23.     XDEF    _BlitFunc
  24.     XDEF    _MinTaskPri
  25.     XDEF    _StartBlit
  26.     XDEF    _ExitBlit
  27.     XDEF    _ShareBlit
  28.     XDEF    _Friend1
  29.     XDEF    _Friend2
  30.  
  31.     XREF    _SysBase
  32.     XREF    _GfxBase
  33.     XREF    _LVOWait
  34.     XREF    _LVOWaitBlit
  35.  
  36.     SECTION Scroll,CODE
  37.  
  38. *****************************************************************************
  39. *
  40. *    NewBltBitMap()
  41. *
  42. *    Replacement BltBitMap which uses the 68030 instead of the blitter.
  43. *    The following conditions must hold for the CPU routine to be used:
  44. *
  45. *        o    Bitmaps aligned on same longword bit offset
  46. *        (i.e. XSrc % 32 == XDest % 32)
  47. *
  48. *        o    If source bitmap == destination bitmap, then YSrc != YDest
  49. *
  50. *        o    Blitter minterm = $Cx (i.e. straight copy)
  51. *
  52. *    If any of these conditions doesn't hold, then the original BltBitMap
  53. *    is called instead.
  54. *
  55. *    Input:
  56. *        D0 - X Source
  57. *        D1 - Y Source
  58. *        D2 - X Dest
  59. *        D3 - Y Dest
  60. *        D4 - X Size
  61. *        D5 - Y Size
  62. *        D6 - Minterm
  63. *        D7 - Mask, indicating which planes are to be affected
  64. *        A0 - Pointer to source bitmap structure
  65. *        A1 - Pointer to destination bitmap structure
  66. *        A2 - Pointer to temporary bitmap structure (not used)
  67. *
  68. *    Output:
  69. *        D0 - Number of planes actually copied
  70. *
  71. *    The copy routine works as follows. Everything is done in longword
  72. *    units. If the bitmap being copied fits horizontally into a single
  73. *    longword, then the CopySingle() routine is used which copies a
  74. *    single column of longwords, masked out as appropriate. Otherwise,
  75. *    there are at least two longwords involved (the left and right edges
  76. *    of the bitmap), with possibly some longwords inbetween as well.
  77. *    CopyMultiple() is called to perform this copy; it uses two mask
  78. *    values to identify which bits in the left and right longwords should
  79. *    be copied. The longwords (if any) in between are copied verbatim.
  80. *
  81. *    Note that using longwords gives a big win on the A3000 since it can
  82. *    access CHIP ram via the 32 bit bus. This relies on the data being
  83. *    longword aligned of course. In the worst case (where a bitmap width
  84. *    is not a multiple of 4), one out of every two rows will be longword
  85. *    aligned, which is not too bad. In the more common case, every row
  86. *    is longword aligned. For overscan users, it's best to have your
  87. *    screen width a multiple of 32.
  88. *
  89. *****************************************************************************
  90.  
  91. PreExit:
  92.     move.w    (sp)+,d0        ; Restore original A0 register
  93.     exg    d6,a0            ; Ignore following instruction
  94. _ExitBlit:
  95.     exg    d6,a0            ; Restore original A0 register
  96. DoOldBlt:
  97.     subq.l    #1,_UsageCount        ; Decrement number of callers in code
  98. oldblt2:
  99.     move.l    (sp)+,d6        ; Restore original mask
  100. oldblit:
  101.     jmp    dummy            ; Filled in with correct address later
  102.  
  103. _BltBitMapAddress equ oldblit+2
  104.  
  105. dummy:    rts
  106.  
  107. _NewBltBitMap:
  108.     tst.w    d4            ; Check if width is zero
  109.     beq.s    dummy            ; If it is, don't do anything
  110.     cmp.l    a0,a1            ; Copying within the same bitmap?
  111.     bne.s    nb1            ; If yes,
  112.     cmp.w    d1,d3            ; and Y row is the same, then it's a
  113.     beq.s    oldblit            ; sideways blit so use system routine
  114.     bra.s    nb2            ; Else skip to next check
  115. nb1:
  116.     tst.l    _OnlySingle        ; Should we handle different src/dest
  117.     bne.s    oldblit            ; If not, use standard system blit
  118. nb2:
  119.     move.l    d6,-(sp)        ; Save current minterm register
  120.     and.b    #$f0,d6            ; Mask out low bits
  121.     cmp.b    #$c0,d6            ; Is it standard COPY minterm?
  122.     bne.s    oldblt2            ; If not, exit
  123.     move.l    d0,d6            ; See if XSrc % 32 == XDest % 32
  124.     eor.l    d2,d6            ; Low 5 bits should be zero if equal
  125.     and.b    #$1f,d6            ;
  126.     bne.s    oldblt2            ; If not, then have to do normal blit
  127.     tst.l    _Broken            ; Are we accomodating broken s/w?
  128.     bne.s    nb3            ; If so, skip checks
  129.     tst.b    bm_Flags(a0)        ; Is source standard Amiga bitmap?
  130.     bne.s    oldblt2            ; If not, use system blit routine
  131.     tst.w    bm_Pad(a0)        ; 
  132.     bne.s    oldblt2            ;
  133.     tst.b    bm_Flags(a1)        ; How about destination?
  134.     bne.s    oldblt2            ; If it isn't, use system blit
  135.     tst.w    bm_Pad(a1)        ; 
  136.     bne.s    oldblt2            ;
  137. nb3:
  138.     addq.l    #1,_UsageCount        ; Increment usage count
  139.     exg    d6,a0            ; Save current A0
  140.     move.l    _BlitFunc,a0        ; Get pointer to appropriate test func
  141.     jmp    (a0)            ; And branch to it
  142. ;
  143. ;    Checks the usage count for the blitter code, to see if anyone else
  144. ;    is currently executing it. If so, use the blitter instead (hence
  145. ;    CPU does one blit while blitter does the other blit; multiprocessing!)
  146. ;
  147. _ShareBlit:
  148.     exg    d6,a0            ; Restore old A0
  149.     move.l    _UsageCount,d6        ; Check if someone already in code
  150.     bne    DoOldBlt        ; If there is, use blitter instead
  151.     bra.s    sblit2            ; Else skip to use CPU
  152. ;
  153. ;    Checks to see if there is more than one task ready to run. If so,
  154. ;    use the blitter, else use the CPU. Note that for the most common case
  155. ;    of scrolling (in a CLI/console window), the task outputting the text
  156. ;    that causes the scroll will be "Ready to Run" since it is pre-empted
  157. ;    by the console device before it has a chance to go into a Wait
  158. ;    condition.
  159. ;
  160. ;    If there is more than one task ready to run, but the second task
  161. ;    in the queue has priority < MinTaskPri, then we can use the CPU
  162. ;    anyway (since the second task is a background task that can be
  163. ;    ignored).
  164. ;
  165. _Friend2:
  166.     move.l    _SysBase,a0        ; Get pointer to ExecBase
  167.     lea.l    TaskReady(a0),a0    ; Get ptr to TaskReady list
  168.     cmp.l    8(a0),a0        ; Empty list?
  169.     beq.s    _StartBlit        ; If yes, do blit
  170.     move.w    d0,-(sp)        ; Grab a register temporarily
  171.     move.l    (a0),a0            ; Get pointer to first waiting task
  172.     move.l    (a0),a0            ; Get pointer to second task
  173.     move.b    LN_PRI(a0),d0        ; Get its priority (if it exists)
  174.     move.l    (a0),a0            ; And final link ptr (NULL if at end)
  175.     exg    d6,a0            ; Restore previous A0
  176.     tst.l    d6            ; More than 1 task?
  177.     beq.s    F2Okay            ; If no, we can use the blitter anyway
  178.     cmp.b    _MinTaskPri,d0        ; Should we make way for waiting task?
  179.     bge    PreExit            ; If so, use blitter instead
  180. F2Okay:
  181.     move.w    (sp)+,d0        ; Else restore D0
  182.     bra.s    sblit2            ; And skip to start blit
  183. ;
  184. ;    Checks to see if there are _any_ other tasks ready to run. If there
  185. ;    are and their task priority is >= MinTaskPri, then uses system blit
  186. ;    instead of CPU.
  187. ;
  188. _Friend1:
  189.     move.l    _SysBase,a0        ; Get pointer to ExecBase
  190.     lea.l    TaskReady(a0),a0    ; Get ptr to TaskReady list, head node
  191.     cmp.l    8(a0),a0        ; Empty list?
  192.     beq.s    _StartBlit        ; If yes, we can safely blit
  193.     move.l    (a0),a0            ; Get pointer to first task
  194.     move.w    LN_TYPE(a0),a0        ; Read ln_Type and ln_Pri
  195.     exg    d6,a0            ; Restore a0
  196.     cmp.b    _MinTaskPri,d6        ; Should we ignore this task?
  197.     bge    DoOldBlt        ; If not, then use blitter instead
  198.     bra.s    sblit2            ; Else skip to use CPU
  199.  
  200. ;----------------------------------------------------------------------------
  201. ;    Where the action starts. Initialises everything and then performs
  202. ;    the blits using the CPU. At this stage, all registers are exactly
  203. ;    as they were on entry to BltBitMap, except for D6 and A0, and these
  204. ;    two are restored to the correct values immediately on entry.
  205. ;----------------------------------------------------------------------------
  206. _StartBlit:
  207.     exg    d6,a0            ; Restore A0
  208. sblit2:                    ; Alternative entry point
  209. ;
  210. ;    Now we need to determine the masks to be used for clipping, along
  211. ;    with the start address in memory of the section of the bit and
  212. ;    the modulo of each bitplane (the amount added onto the end of each
  213. ;    copied row address to get to the start of the next one). Then loop
  214. ;    over all the selected bitplanes, copying those requested.
  215. ;
  216.     movem.l    d1-d5/d7/a0-a6,-(sp)    ; Save rest of the registers
  217. ;
  218. ;    Next, we need to make sure that the blitter is free. This is because
  219. ;    some other blitter operation that operates on the bitmaps we've been
  220. ;    passed may have started but not yet finished. Operations that
  221. ;    depend on the blitter are guaranteed to occur in the right order
  222. ;    (since the blitter can't multitask with itself) but when we start
  223. ;    doing some of them with the CPU, we need to be a bit more careful.
  224. ;
  225. ;    Note: Since we are now "in" graphics.library, a6 holds GfxBase.
  226. ;          WaitBlit() is documented as preserving all registers.
  227. ;
  228.     jsr    _LVOWaitBlit(a6)    ; Wait for blitter to become free
  229.     ext.l    d0            ; Convert all parameters to long
  230.     ext.l    d1            ;
  231.     ext.l    d2            ;
  232.     ext.l    d3            ;
  233.     ext.l    d4            ;
  234.     ext.l    d5            ;
  235.  
  236.     cmp    d1,d3            ; See if we are scrolling up or down
  237.     bhi    bltdown            ;
  238. ;
  239. ;    Since YDest < YSrc, we are copying the bitmap upwards in memory
  240. ;    therefore start at the beginning and work down. (This is only
  241. ;    important if the source and destination bitmaps are the same, but
  242. ;    it doesn't do any harm to check when they are different also.)
  243. ;
  244. bltup:
  245.     move.w    bm_BytesPerRow(a0),d6    ; Get width of source bitmap
  246.     ext.l    d6            ; Extend to full integer
  247.     move.l    d6,a2            ; Initialise modulo for source bitmap
  248.     muls    d6,d1            ; Calculate row offset
  249.     move.l    d0,d6            ; Get XSrc
  250.     lsr.l    #3,d6            ; Get #bytes offset of XSrc
  251.     and.b    #$fc,d6            ; Adjust to longword boundary
  252.     add.l    d6,d1            ; Add on x offset to get bitmap offset
  253.     move.l    d1,a4            ; Now A4 = offset into source bitmap
  254. ;
  255. ;    Repeat for dest bitmap
  256. ;
  257.     move.w    bm_BytesPerRow(a1),d6    ; Get width of dest bitmap
  258.     ext.l    d6            ; Extend to full integer
  259.     move.l    d6,a3            ; Initialise modulo for dest bitmap
  260.     muls    d6,d3            ; Calculate row offset
  261.     move.l    d2,d6            ; Get XDest
  262.     lsr.l    #3,d6            ; (Converted to longword aligned
  263.     and.b    #$fc,d6            ; byteoffset)
  264.     add.l    d6,d3            ; Add on xoffset to get bitmap offset
  265.     move.l    d3,a5            ; Now A5 = offset into dest bitmap
  266.     bra.s    contblit        ; Skip to rest of blitcopy
  267. ;
  268. ;    If we get here, YDest > YSrc, so we are copying the bitmap downwards
  269. ;    which means we need to start from the end and work back. We also
  270. ;    need to initialise the modulo to -BytesPerRow instead of BytesPerRow.
  271. ;
  272. bltdown:
  273.     add.l    d5,d1            ; Add YSize+YSrc to get last row addr
  274.     subq.l    #1,d1            ; Adjust (so we don't have last_row+1)
  275.     move.w    bm_BytesPerRow(a0),d6    ; Get width of source bitmap
  276.     ext.l    d6            ; Extend to full longword
  277.     muls    d6,d1            ; Calculate row offset
  278.     neg.l    d6            ; Negate mod. since copying backwards
  279.     move.l    d6,a2            ; Initialise modulo for source bitmap
  280.     move.l    d0,d6            ; Get XSrc
  281.     lsr.l    #3,d6            ; Get #bytes offset of XSrc
  282.     and.b    #$fc,d6            ; Adjust to longword boundary
  283.     add.l    d6,d1            ; Add on x offset to get bitmap offset
  284.     move.l    d1,a4            ; Now A4 = offset into source bitmap
  285. ;
  286. ;    Do same calculations for dest bitmap
  287. ;
  288.     add.l    d5,d3            ; Add YSize+YSrc to get last row addr
  289.     subq.l    #1,d3            ; Adjust (so we don't have last_row+1)
  290.     move.w    bm_BytesPerRow(a1),d6    ; Get width of dest bitmap
  291.     ext.l    d6            ; Extend to full longword
  292.     muls    d6,d3            ; Calculate row offset
  293.     neg.l    d6            ; Negate, since copying backwards
  294.     move.l    d6,a3            ; Initialise modulo for dest bitmap
  295.     move.l    d2,d6            ; Get XDest
  296.     lsr.l    #3,d6            ; (Converted to longword aligned
  297.     and.b    #$fc,d6            ; byteoffset)
  298.     add.l    d6,d3            ; Add on xoffset to get bitmap offset
  299.     move.l    d3,a5            ; Now A5 = offset into dest bitmap
  300. ;
  301. ;    Now calculate the mask values
  302. ;
  303. contblit:
  304.     and.w    #$1f,d0            ; Calculate XSrc longword bit offset
  305.     add.l    d0,d4            ; Calculate width of bitmap
  306.     move.l    d4,d1            ; Calculate longword bit offset
  307.     and.w    #$1f,d1            ;
  308.     lsr.l    #5,d4            ; Calc # of longwords needed for copy
  309.     add.l    d1,d1            ; Scale XWidth bits to longword index
  310.     add.l    d1,d1            ; into the bitmask array
  311.     bne.s    contb1            ; If zero,
  312.     subq.l    #1,d4            ; Decrement longword count
  313. contb1:
  314.     lea    RightMask(PC),a6    ; Get address of right mask table
  315.     move.l    0(a6,d1.w),d2        ; Get right bitmask
  316.     add.l    d0,d0            ; Scale XSrc bits to longword index
  317.     add.l    d0,d0            ; And again
  318. contb2:
  319.     lea    LeftMask(PC),a6        ; Get address of left mask table
  320.     move.l    0(a6,d0.w),d1        ; Get left bitmask
  321. ;
  322. ;    Calculate minimum number of bitplanes to copy
  323. ;
  324.     moveq.l    #0,d6            ; Zero out high bits of D6
  325.     move.b    bm_Depth(a0),d6        ; Get depth of source bitmap
  326.     cmp.b    bm_Depth(a1),d6        ; If greater than that of dest bitmap
  327.     blo.s    contb3            ;
  328.     move.b    bm_Depth(a1),d6        ; Use dest bitmap depth instead
  329. contb3:
  330.     subq.l    #1,d6            ; Adjust depth to 0-based, not 1-based
  331.     move.l    d4,d0            ; Copy longword count
  332.     addq.l    #1,d0            ; Adjust positively
  333.     add.l    d0,d0            ; Convert longword count to byte count
  334.     add.l    d0,d0            ;
  335.     sub.l    d0,a2            ; Calculate correct modulo for source
  336.     sub.l    d0,a3            ; Calculate correct modulo for dest.
  337.     exg    a2,a4            ; Setup A2/A3 = bitmap offsets
  338.     exg    a3,a5            ;  and  A4/A5 = bitmap modulos
  339.  
  340.     subq.l    #1,d4            ; Adjust longword count to zero-based
  341.     move.l    d4,d3            ; Move to right reg for Copy routine
  342.     move.l    d5,d0            ; Copy YSize to right place also
  343.     lea.l    bm_Planes(a0),a0    ; Get pointer to source bitplane array
  344.     lea.l    bm_Planes(a1),a1    ; Get pointer to dest bitplane array
  345.     move.l    a0,d4            ; Stash bitplane pointers here
  346.     move.l    a1,d5            ;
  347.     move.l    20(sp),d7        ; Read plane mask value from stack
  348. ;
  349. ;    Now build a list of bitmaps to be copied on the stack. To this end,
  350. ;    we reserve 8 * 8 = 64 bytes of stack for source/destination bitmap
  351. ;    pointers.
  352. ;
  353.     lea    -64(sp),sp        ; Reserve space for bitmap ptrs
  354.     move.l    sp,a6            ; And point to it using A6
  355. ;
  356. ;    Loop through bitmaps building bitmap list for bitmaps specified in
  357. ;    the copy mask. Bitplanes which have source and/or destination bitmaps
  358. ;    set to NULL or -1 get handled immediately (new for WB 2.0). All others
  359. ;    get stored on the stack.
  360. ;
  361.     move.w    d7,-(sp)        ; Save plane mask as temporary value
  362.     moveq.l    #0,d7            ; Clear bitmap plane count
  363. cmultlp:
  364.     lsr.w    (sp)            ; See if need to copy this bitplane
  365.     bcc.s    cmultx            ; If not, skip over code
  366.     addq    #1,d7            ; Increment number of bitmaps copied
  367.     move.l    d4,a0            ; Get pointer to source bitplane ptr
  368.     move.l    d5,a1            ; And destination bitplane ptr
  369.     move.l    (a0),d4            ; Read pointers to bitplanes
  370.     move.l    (a1),d5            ;
  371.     not.l    d5            ; Check if dest is -1
  372.     beq    skipfill        ; If so, don't copy anything
  373.     not.l    d5            ; Check if dest is zero
  374.     beq    skipfill        ; If so, don't copy anything
  375.     not.l    d4            ; Check if source is -1
  376.     beq    fillones        ; If so, fill dest with 1's
  377.     not.l    d4            ; Check if source is 0
  378.     beq    fillzeros        ; If so, fill dest with 0's
  379.     exg    d4,a0            ; Put registers back in right place
  380.     exg    d5,a1            ;
  381.     add.l    a2,a0            ; Add in correct offset for src ptr
  382.     add.l    a3,a1            ; Add in correct offset for dest ptr
  383.     move.l    a0,(a6)+        ; Store bitmap pointers on the stack
  384.     move.l    a1,(a6)+        ;     
  385. cmultx:
  386.     addq.l    #4,d4            ; Bump bitplane pointers
  387.     addq.l    #4,d5            ;
  388.     dbf    d6,cmultlp        ; Repeat for remaining bitplanes
  389.     addq.l    #2,sp            ; Pop plane mask from stack
  390. ;
  391. ;    Now copy all the bitmaps we accumulated on the stack. There will be
  392. ;    between 1 and 8 of them. We copy them in groups of 1 to 4, so two
  393. ;    operations may be required.
  394. ;
  395. ;    A quick recap on what the various registers contain:
  396. ;
  397. ;        D0 - Number of rows to copy
  398. ;        D1 - Mask for left edge of bitmap
  399. ;        D2 - Mask for right edge of bitmap
  400. ;        D3 - Number of longwords _between_ left edge and right edge
  401. ;        D7 - Total number of bitplanes copied (including 0 & -1 ptrs)
  402. ;        A4 - Modulo of source bitplanes
  403. ;        A5 - Modulo of dest bitplanes
  404. ;        A6 - Points to end of source/dest bitplane pointers
  405. ;        SP - Points to start of source/dest bitplane pointers
  406. ;
  407.     sub.l    sp,a6            ; Calculate how many bitplanes to copy
  408.     move.l    a6,d6            ; Equals half # of source/dest pairs
  409.     lsr.l    #1,d6            ; (giving a range of 0-28)
  410.     subq    #4,d6            ; Adjust to zero based
  411.     bpl.s    cmultx2            ; If negative, no bitplanes to copy
  412.     lea    64(sp),sp        ; so pop bitplane pointers from stack
  413.     bra    doneblt            ; and exit without doing any work
  414. cmultx2:
  415.     cmpi.w    #12,d6            ; More than 4 bitplanes to copy?
  416.     bhi.s    cmult_db        ; If so, skip to do in two goes
  417.     move.l    d3,d3            ; Does bitmap fits in one longword?
  418.     bpl.s    cmult_mm        ; If not, skip to multiple longwords
  419. ;
  420. ;    We have between 1 and 4 bitplanes to copy, each a single
  421. ;    longword wide.
  422. ;
  423.     and.l    d2,d1            ; Create composite mask
  424.     addq    #8,d6            ; Adjust to index CopySingle() entries
  425.     addq    #8,d6            ; and then fall through.
  426. ;
  427. ;    We have between 1 and 4 bitplanes to copy, each at least two
  428. ;    longwords wide.
  429. ;
  430. cmult_mm:
  431.     move.l    FuncTab(pc,d6),a6    ; Else call appropriate routine
  432.     jsr    (a6)            ;
  433.     lea    64(sp),sp        ; Pop everything off the stack
  434.     bra    doneblt            ; And skip to end of blit
  435.  
  436. cmult_db:
  437.     move.l    d3,d3            ; Does bitplane fit in one longword?
  438.     bpl.s    cmult_dbm        ; If not, skip to multiple copy
  439. ;
  440. ;    We have between 5 and 8 bitplanes to copy, each just one
  441. ;    longword wide. Note that when we exit, we branch into the code to
  442. ;    copy the remaining bitmaps, but with the function index pointing
  443. ;    into the CopySingle() entries rather than CopyMultiple()
  444. ;
  445.     and.l    d2,d1            ; Create composite mask
  446.     bsr    Copy4Single        ; Copy first four bitplanes
  447.     bra.s    cmult_dbm2        ; Skip to exit with correct fn index
  448. ;
  449. ;    We have between 5 and 8 bitplanes to copy, each at least two
  450. ;    longwords wide.
  451. ;
  452. cmult_dbm:
  453.     bsr    Copy4Multiple        ; Copy first four bitmaps in one gulp
  454.     subi.w    #16,d6            ; Adjust bitmap count
  455. cmult_dbm2:
  456.     lea    32(sp),sp        ; Pop first four bitmaps off stack
  457.     move.l    FuncTab(pc,d6),a6    ; Copy remaining bitmaps
  458.     jsr    (a6)            ;
  459.     lea    32(sp),sp        ; Pop remaining bitmaps
  460.     bra    doneblt            ; And skip to end of blit
  461.  
  462. ;
  463. ;    Index to table of functions for copying from 1 to 4 multiple and
  464. ;    single longword bitmaps.
  465. ;
  466. FuncTab:
  467.     dc.l    Copy1Multiple,Copy2Multiple,Copy3Multiple,Copy4Multiple
  468.     dc.l    Copy1Single,Copy2Single,Copy3Single,Copy4Single
  469.  
  470. ;
  471. ;    Skip past current bitplane without doing anything to bitplane data
  472. ;    (used when destination bitmap ptr is 0 or -1).
  473. ;
  474. skipfill:
  475.     exg    d4,a0            ; Restore original pointers
  476.     exg    d5,a1            ;
  477.     bra    cmultx            ; Skip back to do next bitplane
  478. ;
  479. ;    Fill bitplane with one's (source bitplane pointer is -1)
  480. ;
  481. fillones:
  482.     exg    d4,a0            ; Restore register order
  483.     exg    d5,a1            ;
  484.     add.l    a3,a1            ; Add in correct offset into bitplane
  485.     bsr    Fill_1s            ; Fill the bitplane
  486.     bra    cmultx            ; Skip back to do next bitplane
  487. ;
  488. ;    Fill bitplane with zero's (source bitplane pointer is NULL)
  489. ;
  490. fillzeros:
  491.     exg    d4,a0            ; Restore register order
  492.     exg    d5,a1            ;
  493.     add.l    a3,a1            ; Add in correct offset into bitplane
  494.     bsr    Fill_0s            ; Fill the bitplane
  495.     bra    cmultx            ; Skip back to do next bitplane
  496. ;
  497. ;    That's it -- we're done! Now just pop remaining values off the stack
  498. ;    and return to the caller with d0 = number of bitplanes copied.
  499. ;
  500. doneblt:
  501.     move.l    d7,d0            ; Set return value = #bitplanes copied
  502.     subq.l    #1,_UsageCount        ; Decrement number of callers in code
  503.     movem.l    (sp)+,d1-d5/d7/a0-a6    ; Restore registers
  504.     move.l    (sp)+,d6        ; And this one too
  505.     rts                ; Return to caller
  506.  
  507. *****************************************************************************
  508. *
  509. *    CopyMultiple()
  510. *
  511. *    The following routines copy from 1 to 4 bitplanes which span more
  512. *    than one longword boundary horizontally (i.e. the start and finish
  513. *    bitplanes are in different longwords).
  514. *
  515. *    The routines are constructed mainly out of macros, to keep the source
  516. *    code down to size (and also more manageable). All routines take the
  517. *    following parameters:
  518. *
  519. *    Input:
  520. *        D0 - Number of rows to copy
  521. *        D1 - Mask for left edge of source    (000xxx)
  522. *        D2 - Mask for right edge of source    (xxx000)
  523. *        D3 - Number of longwords to copy
  524. *            A4 - Modulo of source (positive or negative)
  525. *            A5 - Modulo of destination (positive or negative)
  526. *
  527. *    In addition, pointers to the source/destination bitplanes are pushed
  528. *    onto the stack, such that 4(SP) = src bp1, 8(SP) = dest bp1,
  529. *    12(SP) = src bp2, 16(SP) = dest bp2 etc.
  530. *
  531. *    Output:
  532. *        None
  533. *
  534. *****************************************************************************
  535.  
  536. *****************************************************************************
  537. *
  538. *    Macros used by the copy routines
  539. *
  540. *****************************************************************************
  541.  
  542. ;-----------------------------------------------------------------------------
  543. ;    Init_Mult Label
  544. ;
  545. ;    This macro is the standard entry to each CopyMultiple() routine. It
  546. ;    checks to see whether the bitplane being copied contains at least
  547. ;    one full longword. If not, it branches to a separate routine
  548. ;    (loop?edges) which is smaller; doing this at the start saves having
  549. ;    to check for zero longwords each time through the main loop.
  550. ;    Label is the name of the routine to perform the separate copy.
  551. ;-----------------------------------------------------------------------------
  552.  
  553. Init_Mult macro
  554.     subq.l    #1,d0            ; Convert row count to zero-based
  555.     move.l    d1,d4            ; Copy left source mask
  556.     not.l    d4            ; And change it into destination mask
  557.     move.l    d2,d5            ; Copy right source mask
  558.     not.l    d5            ; Change into destination mask
  559.     subq.l    #1,d3            ; Adjust longword count to zero based
  560.     bmi    \1            ; If none to copy use seperate routine
  561.     endm
  562.  
  563. ;-----------------------------------------------------------------------------
  564. ;    Left_Mult   src,dest
  565. ;
  566. ;    Copies the left hand side of the bitplane from register src to the
  567. ;    bitplane pointed to by dest, using the masks in d1/d4
  568. ;-----------------------------------------------------------------------------
  569.  
  570. Left_Mult macro
  571.     move.l    (\1)+,d6        ; Read leftmost longword of source
  572.     and.l    d1,d6            ; Mask out bits not to be copied
  573.     move.l    (\2),d7            ; Read leftmost longword of dest
  574.     and.l    d4,d7            ; Mask out bits to remain the same
  575.     or.l    d6,d7            ; Merge source and dest columns
  576.     move.l    d7,(\2)+        ; Output first word of bitplane again
  577.     endm
  578.  
  579. ;-----------------------------------------------------------------------------
  580. ;    Copy_Mult src,dest
  581. ;
  582. ;    Copies all the full longwords between the left and right extremities
  583. ;    of the bitplane row from src to dest. Note that for 68010 upwards, it
  584. ;    is faster to copy using MOVE.L/DBF than to play tricks with MOVEM;
  585. ;    since this program will only be of use to systems with fast CPU's
  586. ;    anyway, this is the route we take.
  587. ;-----------------------------------------------------------------------------
  588.  
  589. Copy_Mult macro
  590.     move.l    d3,d6            ; Copy longword count into scratch reg
  591. loop_m\@:
  592.     move.l    (\1)+,(\2)+        ; Copy longwords
  593.     dbf    d6,loop_m\@        ;
  594.     endm
  595.  
  596. ;-----------------------------------------------------------------------------
  597. ;    Right_Mult   src,dest
  598. ;
  599. ;    Copies the right hand side of the bitplane from register src to the
  600. ;    bitplane pointed to by dest, using the masks in d2/d5
  601. ;-----------------------------------------------------------------------------
  602.  
  603. Right_Mult macro
  604.     move.l    (\1)+,d6        ; Read rightmost longword of source
  605.     and.l    d2,d6            ; Mask out bits not being copied
  606.     move.l    (\2),d7            ; Read rightmost longword of dest
  607.     and.l    d5,d7            ; Mask out bits to remain the same
  608.     or.l    d6,d7            ; Merge source and dest columns
  609.     move.l    d7,(\2)+        ; Output right longword again
  610.     endm
  611.  
  612. ;-----------------------------------------------------------------------------
  613. ;    Advance src,dest
  614. ;
  615. ;    This macro advances the source and destination pointers to point to
  616. ;    the next row in the bitplane.
  617. ;-----------------------------------------------------------------------------
  618.  
  619. Advance macro
  620.     add.l    a4,\1            ; Increment source pointer
  621.     add.l    a5,\2            ; Increment dest pointer
  622.     endm
  623.  
  624. ;-----------------------------------------------------------------------------
  625. ;    Copy_Quick src,dest
  626. ;
  627. ;    This macro copies the left and right edges in one go, when there
  628. ;    are no complete longwords in between. It's quicker than having to
  629. ;    check for zero longwords each time through the main loop. The masks
  630. ;    used are d1/d4 for the left edge of the bitplane, d2/d5 for the
  631. ;    right edge.
  632. ;-----------------------------------------------------------------------------
  633.  
  634. Copy_Quick macro
  635.     move.l    (\1)+,d6        ; Read leftmost longword of source
  636.     and.l    d1,d6            ; Mask out bits not to be copied
  637.     move.l    (\2),d7            ; Read leftmost longword of dest
  638.     and.l    d4,d7            ; Mask out bits to remain the same
  639.     or.l    d6,d7            ; Merge source and dest columns
  640.     move.l    d7,(\2)+        ; Output first word of bitplane again
  641. ;
  642. ;    Now tidy up right hand edge of bitplane
  643. ;
  644.     move.l    (\1)+,d6        ; Read rightmost longword of source
  645.     and.l    d2,d6            ; Mask out bits not being copied
  646.     move.l    (\2),d7            ; Read rightmost longword of dest
  647.     and.l    d5,d7            ; Mask out bits to remain the same
  648.     or.l    d6,d7            ; Merge source and dest columns
  649.     move.l    d7,(\2)+        ; Output right longword again
  650.     endm
  651.  
  652. *****************************************************************************
  653. *
  654. *    The actual copy routines, Copy1Multiple() ... Copy4Multiple()
  655. *
  656. *****************************************************************************
  657.  
  658. ;-----------------------------------------------------------------------------
  659. ;
  660. ;    Copies a single bitplane
  661. ;
  662. ;-----------------------------------------------------------------------------
  663.  
  664. Copy1Multiple:
  665.     movem.l    a0-a1/a6/d0-d7,-(sp)    ; Save registers
  666.     lea.l        48(sp),a6    ; Get pointer to stack
  667.     move.l        (a6)+,a0    ; Read bitplane pointers from stack
  668.     move.l        (a6)+,a1    ; Read bitplane pointers from stack
  669.     Init_Mult    Copy1Quick    ; Setup registers
  670. c1m_loop:
  671.     Left_Mult    a0,a1        ; Copy left edge of bitplane
  672.     Copy_Mult    a0,a1        ; Copy middle of bitplane
  673.     Right_Mult    a0,a1        ; Copy right edge of bitplane
  674.     Advance        a0,a1        ; Increment bitplane ptrs
  675.     dbf        d0,c1m_loop    ; Repeat for remaining rows
  676.     movem.l    (sp)+,a0-a1/a6/d0-d7    ; Restore registers
  677.     rts                ; Return to caller
  678. ;
  679. ;    Handle inner longword count of zero
  680. ;
  681. Copy1Quick:
  682.     Copy_Quick    a0,a1        ; Copy left/right edge of bitplane
  683.     Advance        a0,a1        ; Increment bitplane ptrs
  684.     dbra        d0,Copy1Quick    ; Repeat for all rows
  685.     movem.l    (sp)+,a0-a1/a6/d0-d7    ; Restore registers
  686.     rts                ; Return to caller
  687.  
  688. ;-----------------------------------------------------------------------------
  689. ;
  690. ;    Copies 2 bitplanes simultaneously
  691. ;
  692. ;-----------------------------------------------------------------------------
  693.  
  694. Copy2Multiple:
  695.     movem.l    a0-a3/a6/d0-d7,-(sp)    ; Save registers
  696.     lea.l        56(sp),a6    ; Get pointer to bitplanes
  697.     movem.l        (a6),a0-a3    ; Load bitplane ptrs off stack
  698.     Init_Mult    Copy2Quick    ; Setup registers
  699. c2m_loop:
  700.     Left_Mult    a0,a1        ; Copy left edge of bitplane 1
  701.     Left_Mult    a2,a3        ; Copy left edge of bitplane 2
  702.     Copy_Mult    a0,a1        ; Copy middle of bitplane 1
  703.     Copy_Mult    a2,a3        ; Copy middle of bitplane 2
  704.     Right_Mult    a0,a1        ; Copy right edge of bitplane 1
  705.     Right_Mult    a2,a3        ; Copy right edge of bitplane 2
  706.     Advance        a0,a1        ; Increment bitplane 1 ptrs
  707.     Advance        a2,a3        ; Increment bitplane 2 ptrs
  708.     dbf        d0,c2m_loop    ; Repeat for remaining rows
  709.     movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  710.     rts                ; Return to caller
  711. ;
  712. ;    Handle inner longword count of zero
  713. ;
  714. Copy2Quick:
  715.     Copy_Quick    a0,a1        ; Copy left/right edge of bitplane 1
  716.     Copy_Quick    a2,a3        ; Copy left/right edge of bitplane 2
  717.     Advance        a0,a1        ; Increment bitplane 1 ptrs
  718.     Advance        a2,a3        ; Increment bitplane 2 ptrs
  719.     dbra        d0,Copy2Quick    ; Repeat for all rows
  720.     movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  721.     rts                ; Return to caller
  722.  
  723. ;-----------------------------------------------------------------------------
  724. ;
  725. ;    Copies 3 bitplanes simultaneously
  726. ;
  727. ;-----------------------------------------------------------------------------
  728.  
  729. Copy3Multiple:
  730.     movem.l    a0-a3/a6/d0-d7,-(sp)    ; Save registers
  731.     lea.l        56(sp),a6    ; Get pointer to bitplanes
  732.     movem.l        (a6)+,a0-a3    ; Load bitplane ptrs 1 & 2 off stack
  733.     Init_Mult    Copy3Quick    ; Setup registers
  734. c3m_loop:
  735.     Left_Mult    a0,a1        ; Copy left edge of bitplane 1
  736.     Left_Mult    a2,a3        ; Copy left edge of bitplane 2
  737.     Copy_Mult    a0,a1        ; Copy middle of bitplane 1
  738.     Copy_Mult    a2,a3        ; Copy middle of bitplane 2
  739.     Right_Mult    a0,a1        ; Copy right edge of bitplane 1
  740.     Right_Mult    a2,a3        ; Copy right edge of bitplane 2
  741.     Advance        a0,a1        ; Increment bitplane 1 ptrs
  742.     Advance        a2,a3        ; Increment bitplane 2 ptrs
  743.     move.l        a3,-(sp)    ; Save bitplane 2 ptrs
  744.     move.l        a2,-(sp)    ;
  745.     move.l        (a6)+,a2    ; Load bitplane 3 ptrs
  746.     move.l        (a6),a3        ; 
  747.     Left_Mult    a2,a3        ; Copy left edge of bitplane 3
  748.     Copy_Mult    a2,a3        ; Copy middle of bitplane 3
  749.     Right_Mult    a2,a3        ; Copy right edge of bitplane 3
  750.     Advance        a2,a3        ; Increment bitplane 3 ptrs
  751.     move.l        a3,(a6)        ; Save bitplane 3 ptrs
  752.     move.l        a2,-(a6)    ;
  753.     move.l        (sp)+,a2    ; Restore bitplane 2 ptrs
  754.     move.l        (sp)+,a3    ;
  755.     dbf        d0,c3m_loop    ; Repeat for remaining rows
  756.     movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  757.     rts                ; Return to caller
  758. ;
  759. ;    Handle inner longword count of zero
  760. ;
  761. Copy3Quick:
  762.     Copy_Quick    a0,a1        ; Copy left/right edge of bitplane 1
  763.     Copy_Quick    a2,a3        ; Copy left/right edge of bitplane 2
  764.     Advance        a0,a1        ; Increment bitplane 1 ptrs
  765.     Advance        a2,a3        ; Increment bitplane 2 ptrs
  766.     move.l        a3,-(sp)    ; Save bitplane 2 ptrs
  767.     move.l        a2,-(sp)    ;
  768.     move.l        (a6)+,a2    ; Load bitplane 3 ptrs
  769.     move.l        (a6),a3        ; 
  770.     Copy_Quick    a2,a3        ; Copy left/right edge of bitplane 2
  771.     Advance        a2,a3        ; Increment bitplane 2 ptrs
  772.     move.l        a3,(a6)        ; Save bitplane 3 ptrs
  773.     move.l        a2,-(a6)    ;
  774.     move.l        (sp)+,a2    ; Restore bitplane 2 ptrs
  775.     move.l        (sp)+,a3    ;
  776.     dbra        d0,Copy3Quick    ; Repeat for all rows
  777.     movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  778.     rts                ; Return to caller
  779.  
  780. ;-----------------------------------------------------------------------------
  781. ;
  782. ;    Copies 4 bitplanes simultaneously
  783. ;
  784. ;-----------------------------------------------------------------------------
  785.  
  786. Copy4Multiple:
  787.     movem.l    a0-a3/a6/d0-d7,-(sp)    ; Save registers
  788.     lea.l        56(sp),a6    ; Get pointer to bitplanes
  789.     movem.l        (a6)+,a0-a3    ; Load bitplane ptrs 1 & 2 off stack
  790.     Init_Mult    Copy4Quick    ; Setup registers
  791. c4m_loop:
  792.     Left_Mult    a0,a1        ; Copy left edge of bitplane 1
  793.     Left_Mult    a2,a3        ; Copy left edge of bitplane 2
  794.     Copy_Mult    a0,a1        ; Copy middle of bitplane 1
  795.     Copy_Mult    a2,a3        ; Copy middle of bitplane 2
  796.     Right_Mult    a0,a1        ; Copy right edge of bitplane 1
  797.     Right_Mult    a2,a3        ; Copy right edge of bitplane 2
  798.     Advance        a0,a1        ; Increment bitplane 1 ptrs
  799.     Advance        a2,a3        ; Increment bitplane 2 ptrs
  800.     movem.l        a0-a3,-(sp)    ; Save bitplane 2 ptrs
  801.     movem.l        (a6),a0-a3    ; Load bitplane 3 ptrs
  802.     Left_Mult    a0,a1        ; Copy left edge of bitplane 1
  803.     Left_Mult    a2,a3        ; Copy left edge of bitplane 2
  804.     Copy_Mult    a0,a1        ; Copy middle of bitplane 1
  805.     Copy_Mult    a2,a3        ; Copy middle of bitplane 2
  806.     Right_Mult    a0,a1        ; Copy right edge of bitplane 1
  807.     Right_Mult    a2,a3        ; Copy right edge of bitplane 2
  808.     Advance        a0,a1        ; Increment bitplane 1 ptrs
  809.     Advance        a2,a3        ; Increment bitplane 2 ptrs
  810.     movem.l        a0-a3,(a6)    ; Save bitplane 3 ptrs
  811.     movem.l        (sp)+,a0-a3    ; Restore bitplane 2 ptrs
  812.     dbf        d0,c4m_loop    ; Repeat for remaining rows
  813.     movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  814.     rts                ; Return to caller
  815. ;
  816. ;    Handle inner longword count of zero
  817. ;
  818. Copy4Quick:
  819.     Copy_Quick    a0,a1        ; Copy left/right edge of bitplane 1
  820.     Copy_Quick    a2,a3        ; Copy left/right edge of bitplane 2
  821.     Advance        a0,a1        ; Increment bitplane 1 ptrs
  822.     Advance        a2,a3        ; Increment bitplane 2 ptrs
  823.     movem.l        a0-a3,-(sp)    ; Save bitplane 1,2 ptrs
  824.     movem.l        (a6),a0-a3    ; Load bitplane 3,4 ptrs
  825.     Copy_Quick    a0,a1        ; Copy left/right edge of bitplane 3
  826.     Copy_Quick    a2,a3        ; Copy left/right edge of bitplane 4
  827.     Advance        a0,a1        ; Increment bitplane 3 ptrs
  828.     Advance        a2,a3        ; Increment bitplane 4 ptrs
  829.     movem.l        a0-a3,(a6)    ; Save bitplane 3,4 ptrs
  830.     movem.l        (sp)+,a0-a3    ; Restore bitplane 1,2 ptrs
  831.     dbra        d0,Copy4Quick    ; Repeat for all rows
  832.     movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  833.     rts                ; Return to caller
  834.  
  835. *****************************************************************************
  836. *
  837. *    CopySingle()
  838. *
  839. *    The following routines copy from 1 to 4 bitplanes that start and end
  840. *    (horizontally) within a single longword. CopyMultiple can't be used
  841. *    for such cases, since it always copies at least two longwords (one
  842. *    for the left edge and one for the right).
  843. *
  844. *    Input:
  845. *        D0 - Number of rows to copy
  846. *        D1 - Mask of bits to be copied from source  (000xxx000)
  847. *        A4 - Modulo of source bitplane
  848. *        A5 - Modulo of dest bitplane
  849. *
  850. *    In addition, pointers to the source/destination bitplanes are pushed
  851. *    onto the stack, such that 4(SP) = src bp1, 8(SP) = dest bp1,
  852. *    12(SP) = src bp2, 16(SP) = dest bp2 etc.
  853. *
  854. *    Output:
  855. *        None
  856. *
  857. *****************************************************************************
  858.  
  859. *****************************************************************************
  860. *
  861. *    Macros used by the copy routines
  862. *
  863. *****************************************************************************
  864.  
  865. ;-----------------------------------------------------------------------------
  866. ;    Init_Sing
  867. ;
  868. ;    This macro is the standard entry to each CopySingle() routine. It
  869. ;    creates the complement mask used for masking source/destination
  870. ;    and adjusts the row counter to be zero based.
  871. ;-----------------------------------------------------------------------------
  872.  
  873. Init_Sing macro
  874.     subq.l    #1,d0            ; Adjust row count to zero-based
  875.     move.l    d1,d2            ; Copy mask
  876.     not.l    d2            ; And make mask for dest bitplane
  877.     endm
  878.  
  879. ;-----------------------------------------------------------------------------
  880. ;    Copy_Dual src,dest
  881. ;
  882. ;    Copies the source longword from src to dest, masked with the value
  883. ;    in D2/D4
  884. ;-----------------------------------------------------------------------------
  885.  
  886. Copy_Dual macro
  887.     move.l    (\1)+,d3        ; Read src word
  888.     and.l    d1,d3            ; Mask out unwanted bits
  889.     move.l    (\2),d4            ; Read dest word
  890.     and.l    d2,d4            ; Mask out bits to be replaced
  891.     or.l    d3,d4            ; Combine src and dest bits
  892.     move.l    d4,(\2)+        ; Replace destination word
  893.     endm
  894.  
  895. *****************************************************************************
  896. *
  897. *    The actual copy routines, Copy1Single() ... Copy4Single()
  898. *
  899. *****************************************************************************
  900.  
  901. ;-----------------------------------------------------------------------------
  902. ;
  903. ;    Copies a single bitplane one longword wide
  904. ;
  905. ;-----------------------------------------------------------------------------
  906.  
  907. Copy1Single:
  908.     movem.l    a0-a1/a6/d0-d4,-(sp)    ; Save registers
  909.     lea        36(sp),a6    ; Get pointer to bitplane
  910.     move.l        (a6)+,a0    ; Get bitplane pointers into registers
  911.     move.l        (a6),a1        ;
  912.     Init_Sing            ; Initialise masks etc.
  913. copy1slp:
  914.     Copy_Dual    a0,a1        ; Copy longword
  915.     Advance        a0,a1        ; Move to next longword
  916.     dbra        d0,copy1slp    ; Repeat for all rows
  917.     movem.l    (sp)+,a0-a1/a6/d0-d4    ; Restore registers
  918.     rts
  919.  
  920. ;-----------------------------------------------------------------------------
  921. ;
  922. ;    Copies two bitplanes, each one longword wide
  923. ;
  924. ;-----------------------------------------------------------------------------
  925.  
  926. Copy2Single:
  927.     movem.l    a0-a3/a6/d0-d4,-(sp)    ; Save registers
  928.     lea        44(sp),a6    ; Get ptr to bitplane
  929.     movem.l        (a6)+,a0-a3    ; Get bitplane ptrs into registers
  930.     Init_Sing            ; Initialise masks etc.
  931. copy2slp:
  932.     Copy_Dual    a0,a1        ; Copy longword for bitplane 1
  933.     Copy_Dual    a2,a3        ; Copy longword for bitplane 2
  934.     Advance        a0,a1        ; Advance bitplane 1 ptrs
  935.     Advance        a2,a3        ; Advance bitplane 2 ptrs
  936.     dbra        d0,copy2slp    ; Repeat for all rows
  937.     movem.l    (sp)+,a0-a3/a6/d0-d4    ; Restore registers
  938.     rts
  939.  
  940. ;-----------------------------------------------------------------------------
  941. ;
  942. ;    Copies three bitplanes, each one longword wide
  943. ;
  944. ;-----------------------------------------------------------------------------
  945.  
  946. Copy3Single:
  947.     movem.l    a0-a3/a6/d0-d4,-(sp)    ; Save registers
  948.     lea        44(sp),a6    ; Get pointer to bitplane
  949.     movem.l        (a6)+,a0-a3    ; Get bitplane ptrs into registers
  950.     Init_Sing            ; Initialise masks etc.
  951. copy3slp:
  952.     Copy_Dual    a0,a1        ; Copy longword for bitplane 1
  953.     Copy_Dual    a2,a3        ; Copy longword for bitplane 2
  954.     Advance        a0,a1        ; Advance bitplane 1 ptrs
  955.     Advance        a2,a3        ; Advance bitplane 2 ptrs
  956.     move.l        a1,-(sp)    ; Save bitplane 2 ptrs
  957.     move.l        a0,-(sp)    ;
  958.     move.l        (a6)+,a0    ; Load bitplane 3 ptrs
  959.     move.l        (a6),a1        ; 
  960.     Copy_Dual    a0,a1        ; Copy longword for bitplane 3
  961.     Advance        a0,a1        ; Advance bitplane 3 ptrs
  962.     move.l        a1,(a6)        ; Save bitplane 3 ptrs
  963.     move.l        a0,-(a6)    ;
  964.     move.l        (sp)+,a0    ; Restore bitplane 2 ptrs
  965.     move.l        (sp)+,a1    ;
  966.     dbra        d0,copy3slp    ; Repeat for all rows
  967.     movem.l    (sp)+,a0-a3/a6/d0-d4    ; Restore registers
  968.     rts
  969.  
  970. ;-----------------------------------------------------------------------------
  971. ;
  972. ;    Copies four bitplanes, each one longword wide
  973. ;
  974. ;-----------------------------------------------------------------------------
  975.  
  976. Copy4Single:
  977.     movem.l    a0-a3/a6/d0-d4,-(sp)    ; Save registers
  978.     lea        44(sp),a6    ; Get pointer to bitplane pointers
  979.     movem.l        (a6)+,a0-a3    ; Get bitplane pointers into registers
  980.     Init_Sing            ; Initialise masks etc.
  981. copy4slp:
  982.     Copy_Dual    a0,a1        ; Copy longword for bitplane 1
  983.     Copy_Dual    a2,a3        ; Copy longword for bitplane 2
  984.     Advance        a0,a1        ; Advance bitplane 1 ptrs
  985.     Advance        a2,a3        ; Advance bitplane 2 ptrs
  986.     movem.l        a0-a3,-(sp)    ; Save bitplane 1 and 2 ptrs on stack
  987.     movem.l        (a6),a0-a3    ; Read bitplane 3 and 4 ptrs
  988.     Copy_Dual    a0,a1        ; Copy longword for bitplane 3
  989.     Copy_Dual    a2,a3        ; Copy longword for bitplane 4
  990.     Advance        a0,a1        ; Advance bitplane 3 ptrs
  991.     Advance        a2,a3        ; Advance bitplane 4 ptrs
  992.     movem.l        a0-a3,(a6)    ; Save bitplane 3 and 4 ptrs
  993.     movem.l        (sp)+,a0-a3    ; Restore bitplane 1 and 2 ptrs
  994.     dbra        d0,copy4slp    ; Repeat for all rows
  995.     movem.l    (sp)+,a0-a3/a6/d0-d4    ; Restore registers
  996.     rts
  997.  
  998. *****************************************************************************
  999. *
  1000. *    Fill_1s(), Fill_0s
  1001. *
  1002. *    Handles the case new for Workbench 2.0 where the source bitplane
  1003. *    pointer points to an array of all ones (ptr = $FFFFFFFF) or all
  1004. *    zeros ($ptr = $00000000).
  1005. *
  1006. *        Input:
  1007. *        D0 - Number of rows to copy
  1008. *        D1 - Mask for left edge of source    (000xxx)
  1009. *        D2 - Mask for right edge of source    (xxx000)
  1010. *        D3 - Number of longwords to copy (-1 means single column)
  1011. *        A1 - Pointer to dest bitplane
  1012. *        A5 - Modulo of dest bitplane
  1013. *
  1014. *        Output:
  1015. *        None
  1016. *
  1017. *****************************************************************************
  1018.  
  1019. Fill_1s:
  1020.     movem.l    d0/d3/d6-d7/a1,-(sp)    ; Save registers
  1021.     moveq.l    #-1,d7            ; Set register ready for fills
  1022.     subq.l    #1,d0            ; Adjust row count to zero-based
  1023.     move.l    d3,d3            ; Check how many longwords to copy
  1024.     bmi.s    Fill_1single        ; Branch if only a single longword
  1025.     subq    #1,d3            ; Adjust longword count to zero based
  1026.     bmi.s    Fill_1quick        ; If no complete longwords, handle
  1027. ;
  1028. ;    We have more than two longwords to copy, so loop over them all.
  1029. ;
  1030. fill_1lp1:
  1031.     or.l    d1,(a1)+        ; Set bits on left edge of bitplane
  1032.     move.l    d3,d6            ; Get number of longwords to fill
  1033. fill_1lp2:
  1034.     move.l    d7,(a1)+        ; Fill all the longwords
  1035.     dbra    d6,fill_1lp2        ;
  1036.     or.l    d2,(a1)+        ; Set bits on right edge of bitplane
  1037.     add.l    a5,a1            ; Advance to next bitplane row
  1038.     dbra    d0,fill_1lp1        ; And repeat until done
  1039.     movem.l    (sp)+,d0/d3/d6-d7/a1    ; Restore registers
  1040.     rts                ; Return to caller
  1041. ;
  1042. ;    Only two longwords to copy, the left and right edges
  1043. ;
  1044. Fill_1quick:
  1045.     or.l    d1,(a1)+        ; Set bits on left edge of bitplane
  1046.     or.l    d2,(a1)+        ; Set bits on right edge of bitplane
  1047.     add.l    a5,a1            ; Move to next row
  1048.     dbra    d0,Fill_1quick        ; Repeat for all rows
  1049.     movem.l    (sp)+,d0/d3/d6-d7/a1    ; Restore registers
  1050.     rts                ; Return to caller
  1051. ;
  1052. ;    Only a single longword to copy, with left and right portions masked
  1053. ;
  1054. Fill_1single:
  1055.     move.l    d1,d6            ; Create new mask
  1056.     and.l    d2,d6            ; by combining left and right masks
  1057. Fill_1s2:
  1058.     or.l    d6,(a1)+        ; Fill longword
  1059.     add.l    a5,a1            ; Advance to next row
  1060.     dbra    d0,Fill_1s2        ; Repeat for all rows
  1061.     movem.l    (sp)+,d0/d3/d6-d7/a1    ; Restore registers
  1062.     rts                ; Return to caller
  1063.  
  1064. ;-----------------------------------------------------------------------------
  1065. ;    Clear bitplane with zeros
  1066. ;-----------------------------------------------------------------------------
  1067.  
  1068. Fill_0s:
  1069.     movem.l    d0-d3/d6-d7/a1,-(sp)    ; Save registers
  1070.     not.l    d1            ; Invert masks ready for AND
  1071.     not.l    d2            ;
  1072.     moveq.l    #0,d7            ; Clear register ready for fills
  1073.     subq.l    #1,d0            ; Adjust row count to zero-based
  1074.     move.l    d3,d3            ; Check how many longwords to copy
  1075.     bmi.s    Fill_0single        ; Branch if only a single longword
  1076.     subq    #1,d3            ; Adjust longword count to zero based
  1077.     bmi.s    Fill_0quick        ; If no complete longwords, handle
  1078. ;
  1079. ;    We have more than two longwords to copy, so loop over them all.
  1080. ;
  1081. fill_0lp1:
  1082.     and.l    d1,(a1)+        ; Set bits on left edge of bitplane
  1083.     move.l    d3,d6            ; Get number of longwords to fill
  1084. fill_0lp2:
  1085.     move.l    d7,(a1)+        ; Fill all the longwords
  1086.     dbra    d6,fill_0lp2        ;
  1087.     and.l    d2,(a1)+        ; Set bits on right edge of bitplane
  1088.     add.l    a5,a1            ; Advance to next bitplane row
  1089.     dbra    d0,fill_0lp1        ; And repeat until done
  1090.     movem.l    (sp)+,d0-d3/d6-d7/a1    ; Restore registers
  1091.     rts                ; Return to caller
  1092. ;
  1093. ;    Only two longwords to copy, the left and right edges
  1094. ;
  1095. Fill_0quick:
  1096.     and.l    d1,(a1)+        ; Clear left edge of bitplane
  1097.     and.l    d2,(a1)+        ; Clear right edge of bitplane
  1098.     add.l    a5,a1            ; Move to next row
  1099.     dbra    d0,Fill_0quick        ; Repeat for all rows
  1100.     movem.l    (sp)+,d0-d3/d6-d7/a1    ; Restore registers
  1101.     rts                ; Return to caller
  1102. ;
  1103. ;    Only a single longword to copy, with left and right portions masked
  1104. ;
  1105. Fill_0single:
  1106.     move.l    d1,d6            ; Combine left and right edges
  1107.     or.l    d2,d6            ; to create new mask
  1108. Fill_0s2:
  1109.     and.l    d6,(a1)+        ; Fill longword
  1110.     add.l    a5,a1            ; Advance to next row
  1111.     dbra    d0,Fill_0s2        ; Repeat for all rows
  1112.     movem.l    (sp)+,d0-d3/d6-d7/a1    ; Restore registers
  1113.     rts                ; Return to caller
  1114.  
  1115. *****************************************************************************
  1116. *
  1117. *    These two tables give the mask values used when copying the
  1118. *    bits at the edge of each bitplane row. Note that a right edge
  1119. *    of zero bits in width is handled as a special case in the code
  1120. *    (it gets converted to a bitmap which is one longword narrower
  1121. *    but has a right edge 32 bits wide).
  1122. *
  1123. *****************************************************************************
  1124.  
  1125. LeftMask:
  1126.     dc.l    $ffffffff,$7fffffff,$3fffffff,$1fffffff
  1127.     dc.l    $0fffffff,$07ffffff,$03ffffff,$01ffffff
  1128.     dc.l    $00ffffff,$007fffff,$003fffff,$001fffff
  1129.     dc.l    $000fffff,$0007ffff,$0003ffff,$0001ffff
  1130.     dc.l    $0000ffff,$00007fff,$00003fff,$00001fff
  1131.     dc.l    $00000fff,$000007ff,$000003ff,$000001ff
  1132.     dc.l    $000000ff,$0000007f,$0000003f,$0000001f
  1133.     dc.l    $0000000f,$00000007,$00000003,$00000001
  1134.  
  1135. RightMask:
  1136.     dc.l    $ffffffff,$80000000,$c0000000,$e0000000
  1137.     dc.l    $f0000000,$f8000000,$fc000000,$fe000000
  1138.     dc.l    $ff000000,$ff800000,$ffc00000,$ffe00000
  1139.     dc.l    $fff00000,$fff80000,$fffc0000,$fffe0000
  1140.     dc.l    $ffff0000,$ffff8000,$ffffc000,$ffffe000
  1141.     dc.l    $fffff000,$fffff800,$fffffc00,$fffffe00
  1142.     dc.l    $ffffff00,$ffffff80,$ffffffc0,$ffffffe0
  1143.     dc.l    $fffffff0,$fffffff8,$fffffffc,$fffffffe
  1144.  
  1145.  
  1146. *****************************************************************************
  1147. *
  1148. *    Variables used by the code. _UsageCount is only ever updated
  1149. *    atomically (since the replacement code must be re-entrant), and
  1150. *    _BlitFunc is initialised by the startup code.
  1151. *
  1152. *****************************************************************************
  1153.  
  1154.     SECTION Scroll,DATA
  1155.  
  1156.     cnop    0,4
  1157.  
  1158. _UsageCount:    dc.l    -1        ; Number of callers currently in code
  1159. _BlitFunc:    dc.l    _StartBlit    ; Address of function for blitter test
  1160. _OnlySingle:    dc.l    0        ; Only use CPU when src bm == dest bm?
  1161. _Broken:    dc.l    0        ; Accomodate broken software?
  1162. _MinTaskPri:    dc.b    0        ; Ignore tasks with pri <= this
  1163. Pad        dc.b    0,0,0        ; Padding to round to LW boundary
  1164.  
  1165.     END
  1166.  
  1167.