home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 113
/
EnigmaAmiga113CD.iso
/
software
/
sviluppo
/
quake_src
/
r_edge68k.s
< prev
next >
Wrap
Text File
|
2000-06-17
|
22KB
|
673 lines
*
* 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