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