Un-ignored: the dev drive is the ground truth the restoration and emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio content). Kept in-repo for the pod-owner community. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1552 lines
46 KiB
Plaintext
1552 lines
46 KiB
Plaintext
|
|
/*{{{ banner*/
|
|
/*
|
|
|
|
File eof.c
|
|
project pazpl5
|
|
author pja
|
|
date 7th july 1993
|
|
|
|
(c) DIVISION limited 1993
|
|
|
|
This is the end-of-frame code for pazpl5.
|
|
|
|
|
|
*/
|
|
/*}}} */
|
|
/*{{{ about this code*/
|
|
/*
|
|
|
|
There are 2 end-of-frame sequences - end-of-frame, and end-of-texture
|
|
|
|
As we enter end-of-frame processing, we have a pixel map as defined in
|
|
divpxmap.h, containing colour, texture id and material property
|
|
information. The main task performed at end-of-frame is the texture
|
|
perspective divide, and the subsequent computation of texel address.
|
|
The perspective divide is in fact 2 divides - u and v are both divided
|
|
by homo, then coalesced to form the texel address. This is then added to
|
|
the texture base address (texture id << 12) to yield the texel look-up
|
|
address. Immediately this has been written into pixelmemory:0..23 we can
|
|
sequence the texture lookup - in fact we should perform the divide,
|
|
coalesce the texel offset into the homo coordinate, execute a pxpl5
|
|
'wait for pixel transfer to be complete' opcode, then do a
|
|
copy 16 bits of texel offset to pixel memory, clear next 16 bits of
|
|
pixel memory, then add into bits 12..20 the texture id. We have a full
|
|
texel address, and we can execute a 'do texture lookup' opcode. At this
|
|
point we know we have the end-of-frame area free to write into, and we
|
|
can copy the shading variables into the end-of-frame area, and proceed
|
|
with polygon processing for the next tile. Copying the shading variables
|
|
involves doing just copies, but the location of the copy is dependent on
|
|
the type of pixel - rgb pixels are copied straight into the accumulation
|
|
buffer, but 16-bit intrinsic pixels are multiplied by the 8-bit diffuse
|
|
lighting channel (and possibly by the light colour?) before being dropped
|
|
into the accumulation area. The remainder of the u and v coordinates are then
|
|
copied into the sub-u and sub-v areas, and the 8 bits of specular lighting
|
|
are written into end-of-frame space.
|
|
|
|
When the texture lookup is complete, the opcode sequence is interrupted,
|
|
and effectively a DMA engine subroutine call is performed. At this point we
|
|
have a 24-bit texture value in pixelmemory:0..23, and the end-of-frame
|
|
shading variables in locations dvpx_eofr (see divpxmap.h). The 30-bit
|
|
accumulation area only has 24 used bits at this point, and we need the
|
|
other 6. We have to turn any 6-bit interpolated textures into 24-bit values -
|
|
the first step is to bilinterp to compute an 8-bit modulator. We then need to
|
|
pull in a selection of ramps, and select the right one. I suspect I cant
|
|
support more than 8 ramps (3 extra bits of end-of-frame material); this
|
|
will allow black/white (fine for stuff like wood; brightness modulate yellow)
|
|
and blue/white (sky) - i cant think of another 6, so that's enough. We pull
|
|
in 8 raps, each of 24-bits (12 upper bits, 12 lower bits), and linterp
|
|
between upper and lower, to yield a 24-bit scalar.
|
|
|
|
If these operations are organised to yield a 30-bit accumulation buffer, we
|
|
can accumulate in-place.
|
|
|
|
We now multiply the 24-bit diffuse colour (in end-of-frame space) by the
|
|
24-bit texture look-up value.
|
|
|
|
We have now freed up the 24-bit diffuse slot, and can download the colour of
|
|
the light into this. We now multiply the specular value by the colour of the
|
|
light, and add this into the accumulation area, shifting the results down
|
|
into the lower 24-bits of the word.
|
|
|
|
And that is it - we have 24-bits of pixel memory for dumping into a
|
|
framestore
|
|
|
|
*/
|
|
/*}}} */
|
|
|
|
/*
|
|
*/
|
|
#define FOG 1
|
|
|
|
#include <math.h>
|
|
#include "divpxmap.h"
|
|
#include "dmaengn.h"
|
|
#include "pxpl5typ.h"
|
|
#include "..\pazpl5.h"
|
|
#include "u:\projects\dbi0150\dbi0151\ucode\igc_opco.h"
|
|
#include "u:\projects\dbi0150\dbi0151\ucode\igc_comm.h"
|
|
|
|
/*{{{ int *tblcpy ( int *dst, int *src )*/
|
|
int *tblcpy ( int *dst, int *src )
|
|
{
|
|
int *p=dst;
|
|
|
|
while ((*src & 0x80000000) == 0)
|
|
*p++ = *src++;
|
|
|
|
*p++=*src;
|
|
return p;
|
|
}
|
|
/*}}} */
|
|
|
|
int pxpl5_ticks=0;
|
|
|
|
/* start of frame code */
|
|
|
|
/*{{{ int *configEMCshi ( int *coeffptr, int x0, int y0 )*/
|
|
int *configEMCs_hi ( int *coeffptr, int x0, int y0 )
|
|
{
|
|
|
|
/*{{{ magic table*/
|
|
int EMC[] = {
|
|
0x2,0x0,0xA,0x8,0x12,0x10,0x1A,0x18,
|
|
0x3,0x1,0xB,0x9,0x13,0x11,0x1B,0x19,
|
|
0x6,0x4,0xE,0xC,0x16,0x14,0x1E,0x1C,
|
|
0x7,0x5,0xF,0xD,0x17,0x15,0x1F,0x1D
|
|
};
|
|
/*}}} */
|
|
|
|
int XbAhi, XbBhi, XbAlo, XbBlo, Yb, scalar;
|
|
int i, x=0;
|
|
|
|
Yb = (y0 >> 7) & 0xf;
|
|
/*{{{ walk in x coord*/
|
|
for ( i=0; i<32; i++ ) {
|
|
/*{{{ */
|
|
x = EMC[i] + x0;
|
|
XbAlo = x & 0x7f; /* bottom 7 bits of XbA */
|
|
XbBlo = (x+32) & 0x7f; /* bottom 7 bits of XbB */
|
|
XbAhi = (x >> 7) & 0xf; /* top 4 bits of XbA */
|
|
XbBhi = ((x+32) >> 7) & 0xf; /* top 4 bits of XbB */
|
|
|
|
scalar = (Yb<<22) |
|
|
XbAlo |
|
|
(XbBlo << 7) |
|
|
(XbAhi << 14) |
|
|
(XbBhi << 18);
|
|
|
|
/*}}} */
|
|
IGC_SEPCFG_S1 ( coeffptr, i, 26, scalar );
|
|
/*x0++; */
|
|
}
|
|
/*}}} */
|
|
/*{{{ loads of noops*/
|
|
for (i=0; i<24; i++ )
|
|
IGC_NOOP ( coeffptr );
|
|
|
|
return coeffptr;
|
|
/*}}} */
|
|
}
|
|
|
|
|
|
/* CT */
|
|
/* 0 1 2 3 */
|
|
|
|
/* 0 2 8 3 10 6 18 7 */
|
|
/* E 1 0 9 1 11 4 19 5 */
|
|
/* M 2 A A B 12 E 1A F */
|
|
/* C 3 8 B 9 13 C 1B D */
|
|
/* 4 18 C 19 14 1C 1C 1D */
|
|
/* 5 16 B 17 15 1A 1B 1B */
|
|
/* 6 20 E 21 16 24 1E 25 */
|
|
/* 7 1E F 1D 17 24 1F 25 */
|
|
|
|
/*}}} */
|
|
/*{{{ int *configEMCs ( int *coeffptr, int x0, int y0 )*/
|
|
int *configEMCs ( int *coeffptr, int x0, int y0 )
|
|
{
|
|
/*
|
|
we need to specify
|
|
Yb = bottom of Y in units of 128
|
|
XbA = left of A pixel bank
|
|
XbB = left of B pixel bank
|
|
|
|
pixel banks are separated by 32 pixels, A is lower.
|
|
Yb is a 4-bit field, in bits 22..25
|
|
XbA is 11 bits, split into 7+4. lower 7 in bits 0..6, upper 4 in 14..17
|
|
XbB is 11 bits, split into 7+4. lower 7 in bits 7..13, upper 4 in 18..21
|
|
|
|
This code caters for the 4-way, 8-stedped interleave of EMC->screen
|
|
space - the EMC ordering on-screen is 0, 8, 16, 24, 1, 9, 17 etc
|
|
*/
|
|
int XbAhi, XbBhi, XbAlo, XbBlo, Yb, scalar;
|
|
int i, EMCbase=0, EMCtick=0, lastEMCbase=0;
|
|
|
|
Yb = (y0 >> 7) & 0xf;
|
|
|
|
for ( i=0; i<32; i++ ) {
|
|
|
|
XbAlo = x0 & 0x7f; /* bottom 7 bits of XbA */
|
|
XbBlo = (x0+32) & 0x7f; /* bottom 7 bits of XbB */
|
|
XbAhi = (x0 >> 7) & 0xf; /* top 4 bits of XbA */
|
|
XbBhi = ((x0+32) >> 7) & 0xf; /* top 4 bits of XbB */
|
|
|
|
scalar = (Yb<<22) |
|
|
XbAlo |
|
|
(XbBlo << 7) |
|
|
(XbAhi << 14) |
|
|
(XbBhi << 18);
|
|
|
|
IGC_SEPCFG_S1 ( coeffptr, EMCbase, 26, scalar );
|
|
EMCbase+=8;
|
|
EMCtick++;
|
|
|
|
if (EMCtick == 4) {
|
|
lastEMCbase++;
|
|
EMCbase=lastEMCbase;
|
|
EMCtick=0;
|
|
}
|
|
|
|
x0++;
|
|
}
|
|
|
|
for (i=0; i<4; i++ )
|
|
IGC_NOOP ( coeffptr );
|
|
|
|
return coeffptr;
|
|
}
|
|
|
|
/*}}} */
|
|
/*{{{ int init_screenbin ( binchunk *firstbin,*/
|
|
int init_screenbin ( binchunk *firstbin,
|
|
int pixel_x,
|
|
int pixel_y, int hires )
|
|
{
|
|
/*{{{ what we do*/
|
|
/*
|
|
this function drops the start-of-frame coefficients into the head binchunk
|
|
of the screenbin.
|
|
|
|
There is a fifo latency problem, and we can just make this coefficient
|
|
list sufficiently long that we a) init the tile and also b) eat up
|
|
the latency to guarantee operation
|
|
|
|
In order to minimize eaten-up space, I shall drop the coefficients
|
|
into the binchunk itself. I need to keep around 8 64-bit words free,
|
|
for patching up, which leaves 500+ words of instructions.
|
|
|
|
The DMA opcode sequence is -
|
|
|
|
SEND ( startup, startup_words )
|
|
GOTO ( .after_startup_words )
|
|
|
|
.... put startup words here
|
|
|
|
:after_starup_words )
|
|
|
|
*/
|
|
/*}}} */
|
|
|
|
/*{{{ locals*/
|
|
int *DMAptr = &firstbin->DMA_opcodes[0];
|
|
int *DMAptr0 = DMAptr;
|
|
int *coeffptr = &DMAptr[64];
|
|
int *coeff0;
|
|
int t, bytes, words, i, branchAddr, *texdnAddr;
|
|
int backGND_offset=0;
|
|
/*}}} */
|
|
|
|
coeff0=coeffptr;
|
|
|
|
if ((int) coeff0 & 31) {
|
|
printf ("MISALIGNED ! ! ! ! ! coeff0 = 0x%x\n", coeff0 );
|
|
}
|
|
|
|
/*{{{ do 'start of tile' code*/
|
|
|
|
/* set up FBITs at the beginning of each tile */
|
|
IGC_FBITS ( coeffptr, 15 );
|
|
|
|
/* wait for tree to stabilize */
|
|
for (i=0; i<4; i++ ) {
|
|
IGC_NOOP ( coeffptr );
|
|
}
|
|
|
|
/* tell EMC array where they are on screen */
|
|
|
|
if (hires)
|
|
coeffptr=configEMCs_hi ( coeffptr, pixel_x, pixel_y );
|
|
else
|
|
coeffptr=configEMCs ( coeffptr, pixel_x, pixel_y );
|
|
|
|
/* clear out pixel memory (dont dick with end-of-frame area!) */
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CLEAR ( coeffptr, 32, dvpx_eofstart-32 );
|
|
|
|
/* set background colour */
|
|
|
|
IGC_SET ( coeffptr, dvpx_pixcolourtype, 1 );
|
|
|
|
backGND_offset=(int) coeffptr - (int) DMAptr0;
|
|
|
|
IGC_TREEclmpintoMEM_L3 ( coeffptr, dvpx_r24, 8, 0.0f, 0.0f, 50.0f );
|
|
IGC_TREEclmpintoMEM_L3 ( coeffptr, dvpx_g24, 8, 0.0f, 0.0f, 150.0f );
|
|
IGC_TREEclmpintoMEM_L3 ( coeffptr, dvpx_b24, 8, 0.0f, 0.0f, 210.0f );
|
|
|
|
/* now we need to set up the 50%, 25% etc opacity bits */
|
|
/* initially, just 50% */
|
|
/*
|
|
I should be able to use GRID or MESH, but cant get
|
|
the damn things to work, so generate the on-off pattern longhand
|
|
*/
|
|
|
|
#if 1
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_TREEintoMEM_L3 ( coeffptr, 32, 1, 1.0f, 0.0f, 0.01f );
|
|
IGC_TREEintoMEM_L3 ( coeffptr, 33, 1, 0.0f, 1.0f, 0.01f );
|
|
IGC_MEMintoENAB ( coeffptr, 33 );
|
|
IGC_ENABxoreqMEM ( coeffptr, 32 );
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_opaque_50 );
|
|
#endif
|
|
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_opaque_50 );
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_opaque_25 );
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_opaque_12 );
|
|
|
|
/* a few more NOOPs for good measure */
|
|
|
|
for (i=0; i<4; i++ ) {
|
|
IGC_NOOP ( coeffptr );
|
|
}
|
|
/*}}} */
|
|
/*{{{ note how much code we have generated*/
|
|
|
|
/* count up how much store we have used */
|
|
|
|
bytes=(int) coeffptr - (int) coeff0;
|
|
words=bytes >> 3; /* make into 64-bit count */
|
|
/*}}} */
|
|
|
|
/* these become GOTO next tile */
|
|
*DMAptr++=(int) 0;
|
|
*DMAptr++=(int) 0;
|
|
|
|
*DMAptr++=(int) coeff0;
|
|
*DMAptr++=DMA_SEND(words);
|
|
|
|
branchAddr = (int) coeff0 + (words << 3);
|
|
|
|
*DMAptr++=branchAddr;
|
|
*DMAptr++=DMA_GOTO_VAL;
|
|
|
|
firstbin->usage=(int) branchAddr - (int) DMAptr0;
|
|
firstbin->DMA_opcodes[63]=firstbin->usage;
|
|
|
|
return (backGND_offset >> 2);
|
|
}
|
|
/*}}} */
|
|
|
|
/* end of frame / texture code */
|
|
extern int *texture_table_iptr;
|
|
extern TEXRAMP *texture_ramps;
|
|
|
|
int *tile_poke_address;
|
|
|
|
|
|
/*{{{ static int *linterp ( int *coeffptr,*/
|
|
static int *linterp ( int *coeffptr,
|
|
int result,
|
|
int op1, int op2, int alpha,
|
|
int resultbits,
|
|
int oplen, int alphalen )
|
|
{
|
|
/*
|
|
NB alphabits must be < resultbits
|
|
*/
|
|
|
|
int i, reduced_adds;
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CLEAR ( coeffptr, result, resultbits );
|
|
|
|
if ((oplen + alphalen) < resultbits) {
|
|
reduced_adds=0;
|
|
result+=resultbits-(oplen+alphalen);
|
|
}
|
|
else {
|
|
reduced_adds=(alphalen+oplen) - resultbits;
|
|
op2+=reduced_adds;
|
|
op1+=reduced_adds;
|
|
oplen-=reduced_adds;
|
|
}
|
|
|
|
for (i=0; i<reduced_adds; i++ ) {
|
|
IGC_MEMintoENAB ( coeffptr, alpha );
|
|
IGC_MEMpluseqMEM ( coeffptr, result, op2, oplen+1, oplen );
|
|
|
|
IGC_MEMBARintoENAB ( coeffptr, alpha );
|
|
IGC_MEMpluseqMEM ( coeffptr, result, op1, oplen+1, oplen );
|
|
|
|
op1--;
|
|
op2--;
|
|
alpha++;
|
|
oplen++;
|
|
}
|
|
|
|
for (i=reduced_adds; i<alphalen; i++) {
|
|
IGC_MEMintoENAB ( coeffptr, alpha );
|
|
IGC_MEMpluseqMEM ( coeffptr, result, op2, oplen+1, oplen );
|
|
|
|
IGC_MEMBARintoENAB ( coeffptr, alpha );
|
|
IGC_MEMpluseqMEM ( coeffptr, result, op1, oplen+1, oplen );
|
|
|
|
alpha++;
|
|
result++;
|
|
}
|
|
|
|
return coeffptr;
|
|
|
|
}
|
|
/*}}} */
|
|
/*{{{ static int *multuu_unc ( int *coeffptr,*/
|
|
static int *multuu_unc ( int *coeffptr,
|
|
int res, int Ua, int Ub, int Rlen, int Ualen, int Ublen )
|
|
|
|
/************************************************************************
|
|
**
|
|
** multuu() - unsigned Result <- Unsigned x Unsigned. All in pixel memory.
|
|
** Result length must be >= both operand lengths.
|
|
**
|
|
************************************************************************/
|
|
|
|
{
|
|
int i, j, k;
|
|
|
|
IGC_SETENABS(coeffptr);
|
|
IGC_CLEAR(coeffptr, res, Rlen);
|
|
j = k = Ublen - Rlen + Ualen;
|
|
|
|
if (Ublen >= Ualen) {
|
|
for(i = 0; i < k; i++ ){
|
|
IGC_MEMintoENAB (coeffptr, Ua +i);
|
|
IGC_MEMpluseqMEM(coeffptr, res, Ub +j, Rlen, Ublen -j);
|
|
j--;
|
|
}
|
|
i=k;
|
|
while (i < Ualen) {
|
|
IGC_MEMintoENAB (coeffptr, Ua +i);
|
|
IGC_MEMpluseqMEM(coeffptr, res +j, Ub, Rlen -j, Ublen);
|
|
i++, j++;
|
|
}
|
|
}
|
|
else {
|
|
for(i = 0; i < k; i++ ){
|
|
IGC_MEMintoENAB(coeffptr, Ub +i);
|
|
IGC_MEMpluseqMEM(coeffptr, res, Ua +j, Rlen, Ualen -j);
|
|
j--;
|
|
}
|
|
i=k;
|
|
while (i < Ublen) {
|
|
IGC_MEMintoENAB(coeffptr, Ub +i);
|
|
IGC_MEMpluseqMEM(coeffptr, res +j, Ua, Rlen -j, Ualen);
|
|
i++, j++;
|
|
}
|
|
}
|
|
return coeffptr;
|
|
}
|
|
/*}}} */
|
|
static char* send_pass="zilch";
|
|
|
|
/*{{{ int *send_em ( int **DMAref, int **coeffref, int *coeff0, int flush )*/
|
|
static
|
|
int *send_em ( int **DMAref, int **coeffref, int *coeff0, int flush, int max_long )
|
|
{
|
|
int *coeffptr=*coeffref;
|
|
int *DMAptr =*DMAref;
|
|
int words, longwords;
|
|
|
|
words=((int) coeffptr - (int) coeff0) >> 2;
|
|
longwords = words >> 1;
|
|
|
|
/* pad coefficient stream to ensure 64-bit boundary */
|
|
if ((flush && (longwords > 0)) || (longwords > max_long)) {
|
|
|
|
if (words & 1) {
|
|
IGC_NOOP ( coeffptr );
|
|
longwords++;
|
|
}
|
|
/*
|
|
printf ("send(%d, %s) : DMAptr 0x%x %d words from 0x%x\n",
|
|
flush, send_pass, DMAptr, longwords, coeff0 );
|
|
*/
|
|
|
|
if (longwords > 127) {
|
|
/*
|
|
*/
|
|
printf ("WARNING - long SEND\n" );
|
|
|
|
*DMAptr++=(int) (coeff0);
|
|
*DMAptr++=DMA_SEND(120);
|
|
|
|
longwords-=120;
|
|
coeff0+=240;
|
|
}
|
|
|
|
*DMAptr++=(int) coeff0;
|
|
*DMAptr++=DMA_SEND(longwords);
|
|
|
|
coeffptr = (int *) ((31 + (int) (coeffptr)) & ~31);
|
|
|
|
*DMAref=DMAptr;
|
|
*coeffref=coeffptr;
|
|
|
|
return coeffptr;
|
|
}
|
|
else {
|
|
return coeff0;
|
|
}
|
|
}
|
|
|
|
/*}}} */
|
|
|
|
/*{{{ static void texdivide ( int **DMAref, int **coeffRef,*/
|
|
static void texdivide ( int **DMAref,
|
|
int **coeffRef,
|
|
int *coeff0,
|
|
int num,
|
|
int denom,
|
|
int fullbits,
|
|
int sigbits,
|
|
int terminal_flush )
|
|
{
|
|
/*
|
|
texdivide designed to be done in a scratchpad (normally z-buffer)
|
|
which is less than ubits*2 bits wide; we can only perform 'fullbits'
|
|
subtractions full precision, the remainder must be done at
|
|
reduced precision, the precision shrinking by one every time round the
|
|
loop.
|
|
*/
|
|
int i, res;
|
|
int *coeffptr=*coeffRef;
|
|
int *DMAptr =*DMAref;
|
|
|
|
send_pass="texdivide";
|
|
|
|
/* printf ("texdivide, coeff0=0x%x coeffptr=0x%x\n", coeff0, coeffptr ); */
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
|
|
/* point at MSB of result */
|
|
res=num+dvpx_texubits - 1;
|
|
|
|
for (i=0; i<fullbits; i++ ) {
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 10 );
|
|
|
|
IGC_MEMgeMEM ( coeffptr, num, denom, dvpx_texubits );
|
|
IGC_MEMminuseqMEM ( coeffptr, num, denom, dvpx_texubits, dvpx_texubits );
|
|
IGC_ENABintoMEM ( coeffptr, res );
|
|
IGC_SETENABS ( coeffptr );
|
|
sigbits--, res--, num--;
|
|
|
|
|
|
}
|
|
i=0;
|
|
|
|
|
|
while (sigbits) {
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 10 );
|
|
|
|
IGC_MEMgeMEM ( coeffptr, num, denom+i, dvpx_texubits-i );
|
|
IGC_MEMminuseqMEM ( coeffptr, num, denom+i, dvpx_texubits-i, dvpx_texubits-i );
|
|
IGC_ENABintoMEM ( coeffptr, res );
|
|
IGC_SETENABS ( coeffptr );
|
|
sigbits--, i++, res--;
|
|
|
|
}
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, terminal_flush, 10 );
|
|
|
|
*DMAref=DMAptr;
|
|
*coeffRef=coeff0;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void perspective_divides ( int **DMAref, int** coeffRef )*/
|
|
void perspective_divides ( int **DMAref, int** coeffRef )
|
|
{
|
|
/*
|
|
this is the first operation done at the end-of-frame for a given tile
|
|
we do not hit the i/o area, since it is potentially active (we have
|
|
not yet BSWAITed, but we are guaranteed to have done
|
|
the end-of-texture opcodes
|
|
*/
|
|
|
|
int *coeffptr=*coeffRef;
|
|
int *DMAptr=*DMAref;
|
|
int *coeff0 =coeffptr;
|
|
int *coeff00=coeffptr;
|
|
int i, words;
|
|
|
|
/*
|
|
printf ("coeffptr for perspective at 0x%x DMAptr at 0x%x\n",
|
|
coeffptr, DMAptr );
|
|
|
|
*/
|
|
#if divlogo
|
|
/*{{{ put division logo into bottom right of screen*/
|
|
{
|
|
/* NB only works if texture id=0, size=64, mode=point */
|
|
float x0=532.0f, x1=660.0f,
|
|
y0=382.0f, y1=440.0f;
|
|
float u0=0.001, u1=0.999f,
|
|
v0=0.999, v1=0.001f;
|
|
float du_dx=(u1-u0) / (x1-x0);
|
|
float dv_dy=(v1-v0) / (y1-y0);
|
|
|
|
float zscale=(1<<(dvpx_texzbits - 3)) * 0.999f;
|
|
float uscale=(1<<(dvpx_texubits - 3)) * 0.999f;
|
|
|
|
float uC=(x0*du_dx) - u0;
|
|
float vC=(y0*dv_dy) - v0;
|
|
|
|
/*
|
|
IGC_SETENABS ( coeffptr );
|
|
*/
|
|
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_opaque_50 );
|
|
|
|
IGC_TREEgeZERO_L3 ( coeffptr, 1.0f, 0.0f, -x0 );
|
|
IGC_TREEltZERO_L3 ( coeffptr, 1.0f, 0.0f, -x1 );
|
|
IGC_TREEgeZERO_L3 ( coeffptr, 0.0f, 1.0f, -y0 );
|
|
IGC_TREEltZERO_L3 ( coeffptr, 0.0f, 1.0f, -y1 );
|
|
|
|
/* put texture u into memory */
|
|
IGC_TREEintoMEM_L3 ( coeffptr,
|
|
dvpx_texu,
|
|
dvpx_texubits,
|
|
du_dx*uscale, 0, -uC*uscale );
|
|
/* put texture v into memory */
|
|
IGC_TREEintoMEM_L3 ( coeffptr,
|
|
dvpx_texv,
|
|
dvpx_texvbits,
|
|
0, dv_dy*uscale, -vC*uscale );
|
|
/* put texture z into memory */
|
|
IGC_TREEintoMEM_C1 ( coeffptr,
|
|
dvpx_texz,
|
|
dvpx_texzbits,
|
|
8.0f*zscale );
|
|
|
|
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_scalar, dvpx_intrinsic-dvpx_scalar,
|
|
1 | (4<<1) ); /* patch to indicate texture */
|
|
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_r24, 24, 0xffffff );
|
|
}
|
|
/*}}} */
|
|
#endif
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
|
|
/* lose 1 bit of precision in texz (required by divide) */
|
|
|
|
IGC_CLEAR ( coeffptr, dvpx_texz+dvpx_texzbits, 1 );
|
|
|
|
/* 16 bits of result == 3 (0 .. 7.990), 8 (0 .. 255), 5 sub-texel bits */
|
|
|
|
texdivide ( &DMAptr, &coeffptr, coeff0,
|
|
dvpx_texu,
|
|
dvpx_texz+1, 1,
|
|
16, 0 );
|
|
|
|
coeff0=coeffptr;
|
|
|
|
texdivide ( &DMAptr, &coeffptr, coeff0,
|
|
dvpx_texv,
|
|
dvpx_texz+1, 1,
|
|
16, 1 );
|
|
|
|
coeff0=coeffptr;
|
|
|
|
*coeffRef=coeffptr;
|
|
*DMAref =DMAptr;
|
|
}
|
|
/*}}} */
|
|
|
|
#if 0
|
|
/*{{{ static int* smokey_circle ( int *coeffptr, float xc, float yc, float r, int dark )*/
|
|
static int* smokey_circle ( int *coeffptr,
|
|
float xc, float yc, float r, int dark )
|
|
{
|
|
/*
|
|
scan-convert - g(x,y) = Ax + By + C - Q
|
|
A = 2a, B = 2b C = r2 - a2 - b2, Q = x2 + y2
|
|
*/
|
|
float fA, fB, fC, fD, fE, fF;
|
|
int affect_pixel=dvpx_texz;
|
|
|
|
fD=-1.0f;
|
|
fE= 0.0f;
|
|
fF=-1.0f;
|
|
|
|
fA=xc*2.0f;
|
|
fB=yc*2.0f;
|
|
fC=(r*r) - ((xc*xc) + (yc*yc));
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_TREEgeZERO_Q6 ( coeffptr, fA, fB, fC, fD, fE, fF );
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_enblpush );
|
|
|
|
/* enblpush says i am in the circle */
|
|
IGC_ENABandeqMEM ( coeffptr, dvpx_pixcolourtype );
|
|
IGC_ENABintoMEM ( coeffptr, affect_pixel );
|
|
|
|
IGC_MEMgtSCA_S1 ( coeffptr, dvpx_r24, 8, dark );
|
|
IGC_MEMpluseqSCA_S1 ( coeffptr, dvpx_r24, dvpx_r24, 8, (0xff & (-dark)));
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_ENABandeqMEM ( coeffptr, affect_pixel );
|
|
IGC_CLEAR ( coeffptr, dvpx_r24, 8 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, affect_pixel );
|
|
IGC_MEMgtSCA_S1 ( coeffptr, dvpx_g24, 8, dark );
|
|
IGC_MEMpluseqSCA_S1 ( coeffptr, dvpx_g24, dvpx_g24, 8, (0xff & (-dark)));
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_ENABandeqMEM ( coeffptr, affect_pixel );
|
|
IGC_CLEAR ( coeffptr, dvpx_g24, 8 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, affect_pixel );
|
|
IGC_MEMgtSCA_S1 ( coeffptr, dvpx_b24, 8, dark );
|
|
IGC_MEMpluseqSCA_S1 ( coeffptr, dvpx_b24, dvpx_b24, 8, (0xff & (-dark)));
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_ENABandeqMEM ( coeffptr, affect_pixel );
|
|
IGC_CLEAR ( coeffptr, dvpx_b24, 8 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_enblpush );
|
|
IGC_ENABandeqMEMBAR ( coeffptr, dvpx_pixcolourtype );
|
|
IGC_ENABintoMEM ( coeffptr, affect_pixel );
|
|
|
|
/*{{{ do diff*/
|
|
IGC_MEMgtSCA_S1 ( coeffptr, dvpx_diffuse, 8, dark );
|
|
IGC_MEMpluseqSCA_S1 ( coeffptr, dvpx_diffuse, dvpx_diffuse, 8, (0xff & (-dark)));
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_ENABandeqMEM ( coeffptr, affect_pixel );
|
|
IGC_CLEAR ( coeffptr, dvpx_diffuse, 8 );
|
|
/*}}} */
|
|
/*{{{ do spec*/
|
|
IGC_MEMintoENAB ( coeffptr, affect_pixel );
|
|
IGC_MEMgtSCA_S1 ( coeffptr, dvpx_specular, 8, dark );
|
|
IGC_MEMpluseqSCA_S1 ( coeffptr, dvpx_specular, dvpx_specular, 8, (0xff & (-dark)));
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_ENABandeqMEM ( coeffptr, affect_pixel );
|
|
IGC_CLEAR ( coeffptr, dvpx_specular, 8 );
|
|
/*}}} */
|
|
|
|
return coeffptr;
|
|
|
|
}
|
|
|
|
/*}}} */
|
|
/*{{{ int *scan_dot ( int *coeffptr, int slot, float x, float y, float r,*/
|
|
int *scan_dot ( int *coeffptr,
|
|
int slot,
|
|
float x, float y, float r,
|
|
float lx, float ly, float lz )
|
|
{
|
|
float fA, fB, fC, fD, fE, fF, r2=r*r;
|
|
float K, r_invlz;
|
|
|
|
r_invlz=r/lz;
|
|
K=-255.99f*lz/r2;
|
|
|
|
fF=-1.0f;
|
|
fD=fF;
|
|
fE=0;
|
|
|
|
fA=(x*2.0f) - (lx*r_invlz);
|
|
fB=(y*2.0f) - (ly*r_invlz);
|
|
fC=(r2) - ((x*x) + (y*y)) + (lx*x*r_invlz) + (ly*y*r_invlz);
|
|
|
|
fA*=K;
|
|
fB*=K;
|
|
fC*=K;
|
|
fD*=K;
|
|
fE*=K;
|
|
fF*=K;
|
|
|
|
IGC_TREEgeZERO_Q6 ( coeffptr, fA, fB, fC, fD, fE, fF );
|
|
IGC_TREEclmpintoMEM_Q0 ( coeffptr, slot, 8 );
|
|
|
|
return coeffptr;
|
|
}
|
|
/*}}} */
|
|
#endif
|
|
|
|
/*{{{ int *sphere ( float x, float y, float rad )*/
|
|
int *sphere ( int *coeffptr,
|
|
float x,
|
|
float y,
|
|
float z,
|
|
float r,
|
|
float rz,
|
|
float lx,
|
|
float ly,
|
|
float lz,
|
|
int intrinsic )
|
|
{
|
|
/*
|
|
scan-convert - g(x,y) = Ax + By + C - Q
|
|
A = 2a, B = 2b C = r2 - a2 - b2, Q = x2 + y2
|
|
|
|
Note that r is screen-space radius,
|
|
rz is radius in z-buffer space
|
|
d SAME AS f FOR SQUARE PIXEL DISPLAYS
|
|
*/
|
|
float two=2.0f, fA, fB, fC, fD;
|
|
float r2=r*r,
|
|
x2y2=(x*x)+(y*y),
|
|
r12=1.0f/r2;
|
|
float K, r_invlz;
|
|
|
|
r2-=x2y2;
|
|
|
|
fA=x*two;
|
|
fB=y*two;
|
|
fC=r2;
|
|
fD=-1.0f;
|
|
|
|
/* switch on pixels inside circle */
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_TREEgeZERO_Q6 ( coeffptr, fA, fB, fC, fD, 0.0f, fD );
|
|
|
|
/* z-buffer pixels */
|
|
K=rz*r12;
|
|
fA*=K;
|
|
fB*=K;
|
|
fC=(z+rz)-(x2y2*K);
|
|
fD=-K;
|
|
|
|
IGC_MEMltTREE_Q6 ( coeffptr, dvpx_zbuf, dvpx_zbufbits,
|
|
fA, fB, fC, fD, 0.0f, fD );
|
|
IGC_TREEclmpintoMEM_Q0 ( coeffptr, dvpx_zbuf, dvpx_zbufbits );
|
|
|
|
/* shade pixels */
|
|
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_scalar, dvpx_scalarbits, intrinsic );
|
|
IGC_CLEAR ( coeffptr, dvpx_diffuse, 16 );
|
|
|
|
r_invlz=r/lz;
|
|
K=-255.99f*lz*r12;
|
|
lx*=r_invlz;
|
|
ly*=r_invlz;
|
|
|
|
fA=K*((x*two) - lx);
|
|
fB=K*((y*two) - ly);
|
|
fC=K*(r2 + (lx*x + ly*y));
|
|
fD=-K;
|
|
|
|
IGC_TREEgeZERO_Q6 ( coeffptr, fA, fB, fC, fD, 0.0f, fD );
|
|
IGC_TREEclmpintoMEM_Q0 ( coeffptr, dvpx_specular, 8 );
|
|
|
|
return coeffptr;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void frig_some_smoke ( int **DMAref, int** coeffRef )*/
|
|
void frig_some_smoke ( int **DMAref, int** coeffRef )
|
|
{
|
|
int *coeffptr=*coeffRef;
|
|
int *DMAptr=*DMAref;
|
|
int *coeff0 =coeffptr;
|
|
int *coeff00=coeffptr;
|
|
int i, intrinsic, words;
|
|
float hyp, lx, ly, lz;
|
|
|
|
lx=1.0f;
|
|
ly=-1.0f;
|
|
lz=-1.0f;
|
|
|
|
hyp =(lx*lx);
|
|
hyp+=(ly*ly);
|
|
hyp+=(lz*lz);
|
|
|
|
hyp=1.0f/(sqrt(hyp));
|
|
|
|
lx*=hyp;
|
|
ly*=hyp;
|
|
lz*=hyp;
|
|
|
|
#define r_shift ((dvpx_intrinsic)-(dvpx_scalar))
|
|
|
|
/*{{{ */
|
|
intrinsic = (1 << r_shift) |
|
|
(1 <<(r_shift+4)) |
|
|
(1 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 500.0, 370.0, 145536.0f, 30.0, 48192.0f, lx, ly, lz, intrinsic );
|
|
/*{{{ */
|
|
intrinsic = (15 << r_shift) |
|
|
(0 <<(r_shift+4)) |
|
|
(7 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 520.0, 382.0, 145536.0f, 35.0, 48192.0f, lx, ly, lz, intrinsic );
|
|
/*{{{ */
|
|
intrinsic = (15 << r_shift) |
|
|
(8 <<(r_shift+4)) |
|
|
(0 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 525.0, 410.0, 145536.0f, 40.0, 48192.0f, lx, ly, lz, intrinsic );
|
|
/*{{{ */
|
|
intrinsic = (15 << r_shift) |
|
|
(15 <<(r_shift+4)) |
|
|
(0 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 531.0, 416.0, 145536.0f, 40.0, 48192.0f, lx, ly, lz, intrinsic );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 40 );
|
|
|
|
/*{{{ */
|
|
intrinsic = (15 << r_shift) |
|
|
(0 <<(r_shift+4)) |
|
|
(12 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 430.0, 414.0, 145536.0f, 45.0, 48192.0f, lx, ly, lz, intrinsic );
|
|
/*{{{ */
|
|
intrinsic = (15 << r_shift) |
|
|
(0 <<(r_shift+4)) |
|
|
(0 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 543.0, 425.0, 145536.0f, 50.0, 48192.0f, lx, ly, lz, intrinsic );
|
|
/*{{{ */
|
|
intrinsic = (4 << r_shift) |
|
|
(4 <<(r_shift+4)) |
|
|
(4 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 440.0, 430.0, 145536.0f, 55.0, 48192.0f, lx, ly, lz, intrinsic );
|
|
/*{{{ */
|
|
intrinsic = (2 << r_shift) |
|
|
(4 <<(r_shift+4)) |
|
|
(9 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 415.0, 412.0, 145536.0f, 60.0, 48192.0f, lx, ly, lz, intrinsic );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 40 );
|
|
|
|
/*{{{ */
|
|
intrinsic = (15 << r_shift) |
|
|
(0 <<(r_shift+4)) |
|
|
(0 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 430.0, 450.0, 145536.0f, 65.0, 48192.0f, lx, ly, lz, intrinsic );
|
|
/*{{{ */
|
|
intrinsic = (0 << r_shift) |
|
|
(0 <<(r_shift+4)) |
|
|
(15 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 540.0, 480.0, 145536.0f, 75.0, 48192.0f, lx, ly, lz, intrinsic );
|
|
/*{{{ */
|
|
intrinsic = (0 << r_shift) |
|
|
(15 <<(r_shift+4)) |
|
|
(0 <<(r_shift+8));
|
|
/*}}} */
|
|
coeffptr=sphere ( coeffptr, 200.0, 200.0, 145536.0f, 155.0, 92768.0f, lx, ly, lz, intrinsic );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 40 );
|
|
|
|
*coeffRef=coeffptr;
|
|
*DMAref =DMAptr;
|
|
}
|
|
/*}}} */
|
|
|
|
|
|
/*{{{ static void end_of_texture ( int **DMAref, int** coeffRef )*/
|
|
static void end_of_texture ( int **DMAref, int** coeffRef )
|
|
{
|
|
/*
|
|
NOTE that we have done the BSWAIT and the perspective
|
|
divide before entering here - dvpx_texu and texv hold real u and
|
|
v parametrics to index a texture map
|
|
*/
|
|
int *coeffptr=*coeffRef;
|
|
int *DMAptr =*DMAref;
|
|
int *coeff0 =coeffptr;
|
|
int *coeff00 =coeffptr;
|
|
int words, i;
|
|
|
|
send_pass="end_of_texture";
|
|
|
|
/* *****************************************
|
|
all below here may use ONLY end-of-frame space
|
|
********************************************* */
|
|
|
|
/*{{{ end of texture lookup code, bilinear zoom, linterp texture palette*/
|
|
/* bilinear h-pass, bottom left <-> bottom right */
|
|
IGC_BSWAIT ( coeffptr );
|
|
|
|
coeffptr = linterp ( coeffptr,
|
|
dvpx_io+24, dvpx_io, dvpx_io+6, dvpx_eofsubu,
|
|
8, 6, 5 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, (dvpx_eofpixtype+1) );
|
|
IGC_CPY ( coeffptr, dvpx_io, dvpx_io+26, 6 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
/* bilinear h-pass, top left <-> top right */
|
|
coeffptr = linterp ( coeffptr,
|
|
dvpx_io+24, dvpx_io+12, dvpx_io+18, dvpx_eofsubu,
|
|
8, 6, 5 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, (dvpx_eofpixtype+1) );
|
|
IGC_CPY ( coeffptr, dvpx_io+6, dvpx_io+26, 6 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
/* bilinear v-pass */
|
|
coeffptr = linterp ( coeffptr,
|
|
dvpx_io+24, dvpx_io, dvpx_io+6, dvpx_eofsubv,
|
|
8, 6, 5 );
|
|
|
|
/* now dvpx_io + 24 holds 8 bit luminance value for bilinear texture */
|
|
|
|
/* ************************************************************* */
|
|
/* now access the texture colour map table (8 32-bit entries) */
|
|
/* cant use tblcpy, as i then cant hack in the entries per frame */
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, (dvpx_eofpixtype+1) );
|
|
texture_table_iptr=coeffptr;
|
|
|
|
for (i=0; i<MAX_TEX_RAMPS; i++ ) {
|
|
*coeffptr++ =Ix_TBLENTRY_S1(0,dvpx_eoftexramp,24, dvpx_eoftexrampbits );
|
|
*coeffptr++ =P_TBLENTRY(0, dvpx_eoftexramp, 24, dvpx_eoftexrampbits );
|
|
*coeffptr++ =texture_ramps[i].codeWord;
|
|
}
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
/* now linterp from r0 to r1 */
|
|
coeffptr = linterp ( coeffptr,
|
|
dvpx_eofsubu,
|
|
dvpx_io+0, dvpx_io+4, dvpx_io+24, 10, 4, 8 );
|
|
IGC_MEMintoENAB ( coeffptr, (dvpx_eofpixtype+1));
|
|
IGC_CPY ( coeffptr, dvpx_io, dvpx_eofsubu+2, 8 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
/* now linterp from g0 to g1 */
|
|
coeffptr = linterp ( coeffptr, dvpx_eofsubu,
|
|
dvpx_io+8, dvpx_io+12, dvpx_io+24, 10, 4, 8 );
|
|
IGC_MEMintoENAB ( coeffptr, (dvpx_eofpixtype+1) );
|
|
IGC_CPY ( coeffptr, dvpx_io+8, dvpx_eofsubu+2, 8 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
/* now linterp from b0 to b1 */
|
|
coeffptr = linterp ( coeffptr, dvpx_eofsubu,
|
|
dvpx_io+16, dvpx_io+20, dvpx_io+24, 10, 4, 8 );
|
|
IGC_MEMintoENAB ( coeffptr, (dvpx_eofpixtype+1) );
|
|
IGC_CPY ( coeffptr, dvpx_io+16, dvpx_eofsubu+2, 8 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
/*}}} */
|
|
/*{{{ multiply by end-of-frame colour (just uses end-of-frame)*/
|
|
/* use eofsubu and subv, these are now free for scratchpad */
|
|
|
|
coeffptr=multuu_unc ( coeffptr, dvpx_eofsubu, dvpx_io+16, dvpx_eofb,
|
|
10, 8, 8 );
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_eofpixtype );
|
|
IGC_CPY ( coeffptr, dvpx_eofb, dvpx_eofsubu+2, 8 );
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
coeffptr=multuu_unc ( coeffptr, dvpx_eofsubu, dvpx_io+8, dvpx_eofg,
|
|
10, 8, 8 );
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_eofpixtype );
|
|
IGC_CPY ( coeffptr, dvpx_eofg, dvpx_eofsubu+2, 8 );
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
coeffptr=multuu_unc ( coeffptr, dvpx_eofsubu, dvpx_io, dvpx_eofr,
|
|
10, 8, 8 );
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_eofpixtype );
|
|
IGC_CPY ( coeffptr, dvpx_eofr, dvpx_eofsubu+2, 8 );
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
|
|
/*}}} */
|
|
/*{{{ add in specular (just uses end-of-frame)*/
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMclmppluseqMEM ( coeffptr, dvpx_eofr, dvpx_eofspec, 8, dvpx_io+31 );
|
|
IGC_MEMclmppluseqMEM ( coeffptr, dvpx_eofg, dvpx_eofspec, 8, dvpx_io+31 );
|
|
IGC_MEMclmppluseqMEM ( coeffptr, dvpx_eofb, dvpx_eofspec, 8, dvpx_io+31 );
|
|
/*}}} */
|
|
/*{{{ DONT copy to io area, IN FACT linterp fog*/
|
|
#if FOG
|
|
|
|
/* this should probably happen once per primary, but right now just do grey */
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_io+24, 8, 148 );
|
|
|
|
coeffptr = linterp ( coeffptr,
|
|
dvpx_io+14,
|
|
dvpx_io+24,
|
|
dvpx_eofb,
|
|
dvpx_eoffog,
|
|
10, 8, 8 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_io+24, 8, 106 );
|
|
|
|
coeffptr = linterp ( coeffptr,
|
|
dvpx_io+6,
|
|
dvpx_io+24,
|
|
dvpx_eofg,
|
|
dvpx_eoffog,
|
|
10, 8, 8 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_io+24, 8, 86 );
|
|
|
|
coeffptr = linterp ( coeffptr,
|
|
dvpx_eofg,
|
|
dvpx_io+24,
|
|
dvpx_eofr,
|
|
dvpx_eoffog,
|
|
10, 8, 8 );
|
|
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CPY ( coeffptr, dvpx_io, dvpx_eofg+2, 8 );
|
|
|
|
#else
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
|
|
IGC_CPY ( coeffptr, dvpx_io, dvpx_eofr, 8 );
|
|
IGC_CPY ( coeffptr, dvpx_io+8, dvpx_eofg, 8 );
|
|
IGC_CPY ( coeffptr, dvpx_io+16, dvpx_eofb, 8 );
|
|
|
|
#endif
|
|
/*}}} */
|
|
/*{{{ dither to 12 bits ... (not executed)*/
|
|
/* set up ramp in memory, of flavour
|
|
|
|
0 1 2 3
|
|
4 5 6 7
|
|
8 9 10 11
|
|
12 13 14 15
|
|
|
|
and use a lookup table to yield
|
|
|
|
0 8 2 10
|
|
12 4 14 6
|
|
3 11 1 9
|
|
15 7 13 5
|
|
|
|
*/
|
|
|
|
|
|
#if 0
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_TREEintoMEM_L3 ( coeffptr, 30, 2, 0.0f, 1.0f, 0.1f );
|
|
IGC_TREEintoMEM_L3 ( coeffptr, 28, 2, 1.0f, 0.0f, 0.1f );
|
|
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 0 | (0<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 1 | (8<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 2 | (2<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 3 | (10<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 4 | (12<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 5 | (4<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 6 | (14<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 7 | (6<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 8 | (3<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 9 | (11<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 10 | (1<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 11 | (9<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 12 | (15<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 13 | (7<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 14 | (13<<4) );
|
|
IGC_TBLENTRY_S1 ( coeffptr, 24, 28, 4, 4, 15 | (5<<4) );
|
|
|
|
IGC_CLEAR ( coeffptr, 28, 4 );
|
|
IGC_ENABintoMEM ( coeffptr, 28 );
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMgtMEM ( coeffptr, 2, 24, 4 );
|
|
IGC_MEMclmppluseqMEM ( coeffptr, 6, 28, 2, dvpx_eofsubu );
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CLEAR ( coeffptr, 0, 6 );
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMgtMEM ( coeffptr, 10, 24, 4 );
|
|
IGC_MEMclmppluseqMEM ( coeffptr, 14, 28, 2, dvpx_eofsubu );
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CLEAR ( coeffptr, 8, 6 );
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMgtMEM ( coeffptr, 18, 24, 4 );
|
|
IGC_MEMclmppluseqMEM ( coeffptr, 22, 28, 2, dvpx_eofsubu );
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CLEAR ( coeffptr, 16, 6 );
|
|
|
|
#endif
|
|
|
|
/*}}} */
|
|
/*{{{ and write to VRAM*/
|
|
IGC_VRAMWrite ( coeffptr, 4 );
|
|
|
|
for (i=0; i<4; i++)
|
|
IGC_NOOP ( coeffptr );
|
|
|
|
/*}}} */
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 40 );
|
|
words=(int) coeffptr - (int) coeff00;
|
|
words>>=3;
|
|
|
|
printf ("%d 64-bit words in end-of-texture sequence\n", words );
|
|
/*
|
|
*/
|
|
|
|
*coeffRef=coeffptr;
|
|
*DMAref =DMAptr;
|
|
}
|
|
/*}}} */
|
|
/*{{{ static short_end_of_frame ( int **DMAref, int** coeffRef ) <<< H A C K*/
|
|
static void short_end_of_frame ( int **DMAref, int** coeffRef )
|
|
{
|
|
/*
|
|
NOTE that we have done the BSWAIT and the perspective
|
|
divide before entering here - dvpx_texu and texv hold real u and
|
|
v parametrics to index a texture map
|
|
*/
|
|
int *coeffptr=*coeffRef;
|
|
int *DMAptr =*DMAref;
|
|
int *coeff0 =coeffptr;
|
|
int *coeff00 =coeffptr;
|
|
|
|
|
|
/*{{{ declare some variables*/
|
|
int i, words, edge;
|
|
extern int *ambient_slot;
|
|
|
|
int dotexture= dvpx_opaque_50,
|
|
tmp1 = dvpx_opaque_25,
|
|
bilinear = dvpx_opaque_12;
|
|
|
|
/*}}} */
|
|
|
|
send_pass="end_of_frame";
|
|
/* printf ("short end_of_frame : coeffptr 0x%x DMAptr 0x%x\n", coeffptr, DMAptr ); */
|
|
/*{{{ turn u,v into SRAM address, save subu,v into eofarea*/
|
|
/* a value of 0 in texture type means pixel not textured */
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CLEAR ( coeffptr, dvpx_io, 32 );
|
|
IGC_CLEAR ( coeffptr, bilinear, 1 );
|
|
IGC_MEMneZERO ( coeffptr, dvpx_texsize, dvpx_texsizebits );
|
|
IGC_ENABintoMEM( coeffptr, dotexture );
|
|
|
|
for (i=0; i<3; i++ ) {
|
|
int id, sububase, subvbase,
|
|
ubase, vbase;
|
|
|
|
edge=6+i;
|
|
|
|
id = (i*2)+1;
|
|
ubase = dvpx_texu+(dvpx_texubits-edge);
|
|
vbase = dvpx_texv+(dvpx_texvbits-edge);
|
|
sububase = dvpx_texu+(dvpx_texubits-(edge+dvpx_eofsububits));
|
|
subvbase = dvpx_texv+(dvpx_texvbits-(edge+dvpx_eofsubvbits));
|
|
|
|
ubase-=3; /* eliminate wrap bits */
|
|
vbase-=3;
|
|
|
|
sububase-=3;
|
|
subvbase-=3;
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_texsize, dvpx_texsizebits, id );
|
|
IGC_SET ( coeffptr, bilinear, 1 );
|
|
IGC_ENABintoMEM ( coeffptr, tmp1 );
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_texsize, dvpx_texsizebits, id+1 );
|
|
IGC_ENABoreqMEM ( coeffptr, tmp1 );
|
|
|
|
IGC_CPY ( coeffptr, dvpx_io, ubase, edge );
|
|
IGC_CPY ( coeffptr, dvpx_io+edge, vbase, edge );
|
|
IGC_MEMpluseqMEM ( coeffptr, dvpx_io+12, dvpx_texid,
|
|
dvpx_texidbits+1, dvpx_texidbits );
|
|
IGC_CPY ( coeffptr, dvpx_eofsubu, sububase, dvpx_eofsububits);
|
|
IGC_CPY ( coeffptr, dvpx_eofsubv, subvbase, dvpx_eofsubvbits);
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
}
|
|
/*}}} */
|
|
/*{{{ trigger Texture Look Up H A C K E D O U T*/
|
|
|
|
/* trigger texture lookup sequence */
|
|
|
|
IGC_TextSeq ( coeffptr, 4 );
|
|
/*
|
|
*/
|
|
|
|
for (i=0; i<4; i++ )
|
|
IGC_NOOP ( coeffptr );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 40 );
|
|
/*}}} */
|
|
|
|
/* printf ("TEXTSEQ : coeffptr 0x%x DMAptr 0x%x\n", coeffptr, DMAptr ); */
|
|
|
|
/*{{{ move some variables to eof area*/
|
|
|
|
IGC_MEMintoENAB ( coeffptr, bilinear );
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_eofpixtype+1 );
|
|
IGC_MEMintoENAB ( coeffptr, dotexture );
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_eofpixtype );
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CPY ( coeffptr, dvpx_eoftexramp, dvpx_texrampsel, dvpx_texrampselbits );
|
|
|
|
#if FOG
|
|
/*{{{ HELP ! ! !*/
|
|
/* ok, what the f*** does this do ?
|
|
for a given near clipping plane, we want to set the fog
|
|
to be maxed out at exactly the far clipping plane.
|
|
in McDon-Doug the near clip is at 256.0
|
|
we want the fog to finish at the far clip, and start and
|
|
farclip - n bits, where n is the precision of the fog fade.
|
|
we also want the far clip to be good for chucking away triangles,
|
|
so, lets assume that the far clip is at 512*1024. Then the real
|
|
far z is 2^20 * 256.0 / 512*1024 = 512. So we want the fog to
|
|
be maxed at z=512 (9 bits), so 11 bits of the z-buffer are fogged.
|
|
Let us just have 6 bits of fog precision, then we want to
|
|
start fogging at 5 bits in. Not many.
|
|
|
|
So fog far zbuf value is 512
|
|
max out all pixels further than this
|
|
|
|
So fog near zbuf value is 512+2047
|
|
min out all pixels nearer than this
|
|
|
|
if still enabled, subtract 512 from zbuf, and shift right by 3 - leaves
|
|
a fog fade value in zbuffer
|
|
|
|
lets set fog near zbuf to be 512 + 2048,
|
|
if pixel nearer
|
|
*/
|
|
/*}}} */
|
|
#define max_fog 512
|
|
#define min_fog (512+255)
|
|
#define fog_shift 0
|
|
|
|
/* note dvpx_eofr... is available as a temporary */
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_eofr, dvpx_zbufbits, max_fog );
|
|
|
|
IGC_MEMgeSCA_S1 ( coeffptr, dvpx_zbuf, dvpx_zbufbits, min_fog );
|
|
IGC_SET ( coeffptr, dvpx_eoffog, dvpx_eoffogbits );
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_eofstart-1 );
|
|
|
|
IGC_MEMgeMEM ( coeffptr, dvpx_eofr, dvpx_zbuf, dvpx_zbufbits );
|
|
IGC_CLEAR ( coeffptr, dvpx_eoffog, dvpx_eoffogbits );
|
|
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_ENABandeqMEM ( coeffptr, dvpx_eofstart-1 );
|
|
|
|
IGC_MEMminuseqMEM ( coeffptr, dvpx_zbuf, dvpx_eofr, dvpx_zbufbits, dvpx_zbufbits );
|
|
IGC_CPY ( coeffptr, dvpx_eoffog, dvpx_zbuf+fog_shift, dvpx_eoffogbits );
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
#endif
|
|
/*}}} */
|
|
/*{{{ prepare rgb in dvpx_eofr, g, b*/
|
|
/*
|
|
if (24-bit pixel == 0) do lighted pixels
|
|
add ambient component into lit pixels
|
|
the ambient colour is patched at end-of-frame, so snapshot iptr
|
|
*/
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_pixcolourtype );
|
|
|
|
IGC_CPY ( coeffptr, dvpx_eofr, dvpx_r24, 8 );
|
|
IGC_CPY ( coeffptr, dvpx_eofg, dvpx_g24, 8 );
|
|
IGC_CPY ( coeffptr, dvpx_eofb, dvpx_b24, 8 );
|
|
|
|
IGC_ENABINV ( coeffptr );
|
|
ambient_slot=coeffptr;
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_zbuf, dvpx_diffusebits, 32 );
|
|
IGC_MEMclmppluseqMEM ( coeffptr, dvpx_diffuse, dvpx_zbuf, dvpx_diffusebits,
|
|
dvpx_zbuf+10 );
|
|
|
|
|
|
/* multiply intrinsic red by diffuse, move into red */
|
|
coeffptr=multuu_unc ( coeffptr, dvpx_zbuf, dvpx_intrinsic, dvpx_diffuse,
|
|
10, 4, 8 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
IGC_MEMBARintoENAB ( coeffptr, dvpx_pixcolourtype );
|
|
IGC_CPY ( coeffptr, dvpx_eofr, dvpx_zbuf+2, 8 );
|
|
|
|
/* multiply intrinsic green by diffuse, move into green */
|
|
coeffptr=multuu_unc ( coeffptr, dvpx_zbuf, dvpx_intrinsic+4, dvpx_diffuse,
|
|
10, 4, 8 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
IGC_MEMBARintoENAB ( coeffptr, dvpx_pixcolourtype );
|
|
IGC_CPY ( coeffptr, dvpx_eofg, dvpx_zbuf+2, 8 );
|
|
|
|
|
|
/* multiply intrinsic blue by diffuse, move into blue */
|
|
coeffptr=multuu_unc ( coeffptr, dvpx_zbuf, dvpx_intrinsic+8, dvpx_diffuse,
|
|
10, 4, 8 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
IGC_MEMBARintoENAB ( coeffptr, dvpx_pixcolourtype );
|
|
IGC_CPY ( coeffptr, dvpx_eofb, dvpx_zbuf+2, 8 );
|
|
|
|
/*}}} */
|
|
/*{{{ copy specular term into eofspec*/
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_pixcolourtype );
|
|
IGC_CLEAR ( coeffptr, dvpx_eofspec, 8 );
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_CPY ( coeffptr, dvpx_eofspec, dvpx_specular, 8 );
|
|
/*}}} */
|
|
|
|
#if 0
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CPY ( coeffptr, 0, dvpx_eofr, 8 );
|
|
IGC_CPY ( coeffptr, 8, dvpx_eofg, 8 );
|
|
IGC_CPY ( coeffptr,16, dvpx_eofb, 8 );
|
|
|
|
IGC_VRAMWrite ( coeffptr, 4 );
|
|
|
|
IGC_NOOP ( coeffptr );
|
|
IGC_NOOP ( coeffptr );
|
|
IGC_NOOP ( coeffptr );
|
|
IGC_NOOP ( coeffptr );
|
|
#endif
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 40 );
|
|
|
|
words=(int) coeffptr - (int) coeff00;
|
|
words>>=3;
|
|
|
|
/*
|
|
*/
|
|
printf ("%d 64-bit words in end-of-frame sequence\n", words );
|
|
|
|
*coeffRef=coeffptr;
|
|
*DMAref =DMAptr;
|
|
}
|
|
/*}}} */
|
|
/*{{{ int short_end_of_frame_DMA ( int *DMAptr, int *coeffptr, int *end_of_tex_DMA )*/
|
|
int *wait_poke_address;
|
|
|
|
int short_end_of_frame_DMA ( int *DMAptr, int *coeffptr, int *end_of_tex_DMA )
|
|
{
|
|
int *coeff0 =coeffptr;
|
|
int *coeff00=coeffptr;
|
|
int *DMAptr0=DMAptr;
|
|
int i, DMAbytes, IGCbytes;
|
|
|
|
/*
|
|
frig_some_smoke ( &DMAptr, &coeffptr );
|
|
*/
|
|
|
|
coeff0=coeffptr;
|
|
perspective_divides ( &DMAptr, &coeffptr );
|
|
coeff0=coeffptr;
|
|
send_pass="eofDMA";
|
|
|
|
/* make sure texture sequence has executed */
|
|
|
|
wait_poke_address=DMAptr+1;
|
|
|
|
/* NB this flush is hacked into a WAIT after the first tile */
|
|
|
|
*DMAptr++=0x0;
|
|
*DMAptr++=DMA_FLUSH_VAL;
|
|
|
|
/* reinit semaphore */
|
|
*DMAptr++=(int) end_of_tex_DMA;
|
|
*DMAptr++=DMA_TXDN_VAL;
|
|
|
|
/* make sure VRAM write has terminated */
|
|
IGC_BSWAIT ( coeffptr );
|
|
|
|
for (i=0; i<4; i++)
|
|
IGC_NOOP ( coeffptr );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 20 );
|
|
|
|
/* wait for fifo to empty (i.e BSWAIT has executed) */
|
|
|
|
*DMAptr++=(int) 0;
|
|
*DMAptr++=DMA_FLUSH;
|
|
|
|
*DMAptr++=(int) 0;
|
|
*DMAptr++=DMA_FLUSH;
|
|
|
|
tile_poke_address=DMAptr;
|
|
|
|
/* set up tile address */
|
|
|
|
*DMAptr++= 0; /* these are patched ! */
|
|
*DMAptr++=DMA_TILE;
|
|
|
|
short_end_of_frame ( &DMAptr, &coeffptr );
|
|
coeff0=coeffptr;
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 20 );
|
|
|
|
DMAbytes = (int) DMAptr - (int) DMAptr0;
|
|
IGCbytes = (int) coeffptr - (int) coeff00;
|
|
|
|
|
|
/*
|
|
wait_poke_address=DMAptr+1;
|
|
|
|
printf ("%d bytes of DMA, %d bytes of IGC in end-of-frame\n",
|
|
DMAbytes, IGCbytes );
|
|
*/
|
|
|
|
return (DMAbytes>>2);
|
|
}
|
|
/*}}} */
|
|
/*{{{ int end_of_textr_DMA ( int *DMAptr, int *coeffptr )*/
|
|
int end_of_textr_DMA ( int *DMAptr, int *coeffptr )
|
|
{
|
|
int *coeff0 =coeffptr;
|
|
int *coeff00=coeffptr;
|
|
int *DMAptr0=DMAptr;
|
|
int i, DMAbytes, IGCbytes;
|
|
|
|
end_of_texture ( &DMAptr, &coeffptr );
|
|
coeff0=coeffptr;
|
|
|
|
*DMAptr++=0;
|
|
*DMAptr++=DMA_RETE_VAL;
|
|
|
|
DMAbytes = (int) DMAptr - (int) DMAptr0;
|
|
IGCbytes = (int) coeffptr - (int) coeff00;
|
|
|
|
/*
|
|
printf ("%d bytes of DMA, %d bytes of IGC in end-of-texture\n",
|
|
DMAbytes, IGCbytes );
|
|
*/
|
|
return (DMAbytes>>2);
|
|
}
|
|
/*}}} */
|
|
|
|
|