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