Files
CydandClaude Fable 5 db7745fcd0 sda4: commit the Glaze developer hard-drive dump
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>
2026-07-04 19:41:15 -05:00

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);
}
/*}}} */