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