home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 28 / amigaformatcd28.iso / -websites- / amidoom / adoom_src-0.7.lha / ADoom_src / amiga_draw.s < prev    next >
Text File  |  1998-01-16  |  26KB  |  1,285 lines

  1. *
  2. *       amiga_draw.s - optimized rendering
  3. *       by Aki Laukkanen <amlaukka@cc.helsinki.fi>
  4. *
  5. *       This file is public domain.
  6. *
  7.  
  8.         mc68020
  9.         multipass
  10. ;;;        debug    on,lattice4
  11.  
  12. ;;;        include "exec/types.i"
  13.  
  14. SCREENWIDTH    equ    320
  15.  
  16. FUZZTABLE    equ    250
  17. FUZZOFF        equ    SCREENWIDTH
  18.  
  19. FRACBITS    equ    16
  20. FRACUNIT    equ    (1<<FRACBITS)
  21.  
  22. *
  23. *       global functions
  24. *
  25.  
  26.         xdef    _R_DrawColumn_040            ; high detail
  27.         xdef    @R_DrawColumn_040
  28.         xdef    _R_DrawSpan_040
  29.         xdef    @R_DrawSpan_040
  30.         xdef    _R_DrawColumn_060
  31.         xdef    @R_DrawColumn_060
  32.         xdef    _R_DrawSpan_060
  33.         xdef    @R_DrawSpan_060
  34.         xdef    _R_DrawFuzzColumn
  35.         xdef    @R_DrawFuzzColumn
  36. ;;        xdef    _R_DrawTranslatedColumn
  37. ;;        xdef    @R_DrawTranslatedColumn
  38.  
  39.         xdef    _R_DrawSpanLow                ; low detail
  40.         xdef    @R_DrawSpanLow
  41.         xdef    _R_DrawColumnLow
  42.         xdef    @R_DrawColumnLow
  43.         xdef    _R_DrawFuzzColumnLow
  44.         xdef    @R_DrawFuzzColumnLow
  45. ;;        xdef    _R_DrawTranslatedColumnLow
  46. ;;        xdef    @R_DrawTranslatedColumnLow
  47.         
  48. *
  49. *       needed symbols/labels
  50. *
  51.  
  52.         xref    _dc_yl
  53.         xref    _dc_yh
  54.         xref    _dc_x
  55.         xref    _columnofs
  56.         xref    _ylookup
  57.         xref    _dc_iscale
  58.         xref    _centery
  59.         xref    _dc_texturemid
  60.         xref    _dc_source
  61.         xref    _dc_colormap
  62.         xref    _ds_xfrac
  63.         xref    _ds_yfrac
  64.         xref    _ds_x1
  65.         xref    _ds_y
  66.         xref    _ds_x2
  67.         xref    _ds_xstep
  68.         xref    _ds_ystep
  69.         xref    _ds_source
  70.         xref    _ds_colormap
  71.         xref    _fuzzoffset
  72.         xref    _fuzzpos
  73.         xref    _viewheight
  74.         xref    _dc_translation
  75.         xref    _colormaps
  76.  
  77.  
  78. ; low detail drawing functions
  79.  
  80.         cnop    0,4
  81.  
  82. _R_DrawColumnLow
  83. @R_DrawColumnLow
  84.         movem.l d3-d4/d6-d7/a2/a3,-(sp)
  85.  
  86.         move.l  (_dc_yh),d7     ; count = _dc_yh - _dc_yl
  87.         move.l  (_dc_yl),d0
  88.         sub.l   d0,d7
  89.         bmi     .end
  90.  
  91.         move.l  (_dc_x),d1      ; dest = ylookup[_dc_yl] + columnofs[_dc_x]
  92.         lea     (_ylookup),a0
  93.         add.l    d1,d1        ; dc_x <<= 1 
  94.         move.l  (a0,d0.l*4),a0
  95.         lea     (_columnofs),a1
  96.         add.l   (a1,d1.l*4),a0
  97.  
  98.         move.l  (_dc_colormap),d4
  99.         move.l  (_dc_source),a1
  100.  
  101.         move.l  (_dc_iscale),d1 ; frac = _dc_texturemid + (_dc_yl-centery)*fracstep
  102.         sub.l   (_centery),d0
  103.         muls.l  d1,d0
  104.         add.l   (_dc_texturemid),d0
  105.  
  106.         moveq   #$7f,d3
  107.         lea     (SCREENWIDTH*4).w,a3
  108.  
  109. ; d7: cnt >> 2
  110. ; a0: chunky
  111. ; a1: texture
  112. ; d0: frac  (uuuu uuuu uuuu uuuu 0000 0000 0UUU UUUU)
  113. ; d1: dfrac (.......................................)
  114. ; d3: $7f
  115. ; d4: light table aligned to 256 byte boundary
  116. ; a3: SCREENWIDTH
  117.  
  118.         move.l  d7,d6
  119.         and.w   #3,d6
  120.  
  121.         swap    d0              ; swap decimals and fraction
  122.         swap    d1
  123.  
  124.         add.w   (.width_tab,pc,d6.w*2),a0
  125.         lsr.w   #2,d7
  126.         move.w  (.tmap_tab,pc,d6.w*2),d6
  127.  
  128.         and.w   d3,d0
  129.         sub.w   d1,d0
  130.         add.l   d1,d0           ; setup the X flag
  131.  
  132.         jmp     (.loop,pc,d6.w)
  133.  
  134.         cnop    0,4
  135. .width_tab
  136.         dc.w    -3*SCREENWIDTH
  137.         dc.w    -2*SCREENWIDTH
  138.         dc.w    -1*SCREENWIDTH
  139.         dc.w    0
  140. .tmap_tab
  141.         dc.w    .0-.loop
  142.         dc.w    .1-.loop
  143.         dc.w    .2-.loop
  144.         dc.w    .3-.loop
  145. .loop
  146. .3
  147.         move.b  (a1,d0.w),d4
  148.         addx.l  d1,d0
  149.         move.l  d4,a2
  150.         move.w  (a2),d6
  151.         and.w   d3,d0
  152.         move.b    (a2),d6
  153.         move.w    d6,(a0)
  154. .2
  155.         move.b  (a1,d0.w),d4
  156.         addx.l  d1,d0
  157.         move.l  d4,a2
  158.         move.w  (a2),d6
  159.         and.w   d3,d0
  160.         move.b    (a2),d6
  161.         move.w    d6,(SCREENWIDTH,a0)
  162. .1
  163.         move.b  (a1,d0.w),d4
  164.         addx.l  d1,d0
  165.         move.l  d4,a2
  166.         move.w  (a2),d6
  167.         and.w   d3,d0
  168.         move.b    (a2),d6
  169.         move.w    d6,(SCREENWIDTH*2,a0)
  170. .0
  171.         move.b  (a1,d0.w),d4
  172.         addx.l  d1,d0
  173.         move.l  d4,a2
  174.         move.w    (a2),d6
  175.         and.w   d3,d0
  176.         move.b  (a2),d6
  177.         move.w    d6,(SCREENWIDTH*3,a0)
  178.  
  179.         add.l   a3,a0
  180. .loop_end
  181.         dbf     d7,.loop
  182. .end
  183.         movem.l (sp)+,d3-d4/d6-d7/a2/a3
  184.         rts
  185.  
  186.         cnop    0,4
  187.  
  188. _R_DrawSpanLow
  189. @R_DrawSpanLow
  190.         movem.l d2-d7/a2-a4,-(sp)
  191.         move.l  (_ds_y),d0
  192.         move.l  (_ds_x1),d1     ; dest = ylookup[_ds_y] + columnofs[_ds_x1]
  193.         lea     (_ylookup),a0
  194.         add.l    d1,d1
  195.         move.l  (a0,d0.l*4),a0
  196.         lea     (_columnofs),a1
  197.         add.l   (a1,d1.l*4),a0
  198.         move.l  (_ds_x2),d7     ; count = _ds_x2 - _ds_x1
  199.         move.l  (_ds_source),a1
  200.         add.l    d7,d7
  201.         move.l  (_ds_colormap),a2
  202.         sub.l   d1,d7
  203.         addq.l    #2,d7
  204.         move.l  (_ds_xfrac),d0
  205.         move.l  (_ds_yfrac),d1
  206.         move.l  (_ds_xstep),d2
  207.         move.l  (_ds_ystep),d3
  208.         move.l  a0,d4        ; notice, that this address must already be aligned by word
  209.         btst    #1,d4
  210.         beq     .skips
  211.         move.l  d0,d5           ; do the unaligned pixels
  212.         move.l  d1,d6           ; so we can write to longword
  213.         swap    d5              ; boundary in the main loop
  214.         swap    d6
  215.         and.w   #$3f,d5
  216.         and.w   #$3f,d6        ; this is the worst possible
  217.         lsl.w   #6,d6        ; way but hey, this is not a loop
  218.         or.w    d5,d6
  219.         move.b  (a1,d6.w),d5
  220.         add.l   d2,d0
  221.         move.b  (a2,d5.w),(a0)+
  222.         add.l   d3,d1
  223.         move.b    (a2,d5.w),(a0)+    ; I know this is crap but spare me the comments
  224.         subq.l  #2,d7
  225. .skips        move.l  a2,d4
  226.         lea     ($1000,a1),a1    ; catch 22
  227.         move.l  a0,a3
  228.         add.l   d7,a3
  229.         move.l  d7,d5
  230.         and.b   #~7,d5
  231.         move.l  a0,a4
  232.         add.l   d5,a4
  233.         eor.w   d0,d1           ; swap fraction parts for addx
  234.         eor.w   d2,d3
  235.         eor.w   d1,d0
  236.         eor.w   d3,d2
  237.         eor.w   d0,d1
  238.         eor.w   d2,d3
  239.         swap    d0
  240.         swap    d1
  241.         swap    d2
  242.         swap    d3
  243.         lsl.w   #6,d1
  244.         lsl.w   #6,d3
  245.         move.w  #$ffc0,d6
  246.         move.w  #$f03f,d7
  247.         lsr.w   #3,d5
  248.         beq     .skip_loop2
  249.         sub.w   d2,d0
  250.         add.l   d2,d0           ; setup the X flag
  251. .loop2        or.w    d6,d0        ; Not really and exercise in optimizing
  252.         or.w    d7,d1        ; but I guess it's faster than 1x1 for 030
  253.         and.w   d1,d0        ; where this low detail business is needed.
  254.         addx.l  d3,d1
  255.         move.b  (a1,d0.w),d4
  256.         addx.l  d2,d0
  257.         move.l  d4,a2
  258.         move.w  (a2),d5
  259.         or.w    d6,d0
  260.         move.b    (a2),d5
  261.         or.w    d7,d1
  262.         and.w   d1,d0
  263.         swap    d5
  264.         addx.l  d3,d1
  265.         move.b  (a1,d0.w),d4
  266.         addx.l  d2,d0
  267.         move.l  d4,a2
  268.         move.w  (a2),d5
  269.         or.w    d6,d0
  270.         move.b    (a2),d5
  271.         or.w    d7,d1
  272.         and.w   d1,d0
  273.         move.l    d5,(a0)+
  274.         addx.l  d3,d1
  275.         move.b  (a1,d0.w),d4
  276.         addx.l  d2,d0
  277.         move.l  d4,a2
  278.         move.w  (a2),d5
  279.         or.w    d6,d0
  280.         move.b    (a2),d5
  281.         or.w    d7,d1
  282.         and.w   d1,d0
  283.         swap    d5
  284.         addx.l  d3,d1
  285.         move.b  (a1,d0.w),d4
  286.         addx.l  d2,d0
  287.         move.l  d4,a2
  288.         move.w  (a2),d5
  289.         move.b    (a2),d5
  290.         move.l  d5,(a0)+
  291.         cmp.l   a0,a4
  292.         bne     .loop2
  293. .skip_loop2
  294.         sub.w   d2,d0
  295.         add.l   d2,d0
  296.  
  297.         bra     .loop_end2
  298. .loop3      or.w    d6,d0
  299.         or.w    d7,d1
  300.         and.w   d1,d0
  301.         addx.l  d3,d1
  302.         move.b  (a1,d0.w),d4
  303.         addx.l  d2,d0
  304.         move.l  d4,a2
  305.         move.b  (a2),(a0)+
  306.         move.b    (a2),(a0)+
  307. .loop_end2
  308.         cmp.l   a0,a3
  309.         bne     .loop3
  310. .end2        movem.l (sp)+,d2-d7/a2-a4
  311.         rts
  312.  
  313.         cnop    0,4
  314.  
  315. _R_DrawTranslatedColumnLow
  316. @R_DrawTranslatedColumnLow
  317.         movem.l d2-d4/d6-d7/a2/a3,-(sp)
  318.  
  319.         move.l  (_dc_yh),d7     ; count = _dc_yh - _dc_yl
  320.         move.l  (_dc_yl),d0
  321.         sub.l   d0,d7
  322.         bmi     .end
  323.  
  324.         move.l  (_dc_x),d1      ; dest = ylookup[_dc_yl] + columnofs[_dc_x]
  325.         lea     (_ylookup),a0
  326.         add.l    d1,d1
  327.         move.l  (a0,d0.l*4),a0
  328.         lea     (_columnofs),a1
  329.         add.l   (a1,d1.l*4),a0
  330.  
  331.         move.l    (_dc_translation),d2
  332.         move.l  (_dc_colormap),d4
  333.         move.l  (_dc_source),a1
  334.  
  335.         move.l  (_dc_iscale),d1 ; frac = _dc_texturemid + (_dc_yl-centery)*fracstep
  336.         sub.l   (_centery),d0
  337.         muls.l  d1,d0
  338.         add.l   (_dc_texturemid),d0
  339.  
  340.         moveq   #$7f,d3
  341.         lea     (SCREENWIDTH*4).w,a3
  342.  
  343. ; d7: cnt >> 2
  344. ; a0: chunky
  345. ; a1: texture
  346. ; d0: frac  (uuuu uuuu uuuu uuuu 0000 0000 0UUU UUUU)
  347. ; d1: dfrac (.......................................)
  348. ; d3: $7f
  349. ; d4: light table aligned to 256 byte boundary
  350. ; d2: translation table aligned to 256 byte boundary
  351. ; a3: SCREENWIDTH
  352.  
  353.         move.l  d7,d6
  354.         and.w   #3,d6
  355.  
  356.         swap    d0              ; swap decimals and fraction
  357.         swap    d1
  358.  
  359.         add.w   (.width_tab,pc,d6.w*2),a0
  360.         lsr.w   #2,d7
  361.         move.w  (.tmap_tab,pc,d6.w*2),d6
  362.  
  363.         and.w   d3,d0
  364.         sub.w   d1,d0
  365.         add.l   d1,d0           ; setup the X flag
  366.  
  367.         jmp     (.loop,pc,d6.w)
  368.  
  369.         cnop    0,4
  370. .width_tab
  371.         dc.w    -3*SCREENWIDTH
  372.         dc.w    -2*SCREENWIDTH
  373.         dc.w    -1*SCREENWIDTH
  374.         dc.w    0
  375. .tmap_tab
  376.         dc.w    .0-.loop
  377.         dc.w    .1-.loop
  378.         dc.w    .2-.loop
  379.         dc.w    .3-.loop
  380. .loop
  381. .3
  382.         move.b  (a1,d0.w),d2
  383.         move.l    d2,a2
  384.         addx.l  d1,d0
  385.         move.b    (a2),d4
  386.         move.l  d4,a2
  387.         and.w   d3,d0
  388.         move.w    (a2),d6
  389.         move.b  (a2),d6
  390.         move.w    d6,(a0)
  391. .2
  392.         move.b  (a1,d0.w),d2
  393.         move.l    d2,a2
  394.         addx.l  d1,d0
  395.         move.b    (a2),d4
  396.         move.l  d4,a2
  397.         and.w   d3,d0
  398.         move.w    (a2),d6
  399.         move.b  (a2),d6
  400.         move.w    d6,(SCREENWIDTH,a0)
  401. .1
  402.         move.b  (a1,d0.w),d2
  403.         move.l    d2,a2
  404.         addx.l  d1,d0
  405.         move.b    (a2),d4
  406.         move.l  d4,a2
  407.         and.w   d3,d0
  408.         move.w    (a2),d6
  409.         move.b    (a2),d6
  410.         move.w  d6,(SCREENWIDTH*2,a0)
  411. .0
  412.         move.b  (a1,d0.w),d2
  413.         move.l    d2,a2
  414.         addx.l  d1,d0
  415.         move.b    (a2),d4
  416.         move.l  d4,a2
  417.         and.w   d3,d0
  418.         move.w    (a2),d6
  419.         move.b    (a2),d6
  420.         move.b  d6,(SCREENWIDTH*3,a0)
  421.  
  422.         add.l   a3,a0
  423. .loop_end
  424.         dbf     d7,.loop
  425. .end
  426.         movem.l (sp)+,d2-d4/d6-d7/a2/a3
  427.         rts
  428.  
  429.         cnop    0,4
  430.  
  431. _R_DrawFuzzColumnLow
  432. @R_DrawFuzzColumnLow
  433.         movem.l d4/d6-d7/a2/a3,-(sp)
  434.  
  435.         move.l    (_viewheight),d1
  436.         subq.l    #1,d1
  437.         move.l  (_dc_yh),d7     ; count = _dc_yh - _dc_yl
  438.         cmp.l    d1,d7
  439.         bne    .skip_yh
  440.         subq.l    #1,d1
  441.         move.l    d1,d7
  442. .skip_yh
  443.         move.l  (_dc_yl),d0
  444.         bne    .skip_yl
  445.         moveq    #1,d0
  446. .skip_yl
  447.         sub.l   d0,d7
  448.         bmi     .end
  449.  
  450.         move.l  (_dc_x),d1      ; dest = ylookup[_dc_yl] + columnofs[_dc_x]
  451.         lea     (_ylookup),a0
  452.         add.l    d1,d1
  453.         move.l  (a0,d0.l*4),a0
  454.         lea     (_columnofs),a1
  455.         add.l   (a1,d1.l*4),a0
  456.  
  457.         move.l  (_colormaps),d4
  458.         add.l    #6*256,d4
  459.  
  460.         lea    (_fuzzoffset),a1
  461.         move.l    (_fuzzpos),d0    ; bring it down 
  462. .pos_loop    sub.w    #200,d0
  463.         bpl    .pos_loop
  464.         add.w    #200,d0
  465.         add.l    d0,a1
  466.  
  467.         lea     (SCREENWIDTH*4).w,a3
  468.  
  469. ; d7: cnt >> 2
  470. ; a0: chunky
  471. ; a1: fuzzoffset
  472. ; d0: frac  (uuuu uuuu uuuu uuuu 0000 0000 0UUU UUUU)
  473. ; d1: dfrac (.......................................)
  474. ; d3: $7f
  475. ; d4: light table aligned to 256 byte boundary
  476. ; a3: SCREENWIDTH
  477.  
  478.         move.l  d7,d6
  479.         and.w   #3,d6
  480.  
  481.         add.w   (.width_tab,pc,d6.w*2),a0
  482.         lsr.w   #2,d7
  483.         move.w  (.tmap_tab,pc,d6.w*2),d6
  484.  
  485.         jmp     (.loop,pc,d6.w)
  486.  
  487.         cnop    0,4
  488. .width_tab
  489.         dc.w    -3*SCREENWIDTH
  490.         dc.w    -2*SCREENWIDTH
  491.         dc.w    -1*SCREENWIDTH
  492.         dc.w    0
  493. .tmap_tab
  494.         dc.w    .0-.loop
  495.         dc.w    .1-.loop
  496.         dc.w    .2-.loop
  497.         dc.w    .3-.loop
  498. .loop
  499. .3        move.l    a0,a2            ; This is essentially
  500.         add.l    (a1)+,a2        ; just moving memory around.
  501.         move.b    (a2),d4
  502.         move.l    d4,a2            
  503.         move.w    (a2),d6
  504.         move.b    (a2),d6
  505.         move.w    d6,(a0)        
  506. .2        lea    (SCREENWIDTH,a0),a2    
  507.         add.l    (a1)+,a2        
  508.         move.b    (a2),d4            
  509.         move.l    d4,a2
  510.         move.w    (a2),d6
  511.         move.b    (a2),d6
  512.         move.w    d6,(SCREENWIDTH,a0)
  513. .1        lea    (2*SCREENWIDTH,a0),a2
  514.         add.l    (a1)+,a2
  515.         move.b    (a2),d4
  516.         move.l    d4,a2
  517.         move.w    (a2),d6
  518.         move.b    (a2),d6
  519.         move.w    d6,(2*SCREENWIDTH,a0)
  520. .0        lea    (3*SCREENWIDTH,a0),a2
  521.         add.l    (a1)+,a2
  522.         move.b    (a2),d4
  523.         move.l    d4,a2
  524.         move.w    (a2),d6
  525.         move.b    (a2),d6
  526.         move.w    d6,(3*SCREENWIDTH,a0)
  527.  
  528.         add.l   a3,a0
  529. .loop_end
  530.         dbf    d7,.loop
  531.         sub.l    #_fuzzoffset,a1
  532.         move.l    a1,_fuzzpos
  533. .end
  534.         movem.l (sp)+,d4/d6-d7/a2/a3
  535.         rts
  536.  
  537. ; high detail versions
  538.  
  539.         cnop    0,4
  540.  
  541. _R_DrawFuzzColumn
  542. @R_DrawFuzzColumn
  543.         movem.l d4/d6-d7/a2/a3,-(sp)
  544.  
  545.         move.l    (_viewheight),d1
  546.         subq.l    #1,d1
  547.         move.l  (_dc_yh),d7     ; count = _dc_yh - _dc_yl
  548.         cmp.l    d1,d7
  549.         bne    .skip_yh
  550.         subq.l    #1,d1
  551.         move.l    d1,d7
  552. .skip_yh
  553.         move.l  (_dc_yl),d0
  554.         bne    .skip_yl
  555.         moveq    #1,d0
  556. .skip_yl
  557.         sub.l   d0,d7
  558.         bmi     .end
  559.  
  560.         move.l  (_dc_x),d1      ; dest = ylookup[_dc_yl] + columnofs[_dc_x]
  561.         lea     (_ylookup),a0
  562.         move.l  (a0,d0.l*4),a0
  563.         lea     (_columnofs),a1
  564.         add.l   (a1,d1.l*4),a0
  565.  
  566.         move.l  (_colormaps),d4
  567.         add.l    #6*256,d4
  568.  
  569.         lea    (_fuzzoffset),a1
  570.         move.l    (_fuzzpos),d0
  571. .pos_loop    sub.w    #200,d0
  572.         bpl    .pos_loop
  573.         add.w    #200,d0
  574.         add.l    d0,a1
  575.  
  576.         lea     (SCREENWIDTH*4).w,a3
  577.  
  578. ; d7: cnt >> 2
  579. ; a0: chunky
  580. ; a1: fuzzoffset
  581. ; d0: frac  (uuuu uuuu uuuu uuuu 0000 0000 0UUU UUUU)
  582. ; d1: dfrac (.......................................)
  583. ; d3: $7f
  584. ; d4: light table aligned to 256 byte boundary
  585. ; a3: SCREENWIDTH
  586.  
  587.         move.l  d7,d6
  588.         and.w   #3,d6
  589.  
  590.         add.w   (.width_tab,pc,d6.w*2),a0
  591.         lsr.w   #2,d7
  592.         move.w  (.tmap_tab,pc,d6.w*2),d6
  593.  
  594.         jmp     (.loop,pc,d6.w)
  595.  
  596.         cnop    0,4
  597. .width_tab
  598.         dc.w    -3*SCREENWIDTH
  599.         dc.w    -2*SCREENWIDTH
  600.         dc.w    -1*SCREENWIDTH
  601.         dc.w    0
  602. .tmap_tab
  603.         dc.w    .0-.loop
  604.         dc.w    .1-.loop
  605.         dc.w    .2-.loop
  606.         dc.w    .3-.loop
  607. .loop
  608. .3        move.l    a0,a2            ; This is essentially
  609.         add.l    (a1)+,a2        ; just moving memory around.
  610.         move.b    (a2),d4
  611.         move.l    d4,a2            ; Not 060 optimized but
  612.         move.b    (a2),(a0)        ; if you have hordes of
  613. .2        lea    (SCREENWIDTH,a0),a2    ; invisible monsters which
  614.         add.l    (a1)+,a2        ; slow down the game too much,
  615.         move.b    (a2),d4            ; do tell me.
  616.         move.l    d4,a2
  617.         move.b    (a2),(SCREENWIDTH,a0)
  618. .1        lea    (2*SCREENWIDTH,a0),a2
  619.         add.l    (a1)+,a2
  620.         move.b    (a2),d4
  621.         move.l    d4,a2
  622.         move.b    (a2),(2*SCREENWIDTH,a0)
  623. .0        lea    (3*SCREENWIDTH,a0),a2
  624.         add.l    (a1)+,a2
  625.         move.b    (a2),d4
  626.         move.l    d4,a2
  627.         move.b    (a2),(3*SCREENWIDTH,a0)
  628.  
  629.         add.l   a3,a0
  630. .loop_end
  631.         dbf    d7,.loop
  632.         sub.l    #_fuzzoffset,a1
  633.         move.l    a1,_fuzzpos
  634. .end
  635.         movem.l (sp)+,d4/d6-d7/a2/a3
  636.         rts
  637.  
  638.         cnop    0,4
  639.  
  640. _R_DrawTranslatedColumn                    ; no 060 version :(
  641. @R_DrawTranslatedColumn
  642.         movem.l d2-d4/d6-d7/a2/a3,-(sp)
  643.  
  644.         move.l  (_dc_yh),d7     ; count = _dc_yh - _dc_yl
  645.         move.l  (_dc_yl),d0
  646.         sub.l   d0,d7
  647.         bmi     .end
  648.  
  649.         move.l  (_dc_x),d1      ; dest = ylookup[_dc_yl] + columnofs[_dc_x]
  650.         lea     (_ylookup),a0
  651.         move.l  (a0,d0.l*4),a0
  652.         lea     (_columnofs),a1
  653.         add.l   (a1,d1.l*4),a0
  654.  
  655.         move.l    (_dc_translation),d2
  656.         move.l  (_dc_colormap),d4
  657.         move.l  (_dc_source),a1
  658.  
  659.         move.l  (_dc_iscale),d1 ; frac = _dc_texturemid + (_dc_yl-centery)*fracstep
  660.         sub.l   (_centery),d0
  661.         muls.l  d1,d0
  662.         add.l   (_dc_texturemid),d0
  663.  
  664.         moveq   #$7f,d3
  665.         lea     (SCREENWIDTH*4).w,a3
  666.  
  667. ; d7: cnt >> 2
  668. ; a0: chunky
  669. ; a1: texture
  670. ; d0: frac  (uuuu uuuu uuuu uuuu 0000 0000 0UUU UUUU)
  671. ; d1: dfrac (.......................................)
  672. ; d3: $7f
  673. ; d4: light table aligned to 256 byte boundary
  674. ; d2: translation table aligned to 256 byte boundary
  675. ; a3: SCREENWIDTH
  676.  
  677.         move.l  d7,d6
  678.         and.w   #3,d6
  679.  
  680.         swap    d0              ; swap decimals and fraction
  681.         swap    d1
  682.  
  683.         add.w   (.width_tab,pc,d6.w*2),a0
  684.         lsr.w   #2,d7
  685.         move.w  (.tmap_tab,pc,d6.w*2),d6
  686.  
  687.         and.w   d3,d0
  688.         sub.w   d1,d0
  689.         add.l   d1,d0           ; setup the X flag
  690.  
  691.         jmp     (.loop,pc,d6.w)
  692.  
  693.         cnop    0,4
  694. .width_tab
  695.         dc.w    -3*SCREENWIDTH
  696.         dc.w    -2*SCREENWIDTH
  697.         dc.w    -1*SCREENWIDTH
  698.         dc.w    0
  699. .tmap_tab
  700.         dc.w    .0-.loop
  701.         dc.w    .1-.loop
  702.         dc.w    .2-.loop
  703.         dc.w    .3-.loop
  704. .loop
  705. .3
  706.         move.b  (a1,d0.w),d2
  707.         move.l    d2,a2
  708.         addx.l  d1,d0
  709.         move.b    (a2),d4
  710.         and.w   d3,d0
  711.         move.l  d4,a2
  712.         move.b  (a2),(a0)
  713. .2
  714.         move.b  (a1,d0.w),d2
  715.         move.l    d2,a2
  716.         addx.l  d1,d0
  717.         move.b    (a2),d4
  718.         and.w   d3,d0
  719.         move.l  d4,a2
  720.         move.b  (a2),(SCREENWIDTH,a0)
  721. .1
  722.         move.b  (a1,d0.w),d2
  723.         move.l    d2,a2
  724.         addx.l  d1,d0
  725.         move.b    (a2),d4
  726.         and.w   d3,d0
  727.         move.l  d4,a2
  728.         move.b  (a2),(SCREENWIDTH*2,a0)
  729. .0
  730.         move.b  (a1,d0.w),d2
  731.         move.l    d2,a2
  732.         addx.l  d1,d0
  733.         move.b    (a2),d4
  734.         and.w   d3,d0
  735.         move.l  d4,a2
  736.         move.b  (a2),(SCREENWIDTH*3,a0)
  737.  
  738.         add.l   a3,a0
  739. .loop_end
  740.         dbf     d7,.loop
  741. .end
  742.         movem.l (sp)+,d2-d4/d6-d7/a2/a3
  743.         rts
  744.  
  745.         cnop    0,4
  746.  
  747. _R_DrawColumn_060
  748. @R_DrawColumn_060
  749.         movem.l d2-d3/d5-d7/a2/a3,-(sp)
  750.  
  751.         move.l  (_dc_yh),d7     ; count = _dc_yh - _dc_yl
  752.         move.l  (_dc_yl),d0
  753.         sub.l   d0,d7
  754.         bmi     .end
  755.  
  756.         move.l  (_dc_x),d1      ; dest = ylookup[_dc_yl] + columnofs[_dc_x]
  757.         lea     (_ylookup),a0
  758.         move.l  (a0,d0.l*4),a0
  759.         lea     (_columnofs),a1
  760.         add.l   (a1,d1.l*4),a0
  761.  
  762.         move.l  (_dc_colormap),a2
  763.         move.l  (_dc_source),a1
  764.  
  765.         move.l  (_dc_iscale),d1 ; frac = _dc_texturemid + (_dc_yl-centery)*fracstep
  766.         sub.l   (_centery),d0
  767.         muls.l  d1,d0
  768.         add.l   (_dc_texturemid),d0
  769.  
  770.         moveq   #$7f,d3
  771.         move.l  #SCREENWIDTH,a3
  772.  
  773.         move.l  d7,d6           ; Do the leftover iterations in
  774.         and.w   #3,d6           ; this loop.
  775.         beq     .skip
  776. .skip_loop
  777.         move.l  d0,d5
  778.         swap    d5
  779.         and.l   d3,d5
  780.         move.b  (a1,d5.w),d5
  781.         add.l   d1,d0
  782.         move.b  (a2,d5.w),(a0)
  783.         add.l   a3,a0
  784.         subq.l  #1,d6
  785.         bne     .skip_loop
  786.  
  787. ; d7: cnt >> 2
  788. ; a0: chunky
  789. ; a1: texture
  790. ; a2: light_table
  791. ; d0: frac  (uuuu uuuu uuuu uuuu 0000 0000 0UUU UUUU)
  792. ; d1: dfrac*2   (.......................................)
  793. ; d2: frac+dfrac(.......................................)
  794. ; d3: $7f
  795. ; a3: SCREENWIDTH
  796.  
  797. .skip
  798.         lsr.l   #2,d7
  799.         subq.l  #1,d7
  800.         bmi     .end
  801.  
  802.         add.l   a3,a3
  803.  
  804.         move.l  d0,d2
  805.         add.l   a3,a3
  806.         add.l   d1,d2
  807.         add.l   d1,d1
  808.  
  809.         eor.w   d0,d2           ; swap the fraction part for addx
  810.         eor.w   d2,d0           ; assuming 16.16 fixed point
  811.         eor.w   d0,d2
  812.  
  813.         swap    d0              ; swap decimals and fraction
  814.         swap    d1
  815.         swap    d2
  816.  
  817.         moveq   #0,d5
  818.         and.w   d3,d2
  819.         and.w   d3,d0
  820.  
  821.         sub.w   d1,d0
  822.         add.l   d1,d0           ; setup the X flag
  823.  
  824.         move.b  (a1,d2.w),d5
  825. .loop
  826.         ; This should be reasonably scheduled for
  827.         ; m68060. It should perform well on other processors
  828.         ; too. That AGU stall still bothers me though.
  829.  
  830.         move.b  (a1,d0.w),d6        ; stall + pOEP but allows sOEP
  831.         addx.l  d1,d2               ; pOEP only
  832.         move.b  (a2,d5.l),d5        ; pOEP but allows sOEP
  833.         and.w   d3,d2               ; sOEP
  834.         move.b  (a2,d6.l),d6        ; pOEP but allows sOEP
  835.         move.b  d5,(SCREENWIDTH,a0) ; sOEP
  836.         addx.l  d1,d0               ; pOEP only
  837.         move.b  (a1,d2.w),d5        ; pOEP but allows sOEP
  838.         and.w   d3,d0               ; sOEP
  839.         move.b  d6,(a0)             ; pOEP
  840.                                     ; = ~4 cycles/pixel
  841.                                     ; + cache misses
  842.  
  843.         ; The vertical writes are the true timehog of the loop
  844.         ; because of the characteristics of the copyback cache
  845.         ; operation.
  846.         
  847.         ; Better mark the chunky buffer as write through
  848.         ; with the MMU and have all the horizontal writes
  849.         ; be longs aligned to longword boundary.
  850.  
  851.         move.b  (a1,d0.w),d6
  852.         addx.l  d1,d2
  853.         move.b  (a2,d5.l),d5
  854.         and.w   d3,d2
  855.         move.b  (a2,d6.l),d6
  856.         move.b  d5,(SCREENWIDTH*3,a0)
  857.         addx.l  d1,d0
  858.         move.b  (a1,d2.w),d5
  859.         and.w   d3,d0
  860.         move.b  d6,(SCREENWIDTH*2,a0)
  861.  
  862.         add.l   a3,a0
  863. .loop_end
  864.         dbf     d7,.loop
  865.  
  866.         ; it's faster to divide it to two lines on 060
  867.         ; and shouldn't be slower on 040.
  868.  
  869.         move.b  (a1,d0.w),d6    ; new
  870.         move.b  (a2,d6.l),d6    ; new
  871.         move.b  d6,(a0)     ; new
  872.  
  873. .end
  874.         movem.l (sp)+,d2-d3/d5-d7/a2/a3
  875.         rts
  876.  
  877.         cnop    0,4
  878.  
  879. ; 030/040 version
  880.  
  881. _R_DrawColumn_040
  882. @R_DrawColumn_040
  883.         movem.l d3-d4/d6-d7/a2/a3,-(sp)
  884.  
  885.         move.l  (_dc_yh),d7     ; count = _dc_yh - _dc_yl
  886.         move.l  (_dc_yl),d0
  887.         sub.l   d0,d7
  888.         bmi     .end
  889.  
  890.         move.l  (_dc_x),d1      ; dest = ylookup[_dc_yl] + columnofs[_dc_x]
  891.         lea     (_ylookup),a0
  892.         move.l  (a0,d0.l*4),a0
  893.         lea     (_columnofs),a1
  894.         add.l   (a1,d1.l*4),a0
  895.  
  896.         move.l  (_dc_colormap),d4
  897.         move.l  (_dc_source),a1
  898.  
  899.         move.l  (_dc_iscale),d1 ; frac = _dc_texturemid + (_dc_yl-centery)*fracstep
  900.         sub.l   (_centery),d0
  901.         muls.l  d1,d0
  902.         add.l   (_dc_texturemid),d0
  903.  
  904.         moveq   #$7f,d3
  905.         lea     (SCREENWIDTH*4).w,a3
  906.  
  907. ; d7: cnt >> 2
  908. ; a0: chunky
  909. ; a1: texture
  910. ; d0: frac  (uuuu uuuu uuuu uuuu 0000 0000 0UUU UUUU)
  911. ; d1: dfrac (.......................................)
  912. ; d3: $7f
  913. ; d4: light table aligned to 256 byte boundary
  914. ; a3: SCREENWIDTH
  915.  
  916.         move.l  d7,d6
  917.         and.w   #3,d6
  918.  
  919.         swap    d0              ; swap decimals and fraction
  920.         swap    d1
  921.  
  922.         add.w   (.width_tab,pc,d6.w*2),a0
  923.         lsr.w   #2,d7
  924.         move.w  (.tmap_tab,pc,d6.w*2),d6
  925.  
  926.         and.w   d3,d0
  927.         sub.w   d1,d0
  928.         add.l   d1,d0           ; setup the X flag
  929.  
  930.         jmp (.loop,pc,d6.w)
  931.  
  932.         cnop    0,4
  933. .width_tab
  934.         dc.w    -3*SCREENWIDTH
  935.         dc.w    -2*SCREENWIDTH
  936.         dc.w    -1*SCREENWIDTH
  937.         dc.w    0
  938. .tmap_tab
  939.         dc.w    .0-.loop
  940.         dc.w    .1-.loop
  941.         dc.w    .2-.loop
  942.         dc.w    .3-.loop
  943. .loop
  944. .3
  945.         move.b  (a1,d0.w),d4
  946.         addx.l  d1,d0
  947.         move.l  d4,a2
  948.         and.w   d3,d0
  949.         move.b  (a2),(a0)
  950. .2
  951.         move.b  (a1,d0.w),d4
  952.         addx.l  d1,d0
  953.         move.l  d4,a2
  954.         and.w   d3,d0
  955.         move.b  (a2),(SCREENWIDTH,a0)
  956. .1
  957.         move.b  (a1,d0.w),d4
  958.         addx.l  d1,d0
  959.         move.l  d4,a2
  960.         and.w   d3,d0
  961.         move.b  (a2),(SCREENWIDTH*2,a0)
  962. .0
  963.         move.b  (a1,d0.w),d4
  964.         addx.l  d1,d0
  965.         move.l  d4,a2
  966.         and.w   d3,d0
  967.         move.b  (a2),(SCREENWIDTH*3,a0)
  968.  
  969.         add.l   a3,a0
  970. .loop_end
  971.         dbf d7,.loop
  972. .end
  973.         movem.l (sp)+,d3-d4/d6-d7/a2/a3
  974.         rts
  975.  
  976. ; This faster version by Aki M Laukkanen <amlaukka@cc.helsinki.fi>
  977.  
  978.         cnop    0,4
  979.  
  980. _R_DrawSpan_060
  981. @R_DrawSpan_060
  982.         movem.l d2-d7/a2/a3,-(sp)
  983.         move.l  (_ds_y),d0
  984.         move.l  (_ds_x1),d1     ; dest = ylookup[_ds_y] + columnofs[_ds_x1]
  985.         lea     (_ylookup),a0
  986.         move.l  (a0,d0.l*4),a0
  987.         lea     (_columnofs),a1
  988.         add.l   (a1,d1.l*4),a0
  989.         move.l  (_ds_source),a1
  990.         move.l  (_ds_colormap),a2
  991.         move.l  (_ds_x2),d7     ; count = _ds_x2 - _ds_x1
  992.         sub.l   d1,d7
  993.         addq.l  #1,d7
  994.         move.l  (_ds_xfrac),d0
  995.         move.l  (_ds_yfrac),d1
  996.         move.l  (_ds_xstep),d2
  997.         move.l  (_ds_ystep),d3
  998.         move.l  a0,d4
  999.         btst    #0,d4
  1000.         beq     .skipb
  1001.         move.l  d0,d5           ; do the unaligned pixels
  1002.         move.l  d1,d6           ; so we can write to longword
  1003.         swap    d5              ; boundary in the main loop
  1004.         swap    d6
  1005.         and.w   #$3f,d5
  1006.         and.w   #$3f,d6
  1007.         lsl.w   #6,d6
  1008.         or.w    d5,d6
  1009.         move.b  (a1,d6.w),d5
  1010.         add.l   d2,d0
  1011.         move.b  (a2,d5.w),(a0)+
  1012.         add.l   d3,d1
  1013.         move.l  a0,d4
  1014.         subq.l  #1,d7
  1015. .skipb        btst    #1,d4
  1016.         beq     .skips
  1017.         moveq   #2,d4
  1018.         cmp.l   d4,d7
  1019.         bls     .skips
  1020.         move.l  d0,d5           ; write two pixels
  1021.         move.l  d1,d6
  1022.         swap    d5
  1023.         swap    d6
  1024.         and.w   #$3f,d5
  1025.         and.w   #$3f,d6
  1026.         lsl.w   #6,d6
  1027.         or.w    d5,d6
  1028.         move.b  (a1,d6.w),d5
  1029.         move.w  (a2,d5.w),d4
  1030.         add.l   d2,d0
  1031.         add.l   d3,d1
  1032.         move.l  d0,d5
  1033.         move.l  d1,d6
  1034.         swap    d5
  1035.         swap    d6
  1036.         and.w   #$3f,d5
  1037.         and.w   #$3f,d6
  1038.         lsl.w   #6,d6
  1039.         or.w    d5,d6
  1040.         move.b  (a1,d6.w),d5
  1041.         move.b  (a2,d5.w),d4
  1042.         add.l   d2,d0
  1043.         move.w  d4,(a0)+
  1044.         add.l   d3,d1
  1045.         subq.l  #2,d7
  1046. .skips        move.l  d7,d6           ; setup registers
  1047.         and.w   #3,d6
  1048.         move.l  d6,a3
  1049.         eor.w   d0,d1           ; swap fraction parts for addx
  1050.         eor.w   d2,d3
  1051.         eor.w   d1,d0
  1052.         eor.w   d3,d2
  1053.         eor.w   d0,d1
  1054.         eor.w   d2,d3
  1055.         swap    d0
  1056.         swap    d1
  1057.         swap    d2
  1058.         swap    d3
  1059.         lsl.w   #6,d1
  1060.         lsl.w   #6,d3
  1061.         moveq   #0,d6
  1062.         moveq   #0,d5
  1063.         sub.l   #$f000,a1
  1064.         lsr.l   #2,d7
  1065.         beq     .skip_loop2
  1066.         subq.l  #1,d7
  1067.         sub.w   d3,d1
  1068.         add.l   d3,d1           ; setup the X flag
  1069.         or.w    #$ffc0,d0
  1070.         or.w    #$f03f,d1
  1071.         move.w  d0,d6
  1072.         and.w   d1,d6
  1073.         bra     .start_loop2
  1074.         cnop    0,8
  1075. .loop2        or.w    #$ffc0,d0       ; pOEP
  1076.         or.w    #$f03f,d1       ; sOEP
  1077.         move.b  (a2,d5.l),d4    ; pOEP but allows sOEP
  1078.         move.w  d0,d6           ; sOEP
  1079.         and.w   d1,d6           ; pOEP
  1080.         move.l  d4,(a0)+        ; sOEP
  1081. .start_loop2
  1082.         addx.l  d2,d0           ; pOEP only
  1083.         addx.l  d3,d1           ; pOEP only
  1084.         move.b  (a1,d6.l),d5    ; pOEP but allows sOEP
  1085.         or.w    #$ffc0,d0       ; sOEP
  1086.         or.w    #$f03f,d1       ; pOEP
  1087.         move.w  d0,d6           ; sOEP
  1088.         move.w  (a2,d5.l),d4    ; pOEP but allows sOEP
  1089.         and.w   d1,d6           ; sOEP
  1090.         addx.l  d2,d0           ; pOEP only
  1091.         addx.l  d3,d1           ; pOEP only
  1092.         move.b  (a1,d6.l),d5    ; pOEP but allows sOEP
  1093.         or.w    #$ffc0,d0       ; sOEP
  1094.         or.w    #$f03f,d1       ; pOEP
  1095.         move.w  d0,d6           ; sOEP
  1096.         move.b  (a2,d5.l),d4    ; pOEP but allows sOEP
  1097.         and.w   d1,d6           ; sOEP
  1098.         addx.l  d2,d0           ; pOEP only
  1099.         addx.l  d3,d1           ; pOEP only
  1100.         move.b  (a1,d6.l),d5    ; pOEP but allows sOEP
  1101.         or.w    #$ffc0,d0       ; sOEP
  1102.         or.w    #$f03f,d1       ; pOEP
  1103.         move.w  d0,d6           ; sOEP
  1104.         swap    d4              ; pOEP only
  1105.         move.w  (a2,d5.l),d4    ; pOEP but allows sOEP
  1106.         and.w   d1,d6           ; sOEP
  1107.         addx.l  d2,d0           ; pOEP only
  1108.         addx.l  d3,d1           ; pOEP only
  1109.         move.b  (a1,d6.l),d5    ; pOEP but allows sOEP
  1110.         dbf     d7,.loop2       ; pOEP only = 7.75 cycles/pixel
  1111.         move.b  (a2,d5.l),d4
  1112.         move.l  d4,(a0)+
  1113. .skip_loop2
  1114.         sub.w   d3,d1
  1115.         add.l   d3,d1
  1116.         move.l  a3,d7
  1117.         bra     .loop_end2
  1118. .loop3      or.w    #$ffc0,d0
  1119.         or.w    #$f03f,d1
  1120.         move.w  d0,d6
  1121.         and.w   d1,d6
  1122.         addx.l  d2,d0
  1123.         addx.l  d3,d1
  1124.         move.b  (a1,d6.l),d5
  1125.         move.b  (a2,d5.l),(a0)+
  1126. .loop_end2
  1127.         dbf     d7,.loop3
  1128. .end2       movem.l (sp)+,d2-d7/a2/a3
  1129.         rts
  1130.  
  1131.         cnop    0,4
  1132.  
  1133. ; 030/040 version
  1134.  
  1135. _R_DrawSpan_040
  1136. @R_DrawSpan_040
  1137.         movem.l d2-d7/a2-a4,-(sp)
  1138.         move.l  (_ds_y),d0
  1139.         move.l  (_ds_x1),d1     ; dest = ylookup[_ds_y] + columnofs[_ds_x1]
  1140.         lea     (_ylookup),a0
  1141.         move.l  (a0,d0.l*4),a0
  1142.         lea     (_columnofs),a1
  1143.         add.l   (a1,d1.l*4),a0
  1144.         move.l  (_ds_source),a1
  1145.         move.l  (_ds_colormap),a2
  1146.         move.l  (_ds_x2),d7     ; count = _ds_x2 - _ds_x1
  1147.         sub.l   d1,d7
  1148.         addq.l  #1,d7
  1149.         move.l  (_ds_xfrac),d0
  1150.         move.l  (_ds_yfrac),d1
  1151.         move.l  (_ds_xstep),d2
  1152.         move.l  (_ds_ystep),d3
  1153.         move.l  a0,d4
  1154.         btst    #0,d4
  1155.         beq     .skipb
  1156.         move.l  d0,d5           ; do the unaligned pixels
  1157.         move.l  d1,d6           ; so we can write to longword
  1158.         swap    d5              ; boundary in the main loop
  1159.         swap    d6
  1160.         and.w   #$3f,d5
  1161.         and.w   #$3f,d6
  1162.         lsl.w   #6,d6
  1163.         or.w    d5,d6
  1164.         move.b  (a1,d6.w),d5
  1165.         add.l   d2,d0
  1166.         move.b  (a2,d5.w),(a0)+
  1167.         add.l   d3,d1
  1168.         move.l  a0,d4
  1169.         subq.l  #1,d7
  1170. .skipb        btst    #1,d4
  1171.         beq     .skips
  1172.         moveq   #2,d4
  1173.         cmp.l   d4,d7
  1174.         bls     .skips
  1175.         move.l  d0,d5           ; write two pixels
  1176.         move.l  d1,d6
  1177.         swap    d5
  1178.         swap    d6
  1179.         and.w   #$3f,d5
  1180.         and.w   #$3f,d6
  1181.         lsl.w   #6,d6
  1182.         or.w    d5,d6
  1183.         move.b  (a1,d6.w),d5
  1184.         move.w  (a2,d5.w),d4
  1185.         add.l   d2,d0
  1186.         add.l   d3,d1
  1187.         move.l  d0,d5
  1188.         move.l  d1,d6
  1189.         swap    d5
  1190.         swap    d6
  1191.         and.w   #$3f,d5
  1192.         and.w   #$3f,d6
  1193.         lsl.w   #6,d6
  1194.         or.w    d5,d6
  1195.         move.b  (a1,d6.w),d5
  1196.         move.b  (a2,d5.w),d4
  1197.         add.l   d2,d0
  1198.         move.w  d4,(a0)+
  1199.         add.l   d3,d1
  1200.         subq.l  #2,d7
  1201. .skips        move.l  a2,d4
  1202.         add.l   #$1000,a1       ; catch 22
  1203.         move.l  a0,a3
  1204.         add.l   d7,a3
  1205.         move.l  d7,d5
  1206.         and.b   #~3,d5
  1207.         move.l  a0,a4
  1208.         add.l   d5,a4
  1209.         eor.w   d0,d1           ; swap fraction parts for addx
  1210.         eor.w   d2,d3
  1211.         eor.w   d1,d0
  1212.         eor.w   d3,d2
  1213.         eor.w   d0,d1
  1214.         eor.w   d2,d3
  1215.         swap    d0
  1216.         swap    d1
  1217.         swap    d2
  1218.         swap    d3
  1219.         lsl.w   #6,d1
  1220.         lsl.w   #6,d3
  1221.         move.w  #$ffc0,d6
  1222.         move.w  #$f03f,d7
  1223.         lsr.w   #2,d5
  1224.         beq     .skip_loop2
  1225.         sub.w   d2,d0
  1226.         add.l   d2,d0           ; setup the X flag
  1227. .loop2        or.w    d6,d0
  1228.         or.w    d7,d1
  1229.         and.w   d1,d0
  1230.         addx.l  d3,d1
  1231.         move.b  (a1,d0.w),d4
  1232.         addx.l  d2,d0
  1233.         move.l  d4,a2
  1234.         move.w  (a2),d5
  1235.         or.w    d6,d0
  1236.         or.w    d7,d1
  1237.         and.w   d1,d0
  1238.         addx.l  d3,d1
  1239.         move.b  (a1,d0.w),d4
  1240.         addx.l  d2,d0
  1241.         move.l  d4,a2
  1242.         move.b  (a2),d5
  1243.         swap    d5
  1244.         or.w    d6,d0
  1245.         or.w    d7,d1
  1246.         and.w   d1,d0
  1247.         addx.l  d3,d1
  1248.         move.b  (a1,d0.w),d4
  1249.         addx.l  d2,d0
  1250.         move.l  d4,a2
  1251.         move.w  (a2),d5
  1252.         or.w    d6,d0
  1253.         or.w    d7,d1
  1254.         and.w   d1,d0
  1255.         addx.l  d3,d1
  1256.         move.b  (a1,d0.w),d4
  1257.         addx.l  d2,d0
  1258.         move.l  d4,a2
  1259.         move.b  (a2),d5
  1260.         move.l  d5,(a0)+
  1261.         cmp.l   a0,a4
  1262.         bne     .loop2
  1263. .skip_loop2
  1264.         sub.w   d2,d0
  1265.         add.l   d2,d0
  1266.  
  1267.         bra     .loop_end2
  1268. .loop3        or.w    d6,d0
  1269.         or.w    d7,d1
  1270.         and.w   d1,d0
  1271.         addx.l  d3,d1
  1272.         move.b  (a1,d0.w),d4
  1273.         addx.l  d2,d0
  1274.         move.l  d4,a2
  1275.         move.b  (a2),(a0)+
  1276. .loop_end2
  1277.         cmp.l   a0,a3
  1278.         bne     .loop3
  1279. .end2        movem.l (sp)+,d2-d7/a2-a4
  1280.         rts
  1281.  
  1282. ;***********************************************************************
  1283.  
  1284.         end
  1285.