home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / d_scan68k.s < prev    next >
Text File  |  2000-06-17  |  67KB  |  2,097 lines

  1. * Copyright (C) 1996-1997 Id Software, Inc. 
  2. * This program is free software; you can redistribute it and/or 
  3. * modify it under the terms of the GNU General Public License 
  4. * as published by the Free Software Foundation; either version 2 
  5. * of the License, or (at your option) any later version. 
  6. * This program is distributed in the hope that it will be useful, 
  7. * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  8. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   
  9. * See the GNU General Public License for more details. 
  10. * You should have received a copy of the GNU General Public License 
  11. * along with this program; if not, write to the Free Software 
  12. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
  13.  
  14. **
  15. ** Quake for AMIGA
  16. ** d_scan.c assembler implementations by Frank Wille <frank@phoenix.owl.de>
  17. **
  18.  
  19.         XREF    _cacheblock
  20.         XREF    _d_sdivzorigin
  21.         XREF    _d_sdivzstepu
  22.         XREF    _d_sdivzstepv
  23.         XREF    _d_tdivzorigin
  24.         XREF    _d_tdivzstepu
  25.         XREF    _d_tdivzstepv
  26.         XREF    _d_ziorigin
  27.         XREF    _d_zistepu
  28.         XREF    _d_zistepv
  29.         XREF    _sadjust
  30.         XREF    _tadjust
  31.         XREF    _sdivz
  32.         XREF    _tdivz
  33.         XREF    _bbextents
  34.         XREF    _bbextentt
  35.         XREF    _d_viewbuffer
  36.         XREF    _screenwidth
  37.         XREF    _cachewidth
  38.         XREF    _d_zwidth
  39.         XREF    _d_pzbuffer
  40.         XREF    _sintable
  41.         XREF    _cl
  42.         XREF    _intsintable
  43.         XREF    _vid
  44.         XREF    _scr_vrect
  45.         XREF    _r_refdef
  46.         XREF    _d_subdiv16
  47.  
  48.         XDEF    _D_WarpScreen
  49.         XDEF    _Turbulent8
  50.         XDEF    _D_DrawSpans8
  51.         XDEF    _D_DrawZSpans
  52.  
  53. QDIV                    =       1
  54. NICE_DIV                =       1
  55.  
  56. PSPAN_NEXT              =       $C
  57. CL_TIME                 =       $23C
  58. VID_BUFFER              =       0
  59. VID_ROWBYTES            =       16
  60. SCR_VRECT_X             =       0
  61. SCR_VRECT_Y             =       4
  62. SCR_VRECT_WIDTH         =       8
  63. SCR_VRECT_HEIGHT        =       12
  64. REFDEF_VRECT_X          =       0
  65. REFDEF_VRECT_Y          =       4
  66. REFDEF_VRECT_WIDTH      =       8
  67. REFDEF_VRECT_HEIGHT     =       12
  68. CVAR_VALUE              =       16
  69.  
  70. CYCLE                   =       128             ;MUST match the #define in d_iface.h!
  71. AMP2                    =       3               ;--
  72. SPEED                   =       20              ;--
  73.  
  74.  
  75. ******************************************************************************
  76. *
  77. *       void _D_WarpScreen (void)
  78. *
  79. *       water effect algorithm
  80. *
  81. ******************************************************************************
  82.  
  83.         cnop    0,4
  84. _D_WarpScreen
  85.  
  86.         rsreset
  87. .rowptr         rs.l    1024
  88. .column         rs.l    1280
  89. .stackframe     rs.l    0
  90.  
  91.         movem.l d2-d7/a2-a6,-(sp)
  92.         fmovem.x        fp2/fp3,-(sp)
  93.         sub.l   #.stackframe,sp
  94.         move.l  sp,a2
  95.         lea     .column(sp),a1
  96.         lea     _vid,a3
  97.         lea     _r_refdef,a4
  98.         lea     _scr_vrect,a5
  99.         move.l  _screenwidth,d4
  100.         move.l  SCR_VRECT_WIDTH(a5),d6
  101.         move.l  SCR_VRECT_HEIGHT(a5),d7
  102.         move.l  REFDEF_VRECT_X(a4),d2
  103.         move.l  REFDEF_VRECT_Y(a4),d3
  104.         fmove.l REFDEF_VRECT_WIDTH(a4),fp0
  105.         fmove.l REFDEF_VRECT_HEIGHT(a4),fp1
  106.  
  107. *        w = r_refdef.vrect.width;
  108. *        h = r_refdef.vrect.height;
  109. *
  110. *        wratio = w / (float)scr_vrect.width;
  111. *        hratio = h / (float)scr_vrect.height;
  112.  
  113.         fmove.s #AMP2*2,fp2
  114.         fmove   fp2,fp3
  115.         fadd    fp0,fp2                 ;fp2 = w + AMP2*2
  116.         fadd    fp1,fp3                 ;fp3 = h + AMP2*2
  117.         fmul.l  d6,fp2                  ;* (float)scr_vrect.width
  118.         fmul.l  d7,fp3                  ;* (float)scr_vrect.height
  119.         fmul    fp0,fp0                 ;w*w
  120.         fmul    fp1,fp1                 ;h*h
  121.         fdiv    fp2,fp0                 ;fp0=wratio*w/(w+AMP2*2)
  122.         fdiv    fp3,fp1                 ;fp1=hratio*h/(h+AMP2*2)
  123.         move.l  VID_ROWBYTES(a3),d5
  124.         mulu    d4,d3                   ;d3=r_refdef.vrect.y*screenwidth
  125.         add.l   _d_viewbuffer,d3        ;d3=d_viewbuffer+d3
  126.         add.l   #AMP2*2,d6
  127.         add.l   #AMP2*2,d7
  128.  
  129. *        for (v=0 ; v<scr_vrect.height+AMP2*2 ; v++)
  130. *        {
  131. *                rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
  132. *                                 (screenwidth * (int)((float)v * hratio * h / (h + AMP2 * 2)));
  133. *        }
  134.  
  135.  
  136.         moveq   #0,d0                   ;v = 0
  137.         move.l  a2,a6                   ;a6 -> rowptr[0]
  138. .loop
  139.         fmove.l d0,fp3                  ;fp3 = (float)v
  140.         fmul    fp1,fp3                 ;(float)v*hratio*h/(h+AMP2*2)
  141.         fmove.l fp3,d1                  ;d1 = (int)fp3
  142.         muls    d4,d1                   ;d1 = d1 * screenwidth
  143.         add.l   d3,d1                   ;d1 = d_viewbuffer+(r_...*scr...)+d1
  144.         addq.l  #1,d0                   ;v++
  145.         move.l  d1,(a6)+                ;rowptr[v] = d1
  146.         cmp.l   d7,d0
  147.         blt.b   .loop
  148.  
  149. *        for (u=0 ; u<scr_vrect.width+AMP2*2 ; u++)
  150. *        {
  151. *                column[u] = r_refdef.vrect.x +
  152. *                                (int)((float)u * wratio * w / (w + AMP2 * 2));
  153. *        }
  154.  
  155.         moveq   #0,d0                   ;u = 0
  156.         move.l  a1,a6                   ;a6 -> column[0]
  157. .loop2
  158.         fmove.l d0,fp2                  ;fp2 = (float)u
  159.         fmul    fp0,fp2                 ;(float)u * wratio*w/(w+AMP2*2)
  160.         fmove.l fp2,d1                  ;d1 = (int)fp2
  161.         add.l   d2,d1                   ;d1 = r_refdef.vrect.x + d1
  162.         addq.l  #1,d0                   ;u++
  163.         move.l  d1,(a6)+                ;column[u] = d1
  164.         cmp.l   d6,d0
  165.         blt.b   .loop2
  166.  
  167. ******  d5 = vid.rowbytes
  168. ******  a1 -> column
  169. ******  a2 -> rowptr
  170.  
  171. *        turb = intsintable + ((int)(cl.time*SPEED)&(CYCLE-1));
  172. *        dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
  173. *        for (v=0 ; v<scr_vrect.height ; v++, dest += vid.rowbytes)
  174. *        {
  175. *                col = &column[turb[v]];
  176. *                row = &rowptr[v];
  177. *                for (u=0 ; u<scr_vrect.width ; u+=4)
  178. *                {
  179. *                        dest[u+0] = row[turb[u+0]][col[u+0]];
  180. *                        dest[u+1] = row[turb[u+1]][col[u+1]];
  181. *                        dest[u+2] = row[turb[u+2]][col[u+2]];
  182. *                        dest[u+3] = row[turb[u+3]][col[u+3]];
  183. *                }
  184. *        }
  185.         move.l  SCR_VRECT_WIDTH(a5),d6
  186.         lsr     #2,d6
  187.         subq    #1,d6
  188.         move.l  SCR_VRECT_HEIGHT(a5),d7
  189.  
  190.         fmove.d _cl+CL_TIME,fp0         ;get cl.time
  191.         fmul.s  #SPEED,fp0              ;fp0 = cl.time*SPEED
  192.         fmove.l fp0,d4                  ;(int)(cl.time*SPEED)
  193.         and.l   #CYCLE-1,d4             ;(int)(cl.time*SPEED)&(CYCLE-1)
  194.         lsl.l   #2,d4
  195.         add.l   #_intsintable,d4        ;turb = _intsintable + 4*d0
  196.  
  197.         move.l  SCR_VRECT_Y(a5),d3
  198.         mulu    d5,d3                   ;vid.rowbytes * scr_vrect.y
  199.         add.l   SCR_VRECT_X(a5),d3      ;d3 + scr_vrect.x
  200.         add.l   VID_BUFFER(a3),d3       ;dest = vid.buffer + d3
  201.  
  202.         moveq   #0,d1
  203. .loop3
  204.         move    d6,d0
  205.         move.l  d4,a6                   ;a6 -> turb[u]
  206.         move.l  0(a6,d1.l*4),d2         ;d2 = turb[v]
  207.         move.l  d3,a0                   ;a0 -> dest[u]
  208.         lea     0(a1,d2.l*4),a4         ;col = &column[turb[v]]
  209.         lea     0(a2,d1.l*4),a5         ;row = &rowptr[v]
  210. .loop4
  211.         move.l  (a6)+,d2                ;d2 = turb[u+0]
  212.         move.l  0(a5,d2.l*4),a3         ;a3 = row[turb[u+0]]
  213.         move.l  (a4)+,d2                ;d2 = col[u+0]
  214.         move.b  0(a3,d2.l),(a0)+        ;dest[u+0]=row[turb[u+0][col[u+0]]
  215.         move.l  (a6)+,d2                ;same for u=1,2,3
  216.         move.l  0(a5,d2.l*4),a3
  217.         move.l  (a4)+,d2
  218.         move.b  0(a3,d2.l),(a0)+
  219.         move.l  (a6)+,d2
  220.         move.l  0(a5,d2.l*4),a3
  221.         move.l  (a4)+,d2
  222.         move.b  0(a3,d2.l),(a0)+
  223.         move.l  (a6)+,d2
  224.         move.l  0(a5,d2.l*4),a3
  225.         move.l  (a4)+,d2
  226.         move.b  0(a3,d2.l),(a0)+
  227.         dbra    d0,.loop4
  228.         add.l   d5,d3
  229.         addq    #1,d1
  230.         cmp     d7,d1
  231.         blt.b   .loop3
  232.         add.l   #.stackframe,sp
  233.         fmovem.x        (sp)+,fp2/fp3
  234.         movem.l (sp)+,d2-d7/a2-a6
  235.         rts
  236.  
  237.  
  238. ******************************************************************************
  239. *
  240. *       void Turbulent8 (espan_t *pspan)
  241. *
  242. *       standard scan drawing function for animated textures
  243. *       Note: The function D_DrawTurbulent8Span was inlined into this
  244. *       function, because it's never used anywhere else.
  245. *
  246. ******************************************************************************
  247.  
  248.         cnop    0,4
  249. _Turbulent8
  250.  
  251. *****   stackframe
  252.  
  253.         rsreset
  254. .saved4         rs.l    1
  255. .saved5         rs.l    1
  256. .savea1         rs.l    1
  257. .szstpu         rs.s    1
  258. .szstpv         rs.s    1
  259. .szorg          rs.s    1
  260. .tzstpu         rs.s    1
  261. .tzstpv         rs.s    1
  262. .tzorg          rs.s    1
  263. .zistpu         rs.s    1
  264. .zistpv         rs.s    1
  265. .ziorg          rs.s    1
  266. .fpuregs        rs.x    6
  267. .intregs        rs.l    11
  268.         rs.l    1
  269. .pspan          rs.l    1
  270.  
  271.  
  272. ******  Prologue. Global variables are put into registers or onto the stackframe
  273.  
  274.         movem.l d2-d7/a2-a6,-(sp)
  275.         fmovem.x        fp2-fp7,-(sp)
  276.         move.l  _bbextentt,a2
  277.         move.l  _tadjust,a3
  278.         move.l  _bbextents,a4
  279.         move.l  _sadjust,a5
  280.         move.l  _d_ziorigin,-(sp)
  281.         move.l  _d_zistepv,-(sp)
  282.         move.l  _d_zistepu,-(sp)
  283.         move.l  _d_tdivzorigin,-(sp)
  284.         move.l  _d_tdivzstepv,-(sp)
  285.         move.l  _d_tdivzstepu,-(sp)
  286.         move.l  _d_sdivzorigin,-(sp)
  287.         move.l  _d_sdivzstepv,-(sp)
  288.         move.l  _d_sdivzstepu,-(sp)
  289.         sub.l   #.szstpu,sp
  290.  
  291. ******  First loop. In every iteration one complete span is drawn
  292.  
  293. *        r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
  294. *
  295. *        r_turb_pbase = (unsigned char *)cacheblock;
  296. *
  297. *        sdivz16stepu = d_sdivzstepu * 16;
  298. *        tdivz16stepu = d_tdivzstepu * 16;
  299. *        zi16stepu = d_zistepu * 16;
  300. *
  301. *        do
  302. *        {
  303. *                r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
  304. *                                (screenwidth * pspan->v) + pspan->u);
  305. *
  306. *                count = pspan->count;
  307. *
  308. *        // calculate the initial s/z, t/z, 1/z, s, and t and clamp
  309. *                du = (float)pspan->u;
  310. *                dv = (float)pspan->v;
  311. *
  312. *                sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
  313. *                tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
  314. *                zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  315. *                z = (float)0x10000 / zi;        // prescale to 16.16 fixed-point
  316. *
  317.  
  318.         fmove.d _cl+CL_TIME,fp0         ;get cl.time
  319.         fmul.s  #SPEED,fp0              ;fp0 = cl.time*SPEED
  320.         fmove.l fp0,d0                  ;(int)(cl.time*SPEED)
  321.         and.l   #CYCLE-1,d0             ;(int)(cl.time*SPEED)&(CYCLE-1)
  322.         lsl.l   #2,d0
  323.         add.l   #_sintable,d0           ;r_turb_turb = _sintable + 4*d0
  324.         move.l  d0,a6
  325.         fmove.s #16,fp7
  326.         fmove.s .szstpu(sp),fp3
  327.         fmul    fp7,fp3                 ;sdivz16stepu = d_sdivzstepu * 16
  328.         fmove.s .tzstpu(sp),fp4
  329.         fmul    fp7,fp4                 ;tdivz16stepu = d_tdivzstepu * 16
  330.         fmove.s .zistpu(sp),fp5
  331.         fmul    fp7,fp5                 ;zi16stepu = d_zistepu * 16
  332.         move.l  .pspan(sp),a1           ;get function parameter
  333. .loop
  334.         move.l  a1,.savea1(sp)          ;save actual ptr to pspan
  335.         move.l  _d_viewbuffer,a0
  336.         move.l  _screenwidth,d0
  337.         move.l  (a1)+,d1
  338.         fmove.l d1,fp2                  ;du = (float)pspan->u
  339.         move.l  (a1)+,d2
  340.         fmove.l d2,fp7                  ;dv = (float)pspan->v
  341.         move.l  (a1)+,d4
  342.         muls    d2,d0                   ;d0 = screenwidth * pspan->v
  343.         add.l   d1,d0
  344.         add.l   d0,a0                   ;pdest = d_viewbuffer + pspan->u + d0
  345.         lea     .szstpu(sp),a1          ;a1 -> stackframe
  346.         fmove.s (a1)+,fp0
  347.         fmul    fp2,fp0                 ;fp0 = du * d_sdivzstepu
  348.         fmove.s (a1)+,fp1
  349.         fmul    fp7,fp1                 ;fp1 = dv * d_sdivzstepv
  350.         fadd    fp1,fp0
  351.         fadd.s  (a1)+,fp0               ;sdivz = d_sdivzorigin + fp0 + fp1
  352.         fmove.s (a1)+,fp1
  353.         fmul    fp2,fp1                 ;fp1 = du * d_tdivzstepu
  354.         fmove.s (a1)+,fp6
  355.         fmul    fp7,fp6                 ;fp6 = dv * d_tdivzstepv
  356.         fadd    fp6,fp1
  357.         fadd.s  (a1)+,fp1               ;tdivz = d_tdivzorigin + fp1 + fp6
  358.         fmul.s  (a1)+,fp2               ;fp2 = du * d_zistepu
  359.         fmul.s  (a1)+,fp7               ;fp7 = dv * d_zistepv
  360.         fadd    fp7,fp2
  361.         fadd.s  (a1)+,fp2               ;zi = d_ziorigin + fp2 + fp7
  362.         fmove.s #65536,fp6
  363.         fdiv    fp2,fp6                 ;z = (float)0x10000 / zi
  364.  
  365. *                s = (int)(sdivz * z) + sadjust;
  366. *                if (s > bbextents)
  367. *                        s = bbextents;
  368. *                else if (s < 0)
  369. *                        s = 0;
  370. *
  371. *                t = (int)(tdivz * z) + tadjust;
  372. *                if (t > bbextentt)
  373. *                        t = bbextentt;
  374. *                else if (t < 0)
  375. *                        t = 0;
  376.  
  377.  
  378.         fmove   fp6,fp7
  379.         fmul    fp0,fp7                 ;fp7 = sdivz * z
  380.         fmove.l fp7,d6                  ;convert to integer
  381.         add.l   a5,d6                   ;s = d6 + sadjust
  382.         cmp.l   a4,d6                   ;if (s > bbextents)
  383.         bgt.b   .down
  384.         tst.l   d6                      ;if (s < 0)
  385.         bge.b   .keep
  386. .up
  387.         moveq   #0,d6                   ;s = 0
  388.         bra.b   .keep
  389. .down
  390.         move.l  a4,d6                   ;s = bbextents
  391. .keep
  392.         fmul    fp1,fp6                 ;fp6 = tdivz * z
  393.         fmove.l fp6,d7                  ;convert to integer
  394.         add.l   a3,d7                   ;t = d7 + tadjust
  395.         cmp.l   a2,d7                   ;if (t > bbextentt)
  396.         bgt.b   .down2
  397.         tst.l   d7                      ;if (t < 0)
  398.         bge.b   .keep2
  399. .up2
  400.         moveq   #0,d7                   ;t = 0
  401.         bra.b   .keep2
  402. .down2
  403.         move.l  a2,d7                   ;t = bbextentt
  404. .keep2
  405.         move.l  d4,d1
  406.  
  407.  
  408. ******  Second loop. In every iteration one part of the whole span is drawn
  409. ******  d2 gets the value (spancount-1)! [NOT spancount]
  410.  
  411. ******  d1 = count
  412.  
  413. *                do
  414. *                {
  415. *                // calculate s and t at the far end of the span
  416. *                        if (count >= 16)
  417. *                                spancount = 16;
  418. *                        else
  419. *                                spancount = count;
  420. *
  421. *                        count -= spancount;
  422. *
  423. *                        if (count)
  424. *                        {
  425.  
  426. .loop2
  427.         moveq   #16-1,d2                ;spancount = 16
  428.         cmp.l   #16,d1                  ;if (count >= 16)
  429.         bgt.b   .cont
  430.         move.l  d1,d2                   ;spancount = count
  431.         subq.l  #1,d2
  432.         moveq   #0,d1                   ;count -= spancount
  433.         bra.w   .finalpart
  434. .cont
  435.         sub.l   #16,d1                  ;count -= spancount;
  436.  
  437.  
  438. ******  Evaluation of the values for the inner loop. This version is used for
  439. ******  span size = 16
  440.  
  441. ******  a2  : bbextentt
  442. ******  a3  : tadjust
  443. ******  a4  : bbextents
  444. ******  a5  : sadjust
  445. ******  fp0 : sdivz
  446. ******  fp1 : tdivz
  447. ******  fp2 : zi
  448. ******  fp3 : sdivz16stepu
  449. ******  fp4 : tdivz16stepu
  450. ******  fp5 : zi16stepu
  451.  
  452. *                        // calculate s/z, t/z, zi->fixed s and t at far end of span,
  453. *                        // calculate s and t steps across span by shifting
  454. *                                sdivz += sdivz16stepu;
  455. *                                tdivz += tdivz16stepu;
  456. *                                zi += zi16stepu;
  457. *                                z = (float)0x10000 / zi;        // prescale to 16.16 fixed-point
  458. *
  459. *                                snext = (int)(sdivz * z) + sadjust;
  460. *                                if (snext > bbextents)
  461. *                                        snext = bbextents;
  462. *                                else if (snext < 16)
  463. *                                        snext = 16;     // prevent round-off error on <0 steps from
  464. *                                                                //  from causing overstepping & running off the
  465. *                                                                //  edge of the texture
  466. *
  467. *                                tnext = (int)(tdivz * z) + tadjust;
  468. *                                if (tnext > bbextentt)
  469. *                                        tnext = bbextentt;
  470. *                                else if (tnext < 16)
  471. *                                        tnext = 16;     // guard against round-off error on <0 steps
  472. *
  473. *                                r_turb_sstep = (snext - r_turb_s) >> 4;
  474. *                                r_turb_tstep = (tnext - r_turb_t) >> 4;
  475. *                        }
  476.  
  477.         fadd    fp3,fp0                 ;sdivz += sdivz16stepu
  478.         fadd    fp4,fp1                 ;tdivz += tdivz16stepu
  479.         fadd    fp5,fp2                 ;zi += zi16stepu
  480.         fmove.s #65536,fp7
  481.         fdiv    fp2,fp7                 ;z = (float)0x10000 / zi;
  482.         fmove   fp7,fp6
  483.         fmul    fp0,fp6                 ;fp2 = sdivz * z
  484.         fmove.l fp6,d4                  ;convert to integer
  485.         add.l   a5,d4                   ;snext = d4 + sadjust
  486.         cmp.l   a4,d4                   ;if (snext > bbextents)
  487.         bgt.b   .down3
  488.         cmp.l   #16,d4                  ;if (snext < 16)
  489.         bge.b   .keep3
  490. .up3
  491.         moveq   #16,d4                  ;snext = 16
  492.         bra.b   .keep3
  493. .down3
  494.         move.l  a4,d4                   ;snext = bbextents
  495. .keep3
  496.         fmul    fp1,fp7                 ;fp7 = tdivz * z
  497.         fmove.l fp7,d5                  ;convert to integer
  498.         add.l   a3,d5                   ;tnext = d5 + tadjust
  499.         cmp.l   a2,d5                   ;if (tnext > bbextentt)
  500.         bgt.b   .down4
  501.         cmp.l   #16,d5                  ;if (tnext < 16)
  502.         bge.b   .keep4
  503. .up4
  504.         moveq   #16,d5                  ;tnext = 16
  505.         bra.b   .keep4
  506. .down4
  507.         move.l  a2,d5                   ;tnext = bbextentt
  508. .keep4
  509.         move.l  d4,.saved4(sp)          ;save snext
  510.         move.l  d5,.saved5(sp)          ;save tnext
  511.         sub.l   d6,d4                   ;d4 = snext - s
  512.         sub.l   d7,d5                   ;d5 = tnext - t
  513.         asr.l   #4,d4                   ;r_turb_sstep = d4 >> 4
  514.         asr.l   #4,d5                   ;r_turb_tstep = d5 >> 4
  515.         bra.w   .mainloop
  516.  
  517.  
  518. ******  Evaluation of the values for the inner loop. This version is used for
  519. ******  span size < 16
  520.  
  521. ******  The original algorithm has two ugly divisions at the end of this part.
  522. ******  These are removed by the following optimization:
  523. ******  First, the divisors 1,2 and 4 are handled specially to gain speed. The
  524. ******  other divisors are handled using a reciprocal table.
  525.  
  526. ******  a2  : bbextentt
  527. ******  a3  : tadjust
  528. ******  a4  : bbextents
  529. ******  a5  : sadjust
  530. ******  fp0 : sdivz
  531. ******  fp1 : tdivz
  532. ******  fp2 : zi
  533.  
  534. *                        // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
  535. *                        // can't step off polygon), clamp, calculate s and t steps across
  536. *                        // span by division, biasing steps low so we don't run off the
  537. *                        // texture
  538. *                                spancountminus1 = (float)(r_turb_spancount - 1);
  539. *                                sdivz += d_sdivzstepu * spancountminus1;
  540. *                                tdivz += d_tdivzstepu * spancountminus1;
  541. *                                zi += d_zistepu * spancountminus1;
  542. *                                z = (float)0x10000 / zi;        // prescale to 16.16 fixed-point
  543. *                                snext = (int)(sdivz * z) + sadjust;
  544. *                                if (snext > bbextents)
  545. *                                        snext = bbextents;
  546. *                                else if (snext < 16)
  547. *                                        snext = 16;     // prevent round-off error on <0 steps from
  548. *                                                                //  from causing overstepping & running off the
  549. *                                                                //  edge of the texture
  550. *
  551. *                                tnext = (int)(tdivz * z) + tadjust;
  552. *                                if (tnext > bbextentt)
  553. *                                        tnext = bbextentt;
  554. *                                else if (tnext < 16)
  555. *                                        tnext = 16;     // guard against round-off error on <0 steps
  556. *
  557. *                                if (r_turb_spancount > 1)
  558. *                                {
  559. *                                        r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
  560. *                                        r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
  561. *                                }
  562. *                        }
  563.  
  564. .finalpart
  565.         fmove.l d2,fp7                  ;spancountminus1 = (float)(r_turb_spancount-1)
  566.         fmove   fp7,fp6
  567.         fmul.s  .szstpu(sp),fp6         ;fp6 = d_sdivzstepu * spancountminus1
  568.         fadd    fp6,fp0                 ;sdivz += fp6
  569.         fmove   fp7,fp6
  570.         fmul.s  .tzstpu(sp),fp6         ;fp6 = d_tdivzstepu * spancountminus1
  571.         fadd    fp6,fp1                 ;tdivz += fp6
  572.         fmul.s  .zistpu(sp),fp7         ;fp7 = d_zistepu * spancountminus1
  573.         fadd    fp7,fp2                 ;zi += fp7
  574.         fmove.s #65536,fp7
  575.         fdiv    fp2,fp7                 ;z = (float)0x10000 / zi;
  576.         fmove   fp7,fp6
  577.         fmul    fp0,fp6                 ;fp6 = sdivz * z
  578.         fmove.l fp6,d4                  ;convert to integer
  579.         add.l   a5,d4                   ;snext = d4 + sadjust
  580.         cmp.l   a4,d4                   ;if (snext > bbextents)
  581.         bgt.b   .down5
  582.         cmp.l   #16,d4                  ;if (snext < 16)
  583.         bge.b   .keep5
  584. .up5
  585.         moveq   #16,d4                  ;snext = 16
  586.         bra.b   .keep5
  587. .down5
  588.         move.l  a4,d4                   ;snext = bbextents
  589. .keep5
  590.         fmul    fp1,fp7                 ;fp7 = tdivz * z
  591.         fmove.l fp7,d5                  ;convert to integer
  592.         add.l   a3,d5                   ;tnext = d5 + tadjust
  593.         cmp.l   a2,d5                   ;if (tnext > bbextentt)
  594.         bgt.b   .down6
  595.         cmp.l   #16,d5                  ;if (tnext < 16)
  596.         bge.b   .keep6
  597. .up6
  598.         moveq   #16,d5                  ;tnext = 16
  599.         bra.b   .keep6
  600. .down6
  601.         move.l  a2,d5                   ;tnext = bbextentt
  602. .keep6
  603.         move.l  d4,.saved4(sp)          ;save snext
  604.         move.l  d5,.saved5(sp)          ;save tnext
  605.         sub.l   d6,d4                   ;d4 = snext - r_turb_s
  606.         sub.l   d7,d5                   ;d5 = tnext - r_turb_t
  607.         IFEQ    QDIV
  608.         tst.l   d2
  609.         beq.w   .mainloop
  610.         divs.l  d2,d4
  611.         divs.l  d2,d5
  612.         ELSEIF
  613.         cmp     #5,d2                   ;(r_turb_spancount-1) < 5?
  614.         blt.b   .special                ;yes -> special case
  615.         cmp     #8,d2
  616.         beq.b   .spec_8
  617. .qdiv
  618.         IFNE    NICE_DIV
  619.         lsl.l   #2,d4
  620.         lsl.l   #2,d5
  621.         lea     ReciprocTable,a1
  622.         move    0(a1,d2.w*2),d0
  623.         move.l  d4,d3
  624.         mulu    d0,d3
  625.         clr     d3
  626.         swap    d3
  627.         swap    d4
  628.         muls    d0,d4
  629.         add.l   d3,d4
  630.         move.l  d5,d3
  631.         mulu    d0,d3
  632.         clr     d3
  633.         swap    d3
  634.         swap    d5
  635.         muls    d0,d5
  636.         add.l   d3,d5
  637.         bra.b   .mainloop
  638.         ELSEIF
  639.         asr.l   #7,d4                   ;d4 >> 7
  640.         asr.l   #7,d5                   ;d5 >> 7
  641.         lea     ReciprocTable,a1        ;a1 -> reciprocal table
  642.         move    0(a1,d2.w*2),d0         ;d0 = (1/(r_turb_spancount-1))<<16
  643.         muls    d0,d4                   ;d4 = d4 / (r_turb_spancount-1)
  644.         asr.l   #7,d4                   ;sstep = d4 >> 7
  645.         muls    d0,d5                   ;d5 = d5 / (r_turb_spancount-1)
  646.         asr.l   #7,d5                   ;tstep = d5 >> 7
  647.         bra.b   .mainloop
  648.         ENDC
  649. .special
  650.         cmp     #1,d2                   ;switch (r_turb_spancount-1)
  651.         ble.b   .mainloop               ;0,1 -> no scaling needed
  652.         cmp     #3,d2                   ;3 -> standard qdiv
  653.         beq.b   .qdiv
  654.         blt.b   .spec_2
  655.         asr.l   #2,d4                   ;4 -> scale by shifting right
  656.         asr.l   #2,d5
  657.         bra.b   .mainloop
  658. .spec_8
  659.         asr.l   #3,d4                   ;8 -> scale by shifting right
  660.         asr.l   #3,d5
  661.         bra.b   .mainloop
  662. .spec_2
  663.         asr.l   #1,d4                   ;2 -> scale by shifting right
  664.         asr.l   #1,d5
  665.         ENDC
  666.  
  667. ******  D_DrawTurbulent8Span (inlined)
  668. ******  Main drawing loop.
  669.  
  670. ******  d2 : r_turb_spancount
  671. ******  d4 : r_turb_sstep
  672. ******  d5 : r_turb_tstep
  673. ******  d6 : r_turb_s
  674. ******  d7 : r_turb_t
  675. ******  a0 : r_turb_pdest
  676. ******  a6 : r_turb_turb
  677.  
  678. *        do
  679. *        {
  680. *                sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
  681. *                tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
  682. *                *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
  683. *                r_turb_s += r_turb_sstep;
  684. *                r_turb_t += r_turb_tstep;
  685. *        } while (--r_turb_spancount > 0);
  686.  
  687. .mainloop
  688.         move.l  d1,-(sp)
  689.         move.l  _cacheblock,a1          ;pbase = (unsigned char *)cacheblock
  690.         moveq   #10,d1
  691. .draw
  692.         swap    d6                      ;r_turb_s >> 16
  693.         swap    d7                      ;r_turb_t >> 16
  694.         and     #CYCLE-1,d6             ;(r_turb_s >> 16) & (CYCLE-1)
  695.         and     #CYCLE-1,d7             ;(r_turb_t >> 16) & (CYCLE-1)
  696.         move.l  0(a6,d7.w*4),d0         ;r_turb_turb [d7]
  697.         move.l  0(a6,d6.w*4),d3         ;r_turb_turb [d6]
  698.         swap    d6
  699.         swap    d7
  700.         add.l   d6,d0                   ;r_turb_s + r_turb_turb []
  701.         add.l   d7,d3                   ;r_turb_t + r_turb_turb []
  702.         swap    d0                      ;d0 >> 16
  703.         and.l   #$3f,d0                 ;sturb = (d0 >> 16) & 63
  704.         lsr.l   d1,d3                   ;(d3 >> (16-6))
  705.         and.l   #$fc0,d3                ;tturb<<6 = (d3 >> (16-6)) & (63 << 6)
  706.         add.l   d3,d0                   ;sturb + tturb << 6
  707.         move.b  0(a1,d0.l),(a0)+        ;*r_turb_pdest++ = *(r_turb_pbase + d0)
  708.         add.l   d4,d6                   ;r_turb_s += r_turb_sstep
  709.         add.l   d5,d7                   ;r_turb_t += r_turb_tstep
  710.         dbra    d2,.draw                ;while (--r_turb_spancount > 0)
  711.         move.l  (sp)+,d1
  712.  
  713. ******  loop terminations
  714.  
  715.  
  716.         move.l   .saved5(sp),d7         ;r_turb_t = tnext
  717.         move.l   .saved4(sp),d6         ;r_turb_s = snext
  718.  
  719.         tst.l   d1                      ;while (count > 0)
  720.         bgt.w   .loop2
  721.  
  722.         move.l  .savea1(sp),a1          ;while ((pspan = pspan->next) != NULL)
  723.         move.l  PSPAN_NEXT(a1),a1
  724.         tst.l   a1
  725.         bne.w   .loop
  726.         add.l   #.fpuregs,sp
  727.         fmovem.x        (sp)+,fp2-fp7
  728.         movem.l (sp)+,d2-d7/a2-a6
  729.         rts
  730.  
  731.  
  732.  
  733.  
  734.  
  735.  
  736.  
  737.  
  738.  
  739.  
  740.  
  741.  
  742. ******************************************************************************
  743. *
  744. *       void D_DrawSpans8 (espan_t *pspan)
  745. *
  746. *       standard scan drawing function (8 pixel subdivision)
  747. *
  748. ******************************************************************************
  749.  
  750.         cnop    0,4
  751. _D_DrawSpans8
  752.  
  753.  
  754. *****   stackframe
  755.  
  756.         rsreset
  757. .saved4         rs.l    1
  758. .saved5         rs.l    1
  759. .savea6         rs.l    1
  760. .szstpu         rs.s    1
  761. .szstpv         rs.s    1
  762. .szorg          rs.s    1
  763. .tzstpu         rs.s    1
  764. .tzstpv         rs.s    1
  765. .tzorg          rs.s    1
  766. .zistpu         rs.s    1
  767. .zistpv         rs.s    1
  768. .ziorg          rs.s    1
  769. .fpuregs        rs.x    6
  770. .intregs        rs.l    11
  771.         rs.l    1
  772. .pspan          rs.l    1
  773.  
  774.  
  775. ******  Prologue. Global variables are put into registers or onto the stackframe
  776.  
  777.         fmove.s _d_subdiv16+CVAR_VALUE,fp0
  778.         fcmp.s  #0,fp0
  779.         fbne    _D_DrawSpans16
  780.         movem.l d2-d7/a2-a6,-(sp)
  781.         fmovem.x        fp2-fp7,-(sp)
  782.         move.l  _bbextentt,a2
  783.         move.l  _tadjust,a3
  784.         move.l  _bbextents,a4
  785.         move.l  _sadjust,a5
  786.         move.l  _d_ziorigin,-(sp)
  787.         move.l  _d_zistepv,-(sp)
  788.         move.l  _d_zistepu,-(sp)
  789.         move.l  _d_tdivzorigin,-(sp)
  790.         move.l  _d_tdivzstepv,-(sp)
  791.         move.l  _d_tdivzstepu,-(sp)
  792.         move.l  _d_sdivzorigin,-(sp)
  793.         move.l  _d_sdivzstepv,-(sp)
  794.         move.l  _d_sdivzstepu,-(sp)
  795.         sub.l   #.szstpu,sp
  796.  
  797. ******  First loop. In every iteration one complete span is drawn
  798.  
  799. *        pbase = (unsigned char *)cacheblock;
  800. *
  801. *        sdivz8stepu = d_sdivzstepu * 8;
  802. *        tdivz8stepu = d_tdivzstepu * 8;
  803. *        zi8stepu = d_zistepu * 8;
  804. *
  805. *        do
  806. *        {
  807. *                pdest = (unsigned char *)((byte *)d_viewbuffer +
  808. *                                (screenwidth * pspan->v) + pspan->u);
  809. *
  810. *                count = pspan->count;
  811. *
  812. *        // calculate the initial s/z, t/z, 1/z, s, and t and clamp
  813. *                du = (float)pspan->u;
  814. *                dv = (float)pspan->v;
  815. *
  816. *                sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
  817. *                tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
  818. *                zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  819. *                z = (float)0x10000 / zi;        // prescale to 16.16 fixed-point
  820. *
  821.  
  822.         move.l  _cacheblock,a1          ;pbase = (unsigned char *)cacheblock
  823.         fmove.s #8,fp7
  824.         fmove.s .szstpu(sp),fp3
  825.         fmul    fp7,fp3                 ;sdivz8stepu = d_sdivzstepu * 8
  826.         fmove.s .tzstpu(sp),fp4
  827.         fmul    fp7,fp4                 ;tdivz8stepu = d_tdivzstepu * 8
  828.         fmove.s .zistpu(sp),fp5
  829.         fmul    fp7,fp5                 ;zi8stepu = d_zistepu * 8
  830.         move.l  .pspan(sp),a6           ;get function parameter
  831. .loop
  832.         move.l  a6,.savea6(sp)          ;save actual ptr to pspan
  833.         move.l  _d_viewbuffer,a0
  834.         move.l  _screenwidth,d0
  835.         move.l  (a6)+,d1
  836.         fmove.l d1,fp2                  ;du = (float)pspan->u
  837.         move.l  (a6)+,d2
  838.         fmove.l d2,fp7                  ;dv = (float)pspan->v
  839.         move.l  (a6)+,d4
  840.         muls    d2,d0                   ;d0 = screenwidth * pspan->v
  841.         add.l   d1,d0
  842.         add.l   d0,a0                   ;pdest = d_viewbuffer + pspan->u + d0
  843.         lea     .szstpu(sp),a6          ;a6 -> stackframe
  844.         fmove.s (a6)+,fp0
  845.         fmul    fp2,fp0                 ;fp0 = du * d_sdivzstepu
  846.         fmove.s (a6)+,fp1
  847.         fmul    fp7,fp1                 ;fp1 = dv * d_sdivzstepv
  848.         fadd    fp1,fp0
  849.         fadd.s  (a6)+,fp0               ;sdivz = d_sdivzorigin + fp0 + fp1
  850.         fmove.s (a6)+,fp1
  851.         fmul    fp2,fp1                 ;fp1 = du * d_tdivzstepu
  852.         fmove.s (a6)+,fp6
  853.         fmul    fp7,fp6                 ;fp6 = dv * d_tdivzstepv
  854.         fadd    fp6,fp1
  855.         fadd.s  (a6)+,fp1               ;tdivz = d_tdivzorigin + fp1 + fp6
  856.         fmul.s  (a6)+,fp2               ;fp2 = du * d_zistepu
  857.         fmul.s  (a6)+,fp7               ;fp7 = dv * d_zistepv
  858.         fadd    fp7,fp2
  859.         fadd.s  (a6)+,fp2               ;zi = d_ziorigin + fp2 + fp7
  860.         fmove.s #65536,fp6
  861.         fdiv    fp2,fp6                 ;z = (float)0x10000 / zi
  862.  
  863. *                s = (int)(sdivz * z) + sadjust;
  864. *                if (s > bbextents)
  865. *                        s = bbextents;
  866. *                else if (s < 0)
  867. *                        s = 0;
  868. *
  869. *                t = (int)(tdivz * z) + tadjust;
  870. *                if (t > bbextentt)
  871. *                        t = bbextentt;
  872. *                else if (t < 0)
  873. *                        t = 0;
  874.  
  875.  
  876.         fmove   fp6,fp7
  877.         fmul    fp0,fp7                 ;fp7 = sdivz * z
  878.         fmove.l fp7,d6                  ;convert to integer
  879.         add.l   a5,d6                   ;s = d6 + sadjust
  880.         cmp.l   a4,d6                   ;if (s > bbextents)
  881.         bgt.b   .down
  882.         tst.l   d6                      ;if (s < 0)
  883.         bge.b   .keep
  884. .up
  885.         moveq   #0,d6                   ;s = 0
  886.         bra.b   .keep
  887. .down
  888.         move.l  a4,d6                   ;s = bbextents
  889. .keep
  890.         fmul    fp1,fp6                 ;fp6 = tdivz * z
  891.         fmove.l fp6,d7                  ;convert to integer
  892.         add.l   a3,d7                   ;t = d7 + tadjust
  893.         cmp.l   a2,d7                   ;if (t > bbextentt)
  894.         bgt.b   .down2
  895.         tst.l   d7                      ;if (t < 0)
  896.         bge.b   .keep2
  897. .up2
  898.         moveq   #0,d7                   ;t = 0
  899.         bra.b   .keep2
  900. .down2
  901.         move.l  a2,d7                   ;t = bbextentt
  902. .keep2
  903.         move.l  d4,d1
  904.  
  905. ******  Second loop. In every iteration one part of the whole span is drawn
  906. ******  d2 gets the value (spancount-1)! [NOT spancount]
  907.  
  908. ******  d1 = count
  909.  
  910. *                do
  911. *                {
  912. *                // calculate s and t at the far end of the span
  913. *                        if (count >= 8)
  914. *                                spancount = 8;
  915. *                        else
  916. *                                spancount = count;
  917. *
  918. *                        count -= spancount;
  919. *
  920. *                        if (count)
  921. *                        {
  922.  
  923. .loop2
  924.         moveq   #8-1,d2                 ;spancount = 8
  925.         cmp.l   #8,d1                   ;if (count >= 8)
  926.         bgt.b   .cont
  927.         move.l  d1,d2                   ;spancount = count
  928.         subq.l  #1,d2
  929.         moveq   #0,d1                   ;count -= spancount
  930.         bra.w   .finalpart
  931. .cont
  932.         subq.l  #8,d1                   ;count -= spancount;
  933.  
  934. ******  Evaluation of the values for the inner loop. This version is used for
  935. ******  span size = 8
  936.  
  937. ******  a2  : bbextentt
  938. ******  a3  : tadjust
  939. ******  a4  : bbextents
  940. ******  a5  : sadjust
  941. ******  fp0 : sdivz
  942. ******  fp1 : tdivz
  943. ******  fp2 : zi
  944. ******  fp3 : sdivz8stepu
  945. ******  fp4 : tdivz8stepu
  946. ******  fp5 : zi8stepu
  947.  
  948. *                        // calculate s/z, t/z, zi->fixed s and t at far end of span,
  949. *                        // calculate s and t steps across span by shifting
  950. *                                sdivz += sdivz8stepu;
  951. *                                tdivz += tdivz8stepu;
  952. *                                zi += zi8stepu;
  953. *                                z = (float)0x10000 / zi;        // prescale to 16.16 fixed-point
  954. *                                snext = (int)(sdivz * z) + sadjust;
  955. *                                if (snext > bbextents)
  956. *                                        snext = bbextents;
  957. *                                else if (snext < 8)
  958. *                                        snext = 8;      // prevent round-off error on <0 steps from
  959. *                                                                //  from causing overstepping & running off the
  960. *                                                                //  edge of the texture
  961. *                                tnext = (int)(tdivz * z) + tadjust;
  962. *                                if (tnext > bbextentt)
  963. *                                        tnext = bbextentt;
  964. *                                else if (tnext < 8)
  965. *                                        tnext = 8;      // guard against round-off error on <0 steps
  966. *                                sstep = (snext - s) >> 3;
  967. *                                tstep = (tnext - t) >> 3;
  968. *                        }
  969.  
  970.         fadd    fp3,fp0                 ;sdivz += sdivz8stepu
  971.         fadd    fp4,fp1                 ;tdivz += tdivz8stepu
  972.         fadd    fp5,fp2                 ;zi += zi8stepu
  973.         fmove.s #65536,fp7
  974.         fdiv    fp2,fp7                 ;z = (float)0x10000 / zi;
  975.         fmove   fp7,fp6
  976.         fmul    fp0,fp6                 ;fp2 = sdivz * z
  977.         fmove.l fp6,d4                  ;convert to integer
  978.         add.l   a5,d4                   ;snext = d4 + sadjust
  979.         cmp.l   a4,d4                   ;if (snext > bbextents)
  980.         bgt.b   .down3
  981.         cmp.l   #8,d4                   ;if (snext < 8)
  982.         bge.b   .keep3
  983. .up3
  984.         moveq   #8,d4                   ;snext = 8
  985.         bra.b   .keep3
  986. .down3
  987.         move.l  a4,d4                   ;snext = bbextents
  988. .keep3
  989.         fmul    fp1,fp7                 ;fp7 = tdivz * z
  990.         fmove.l fp7,d5                  ;convert to integer
  991.         add.l   a3,d5                   ;tnext = d5 + tadjust
  992.         cmp.l   a2,d5                   ;if (tnext > bbextentt)
  993.         bgt.b   .down4
  994.         cmp.l   #8,d5                   ;if (tnext < 8)
  995.         bge.b   .keep4
  996. .up4
  997.         moveq   #8,d5                   ;tnext = 8
  998.         bra.b   .keep4
  999. .down4
  1000.         move.l  a2,d5                   ;tnext = bbextentt
  1001. .keep4
  1002.         move.l  d4,.saved4(sp)          ;save snext
  1003.         move.l  d5,.saved5(sp)          ;save tnext
  1004.         sub.l   d6,d4                   ;d4 = snext - s
  1005.         sub.l   d7,d5                   ;d5 = tnext - t
  1006.         asr.l   #3,d4                   ;sstep = d4 >> 3
  1007.         asr.l   #3,d5                   ;tstep = d5 >> 3
  1008.         bra.w   .mainloop
  1009.  
  1010.  
  1011. ******  Evaluation of the values for the inner loop. This version is used for
  1012. ******  span size < 8
  1013.  
  1014. ******  The original algorithm has two ugly divisions at the end of this part.
  1015. ******  These are removed by the following optimization:
  1016. ******  First, the divisors 1,2 and 4 are handled specially to gain speed. The
  1017. ******  other divisors are handled using a reciprocal table.
  1018.  
  1019. ******  a2  : bbextentt
  1020. ******  a3  : tadjust
  1021. ******  a4  : bbextents
  1022. ******  a5  : sadjust
  1023. ******  fp0 : sdivz
  1024. ******  fp1 : tdivz
  1025. ******  fp2 : zi
  1026.  
  1027. *                        // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
  1028. *                        // can't step off polygon), clamp, calculate s and t steps across
  1029. *                        // span by division, biasing steps low so we don't run off the
  1030. *                        // texture
  1031. *                                spancountminus1 = (float)(spancount - 1);
  1032. *                                sdivz += d_sdivzstepu * spancountminus1;
  1033. *                                tdivz += d_tdivzstepu * spancountminus1;
  1034. *                                zi += d_zistepu * spancountminus1;
  1035. *                                z = (float)0x10000 / zi;        // prescale to 16.16 fixed-point
  1036. *                                snext = (int)(sdivz * z) + sadjust;
  1037. *                                if (snext > bbextents)
  1038. *                                        snext = bbextents;
  1039. *                                else if (snext < 8)
  1040. *                                        snext = 8;      // prevent round-off error on <0 steps from
  1041. *                                                                //  from causing overstepping & running off the
  1042. *                                                                //  edge of the texture
  1043. *
  1044. *                                tnext = (int)(tdivz * z) + tadjust;
  1045. *                                if (tnext > bbextentt)
  1046. *                                        tnext = bbextentt;
  1047. *                                else if (tnext < 8)
  1048. *                                        tnext = 8;      // guard against round-off error on <0 steps
  1049. *
  1050. *                                if (spancount > 1)
  1051. *                                {
  1052. *                                        sstep = (snext - s) / (spancount - 1);
  1053. *                                        tstep = (tnext - t) / (spancount - 1);
  1054. *                                }
  1055. *                        }
  1056.  
  1057. .finalpart
  1058.         fmove.l d2,fp7                  ;spancountminus1 = (float)(spancount-1)
  1059.         fmove   fp7,fp6
  1060.         fmul.s  .szstpu(sp),fp6         ;fp6 = d_sdivzstepu * spancountminus1
  1061.         fadd    fp6,fp0                 ;sdivz += fp6
  1062.         fmove   fp7,fp6
  1063.         fmul.s  .tzstpu(sp),fp6         ;fp6 = d_tdivzstepu * spancountminus1
  1064.         fadd    fp6,fp1                 ;tdivz += fp6
  1065.         fmul.s  .zistpu(sp),fp7         ;fp7 = d_zistepu * spancountminus1
  1066.         fadd    fp7,fp2                 ;zi += fp7
  1067.         fmove.s #65536,fp7
  1068.         fdiv    fp2,fp7                 ;z = (float)0x10000 / zi;
  1069.         fmove   fp7,fp6
  1070.         fmul    fp0,fp6                 ;fp6 = sdivz * z
  1071.         fmove.l fp6,d4                  ;convert to integer
  1072.         add.l   a5,d4                   ;snext = d4 + sadjust
  1073.         cmp.l   a4,d4                   ;if (snext > bbextents)
  1074.         bgt.b   .down5
  1075.         cmp.l   #8,d4                   ;if (snext < 8)
  1076.         bge.b   .keep5
  1077. .up5
  1078.         moveq   #8,d4                   ;snext = 8
  1079.         bra.b   .keep5
  1080. .down5
  1081.         move.l  a4,d4                   ;snext = bbextents
  1082. .keep5
  1083.         fmul    fp1,fp7                 ;fp7 = tdivz * z
  1084.         fmove.l fp7,d5                  ;convert to integer
  1085.         add.l   a3,d5                   ;tnext = d5 + tadjust
  1086.         cmp.l   a2,d5                   ;if (tnext > bbextentt)
  1087.         bgt.b   .down6
  1088.         cmp.l   #8,d5                   ;if (tnext < 8)
  1089.         bge.b   .keep6
  1090. .up6
  1091.         moveq   #8,d5                   ;tnext = 8
  1092.         bra.b   .keep6
  1093. .down6
  1094.         move.l  a2,d5                   ;tnext = bbextentt
  1095. .keep6
  1096.         move.l  d4,.saved4(sp)          ;save snext
  1097.         move.l  d5,.saved5(sp)          ;save tnext
  1098.         sub.l   d6,d4                   ;d4 = snext - s
  1099.         sub.l   d7,d5                   ;d5 = tnext - t
  1100.         IFEQ    QDIV
  1101.         tst.l   d2
  1102.         beq.w   .mainloop
  1103.         divs.l  d2,d4
  1104.         divs.l  d2,d5
  1105.         ELSEIF
  1106.         cmp     #5,d2                   ;(spancount-1) < 5?
  1107.         blt.b   .special                ;yes -> special case
  1108. .qdiv
  1109.         IFNE    NICE_DIV
  1110.         lsl.l   #2,d4
  1111.         lsl.l   #2,d5
  1112.         lea     ReciprocTable,a6
  1113.         move    0(a6,d2.w*2),d0
  1114.         move.l  d4,d3
  1115.         mulu    d0,d3
  1116.         clr     d3
  1117.         swap    d3
  1118.         swap    d4
  1119.         muls    d0,d4
  1120.         add.l   d3,d4
  1121.         move.l  d5,d3
  1122.         mulu    d0,d3
  1123.         clr     d3
  1124.         swap    d3
  1125.         swap    d5
  1126.         muls    d0,d5
  1127.         add.l   d3,d5
  1128.         bra.b   .mainloop
  1129.         ELSEIF
  1130.         asr.l   #7,d4                   ;d4 >> 7
  1131.         asr.l   #7,d5                   ;d5 >> 7
  1132.         lea     ReciprocTable,a6        ;a6 -> reciprocal table
  1133.         move    0(a6,d2.w*2),d0         ;d0 = (1/(spancount-1))<<16
  1134.         muls    d0,d4                   ;d4 = d4 / (spancount-1)
  1135.         asr.l   #7,d4                   ;sstep = d4 >> 7
  1136.         muls    d0,d5                   ;d5 = d5 / (spancount-1)
  1137.         asr.l   #7,d5                   ;tstep = d5 >> 7
  1138.         bra.b   .mainloop
  1139.         ENDC
  1140. .special
  1141.         cmp     #1,d2                   ;switch (spancount-1)
  1142.         ble.b   .mainloop               ;0,1 -> no scaling needed
  1143.         cmp     #3,d2                   ;3 -> standard qdiv
  1144.         beq.b   .qdiv
  1145.         blt.b   .spec_2
  1146.         asr.l   #2,d4                   ;4 -> scale by shifting right
  1147.         asr.l   #2,d5
  1148.         bra.b   .mainloop
  1149. .spec_2
  1150.         asr.l   #1,d4                   ;2 -> scale by shifting right
  1151.         asr.l   #1,d5
  1152.         ENDC
  1153.  
  1154. ******  Main drawing loop. Here lies the speed.
  1155. ******  Very optimized (removed multiplication from inner loop)
  1156.  
  1157. ******  d2 : spancount
  1158. ******  d4 : sstep
  1159. ******  d5 : tstep
  1160. ******  d6 : s
  1161. ******  d7 : t
  1162. ******  a0 : pdest
  1163. ******  a1 : pbase
  1164.  
  1165. *                        do
  1166. *                        {
  1167. *                                *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
  1168. *                                s += sstep;
  1169. *                                t += tstep;
  1170. *                        } while (--spancount > 0);
  1171.  
  1172. .mainloop
  1173.         move.l  d1,-(sp)
  1174.         lea     .PixTable,a6            ;a6 -> Functable
  1175.         move.l  _cachewidth,d3          ;read cachewidth
  1176.         move.l  0(a6,d2.w*4),a6         ;get pointer to function
  1177.         swap    d7
  1178.         swap    d4
  1179.         move.l  d7,d1
  1180.         swap    d5
  1181.         muls    d3,d7                   ;d7 = t integer part * cachewidth
  1182.         move    d5,d2
  1183.         clr     d1                      ;d1 = t fractional part
  1184.         muls    d3,d2                   ;tstep integer part * cachewidth
  1185.         move    d4,d0                   ;d0 = sstep integer part
  1186.         clr     d5                      ;d5 = tstep fractional part
  1187.         clr     d4                      ;d4 = sstep fractional part
  1188.         swap    d6                      ;d6 = s swapped
  1189.         jmp     (a6)
  1190. .Pix8
  1191.         lea     0(a1,d6.w),a6
  1192.         move.b  0(a6,d7.l),(a0)+
  1193.         add.l   d4,d6                   ;increment s fractional part
  1194.         addx.w  d0,d6                   ;increment s integer part
  1195.         add.l   d2,d7                   ;increment t integer part
  1196.         add.l   d5,d1                   ;increment t fractional part
  1197.         bcc.b   .Pix7                   ;check if carry
  1198.         add.l   d3,d7                   ;add cachewidth to t
  1199. .Pix7
  1200.         lea     0(a1,d6.w),a6           ;and so long...
  1201.         move.b  0(a6,d7.l),(a0)+
  1202.         add.l   d4,d6
  1203.         addx.w  d0,d6
  1204.         add.l   d2,d7
  1205.         add.l   d5,d1
  1206.         bcc.b   .Pix6
  1207.         add.l   d3,d7
  1208. .Pix6
  1209.         lea     0(a1,d6.w),a6
  1210.         move.b  0(a6,d7.l),(a0)+
  1211.         add.l   d4,d6
  1212.         addx.w  d0,d6
  1213.         add.l   d2,d7
  1214.         add.l   d5,d1
  1215.         bcc.b   .Pix5
  1216.         add.l   d3,d7
  1217. .Pix5
  1218.         lea     0(a1,d6.w),a6
  1219.         move.b  0(a6,d7.l),(a0)+
  1220.         add.l   d4,d6
  1221.         addx.w  d0,d6
  1222.         add.l   d2,d7
  1223.         add.l   d5,d1
  1224.         bcc.b   .Pix4
  1225.         add.l   d3,d7
  1226. .Pix4
  1227.         lea     0(a1,d6.w),a6
  1228.         move.b  0(a6,d7.l),(a0)+
  1229.         add.l   d4,d6
  1230.         addx.w  d0,d6
  1231.         add.l   d2,d7
  1232.         add.l   d5,d1
  1233.         bcc.b   .Pix3
  1234.         add.l   d3,d7
  1235. .Pix3
  1236.         lea     0(a1,d6.w),a6
  1237.         move.b  0(a6,d7.l),(a0)+
  1238.         add.l   d4,d6
  1239.         addx.w  d0,d6
  1240.         add.l   d2,d7
  1241.         add.l   d5,d1
  1242.         bcc.b   .Pix2
  1243.         add.l   d3,d7
  1244. .Pix2
  1245.         lea     0(a1,d6.w),a6
  1246.         move.b  0(a6,d7.l),(a0)+
  1247.         add.l   d4,d6
  1248.         addx.w  d0,d6
  1249.         add.l   d2,d7
  1250.         add.l   d5,d1
  1251.         bcc.b   .Pix1
  1252.         add.l   d3,d7
  1253. .Pix1
  1254.         lea     0(a1,d6.w),a6
  1255.         move.b  0(a6,d7.l),(a0)+
  1256.         add.l   d4,d6
  1257.         addx.w  d0,d6
  1258.         add.l   d2,d7
  1259.         add.l   d5,d1
  1260.         bcc.b   .Pix0
  1261.         add.l   d3,d7
  1262. .Pix0
  1263.         move.l  (sp)+,d1
  1264.  
  1265. ******  loop terminations
  1266.  
  1267.  
  1268.         move.l   .saved5(sp),d7         ;t = tnext
  1269.         move.l   .saved4(sp),d6         ;s = snext
  1270.  
  1271.         tst.l   d1                      ;while (count > 0)
  1272.         bgt.w   .loop2
  1273.  
  1274.         move.l  .savea6(sp),a6          ;while ((pspan = pspan->next) != NULL)
  1275.         move.l  PSPAN_NEXT(a6),a6
  1276.         tst.l   a6
  1277.         bne.w   .loop
  1278.         add.l   #.fpuregs,sp
  1279.         fmovem.x        (sp)+,fp2-fp7
  1280.         movem.l (sp)+,d2-d7/a2-a6
  1281.         rts
  1282.  
  1283. .PixTable
  1284.         dc.l    .Pix1
  1285.         dc.l    .Pix2
  1286.         dc.l    .Pix3
  1287.         dc.l    .Pix4
  1288.         dc.l    .Pix5
  1289.         dc.l    .Pix6
  1290.         dc.l    .Pix7
  1291.         dc.l    .Pix8
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300. ******************************************************************************
  1301. *
  1302. *       void D_DrawSpans16 (espan_t *pspan)
  1303. *
  1304. *       standard scan drawing function (16 pixel subdivision)
  1305. *
  1306. ******************************************************************************
  1307.  
  1308.         cnop    0,4
  1309. _D_DrawSpans16
  1310.  
  1311.  
  1312. *****   stackframe
  1313.  
  1314.         rsreset
  1315. .saved4         rs.l    1
  1316. .saved5         rs.l    1
  1317. .savea6         rs.l    1
  1318. .szstpu         rs.s    1
  1319. .szstpv         rs.s    1
  1320. .szorg          rs.s    1
  1321. .tzstpu         rs.s    1
  1322. .tzstpv         rs.s    1
  1323. .tzorg          rs.s    1
  1324. .zistpu         rs.s    1
  1325. .zistpv         rs.s    1
  1326. .ziorg          rs.s    1
  1327. .fpuregs        rs.x    6
  1328. .intregs        rs.l    11
  1329.         rs.l    1
  1330. .pspan          rs.l    1
  1331.  
  1332. ******  Prologue. Global variables are put into registers or onto the stackframe
  1333.  
  1334.         movem.l d2-d7/a2-a6,-(sp)
  1335.         fmovem.x        fp2-fp7,-(sp)
  1336.         move.l  _bbextentt,a2
  1337.         move.l  _tadjust,a3
  1338.         move.l  _bbextents,a4
  1339.         move.l  _sadjust,a5
  1340.         move.l  _d_ziorigin,-(sp)
  1341.         move.l  _d_zistepv,-(sp)
  1342.         move.l  _d_zistepu,-(sp)
  1343.         move.l  _d_tdivzorigin,-(sp)
  1344.         move.l  _d_tdivzstepv,-(sp)
  1345.         move.l  _d_tdivzstepu,-(sp)
  1346.         move.l  _d_sdivzorigin,-(sp)
  1347.         move.l  _d_sdivzstepv,-(sp)
  1348.         move.l  _d_sdivzstepu,-(sp)
  1349.         sub.l   #.szstpu,sp
  1350.  
  1351. ******  First loop. In every iteration one complete span is drawn
  1352.  
  1353. *        pbase = (unsigned char *)cacheblock;
  1354. *
  1355. *        sdivz16stepu = d_sdivzstepu * 16;
  1356. *        tdivz16stepu = d_tdivzstepu * 16;
  1357. *        zi16stepu = d_zistepu * 16;
  1358. *
  1359. *        do
  1360. *        {
  1361. *                pdest = (unsigned char *)((byte *)d_viewbuffer +
  1362. *                                (screenwidth * pspan->v) + pspan->u);
  1363. *
  1364. *                count = pspan->count;
  1365. *
  1366. *        // calculate the initial s/z, t/z, 1/z, s, and t and clamp
  1367. *                du = (float)pspan->u;
  1368. *                dv = (float)pspan->v;
  1369. *
  1370. *                sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
  1371. *                tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
  1372. *                zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  1373. *                z = (float)0x10000 / zi;        // prescale to 16.16 fixed-point
  1374. *
  1375.  
  1376.         move.l  _cacheblock,a1          ;pbase = (unsigned char *)cacheblock
  1377.         fmove.s #16,fp7
  1378.         fmove.s .szstpu(sp),fp3
  1379.         fmul    fp7,fp3                 ;sdivz16stepu = d_sdivzstepu * 16
  1380.         fmove.s .tzstpu(sp),fp4
  1381.         fmul    fp7,fp4                 ;tdivz16stepu = d_tdivzstepu * 16
  1382.         fmove.s .zistpu(sp),fp5
  1383.         fmul    fp7,fp5                 ;zi16stepu = d_zistepu * 16
  1384.         move.l  .pspan(sp),a6           ;get function parameter
  1385. .loop
  1386.         move.l  a6,.savea6(sp)          ;save actual ptr to pspan
  1387.         move.l  _d_viewbuffer,a0
  1388.         move.l  _screenwidth,d0
  1389.         move.l  (a6)+,d1
  1390.         fmove.l d1,fp2                  ;du = (float)pspan->u
  1391.         move.l  (a6)+,d2
  1392.         fmove.l d2,fp7                  ;dv = (float)pspan->v
  1393.         move.l  (a6)+,d4
  1394.         muls    d2,d0                   ;d0 = screenwidth * pspan->v
  1395.         add.l   d1,d0
  1396.         add.l   d0,a0                   ;pdest = d_viewbuffer + pspan->u + d0
  1397.         lea     .szstpu(sp),a6          ;a6 -> stackframe
  1398.         fmove.s (a6)+,fp0
  1399.         fmul    fp2,fp0                 ;fp0 = du * d_sdivzstepu
  1400.         fmove.s (a6)+,fp1
  1401.         fmul    fp7,fp1                 ;fp1 = dv * d_sdivzstepv
  1402.         fadd    fp1,fp0
  1403.         fadd.s  (a6)+,fp0               ;sdivz = d_sdivzorigin + fp0 + fp1
  1404.         fmove.s (a6)+,fp1
  1405.         fmul    fp2,fp1                 ;fp1 = du * d_tdivzstepu
  1406.         fmove.s (a6)+,fp6
  1407.         fmul    fp7,fp6                 ;fp6 = dv * d_tdivzstepv
  1408.         fadd    fp6,fp1
  1409.         fadd.s  (a6)+,fp1               ;tdivz = d_tdivzorigin + fp1 + fp6
  1410.         fmul.s  (a6)+,fp2               ;fp2 = du * d_zistepu
  1411.         fmul.s  (a6)+,fp7               ;fp7 = dv * d_zistepv
  1412.         fadd    fp7,fp2
  1413.         fadd.s  (a6)+,fp2               ;zi = d_ziorigin + fp2 + fp7
  1414.         fmove.s #65536,fp6
  1415.         fdiv    fp2,fp6                 ;z = (float)0x10000 / zi
  1416.  
  1417. *                s = (int)(sdivz * z) + sadjust;
  1418. *                if (s > bbextents)
  1419. *                        s = bbextents;
  1420. *                else if (s < 0)
  1421. *                        s = 0;
  1422. *
  1423. *                t = (int)(tdivz * z) + tadjust;
  1424. *                if (t > bbextentt)
  1425. *                        t = bbextentt;
  1426. *                else if (t < 0)
  1427. *                        t = 0;
  1428.  
  1429.  
  1430.         fmove   fp6,fp7
  1431.         fmul    fp0,fp7                 ;fp7 = sdivz * z
  1432.         fmove.l fp7,d6                  ;convert to integer
  1433.         add.l   a5,d6                   ;s = d6 + sadjust
  1434.         cmp.l   a4,d6                   ;if (s > bbextents)
  1435.         bgt.b   .down
  1436.         tst.l   d6                      ;if (s < 0)
  1437.         bge.b   .keep
  1438. .up
  1439.         moveq   #0,d6                   ;s = 0
  1440.         bra.b   .keep
  1441. .down
  1442.         move.l  a4,d6                   ;s = bbextents
  1443. .keep
  1444.         fmul    fp1,fp6                 ;fp6 = tdivz * z
  1445.         fmove.l fp6,d7                  ;convert to integer
  1446.         add.l   a3,d7                   ;t = d7 + tadjust
  1447.         cmp.l   a2,d7                   ;if (t > bbextentt)
  1448.         bgt.b   .down2
  1449.         tst.l   d7                      ;if (t < 0)
  1450.         bge.b   .keep2
  1451. .up2
  1452.         moveq   #0,d7                   ;t = 0
  1453.         bra.b   .keep2
  1454. .down2
  1455.         move.l  a2,d7                   ;t = bbextentt
  1456. .keep2
  1457.         move.l  d4,d1
  1458.  
  1459. ******  Second loop. In every iteration one part of the whole span is drawn
  1460. ******  d2 gets the value (spancount-1)! [NOT spancount]
  1461.  
  1462. ******  d1 = count
  1463.  
  1464. *                do
  1465. *                {
  1466. *                // calculate s and t at the far end of the span
  1467. *                        if (count >= 16)
  1468. *                                spancount = 16;
  1469. *                        else
  1470. *                                spancount = count;
  1471. *
  1472. *                        count -= spancount;
  1473. *
  1474. *                        if (count)
  1475. *                        {
  1476.  
  1477. .loop2
  1478.         moveq   #16-1,d2                ;spancount = 16
  1479.         cmp.l   #16,d1                  ;if (count >= 16)
  1480.         bgt.b   .cont
  1481.         move.l  d1,d2                   ;spancount = count
  1482.         subq.l  #1,d2
  1483.         moveq   #0,d1                   ;count -= spancount
  1484.         bra.w   .finalpart
  1485. .cont
  1486.         sub.l   #16,d1                  ;count -= spancount;
  1487.  
  1488. ******  Evaluation of the values for the inner loop. This version is used for
  1489. ******  span size = 16
  1490.  
  1491. ******  a2  : bbextentt
  1492. ******  a3  : tadjust
  1493. ******  a4  : bbextents
  1494. ******  a5  : sadjust
  1495. ******  fp0 : sdivz
  1496. ******  fp1 : tdivz
  1497. ******  fp2 : zi
  1498. ******  fp3 : sdivz16stepu
  1499. ******  fp4 : tdivz16stepu
  1500. ******  fp5 : zi16stepu
  1501.  
  1502. *                        // calculate s/z, t/z, zi->fixed s and t at far end of span,
  1503. *                        // calculate s and t steps across span by shifting
  1504. *                                sdivz += sdivz16stepu;
  1505. *                                tdivz += tdivz16stepu;
  1506. *                                zi += zi16stepu;
  1507. *                                z = (float)0x10000 / zi;        // prescale to 16.16 fixed-point
  1508. *                                snext = (int)(sdivz * z) + sadjust;
  1509. *                                if (snext > bbextents)
  1510. *                                        snext = bbextents;
  1511. *                                else if (snext < 16)
  1512. *                                        snext = 16;      // prevent round-off error on <0 steps from
  1513. *                                                                //  from causing overstepping & running off the
  1514. *                                                                //  edge of the texture
  1515. *                                tnext = (int)(tdivz * z) + tadjust;
  1516. *                                if (tnext > bbextentt)
  1517. *                                        tnext = bbextentt;
  1518. *                                else if (tnext < 16)
  1519. *                                        tnext = 16;      // guard against round-off error on <0 steps
  1520. *                                sstep = (snext - s) >> 4;
  1521. *                                tstep = (tnext - t) >> 4;
  1522. *                        }
  1523.  
  1524.         fadd    fp3,fp0                 ;sdivz += sdivz16stepu
  1525.         fadd    fp4,fp1                 ;tdivz += tdivz16stepu
  1526.         fadd    fp5,fp2                 ;zi += zi16stepu
  1527.         fmove.s #65536,fp7
  1528.         fdiv    fp2,fp7                 ;z = (float)0x10000 / zi;
  1529.         fmove   fp7,fp6
  1530.         fmul    fp0,fp6                 ;fp2 = sdivz * z
  1531.         fmove.l fp6,d4                  ;convert to integer
  1532.         add.l   a5,d4                   ;snext = d4 + sadjust
  1533.         cmp.l   a4,d4                   ;if (snext > bbextents)
  1534.         bgt.b   .down3
  1535.         cmp.l   #16,d4                  ;if (snext < 16)
  1536.         bge.b   .keep3
  1537. .up3
  1538.         moveq   #16,d4                  ;snext = 16
  1539.         bra.b   .keep3
  1540. .down3
  1541.         move.l  a4,d4                   ;snext = bbextents
  1542. .keep3
  1543.         fmul    fp1,fp7                 ;fp7 = tdivz * z
  1544.         fmove.l fp7,d5                  ;convert to integer
  1545.         add.l   a3,d5                   ;tnext = d5 + tadjust
  1546.         cmp.l   a2,d5                   ;if (tnext > bbextentt)
  1547.         bgt.b   .down4
  1548.         cmp.l   #16,d5                  ;if (tnext < 16)
  1549.         bge.b   .keep4
  1550. .up4
  1551.         moveq   #16,d5                  ;tnext = 16
  1552.         bra.b   .keep4
  1553. .down4
  1554.         move.l  a2,d5                   ;tnext = bbextentt
  1555. .keep4
  1556.         move.l  d4,.saved4(sp)          ;save snext
  1557.         move.l  d5,.saved5(sp)          ;save tnext
  1558.         sub.l   d6,d4                   ;d4 = snext - s
  1559.         sub.l   d7,d5                   ;d5 = tnext - t
  1560.         asr.l   #4,d4                   ;sstep = d4 >> 4
  1561.         asr.l   #4,d5                   ;tstep = d5 >> 4
  1562.         bra.w   .mainloop
  1563.  
  1564.  
  1565. ******  Evaluation of the values for the inner loop. This version is used for
  1566. ******  span size < 16
  1567.  
  1568. ******  The original algorithm has two ugly divisions at the end of this part.
  1569. ******  These are removed by the following optimization:
  1570. ******  First, the divisors 1,2 and 4 are handled specially to gain speed. The
  1571. ******  other divisors are handled using a reciprocal table.
  1572.  
  1573. ******  a2  : bbextentt
  1574. ******  a3  : tadjust
  1575. ******  a4  : bbextents
  1576. ******  a5  : sadjust
  1577. ******  fp0 : sdivz
  1578. ******  fp1 : tdivz
  1579. ******  fp2 : zi
  1580.  
  1581. *                        // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
  1582. *                        // can't step off polygon), clamp, calculate s and t steps across
  1583. *                        // span by division, biasing steps low so we don't run off the
  1584. *                        // texture
  1585. *                                spancountminus1 = (float)(spancount - 1);
  1586. *                                sdivz += d_sdivzstepu * spancountminus1;
  1587. *                                tdivz += d_tdivzstepu * spancountminus1;
  1588. *                                zi += d_zistepu * spancountminus1;
  1589. *                                z = (float)0x10000 / zi;        // prescale to 16.16 fixed-point
  1590. *                                snext = (int)(sdivz * z) + sadjust;
  1591. *                                if (snext > bbextents)
  1592. *                                        snext = bbextents;
  1593. *                                else if (snext < 16)
  1594. *                                        snext = 16;      // prevent round-off error on <0 steps from
  1595. *                                                                //  from causing overstepping & running off the
  1596. *                                                                //  edge of the texture
  1597. *
  1598. *                                tnext = (int)(tdivz * z) + tadjust;
  1599. *                                if (tnext > bbextentt)
  1600. *                                        tnext = bbextentt;
  1601. *                                else if (tnext < 16)
  1602. *                                        tnext = 16;      // guard against round-off error on <0 steps
  1603. *
  1604. *                                if (spancount > 1)
  1605. *                                {
  1606. *                                        sstep = (snext - s) / (spancount - 1);
  1607. *                                        tstep = (tnext - t) / (spancount - 1);
  1608. *                                }
  1609. *                        }
  1610.  
  1611. .finalpart
  1612.         fmove.l d2,fp7                  ;spancountminus1 = (float)(spancount-1)
  1613.         fmove   fp7,fp6
  1614.         fmul.s  .szstpu(sp),fp6         ;fp6 = d_sdivzstepu * spancountminus1
  1615.         fadd    fp6,fp0                 ;sdivz += fp6
  1616.         fmove   fp7,fp6
  1617.         fmul.s  .tzstpu(sp),fp6         ;fp6 = d_tdivzstepu * spancountminus1
  1618.         fadd    fp6,fp1                 ;tdivz += fp6
  1619.         fmul.s  .zistpu(sp),fp7         ;fp7 = d_zistepu * spancountminus1
  1620.         fadd    fp7,fp2                 ;zi += fp7
  1621.         fmove.s #65536,fp7
  1622.         fdiv    fp2,fp7                 ;z = (float)0x10000 / zi;
  1623.         fmove   fp7,fp6
  1624.         fmul    fp0,fp6                 ;fp6 = sdivz * z
  1625.         fmove.l fp6,d4                  ;convert to integer
  1626.         add.l   a5,d4                   ;snext = d4 + sadjust
  1627.         cmp.l   a4,d4                   ;if (snext > bbextents)
  1628.         bgt.b   .down5
  1629.         cmp.l   #16,d4                  ;if (snext < 16)
  1630.         bge.b   .keep5
  1631. .up5
  1632.         moveq   #16,d4                  ;snext = 16
  1633.         bra.b   .keep5
  1634. .down5
  1635.         move.l  a4,d4                   ;snext = bbextents
  1636. .keep5
  1637.         fmul    fp1,fp7                 ;fp7 = tdivz * z
  1638.         fmove.l fp7,d5                  ;convert to integer
  1639.         add.l   a3,d5                   ;tnext = d5 + tadjust
  1640.         cmp.l   a2,d5                   ;if (tnext > bbextentt)
  1641.         bgt.b   .down6
  1642.         cmp.l   #16,d5                  ;if (tnext < 16)
  1643.         bge.b   .keep6
  1644. .up6
  1645.         moveq   #16,d5                  ;tnext = 16
  1646.         bra.b   .keep6
  1647. .down6
  1648.         move.l  a2,d5                   ;tnext = bbextentt
  1649. .keep6
  1650.         move.l  d4,.saved4(sp)          ;save snext
  1651.         move.l  d5,.saved5(sp)          ;save tnext
  1652.         sub.l   d6,d4                   ;d4 = snext - s
  1653.         sub.l   d7,d5                   ;d5 = tnext - t
  1654.         IFEQ    QDIV
  1655.         tst.l   d2
  1656.         beq.w   .mainloop
  1657.         divs.l  d2,d4
  1658.         divs.l  d2,d5
  1659.         ELSEIF
  1660.         cmp     #5,d2                   ;(spancount-1) < 5?
  1661.         blt.b   .special                ;yes -> special case
  1662.         cmp     #8,d2
  1663.         beq.b   .spec_8
  1664. .qdiv
  1665.         IFNE    NICE_DIV
  1666.         lsl.l   #2,d4
  1667.         lsl.l   #2,d5
  1668.         lea     ReciprocTable,a6
  1669.         move    0(a6,d2.w*2),d0
  1670.         move.l  d4,d3
  1671.         mulu    d0,d3
  1672.         clr     d3
  1673.         swap    d3
  1674.         swap    d4
  1675.         muls    d0,d4
  1676.         add.l   d3,d4
  1677.         move.l  d5,d3
  1678.         mulu    d0,d3
  1679.         clr     d3
  1680.         swap    d3
  1681.         swap    d5
  1682.         muls    d0,d5
  1683.         add.l   d3,d5
  1684.         bra.b   .mainloop
  1685.         ELSEIF
  1686.         asr.l   #7,d4                   ;d4 >> 7
  1687.         asr.l   #7,d5                   ;d5 >> 7
  1688.         lea     ReciprocTable,a6        ;a6 -> reciprocal table
  1689.         move    0(a6,d2.w*2),d0         ;d0 = (1/(spancount-1))<<16
  1690.         muls    d0,d4                   ;d4 = d4 / (spancount-1)
  1691.         asr.l   #7,d4                   ;sstep = d4 >> 7
  1692.         muls    d0,d5                   ;d5 = d5 / (spancount-1)
  1693.         asr.l   #7,d5                   ;tstep = d5 >> 7
  1694.         bra.b   .mainloop
  1695.         ENDC
  1696. .special
  1697.         cmp     #1,d2                   ;switch (spancount-1)
  1698.         ble.b   .mainloop               ;0,1 -> no scaling needed
  1699.         cmp     #3,d2                   ;3 -> standard qdiv
  1700.         beq.b   .qdiv
  1701.         blt.b   .spec_2
  1702.         asr.l   #2,d4                   ;4 -> scale by shifting right
  1703.         asr.l   #2,d5
  1704.         bra.b   .mainloop
  1705. .spec_8
  1706.         asr.l   #3,d4                   ;8 -> scale by shifting right
  1707.         asr.l   #3,d5
  1708.         bra.b   .mainloop
  1709. .spec_2
  1710.         asr.l   #1,d4                   ;2 -> scale by shifting right
  1711.         asr.l   #1,d5
  1712.         ENDC
  1713.  
  1714. ******  Main drawing loop. Here lies the speed.
  1715. ******  Very optimized (removed multiplication from inner loop)
  1716.  
  1717. ******  d2 : spancount
  1718. ******  d4 : sstep
  1719. ******  d5 : tstep
  1720. ******  d6 : s
  1721. ******  d7 : t
  1722. ******  a0 : pdest
  1723. ******  a1 : pbase
  1724.  
  1725. *                        do
  1726. *                        {
  1727. *                                *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
  1728. *                                s += sstep;
  1729. *                                t += tstep;
  1730. *                        } while (--spancount > 0);
  1731.  
  1732. .mainloop
  1733.         move.l  d1,-(sp)
  1734.         lea     .PixTable,a6            ;a6 -> Functable
  1735.         move.l  _cachewidth,d3          ;read cachewidth
  1736.         move.l  0(a6,d2.w*4),a6         ;get pointer to function
  1737.         swap    d7
  1738.         swap    d4
  1739.         move.l  d7,d1
  1740.         swap    d5
  1741.         muls    d3,d7                   ;d7 = t integer part * cachewidth
  1742.         move    d5,d2
  1743.         clr     d1                      ;d1 = t fractional part
  1744.         muls    d3,d2                   ;tstep integer part * cachewidth
  1745.         move    d4,d0                   ;d0 = sstep integer part
  1746.         clr     d5                      ;d5 = tstep fractional part
  1747.         clr     d4                      ;d4 = sstep fractional part
  1748.         swap    d6                      ;d6 = s swapped
  1749.         jmp     (a6)
  1750. .Pix16
  1751.         lea     0(a1,d6.w),a6
  1752.         move.b  0(a6,d7.l),(a0)+
  1753.         add.l   d4,d6                   ;increment s fractional part
  1754.         addx.w  d0,d6                   ;increment s integer part
  1755.         add.l   d2,d7                   ;increment t integer part
  1756.         add.l   d5,d1                   ;increment t fractional part
  1757.         bcc.b   .Pix15                   ;check if carry
  1758.         add.l   d3,d7                   ;add cachewidth to t
  1759. .Pix15
  1760.         lea     0(a1,d6.w),a6           ;and so long...
  1761.         move.b  0(a6,d7.l),(a0)+
  1762.         add.l   d4,d6
  1763.         addx.w  d0,d6
  1764.         add.l   d2,d7
  1765.         add.l   d5,d1
  1766.         bcc.b   .Pix14
  1767.         add.l   d3,d7
  1768. .Pix14
  1769.         lea     0(a1,d6.w),a6
  1770.         move.b  0(a6,d7.l),(a0)+
  1771.         add.l   d4,d6
  1772.         addx.w  d0,d6
  1773.         add.l   d2,d7
  1774.         add.l   d5,d1
  1775.         bcc.b   .Pix13
  1776.         add.l   d3,d7
  1777. .Pix13
  1778.         lea     0(a1,d6.w),a6
  1779.         move.b  0(a6,d7.l),(a0)+
  1780.         add.l   d4,d6
  1781.         addx.w  d0,d6
  1782.         add.l   d2,d7
  1783.         add.l   d5,d1
  1784.         bcc.b   .Pix12
  1785.         add.l   d3,d7
  1786. .Pix12
  1787.         lea     0(a1,d6.w),a6
  1788.         move.b  0(a6,d7.l),(a0)+
  1789.         add.l   d4,d6
  1790.         addx.w  d0,d6
  1791.         add.l   d2,d7
  1792.         add.l   d5,d1
  1793.         bcc.b   .Pix11
  1794.         add.l   d3,d7
  1795. .Pix11
  1796.         lea     0(a1,d6.w),a6
  1797.         move.b  0(a6,d7.l),(a0)+
  1798.         add.l   d4,d6
  1799.         addx.w  d0,d6
  1800.         add.l   d2,d7
  1801.         add.l   d5,d1
  1802.         bcc.b   .Pix10
  1803.         add.l   d3,d7
  1804. .Pix10
  1805.         lea     0(a1,d6.w),a6
  1806.         move.b  0(a6,d7.l),(a0)+
  1807.         add.l   d4,d6
  1808.         addx.w  d0,d6
  1809.         add.l   d2,d7
  1810.         add.l   d5,d1
  1811.         bcc.b   .Pix9
  1812.         add.l   d3,d7
  1813. .Pix9
  1814.         lea     0(a1,d6.w),a6
  1815.         move.b  0(a6,d7.l),(a0)+
  1816.         add.l   d4,d6
  1817.         addx.w  d0,d6
  1818.         add.l   d2,d7
  1819.         add.l   d5,d1
  1820.         bcc.b   .Pix8
  1821.         add.l   d3,d7
  1822. .Pix8
  1823.         lea     0(a1,d6.w),a6
  1824.         move.b  0(a6,d7.l),(a0)+
  1825.         add.l   d4,d6
  1826.         addx.w  d0,d6
  1827.         add.l   d2,d7
  1828.         add.l   d5,d1
  1829.         bcc.b   .Pix7
  1830.         add.l   d3,d7
  1831. .Pix7
  1832.         lea     0(a1,d6.w),a6
  1833.         move.b  0(a6,d7.l),(a0)+
  1834.         add.l   d4,d6
  1835.         addx.w  d0,d6
  1836.         add.l   d2,d7
  1837.         add.l   d5,d1
  1838.         bcc.b   .Pix6
  1839.         add.l   d3,d7
  1840. .Pix6
  1841.         lea     0(a1,d6.w),a6
  1842.         move.b  0(a6,d7.l),(a0)+
  1843.         add.l   d4,d6
  1844.         addx.w  d0,d6
  1845.         add.l   d2,d7
  1846.         add.l   d5,d1
  1847.         bcc.b   .Pix5
  1848.         add.l   d3,d7
  1849. .Pix5
  1850.         lea     0(a1,d6.w),a6
  1851.         move.b  0(a6,d7.l),(a0)+
  1852.         add.l   d4,d6
  1853.         addx.w  d0,d6
  1854.         add.l   d2,d7
  1855.         add.l   d5,d1
  1856.         bcc.b   .Pix4
  1857.         add.l   d3,d7
  1858. .Pix4
  1859.         lea     0(a1,d6.w),a6
  1860.         move.b  0(a6,d7.l),(a0)+
  1861.         add.l   d4,d6
  1862.         addx.w  d0,d6
  1863.         add.l   d2,d7
  1864.         add.l   d5,d1
  1865.         bcc.b   .Pix3
  1866.         add.l   d3,d7
  1867. .Pix3
  1868.         lea     0(a1,d6.w),a6
  1869.         move.b  0(a6,d7.l),(a0)+
  1870.         add.l   d4,d6
  1871.         addx.w  d0,d6
  1872.         add.l   d2,d7
  1873.         add.l   d5,d1
  1874.         bcc.b   .Pix2
  1875.         add.l   d3,d7
  1876. .Pix2
  1877.         lea     0(a1,d6.w),a6
  1878.         move.b  0(a6,d7.l),(a0)+
  1879.         add.l   d4,d6
  1880.         addx.w  d0,d6
  1881.         add.l   d2,d7
  1882.         add.l   d5,d1
  1883.         bcc.b   .Pix1
  1884.         add.l   d3,d7
  1885. .Pix1
  1886.         lea     0(a1,d6.w),a6
  1887.         move.b  0(a6,d7.l),(a0)+
  1888.         add.l   d4,d6
  1889.         addx.w  d0,d6
  1890.         add.l   d2,d7
  1891.         add.l   d5,d1
  1892.         bcc.b   .Pix0
  1893.         add.l   d3,d7
  1894. .Pix0
  1895.         move.l  (sp)+,d1
  1896.  
  1897. ******  loop terminations
  1898.  
  1899.  
  1900.         move.l   .saved5(sp),d7         ;t = tnext
  1901.         move.l   .saved4(sp),d6         ;s = snext
  1902.  
  1903.         tst.l   d1                      ;while (count > 0)
  1904.         bgt.w   .loop2
  1905.  
  1906.         move.l  .savea6(sp),a6          ;while ((pspan = pspan->next) != NULL)
  1907.         move.l  PSPAN_NEXT(a6),a6
  1908.         tst.l   a6
  1909.         bne.w   .loop
  1910.         add.l   #.fpuregs,sp
  1911.         fmovem.x        (sp)+,fp2-fp7
  1912.         movem.l (sp)+,d2-d7/a2-a6
  1913.         rts
  1914.  
  1915. .PixTable
  1916.         dc.l    .Pix1
  1917.         dc.l    .Pix2
  1918.         dc.l    .Pix3
  1919.         dc.l    .Pix4
  1920.         dc.l    .Pix5
  1921.         dc.l    .Pix6
  1922.         dc.l    .Pix7
  1923.         dc.l    .Pix8
  1924.         dc.l    .Pix9
  1925.         dc.l    .Pix10
  1926.         dc.l    .Pix11
  1927.         dc.l    .Pix12
  1928.         dc.l    .Pix13
  1929.         dc.l    .Pix14
  1930.         dc.l    .Pix15
  1931.         dc.l    .Pix16
  1932.  
  1933.  
  1934.  
  1935.  
  1936.  
  1937.  
  1938.  
  1939.  
  1940.  
  1941. ******************************************************************************
  1942. *
  1943. *       void D_DrawZSpans (espan_t *pspan)
  1944. *
  1945. *       standard z-scan drawing function
  1946. *
  1947. ******************************************************************************
  1948.  
  1949.         cnop    0,4
  1950. _D_DrawZSpans
  1951.  
  1952.  
  1953. ******  Prologue. Global variables are put into registers or onto the stack
  1954.  
  1955. *****   stackframe
  1956.  
  1957.         rsreset
  1958. .fpuregs        rs.x    5
  1959. .intregs        rs.l    7
  1960.         rs.l    1
  1961. .pspan          rs.l    1
  1962.  
  1963.         movem.l d2-d7/a2,-(sp)
  1964.         fmovem.x        fp3-fp7,-(sp)
  1965.         move.l  .pspan(sp),a2
  1966.         move.l  _d_pzbuffer,a0
  1967.         move.l  _d_zwidth,d7
  1968.         fmove.s _d_ziorigin,fp5
  1969.         fmove.s _d_zistepv,fp6
  1970.         fmove.s _d_zistepu,fp7
  1971.         fmove.s #32768*65536,fp0
  1972.  
  1973. *        izistep = (int)(d_zistepu * 0x8000 * 0x10000);
  1974.  
  1975.         fmove   fp7,fp1                 ;fp1 = d_zistepu
  1976.         fmul    fp0,fp1                 ;multiply by $8000*$10000
  1977.         fmove.l fp1,d4                  ;izistep = d4
  1978.         moveq   #16,d6
  1979.  
  1980. *                pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
  1981. *
  1982. *                count = pspan->count;
  1983. *
  1984. *        // calculate the initial 1/z
  1985. *                du = (float)pspan->u;
  1986. *                dv = (float)pspan->v;
  1987. *
  1988. *                zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  1989. *        // we count on FP exceptions being turned off to avoid range problems
  1990. *                izi = (int)(zi * 0x8000 * 0x10000);
  1991.  
  1992.  
  1993. .loop
  1994.         move.l  (a2)+,d0
  1995.         fmove   fp7,fp4
  1996.         fmul.l  d0,fp4                  ;fp4 = du * d_zistepu
  1997.         move.l  (a2)+,d1
  1998.         fmove   fp6,fp3
  1999.         fmul.l  d1,fp3                  ;fp3 = dv * d_zistepv
  2000.         move.l  (a2)+,d2
  2001.         fadd    fp3,fp4
  2002.         muls    d7,d1                   ;d1 = pspan->v * d_zwidth
  2003.         fadd    fp5,fp4                 ;fp4 = d_ziorigin + fp3 + fp4
  2004.         add.l   d0,d1                   ;d1 = d1 + pspan->u
  2005.         lea     0(a0,d1.l*2),a1         ;pdest = d_pzbuffer + d1
  2006.         fmul    fp0,fp4                 ;izi = zi * $8000 * $10000
  2007.         fmove.l fp4,d3                  ;convert to integer
  2008.  
  2009. *                if ((long)pdest & 0x02)
  2010. *                {
  2011. *                        *pdest++ = (short)(izi >> 16);
  2012. *                        izi += izistep;
  2013. *                        count--;
  2014. *                }
  2015.  
  2016.         move.l  a1,d0                   ;if ((long)pdest & 0x02)
  2017.         and.l   #2,d0
  2018.         beq.b   .cont
  2019.         swap    d3
  2020.         move    d3,(a1)+                ;*pdest++ = (short)(izi>>16)
  2021.         swap    d3
  2022.         add.l   d4,d3                   ;izi += izistep;
  2023.         subq    #1,d2                   ;count--
  2024. .cont
  2025.  
  2026. *                if ((doublecount = count >> 1) > 0)
  2027. *                {
  2028. *                        do
  2029. *                        {
  2030. *                                ltemp = izi >> 16;
  2031. *                                izi += izistep;
  2032. *                                ltemp |= izi & 0xFFFF0000;
  2033. *                                izi += izistep;
  2034. *                                *(int *)pdest = ltemp;
  2035. *                                pdest += 2;
  2036. *                        } while (--doublecount > 0);
  2037. *                }
  2038.  
  2039.         move.l  d2,d0                   ;if ((doublecount=count>>1)>0)
  2040.         asr.l   #1,d0
  2041.         ble.b   .cont2
  2042.         subq    #1,d0
  2043. .loop2
  2044.         move.l  d3,d5
  2045.         lsr.l   d6,d5                   ;temp = izi >> 16
  2046.         add.l   d4,d3                   ;izi += izistep
  2047.         move.l  d3,d1
  2048.         and.l   #$ffff0000,d1
  2049.         or.l    d1,d5                   ;ltemp |= izi & 0xFFFF0000
  2050.         add.l   d4,d3                   ;izi += izistep
  2051.         move.l  d5,(a1)+                ;*(int *)pdest = ltemp
  2052.         dbra    d0,.loop2               ;while (--doublecount > 0)
  2053. .cont2
  2054.  
  2055. *                if (count & 1)
  2056. *                        *pdest = (short)(izi >> 16);
  2057.  
  2058.         and.l   #$1,d2                  ;if (count & 1)
  2059.         beq.b   .cont3
  2060.         swap    d3
  2061.         move    d3,(a1)+                ;*pdest = (short)(izi >> 16)
  2062. .cont3
  2063.  
  2064. *        } while ((pspan = pspan->pnext) != NULL);
  2065.  
  2066.         move.l  (a2)+,a2
  2067.         tst.l   a2
  2068.         bne.w   .loop
  2069.         fmovem.x        (sp)+,fp3-fp7
  2070.         movem.l (sp)+,d2-d7/a2
  2071.         rts
  2072.  
  2073. ReciprocTable
  2074.         dc.w    0
  2075.         dc.w    0
  2076.         dc.w    0
  2077.         dc.w    16384/3
  2078.         dc.w    0
  2079.         dc.w    16384/5
  2080.         dc.w    16384/6
  2081.         dc.w    16384/7
  2082.         dc.w    0
  2083.         dc.w    16384/9
  2084.         dc.w    16384/10
  2085.         dc.w    16384/11
  2086.         dc.w    16384/12
  2087.         dc.w    16384/13
  2088.         dc.w    16384/14
  2089.         dc.w    16384/15
  2090. _SysBase        dc.l    0
  2091.