------------------------------------------------------------------ * New functions for F3DEX(.NoN), F3DLX(.NoN), F3DLX.Rej, F3DLP.Rej, L3DEX ucode release 1.20. + gSPVertex (Gfx *pkt, Vtx *v, u32 n, u32 v0) gsSPVertex( Vtx *v, u32 n, u32 v0) Made the vertex cache larger, so changed the range of parameters n and v0. (see below) g*SPVertex accepts less than 33 vertice per one load. (n accepts 1-32.) So, you may use it twice or more to load more than 32 vertice(*). Vertice cache size Range of n Range of v0 F3DEX/F3DEX.NoN 32 1-32 0-31 F3DLX/F3DLX.NoN 32 1-32 0-31 F3DLX.Rej 64 1-32(*) 0-63 F3DLP.Rej 80 1-32(*) 0-79 L3DEX 32 1-32 0-31 + gSP2Triangles (pkt, v00, v01, v02, flag0, v10, v11, v12, flag1) gsSP2Triangles( v00, v01, v02, flag0, v10, v11, v12, flag1) gSP2Triangles are "double triangle face command." This command generates *two* triangles same as gSP1Triangle(pkt++, v00, v01, v02, flag0); gSP1Triangle(pkt++, v10, v11, v12, flag1); You can replace two g*SP1Triangle to one g*SP2Triangles, so this command can make DL size shorter. F3DLX.Rej and F3DLP.Rej are very fast because they are optimized for executing g*SP2Triangle. So you'd better use g*SPTriangle to get more performance. + gSP1Quadrangle (pkt, v0, v1, v2, v3, flag) gsSP1Quadrangle( v0, v1, v2, v3, flag) g*SP1Quadrangle generates a quadrangle (v0,v1,v2,v3). flag should be either 0,1,2 or 3 for flat shading. We don't support dynamic divide selection for quadrangle in this and later release. Because SP's overhead is larger than DP's increase of performance we had expected. In release 0.96 and later, g*SP1Quadrangle is emulated by g*SP2Triangles, so apps for release 0.95 or before can work with re-compiling. + gSPSetGeometryMode(Gfx *gdl, unsigned int mode) gsSPSetGeometryMode(unsigned int mode) G_CLIPPING would be available for mode identify. If G_CLIPPING has cleared, F3DLX does not clip any triangle (quadrangle) but faster. If G_CLIPPING has cleared.... gSPVertex : Does not make pre-calculated vertex data for clipping. gSP*Triangle: Does not work any clipping. (Also gSP1Quadrangle) So, following DL is *not* correct because gsSP1Triangle cannot get pre-calculated vertex data of clipping from gsSPVertex. In this DL, gsSP1Triangle cannot work. gsSPClearGeometryMode(G_CLIPPING), // Clipping OFF gsSPVertex(v, 3, 0), // Load 3 vertices gsSPSetGeometryMode(G_CLIPPING), // Clipping ON gsSP1Triangle(0,1,2,0), // Draw TRI Also gSPCullDisplayList() cannot work with no pre-calculated vertex data made by no G_CLIPPING. G_CLIPPING is available in F3DLX only. It's ignored in other ucodes. G_CLIPPING is set when initialized RSP. + gSPCullDisplaylist(Gfx *gdl, unsigned int v0, unsigned int vn) gsSPCullDisplaylist(unsigned int v0, unsigned int vn) Change ranges of v0 and vn by increase vertices cache size. The ranges are same as v0 of gSPVertex parameter. But, must be v0 <= vn. (man pages are incorrect.) g*SPClipRatio of F3DEX(.NoN), F3DLX(.NoN) and L3DEX works same as Fast3D's. But F3DLX.Rej's and F3DLP.Rej's are not same at all. + gSPClipRatio(Gfx *gdl, r) gsSPClipRatio(r) Also, g*SPClipRatio of F3DEX(.NoN), F3DLX(.NoN) and L3DEX works same as Fast3D's. But F3DLX.Rej's and F3DLP.Rej's are not same at all. In F3DL*.Rej, g*SPClipRatio defines a size of the rejecting box. (default rejecting box size: FRUSTRATIO_2) + gSPModiftVertex(Gfx *gdl, unsigned int vtx, unsigned int where, unsigned int val) gsSPModifyVertex(unsigned int vtx, unsigned int where, unsigned int val) Change ranges of vtx by increase vertices cache size. The ranges are same as v0 of gSPVertex parameter. + gSPBranchLessZ(Gfx *gdl, Gfx *branchdl, unsigned int vtx, float zval, float near, float far, int flag) gsSPBranchLessZ(Gfx *branchdl, unsigned int vtx, float zval, float near, float far, int flag) Branch display list to pointer specified `branchdl' if screen depth of `vtx' less than or equal `zval'. If greater, do nothing. It makes supporting model LOD very easier. Here is a sample model with 3 level LOD. Gfx model_near[] = { // Model DL on 32<=depth<=200 ..... gsSPEndDisplayList(), }; Gfx model_mid[] = { // Model DL on 201<=depth<=800 ..... gsSPEndDisplayList(), }; Gfx model_far[] = { // Model DL on 801<=depth<=1600 ..... gsSPEndDisplayList(), }; Gfx model[] = { gsSPVertex(testvtx, 1, 0), gsSPBranchLessZ(model_near, 0, 200, 32, 2000, G_BZ_PERSP), gsSPBranchLessZ(model_mid, 0, 800, 32, 2000, G_BZ_PERSP), gsSPBranchLessZ(model_far, 0, 1600, 32, 2000, G_BZ_PERSP), gsSPEndDisplayList(), // Don't display if 1601<=depth. }; This GBI needs some parameters about viewing frustum as following. `near' Distance to the near clipping plane. Same value specified in guPerspective()/guOrtho(). `far' Distance to the far clipping plane. Same value specified in guPerspective()/guOrtho(). `flag' Set `G_BZ_PERSP' for perspective projection(guPerspective). Set `G_BZ_ORTHO' for orthographic projection(guOrtho). To use g*SPBranchLessZ(), the view port parameters `vp.vscale[2]' and `vp.vtrans[2]' should be set `G_MAXZ/2'. Normally, it is unnecessary to set other values for vp.vscale[2], and vp.vtrans[2]. But, when you want other values, you may use g*SPBranchLessZrg() instead of g*SPBranchLessZ(). This GBI's are supported in release 1.02 or later, and available in F3DEX(.NoN), F3DLX(.NoN), F3DLX.Rej, F3DLP.Rej and L3DEX. + gSPBranchLessZrg(Gfx *gdl, Gfx *branchdl, unsigned int vtx, float zval, float near, float far, int flag, int zmin, int zmax) gsSPBranchLessZrg(Gfx *branchdl, unsigned int vtx, float zval, float near, float far, int flag, int zmin, int zmax) Normally, the range of screen depth value should be 0 to G_MAXZ with g*SPBranchLessZ. However, if you want to use another range `zmin' to `zmax', you should use g*SPBranchLessZrg instead of g*SPBranchLessZ. g*SPBranchLessZrg needs two more parameters than g*SPBranchLessZ. `zmin' depth value minimum. (= vp.vtrans[2]-vp.vscale[2]) `zmax' depth value maximum. (= vp.vtrans[2]+vp.vscale[2]) Other paramters (gdl, branchdl, vtx, zval, near, far and flag) are same as g*SPBranchLessZ's. This GBI's are supported in release 1.02 or later, and available in F3DEX(.NoN), F3DLX(.NoN), F3DLX.Rej, F3DLP.Rej and L3DEX. + gSPLoadUcode(Gfx *gdl, u64 *uc_start, u64 *uc_dstart) gsSPLoadUcode(u64 *uc_start, u64 *uc_dstart) uc_start : Physical address of the top of the ucode text section. uc_dstart: Physical address of the top of the ucode data section. Load ucode into IMEM/DMEM and initailize RSP. Loadable ucodes are F3DEX(.NoN), F3DLX(.NoN), F3DLX_Rej, F3DLP_Rej and L3DEX. Fast3D and Turbo3D are not loadable. If you have F3DEX 1.22 (in the N64 Dev 2.0H) and S2DEX ucode for Sprite drawing, you can use gSPLoadUcode to load S2DEX for drawing sprite. You should be careful to `Load ucode'. Because to load ucode would often take some processing time. It's overhead. So, you should avoid useless ucode loading. The ucodes would be changed to get best performance in the situation, such as... o Loading F3DLX ucode to draw game field with clipping function. (Clipping is necessary to draw game field.) o Loading F3DLX.Rej (after draw game field) to draw game object as a man, a car ... (F3DLX.Rej is faster than F3DLX.) And you can load line ucode `L3DEX' to draw line without CPU processing. *** Caution *** This GBI command g*SPLoadUcode makes RSP initailized. So, you should set all parameters of RSP status again (Segment address, Viewport, Geometry-mode, Matrix, Link info. of display list ... and more). So, when you use g*SPLoadUcode in Display list (DL1) linked from another Display List (DL2) by g*SPDisplayList, the DL1 cannot return back to DL2. It's very dangerous implemention I think, but we don't have enough code space to fix it. You should set `OS_TASK_LOADABLE' to member `flag' in `OSTask' to use this GBI g*SPLoadUcode like as this. OSTask *tp; tp->t.flag = OS_TASK_LOADABLE | OS_TASK_DP_WAIT; To make OS_TASK_LOADABLE available, you need some patches for N64 OS libraries. For more information, see `OS patches:' in file `README'. The patched OS libultra*.a have upper compatiblility with original OS. + gSPLoadUcodeL(Gfx *gdl, ucode_name) gsSPLoadUcodeL(ucode_name) g*SPLoadUcodeL is same as g*SPLoadUcode expect an expression. See following, (a) and (b) works equally. (a) gsSPLoadUcode(OS_K0_TO_PHYSICAL(&gspF3DEX_fifoTextStart), OS_K0_TO_PHYSICAL(&gspF3DEX_fifoDataStart)) (b) gsSPLoadUcodeL(gspF3DEX_fifo)