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>
1830 lines
52 KiB
C++
1830 lines
52 KiB
C++
|
|
/*{{{ 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
|
|
|
|
*/
|
|
/*}}} */
|
|
|
|
/*{{{ includes*/
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "divpxmap.h"
|
|
#include "dmaengn.h"
|
|
#include "pxpl5typ.h"
|
|
#include "..\dpltypes.h"
|
|
#include "..\culltype.h"
|
|
#include "\projects\dbi0150\dbi0151\ucode\igc_opco.h"
|
|
#include "\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;
|
|
int random_index=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<4; 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 );
|
|
|
|
/*{{{ linear feedback register opacity*/
|
|
#define bump(save,length)save++; if (save==length) save=0;
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
|
|
/*
|
|
|
|
IGC_TREEintoMEM_L3 ( coeffptr, dvpx_texu, 20, 1.0f, 1024.0f, 0.0f );
|
|
*/
|
|
|
|
|
|
random_index=((int) coeffptr - (int) coeff0) >> 2;
|
|
/*
|
|
*/
|
|
IGC_TREEintoMEM_L3 ( coeffptr, dvpx_texu, 7, -1.0f, 0.0f, 0.0f );
|
|
IGC_TREEintoMEM_L3 ( coeffptr, dvpx_texu+7, 15, 0.0f, 1.0f, 0.0f );
|
|
|
|
{
|
|
int tap0, tap1, tap2, tap3, save, length, base;
|
|
|
|
base=dvpx_texu;
|
|
|
|
length=12;
|
|
save=0;
|
|
tap0=0;
|
|
tap1=1;
|
|
tap2=4;
|
|
tap3=6;
|
|
|
|
for (i=0; i<length/2; i++) {
|
|
int ix0, ix1;
|
|
|
|
ix0=base+i;
|
|
ix1=base+((length - 1) - i);
|
|
|
|
/* reverse order of bits in word */
|
|
IGC_MEMintoENAB ( coeffptr, ix0 );
|
|
IGC_ENABxoreqMEM ( coeffptr, ix1 );
|
|
IGC_ENABintoMEM ( coeffptr, ix0 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, ix0 );
|
|
IGC_ENABxoreqMEM ( coeffptr, ix1 );
|
|
IGC_ENABintoMEM ( coeffptr, ix1 );
|
|
}
|
|
|
|
for (i=0; i<length; i++) {
|
|
|
|
IGC_MEMintoENAB ( coeffptr, base+tap0 );
|
|
IGC_ENABxoreqMEM ( coeffptr, base+tap1 );
|
|
IGC_ENABxoreqMEM ( coeffptr, base+tap2 );
|
|
IGC_ENABxoreqMEM ( coeffptr, base+tap3 );
|
|
IGC_ENABintoMEM ( coeffptr, base+save );
|
|
|
|
bump (save, length );
|
|
bump (tap0, length );
|
|
bump (tap1, length );
|
|
bump (tap2, length );
|
|
bump (tap3, length );
|
|
}
|
|
}
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
|
|
IGC_CPY ( coeffptr, dvpx_opacity, dvpx_texu+7, dvpx_opacitybits );
|
|
IGC_MEMgeSCA_S1 ( coeffptr, dvpx_opacity, dvpx_opacitybits, 29 );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_opacity, dvpx_opacitybits, 29 );
|
|
|
|
#undef bump
|
|
/*}}} */
|
|
|
|
/* 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 */
|
|
int *texture_table_iptr=NULL;
|
|
|
|
extern cull_RAMP texture_ramps[MAX_TEX_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;
|
|
}
|
|
}
|
|
|
|
/*}}} */
|
|
|
|
/*
|
|
stuff for perspective division of textures. perspective divides does
|
|
the full-precision divide, transpective divide does the limited precision
|
|
transparent texture divide
|
|
*/
|
|
/*{{{ static void texdivide ( int **DMAref, int **coeffRef,*/
|
|
static void texdivide ( int **DMAref,
|
|
int **coeffRef,
|
|
int *coeff0,
|
|
int num,
|
|
int denom,
|
|
int sigbits )
|
|
{
|
|
/*
|
|
this texdivide operates in-place - the numerator is replaced by
|
|
its perspective divided version.
|
|
*/
|
|
int i, res, divbits;
|
|
int *coeffptr=*coeffRef;
|
|
int *DMAptr =*DMAref;
|
|
|
|
send_pass="texdivide";
|
|
|
|
res =num+dvpx_texubits - 1;
|
|
divbits=dvpx_texubits;
|
|
|
|
for (i=0; i<sigbits; i++ ) {
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMgeMEM ( coeffptr, num, denom, divbits );
|
|
IGC_MEMminuseqMEM ( coeffptr, num, denom, divbits, divbits );
|
|
IGC_ENABintoMEM ( coeffptr, res );
|
|
res--, denom++, divbits--;
|
|
}
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 30 );
|
|
|
|
*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,
|
|
17 );
|
|
|
|
coeff0=coeffptr;
|
|
|
|
texdivide ( &DMAptr, &coeffptr, coeff0,
|
|
dvpx_texv,
|
|
dvpx_texz+1,
|
|
17 );
|
|
|
|
coeff0=coeffptr;
|
|
|
|
*coeffRef=coeffptr;
|
|
*DMAref =DMAptr;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void transpective_divides ( int **DMAref, int** coeffRef )*/
|
|
void transpective_divides ( int **DMAref, int** coeffRef )
|
|
{
|
|
/*
|
|
this does the limited-precision perspective divides for
|
|
transparent texturing
|
|
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 );
|
|
*/
|
|
IGC_SETENABS ( coeffptr );
|
|
|
|
/* lose 1 bit of precision in texz (required by divide) */
|
|
|
|
IGC_CLEAR ( coeffptr, dvpx_texz+dvpx_texzbits, 1 );
|
|
|
|
/* 11 bits of result == 3 (0 .. 7.990), 8 (0 .. 255), 0 sub-texel bits */
|
|
/* I AM CONFUSED - why do i have to do 12 ?????? */
|
|
texdivide ( &DMAptr, &coeffptr, coeff0,
|
|
dvpx_texu,
|
|
dvpx_texz+1,
|
|
12 );
|
|
|
|
coeff0=coeffptr;
|
|
|
|
texdivide ( &DMAptr, &coeffptr, coeff0,
|
|
dvpx_texv,
|
|
dvpx_texz+1,
|
|
13 );
|
|
|
|
coeff0=coeffptr;
|
|
|
|
*coeffRef=coeffptr;
|
|
*DMAref =DMAptr;
|
|
}
|
|
/*}}} */
|
|
|
|
#if 0
|
|
/*{{{ old sphere stuff - dont chunk this*/
|
|
/*{{{ 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;
|
|
}
|
|
/*}}} */
|
|
/*{{{ 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;
|
|
}
|
|
/*}}} */
|
|
/*}}} */
|
|
#endif
|
|
|
|
/*{{{ end of frame variables*/
|
|
int eof_backR=90,
|
|
eof_backG=110,
|
|
eof_backB=190,
|
|
eof_farZ=30,
|
|
eof_doFOG=0,
|
|
eof_FOG_rval=81,
|
|
eof_FOG_gval=61,
|
|
eof_FOG_bval=31;
|
|
|
|
float eof_FOG_near= 5000.0f,
|
|
eof_FOG_far = 10000.0f;
|
|
|
|
int eof_Z_near = 65536,
|
|
eof_Z_far = 20;
|
|
/*}}} */
|
|
|
|
/*{{{ explode4 ( int *coeffptr, int where4, int where8, int enbl )*/
|
|
int *
|
|
explode4 ( int *coeffptr, int where4, int where8, int enbl )
|
|
{
|
|
/*
|
|
IGC_MEMintoENAB ( coeffptr, enbl );
|
|
IGC_CLEAR ( coeffptr, where8, 8 );
|
|
IGC_MEMeqONES ( coeffptr, where4+2, 2 );
|
|
IGC_SET ( coeffptr, where8+7, 1 );
|
|
IGC_CPY ( coeffptr, where8+5, where4, 2 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, enbl );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, where4+2, 2, 0x2 );
|
|
IGC_SET ( coeffptr, where8+6, 1 );
|
|
IGC_CPY ( coeffptr, where8+4, where4, 2 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, enbl );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, where4+2, 2, 0x1 );
|
|
IGC_SET ( coeffptr, where8+5, 1 );
|
|
IGC_CPY ( coeffptr, where8+3, where4, 2 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, enbl );
|
|
IGC_MEMeqZERO ( coeffptr, where4+2, 2 );
|
|
IGC_SET ( coeffptr, where8+4, 1 );
|
|
IGC_CPY ( coeffptr, where8+2, where4, 2 );
|
|
*/
|
|
IGC_MEMintoENAB ( coeffptr, enbl );
|
|
IGC_CLEAR ( coeffptr, where8, 4 );
|
|
IGC_CPY ( coeffptr, where8+4, where4, 4 );
|
|
|
|
return coeffptr;
|
|
|
|
}
|
|
/*}}} */
|
|
/*{{{ 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
|
|
********************************************* */
|
|
/*{{{ notes on vwe format*/
|
|
/*
|
|
|
|
Implement 8 texture formats -
|
|
|
|
000 = bits 20..23 \
|
|
001 = bits 16..19 \ monochrome
|
|
010 = bits 12..15 / modulators, contrast tbd
|
|
011 = bits 8..11 /
|
|
100 = bits 8..16 8-bit monochrome
|
|
101 = bilinear interp
|
|
110 = bits 8..16 3:3:2 color
|
|
111 = bits 12..23 4:4:4 floating-point color
|
|
|
|
magic combination of id==64, size == 256x256 indicates dont texture
|
|
|
|
So option is, do we use floating-point format for 4-bit monochrome,
|
|
or do we just flat-map with big 16-level contours. The 4-bit table is
|
|
|
|
4 5 6 7 8 10 12 14 16 20 24 28 32 40 48 56
|
|
16 20 24 30 32 40 48 56 64 80 96 112 128 160 192 224
|
|
|
|
an alternate 5-bit table uses just 1 fp bit -
|
|
|
|
8 9 10 11 12 13 14 15 16 18 20 22 24 26 28 30
|
|
64 72 80 88 96 104 112 120 128 144 160 176 192 208 224 240
|
|
|
|
or
|
|
|
|
*/
|
|
/*}}} */
|
|
|
|
/* the all-important bswait */
|
|
IGC_BSWAIT ( coeffptr );
|
|
|
|
/*{{{ bilinear zoom into 8 top bits for lerp*/
|
|
/* bilinear h-pass, bottom left <-> bottom right */
|
|
|
|
coeffptr = linterp ( coeffptr,
|
|
dvpx_io+24, dvpx_io, dvpx_io+6, dvpx_eofsubu,
|
|
8, 6, 5 );
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits, 0x5 );
|
|
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_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits, 0x5 );
|
|
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 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
/*}}} */
|
|
/*{{{ modes 0..4 - copy to top 8-bits for ramp lerp*/
|
|
/* 4-bit monochrome bits 20..24 */
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqZERO ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits );
|
|
IGC_SET ( coeffptr, dvpx_io+24, 4 );
|
|
IGC_CPY ( coeffptr, dvpx_io+28, dvpx_io+20, 4 );
|
|
|
|
/* 4-bit monochrome bits 16..20 */
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits, 0x1 );
|
|
IGC_SET ( coeffptr, dvpx_io+24, 4 );
|
|
IGC_CPY ( coeffptr, dvpx_io+28, dvpx_io+16, 4 );
|
|
|
|
/* 4-bit monochrome bits 12..16 */
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits, 0x2 );
|
|
IGC_SET ( coeffptr, dvpx_io+24, 4 );
|
|
IGC_CPY ( coeffptr, dvpx_io+28, dvpx_io+12, 4 );
|
|
|
|
/* 4-bit monochrome bits 8..12 */
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits, 0x3 );
|
|
IGC_SET ( coeffptr, dvpx_io+24, 4 );
|
|
IGC_CPY ( coeffptr, dvpx_io+28, dvpx_io+8, 4 );
|
|
|
|
/* 8-bit monochrome */
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits, 0x4 );
|
|
IGC_CPY ( coeffptr, dvpx_io+24, dvpx_io+8, 8 );
|
|
/*}}} */
|
|
/*{{{ clear mode memory*/
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMgeSCA_S1 ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits, 0x6 );
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_CLEAR ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits );
|
|
/*}}} */
|
|
/*{{{ lerp texture ramp*/
|
|
/* ************************************************************* */
|
|
/* 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_SETENABS ( coeffptr );
|
|
IGC_MEMeqZERO ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits );
|
|
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_SETENABS ( coeffptr );
|
|
IGC_MEMeqZERO ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits );
|
|
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_SETENABS ( coeffptr );
|
|
IGC_MEMeqZERO ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits );
|
|
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_SETENABS ( coeffptr );
|
|
IGC_MEMeqZERO ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits );
|
|
IGC_CPY ( coeffptr, dvpx_io+16, dvpx_eofsubu+2, 8 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
/*}}} */
|
|
/*{{{ full-color formats*/
|
|
/* both full-color modes, make a copy of i/o area in sub-u */
|
|
|
|
/* 8-bit 3-3-2 full color */
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits, 0x6 );
|
|
|
|
IGC_CPY ( coeffptr, dvpx_eofsubu, dvpx_io, 8 );
|
|
IGC_CLEAR ( coeffptr, dvpx_io, 24 );
|
|
IGC_CPY ( coeffptr, dvpx_io+(16+6), dvpx_eofsubu+6, 2 );
|
|
IGC_CPY ( coeffptr, dvpx_io+(8+5), dvpx_eofsubu+3, 3 );
|
|
IGC_CPY ( coeffptr, dvpx_io+(0+5), dvpx_eofsubu, 3 );
|
|
|
|
/* 12-bit 4-4-4 full color */
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits, 0x7 );
|
|
IGC_CPY ( coeffptr, dvpx_eofsubu, dvpx_io, 8 );
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_eofsubu+9 );
|
|
|
|
coeffptr = explode4 ( coeffptr, dvpx_io+8, dvpx_io+16, dvpx_eofsubu+9 );
|
|
coeffptr = explode4 ( coeffptr, dvpx_eofsubu+4, dvpx_io+8, dvpx_eofsubu+9 );
|
|
coeffptr = explode4 ( coeffptr, dvpx_eofsubu, dvpx_io, dvpx_eofsubu+9 );
|
|
|
|
/*
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_eoftexmode, dvpx_eoftexmodebits, 0x7 );
|
|
IGC_CPY ( coeffptr, dvpx_eofsubu, dvpx_io, 8 );
|
|
IGC_CLEAR ( coeffptr, dvpx_io+16, 4 );
|
|
IGC_CPY ( coeffptr, dvpx_io+20, dvpx_io+8, 4 );
|
|
IGC_CLEAR ( coeffptr, dvpx_io+8, 4 );
|
|
IGC_CPY ( coeffptr, dvpx_io+12, dvpx_eofsubu+4, 4 );
|
|
IGC_CLEAR ( coeffptr, dvpx_io, 4 );
|
|
IGC_CPY ( coeffptr, dvpx_io+4, dvpx_eofsubu, 4 );
|
|
*/
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
/*}}} */
|
|
/*{{{ multiply by end-of-frame colour*/
|
|
/* 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_eoftextured );
|
|
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_eoftextured );
|
|
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_eoftextured );
|
|
IGC_CPY ( coeffptr, dvpx_eofr, dvpx_eofsubu+2, 8 );
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
|
|
/*}}} */
|
|
/*{{{ DONT copy to io area, IN FACT linterp fog*/
|
|
if (eof_doFOG) {
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_io+24, 8, eof_FOG_bval );
|
|
|
|
coeffptr = linterp ( coeffptr,
|
|
dvpx_io+14,
|
|
dvpx_io+24,
|
|
dvpx_eofb,
|
|
dvpx_eoffog,
|
|
10, 8, 8 ); /* the 8 msbs end up in dvpx_io+16 */
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_io+24, 8, eof_FOG_gval );
|
|
|
|
coeffptr = linterp ( coeffptr,
|
|
dvpx_io+6,
|
|
dvpx_io+24,
|
|
dvpx_eofg,
|
|
dvpx_eoffog,
|
|
10, 8, 8 ); /* ditto dvpx_io+8 */
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_io+24, 8, eof_FOG_rval );
|
|
|
|
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, 24 );
|
|
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ 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;
|
|
|
|
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 0x3f in texture id and 0x3 in type means
|
|
pixel not textured */
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CLEAR ( coeffptr, dvpx_io, 24 );
|
|
IGC_CLEAR ( coeffptr, bilinear, 1 );
|
|
|
|
/* so only if memory == all ones do we not texture */
|
|
IGC_MEMeqONES ( coeffptr, dvpx_texsize, dvpx_texsizebits+dvpx_texidbits );
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_ENABintoMEM ( coeffptr, dotexture );
|
|
|
|
for (i=0; i<3; i++ ) {
|
|
int id, sububase, subvbase,
|
|
ubase, vbase;
|
|
|
|
edge=6+i;
|
|
|
|
id = i;
|
|
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_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*/
|
|
|
|
/* 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 );
|
|
/*}}} */
|
|
|
|
/*{{{ move some variables to eof area*/
|
|
|
|
IGC_MEMintoENAB ( coeffptr, dotexture );
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_eoftextured );
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CPY ( coeffptr, dvpx_eoftexramp, dvpx_texrampsel, dvpx_texrampselbits );
|
|
IGC_CPY ( coeffptr, dvpx_eoftexmode, dvpx_texmode, dvpx_texmodebits );
|
|
|
|
/*}}} */
|
|
/*{{{ if z further than far clip, set to backGND*/
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMgtSCA_S1 ( coeffptr, dvpx_zbuf, dvpx_zbufbits, eof_farZ );
|
|
IGC_ENABINV ( coeffptr );
|
|
|
|
/* IGC_CLEAR ( coeffptr, dvpx_zbuf, dvpx_zbufbits ); */
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_r24, 8, eof_backR );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_g24, 8, eof_backG );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_b24, 8, eof_backB );
|
|
|
|
/*}}} */
|
|
/*{{{ cheap fog - uses eofrgb as scratchpad, do before ...*/
|
|
if (eof_doFOG) {
|
|
int sigbits,
|
|
basebit,
|
|
t=eof_Z_near - eof_Z_far,
|
|
scalar;
|
|
|
|
/* ********************************************************************
|
|
|
|
OK, here is a no-divides fog algorithm, which needs a multiply
|
|
Take as input fog_near and fog_far. Turn these into z-buffer coordinates
|
|
by z_near (d*near*2^20 / fog_near) etc. If z>z_near, fog=ff. If z<z_far,
|
|
fog =0. otherwise, compute t=z-fog_far, giving a number in range
|
|
0..(fog_near-fog_far). We know how many bits are needed to represent this,
|
|
so shift down until it occupies 9 bits (in fact, compute a base bit).
|
|
Now put a scalar into memory, which is 0.999 / (fog_near-fog_far).
|
|
This number is then multiplied by the z-buffer contents, so that, if
|
|
z was fog_near, we yield 255, and if z was fog_far, we get 0. In terms
|
|
of executed IGC ops, we do a pair of compares and 8-bit writes, a 20-bit
|
|
subtract and a 9x9 ==> 10 bit multiply, then an 8-bit copy into fog.
|
|
|
|
NOTE direction of fog - fog value is 0xff if we are up close,
|
|
0x00 if we are fully fogged
|
|
*/
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_eofr, dvpx_zbufbits, eof_Z_far );
|
|
IGC_MEMgeSCA_S1 ( coeffptr, dvpx_zbuf, dvpx_zbufbits, eof_Z_near );
|
|
IGC_SET ( coeffptr, dvpx_eoffog, dvpx_eoffogbits );
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_opaque_50 );
|
|
IGC_MEMgeMEM ( coeffptr, dvpx_eofr, dvpx_zbuf, dvpx_zbufbits );
|
|
IGC_CLEAR ( coeffptr, dvpx_eoffog, dvpx_eoffogbits );
|
|
IGC_ENABINV ( coeffptr );
|
|
IGC_ENABandeqMEM ( coeffptr, dvpx_opaque_50 );
|
|
|
|
/* we are now enabled if we need fogging */
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_opaque_50 );
|
|
/* push enable to safety */
|
|
IGC_MEMminuseqMEM ( coeffptr, dvpx_zbuf, dvpx_eofr, dvpx_zbufbits, dvpx_zbufbits );
|
|
/* now zbuf = zbuf - farz
|
|
so the trick now is, how many bits are needed to represent this,
|
|
to make the multiply as short as possible ?
|
|
*/
|
|
sigbits=0;
|
|
|
|
while (t) {
|
|
t>>=1;
|
|
sigbits++;
|
|
}
|
|
|
|
/*
|
|
so now we know maximum number of significant bits in zbuf - however,
|
|
this is potentially misleading; if near-far = 129, then we need 8 bits,
|
|
but are almost a factor of 2 off. So we scale up to 255, which involves
|
|
scan-converting (255.9f * (1 << sigbits)) / (near - far), a 9-bit number
|
|
*/
|
|
scalar = (int) ((255.9f * (float) (1 << sigbits)) /
|
|
(float) (eof_Z_near - eof_Z_far));
|
|
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_eofr, 9, scalar );
|
|
|
|
/*
|
|
printf ("scalar = %d from sigbits of %d\n", scalar, sigbits );
|
|
printf ("z near = %d z far = %d difference = %d\n",
|
|
eof_Z_near,
|
|
eof_Z_far,
|
|
eof_Z_near-eof_Z_far );
|
|
*/
|
|
basebit=(dvpx_zbuf+sigbits) - 9;
|
|
|
|
coeffptr=multuu_unc ( coeffptr, dvpx_eofg+2, dvpx_eofr, basebit,
|
|
10, 9, 9 );
|
|
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_opaque_50 );
|
|
IGC_CPY ( coeffptr, dvpx_eoffog, dvpx_eofg+3, 8 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
}
|
|
/*}}} */
|
|
/*{{{ ... prepare rgb in dvpx_eofr, g, b*/
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
|
|
IGC_CPY ( coeffptr, dvpx_eofr, dvpx_r24, 24 );
|
|
|
|
/*}}} */
|
|
|
|
IGC_CLEAR ( coeffptr, dvpx_zbuf, dvpx_zbufbits );
|
|
IGC_CLEAR ( coeffptr, dvpx_scalar, dvpx_scalarbits );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_r24, 8, eof_backR );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_g24, 8, eof_backG );
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_b24, 8, eof_backB );
|
|
|
|
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;
|
|
|
|
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);
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static void end_of_transptex ( int **DMAref, int** coeffRef )*/
|
|
static void end_of_transptex ( 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_transptex";
|
|
|
|
/* *****************************************
|
|
all below here may use ONLY end-of-frame space
|
|
********************************************* */
|
|
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_io + 31 );
|
|
|
|
/*{{{ should we keep this pixel?*/
|
|
/* *************************************
|
|
|
|
if opaque AND eof_zbuf > zbuf,
|
|
replace zbuf,
|
|
multiply texture by eofrgb,
|
|
replace pixel,
|
|
flag pixel type as 24-bit, non-textured
|
|
|
|
*/
|
|
|
|
/* lsb of blue is write-enable */
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_io+16 );
|
|
IGC_MEMgtMEM ( coeffptr, dvpx_eoftranspz, dvpx_zbuf, dvpx_zbufbits );
|
|
|
|
/*
|
|
enable set if a) blue texel write-enable asserted and
|
|
b) transp z-buffer closer than current z-buffer
|
|
*/
|
|
IGC_ENABintoMEM ( coeffptr, dvpx_io+30 ); /* trash this for temp */
|
|
/*}}} */
|
|
/*{{{ yes - set pixel type*/
|
|
/*
|
|
NB enable is set if we had a blue write enable AND our eofzbuf is > zbuf
|
|
|
|
so - force pixel type to be 24-bit, non-textured
|
|
*/
|
|
IGC_CLEAR ( coeffptr, dvpx_texsize, dvpx_texsizebits );
|
|
IGC_CPY ( coeffptr, dvpx_zbuf, dvpx_eoftranspz, dvpx_zbufbits );
|
|
/*}}} */
|
|
/*{{{ and multiply looked-up texture by end-of-frame colour*/
|
|
/* use eofsubu and subv, these are now free for scratchpad */
|
|
|
|
coeffptr=multuu_unc ( coeffptr, dvpx_eofsubu, dvpx_io+16, dvpx_eofb,
|
|
9, 8, 8 );
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_io+30 );
|
|
IGC_CPY ( coeffptr, dvpx_b24, dvpx_eofsubu+1, 8 );
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
coeffptr=multuu_unc ( coeffptr, dvpx_eofsubu, dvpx_io+8, dvpx_eofg,
|
|
9, 8, 8 );
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_io+30 );
|
|
IGC_CPY ( coeffptr, dvpx_g24, dvpx_eofsubu+1, 8 );
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
|
|
coeffptr=multuu_unc ( coeffptr, dvpx_eofsubu, dvpx_io, dvpx_eofr,
|
|
9, 8, 8 );
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_io+30 );
|
|
IGC_CPY ( coeffptr, dvpx_r24, dvpx_eofsubu+1, 8 );
|
|
|
|
/*}}} */
|
|
IGC_MEMintoENAB ( coeffptr, dvpx_io + 31 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 40 );
|
|
words=(int) coeffptr - (int) coeff00;
|
|
words>>=3;
|
|
|
|
/*
|
|
printf ("%d 64-bit words in end-of-transptex sequence\n", words );
|
|
*/
|
|
|
|
*coeffRef=coeffptr;
|
|
*DMAref =DMAptr;
|
|
}
|
|
/*}}} */
|
|
/*{{{ static void end_of_transframe ( int **DMAref, int** coeffRef )*/
|
|
|
|
int *trans_wait_poke_address;
|
|
|
|
static void end_of_transframe ( 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;
|
|
/*}}} */
|
|
|
|
send_pass="end_of_frame";
|
|
|
|
/*{{{ turn u,v into SRAM address*/
|
|
/* a value of 0 in texture type means pixel not textured */
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CLEAR ( coeffptr, dvpx_io, 24 );
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqZERO ( coeffptr, dvpx_texsize, dvpx_texsizebits );
|
|
IGC_CLEAR ( coeffptr, dvpx_zbuf, dvpx_zbufbits );
|
|
|
|
/*
|
|
note the end-of-transparent texture frig - we force our zbuf to
|
|
be maximally distant, so no matter what the compare, we lose.
|
|
NBB MAKE SURE WE DO A GT, NOT a GE !
|
|
*/
|
|
|
|
for (i=0; i<3; i++ ) {
|
|
int id, ubase, vbase;
|
|
|
|
edge=6+i;
|
|
|
|
id = (i+1)*2; /* 2 == 64x64 point-24 */
|
|
|
|
ubase = (dvpx_texu + (dvpx_texubits - edge)) - 3;
|
|
vbase = (dvpx_texv + (dvpx_texvbits - edge)) - 3;
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_MEMeqSCA_S1 ( coeffptr, dvpx_texsize, dvpx_texsizebits, id );
|
|
|
|
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 );
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 0, 40 );
|
|
}
|
|
/*}}} */
|
|
/*{{{ trigger Texture Look Up*/
|
|
|
|
/* 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 );
|
|
/*}}} */
|
|
|
|
/*{{{ move zbuffer to eof area*/
|
|
|
|
IGC_SETENABS ( coeffptr );
|
|
IGC_CPY ( coeffptr, dvpx_eoftranspz, dvpx_zbuf, dvpx_zbufbits );
|
|
|
|
/*}}} */
|
|
/*{{{ prepare rgb in dvpx_eofr, g, b*/
|
|
IGC_CPY ( coeffptr, dvpx_eofr, dvpx_r24, 24 );
|
|
IGC_CLEAR ( coeffptr, dvpx_zbuf, dvpx_zbufbits );
|
|
|
|
/*}}} */
|
|
|
|
/* and the code in init_screenbin for the opaque tile does the rest */
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 40 );
|
|
|
|
words=(int) coeffptr - (int) coeff00;
|
|
words>>=3;
|
|
|
|
*coeffRef=coeffptr;
|
|
*DMAref =DMAptr;
|
|
}
|
|
/*}}} */
|
|
/*{{{ int end_of_transframe_DMA ( int *DMAptr, int *coeffptr, int *end_of_tex_DMA )*/
|
|
int end_of_transframe_DMA ( int *DMAptr, int *coeffptr,
|
|
int *end_of_transptex_DMA )
|
|
{
|
|
int *coeff0 = coeffptr;
|
|
int *coeff00 = coeffptr;
|
|
int *DMAptr0 = DMAptr;
|
|
int i, DMAbytes,
|
|
IGCbytes;
|
|
|
|
coeff0=coeffptr;
|
|
transpective_divides ( &DMAptr, &coeffptr );
|
|
coeff0=coeffptr;
|
|
send_pass="eofDMA";
|
|
|
|
/* make sure last opaque texture sequence has executed */
|
|
trans_wait_poke_address=DMAptr+1;
|
|
|
|
*DMAptr++=0x0;
|
|
*DMAptr++=DMA_FLUSH_VAL;
|
|
|
|
/* reinit semaphore */
|
|
*DMAptr++=(int) end_of_transptex_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;
|
|
|
|
end_of_transframe ( &DMAptr, &coeffptr );
|
|
coeff0=coeffptr;
|
|
|
|
coeff0=send_em(&DMAptr, &coeffptr, coeff0, 1, 20 );
|
|
|
|
DMAbytes = (int) DMAptr - (int) DMAptr0;
|
|
IGCbytes = (int) coeffptr - (int) coeff00;
|
|
|
|
return (DMAbytes>>2);
|
|
}
|
|
/*}}} */
|
|
/*{{{ int end_of_transp_DMA ( int *DMAptr, int *coeffptr )*/
|
|
int end_of_transp_DMA ( int *DMAptr, int *coeffptr )
|
|
{
|
|
int *coeff0 =coeffptr;
|
|
int *coeff00=coeffptr;
|
|
int *DMAptr0=DMAptr;
|
|
int i, DMAbytes, IGCbytes;
|
|
|
|
end_of_transptex ( &DMAptr, &coeffptr );
|
|
coeff0=coeffptr;
|
|
|
|
*DMAptr++=0;
|
|
*DMAptr++=DMA_RETE_VAL;
|
|
|
|
DMAbytes = (int) DMAptr - (int) DMAptr0;
|
|
IGCbytes = (int) coeffptr - (int) coeff00;
|
|
|
|
return (DMAbytes>>2);
|
|
}
|
|
/*}}} */
|
|
|