home *** CD-ROM | disk | FTP | other *** search
- *
- * Copyright (C) 1996-1997 Id Software, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
-
- **
- ** Quake for AMIGA
- ** r_edge.c assembler implementations by Frank Wille <frank@phoenix.owl.de>
- **
-
- XREF _r_bmodelactive
- XREF _surfaces
- XREF _span_p
- XREF _current_iv
- XREF _fv
- XREF _edge_head
- XREF _edge_tail
- XREF _edge_aftertail
- XREF _edge_head_u_shift20
- XREF _R_CleanupSpan
-
- XDEF _R_RemoveEdges
- XDEF _R_InsertNewEdges
- XDEF _R_StepActiveU
- XDEF _R_GenerateSpans
-
- SURF_NEXT = 0
- SURF_PREV = 4
- SURF_SPANS = 8
- SURF_KEY = 12
- SURF_LAST_U = 16
- SURF_SPANSTATE = 20
- SURF_INSUBMODEL = 40
- SURF_D_ZIORIGIN = 44
- SURF_D_ZISTEPU = 48
- SURF_D_ZISTEPV = 52
- SURF_SIZEOF_EXP = 6
- SURF_SIZEOF = (1<<SURF_SIZEOF_EXP)
- SPAN_U = 0
- SPAN_V = 4
- SPAN_COUNT = 8
- SPAN_PNEXT = 12
- SPAN_SIZEOF = 16
- EDGE_U = 0
- EDGE_U_STEP = 4
- EDGE_PREV = 8
- EDGE_NEXT = 12
- EDGE_SURFS = 16
- EDGE_NEXTREMOVE = 20
-
- fpu
-
- ******************************************************************************
- *
- * void _R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist)
- *
- ******************************************************************************
-
- cnop 0,4
- _R_InsertNewEdges
-
- ***** stackframe
-
- rsreset
- .intregs rs.l 1
- rs.l 1
- .edgestoadd rs.l 1
- .edgelist rs.l 1
-
-
- * do
- * {
- * next_edge = edgestoadd->next;
- *edgesearch:
- * if (edgelist->u >= edgestoadd->u)
- * goto addedge;
- * edgelist=edgelist->next;
- * if (edgelist->u >= edgestoadd->u)
- * goto addedge;
- * edgelist=edgelist->next;
- * if (edgelist->u >= edgestoadd->u)
- * goto addedge;
- * edgelist=edgelist->next;
- * if (edgelist->u >= edgestoadd->u)
- * goto addedge;
- * edgelist=edgelist->next;
- * goto edgesearch;
- *
- * // insert edgestoadd before edgelist
- *addedge:
- * edgestoadd->next = edgelist;
- * edgestoadd->prev = edgelist->prev;
- * edgelist->prev->next = edgestoadd;
- * edgelist->prev = edgestoadd;
- * } while ((edgestoadd = next_edge) != NULL);
-
- move.l a2,-(sp)
- move.l .edgestoadd(sp),a0
- move.l .edgelist(sp),a1
- move.l EDGE_U(a0),d1
- .loop
- cmp.l EDGE_U(a1),d1 ;if (edgelist->u >= edgestoadd->u)
- ble.b .addedge ;goto addedge
- move.l EDGE_NEXT(a1),a1 ;edgelist=edgelist->next
- cmp.l EDGE_U(a1),d1
- ble.b .addedge
- move.l EDGE_NEXT(a1),a1
- cmp.l EDGE_U(a1),d1
- ble.b .addedge
- move.l EDGE_NEXT(a1),a1
- cmp.l EDGE_U(a1),d1
- ble.b .addedge
- move.l EDGE_NEXT(a1),a1
- bra.b .loop
- .addedge
- move.l EDGE_NEXT(a0),d0 ;next_edge = edgestoadd->next
- move.l a1,EDGE_NEXT(a0) ;edgestoadd->next = edgelist
- move.l EDGE_PREV(a1),a2
- move.l a2,EDGE_PREV(a0) ;edgestoadd->prev = edgelist->prev
- move.l a0,EDGE_NEXT(a2) ;edgelist->prev->next = edgestoadd
- move.l a0,EDGE_PREV(a1) ;edgelist->prev = edgestoadd
- tst.l d0 ;while ((edgestoadd = next_edge) != NULL)
- beq.b .end
- move.l d0,a0
- move.l EDGE_U(a0),d1
- bra.b .loop
- .end
- move.l (sp)+,a2
- rts
-
-
-
-
-
-
- ******************************************************************************
- *
- * void _R_RemoveEdges (edge_t *pedge)
- *
- ******************************************************************************
-
- cnop 0,4
- _R_RemoveEdges
-
- ***** stackframe
-
- rsreset
- .intregs rs.l 1
- rs.l 1
- .pedge rs.l 1
-
-
- * do
- * {
- * pedge->next->prev = pedge->prev;
- * pedge->prev->next = pedge->next;
- * } while ((pedge = pedge->nextremove) != NULL);
-
- move.l a2,-(sp)
- move.l .pedge(sp),a0
- .loop
- move.l EDGE_NEXT(a0),a1
- move.l EDGE_PREV(a0),a2
- move.l a2,EDGE_PREV(a1) ;pedge->next->prev = pedge->prev
- move.l a1,EDGE_NEXT(a2) ;pedge->prev->next = pedge->next
- move.l EDGE_NEXTREMOVE(a0),a0 ;while ((pedge = pedge->nextremove) != NULL)
- tst.l a0
- bne.b .loop
- move.l (sp)+,a2
- rts
-
-
-
-
-
-
-
-
- ******************************************************************************
- *
- * void _R_StepActiveU (edge_t *pedge)
- *
- ******************************************************************************
-
- cnop 0,4
- _R_StepActiveU
-
- ***** stackframe
-
- rsreset
- .intregs rs.l 5
- rs.l 1
- .pedge rs.l 1
-
-
- *nextedge:
- * pedge->u += pedge->u_step;
- * if (pedge->u < pedge->prev->u)
- * goto pushback;
- * pedge = pedge->next;
- *
- * pedge->u += pedge->u_step;
- * if (pedge->u < pedge->prev->u)
- * goto pushback;
- * pedge = pedge->next;
- *
- * pedge->u += pedge->u_step;
- * if (pedge->u < pedge->prev->u)
- * goto pushback;
- * pedge = pedge->next;
- *
- * pedge->u += pedge->u_step;
- * if (pedge->u < pedge->prev->u)
- * goto pushback;
- * pedge = pedge->next;
- *
- * goto nextedge;
-
- movem.l a2-a6,-(sp)
- move.l .pedge(sp),a0
- move.l EDGE_PREV(a0),a1
- move.l EDGE_U(a1),d1
- lea _edge_aftertail,a2
- lea _edge_tail,a3
- .loop
- move.l EDGE_U(a0),d0
- add.l EDGE_U_STEP(a0),d0
- move.l d0,EDGE_U(a0) ;pedge->u += pedge->u_step
- cmp.l d1,d0 ;if (pedge->u < pedge->prev->u)
- blt.b .pushback ;goto pushback
- move.l d0,d1
- move.l EDGE_NEXT(a0),a0 ;pedge = pedge->next
- move.l EDGE_U(a0),d0
- add.l EDGE_U_STEP(a0),d0
- move.l d0,EDGE_U(a0)
- cmp.l d1,d0
- blt.b .pushback
- move.l d0,d1
- move.l EDGE_NEXT(a0),a0
- move.l EDGE_U(a0),d0
- add.l EDGE_U_STEP(a0),d0
- move.l d0,EDGE_U(a0)
- cmp.l d1,d0
- blt.b .pushback
- move.l d0,d1
- move.l EDGE_NEXT(a0),a0
- move.l EDGE_U(a0),d0
- add.l EDGE_U_STEP(a0),d0
- move.l d0,EDGE_U(a0)
- cmp.l d1,d0
- blt.b .pushback
- move.l d0,d1
- move.l EDGE_NEXT(a0),a0
- bra.b .loop
-
- * if (pedge == &edge_aftertail)
- * return;
- *
- * // push it back to keep it sorted
- * pnext_edge = pedge->next;
- *
- * // pull the edge out of the edge list
- * pedge->next->prev = pedge->prev;
- * pedge->prev->next = pedge->next;
- *
- * // find out where the edge goes in the edge list
- * pwedge = pedge->prev->prev;
- *
- * while (pwedge->u > pedge->u)
- * {
- * pwedge = pwedge->prev;
- * }
- *
- * // put the edge back into the edge list
- * pedge->next = pwedge->next;
- * pedge->prev = pwedge;
- * pedge->next->prev = pedge;
- * pwedge->next = pedge;
- *
- * pedge = pnext_edge;
- * if (pedge == &edge_tail)
- * return;
-
- .pushback
- cmp.l a0,a2 ;if (pedge == &edge_aftertail)
- beq.w .end ;return
- move.l EDGE_NEXT(a0),a4 ;pnext_edge = pedge->next
- move.l EDGE_PREV(a0),a5
- move.l a5,EDGE_PREV(a4) ;pedge->next->prev = pedge->prev
- move.l a4,EDGE_NEXT(a5) ;pedge->prev->next = pedge->next
- move.l EDGE_PREV(a5),a5 ;pwedge = pedge->prev->prev
- .loop2
- cmp.l EDGE_U(a5),d0 ;while (pwedge->u > pedge->u)
- bgt.b .cont
- move.l EDGE_PREV(a5),a5 ;pwedge = pwedge->prev
- bra.b .loop2
- .cont
- move.l EDGE_NEXT(a5),a1
- move.l a1,EDGE_NEXT(a0) ;pedge->next = pwedge->next
- move.l a5,EDGE_PREV(a0) ;pedge->prev = pwedge
- move.l a0,EDGE_PREV(a1) ;pedge->next->prev = pedge
- move.l a0,EDGE_NEXT(a5) ;pwedge->next = pedge
- move.l a4,a0 ;pedge = pnext_edge
- cmp.l a3,a0 ;if (pedge == &edge_tail)
- bne.b .loop
- .end
- movem.l (sp)+,a2-a6
- rts
-
-
-
-
-
-
-
-
- ******************************************************************************
- *
- * void _R_GenerateSpans (void)
- *
- * R_TrailingEdge and R_LeadingEdge are inlined
- *
- * notes:
- * Increment and Decrement of _r_bmodelactive removed, because it's
- * obsolete here
- *
- ******************************************************************************
-
- cnop 0,4
- _R_GenerateSpans
-
- ****** prologue
-
- movem.l d2-d7/a2-a6,-(sp)
- fmovem.x fp2-fp7,-(sp)
- clr.l _r_bmodelactive
- move.l _current_iv,d2
- move.l _surfaces,a3
- lea 1*SURF_SIZEOF(a3),a4
- move.l a4,SURF_NEXT(a4)
- move.l a4,SURF_PREV(a4)
- move.l _edge_head_u_shift20,SURF_LAST_U(a4)
- move.l _edge_head+EDGE_NEXT,a5
- lea _edge_tail,a6
- move.l _span_p,a4
- bra.w .try
- .loop
- move.l EDGE_U(a5),d4
- move.l d4,d7
- moveq #20,d0
- asr.l d0,d4
- move.l EDGE_SURFS(a5),d1
- move.l d1,d0
- swap d0
- ext.l d0
- beq.b .cont
- asl.l #SURF_SIZEOF_EXP,d0
- lea 0(a3,d0.l),a0
-
- ****** R_TrailingEdge (inlined)
-
- * if (--surf->spanstate == 0)
- * {
- * if (surf->insubmodel)
- * r_bmodelactive--;
- *
- * if (surf == surfaces[1].next)
- * {
- * // emit a span (current top going away)
- * iu = edge->u >> 20;
- * if (iu > surf->last_u)
- * {
- * span = span_p++;
- * span->u = surf->last_u;
- * span->count = iu - span->u;
- * span->v = current_iv;
- * span->pnext = surf->spans;
- * surf->spans = span;
- * }
- *
- * // set last_u on the surface below
- * surf->next->last_u = iu;
- * }
- *
- * surf->prev->next = surf->next;
- * surf->next->prev = surf->prev;
- * }
-
- subq.l #1,SURF_SPANSTATE(a0) ;if (--surf->spanstate) == 0
- bne.b .cont
- move.l SURF_NEXT(a0),a1
- cmp.l 1*SURF_SIZEOF+SURF_NEXT(a3),a0 ;if (surf==surfaces[1].next)
- bne.b .te_cont2
- move.l d4,d0 ;iu = edge->u >> 20
- move.l SURF_LAST_U(a0),d5
- move.l d0,SURF_LAST_U(a1) ;surf->next->last_u = iu
- sub.l d5,d0 ;if (iu > surf->last_u)
- ble.b .te_cont2
- move.l SURF_SPANS(a0),d3
- move.l a4,SURF_SPANS(a0) ;surf->spans = span
- move.l d5,(a4)+ ;span->u = surf->last_u
- move.l d2,(a4)+ ;span->v = current_iv
- move.l d0,(a4)+ ;span->count = iu - span->u
- move.l d3,(a4)+ ;span->pnext = surf->spans
- .te_cont2
- move.l SURF_PREV(a0),a2
- move.l a1,SURF_NEXT(a2) ;surf->prev->next = surf->next
- move.l a2,SURF_PREV(a1) ;surf->next->prev = surf->prev
-
- ****** end of R_TrailingEdge
-
- .cont
-
- ****** R_LeadingEdge (inlined)
-
- * if (edge->surfs[1])
- * {
- * // it's adding a new surface in, so find the correct place
- * surf = &surfaces[edge->surfs[1]];
- *
- ext.l d1
- beq.w .next
- asl.l #SURF_SIZEOF_EXP,d1
- lea 0(a3,d1.l),a1 ;surf = &surfaces[edge->surfs[1]]
- *
- * // don't start a span if this is an inverted span, with the end
- * // edge preceding the start edge (that is, we've already seen the
- * // end edge)
- * if (++surf->spanstate == 1)
- * {
- * if (surf->insubmodel)
- * r_bmodelactive++;
- *
- * surf2 = surfaces[1].next;
- *
- * if (surf->key < surf2->key)
- * goto newtop;
- * // if it's two surfaces on the same plane, the one that's already
- * // active is in front, so keep going unless it's a bmodel
- * if (surf->insubmodel && (surf->key == surf2->key))
- * {
-
-
- move.l SURF_SPANSTATE(a1),d0 ;if (++surf->spanstate == 1)
- beq.b .le_zero
- addq.l #1,SURF_SPANSTATE(a1)
- bra.w .next
- .le_zero
- addq.l #1,d0
- move.l d0,SURF_SPANSTATE(a1)
- move.l SURF_INSUBMODEL(a1),d5 ;if (surf->insubmodel)
- move.l 1*SURF_SIZEOF+SURF_NEXT(a3),a0 ;surf2 = surfaces[1].next
- move.l SURF_KEY(a1),d6
- moveq #0,d3
- cmp.l SURF_KEY(a0),d6 ;if (surf->key < surf2->key)
- blt.b .le_newtop ;goto newtop
- bgt.b .le_search
- tst.b d5
- beq.b .le_search
-
- moveq #-1,d3
- move.l d7,d0
- sub.l #$fffff,d0 ;edge->u - 0xFFFFF
- fmove.l d0,fp0 :(float)(edge->u - 0xFFFFF)
- fmul.s #(1.0/(16*65536)),fp0 ;fu = fp0 * (1 / $100000)
- fmove.s _fv,fp1 ;fv
- fmove.s SURF_D_ZIORIGIN(a1),fp2
- fmove.s SURF_D_ZISTEPV(a1),fp3
- fmul fp1,fp3 ;fp1 = fv * surf->d_zistepv
- fadd fp3,fp2
- fmove.s SURF_D_ZISTEPU(a1),fp3
- fmove fp3,fp4 ;fp4 = surf->d_zistepu
- fmul fp0,fp3 ;fp3 = fu * surf->d_zistepu
- fadd fp3,fp2 ;newzi = d_ziorigin + fp1 + fp3
- fmove fp2,fp3
- fmul.s #0.99,fp2 ;newzibottom = newzi * 0.99
- fmul.s #1.01,fp3 ;newzitop = newzi * 1.01
-
-
- * // must be two bmodels in the same leaf; sort on 1/z
- * fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
- * newzi = surf->d_ziorigin + fv*surf->d_zistepv +
- * fu*surf->d_zistepu;
- * newzibottom = newzi * 0.99;
- *
- * testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
- * fu*surf2->d_zistepu;
- *
- * if (newzibottom >= testzi)
- * {
- * goto newtop;
- * }
- *
- * newzitop = newzi * 1.01;
- * if (newzitop >= testzi)
- * {
- * if (surf->d_zistepu >= surf2->d_zistepu)
- * {
- * goto newtop;
- * }
- * }
-
- fmove.s SURF_D_ZIORIGIN(a0),fp5
- fmove.s SURF_D_ZISTEPV(a0),fp6
- fmul fp1,fp6 ;fp1 = fv * surf2->d_zistepv
- fadd fp6,fp5
- fmove.s SURF_D_ZISTEPU(a0),fp6
- fmove fp6,fp7
- fmul fp0,fp6 ;fp3 = fu * surf2->d_zistepu
- fadd fp6,fp5 ;testzi = d_ziorigin + fp1 + fp3
- fcmp fp5,fp2 ;if (newzibottom >= testzi)
- fbge.b .le_newtop ;goto newtop
- fcmp fp5,fp3 ;if (newzitop >= testzi)
- fblt.b .le_search
- fcmp fp7,fp4 ;if (surf->d_zistepu >= surf2->d_zistepu)
- fbge.b .le_newtop ;goto newtop
-
- * do
- * {
- * surf2 = surf2->next;
- * } while (surf->key > surf2->key);
- *
-
-
- .le_search
- move.l SURF_NEXT(a0),a0 ;surf2 = surf2->next
- cmp.l SURF_KEY(a0),d6 ;while (surf->key > surf2->key)
- bgt.b .le_search
-
- * if (surf->key == surf2->key)
- * {
- * // if it's two surfaces on the same plane, the one that's already
- * // active is in front, so keep going unless it's a bmodel
- * if (!surf->insubmodel)
- * goto continue_search;
-
- bne.b .le_gotposition
- tst.b d5
- beq.b .le_search
- tst d3
- bne.b .le_precalc_done
- moveq #-1,d3
- move.l d7,d0
- sub.l #$fffff,d0 ;edge->u - 0xFFFFF
- fmove.l d0,fp0 :(float)(edge->u - 0xFFFFF)
- fmul.s #(1.0/(16*65536)),fp0 ;fu = fp0 * (1 / $100000)
- fmove.s _fv,fp1 ;fv
- fmove.s SURF_D_ZIORIGIN(a1),fp2
- fmove.s SURF_D_ZISTEPV(a1),fp3
- fmul fp1,fp3 ;fp1 = fv * surf->d_zistepv
- fadd fp3,fp2
- fmove.s SURF_D_ZISTEPU(a1),fp3
- fmove fp3,fp4 ;fp4 = surf->d_zistepu
- fmul fp0,fp3 ;fp3 = fu * surf->d_zistepu
- fadd fp3,fp2 ;newzi = d_ziorigin + fp1 + fp3
- fmove fp2,fp3
- fmul.s #0.99,fp2 ;newzibottom = newzi * 0.99
- fmul.s #1.01,fp3 ;newzitop = newzi * 1.01
- .le_precalc_done
-
- * // must be two bmodels in the same leaf; sort on 1/z
- * fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
- * newzi = surf->d_ziorigin + fv*surf->d_zistepv +
- * fu*surf->d_zistepu;
- * newzibottom = newzi * 0.99;
- *
- * testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
- * fu*surf2->d_zistepu;
- *
- * if (newzibottom >= testzi)
- * {
- * goto gotposition;
- * }
- *
- * newzitop = newzi * 1.01;
- * if (newzitop >= testzi)
- * {
- * if (surf->d_zistepu >= surf2->d_zistepu)
- * {
- * goto gotposition;
- * }
- * }
- *
- * goto continue_search;
- * }
- *
- * goto gotposition;
-
- fmove.s SURF_D_ZIORIGIN(a0),fp5
- fmove.s SURF_D_ZISTEPV(a0),fp6
- fmul fp1,fp6 ;fp1 = fv * surf2->d_zistepv
- fadd fp6,fp5
- fmove.s SURF_D_ZISTEPU(a0),fp6
- fmove fp6,fp7
- fmul fp0,fp6 ;fp3 = fu * surf2->d_zistepu
- fadd fp6,fp5 ;testzi = d_ziorigin + fp1 + fp3
- fcmp fp5,fp2 ;if (newzibottom >= testzi)
- fbge.b .le_gotposition ;goto gotposition
- fcmp fp5,fp3 ;if (newzitop >= testzi)
- fblt.b .le_search
- fcmp fp7,fp4 ;if (surf->d_zistepu >= surf2->d_zistepu)
- fbge.b .le_gotposition ;goto gotposition
- bra.b .le_search
-
- * // emit a span (obscures current top)
- * iu = edge->u >> 20;
- *
- * if (iu > surf2->last_u)
- * {
- * span = span_p++;
- * span->u = surf2->last_u;
- * span->count = iu - span->u;
- * span->v = current_iv;
- * span->pnext = surf2->spans;
- * surf2->spans = span;
- * }
- *
- * // set last_u on the new span
- * surf->last_u = iu;
-
- .le_newtop
- move.l SURF_LAST_U(a0),d5
- move.l d4,SURF_LAST_U(a1) ;surf->last_u = iu
- sub.l d5,d4 ;if (iu > surf2->last_u)
- ble.b .le_cont2
- move.l SURF_SPANS(a0),d3
- move.l a4,SURF_SPANS(a0) ;surf2->spans = span
- move.l d5,(a4)+ ;span->u = surf2->last_u
- move.l d2,(a4)+ ;span->v = current_iv
- move.l d4,(a4)+ ;span->count = iu - span->u
- move.l d3,(a4)+ ;span->pnext = surf2->spans
- .le_cont2
-
- * // insert before surf2
- * surf->next = surf2;
- * surf->prev = surf2->prev;
- * surf2->prev->next = surf;
- * surf2->prev = surf;
-
- .le_gotposition
- move.l SURF_PREV(a0),a2
- move.l a2,SURF_PREV(a1) ;surf->prev = surf2->prev
- move.l a0,SURF_NEXT(a1) ;surf->next = surf2
- move.l a1,SURF_NEXT(a2) ;surf2->prev->next = surf
- move.l a1,SURF_PREV(a0) ;surf2->prev = surf
-
- ****** end of R_LeadingEdge
-
- .next
- move.l EDGE_NEXT(a5),a5
- .try
- cmp.l a5,a6
- bne.b .loop
- move.l a4,_span_p
- jsr _R_CleanupSpan
- fmovem.x (sp)+,fp2-fp7
- movem.l (sp)+,d2-d7/a2-a6
- rts
-