home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 073.lha / XText / xtext.asm < prev    next >
Assembly Source File  |  1987-06-02  |  23KB  |  603 lines

  1.  
  2. * *** xtext.asm *************************************************************
  3. *
  4. * XText  --  The XText Routine
  5. * (from the FastText algorithms created in January, 1986)
  6. *   from Book 1 of the Amiga Programmers' Suite by RJ Mical
  7. *
  8. * Copyright (C) 1986, 1987, Robert J. Mical
  9. * All Rights Reserved.
  10. *
  11. * Created for Amiga developers.
  12. * Any or all of this code can be used in any program as long as this
  13. * entire copyright notice is retained, ok?  Thanks.
  14. *
  15. * HISTORY       Name             Description
  16. * ------------  ---------------  -------------------------------------------
  17. * 27 Oct 86     RJ Mical >:-{)*  Translated this file.
  18. *
  19. * ***************************************************************************
  20.  
  21.         INCLUDE "xtext.i"
  22.  
  23.  
  24.         IFND    AZTEC ; If AZTEC not defined, do it the standard way
  25.         XDEF    _XText
  26.         XREF    _custom
  27.         XREF    _GfxBase
  28.         ENDC
  29.         IFD     AZTEC ; If AZTEC defined, do it the non-standard way (sigh)
  30.         PUBLIC  _XText
  31.         PUBLIC  _custom
  32.         PUBLIC  _GfxBase
  33.         ENDC
  34.  
  35.  
  36.  
  37. _XText:
  38. * ***************************************************************************
  39. * These FastText algorithms were created by =Robert J. Mical= in January 1986
  40. * Copyright (C) 1986, =Robert J. Mical=
  41. * All Rights Reserved
  42. *
  43. * This is my brute-force XText() routine.
  44. * It presumes many things about text:  that the characters come in
  45. * pairs, that the characters are 8-bits wide (this one is not easily 
  46. * undone), and more.
  47. *
  48. * The theory of operation here is that I will build a single plane of
  49. * normal characters (character data bits set, background bits clear)
  50. * in the Normal Text Plane, using the data from the Output Characters
  51. * Buffer.  As needed, I will invert this plane (character bits clear,
  52. * background bits set) into the Inverted Text Plane.  There's two other
  53. * globally accessible (pre-initialized) planes used:  an AllClearPlane plane
  54. * of all bits clear, and an AllSetPlane plane of all bits set.
  55. *
  56. * Using these four planes, I can construct a bitmap of all possible pen
  57. * settings for the foreground and background.  If corresponding bits
  58. * in the FgPen and BgPen are:
  59. *        -----      -----
  60. *          0       0        Use All Clear Plane
  61. *          0       1        Use Inverted Text Plane
  62. *          1       0        Use Normal Text Plane
  63. *          1       1        Use All Set Plane
  64. *
  65. * Note that if FgPen and BgPen are equal, I don't have to bother
  66. * constructing the Normal or Inverted Text Planes, since they'll
  67. * never be used.
  68. *
  69. * An optimization that evolves out of this fact is that you can fill a line
  70. * or part of a line of your text with spaces (blank characters) much more
  71. * quickly by setting the foreground pen equal to the background pen.  The
  72. * trick with this optimization is to not spend too much time detecting
  73. * whether or not an area of text is all blank, for you may lose the
  74. * increased performance during the handling of normal text lines.
  75. *
  76. * A further optimization is that I'm guessing that many text calls
  77. * will not require the inverted plane, so I won't make it until I 
  78. * discover that I need it.  If programmers follow the
  79. * Intuition-encouraged standard of pen 1 for foreground and pen 0
  80. * for background, then the bits are:  FgPen -- 00001
  81. *                                     BgPen -- 00000
  82. * In fact, if the text is *any* color against a background of zero,
  83. * this optimization works.
  84. *
  85. * For example, the plain PC monochrome text turns out to be pen 1 on
  86. * pen 0.  No need to invert here!
  87. *
  88. * So I won't bother constructing the inverted plane until I discover
  89. * that it's needed.  The cost of this is that I have to check a flag
  90. * once per time that I find an inverted bit plane is called for (6 times 
  91. * maximum (though of course Dale would say 8 times maximum)), and the 
  92. * savings is avoiding an unnecessary inversion.
  93. *
  94. * Note that this routine works with character pairs while building the
  95. * buffer.  If you specify an odd number of characters, this routine will 
  96. * round up the character count to the next higher even number, and then 
  97. * build the buffer with that many characters.  However, only the number
  98. * of characters you specify will actually be printed to the screen.
  99. *
  100. * ON ENTRY (on stack):
  101. *       ARG0 = address of the XTextSupport structure
  102. *       ARG1 = address of the text string
  103. *       ARG2 = character count
  104. *       ARG3 = x position for text output
  105. *       ARG4 = y position for text output
  106.  
  107. DREGS EQU       0         ; Offset to the pushed D-Registers
  108. DREGCOUNT EQU   6         ; How many D-Registers were pushed
  109. AREGS EQU       (DREGS+(DREGCOUNT*4)) ; Offset to the pushed A-Registers
  110. AREGCOUNT EQU   5
  111. FRONTPEN EQU    (AREGS+(AREGCOUNT*4))   ; Local variable
  112. BACKPEN  EQU    (FRONTPEN+2)    ; Local variable
  113. DRAWMODE EQU    (BACKPEN+2) ; Local variable
  114. XBLTSIZE EQU    (DRAWMODE+2)
  115. RETADDR  EQU    (XBLTSIZE+2)    ; Our return address
  116. ARG0  EQU       (RETADDR+4) ; Offset to passed arguments
  117. ARG1  EQU       (ARG0+4)
  118. ARG2  EQU       (ARG1+4)
  119. ARG3  EQU       (ARG2+4)
  120. ARG4  EQU       (ARG3+4)
  121.  
  122.  
  123.         LEA     -8(SP),SP               ; Reserve memory for local variables
  124.         MOVEM.L A2-A6/D2-D7,-(SP)
  125.  
  126.  
  127.         MOVE.L  ARG0(SP),A2     ; Get the XTextSupport structure address
  128.         MOVE.L  #_custom,A5     ; Get the address of the custom chip
  129.         MOVE.L  _GfxBase,A6     ; Load up A6 for graphics calls
  130.  
  131.  
  132. * Check the character count.
  133. * If it's zero, then split as there's nothing to do.
  134. * If it's less than zero, this is the signal that the programmer
  135. * wants *us* to figure out how long the string is.  Nice touch, eh?
  136. * If it's greater than zero, then presume it's valid.
  137.         MOVE.W  ARG2+2(SP),D2   ; Get the character count
  138.         BEQ     RETURN          ; and split if there's none to do
  139.         BGT     GOT_TEXT_COUNT  ; If greater than zero, then it's real
  140.  
  141.         MOVE.L  ARG1(SP),A4     ; Address of text string
  142.         MOVEQ.L #-1,D2          ; Start with less than no characters
  143. 10$     ADDQ.W  #1,D2           ; Increment character count
  144.         TST.B   (A4)+           ; Test if next is end of text
  145.         BNE     10$             ; Branch if not
  146.  
  147.         MOVE.W  D2,ARG2+2(SP)   ; Save as character count
  148.  
  149. GOT_TEXT_COUNT:
  150. * The result of the following 3 instructions is created by the 2 below
  151. * I include this commentary to keep things from getting confusing
  152. *  ADDQ  #1,D2   ; to round up
  153. *  LSR.B #1,D2   ; Turn the char count into a pair count
  154. *  SUBQ.W       #1,D2    ; (-1 for DBRA of PAIRLOOP below)
  155.         SUBQ.B  #1,D2
  156.         LSR.B   #1,D2
  157.  
  158.  
  159.         CALLSYS OwnBlitter      ; Get that blitter
  160.  
  161.  
  162. * Get local copies of the pens, jazzed around to take the DrawMode into
  163. * account.  Namely, if JAM1 then the background pen is automatically zero,
  164. * and if the INVERSVID flag is set then swap the foreground/background pens
  165.  
  166.         CLEAR   D3              ; Save them as words
  167.         MOVE.B  xt_FrontPen(A2),D3 ; Load up the local front pen
  168.         CLEAR   D4              ; Start out presuming that back is zero
  169.         MOVE.B  xt_DrawMode(A2),D5 ; Test the draw mode 
  170.         MOVE.B  D5,D6           ; Save a copy
  171.         ANDI.W  #3,D5           ; Strip off INVERSVID (and any other) bit
  172.         MOVE.W  D5,DRAWMODE(SP) ; and save the true drawmode
  173.         CMP.B   #RP_JAM1,D5     ; Is it JAM1?
  174.         BEQ     1$              ; If it's JAM1, leave the local back as zero
  175.         MOVE.B  xt_BackPen(A2),D4 ; else load up the local back pen
  176.  
  177. 1$      ANDI.B  #RP_INVERSVID,D6 ; Was INVERSVID bit set?
  178.         BEQ     2$              ; and skip if not
  179.         EXG     D3,D4           ; else exchange the pen registers
  180.  
  181. 2$
  182.         MOVE.W  D3,FRONTPEN(SP) ; Save the local front pen
  183.         MOVE.W  D4,BACKPEN(SP)  ; Save the local back pen
  184.  
  185.  
  186.         MOVE.W  xt_CharHeight(A2),D6    ; Build the bltsize word
  187.         LSL.W   #6,D6           ; Height is shifted over as blitter likes it
  188.         MOVE.W  D6,XBLTSIZE(SP) ; Save this partial for later
  189.  
  190.  
  191.         CMP.W   D3,D4           ; Are the pens equal?
  192.         BEQ     PLANESET        ; If so, skip building the planes
  193.  
  194.  
  195. * Wait 'til any blitting is done, and then initialize 
  196. * the blitter for my personal use ...
  197.         CALLSYS WaitBlit        ; and wait for that baby to be free!
  198.  
  199.  
  200.         CLEAR   D3
  201.         MOVE.W  D3,bltamod(A5)  ; Set up the SRCA and SRCB modulos
  202.         MOVE.W  D3,bltbmod(A5)
  203.         SUBI.W  #1,D3
  204.         MOVE.W  D3,bltafwm(A5)  ; Masks are all set
  205.         MOVE.W  D3,bltalwm(A5)
  206.  
  207.         CLEAR   D3
  208.         MOVE.B  xt_MaxTextWidth(A2),D3
  209.         SUBQ.W  #2,D3
  210.         MOVE.W  D3,bltdmod(A5)
  211.         MOVE.W  #$0DFC,bltcon0(A5)      ; Use ABD, minterm is A or B, don't
  212.         MOVE.W  #$8000,bltcon1(A5)      ; shift A, shift B by 8
  213.  
  214.         MOVE.L  xt_NormalTextPlane(A2),D3 ; Address of the normal text plane
  215.  
  216.         MOVE.W  xt_FontSelect(A2),D6    ; Get the address of the font data
  217.         LSL.W   #2,D6
  218.         LEA     xt_FontData(A2),A3
  219.         ADD.W   D6,A3
  220.         MOVE.L  (A3),A3
  221.         MOVE.L  ARG1(SP),A4     ; Address of text string
  222.  
  223.         MOVE.W  xt_CharHeight(A2),D7
  224.  
  225.         MOVE.W  xt_Flags(A2),D6 ; Get the Flags
  226.         ANDI    #SLIM_XTEXT,D6  ; and test if the programmer wants SLIM_XTEXT
  227.         BNE     SLIM_CHARS      ; and go build the text the "slim" way if so
  228.                                 ; else we're doing text the faster "fat" way
  229.  
  230.         MOVE.W  XBLTSIZE(SP),D6 ; Get the blit size partial
  231.         ORI     #1,D6           ; and make blit size one word wide
  232.  
  233.         CMPI    #8,D7           ; Can we do fast building?
  234.         BNE     SLOW_PAIRLOOP   ; If not 8, do it the "slow" way
  235.  
  236.  
  237. PAIRLOOP:
  238. * The normal text plane is constructed here.
  239. * Do as much pre-calculating as possible before actually waiting for the
  240. * blitter to be ready for re-use.
  241.  
  242.  
  243.         CLEAR   D4              ; Get the address of the font data of
  244.         MOVE.B  (A4)+,D4        ; the next character
  245.         LSL.W   #4,D4           ; (This presumes that each char is 16 bytes)
  246.         ADD.L   A3,D4
  247.  
  248.         CLEAR   D5              ; Get font data of next in pair (if there's
  249.         MOVE.B  (A4)+,D5        ; not really a second character (odd-numbered
  250.         LSL.W   #4,D5           ; string lengths) then this second move of
  251.         ADD.L   A3,D5           ; data will be unnecessary, but at least is
  252.                                 ; harmless since the buffer is *always*
  253.                                 ; pair-sized and the speed improvement is
  254.                                 ; great when handling two characters at once)
  255.  
  256.         CALLSYS WaitBlit        ; (this is redundant the first time through)
  257.  
  258.         MOVE.L  D4,bltapt(A5)
  259.         MOVE.L  D5,bltbpt(A5)
  260.         MOVE.L  D3,bltdpt(A5)
  261.  
  262.         MOVE.W  D6,bltsize(A5)  ; Bombs away!
  263.  
  264.         ADDQ.L  #2,D3           ; Advance destination pointer to next word
  265.  
  266.         DBRA    D2,PAIRLOOP
  267.  
  268. * Done, so go start setting up the planes 
  269.         BRA     PLANESET
  270.  
  271.  
  272. SLOW_PAIRLOOP:
  273. * The normal text plane is constructed here.
  274. * Done the "slow" way using a MULU because the character height isn't 8.
  275. * Do as much pre-calculating as possible before actually waiting for the
  276. * blitter to be ready for re-use.
  277.  
  278.  
  279.         CLEAR   D4              ; Get the address of the font data of
  280.         MOVE.B  (A4)+,D4        ; the next character
  281.         ADD.W   D4,D4
  282.         MULU    D7,D4           ; Offset * 2 * CharHeight
  283.         ADD.L   A3,D4
  284.  
  285.         CLEAR   D5              ; Get font data of next in pair (if there's
  286.         MOVE.B  (A4)+,D5        ; not really a second character (odd-numbered
  287.         ADD.W   D5,D5           ; string lengths) then this second move of
  288.         MULU    D7,D5
  289.         ADD.L   A3,D5           ; data will be unnecessary, but at least is
  290.                                 ; harmless since the buffer is *always*
  291.                                 ; pair-sized and the speed improvement is
  292.                                 ; great when handling two characters at once)
  293.  
  294.         CALLSYS WaitBlit        ; (this is redundant the first time through)
  295.  
  296.         MOVE.L  D4,bltapt(A5)
  297.         MOVE.L  D5,bltbpt(A5)
  298.         MOVE.L  D3,bltdpt(A5)
  299.  
  300.         MOVE.W  D6,bltsize(A5)  ; Bombs away!
  301.  
  302.         ADDQ.L  #2,D3           ; Advance destination pointer to next word
  303.  
  304.         DBRA    D2,SLOW_PAIRLOOP
  305.  
  306. * Done, so go start setting up the planes 
  307.         BRA     PLANESET
  308.  
  309.  
  310.  
  311. SLIM_CHARS:
  312. * OK, the programmer asked for SLIM_XTEXT, which is the half-size memory 
  313. * buffer for text to be built using the processor rather than the blitter
  314.  
  315.         MOVE.L  A5,-(SP)                ; Save A5 during the SLIM build
  316.  
  317.         CLEAR   D0                      ; Build the byte-size modulo
  318.         MOVE.B  xt_MaxTextWidth(A2),D0
  319.         SUBQ    #1,D0
  320.  
  321.         MOVE.W  D7,D1                   ; Build the line height (-1 for DBRA)
  322.         SUBQ    #1,D1
  323.         CMPI    #8,D7                   ; Can we do fast building?
  324.         BNE     SLIM_SLOW_PAIRLOOP      ; If not 8, do it the "slow" way
  325.  
  326.  
  327. SLIM_PAIRLOOP:
  328. * The normal "slim" text plane is constructed here.
  329.  
  330.         CLEAR   D4              ; Get the address of the font data of
  331.         MOVE.B  (A4)+,D4        ; the next character
  332.         LSL.W   #3,D4           ; (This presumes that each char is 8 bytes)
  333.         ADD.L   A3,D4
  334.         MOVE.L  D4,A0
  335.  
  336.         CLEAR   D5              ; Get font data of next in pair (if there's
  337.         MOVE.B  (A4)+,D5        ; not really a second character (odd-numbered
  338.         LSL.W   #3,D5           ; string lengths) then this second move of
  339.         ADD.L   A3,D5           ; data will be unnecessary, but at least is
  340.         MOVE.L  D5,A1
  341.                                 ; harmless since the buffer is *always*
  342.                                 ; pair-sized and the speed improvement is
  343.                                 ; great when handling two characters at once)
  344.  
  345.         MOVE.W  D1,D6           ; Build the bltsize word
  346.         MOVE.L  D3,A5
  347.  
  348. SLIM_BUILD:
  349.         MOVE.B  (A0)+,(A5)+
  350.         MOVE.B  (A1)+,(A5)
  351.         ADD.L   D0,A5
  352.         DBRA    D6,SLIM_BUILD
  353.  
  354.         ADDQ.L  #2,D3           ; Advance destination pointer to next word
  355.  
  356.         DBRA    D2,SLIM_PAIRLOOP ; Count down the character pairs to print 
  357.  
  358.         MOVE.L (SP)+,A5         ; Restore A5 at end of SLIM_BUILD 
  359.  
  360. * Done, so go start setting up the planes 
  361.         BRA     PLANESET
  362.  
  363.  
  364.  
  365. SLIM_SLOW_PAIRLOOP:
  366. * The normal "slim" text plane is slowly constructed here, slow because 
  367. * the characters are other than 8 lines tall.
  368.  
  369.         CLEAR   D4              ; Get the address of the font data of
  370.         MOVE.B  (A4)+,D4        ; the next character
  371.         MULU    D7,D4
  372.         ADD.L   A3,D4
  373.         MOVE.L  D4,A0
  374.  
  375.         CLEAR   D5              ; Get font data of next in pair (if there's
  376.         MOVE.B  (A4)+,D5        ; not really a second character (odd-numbered
  377.         MULU    D7,D5           ; string lengths) then this second move
  378.         ADD.L   A3,D5           ; will be unnecessary, but at least is
  379.         MOVE.L  D5,A1
  380.                                 ; harmless since the buffer is *always*
  381.                                 ; pair-sized and the speed improvement is
  382.                                 ; great when handling two characters at once)
  383.  
  384.         MOVE.W  D1,D6           ; Build the bltsize word
  385.         MOVE.L  D3,A5
  386.  
  387. SLIM_SLOW_BUILD:
  388.         MOVE.B  (A0)+,(A5)+
  389.         MOVE.B  (A1)+,(A5)
  390.         ADD.L   D0,A5
  391.         DBRA    D6,SLIM_SLOW_BUILD
  392.  
  393.         ADDQ.L  #2,D3           ; Advance destination pointer to next word
  394.  
  395.         DBRA    D2,SLIM_SLOW_PAIRLOOP ; Count down the pairs to print 
  396.  
  397.         MOVE.L (SP)+,A5         ; Restore A5 at end of SLIM_BUILD 
  398.  
  399. * Done, so fall into starting setting up the planes 
  400.  
  401.  
  402.  
  403. PLANESET:
  404. * Well, that was quick, wasn't it.  Here all of the required planes (except
  405. * the bothersome Inverted Text Plane) are ready to go.  So let's figure
  406. * out how to initialize the plane pointers in the BitMap ...
  407.  
  408.         LEA     xt_TextBitMap(A2),A3
  409.         LEA     bm_Planes(A3),A4        ; Get address of first plane pointer
  410.  
  411.         CLEAR   D0                      ; Set up the pen-test mask
  412.         MOVE.W  FRONTPEN(SP),D1         ; Fetch the foreground pen
  413.         MOVE.W  BACKPEN(SP),D2          ; and the background pen
  414.         CLEAR   D3
  415.         MOVE.B  bm_Depth(A3),D3         ; Get the BitMap depth ...
  416.         SUBQ.W  #1,D3                   ; ... and set the loop count for DBRA
  417.         CLEAR   D4                      ; Clear the Inverted flag
  418.  
  419.  
  420. PLANELOOP:
  421. * First, find out if the foreground/background pattern for this plane 
  422. * is 00, 01, 10 or 11.  based on the pattern, select the associated 
  423. * plane pointer for the BitMap
  424.         BTST    D0,D1           ; If the bit is set in the foreground pen
  425.         BNE     PAT_ONE         ; then go process 1x combinations
  426.  
  427. * Else we have a 0x combination.  Which one is it?
  428.         BTST    D0,D2           ; This time test the background pen
  429.         BNE     PAT_01          ; and if set then our pattern is 01
  430.  
  431. PAT_00:
  432.         MOVE.L  xt_AllClearPlane(A2),A3 ; This plane is the 00 plane
  433.         BRA     PLANE_STUFF
  434.  
  435. PAT_01:
  436. * The dreaded Inverse Text Plane selector.  If it doesn't exist yet,
  437. * I have to create it now.
  438.         MOVE.L  xt_InverseTextPlane(A2),A3 ; This plane is the inverse plane
  439.         TST.B   D4              ; Test our Inverted Plane flag
  440.         BNE     PLANE_STUFF     ; and skip this mess if it's already set
  441.                                 ; else we'll have to invert it.
  442.         ADDQ.B  #1,D4           ; Set the inversion flag
  443.  
  444. * OK, so use the blitter inversion algorithm:  Dest = NOT SRC.
  445.  
  446.         CLEAR   D5
  447.         MOVE.B  xt_MaxTextWidth(A2),D5 ; Build the Group-of-2 values:
  448.         MOVE.W  ARG2+2(SP),D6
  449.         ADDQ.W  #1,D6           ; Get the first multiple of 2 that's greater
  450.         ANDI.W  #$FFFE,D6       ; than or equal to the character count, and
  451.         SUB.W   D6,D5           ; subtract that from the total buffer width
  452.                                 ; to make the Group-of-2 row modulo
  453.  
  454.         LSR.W   #1,D6           ; Turn char count into pair count
  455.         OR.W    XBLTSIZE(SP),D6 ; and prepare for starting the blitter
  456.  
  457.         MOVEM.L D0-D1,-(SP)
  458.         CALLSYS WaitBlit        ; Wait for the blitter before I jam it.
  459.         MOVEM.L (SP)+,D0-D1
  460.  
  461.         MOVE.L  xt_NormalTextPlane(A2),bltbpt(A5)
  462.         MOVE.L  A3,bltdpt(A5)
  463.  
  464.         MOVE.W  D5,bltbmod(A5)  ; Set up the SRCB and DEST modulos
  465.         MOVE.W  D5,bltdmod(A5)
  466.  
  467.         MOVE.W  #$0533,bltcon0(A5)
  468.         MOVE.W  #$0000,bltcon1(A5)
  469.  
  470.         MOVE.W  D6,bltsize(A5)  ; Bombs away!
  471.                         
  472.         BRA     PLANE_STUFF
  473.  
  474.  
  475. PAT_ONE:
  476. * We've got a 1x pattern.  Which one do you suppose it is?  Hmm ...
  477.         BTST    D0,D2           ; This time, test the back pen only
  478.         BNE     PAT_11
  479.  
  480.  
  481. PAT_10:
  482. * Normal Text Plane?  No problem.
  483.         MOVE.L  xt_NormalTextPlane(A2),A3
  484.         BRA     PLANE_STUFF
  485.  
  486. PAT_11:
  487.         MOVE.L  xt_AllSetPlane(A2),A3   ; This plane must have all bits set
  488.  
  489. * and fall into ...
  490.  
  491.  
  492. PLANE_STUFF:
  493. * OK, so A3 has the address of this plane's data.  Stuff that baby
  494. * into the BitMap structure.
  495.         MOVE.L  A3,(A4)+
  496.  
  497.         ADDQ    #1,D0           ; Advance our mask to the next position
  498.  
  499.         DBRA    D3,PLANELOOP    ; Loop on the depth of the BitMap
  500.  
  501.  
  502. * Now, all done with the private use of the blitter.  Here, I would prefer
  503. * to retain exclusive use of the blitter even throughout the call to
  504. * BlitBMRP below, but the system won't let me.  Too bad!
  505.  
  506.  
  507.         CALLSYS DisownBlitter
  508.  
  509.  
  510. * Well, now the BitMap is all ready to blast out our new line
  511. * of text.  Wasn't that fun?  Now the simple final stroke:  zap that
  512. * data into the RastPort, using the ever-popular, cleverly-named
  513. * BltBitMapRastPort function (if Dale wasn't so good, I'd suggest
  514. * that we take him out and shoot him for that name).
  515. *
  516. * BlitBMRP wants:
  517. *
  518. * A0 = Source BitMap  
  519. * A1 = Destination RastPort
  520. * A6 = GfxBase
  521. *
  522. * D0 = Source X
  523. * D1 = Source Y
  524. * D2 = Destination X
  525. * D3 = Destination Y
  526. * D4 = Pixel Width of block to be moved
  527. * D5 = Scan-line Height of block to be moved
  528. * D6 = Minterm
  529.  
  530.         CLEAR   D5
  531.         MOVE.W  xt_CharHeight(A2),D5    ; Height of transfer
  532.  
  533.         MOVE.W  #XTEXT_CHARWIDTH,D4     ; Create the blit width ...
  534.         MOVE.W  ARG2+2(SP),D3           ; Character count
  535.         MULU    D3,D4                   ; Width of transfer (creates LONG)
  536.  
  537.         MOVE.L  ARG4(SP),D3             ; Get the Y position into D3
  538.         MOVE.L  ARG3(SP),D2             ; Get the X position into D2
  539.  
  540.         CLEAR   D1                      ; Source x and y are 0
  541.         CLEAR   D0
  542.  
  543.         MOVE.L  xt_OutputRPort(A2),A1   ; and get the RPort of the display
  544.  
  545.         LEA     xt_TextBitMap(A2),A0    ; Get the address of the BitMap arg
  546.  
  547. * The DrawMode defines what minterm we use and which routine we call.
  548.         CMP.W   #RP_JAM1,DRAWMODE(SP)   ; Are we doing JAM1?
  549.         BEQ     DO_JAM1
  550.  
  551. * The DrawMode can be JAM2 or COMPLEMENT.  Which is it, hmm?
  552.         MOVE.L  #$C0,D6                 ; Minterm (simple transfer) for JAM2
  553.         CMP.W   #RP_JAM2,DRAWMODE(SP)   ; Is it really JAM2?
  554.         BEQ     BBMRP                   ; Branch if so
  555.  
  556.         MOVE.L  #$60,D6                 ; Only other is complement mode
  557.  
  558. BBMRP:
  559.         CALLSYS BltBitMapRastPort       ; Do the normal (fast) BBMRP
  560.         BRA     RETURN
  561.  
  562.  
  563. DO_JAM1:
  564. * Call BltMaskBitMapRastPort, which is the same as BBMRP except that a
  565. * mask is used to cookie-cut the source into the destination.
  566. * JAM1 requires a mask, because JAM1 is cookie-cut!
  567. * The mask goes into A2.  If either pen was non-zero then we built 
  568. * the normal plane so use that as the mask,
  569. * else use the AllZeroPlane for the mask (which produces zip imagery!).
  570. * The minterm sez:  cut me in, daddio.
  571.  
  572.         MOVE.B  xt_DrawMode(A2),D6      ; Was this inverse video?
  573.         ANDI.B  #RP_INVERSVID,D6
  574.         BNE     1$                      ; If so, use inverse JAM1 minterm
  575.         MOVE.L  #$E0,D6                 ; else use normal JAM1 minterm
  576.         BRA     2$
  577.  
  578. 1$      MOVE.L  #$B0,D6
  579.  
  580. 2$      TST.W   FRONTPEN(SP)            ; Was the front pen zero?
  581.         BNE     3$                      ; If not then get Normal for mask
  582.         TST.W   BACKPEN(SP)             ; Was the back pen zero?
  583.         BNE     3$                      ; If not then get Normal for mask
  584.         MOVE.L  xt_AllClearPlane(A2),A2 ; AllClearPlane is the mask
  585.         BRA     4$
  586.  
  587. 3$      MOVE.L  xt_NormalTextPlane(A2),A2 ; use the plane as the mask
  588.  
  589. 4$      CALLSYS BltMaskBitMapRastPort   ; Do the not-as-fast BMBMRP
  590.  
  591.  
  592.  
  593. RETURN:
  594.         MOVEM.L (SP)+,A2-A6/D2-D7
  595.         LEA     8(SP),SP                ; Release memory of local variables
  596.  
  597.         RTS
  598.  
  599.  
  600.         END
  601.  
  602.  
  603.