From 8ed65e05aed12965e5b75991d388ae33228812e7 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sun, 4 Feb 2024 17:58:03 -0500 Subject: [PATCH 01/30] Initial F3DEX3 work --- Makefile | 18 +- include/n64/PR/gbi.h | 4875 +------------------------ include/n64/PR/gbi_f3dex3.h | 5166 +++++++++++++++++++++++++++ include/n64/PR/gbi_std.h | 4873 +++++++++++++++++++++++++ include/n64/PR/ucode.h | 7 + lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o | Bin 0 -> 7728 bytes rspdata.inc.ld | 19 +- rsptext.inc.ld | 27 +- src/game/game_init.c | 5 + src/goddard/renderer.c | 17 +- src/s2d_engine/init.h | 3 + 11 files changed, 10112 insertions(+), 4898 deletions(-) create mode 100644 include/n64/PR/gbi_f3dex3.h create mode 100644 include/n64/PR/gbi_std.h create mode 100644 lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o diff --git a/Makefile b/Makefile index 35fb2a12d6..353945779d 100644 --- a/Makefile +++ b/Makefile @@ -96,13 +96,14 @@ TARGET := sm64 # GRUCODE - selects which RSP microcode to use. -# f3dex - -# f3dex2 - -# l3dex2 - F3DEX2 version that only renders in wireframe -# f3dzex - newer, experimental microcode used in Animal Crossing -# super3d - extremely experimental version of Fast3D lacking many features for speed -GRUCODE ?= f3dzex -$(eval $(call validate-option,GRUCODE,f3dex f3dex2 f3dex2pl f3dzex super3d l3dex2)) +# f3dex - Upgraded Fast3D. Offers worse performance than Fast3DEX2, but has a more precise z-buffer. +# f3dex2 - Upgraded Fast3DEX. Good performance and widely supported across almost all emulators. +# l3dex2 - Fast3DEX2 version that only renders in wireframe. +# f3dzex - Newer, experimental microcode based on Fast3DEX2 used in Animal Crossing and Zelda 64. +# f3dex3 - Upgraded Fast3DEX2. Great performance, but as of February 4th, 2024, it is only supported across LLE emulators and real hardware. +# super3d - Extremely experimental version of Fast3D lacking many features and simplified routines for speed. +GRUCODE ?= f3dex3 +$(eval $(call validate-option,GRUCODE,f3dex f3dex2 f3dex2pl f3dzex super3d l3dex2 f3dex3)) ifeq ($(GRUCODE),f3dex) # Fast3DEX DEFINES += F3DEX_GBI=1 F3DEX_GBI_SHARED=1 @@ -117,6 +118,9 @@ else ifeq ($(GRUCODE),f3dzex) # Fast3DZEX (2.08J / Animal Forest - Dōbutsu no M else ifeq ($(GRUCODE),super3d) # Super3D $(warning Super3D is experimental. Try at your own risk.) DEFINES += SUPER3D_GBI=1 F3D_NEW=1 +else ifeq ($(GRUCODE),f3dex3) # Fast3DEX3 + DEFINES += F3DEX_GBI_3=1 F3DEX_GBI_SHARED=1 + $(warning Fast3DEX3 is experimental. Try at your own risk.) endif # TEXT ENGINES diff --git a/include/n64/PR/gbi.h b/include/n64/PR/gbi.h index 7461fa9170..ddf20d706e 100644 --- a/include/n64/PR/gbi.h +++ b/include/n64/PR/gbi.h @@ -1,1242 +1,5 @@ -/************************************************************************** - * * - * Copyright (C) 1994, Silicon Graphics, Inc. * - * * - * These coded instructions, statements, and computer programs contain * - * unpublished proprietary information of Silicon Graphics, Inc., and * - * are protected by Federal copyright law. They may not be disclosed * - * to third parties or copied or duplicated in any form, in whole or * - * in part, without the prior written consent of Silicon Graphics, Inc. * - * * - **************************************************************************/ -/************************************************************************** - * - * $Revision: 1.141 $ - * $Date: 1999/09/03 03:43:08 $ - * $Source: /exdisk2/cvs/N64OS/Master/cvsmdev2/PR/include/gbi.h,v $ - * - **************************************************************************/ - -#ifndef _GBI_H_ -#define _GBI_H_ - -#include -#include - -/* - * Converts texel coordinates to S and T values - */ -// Bilerp/Average filter -#define TC_B_OFF -0.5 -#define TC_B(p) (((p) + TC_B_OFF) * 32) -// #define TC_B(p) ((((p) > TC_B_OFF) ? ((p) - TC_B_OFF) : (p)) * 32) -#define ST_B(s, t) {TC_B(s), TC_B(t)} - -// Point filter -#define TX_P_OFF 0.25 -#define TC_P(p) (((p) + TX_P_OFF) * 32) -#define ST_P(s, t) {TC_P(s), TC_P(t)} - -/* - * To use the F3DEX ucodes, define F3DEX_GBI before include this file. - * - * #define F3DEX_GBI - * #include - * - * or - * - * cc -c -DF3DEX_GBI -I.... foo.c - * - */ - -/************************************************************************** - * - * Graphics Binary Interface - * - **************************************************************************/ - -/* - * Graphics Commands, 'xxx' parts may be generated from ucode - * - * The command format is - * - * |00xxxxxx| = DMA 0,..,127 - * |10xxxxxx| = Immediate Mode -65,..,-128 - * |11xxxxxx| = RDP cmds -1,..,-64 - * - * Note: in order for the RSP microcode to process RDP commands opaquely, - * we need to further identify those RDP commands that need DRAM address - * "fixup". To do this, we have the dummy command G_RDP_ADDR_FIXUP, and - * all |RDP commands| less than this are commands with embedded DRAM - * addresses. Further, the format of these commands should be similar so - * only one fixup routine is needed. - * - * Further explanation: - * The names of the commands are somewhat misleading. Here is clarification: - * - * - a 'DMA' type command has a pointer to additional data and - * causes a DMA transfer to bring that into DMEM. - * - * - an 'Immediate' type command isn't really 'immediate', in the - * traditional sense. This just means that the entire command fits - * in the 64-bit word, and the ucode can execute it 'immediately' - * without additional memory transfers. - * - * - an 'RDP' command is identified as such because the RDP - * commands can be passed-thru the RSP and sent to the RDP - * directly. One further confusing thing, is that some 'DP' - * macros below actually generate immediate commands, not - * not direct DP commands. - * - * IMPLEMENTATION NOTE: - * There is another group of RDP commands that includes the triangle commands - * generated by the RSP code. These are the raw commands the rasterizer - * hardware chews on, with slope info, etc. They will follow the RDP - * ordering... - * - * IMPLEMENTATION NOTE: - * The RDP hardware has some of these bit patterns wired up. If the hardware - * changes, we must adjust this table, likewise we can't change/add things - * once the hardware is frozen. (actually, the RDP hardware only looks at - * the lower 6 bits of the command byte) - * - */ - -#ifdef F3DEX_GBI_2E -# ifndef F3DEX_GBI_2 -# define F3DEX_GBI_2 -# endif -# define GBI_FLOATS -#endif - -#ifdef F3DEX_GBI_2 -# ifndef F3DEX_GBI -# define F3DEX_GBI -# endif -#define G_NOOP 0x00 -#define G_RDPHALF_2 0xf1 -#define G_SETOTHERMODE_H 0xe3 -#define G_SETOTHERMODE_L 0xe2 -#define G_RDPHALF_1 0xe1 -#define G_SPNOOP 0xe0 -#define G_ENDDL 0xdf -#define G_DL 0xde -#define G_LOAD_UCODE 0xdd -#define G_MOVEMEM 0xdc -#define G_MOVEWORD 0xdb -#define G_MTX 0xda -#define G_GEOMETRYMODE 0xd9 -#define G_POPMTX 0xd8 -#define G_TEXTURE 0xd7 -#define G_DMA_IO 0xd6 -#define G_SPECIAL_1 0xd5 -#define G_SPECIAL_2 0xd4 -#define G_SPECIAL_3 0xd3 - -#define G_VTX 0x01 -#define G_MODIFYVTX 0x02 -#define G_CULLDL 0x03 -#define G_BRANCH_Z 0x04 -#define G_TRI1 0x05 -#define G_TRI2 0x06 -#define G_QUAD 0x07 -#define G_LINE3D 0x08 -#else /* F3DEX_GBI_2 */ - -/* DMA commands: */ -#define G_SPNOOP 0 /* handle 0 gracefully */ -#define G_MTX 1 -#define G_RESERVED0 2 /* not implemeted */ -#define G_MOVEMEM 3 /* move a block of memory (up to 4 words) to dmem */ -#define G_VTX 4 -#define G_RESERVED1 5 /* not implemeted */ -#define G_DL 6 -#define G_RESERVED2 7 /* not implemeted */ -#define G_RESERVED3 8 /* not implemeted */ -#define G_SPRITE2D_BASE 9 /* sprite command */ - -/* IMMEDIATE commands: */ -#define G_IMMFIRST -65 -#define G_TRI1 (G_IMMFIRST-0) -#define G_CULLDL (G_IMMFIRST-1) -#define G_POPMTX (G_IMMFIRST-2) -#define G_MOVEWORD (G_IMMFIRST-3) -#define G_TEXTURE (G_IMMFIRST-4) -#define G_SETOTHERMODE_H (G_IMMFIRST-5) -#define G_SETOTHERMODE_L (G_IMMFIRST-6) -#define G_ENDDL (G_IMMFIRST-7) -#define G_SETGEOMETRYMODE (G_IMMFIRST-8) -#define G_CLEARGEOMETRYMODE (G_IMMFIRST-9) -#define G_LINE3D (G_IMMFIRST-10) -#define G_RDPHALF_1 (G_IMMFIRST-11) -#define G_RDPHALF_2 (G_IMMFIRST-12) -#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) -# define G_MODIFYVTX (G_IMMFIRST-13) -# define G_TRI2 (G_IMMFIRST-14) -# define G_BRANCH_Z (G_IMMFIRST-15) -# define G_LOAD_UCODE (G_IMMFIRST-16) -#else -# define G_RDPHALF_CONT (G_IMMFIRST-13) -#endif - -/* We are overloading 2 of the immediate commands - to keep the byte alignment of dmem the same */ - -#define G_SPRITE2D_SCALEFLIP (G_IMMFIRST-1) -#define G_SPRITE2D_DRAW (G_IMMFIRST-2) - -/* RDP commands: */ -#define G_NOOP 0xc0 /* 0 */ - -#endif /* F3DEX_GBI_2 */ - -/* RDP commands: */ -#define G_SETCIMG 0xff /* -1 */ -#define G_SETZIMG 0xfe /* -2 */ -#define G_SETTIMG 0xfd /* -3 */ -#define G_SETCOMBINE 0xfc /* -4 */ -#define G_SETENVCOLOR 0xfb /* -5 */ -#define G_SETPRIMCOLOR 0xfa /* -6 */ -#define G_SETBLENDCOLOR 0xf9 /* -7 */ -#define G_SETFOGCOLOR 0xf8 /* -8 */ -#define G_SETFILLCOLOR 0xf7 /* -9 */ -#define G_FILLRECT 0xf6 /* -10 */ -#define G_SETTILE 0xf5 /* -11 */ -#define G_LOADTILE 0xf4 /* -12 */ -#define G_LOADBLOCK 0xf3 /* -13 */ -#define G_SETTILESIZE 0xf2 /* -14 */ -#define G_LOADTLUT 0xf0 /* -16 */ -#define G_RDPSETOTHERMODE 0xef /* -17 */ -#define G_SETPRIMDEPTH 0xee /* -18 */ -#define G_SETSCISSOR 0xed /* -19 */ -#define G_SETCONVERT 0xec /* -20 */ -#define G_SETKEYR 0xeb /* -21 */ -#define G_SETKEYGB 0xea /* -22 */ -#define G_RDPFULLSYNC 0xe9 /* -23 */ -#define G_RDPTILESYNC 0xe8 /* -24 */ -#define G_RDPPIPESYNC 0xe7 /* -25 */ -#define G_RDPLOADSYNC 0xe6 /* -26 */ -#define G_TEXRECTFLIP 0xe5 /* -27 */ -#define G_TEXRECT 0xe4 /* -28 */ - - -/* - * The following commands are the "generated" RDP commands; the user - * never sees them, the RSP microcode generates them. - * - * The layout of the bits is magical, to save work in the ucode. - * These id's are -56, -52, -54, -50, -55, -51, -53, -49, ... - * edge, shade, texture, zbuff bits: estz - */ -#define G_TRI_FILL 0xc8 /* fill triangle: 11001000 */ -#define G_TRI_SHADE 0xcc /* shade triangle: 11001100 */ -#define G_TRI_TXTR 0xca /* texture triangle: 11001010 */ -#define G_TRI_SHADE_TXTR 0xce /* shade, texture triangle: 11001110 */ -#define G_TRI_FILL_ZBUFF 0xc9 /* fill, zbuff triangle: 11001001 */ -#define G_TRI_SHADE_ZBUFF 0xcd /* shade, zbuff triangle: 11001101 */ -#define G_TRI_TXTR_ZBUFF 0xcb /* texture, zbuff triangle: 11001011 */ -#define G_TRI_SHADE_TXTR_ZBUFF 0xcf /* shade, txtr, zbuff trngl: 11001111 */ - -/* - * A TRI_FILL triangle is just the edges. You need to set the DP - * to use primcolor, in order to see anything. (it is NOT a triangle - * that gets rendered in 'fill mode'. Triangles can't be rendered - * in 'fill mode') - * - * A TRI_SHADE is a gouraud triangle that has colors interpolated. - * Flat-shaded triangles (from the software) are still gouraud shaded, - * it's just the colors are all the same and the deltas are 0. - * - * Other triangle types, and combinations are more obvious. - */ - -/* masks to build RDP triangle commands: */ -#define G_RDP_TRI_FILL_MASK 0x08 -#define G_RDP_TRI_SHADE_MASK 0x04 -#define G_RDP_TRI_TXTR_MASK 0x02 -#define G_RDP_TRI_ZBUFF_MASK 0x01 - -/* - * HACK: - * This is a dreadful hack. For version 1.0 hardware, there are still - * some 'bowtie' hangs. This parameter can be increased to avoid - * the hangs. Every increase of 4 chops one scanline off of every - * triangle. Values of 4,8,12 should be sufficient to avoid any - * bowtie hang. - * - * Change this value, then recompile ALL of your program (including static - * display lists!) - * - * THIS WILL BE REMOVED FOR HARDWARE VERSION 2.0! - */ -#define BOWTIE_VAL 0 - - -/* gets added to RDP command, in order to test for addres fixup: */ -#define G_RDP_ADDR_FIXUP 3 /* |RDP cmds| <= this, do addr fixup */ -#ifdef _LANGUAGE_ASSEMBLY -#define G_RDP_TEXRECT_CHECK ((-1*G_TEXRECTFLIP)& 0xff) -#endif - -/* macros for command parsing: */ -#define GDMACMD(x) (x) -#define GIMMCMD(x) (G_IMMFIRST-(x)) -#define GRDPCMD(x) (0xff-(x)) - -#define G_DMACMDSIZ 128 -#define G_IMMCMDSIZ 64 -#define G_RDPCMDSIZ 64 - -/* - * Coordinate shift values, number of bits of fraction - */ -#define G_TEXTURE_IMAGE_FRAC 2 -#define G_TEXTURE_SCALE_FRAC 16 -#define G_SCALE_FRAC 8 -#define G_ROTATE_FRAC 16 - -/* - * Parameters to graphics commands - */ - -/* - * Data packing macros - */ - -/* - * Maximum z-buffer value, used to initialize the z-buffer. - * Note : this number is NOT the viewport z-scale constant. - * See the comment next to G_MAXZ for more info. - */ -#define G_MAXFBZ 0x3fff /* 3b exp, 11b mantissa */ - -#define GPACK_RGBA5551(r, g, b, a) ((((r)<<8) & 0xf800) | \ - (((g)<<3) & 0x7c0) | \ - (((b)>>2) & 0x3e) | ((a) & 0x1)) -#define GPACK_ZDZ(z, dz) ((z) << 2 | (dz)) - -/* - * G_MTX: parameter flags - */ -#ifdef F3DEX_GBI_2 -# define G_MTX_MODELVIEW 0x00 /* matrix types */ -# define G_MTX_PROJECTION 0x04 -# define G_MTX_MUL 0x00 /* concat or load */ -# define G_MTX_LOAD 0x02 -# define G_MTX_NOPUSH 0x00 /* push or not */ -# define G_MTX_PUSH 0x01 -#else /* F3DEX_GBI_2 */ -# define G_MTX_MODELVIEW 0x00 /* matrix types */ -# define G_MTX_PROJECTION 0x01 -# define G_MTX_MUL 0x00 /* concat or load */ -# define G_MTX_LOAD 0x02 -# define G_MTX_NOPUSH 0x00 /* push or not */ -# define G_MTX_PUSH 0x04 -#endif /* F3DEX_GBI_2 */ - -/* - * flags for G_SETGEOMETRYMODE - * (this rendering state is maintained in RSP) - * - * DO NOT USE THE LOW 8 BITS OF GEOMETRYMODE: - * The weird bit-ordering is for the micro-code: the lower byte - * can be OR'd in with G_TRI_SHADE (11001100) to construct - * the triangle command directly. Don't break it... - * - * DO NOT USE THE HIGH 8 BITS OF GEOMETRYMODE: - * The high byte is OR'd with 0x703 to form the clip code mask. - * If it is set to 0x04, this will cause near clipping to occur. - * If it is zero, near clipping will not occur. - * - * Further explanation: - * G_SHADE is necessary in order to see the color that you passed - * down with the vertex. If G_SHADE isn't set, you need to set the DP - * appropriately and use primcolor to see anything. - * - * G_SHADING_SMOOTH enabled means use all 3 colors of the triangle. - * If it is not set, then do 'flat shading', where only one vertex color - * is used (and all 3 vertices are set to that same color by the ucode) - * See the man page for gSP1Triangle(). - * - */ -#define G_ZBUFFER 0x00000001 -#define G_SHADE 0x00000004 /* enable Gouraud interp */ -/* rest of low byte reserved for setup ucode */ -#ifdef F3DEX_GBI_2 -# define G_TEXTURE_ENABLE 0x00000000 /* Ignored */ -# define G_SHADING_SMOOTH 0x00200000 /* flat or smooth shaded */ -# define G_CULL_FRONT 0x00000200 -# define G_CULL_BACK 0x00000400 -# define G_CULL_BOTH 0x00000600 /* To make code cleaner */ -#else -# define G_TEXTURE_ENABLE 0x00000002 /* Microcode use only */ -# define G_SHADING_SMOOTH 0x00000200 /* flat or smooth shaded */ -# define G_CULL_FRONT 0x00001000 -# define G_CULL_BACK 0x00002000 -# define G_CULL_BOTH 0x00003000 /* To make code cleaner */ -#endif -#define G_FOG 0x00010000 -#define G_LIGHTING 0x00020000 -#define G_TEXTURE_GEN 0x00040000 -#define G_TEXTURE_GEN_LINEAR 0x00080000 -#define G_LOD 0x00100000 /* NOT IMPLEMENTED */ -#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) -# define G_CLIPPING 0x00800000 -#else -# define G_CLIPPING 0x00000000 -#endif - -#ifdef _LANGUAGE_ASSEMBLY -#define G_FOG_H (G_FOG/0x10000) -#define G_LIGHTING_H (G_LIGHTING/0x10000) -#define G_TEXTURE_GEN_H (G_TEXTURE_GEN/0x10000) -#define G_TEXTURE_GEN_LINEAR_H (G_TEXTURE_GEN_LINEAR/0x10000) -#define G_LOD_H (G_LOD/0x10000) /* NOT IMPLEMENTED */ -#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) -# define G_CLIPPING_H (G_CLIPPING/0x10000) -#endif -#endif - -/* Need these defined for Sprite Microcode */ -#ifdef _LANGUAGE_ASSEMBLY -#define G_TX_LOADTILE 7 -#define G_TX_RENDERTILE 0 - -#define G_TX_NOMIRROR 0 -#define G_TX_WRAP 0 -#define G_TX_MIRROR 0x1 -#define G_TX_CLAMP 0x2 -#define G_TX_NOMASK 0 -#define G_TX_NOLOD 0 -#endif - -/* - * G_SETIMG fmt: set image formats - */ -#define G_IM_FMT_RGBA 0 -#define G_IM_FMT_YUV 1 -#define G_IM_FMT_CI 2 -#define G_IM_FMT_IA 3 -#define G_IM_FMT_I 4 - -/* - * G_SETIMG siz: set image pixel size - */ -#define G_IM_SIZ_4b 0 -#define G_IM_SIZ_8b 1 -#define G_IM_SIZ_16b 2 -#define G_IM_SIZ_32b 3 -#define G_IM_SIZ_DD 5 - -#define G_IM_SIZ_4b_BYTES 0 -#define G_IM_SIZ_4b_TILE_BYTES G_IM_SIZ_4b_BYTES -#define G_IM_SIZ_4b_LINE_BYTES G_IM_SIZ_4b_BYTES - -#define G_IM_SIZ_8b_BYTES 1 -#define G_IM_SIZ_8b_TILE_BYTES G_IM_SIZ_8b_BYTES -#define G_IM_SIZ_8b_LINE_BYTES G_IM_SIZ_8b_BYTES - -#define G_IM_SIZ_16b_BYTES 2 -#define G_IM_SIZ_16b_TILE_BYTES G_IM_SIZ_16b_BYTES -#define G_IM_SIZ_16b_LINE_BYTES G_IM_SIZ_16b_BYTES - -#define G_IM_SIZ_32b_BYTES 4 -#define G_IM_SIZ_32b_TILE_BYTES 2 -#define G_IM_SIZ_32b_LINE_BYTES 2 - -#define G_IM_SIZ_4b_LOAD_BLOCK G_IM_SIZ_16b -#define G_IM_SIZ_8b_LOAD_BLOCK G_IM_SIZ_16b -#define G_IM_SIZ_16b_LOAD_BLOCK G_IM_SIZ_16b -#define G_IM_SIZ_32b_LOAD_BLOCK G_IM_SIZ_32b - -#define G_IM_SIZ_4b_SHIFT 2 -#define G_IM_SIZ_8b_SHIFT 1 -#define G_IM_SIZ_16b_SHIFT 0 -#define G_IM_SIZ_32b_SHIFT 0 - -#define G_IM_SIZ_4b_INCR 3 -#define G_IM_SIZ_8b_INCR 1 -#define G_IM_SIZ_16b_INCR 0 -#define G_IM_SIZ_32b_INCR 0 - -/* - * G_SETCOMBINE: color combine modes - */ -/* Color combiner constants: */ -#define G_CCMUX_COMBINED 0 -#define G_CCMUX_TEXEL0 1 -#define G_CCMUX_TEXEL1 2 -#define G_CCMUX_PRIMITIVE 3 -#define G_CCMUX_SHADE 4 -#define G_CCMUX_ENVIRONMENT 5 -#define G_CCMUX_CENTER 6 -#define G_CCMUX_SCALE 6 -#define G_CCMUX_COMBINED_ALPHA 7 -#define G_CCMUX_TEXEL0_ALPHA 8 -#define G_CCMUX_TEXEL1_ALPHA 9 -#define G_CCMUX_PRIMITIVE_ALPHA 10 -#define G_CCMUX_SHADE_ALPHA 11 -#define G_CCMUX_ENV_ALPHA 12 -#define G_CCMUX_LOD_FRACTION 13 -#define G_CCMUX_PRIM_LOD_FRAC 14 -#define G_CCMUX_NOISE 7 -#define G_CCMUX_K4 7 -#define G_CCMUX_K5 15 -#define G_CCMUX_1 6 -#define G_CCMUX_0 31 - -/* Alpha combiner constants: */ -#define G_ACMUX_COMBINED 0 -#define G_ACMUX_TEXEL0 1 -#define G_ACMUX_TEXEL1 2 -#define G_ACMUX_PRIMITIVE 3 -#define G_ACMUX_SHADE 4 -#define G_ACMUX_ENVIRONMENT 5 -#define G_ACMUX_LOD_FRACTION 0 -#define G_ACMUX_PRIM_LOD_FRAC 6 -#define G_ACMUX_1 6 -#define G_ACMUX_0 7 - -/* typical CC cycle 1 modes */ -#define G_CC_PRIMITIVE 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE -#define G_CC_SHADE 0, 0, 0, SHADE, 0, 0, 0, SHADE - -#define G_CC_MODULATEI TEXEL0, 0, SHADE, 0, 0, 0, 0, SHADE -#define G_CC_MODULATEIDECALA TEXEL0, 0, SHADE, 0, 0, 0, 0, TEXEL0 -#define G_CC_MODULATEIFADE TEXEL0, 0, SHADE, 0, 0, 0, 0, ENVIRONMENT - -#define G_CC_MODULATERGB G_CC_MODULATEI -#define G_CC_MODULATERGBDECALA G_CC_MODULATEIDECALA -#define G_CC_MODULATERGBFADE G_CC_MODULATEIFADE - -#define G_CC_MODULATEIA TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0 -#define G_CC_MODULATEIFADEA TEXEL0, 0, SHADE, 0, TEXEL0, 0, ENVIRONMENT, 0 - -#define G_CC_MODULATEFADE TEXEL0, 0, SHADE, 0, ENVIRONMENT, 0, TEXEL0, 0 - -#define G_CC_MODULATERGBA G_CC_MODULATEIA -#define G_CC_MODULATERGBFADEA G_CC_MODULATEIFADEA - -#define G_CC_MODULATEI_PRIM TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE -#define G_CC_MODULATEIA_PRIM TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0 -#define G_CC_MODULATEIDECALA_PRIM TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, TEXEL0 - -#define G_CC_MODULATERGB_PRIM G_CC_MODULATEI_PRIM -#define G_CC_MODULATERGBA_PRIM G_CC_MODULATEIA_PRIM -#define G_CC_MODULATERGBDECALA_PRIM G_CC_MODULATEIDECALA_PRIM - -#define G_CC_FADE SHADE, 0, ENVIRONMENT, 0, SHADE, 0, ENVIRONMENT, 0 -#define G_CC_FADEA TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0 - -#define G_CC_DECALRGB 0, 0, 0, TEXEL0, 0, 0, 0, SHADE -#define G_CC_DECALRGBA 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0 -#define G_CC_DECALFADE 0, 0, 0, TEXEL0, 0, 0, 0, ENVIRONMENT - -#define G_CC_DECALFADEA 0, 0, 0, TEXEL0, TEXEL0, 0, ENVIRONMENT, 0 - -#define G_CC_BLENDI ENVIRONMENT, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE -#define G_CC_BLENDIA ENVIRONMENT, SHADE, TEXEL0, SHADE, TEXEL0, 0, SHADE, 0 -#define G_CC_BLENDIDECALA ENVIRONMENT, SHADE, TEXEL0, SHADE, 0, 0, 0, TEXEL0 - -#define G_CC_BLENDRGBA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, SHADE -#define G_CC_BLENDRGBDECALA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, TEXEL0 -#define G_CC_BLENDRGBFADEA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, ENVIRONMENT - -#define G_CC_ADDRGB TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, SHADE -#define G_CC_ADDRGBDECALA TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, TEXEL0 -#define G_CC_ADDRGBFADE TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, ENVIRONMENT - -#define G_CC_REFLECTRGB ENVIRONMENT, 0, TEXEL0, SHADE, 0, 0, 0, SHADE -#define G_CC_REFLECTRGBDECALA ENVIRONMENT, 0, TEXEL0, SHADE, 0, 0, 0, TEXEL0 - -#define G_CC_HILITERGB PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE -#define G_CC_HILITERGBA PRIMITIVE, SHADE, TEXEL0, SHADE, PRIMITIVE, SHADE, TEXEL0, SHADE -#define G_CC_HILITERGBDECALA PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, TEXEL0 - -#define G_CC_SHADEDECALA 0, 0, 0, SHADE, 0, 0, 0, TEXEL0 -#define G_CC_SHADEFADEA 0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT - -#define G_CC_BLENDPE PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, SHADE, 0 -#define G_CC_BLENDPEDECALA PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, TEXEL0 - -/* oddball modes */ -#define _G_CC_BLENDPE ENVIRONMENT, PRIMITIVE, TEXEL0, PRIMITIVE, TEXEL0, 0, SHADE, 0 -#define _G_CC_BLENDPEDECALA ENVIRONMENT, PRIMITIVE, TEXEL0, PRIMITIVE, 0, 0, 0, TEXEL0 -#define _G_CC_TWOCOLORTEX PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE -/* used for 1-cycle sparse mip-maps, primitive color has color of lowest LOD */ -#define _G_CC_SPARSEST PRIMITIVE, TEXEL0, LOD_FRACTION, TEXEL0, PRIMITIVE, TEXEL0, LOD_FRACTION, TEXEL0 -#define G_CC_TEMPLERP TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0, TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0 - -/* typical CC cycle 1 modes, usually followed by other cycle 2 modes */ -#define G_CC_TRILERP TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0 -#define G_CC_INTERFERENCE TEXEL0, 0, TEXEL1, 0, TEXEL0, 0, TEXEL1, 0 - -/* - * One-cycle color convert operation - */ -#define G_CC_1CYUV2RGB TEXEL0, K4, K5, TEXEL0, 0, 0, 0, SHADE - -/* - * NOTE: YUV2RGB expects TF step1 color conversion to occur in 2nd clock. - * Therefore, CC looks for step1 results in TEXEL1 - */ -#define G_CC_YUV2RGB TEXEL1, K4, K5, TEXEL1, 0, 0, 0, 0 - -/* typical CC cycle 2 modes */ -#define G_CC_PASS2 0, 0, 0, COMBINED, 0, 0, 0, COMBINED -#define G_CC_MODULATEI2 COMBINED, 0, SHADE, 0, 0, 0, 0, SHADE -#define G_CC_MODULATEIA2 COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0 -#define G_CC_MODULATERGB2 G_CC_MODULATEI2 -#define G_CC_MODULATERGBA2 G_CC_MODULATEIA2 -#define G_CC_MODULATEI_PRIM2 COMBINED, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE -#define G_CC_MODULATEIA_PRIM2 COMBINED, 0, PRIMITIVE, 0, COMBINED, 0, PRIMITIVE, 0 -#define G_CC_MODULATERGB_PRIM2 G_CC_MODULATEI_PRIM2 -#define G_CC_MODULATERGBA_PRIM2 G_CC_MODULATEIA_PRIM2 -#define G_CC_DECALRGB2 0, 0, 0, COMBINED, 0, 0, 0, SHADE -/* - * ? -#define G_CC_DECALRGBA2 COMBINED, SHADE, COMBINED_ALPHA, SHADE, 0, 0, 0, SHADE -*/ -#define G_CC_BLENDI2 ENVIRONMENT, SHADE, COMBINED, SHADE, 0, 0, 0, SHADE -#define G_CC_BLENDIA2 ENVIRONMENT, SHADE, COMBINED, SHADE, COMBINED, 0, SHADE, 0 -#define G_CC_CHROMA_KEY2 TEXEL0, CENTER, SCALE, 0, 0, 0, 0, 0 -#define G_CC_HILITERGB2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, SHADE -#define G_CC_HILITERGBA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, ENVIRONMENT, COMBINED, TEXEL0, COMBINED -#define G_CC_HILITERGBDECALA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, TEXEL0 -#define G_CC_HILITERGBPASSA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, COMBINED - -/* - * G_SETOTHERMODE_L sft: shift count - */ -#define G_MDSFT_ALPHACOMPARE 0 -#define G_MDSFT_ZSRCSEL 2 -#define G_MDSFT_RENDERMODE 3 -#define G_MDSFT_BLENDER 16 - -/* - * G_SETOTHERMODE_H sft: shift count - */ -#define G_MDSFT_BLENDMASK 0 /* unsupported */ -#define G_MDSFT_ALPHADITHER 4 -#define G_MDSFT_RGBDITHER 6 - -#define G_MDSFT_COMBKEY 8 -#define G_MDSFT_TEXTCONV 9 -#define G_MDSFT_TEXTFILT 12 -#define G_MDSFT_TEXTLUT 14 -#define G_MDSFT_TEXTLOD 16 -#define G_MDSFT_TEXTDETAIL 17 -#define G_MDSFT_TEXTPERSP 19 -#define G_MDSFT_CYCLETYPE 20 -#define G_MDSFT_COLORDITHER 22 /* unsupported in HW 2.0 */ -#define G_MDSFT_PIPELINE 23 - -/* G_SETOTHERMODE_H gPipelineMode */ -#define G_PM_1PRIMITIVE (1 << G_MDSFT_PIPELINE) -#define G_PM_NPRIMITIVE (0 << G_MDSFT_PIPELINE) - -/* G_SETOTHERMODE_H gSetCycleType */ -#define G_CYC_1CYCLE (0 << G_MDSFT_CYCLETYPE) -#define G_CYC_2CYCLE (1 << G_MDSFT_CYCLETYPE) -#define G_CYC_COPY (2 << G_MDSFT_CYCLETYPE) -#define G_CYC_FILL (3 << G_MDSFT_CYCLETYPE) - -/* G_SETOTHERMODE_H gSetTexturePersp */ -#define G_TP_NONE (0 << G_MDSFT_TEXTPERSP) -#define G_TP_PERSP (1 << G_MDSFT_TEXTPERSP) - -/* G_SETOTHERMODE_H gSetTextureDetail */ -#define G_TD_CLAMP (0 << G_MDSFT_TEXTDETAIL) -#define G_TD_SHARPEN (1 << G_MDSFT_TEXTDETAIL) -#define G_TD_DETAIL (2 << G_MDSFT_TEXTDETAIL) - -/* G_SETOTHERMODE_H gSetTextureLOD */ -#define G_TL_TILE (0 << G_MDSFT_TEXTLOD) -#define G_TL_LOD (1 << G_MDSFT_TEXTLOD) - -/* G_SETOTHERMODE_H gSetTextureLUT */ -#define G_TT_NONE (0 << G_MDSFT_TEXTLUT) -#define G_TT_RGBA16 (2 << G_MDSFT_TEXTLUT) -#define G_TT_IA16 (3 << G_MDSFT_TEXTLUT) - -/* G_SETOTHERMODE_H gSetTextureFilter */ -#define G_TF_POINT (0 << G_MDSFT_TEXTFILT) -#define G_TF_AVERAGE (3 << G_MDSFT_TEXTFILT) -#define G_TF_BILERP (2 << G_MDSFT_TEXTFILT) - -/* G_SETOTHERMODE_H gSetTextureConvert */ -#define G_TC_CONV (0 << G_MDSFT_TEXTCONV) -#define G_TC_FILTCONV (5 << G_MDSFT_TEXTCONV) -#define G_TC_FILT (6 << G_MDSFT_TEXTCONV) - -/* G_SETOTHERMODE_H gSetCombineKey */ -#define G_CK_NONE (0 << G_MDSFT_COMBKEY) -#define G_CK_KEY (1 << G_MDSFT_COMBKEY) - -/* G_SETOTHERMODE_H gSetColorDither */ -#define G_CD_MAGICSQ (0 << G_MDSFT_RGBDITHER) -#define G_CD_BAYER (1 << G_MDSFT_RGBDITHER) -#define G_CD_NOISE (2 << G_MDSFT_RGBDITHER) - -#ifndef _HW_VERSION_1 -#define G_CD_DISABLE (3 << G_MDSFT_RGBDITHER) -#define G_CD_ENABLE G_CD_NOISE /* HW 1.0 compatibility mode */ -#else -#define G_CD_ENABLE (1 << G_MDSFT_COLORDITHER) -#define G_CD_DISABLE (0 << G_MDSFT_COLORDITHER) -#endif - -/* G_SETOTHERMODE_H gSetAlphaDither */ -#define G_AD_PATTERN (0 << G_MDSFT_ALPHADITHER) -#define G_AD_NOTPATTERN (1 << G_MDSFT_ALPHADITHER) -#define G_AD_NOISE (2 << G_MDSFT_ALPHADITHER) -#define G_AD_DISABLE (3 << G_MDSFT_ALPHADITHER) - -/* G_SETOTHERMODE_L gSetAlphaCompare */ -#define G_AC_NONE (0 << G_MDSFT_ALPHACOMPARE) -#define G_AC_THRESHOLD (1 << G_MDSFT_ALPHACOMPARE) -#define G_AC_DITHER (3 << G_MDSFT_ALPHACOMPARE) - -/* G_SETOTHERMODE_L gSetDepthSource */ -#define G_ZS_PIXEL (0 << G_MDSFT_ZSRCSEL) -#define G_ZS_PRIM (1 << G_MDSFT_ZSRCSEL) - -/* G_SETOTHERMODE_L gSetRenderMode */ -#define AA_EN 0x8 -#define Z_CMP 0x10 -#define Z_UPD 0x20 -#define IM_RD 0x40 -#define CLR_ON_CVG 0x80 -#define CVG_DST_CLAMP 0 -#define CVG_DST_WRAP 0x100 -#define CVG_DST_FULL 0x200 -#define CVG_DST_SAVE 0x300 -#define ZMODE_OPA 0 -#define ZMODE_INTER 0x400 -#define ZMODE_XLU 0x800 -#define ZMODE_DEC 0xc00 -#define CVG_X_ALPHA 0x1000 -#define ALPHA_CVG_SEL 0x2000 -#define FORCE_BL 0x4000 -#define TEX_EDGE 0x0000 /* used to be 0x8000 */ - -#define G_BL_CLR_IN 0 -#define G_BL_CLR_MEM 1 -#define G_BL_CLR_BL 2 -#define G_BL_CLR_FOG 3 -#define G_BL_1MA 0 -#define G_BL_A_MEM 1 -#define G_BL_A_IN 0 -#define G_BL_A_FOG 1 -#define G_BL_A_SHADE 2 -#define G_BL_1 2 -#define G_BL_0 3 - -#ifdef DISABLE_AA -#define AA_DEF -#define RD_DEF -#else -#define AA_DEF AA_EN | -#define RD_DEF IM_RD | -#endif - -#define GBL_c1(m1a, m1b, m2a, m2b) \ - (m1a) << 30 | (m1b) << 26 | (m2a) << 22 | (m2b) << 18 -#define GBL_c2(m1a, m1b, m2a, m2b) \ - (m1a) << 28 | (m1b) << 24 | (m2a) << 20 | (m2b) << 16 - -#define RM_AA_ZB_OPA_SURF(clk) \ - AA_DEF Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ - ZMODE_OPA | ALPHA_CVG_SEL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_RA_ZB_OPA_SURF(clk) \ - AA_DEF Z_CMP | Z_UPD | CVG_DST_CLAMP | \ - ZMODE_OPA | ALPHA_CVG_SEL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_AA_ZB_XLU_SURF(clk) \ - AA_DEF Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ - FORCE_BL | ZMODE_XLU | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_ZB_OPA_DECAL(clk) \ - AA_DEF Z_CMP | RD_DEF CVG_DST_WRAP | ALPHA_CVG_SEL | \ - ZMODE_DEC | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_RA_ZB_OPA_DECAL(clk) \ - AA_DEF Z_CMP | CVG_DST_WRAP | ALPHA_CVG_SEL | \ - ZMODE_DEC | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_AA_ZB_XLU_DECAL(clk) \ - AA_DEF Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ - FORCE_BL | ZMODE_DEC | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_ZB_OPA_INTER(clk) \ - AA_DEF Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ - ALPHA_CVG_SEL | ZMODE_INTER | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_RA_ZB_OPA_INTER(clk) \ - AA_DEF Z_CMP | Z_UPD | CVG_DST_CLAMP | \ - ALPHA_CVG_SEL | ZMODE_INTER | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_AA_ZB_XLU_INTER(clk) \ - AA_DEF Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ - FORCE_BL | ZMODE_INTER | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_ZB_XLU_LINE(clk) \ - AA_DEF Z_CMP | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | \ - ALPHA_CVG_SEL | FORCE_BL | ZMODE_XLU | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_ZB_DEC_LINE(clk) \ - AA_DEF Z_CMP | IM_RD | CVG_DST_SAVE | CVG_X_ALPHA | \ - ALPHA_CVG_SEL | FORCE_BL | ZMODE_DEC | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_ZB_TEX_EDGE(clk) \ - AA_EN | Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ - CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_AA_ZB_TEX_INTER(clk) \ - AA_DEF Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ - CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_INTER | TEX_EDGE | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_AA_ZB_SUB_SURF(clk) \ - AA_DEF Z_CMP | Z_UPD | IM_RD | CVG_DST_FULL | \ - ZMODE_OPA | ALPHA_CVG_SEL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_AA_ZB_PCL_SURF(clk) \ - AA_DEF Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ - ZMODE_OPA | G_AC_DITHER | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_ZB_OPA_TERR(clk) \ - AA_DEF Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ - ZMODE_OPA | ALPHA_CVG_SEL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_ZB_TEX_TERR(clk) \ - AA_DEF Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ - CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_ZB_SUB_TERR(clk) \ - AA_DEF Z_CMP | Z_UPD | IM_RD | CVG_DST_FULL | \ - ZMODE_OPA | ALPHA_CVG_SEL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - - -#define RM_AA_OPA_SURF(clk) \ - AA_DEF RD_DEF CVG_DST_CLAMP | \ - ZMODE_OPA | ALPHA_CVG_SEL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_RA_OPA_SURF(clk) \ - AA_DEF CVG_DST_CLAMP | \ - ZMODE_OPA | ALPHA_CVG_SEL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_AA_XLU_SURF(clk) \ - AA_DEF IM_RD | CVG_DST_WRAP | CLR_ON_CVG | FORCE_BL | \ - ZMODE_OPA | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_XLU_LINE(clk) \ - AA_DEF IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | \ - ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_DEC_LINE(clk) \ - AA_DEF IM_RD | CVG_DST_FULL | CVG_X_ALPHA | \ - ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_TEX_EDGE(clk) \ - AA_EN | RD_DEF CVG_DST_CLAMP | \ - CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_AA_SUB_SURF(clk) \ - AA_DEF IM_RD | CVG_DST_FULL | \ - ZMODE_OPA | ALPHA_CVG_SEL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_AA_PCL_SURF(clk) \ - AA_DEF IM_RD | CVG_DST_CLAMP | \ - ZMODE_OPA | G_AC_DITHER | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_OPA_TERR(clk) \ - AA_DEF RD_DEF CVG_DST_CLAMP | \ - ZMODE_OPA | ALPHA_CVG_SEL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_TEX_TERR(clk) \ - AA_DEF RD_DEF CVG_DST_CLAMP | \ - CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_AA_SUB_TERR(clk) \ - AA_DEF IM_RD | CVG_DST_FULL | \ - ZMODE_OPA | ALPHA_CVG_SEL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - - -#define RM_ZB_OPA_SURF(clk) \ - Z_CMP | Z_UPD | CVG_DST_FULL | ALPHA_CVG_SEL | \ - ZMODE_OPA | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_ZB_XLU_SURF(clk) \ - Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_XLU | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_ZB_OPA_DECAL(clk) \ - Z_CMP | CVG_DST_FULL | ALPHA_CVG_SEL | ZMODE_DEC | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) - -#define RM_ZB_XLU_DECAL(clk) \ - Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_DEC | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_ZB_CLD_SURF(clk) \ - Z_CMP | IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_XLU | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_ZB_OVL_SURF(clk) \ - Z_CMP | IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_DEC | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_ZB_PCL_SURF(clk) \ - Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | \ - G_AC_DITHER | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) - - -#define RM_OPA_SURF(clk) \ - CVG_DST_CLAMP | FORCE_BL | ZMODE_OPA | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) - -#define RM_XLU_SURF(clk) \ - IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_OPA | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_TEX_EDGE(clk) \ - CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | FORCE_BL |\ - ZMODE_OPA | TEX_EDGE | AA_EN | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) - -#define RM_CLD_SURF(clk) \ - IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) - -#define RM_PCL_SURF(clk) \ - CVG_DST_FULL | FORCE_BL | ZMODE_OPA | \ - G_AC_DITHER | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) - -#define RM_ADD(clk) \ - IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_A_FOG, G_BL_CLR_MEM, G_BL_1) - -#define RM_NOOP(clk) \ - GBL_c##clk(0, 0, 0, 0) - -#define RM_VISCVG(clk) \ - IM_RD | FORCE_BL | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_BL, G_BL_A_MEM) - -/* for rendering to an 8-bit framebuffer */ -#define RM_OPA_CI(clk) \ - CVG_DST_CLAMP | ZMODE_OPA | \ - GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) - -/* Custom version of RM_AA_ZB_XLU_SURF with Z_UPD */ -#define RM_CUSTOM_AA_ZB_XLU_SURF(clk) \ - RM_AA_ZB_XLU_SURF(clk) | Z_UPD - - -#ifdef DISABLE_AA - -#define G_RM_AA_ZB_OPA_SURF RM_ZB_OPA_SURF(1) -#define G_RM_AA_ZB_OPA_SURF2 RM_ZB_OPA_SURF(2) -#define G_RM_AA_ZB_XLU_SURF RM_ZB_XLU_SURF(1) -#define G_RM_AA_ZB_XLU_SURF2 RM_ZB_XLU_SURF(2) -#define G_RM_AA_ZB_OPA_DECAL RM_ZB_OPA_DECAL(1) -#define G_RM_AA_ZB_OPA_DECAL2 RM_ZB_OPA_DECAL(2) -#define G_RM_AA_ZB_XLU_DECAL RM_ZB_XLU_DECAL(1) -#define G_RM_AA_ZB_XLU_DECAL2 RM_ZB_XLU_DECAL(2) -#define G_RM_AA_ZB_OPA_INTER RM_AA_ZB_OPA_INTER(1) -#define G_RM_AA_ZB_OPA_INTER2 RM_AA_ZB_OPA_INTER(2) -#define G_RM_AA_ZB_XLU_INTER RM_AA_ZB_XLU_INTER(1) -#define G_RM_AA_ZB_XLU_INTER2 RM_AA_ZB_XLU_INTER(2) -#define G_RM_AA_ZB_XLU_LINE RM_AA_ZB_XLU_LINE(1) -#define G_RM_AA_ZB_XLU_LINE2 RM_AA_ZB_XLU_LINE(2) -#define G_RM_AA_ZB_DEC_LINE RM_AA_ZB_DEC_LINE(1) -#define G_RM_AA_ZB_DEC_LINE2 RM_AA_ZB_DEC_LINE(2) -#define G_RM_AA_ZB_TEX_EDGE RM_AA_ZB_TEX_EDGE(1) -#define G_RM_AA_ZB_TEX_EDGE2 RM_AA_ZB_TEX_EDGE(2) -#define G_RM_AA_ZB_TEX_INTER RM_AA_ZB_TEX_INTER(1) -#define G_RM_AA_ZB_TEX_INTER2 RM_AA_ZB_TEX_INTER(2) -#define G_RM_AA_ZB_SUB_SURF RM_AA_ZB_SUB_SURF(1) -#define G_RM_AA_ZB_SUB_SURF2 RM_AA_ZB_SUB_SURF(2) -#define G_RM_AA_ZB_PCL_SURF RM_ZB_PCL_SURF(1) -#define G_RM_AA_ZB_PCL_SURF2 RM_ZB_PCL_SURF(2) -#define G_RM_AA_ZB_OPA_TERR RM_AA_ZB_OPA_TERR(1) -#define G_RM_AA_ZB_OPA_TERR2 RM_AA_ZB_OPA_TERR(2) -#define G_RM_AA_ZB_TEX_TERR RM_AA_ZB_TEX_TERR(1) -#define G_RM_AA_ZB_TEX_TERR2 RM_AA_ZB_TEX_TERR(2) -#define G_RM_AA_ZB_SUB_TERR RM_AA_ZB_SUB_TERR(1) -#define G_RM_AA_ZB_SUB_TERR2 RM_AA_ZB_SUB_TERR(2) - -#define G_RM_RA_ZB_OPA_SURF RM_RA_ZB_OPA_SURF(1) -#define G_RM_RA_ZB_OPA_SURF2 RM_RA_ZB_OPA_SURF(2) -#define G_RM_RA_ZB_OPA_DECAL RM_RA_ZB_OPA_DECAL(1) -#define G_RM_RA_ZB_OPA_DECAL2 RM_RA_ZB_OPA_DECAL(2) -#define G_RM_RA_ZB_OPA_INTER RM_RA_ZB_OPA_INTER(1) -#define G_RM_RA_ZB_OPA_INTER2 RM_RA_ZB_OPA_INTER(2) - -#define G_RM_AA_OPA_SURF RM_OPA_SURF(1) -#define G_RM_AA_OPA_SURF2 RM_OPA_SURF(2) -#define G_RM_AA_XLU_SURF RM_XLU_SURF(1) -#define G_RM_AA_XLU_SURF2 RM_XLU_SURF(2) -#define G_RM_AA_XLU_LINE RM_AA_XLU_LINE(1) -#define G_RM_AA_XLU_LINE2 RM_AA_XLU_LINE(2) -#define G_RM_AA_DEC_LINE RM_AA_DEC_LINE(1) -#define G_RM_AA_DEC_LINE2 RM_AA_DEC_LINE(2) -#define G_RM_AA_TEX_EDGE RM_TEX_EDGE(1) -#define G_RM_AA_TEX_EDGE2 RM_TEX_EDGE(2) -#define G_RM_AA_SUB_SURF RM_AA_SUB_SURF(1) -#define G_RM_AA_SUB_SURF2 RM_AA_SUB_SURF(2) -#define G_RM_AA_PCL_SURF RM_PCL_SURF(1) -#define G_RM_AA_PCL_SURF2 RM_PCL_SURF(2) -#define G_RM_AA_OPA_TERR RM_AA_OPA_TERR(1) -#define G_RM_AA_OPA_TERR2 RM_AA_OPA_TERR(2) -#define G_RM_AA_TEX_TERR RM_AA_TEX_TERR(1) -#define G_RM_AA_TEX_TERR2 RM_AA_TEX_TERR(2) -#define G_RM_AA_SUB_TERR RM_AA_SUB_TERR(1) -#define G_RM_AA_SUB_TERR2 RM_AA_SUB_TERR(2) - -#else - -#define G_RM_AA_ZB_OPA_SURF RM_AA_ZB_OPA_SURF(1) -#define G_RM_AA_ZB_OPA_SURF2 RM_AA_ZB_OPA_SURF(2) -#define G_RM_AA_ZB_XLU_SURF RM_AA_ZB_XLU_SURF(1) -#define G_RM_AA_ZB_XLU_SURF2 RM_AA_ZB_XLU_SURF(2) -#define G_RM_AA_ZB_OPA_DECAL RM_AA_ZB_OPA_DECAL(1) -#define G_RM_AA_ZB_OPA_DECAL2 RM_AA_ZB_OPA_DECAL(2) -#define G_RM_AA_ZB_XLU_DECAL RM_AA_ZB_XLU_DECAL(1) -#define G_RM_AA_ZB_XLU_DECAL2 RM_AA_ZB_XLU_DECAL(2) -#define G_RM_AA_ZB_OPA_INTER RM_AA_ZB_OPA_INTER(1) -#define G_RM_AA_ZB_OPA_INTER2 RM_AA_ZB_OPA_INTER(2) -#define G_RM_AA_ZB_XLU_INTER RM_AA_ZB_XLU_INTER(1) -#define G_RM_AA_ZB_XLU_INTER2 RM_AA_ZB_XLU_INTER(2) -#define G_RM_AA_ZB_XLU_LINE RM_AA_ZB_XLU_LINE(1) -#define G_RM_AA_ZB_XLU_LINE2 RM_AA_ZB_XLU_LINE(2) -#define G_RM_AA_ZB_DEC_LINE RM_AA_ZB_DEC_LINE(1) -#define G_RM_AA_ZB_DEC_LINE2 RM_AA_ZB_DEC_LINE(2) -#define G_RM_AA_ZB_TEX_EDGE RM_AA_ZB_TEX_EDGE(1) -#define G_RM_AA_ZB_TEX_EDGE2 RM_AA_ZB_TEX_EDGE(2) -#define G_RM_AA_ZB_TEX_INTER RM_AA_ZB_TEX_INTER(1) -#define G_RM_AA_ZB_TEX_INTER2 RM_AA_ZB_TEX_INTER(2) -#define G_RM_AA_ZB_SUB_SURF RM_AA_ZB_SUB_SURF(1) -#define G_RM_AA_ZB_SUB_SURF2 RM_AA_ZB_SUB_SURF(2) -#define G_RM_AA_ZB_PCL_SURF RM_AA_ZB_PCL_SURF(1) -#define G_RM_AA_ZB_PCL_SURF2 RM_AA_ZB_PCL_SURF(2) -#define G_RM_AA_ZB_OPA_TERR RM_AA_ZB_OPA_TERR(1) -#define G_RM_AA_ZB_OPA_TERR2 RM_AA_ZB_OPA_TERR(2) -#define G_RM_AA_ZB_TEX_TERR RM_AA_ZB_TEX_TERR(1) -#define G_RM_AA_ZB_TEX_TERR2 RM_AA_ZB_TEX_TERR(2) -#define G_RM_AA_ZB_SUB_TERR RM_AA_ZB_SUB_TERR(1) -#define G_RM_AA_ZB_SUB_TERR2 RM_AA_ZB_SUB_TERR(2) - -#define G_RM_RA_ZB_OPA_SURF RM_RA_ZB_OPA_SURF(1) -#define G_RM_RA_ZB_OPA_SURF2 RM_RA_ZB_OPA_SURF(2) -#define G_RM_RA_ZB_OPA_DECAL RM_RA_ZB_OPA_DECAL(1) -#define G_RM_RA_ZB_OPA_DECAL2 RM_RA_ZB_OPA_DECAL(2) -#define G_RM_RA_ZB_OPA_INTER RM_RA_ZB_OPA_INTER(1) -#define G_RM_RA_ZB_OPA_INTER2 RM_RA_ZB_OPA_INTER(2) - -#define G_RM_AA_OPA_SURF RM_AA_OPA_SURF(1) -#define G_RM_AA_OPA_SURF2 RM_AA_OPA_SURF(2) -#define G_RM_AA_XLU_SURF RM_AA_XLU_SURF(1) -#define G_RM_AA_XLU_SURF2 RM_AA_XLU_SURF(2) -#define G_RM_AA_XLU_LINE RM_AA_XLU_LINE(1) -#define G_RM_AA_XLU_LINE2 RM_AA_XLU_LINE(2) -#define G_RM_AA_DEC_LINE RM_AA_DEC_LINE(1) -#define G_RM_AA_DEC_LINE2 RM_AA_DEC_LINE(2) -#define G_RM_AA_TEX_EDGE RM_AA_TEX_EDGE(1) -#define G_RM_AA_TEX_EDGE2 RM_AA_TEX_EDGE(2) -#define G_RM_AA_SUB_SURF RM_AA_SUB_SURF(1) -#define G_RM_AA_SUB_SURF2 RM_AA_SUB_SURF(2) -#define G_RM_AA_PCL_SURF RM_AA_PCL_SURF(1) -#define G_RM_AA_PCL_SURF2 RM_AA_PCL_SURF(2) -#define G_RM_AA_OPA_TERR RM_AA_OPA_TERR(1) -#define G_RM_AA_OPA_TERR2 RM_AA_OPA_TERR(2) -#define G_RM_AA_TEX_TERR RM_AA_TEX_TERR(1) -#define G_RM_AA_TEX_TERR2 RM_AA_TEX_TERR(2) -#define G_RM_AA_SUB_TERR RM_AA_SUB_TERR(1) -#define G_RM_AA_SUB_TERR2 RM_AA_SUB_TERR(2) - -#endif - -#define G_RM_RA_OPA_SURF RM_RA_OPA_SURF(1) -#define G_RM_RA_OPA_SURF2 RM_RA_OPA_SURF(2) - -#define G_RM_ZB_OPA_SURF RM_ZB_OPA_SURF(1) -#define G_RM_ZB_OPA_SURF2 RM_ZB_OPA_SURF(2) -#define G_RM_ZB_XLU_SURF RM_ZB_XLU_SURF(1) -#define G_RM_ZB_XLU_SURF2 RM_ZB_XLU_SURF(2) -#define G_RM_ZB_OPA_DECAL RM_ZB_OPA_DECAL(1) -#define G_RM_ZB_OPA_DECAL2 RM_ZB_OPA_DECAL(2) -#define G_RM_ZB_XLU_DECAL RM_ZB_XLU_DECAL(1) -#define G_RM_ZB_XLU_DECAL2 RM_ZB_XLU_DECAL(2) -#define G_RM_ZB_CLD_SURF RM_ZB_CLD_SURF(1) -#define G_RM_ZB_CLD_SURF2 RM_ZB_CLD_SURF(2) -#define G_RM_ZB_OVL_SURF RM_ZB_OVL_SURF(1) -#define G_RM_ZB_OVL_SURF2 RM_ZB_OVL_SURF(2) -#define G_RM_ZB_PCL_SURF RM_ZB_PCL_SURF(1) -#define G_RM_ZB_PCL_SURF2 RM_ZB_PCL_SURF(2) - -#define G_RM_OPA_SURF RM_OPA_SURF(1) -#define G_RM_OPA_SURF2 RM_OPA_SURF(2) -#define G_RM_XLU_SURF RM_XLU_SURF(1) -#define G_RM_XLU_SURF2 RM_XLU_SURF(2) -#define G_RM_CLD_SURF RM_CLD_SURF(1) -#define G_RM_CLD_SURF2 RM_CLD_SURF(2) -#define G_RM_TEX_EDGE RM_TEX_EDGE(1) -#define G_RM_TEX_EDGE2 RM_TEX_EDGE(2) -#define G_RM_PCL_SURF RM_PCL_SURF(1) -#define G_RM_PCL_SURF2 RM_PCL_SURF(2) -#define G_RM_ADD RM_ADD(1) -#define G_RM_ADD2 RM_ADD(2) -#define G_RM_NOOP RM_NOOP(1) -#define G_RM_NOOP2 RM_NOOP(2) -#define G_RM_VISCVG RM_VISCVG(1) -#define G_RM_VISCVG2 RM_VISCVG(2) -#define G_RM_OPA_CI RM_OPA_CI(1) -#define G_RM_OPA_CI2 RM_OPA_CI(2) - -#define G_RM_CUSTOM_AA_ZB_XLU_SURF RM_CUSTOM_AA_ZB_XLU_SURF(1) -#define G_RM_CUSTOM_AA_ZB_XLU_SURF2 RM_CUSTOM_AA_ZB_XLU_SURF(2) - - -#define G_RM_FOG_SHADE_A GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA) -#define G_RM_FOG_PRIM_A GBL_c1(G_BL_CLR_FOG, G_BL_A_FOG, G_BL_CLR_IN, G_BL_1MA) -#define G_RM_PASS GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) - -#define G_RM_ZB_1C_FOG_SHADE_A \ - Z_CMP | Z_UPD | CVG_DST_FULL | ALPHA_CVG_SEL | ZMODE_OPA | \ - GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA) - -#define G_RM_ZB_1C_FOG_SHADE_A2 \ - CVG_DST_FULL | FORCE_BL | ZMODE_OPA | \ - GBL_c2(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA) - -/* - * G_SETCONVERT: K0-5 - */ -#define G_CV_K0 175 -#define G_CV_K1 -43 -#define G_CV_K2 -89 -#define G_CV_K3 222 -#define G_CV_K4 114 -#define G_CV_K5 42 - -/* - * G_SETSCISSOR: interlace mode - */ -#define G_SC_NON_INTERLACE 0 -#define G_SC_ODD_INTERLACE 3 -#define G_SC_EVEN_INTERLACE 2 - -/* flags to inhibit pushing of the display list (on branch) */ -#define G_DL_PUSH 0x00 -#define G_DL_NOPUSH 0x01 - -/* - * BEGIN C-specific section: (typedef's) - */ -#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) - -/* - * Data Structures - * - * NOTE: - * The DMA transfer hardware requires 64-bit aligned, 64-bit multiple- - * sized transfers. This important hardware optimization is unfortunately - * reflected in the programming interface, with some structures - * padded and alignment enforced. - * - * Since structures are aligned to the boundary of the "worst-case" - * element, we can't depend on the C compiler to align things - * properly. - * - * 64-bit structure alignment is enforced by wrapping structures with - * unions that contain a dummy "long long int". Why this works is - * explained in the ANSI C Spec, or on page 186 of the second edition - * of K&R, "The C Programming Language". - * - * The price we pay for this is a little awkwardness referencing the - * structures through the union. There is no memory penalty, since - * all the structures are at least 64-bits the dummy alignment field - * does not increase the size of the union. - * - * Static initialization of these union structures works because - * the ANSI C spec states that static initialization for unions - * works by using the first union element. We put the dummy alignment - * field last for this reason. - * - * (it's possible a newer 64-bit compiler from MIPS might make this - * easier with a flag, but we can't wait for it...) - * - */ - -/* - * Vertex (set up for use with colors) - */ -typedef struct { -#ifndef GBI_FLOATS - short ob[3]; /* x, y, z */ -#else - float ob[3]; /* x, y, z */ -#endif - unsigned short flag; - short tc[2]; /* texture coord */ - unsigned char cn[4]; /* color & alpha */ -} Vtx_t; - -/* - * Vertex (set up for use with normals) - */ -typedef struct { -#ifndef GBI_FLOATS - short ob[3]; /* x, y, z */ -#else - float ob[3]; /* x, y, z */ -#endif - unsigned short flag; - short tc[2]; /* texture coord */ - signed char n[3]; /* normal */ - unsigned char a; /* alpha */ -} Vtx_tn; - -typedef union { - Vtx_t v; /* Use this one for colors */ - Vtx_tn n; /* Use this one for normals */ - long long int force_structure_alignment; -} Vtx; - +#ifndef GBI_CONTAINER +#define GBI_CONTAINER /* * Sprite structure */ @@ -1265,3637 +28,9 @@ typedef union { long long int force_structure_allignment[3]; } uSprite; -/* - * Triangle face - */ -typedef struct { - unsigned char flag; - unsigned char v[3]; -} Tri; - -#ifndef GBI_FLOATS -/* - * 4x4 matrix, fixed point s15.16 format. - * First 8 words are integer portion of the 4x4 matrix - * Last 8 words are the fraction portion of the 4x4 matrix - */ -typedef s32 Mtx_t[4][4]; - -typedef union { - Mtx_t m; - long long int force_structure_alignment; -} Mtx; +#ifdef F3DEX_GBI_3 + #include "gbi_f3dex3.h" #else -typedef struct { - float m[4][4]; -} Mtx; + #include "gbi_std.h" // All other microcodes #endif - -/* - * Viewport - */ - -/* - * - * This magic value is the maximum INTEGER z-range of the hardware - * (there are also 16-bits of fraction, which are introduced during - * any transformations). This is not just a good idea, it's the law. - * Feeding the hardware eventual z-coordinates (after any transforms - * or scaling) bigger than this, will not work. - * - * This number is DIFFERENT than G_MAXFBZ, which is the maximum value - * you want to use to initialize the z-buffer. - * - * The reason these are different is mildly interesting, but too long - * to explain here. It is basically the result of optimizations in the - * hardware. A more generic API might hide this detail from the users, - * but we don't have the ucode to do that... - * - */ -#define G_MAXZ 0x03ff /* 10 bits of integer screen-Z precision */ - -/* - * The viewport structure elements have 2 bits of fraction, necessary - * to accomodate the sub-pixel positioning scaling for the hardware. - * This can also be exploited to handle odd-sized viewports. - * - * Accounting for these fractional bits, using the default projection - * and viewing matrices, the viewport structure is initialized thusly: - * - * (SCREEN_WD/2)*4, (SCREEN_HT/2)*4, G_MAXZ, 0, - * (SCREEN_WD/2)*4, (SCREEN_HT/2)*4, 0, 0, - */ -typedef struct { - short vscale[4]; /* scale, 2 bits fraction */ - short vtrans[4]; /* translate, 2 bits fraction */ - /* both the above arrays are padded to 64-bit boundary */ -} Vp_t; - -typedef union { - Vp_t vp; - long long int force_structure_alignment; -} Vp; - -/* - * MOVEMEM indices - * - * Each of these indexes an entry in a dmem table - * which points to a 1-4 word block of dmem in - * which to store a 1-4 word DMA. - * - */ -#ifdef F3DEX_GBI_2 -/* 0,4 are reserved by G_MTX */ -# define G_MV_MMTX 2 -# define G_MV_PMTX 6 -# define G_MV_VIEWPORT 8 -# define G_MV_LIGHT 10 -# define G_MV_POINT 12 -# define G_MV_MATRIX 14 /* NOTE: this is in moveword table */ -# define G_MVO_LOOKATX (0*24) -# define G_MVO_LOOKATY (1*24) -# define G_MVO_L0 (2*24) -# define G_MVO_L1 (3*24) -# define G_MVO_L2 (4*24) -# define G_MVO_L3 (5*24) -# define G_MVO_L4 (6*24) -# define G_MVO_L5 (7*24) -# define G_MVO_L6 (8*24) -# define G_MVO_L7 (9*24) -#else /* F3DEX_GBI_2 */ -# define G_MV_VIEWPORT 0x80 -# define G_MV_LOOKATY 0x82 -# define G_MV_LOOKATX 0x84 -# define G_MV_L0 0x86 -# define G_MV_L1 0x88 -# define G_MV_L2 0x8a -# define G_MV_L3 0x8c -# define G_MV_L4 0x8e -# define G_MV_L5 0x90 -# define G_MV_L6 0x92 -# define G_MV_L7 0x94 -# define G_MV_TXTATT 0x96 -# define G_MV_MATRIX_1 0x9e /* NOTE: this is in moveword table */ -# define G_MV_MATRIX_2 0x98 -# define G_MV_MATRIX_3 0x9a -# define G_MV_MATRIX_4 0x9c -#endif /* F3DEX_GBI_2 */ - -/* - * MOVEWORD indices - * - * Each of these indexes an entry in a dmem table - * which points to a word in dmem in dmem where - * an immediate word will be stored. - * - */ -#define G_MW_MATRIX 0x00 /* NOTE: also used by movemem */ -#define G_MW_NUMLIGHT 0x02 -#define G_MW_CLIP 0x04 -#define G_MW_SEGMENT 0x06 -#define G_MW_FOG 0x08 -#define G_MW_LIGHTCOL 0x0a -#ifdef F3DEX_GBI_2 -# define G_MW_FORCEMTX 0x0c -#else /* F3DEX_GBI_2 */ -# define G_MW_POINTS 0x0c -#endif /* F3DEX_GBI_2 */ -#define G_MW_PERSPNORM 0x0e - -/* - * These are offsets from the address in the dmem table - */ -#define G_MWO_NUMLIGHT 0x00 -#define G_MWO_CLIP_RNX 0x04 -#define G_MWO_CLIP_RNY 0x0c -#define G_MWO_CLIP_RPX 0x14 -#define G_MWO_CLIP_RPY 0x1c -#define G_MWO_SEGMENT_0 0x00 -#define G_MWO_SEGMENT_1 0x01 -#define G_MWO_SEGMENT_2 0x02 -#define G_MWO_SEGMENT_3 0x03 -#define G_MWO_SEGMENT_4 0x04 -#define G_MWO_SEGMENT_5 0x05 -#define G_MWO_SEGMENT_6 0x06 -#define G_MWO_SEGMENT_7 0x07 -#define G_MWO_SEGMENT_8 0x08 -#define G_MWO_SEGMENT_9 0x09 -#define G_MWO_SEGMENT_A 0x0a -#define G_MWO_SEGMENT_B 0x0b -#define G_MWO_SEGMENT_C 0x0c -#define G_MWO_SEGMENT_D 0x0d -#define G_MWO_SEGMENT_E 0x0e -#define G_MWO_SEGMENT_F 0x0f -#define G_MWO_FOG 0x00 -#define G_MWO_aLIGHT_1 0x00 -#define G_MWO_bLIGHT_1 0x04 -#ifdef F3DEX_GBI_2 -#define G_MWO_aLIGHT_2 0x18 -#define G_MWO_bLIGHT_2 0x1c -#define G_MWO_aLIGHT_3 0x30 -#define G_MWO_bLIGHT_3 0x34 -#define G_MWO_aLIGHT_4 0x48 -#define G_MWO_bLIGHT_4 0x4c -#define G_MWO_aLIGHT_5 0x60 -#define G_MWO_bLIGHT_5 0x64 -#define G_MWO_aLIGHT_6 0x78 -#define G_MWO_bLIGHT_6 0x7c -#define G_MWO_aLIGHT_7 0x90 -#define G_MWO_bLIGHT_7 0x94 -#define G_MWO_aLIGHT_8 0xa8 -#define G_MWO_bLIGHT_8 0xac -#else -#define G_MWO_aLIGHT_2 0x20 -#define G_MWO_bLIGHT_2 0x24 -#define G_MWO_aLIGHT_3 0x40 -#define G_MWO_bLIGHT_3 0x44 -#define G_MWO_aLIGHT_4 0x60 -#define G_MWO_bLIGHT_4 0x64 -#define G_MWO_aLIGHT_5 0x80 -#define G_MWO_bLIGHT_5 0x84 -#define G_MWO_aLIGHT_6 0xa0 -#define G_MWO_bLIGHT_6 0xa4 -#define G_MWO_aLIGHT_7 0xc0 -#define G_MWO_bLIGHT_7 0xc4 -#define G_MWO_aLIGHT_8 0xe0 -#define G_MWO_bLIGHT_8 0xe4 -#endif -#define G_MWO_MATRIX_XX_XY_I 0x00 -#define G_MWO_MATRIX_XZ_XW_I 0x04 -#define G_MWO_MATRIX_YX_YY_I 0x08 -#define G_MWO_MATRIX_YZ_YW_I 0x0c -#define G_MWO_MATRIX_ZX_ZY_I 0x10 -#define G_MWO_MATRIX_ZZ_ZW_I 0x14 -#define G_MWO_MATRIX_WX_WY_I 0x18 -#define G_MWO_MATRIX_WZ_WW_I 0x1c -#define G_MWO_MATRIX_XX_XY_F 0x20 -#define G_MWO_MATRIX_XZ_XW_F 0x24 -#define G_MWO_MATRIX_YX_YY_F 0x28 -#define G_MWO_MATRIX_YZ_YW_F 0x2c -#define G_MWO_MATRIX_ZX_ZY_F 0x30 -#define G_MWO_MATRIX_ZZ_ZW_F 0x34 -#define G_MWO_MATRIX_WX_WY_F 0x38 -#define G_MWO_MATRIX_WZ_WW_F 0x3c -#define G_MWO_POINT_RGBA 0x10 -#define G_MWO_POINT_ST 0x14 -#define G_MWO_POINT_XYSCREEN 0x18 -#define G_MWO_POINT_ZSCREEN 0x1c - -/* - * Light structure. - * - * Note: only directional (infinite) lights are currently supported. - * - * Note: the weird order is for the DMEM alignment benefit of - * the microcode. - * - */ - -typedef struct { - unsigned char col[3]; /* diffuse light value (rgba) */ - char pad1; - unsigned char colc[3]; /* copy of diffuse light value (rgba) */ - char pad2; - signed char dir[3]; /* direction of light (normalized) */ - char pad3; -} Light_t; - -typedef struct { - unsigned char col[3]; /* ambient light value (rgba) */ - char pad1; - unsigned char colc[3]; /* copy of ambient light value (rgba) */ - char pad2; -} Ambient_t; - -typedef struct { - int x1,y1,x2,y2; /* texture offsets for highlight 1/2 */ -} Hilite_t; - -typedef union { - Light_t l; - long long int force_structure_alignment[2]; -} Light; - -typedef union { - Ambient_t l; - long long int force_structure_alignment[1]; -} Ambient; - -typedef struct { - Ambient a; - Light l[7]; -} Lightsn; - -typedef struct { - Ambient a; - Light l[1]; -} Lights0; - -typedef struct { - Ambient a; - Light l[1]; -} Lights1; - -typedef struct { - Ambient a; - Light l[2]; -} Lights2; - -typedef struct { - Ambient a; - Light l[3]; -} Lights3; - -typedef struct { - Ambient a; - Light l[4]; -} Lights4; - -typedef struct { - Ambient a; - Light l[5]; -} Lights5; - -typedef struct { - Ambient a; - Light l[6]; -} Lights6; - -typedef struct { - Ambient a; - Light l[7]; -} Lights7; - -typedef struct { - Light l[2]; -} LookAt; - -typedef union { - Hilite_t h; - long int force_structure_alignment[4]; -} Hilite; - -#define gdSPDefLights0(ar,ag,ab) \ - { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ - {{{ { 0, 0, 0},0,{ 0, 0, 0},0,{ 0, 0, 0},0}}} } -#define gdSPDefLights1(ar,ag,ab,r1,g1,b1,x1,y1,z1) \ - { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ - {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}} } -#define gdSPDefLights2(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2) \ - { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ - {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ - {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}} } -#define gdSPDefLights3(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3) \ - { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ - {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ - {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ - {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}} } -#define gdSPDefLights4(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4) \ - { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ - {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ - {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ - {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ - {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}} } -#define gdSPDefLights5(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4,r5,g5,b5,x5,y5,z5) \ - { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ - {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ - {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ - {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ - {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}, \ - {{ {r5,g5,b5},0,{r5,g5,b5},0,{x5,y5,z5},0}}} } - - -#define gdSPDefLights6(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4,r5,g5,b5,x5,y5,z5,r6,g6,b6,x6,y6,z6) \ - { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ - {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ - {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ - {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ - {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}, \ - {{ {r5,g5,b5},0,{r5,g5,b5},0,{x5,y5,z5},0}}, \ - {{ {r6,g6,b6},0,{r6,g6,b6},0,{x6,y6,z6},0}}} } - - -#define gdSPDefLights7(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4,r5,g5,b5,x5,y5,z5,r6,g6,b6,x6,y6,z6,r7,g7,b7,x7,y7,z7) \ - { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ - {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ - {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ - {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ - {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}, \ - {{ {r5,g5,b5},0,{r5,g5,b5},0,{x5,y5,z5},0}}, \ - {{ {r6,g6,b6},0,{r6,g6,b6},0,{x6,y6,z6},0}}, \ - {{ {r7,g7,b7},0,{r7,g7,b7},0,{x7,y7,z7},0}}} } - - -#define gdSPDefLookAt(rightx,righty,rightz,upx,upy,upz) \ - { {{ {{0,0,0},0,{0,0,0},0,{rightx,righty,rightz},0}}, \ - { {{0,0x80,0},0,{0,0x80,0},0,{upx,upy,upz},0}}} } - -/* Don't declare these for F3D_OLD to avoid bss reordering */ -#ifndef F3D_OLD -/* - * Graphics DMA Packet - */ -typedef struct { - int cmd:8; - unsigned int par:8; - unsigned int len:16; - uintptr_t addr; -} Gdma; - -/* - * Graphics Immediate Mode Packet types - */ -typedef struct { - int cmd:8; - int pad:24; - Tri tri; -} Gtri; - -typedef struct { - int cmd:8; - int pad1:24; - int pad2:24; - unsigned char param:8; -} Gpopmtx; - -/* - * typedef struct { - * int cmd:8; - * int pad0:24; - * int pad1:4; - * int number:4; - * int base:24; - * } Gsegment; - */ -typedef struct { - int cmd:8; - int pad0:8; - int mw_index:8; - int number:8; - int pad1:8; - int base:24; -} Gsegment; - -typedef struct { - int cmd:8; - int pad0:8; - int sft:8; - int len:8; - unsigned int data:32; -} GsetothermodeL; - -typedef struct { - int cmd:8; - int pad0:8; - int sft:8; - int len:8; - unsigned int data:32; -} GsetothermodeH; - -typedef struct { - unsigned char cmd; - unsigned char lodscale; - unsigned char tile; - unsigned char on; - unsigned short s; - unsigned short t; -} Gtexture; - -typedef struct { - int cmd:8; - int pad:24; - Tri line; -} Gline3D; - -typedef struct { - int cmd:8; - int pad1:24; - short int pad2; - short int scale; -} Gperspnorm; - - -/* - * RDP Packet types - */ -typedef struct { - int cmd:8; - unsigned int fmt:3; - unsigned int siz:2; - unsigned int pad:7; - unsigned int wd:12; /* really only 10 bits, extra */ - uintptr_t dram; /* to account for 1024 */ -} Gsetimg; - -typedef struct { - int cmd:8; - unsigned int muxs0:24; - unsigned int muxs1:32; -} Gsetcombine; - -typedef struct { - int cmd:8; - unsigned char pad; - unsigned char prim_min_level; - unsigned char prim_level; - unsigned long color; -} Gsetcolor; - -typedef struct { - int cmd:8; - int x0:10; - int x0frac:2; - int y0:10; - int y0frac:2; - unsigned int pad:8; - int x1:10; - int x1frac:2; - int y1:10; - int y1frac:2; -} Gfillrect; - -typedef struct { - int cmd:8; - unsigned int fmt:3; - unsigned int siz:2; - unsigned int pad0:1; - unsigned int line:9; - unsigned int tmem:9; - unsigned int pad1:5; - unsigned int tile:3; - unsigned int palette:4; - unsigned int ct:1; - unsigned int mt:1; - unsigned int maskt:4; - unsigned int shiftt:4; - unsigned int cs:1; - unsigned int ms:1; - unsigned int masks:4; - unsigned int shifts:4; -} Gsettile; - -typedef struct { - int cmd:8; - unsigned int sl:12; - unsigned int tl:12; - int pad:5; - unsigned int tile:3; - unsigned int sh:12; - unsigned int th:12; -} Gloadtile; - -typedef Gloadtile Gloadblock; - -typedef Gloadtile Gsettilesize; - -typedef Gloadtile Gloadtlut; - -typedef struct { - unsigned int cmd:8; /* command */ - unsigned int xl:12; /* X coordinate of upper left */ - unsigned int yl:12; /* Y coordinate of upper left */ - unsigned int pad1:5; /* Padding */ - unsigned int tile:3; /* Tile descriptor index */ - unsigned int xh:12; /* X coordinate of lower right */ - unsigned int yh:12; /* Y coordinate of lower right */ - unsigned int s:16; /* S texture coord at top left */ - unsigned int t:16; /* T texture coord at top left */ - unsigned int dsdx:16;/* Change in S per change in X */ - unsigned int dtdy:16;/* Change in T per change in Y */ -} Gtexrect; - -/* - * Textured rectangles are 128 bits not 64 bits - */ -typedef struct { - unsigned long w0; - unsigned long w1; - unsigned long w2; - unsigned long w3; -} TexRect; -#endif - -#define MakeTexRect(xh,yh,flip,tile,xl,yl,s,t,dsdx,dtdy) \ - G_TEXRECT, xh, yh, 0, flip, 0, tile, xl, yl, s, t, dsdx, dtdy - -/* - * Generic Gfx Packet - */ -typedef struct { - uintptr_t w0; - uintptr_t w1; -} Gwords; - -/* - * This union is the fundamental type of the display list. - * It is, by law, exactly 64 bits in size. - * - * (Edit: except on 64-bit, where it is exactly 128 bit. On little-endian or - * 64-bit systems, only the 'words' member may be accessed; the rest of the - * structs don't have matching layouts for now.) - */ -typedef union { - Gwords words; -#if !defined(F3D_OLD) && IS_BIG_ENDIAN && !IS_64_BIT - Gdma dma; - Gtri tri; - Gline3D line; - Gpopmtx popmtx; - Gsegment segment; - GsetothermodeH setothermodeH; - GsetothermodeL setothermodeL; - Gtexture texture; - Gperspnorm perspnorm; - Gsetimg setimg; - Gsetcombine setcombine; - Gsetcolor setcolor; - Gfillrect fillrect; /* use for setscissor also */ - Gsettile settile; - Gloadtile loadtile; /* use for loadblock also, th is dxt */ - Gsettilesize settilesize; - Gloadtlut loadtlut; -#endif - long long int force_structure_alignment; -} Gfx; - -/* - * Macros to assemble the graphics display list - */ - -/* - * DMA macros - */ -#define gDma0p(pkt, c, s, l) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24); \ - _g->words.w1 = (uintptr_t)(s); \ -} - -#define gsDma0p(c, s, l) \ -{{ \ - _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24), (uintptr_t)(s) \ -}} - -#define gDma1p(pkt, c, s, l, p) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \ - _SHIFTL((l), 0, 16)); \ - _g->words.w1 = (uintptr_t)(s); \ -} - -#define gsDma1p(c, s, l, p) \ -{{ \ - (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \ - _SHIFTL((l), 0, 16)), \ - (uintptr_t)(s) \ -}} - -#define gDma2p(pkt, c, adrs, len, idx, ofs) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - _g->words.w0 = (_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \ - _SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)); \ - _g->words.w1 = (uintptr_t)(adrs); \ -} -#define gsDma2p(c, adrs, len, idx, ofs) \ -{{ \ - (_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \ - _SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)), \ - (uintptr_t)(adrs) \ -}} - -#define gSPNoOp(pkt) gDma0p(pkt, G_SPNOOP, 0, 0) -#define gsSPNoOp() gsDma0p(G_SPNOOP, 0, 0) - -#ifdef F3DEX_GBI_2 -# define gSPMatrix(pkt, m, p) \ - gDma2p((pkt),G_MTX,(m),sizeof(Mtx),(p)^G_MTX_PUSH,0) -# define gsSPMatrix(m, p) \ - gsDma2p( G_MTX,(m),sizeof(Mtx),(p)^G_MTX_PUSH,0) -#else /* F3DEX_GBI_2 */ -# define gSPMatrix(pkt, m, p) gDma1p(pkt, G_MTX, m, sizeof(Mtx), p) -# define gsSPMatrix(m, p) gsDma1p(G_MTX, m, sizeof(Mtx), p) -#endif /* F3DEX_GBI_2 */ - -#if defined(F3DEX_GBI_2) -/* - * F3DEX_GBI_2: G_VTX GBI format was changed. - * - * +--------+----+---+---+----+------+-+ - * G_VTX | cmd:8 |0000| n:8 |0000|v0+n:7|0| - * +-+---+--+----+---+---+----+------+-+ - * | |seg| address | - * +-+---+-----------------------------+ - */ -# define gSPVertex(pkt, v, n, v0) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - _g->words.w0 = \ - _SHIFTL(G_VTX,24,8)|_SHIFTL((n),12,8)|_SHIFTL((v0)+(n),1,7); \ - _g->words.w1 = (uintptr_t)(v); \ -} -# define gsSPVertex(v, n, v0) \ -{{ \ - (_SHIFTL(G_VTX,24,8)|_SHIFTL((n),12,8)|_SHIFTL((v0)+(n),1,7)), \ - (uintptr_t)(v) \ -}} -#elif (defined(F3DEX_GBI)||defined(F3DLP_GBI)) -/* - * F3DEX_GBI: G_VTX GBI format was changed to support 64 vertice. - * - * +--------+--------+------+----------+ - * G_VTX | cmd:8 | v0:8 | n:6 |length:10 | - * +-+---+--+--------+------+----------+ - * | |seg| address | - * +-+---+-----------------------------+ - */ -# define gSPVertex(pkt, v, n, v0) \ - gDma1p((pkt),G_VTX,(v),((n)<<10)|(sizeof(Vtx)*(n)-1),(v0)*2) -# define gsSPVertex(v, n, v0) \ - gsDma1p(G_VTX,(v),((n)<<10)|(sizeof(Vtx)*(n)-1),(v0)*2) -#else -# define gSPVertex(pkt, v, n, v0) \ - gDma1p(pkt, G_VTX, v, sizeof(Vtx)*(n),((n)-1)<<4|(v0)) -# define gsSPVertex(v, n, v0) \ - gsDma1p(G_VTX, v, sizeof(Vtx)*(n), ((n)-1)<<4|(v0)) -#endif - - -#ifdef F3DEX_GBI_2 -# define gSPViewport(pkt, v) \ - gDma2p((pkt), G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT, 0) -# define gsSPViewport(v) \ - gsDma2p( G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT, 0) -#else /* F3DEX_GBI_2 */ -# define gSPViewport(pkt,v) \ - gDma1p((pkt), G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT) -# define gsSPViewport(v) \ - gsDma1p( G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT) -#endif /* F3DEX_GBI_2 */ - -#define gSPDisplayList(pkt,dl) gDma1p(pkt,G_DL,dl,0,G_DL_PUSH) -#define gsSPDisplayList( dl) gsDma1p( G_DL,dl,0,G_DL_PUSH) - -#define gSPBranchList(pkt,dl) gDma1p(pkt,G_DL,dl,0,G_DL_NOPUSH) -#define gsSPBranchList( dl) gsDma1p( G_DL,dl,0,G_DL_NOPUSH) - -#define gSPSprite2DBase(pkt, s) gDma1p(pkt, G_SPRITE2D_BASE, s, sizeof(uSprite), 0) -#define gsSPSprite2DBase(s) gsDma1p(G_SPRITE2D_BASE, s, sizeof(uSprite), 0) - -/* - * RSP short command (no DMA required) macros - */ -#define gImmp0(pkt, c) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL((c), 24, 8); \ -} - -#define gsImmp0(c) \ -{{ \ - _SHIFTL((c), 24, 8) \ -}} - -#define gImmp1(pkt, c, p0) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL((c), 24, 8); \ - _g->words.w1 = (uintptr_t)(p0); \ -} - -#define gsImmp1(c, p0) \ -{{ \ - _SHIFTL((c), 24, 8), (uintptr_t)(p0) \ -}} - -#define gImmp2(pkt, c, p0, p1) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL((c), 24, 8); \ - _g->words.w1 = _SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8); \ -} - -#define gsImmp2(c, p0, p1) \ -{{ \ - _SHIFTL((c), 24, 8), _SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8)\ -}} - -#define gImmp3(pkt, c, p0, p1, p2) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL((c), 24, 8); \ - _g->words.w1 = (_SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8) | \ - _SHIFTL((p2), 0, 8)); \ -} - -#define gsImmp3(c, p0, p1, p2) \ -{{ \ - _SHIFTL((c), 24, 8), (_SHIFTL((p0), 16, 16) | \ - _SHIFTL((p1), 8, 8) | _SHIFTL((p2), 0, 8))\ -}} - -#define gImmp21(pkt, c, p0, p1, dat) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | \ - _SHIFTL((p1), 0, 8)); \ - _g->words.w1 = (uintptr_t) (dat); \ -} - -#define gsImmp21(c, p0, p1, dat) \ -{{ \ - _SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | _SHIFTL((p1), 0, 8),\ - (uintptr_t) (dat) \ -}} - -#ifdef F3DEX_GBI_2 -#define gMoveWd(pkt, index, offset, data) \ - gDma1p((pkt), G_MOVEWORD, data, offset, index) -#define gsMoveWd( index, offset, data) \ - gsDma1p( G_MOVEWORD, data, offset, index) -#else /* F3DEX_GBI_2 */ -#define gMoveWd(pkt, index, offset, data) \ - gImmp21((pkt), G_MOVEWORD, offset, index, data) -#define gsMoveWd( index, offset, data) \ - gsImmp21( G_MOVEWORD, offset, index, data) -#endif /* F3DEX_GBI_2 */ - -/* Sprite immediate macros, there is also a sprite dma macro above */ - -#define gSPSprite2DScaleFlip(pkt, sx, sy, fx, fy) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_SPRITE2D_SCALEFLIP, 24, 8) | \ - _SHIFTL((fx), 8, 8) | \ - _SHIFTL((fy), 0, 8)); \ - _g->words.w1 = (_SHIFTL((sx), 16, 16) | \ - _SHIFTL((sy), 0, 16)); \ -} - -#define gsSPSprite2DScaleFlip(sx, sy, fx, fy) \ -{{ \ - (_SHIFTL(G_SPRITE2D_SCALEFLIP, 24, 8) | \ - _SHIFTL((fx), 8, 8) | \ - _SHIFTL((fy), 0, 8)), \ - (_SHIFTL((sx), 16, 16) | \ - _SHIFTL((sy), 0, 16)) \ -}} - -#define gSPSprite2DDraw(pkt, px, py) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_SPRITE2D_DRAW, 24, 8)); \ - _g->words.w1 = (_SHIFTL((px), 16, 16) | \ - _SHIFTL((py), 0, 16)); \ -} - -#define gsSPSprite2DDraw(px, py) \ -{{ \ - (_SHIFTL(G_SPRITE2D_DRAW, 24, 8)), \ - (_SHIFTL((px), 16, 16) | \ - _SHIFTL((py), 0, 16)) \ -}} - - -/* - * Note: the SP1Triangle() and line macros multiply the vertex indices - * by 10, this is an optimization for the microcode. - */ -#if (defined(F3DLP_GBI)||defined(F3DEX_GBI)) -# define __gsSP1Triangle_w1(v0, v1, v2) \ - (_SHIFTL((v0)*2,16,8)|_SHIFTL((v1)*2,8,8)|_SHIFTL((v2)*2,0,8)) -# define __gsSP1Triangle_w1f(v0, v1, v2, flag) \ - (((flag) == 0) ? __gsSP1Triangle_w1(v0, v1, v2): \ - ((flag) == 1) ? __gsSP1Triangle_w1(v1, v2, v0): \ - __gsSP1Triangle_w1(v2, v0, v1)) -# define __gsSPLine3D_w1(v0, v1, wd) \ - (_SHIFTL((v0)*2,16,8)|_SHIFT((v1)*2,8,8)|_SHIFT((wd),0,8)) -# define __gsSPLine3D_w1f(v0, v1, wd, flag) \ - (((flag) == 0) ? __gsSPLine3D_w1(v0, v1, wd): \ - __gsSPLine3D_w1(v1, v0, wd)) -# define __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag) \ - (((flag) == 0) ? __gsSP1Triangle_w1(v0, v1, v2): \ - ((flag) == 1) ? __gsSP1Triangle_w1(v1, v2, v3): \ - ((flag) == 2) ? __gsSP1Triangle_w1(v2, v3, v0): \ - __gsSP1Triangle_w1(v3, v0, v1)) -# define __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ - (((flag) == 0) ? __gsSP1Triangle_w1(v0, v2, v3): \ - ((flag) == 1) ? __gsSP1Triangle_w1(v1, v3, v0): \ - ((flag) == 2) ? __gsSP1Triangle_w1(v2, v0, v1): \ - __gsSP1Triangle_w1(v3, v1, v2)) -#else -# define __gsSP1Triangle_w1f(v0, v1, v2, flag) \ - (_SHIFTL((flag), 24,8)|_SHIFTL((v0)*10,16,8)| \ - _SHIFTL((v1)*10, 8,8)|_SHIFTL((v2)*10, 0,8)) -# define __gsSPLine3D_w1f(v0, v1, wd, flag) \ - (_SHIFTL((flag), 24,8)|_SHIFTL((v0)*10,16,8)| \ - _SHIFTL((v1)*10, 8,8)|_SHIFTL((wd), 0,8)) -#endif - -#ifdef F3DEX_GBI_2 -/*** - *** 1 Triangle - ***/ -#define gSP1Triangle(pkt, v0, v1, v2, flag) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_TRI1, 24, 8)| \ - __gsSP1Triangle_w1f(v0, v1, v2, flag); \ - _g->words.w1 = 0; \ -} -#define gsSP1Triangle(v0, v1, v2, flag) \ -{{ \ - _SHIFTL(G_TRI1, 24, 8)|__gsSP1Triangle_w1f(v0, v1, v2, flag), \ - 0 \ -}} - -/*** - *** Line - ***/ -#define gSPLine3D(pkt, v0, v1, flag) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8)| \ - __gsSPLine3D_w1f(v0, v1, 0, flag); \ - _g->words.w1 = 0; \ -} -#define gsSPLine3D(v0, v1, flag) \ -{{ \ - _SHIFTL(G_LINE3D, 24, 8)|__gsSPLine3D_w1f(v0, v1, 0, flag), \ - 0 \ -}} - -/*** - *** LineW - ***/ -/* these macros are the same as SPLine3D, except they have an - * additional parameter for width. The width is added to the "minimum" - * thickness, which is 1.5 pixels. The units for width are in - * half-pixel units, so a width of 1 translates to (.5 + 1.5) or - * a 2.0 pixels wide line. - */ -#define gSPLineW3D(pkt, v0, v1, wd, flag) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8)| \ - __gsSPLine3D_w1f(v0, v1, wd, flag); \ - _g->words.w1 = 0; \ -} -#define gsSPLineW3D(v0, v1, wd, flag) \ -{{ \ - _SHIFTL(G_LINE3D, 24, 8)|__gsSPLine3D_w1f(v0, v1, wd, flag), \ - 0 \ -}} - -/*** - *** 1 Quadrangle - ***/ -#define gSP1Quadrangle(pkt, v0, v1, v2, v3, flag) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_QUAD, 24, 8)| \ - __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)); \ - _g->words.w1 = __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag); \ -} - -#define gsSP1Quadrangle(v0, v1, v2, v3, flag) \ -{{ \ - (_SHIFTL(G_QUAD, 24, 8)| \ - __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)), \ - __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ -}} -#else /* F3DEX_GBI_2 */ - -/*** - *** 1 Triangle - ***/ -#define gSP1Triangle(pkt, v0, v1, v2, flag) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_TRI1, 24, 8); \ - _g->words.w1 = __gsSP1Triangle_w1f(v0, v1, v2, flag); \ -} -#define gsSP1Triangle(v0, v1, v2, flag) \ -{{ \ - _SHIFTL(G_TRI1, 24, 8), \ - __gsSP1Triangle_w1f(v0, v1, v2, flag) \ -}} - -/*** - *** Line - ***/ -#define gSPLine3D(pkt, v0, v1, flag) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8); \ - _g->words.w1 = __gsSPLine3D_w1f(v0, v1, 0, flag); \ -} -#define gsSPLine3D(v0, v1, flag) \ -{{ \ - _SHIFTL(G_LINE3D, 24, 8), \ - __gsSPLine3D_w1f(v0, v1, 0, flag) \ -}} - -/*** - *** LineW - ***/ -/* these macros are the same as SPLine3D, except they have an - * additional parameter for width. The width is added to the "minimum" - * thickness, which is 1.5 pixels. The units for width are in - * half-pixel units, so a width of 1 translates to (.5 + 1.5) or - * a 2.0 pixels wide line. - */ -#define gSPLineW3D(pkt, v0, v1, wd, flag) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8); \ - _g->words.w1 = __gsSPLine3D_w1f(v0, v1, wd, flag); \ -} -#define gsSPLineW3D(v0, v1, wd, flag) \ -{{ \ - _SHIFTL(G_LINE3D, 24, 8), \ - __gsSPLine3D_w1f(v0, v1, wd, flag) \ -}} - -/*** - *** 1 Quadrangle - ***/ -#define gSP1Quadrangle(pkt, v0, v1, v2, v3, flag) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TRI2, 24, 8)| \ - __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)); \ - _g->words.w1 = __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag); \ -} - -#define gsSP1Quadrangle(v0, v1, v2, v3, flag) \ -{{ \ - (_SHIFTL(G_TRI2, 24, 8)| \ - __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)), \ - __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ -}} -#endif /* F3DEX_GBI_2 */ - -#if (defined(F3DLP_GBI)||defined(F3DEX_GBI)) -/*** - *** 2 Triangles - ***/ -#define gSP2Triangles(pkt, v00, v01, v02, flag0, v10, v11, v12, flag1) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TRI2, 24, 8)| \ - __gsSP1Triangle_w1f(v00, v01, v02, flag0)); \ - _g->words.w1 = __gsSP1Triangle_w1f(v10, v11, v12, flag1); \ -} - -#define gsSP2Triangles(v00, v01, v02, flag0, v10, v11, v12, flag1) \ -{{ \ - (_SHIFTL(G_TRI2, 24, 8)| \ - __gsSP1Triangle_w1f(v00, v01, v02, flag0)), \ - __gsSP1Triangle_w1f(v10, v11, v12, flag1) \ -}} -#else -#define gSP2Triangles(pkt, v00, v01, v02, flag0, v10, v11, v12, flag1) \ -{ \ - gSP1Triangle(pkt, v00, v01, v02, flag0); \ - gSP1Triangle(pkt, v10, v11, v12, flag1); \ -} -#define gsSP2Triangles(v00, v01, v02, flag0, v10, v11, v12, flag1) \ - gsSP1Triangle(v00, v01, v02, flag0), \ - gsSP1Triangle(v10, v11, v12, flag1) -#endif /* F3DEX_GBI/F3DLP_GBI */ - -#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) -#define gSPCullDisplayList(pkt,vstart,vend) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | \ - _SHIFTL((vstart)*2, 0, 16); \ - _g->words.w1 = _SHIFTL((vend)*2, 0, 16); \ -} - -#define gsSPCullDisplayList(vstart,vend) \ -{{ \ - _SHIFTL(G_CULLDL, 24, 8) | _SHIFTL((vstart)*2, 0, 16), \ - _SHIFTL((vend)*2, 0, 16) \ -}} - -#else -#define gSPCullDisplayList(pkt,vstart,vend) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | \ - ((0x0f & (vstart))*40); \ - _g->words.w1 = (unsigned int)((0x0f & ((vend)+1))*40); \ -} - -#define gsSPCullDisplayList(vstart,vend) \ -{{ \ - _SHIFTL(G_CULLDL, 24, 8) | ((0x0f & (vstart))*40), \ - ((0x0f & ((vend)+1))*40) \ -}} -#endif - -#define gSPSegment(pkt, segment, base) \ - gMoveWd(pkt, G_MW_SEGMENT, (segment)*4, base) -#define gsSPSegment(segment, base) \ - gsMoveWd( G_MW_SEGMENT, (segment)*4, base) - -/* - * Clipping Macros - */ -#define FR_NEG_FRUSTRATIO_1 0x00000001 -#define FR_POS_FRUSTRATIO_1 0x0000ffff -#define FR_NEG_FRUSTRATIO_2 0x00000002 -#define FR_POS_FRUSTRATIO_2 0x0000fffe -#define FR_NEG_FRUSTRATIO_3 0x00000003 -#define FR_POS_FRUSTRATIO_3 0x0000fffd -#define FR_NEG_FRUSTRATIO_4 0x00000004 -#define FR_POS_FRUSTRATIO_4 0x0000fffc -#define FR_NEG_FRUSTRATIO_5 0x00000005 -#define FR_POS_FRUSTRATIO_5 0x0000fffb -#define FR_NEG_FRUSTRATIO_6 0x00000006 -#define FR_POS_FRUSTRATIO_6 0x0000fffa -/* - * r should be one of: FRUSTRATIO_1, FRUSTRATIO_2, FRUSTRATIO_3, ... FRUSTRATIO_6 - */ -#define gSPClipRatio(pkt, r) \ -{ \ - gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RNX, FR_NEG_##r); \ - gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RNY, FR_NEG_##r); \ - gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RPX, FR_POS_##r); \ - gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RPY, FR_POS_##r); \ -} - -#define gsSPClipRatio(r) \ - gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RNX, FR_NEG_##r), \ - gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RNY, FR_NEG_##r), \ - gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RPX, FR_POS_##r), \ - gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RPY, FR_POS_##r) - -/* - * Insert values into Matrix - * - * where = element of matrix (byte offset) - * num = new element (32 bit value replacing 2 int or 2 frac matrix - * componants - */ -#ifdef F3DEX_GBI_2 -#define gSPInsertMatrix(pkt, where, num) \ - ERROR!! gSPInsertMatrix is no longer supported. -#define gsSPInsertMatrix(where, num) \ - ERROR!! gsSPInsertMatrix is no longer supported. -#else -#define gSPInsertMatrix(pkt, where, num) \ - gMoveWd(pkt, G_MW_MATRIX, where, num) -#define gsSPInsertMatrix(where, num) \ - gsMoveWd(G_MW_MATRIX, where, num) -#endif - -/* - * Load new matrix directly - * - * mptr = pointer to matrix - */ -#ifdef F3DEX_GBI_2 -#define gSPForceMatrix(pkt, mptr) \ -{ gDma2p((pkt),G_MOVEMEM,(mptr),sizeof(Mtx),G_MV_MATRIX,0); \ - gMoveWd((pkt), G_MW_FORCEMTX,0,0x00010000); \ -} -#define gsSPForceMatrix(mptr) \ - gsDma2p(G_MOVEMEM,(mptr),sizeof(Mtx),G_MV_MATRIX,0), \ - gsMoveWd(G_MW_FORCEMTX,0,0x00010000) - -#else /* F3DEX_GBI_2 */ -#define gSPForceMatrix(pkt, mptr) \ -{ \ - gDma1p(pkt, G_MOVEMEM, mptr, 16, G_MV_MATRIX_1); \ - gDma1p(pkt, G_MOVEMEM, (char *)(mptr)+16, 16, G_MV_MATRIX_2); \ - gDma1p(pkt, G_MOVEMEM, (char *)(mptr)+32, 16, G_MV_MATRIX_3); \ - gDma1p(pkt, G_MOVEMEM, (char *)(mptr)+48, 16, G_MV_MATRIX_4); \ -} -#define gsSPForceMatrix(mptr) \ - gsDma1p( G_MOVEMEM, mptr, 16, G_MV_MATRIX_1), \ - gsDma1p( G_MOVEMEM, (char *)(mptr)+16, 16, G_MV_MATRIX_2), \ - gsDma1p( G_MOVEMEM, (char *)(mptr)+32, 16, G_MV_MATRIX_3), \ - gsDma1p( G_MOVEMEM, (char *)(mptr)+48, 16, G_MV_MATRIX_4) -#endif /* F3DEX_GBI_2 */ - -/* - * Insert values into Points - * - * point = point number 0-15 - * where = which element of point to modify (byte offset into point) - * num = new value (32 bit) - */ -#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) -# define gSPModifyVertex(pkt, vtx, where, val) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - _g->words.w0 = (_SHIFTL(G_MODIFYVTX,24,8)| \ - _SHIFTL((where),16,8)|_SHIFTL((vtx)*2,0,16)); \ - _g->words.w1 = (unsigned int)(val); \ -} -# define gsSPModifyVertex(vtx, where, val) \ -{{ \ - _SHIFTL(G_MODIFYVTX,24,8)| \ - _SHIFTL((where),16,8)|_SHIFTL((vtx)*2,0,16), \ - (unsigned int)(val) \ -}} -#else -# define gSPModifyVertex(pkt, vtx, where, val) \ - gMoveWd(pkt, G_MW_POINTS, (vtx)*40+(where), val) -# define gsSPModifyVertex(vtx, where, val) \ - gsMoveWd(G_MW_POINTS, (vtx)*40+(where), val) -#endif - -#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) -/* - * gSPBranchLessZ Branch DL if (vtx.z) less than or equal (zval). - * - * dl = DL branch to - * vtx = Vertex - * zval = Screen depth - * near = Near plane - * far = Far plane - * flag = G_BZ_PERSP or G_BZ_ORTHO - */ - -#define G_BZ_PERSP 0 -#define G_BZ_ORTHO 1 - -#define G_DEPTOZSrg(zval, near, far, flag, zmin, zmax) \ -(((unsigned int)FTOFIX32(((flag) == G_BZ_PERSP ? \ - (1.0f-(float)(near)/(float)(zval)) / \ - (1.0f-(float)(near)/(float)(far )) : \ - ((float)(zval) - (float)(near)) / \ - ((float)(far ) - (float)(near))))) * \ - (((int)((zmax) - (zmin)))&~1) + (int)FTOFIX32(zmin)) - -#define G_DEPTOZS(zval, near, far, flag) \ - G_DEPTOZSrg(zval, near, far, flag, 0, G_MAXZ) - -#define gSPBranchLessZrg(pkt, dl, vtx, zval, near, far, flag, zmin, zmax) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ - _g->words.w1 = (uintptr_t)(dl); \ - _g = (Gfx *)(pkt); \ - _g->words.w0 = (_SHIFTL(G_BRANCH_Z,24,8)| \ - _SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12)); \ - _g->words.w1 = G_DEPTOZSrg(zval, near, far, flag, zmin, zmax); \ -} - -#define gsSPBranchLessZrg(dl, vtx, zval, near, far, flag, zmin, zmax) \ -{{ _SHIFTL(G_RDPHALF_1,24,8), \ - (uintptr_t)(dl), }}, \ -{{ _SHIFTL(G_BRANCH_Z,24,8)|_SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12),\ - G_DEPTOZSrg(zval, near, far, flag, zmin, zmax), }} - -#define gSPBranchLessZ(pkt, dl, vtx, zval, near, far, flag) \ - gSPBranchLessZrg(pkt, dl, vtx, zval, near, far, flag, 0, G_MAXZ) -#define gsSPBranchLessZ(dl, vtx, zval, near, far, flag) \ - gsSPBranchLessZrg(dl, vtx, zval, near, far, flag, 0, G_MAXZ) - -/* - * gSPBranchLessZraw Branch DL if (vtx.z) less than or equal (raw zval). - * - * dl = DL branch to - * vtx = Vertex - * zval = Raw value of screen depth - */ -#define gSPBranchLessZraw(pkt, dl, vtx, zval) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ - _g->words.w1 = (uintptr_t)(dl); \ - _g = (Gfx *)(pkt); \ - _g->words.w0 = (_SHIFTL(G_BRANCH_Z,24,8)| \ - _SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12)); \ - _g->words.w1 = (unsigned int)(zval); \ -} - -#define gsSPBranchLessZraw(dl, vtx, zval) \ -{{ _SHIFTL(G_RDPHALF_1,24,8), \ - (uintptr_t)(dl), }}, \ -{{ _SHIFTL(G_BRANCH_Z,24,8)|_SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12),\ - (unsigned int)(zval), }} - -/* - * gSPLoadUcode RSP loads specified ucode. - * - * uc_start = ucode text section start - * uc_dstart = ucode data section start - */ -#define gSPLoadUcodeEx(pkt, uc_start, uc_dstart, uc_dsize) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ - _g->words.w1 = (uintptr_t)(uc_dstart); \ - _g = (Gfx *)(pkt); \ - _g->words.w0 = (_SHIFTL(G_LOAD_UCODE,24,8)| \ - _SHIFTL((int)(uc_dsize)-1,0,16)); \ - _g->words.w1 = (uintptr_t)(uc_start); \ -} - -#define gsSPLoadUcodeEx(uc_start, uc_dstart, uc_dsize) \ -{{ _SHIFTL(G_RDPHALF_1,24,8), \ - (uintptr_t)(uc_dstart), }}, \ -{{ _SHIFTL(G_LOAD_UCODE,24,8)| \ - _SHIFTL((int)(uc_dsize)-1,0,16), \ - (uintptr_t)(uc_start), }} - -#define gSPLoadUcode(pkt, uc_start, uc_dstart) \ - gSPLoadUcodeEx((pkt), (uc_start), (uc_dstart), SP_UCODE_DATA_SIZE) -#define gsSPLoadUcode(uc_start, uc_dstart) \ - gsSPLoadUcodeEx((uc_start), (uc_dstart), SP_UCODE_DATA_SIZE) - -#define gSPLoadUcodeL(pkt, ucode) \ - gSPLoadUcode((pkt), OS_K0_TO_PHYSICAL(&ucode##TextStart), \ - OS_K0_TO_PHYSICAL(&ucode##DataStart)) -#define gsSPLoadUcodeL(ucode) \ - gsSPLoadUcode(OS_K0_TO_PHYSICAL(&ucode##TextStart), \ - OS_K0_TO_PHYSICAL(&ucode##DataStart)) -#endif - -#ifdef F3DEX_GBI_2 -/* - * gSPDma_io DMA to/from DMEM/IMEM for DEBUG. - */ -#define gSPDma_io(pkt, flag, dmem, dram, size) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - _g->words.w0 = _SHIFTL(G_DMA_IO,24,8)|_SHIFTL((flag),23,1)| \ - _SHIFTL((dmem)/8,13,10)|_SHIFTL((size)-1,0,12); \ - _g->words.w1 = (uintptr_t)(dram); \ -} - -#define gsSPDma_io(flag, dmem, dram, size) \ -{{ \ - _SHIFTL(G_DMA_IO,24,8)|_SHIFTL((flag),23,1)| \ - _SHIFTL((dmem)/8,13,10)|_SHIFTL((size)-1,0,12), \ - (uintptr_t)(dram) \ -}} - -#define gSPDmaRead(pkt,dmem,dram,size) gSPDma_io((pkt),0,(dmem),(dram),(size)) -#define gsSPDmaRead(dmem,dram,size) gsSPDma_io(0,(dmem),(dram),(size)) -#define gSPDmaWrite(pkt,dmem,dram,size) gSPDma_io((pkt),1,(dmem),(dram),(size)) -#define gsSPDmaWrite(dmem,dram,size) gsSPDma_io(1,(dmem),(dram),(size)) -#endif - -/* - * Lighting Macros - */ -#ifdef F3DEX_GBI_2 -# define NUML(n) ((n)*24) -#else -# define NUML(n) (((n)+1)*32 + 0x80000000) -#endif -#define NUMLIGHTS_0 1 -#define NUMLIGHTS_1 1 -#define NUMLIGHTS_2 2 -#define NUMLIGHTS_3 3 -#define NUMLIGHTS_4 4 -#define NUMLIGHTS_5 5 -#define NUMLIGHTS_6 6 -#define NUMLIGHTS_7 7 -/* - * n should be one of: NUMLIGHTS_0, NUMLIGHTS_1, ..., NUMLIGHTS_7 - * NOTE: in addition to the number of directional lights specified, - * there is always 1 ambient light - */ -#define gSPNumLights(pkt, n) \ - gMoveWd(pkt, G_MW_NUMLIGHT, G_MWO_NUMLIGHT, NUML(n)) -#define gsSPNumLights(n) \ - gsMoveWd( G_MW_NUMLIGHT, G_MWO_NUMLIGHT, NUML(n)) - -#define LIGHT_1 1 -#define LIGHT_2 2 -#define LIGHT_3 3 -#define LIGHT_4 4 -#define LIGHT_5 5 -#define LIGHT_6 6 -#define LIGHT_7 7 -#define LIGHT_8 8 -/* - * l should point to a Light struct - * n should be one of: LIGHT_1, LIGHT_2, ..., LIGHT_8 - * NOTE: the highest numbered light is always the ambient light (eg if there are - * 3 directional lights defined: gsSPNumLights(NUMLIGHTS_3), then lights - * LIGHT_1 through LIGHT_3 will be the directional lights and light - * LIGHT_4 will be the ambient light. - */ -#ifdef F3DEX_GBI_2 -# define gSPLight(pkt, l, n) \ - gDma2p((pkt),G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,(n)*24+24) -# define gsSPLight(l, n) \ - gsDma2p( G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,(n)*24+24) -#else /* F3DEX_GBI_2 */ -# define gSPLight(pkt, l, n) \ - gDma1p(pkt, G_MOVEMEM, l, sizeof(Light),((n)-1)*2+G_MV_L0) -# define gsSPLight(l, n) \ - gsDma1p( G_MOVEMEM, l, sizeof(Light),((n)-1)*2+G_MV_L0) -#endif /* F3DEX_GBI_2 */ - -/* - * gSPLightColor changes color of light without recalculating light direction - * col is a 32 bit word with r,g,b,a (alpha is ignored) - * n should be one of LIGHT_1, LIGHT_2, ..., LIGHT_8 - */ -#define gSPLightColor(pkt, n, col) \ -{ \ - gMoveWd(pkt, G_MW_LIGHTCOL, G_MWO_a##n, col); \ - gMoveWd(pkt, G_MW_LIGHTCOL, G_MWO_b##n, col); \ -} -#define gsSPLightColor(n, col) \ - gsMoveWd(G_MW_LIGHTCOL, G_MWO_a##n, col), \ - gsMoveWd(G_MW_LIGHTCOL, G_MWO_b##n, col) - -/* These macros use a structure "name" which is init'd with the gdSPDefLights macros*/ - -#define gSPSetLights0(pkt,name) \ -{ \ - gSPNumLights(pkt,NUMLIGHTS_0); \ - gSPLight(pkt,&name.l[0],1); \ - gSPLight(pkt,&name.a,2); \ -} -#define gsSPSetLights0(name) \ - gsSPNumLights(NUMLIGHTS_0), \ - gsSPLight(&name.l[0],1), \ - gsSPLight(&name.a,2) - -#define gSPSetLights1(pkt,name) \ -{ \ - gSPNumLights(pkt,NUMLIGHTS_1); \ - gSPLight(pkt,&name.l[0],1); \ - gSPLight(pkt,&name.a,2); \ -} -#define gsSPSetLights1(name) \ - gsSPNumLights(NUMLIGHTS_1), \ - gsSPLight(&name.l[0],1), \ - gsSPLight(&name.a,2) - -#define gSPSetLights2(pkt,name) \ -{ \ - gSPNumLights(pkt,NUMLIGHTS_2); \ - gSPLight(pkt,&name.l[0],1); \ - gSPLight(pkt,&name.l[1],2); \ - gSPLight(pkt,&name.a,3); \ -} -#define gsSPSetLights2(name) \ - gsSPNumLights(NUMLIGHTS_2), \ - gsSPLight(&name.l[0],1), \ - gsSPLight(&name.l[1],2), \ - gsSPLight(&name.a,3) - -#define gSPSetLights3(pkt,name) \ -{ \ - gSPNumLights(pkt,NUMLIGHTS_3); \ - gSPLight(pkt,&name.l[0],1); \ - gSPLight(pkt,&name.l[1],2); \ - gSPLight(pkt,&name.l[2],3); \ - gSPLight(pkt,&name.a,4); \ -} -#define gsSPSetLights3(name) \ - gsSPNumLights(NUMLIGHTS_3), \ - gsSPLight(&name.l[0],1), \ - gsSPLight(&name.l[1],2), \ - gsSPLight(&name.l[2],3), \ - gsSPLight(&name.a,4) - -#define gSPSetLights4(pkt,name) \ -{ \ - gSPNumLights(pkt,NUMLIGHTS_4); \ - gSPLight(pkt,&name.l[0],1); \ - gSPLight(pkt,&name.l[1],2); \ - gSPLight(pkt,&name.l[2],3); \ - gSPLight(pkt,&name.l[3],4); \ - gSPLight(pkt,&name.a,5); \ -} -#define gsSPSetLights4(name) \ - gsSPNumLights(NUMLIGHTS_4), \ - gsSPLight(&name.l[0],1), \ - gsSPLight(&name.l[1],2), \ - gsSPLight(&name.l[2],3), \ - gsSPLight(&name.l[3],4), \ - gsSPLight(&name.a,5) - -#define gSPSetLights5(pkt,name) \ -{ \ - gSPNumLights(pkt,NUMLIGHTS_5); \ - gSPLight(pkt,&name.l[0],1); \ - gSPLight(pkt,&name.l[1],2); \ - gSPLight(pkt,&name.l[2],3); \ - gSPLight(pkt,&name.l[3],4); \ - gSPLight(pkt,&name.l[4],5); \ - gSPLight(pkt,&name.a,6); \ -} - -#define gsSPSetLights5(name) \ - gsSPNumLights(NUMLIGHTS_5), \ - gsSPLight(&name.l[0],1), \ - gsSPLight(&name.l[1],2), \ - gsSPLight(&name.l[2],3), \ - gsSPLight(&name.l[3],4), \ - gsSPLight(&name.l[4],5), \ - gsSPLight(&name.a,6) - -#define gSPSetLights6(pkt,name) \ -{ \ - gSPNumLights(pkt,NUMLIGHTS_6); \ - gSPLight(pkt,&name.l[0],1); \ - gSPLight(pkt,&name.l[1],2); \ - gSPLight(pkt,&name.l[2],3); \ - gSPLight(pkt,&name.l[3],4); \ - gSPLight(pkt,&name.l[4],5); \ - gSPLight(pkt,&name.l[5],6); \ - gSPLight(pkt,&name.a,7); \ -} - -#define gsSPSetLights6(name) \ - gsSPNumLights(NUMLIGHTS_6), \ - gsSPLight(&name.l[0],1), \ - gsSPLight(&name.l[1],2), \ - gsSPLight(&name.l[2],3), \ - gsSPLight(&name.l[3],4), \ - gsSPLight(&name.l[4],5), \ - gsSPLight(&name.l[5],6), \ - gsSPLight(&name.a,7) - -#define gSPSetLights7(pkt,name) \ -{ \ - gSPNumLights(pkt,NUMLIGHTS_7); \ - gSPLight(pkt,&name.l[0],1); \ - gSPLight(pkt,&name.l[1],2); \ - gSPLight(pkt,&name.l[2],3); \ - gSPLight(pkt,&name.l[3],4); \ - gSPLight(pkt,&name.l[4],5); \ - gSPLight(pkt,&name.l[5],6); \ - gSPLight(pkt,&name.l[6],7); \ - gSPLight(pkt,&name.a,8); \ -} - -#define gsSPSetLights7(name) \ - gsSPNumLights(NUMLIGHTS_7), \ - gsSPLight(&name.l[0],1), \ - gsSPLight(&name.l[1],2), \ - gsSPLight(&name.l[2],3), \ - gsSPLight(&name.l[3],4), \ - gsSPLight(&name.l[4],5), \ - gsSPLight(&name.l[5],6), \ - gsSPLight(&name.l[6],7), \ - gsSPLight(&name.a,8) - -/* - * Reflection/Hiliting Macros - */ -#ifdef F3DEX_GBI_2 -# define gSPLookAtX(pkt, l) \ - gDma2p((pkt),G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATX) -# define gsSPLookAtX(l) \ - gsDma2p( G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATX) -# define gSPLookAtY(pkt, l) \ - gDma2p((pkt),G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATY) -# define gsSPLookAtY(l) \ - gsDma2p( G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATY) -#else /* F3DEX_GBI_2 */ -# define gSPLookAtX(pkt, l) \ - gDma1p(pkt, G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATX) -# define gsSPLookAtX(l) \ - gsDma1p( G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATX) -# define gSPLookAtY(pkt, l) \ - gDma1p(pkt, G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATY) -# define gsSPLookAtY(l) \ - gsDma1p( G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATY) -#endif /* F3DEX_GBI_2 */ - -#define gSPLookAt(pkt, la) \ -{ \ - gSPLookAtX(pkt,la) \ - gSPLookAtY(pkt,(char *)(la)+16) \ -} -#define gsSPLookAt(la) \ - gsSPLookAtX(la), \ - gsSPLookAtY((char *)(la)+16) - -#define gDPSetHilite1Tile(pkt, tile, hilite, width, height) \ - gDPSetTileSize(pkt, tile, (hilite)->h.x1 & 0xfff, (hilite)->h.y1 & 0xfff, \ - ((((width)-1)*4)+(hilite)->h.x1) & 0xfff, ((((height)-1)*4)+(hilite)->h.y1) & 0xfff) - -#define gDPSetHilite2Tile(pkt, tile, hilite, width, height) \ - gDPSetTileSize(pkt, tile, (hilite)->h.x2 & 0xfff, (hilite)->h.y2 & 0xfff, \ - ((((width)-1)*4)+(hilite)->h.x2) & 0xfff, ((((height)-1)*4)+(hilite)->h.y2) & 0xfff) - - -/* - * FOG macros - * fm = z multiplier - * fo = z offset - * FOG FORMULA: alpha(fog) = (eyespace z) * fm + fo CLAMPED 0 to 255 - * note: (eyespace z) ranges -1 to 1 - * - * Alternate method of setting fog: - * min, max: range 0 to 1000: 0=nearplane, 1000=farplane - * min is where fog begins (usually less than max and often 0) - * max is where fog is thickest (usually 1000) - * - */ -#define gSPFogFactor(pkt, fm, fo) \ - gMoveWd(pkt, G_MW_FOG, G_MWO_FOG, \ - (_SHIFTL(fm,16,16) | _SHIFTL(fo,0,16))) - -#define gsSPFogFactor(fm, fo) \ - gsMoveWd(G_MW_FOG, G_MWO_FOG, \ - (_SHIFTL(fm,16,16) | _SHIFTL(fo,0,16))) - -#define gSPFogPosition(pkt, min, max) \ - gMoveWd(pkt, G_MW_FOG, G_MWO_FOG, \ - (_SHIFTL((128000/((max)-(min))),16,16) | \ - _SHIFTL(((500-(min))*256/((max)-(min))),0,16))) - -#define gsSPFogPosition(min, max) \ - gsMoveWd(G_MW_FOG, G_MWO_FOG, \ - (_SHIFTL((128000/((max)-(min))),16,16) | \ - _SHIFTL(((500-(min))*256/((max)-(min))),0,16))) - -#ifdef F3DEX_GBI_2 -/* - * Macros to turn texture on/off - */ -# define gSPTexture(pkt, s, t, level, tile, on) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8) | \ - _SHIFTL(BOWTIE_VAL,16,8) | \ - _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | \ - _SHIFTL((on),1,7)); \ - _g->words.w1 = (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)); \ -} -# define gsSPTexture(s, t, level, tile, on) \ -{{ \ - (_SHIFTL(G_TEXTURE,24,8) | _SHIFTL(BOWTIE_VAL,16,8) | \ - _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | _SHIFTL((on),1,7)),\ - (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)) \ -}} -/* - * Different version of SPTexture macro, has an additional parameter - * which is currently reserved in the microcode. - */ -# define gSPTextureL(pkt, s, t, level, xparam, tile, on) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8) | \ - _SHIFTL((xparam),16,8) | \ - _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | \ - _SHIFTL((on),1,7)); \ - _g->words.w1 = (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)); \ -} -# define gsSPTextureL(s, t, level, xparam, tile, on) \ -{{ \ - (_SHIFTL(G_TEXTURE,24,8) | _SHIFTL((xparam),16,8) | \ - _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | _SHIFTL((on),1,7)),\ - (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)) \ -}} -#else -/* - * Macros to turn texture on/off - */ -# define gSPTexture(pkt, s, t, level, tile, on) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL(BOWTIE_VAL,16,8)|\ - _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)| \ - _SHIFTL((on),0,8)); \ - _g->words.w1 = (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)); \ -} -# define gsSPTexture(s, t, level, tile, on) \ -{{ \ - (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL(BOWTIE_VAL,16,8)| \ - _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)|_SHIFTL((on),0,8)), \ - (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)) \ -}} -/* - * Different version of SPTexture macro, has an additional parameter - * which is currently reserved in the microcode. - */ -# define gSPTextureL(pkt, s, t, level, xparam, tile, on) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL((xparam),16,8)| \ - _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)| \ - _SHIFTL((on),0,8)); \ - _g->words.w1 = (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)); \ -} -# define gsSPTextureL(s, t, level, xparam, tile, on) \ -{{ \ - (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL((xparam),16,8)| \ - _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)|_SHIFTL((on),0,8)), \ - (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)) \ -}} -#endif - -#ifndef F3D_OLD -# define gSPPerspNormalize(pkt, s) gMoveWd(pkt, G_MW_PERSPNORM, 0, (s)) -# define gsSPPerspNormalize(s) gsMoveWd( G_MW_PERSPNORM, 0, (s)) -#else -# define gSPPerspNormalize(pkt, s) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_RDPHALF_1, 24, 8); \ - _g->words.w1 = (s); \ -} -# define gsSPPerspNormalize(s) \ -{{ \ - _SHIFTL(G_RDPHALF_1, 24, 8), \ - (s) \ -}} -#endif - -#ifdef F3DEX_GBI_2 -# define gSPPopMatrixN(pkt, n, num) gDma2p((pkt),G_POPMTX,(num)*64,64,2,0) -# define gsSPPopMatrixN(n, num) gsDma2p( G_POPMTX,(num)*64,64,2,0) -# define gSPPopMatrix(pkt, n) gSPPopMatrixN((pkt), (n), 1) -# define gsSPPopMatrix(n) gsSPPopMatrixN( (n), 1) -#else /* F3DEX_GBI_2 */ -# define gSPPopMatrix(pkt, n) gImmp1(pkt, G_POPMTX, n) -# define gsSPPopMatrix(n) gsImmp1( G_POPMTX, n) -#endif /* F3DEX_GBI_2 */ - -#define gSPEndDisplayList(pkt) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_ENDDL, 24, 8); \ - _g->words.w1 = 0; \ -} - -#define gsSPEndDisplayList() \ -{{ \ - _SHIFTL(G_ENDDL, 24, 8), 0 \ -}} - -#ifdef F3DEX_GBI_2 -/* - * One gSPGeometryMode(pkt,c,s) GBI is equal to these two GBIs. - * - * gSPClearGeometryMode(pkt,c) - * gSPSetGeometryMode(pkt,s) - * - * gSPLoadGeometryMode(pkt, word) sets GeometryMode directly. - */ -#define gSPGeometryMode(pkt, c, s) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - _g->words.w0 = _SHIFTL(G_GEOMETRYMODE,24,8)|_SHIFTL(~(u32)(c),0,24);\ - _g->words.w1 = (u32)(s); \ -} - -#define gsSPGeometryMode(c, s) \ -{{ \ - (_SHIFTL(G_GEOMETRYMODE,24,8)|_SHIFTL(~(u32)(c),0,24)),(u32)(s) \ -}} -#define gSPSetGeometryMode(pkt, word) gSPGeometryMode((pkt),0,(word)) -#define gsSPSetGeometryMode(word) gsSPGeometryMode(0,(word)) -#define gSPClearGeometryMode(pkt, word) gSPGeometryMode((pkt),(word),0) -#define gsSPClearGeometryMode(word) gsSPGeometryMode((word),0) -#define gSPLoadGeometryMode(pkt, word) gSPGeometryMode((pkt),-1,(word)) -#define gsSPLoadGeometryMode(word) gsSPGeometryMode(-1,(word)) -#define gsSPGeometryModeSetFirst(c, s) gsSPGeometryMode(c, s) -#else /* F3DEX_GBI_2 */ -#define gSPSetGeometryMode(pkt, word) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_SETGEOMETRYMODE, 24, 8); \ - _g->words.w1 = (unsigned int)(word); \ -} - -#define gsSPSetGeometryMode(word) \ -{{ \ - _SHIFTL(G_SETGEOMETRYMODE, 24, 8), (unsigned int)(word) \ -}} - -#define gSPClearGeometryMode(pkt, word) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8); \ - _g->words.w1 = (unsigned int)(word); \ -} - -#define gsSPClearGeometryMode(word) \ -{{ \ - _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8), (unsigned int)(word) \ -}} - -/* - * gsSPGeometryMode - * In Fast3DEX2 it is better to use this, as the RSP geometry mode - * is able to be set and cleared in a single command. - */ -#define gsSPGeometryMode(c, s) \ - gsSPClearGeometryMode(c), \ - gsSPSetGeometryMode(s) -#define gsSPGeometryModeSetFirst(c, s) \ - gsSPSetGeometryMode(s), \ - gsSPClearGeometryMode(c) -#endif /* F3DEX_GBI_2 */ - -#ifdef F3DEX_GBI_2 -#define gSPSetOtherMode(pkt, cmd, sft, len, data) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - _g->words.w0 = (_SHIFTL(cmd,24,8)|_SHIFTL(32-(sft)-(len),8,8)| \ - _SHIFTL((len)-1,0,8)); \ - _g->words.w1 = (unsigned int)(data); \ -} - -#define gsSPSetOtherMode(cmd, sft, len, data) \ -{{ \ - _SHIFTL(cmd,24,8)|_SHIFTL(32-(sft)-(len),8,8)|_SHIFTL((len)-1,0,8), \ - (unsigned int)(data) \ -}} -#else -#define gSPSetOtherMode(pkt, cmd, sft, len, data) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | \ - _SHIFTL(len, 0, 8)); \ - _g->words.w1 = (unsigned int)(data); \ -} - -#define gsSPSetOtherMode(cmd, sft, len, data) \ -{{ \ - _SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | _SHIFTL(len, 0, 8), \ - (unsigned int)(data) \ -}} -#endif - -/* - * RDP setothermode register commands - register shadowed in RSP - */ -#define gDPPipelineMode(pkt, mode) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_PIPELINE, 1, mode) -#define gsDPPipelineMode(mode) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_PIPELINE, 1, mode) - -#define gDPSetCycleType(pkt, type) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_CYCLETYPE, 2, type) -#define gsDPSetCycleType(type) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_CYCLETYPE, 2, type) - -#define gDPSetTexturePersp(pkt, type) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTPERSP, 1, type) -#define gsDPSetTexturePersp(type) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTPERSP, 1, type) - -#define gDPSetTextureDetail(pkt, type) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTDETAIL, 2, type) -#define gsDPSetTextureDetail(type) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTDETAIL, 2, type) - -#define gDPSetTextureLOD(pkt, type) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTLOD, 1, type) -#define gsDPSetTextureLOD(type) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTLOD, 1, type) - -#define gDPSetTextureLUT(pkt, type) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTLUT, 2, type) -#define gsDPSetTextureLUT(type) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTLUT, 2, type) - -#define gDPSetTextureFilter(pkt, type) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTFILT, 2, type) -#define gsDPSetTextureFilter(type) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTFILT, 2, type) - -#define gDPSetTextureConvert(pkt, type) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTCONV, 3, type) -#define gsDPSetTextureConvert(type) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTCONV, 3, type) - -#define gDPSetCombineKey(pkt, type) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_COMBKEY, 1, type) -#define gsDPSetCombineKey(type) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_COMBKEY, 1, type) - -#ifndef _HW_VERSION_1 -#define gDPSetColorDither(pkt, mode) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_RGBDITHER, 2, mode) -#define gsDPSetColorDither(mode) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_RGBDITHER, 2, mode) -#else -#define gDPSetColorDither(pkt, mode) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_COLORDITHER, 1, mode) -#define gsDPSetColorDither(mode) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_COLORDITHER, 1, mode) -#endif - -#ifndef _HW_VERSION_1 -#define gDPSetAlphaDither(pkt, mode) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode) -#define gsDPSetAlphaDither(mode) \ - gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode) -#endif - -/* 'blendmask' is not supported anymore. - * The bits are reserved for future use. - * Fri May 26 13:45:55 PDT 1995 - */ -#define gDPSetBlendMask(pkt, mask) gDPNoOp(pkt) -#define gsDPSetBlendMask(mask) gsDPNoOp() - -#define gDPSetAlphaCompare(pkt, type) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_ALPHACOMPARE, 2, type) -#define gsDPSetAlphaCompare(type) \ - gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_ALPHACOMPARE, 2, type) - -#define gDPSetDepthSource(pkt, src) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_ZSRCSEL, 1, src) -#define gsDPSetDepthSource(src) \ - gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_ZSRCSEL, 1, src) - -#define gDPSetRenderMode(pkt, c0, c1) \ - gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_RENDERMODE, 29, \ - (c0) | (c1)) -#define gsDPSetRenderMode(c0, c1) \ - gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_RENDERMODE, 29, \ - (c0) | (c1)) - -#define gSetImage(pkt, cmd, fmt, siz, width, i) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \ - _SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12); \ - _g->words.w1 = (uintptr_t)(i); \ -} - -#define gsSetImage(cmd, fmt, siz, width, i) \ -{{ \ - _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \ - _SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12), \ - (uintptr_t)(i) \ -}} - -#define gDPSetColorImage(pkt, f, s, w, i) gSetImage(pkt, G_SETCIMG, f, s, w, i) -#define gsDPSetColorImage(f, s, w, i) gsSetImage(G_SETCIMG, f, s, w, i) - - -/* use these for new code */ -#define gDPSetDepthImage(pkt, i) gSetImage(pkt, G_SETZIMG, 0, 0, 1, i) -#define gsDPSetDepthImage(i) gsSetImage(G_SETZIMG, 0, 0, 1, i) -/* kept for compatibility */ -#define gDPSetMaskImage(pkt, i) gDPSetDepthImage(pkt, i) -#define gsDPSetMaskImage(i) gsDPSetDepthImage(i) - -#define gDPSetTextureImage(pkt, f, s, w, i) gSetImage(pkt, G_SETTIMG, f, s, w, i) -#define gsDPSetTextureImage(f, s, w, i) gsSetImage(G_SETTIMG, f, s, w, i) - -/* - * RDP macros - */ - -#define gDPSetCombine(pkt, muxs0, muxs1) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24);\ - _g->words.w1 = (unsigned int)(muxs1); \ -} - -#define gsDPSetCombine(muxs0, muxs1) \ -{{ \ - _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24), \ - (unsigned int)(muxs1) \ -}} - -#define GCCc0w0(saRGB0, mRGB0, saA0, mA0) \ - (_SHIFTL((saRGB0), 20, 4) | _SHIFTL((mRGB0), 15, 5) | \ - _SHIFTL((saA0), 12, 3) | _SHIFTL((mA0), 9, 3)) - -#define GCCc1w0(saRGB1, mRGB1) \ - (_SHIFTL((saRGB1), 5, 4) | _SHIFTL((mRGB1), 0, 5)) - -#define GCCc0w1(sbRGB0, aRGB0, sbA0, aA0) \ - (_SHIFTL((sbRGB0), 28, 4) | _SHIFTL((aRGB0), 15, 3) | \ - _SHIFTL((sbA0), 12, 3) | _SHIFTL((aA0), 9, 3)) - -#define GCCc1w1(sbRGB1, saA1, mA1, aRGB1, sbA1, aA1) \ - (_SHIFTL((sbRGB1), 24, 4) | _SHIFTL((saA1), 21, 3) | \ - _SHIFTL((mA1), 18, 3) | _SHIFTL((aRGB1), 6, 3) | \ - _SHIFTL((sbA1), 3, 3) | _SHIFTL((aA1), 0, 3)) - -#define gDPSetCombineLERP(pkt, a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, \ - a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_SETCOMBINE, 24, 8) | \ - _SHIFTL(GCCc0w0(G_CCMUX_##a0, G_CCMUX_##c0, \ - G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \ - GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), \ - 0, 24); \ - _g->words.w1 = (unsigned int)(GCCc0w1(G_CCMUX_##b0, \ - G_CCMUX_##d0, \ - G_ACMUX_##Ab0, \ - G_ACMUX_##Ad0) | \ - GCCc1w1(G_CCMUX_##b1, \ - G_ACMUX_##Aa1, \ - G_ACMUX_##Ac1, \ - G_CCMUX_##d1, \ - G_ACMUX_##Ab1, \ - G_ACMUX_##Ad1)); \ -} - -#define gsDPSetCombineLERP(a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, \ - a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \ -{{ \ - _SHIFTL(G_SETCOMBINE, 24, 8) | \ - _SHIFTL(GCCc0w0(G_CCMUX_##a0, G_CCMUX_##c0, \ - G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \ - GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), 0, 24), \ - (unsigned int)(GCCc0w1(G_CCMUX_##b0, G_CCMUX_##d0, \ - G_ACMUX_##Ab0, G_ACMUX_##Ad0) | \ - GCCc1w1(G_CCMUX_##b1, G_ACMUX_##Aa1, \ - G_ACMUX_##Ac1, G_CCMUX_##d1, \ - G_ACMUX_##Ab1, G_ACMUX_##Ad1)) \ -}} - -/* - * SetCombineMode macros are NOT redunant. It allow the C preprocessor - * to substitute single parameter which includes commas in the token and - * rescan for higher parameter count macro substitution. - * - * eg. gsDPSetCombineMode(G_CC_MODULATE, G_CC_MODULATE) turns into - * gsDPSetCombineLERP(TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0, - * TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0) - */ - -#define gDPSetCombineMode(pkt, a, b) gDPSetCombineLERP(pkt, a, b) -#define gsDPSetCombineMode(a, b) gsDPSetCombineLERP(a, b) - -#define gDPSetColor(pkt, c, d) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(c, 24, 8); \ - _g->words.w1 = (unsigned int)(d); \ -} - -#define gsDPSetColor(c, d) \ -{{ \ - _SHIFTL(c, 24, 8), (unsigned int)(d) \ -}} - -#define DPRGBColor(pkt, cmd, r, g, b, a) \ - gDPSetColor(pkt, cmd, \ - (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | \ - _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8))) -#define sDPRGBColor(cmd, r, g, b, a) \ - gsDPSetColor(cmd, \ - (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | \ - _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8))) - -#define gDPSetEnvColor(pkt, r, g, b, a) \ - DPRGBColor(pkt, G_SETENVCOLOR, r,g,b,a) -#define gsDPSetEnvColor(r, g, b, a) \ - sDPRGBColor(G_SETENVCOLOR, r,g,b,a) -#define gDPSetBlendColor(pkt, r, g, b, a) \ - DPRGBColor(pkt, G_SETBLENDCOLOR, r,g,b,a) -#define gsDPSetBlendColor(r, g, b, a) \ - sDPRGBColor(G_SETBLENDCOLOR, r,g,b,a) -#define gDPSetFogColor(pkt, r, g, b, a) \ - DPRGBColor(pkt, G_SETFOGCOLOR, r,g,b,a) -#define gsDPSetFogColor(r, g, b, a) \ - sDPRGBColor(G_SETFOGCOLOR, r,g,b,a) -#define gDPSetFillColor(pkt, d) \ - gDPSetColor(pkt, G_SETFILLCOLOR, (d)) -#define gsDPSetFillColor(d) \ - gsDPSetColor(G_SETFILLCOLOR, (d)) - -#define gDPSetPrimDepth(pkt, z, dz) \ - gDPSetColor(pkt, G_SETPRIMDEPTH, \ - _SHIFTL(z, 16, 16) | _SHIFTL(dz, 0, 16)) -#define gsDPSetPrimDepth(z, dz) \ - gsDPSetColor(G_SETPRIMDEPTH, _SHIFTL(z, 16, 16) | \ - _SHIFTL(dz, 0, 16)) - -#define gDPSetPrimColor(pkt, m, l, r, g, b, a) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | \ - _SHIFTL(m, 8, 8) | _SHIFTL(l, 0, 8)); \ - _g->words.w1 = (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | \ - _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8)); \ -} - -#define gsDPSetPrimColor(m, l, r, g, b, a) \ -{{ \ - (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | _SHIFTL(m, 8, 8) | \ - _SHIFTL(l, 0, 8)), \ - (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | \ - _SHIFTL(a, 0, 8)) \ -}} - -/* - * gDPSetOtherMode (This is for expert user.) - * - * This command makes all othermode parameters set. - * Do not use this command in the same DL with another g*SPSetOtherMode DLs. - * - * [Usage] - * gDPSetOtherMode(pkt, modeA, modeB) - * - * 'modeA' is described all parameters of GroupA GBI command. - * 'modeB' is also described all parameters of GroupB GBI command. - * - * GroupA: - * gDPPipelineMode, gDPSetCycleType, gSPSetTexturePersp, - * gDPSetTextureDetail, gDPSetTextureLOD, gDPSetTextureLUT, - * gDPSetTextureFilter, gDPSetTextureConvert, gDPSetCombineKey, - * gDPSetColorDither, gDPSetAlphaDither - * - * GroupB: - * gDPSetAlphaCompare, gDPSetDepthSource, gDPSetRenderMode - * - * Use 'OR' operation to get modeA and modeB. - * - * modeA = G_PM_* | G_CYC_* | G_TP_* | G_TD_* | G_TL_* | G_TT_* | G_TF_* - * G_TC_* | G_CK_* | G_CD_* | G_AD_*; - * - * modeB = G_AC_* | G_ZS_* | G_RM_* | G_RM_*2; - */ -#define gDPSetOtherMode(pkt, mode0, mode1) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24);\ - _g->words.w1 = (unsigned int)(mode1); \ -} - -#define gsDPSetOtherMode(mode0, mode1) \ -{{ \ - _SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24), \ - (unsigned int)(mode1) \ -}} - -/* - * Texturing macros - */ - -/* These are also defined defined above for Sprite Microcode */ - -#define G_TX_LOADTILE 7 -#define G_TX_RENDERTILE 0 - -#define G_TX_NOMIRROR 0 -#define G_TX_WRAP 0 -#define G_TX_MIRROR 0x1 -#define G_TX_CLAMP 0x2 -#define G_TX_NOMASK 0 -#define G_TX_NOLOD 0 - - -#ifndef MAX -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif -/* - * Dxt is the inverse of the number of 64-bit words in a line of - * the texture being loaded using the load_block command. If - * there are any 1's to the right of the 11th fractional bit, - * dxt should be rounded up. The following macros accomplish - * this. The 4b macros are a special case since 4-bit textures - * are loaded as 8-bit textures. Dxt is fixed point 1.11. RJM - */ -#define G_TX_DXT_FRAC 11 - -/* - * For RCP 2.0, the maximum number of texels that can be loaded - * using a load_block command is 2048. In order to load the total - * 4kB of Tmem, change the texel size when loading to be G_IM_SIZ_16b, - * then change the tile to the proper texel size after the load. - * The g*DPLoadTextureBlock macros already do this, so this change - * will be transparent if you use these macros. If you use - * the g*DPLoadBlock macros directly, you will need to handle this - * tile manipulation yourself. RJM. - */ -#ifdef _HW_VERSION_1 -#define G_TX_LDBLK_MAX_TXL 4095 -#else -#define G_TX_LDBLK_MAX_TXL 2047 -#endif /* _HW_VERSION_1 */ - -#define TXL2WORDS(txls, b_txl) MAX(1, ((txls)*(b_txl)/8)) -#define CALC_DXT(width, b_txl) \ - (((1 << G_TX_DXT_FRAC) + TXL2WORDS(width, b_txl) - 1) / \ - TXL2WORDS(width, b_txl)) - -#define TXL2WORDS_4b(txls) MAX(1, ((txls)/16)) -#define CALC_DXT_4b(width) \ - (((1 << G_TX_DXT_FRAC) + TXL2WORDS_4b(width) - 1) / \ - TXL2WORDS_4b(width)) - -#define gDPLoadTileGeneric(pkt, c, tile, uls, ult, lrs, lrt) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(c, 24, 8) | _SHIFTL(uls, 12, 12) | \ - _SHIFTL(ult, 0, 12); \ - _g->words.w1 = _SHIFTL(tile, 24, 3) | _SHIFTL(lrs, 12, 12) | \ - _SHIFTL(lrt, 0, 12); \ -} - -#define gsDPLoadTileGeneric(c, tile, uls, ult, lrs, lrt) \ -{{ \ - _SHIFTL(c, 24, 8) | _SHIFTL(uls, 12, 12) | _SHIFTL(ult, 0, 12), \ - _SHIFTL(tile, 24, 3) | _SHIFTL(lrs, 12, 12) | _SHIFTL(lrt, 0, 12)\ -}} - -#define gDPSetTileSize(pkt, t, uls, ult, lrs, lrt) \ - gDPLoadTileGeneric(pkt, G_SETTILESIZE, t, uls, ult, lrs, lrt) -#define gsDPSetTileSize(t, uls, ult, lrs, lrt) \ - gsDPLoadTileGeneric(G_SETTILESIZE, t, uls, ult, lrs, lrt) -#define gDPLoadTile(pkt, t, uls, ult, lrs, lrt) \ - gDPLoadTileGeneric(pkt, G_LOADTILE, t, uls, ult, lrs, lrt) -#define gsDPLoadTile(t, uls, ult, lrs, lrt) \ - gsDPLoadTileGeneric(G_LOADTILE, t, uls, ult, lrs, lrt) - -#define gDPSetTile(pkt, fmt, siz, line, tmem, tile, palette, cmt, \ - maskt, shiftt, cms, masks, shifts) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_SETTILE, 24, 8) | _SHIFTL(fmt, 21, 3) |\ - _SHIFTL(siz, 19, 2) | _SHIFTL(line, 9, 9) | \ - _SHIFTL(tmem, 0, 9); \ - _g->words.w1 = _SHIFTL(tile, 24, 3) | _SHIFTL(palette, 20, 4) | \ - _SHIFTL(cmt, 18, 2) | _SHIFTL(maskt, 14, 4) | \ - _SHIFTL(shiftt, 10, 4) |_SHIFTL(cms, 8, 2) | \ - _SHIFTL(masks, 4, 4) | _SHIFTL(shifts, 0, 4); \ -} - -#define gsDPSetTile(fmt, siz, line, tmem, tile, palette, cmt, \ - maskt, shiftt, cms, masks, shifts) \ -{{ \ - (_SHIFTL(G_SETTILE, 24, 8) | _SHIFTL(fmt, 21, 3) | \ - _SHIFTL(siz, 19, 2) | _SHIFTL(line, 9, 9) | _SHIFTL(tmem, 0, 9)),\ - (_SHIFTL(tile, 24, 3) | _SHIFTL(palette, 20, 4) | \ - _SHIFTL(cmt, 18, 2) | _SHIFTL(maskt, 14, 4) | \ - _SHIFTL(shiftt, 10, 4) | _SHIFTL(cms, 8, 2) | \ - _SHIFTL(masks, 4, 4) | _SHIFTL(shifts, 0, 4)) \ -}} - -/* - * For RCP 2.0, the maximum number of texels that can be loaded - * using a load_block command is 2048. In order to load the total - * 4kB of Tmem, change the texel size when loading to be G_IM_SIZ_16b, - * then change the tile to the proper texel size after the load. - * The g*DPLoadTextureBlock macros already do this, so this change - * will be transparent if you use these macros. If you use - * the g*DPLoadBlock macros directly, you will need to handle this - * tile manipulation yourself. RJM. - */ -#define gDPLoadBlock(pkt, tile, uls, ult, lrs, dxt) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_LOADBLOCK, 24, 8) | \ - _SHIFTL(uls, 12, 12) | _SHIFTL(ult, 0, 12)); \ - _g->words.w1 = (_SHIFTL(tile, 24, 3) | \ - _SHIFTL((MIN(lrs,G_TX_LDBLK_MAX_TXL)), 12, 12) |\ - _SHIFTL(dxt, 0, 12)); \ -} - -#define gsDPLoadBlock(tile, uls, ult, lrs, dxt) \ -{{ \ - (_SHIFTL(G_LOADBLOCK, 24, 8) | _SHIFTL(uls, 12, 12) | \ - _SHIFTL(ult, 0, 12)), \ - (_SHIFTL(tile, 24, 3) | \ - _SHIFTL((MIN(lrs,G_TX_LDBLK_MAX_TXL)), 12, 12) | \ - _SHIFTL(dxt, 0, 12)) \ -}} - -#define gDPLoadTLUTCmd(pkt, tile, count) \ -{ \ - Gfx *_g = (Gfx *)pkt; \ - \ - _g->words.w0 = _SHIFTL(G_LOADTLUT, 24, 8); \ - _g->words.w1 = _SHIFTL((tile), 24, 3) | _SHIFTL((count), 14, 10);\ -} - -#define gsDPLoadTLUTCmd(tile, count) \ -{{ \ - _SHIFTL(G_LOADTLUT, 24, 8), \ - _SHIFTL((tile), 24, 3) | _SHIFTL((count), 14, 10) \ -}} - -#define gDPLoadTextureBlock(pkt, timg, fmt, siz, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ - gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ - 0 , cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT) -1, \ - CALC_DXT(width, siz##_BYTES)); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, siz, \ - (((width) * siz##_LINE_BYTES)+7)>>3, 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -#define gDPLoadTextureBlockYuv(pkt, timg, fmt, siz, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ - gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ - 0 , cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT) -1, \ - CALC_DXT(width, siz##_BYTES)); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, siz, \ - (((width) * 1)+7)>>3, 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -/* Load fix rww 27jun95 */ -/* The S at the end means odd lines are already word Swapped */ - -#define gDPLoadTextureBlockS(pkt, timg, fmt, siz, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ - gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ - 0 , cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1,0); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, siz, \ - (((width) * siz##_LINE_BYTES)+7)>>3, 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -/* - * Allow tmem address and render tile to be specified. - * The S at the end means odd lines are already word Swapped - */ -#define gDPLoadMultiBlockS(pkt, timg, tmem, rtile, fmt, siz, width, \ - height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ - gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ - 0 , cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1,0); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, siz, \ - (((width) * siz##_LINE_BYTES)+7)>>3, tmem, \ - rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, rtile, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - - -#define gDPLoadTextureBlockYuvS(pkt, timg, fmt, siz, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ - gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ - 0 , cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1,0); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, siz, \ - (((width) * 1)+7)>>3, 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -/* - * allows tmem address to be specified - */ -#define _gDPLoadTextureBlock(pkt, timg, tmem, fmt, siz, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ - gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ - 0, cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ - CALC_DXT(width, siz##_BYTES)); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES)+7)>>3, \ - tmem, G_TX_RENDERTILE, pal, cmt, \ - maskt, shiftt, cms, masks, shifts); \ - gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -/* - * allows tmem address and render tile to be specified - */ -#define _gDPLoadTextureBlockTile(pkt, timg, tmem, rtile, fmt, siz, width, \ - height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ - gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0,\ - cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ - CALC_DXT(width, siz##_BYTES)); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES)+7)>>3, \ - tmem, rtile, pal, cmt, \ - maskt, shiftt, cms, masks, shifts); \ - gDPSetTileSize(pkt, rtile, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -/* - * allows tmem address and render tile to be specified - */ -#define gDPLoadMultiBlock(pkt, timg, tmem, rtile, fmt, siz, width, \ - height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ - gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0,\ - cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ - CALC_DXT(width, siz##_BYTES)); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES)+7)>>3, \ - tmem, rtile, pal, cmt, \ - maskt, shiftt, cms, masks, shifts); \ - gDPSetTileSize(pkt, rtile, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -#define gsDPLoadTextureBlock(timg, fmt, siz, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ - gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, 0, \ - G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, \ - masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ - CALC_DXT(width, siz##_BYTES)), \ - gsDPPipeSync(), \ - gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES)+7)>>3), 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - -/* Here is the static form of the pre-swapped texture block loading */ -/* See gDPLoadTextureBlockS() for reference. Basically, just don't - calculate DxT, use 0 */ - -#define gsDPLoadTextureBlockS(timg, fmt, siz, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ - gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, 0 , \ - cmt, maskt,shiftt, cms, masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, 0 ),\ - gsDPPipeSync(), \ - gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES)+7)>>3), 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - -/* - * Allow tmem address to be specified - */ -#define _gsDPLoadTextureBlock(timg, tmem, fmt, siz, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ - gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ - 0 , cmt, maskt, shiftt, cms, masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ - CALC_DXT(width, siz##_BYTES)), \ - gsDPPipeSync(), \ - gsDPSetTile(fmt, siz, \ - ((((width) * siz##_LINE_BYTES)+7)>>3), tmem, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - - -/* - * Allow tmem address and render_tile to be specified - */ -#define _gsDPLoadTextureBlockTile(timg, tmem, rtile, fmt, siz, width, \ - height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ - gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ - 0 , cmt, maskt, shiftt, cms, masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ - CALC_DXT(width, siz##_BYTES)), \ - gsDPPipeSync(), \ - gsDPSetTile(fmt, siz, \ - ((((width) * siz##_LINE_BYTES)+7)>>3), tmem, \ - rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(rtile, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - - -/* - * Allow tmem address and render_tile to be specified, useful when loading - * mutilple tiles at a time. - */ -#define gsDPLoadMultiBlock(timg, tmem, rtile, fmt, siz, width, \ - height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ - gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ - 0 , cmt, maskt, shiftt, cms, masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ - CALC_DXT(width, siz##_BYTES)), \ - gsDPPipeSync(), \ - gsDPSetTile(fmt, siz, \ - ((((width) * siz##_LINE_BYTES)+7)>>3), tmem, \ - rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(rtile, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - -/* - * Allows tmem and render tile to be specified. Useful when loading - * several tiles at a time. - * - * Here is the static form of the pre-swapped texture block loading - * See gDPLoadTextureBlockS() for reference. Basically, just don't - * calculate DxT, use 0 - */ - -#define gsDPLoadMultiBlockS(timg, tmem, rtile, fmt, siz, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ - gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0 , \ - cmt, maskt,shiftt, cms, masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ - (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, 0 ),\ - gsDPPipeSync(), \ - gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES)+7)>>3), tmem,\ - rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(rtile, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - - -#define gDPLoadTextureBlock_4b(pkt, timg, fmt, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, \ - cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height)+3)>>2)-1, \ - CALC_DXT_4b(width)); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -/* Load fix rww 27jun95 */ -/* The S at the end means odd lines are already word Swapped */ - -#define gDPLoadTextureBlock_4bS(pkt, timg, fmt, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, \ - cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height)+3)>>2)-1, 0 ); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -/* - * 4-bit load block. Useful when loading multiple tiles - */ -#define gDPLoadMultiBlock_4b(pkt, timg, tmem, rtile, fmt, width, height,\ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, \ - cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height)+3)>>2)-1, \ - CALC_DXT_4b(width)); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ - rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, rtile, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -/* - * 4-bit load block. Allows tmem and render tile to be specified. Useful when - * loading multiple tiles. The S means odd lines are already word swapped. - */ -#define gDPLoadMultiBlock_4bS(pkt, timg, tmem, rtile, fmt, width, height,\ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, \ - cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height)+3)>>2)-1, 0 ); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ - rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, rtile, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - - -#define _gDPLoadTextureBlock_4b(pkt, timg, tmem, fmt, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, \ - cmt, maskt, shiftt, cms, masks, shifts); \ - gDPLoadSync(pkt); \ - gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ - (((width)*(height)+3)>>2)-1, \ - CALC_DXT_4b(width)); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ -} - -#define gsDPLoadTextureBlock_4b(timg, fmt, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ - gsDPSetTile(fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0 , cmt, \ - maskt, shiftt, cms, masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1, \ - CALC_DXT_4b(width)), \ - gsDPPipeSync(), \ - gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - -#define gsDPLoadTextureBlock_4bS(timg, fmt, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ - gsDPSetTile(fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0 , cmt, \ - maskt, shiftt, cms, masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1,0),\ - gsDPPipeSync(), \ - gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - -/* - * 4-bit load block. Allows tmem address and render tile to be specified. - * Useful when loading multiple tiles. - */ -#define gsDPLoadMultiBlock_4b(timg, tmem, rtile, fmt, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ - gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0 , cmt, \ - maskt, shiftt, cms, masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1, \ - CALC_DXT_4b(width)), \ - gsDPPipeSync(), \ - gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ - rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(rtile, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - - -/* - * 4-bit load block. Allows tmem address and render tile to be specified. - * Useful when loading multiple tiles. S means odd lines are already swapped. - */ -#define gsDPLoadMultiBlock_4bS(timg, tmem, rtile, fmt, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ - gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0 , cmt, \ - maskt, shiftt, cms, masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1,0),\ - gsDPPipeSync(), \ - gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ - rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(rtile, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - - -/* - * Allows tmem address to be specified - */ -#define _gsDPLoadTextureBlock_4b(timg, tmem, fmt, width, height, \ - pal, cms, cmt, masks, maskt, shifts, shiftt) \ - \ - gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ - gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0 , cmt, \ - maskt, shiftt, cms, masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1, \ - CALC_DXT_4b(width)), \ - gsDPPipeSync(), \ - gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ - ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ - ((height)-1) << G_TEXTURE_IMAGE_FRAC) - -#ifndef _HW_VERSION_1 - -#define gDPLoadTextureTile(pkt, timg, fmt, siz, width, height, \ - uls, ult, lrs, lrt, pal, \ - cms, cmt, masks, maskt, shifts, shiftt) \ -{ \ - gDPSetTextureImage(pkt, fmt, siz, width, timg); \ - gDPSetTile(pkt, fmt, siz, \ - (((((lrs)-(uls)+1) * siz##_TILE_BYTES)+7)>>3), 0, \ - G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPLoadSync(pkt); \ - gDPLoadTile( pkt, G_TX_LOADTILE, \ - (uls)<>3), 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, G_TX_RENDERTILE, \ - (uls)<>3), tmem, \ - G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPLoadSync(pkt); \ - gDPLoadTile( pkt, G_TX_LOADTILE, \ - (uls)<>3), tmem, \ - rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, rtile, \ - (uls)<>3), 0, \ - G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPLoadSync(), \ - gsDPLoadTile( G_TX_LOADTILE, \ - (uls)<>3), 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks,\ - shifts), \ - gsDPSetTileSize(G_TX_RENDERTILE, \ - (uls)<>3), \ - tmem, G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, \ - masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadTile( G_TX_LOADTILE, \ - (uls)<>3), \ - tmem, rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(rtile, \ - (uls)<>1), timg); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_8b, \ - (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ - G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPLoadSync(pkt); \ - gDPLoadTile( pkt, G_TX_LOADTILE, \ - (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ - (ult)<<(G_TEXTURE_IMAGE_FRAC), \ - (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ - (lrt)<<(G_TEXTURE_IMAGE_FRAC)); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ - (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, \ - masks, shifts); \ - gDPSetTileSize(pkt, G_TX_RENDERTILE, \ - (uls)<>1), timg); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_8b, \ - (((((lrs)-(uls)+1)>>1)+7)>>3), tmem, \ - G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPLoadSync(pkt); \ - gDPLoadTile( pkt, G_TX_LOADTILE, \ - (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ - (ult)<<(G_TEXTURE_IMAGE_FRAC), \ - (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ - (lrt)<<(G_TEXTURE_IMAGE_FRAC)); \ - gDPPipeSync(pkt); \ - gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ - (((((lrs)-(uls)+1)>>1)+7)>>3), tmem, \ - rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts); \ - gDPSetTileSize(pkt, rtile, \ - (uls)<>1), timg), \ - gsDPSetTile(fmt, G_IM_SIZ_8b, (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ - G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPLoadSync(), \ - gsDPLoadTile( G_TX_LOADTILE, \ - (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ - (ult)<<(G_TEXTURE_IMAGE_FRAC), \ - (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ - (lrt)<<(G_TEXTURE_IMAGE_FRAC)), \ - gsDPPipeSync(), \ - gsDPSetTile(fmt, G_IM_SIZ_4b, (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ - G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(G_TX_RENDERTILE, \ - (uls)<>1), timg), \ - gsDPSetTile(fmt, G_IM_SIZ_8b, (((((lrs)-(uls)+1)>>1)+7)>>3), \ - tmem, G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, \ - masks, shifts), \ - gsDPLoadSync(), \ - gsDPLoadTile( G_TX_LOADTILE, \ - (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ - (ult)<<(G_TEXTURE_IMAGE_FRAC), \ - (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ - (lrt)<<(G_TEXTURE_IMAGE_FRAC)), \ - gsDPPipeSync(), \ - gsDPSetTile(fmt, G_IM_SIZ_4b, (((((lrs)-(uls)+1)>>1)+7)>>3), \ - tmem, rtile, pal, cmt, maskt, shiftt, cms, masks, \ - shifts), \ - gsDPSetTileSize(rtile, \ - (uls)<words.w0 = _SHIFTL(G_SETSCISSOR, 24, 8) | \ - _SHIFTL((int)((float)(ulx)*4.0F), 12, 12) | \ - _SHIFTL((int)((float)(uly)*4.0F), 0, 12); \ - _g->words.w1 = _SHIFTL(mode, 24, 2) | \ - _SHIFTL((int)((float)(lrx)*4.0F), 12, 12) | \ - _SHIFTL((int)((float)(lry)*4.0F), 0, 12); \ -} - - -#define gDPSetScissorFrac(pkt, mode, ulx, uly, lrx, lry) \ -{ \ - Gfx *_g = (Gfx *)pkt; \ - \ - _g->words.w0 = _SHIFTL(G_SETSCISSOR, 24, 8) | \ - _SHIFTL((int)((ulx)), 12, 12) | \ - _SHIFTL((int)((uly)), 0, 12); \ - _g->words.w1 = _SHIFTL(mode, 24, 2) | \ - _SHIFTL((int)((lrx)), 12, 12) | \ - _SHIFTL((int)((lry)), 0, 12); \ -} - -#define gsDPSetScissor(mode, ulx, uly, lrx, lry) \ -{{ \ - _SHIFTL(G_SETSCISSOR, 24, 8) | \ - _SHIFTL((int)((float)(ulx)*4.0F), 12, 12) | \ - _SHIFTL((int)((float)(uly)*4.0F), 0, 12), \ - _SHIFTL(mode, 24, 2) | \ - _SHIFTL((int)((float)(lrx)*4.0F), 12, 12) | \ - _SHIFTL((int)((float)(lry)*4.0F), 0, 12) \ -}} - -#define gsDPSetScissorFrac(mode, ulx, uly, lrx, lry) \ -{{ \ - _SHIFTL(G_SETSCISSOR, 24, 8) | \ - _SHIFTL((int)((ulx)), 12, 12) | \ - _SHIFTL((int)((uly)), 0, 12), \ - _SHIFTL(mode, 24, 2) | \ - _SHIFTL((int)(lrx), 12, 12) | \ - _SHIFTL((int)(lry), 0, 12) \ -}} - -/* Fraction never used in fill */ -#ifdef F3DEX_GBI_2E -#define gDPFillRectangle(pkt, ulx, uly, lrx, lry) \ -{ \ - Gfx *_g0 = (Gfx *)(pkt), *_g1 = (Gfx *)(pkt); \ - _g0->words.w0 = _SHIFTL(G_FILLRECT, 24, 8) | \ - _SHIFTL((lrx), 2, 22); \ - _g0->words.w1 = _SHIFTL((lry), 2, 22); \ - _g1->words.w0 = _SHIFTL((ulx), 2, 22); \ - _g1->words.w1 = _SHIFTL((uly), 2, 22); \ -} -#define gsDPFillRectangle(ulx, uly, lrx, lry) \ -{{ \ - (_SHIFTL(G_FILLRECT, 24, 8) | _SHIFTL((lrx), 2, 22)), \ - _SHIFTL((lry), 2, 22), \ -}}, \ -{{ \ - _SHIFTL((ulx), 2, 22), \ - _SHIFTL((uly), 2, 22), \ -}} -#else -#define gDPFillRectangle(pkt, ulx, uly, lrx, lry) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_FILLRECT, 24, 8) | \ - _SHIFTL((lrx), 14, 10) | _SHIFTL((lry), 2, 10));\ - _g->words.w1 = (_SHIFTL((ulx), 14, 10) | _SHIFTL((uly), 2, 10));\ -} -#define gsDPFillRectangle(ulx, uly, lrx, lry) \ -{{ \ - (_SHIFTL(G_FILLRECT, 24, 8) | _SHIFTL((lrx), 14, 10) | \ - _SHIFTL((lry), 2, 10)), \ - (_SHIFTL((ulx), 14, 10) | _SHIFTL((uly), 2, 10)) \ -}} -#endif - -/* like gDPFillRectangle but accepts negative arguments */ -#ifndef F3DEX_GBI_2E -#define gDPScisFillRectangle(pkt, ulx, uly, lrx, lry) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_FILLRECT, 24, 8) | \ - _SHIFTL(MAX((lrx),0), 14, 10) | \ - _SHIFTL(MAX((lry),0), 2, 10)); \ - _g->words.w1 = (_SHIFTL(MAX((ulx),0), 14, 10) | \ - _SHIFTL(MAX((uly),0), 2, 10)); \ -} -#endif - -#define gDPSetConvert(pkt, k0, k1, k2, k3, k4, k5) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_SETCONVERT, 24, 8) | \ - _SHIFTL(k0, 13, 9) | _SHIFTL(k1, 4, 9) | \ - _SHIFTR(k2, 5, 4)); \ - _g->words.w1 = (_SHIFTL(k2, 27, 5) | _SHIFTL(k3, 18, 9) | \ - _SHIFTL(k4, 9, 9) | _SHIFTL(k5, 0, 9)); \ -} - -#define gsDPSetConvert(k0, k1, k2, k3, k4, k5) \ -{{ \ - (_SHIFTL(G_SETCONVERT, 24, 8) | \ - _SHIFTL(k0, 13, 9) | _SHIFTL(k1, 4, 9) | _SHIFTR(k2, 5, 4)), \ - (_SHIFTL(k2, 27, 5) | _SHIFTL(k3, 18, 9) | _SHIFTL(k4, 9, 9) | \ - _SHIFTL(k5, 0, 9)) \ -}} - -#define gDPSetKeyR(pkt, cR, sR, wR) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(G_SETKEYR, 24, 8); \ - _g->words.w1 = (_SHIFTL(wR, 16, 12) | _SHIFTL(cR, 8, 8) | \ - _SHIFTL(sR, 0, 8)); \ -} - -#define gsDPSetKeyR(cR, sR, wR) \ -{{ \ - _SHIFTL(G_SETKEYR, 24, 8), \ - _SHIFTL(wR, 16, 12) | _SHIFTL(cR, 8, 8) | _SHIFTL(sR, 0, 8) \ -}} - -#define gDPSetKeyGB(pkt, cG, sG, wG, cB, sB, wB) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_SETKEYGB, 24, 8) | \ - _SHIFTL(wG, 12, 12) | _SHIFTL(wB, 0, 12)); \ - _g->words.w1 = (_SHIFTL(cG, 24, 8) | _SHIFTL(sG, 16, 8) | \ - _SHIFTL(cB, 8, 8) | _SHIFTL(sB, 0, 8)); \ -} - -#define gsDPSetKeyGB(cG, sG, wG, cB, sB, wB) \ -{{ \ - (_SHIFTL(G_SETKEYGB, 24, 8) | _SHIFTL(wG, 12, 12) | \ - _SHIFTL(wB, 0, 12)), \ - (_SHIFTL(cG, 24, 8) | _SHIFTL(sG, 16, 8) | _SHIFTL(cB, 8, 8) | \ - _SHIFTL(sB, 0, 8)) \ -}} - -#define gDPNoParam(pkt, cmd) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(cmd, 24, 8); \ - _g->words.w1 = 0; \ -} - -#define gsDPNoParam(cmd) \ -{{ \ - _SHIFTL(cmd, 24, 8), 0 \ -}} - -#define gDPParam(pkt, cmd, param) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = _SHIFTL(cmd, 24, 8); \ - _g->words.w1 = (param); \ -} - -#define gsDPParam(cmd, param) \ -{{ \ - _SHIFTL(cmd, 24, 8), (param) \ -}} - -/* Notice that textured rectangles are 128-bit commands, therefore - * gsDPTextureRectangle() should not be used in display lists - * under normal circumstances (use gsSPTextureRectangle()). - * That is also why there is no gDPTextureRectangle() macros. - */ -#define gsDPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ -{{ \ - (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ - _SHIFTL(yh, 0, 12)), \ - (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)), \ -}}, \ -{{ \ - _SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), \ - _SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) \ -}} - -#define gDPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - if (pkt); \ - _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ - _SHIFTL(yh, 0, 12)); \ - _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ - _SHIFTL(yl, 0, 12)); \ - _g ++; \ - _g->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ - _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ -} - -#define gsDPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ -{{ \ - (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ - _SHIFTL(yh, 0, 12)), \ - (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)), \ -}}, \ -{{ \ - _SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), \ - _SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) \ -}} - -#define gDPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - if (pkt); \ - _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ - _SHIFTL(yh, 0, 12)); \ - _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ - _SHIFTL(yl, 0, 12)); \ - _g ++; \ - _g->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ - _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ -} - -#ifdef F3D_OLD -# define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ - _SHIFTL(yh, 0, 12)); \ - _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ - _SHIFTL(yl, 0, 12)); \ - gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \ - gImmp1(pkt, G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)));\ -} - -#define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ - {{(_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)),\ - (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12))}}, \ - gsImmp1(G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \ - gsImmp1(G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))) - -/* like gSPTextureRectangle but accepts negative position arguments */ -# define gSPScisTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | \ - _SHIFTL(MAX((s16)(xh),0), 12, 12) | \ - _SHIFTL(MAX((s16)(yh),0), 0, 12)); \ - _g->words.w1 = (_SHIFTL((tile), 24, 3) | \ - _SHIFTL(MAX((s16)(xl),0), 12, 12) | \ - _SHIFTL(MAX((s16)(yl),0), 0, 12)); \ - gImmp1(pkt, G_RDPHALF_2, \ - (_SHIFTL(((s) - \ - (((s16)(xl) < 0) ? \ - (((s16)(dsdx) < 0) ? \ - (MAX((((s16)(xl)*(s16)(dsdx))>>7),0)) : \ - (MIN((((s16)(xl)*(s16)(dsdx))>>7),0))) : 0)), \ - 16, 16) | \ - _SHIFTL(((t) - \ - (((yl) < 0) ? \ - (((s16)(dtdy) < 0) ? \ - (MAX((((s16)(yl)*(s16)(dtdy))>>7),0)) : \ - (MIN((((s16)(yl)*(s16)(dtdy))>>7),0))) : 0)), \ - 0, 16))); \ - gImmp1(pkt, G_RDPHALF_CONT, (_SHIFTL((dsdx), 16, 16) | \ - _SHIFTL((dtdy), 0, 16))); \ -} - -# define gsSPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ - {{(_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ - _SHIFTL(yh, 0, 12)), \ - (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12))}}, \ - gsImmp1(G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \ - gsImmp1(G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))) - -# define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) |\ - _SHIFTL(yh, 0, 12)); \ - _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ - _SHIFTL(yl, 0, 12)); \ - gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \ - gImmp1(pkt, G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))); \ -} -#elif defined(F3DEX_GBI_2E) -# define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ -{ \ - Gfx *_g0 = (Gfx *)(pkt), *_g1 = (Gfx *)(pkt), *_g2 = (Gfx *)(pkt); \ - \ - _g0->words.w0 = _SHIFTL(G_TEXRECT, 24, 8) | \ - _SHIFTL((xh), 0, 24); \ - _g0->words.w1 = _SHIFTL((yh), 0, 24); \ - _g1->words.w0 = (_SHIFTL(tile, 24, 3) | _SHIFTL((xl), 0, 24)); \ - _g1->words.w1 = _SHIFTL((yl), 0, 24); \ - _g2->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ - _g2->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ -} - -# define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ -{{ \ - (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL((xh), 0, 24)), \ - _SHIFTL((yh), 0, 24), \ -}}, \ -{{ \ - (_SHIFTL((tile), 24, 3) | _SHIFTL((xl), 0, 24)), \ - _SHIFTL((yl), 0, 24), \ -}}, \ -{{ \ - _SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), \ - _SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) \ -}} - -# define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ -{ \ - Gfx *_g0 = (Gfx *)(pkt), *_g1 = (Gfx *)(pkt), *_g2 = (Gfx *)(pkt); \ - \ - _g0->words.w0 = _SHIFTL(G_TEXRECTFLIP, 24, 8) | \ - _SHIFTL((xh), 0, 24); \ - _g0->words.w1 = _SHIFTL((yh), 0, 24); \ - _g1->words.w0 = (_SHIFTL(tile, 24, 3) | _SHIFTL((xl), 0, 24)); \ - _g1->words.w1 = _SHIFTL((yl), 0, 24); \ - _g2->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ - _g2->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ -} -#else -# define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ - _SHIFTL(yh, 0, 12)); \ - _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ - _SHIFTL(yl, 0, 12)); \ - gImmp1(pkt, G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \ - gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)));\ -} - -#define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ - {{(_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)),\ - (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12))}}, \ - gsImmp1(G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \ - gsImmp1(G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))) - -/* like gSPTextureRectangle but accepts negative position arguments */ -# define gSPScisTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | \ - _SHIFTL(MAX((s16)(xh),0), 12, 12) | \ - _SHIFTL(MAX((s16)(yh),0), 0, 12)); \ - _g->words.w1 = (_SHIFTL((tile), 24, 3) | \ - _SHIFTL(MAX((s16)(xl),0), 12, 12) | \ - _SHIFTL(MAX((s16)(yl),0), 0, 12)); \ - gImmp1(pkt, G_RDPHALF_1, \ - (_SHIFTL(((s) - \ - (((s16)(xl) < 0) ? \ - (((s16)(dsdx) < 0) ? \ - (MAX((((s16)(xl)*(s16)(dsdx))>>7),0)) : \ - (MIN((((s16)(xl)*(s16)(dsdx))>>7),0))) : 0)), \ - 16, 16) | \ - _SHIFTL(((t) - \ - (((yl) < 0) ? \ - (((s16)(dtdy) < 0) ? \ - (MAX((((s16)(yl)*(s16)(dtdy))>>7),0)) : \ - (MIN((((s16)(yl)*(s16)(dtdy))>>7),0))) : 0)), \ - 0, 16))); \ - gImmp1(pkt, G_RDPHALF_2, (_SHIFTL((dsdx), 16, 16) | \ - _SHIFTL((dtdy), 0, 16))); \ -} - -# define gsSPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ - {{(_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ - _SHIFTL(yh, 0, 12)), \ - (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12))}}, \ - gsImmp1(G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \ - gsImmp1(G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))) - -# define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) |\ - _SHIFTL(yh, 0, 12)); \ - _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ - _SHIFTL(yl, 0, 12)); \ - gImmp1(pkt, G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \ - gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))); \ -} #endif - -#define gsDPWord(wordhi, wordlo) \ - gsImmp1(G_RDPHALF_1, (uintptr_t)(wordhi)), \ - gsImmp1(G_RDPHALF_2, (uintptr_t)(wordlo)) - -#define gDPWord(pkt, wordhi, wordlo) \ -{ \ - Gfx *_g = (Gfx *)(pkt); \ - \ - gImmp1(pkt, G_RDPHALF_1, (uintptr_t)(wordhi)); \ - gImmp1(pkt, G_RDPHALF_2, (uintptr_t)(wordlo)); \ -} - -#define gDPFullSync(pkt) gDPNoParam(pkt, G_RDPFULLSYNC) -#define gsDPFullSync() gsDPNoParam(G_RDPFULLSYNC) -#define gDPTileSync(pkt) gDPNoParam(pkt, G_RDPTILESYNC) -#define gsDPTileSync() gsDPNoParam(G_RDPTILESYNC) -#define gDPPipeSync(pkt) gDPNoParam(pkt, G_RDPPIPESYNC) -#define gsDPPipeSync() gsDPNoParam(G_RDPPIPESYNC) -#define gDPLoadSync(pkt) gDPNoParam(pkt, G_RDPLOADSYNC) -#define gsDPLoadSync() gsDPNoParam(G_RDPLOADSYNC) -#define gDPNoOp(pkt) gDPNoParam(pkt, G_NOOP) -#define gsDPNoOp() gsDPNoParam(G_NOOP) -#define gDPNoOpTag(pkt, tag) gDPParam(pkt, G_NOOP, tag) -#define gsDPNoOpTag(tag) gsDPParam(G_NOOP, tag) - -#if defined(F3DZEX_GBI_2) || defined(F3DZEX_NON_GBI_2) || defined(L3DZEX_GBI) -#include "gbi-poslight.h" -#endif - -#endif /* _LANGUAGE_C */ - - -#endif /* _GBI_H_ */ diff --git a/include/n64/PR/gbi_f3dex3.h b/include/n64/PR/gbi_f3dex3.h new file mode 100644 index 0000000000..3dbc364414 --- /dev/null +++ b/include/n64/PR/gbi_f3dex3.h @@ -0,0 +1,5166 @@ +/* Modded GBI for use with F3DEX3 custom microcode. */ + +#include "mbi.h" + +#ifndef F3DEX3_H +#define F3DEX3_H + +#define F3DEX_GBI_2 1 +#define F3DEX_GBI_3 1 + +#ifdef REQUIRE_SEMICOLONS_AFTER_GBI_COMMANDS +/* OoT style, semicolons required after using macros, cleaner code. If modding +SM64, will have to fix a few places the codebase omits the semicolons. */ +#define _DW(macro) do {macro} while (0) +#else +/* SM64 style, semicolons optional, uglier code, will produce tens of thousands +of warnings if you use -Wpedantic. */ +#define _DW(macro) macro +#endif + +/* + * The following commands are the "generated" RDP commands; the user + * never sees them, the RSP microcode generates them. + * edge, shade, texture, zbuff bits: estz + */ +#define G_TRI_FILL 0xC8 /* fill triangle: 11001000 */ +#define G_TRI_SHADE 0xCC /* shade triangle: 11001100 */ +#define G_TRI_TXTR 0xCA /* texture triangle: 11001010 */ +#define G_TRI_SHADE_TXTR 0xCE /* shade, texture triangle: 11001110 */ +#define G_TRI_FILL_ZBUFF 0xC9 /* fill, zbuff triangle: 11001001 */ +#define G_TRI_SHADE_ZBUFF 0xCD /* shade, zbuff triangle: 11001101 */ +#define G_TRI_TXTR_ZBUFF 0xCB /* texture, zbuff triangle: 11001011 */ +#define G_TRI_SHADE_TXTR_ZBUFF 0xCF /* shade, txtr, zbuff trngl: 11001111 */ + +/* masks to create the above: */ +#define G_RDP_TRI_FILL_MASK 0x08 +#define G_RDP_TRI_SHADE_MASK 0x04 +#define G_RDP_TRI_TXTR_MASK 0x02 +#define G_RDP_TRI_ZBUFF_MASK 0x01 + +/* + * GBI commands in order + */ +/*#define G_SPECIAL_3 0xD3 no-op in F3DEX2 */ +/*#define G_SPECIAL_2 0xD4 no-op in F3DEX2 */ +/*#define G_SPECIAL_1 0xD5 triggered MVP recalculation, not supported in F3DEX3 */ +#define G_DMA_IO 0xD6 +#define G_TEXTURE 0xD7 +#define G_POPMTX 0xD8 +#define G_GEOMETRYMODE 0xD9 +#define G_MTX 0xDA +#define G_MOVEWORD 0xDB +#define G_MOVEMEM 0xDC +#define G_LOAD_UCODE 0xDD +#define G_DL 0xDE +#define G_ENDDL 0xDF +#define G_SPNOOP 0xE0 +#define G_RDPHALF_1 0xE1 +#define G_SETOTHERMODE_L 0xE2 +#define G_SETOTHERMODE_H 0xE3 +#define G_TEXRECT 0xE4 +#define G_TEXRECTFLIP 0xE5 +#define G_RDPLOADSYNC 0xE6 +#define G_RDPPIPESYNC 0xE7 +#define G_RDPTILESYNC 0xE8 +#define G_RDPFULLSYNC 0xE9 +#define G_SETKEYGB 0xEA +#define G_SETKEYR 0xEB +#define G_SETCONVERT 0xEC +#define G_SETSCISSOR 0xED +#define G_SETPRIMDEPTH 0xEE +#define G_RDPSETOTHERMODE 0xEF +#define G_LOADTLUT 0xF0 +#define G_RDPHALF_2 0xF1 +#define G_SETTILESIZE 0xF2 +#define G_LOADBLOCK 0xF3 +#define G_LOADTILE 0xF4 +#define G_SETTILE 0xF5 +#define G_FILLRECT 0xF6 +#define G_SETFILLCOLOR 0xF7 +#define G_SETFOGCOLOR 0xF8 +#define G_SETBLENDCOLOR 0xF9 +#define G_SETPRIMCOLOR 0xFA +#define G_SETENVCOLOR 0xFB +#define G_SETCOMBINE 0xFC +#define G_SETTIMG 0xFD +#define G_SETZIMG 0xFE +#define G_SETCIMG 0xFF +#define G_NOOP 0x00 +#define G_VTX 0x01 +#define G_MODIFYVTX 0x02 +#define G_CULLDL 0x03 +#define G_BRANCH_WZ 0x04 +#define G_TRI1 0x05 +#define G_TRI2 0x06 +#define G_QUAD 0x07 +#define G_TRISTRIP 0x08 /* = G_LINE3D was a no-op in F3DEX2, has been removed */ +#define G_TRIFAN 0x09 +#define G_LIGHTTORDP 0x0A +#define G_RELSEGMENT 0x0B + +/* names differ between F3DEX2 and F3DZEX */ +#define G_BRANCH_Z G_BRANCH_WZ +#define G_BRANCH_W G_BRANCH_WZ + +/* + * RSP command argument and misc defines + */ + +/* Maximum number of transformed vertices kept in buffer in RSP DMEM */ +#define G_MAX_VERTS 56 + +/* Maximum number of directional / point lights, not counting ambient */ +#define G_MAX_LIGHTS 9 + +/* Maximum number of display list commands loaded at once into RSP DMEM */ +#define G_INPUT_BUFFER_CMDS 21 + +/* + * flags for G_SETGEOMETRYMODE + * + * Note that flat shading, i.e. not G_SHADING_SMOOTH, sets shade RGB for all + * three verts to the value of the first vertex in the triangle. Shade alpha is + * still separate for each vertex, which is desired behavior for fog but not for + * any other F3DEX3 effects which use shade alpha. + */ +#define G_ZBUFFER 0x00000001 +#define G_TEXTURE_ENABLE 0x00000000 /* actually 2, but controlled by SPTexture */ +#define G_SHADE 0x00000004 +#define G_AMBOCCLUSION 0x00000040 +#define G_ATTROFFSET_Z_ENABLE 0x00000080 +#define G_ATTROFFSET_ST_ENABLE 0x00000100 +#define G_CULL_NEITHER 0x00000000 +#define G_CULL_FRONT 0x00000200 +#define G_CULL_BACK 0x00000400 +#define G_CULL_BOTH 0x00000600 /* useless but supported */ +#define G_PACKED_NORMALS 0x00000800 +#define G_LIGHTTOALPHA 0x00001000 +#define G_LIGHTING_SPECULAR 0x00002000 +#define G_FRESNEL_COLOR 0x00004000 +#define G_FRESNEL_ALPHA 0x00008000 +#define G_FOG 0x00010000 +#define G_LIGHTING 0x00020000 +#define G_TEXTURE_GEN 0x00040000 +#define G_TEXTURE_GEN_LINEAR 0x00080000 +#define G_LOD 0x00100000 /* Ignored by all F3DEX* variants */ +#define G_SHADING_SMOOTH 0x00200000 +#define G_LIGHTING_POSITIONAL 0x00400000 /* Ignored by F3DEX3, assumed always on */ +#define G_CLIPPING 0x00800000 /* Ignored by all F3DEX* variants */ + +/* See SPDisplayList / SPBranchList */ +#define G_DL_PUSH 0 +#define G_DL_NOPUSH 1 + +/* See SPMatrix */ +#define G_MTX_MODELVIEW 0x00 /* matrix types */ +#define G_MTX_PROJECTION 0x04 +#define G_MTX_MUL 0x00 /* concat or load */ +#define G_MTX_LOAD 0x02 +#define G_MTX_NOPUSH 0x00 /* push or not */ +#define G_MTX_PUSH 0x01 + +/* See SPNormalsMode */ +#define G_NORMALS_MODE_FAST 0x00 +#define G_NORMALS_MODE_AUTO 0x01 +#define G_NORMALS_MODE_MANUAL 0x02 + +/* See SPAlphaCompareCull */ +#define G_ALPHA_COMPARE_CULL_DISABLE 0 +#define G_ALPHA_COMPARE_CULL_BELOW 1 +#define G_ALPHA_COMPARE_CULL_ABOVE -1 + +/* + * MOVEMEM indices + * Each of these indexes an entry in a dmem table which points to an arbitrarily + * sized block of dmem in which to store the result of a DMA. + */ +#define G_MV_TEMPMTX0 0 /* for internal use by G_MTX multiply mode */ +#define G_MV_MMTX 2 +#define G_MV_TEMPMTX1 4 /* for internal use by G_MTX multiply mode */ +#define G_MV_VPMTX 6 +#define G_MV_VIEWPORT 8 +#define G_MV_LIGHT 10 +/* G_MV_POINT is no longer supported because the internal vertex format is no +longer a multiple of 8 (DMA word). This was not used in any command anyway. */ +/* G_MV_MATRIX is no longer supported because there is no MVP matrix in F3DEX3. */ +#define G_MV_PMTX G_MV_VPMTX /* backwards compatibility */ + +/* + * MOVEWORD indices + * Each of these indexes an entry in a dmem table which points to a word in dmem + * where an immediate word will be stored. + */ +#define G_MW_FX 0x00 /* replaces G_MW_MATRIX which is no longer supported */ +#define G_MW_NUMLIGHT 0x02 +/* nothing for 0x04; G_MW_CLIP is no longer supported */ +#define G_MW_SEGMENT 0x06 +#define G_MW_FOG 0x08 +#define G_MW_LIGHTCOL 0x0A +/* G_MW_FORCEMTX is no longer supported because there is no MVP matrix in F3DEX3. */ +/* G_MW_PERSPNORM is removed; perspective norm is now set via G_MW_FX. */ + +#define G_MW_HALFWORD_FLAG 0x8000 /* indicates store 2 bytes instead of 4 */ + +/* + * These are offsets from the address in the dmem table + */ +#define G_MWO_NUMLIGHT 0x00 +#define G_MWO_FOG 0x00 + +#define G_MWO_SEGMENT_0 0x00 +#define G_MWO_SEGMENT_1 0x01 +#define G_MWO_SEGMENT_2 0x02 +#define G_MWO_SEGMENT_3 0x03 +#define G_MWO_SEGMENT_4 0x04 +#define G_MWO_SEGMENT_5 0x05 +#define G_MWO_SEGMENT_6 0x06 +#define G_MWO_SEGMENT_7 0x07 +#define G_MWO_SEGMENT_8 0x08 +#define G_MWO_SEGMENT_9 0x09 +#define G_MWO_SEGMENT_A 0x0A +#define G_MWO_SEGMENT_B 0x0B +#define G_MWO_SEGMENT_C 0x0C +#define G_MWO_SEGMENT_D 0x0D +#define G_MWO_SEGMENT_E 0x0E +#define G_MWO_SEGMENT_F 0x0F + +/* These are deprecated and no longer needed. */ +#define G_MWO_aLIGHT_1 0x00 +#define G_MWO_bLIGHT_1 0x04 +#define G_MWO_aLIGHT_2 0x10 +#define G_MWO_bLIGHT_2 0x14 +#define G_MWO_aLIGHT_3 0x20 +#define G_MWO_bLIGHT_3 0x24 +#define G_MWO_aLIGHT_4 0x30 +#define G_MWO_bLIGHT_4 0x34 +#define G_MWO_aLIGHT_5 0x40 +#define G_MWO_bLIGHT_5 0x44 +#define G_MWO_aLIGHT_6 0x50 +#define G_MWO_bLIGHT_6 0x54 +#define G_MWO_aLIGHT_7 0x60 +#define G_MWO_bLIGHT_7 0x64 +#define G_MWO_aLIGHT_8 0x70 +#define G_MWO_bLIGHT_8 0x74 +#define G_MWO_aLIGHT_9 0x80 +#define G_MWO_bLIGHT_9 0x84 +#define G_MWO_aLIGHT_10 0x90 +#define G_MWO_bLIGHT_10 0x94 + +#define G_MWO_POINT_RGBA 0x10 +#define G_MWO_POINT_ST 0x14 +#define G_MWO_POINT_XYSCREEN 0x18 /* not recommended to use, won't work if */ +#define G_MWO_POINT_ZSCREEN 0x1C /* the tri gets clipped */ + +#define G_MWO_AO_AMBIENT 0x00 +#define G_MWO_AO_DIRECTIONAL 0x02 +#define G_MWO_AO_POINT 0x04 +#define G_MWO_PERSPNORM 0x06 +#define G_MWO_FRESNEL_SCALE 0x0C +#define G_MWO_FRESNEL_OFFSET 0x0E +#define G_MWO_ATTR_OFFSET_S 0x10 +#define G_MWO_ATTR_OFFSET_T 0x12 +#define G_MWO_ATTR_OFFSET_Z 0x14 +#define G_MWO_ALPHA_COMPARE_CULL 0x16 +#define G_MWO_NORMALS_MODE 0x18 + +/* + * RDP command argument defines + */ + +/* + * Coordinate shift values, number of bits of fraction + */ +#define G_TEXTURE_IMAGE_FRAC 2 +#define G_TEXTURE_SCALE_FRAC 16 +#define G_SCALE_FRAC 8 +#define G_ROTATE_FRAC 16 + +/* + * Maximum z-buffer value, used to initialize the z-buffer. + * Note : this number is NOT the viewport z-scale constant. + * See the comment next to G_MAXZ for more info. + */ +#define G_MAXFBZ 0x3FFF /* 3b exp, 11b mantissa */ + +#define GPACK_RGBA5551(r, g, b, a) \ + ((((r) << 8) & 0xF800) | \ + (((g) << 3) & 0x07C0) | \ + (((b) >> 2) & 0x003E) | \ + ((a) & 1)) + +#define GPACK_IA16(i, a) (((i) << 8) | (a)) + +#define GPACK_ZDZ(z, dz) (((z) << 2) | (dz)) + +/* + * G_SETIMG fmt: set image formats + */ +#define G_IM_FMT_RGBA 0 +#define G_IM_FMT_YUV 1 +#define G_IM_FMT_CI 2 +#define G_IM_FMT_IA 3 +#define G_IM_FMT_I 4 + +/* + * G_SETIMG siz: set image pixel size + */ +#define G_IM_SIZ_4b 0 +#define G_IM_SIZ_8b 1 +#define G_IM_SIZ_16b 2 +#define G_IM_SIZ_32b 3 +#define G_IM_SIZ_DD 5 + +#define G_IM_SIZ_4b_BYTES 0 +#define G_IM_SIZ_4b_TILE_BYTES G_IM_SIZ_4b_BYTES +#define G_IM_SIZ_4b_LINE_BYTES G_IM_SIZ_4b_BYTES + +#define G_IM_SIZ_8b_BYTES 1 +#define G_IM_SIZ_8b_TILE_BYTES G_IM_SIZ_8b_BYTES +#define G_IM_SIZ_8b_LINE_BYTES G_IM_SIZ_8b_BYTES + +#define G_IM_SIZ_16b_BYTES 2 +#define G_IM_SIZ_16b_TILE_BYTES G_IM_SIZ_16b_BYTES +#define G_IM_SIZ_16b_LINE_BYTES G_IM_SIZ_16b_BYTES + +#define G_IM_SIZ_32b_BYTES 4 +#define G_IM_SIZ_32b_TILE_BYTES 2 +#define G_IM_SIZ_32b_LINE_BYTES 2 + +#define G_IM_SIZ_4b_LOAD_BLOCK G_IM_SIZ_16b +#define G_IM_SIZ_8b_LOAD_BLOCK G_IM_SIZ_16b +#define G_IM_SIZ_16b_LOAD_BLOCK G_IM_SIZ_16b +#define G_IM_SIZ_32b_LOAD_BLOCK G_IM_SIZ_32b + +#define G_IM_SIZ_4b_SHIFT 2 +#define G_IM_SIZ_8b_SHIFT 1 +#define G_IM_SIZ_16b_SHIFT 0 +#define G_IM_SIZ_32b_SHIFT 0 + +#define G_IM_SIZ_4b_INCR 3 +#define G_IM_SIZ_8b_INCR 1 +#define G_IM_SIZ_16b_INCR 0 +#define G_IM_SIZ_32b_INCR 0 + +/* + * G_SETCOMBINE: color combine modes + */ +/* Color combiner constants: */ +#define G_CCMUX_COMBINED 0 +#define G_CCMUX_TEXEL0 1 +#define G_CCMUX_TEXEL1 2 +#define G_CCMUX_PRIMITIVE 3 +#define G_CCMUX_SHADE 4 +#define G_CCMUX_ENVIRONMENT 5 +#define G_CCMUX_CENTER 6 +#define G_CCMUX_SCALE 6 +#define G_CCMUX_COMBINED_ALPHA 7 +#define G_CCMUX_TEXEL0_ALPHA 8 +#define G_CCMUX_TEXEL1_ALPHA 9 +#define G_CCMUX_PRIMITIVE_ALPHA 10 +#define G_CCMUX_SHADE_ALPHA 11 +#define G_CCMUX_ENV_ALPHA 12 +#define G_CCMUX_LOD_FRACTION 13 +#define G_CCMUX_PRIM_LOD_FRAC 14 +#define G_CCMUX_NOISE 7 +#define G_CCMUX_K4 7 +#define G_CCMUX_K5 15 +#define G_CCMUX_1 6 +#define G_CCMUX_0 31 + +/* Alpha combiner constants: */ +#define G_ACMUX_COMBINED 0 +#define G_ACMUX_TEXEL0 1 +#define G_ACMUX_TEXEL1 2 +#define G_ACMUX_PRIMITIVE 3 +#define G_ACMUX_SHADE 4 +#define G_ACMUX_ENVIRONMENT 5 +#define G_ACMUX_LOD_FRACTION 0 +#define G_ACMUX_PRIM_LOD_FRAC 6 +#define G_ACMUX_1 6 +#define G_ACMUX_0 7 + +/* typical CC cycle 1 modes */ + +/* typical CC cycle 1 modes */ +#define G_CC_PRIMITIVE 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE +#define G_CC_SHADE 0, 0, 0, SHADE, 0, 0, 0, SHADE + +#define G_CC_MODULATEI TEXEL0, 0, SHADE, 0, 0, 0, 0, SHADE +#define G_CC_MODULATEIDECALA TEXEL0, 0, SHADE, 0, 0, 0, 0, TEXEL0 +#define G_CC_MODULATEIFADE TEXEL0, 0, SHADE, 0, 0, 0, 0, ENVIRONMENT + +#define G_CC_MODULATERGB G_CC_MODULATEI +#define G_CC_MODULATERGBDECALA G_CC_MODULATEIDECALA +#define G_CC_MODULATERGBFADE G_CC_MODULATEIFADE + +#define G_CC_MODULATEIA TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0 +#define G_CC_MODULATEIFADEA TEXEL0, 0, SHADE, 0, TEXEL0, 0, ENVIRONMENT, 0 + +#define G_CC_MODULATEFADE TEXEL0, 0, SHADE, 0, ENVIRONMENT, 0, TEXEL0, 0 + +#define G_CC_MODULATERGBA G_CC_MODULATEIA +#define G_CC_MODULATERGBFADEA G_CC_MODULATEIFADEA + +#define G_CC_MODULATEI_PRIM TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE +#define G_CC_MODULATEIA_PRIM TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0 +#define G_CC_MODULATEIDECALA_PRIM TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, TEXEL0 + +#define G_CC_MODULATERGB_PRIM G_CC_MODULATEI_PRIM +#define G_CC_MODULATERGBA_PRIM G_CC_MODULATEIA_PRIM +#define G_CC_MODULATERGBDECALA_PRIM G_CC_MODULATEIDECALA_PRIM + +#define G_CC_FADE SHADE, 0, ENVIRONMENT, 0, SHADE, 0, ENVIRONMENT, 0 +#define G_CC_FADEA TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0 + +#define G_CC_DECALRGB 0, 0, 0, TEXEL0, 0, 0, 0, SHADE +#define G_CC_DECALRGBA 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0 +#define G_CC_DECALFADE 0, 0, 0, TEXEL0, 0, 0, 0, ENVIRONMENT + +#define G_CC_DECALFADEA 0, 0, 0, TEXEL0, TEXEL0, 0, ENVIRONMENT, 0 + +#define G_CC_BLENDI ENVIRONMENT, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_BLENDIA ENVIRONMENT, SHADE, TEXEL0, SHADE, TEXEL0, 0, SHADE, 0 +#define G_CC_BLENDIDECALA ENVIRONMENT, SHADE, TEXEL0, SHADE, 0, 0, 0, TEXEL0 + +#define G_CC_BLENDRGBA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, SHADE +#define G_CC_BLENDRGBDECALA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_BLENDRGBFADEA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, ENVIRONMENT + +#define G_CC_ADDRGB TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_ADDRGBDECALA TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_ADDRGBFADE TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, ENVIRONMENT + +#define G_CC_REFLECTRGB ENVIRONMENT, 0, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_REFLECTRGBDECALA ENVIRONMENT, 0, TEXEL0, SHADE, 0, 0, 0, TEXEL0 + +#define G_CC_HILITERGB PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_HILITERGBA PRIMITIVE, SHADE, TEXEL0, SHADE, PRIMITIVE, SHADE, TEXEL0, SHADE +#define G_CC_HILITERGBDECALA PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, TEXEL0 + +#define G_CC_SHADEDECALA 0, 0, 0, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_SHADEFADEA 0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT + +#define G_CC_BLENDPE PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, SHADE, 0 +#define G_CC_BLENDPEDECALA PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, TEXEL0 + +/* oddball modes */ +#define _G_CC_BLENDPE ENVIRONMENT, PRIMITIVE, TEXEL0, PRIMITIVE, TEXEL0, 0, SHADE, 0 +#define _G_CC_BLENDPEDECALA ENVIRONMENT, PRIMITIVE, TEXEL0, PRIMITIVE, 0, 0, 0, TEXEL0 +#define _G_CC_TWOCOLORTEX PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE +/* used for 1-cycle sparse mip-maps, primitive color has color of lowest LOD */ +#define _G_CC_SPARSEST PRIMITIVE, TEXEL0, LOD_FRACTION, TEXEL0, PRIMITIVE, TEXEL0, LOD_FRACTION, TEXEL0 +#define G_CC_TEMPLERP TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0, TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0 + +/* typical CC cycle 1 modes, usually followed by other cycle 2 modes */ +#define G_CC_TRILERP TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0 +#define G_CC_INTERFERENCE TEXEL0, 0, TEXEL1, 0, TEXEL0, 0, TEXEL1, 0 + +/* + * One-cycle color convert operation + */ +#define G_CC_1CYUV2RGB TEXEL0, K4, K5, TEXEL0, 0, 0, 0, SHADE + +/* + * NOTE: YUV2RGB expects TF step1 color conversion to occur in 2nd clock. + * Therefore, CC looks for step1 results in TEXEL1 + */ +#define G_CC_YUV2RGB TEXEL1, K4, K5, TEXEL1, 0, 0, 0, 0 + +/* typical CC cycle 2 modes */ +#define G_CC_PASS2 0, 0, 0, COMBINED, 0, 0, 0, COMBINED +#define G_CC_MODULATEI2 COMBINED, 0, SHADE, 0, 0, 0, 0, SHADE +#define G_CC_MODULATEIA2 COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0 +#define G_CC_MODULATERGB2 G_CC_MODULATEI2 +#define G_CC_MODULATERGBA2 G_CC_MODULATEIA2 +#define G_CC_MODULATEI_PRIM2 COMBINED, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE +#define G_CC_MODULATEIA_PRIM2 COMBINED, 0, PRIMITIVE, 0, COMBINED, 0, PRIMITIVE, 0 +#define G_CC_MODULATERGB_PRIM2 G_CC_MODULATEI_PRIM2 +#define G_CC_MODULATERGBA_PRIM2 G_CC_MODULATEIA_PRIM2 +#define G_CC_DECALRGB2 0, 0, 0, COMBINED, 0, 0, 0, SHADE +/* + * ? +#define G_CC_DECALRGBA2 COMBINED, SHADE, COMBINED_ALPHA, SHADE, 0, 0, 0, SHADE +*/ +#define G_CC_BLENDI2 ENVIRONMENT, SHADE, COMBINED, SHADE, 0, 0, 0, SHADE +#define G_CC_BLENDIA2 ENVIRONMENT, SHADE, COMBINED, SHADE, COMBINED, 0, SHADE, 0 +#define G_CC_CHROMA_KEY2 TEXEL0, CENTER, SCALE, 0, 0, 0, 0, 0 +#define G_CC_HILITERGB2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, SHADE +#define G_CC_HILITERGBA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, ENVIRONMENT, COMBINED, TEXEL0, COMBINED +#define G_CC_HILITERGBDECALA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, TEXEL0 +#define G_CC_HILITERGBPASSA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, COMBINED + + +/* + * One-cycle color convert operation + */ +#define G_CC_1CYUV2RGB TEXEL0, K4, K5, TEXEL0, 0, 0, 0, SHADE + +/* + * NOTE: YUV2RGB expects TF step1 color conversion to occur in 2nd clock. + * Therefore, CC looks for step1 results in TEXEL1 + */ +#define G_CC_YUV2RGB TEXEL1, K4, K5, TEXEL1, 0, 0, 0, 0 + +/* typical CC cycle 2 modes */ +#define G_CC_PASS2 0, 0, 0, COMBINED, 0, 0, 0, COMBINED +#define G_CC_MODULATEI2 COMBINED, 0, SHADE, 0, 0, 0, 0, SHADE +#define G_CC_MODULATEIA2 COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0 +#define G_CC_MODULATERGB2 G_CC_MODULATEI2 +#define G_CC_MODULATERGBA2 G_CC_MODULATEIA2 +#define G_CC_MODULATEI_PRIM2 COMBINED, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE +#define G_CC_MODULATEIA_PRIM2 COMBINED, 0, PRIMITIVE, 0, COMBINED, 0, PRIMITIVE, 0 +#define G_CC_MODULATERGB_PRIM2 G_CC_MODULATEI_PRIM2 +#define G_CC_MODULATERGBA_PRIM2 G_CC_MODULATEIA_PRIM2 +#define G_CC_DECALRGB2 0, 0, 0, COMBINED, 0, 0, 0, SHADE +/* + * ? +#define G_CC_DECALRGBA2 COMBINED, SHADE, COMBINED_ALPHA, SHADE, 0, 0, 0, SHADE +*/ +#define G_CC_BLENDI2 ENVIRONMENT, SHADE, COMBINED, SHADE, 0, 0, 0, SHADE +#define G_CC_BLENDIA2 ENVIRONMENT, SHADE, COMBINED, SHADE, COMBINED, 0, SHADE, 0 +#define G_CC_CHROMA_KEY2 TEXEL0, CENTER, SCALE, 0, 0, 0, 0, 0 +#define G_CC_HILITERGB2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, SHADE +#define G_CC_HILITERGBA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, ENVIRONMENT, COMBINED, TEXEL0, COMBINED +#define G_CC_HILITERGBDECALA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, TEXEL0 +#define G_CC_HILITERGBPASSA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, COMBINED + +/* + * G_SETOTHERMODE_L sft: shift count + */ +#define G_MDSFT_ALPHACOMPARE 0 +#define G_MDSFT_ZSRCSEL 2 +#define G_MDSFT_RENDERMODE 3 +#define G_MDSFT_BLENDER 16 + +/* + * G_SETOTHERMODE_H sft: shift count + */ +#define G_MDSFT_ALPHADITHER 4 +#define G_MDSFT_RGBDITHER 6 +#define G_MDSFT_COMBKEY 8 +#define G_MDSFT_TEXTCONV 9 +#define G_MDSFT_TEXTFILT 12 +#define G_MDSFT_TEXTLUT 14 +#define G_MDSFT_TEXTLOD 16 +#define G_MDSFT_TEXTDETAIL 17 +#define G_MDSFT_TEXTPERSP 19 +#define G_MDSFT_CYCLETYPE 20 +#define G_MDSFT_COLORDITHER 22 /* Needed for OoT ucode_disas even though HW 1.0 only */ +#define G_MDSFT_PIPELINE 23 + +/* G_SETOTHERMODE_H gPipelineMode */ +#define G_PM_1PRIMITIVE (1 << G_MDSFT_PIPELINE) +#define G_PM_NPRIMITIVE (0 << G_MDSFT_PIPELINE) + +/* G_SETOTHERMODE_H gSetCycleType */ +#define G_CYC_1CYCLE (0 << G_MDSFT_CYCLETYPE) +#define G_CYC_2CYCLE (1 << G_MDSFT_CYCLETYPE) +#define G_CYC_COPY (2 << G_MDSFT_CYCLETYPE) +#define G_CYC_FILL (3 << G_MDSFT_CYCLETYPE) + +/* G_SETOTHERMODE_H gSetTexturePersp */ +#define G_TP_NONE (0 << G_MDSFT_TEXTPERSP) +#define G_TP_PERSP (1 << G_MDSFT_TEXTPERSP) + +/* G_SETOTHERMODE_H gSetTextureDetail */ +#define G_TD_CLAMP (0 << G_MDSFT_TEXTDETAIL) +#define G_TD_SHARPEN (1 << G_MDSFT_TEXTDETAIL) +#define G_TD_DETAIL (2 << G_MDSFT_TEXTDETAIL) + +/* G_SETOTHERMODE_H gSetTextureLOD */ +#define G_TL_TILE (0 << G_MDSFT_TEXTLOD) +#define G_TL_LOD (1 << G_MDSFT_TEXTLOD) + +/* G_SETOTHERMODE_H gSetTextureLUT */ +#define G_TT_NONE (0 << G_MDSFT_TEXTLUT) +#define G_TT_RGBA16 (2 << G_MDSFT_TEXTLUT) +#define G_TT_IA16 (3 << G_MDSFT_TEXTLUT) + +/* G_SETOTHERMODE_H gSetTextureFilter */ +#define G_TF_POINT (0 << G_MDSFT_TEXTFILT) +#define G_TF_AVERAGE (3 << G_MDSFT_TEXTFILT) +#define G_TF_BILERP (2 << G_MDSFT_TEXTFILT) + +/* G_SETOTHERMODE_H gSetTextureConvert */ +#define G_TC_CONV (0 << G_MDSFT_TEXTCONV) +#define G_TC_FILTCONV (5 << G_MDSFT_TEXTCONV) +#define G_TC_FILT (6 << G_MDSFT_TEXTCONV) + +/* G_SETOTHERMODE_H gSetCombineKey */ +#define G_CK_NONE (0 << G_MDSFT_COMBKEY) +#define G_CK_KEY (1 << G_MDSFT_COMBKEY) + +/* G_SETOTHERMODE_H gSetColorDither */ +#define G_CD_MAGICSQ (0 << G_MDSFT_RGBDITHER) +#define G_CD_BAYER (1 << G_MDSFT_RGBDITHER) +#define G_CD_NOISE (2 << G_MDSFT_RGBDITHER) +#define G_CD_DISABLE (3 << G_MDSFT_RGBDITHER) + +/* G_SETOTHERMODE_H gSetAlphaDither */ +#define G_AD_PATTERN (0 << G_MDSFT_ALPHADITHER) +#define G_AD_NOTPATTERN (1 << G_MDSFT_ALPHADITHER) +#define G_AD_NOISE (2 << G_MDSFT_ALPHADITHER) +#define G_AD_DISABLE (3 << G_MDSFT_ALPHADITHER) + +/* G_SETOTHERMODE_L gSetAlphaCompare */ +#define G_AC_NONE (0 << G_MDSFT_ALPHACOMPARE) +#define G_AC_THRESHOLD (1 << G_MDSFT_ALPHACOMPARE) +#define G_AC_DITHER (3 << G_MDSFT_ALPHACOMPARE) + +/* G_SETOTHERMODE_L gSetDepthSource */ +#define G_ZS_PIXEL (0 << G_MDSFT_ZSRCSEL) +#define G_ZS_PRIM (1 << G_MDSFT_ZSRCSEL) + +/* G_SETOTHERMODE_L gSetRenderMode */ +#define AA_EN 0x0008 +#define Z_CMP 0x0010 +#define Z_UPD 0x0020 +#define IM_RD 0x0040 +#define CLR_ON_CVG 0x0080 +#define CVG_DST_CLAMP 0x0000 +#define CVG_DST_WRAP 0x0100 +#define CVG_DST_FULL 0x0200 +#define CVG_DST_SAVE 0x0300 +#define ZMODE_OPA 0x0000 +#define ZMODE_INTER 0x0400 +#define ZMODE_XLU 0x0800 +#define ZMODE_DEC 0x0C00 +#define CVG_X_ALPHA 0x1000 +#define ALPHA_CVG_SEL 0x2000 +#define FORCE_BL 0x4000 +#define TEX_EDGE 0x0000 /* used to be 0x8000 */ + +#define G_BL_CLR_IN 0 +#define G_BL_CLR_MEM 1 +#define G_BL_CLR_BL 2 +#define G_BL_CLR_FOG 3 +#define G_BL_1MA 0 +#define G_BL_A_MEM 1 +#define G_BL_A_IN 0 +#define G_BL_A_FOG 1 +#define G_BL_A_SHADE 2 +#define G_BL_1 2 +#define G_BL_0 3 + +#define GBL_c1(m1a, m1b, m2a, m2b) \ + (m1a) << 30 | (m1b) << 26 | (m2a) << 22 | (m2b) << 18 +#define GBL_c2(m1a, m1b, m2a, m2b) \ + (m1a) << 28 | (m1b) << 24 | (m2a) << 20 | (m2b) << 16 + +#define RM_AA_ZB_OPA_SURF(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_ZB_OPA_SURF(clk) \ + AA_EN | Z_CMP | Z_UPD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_XLU_SURF(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ + FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_OPA_DECAL(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | ALPHA_CVG_SEL | \ + ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_ZB_OPA_DECAL(clk) \ + AA_EN | Z_CMP | CVG_DST_WRAP | ALPHA_CVG_SEL | \ + ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_XLU_DECAL(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ + FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_OPA_INTER(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + ALPHA_CVG_SEL | ZMODE_INTER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_ZB_OPA_INTER(clk) \ + AA_EN | Z_CMP | Z_UPD | CVG_DST_CLAMP | \ + ALPHA_CVG_SEL | ZMODE_INTER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_XLU_INTER(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ + FORCE_BL | ZMODE_INTER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_XLU_LINE(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_DEC_LINE(clk) \ + AA_EN | Z_CMP | IM_RD | CVG_DST_SAVE | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_TEX_EDGE(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_TEX_INTER(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_INTER | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_SUB_SURF(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_PCL_SURF(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_OPA_TERR(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_TEX_TERR(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_SUB_TERR(clk) \ + AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + + +#define RM_AA_OPA_SURF(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_OPA_SURF(clk) \ + AA_EN | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_XLU_SURF(clk) \ + AA_EN | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | FORCE_BL | \ + ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_XLU_LINE(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_DEC_LINE(clk) \ + AA_EN | IM_RD | CVG_DST_FULL | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_TEX_EDGE(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_SUB_SURF(clk) \ + AA_EN | IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_PCL_SURF(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_OPA_TERR(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_TEX_TERR(clk) \ + AA_EN | IM_RD | CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_SUB_TERR(clk) \ + AA_EN | IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + + +#define RM_ZB_OPA_SURF(clk) \ + Z_CMP | Z_UPD | CVG_DST_FULL | ALPHA_CVG_SEL | \ + ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_ZB_XLU_SURF(clk) \ + Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_OPA_DECAL(clk) \ + Z_CMP | CVG_DST_FULL | ALPHA_CVG_SEL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_ZB_XLU_DECAL(clk) \ + Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_CLD_SURF(clk) \ + Z_CMP | IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_OVL_SURF(clk) \ + Z_CMP | IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_PCL_SURF(clk) \ + Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | \ + G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + + +#define RM_OPA_SURF(clk) \ + CVG_DST_CLAMP | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +#define RM_XLU_SURF(clk) \ + IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_TEX_EDGE(clk) \ + CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | FORCE_BL | \ + ZMODE_OPA | TEX_EDGE | AA_EN | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +#define RM_CLD_SURF(clk) \ + IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_PCL_SURF(clk) \ + CVG_DST_FULL | FORCE_BL | ZMODE_OPA | \ + G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +#define RM_ADD(clk) \ + IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_FOG, G_BL_CLR_MEM, G_BL_1) + +#define RM_NOOP(clk) \ + GBL_c##clk(0, 0, 0, 0) + +#define RM_VISCVG(clk) \ + IM_RD | FORCE_BL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_BL, G_BL_A_MEM) + +/* for rendering to an 8-bit framebuffer */ +#define RM_OPA_CI(clk) \ + CVG_DST_CLAMP | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +/* Custom version of RM_AA_ZB_XLU_SURF with Z_UPD */ +#define RM_CUSTOM_AA_ZB_XLU_SURF(clk) \ + RM_AA_ZB_XLU_SURF(clk) | Z_UPD + +#define G_RM_CUSTOM_AA_ZB_XLU_SURF RM_CUSTOM_AA_ZB_XLU_SURF(1) +#define G_RM_CUSTOM_AA_ZB_XLU_SURF2 RM_CUSTOM_AA_ZB_XLU_SURF(2) + +#define G_RM_AA_ZB_OPA_SURF RM_AA_ZB_OPA_SURF(1) +#define G_RM_AA_ZB_OPA_SURF2 RM_AA_ZB_OPA_SURF(2) +#define G_RM_AA_ZB_XLU_SURF RM_AA_ZB_XLU_SURF(1) +#define G_RM_AA_ZB_XLU_SURF2 RM_AA_ZB_XLU_SURF(2) +#define G_RM_AA_ZB_OPA_DECAL RM_AA_ZB_OPA_DECAL(1) +#define G_RM_AA_ZB_OPA_DECAL2 RM_AA_ZB_OPA_DECAL(2) +#define G_RM_AA_ZB_XLU_DECAL RM_AA_ZB_XLU_DECAL(1) +#define G_RM_AA_ZB_XLU_DECAL2 RM_AA_ZB_XLU_DECAL(2) +#define G_RM_AA_ZB_OPA_INTER RM_AA_ZB_OPA_INTER(1) +#define G_RM_AA_ZB_OPA_INTER2 RM_AA_ZB_OPA_INTER(2) +#define G_RM_AA_ZB_XLU_INTER RM_AA_ZB_XLU_INTER(1) +#define G_RM_AA_ZB_XLU_INTER2 RM_AA_ZB_XLU_INTER(2) +#define G_RM_AA_ZB_XLU_LINE RM_AA_ZB_XLU_LINE(1) +#define G_RM_AA_ZB_XLU_LINE2 RM_AA_ZB_XLU_LINE(2) +#define G_RM_AA_ZB_DEC_LINE RM_AA_ZB_DEC_LINE(1) +#define G_RM_AA_ZB_DEC_LINE2 RM_AA_ZB_DEC_LINE(2) +#define G_RM_AA_ZB_TEX_EDGE RM_AA_ZB_TEX_EDGE(1) +#define G_RM_AA_ZB_TEX_EDGE2 RM_AA_ZB_TEX_EDGE(2) +#define G_RM_AA_ZB_TEX_INTER RM_AA_ZB_TEX_INTER(1) +#define G_RM_AA_ZB_TEX_INTER2 RM_AA_ZB_TEX_INTER(2) +#define G_RM_AA_ZB_SUB_SURF RM_AA_ZB_SUB_SURF(1) +#define G_RM_AA_ZB_SUB_SURF2 RM_AA_ZB_SUB_SURF(2) +#define G_RM_AA_ZB_PCL_SURF RM_AA_ZB_PCL_SURF(1) +#define G_RM_AA_ZB_PCL_SURF2 RM_AA_ZB_PCL_SURF(2) +#define G_RM_AA_ZB_OPA_TERR RM_AA_ZB_OPA_TERR(1) +#define G_RM_AA_ZB_OPA_TERR2 RM_AA_ZB_OPA_TERR(2) +#define G_RM_AA_ZB_TEX_TERR RM_AA_ZB_TEX_TERR(1) +#define G_RM_AA_ZB_TEX_TERR2 RM_AA_ZB_TEX_TERR(2) +#define G_RM_AA_ZB_SUB_TERR RM_AA_ZB_SUB_TERR(1) +#define G_RM_AA_ZB_SUB_TERR2 RM_AA_ZB_SUB_TERR(2) + +#define G_RM_RA_ZB_OPA_SURF RM_RA_ZB_OPA_SURF(1) +#define G_RM_RA_ZB_OPA_SURF2 RM_RA_ZB_OPA_SURF(2) +#define G_RM_RA_ZB_OPA_DECAL RM_RA_ZB_OPA_DECAL(1) +#define G_RM_RA_ZB_OPA_DECAL2 RM_RA_ZB_OPA_DECAL(2) +#define G_RM_RA_ZB_OPA_INTER RM_RA_ZB_OPA_INTER(1) +#define G_RM_RA_ZB_OPA_INTER2 RM_RA_ZB_OPA_INTER(2) + +#define G_RM_AA_OPA_SURF RM_AA_OPA_SURF(1) +#define G_RM_AA_OPA_SURF2 RM_AA_OPA_SURF(2) +#define G_RM_AA_XLU_SURF RM_AA_XLU_SURF(1) +#define G_RM_AA_XLU_SURF2 RM_AA_XLU_SURF(2) +#define G_RM_AA_XLU_LINE RM_AA_XLU_LINE(1) +#define G_RM_AA_XLU_LINE2 RM_AA_XLU_LINE(2) +#define G_RM_AA_DEC_LINE RM_AA_DEC_LINE(1) +#define G_RM_AA_DEC_LINE2 RM_AA_DEC_LINE(2) +#define G_RM_AA_TEX_EDGE RM_AA_TEX_EDGE(1) +#define G_RM_AA_TEX_EDGE2 RM_AA_TEX_EDGE(2) +#define G_RM_AA_SUB_SURF RM_AA_SUB_SURF(1) +#define G_RM_AA_SUB_SURF2 RM_AA_SUB_SURF(2) +#define G_RM_AA_PCL_SURF RM_AA_PCL_SURF(1) +#define G_RM_AA_PCL_SURF2 RM_AA_PCL_SURF(2) +#define G_RM_AA_OPA_TERR RM_AA_OPA_TERR(1) +#define G_RM_AA_OPA_TERR2 RM_AA_OPA_TERR(2) +#define G_RM_AA_TEX_TERR RM_AA_TEX_TERR(1) +#define G_RM_AA_TEX_TERR2 RM_AA_TEX_TERR(2) +#define G_RM_AA_SUB_TERR RM_AA_SUB_TERR(1) +#define G_RM_AA_SUB_TERR2 RM_AA_SUB_TERR(2) + +#define G_RM_RA_OPA_SURF RM_RA_OPA_SURF(1) +#define G_RM_RA_OPA_SURF2 RM_RA_OPA_SURF(2) + +#define G_RM_ZB_OPA_SURF RM_ZB_OPA_SURF(1) +#define G_RM_ZB_OPA_SURF2 RM_ZB_OPA_SURF(2) +#define G_RM_ZB_XLU_SURF RM_ZB_XLU_SURF(1) +#define G_RM_ZB_XLU_SURF2 RM_ZB_XLU_SURF(2) +#define G_RM_ZB_OPA_DECAL RM_ZB_OPA_DECAL(1) +#define G_RM_ZB_OPA_DECAL2 RM_ZB_OPA_DECAL(2) +#define G_RM_ZB_XLU_DECAL RM_ZB_XLU_DECAL(1) +#define G_RM_ZB_XLU_DECAL2 RM_ZB_XLU_DECAL(2) +#define G_RM_ZB_CLD_SURF RM_ZB_CLD_SURF(1) +#define G_RM_ZB_CLD_SURF2 RM_ZB_CLD_SURF(2) +#define G_RM_ZB_OVL_SURF RM_ZB_OVL_SURF(1) +#define G_RM_ZB_OVL_SURF2 RM_ZB_OVL_SURF(2) +#define G_RM_ZB_PCL_SURF RM_ZB_PCL_SURF(1) +#define G_RM_ZB_PCL_SURF2 RM_ZB_PCL_SURF(2) + +#define G_RM_OPA_SURF RM_OPA_SURF(1) +#define G_RM_OPA_SURF2 RM_OPA_SURF(2) +#define G_RM_XLU_SURF RM_XLU_SURF(1) +#define G_RM_XLU_SURF2 RM_XLU_SURF(2) +#define G_RM_CLD_SURF RM_CLD_SURF(1) +#define G_RM_CLD_SURF2 RM_CLD_SURF(2) +#define G_RM_TEX_EDGE RM_TEX_EDGE(1) +#define G_RM_TEX_EDGE2 RM_TEX_EDGE(2) +#define G_RM_PCL_SURF RM_PCL_SURF(1) +#define G_RM_PCL_SURF2 RM_PCL_SURF(2) +#define G_RM_ADD RM_ADD(1) +#define G_RM_ADD2 RM_ADD(2) +#define G_RM_NOOP RM_NOOP(1) +#define G_RM_NOOP2 RM_NOOP(2) +#define G_RM_VISCVG RM_VISCVG(1) +#define G_RM_VISCVG2 RM_VISCVG(2) +#define G_RM_OPA_CI RM_OPA_CI(1) +#define G_RM_OPA_CI2 RM_OPA_CI(2) + + +#define G_RM_FOG_SHADE_A GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA) +#define G_RM_FOG_PRIM_A GBL_c1(G_BL_CLR_FOG, G_BL_A_FOG, G_BL_CLR_IN, G_BL_1MA) +#define G_RM_PASS GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +/* + * G_SETCONVERT: K0-5 + */ +#define G_CV_K0 175 +#define G_CV_K1 -43 +#define G_CV_K2 -89 +#define G_CV_K3 222 +#define G_CV_K4 114 +#define G_CV_K5 42 + +/* + * G_SETSCISSOR: interlace mode + */ +#define G_SC_NON_INTERLACE 0 +#define G_SC_ODD_INTERLACE 3 +#define G_SC_EVEN_INTERLACE 2 + +/* + * Data Structures + */ + +/* + * Vertex (set up for use with colors) + */ +typedef struct { + short ob[3]; /* x, y, z */ + unsigned short flag; /* Holds packed normals, or unused */ + short tc[2]; /* texture coord */ + unsigned char cn[4]; /* color & alpha */ +} Vtx_t; + +/* + * Vertex (set up for use with normals) + */ +typedef struct { + short ob[3]; /* x, y, z */ + unsigned short flag; /* Packed normals are not used when normals are in colors */ + short tc[2]; /* texture coord */ + signed char n[3]; /* normal */ + unsigned char a; /* alpha */ +} Vtx_tn; + +typedef union { + Vtx_t v; /* Use this one for colors */ + Vtx_tn n; /* Use this one for normals */ + long long int force_structure_alignment; +} Vtx; + +typedef struct { + short pos[3]; + short pad; /* value ignored, need not be 0 */ +} PlainVtx_t; + +typedef union { + PlainVtx_t c; + long long int force_structure_alignment; +} PlainVtx; + +/* + * Triangle face + */ +typedef struct { + unsigned char flag; + unsigned char v[3]; +} Tri; + +/* + * 4x4 matrix, fixed point s15.16 format. + * First 8 words are integer portion of the 4x4 matrix + * Last 8 words are the fraction portion of the 4x4 matrix + */ +typedef long int Mtx_t[4][4]; +typedef union { + Mtx_t m; + struct { + u16 intPart[4][4]; + u16 fracPart[4][4]; + }; + long long int force_structure_alignment; +} Mtx; + +#define IPART(x) (((s32)((x) * 0x10000) >> 16) & 0xFFFF) +#define FPART(x) ((s32)((x) * 0x10000) & 0xFFFF) + +#define gdSPDefMtx( \ + xx, xy, xz, xw, \ + yx, yy, yz, yw, \ + zx, zy, zz, zw, \ + wx, wy, wz, ww) \ + { { \ + (IPART(xx) << 16) | IPART(yx), \ + (IPART(zx) << 16) | IPART(wx), \ + (IPART(xy) << 16) | IPART(yy), \ + (IPART(zy) << 16) | IPART(wy), \ + (IPART(xz) << 16) | IPART(yz), \ + (IPART(zz) << 16) | IPART(wz), \ + (IPART(xw) << 16) | IPART(yw), \ + (IPART(zw) << 16) | IPART(ww), \ + (FPART(xx) << 16) | FPART(yx), \ + (FPART(zx) << 16) | FPART(wx), \ + (FPART(xy) << 16) | FPART(yy), \ + (FPART(zy) << 16) | FPART(wy), \ + (FPART(xz) << 16) | FPART(yz), \ + (FPART(zz) << 16) | FPART(wz), \ + (FPART(xw) << 16) | FPART(yw), \ + (FPART(zw) << 16) | FPART(ww), \ + } } + +/* + * Viewport + */ + +/* + * This magic value is the maximum INTEGER z-range of the hardware + * (there are also 16-bits of fraction, which are introduced during + * any transformations). This is not just a good idea, it's the law. + * Feeding the hardware eventual z-coordinates (after any transforms + * or scaling) bigger than this, will not work. + * + * This number is DIFFERENT than G_MAXFBZ, which is the maximum value + * you want to use to initialize the z-buffer. + * + * The reason these are different is mildly interesting, but too long + * to explain here. It is basically the result of optimizations in the + * hardware. A more generic API might hide this detail from the users, + * but we don't have the ucode to do that... + * + */ +#define G_MAXZ 0x03FF /* 10 bits of integer screen-Z precision */ + +/* + * The viewport structure elements have 2 bits of fraction, necessary + * to accomodate the sub-pixel positioning scaling for the hardware. + * This can also be exploited to handle odd-sized viewports. + * + * Accounting for these fractional bits, using the default projection + * and viewing matrices, the viewport structure is initialized thusly: + * + * (SCREEN_WD/2)*4, (SCREEN_HT/2)*4, G_MAXZ, 0, + * (SCREEN_WD/2)*4, (SCREEN_HT/2)*4, 0, 0, + */ +typedef struct { + short vscale[4]; /* scale, 2 bits fraction */ + short vtrans[4]; /* translate, 2 bits fraction */ + /* both the above arrays are padded to 64-bit boundary */ +} Vp_t; + +typedef union { + Vp_t vp; + long long int force_structure_alignment[2]; +} Vp; + +/* + * Light structure. + * + * Note: the weird order is for the DMEM alignment benefit of + * the microcode. + */ + +typedef struct { + unsigned char col[3]; /* diffuse light color (rgb) */ + unsigned char type; /* formerly pad1; MUST SET TO 0 to indicate directional light */ + unsigned char colc[3]; /* copy of diffuse light color (rgb) */ + char pad2; + signed char dir[3]; /* direction of light (normalized) */ + char pad3; + char pad4[3]; + unsigned char size; /* For specular only; reasonable values are 1-4 */ +} Light_t; + +typedef struct { + unsigned char col[3]; /* point light color (rgb) */ + unsigned char kc; /* point light enable flag (> 0) & constant attenuation Kc */ + unsigned char colc[3]; /* copy of point light color (rgb) */ + unsigned char kl; /* linear attenuation Kl */ + short pos[3]; /* light position x, y, z in world space */ + unsigned char kq; /* quadratic attenuation Kq */ + unsigned char size; /* For specular only; reasonable values are 1-4 */ +} PosLight_t; + +typedef struct { + unsigned char col[3]; /* ambient light color (rgb) */ + char pad1; + unsigned char colc[3]; /* copy of ambient light color (rgb) */ + char pad2; +} Ambient_t; + +typedef struct { + signed char dir[3]; /* direction of lookat (normalized) */ + char pad1; +} LookAt_t; + +typedef struct { + LookAt_t l; /* for backwards compatibility */ +} LookAtWrapper; + +typedef struct { + /* texture offsets for highlight 1/2 */ + int x1; + int y1; + int x2; + int y2; +} Hilite_t; + +typedef struct { + short c0; + short c1; + short c2; + short c3; + short c4; + short c5; + short c6; + short c7; + short kx; + short ky; + short kz; + short kc; +} OcclusionPlane_t; + +typedef union { + Light_t l; + long long int force_structure_alignment[2]; +} Light; + +typedef union { + Ambient_t l; + long long int force_structure_alignment[1]; +} Ambient; + +typedef union { + PosLight_t p; + Light_t l; + long long int force_structure_alignment[2]; +} PosLight; + +typedef union { + LookAtWrapper l[2]; + long long int force_structure_alignment[1]; +} LookAt; + +typedef union { + Hilite_t h; + long int force_structure_alignment; +} Hilite; + +typedef union { + OcclusionPlane_t o; + short c[12]; + long long int force_structure_alignment[3]; +} OcclusionPlane; + +typedef struct { + Light l[9]; + Ambient a; +} Lightsn; + +typedef struct { + /* F3DEX3 properly supports zero lights, unlike F3DEX2 where you need + to include one black directional light. */ + Ambient a; +} Lights0; + +typedef struct { + Light l[1]; + Ambient a; +} Lights1; + +typedef struct { + Light l[2]; + Ambient a; +} Lights2; + +typedef struct { + Light l[3]; + Ambient a; +} Lights3; + +typedef struct { + Light l[4]; + Ambient a; +} Lights4; + +typedef struct { + Light l[5]; + Ambient a; +} Lights5; + +typedef struct { + Light l[6]; + Ambient a; +} Lights6; + +typedef struct { + Light l[7]; + Ambient a; +} Lights7; + +typedef struct { + Light l[8]; + Ambient a; +} Lights8; + +typedef struct { + Light l[9]; + Ambient a; +} Lights9; + +typedef struct { + PosLight l[9]; + Ambient a; +} PosLightsn; + +typedef struct { + /* F3DEX3 properly supports zero lights, unlike F3DEX2 where you need + to include one black directional light. */ + Ambient a; +} PosLights0; + +typedef struct { + PosLight l[1]; + Ambient a; +} PosLights1; + +typedef struct { + PosLight l[2]; + Ambient a; +} PosLights2; + +typedef struct { + PosLight l[3]; + Ambient a; +} PosLights3; + +typedef struct { + PosLight l[4]; + Ambient a; +} PosLights4; + +typedef struct { + PosLight l[5]; + Ambient a; +} PosLights5; + +typedef struct { + PosLight l[6]; + Ambient a; +} PosLights6; + +typedef struct { + PosLight l[7]; + Ambient a; +} PosLights7; + +typedef struct { + PosLight l[8]; + Ambient a; +} PosLights8; + +typedef struct { + PosLight l[9]; + Ambient a; +} PosLights9; + +#define gdSPDefLights0(ar, ag, ab) \ + { \ + {{ \ + { ar, ag, ab }, 0, \ + { ar, ag, ab }, 0, \ + }} \ + } + +#define gdSPDefLights1(ar, ag, ab, \ + r1, g1, b1, x1, y1, z1) \ + { \ + { \ + {{ \ + { r1, g1, b1 }, 0, \ + { r1, g1, b1 }, 0, \ + { x1, y1, z1 }, 0, \ + { 0, 0, 0 }, 0 \ + }} \ + }, \ + {{ \ + { ar, ag, ab }, 0, \ + { ar, ag, ab }, 0, \ + }} \ + } + +#define gdSPDefLights2(ar, ag, ab, \ + r1, g1, b1, x1, y1, z1, \ + r2, g2, b2, x2, y2, z2) \ + { \ + { \ + {{ \ + { r1, g1, b1 }, 0, \ + { r1, g1, b1 }, 0, \ + { x1, y1, z1 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r2, g2, b2 }, 0, \ + { r2, g2, b2 }, 0, \ + { x2, y2, z2 }, 0, \ + { 0, 0, 0 }, 0 \ + }} \ + }, \ + {{ \ + { ar, ag, ab }, 0, \ + { ar, ag, ab }, 0, \ + }} \ + } + +#define gdSPDefLights3(ar, ag, ab, \ + r1, g1, b1, x1, y1, z1, \ + r2, g2, b2, x2, y2, z2, \ + r3, g3, b3, x3, y3, z3) \ + { \ + { \ + {{ \ + { r1, g1, b1 }, 0, \ + { r1, g1, b1 }, 0, \ + { x1, y1, z1 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r2, g2, b2 }, 0, \ + { r2, g2, b2 }, 0, \ + { x2, y2, z2 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r3, g3, b3 }, 0, \ + { r3, g3, b3 }, 0, \ + { x3, y3, z3 }, 0, \ + { 0, 0, 0 }, 0 \ + }} \ + }, \ + {{ \ + { ar, ag, ab }, 0, \ + { ar, ag, ab }, 0, \ + }} \ + } + +#define gdSPDefLights4(ar, ag, ab, \ + r1, g1, b1, x1, y1, z1, \ + r2, g2, b2, x2, y2, z2, \ + r3, g3, b3, x3, y3, z3, \ + r4, g4, b4, x4, y4, z4) \ + { \ + { \ + {{ \ + { r1, g1, b1 }, 0, \ + { r1, g1, b1 }, 0, \ + { x1, y1, z1 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r2, g2, b2 }, 0, \ + { r2, g2, b2 }, 0, \ + { x2, y2, z2 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r3, g3, b3 }, 0, \ + { r3, g3, b3 }, 0, \ + { x3, y3, z3 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r4, g4, b4 }, 0, \ + { r4, g4, b4 }, 0, \ + { x4, y4, z4 }, 0, \ + { 0, 0, 0 }, 0 \ + }} \ + }, \ + {{ \ + { ar, ag, ab }, 0, \ + { ar, ag, ab }, 0, \ + }} \ + } + +#define gdSPDefLights5(ar, ag, ab, \ + r1, g1, b1, x1, y1, z1, \ + r2, g2, b2, x2, y2, z2, \ + r3, g3, b3, x3, y3, z3, \ + r4, g4, b4, x4, y4, z4, \ + r5, g5, b5, x5, y5, z5) \ + { \ + { \ + {{ \ + { r1, g1, b1 }, 0, \ + { r1, g1, b1 }, 0, \ + { x1, y1, z1 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r2, g2, b2 }, 0, \ + { r2, g2, b2 }, 0, \ + { x2, y2, z2 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r3, g3, b3 }, 0, \ + { r3, g3, b3 }, 0, \ + { x3, y3, z3 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r4, g4, b4 }, 0, \ + { r4, g4, b4 }, 0, \ + { x4, y4, z4 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r5, g5, b5 }, 0, \ + { r5, g5, b5 }, 0, \ + { x5, y5, z5 }, 0, \ + { 0, 0, 0 }, 0 \ + }} \ + }, \ + {{ \ + { ar, ag, ab }, 0, \ + { ar, ag, ab }, 0, \ + }} \ + } + +#define gdSPDefLights6(ar, ag, ab, \ + r1, g1, b1, x1, y1, z1, \ + r2, g2, b2, x2, y2, z2, \ + r3, g3, b3, x3, y3, z3, \ + r4, g4, b4, x4, y4, z4, \ + r5, g5, b5, x5, y5, z5, \ + r6, g6, b6, x6, y6, z6) \ + { \ + { \ + {{ \ + { r1, g1, b1 }, 0, \ + { x1, y1, z1 }, 0, \ + { r1, g1, b1 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r2, g2, b2 }, 0, \ + { r2, g2, b2 }, 0, \ + { x2, y2, z2 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r3, g3, b3 }, 0, \ + { r3, g3, b3 }, 0, \ + { x3, y3, z3 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r4, g4, b4 }, 0, \ + { r4, g4, b4 }, 0, \ + { x4, y4, z4 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r5, g5, b5 }, 0, \ + { r5, g5, b5 }, 0, \ + { x5, y5, z5 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r6, g6, b6 }, 0, \ + { r6, g6, b6 }, 0, \ + { x6, y6, z6 }, 0, \ + { 0, 0, 0 }, 0 \ + }} \ + }, \ + {{ \ + { ar, ag, ab }, 0, \ + { ar, ag, ab }, 0, \ + }} \ + } + +#define gdSPDefLights7(ar, ag, ab, \ + r1, g1, b1, x1, y1, z1, \ + r2, g2, b2, x2, y2, z2, \ + r3, g3, b3, x3, y3, z3, \ + r4, g4, b4, x4, y4, z4, \ + r5, g5, b5, x5, y5, z5, \ + r6, g6, b6, x6, y6, z6, \ + r7, g7, b7, x7, y7, z7) \ + { \ + { \ + {{ \ + { r1, g1, b1 }, 0, \ + { r1, g1, b1 }, 0, \ + { x1, y1, z1 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r2, g2, b2 }, 0, \ + { r2, g2, b2 }, 0, \ + { x2, y2, z2 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r3, g3, b3 }, 0, \ + { r3, g3, b3 }, 0, \ + { x3, y3, z3 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r4, g4, b4 }, 0, \ + { r4, g4, b4 }, 0, \ + { x4, y4, z4 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r5, g5, b5 }, 0, \ + { r5, g5, b5 }, 0, \ + { x5, y5, z5 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r6, g6, b6 }, 0, \ + { r6, g6, b6 }, 0, \ + { x6, y6, z6 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r7, g7, b7 }, 0, \ + { r7, g7, b7 }, 0, \ + { x7, y7, z7 }, 0, \ + { 0, 0, 0 }, 0 \ + }} \ + }, \ + {{ \ + { ar, ag, ab }, 0, \ + { ar, ag, ab }, 0, \ + }} \ + } + +#define gdSPDefLights8(ar, ag, ab, \ + r1, g1, b1, x1, y1, z1, \ + r2, g2, b2, x2, y2, z2, \ + r3, g3, b3, x3, y3, z3, \ + r4, g4, b4, x4, y4, z4, \ + r5, g5, b5, x5, y5, z5, \ + r6, g6, b6, x6, y6, z6, \ + r7, g7, b7, x7, y7, z7, \ + r8, g8, b8, x8, y8, z8) \ + { \ + { \ + {{ \ + { r1, g1, b1 }, 0, \ + { r1, g1, b1 }, 0, \ + { x1, y1, z1 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r2, g2, b2 }, 0, \ + { r2, g2, b2 }, 0, \ + { x2, y2, z2 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r3, g3, b3 }, 0, \ + { r3, g3, b3 }, 0, \ + { x3, y3, z3 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r4, g4, b4 }, 0, \ + { r4, g4, b4 }, 0, \ + { x4, y4, z4 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r5, g5, b5 }, 0, \ + { r5, g5, b5 }, 0, \ + { x5, y5, z5 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r6, g6, b6 }, 0, \ + { r6, g6, b6 }, 0, \ + { x6, y6, z6 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r7, g7, b7 }, 0, \ + { r7, g7, b7 }, 0, \ + { x7, y7, z7 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r8, g8, b8 }, 0, \ + { r8, g8, b8 }, 0, \ + { x8, y8, z8 }, 0, \ + { 0, 0, 0 }, 0 \ + }} \ + }, \ + {{ \ + { ar, ag, ab }, 0, \ + { ar, ag, ab }, 0, \ + }} \ + } + +#define gdSPDefLights9(ar, ag, ab, \ + r1, g1, b1, x1, y1, z1, \ + r2, g2, b2, x2, y2, z2, \ + r3, g3, b3, x3, y3, z3, \ + r4, g4, b4, x4, y4, z4, \ + r5, g5, b5, x5, y5, z5, \ + r6, g6, b6, x6, y6, z6, \ + r7, g7, b7, x7, y7, z7, \ + r8, g8, b8, x8, y8, z8, \ + r9, g9, b9, x9, y9, z9) \ + { \ + { \ + {{ \ + { r1, g1, b1 }, 0, \ + { r1, g1, b1 }, 0, \ + { x1, y1, z1 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r2, g2, b2 }, 0, \ + { r2, g2, b2 }, 0, \ + { x2, y2, z2 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r3, g3, b3 }, 0, \ + { r3, g3, b3 }, 0, \ + { x3, y3, z3 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r4, g4, b4 }, 0, \ + { r4, g4, b4 }, 0, \ + { x4, y4, z4 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r5, g5, b5 }, 0, \ + { r5, g5, b5 }, 0, \ + { x5, y5, z5 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r6, g6, b6 }, 0, \ + { r6, g6, b6 }, 0, \ + { x6, y6, z6 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r7, g7, b7 }, 0, \ + { r7, g7, b7 }, 0, \ + { x7, y7, z7 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r8, g8, b8 }, 0, \ + { r8, g8, b8 }, 0, \ + { x8, y8, z8 }, 0, \ + { 0, 0, 0 }, 0 \ + }}, \ + {{ \ + { r9, g9, b9 }, 0, \ + { r9, g9, b9 }, 0, \ + { x9, y9, z9 }, 0, \ + { 0, 0, 0 }, 0 \ + }} \ + }, \ + {{ \ + { ar, ag, ab }, 0, \ + { ar, ag, ab }, 0, \ + }} \ + } + +#define gdSPDefLookAt(rightx, righty, rightz, upx, upy, upz) \ + { \ + {{{ rightx, righty, rightz }, 0 }}, \ + {{{ upx, upy, upz }, 0 }}, \ + } + + +#define _gdSPDefAmbient(ar,ag,ab) \ + {{ {ar,ag,ab},0,{ar,ag,ab},0}} +#define _gdSPDefPosLight(r,g,b,x,y,z,c,l,q) \ + {{ {r,g,b},c,{r,g,b},l,{x,y,z},q,0 }} +#define _gdSPDefInfLight(r,g,b,x,y,z) \ + {{ {r,g,b},0,{r,g,b},0,{((x)<<8)|((y)&0xff),(z)<<8,0},0,0}} +#define gdSPDefPosLights0(ar,ag,ab) \ + { _gdSPDefAmbient(ar,ag,ab) } +#define gdSPDefPosLights1(ar,ag,ab,r1,g1,b1,x1,y1,z1,c1,l1,q1) \ + {{ _gdSPDefPosLight(r1,g1,b1,x1,y1,z1,c1,l1,q1) }, \ + _gdSPDefAmbient(ar,ag,ab) } +#define gdSPDefPosLights2(ar,ag,ab,r1,g1,b1,x1,y1,z1,c1,l1,q1,r2,g2,b2,x2,y2,z2,c2,l2,q2) \ + {{ _gdSPDefPosLight(r1,g1,b1,x1,y1,z1,c1,l1,q1), \ + _gdSPDefPosLight(r2,g2,b2,x2,y2,z2,c2,l2,q2) }, \ + _gdSPDefAmbient(ar,ag,ab) } +#define gdSPDefPosLights3(ar,ag,ab,r1,g1,b1,x1,y1,z1,c1,l1,q1,r2,g2,b2,x2,y2,z2,c2,l2,q2,r3,g3,b3,x3,y3,z3,c3,l3,q3) \ + {{ _gdSPDefPosLight(r1,g1,b1,x1,y1,z1,c1,l1,q1), \ + _gdSPDefPosLight(r2,g2,b2,x2,y2,z2,c2,l2,q2), \ + _gdSPDefPosLight(r3,g3,b3,x3,y3,z3,c3,l3,q3) }, \ + _gdSPDefAmbient(ar,ag,ab) } +#define gdSPDefPosLights4(ar,ag,ab,r1,g1,b1,x1,y1,z1,c1,l1,q1,r2,g2,b2,x2,y2,z2,c2,l2,q2,r3,g3,b3,x3,y3,z3,c3,l3,q3,r4,g4,b4,x4,y4,z4,c4,l4,q4) \ + {{ _gdSPDefPosLight(r1,g1,b1,x1,y1,z1,c1,l1,q1), \ + _gdSPDefPosLight(r2,g2,b2,x2,y2,z2,c2,l2,q2), \ + _gdSPDefPosLight(r3,g3,b3,x3,y3,z3,c3,l3,q3), \ + _gdSPDefPosLight(r4,g4,b4,x4,y4,z4,c4,l4,q4) }, \ + _gdSPDefAmbient(ar,ag,ab) } +#define gdSPDefPosLights5(ar,ag,ab,r1,g1,b1,x1,y1,z1,c1,l1,q1,r2,g2,b2,x2,y2,z2,c2,l2,q2,r3,g3,b3,x3,y3,z3,c3,l3,q3,r4,g4,b4,x4,y4,z4,c4,l4,q4,r5,g5,b5,x5,y5,z5,c5,l5,q5) \ + {{ _gdSPDefPosLight(r1,g1,b1,x1,y1,z1,c1,l1,q1), \ + _gdSPDefPosLight(r2,g2,b2,x2,y2,z2,c2,l2,q2), \ + _gdSPDefPosLight(r3,g3,b3,x3,y3,z3,c3,l3,q3), \ + _gdSPDefPosLight(r4,g4,b4,x4,y4,z4,c4,l4,q4), \ + _gdSPDefPosLight(r5,g5,b5,x5,y5,z5,c5,l5,q5) }, \ + _gdSPDefAmbient(ar,ag,ab) } +#define gdSPDefPosLights6(ar,ag,ab,r1,g1,b1,x1,y1,z1,c1,l1,q1,r2,g2,b2,x2,y2,z2,c2,l2,q2,r3,g3,b3,x3,y3,z3,c3,l3,q3,r4,g4,b4,x4,y4,z4,c4,l4,q4,r5,g5,b5,x5,y5,z5,c5,l5,q5,r6,g6,b6,x6,y6,z6,c6,l6,q6) \ + {{ _gdSPDefPosLight(r1,g1,b1,x1,y1,z1,c1,l1,q1), \ + _gdSPDefPosLight(r2,g2,b2,x2,y2,z2,c2,l2,q2), \ + _gdSPDefPosLight(r3,g3,b3,x3,y3,z3,c3,l3,q3), \ + _gdSPDefPosLight(r4,g4,b4,x4,y4,z4,c4,l4,q4), \ + _gdSPDefPosLight(r5,g5,b5,x5,y5,z5,c5,l5,q5), \ + _gdSPDefPosLight(r6,g6,b6,x6,y6,z6,c6,l6,q6) }, \ + _gdSPDefAmbient(ar,ag,ab) } +#define gdSPDefPosLights7(ar,ag,ab,r1,g1,b1,x1,y1,z1,c1,l1,q1,r2,g2,b2,x2,y2,z2,c2,l2,q2,r3,g3,b3,x3,y3,z3,c3,l3,q3,r4,g4,b4,x4,y4,z4,c4,l4,q4,r5,g5,b5,x5,y5,z5,c5,l5,q5,r6,g6,b6,x6,y6,z6,c6,l6,q6,r7,g7,b7,x7,y7,z7,c7,l7,q7) \ + {{ _gdSPDefPosLight(r1,g1,b1,x1,y1,z1,c1,l1,q1), \ + _gdSPDefPosLight(r2,g2,b2,x2,y2,z2,c2,l2,q2), \ + _gdSPDefPosLight(r3,g3,b3,x3,y3,z3,c3,l3,q3), \ + _gdSPDefPosLight(r4,g4,b4,x4,y4,z4,c4,l4,q4), \ + _gdSPDefPosLight(r5,g5,b5,x5,y5,z5,c5,l5,q5), \ + _gdSPDefPosLight(r6,g6,b6,x6,y6,z6,c6,l6,q6), \ + _gdSPDefPosLight(r7,g7,b7,x7,y7,z7,c7,l7,q7) }, \ + _gdSPDefAmbient(ar,ag,ab) } +#define gdSPDefPosLights8(ar,ag,ab,r1,g1,b1,x1,y1,z1,c1,l1,q1,r2,g2,b2,x2,y2,z2,c2,l2,q2,r3,g3,b3,x3,y3,z3,c3,l3,q3,r4,g4,b4,x4,y4,z4,c4,l4,q4,r5,g5,b5,x5,y5,z5,c5,l5,q5,r6,g6,b6,x6,y6,z6,c6,l6,q6,r7,g7,b7,x7,y7,z7,c7,l7,q7,r8,g8,b8,x8,y8,z8,c8,l8,q8) \ + {{ _gdSPDefPosLight(r1,g1,b1,x1,y1,z1,c1,l1,q1), \ + _gdSPDefPosLight(r2,g2,b2,x2,y2,z2,c2,l2,q2), \ + _gdSPDefPosLight(r3,g3,b3,x3,y3,z3,c3,l3,q3), \ + _gdSPDefPosLight(r4,g4,b4,x4,y4,z4,c4,l4,q4), \ + _gdSPDefPosLight(r5,g5,b5,x5,y5,z5,c5,l5,q5), \ + _gdSPDefPosLight(r6,g6,b6,x6,y6,z6,c6,l6,q6), \ + _gdSPDefPosLight(r7,g7,b7,x7,y7,z7,c7,l7,q7), \ + _gdSPDefPosLight(r8,g8,b8,x8,y8,z8,c8,l8,q8) }, \ + _gdSPDefAmbient(ar,ag,ab) } +#define gdSPDefPosLights9(ar,ag,ab,r1,g1,b1,x1,y1,z1,c1,l1,q1,r2,g2,b2,x2,y2,z2,c2,l2,q2,r3,g3,b3,x3,y3,z3,c3,l3,q3,r4,g4,b4,x4,y4,z4,c4,l4,q4,r5,g5,b5,x5,y5,z5,c5,l5,q5,r6,g6,b6,x6,y6,z6,c6,l6,q6,r7,g7,b7,x7,y7,z7,c7,l7,q7,r8,g8,b8,x8,y8,z8,c8,l8,q8,r9,g9,b9,x9,y9,z9,c9,l9,q9) \ + {{ _gdSPDefPosLight(r1,g1,b1,x1,y1,z1,c1,l1,q1), \ + _gdSPDefPosLight(r2,g2,b2,x2,y2,z2,c2,l2,q2), \ + _gdSPDefPosLight(r3,g3,b3,x3,y3,z3,c3,l3,q3), \ + _gdSPDefPosLight(r4,g4,b4,x4,y4,z4,c4,l4,q4), \ + _gdSPDefPosLight(r5,g5,b5,x5,y5,z5,c5,l5,q5), \ + _gdSPDefPosLight(r6,g6,b6,x6,y6,z6,c6,l6,q6), \ + _gdSPDefPosLight(r7,g7,b7,x7,y7,z7,c7,l7,q7), \ + _gdSPDefPosLight(r8,g8,b8,x8,y8,z8,c8,l8,q8), \ + _gdSPDefPosLight(r9,g9,b9,x9,y9,z9,c9,l9,q9) }, \ + _gdSPDefAmbient(ar,ag,ab) } + + +typedef struct { + int cmd : 8; + unsigned int type : 8; + unsigned int len : 16; + union { + /* The exact form of this callback is intentionally left unspecified, a display list + parser may choose the return value and parameters so long as it is consistent. */ + void (*callback)(); + const char* str; + unsigned int u32; + float f32; + void* addr; + } value; +} Gnoop; + +/* + * Graphics DMA Packet + */ +typedef struct { + int cmd : 8; + unsigned int par : 8; + unsigned int len : 16; + unsigned int addr; +} Gdma; + +typedef struct { + int cmd : 8; + unsigned int len : 8; + unsigned int ofs : 8; + unsigned int par : 8; + unsigned int addr; +} Gdma2; + +/* + * Graphics Moveword Packet + */ +typedef struct { + int cmd : 8; + unsigned int index : 8; + unsigned int offset : 16; + unsigned int data; +} Gmovewd; + +/* + * Graphics Movemem Packet + */ +typedef struct { + int cmd : 8; + unsigned int size : 8; + unsigned int offset : 8; + unsigned int index : 8; + unsigned int data; +} Gmovemem; + +/* + * Graphics Immediate Mode Packet types + */ +typedef struct { + int cmd : 8; + int pad : 24; + Tri tri; +} Gtri; + +typedef struct { + Tri tri1; /* flag is the command byte */ + Tri tri2; +} Gtri2; + +typedef struct { + Tri tri1; /* flag is the command byte */ + Tri tri2; +} Gquad; + +typedef struct { + int cmd : 8; + unsigned int pad : 8; + unsigned short vstart_x2; + unsigned short pad2; + unsigned short vend_x2; +} Gcull; + +typedef struct { + int cmd : 8; + unsigned int pad : 24; + unsigned short z; + unsigned short dz; +} Gsetprimdepth; + +typedef struct { + int cmd : 8; + int pad1 : 24; + unsigned int param; +} Gpopmtx; + +typedef struct { + int cmd : 8; + int mw_index : 8; + int pad0 : 8; + int number : 8; + int pad1 : 8; + int base : 24; +} Gsegment; + +typedef struct { + int cmd : 8; + int pad0 : 8; + unsigned int sft : 8; + unsigned int len : 8; + unsigned int data : 32; +} GsetothermodeL; + +typedef struct { + int cmd : 8; + int pad0 : 8; + unsigned int sft : 8; + unsigned int len : 8; + unsigned int data : 32; +} GsetothermodeH; + +typedef struct { + unsigned char cmd; + unsigned char lodscale; + unsigned char pad : 2; + unsigned char level : 3; + unsigned char tile : 3; + unsigned char on; + unsigned short s; + unsigned short t; +} Gtexture; + +typedef struct { + int cmd : 8; + int pad1 : 24; + short int pad2; + short int scale; +} Gperspnorm; + + +/* + * RDP Packet types + */ +typedef struct { + int cmd : 8; + unsigned int fmt : 3; + unsigned int siz : 2; + unsigned int pad : 7; + unsigned int wd : 12; /* really only 10 bits, extra */ + unsigned int dram; /* to account for 1024 */ +} Gsetimg; + +typedef struct { + int cmd : 8; + /* muxs0 */ + unsigned int a0 : 4; + unsigned int c0 : 5; + unsigned int Aa0 : 3; + unsigned int Ac0 : 3; + unsigned int a1 : 4; + unsigned int c1 : 5; + /* muxs1 */ + unsigned int b0 : 4; + unsigned int b1 : 4; + unsigned int Aa1 : 3; + unsigned int Ac1 : 3; + unsigned int d0 : 3; + unsigned int Ab0 : 3; + unsigned int Ad0 : 3; + unsigned int d1 : 3; + unsigned int Ab1 : 3; + unsigned int Ad1 : 3; +} Gsetcombine; + +typedef struct { + int cmd : 8; + unsigned char pad; + unsigned char prim_min_level; + unsigned char prim_level; + union { + unsigned long color; + struct { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + }; + }; +} Gsetcolor; + +typedef struct { + int cmd : 8; + int x0 : 10; + int x0frac : 2; + int y0 : 10; + int y0frac : 2; + unsigned int pad : 8; + int x1 : 10; + int x1frac : 2; + int y1 : 10; + int y1frac : 2; +} Gfillrect; + +typedef struct { + int cmd : 8; + unsigned int fmt : 3; + unsigned int siz : 2; + unsigned int pad0 : 1; + unsigned int line : 9; + unsigned int tmem : 9; + unsigned int pad1 : 5; + unsigned int tile : 3; + unsigned int palette : 4; + unsigned int ct : 1; + unsigned int mt : 1; + unsigned int maskt : 4; + unsigned int shiftt : 4; + unsigned int cs : 1; + unsigned int ms : 1; + unsigned int masks : 4; + unsigned int shifts : 4; +} Gsettile; + +typedef struct { + int cmd : 8; + unsigned int sl : 12; + unsigned int tl : 12; + int pad : 5; + unsigned int tile : 3; + unsigned int sh : 12; + unsigned int th : 12; +} Gloadtile; + +typedef Gloadtile Gloadblock; + +typedef Gloadtile Gsettilesize; + +typedef Gloadtile Gloadtlut; + +typedef struct { + unsigned int cmd : 8; /* command */ + unsigned int xl : 12; /* X coordinate of upper left */ + unsigned int yl : 12; /* Y coordinate of upper left */ + unsigned int pad1 : 5; /* Padding */ + unsigned int tile : 3; /* Tile descriptor index */ + unsigned int xh : 12; /* X coordinate of lower right */ + unsigned int yh : 12; /* Y coordinate of lower right */ + unsigned int s : 16; /* S texture coord at top left */ + unsigned int t : 16; /* T texture coord at top left */ + unsigned int dsdx : 16; /* Change in S per change in X */ + unsigned int dtdy : 16; /* Change in T per change in Y */ +} Gtexrect; + +#define MakeTexRect(xh,yh,flip,tile,xl,yl,s,t,dsdx,dtdy) \ + G_TEXRECT, xh, yh, 0, flip, 0, tile, xl, yl, s, t, dsdx, dtdy + +/* + * Textured rectangles are 128 bits not 64 bits + */ +typedef struct { + unsigned long w0; + unsigned long w1; + unsigned long w2; + unsigned long w3; +} TexRect; + +typedef struct { + int cmd : 8; + unsigned int pad : 4; + unsigned int len : 8; /* n */ + unsigned int pad2 : 4; + unsigned char par; /* v0 */ + unsigned int addr; +} Gvtx; + +/* + * Generic Gfx Packet + */ +typedef struct { + unsigned int w0; + unsigned int w1; +} Gwords; + +/* + * This union is the fundamental type of the display list. + * It is, by law, exactly 64 bits in size. + */ +typedef union { + Gwords words; + Gnoop noop; + Gdma dma; + Gdma2 dma2; + Gvtx vtx; + Gtri tri; + Gtri2 tri2; + Gquad quad; + Gcull cull; + Gmovewd movewd; + Gmovemem movemem; + Gpopmtx popmtx; + Gsegment segment; + GsetothermodeH setothermodeH; + GsetothermodeL setothermodeL; + Gtexture texture; + Gperspnorm perspnorm; + Gsetimg setimg; + Gsetcombine setcombine; + Gsetcolor setcolor; + Gfillrect fillrect; /* use for setscissor also */ + Gsettile settile; + Gloadtile loadtile; /* use for loadblock also, th is dxt */ + Gsettilesize settilesize; + Gloadtlut loadtlut; + Gsetprimdepth setprimdepth; + long long int force_structure_alignment; +} Gfx; + +/* + * Macros to assemble the graphics display list + */ + +/* + * DMA macros + */ +#define gDma0p(pkt, c, s, l) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL((c), 24, 8) | \ + _SHIFTL((l), 0, 24)); \ + _g->words.w1 = (unsigned int)(s); \ +}) + +#define gsDma0p(c, s, l) \ +{ \ + (_SHIFTL((c), 24, 8) | \ + _SHIFTL((l), 0, 24)), \ + (unsigned int)(s) \ +} + +#define gDma1p(pkt, c, s, l, p) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL((c), 24, 8) | \ + _SHIFTL((p), 16, 8) | \ + _SHIFTL((l), 0, 16)); \ + _g->words.w1 = (unsigned int)(s); \ +}) + +#define gsDma1p(c, s, l, p) \ +{ \ + (_SHIFTL((c), 24, 8) | \ + _SHIFTL((p), 16, 8) | \ + _SHIFTL((l), 0, 16)), \ + (unsigned int)(s) \ +} + +#define gDma2p(pkt, c, adrs, len, idx, ofs) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL((c), 24, 8) | \ + _SHIFTL(((len) - 1) / 8, 19, 5) | \ + _SHIFTL((ofs) / 8, 8, 8) | \ + _SHIFTL((idx), 0, 8)); \ + _g->words.w1 = (unsigned int)(adrs); \ +}) + +#define gsDma2p(c, adrs, len, idx, ofs) \ +{ \ + (_SHIFTL((c), 24, 8) | \ + _SHIFTL(((len) - 1) / 8, 19, 5) | \ + _SHIFTL((ofs) / 8, 8, 8) | \ + _SHIFTL((idx), 0, 8)), \ + (unsigned int)(adrs) \ +} + +#define gSPNoOp(pkt) gDma0p(pkt, G_SPNOOP, 0, 0) +#define gsSPNoOp() gsDma0p( G_SPNOOP, 0, 0) + +#define gSPMatrix(pkt, m, p) \ + gDma2p((pkt),G_MTX, (m), sizeof(Mtx), (p) ^ G_MTX_PUSH, 0) +#define gsSPMatrix(m, p) \ + gsDma2p( G_MTX, (m), sizeof(Mtx), (p) ^ G_MTX_PUSH, 0) + +#define gSPPopMatrixN(pkt, n, num) gDma2p((pkt), G_POPMTX, (num) * 64, 64, 2, 0) +#define gsSPPopMatrixN(n, num) gsDma2p( G_POPMTX, (num) * 64, 64, 2, 0) +#define gSPPopMatrix(pkt, n) gSPPopMatrixN((pkt), (n), 1) +#define gsSPPopMatrix(n) gsSPPopMatrixN( (n), 1) + +/* + * +--------+----+---+---+----+------+-+ + * G_VTX | cmd:8 |0000| n:8 |0000|v0+n:7|0| + * +-+---+--+----+---+---+----+------+-+ + * | |seg| address | + * +-+---+-----------------------------+ + */ +#define gSPVertex(pkt, v, n, v0) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_VTX, 24, 8) | \ + _SHIFTL((n), 12, 8) | \ + _SHIFTL((v0) + (n), 1, 7)); \ + _g->words.w1 = (unsigned int)(v); \ +}) + +#define gsSPVertex(v, n, v0) \ +{ \ + (_SHIFTL(G_VTX, 24, 8) | \ + _SHIFTL((n), 12, 8) | \ + _SHIFTL((v0) + (n), 1, 7)), \ + (unsigned int)(v) \ +} + +#define gSPViewport(pkt, v) \ + gDma2p((pkt), G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT, 0) +#define gsSPViewport(v) \ + gsDma2p( G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT, 0) + +/* + * Display list control flow + */ + +#define _gSPDisplayListRaw(pkt,dl,hint) gDma1p(pkt, G_DL, dl, hint, G_DL_PUSH) +#define _gsSPDisplayListRaw( dl,hint) gsDma1p( G_DL, dl, hint, G_DL_PUSH) + +#define _gSPBranchListRaw(pkt,dl,hint) gDma1p(pkt, G_DL, dl, hint, G_DL_NOPUSH) +#define _gsSPBranchListRaw( dl,hint) gsDma1p( G_DL, dl, hint, G_DL_NOPUSH) + +#define _gSPEndDisplayListRaw(pkt,hint) gDma0p(pkt, G_ENDDL, 0, hint) +#define _gsSPEndDisplayListRaw(hint) gsDma0p( G_ENDDL, 0, hint) + +/* + * Converts a total expected count of DL commands to a number of bytes to + * initially NOT load into the DL command buffer. + */ +#define _DLHINTVALUE(count) \ + (((count) > 0 && ((count) % G_INPUT_BUFFER_CMDS) > 0) ? \ + ((G_INPUT_BUFFER_CMDS - ((count) % G_INPUT_BUFFER_CMDS)) << 3) : 0) + +/* + * Optimization for reduced memory traffic. In count, put the estimated number + * of DL commands in the target DL (the DL being called / jumped to, or the DL + * being returned to, starting from the next command to be executed) up to and + * including the next call / jump / return. Normally, for SPDisplayList, this is + * just the total number of commands in the target DL. The actual on-screen + * result will not change regardless of the value of count, but the performance + * will be best if count is correct, and potentially worse than not specifying + * count if it is wrong. + * Feature suggested by Kaze Emanuar +*/ + +#define gSPDisplayListHint(pkt, dl, count) _gSPDisplayListRaw(pkt, dl, _DLHINTVALUE(count)) +#define gsSPDisplayListHint( dl, count) _gsSPDisplayListRaw( dl, _DLHINTVALUE(count)) + +#define gSPBranchListHint(pkt, dl, count) _gSPBranchListRaw( pkt, dl, _DLHINTVALUE(count)) +#define gsSPBranchListHint( dl, count) _gsSPBranchListRaw( dl, _DLHINTVALUE(count)) + +#define gSPEndDisplayListHint(pkt, count) _gSPEndDisplayListRaw( pkt, _DLHINTVALUE(count)) +#define gsSPEndDisplayListHint( count) _gsSPEndDisplayListRaw( _DLHINTVALUE(count)) + +/* + * Normal control flow commands; same as above but with hint of 0 + */ + +#define gSPDisplayList(pkt, dl) _gSPDisplayListRaw(pkt, dl, 0) +#define gsSPDisplayList( dl) _gsSPDisplayListRaw( dl, 0) + +#define gSPBranchList(pkt, dl) _gSPBranchListRaw( pkt, dl, 0) +#define gsSPBranchList( dl) _gsSPBranchListRaw( dl, 0) + +#define gSPEndDisplayList(pkt) _gSPEndDisplayListRaw( pkt, 0) +#define gsSPEndDisplayList( ) _gsSPEndDisplayListRaw( 0) + + +/* + * gSPLoadUcode RSP loads specified ucode. + * + * uc_start = ucode text section start + * uc_dstart = ucode data section start + */ +#define gSPLoadUcodeEx(pkt, uc_start, uc_dstart, uc_dsize) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_RDPHALF_1, 24, 8); \ + _g->words.w1 = (unsigned int)(uc_dstart); \ + \ + _g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_LOAD_UCODE, 24, 8) | \ + _SHIFTL((int)(uc_dsize) - 1, 0, 16)); \ + _g->words.w1 = (unsigned int)(uc_start); \ +}) + +#define gsSPLoadUcodeEx(uc_start, uc_dstart, uc_dsize) \ +{ \ + _SHIFTL(G_RDPHALF_1, 24, 8), \ + (unsigned int)(uc_dstart), \ +}, \ +{ \ + (_SHIFTL(G_LOAD_UCODE, 24, 8) | \ + _SHIFTL((int)(uc_dsize) - 1, 0, 16)), \ + (unsigned int)(uc_start), \ +} + +#define gSPLoadUcode(pkt, uc_start, uc_dstart) \ + gSPLoadUcodeEx((pkt), (uc_start), (uc_dstart), SP_UCODE_DATA_SIZE) +#define gsSPLoadUcode(uc_start, uc_dstart) \ + gsSPLoadUcodeEx((uc_start), (uc_dstart), SP_UCODE_DATA_SIZE) + +#define gSPLoadUcodeL(pkt, ucode) \ + gSPLoadUcode((pkt), OS_K0_TO_PHYSICAL(& ucode##TextStart), \ + OS_K0_TO_PHYSICAL(& ucode##DataStart)) +#define gsSPLoadUcodeL(ucode) \ + gsSPLoadUcode( OS_K0_TO_PHYSICAL(& ucode##TextStart), \ + OS_K0_TO_PHYSICAL(& ucode##DataStart)) + +/* + * gSPDma_io DMA to/from DMEM/IMEM for DEBUG. + */ +#define gSPDma_io(pkt, flag, dmem, dram, size) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_DMA_IO, 24, 8) | \ + _SHIFTL((flag), 23, 1) | \ + _SHIFTL((dmem) / 8, 13, 10) | \ + _SHIFTL((size) - 1, 0, 12)); \ + _g->words.w1 = (unsigned int)(dram); \ +}) + +#define gsSPDma_io(flag, dmem, dram, size) \ +{ \ + (_SHIFTL(G_DMA_IO, 24, 8) | \ + _SHIFTL((flag), 23, 1) | \ + _SHIFTL((dmem) / 8, 13, 10) | \ + _SHIFTL((size) - 1, 0, 12)), \ + (unsigned int)(dram) \ +} + +#define gSPDmaRead(pkt,dmem,dram,size) gSPDma_io((pkt),0,(dmem),(dram),(size)) +#define gsSPDmaRead(dmem,dram,size) gsSPDma_io( 0,(dmem),(dram),(size)) +#define gSPDmaWrite(pkt,dmem,dram,size) gSPDma_io((pkt),1,(dmem),(dram),(size)) +#define gsSPDmaWrite(dmem,dram,size) gsSPDma_io( 1,(dmem),(dram),(size)) + + +/* + * RSP short command (no DMA required) macros + */ +#define gImmp0(pkt, c) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ +}) + +#define gsImmp0(c) \ +{ \ + _SHIFTL((c), 24, 8) \ +} + +#define gImmp1(pkt, c, p0) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ + _g->words.w1 = (unsigned int)(p0); \ +}) + +#define gsImmp1(c, p0) \ +{ \ + _SHIFTL((c), 24, 8), \ + (unsigned int)(p0) \ +} + +#define gImmp2(pkt, c, p0, p1) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ + _g->words.w1 = (_SHIFTL((p0), 16, 16) | \ + _SHIFTL((p1), 8, 8)); \ +}) + +#define gsImmp2(c, p0, p1) \ +{ \ + _SHIFTL((c), 24, 8), \ + (_SHIFTL((p0), 16, 16) | \ + _SHIFTL((p1), 8, 8)) \ +} + +#define gImmp3(pkt, c, p0, p1, p2) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ + _g->words.w1 = (_SHIFTL((p0), 16, 16) | \ + _SHIFTL((p1), 8, 8) | \ + _SHIFTL((p2), 0, 8)); \ +}) + +#define gsImmp3(c, p0, p1, p2) \ +{ \ + _SHIFTL((c), 24, 8), \ + (_SHIFTL((p0), 16, 16) | \ + _SHIFTL((p1), 8, 8) | \ + _SHIFTL((p2), 0, 8)) \ +} + +#define gImmp21(pkt, c, p0, p1, dat) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL((c), 24, 8) | \ + _SHIFTL((p0), 8, 16) | \ + _SHIFTL((p1), 0, 8)); \ + _g->words.w1 = (unsigned int) (dat); \ +}) + +#define gsImmp21(c, p0, p1, dat) \ +{ \ + (_SHIFTL((c), 24, 8) | \ + _SHIFTL((p0), 8, 16) | \ + _SHIFTL((p1), 0, 8)), \ + (unsigned int) (dat) \ +} + +#define gMoveWd(pkt, index, offset, data) \ + gDma1p((pkt), G_MOVEWORD, data, (offset & 0xFFF), index) +#define gsMoveWd( index, offset, data) \ + gsDma1p( G_MOVEWORD, data, (offset & 0xFFF), index) + +#define gMoveHalfwd(pkt, index, offset, data) \ + gDma1p((pkt), G_MOVEWORD, data, (offset & 0xFFF) | G_MW_HALFWORD_FLAG, index) +#define gsMoveHalfwd( index, offset, data) \ + gsDma1p( G_MOVEWORD, data, (offset & 0xFFF) | G_MW_HALFWORD_FLAG, index) + + +/* + * Triangle commands + */ + +#define __gsSP1Triangle_w1(v0, v1, v2) \ + (_SHIFTL((v0) * 2, 16, 8) | \ + _SHIFTL((v1) * 2, 8, 8) | \ + _SHIFTL((v2) * 2, 0, 8)) + +#define __gsSP1Triangle_w1f(v0, v1, v2, flag) \ + (((flag) == 0) ? __gsSP1Triangle_w1(v0, v1, v2) : \ + ((flag) == 1) ? __gsSP1Triangle_w1(v1, v2, v0) : \ + __gsSP1Triangle_w1(v2, v0, v1)) + +#define __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag) \ + (((flag) == 0) ? __gsSP1Triangle_w1(v0, v1, v2) : \ + ((flag) == 1) ? __gsSP1Triangle_w1(v1, v2, v3) : \ + ((flag) == 2) ? __gsSP1Triangle_w1(v2, v3, v0) : \ + __gsSP1Triangle_w1(v3, v0, v1)) + +#define __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ + (((flag) == 0) ? __gsSP1Triangle_w1(v0, v2, v3) : \ + ((flag) == 1) ? __gsSP1Triangle_w1(v1, v3, v0) : \ + ((flag) == 2) ? __gsSP1Triangle_w1(v2, v0, v1) : \ + __gsSP1Triangle_w1(v3, v1, v2)) + + +/*** + *** 1 Triangle + ***/ +#define gSP1Triangle(pkt, v0, v1, v2, flag) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_TRI1, 24, 8) | \ + __gsSP1Triangle_w1f(v0, v1, v2, flag)); \ + _g->words.w1 = 0; \ +}) +#define gsSP1Triangle(v0, v1, v2, flag) \ +{ \ + (_SHIFTL(G_TRI1, 24, 8) | \ + __gsSP1Triangle_w1f(v0, v1, v2, flag)), \ + 0 \ +} + +/*** + *** 1 Quadrangle + ***/ +#define gSP1Quadrangle(pkt, v0, v1, v2, v3, flag) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_QUAD, 24, 8) | \ + __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)); \ + _g->words.w1 = (__gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag)); \ +}) + +#define gsSP1Quadrangle(v0, v1, v2, v3, flag) \ +{ \ + (_SHIFTL(G_QUAD, 24, 8) | \ + __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)), \ + __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ +} + +/*** + *** 2 Triangles + ***/ +#define gSP2Triangles(pkt, v00, v01, v02, flag0, v10, v11, v12, flag1) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_TRI2, 24, 8) | \ + __gsSP1Triangle_w1f(v00, v01, v02, flag0)); \ + _g->words.w1 = __gsSP1Triangle_w1f(v10, v11, v12, flag1); \ +}) + +#define gsSP2Triangles(v00, v01, v02, flag0, v10, v11, v12, flag1) \ +{ \ + (_SHIFTL(G_TRI2, 24, 8) | \ + __gsSP1Triangle_w1f(v00, v01, v02, flag0)), \ + __gsSP1Triangle_w1f(v10, v11, v12, flag1) \ +} + +/* + * 5 Triangles base commands + */ +#define _gSP5Triangles(pkt, cmd, v1, v2, v3, v4, v5, v6, v7) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(cmd, 24, 8) | \ + _SHIFTL((v1)*2, 16, 8) | \ + _SHIFTL((v2)*2, 8, 8) | \ + _SHIFTL((v3)*2, 0, 8)); \ + _g->words.w1 = (_SHIFTL((v4)*2, 24, 8) | \ + _SHIFTL((v5)*2, 16, 8) | \ + _SHIFTL((v6)*2, 8, 8) | \ + _SHIFTL((v7)*2, 0, 8)); \ +}) +#define _gsSP5Triangles(cmd, v1, v2, v3, v4, v5, v6, v7) \ +{ \ + (_SHIFTL(cmd, 24, 8) | \ + _SHIFTL((v1)*2, 16, 8) | \ + _SHIFTL((v2)*2, 8, 8) | \ + _SHIFTL((v3)*2, 0, 8)), \ + (_SHIFTL((v4)*2, 24, 8) | \ + _SHIFTL((v5)*2, 16, 8) | \ + _SHIFTL((v6)*2, 8, 8) | \ + _SHIFTL((v7)*2, 0, 8)) \ +}) +/* + * 5 Triangles in strip arrangement. Draws the following tris: + * v1-v2-v3, v3-v2-v4, v3-v4-v5, v5-v4-v6, v5-v6-v7 + * If you want to draw fewer tris, set indices to -1 from the right. + * e.g. to draw 4 tris, set v7 to -1; to draw 3 tris, set v6 to -1 + * Note that any set of 3 adjacent tris can be drawn with either SPTriStrip + * or SPTriFan. For arbitrary sets of 4 adjacent tris, four out of five of them + * can be drawn with one of SPTriStrip or SPTriFan. The 4-triangle formation + * which can't be drawn with either command looks like the Triforce. + */ +#define gSPTriStrip(pkt, v1, v2, v3, v4, v5, v6, v7) \ + _gSP5Triangles(pkt, G_TRISTRIP, v1, v2, v3, v4, v5, v6, v7) +#define gsSPTriStrip(v1, v2, v3, v4, v5, v6, v7) \ + _gsSP5Triangles(G_TRISTRIP, v1, v2, v3, v4, v5, v6, v7) +/* + * 5 Triangles in fan arrangement. Draws the following tris: + * v1-v2-v3, v1-v3-v4, v1-v4-v5, v1-v5-v6, v1-v6-v7 + * Otherwise works the same as SPTriStrip, see above. + */ +#define gSPTriFan(pkt, v1, v2, v3, v4, v5, v6, v7) \ + _gSP5Triangles(pkt, G_TRIFAN, v1, v2, v3, v4, v5, v6, v7) +#define gsSPTriFan(v1, v2, v3, v4, v5, v6, v7) \ + _gsSP5Triangles(G_TRIFAN, v1, v2, v3, v4, v5, v6, v7) + + +/* + * Moveword commands + */ +/* not strictly a moveword command anymore */ +#define gSPSegment(pkt, segment, base) \ + gDma1p((pkt), G_RELSEGMENT, (base), ((segment) * 4) & 0xFFF, G_MW_SEGMENT) +#define gsSPSegment(segment, base) \ + gsDma1p( G_RELSEGMENT, (base), ((segment) * 4) & 0xFFF, G_MW_SEGMENT) + +#define gSPPerspNormalize(pkt, s) gMoveHalfwd(pkt, G_MW_FX, G_MWO_PERSPNORM, (s)) +#define gsSPPerspNormalize(s) gsMoveHalfwd( G_MW_FX, G_MWO_PERSPNORM, (s)) + +/* + * Clipping Macros - Deprecated, encodes SP no-ops + * It is not possible to change the clip ratio from 2 in F3DEX3. + */ +#define gSPClipRatio(pkt, r) gSPNoOp(pkt) +#define gsSPClipRatio(r) gsSPNoOp() + +/* + * Load new MVP matrix directly. + * This is no longer supported as there is no MVP matrix in F3DEX3. + */ +#define gSPForceMatrix(pkt, mptr) gSPNoOp(pkt) +#define gsSPForceMatrix(mptr) gsSPNoOp() + +/* + * Ambient occlusion + * Enabled with the G_AMBOCCLUSION bit in geometry mode. + * Each of these factors sets how much ambient occlusion affects lights of + * the given type (ambient, directional, point). They are u16s. + * You can set each independently or two adjacent values with one moveword. + * A two-command macro is also provided to set all three values. + * + * When building the model, you must encode the amount of ambient occlusion at + * each vertex--effectively the shadow map for the model--in vertex alpha, where + * 00 means darkest and FF means lightest. Then, the factors set with the + * SPAmbOcclusion command determine how much the vertex alpha values affect the + * light intensity. For example, if the ambient factor is set to 0x8000, this + * means that in the darkest parts of the model, the ambient light intensity + * will be reduced by 50%, and in the lightest parts of the model, the ambient + * light intensity won't be reduced at all. + * + * The default is: + * amb = 0xFFFF (ambient light fully affected by vertex alpha) + * dir = 0xA000 (directional lights 62% affected by vertex alpha) + * point = 0 (point lights not at all affected by vertex alpha) + * + * Two reasons to use ambient occlusion rather than darkening the vertex colors: + * - With ambient occlusion, the geometry can be fully lit up with point and/or + * directional lights, depending on your settings here. + * - Ambient occlusion can be used with cel shading to create areas which are + * "darker" for the cel shading thresholds, but still have bright / white + * vertex colors. + * + * Two reasons to use these factors to modify ambient occlusion rather than + * just manually scaling and offsetting all the vertex alpha values: + * - To allow the behavior to differ between ambient, directional, and point + * lights + * - To allow the lighting to be adjusted at the scene level on-the-fly + */ + +#define gSPAmbOcclusionAmb(pkt, amb) gMoveHalfwd(pkt, G_MW_FX, G_MWO_AO_AMBIENT, amb) +#define gsSPAmbOcclusionAmb(amb) gsMoveHalfwd( G_MW_FX, G_MWO_AO_AMBIENT, amb) +#define gSPAmbOcclusionDir(pkt, dir) gMoveHalfwd(pkt, G_MW_FX, G_MWO_AO_DIRECTIONAL, dir) +#define gsSPAmbOcclusionDir(dir) gsMoveHalfwd( G_MW_FX, G_MWO_AO_DIRECTIONAL, dir) +#define gSPAmbOcclusionPoint(pkt, point) gMoveHalfwd(pkt, G_MW_FX, G_MWO_AO_POINT, point) +#define gsSPAmbOcclusionPoint(point) gsMoveHalfwd( G_MW_FX, G_MWO_AO_POINT, point) + +#define gSPAmbOcclusionAmbDir(pkt, amb, dir) \ + gMoveWd(pkt, G_MW_FX, G_MWO_AO_AMBIENT, \ + (_SHIFTL((amb), 16, 16) | _SHIFTL((dir), 0, 16))) +#define gsSPAmbOcclusionAmbDir(amb, dir) \ + gsMoveWd(G_MW_FX, G_MWO_AO_AMBIENT, \ + (_SHIFTL((amb), 16, 16) | _SHIFTL((dir), 0, 16))) +#define gSPAmbOcclusionDirPoint(pkt, dir, point) \ + gMoveWd(pkt, G_MW_FX, G_MWO_AO_DIRECTIONAL, \ + (_SHIFTL((dir), 16, 16) | _SHIFTL((point), 0, 16))) +#define gsSPAmbOcclusionDirPoint(dir, point) \ + gsMoveWd(G_MW_FX, G_MWO_AO_DIRECTIONAL, \ + (_SHIFTL((dir), 16, 16) | _SHIFTL((point), 0, 16))) + +#define gSPAmbOcclusion(pkt, amb, dir, point) \ +_DW({ \ + gSPAmbOcclusionAmbDir(pkt, amb, dir); \ + gSPAmbOcclusionPoint(pkt, point); \ +}) +#define gsSPAmbOcclusion(amb, dir, point) \ + gsSPAmbOcclusionAmbDir(amb, dir), \ + gsSPAmbOcclusionPoint(point) + +/* + * Fresnel - Feature suggested by thecozies + * Enabled with the G_FRESNEL bit in geometry mode. + * The dot product between a vertex normal and the vector from the vertex to the + * camera is computed. The offset and scale here convert this to a shade alpha + * value. This is useful for making surfaces fade between transparent when + * viewed straight-on and opaque when viewed at a large angle, or for applying a + * fake "outline" around the border of meshes. + * + * If using Fresnel, you need to set the camera world position whenever you set + * the VP matrix, viewport, etc. See SPCameraWorld. + * + * The RSP does: + * s16 dotProduct = dot(vertex normal, camera pos - vertex pos); + * dotProduct = abs(dotProduct); // 0 = points to side, 7FFF = points at or away + * s32 factor = ((scale * dotProduct) >> 15) + offset; + * s16 result = clamp(factor << 8, 0, 7FFF); + * color_or_alpha = result >> 7; + * + * At dotMax, color_or_alpha = FF, result = 7F80, factor = 7F + * At dotMin, color_or_alpha = 00, result = 0, factor = 0 + * 7F = ((scale * dotMax) >> 15) + offset + * 00 = ((scale * dotMin) >> 15) + offset + * Subtract: 7F = (scale * (dotMax - dotMin)) >> 15 + * 3F8000 = scale * (dotMax - dotMin) + * scale = 3F8000 / (dotMax - dotMin) <-- + * offset = -(((3F8000 / (dotMax - dotMin)) * dotMin) >> 15) + * offset = -((7F * dotMin) / (dotMax - dotMin)) <-- + * + * To convert in the opposite direction: + * ((7F - offset) << 15) / scale = dotMax + * ((00 - offset) << 15) / scale = dotMin + */ +#define gSPFresnelScale(pkt, scale) \ + gMoveHalfwd(pkt, G_MW_FX, G_MWO_FRESNEL_SCALE, scale) +#define gsSPFresnelScale(scale) \ + gsMoveHalfwd(G_MW_FX, G_MWO_FRESNEL_SCALE, scale) +#define gSPFresnelOffset(pkt, offset) \ + gMoveHalfwd(pkt, G_MW_FX, G_MWO_FRESNEL_OFFSET, offset) +#define gsSPFresnelOffset(offset) \ + gsMoveHalfwd(G_MW_FX, G_MWO_FRESNEL_OFFSET, offset) +#define gSPFresnel(pkt, scale, offset) \ + gMoveWd(pkt, G_MW_FX, G_MWO_FRESNEL_SCALE, \ + (_SHIFTL((scale), 16, 16) | _SHIFTL((offset), 0, 16))) +#define gsSPFresnel(scale, offset) \ + gsMoveWd(G_MW_FX, G_MWO_FRESNEL_SCALE, \ + (_SHIFTL((scale), 16, 16) | _SHIFTL((offset), 0, 16))) + +/* + * Attribute offsets + * These are added to ST or Z values after vertices are loaded and transformed. + * They are all s16s. + * For ST, the addition is after the multiplication for ST scale in SPTexture. + * For Z, this simply adds to the Z offset from the viewport. + * Whether each feature is enabled or disabled at a given time is determined + * by the G_ATTROFFSET_ST_ENABLE and G_ATTROFFSET_Z_ENABLE bits respectively in + * the geometry mode. + * Normally you would use ST offsets for UV scrolling, and you would use a Z + * offset of -2 (which it is set to by default) to fix decal mode. For the + * latter, enable the Z offset and set the Z mode to opaque. + */ +#define gSPAttrOffsetST(pkt, s, t) \ + gMoveWd(pkt, G_MW_FX, G_MWO_ATTR_OFFSET_S, \ + (_SHIFTL((s), 16, 16) | _SHIFTL((t), 0, 16))) +#define gsSPAttrOffsetST(s, t) \ + gsMoveWd(G_MW_FX, G_MWO_ATTR_OFFSET_S, \ + (_SHIFTL((s), 16, 16) | _SHIFTL((t), 0, 16))) +#define gSPAttrOffsetZ(pkt, z) \ + gMoveHalfwd(pkt, G_MW_FX, G_MWO_ATTR_OFFSET_Z, z) +#define gsSPAttrOffsetZ(z) \ + gsMoveHalfwd(G_MW_FX, G_MWO_ATTR_OFFSET_Z, z) + +/* + * Alpha compare culling. Optimization for cel shading, could also be used for + * other scenarios where lots of tris are being drawn with alpha compare. + * + * If mode == G_ALPHA_COMPARE_CULL_DISABLE, tris are drawn normally. + * + * Otherwise: + * - "vertex alpha" means the post-transform alpha value at each vertex being + * sent to the RDP. This may be the original model vertex alpha, fog, light + * level (for cel shading), or Fresnel. + * - Assuming a cel shading context: you have a threshold value thresh, you draw + * tris once and want to write all pixels where shade alpha >= thresh. Then + * you change color settings and draw tris again, and want to write all other + * pixels, i.e. where shade alpha < thresh. + * + * For the light pass: + * - Set blend color alpha to thresh + * - Set CC alpha cycle 1 (or only cycle) to (shade alpha - 0) * tex alpha + 0 + * - The RDP will draw pixels whenever shade alpha >= thresh (with binary alpha + * from the texture) + * - Set mode = G_ALPHA_COMPARE_CULL_BELOW in SPAlphaCompareCull, and thresh + * - The RSP will cull any tris where all three vertex alpha values (i.e. light + * level) are < thresh + * + * For the dark pass: + * - Set blend color alpha to 0x100 - thresh (yes, not 0xFF - thresh). + * - Set CC alpha cycle 1 (or only cycle) to (1 - shade alpha) * tex alpha + 0 + * - The RDP will draw pixels whenever shade alpha < thresh (with binary alpha + * from the texture) + * - Set mode = G_ALPHA_COMPARE_CULL_ABOVE in SPAlphaCompareCull, and thresh + * - The RSP will cull any tris where all three vertex alpha values (i.e. light + * level) are >= thresh + * + * The idea is to cull tris early on the RSP which won't have any of their + * fragments drawn on the RDP, to save RDP time and memory bandwidth. + */ +#define gSPAlphaCompareCull(pkt, mode, thresh) \ + gMoveHalfwd(pkt, G_MW_FX, G_MWO_ALPHA_COMPARE_CULL, \ + (_SHIFTL((mode), 8, 8) | _SHIFTL((thresh), 0, 8))) +#define gsSPAlphaCompareCull(mode, thresh) \ + gsMoveHalfwd(G_MW_FX, G_MWO_ALPHA_COMPARE_CULL, \ + (_SHIFTL((mode), 8, 8) | _SHIFTL((thresh), 0, 8))) + +/* + * Normals mode: How to handle transformation of vertex normals from model to + * world space for lighting. + * + * If mode = G_NORMALS_MODE_FAST, transforms normals from model space to world + * space with the M matrix. This is correct if the object's transformation + * matrix stack only included translations, rotations, and uniform scale (i.e. + * same scale in X, Y, and Z); otherwise, if the transformation matrix has + * nonuniform scale or shear, the lighting on the object will be somewhat + * distorted. + * + * If mode = G_NORMALS_MODE_AUTO, transforms normals from model space to world + * space with M inverse transpose, which renders lighting correctly for the + * object regardless of its transformation matrix (nonuniform scale or shear is + * okay). Whenever vertices are drawn with lighting enabled after M has been + * changed, computes M inverse transpose from M. This requires swapping to + * overlay 4 for M inverse transpose and then back to overlay 2 for lighting, + * which produces roughly 3.5 us of extra DRAM traffic. This performance penalty + * happens effectively once per matrix, which is once per normal object or + * separated limb or about twice per flex skeleton limb. So in a scene with lots + * of complex skeletons, this may have a noticeable performance impact. + * + * If mode = G_NORMALS_MODE_MANUAL, uses M inverse transpose for correct results + * like G_NORMALS_MODE_AUTO, but it never internally computes M inverse + * transpose. You have to upload M inverse transpose to the RSP using + * SPMITMatrix every time you change the M matrix. The DRAM traffic for the + * extra matrix uploads is much smaller than the overlay swaps, so if you can + * efficiently compute M inverse transpose on the CPU, this may be faster than + * G_NORMALS_MODE_AUTO. + * + * Recommended to leave this set to G_NORMALS_MODE_FAST generally, and only set + * it to G_NORMALS_MODE_AUTO for specific objects at times when they actually + * have a nonuniform scale. For example, G_NORMALS_MODE_FAST for Mario + * generally, but G_NORMALS_MODE_AUTO temporarily while he is squashed. + */ +#define gSPNormalsMode(pkt, mode) \ + gMoveHalfwd(pkt, G_MW_FX, G_MWO_NORMALS_MODE, (mode) & 0xFF) +#define gsSPNormalsMode(mode) \ + gsMoveHalfwd(G_MW_FX, G_MWO_NORMALS_MODE, (mode) & 0xFF) + +typedef union { + struct { + s16 intPart[3][4]; /* Fourth row containing translations is omitted. */ + u16 fracPart[3][4]; /* Also the fourth column data is ignored, need not be 0. */ + }; + long long int force_structure_alignment; +} MITMtx; + +/* + * See SPNormalsMode. mtx is the address of a MITMtx (M inverse transpose). + * + * The matrix values must be scaled down so that the matrix norm is <= 1, + * i.e. multiplying this matrix by any vector length <= 1 must produce a vector + * with length <= 1. Normally, M scales things down substantially, so M inverse + * transpose natively would scale them up substantially; you need to apply a + * constant scale to counteract this. One easy way to do this is compute M + * inverse transpose normally, then scale it so until the maximum absolute + * value of any element is 0.5. Because of this scaling, you can also skip the + * part of the inverse computation where you compute the determinant and divide + * by it, cause you're going to rescale it arbitrarily anyway. + */ +#define gSPMITMatrix(pkt, mit) \ + gDma2p((pkt), G_MOVEMEM, (mit), sizeof(MITMtx), G_MV_MMTX, 0x80) +#define gsSPMITMatrix(mtx) \ + gsDma2p( G_MOVEMEM, (mit), sizeof(MITMtx), G_MV_MMTX, 0x80) + + +/* + * Insert values into Vertices + * + * vtx = vertex number 0-55 + * where = which element of point to modify (byte offset into vertex) + * num = new value (32 bit) + */ +# define gSPModifyVertex(pkt, vtx, where, val) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_MODIFYVTX, 24, 8) | \ + _SHIFTL((where), 16, 8) | \ + _SHIFTL((vtx) * 2, 0, 16)); \ + _g->words.w1 = (unsigned int)(val); \ +}) +# define gsSPModifyVertex(vtx, where, val) \ +{ \ + (_SHIFTL(G_MODIFYVTX, 24, 8) | \ + _SHIFTL((where), 16, 8) | \ + _SHIFTL((vtx) * 2, 0, 16)), \ + (unsigned int)(val) \ +} + +/* + * Display list optimization / object culling + */ + +/* + * Cull the display list based on screen clip flags of range of loaded verts. + * Executes SPEndDisplayList if the convex hull formed by the specified range of + * already-loaded vertices is offscreen. + */ +#define gSPCullDisplayList(pkt,vstart,vend) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_CULLDL, 24, 8) | \ + _SHIFTL((vstart) * 2, 0, 16)); \ + _g->words.w1 = _SHIFTL((vend) * 2, 0, 16); \ +}) + +#define gsSPCullDisplayList(vstart,vend) \ +{ \ + (_SHIFTL(G_CULLDL, 24, 8) | \ + _SHIFTL((vstart) * 2, 0, 16)), \ + _SHIFTL((vend) * 2, 0, 16) \ +} + +/* + * gSPBranchLessZ Branch DL if (vtx.z) less than or equal (zval). + * Note that this uses W in F3DZEX / CFG_G_BRANCH_W, in which case all the + * Z calculations below are wrong and raw values must be used. + * + * dl = DL branch to + * vtx = Vertex + * zval = Screen depth + * near = Near plane + * far = Far plane + * flag = G_BZ_PERSP or G_BZ_ORTHO + */ + +/* From gu.h */ +#ifndef FTOFIX32 +# define FTOFIX32(x) (long)((x) * (float)0x00010000) +#endif + +#define G_BZ_PERSP 0 +#define G_BZ_ORTHO 1 + +#define G_DEPTOZSrg(zval, near, far, flag, zmin, zmax) \ + (((unsigned int)FTOFIX32(((flag) == G_BZ_PERSP ? \ + (1.0f - (float)(near) / (float)(zval)) / \ + (1.0f - (float)(near) / (float)(far )) : \ + ((float)(zval) - (float)(near)) / \ + ((float)(far ) - (float)(near))))) * \ + (((int)((zmax) - (zmin))) & ~1) + (int)FTOFIX32(zmin)) + +#define G_DEPTOZS(zval, near, far, flag) \ + G_DEPTOZSrg(zval, near, far, flag, 0, G_MAXZ) + +#define gSPBranchLessZrg(pkt, dl, vtx, zval, near, far, flag, zmin, zmax) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_RDPHALF_1, 24, 8); \ + _g->words.w1 = (unsigned int)(dl); \ + \ + _g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_BRANCH_Z, 24, 8) | \ + _SHIFTL((vtx) * 5, 12, 12) | \ + _SHIFTL((vtx) * 2, 0, 12)); \ + _g->words.w1 = G_DEPTOZSrg(zval, near, far, flag, zmin, zmax); \ +}) + +#define gsSPBranchLessZrg(dl, vtx, zval, near, far, flag, zmin, zmax) \ +{ \ + _SHIFTL(G_RDPHALF_1, 24, 8), \ + (unsigned int)(dl), \ +}, \ +{ \ + (_SHIFTL(G_BRANCH_Z, 24, 8) | \ + _SHIFTL((vtx) * 5, 12, 12) | \ + _SHIFTL((vtx) * 2, 0, 12)), \ + G_DEPTOZSrg(zval, near, far, flag, zmin, zmax), \ +} + +#define gSPBranchLessZ(pkt, dl, vtx, zval, near, far, flag) \ + gSPBranchLessZrg(pkt, dl, vtx, zval, near, far, flag, 0, G_MAXZ) +#define gsSPBranchLessZ(dl, vtx, zval, near, far, flag) \ + gsSPBranchLessZrg(dl, vtx, zval, near, far, flag, 0, G_MAXZ) + +/* + * gSPBranchLessZraw Branch DL if (vtx.z) less than or equal (raw zval). + * + * dl = DL branch to + * vtx = Vertex + * zval = Raw value of screen depth + */ +#define gSPBranchLessZraw(pkt, dl, vtx, zval) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_RDPHALF_1, 24, 8); \ + _g->words.w1 = (unsigned int)(dl); \ + \ + _g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_BRANCH_Z, 24, 8) | \ + _SHIFTL((vtx) * 5, 12, 12) | \ + _SHIFTL((vtx) * 2, 0, 12)); \ + _g->words.w1 = (unsigned int)(zval); \ +}) + +#define gsSPBranchLessZraw(dl, vtx, zval) \ +{ \ + _SHIFTL(G_RDPHALF_1, 24, 8), \ + (unsigned int)(dl), \ +}, \ +{ \ + (_SHIFTL(G_BRANCH_Z, 24, 8) | \ + _SHIFTL((vtx) * 5, 12, 12) | \ + _SHIFTL((vtx) * 2, 0, 12)), \ + (unsigned int)(zval), \ +} + + +/* + * Lighting Commands + */ + +#define NUML(n) ((n) * 0x10) +/* + * F3DEX3 properly supports zero lights, so there is no need to use these macros + * anymore. + */ +#define NUMLIGHTS_0 0 +#define NUMLIGHTS_1 1 +#define NUMLIGHTS_2 2 +#define NUMLIGHTS_3 3 +#define NUMLIGHTS_4 4 +#define NUMLIGHTS_5 5 +#define NUMLIGHTS_6 6 +#define NUMLIGHTS_7 7 +#define NUMLIGHTS_8 8 +#define NUMLIGHTS_9 9 + +/* + * Number of directional / point lights, in the range 0-9. There is also always + * one ambient light not counted in this number. + */ +#define gSPNumLights(pkt, n) \ + gMoveWd(pkt, G_MW_NUMLIGHT, G_MWO_NUMLIGHT, NUML(n)) +#define gsSPNumLights(n) \ + gsMoveWd( G_MW_NUMLIGHT, G_MWO_NUMLIGHT, NUML(n)) + +/* There is also no need to use these macros. */ +#define LIGHT_1 1 +#define LIGHT_2 2 +#define LIGHT_3 3 +#define LIGHT_4 4 +#define LIGHT_5 5 +#define LIGHT_6 6 +#define LIGHT_7 7 +#define LIGHT_8 8 +#define LIGHT_9 9 +#define LIGHT_10 10 + +/* + * l should point to a Light or PosLight struct. + * n should be an integer 1-9 to load lights 0-8. + * Can also load Ambient lights to lights 0-8 with this. However, if you have + * 9 directional / point lights, you must use SPAmbient to load light 9 + * (LIGHT_10) with an ambient light. (That is, the memory for light 9 (LIGHT_10) + * is only sizeof(Ambient), so if you load this with SPLight, it will overwrite + * other DMEM and corrupt unrelated things.) + * New code should not generally use SPLight, and instead use SPSetLights to set + * all lights in one memory transaction. + */ +#define _LIGHT_TO_OFFSET(n) (((n) - 1) * 0x10 + 0x10) /* The + 0x10 skips cam pos and lookat */ +#define gSPLight(pkt, l, n) \ + gDma2p((pkt), G_MOVEMEM, (l), sizeof(Light), G_MV_LIGHT, _LIGHT_TO_OFFSET(n)) +#define gsSPLight(l, n) \ + gsDma2p( G_MOVEMEM, (l), sizeof(Light), G_MV_LIGHT, _LIGHT_TO_OFFSET(n)) + +/* + * l should point to an Ambient struct. + * n should be an integer 1-10 to load lights 0-9. + */ +#define gSPAmbient(pkt, l, n) \ + gDma2p((pkt), G_MOVEMEM, (l), sizeof(Ambient), G_MV_LIGHT, _LIGHT_TO_OFFSET(n)) +#define gsSPAmbient(l, n) \ + gsDma2p( G_MOVEMEM, (l), sizeof(Ambient), G_MV_LIGHT, _LIGHT_TO_OFFSET(n)) + +/* + * gSPLightColor changes the color of a directional light without an additional + * DMA transfer. + * col is a 32 bit word where (col >> 24) & 0xFF is red, (col >> 16) & 0xFF is + * green, and (col >> 8) & 0xFF is blue. (col & 0xFF) is ignored and masked to + * zero. + * n should be an integer 1-10 to apply to light 0-9. + */ +#define gSPLightColor(pkt, n, col) \ +_DW({ \ + gMoveWd(pkt, G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 0, ((col) & 0xFFFFFF00)); \ + gMoveWd(pkt, G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 4, ((col) & 0xFFFFFF00)); \ +}) +#define gsSPLightColor(n, col) \ + gsMoveWd(G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 0, ((col) & 0xFFFFFF00)), \ + gsMoveWd(G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 4, ((col) & 0xFFFFFF00)) +/* + * Version for point lights. (col1 & 0xFF) must be set to the point light constant + * factor (must be nonzero), and (col2 & 0xFF) must be set to the point light + * linear factor. + * n should be an integer 1-10 to apply to light 0-9. + */ +#define _gSPLightColor2(pkt, n, col1, col2) \ +_DW({\ + gMoveWd(pkt, G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 0, col1); \ + gMoveWd(pkt, G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 4, col2); \ +}) +#define _gsSPLightColor2(n, col1, col2) \ + gsMoveWd(G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 0, col1), \ + gsMoveWd(G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 4, col2) + + +/* + * Set all your scene's lights (directional/point + ambient) with one memory + * transaction. + * n is the number of directional / point lights, from 0 to 9. There is also + * always an ambient light. + * name should be the NAME of a Lights or PosLights struct (NOT A POINTER) + * filled in with all the lighting data. You can use the gdSPDef* macros to fill + * in the struct or just do it manually. Example: + * PosLights2 myLights; // 2 pos + 1 ambient + * + * gSPSetLights(POLY_OPA_DISP++, 2, myLights); + * + * If you need to use a pointer, e.g. if the number of lights is variable at + * runtime: + * PosLight *lights = memory_allocate((numLights + 1) * sizeof(PosLight)); + * lights[0].p.pos = ...; + * lights[1].l.dir = ...; + * ... + * lights[numLights].l.col = ambient_color(); + * gSPSetLights(POLY_OPA_DISP++, numLights, *lights); // <- NOTE DEREFERENCE + * + * If you're wondering why this macro takes a name / dereference instead of a + * pointer, it's for backwards compatibility. + */ +#define gSPSetLights(pkt, n, name) \ +_DW({ \ + gSPNumLights(pkt, n); \ + gDma2p((pkt), G_MOVEMEM, &(name), (n) * 0x10 + 8, G_MV_LIGHT, 0x10); \ +}) +#define gsSPSetLights(n, name) \ + gsSPNumLights(n), \ + gsDma2p(G_MOVEMEM, &(name), (n) * 0x10 + 8, G_MV_LIGHT, 0x10) + +#define gSPSetLights0(pkt, name) gSPSetLights(pkt, 0, name) +#define gsSPSetLights0(name) gsSPSetLights( 0, name) +#define gSPSetLights1(pkt, name) gSPSetLights(pkt, 1, name) +#define gsSPSetLights1(name) gsSPSetLights( 1, name) +#define gSPSetLights2(pkt, name) gSPSetLights(pkt, 2, name) +#define gsSPSetLights2(name) gsSPSetLights( 2, name) +#define gSPSetLights3(pkt, name) gSPSetLights(pkt, 3, name) +#define gsSPSetLights3(name) gsSPSetLights( 3, name) +#define gSPSetLights4(pkt, name) gSPSetLights(pkt, 4, name) +#define gsSPSetLights4(name) gsSPSetLights( 4, name) +#define gSPSetLights5(pkt, name) gSPSetLights(pkt, 5, name) +#define gsSPSetLights5(name) gsSPSetLights( 5, name) +#define gSPSetLights6(pkt, name) gSPSetLights(pkt, 6, name) +#define gsSPSetLights6(name) gsSPSetLights( 6, name) +#define gSPSetLights7(pkt, name) gSPSetLights(pkt, 7, name) +#define gsSPSetLights7(name) gsSPSetLights( 7, name) +#define gSPSetLights8(pkt, name) gSPSetLights(pkt, 8, name) +#define gsSPSetLights8(name) gsSPSetLights( 8, name) +#define gSPSetLights9(pkt, name) gSPSetLights(pkt, 9, name) +#define gsSPSetLights9(name) gsSPSetLights( 9, name) + + +/* + * Camera world position for Fresnel and specular lighting. Set this whenever + * you set the VP matrix, viewport, etc. cam is the address of a PlainVtx struct. + */ +#define gSPCameraWorld(pkt, cam) \ + gDma2p((pkt), G_MOVEMEM, (cam), sizeof(PlainVtx), G_MV_LIGHT, 0) +#define gsSPCameraWorld(cam) \ + gsDma2p( G_MOVEMEM, (cam), sizeof(PlainVtx), G_MV_LIGHT, 0) + + +/* + * Reflection/Hiliting Macros. + * la is the address of a LookAt struct. + */ +#define gSPLookAt(pkt, la) \ + gDma2p((pkt), G_MOVEMEM, (la), sizeof(LookAt), G_MV_LIGHT, 8) +#define gsSPLookAt(la) \ + gsDma2p( G_MOVEMEM, (la), sizeof(LookAt), G_MV_LIGHT, 8) + +/* + * These versions are deprecated, please use g*SPLookAt. The two directions + * cannot be set independently anymore as they both fit within one memory word. + * (They could be set with moveword, but then the values would have to be within + * the command itself, not at a memory address.) + * This deprecated version has the X command set both (assuming l is the name / + * address of a LookAt struct) and has the Y command as a SP no-op. + */ +#define gSPLookAtX(pkt, l) gSPLookAt(pkt, l) +#define gsSPLookAtX(l) gsSPLookAt(l) +#define gSPLookAtY(pkt, l) gSPNoOp(pkt) +#define gsSPLookAtY(l) gsSPNoOp() + + +#define gDPSetHilite1Tile(pkt, tile, hilite, width, height) \ + gDPSetTileSize(pkt, tile, \ + (hilite)->h.x1 & 0xFFF, \ + (hilite)->h.y1 & 0xFFF, \ + ((((width) - 1) * 4) + (hilite)->h.x1) & 0xFFF, \ + ((((height) - 1) * 4) + (hilite)->h.y1) & 0xFFF) +#define gsDPSetHilite1Tile(tile, hilite, width, height) \ + gsDPSetTileSize(tile, \ + (hilite)->h.x1 & 0xFFF, \ + (hilite)->h.y1 & 0xFFF, \ + ((((width) - 1) * 4) + (hilite)->h.x1) & 0xFFF, \ + ((((height) - 1) * 4) + (hilite)->h.y1) & 0xFFF) + +#define gDPSetHilite2Tile(pkt, tile, hilite, width, height) \ + gDPSetTileSize(pkt, tile, \ + (hilite)->h.x2 & 0xFFF, \ + (hilite)->h.y2 & 0xFFF, \ + ((((width) - 1) * 4) + (hilite)->h.x2) & 0xFFF, \ + ((((height) - 1) * 4) + (hilite)->h.y2) & 0xFFF) +#define gsDPSetHilite2Tile(tile, hilite, width, height) \ + gsDPSetTileSize(tile, \ + (hilite)->h.x2 & 0xFFF, \ + (hilite)->h.y2 & 0xFFF, \ + ((((width) - 1) * 4) + (hilite)->h.x2) & 0xFFF, \ + ((((height) - 1) * 4) + (hilite)->h.y2) & 0xFFF) + + +/* + * Set the occlusion plane. This is a quadrilateral in 3D space where all + * geometry behind it is culled. You should create occlusion plane candidates + * just behind walls and other large objects, and have your game engine pick + * the most optimal one every frame to send to the RSP. + * + * Computing the coefficients for the occlusion plane is far too complicated to + * explain here. The reference implementation `guOcclusionPlane` is provided + * separately. + * + * o is the address of an OcclusionPlane struct + */ +#define gSPOcclusionPlane(pkt, o) \ + gDma2p((pkt), G_MOVEMEM, (o), sizeof(OcclusionPlane), G_MV_LIGHT, \ + (G_MAX_LIGHTS * 0x10) + 0x18) +#define gsSPOcclusionPlane(o) \ + gsDma2p( G_MOVEMEM, (o), sizeof(OcclusionPlane), G_MV_LIGHT, \ + (G_MAX_LIGHTS * 0x10) + 0x18) + + +/* + * FOG macros + * fm = z multiplier + * fo = z offset + * FOG FORMULA: alpha(fog) = (eyespace z) * fm + fo CLAMPED 0 to 255 + * note: (eyespace z) ranges -1 to 1 + * + * Alternate method of setting fog: + * min, max: range 0 to 1000: 0=nearplane, 1000=farplane + * min is where fog begins (usually less than max and often 0) + * max is where fog is thickest (usually 1000) + * + */ +#define gSPFogFactor(pkt, fm, fo) \ + gMoveWd(pkt, G_MW_FOG, G_MWO_FOG, \ + (_SHIFTL(fm, 16, 16) | _SHIFTL(fo, 0, 16))) + +#define gsSPFogFactor(fm, fo) \ + gsMoveWd(G_MW_FOG, G_MWO_FOG, \ + (_SHIFTL(fm, 16, 16) | _SHIFTL(fo, 0, 16))) + +#define gSPFogPosition(pkt, min, max) \ + gMoveWd(pkt, G_MW_FOG, G_MWO_FOG, \ + (_SHIFTL((128000 / ((max) - (min))), 16, 16) | \ + _SHIFTL(((500 - (min)) * 256 / ((max) - (min))), 0, 16))) + +#define gsSPFogPosition(min, max) \ + gsMoveWd(G_MW_FOG, G_MWO_FOG, \ + (_SHIFTL((128000 / ((max) - (min))), 16, 16) | \ + _SHIFTL(((500 - (min)) * 256 / ((max) - (min))), 0, 16))) + + +/* + * Macros to turn texture on/off + */ +#define gSPTexture(pkt, s, t, level, tile, on) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXTURE, 24, 8) | \ + _SHIFTL((level), 11, 3) | \ + _SHIFTL((tile), 8, 3) | \ + _SHIFTL((on), 1, 7)); \ + _g->words.w1 = (_SHIFTL((s), 16, 16) | \ + _SHIFTL((t), 0, 16)); \ +}) +#define gsSPTexture(s, t, level, tile, on) \ +{ \ + (_SHIFTL(G_TEXTURE, 24, 8) | \ + _SHIFTL((level), 11, 3) | \ + _SHIFTL((tile), 8, 3) | \ + _SHIFTL((on), 1, 7)), \ + (_SHIFTL((s), 16, 16) | \ + _SHIFTL((t), 0, 16)) \ +} + +/* + * The bowtie value is a workaround for a bug in HW V1, and is not supported + * by F3DEX2, let alone F3DEX3. + */ +#define gSPTextureL(pkt, s, t, level, bowtie, tile, on) \ + gSPTexture(pkt, s, t, level, tile, on) +#define gsSPTextureL(s, t, level, bowtie, tile, on) \ + gsSPTexture(s, t, level, tile, on) + +/* + * One gSPGeometryMode(pkt,c,s) GBI is equal to these two GBIs. + * + * gSPClearGeometryMode(pkt,c) + * gSPSetGeometryMode(pkt,s) + * + * gSPLoadGeometryMode(pkt, word) sets GeometryMode directly. + */ +#define gSPGeometryMode(pkt, c, s) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_GEOMETRYMODE, 24, 8) | \ + _SHIFTL(~(u32)(c), 0, 24)); \ + _g->words.w1 = (u32)(s); \ +}) + +#define gsSPGeometryMode(c, s) \ +{ \ + (_SHIFTL(G_GEOMETRYMODE, 24, 8) | \ + _SHIFTL(~(u32)(c), 0, 24)), \ + (u32)(s) \ +} + +#define gSPSetGeometryMode(pkt, word) gSPGeometryMode((pkt), 0, (word)) +#define gsSPSetGeometryMode(word) gsSPGeometryMode( 0, (word)) +#define gSPClearGeometryMode(pkt, word) gSPGeometryMode((pkt), (word), 0) +#define gsSPClearGeometryMode(word) gsSPGeometryMode( (word), 0) +#define gSPLoadGeometryMode(pkt, word) gSPGeometryMode((pkt), -1, (word)) +#define gsSPLoadGeometryMode(word) gsSPGeometryMode( -1, (word)) + +#define gsSPGeometryModeSetFirst(c, s) gsSPGeometryMode(c, s) + +#define gSPSetOtherMode(pkt, cmd, sft, len, data) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(cmd, 24, 8) | \ + _SHIFTL(32 - (sft) - (len), 8, 8) | \ + _SHIFTL((len) - 1, 0, 8)); \ + _g->words.w1 = (unsigned int)(data); \ +}) + +#define gsSPSetOtherMode(cmd, sft, len, data) \ +{ \ + (_SHIFTL(cmd, 24, 8) | \ + _SHIFTL(32 - (sft) - (len), 8, 8) | \ + _SHIFTL((len) - 1, 0, 8)), \ + (unsigned int)(data) \ +} + +/* + * RDP setothermode register commands - register shadowed in RSP + */ +#define gDPPipelineMode(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_PIPELINE, 1, mode) +#define gsDPPipelineMode(mode) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_PIPELINE, 1, mode) + +#define gDPSetCycleType(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_CYCLETYPE, 2, type) +#define gsDPSetCycleType(type) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_CYCLETYPE, 2, type) + +#define gDPSetTexturePersp(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTPERSP, 1, type) +#define gsDPSetTexturePersp(type) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_TEXTPERSP, 1, type) + +#define gDPSetTextureDetail(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTDETAIL, 2, type) +#define gsDPSetTextureDetail(type) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_TEXTDETAIL, 2, type) + +#define gDPSetTextureLOD(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTLOD, 1, type) +#define gsDPSetTextureLOD(type) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_TEXTLOD, 1, type) + +#define gDPSetTextureLUT(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTLUT, 2, type) +#define gsDPSetTextureLUT(type) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_TEXTLUT, 2, type) + +#define gDPSetTextureFilter(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTFILT, 2, type) +#define gsDPSetTextureFilter(type) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_TEXTFILT, 2, type) + +#define gDPSetTextureConvert(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTCONV, 3, type) +#define gsDPSetTextureConvert(type) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_TEXTCONV, 3, type) + +#define gDPSetCombineKey(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_COMBKEY, 1, type) +#define gsDPSetCombineKey(type) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_COMBKEY, 1, type) + +#define gDPSetColorDither(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_RGBDITHER, 2, mode) +#define gsDPSetColorDither(mode) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_RGBDITHER, 2, mode) + +#define gDPSetAlphaDither(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode) +#define gsDPSetAlphaDither(mode) \ + gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode) + +/* 'blendmask' is not supported anymore. + * The bits are reserved for future use. + * Fri May 26 13:45:55 PDT 1995 + */ +#define gDPSetBlendMask(pkt, mask) gDPNoOp(pkt) +#define gsDPSetBlendMask(mask) gsDPNoOp() + +#define gDPSetAlphaCompare(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_ALPHACOMPARE, 2, type) +#define gsDPSetAlphaCompare(type) \ + gsSPSetOtherMode( G_SETOTHERMODE_L, G_MDSFT_ALPHACOMPARE, 2, type) + +#define gDPSetDepthSource(pkt, src) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_ZSRCSEL, 1, src) +#define gsDPSetDepthSource(src) \ + gsSPSetOtherMode( G_SETOTHERMODE_L, G_MDSFT_ZSRCSEL, 1, src) + +#define gDPSetRenderMode(pkt, c0, c1) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_RENDERMODE, 29, (c0) | (c1)) +#define gsDPSetRenderMode(c0, c1) \ + gsSPSetOtherMode( G_SETOTHERMODE_L, G_MDSFT_RENDERMODE, 29, (c0) | (c1)) + +#define gSetImage(pkt, cmd, fmt, siz, width, i) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(cmd, 24, 8) | \ + _SHIFTL(fmt, 21, 3) | \ + _SHIFTL(siz, 19, 2) | \ + _SHIFTL((width) - 1, 0, 12)); \ + _g->words.w1 = (unsigned int)(i); \ +}) + +#define gsSetImage(cmd, fmt, siz, width, i) \ +{ \ + (_SHIFTL(cmd, 24, 8) | \ + _SHIFTL(fmt, 21, 3) | \ + _SHIFTL(siz, 19, 2) | \ + _SHIFTL((width) - 1, 0, 12)), \ + (unsigned int)(i) \ +} + +#define gDPSetColorImage(pkt, f, s, w, i) gSetImage(pkt, G_SETCIMG, f, s, w, i) +#define gsDPSetColorImage(f, s, w, i) gsSetImage( G_SETCIMG, f, s, w, i) + + +/* use these for new code */ +#define gDPSetDepthImage(pkt, i) gSetImage(pkt, G_SETZIMG, 0, 0, 1, i) +#define gsDPSetDepthImage(i) gsSetImage( G_SETZIMG, 0, 0, 1, i) +/* kept for compatibility */ +#define gDPSetMaskImage(pkt, i) gDPSetDepthImage(pkt, i) +#define gsDPSetMaskImage(i) gsDPSetDepthImage( i) + +#define gDPSetTextureImage(pkt, f, s, w, i) gSetImage(pkt, G_SETTIMG, f, s, w, i) +#define gsDPSetTextureImage(f, s, w, i) gsSetImage( G_SETTIMG, f, s, w, i) + +/* + * RDP macros + */ + +#define gDPSetCombine(pkt, muxs0, muxs1) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETCOMBINE, 24, 8) | \ + _SHIFTL(muxs0, 0, 24)); \ + _g->words.w1 = (unsigned int)(muxs1); \ +}) + +#define gsDPSetCombine(muxs0, muxs1) \ +{ \ + (_SHIFTL(G_SETCOMBINE, 24, 8) | \ + _SHIFTL(muxs0, 0, 24)), \ + (unsigned int)(muxs1) \ +} + +#define GCCc0w0(saRGB0, mRGB0, saA0, mA0) \ + (_SHIFTL((saRGB0), 20, 4) | \ + _SHIFTL((mRGB0), 15, 5) | \ + _SHIFTL((saA0), 12, 3) | \ + _SHIFTL((mA0), 9, 3)) + +#define GCCc1w0(saRGB1, mRGB1) \ + (_SHIFTL((saRGB1), 5, 4) | \ + _SHIFTL((mRGB1), 0, 5)) + +#define GCCc0w1(sbRGB0, aRGB0, sbA0, aA0) \ + (_SHIFTL((sbRGB0), 28, 4) | \ + _SHIFTL((aRGB0), 15, 3) | \ + _SHIFTL((sbA0), 12, 3) | \ + _SHIFTL((aA0), 9, 3)) + +#define GCCc1w1(sbRGB1, saA1, mA1, aRGB1, sbA1, aA1) \ + (_SHIFTL((sbRGB1), 24, 4) | \ + _SHIFTL((saA1), 21, 3) | \ + _SHIFTL((mA1), 18, 3) | \ + _SHIFTL((aRGB1), 6, 3) | \ + _SHIFTL((sbA1), 3, 3) | \ + _SHIFTL((aA1), 0, 3)) + +#define gDPSetCombineLERP(pkt, a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, \ + a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETCOMBINE, 24, 8) | \ + _SHIFTL(GCCc0w0(G_CCMUX_##a0, G_CCMUX_##c0, \ + G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \ + GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), \ + 0, 24)); \ + _g->words.w1 = (unsigned int)(GCCc0w1(G_CCMUX_##b0, G_CCMUX_##d0, \ + G_ACMUX_##Ab0, G_ACMUX_##Ad0) | \ + GCCc1w1(G_CCMUX_##b1, G_ACMUX_##Aa1, \ + G_ACMUX_##Ac1, G_CCMUX_##d1, \ + G_ACMUX_##Ab1, G_ACMUX_##Ad1)); \ +}) + +#define gsDPSetCombineLERP(a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, \ + a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \ +{ \ + (_SHIFTL(G_SETCOMBINE, 24, 8) | \ + _SHIFTL(GCCc0w0(G_CCMUX_##a0, G_CCMUX_##c0, \ + G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \ + GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), \ + 0, 24)), \ + (unsigned int)(GCCc0w1(G_CCMUX_##b0, G_CCMUX_##d0, \ + G_ACMUX_##Ab0, G_ACMUX_##Ad0) | \ + GCCc1w1(G_CCMUX_##b1, G_ACMUX_##Aa1, \ + G_ACMUX_##Ac1, G_CCMUX_##d1, \ + G_ACMUX_##Ab1, G_ACMUX_##Ad1)) \ +} + +/* + * SetCombineMode macros are NOT redunant. It allow the C preprocessor + * to substitute single parameter which includes commas in the token and + * rescan for higher parameter count macro substitution. + * + * eg. gsDPSetCombineMode(G_CC_MODULATE, G_CC_MODULATE) turns into + * gsDPSetCombineLERP(TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0, + * TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0) + */ + +#define gDPSetCombineMode(pkt, a, b) gDPSetCombineLERP(pkt, a, b) +#define gsDPSetCombineMode(a, b) gsDPSetCombineLERP( a, b) + +#define gDPSetColor(pkt, c, d) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(c, 24, 8); \ + _g->words.w1 = (unsigned int)(d); \ +}) + +#define gsDPSetColor(c, d) \ +{ \ + _SHIFTL(c, 24, 8), \ + (unsigned int)(d) \ +} + +#define DPRGBColor(pkt, cmd, r, g, b, a) \ + gDPSetColor(pkt, cmd, \ + (_SHIFTL(r, 24, 8) | \ + _SHIFTL(g, 16, 8) | \ + _SHIFTL(b, 8, 8) | \ + _SHIFTL(a, 0, 8))) + +#define sDPRGBColor(cmd, r, g, b, a) \ + gsDPSetColor(cmd, \ + (_SHIFTL(r, 24, 8) | \ + _SHIFTL(g, 16, 8) | \ + _SHIFTL(b, 8, 8) | \ + _SHIFTL(a, 0, 8))) + +#define gDPSetEnvColor(pkt, r, g, b, a) \ + DPRGBColor(pkt, G_SETENVCOLOR, r, g, b, a) + +#define gsDPSetEnvColor(r, g, b, a) \ + sDPRGBColor( G_SETENVCOLOR, r, g, b, a) + +#define gDPSetBlendColor(pkt, r, g, b, a) \ + DPRGBColor(pkt, G_SETBLENDCOLOR, r, g, b, a) + +#define gsDPSetBlendColor(r, g, b, a) \ + sDPRGBColor( G_SETBLENDCOLOR, r, g, b, a) + +#define gDPSetFogColor(pkt, r, g, b, a) \ + DPRGBColor(pkt, G_SETFOGCOLOR, r, g, b, a) + +#define gsDPSetFogColor(r, g, b, a) \ + sDPRGBColor( G_SETFOGCOLOR, r, g, b, a) + +#define gDPSetFillColor(pkt, d) \ + gDPSetColor(pkt, G_SETFILLCOLOR, (d)) + +#define gsDPSetFillColor(d) \ + gsDPSetColor( G_SETFILLCOLOR, (d)) + +#define gDPSetPrimDepth(pkt, z, dz) \ + gDPSetColor(pkt, G_SETPRIMDEPTH, \ + _SHIFTL(z, 16, 16) | _SHIFTL(dz, 0, 16)) + +#define gsDPSetPrimDepth(z, dz) \ + gsDPSetColor(G_SETPRIMDEPTH, \ + _SHIFTL(z, 16, 16) | _SHIFTL(dz, 0, 16)) + +#define gDPSetPrimColor(pkt, m, l, r, g, b, a) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | \ + _SHIFTL(m, 8, 8) | \ + _SHIFTL(l, 0, 8)); \ + _g->words.w1 = (_SHIFTL(r, 24, 8) | \ + _SHIFTL(g, 16, 8) | \ + _SHIFTL(b, 8, 8) | \ + _SHIFTL(a, 0, 8)); \ +}) + +#define gsDPSetPrimColor(m, l, r, g, b, a) \ +{ \ + (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | \ + _SHIFTL(m, 8, 8) | \ + _SHIFTL(l, 0, 8)), \ + (_SHIFTL(r, 24, 8) | \ + _SHIFTL(g, 16, 8) | \ + _SHIFTL(b, 8, 8) | \ + _SHIFTL(a, 0, 8)) \ +} + +/* + * Send the color of the specified light to one of the RDP's color registers. + * light is the index of a light in the RSP counting from the end, i.e. 0 is + * the ambient light, 1 is the last directional / point light, etc. The RGB + * color of the selected light is combined with the alpha specified in this + * command as word 1 of a RDP command, and word 0 is specified in this command. + * Specialized versions are provided below for prim color and fog color, + * because these are the two versions needed for cel shading, but any RDP color + * command could be specified this way. + */ +#define gSPLightToRDP(pkt, light, alpha, word0) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_LIGHTTORDP, 24, 8) | \ + _SHIFTL(light * 0x10, 8, 8) | \ + _SHIFTL(alpha, 0, 8)); \ + _g->words.w1 = (word0); \ +}) +#define gsSPLightToRDP(light, alpha, word0) \ +{ \ + (_SHIFTL(G_LIGHTTORDP, 24, 8) | \ + _SHIFTL(light * 0x10, 8, 8) | \ + _SHIFTL(alpha, 0, 8)), \ + (word0) \ +} +#define gSPLightToPrimColor(pkt, light, alpha, m, l) \ + gSPLightToRDP(pkt, light, alpha, \ + (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | _SHIFTL(m, 8, 8) | _SHIFTL(l, 0, 8))) +#define gsSPLightToPrimColor(light, alpha, m, l) \ + gsSPLightToRDP(light, alpha, \ + (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | _SHIFTL(m, 8, 8) | _SHIFTL(l, 0, 8))) +#define gSPLightToFogColor(pkt, light, alpha) \ + gSPLightToRDP(pkt, light, alpha, _SHIFTL(G_SETFOGCOLOR, 24, 8)) +#define gsSPLightToFogColor(light, alpha) \ + gsSPLightToRDP(light, alpha, _SHIFTL(G_SETFOGCOLOR, 24, 8)) + +/* + * gDPSetOtherMode (This is for expert user.) + * + * This command makes all othermode parameters set. + * Do not use this command in the same DL with another g*SPSetOtherMode DLs. + * + * [Usage] + * gDPSetOtherMode(pkt, modeA, modeB) + * + * 'modeA' is described all parameters of GroupA GBI command. + * 'modeB' is also described all parameters of GroupB GBI command. + * + * GroupA: + * gDPPipelineMode, gDPSetCycleType, gSPSetTexturePersp, + * gDPSetTextureDetail, gDPSetTextureLOD, gDPSetTextureLUT, + * gDPSetTextureFilter, gDPSetTextureConvert, gDPSetCombineKey, + * gDPSetColorDither, gDPSetAlphaDither + * + * GroupB: + * gDPSetAlphaCompare, gDPSetDepthSource, gDPSetRenderMode + * + * Use 'OR' operation to get modeA and modeB. + * + * modeA = G_PM_* | G_CYC_* | G_TP_* | G_TD_* | G_TL_* | G_TT_* | G_TF_* + * G_TC_* | G_CK_* | G_CD_* | G_AD_*; + * + * modeB = G_AC_* | G_ZS_* | G_RM_* | G_RM_*2; + */ +#define gDPSetOtherMode(pkt, mode0, mode1) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_RDPSETOTHERMODE, 24, 8) | \ + _SHIFTL(mode0, 0, 24)); \ + _g->words.w1 = (unsigned int)(mode1); \ +}) + +#define gsDPSetOtherMode(mode0, mode1) \ +{ \ + (_SHIFTL(G_RDPSETOTHERMODE, 24, 8) | \ + _SHIFTL(mode0, 0, 24)), \ + (unsigned int)(mode1) \ +} + +/* + * Texturing macros + */ + +#define G_TX_LOADTILE 7 +#define G_TX_RENDERTILE 0 + +/* + * Define this to remove syncs from texture loading multi-command macros. + * + * You should convert your romhack codebase to F3DEX3 without this defined + * first, then once everything is stable, define it and fix any crashes or + * graphical issues that arise. + * + * How the syncs work: load, tile, and pipe sync all delay the RDP by fixed + * numbers of cycles. It is the smallest number for load, a medium number for + * tile, and the largest number for pipe. These syncs do NOT wait until + * something is finished being used; they just stall for a fixed time. + * (DPFullSync is different and DOES wait for writebacks to memory to be done; + * that is not considered in this explanation.) + * + * Syncs always happen after rendering something and before changing some + * settings. In other words: + * - gsSP2Triangles(), gsSPTextureRectangle(), etc. + * - gsDPSomeSync(), + * - gsDPSetSomething() + * You never need the opposite, i.e. you never need a sync after changing + * settings but before rendering. + * + * Which sync you use depends on which settings you are changing. If you are + * doing a texture load (DPLoadBlock or DPLoadTile), you need a load sync (or + * either of the other syncs which wait for even longer). If you are changing + * tile settings, you need a tile sync (or pipe sync which is longer). If you + * are changing CC, othermode, env color, or other things like that, you need + * a pipe sync. + * + * Display lists overall should be structured like: + * + * - ... + * - previous draw tris + * - pipe sync + * - texture load, CC settings, othermode, etc. (no syncs within these) + * - (no sync here) + * - draw tris + * - pipe sync + * - next material setup + * - ... + * + * In SM64, the pipe sync is at the end of each object or sub-object; in OoT + * it is at the start of each display list. This ends up being the same thing + * when the display lists are effectively concatenated: you have a pipe sync + * after each set of rendering things, and before each new set of changing + * settings. + * + * If you are doing multitexture and/or CI texture loads, use a different tile + * for each load, and then you don't need any syncs in the loads. As an extreme + * example with two CI textures: + * - previous pipe sync, either at the start of this DL or the end of the last + * - set tile 7 to load texture 0 CIs (no syncs) + * - load block on tile 7 (no syncs) + * - set tile 5 to load texture 0 palette (no syncs) + * - load block on tile 5 (no syncs) + * - set tile 6 to load texture 1 CIs (no syncs) + * - load block on tile 6 (no syncs) + * - set tile 4 to load texture 1 palette (no syncs) + * - load block on tile 4 (no syncs) + * - set tile 0 for render texture 0 (no syncs) + * - set tile 1 for render texture 0 (no syncs) + * - set othermode, CC, etc. (no syncs) + * - draw tris (no syncs) + * - next pipe sync, either at the end of this DL or the start of the next + * Both fast64 and the multi-command macros in this GBI if + * NO_SYNCS_IN_TEXTURE_LOADS is enabled do this, but if you wrote the DLs by + * hand or they were vanilla DLs not using the multi-command macros, they may + * need to be updated. (Then again, in that case the syncs are also written by + * hand, so these syncs changes do not affect them.) + * + * If you are writing GUI display lists with texture rectangle which look like + * - load tex + * - tex rect + * - load tex + * - tex rect + * you need a load sync before each load tex, and you don't need any other + * syncs. + */ +#ifdef NO_SYNCS_IN_TEXTURE_LOADS +#define gDPLoadSyncInTexLoad(pkt) (void)0 +#define gDPTileSyncInTexLoad(pkt) (void)0 +#define gDPPipeSyncInTexLoad(pkt) (void)0 +#define gsDPLoadSyncInTexLoad +#define gsDPTileSyncInTexLoad +#define gsDPPipeSyncInTexLoad +#define gsDPPipeSyncEndOfTexLoad +#define _G_TEXLOADTILE(rtile) (G_TX_LOADTILE - (rtile)) +#define _G_PALLOADTILE(rtile) (G_TX_LOADTILE - 2 - (rtile)) +#else +#define gDPLoadSyncInTexLoad(pkt) gDPLoadSync(pkt) +#define gDPTileSyncInTexLoad(pkt) gDPTileSync(pkt) +#define gDPPipeSyncInTexLoad(pkt) gDPPipeSync(pkt) +#define gsDPLoadSyncInTexLoad gsDPLoadSync(), +#define gsDPTileSyncInTexLoad gsDPTileSync(), +#define gsDPPipeSyncInTexLoad gsDPPipeSync(), +#define gsDPPipeSyncEndOfTexLoad , gsDPPipeSync() +#define _G_TEXLOADTILE(rtile) G_TX_LOADTILE +#define _G_PALLOADTILE(rtile) G_TX_LOADTILE +#endif + + +#define G_TX_NOMIRROR (0 << 0) +#define G_TX_WRAP (0 << 1) +#define G_TX_MIRROR (1 << 0) +#define G_TX_CLAMP (1 << 1) +#define G_TX_NOMASK 0 +#define G_TX_NOLOD 0 + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +/* + * Dxt is the inverse of the number of 64-bit words in a line of + * the texture being loaded using the load_block command. If + * there are any 1's to the right of the 11th fractional bit, + * dxt should be rounded up. The following macros accomplish + * this. The 4b macros are a special case since 4-bit textures + * are loaded as 8-bit textures. Dxt is fixed point 1.11. RJM + */ +#define G_TX_DXT_FRAC 11 + +/* + * For RCP 2.0, the maximum number of texels that can be loaded + * using a load_block command is 2048. In order to load the total + * 4kB of Tmem, change the texel size when loading to be G_IM_SIZ_16b, + * then change the tile to the proper texel size after the load. + * The g*DPLoadTextureBlock macros already do this, so this change + * will be transparent if you use these macros. If you use + * the g*DPLoadBlock macros directly, you will need to handle this + * tile manipulation yourself. RJM. + */ +#define G_TX_LDBLK_MAX_TXL 2047 + +#define TXL2WORDS(txls, b_txl) \ + MAX(1, ((txls) * (b_txl) / 8)) + +#define CALC_DXT(width, b_txl) \ + (((1 << G_TX_DXT_FRAC) + TXL2WORDS(width, b_txl) - 1) / TXL2WORDS(width, b_txl)) + +#define TXL2WORDS_4b(txls) \ + MAX(1, ((txls) / 16)) + +#define CALC_DXT_4b(width) \ + (((1 << G_TX_DXT_FRAC) + TXL2WORDS_4b(width) - 1) / TXL2WORDS_4b(width)) + +#define gDPLoadTileGeneric(pkt, c, tile, uls, ult, lrs, lrt) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(c, 24, 8) | \ + _SHIFTL(uls, 12, 12) | \ + _SHIFTL(ult, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(lrs, 12, 12) | \ + _SHIFTL(lrt, 0, 12)); \ +}) + +#define gsDPLoadTileGeneric(c, tile, uls, ult, lrs, lrt) \ +{ \ + (_SHIFTL(c, 24, 8) | \ + _SHIFTL(uls, 12, 12) | \ + _SHIFTL(ult, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(lrs, 12, 12) | \ + _SHIFTL(lrt, 0, 12)) \ +} + +#define gDPSetTileSize(pkt, t, uls, ult, lrs, lrt) \ + gDPLoadTileGeneric(pkt, G_SETTILESIZE, t, uls, ult, lrs, lrt) +#define gsDPSetTileSize(t, uls, ult, lrs, lrt) \ + gsDPLoadTileGeneric( G_SETTILESIZE, t, uls, ult, lrs, lrt) +#define gDPLoadTile(pkt, t, uls, ult, lrs, lrt) \ + gDPLoadTileGeneric(pkt, G_LOADTILE, t, uls, ult, lrs, lrt) +#define gsDPLoadTile(t, uls, ult, lrs, lrt) \ + gsDPLoadTileGeneric( G_LOADTILE, t, uls, ult, lrs, lrt) + +#define gDPSetTile(pkt, fmt, siz, line, tmem, tile, palette, cmt, \ + maskt, shiftt, cms, masks, shifts) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETTILE, 24, 8) | \ + _SHIFTL(fmt, 21, 3) | \ + _SHIFTL(siz, 19, 2) | \ + _SHIFTL(line, 9, 9) | \ + _SHIFTL(tmem, 0, 9)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(palette, 20, 4) | \ + _SHIFTL(cmt, 18, 2) | \ + _SHIFTL(maskt, 14, 4) | \ + _SHIFTL(shiftt, 10, 4) | \ + _SHIFTL(cms, 8, 2) | \ + _SHIFTL(masks, 4, 4) | \ + _SHIFTL(shifts, 0, 4)); \ +}) + +#define gsDPSetTile(fmt, siz, line, tmem, tile, palette, cmt, \ + maskt, shiftt, cms, masks, shifts) \ +{ \ + (_SHIFTL(G_SETTILE, 24, 8) | \ + _SHIFTL(fmt, 21, 3) | \ + _SHIFTL(siz, 19, 2) | \ + _SHIFTL(line, 9, 9) | \ + _SHIFTL(tmem, 0, 9)), \ + (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(palette, 20, 4) | \ + _SHIFTL(cmt, 18, 2) | \ + _SHIFTL(maskt, 14, 4) | \ + _SHIFTL(shiftt, 10, 4) | \ + _SHIFTL(cms, 8, 2) | \ + _SHIFTL(masks, 4, 4) | \ + _SHIFTL(shifts, 0, 4)) \ +} + +#define gDPLoadBlock(pkt, tile, uls, ult, lrs, dxt) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_LOADBLOCK, 24, 8) | \ + _SHIFTL(uls, 12, 12) | \ + _SHIFTL(ult, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(MIN(lrs, G_TX_LDBLK_MAX_TXL), 12, 12) | \ + _SHIFTL(dxt, 0, 12)); \ +}) + +#define gsDPLoadBlock(tile, uls, ult, lrs, dxt) \ +{ \ + (_SHIFTL(G_LOADBLOCK, 24, 8) | \ + _SHIFTL(uls, 12, 12) | \ + _SHIFTL(ult, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | \ + _SHIFTL((MIN(lrs, G_TX_LDBLK_MAX_TXL)), 12, 12) | \ + _SHIFTL(dxt, 0, 12)) \ +} + +#define gDPLoadTLUTCmd(pkt, tile, count) \ +_DW({ \ + Gfx *_g = (Gfx *)pkt; \ + \ + _g->words.w0 = _SHIFTL(G_LOADTLUT, 24, 8); \ + _g->words.w1 = (_SHIFTL((tile), 24, 3) | \ + _SHIFTL((count), 14, 10)); \ +}) + +#define gsDPLoadTLUTCmd(tile, count) \ +{ \ + _SHIFTL(G_LOADTLUT, 24, 8), \ + (_SHIFTL((tile), 24, 3) | \ + _SHIFTL((count), 14, 10)) \ +} + +#define gDPLoadTextureBlock(pkt, timg, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) -1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES) + 7) >> 3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +#define gDPLoadTextureBlockYuv(pkt, timg, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) -1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * 1) + 7) >> 3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +/* Load fix rww 27jun95 */ +/* The S at the end means odd lines are already word Swapped */ + +#define gDPLoadTextureBlockS(pkt, timg, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, 0); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES) + 7) >> 3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +/* + * Allow tmem address and render tile to be specified. + * The S at the end means odd lines are already word Swapped + */ +#define gDPLoadMultiBlockS(pkt, timg, tmem, rtile, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, _G_TEXLOADTILE(rtile), \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, _G_TEXLOADTILE(rtile), 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1,0); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES) + 7) >> 3, tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + + +#define gDPLoadTextureBlockYuvS(pkt, timg, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1,0); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * 1) + 7) >> 3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +/* + * allows tmem address to be specified + */ +#define _gDPLoadTextureBlock(pkt, timg, tmem, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES) + 7) >> 3, tmem, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +/* + * allows tmem address and render tile to be specified + */ +#define _gDPLoadTextureBlockTile(pkt, timg, tmem, rtile, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, _G_TEXLOADTILE(rtile), \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, _G_TEXLOADTILE(rtile), 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES) + 7) >> 3, tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +/* + * allows tmem address and render tile to be specified + */ +#define gDPLoadMultiBlock(pkt, timg, tmem, rtile, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, _G_TEXLOADTILE(rtile), \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, _G_TEXLOADTILE(rtile), 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES) + 7) >> 3, tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +#define gsDPLoadTextureBlock(timg, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT) - 1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES) + 7) >> 3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC) + +/* Here is the static form of the pre-swapped texture block loading */ +/* See gDPLoadTextureBlockS() for reference. Basically, just don't + calculate DxT, use 0 */ + +#define gsDPLoadTextureBlockS(timg, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0, cmt, maskt,shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, 0), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES) + 7) >> 3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC) + +/* + * Allow tmem address to be specified + */ +#define _gsDPLoadTextureBlock(timg, tmem, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES) + 7) >> 3), tmem, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * Allow tmem address and render_tile to be specified + */ +#define _gsDPLoadTextureBlockTile(timg, tmem, rtile, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, _G_TEXLOADTILE(rtile), \ + 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(_G_TEXLOADTILE(rtile), 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES) + 7) >> 3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * Allow tmem address and render_tile to be specified, useful when loading + * mutilple tiles at a time. + */ +#define gsDPLoadMultiBlock(timg, tmem, rtile, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, _G_TEXLOADTILE(rtile), \ + 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(_G_TEXLOADTILE(rtile), 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES) + 7) >> 3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC) + +/* + * Allows tmem and render tile to be specified. Useful when loading + * several tiles at a time. + * + * Here is the static form of the pre-swapped texture block loading + * See gDPLoadTextureBlockS() for reference. Basically, just don't + * calculate DxT, use 0 + */ + +#define gsDPLoadMultiBlockS(timg, tmem, rtile, fmt, siz, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, _G_TEXLOADTILE(rtile), \ + 0, cmt, maskt,shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(_G_TEXLOADTILE(rtile), 0, 0, \ + (((width) * (height) + siz##_INCR) >> siz##_SHIFT) - 1, 0), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES) + 7) >> 3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC) + + +#define gDPLoadTextureBlock_4b(pkt, timg, fmt, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + 3) >> 2) - 1, \ + CALC_DXT_4b(width)); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + ((((width) >> 1) + 7) >> 3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +/* Load fix rww 27jun95 */ +/* The S at the end means odd lines are already word Swapped */ + +#define gDPLoadTextureBlock_4bS(pkt, timg, fmt, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + 3) >> 2) - 1, \ + 0); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + ((((width) >> 1) + 7) >> 3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +/* + * 4-bit load block. Useful when loading multiple tiles + */ +#define gDPLoadMultiBlock_4b(pkt, timg, tmem, rtile, fmt, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, _G_TEXLOADTILE(rtile), \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, _G_TEXLOADTILE(rtile), 0, 0, \ + (((width) * (height) + 3) >> 2) - 1, \ + CALC_DXT_4b(width)); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + ((((width) >> 1) + 7) >> 3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +/* + * 4-bit load block. Allows tmem and render tile to be specified. Useful when + * loading multiple tiles. The S means odd lines are already word swapped. + */ +#define gDPLoadMultiBlock_4bS(pkt, timg, tmem, rtile, fmt, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, _G_TEXLOADTILE(rtile), \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, _G_TEXLOADTILE(rtile), 0, 0, \ + (((width) * (height) + 3) >> 2) - 1, \ + 0); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + ((((width) >> 1) + 7) >> 3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + + +#define _gDPLoadTextureBlock_4b(pkt, timg, tmem, fmt, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + 3) >> 2) - 1, \ + CALC_DXT_4b(width)); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + ((((width) >> 1) + 7) >> 3), tmem, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC); \ +}) + +#define gsDPLoadTextureBlock_4b(timg, fmt, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + 3) >> 2) - 1, \ + CALC_DXT_4b(width)), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, G_IM_SIZ_4b, \ + ((((width) >> 1) + 7) >> 3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC) + +#define gsDPLoadTextureBlock_4bS(timg, fmt, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + 3) >> 2) - 1, \ + 0), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, G_IM_SIZ_4b, \ + ((((width) >> 1) + 7) >> 3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC) + +/* + * 4-bit load block. Allows tmem address and render tile to be specified. + * Useful when loading multiple tiles. + */ +#define gsDPLoadMultiBlock_4b(timg, tmem, rtile, fmt, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, _G_TEXLOADTILE(rtile), \ + 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(_G_TEXLOADTILE(rtile), 0, 0, \ + (((width) * (height) + 3) >> 2) - 1, \ + CALC_DXT_4b(width)), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, G_IM_SIZ_4b, \ + ((((width) >> 1) + 7) >> 3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * 4-bit load block. Allows tmem address and render tile to be specified. + * Useful when loading multiple tiles. S means odd lines are already swapped. + */ +#define gsDPLoadMultiBlock_4bS(timg, tmem, rtile, fmt, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, _G_TEXLOADTILE(rtile), \ + 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(_G_TEXLOADTILE(rtile), 0, 0, \ + (((width) * (height) + 3) >> 2) - 1, \ + 0), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, G_IM_SIZ_4b, \ + ((((width) >> 1) + 7) >> 3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * Allows tmem address to be specified + */ +#define _gsDPLoadTextureBlock_4b(timg, tmem, fmt, width, height, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width) * (height) + 3) >> 2) - 1, \ + CALC_DXT_4b(width)), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, G_IM_SIZ_4b, \ + ((((width) >> 1) + 7) >> 3), tmem, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width) - 1) << G_TEXTURE_IMAGE_FRAC, \ + ((height) - 1) << G_TEXTURE_IMAGE_FRAC) + +#define gDPLoadTextureTile(pkt, timg, fmt, siz, width, height, \ + uls, ult, lrs, lrt, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, siz, width, timg); \ + gDPSetTile(pkt, fmt, siz, \ + (((((lrs) - (uls) + 1) * siz##_TILE_BYTES) + 7) >> 3), 0, \ + G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadTile(pkt, G_TX_LOADTILE, \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((((lrs) - (uls) + 1) * siz##_LINE_BYTES) + 7) >> 3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC); \ +}) + +/* + * Load texture tile. Allows tmem address and render tile to be specified. + * Useful for loading multiple tiles. + */ +#define gDPLoadMultiTile(pkt, timg, tmem, rtile, fmt, siz, width, height, \ + uls, ult, lrs, lrt, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, siz, width, timg); \ + gDPSetTile(pkt, fmt, siz, \ + (((((lrs) - (uls) + 1) * siz##_TILE_BYTES) + 7) >> 3), tmem, \ + _G_TEXLOADTILE(rtile), 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadTile(pkt, _G_TEXLOADTILE(rtile), \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((((lrs) - (uls) + 1) * siz##_LINE_BYTES) + 7) >> 3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, rtile, \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC); \ +}) + + +#define gsDPLoadTextureTile(timg, fmt, siz, width, height, \ + uls, ult, lrs, lrt, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, siz, width, timg), \ + gsDPSetTile(fmt, siz, \ + (((((lrs) - (uls) + 1) * siz##_TILE_BYTES) + 7) >> 3), 0, \ + G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadTile(G_TX_LOADTILE, \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, siz, \ + (((((lrs) - (uls) + 1) * siz##_LINE_BYTES) + 7) >> 3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC) + +/* + * Load texture tile. Allows tmem address and render tile to be specified. + * Useful for loading multiple tiles. + */ +#define gsDPLoadMultiTile(timg, tmem, rtile, fmt, siz, width, height, \ + uls, ult, lrs, lrt, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, siz, width, timg), \ + gsDPSetTile(fmt, siz, \ + (((((lrs) - (uls) + 1) * siz##_TILE_BYTES) + 7) >> 3), tmem, \ + _G_TEXLOADTILE(rtile), 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadTile(_G_TEXLOADTILE(rtile), \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, siz, \ + (((((lrs) - (uls) + 1) * siz##_LINE_BYTES) + 7) >> 3), \ + tmem, rtile, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(rtile, \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC) + +#define gDPLoadTextureTile_4b(pkt, timg, fmt, width, height, \ + uls, ult, lrs, lrt, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_8b, ((width) >> 1), timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_8b, \ + (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), 0, \ + G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadTile(pkt, G_TX_LOADTILE, \ + (uls) << (G_TEXTURE_IMAGE_FRAC - 1), \ + (ult) << (G_TEXTURE_IMAGE_FRAC), \ + (lrs) << (G_TEXTURE_IMAGE_FRAC - 1), \ + (lrt) << (G_TEXTURE_IMAGE_FRAC)); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC); \ +}) + +/* + * Load texture tile. Allows tmem address and render tile to be specified. + * Useful for loading multiple tiles. + */ +#define gDPLoadMultiTile_4b(pkt, timg, tmem, rtile, fmt, width, height, \ + uls, ult, lrs, lrt, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +_DW({ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_8b, ((width) >> 1), timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_8b, \ + (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), tmem, \ + _G_TEXLOADTILE(rtile), 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadTile(pkt, _G_TEXLOADTILE(rtile), \ + (uls) << (G_TEXTURE_IMAGE_FRAC - 1), \ + (ult) << (G_TEXTURE_IMAGE_FRAC), \ + (lrs) << (G_TEXTURE_IMAGE_FRAC - 1), \ + (lrt) << (G_TEXTURE_IMAGE_FRAC)); \ + gDPPipeSyncInTexLoad(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, rtile, \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC); \ +}) + +#define gsDPLoadTextureTile_4b(timg, fmt, width, height, \ + uls, ult, lrs, lrt, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + gsDPSetTextureImage(fmt, G_IM_SIZ_8b, ((width) >> 1), timg), \ + gsDPSetTile(fmt, G_IM_SIZ_8b, \ + (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), 0, \ + G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadTile(G_TX_LOADTILE, \ + (uls) << (G_TEXTURE_IMAGE_FRAC - 1), \ + (ult) << (G_TEXTURE_IMAGE_FRAC), \ + (lrs) << (G_TEXTURE_IMAGE_FRAC - 1), \ + (lrt) << (G_TEXTURE_IMAGE_FRAC)), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, G_IM_SIZ_4b, \ + (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC) + +/* + * Load texture tile. Allows tmem address and render tile to be specified. + * Useful for loading multiple tiles. + */ +#define gsDPLoadMultiTile_4b(timg, tmem, rtile, fmt, width, height, \ + uls, ult, lrs, lrt, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_8b, ((width) >> 1), timg), \ + gsDPSetTile(fmt, G_IM_SIZ_8b, \ + (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), tmem, \ + _G_TEXLOADTILE(rtile), 0, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadTile(_G_TEXLOADTILE(rtile), \ + (uls) << (G_TEXTURE_IMAGE_FRAC - 1), \ + (ult) << (G_TEXTURE_IMAGE_FRAC), \ + (lrs) << (G_TEXTURE_IMAGE_FRAC - 1), \ + (lrt) << (G_TEXTURE_IMAGE_FRAC)), \ + gsDPPipeSyncInTexLoad \ + gsDPSetTile(fmt, G_IM_SIZ_4b, \ + (((((lrs) - (uls) + 1) >> 1) + 7) >> 3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPSetTileSize(rtile, \ + (uls) << G_TEXTURE_IMAGE_FRAC, \ + (ult) << G_TEXTURE_IMAGE_FRAC, \ + (lrs) << G_TEXTURE_IMAGE_FRAC, \ + (lrt) << G_TEXTURE_IMAGE_FRAC) + +/* + * Load a 16-entry palette (for 4-bit CI textures) + * Assumes a 16 entry tlut is being loaded, palette # is 0-15 + * With NO_SYNCS_IN_TEXTURE_LOADS: assumes that palette 0 is for multitexture + * texture 0 and palette 1 is for texture 1 (uses load tiles 5 and 4) + */ + +#define gDPLoadTLUT_pal16(pkt, pal, dram) \ +_DW({ \ + gDPSetTextureImage(pkt, G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram); \ + gDPTileSyncInTexLoad(pkt); \ + gDPSetTile(pkt, 0, 0, 0, (256 + (((pal) & 0xF) * 16)), \ + _G_PALLOADTILE((pal) & 1), 0, 0, 0, 0, 0, 0, 0); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadTLUTCmd(pkt, _G_PALLOADTILE((pal) & 1), 15); \ + gDPPipeSyncInTexLoad(pkt); \ +}) + +#define gsDPLoadTLUT_pal16(pal, dram) \ + gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram), \ + gsDPTileSyncInTexLoad \ + gsDPSetTile(0, 0, 0, (256 + (((pal) & 0xF) * 16)), \ + _G_PALLOADTILE((pal) & 1), 0, 0, 0, 0, 0, 0, 0), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadTLUTCmd(_G_PALLOADTILE((pal) & 1), 15) \ + gsDPPipeSyncEndOfTexLoad + +/* + * Load a 256-entry palette (for 8-bit CI textures) + * Assumes a 256 entry tlut is being loaded, palette # is not used + */ + +#define gDPLoadTLUT_pal256(pkt, dram) \ +_DW({ \ + gDPSetTextureImage(pkt, G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram); \ + gDPTileSyncInTexLoad(pkt); \ + gDPSetTile(pkt, 0, 0, 0, 256, \ + _G_PALLOADTILE(0), 0, 0, 0, 0, 0, 0, 0); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadTLUTCmd(pkt, _G_PALLOADTILE(0), 255); \ + gDPPipeSyncInTexLoad(pkt); \ +}) + +#define gsDPLoadTLUT_pal256(dram) \ + gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram), \ + gsDPTileSyncInTexLoad \ + gsDPSetTile(0, 0, 0, 256, \ + _G_PALLOADTILE(0), 0, 0, 0, 0, 0, 0, 0), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadTLUTCmd(_G_PALLOADTILE(0), 255) \ + gsDPPipeSyncEndOfTexLoad + +/* + * Assumes that the starting TMEM address is calculated like in DPLoadTLUT_pal16 + * (which is the only sane way to do it if you are loading two palettes for + * multitexture) + */ +#define _G_PALTMEMTOTILE(tmemaddr) _G_PALLOADTILE(((tmemaddr) >> 4) & 1) + +#define gDPLoadTLUT(pkt, count, tmemaddr, dram) \ +_DW({ \ + gDPSetTextureImage(pkt, G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram); \ + gDPTileSyncInTexLoad(pkt); \ + gDPSetTile(pkt, 0, 0, 0, tmemaddr, \ + _G_PALTMEMTOTILE(tmemaddr), 0, 0, 0, 0, 0, 0, 0); \ + gDPLoadSyncInTexLoad(pkt); \ + gDPLoadTLUTCmd(pkt, _G_PALTMEMTOTILE(tmemaddr), ((count) - 1)); \ + gDPPipeSyncInTexLoad(pkt); \ +}) + +#define gsDPLoadTLUT(count, tmemaddr, dram) \ + gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram), \ + gsDPTileSyncInTexLoad \ + gsDPSetTile(0, 0, 0, tmemaddr, \ + _G_PALTMEMTOTILE(tmemaddr), 0, 0, 0, 0, 0, 0, 0), \ + gsDPLoadSyncInTexLoad \ + gsDPLoadTLUTCmd(_G_PALTMEMTOTILE(tmemaddr), ((count) - 1)) \ + gsDPPipeSyncEndOfTexLoad + + + +#define gDPSetScissor(pkt, mode, ulx, uly, lrx, lry) \ +_DW({ \ + Gfx *_g = (Gfx *)pkt; \ + \ + _g->words.w0 = (_SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((float)(ulx) * 4.0f), 12, 12) | \ + _SHIFTL((int)((float)(uly) * 4.0f), 0, 12)); \ + _g->words.w1 = (_SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)((float)(lrx) * 4.0f), 12, 12) | \ + _SHIFTL((int)((float)(lry) * 4.0f), 0, 12)); \ +}) + + +#define gDPSetScissorFrac(pkt, mode, ulx, uly, lrx, lry) \ +_DW({ \ + Gfx *_g = (Gfx *)pkt; \ + \ + _g->words.w0 = (_SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((ulx)), 12, 12) | \ + _SHIFTL((int)((uly)), 0, 12)); \ + _g->words.w1 = (_SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)((lrx)), 12, 12) | \ + _SHIFTL((int)((lry)), 0, 12)); \ +}) + +#define gsDPSetScissor(mode, ulx, uly, lrx, lry) \ +{ \ + (_SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((float)(ulx) * 4.0f), 12, 12) | \ + _SHIFTL((int)((float)(uly) * 4.0f), 0, 12)), \ + (_SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)((float)(lrx) * 4.0f), 12, 12) | \ + _SHIFTL((int)((float)(lry) * 4.0f), 0, 12)) \ +} + +#define gsDPSetScissorFrac(mode, ulx, uly, lrx, lry) \ +{ \ + (_SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((ulx)), 12, 12) | \ + _SHIFTL((int)((uly)), 0, 12)), \ + (_SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)(lrx), 12, 12) | \ + _SHIFTL((int)(lry), 0, 12)) \ +} + +/* Fraction never used in fill */ +#define gDPFillRectangle(pkt, ulx, uly, lrx, lry) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_FILLRECT, 24, 8) | \ + _SHIFTL((lrx), 14, 10) | \ + _SHIFTL((lry), 2, 10)); \ + _g->words.w1 = (_SHIFTL((ulx), 14, 10) | \ + _SHIFTL((uly), 2, 10)); \ +}) + +#define gsDPFillRectangle(ulx, uly, lrx, lry) \ +{ \ + (_SHIFTL(G_FILLRECT, 24, 8) | \ + _SHIFTL((lrx), 14, 10) | \ + _SHIFTL((lry), 2, 10)), \ + (_SHIFTL((ulx), 14, 10) | \ + _SHIFTL((uly), 2, 10)) \ +} + +/* like gDPFillRectangle but accepts negative arguments */ +#define gDPScisFillRectangle(pkt, ulx, uly, lrx, lry) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_FILLRECT, 24, 8) | \ + _SHIFTL(MAX((lrx), 0), 14, 10) | \ + _SHIFTL(MAX((lry), 0), 2, 10)); \ + _g->words.w1 = (_SHIFTL(MAX((ulx), 0), 14, 10) | \ + _SHIFTL(MAX((uly), 0), 2, 10)); \ +}) + +#define gDPSetConvert(pkt, k0, k1, k2, k3, k4, k5) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETCONVERT, 24, 8) | \ + _SHIFTL(k0, 13, 9) | \ + _SHIFTL(k1, 4, 9) | \ + _SHIFTR(k2, 5, 4)); \ + _g->words.w1 = (_SHIFTL(k2, 27, 5) | \ + _SHIFTL(k3, 18, 9) | \ + _SHIFTL(k4, 9, 9) | \ + _SHIFTL(k5, 0, 9)); \ +}) + +#define gsDPSetConvert(k0, k1, k2, k3, k4, k5) \ +{ \ + (_SHIFTL(G_SETCONVERT, 24, 8) | \ + _SHIFTL(k0, 13, 9) | \ + _SHIFTL(k1, 4, 9) | \ + _SHIFTL(k2, 5, 4)), \ + (_SHIFTL(k2, 27, 5) | \ + _SHIFTL(k3, 18, 9) | \ + _SHIFTL(k4, 9, 9) | \ + _SHIFTL(k5, 0, 9)) \ +} + +#define gDPSetKeyR(pkt, cR, sR, wR) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETKEYR, 24, 8); \ + _g->words.w1 = (_SHIFTL(wR, 16, 12) | \ + _SHIFTL(cR, 8, 8) | \ + _SHIFTL(sR, 0, 8)); \ +}) + +#define gsDPSetKeyR(cR, sR, wR) \ +{ \ + _SHIFTL(G_SETKEYR, 24, 8), \ + (_SHIFTL(wR, 16, 12) | \ + _SHIFTL(cR, 8, 8) | \ + _SHIFTL(sR, 0, 8)) \ +} + +#define gDPSetKeyGB(pkt, cG, sG, wG, cB, sB, wB) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETKEYGB, 24, 8) | \ + _SHIFTL(wG, 12, 12) | \ + _SHIFTL(wB, 0, 12)); \ + _g->words.w1 = (_SHIFTL(cG, 24, 8) | \ + _SHIFTL(sG, 16, 8) | \ + _SHIFTL(cB, 8, 8) | \ + _SHIFTL(sB, 0, 8)); \ +}) + +#define gsDPSetKeyGB(cG, sG, wG, cB, sB, wB) \ +{ \ + (_SHIFTL(G_SETKEYGB, 24, 8) | \ + _SHIFTL(wG, 12, 12) | \ + _SHIFTL(wB, 0, 12)), \ + (_SHIFTL(cG, 24, 8) | \ + _SHIFTL(sG, 16, 8) | \ + _SHIFTL(cB, 8, 8) | \ + _SHIFTL(sB, 0, 8)) \ +} + +#define gDPNoParam(pkt, cmd) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(cmd, 24, 8); \ + _g->words.w1 = 0; \ +}) + +#define gsDPNoParam(cmd) \ +{ \ + _SHIFTL(cmd, 24, 8), \ + 0 \ +} + +#define gDPParam(pkt, cmd, param) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(cmd, 24, 8); \ + _g->words.w1 = (param); \ +}) + +#define gsDPParam(cmd, param) \ +{ \ + _SHIFTL(cmd, 24, 8), \ + (param) \ +} + +/* Notice that textured rectangles are 128-bit commands, therefore + * gsDPTextureRectangle() should not be used in display lists + * under normal circumstances (use gsSPTextureRectangle()). + * That is also why there is no gDPTextureRectangle() macros. + */ +#define gsDPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + (_SHIFTL(G_TEXRECT, 24, 8) | \ + _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)), \ +}, \ +{ \ + (_SHIFTL(s, 16, 16) | \ + _SHIFTL(t, 0, 16)), \ + (_SHIFTL(dsdx, 16, 16) | \ + _SHIFTL(dtdy, 0, 16)) \ +} + +#define gDPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + if (pkt); \ + _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | \ + _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + _g ++; \ + _g->words.w0 = (_SHIFTL(s, 16, 16) | \ + _SHIFTL(t, 0, 16)); \ + _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | \ + _SHIFTL(dtdy, 0, 16)); \ +}) + +#define gsDPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + (_SHIFTL(G_TEXRECTFLIP, 24, 8) | \ + _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)), \ +}, \ +{ \ + (_SHIFTL(s, 16, 16) | \ + _SHIFTL(t, 0, 16)), \ + (_SHIFTL(dsdx, 16, 16) | \ + _SHIFTL(dtdy, 0, 16)) \ +} + +#define gDPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + if (pkt); \ + _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | \ + _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + _g ++; \ + _g->words.w0 = (_SHIFTL(s, 16, 16) | \ + _SHIFTL(t, 0, 16)); \ + _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | \ + _SHIFTL(dtdy, 0, 16)); \ +}) + +#define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ + (_SHIFTL(G_TEXRECT, 24, 8) | \ + _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)), \ + gsImmp1(G_RDPHALF_1, \ + (_SHIFTL(s, 16, 16) | \ + _SHIFTL(t, 0, 16))), \ + gsImmp1(G_RDPHALF_2, \ + (_SHIFTL(dsdx, 16, 16) | \ + _SHIFTL(dtdy, 0, 16))) + +#define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | \ + _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + gImmp1(pkt, G_RDPHALF_1, \ + (_SHIFTL(s, 16, 16) | \ + _SHIFTL(t, 0, 16))); \ + gImmp1(pkt, G_RDPHALF_2, \ + (_SHIFTL(dsdx, 16, 16) | \ + _SHIFTL(dtdy, 0, 16))); \ +}) + +/* like gSPTextureRectangle but accepts negative position arguments */ +#define gSPScisTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | \ + _SHIFTL(MAX((s16)(xh),0), 12, 12) | \ + _SHIFTL(MAX((s16)(yh),0), 0, 12)); \ + _g->words.w1 = (_SHIFTL((tile), 24, 3) | \ + _SHIFTL(MAX((s16)(xl),0), 12, 12) | \ + _SHIFTL(MAX((s16)(yl),0), 0, 12)); \ + gImmp1(pkt, G_RDPHALF_1, \ + (_SHIFTL(((s) - \ + (((s16)(xl) < 0) ? \ + (((s16)(dsdx) < 0) ? \ + (MAX((((s16)(xl) * (s16)(dsdx)) >> 7), 0)) : \ + (MIN((((s16)(xl) * (s16)(dsdx)) >> 7), 0))) : 0)), 16, 16) | \ + _SHIFTL(((t) - \ + (( (yl) < 0) ? \ + (((s16)(dtdy) < 0) ? \ + (MAX((((s16)(yl) * (s16)(dtdy)) >> 7), 0)) : \ + (MIN((((s16)(yl) * (s16)(dtdy)) >> 7), 0))) : 0)), 0, 16))); \ + gImmp1(pkt, G_RDPHALF_2, \ + (_SHIFTL((dsdx), 16, 16) | \ + _SHIFTL((dtdy), 0, 16))); \ +}) + +#define gsSPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ + (_SHIFTL(G_TEXRECTFLIP, 24, 8) | \ + _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)), \ + gsImmp1(G_RDPHALF_1, \ + (_SHIFTL(s, 16, 16) | \ + _SHIFTL(t, 0, 16))), \ + gsImmp1(G_RDPHALF_2, \ + (_SHIFTL(dsdx, 16, 16) | \ + _SHIFTL(dtdy, 0, 16))) + +#define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | \ + _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | \ + _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + gImmp1(pkt, G_RDPHALF_1, \ + (_SHIFTL(s, 16, 16) | \ + _SHIFTL(t, 0, 16))); \ + gImmp1(pkt, G_RDPHALF_2, \ + (_SHIFTL(dsdx, 16, 16) | \ + _SHIFTL(dtdy, 0, 16))); \ +}) + +#define gsDPWord(wordhi, wordlo) \ + gsImmp1(G_RDPHALF_1, (unsigned int)(wordhi)), \ + gsImmp1(G_RDPHALF_2, (unsigned int)(wordlo)) + +#define gDPWord(pkt, wordhi, wordlo) \ +_DW({ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + gImmp1(pkt, G_RDPHALF_1, (unsigned int)(wordhi)); \ + gImmp1(pkt, G_RDPHALF_2, (unsigned int)(wordlo)); \ +}) + +#define gDPFullSync(pkt) gDPNoParam(pkt, G_RDPFULLSYNC) +#define gsDPFullSync() gsDPNoParam( G_RDPFULLSYNC) +#define gDPTileSync(pkt) gDPNoParam(pkt, G_RDPTILESYNC) +#define gsDPTileSync() gsDPNoParam( G_RDPTILESYNC) +#define gDPPipeSync(pkt) gDPNoParam(pkt, G_RDPPIPESYNC) +#define gsDPPipeSync() gsDPNoParam( G_RDPPIPESYNC) +#define gDPLoadSync(pkt) gDPNoParam(pkt, G_RDPLOADSYNC) +#define gsDPLoadSync() gsDPNoParam( G_RDPLOADSYNC) +#define gDPNoOp(pkt) gDPNoParam(pkt, G_NOOP) +#define gsDPNoOp() gsDPNoParam( G_NOOP) +#define gDPNoOpTag(pkt, tag) gDPParam(pkt, G_NOOP, tag) +#define gsDPNoOpTag(tag) gsDPParam( G_NOOP, tag) + +#define gDPNoOpHere(pkt, file, line) gDma1p(pkt, G_NOOP, file, line, 1) +#define gDPNoOpString(pkt, data, n) gDma1p(pkt, G_NOOP, data, n, 2) +#define gDPNoOpWord(pkt, data, n) gDma1p(pkt, G_NOOP, data, n, 3) +#define gDPNoOpFloat(pkt, data, n) gDma1p(pkt, G_NOOP, data, n, 4) +#define gDPNoOpQuiet(pkt) gDma1p(pkt, G_NOOP, 0, 0, 5) +#define gDPNoOpVerbose(pkt, n) gDma1p(pkt, G_NOOP, 0, n, 5) +#define gDPNoOpCallBack(pkt, callback, arg) gDma1p(pkt, G_NOOP, callback, arg, 6) +#define gDPNoOpOpenDisp(pkt, file, line) gDma1p(pkt, G_NOOP, file, line, 7) +#define gDPNoOpCloseDisp(pkt, file, line) gDma1p(pkt, G_NOOP, file, line, 8) +#define gDPNoOpTag3(pkt, type, data, n) gDma1p(pkt, G_NOOP, data, n, type) + +#endif /* F3DEX3_H */ diff --git a/include/n64/PR/gbi_std.h b/include/n64/PR/gbi_std.h new file mode 100644 index 0000000000..f1627d220e --- /dev/null +++ b/include/n64/PR/gbi_std.h @@ -0,0 +1,4873 @@ +/************************************************************************** + * * + * Copyright (C) 1994, Silicon Graphics, Inc. * + * * + * These coded instructions, statements, and computer programs contain * + * unpublished proprietary information of Silicon Graphics, Inc., and * + * are protected by Federal copyright law. They may not be disclosed * + * to third parties or copied or duplicated in any form, in whole or * + * in part, without the prior written consent of Silicon Graphics, Inc. * + * * + **************************************************************************/ +/************************************************************************** + * + * $Revision: 1.141 $ + * $Date: 1999/09/03 03:43:08 $ + * $Source: /exdisk2/cvs/N64OS/Master/cvsmdev2/PR/include/gbi.h,v $ + * + **************************************************************************/ + +#ifndef _GBI_H_ +#define _GBI_H_ + +#include +#include + +/* + * Converts texel coordinates to S and T values + */ +// Bilerp/Average filter +#define TC_B_OFF -0.5 +#define TC_B(p) (((p) + TC_B_OFF) * 32) +// #define TC_B(p) ((((p) > TC_B_OFF) ? ((p) - TC_B_OFF) : (p)) * 32) +#define ST_B(s, t) {TC_B(s), TC_B(t)} + +// Point filter +#define TX_P_OFF 0.25 +#define TC_P(p) (((p) + TX_P_OFF) * 32) +#define ST_P(s, t) {TC_P(s), TC_P(t)} + +/* + * To use the F3DEX ucodes, define F3DEX_GBI before include this file. + * + * #define F3DEX_GBI + * #include + * + * or + * + * cc -c -DF3DEX_GBI -I.... foo.c + * + */ + +/************************************************************************** + * + * Graphics Binary Interface + * + **************************************************************************/ + +/* + * Graphics Commands, 'xxx' parts may be generated from ucode + * + * The command format is + * + * |00xxxxxx| = DMA 0,..,127 + * |10xxxxxx| = Immediate Mode -65,..,-128 + * |11xxxxxx| = RDP cmds -1,..,-64 + * + * Note: in order for the RSP microcode to process RDP commands opaquely, + * we need to further identify those RDP commands that need DRAM address + * "fixup". To do this, we have the dummy command G_RDP_ADDR_FIXUP, and + * all |RDP commands| less than this are commands with embedded DRAM + * addresses. Further, the format of these commands should be similar so + * only one fixup routine is needed. + * + * Further explanation: + * The names of the commands are somewhat misleading. Here is clarification: + * + * - a 'DMA' type command has a pointer to additional data and + * causes a DMA transfer to bring that into DMEM. + * + * - an 'Immediate' type command isn't really 'immediate', in the + * traditional sense. This just means that the entire command fits + * in the 64-bit word, and the ucode can execute it 'immediately' + * without additional memory transfers. + * + * - an 'RDP' command is identified as such because the RDP + * commands can be passed-thru the RSP and sent to the RDP + * directly. One further confusing thing, is that some 'DP' + * macros below actually generate immediate commands, not + * not direct DP commands. + * + * IMPLEMENTATION NOTE: + * There is another group of RDP commands that includes the triangle commands + * generated by the RSP code. These are the raw commands the rasterizer + * hardware chews on, with slope info, etc. They will follow the RDP + * ordering... + * + * IMPLEMENTATION NOTE: + * The RDP hardware has some of these bit patterns wired up. If the hardware + * changes, we must adjust this table, likewise we can't change/add things + * once the hardware is frozen. (actually, the RDP hardware only looks at + * the lower 6 bits of the command byte) + * + */ + +#ifdef F3DEX_GBI_2E +# ifndef F3DEX_GBI_2 +# define F3DEX_GBI_2 +# endif +# define GBI_FLOATS +#endif + +#ifdef F3DEX_GBI_2 +# ifndef F3DEX_GBI +# define F3DEX_GBI +# endif +#define G_NOOP 0x00 +#define G_RDPHALF_2 0xf1 +#define G_SETOTHERMODE_H 0xe3 +#define G_SETOTHERMODE_L 0xe2 +#define G_RDPHALF_1 0xe1 +#define G_SPNOOP 0xe0 +#define G_ENDDL 0xdf +#define G_DL 0xde +#define G_LOAD_UCODE 0xdd +#define G_MOVEMEM 0xdc +#define G_MOVEWORD 0xdb +#define G_MTX 0xda +#define G_GEOMETRYMODE 0xd9 +#define G_POPMTX 0xd8 +#define G_TEXTURE 0xd7 +#define G_DMA_IO 0xd6 +#define G_SPECIAL_1 0xd5 +#define G_SPECIAL_2 0xd4 +#define G_SPECIAL_3 0xd3 + +#define G_VTX 0x01 +#define G_MODIFYVTX 0x02 +#define G_CULLDL 0x03 +#define G_BRANCH_Z 0x04 +#define G_TRI1 0x05 +#define G_TRI2 0x06 +#define G_QUAD 0x07 +#define G_LINE3D 0x08 +#else /* F3DEX_GBI_2 */ + +/* DMA commands: */ +#define G_SPNOOP 0 /* handle 0 gracefully */ +#define G_MTX 1 +#define G_RESERVED0 2 /* not implemeted */ +#define G_MOVEMEM 3 /* move a block of memory (up to 4 words) to dmem */ +#define G_VTX 4 +#define G_RESERVED1 5 /* not implemeted */ +#define G_DL 6 +#define G_RESERVED2 7 /* not implemeted */ +#define G_RESERVED3 8 /* not implemeted */ +#define G_SPRITE2D_BASE 9 /* sprite command */ + +/* IMMEDIATE commands: */ +#define G_IMMFIRST -65 +#define G_TRI1 (G_IMMFIRST-0) +#define G_CULLDL (G_IMMFIRST-1) +#define G_POPMTX (G_IMMFIRST-2) +#define G_MOVEWORD (G_IMMFIRST-3) +#define G_TEXTURE (G_IMMFIRST-4) +#define G_SETOTHERMODE_H (G_IMMFIRST-5) +#define G_SETOTHERMODE_L (G_IMMFIRST-6) +#define G_ENDDL (G_IMMFIRST-7) +#define G_SETGEOMETRYMODE (G_IMMFIRST-8) +#define G_CLEARGEOMETRYMODE (G_IMMFIRST-9) +#define G_LINE3D (G_IMMFIRST-10) +#define G_RDPHALF_1 (G_IMMFIRST-11) +#define G_RDPHALF_2 (G_IMMFIRST-12) +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +# define G_MODIFYVTX (G_IMMFIRST-13) +# define G_TRI2 (G_IMMFIRST-14) +# define G_BRANCH_Z (G_IMMFIRST-15) +# define G_LOAD_UCODE (G_IMMFIRST-16) +#else +# define G_RDPHALF_CONT (G_IMMFIRST-13) +#endif + +/* We are overloading 2 of the immediate commands + to keep the byte alignment of dmem the same */ + +#define G_SPRITE2D_SCALEFLIP (G_IMMFIRST-1) +#define G_SPRITE2D_DRAW (G_IMMFIRST-2) + +/* RDP commands: */ +#define G_NOOP 0xc0 /* 0 */ + +#endif /* F3DEX_GBI_2 */ + +/* RDP commands: */ +#define G_SETCIMG 0xff /* -1 */ +#define G_SETZIMG 0xfe /* -2 */ +#define G_SETTIMG 0xfd /* -3 */ +#define G_SETCOMBINE 0xfc /* -4 */ +#define G_SETENVCOLOR 0xfb /* -5 */ +#define G_SETPRIMCOLOR 0xfa /* -6 */ +#define G_SETBLENDCOLOR 0xf9 /* -7 */ +#define G_SETFOGCOLOR 0xf8 /* -8 */ +#define G_SETFILLCOLOR 0xf7 /* -9 */ +#define G_FILLRECT 0xf6 /* -10 */ +#define G_SETTILE 0xf5 /* -11 */ +#define G_LOADTILE 0xf4 /* -12 */ +#define G_LOADBLOCK 0xf3 /* -13 */ +#define G_SETTILESIZE 0xf2 /* -14 */ +#define G_LOADTLUT 0xf0 /* -16 */ +#define G_RDPSETOTHERMODE 0xef /* -17 */ +#define G_SETPRIMDEPTH 0xee /* -18 */ +#define G_SETSCISSOR 0xed /* -19 */ +#define G_SETCONVERT 0xec /* -20 */ +#define G_SETKEYR 0xeb /* -21 */ +#define G_SETKEYGB 0xea /* -22 */ +#define G_RDPFULLSYNC 0xe9 /* -23 */ +#define G_RDPTILESYNC 0xe8 /* -24 */ +#define G_RDPPIPESYNC 0xe7 /* -25 */ +#define G_RDPLOADSYNC 0xe6 /* -26 */ +#define G_TEXRECTFLIP 0xe5 /* -27 */ +#define G_TEXRECT 0xe4 /* -28 */ + + +/* + * The following commands are the "generated" RDP commands; the user + * never sees them, the RSP microcode generates them. + * + * The layout of the bits is magical, to save work in the ucode. + * These id's are -56, -52, -54, -50, -55, -51, -53, -49, ... + * edge, shade, texture, zbuff bits: estz + */ +#define G_TRI_FILL 0xc8 /* fill triangle: 11001000 */ +#define G_TRI_SHADE 0xcc /* shade triangle: 11001100 */ +#define G_TRI_TXTR 0xca /* texture triangle: 11001010 */ +#define G_TRI_SHADE_TXTR 0xce /* shade, texture triangle: 11001110 */ +#define G_TRI_FILL_ZBUFF 0xc9 /* fill, zbuff triangle: 11001001 */ +#define G_TRI_SHADE_ZBUFF 0xcd /* shade, zbuff triangle: 11001101 */ +#define G_TRI_TXTR_ZBUFF 0xcb /* texture, zbuff triangle: 11001011 */ +#define G_TRI_SHADE_TXTR_ZBUFF 0xcf /* shade, txtr, zbuff trngl: 11001111 */ + +/* + * A TRI_FILL triangle is just the edges. You need to set the DP + * to use primcolor, in order to see anything. (it is NOT a triangle + * that gets rendered in 'fill mode'. Triangles can't be rendered + * in 'fill mode') + * + * A TRI_SHADE is a gouraud triangle that has colors interpolated. + * Flat-shaded triangles (from the software) are still gouraud shaded, + * it's just the colors are all the same and the deltas are 0. + * + * Other triangle types, and combinations are more obvious. + */ + +/* masks to build RDP triangle commands: */ +#define G_RDP_TRI_FILL_MASK 0x08 +#define G_RDP_TRI_SHADE_MASK 0x04 +#define G_RDP_TRI_TXTR_MASK 0x02 +#define G_RDP_TRI_ZBUFF_MASK 0x01 + +/* + * HACK: + * This is a dreadful hack. For version 1.0 hardware, there are still + * some 'bowtie' hangs. This parameter can be increased to avoid + * the hangs. Every increase of 4 chops one scanline off of every + * triangle. Values of 4,8,12 should be sufficient to avoid any + * bowtie hang. + * + * Change this value, then recompile ALL of your program (including static + * display lists!) + * + * THIS WILL BE REMOVED FOR HARDWARE VERSION 2.0! + */ +#define BOWTIE_VAL 0 + + +/* gets added to RDP command, in order to test for addres fixup: */ +#define G_RDP_ADDR_FIXUP 3 /* |RDP cmds| <= this, do addr fixup */ +#ifdef _LANGUAGE_ASSEMBLY +#define G_RDP_TEXRECT_CHECK ((-1*G_TEXRECTFLIP)& 0xff) +#endif + +/* macros for command parsing: */ +#define GDMACMD(x) (x) +#define GIMMCMD(x) (G_IMMFIRST-(x)) +#define GRDPCMD(x) (0xff-(x)) + +#define G_DMACMDSIZ 128 +#define G_IMMCMDSIZ 64 +#define G_RDPCMDSIZ 64 + +/* + * Coordinate shift values, number of bits of fraction + */ +#define G_TEXTURE_IMAGE_FRAC 2 +#define G_TEXTURE_SCALE_FRAC 16 +#define G_SCALE_FRAC 8 +#define G_ROTATE_FRAC 16 + +/* + * Parameters to graphics commands + */ + +/* + * Data packing macros + */ + +/* + * Maximum z-buffer value, used to initialize the z-buffer. + * Note : this number is NOT the viewport z-scale constant. + * See the comment next to G_MAXZ for more info. + */ +#define G_MAXFBZ 0x3fff /* 3b exp, 11b mantissa */ + +#define GPACK_RGBA5551(r, g, b, a) ((((r)<<8) & 0xf800) | \ + (((g)<<3) & 0x7c0) | \ + (((b)>>2) & 0x3e) | ((a) & 0x1)) +#define GPACK_ZDZ(z, dz) ((z) << 2 | (dz)) + +/* + * G_MTX: parameter flags + */ +#ifdef F3DEX_GBI_2 +# define G_MTX_MODELVIEW 0x00 /* matrix types */ +# define G_MTX_PROJECTION 0x04 +# define G_MTX_MUL 0x00 /* concat or load */ +# define G_MTX_LOAD 0x02 +# define G_MTX_NOPUSH 0x00 /* push or not */ +# define G_MTX_PUSH 0x01 +#else /* F3DEX_GBI_2 */ +# define G_MTX_MODELVIEW 0x00 /* matrix types */ +# define G_MTX_PROJECTION 0x01 +# define G_MTX_MUL 0x00 /* concat or load */ +# define G_MTX_LOAD 0x02 +# define G_MTX_NOPUSH 0x00 /* push or not */ +# define G_MTX_PUSH 0x04 +#endif /* F3DEX_GBI_2 */ + +/* + * flags for G_SETGEOMETRYMODE + * (this rendering state is maintained in RSP) + * + * DO NOT USE THE LOW 8 BITS OF GEOMETRYMODE: + * The weird bit-ordering is for the micro-code: the lower byte + * can be OR'd in with G_TRI_SHADE (11001100) to construct + * the triangle command directly. Don't break it... + * + * DO NOT USE THE HIGH 8 BITS OF GEOMETRYMODE: + * The high byte is OR'd with 0x703 to form the clip code mask. + * If it is set to 0x04, this will cause near clipping to occur. + * If it is zero, near clipping will not occur. + * + * Further explanation: + * G_SHADE is necessary in order to see the color that you passed + * down with the vertex. If G_SHADE isn't set, you need to set the DP + * appropriately and use primcolor to see anything. + * + * G_SHADING_SMOOTH enabled means use all 3 colors of the triangle. + * If it is not set, then do 'flat shading', where only one vertex color + * is used (and all 3 vertices are set to that same color by the ucode) + * See the man page for gSP1Triangle(). + * + */ +#define G_ZBUFFER 0x00000001 +#define G_SHADE 0x00000004 /* enable Gouraud interp */ +/* rest of low byte reserved for setup ucode */ +#ifdef F3DEX_GBI_2 +# define G_TEXTURE_ENABLE 0x00000000 /* Ignored */ +# define G_SHADING_SMOOTH 0x00200000 /* flat or smooth shaded */ +# define G_CULL_FRONT 0x00000200 +# define G_CULL_BACK 0x00000400 +# define G_CULL_BOTH 0x00000600 /* To make code cleaner */ +#else +# define G_TEXTURE_ENABLE 0x00000002 /* Microcode use only */ +# define G_SHADING_SMOOTH 0x00000200 /* flat or smooth shaded */ +# define G_CULL_FRONT 0x00001000 +# define G_CULL_BACK 0x00002000 +# define G_CULL_BOTH 0x00003000 /* To make code cleaner */ +#endif +#define G_FOG 0x00010000 +#define G_LIGHTING 0x00020000 +#define G_TEXTURE_GEN 0x00040000 +#define G_TEXTURE_GEN_LINEAR 0x00080000 +#define G_LOD 0x00100000 /* NOT IMPLEMENTED */ +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +# define G_CLIPPING 0x00800000 +#else +# define G_CLIPPING 0x00000000 +#endif + +#ifdef _LANGUAGE_ASSEMBLY +#define G_FOG_H (G_FOG/0x10000) +#define G_LIGHTING_H (G_LIGHTING/0x10000) +#define G_TEXTURE_GEN_H (G_TEXTURE_GEN/0x10000) +#define G_TEXTURE_GEN_LINEAR_H (G_TEXTURE_GEN_LINEAR/0x10000) +#define G_LOD_H (G_LOD/0x10000) /* NOT IMPLEMENTED */ +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +# define G_CLIPPING_H (G_CLIPPING/0x10000) +#endif +#endif + +/* Need these defined for Sprite Microcode */ +#ifdef _LANGUAGE_ASSEMBLY +#define G_TX_LOADTILE 7 +#define G_TX_RENDERTILE 0 + +#define G_TX_NOMIRROR 0 +#define G_TX_WRAP 0 +#define G_TX_MIRROR 0x1 +#define G_TX_CLAMP 0x2 +#define G_TX_NOMASK 0 +#define G_TX_NOLOD 0 +#endif + +/* + * G_SETIMG fmt: set image formats + */ +#define G_IM_FMT_RGBA 0 +#define G_IM_FMT_YUV 1 +#define G_IM_FMT_CI 2 +#define G_IM_FMT_IA 3 +#define G_IM_FMT_I 4 + +/* + * G_SETIMG siz: set image pixel size + */ +#define G_IM_SIZ_4b 0 +#define G_IM_SIZ_8b 1 +#define G_IM_SIZ_16b 2 +#define G_IM_SIZ_32b 3 +#define G_IM_SIZ_DD 5 + +#define G_IM_SIZ_4b_BYTES 0 +#define G_IM_SIZ_4b_TILE_BYTES G_IM_SIZ_4b_BYTES +#define G_IM_SIZ_4b_LINE_BYTES G_IM_SIZ_4b_BYTES + +#define G_IM_SIZ_8b_BYTES 1 +#define G_IM_SIZ_8b_TILE_BYTES G_IM_SIZ_8b_BYTES +#define G_IM_SIZ_8b_LINE_BYTES G_IM_SIZ_8b_BYTES + +#define G_IM_SIZ_16b_BYTES 2 +#define G_IM_SIZ_16b_TILE_BYTES G_IM_SIZ_16b_BYTES +#define G_IM_SIZ_16b_LINE_BYTES G_IM_SIZ_16b_BYTES + +#define G_IM_SIZ_32b_BYTES 4 +#define G_IM_SIZ_32b_TILE_BYTES 2 +#define G_IM_SIZ_32b_LINE_BYTES 2 + +#define G_IM_SIZ_4b_LOAD_BLOCK G_IM_SIZ_16b +#define G_IM_SIZ_8b_LOAD_BLOCK G_IM_SIZ_16b +#define G_IM_SIZ_16b_LOAD_BLOCK G_IM_SIZ_16b +#define G_IM_SIZ_32b_LOAD_BLOCK G_IM_SIZ_32b + +#define G_IM_SIZ_4b_SHIFT 2 +#define G_IM_SIZ_8b_SHIFT 1 +#define G_IM_SIZ_16b_SHIFT 0 +#define G_IM_SIZ_32b_SHIFT 0 + +#define G_IM_SIZ_4b_INCR 3 +#define G_IM_SIZ_8b_INCR 1 +#define G_IM_SIZ_16b_INCR 0 +#define G_IM_SIZ_32b_INCR 0 + +/* + * G_SETCOMBINE: color combine modes + */ +/* Color combiner constants: */ +#define G_CCMUX_COMBINED 0 +#define G_CCMUX_TEXEL0 1 +#define G_CCMUX_TEXEL1 2 +#define G_CCMUX_PRIMITIVE 3 +#define G_CCMUX_SHADE 4 +#define G_CCMUX_ENVIRONMENT 5 +#define G_CCMUX_CENTER 6 +#define G_CCMUX_SCALE 6 +#define G_CCMUX_COMBINED_ALPHA 7 +#define G_CCMUX_TEXEL0_ALPHA 8 +#define G_CCMUX_TEXEL1_ALPHA 9 +#define G_CCMUX_PRIMITIVE_ALPHA 10 +#define G_CCMUX_SHADE_ALPHA 11 +#define G_CCMUX_ENV_ALPHA 12 +#define G_CCMUX_LOD_FRACTION 13 +#define G_CCMUX_PRIM_LOD_FRAC 14 +#define G_CCMUX_NOISE 7 +#define G_CCMUX_K4 7 +#define G_CCMUX_K5 15 +#define G_CCMUX_1 6 +#define G_CCMUX_0 31 + +/* Alpha combiner constants: */ +#define G_ACMUX_COMBINED 0 +#define G_ACMUX_TEXEL0 1 +#define G_ACMUX_TEXEL1 2 +#define G_ACMUX_PRIMITIVE 3 +#define G_ACMUX_SHADE 4 +#define G_ACMUX_ENVIRONMENT 5 +#define G_ACMUX_LOD_FRACTION 0 +#define G_ACMUX_PRIM_LOD_FRAC 6 +#define G_ACMUX_1 6 +#define G_ACMUX_0 7 + +/* typical CC cycle 1 modes */ +#define G_CC_PRIMITIVE 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE +#define G_CC_SHADE 0, 0, 0, SHADE, 0, 0, 0, SHADE + +#define G_CC_MODULATEI TEXEL0, 0, SHADE, 0, 0, 0, 0, SHADE +#define G_CC_MODULATEIDECALA TEXEL0, 0, SHADE, 0, 0, 0, 0, TEXEL0 +#define G_CC_MODULATEIFADE TEXEL0, 0, SHADE, 0, 0, 0, 0, ENVIRONMENT + +#define G_CC_MODULATERGB G_CC_MODULATEI +#define G_CC_MODULATERGBDECALA G_CC_MODULATEIDECALA +#define G_CC_MODULATERGBFADE G_CC_MODULATEIFADE + +#define G_CC_MODULATEIA TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0 +#define G_CC_MODULATEIFADEA TEXEL0, 0, SHADE, 0, TEXEL0, 0, ENVIRONMENT, 0 + +#define G_CC_MODULATEFADE TEXEL0, 0, SHADE, 0, ENVIRONMENT, 0, TEXEL0, 0 + +#define G_CC_MODULATERGBA G_CC_MODULATEIA +#define G_CC_MODULATERGBFADEA G_CC_MODULATEIFADEA + +#define G_CC_MODULATEI_PRIM TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE +#define G_CC_MODULATEIA_PRIM TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0 +#define G_CC_MODULATEIDECALA_PRIM TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, TEXEL0 + +#define G_CC_MODULATERGB_PRIM G_CC_MODULATEI_PRIM +#define G_CC_MODULATERGBA_PRIM G_CC_MODULATEIA_PRIM +#define G_CC_MODULATERGBDECALA_PRIM G_CC_MODULATEIDECALA_PRIM + +#define G_CC_FADE SHADE, 0, ENVIRONMENT, 0, SHADE, 0, ENVIRONMENT, 0 +#define G_CC_FADEA TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0 + +#define G_CC_DECALRGB 0, 0, 0, TEXEL0, 0, 0, 0, SHADE +#define G_CC_DECALRGBA 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0 +#define G_CC_DECALFADE 0, 0, 0, TEXEL0, 0, 0, 0, ENVIRONMENT + +#define G_CC_DECALFADEA 0, 0, 0, TEXEL0, TEXEL0, 0, ENVIRONMENT, 0 + +#define G_CC_BLENDI ENVIRONMENT, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_BLENDIA ENVIRONMENT, SHADE, TEXEL0, SHADE, TEXEL0, 0, SHADE, 0 +#define G_CC_BLENDIDECALA ENVIRONMENT, SHADE, TEXEL0, SHADE, 0, 0, 0, TEXEL0 + +#define G_CC_BLENDRGBA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, SHADE +#define G_CC_BLENDRGBDECALA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_BLENDRGBFADEA TEXEL0, SHADE, TEXEL0_ALPHA, SHADE, 0, 0, 0, ENVIRONMENT + +#define G_CC_ADDRGB TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_ADDRGBDECALA TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_ADDRGBFADE TEXEL0, 0, TEXEL0, SHADE, 0, 0, 0, ENVIRONMENT + +#define G_CC_REFLECTRGB ENVIRONMENT, 0, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_REFLECTRGBDECALA ENVIRONMENT, 0, TEXEL0, SHADE, 0, 0, 0, TEXEL0 + +#define G_CC_HILITERGB PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE +#define G_CC_HILITERGBA PRIMITIVE, SHADE, TEXEL0, SHADE, PRIMITIVE, SHADE, TEXEL0, SHADE +#define G_CC_HILITERGBDECALA PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, TEXEL0 + +#define G_CC_SHADEDECALA 0, 0, 0, SHADE, 0, 0, 0, TEXEL0 +#define G_CC_SHADEFADEA 0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT + +#define G_CC_BLENDPE PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, SHADE, 0 +#define G_CC_BLENDPEDECALA PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, TEXEL0 + +/* oddball modes */ +#define _G_CC_BLENDPE ENVIRONMENT, PRIMITIVE, TEXEL0, PRIMITIVE, TEXEL0, 0, SHADE, 0 +#define _G_CC_BLENDPEDECALA ENVIRONMENT, PRIMITIVE, TEXEL0, PRIMITIVE, 0, 0, 0, TEXEL0 +#define _G_CC_TWOCOLORTEX PRIMITIVE, SHADE, TEXEL0, SHADE, 0, 0, 0, SHADE +/* used for 1-cycle sparse mip-maps, primitive color has color of lowest LOD */ +#define _G_CC_SPARSEST PRIMITIVE, TEXEL0, LOD_FRACTION, TEXEL0, PRIMITIVE, TEXEL0, LOD_FRACTION, TEXEL0 +#define G_CC_TEMPLERP TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0, TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0 + +/* typical CC cycle 1 modes, usually followed by other cycle 2 modes */ +#define G_CC_TRILERP TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0 +#define G_CC_INTERFERENCE TEXEL0, 0, TEXEL1, 0, TEXEL0, 0, TEXEL1, 0 + +/* + * One-cycle color convert operation + */ +#define G_CC_1CYUV2RGB TEXEL0, K4, K5, TEXEL0, 0, 0, 0, SHADE + +/* + * NOTE: YUV2RGB expects TF step1 color conversion to occur in 2nd clock. + * Therefore, CC looks for step1 results in TEXEL1 + */ +#define G_CC_YUV2RGB TEXEL1, K4, K5, TEXEL1, 0, 0, 0, 0 + +/* typical CC cycle 2 modes */ +#define G_CC_PASS2 0, 0, 0, COMBINED, 0, 0, 0, COMBINED +#define G_CC_MODULATEI2 COMBINED, 0, SHADE, 0, 0, 0, 0, SHADE +#define G_CC_MODULATEIA2 COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0 +#define G_CC_MODULATERGB2 G_CC_MODULATEI2 +#define G_CC_MODULATERGBA2 G_CC_MODULATEIA2 +#define G_CC_MODULATEI_PRIM2 COMBINED, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE +#define G_CC_MODULATEIA_PRIM2 COMBINED, 0, PRIMITIVE, 0, COMBINED, 0, PRIMITIVE, 0 +#define G_CC_MODULATERGB_PRIM2 G_CC_MODULATEI_PRIM2 +#define G_CC_MODULATERGBA_PRIM2 G_CC_MODULATEIA_PRIM2 +#define G_CC_DECALRGB2 0, 0, 0, COMBINED, 0, 0, 0, SHADE +/* + * ? +#define G_CC_DECALRGBA2 COMBINED, SHADE, COMBINED_ALPHA, SHADE, 0, 0, 0, SHADE +*/ +#define G_CC_BLENDI2 ENVIRONMENT, SHADE, COMBINED, SHADE, 0, 0, 0, SHADE +#define G_CC_BLENDIA2 ENVIRONMENT, SHADE, COMBINED, SHADE, COMBINED, 0, SHADE, 0 +#define G_CC_CHROMA_KEY2 TEXEL0, CENTER, SCALE, 0, 0, 0, 0, 0 +#define G_CC_HILITERGB2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, SHADE +#define G_CC_HILITERGBA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, ENVIRONMENT, COMBINED, TEXEL0, COMBINED +#define G_CC_HILITERGBDECALA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, TEXEL0 +#define G_CC_HILITERGBPASSA2 ENVIRONMENT, COMBINED, TEXEL0, COMBINED, 0, 0, 0, COMBINED + +/* + * G_SETOTHERMODE_L sft: shift count + */ +#define G_MDSFT_ALPHACOMPARE 0 +#define G_MDSFT_ZSRCSEL 2 +#define G_MDSFT_RENDERMODE 3 +#define G_MDSFT_BLENDER 16 + +/* + * G_SETOTHERMODE_H sft: shift count + */ +#define G_MDSFT_BLENDMASK 0 /* unsupported */ +#define G_MDSFT_ALPHADITHER 4 +#define G_MDSFT_RGBDITHER 6 + +#define G_MDSFT_COMBKEY 8 +#define G_MDSFT_TEXTCONV 9 +#define G_MDSFT_TEXTFILT 12 +#define G_MDSFT_TEXTLUT 14 +#define G_MDSFT_TEXTLOD 16 +#define G_MDSFT_TEXTDETAIL 17 +#define G_MDSFT_TEXTPERSP 19 +#define G_MDSFT_CYCLETYPE 20 +#define G_MDSFT_COLORDITHER 22 /* unsupported in HW 2.0 */ +#define G_MDSFT_PIPELINE 23 + +/* G_SETOTHERMODE_H gPipelineMode */ +#define G_PM_1PRIMITIVE (1 << G_MDSFT_PIPELINE) +#define G_PM_NPRIMITIVE (0 << G_MDSFT_PIPELINE) + +/* G_SETOTHERMODE_H gSetCycleType */ +#define G_CYC_1CYCLE (0 << G_MDSFT_CYCLETYPE) +#define G_CYC_2CYCLE (1 << G_MDSFT_CYCLETYPE) +#define G_CYC_COPY (2 << G_MDSFT_CYCLETYPE) +#define G_CYC_FILL (3 << G_MDSFT_CYCLETYPE) + +/* G_SETOTHERMODE_H gSetTexturePersp */ +#define G_TP_NONE (0 << G_MDSFT_TEXTPERSP) +#define G_TP_PERSP (1 << G_MDSFT_TEXTPERSP) + +/* G_SETOTHERMODE_H gSetTextureDetail */ +#define G_TD_CLAMP (0 << G_MDSFT_TEXTDETAIL) +#define G_TD_SHARPEN (1 << G_MDSFT_TEXTDETAIL) +#define G_TD_DETAIL (2 << G_MDSFT_TEXTDETAIL) + +/* G_SETOTHERMODE_H gSetTextureLOD */ +#define G_TL_TILE (0 << G_MDSFT_TEXTLOD) +#define G_TL_LOD (1 << G_MDSFT_TEXTLOD) + +/* G_SETOTHERMODE_H gSetTextureLUT */ +#define G_TT_NONE (0 << G_MDSFT_TEXTLUT) +#define G_TT_RGBA16 (2 << G_MDSFT_TEXTLUT) +#define G_TT_IA16 (3 << G_MDSFT_TEXTLUT) + +/* G_SETOTHERMODE_H gSetTextureFilter */ +#define G_TF_POINT (0 << G_MDSFT_TEXTFILT) +#define G_TF_AVERAGE (3 << G_MDSFT_TEXTFILT) +#define G_TF_BILERP (2 << G_MDSFT_TEXTFILT) + +/* G_SETOTHERMODE_H gSetTextureConvert */ +#define G_TC_CONV (0 << G_MDSFT_TEXTCONV) +#define G_TC_FILTCONV (5 << G_MDSFT_TEXTCONV) +#define G_TC_FILT (6 << G_MDSFT_TEXTCONV) + +/* G_SETOTHERMODE_H gSetCombineKey */ +#define G_CK_NONE (0 << G_MDSFT_COMBKEY) +#define G_CK_KEY (1 << G_MDSFT_COMBKEY) + +/* G_SETOTHERMODE_H gSetColorDither */ +#define G_CD_MAGICSQ (0 << G_MDSFT_RGBDITHER) +#define G_CD_BAYER (1 << G_MDSFT_RGBDITHER) +#define G_CD_NOISE (2 << G_MDSFT_RGBDITHER) + +#ifndef _HW_VERSION_1 +#define G_CD_DISABLE (3 << G_MDSFT_RGBDITHER) +#define G_CD_ENABLE G_CD_NOISE /* HW 1.0 compatibility mode */ +#else +#define G_CD_ENABLE (1 << G_MDSFT_COLORDITHER) +#define G_CD_DISABLE (0 << G_MDSFT_COLORDITHER) +#endif + +/* G_SETOTHERMODE_H gSetAlphaDither */ +#define G_AD_PATTERN (0 << G_MDSFT_ALPHADITHER) +#define G_AD_NOTPATTERN (1 << G_MDSFT_ALPHADITHER) +#define G_AD_NOISE (2 << G_MDSFT_ALPHADITHER) +#define G_AD_DISABLE (3 << G_MDSFT_ALPHADITHER) + +/* G_SETOTHERMODE_L gSetAlphaCompare */ +#define G_AC_NONE (0 << G_MDSFT_ALPHACOMPARE) +#define G_AC_THRESHOLD (1 << G_MDSFT_ALPHACOMPARE) +#define G_AC_DITHER (3 << G_MDSFT_ALPHACOMPARE) + +/* G_SETOTHERMODE_L gSetDepthSource */ +#define G_ZS_PIXEL (0 << G_MDSFT_ZSRCSEL) +#define G_ZS_PRIM (1 << G_MDSFT_ZSRCSEL) + +/* G_SETOTHERMODE_L gSetRenderMode */ +#define AA_EN 0x8 +#define Z_CMP 0x10 +#define Z_UPD 0x20 +#define IM_RD 0x40 +#define CLR_ON_CVG 0x80 +#define CVG_DST_CLAMP 0 +#define CVG_DST_WRAP 0x100 +#define CVG_DST_FULL 0x200 +#define CVG_DST_SAVE 0x300 +#define ZMODE_OPA 0 +#define ZMODE_INTER 0x400 +#define ZMODE_XLU 0x800 +#define ZMODE_DEC 0xc00 +#define CVG_X_ALPHA 0x1000 +#define ALPHA_CVG_SEL 0x2000 +#define FORCE_BL 0x4000 +#define TEX_EDGE 0x0000 /* used to be 0x8000 */ + +#define G_BL_CLR_IN 0 +#define G_BL_CLR_MEM 1 +#define G_BL_CLR_BL 2 +#define G_BL_CLR_FOG 3 +#define G_BL_1MA 0 +#define G_BL_A_MEM 1 +#define G_BL_A_IN 0 +#define G_BL_A_FOG 1 +#define G_BL_A_SHADE 2 +#define G_BL_1 2 +#define G_BL_0 3 + +#ifdef DISABLE_AA +#define AA_DEF +#define RD_DEF +#else +#define AA_DEF AA_EN | +#define RD_DEF IM_RD | +#endif + +#define GBL_c1(m1a, m1b, m2a, m2b) \ + (m1a) << 30 | (m1b) << 26 | (m2a) << 22 | (m2b) << 18 +#define GBL_c2(m1a, m1b, m2a, m2b) \ + (m1a) << 28 | (m1b) << 24 | (m2a) << 20 | (m2b) << 16 + +#define RM_AA_ZB_OPA_SURF(clk) \ + AA_DEF Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_ZB_OPA_SURF(clk) \ + AA_DEF Z_CMP | Z_UPD | CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_XLU_SURF(clk) \ + AA_DEF Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ + FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_OPA_DECAL(clk) \ + AA_DEF Z_CMP | RD_DEF CVG_DST_WRAP | ALPHA_CVG_SEL | \ + ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_ZB_OPA_DECAL(clk) \ + AA_DEF Z_CMP | CVG_DST_WRAP | ALPHA_CVG_SEL | \ + ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_XLU_DECAL(clk) \ + AA_DEF Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ + FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_OPA_INTER(clk) \ + AA_DEF Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ + ALPHA_CVG_SEL | ZMODE_INTER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_ZB_OPA_INTER(clk) \ + AA_DEF Z_CMP | Z_UPD | CVG_DST_CLAMP | \ + ALPHA_CVG_SEL | ZMODE_INTER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_XLU_INTER(clk) \ + AA_DEF Z_CMP | IM_RD | CVG_DST_WRAP | CLR_ON_CVG | \ + FORCE_BL | ZMODE_INTER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_XLU_LINE(clk) \ + AA_DEF Z_CMP | IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_DEC_LINE(clk) \ + AA_DEF Z_CMP | IM_RD | CVG_DST_SAVE | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_TEX_EDGE(clk) \ + AA_EN | Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_TEX_INTER(clk) \ + AA_DEF Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_INTER | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_SUB_SURF(clk) \ + AA_DEF Z_CMP | Z_UPD | IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_ZB_PCL_SURF(clk) \ + AA_DEF Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_OPA_TERR(clk) \ + AA_DEF Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_TEX_TERR(clk) \ + AA_DEF Z_CMP | Z_UPD | RD_DEF CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_ZB_SUB_TERR(clk) \ + AA_DEF Z_CMP | Z_UPD | IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + + +#define RM_AA_OPA_SURF(clk) \ + AA_DEF RD_DEF CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_RA_OPA_SURF(clk) \ + AA_DEF CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_XLU_SURF(clk) \ + AA_DEF IM_RD | CVG_DST_WRAP | CLR_ON_CVG | FORCE_BL | \ + ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_XLU_LINE(clk) \ + AA_DEF IM_RD | CVG_DST_CLAMP | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_DEC_LINE(clk) \ + AA_DEF IM_RD | CVG_DST_FULL | CVG_X_ALPHA | \ + ALPHA_CVG_SEL | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_TEX_EDGE(clk) \ + AA_EN | RD_DEF CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_SUB_SURF(clk) \ + AA_DEF IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_AA_PCL_SURF(clk) \ + AA_DEF IM_RD | CVG_DST_CLAMP | \ + ZMODE_OPA | G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_OPA_TERR(clk) \ + AA_DEF RD_DEF CVG_DST_CLAMP | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_TEX_TERR(clk) \ + AA_DEF RD_DEF CVG_DST_CLAMP | \ + CVG_X_ALPHA | ALPHA_CVG_SEL | ZMODE_OPA | TEX_EDGE | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_AA_SUB_TERR(clk) \ + AA_DEF IM_RD | CVG_DST_FULL | \ + ZMODE_OPA | ALPHA_CVG_SEL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + + +#define RM_ZB_OPA_SURF(clk) \ + Z_CMP | Z_UPD | CVG_DST_FULL | ALPHA_CVG_SEL | \ + ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_ZB_XLU_SURF(clk) \ + Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_OPA_DECAL(clk) \ + Z_CMP | CVG_DST_FULL | ALPHA_CVG_SEL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_A_MEM) + +#define RM_ZB_XLU_DECAL(clk) \ + Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_CLD_SURF(clk) \ + Z_CMP | IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_XLU | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_OVL_SURF(clk) \ + Z_CMP | IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_DEC | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_ZB_PCL_SURF(clk) \ + Z_CMP | Z_UPD | CVG_DST_FULL | ZMODE_OPA | \ + G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + + +#define RM_OPA_SURF(clk) \ + CVG_DST_CLAMP | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +#define RM_XLU_SURF(clk) \ + IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_TEX_EDGE(clk) \ + CVG_DST_CLAMP | CVG_X_ALPHA | ALPHA_CVG_SEL | FORCE_BL |\ + ZMODE_OPA | TEX_EDGE | AA_EN | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +#define RM_CLD_SURF(clk) \ + IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define RM_PCL_SURF(clk) \ + CVG_DST_FULL | FORCE_BL | ZMODE_OPA | \ + G_AC_DITHER | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +#define RM_ADD(clk) \ + IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_FOG, G_BL_CLR_MEM, G_BL_1) + +#define RM_NOOP(clk) \ + GBL_c##clk(0, 0, 0, 0) + +#define RM_VISCVG(clk) \ + IM_RD | FORCE_BL | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_BL, G_BL_A_MEM) + +/* for rendering to an 8-bit framebuffer */ +#define RM_OPA_CI(clk) \ + CVG_DST_CLAMP | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +/* Custom version of RM_AA_ZB_XLU_SURF with Z_UPD */ +#define RM_CUSTOM_AA_ZB_XLU_SURF(clk) \ + RM_AA_ZB_XLU_SURF(clk) | Z_UPD + + +#ifdef DISABLE_AA + +#define G_RM_AA_ZB_OPA_SURF RM_ZB_OPA_SURF(1) +#define G_RM_AA_ZB_OPA_SURF2 RM_ZB_OPA_SURF(2) +#define G_RM_AA_ZB_XLU_SURF RM_ZB_XLU_SURF(1) +#define G_RM_AA_ZB_XLU_SURF2 RM_ZB_XLU_SURF(2) +#define G_RM_AA_ZB_OPA_DECAL RM_ZB_OPA_DECAL(1) +#define G_RM_AA_ZB_OPA_DECAL2 RM_ZB_OPA_DECAL(2) +#define G_RM_AA_ZB_XLU_DECAL RM_ZB_XLU_DECAL(1) +#define G_RM_AA_ZB_XLU_DECAL2 RM_ZB_XLU_DECAL(2) +#define G_RM_AA_ZB_OPA_INTER RM_AA_ZB_OPA_INTER(1) +#define G_RM_AA_ZB_OPA_INTER2 RM_AA_ZB_OPA_INTER(2) +#define G_RM_AA_ZB_XLU_INTER RM_AA_ZB_XLU_INTER(1) +#define G_RM_AA_ZB_XLU_INTER2 RM_AA_ZB_XLU_INTER(2) +#define G_RM_AA_ZB_XLU_LINE RM_AA_ZB_XLU_LINE(1) +#define G_RM_AA_ZB_XLU_LINE2 RM_AA_ZB_XLU_LINE(2) +#define G_RM_AA_ZB_DEC_LINE RM_AA_ZB_DEC_LINE(1) +#define G_RM_AA_ZB_DEC_LINE2 RM_AA_ZB_DEC_LINE(2) +#define G_RM_AA_ZB_TEX_EDGE RM_AA_ZB_TEX_EDGE(1) +#define G_RM_AA_ZB_TEX_EDGE2 RM_AA_ZB_TEX_EDGE(2) +#define G_RM_AA_ZB_TEX_INTER RM_AA_ZB_TEX_INTER(1) +#define G_RM_AA_ZB_TEX_INTER2 RM_AA_ZB_TEX_INTER(2) +#define G_RM_AA_ZB_SUB_SURF RM_AA_ZB_SUB_SURF(1) +#define G_RM_AA_ZB_SUB_SURF2 RM_AA_ZB_SUB_SURF(2) +#define G_RM_AA_ZB_PCL_SURF RM_ZB_PCL_SURF(1) +#define G_RM_AA_ZB_PCL_SURF2 RM_ZB_PCL_SURF(2) +#define G_RM_AA_ZB_OPA_TERR RM_AA_ZB_OPA_TERR(1) +#define G_RM_AA_ZB_OPA_TERR2 RM_AA_ZB_OPA_TERR(2) +#define G_RM_AA_ZB_TEX_TERR RM_AA_ZB_TEX_TERR(1) +#define G_RM_AA_ZB_TEX_TERR2 RM_AA_ZB_TEX_TERR(2) +#define G_RM_AA_ZB_SUB_TERR RM_AA_ZB_SUB_TERR(1) +#define G_RM_AA_ZB_SUB_TERR2 RM_AA_ZB_SUB_TERR(2) + +#define G_RM_RA_ZB_OPA_SURF RM_RA_ZB_OPA_SURF(1) +#define G_RM_RA_ZB_OPA_SURF2 RM_RA_ZB_OPA_SURF(2) +#define G_RM_RA_ZB_OPA_DECAL RM_RA_ZB_OPA_DECAL(1) +#define G_RM_RA_ZB_OPA_DECAL2 RM_RA_ZB_OPA_DECAL(2) +#define G_RM_RA_ZB_OPA_INTER RM_RA_ZB_OPA_INTER(1) +#define G_RM_RA_ZB_OPA_INTER2 RM_RA_ZB_OPA_INTER(2) + +#define G_RM_AA_OPA_SURF RM_OPA_SURF(1) +#define G_RM_AA_OPA_SURF2 RM_OPA_SURF(2) +#define G_RM_AA_XLU_SURF RM_XLU_SURF(1) +#define G_RM_AA_XLU_SURF2 RM_XLU_SURF(2) +#define G_RM_AA_XLU_LINE RM_AA_XLU_LINE(1) +#define G_RM_AA_XLU_LINE2 RM_AA_XLU_LINE(2) +#define G_RM_AA_DEC_LINE RM_AA_DEC_LINE(1) +#define G_RM_AA_DEC_LINE2 RM_AA_DEC_LINE(2) +#define G_RM_AA_TEX_EDGE RM_TEX_EDGE(1) +#define G_RM_AA_TEX_EDGE2 RM_TEX_EDGE(2) +#define G_RM_AA_SUB_SURF RM_AA_SUB_SURF(1) +#define G_RM_AA_SUB_SURF2 RM_AA_SUB_SURF(2) +#define G_RM_AA_PCL_SURF RM_PCL_SURF(1) +#define G_RM_AA_PCL_SURF2 RM_PCL_SURF(2) +#define G_RM_AA_OPA_TERR RM_AA_OPA_TERR(1) +#define G_RM_AA_OPA_TERR2 RM_AA_OPA_TERR(2) +#define G_RM_AA_TEX_TERR RM_AA_TEX_TERR(1) +#define G_RM_AA_TEX_TERR2 RM_AA_TEX_TERR(2) +#define G_RM_AA_SUB_TERR RM_AA_SUB_TERR(1) +#define G_RM_AA_SUB_TERR2 RM_AA_SUB_TERR(2) + +#else + +#define G_RM_AA_ZB_OPA_SURF RM_AA_ZB_OPA_SURF(1) +#define G_RM_AA_ZB_OPA_SURF2 RM_AA_ZB_OPA_SURF(2) +#define G_RM_AA_ZB_XLU_SURF RM_AA_ZB_XLU_SURF(1) +#define G_RM_AA_ZB_XLU_SURF2 RM_AA_ZB_XLU_SURF(2) +#define G_RM_AA_ZB_OPA_DECAL RM_AA_ZB_OPA_DECAL(1) +#define G_RM_AA_ZB_OPA_DECAL2 RM_AA_ZB_OPA_DECAL(2) +#define G_RM_AA_ZB_XLU_DECAL RM_AA_ZB_XLU_DECAL(1) +#define G_RM_AA_ZB_XLU_DECAL2 RM_AA_ZB_XLU_DECAL(2) +#define G_RM_AA_ZB_OPA_INTER RM_AA_ZB_OPA_INTER(1) +#define G_RM_AA_ZB_OPA_INTER2 RM_AA_ZB_OPA_INTER(2) +#define G_RM_AA_ZB_XLU_INTER RM_AA_ZB_XLU_INTER(1) +#define G_RM_AA_ZB_XLU_INTER2 RM_AA_ZB_XLU_INTER(2) +#define G_RM_AA_ZB_XLU_LINE RM_AA_ZB_XLU_LINE(1) +#define G_RM_AA_ZB_XLU_LINE2 RM_AA_ZB_XLU_LINE(2) +#define G_RM_AA_ZB_DEC_LINE RM_AA_ZB_DEC_LINE(1) +#define G_RM_AA_ZB_DEC_LINE2 RM_AA_ZB_DEC_LINE(2) +#define G_RM_AA_ZB_TEX_EDGE RM_AA_ZB_TEX_EDGE(1) +#define G_RM_AA_ZB_TEX_EDGE2 RM_AA_ZB_TEX_EDGE(2) +#define G_RM_AA_ZB_TEX_INTER RM_AA_ZB_TEX_INTER(1) +#define G_RM_AA_ZB_TEX_INTER2 RM_AA_ZB_TEX_INTER(2) +#define G_RM_AA_ZB_SUB_SURF RM_AA_ZB_SUB_SURF(1) +#define G_RM_AA_ZB_SUB_SURF2 RM_AA_ZB_SUB_SURF(2) +#define G_RM_AA_ZB_PCL_SURF RM_AA_ZB_PCL_SURF(1) +#define G_RM_AA_ZB_PCL_SURF2 RM_AA_ZB_PCL_SURF(2) +#define G_RM_AA_ZB_OPA_TERR RM_AA_ZB_OPA_TERR(1) +#define G_RM_AA_ZB_OPA_TERR2 RM_AA_ZB_OPA_TERR(2) +#define G_RM_AA_ZB_TEX_TERR RM_AA_ZB_TEX_TERR(1) +#define G_RM_AA_ZB_TEX_TERR2 RM_AA_ZB_TEX_TERR(2) +#define G_RM_AA_ZB_SUB_TERR RM_AA_ZB_SUB_TERR(1) +#define G_RM_AA_ZB_SUB_TERR2 RM_AA_ZB_SUB_TERR(2) + +#define G_RM_RA_ZB_OPA_SURF RM_RA_ZB_OPA_SURF(1) +#define G_RM_RA_ZB_OPA_SURF2 RM_RA_ZB_OPA_SURF(2) +#define G_RM_RA_ZB_OPA_DECAL RM_RA_ZB_OPA_DECAL(1) +#define G_RM_RA_ZB_OPA_DECAL2 RM_RA_ZB_OPA_DECAL(2) +#define G_RM_RA_ZB_OPA_INTER RM_RA_ZB_OPA_INTER(1) +#define G_RM_RA_ZB_OPA_INTER2 RM_RA_ZB_OPA_INTER(2) + +#define G_RM_AA_OPA_SURF RM_AA_OPA_SURF(1) +#define G_RM_AA_OPA_SURF2 RM_AA_OPA_SURF(2) +#define G_RM_AA_XLU_SURF RM_AA_XLU_SURF(1) +#define G_RM_AA_XLU_SURF2 RM_AA_XLU_SURF(2) +#define G_RM_AA_XLU_LINE RM_AA_XLU_LINE(1) +#define G_RM_AA_XLU_LINE2 RM_AA_XLU_LINE(2) +#define G_RM_AA_DEC_LINE RM_AA_DEC_LINE(1) +#define G_RM_AA_DEC_LINE2 RM_AA_DEC_LINE(2) +#define G_RM_AA_TEX_EDGE RM_AA_TEX_EDGE(1) +#define G_RM_AA_TEX_EDGE2 RM_AA_TEX_EDGE(2) +#define G_RM_AA_SUB_SURF RM_AA_SUB_SURF(1) +#define G_RM_AA_SUB_SURF2 RM_AA_SUB_SURF(2) +#define G_RM_AA_PCL_SURF RM_AA_PCL_SURF(1) +#define G_RM_AA_PCL_SURF2 RM_AA_PCL_SURF(2) +#define G_RM_AA_OPA_TERR RM_AA_OPA_TERR(1) +#define G_RM_AA_OPA_TERR2 RM_AA_OPA_TERR(2) +#define G_RM_AA_TEX_TERR RM_AA_TEX_TERR(1) +#define G_RM_AA_TEX_TERR2 RM_AA_TEX_TERR(2) +#define G_RM_AA_SUB_TERR RM_AA_SUB_TERR(1) +#define G_RM_AA_SUB_TERR2 RM_AA_SUB_TERR(2) + +#endif + +#define G_RM_RA_OPA_SURF RM_RA_OPA_SURF(1) +#define G_RM_RA_OPA_SURF2 RM_RA_OPA_SURF(2) + +#define G_RM_ZB_OPA_SURF RM_ZB_OPA_SURF(1) +#define G_RM_ZB_OPA_SURF2 RM_ZB_OPA_SURF(2) +#define G_RM_ZB_XLU_SURF RM_ZB_XLU_SURF(1) +#define G_RM_ZB_XLU_SURF2 RM_ZB_XLU_SURF(2) +#define G_RM_ZB_OPA_DECAL RM_ZB_OPA_DECAL(1) +#define G_RM_ZB_OPA_DECAL2 RM_ZB_OPA_DECAL(2) +#define G_RM_ZB_XLU_DECAL RM_ZB_XLU_DECAL(1) +#define G_RM_ZB_XLU_DECAL2 RM_ZB_XLU_DECAL(2) +#define G_RM_ZB_CLD_SURF RM_ZB_CLD_SURF(1) +#define G_RM_ZB_CLD_SURF2 RM_ZB_CLD_SURF(2) +#define G_RM_ZB_OVL_SURF RM_ZB_OVL_SURF(1) +#define G_RM_ZB_OVL_SURF2 RM_ZB_OVL_SURF(2) +#define G_RM_ZB_PCL_SURF RM_ZB_PCL_SURF(1) +#define G_RM_ZB_PCL_SURF2 RM_ZB_PCL_SURF(2) + +#define G_RM_OPA_SURF RM_OPA_SURF(1) +#define G_RM_OPA_SURF2 RM_OPA_SURF(2) +#define G_RM_XLU_SURF RM_XLU_SURF(1) +#define G_RM_XLU_SURF2 RM_XLU_SURF(2) +#define G_RM_CLD_SURF RM_CLD_SURF(1) +#define G_RM_CLD_SURF2 RM_CLD_SURF(2) +#define G_RM_TEX_EDGE RM_TEX_EDGE(1) +#define G_RM_TEX_EDGE2 RM_TEX_EDGE(2) +#define G_RM_PCL_SURF RM_PCL_SURF(1) +#define G_RM_PCL_SURF2 RM_PCL_SURF(2) +#define G_RM_ADD RM_ADD(1) +#define G_RM_ADD2 RM_ADD(2) +#define G_RM_NOOP RM_NOOP(1) +#define G_RM_NOOP2 RM_NOOP(2) +#define G_RM_VISCVG RM_VISCVG(1) +#define G_RM_VISCVG2 RM_VISCVG(2) +#define G_RM_OPA_CI RM_OPA_CI(1) +#define G_RM_OPA_CI2 RM_OPA_CI(2) + +#define G_RM_CUSTOM_AA_ZB_XLU_SURF RM_CUSTOM_AA_ZB_XLU_SURF(1) +#define G_RM_CUSTOM_AA_ZB_XLU_SURF2 RM_CUSTOM_AA_ZB_XLU_SURF(2) + + +#define G_RM_FOG_SHADE_A GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA) +#define G_RM_FOG_PRIM_A GBL_c1(G_BL_CLR_FOG, G_BL_A_FOG, G_BL_CLR_IN, G_BL_1MA) +#define G_RM_PASS GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) + +#define G_RM_ZB_1C_FOG_SHADE_A \ + Z_CMP | Z_UPD | CVG_DST_FULL | ALPHA_CVG_SEL | ZMODE_OPA | \ + GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA) + +#define G_RM_ZB_1C_FOG_SHADE_A2 \ + CVG_DST_FULL | FORCE_BL | ZMODE_OPA | \ + GBL_c2(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA) + +/* + * G_SETCONVERT: K0-5 + */ +#define G_CV_K0 175 +#define G_CV_K1 -43 +#define G_CV_K2 -89 +#define G_CV_K3 222 +#define G_CV_K4 114 +#define G_CV_K5 42 + +/* + * G_SETSCISSOR: interlace mode + */ +#define G_SC_NON_INTERLACE 0 +#define G_SC_ODD_INTERLACE 3 +#define G_SC_EVEN_INTERLACE 2 + +/* flags to inhibit pushing of the display list (on branch) */ +#define G_DL_PUSH 0x00 +#define G_DL_NOPUSH 0x01 + +/* + * BEGIN C-specific section: (typedef's) + */ +#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) + +/* + * Data Structures + * + * NOTE: + * The DMA transfer hardware requires 64-bit aligned, 64-bit multiple- + * sized transfers. This important hardware optimization is unfortunately + * reflected in the programming interface, with some structures + * padded and alignment enforced. + * + * Since structures are aligned to the boundary of the "worst-case" + * element, we can't depend on the C compiler to align things + * properly. + * + * 64-bit structure alignment is enforced by wrapping structures with + * unions that contain a dummy "long long int". Why this works is + * explained in the ANSI C Spec, or on page 186 of the second edition + * of K&R, "The C Programming Language". + * + * The price we pay for this is a little awkwardness referencing the + * structures through the union. There is no memory penalty, since + * all the structures are at least 64-bits the dummy alignment field + * does not increase the size of the union. + * + * Static initialization of these union structures works because + * the ANSI C spec states that static initialization for unions + * works by using the first union element. We put the dummy alignment + * field last for this reason. + * + * (it's possible a newer 64-bit compiler from MIPS might make this + * easier with a flag, but we can't wait for it...) + * + */ + +/* + * Vertex (set up for use with colors) + */ +typedef struct { +#ifndef GBI_FLOATS + short ob[3]; /* x, y, z */ +#else + float ob[3]; /* x, y, z */ +#endif + unsigned short flag; + short tc[2]; /* texture coord */ + unsigned char cn[4]; /* color & alpha */ +} Vtx_t; + +/* + * Vertex (set up for use with normals) + */ +typedef struct { +#ifndef GBI_FLOATS + short ob[3]; /* x, y, z */ +#else + float ob[3]; /* x, y, z */ +#endif + unsigned short flag; + short tc[2]; /* texture coord */ + signed char n[3]; /* normal */ + unsigned char a; /* alpha */ +} Vtx_tn; + +typedef union { + Vtx_t v; /* Use this one for colors */ + Vtx_tn n; /* Use this one for normals */ + long long int force_structure_alignment; +} Vtx; + +/* + * Triangle face + */ +typedef struct { + unsigned char flag; + unsigned char v[3]; +} Tri; + +#ifndef GBI_FLOATS +/* + * 4x4 matrix, fixed point s15.16 format. + * First 8 words are integer portion of the 4x4 matrix + * Last 8 words are the fraction portion of the 4x4 matrix + */ +typedef s32 Mtx_t[4][4]; + +typedef union { + Mtx_t m; + long long int force_structure_alignment; +} Mtx; +#else +typedef struct { + float m[4][4]; +} Mtx; +#endif + +/* + * Viewport + */ + +/* + * + * This magic value is the maximum INTEGER z-range of the hardware + * (there are also 16-bits of fraction, which are introduced during + * any transformations). This is not just a good idea, it's the law. + * Feeding the hardware eventual z-coordinates (after any transforms + * or scaling) bigger than this, will not work. + * + * This number is DIFFERENT than G_MAXFBZ, which is the maximum value + * you want to use to initialize the z-buffer. + * + * The reason these are different is mildly interesting, but too long + * to explain here. It is basically the result of optimizations in the + * hardware. A more generic API might hide this detail from the users, + * but we don't have the ucode to do that... + * + */ +#define G_MAXZ 0x03ff /* 10 bits of integer screen-Z precision */ + +/* + * The viewport structure elements have 2 bits of fraction, necessary + * to accomodate the sub-pixel positioning scaling for the hardware. + * This can also be exploited to handle odd-sized viewports. + * + * Accounting for these fractional bits, using the default projection + * and viewing matrices, the viewport structure is initialized thusly: + * + * (SCREEN_WD/2)*4, (SCREEN_HT/2)*4, G_MAXZ, 0, + * (SCREEN_WD/2)*4, (SCREEN_HT/2)*4, 0, 0, + */ +typedef struct { + short vscale[4]; /* scale, 2 bits fraction */ + short vtrans[4]; /* translate, 2 bits fraction */ + /* both the above arrays are padded to 64-bit boundary */ +} Vp_t; + +typedef union { + Vp_t vp; + long long int force_structure_alignment; +} Vp; + +/* + * MOVEMEM indices + * + * Each of these indexes an entry in a dmem table + * which points to a 1-4 word block of dmem in + * which to store a 1-4 word DMA. + * + */ +#ifdef F3DEX_GBI_2 +/* 0,4 are reserved by G_MTX */ +# define G_MV_MMTX 2 +# define G_MV_PMTX 6 +# define G_MV_VIEWPORT 8 +# define G_MV_LIGHT 10 +# define G_MV_POINT 12 +# define G_MV_MATRIX 14 /* NOTE: this is in moveword table */ +# define G_MVO_LOOKATX (0*24) +# define G_MVO_LOOKATY (1*24) +# define G_MVO_L0 (2*24) +# define G_MVO_L1 (3*24) +# define G_MVO_L2 (4*24) +# define G_MVO_L3 (5*24) +# define G_MVO_L4 (6*24) +# define G_MVO_L5 (7*24) +# define G_MVO_L6 (8*24) +# define G_MVO_L7 (9*24) +#else /* F3DEX_GBI_2 */ +# define G_MV_VIEWPORT 0x80 +# define G_MV_LOOKATY 0x82 +# define G_MV_LOOKATX 0x84 +# define G_MV_L0 0x86 +# define G_MV_L1 0x88 +# define G_MV_L2 0x8a +# define G_MV_L3 0x8c +# define G_MV_L4 0x8e +# define G_MV_L5 0x90 +# define G_MV_L6 0x92 +# define G_MV_L7 0x94 +# define G_MV_TXTATT 0x96 +# define G_MV_MATRIX_1 0x9e /* NOTE: this is in moveword table */ +# define G_MV_MATRIX_2 0x98 +# define G_MV_MATRIX_3 0x9a +# define G_MV_MATRIX_4 0x9c +#endif /* F3DEX_GBI_2 */ + +/* + * MOVEWORD indices + * + * Each of these indexes an entry in a dmem table + * which points to a word in dmem in dmem where + * an immediate word will be stored. + * + */ +#define G_MW_MATRIX 0x00 /* NOTE: also used by movemem */ +#define G_MW_NUMLIGHT 0x02 +#define G_MW_CLIP 0x04 +#define G_MW_SEGMENT 0x06 +#define G_MW_FOG 0x08 +#define G_MW_LIGHTCOL 0x0a +#ifdef F3DEX_GBI_2 +# define G_MW_FORCEMTX 0x0c +#else /* F3DEX_GBI_2 */ +# define G_MW_POINTS 0x0c +#endif /* F3DEX_GBI_2 */ +#define G_MW_PERSPNORM 0x0e + +/* + * These are offsets from the address in the dmem table + */ +#define G_MWO_NUMLIGHT 0x00 +#define G_MWO_CLIP_RNX 0x04 +#define G_MWO_CLIP_RNY 0x0c +#define G_MWO_CLIP_RPX 0x14 +#define G_MWO_CLIP_RPY 0x1c +#define G_MWO_SEGMENT_0 0x00 +#define G_MWO_SEGMENT_1 0x01 +#define G_MWO_SEGMENT_2 0x02 +#define G_MWO_SEGMENT_3 0x03 +#define G_MWO_SEGMENT_4 0x04 +#define G_MWO_SEGMENT_5 0x05 +#define G_MWO_SEGMENT_6 0x06 +#define G_MWO_SEGMENT_7 0x07 +#define G_MWO_SEGMENT_8 0x08 +#define G_MWO_SEGMENT_9 0x09 +#define G_MWO_SEGMENT_A 0x0a +#define G_MWO_SEGMENT_B 0x0b +#define G_MWO_SEGMENT_C 0x0c +#define G_MWO_SEGMENT_D 0x0d +#define G_MWO_SEGMENT_E 0x0e +#define G_MWO_SEGMENT_F 0x0f +#define G_MWO_FOG 0x00 +#define G_MWO_aLIGHT_1 0x00 +#define G_MWO_bLIGHT_1 0x04 +#ifdef F3DEX_GBI_2 +#define G_MWO_aLIGHT_2 0x18 +#define G_MWO_bLIGHT_2 0x1c +#define G_MWO_aLIGHT_3 0x30 +#define G_MWO_bLIGHT_3 0x34 +#define G_MWO_aLIGHT_4 0x48 +#define G_MWO_bLIGHT_4 0x4c +#define G_MWO_aLIGHT_5 0x60 +#define G_MWO_bLIGHT_5 0x64 +#define G_MWO_aLIGHT_6 0x78 +#define G_MWO_bLIGHT_6 0x7c +#define G_MWO_aLIGHT_7 0x90 +#define G_MWO_bLIGHT_7 0x94 +#define G_MWO_aLIGHT_8 0xa8 +#define G_MWO_bLIGHT_8 0xac +#else +#define G_MWO_aLIGHT_2 0x20 +#define G_MWO_bLIGHT_2 0x24 +#define G_MWO_aLIGHT_3 0x40 +#define G_MWO_bLIGHT_3 0x44 +#define G_MWO_aLIGHT_4 0x60 +#define G_MWO_bLIGHT_4 0x64 +#define G_MWO_aLIGHT_5 0x80 +#define G_MWO_bLIGHT_5 0x84 +#define G_MWO_aLIGHT_6 0xa0 +#define G_MWO_bLIGHT_6 0xa4 +#define G_MWO_aLIGHT_7 0xc0 +#define G_MWO_bLIGHT_7 0xc4 +#define G_MWO_aLIGHT_8 0xe0 +#define G_MWO_bLIGHT_8 0xe4 +#endif +#define G_MWO_MATRIX_XX_XY_I 0x00 +#define G_MWO_MATRIX_XZ_XW_I 0x04 +#define G_MWO_MATRIX_YX_YY_I 0x08 +#define G_MWO_MATRIX_YZ_YW_I 0x0c +#define G_MWO_MATRIX_ZX_ZY_I 0x10 +#define G_MWO_MATRIX_ZZ_ZW_I 0x14 +#define G_MWO_MATRIX_WX_WY_I 0x18 +#define G_MWO_MATRIX_WZ_WW_I 0x1c +#define G_MWO_MATRIX_XX_XY_F 0x20 +#define G_MWO_MATRIX_XZ_XW_F 0x24 +#define G_MWO_MATRIX_YX_YY_F 0x28 +#define G_MWO_MATRIX_YZ_YW_F 0x2c +#define G_MWO_MATRIX_ZX_ZY_F 0x30 +#define G_MWO_MATRIX_ZZ_ZW_F 0x34 +#define G_MWO_MATRIX_WX_WY_F 0x38 +#define G_MWO_MATRIX_WZ_WW_F 0x3c +#define G_MWO_POINT_RGBA 0x10 +#define G_MWO_POINT_ST 0x14 +#define G_MWO_POINT_XYSCREEN 0x18 +#define G_MWO_POINT_ZSCREEN 0x1c + +/* + * Light structure. + * + * Note: only directional (infinite) lights are currently supported. + * + * Note: the weird order is for the DMEM alignment benefit of + * the microcode. + * + */ + +typedef struct { + unsigned char col[3]; /* diffuse light value (rgba) */ + char pad1; + unsigned char colc[3]; /* copy of diffuse light value (rgba) */ + char pad2; + signed char dir[3]; /* direction of light (normalized) */ + char pad3; +} Light_t; + +typedef struct { + unsigned char col[3]; /* ambient light value (rgba) */ + char pad1; + unsigned char colc[3]; /* copy of ambient light value (rgba) */ + char pad2; +} Ambient_t; + +typedef struct { + int x1,y1,x2,y2; /* texture offsets for highlight 1/2 */ +} Hilite_t; + +typedef union { + Light_t l; + long long int force_structure_alignment[2]; +} Light; + +typedef union { + Ambient_t l; + long long int force_structure_alignment[1]; +} Ambient; + +typedef struct { + Ambient a; + Light l[7]; +} Lightsn; + +typedef struct { + Ambient a; + Light l[1]; +} Lights0; + +typedef struct { + Ambient a; + Light l[1]; +} Lights1; + +typedef struct { + Ambient a; + Light l[2]; +} Lights2; + +typedef struct { + Ambient a; + Light l[3]; +} Lights3; + +typedef struct { + Ambient a; + Light l[4]; +} Lights4; + +typedef struct { + Ambient a; + Light l[5]; +} Lights5; + +typedef struct { + Ambient a; + Light l[6]; +} Lights6; + +typedef struct { + Ambient a; + Light l[7]; +} Lights7; + +typedef struct { + Light l[2]; +} LookAt; + +typedef union { + Hilite_t h; + long int force_structure_alignment[4]; +} Hilite; + +#define gdSPDefLights0(ar,ag,ab) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ { 0, 0, 0},0,{ 0, 0, 0},0,{ 0, 0, 0},0}}} } +#define gdSPDefLights1(ar,ag,ab,r1,g1,b1,x1,y1,z1) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}} } +#define gdSPDefLights2(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}} } +#define gdSPDefLights3(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ + {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}} } +#define gdSPDefLights4(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ + {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ + {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}} } +#define gdSPDefLights5(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4,r5,g5,b5,x5,y5,z5) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ + {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ + {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}, \ + {{ {r5,g5,b5},0,{r5,g5,b5},0,{x5,y5,z5},0}}} } + + +#define gdSPDefLights6(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4,r5,g5,b5,x5,y5,z5,r6,g6,b6,x6,y6,z6) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ + {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ + {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}, \ + {{ {r5,g5,b5},0,{r5,g5,b5},0,{x5,y5,z5},0}}, \ + {{ {r6,g6,b6},0,{r6,g6,b6},0,{x6,y6,z6},0}}} } + + +#define gdSPDefLights7(ar,ag,ab,r1,g1,b1,x1,y1,z1,r2,g2,b2,x2,y2,z2,r3,g3,b3,x3,y3,z3,r4,g4,b4,x4,y4,z4,r5,g5,b5,x5,y5,z5,r6,g6,b6,x6,y6,z6,r7,g7,b7,x7,y7,z7) \ + { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{ {r1,g1,b1},0,{r1,g1,b1},0,{x1,y1,z1},0}}, \ + {{ {r2,g2,b2},0,{r2,g2,b2},0,{x2,y2,z2},0}}, \ + {{ {r3,g3,b3},0,{r3,g3,b3},0,{x3,y3,z3},0}}, \ + {{ {r4,g4,b4},0,{r4,g4,b4},0,{x4,y4,z4},0}}, \ + {{ {r5,g5,b5},0,{r5,g5,b5},0,{x5,y5,z5},0}}, \ + {{ {r6,g6,b6},0,{r6,g6,b6},0,{x6,y6,z6},0}}, \ + {{ {r7,g7,b7},0,{r7,g7,b7},0,{x7,y7,z7},0}}} } + + +#define gdSPDefLookAt(rightx,righty,rightz,upx,upy,upz) \ + { {{ {{0,0,0},0,{0,0,0},0,{rightx,righty,rightz},0}}, \ + { {{0,0x80,0},0,{0,0x80,0},0,{upx,upy,upz},0}}} } + +/* Don't declare these for F3D_OLD to avoid bss reordering */ +#ifndef F3D_OLD +/* + * Graphics DMA Packet + */ +typedef struct { + int cmd:8; + unsigned int par:8; + unsigned int len:16; + uintptr_t addr; +} Gdma; + +/* + * Graphics Immediate Mode Packet types + */ +typedef struct { + int cmd:8; + int pad:24; + Tri tri; +} Gtri; + +typedef struct { + int cmd:8; + int pad1:24; + int pad2:24; + unsigned char param:8; +} Gpopmtx; + +/* + * typedef struct { + * int cmd:8; + * int pad0:24; + * int pad1:4; + * int number:4; + * int base:24; + * } Gsegment; + */ +typedef struct { + int cmd:8; + int pad0:8; + int mw_index:8; + int number:8; + int pad1:8; + int base:24; +} Gsegment; + +typedef struct { + int cmd:8; + int pad0:8; + int sft:8; + int len:8; + unsigned int data:32; +} GsetothermodeL; + +typedef struct { + int cmd:8; + int pad0:8; + int sft:8; + int len:8; + unsigned int data:32; +} GsetothermodeH; + +typedef struct { + unsigned char cmd; + unsigned char lodscale; + unsigned char tile; + unsigned char on; + unsigned short s; + unsigned short t; +} Gtexture; + +typedef struct { + int cmd:8; + int pad:24; + Tri line; +} Gline3D; + +typedef struct { + int cmd:8; + int pad1:24; + short int pad2; + short int scale; +} Gperspnorm; + + +/* + * RDP Packet types + */ +typedef struct { + int cmd:8; + unsigned int fmt:3; + unsigned int siz:2; + unsigned int pad:7; + unsigned int wd:12; /* really only 10 bits, extra */ + uintptr_t dram; /* to account for 1024 */ +} Gsetimg; + +typedef struct { + int cmd:8; + unsigned int muxs0:24; + unsigned int muxs1:32; +} Gsetcombine; + +typedef struct { + int cmd:8; + unsigned char pad; + unsigned char prim_min_level; + unsigned char prim_level; + unsigned long color; +} Gsetcolor; + +typedef struct { + int cmd:8; + int x0:10; + int x0frac:2; + int y0:10; + int y0frac:2; + unsigned int pad:8; + int x1:10; + int x1frac:2; + int y1:10; + int y1frac:2; +} Gfillrect; + +typedef struct { + int cmd:8; + unsigned int fmt:3; + unsigned int siz:2; + unsigned int pad0:1; + unsigned int line:9; + unsigned int tmem:9; + unsigned int pad1:5; + unsigned int tile:3; + unsigned int palette:4; + unsigned int ct:1; + unsigned int mt:1; + unsigned int maskt:4; + unsigned int shiftt:4; + unsigned int cs:1; + unsigned int ms:1; + unsigned int masks:4; + unsigned int shifts:4; +} Gsettile; + +typedef struct { + int cmd:8; + unsigned int sl:12; + unsigned int tl:12; + int pad:5; + unsigned int tile:3; + unsigned int sh:12; + unsigned int th:12; +} Gloadtile; + +typedef Gloadtile Gloadblock; + +typedef Gloadtile Gsettilesize; + +typedef Gloadtile Gloadtlut; + +typedef struct { + unsigned int cmd:8; /* command */ + unsigned int xl:12; /* X coordinate of upper left */ + unsigned int yl:12; /* Y coordinate of upper left */ + unsigned int pad1:5; /* Padding */ + unsigned int tile:3; /* Tile descriptor index */ + unsigned int xh:12; /* X coordinate of lower right */ + unsigned int yh:12; /* Y coordinate of lower right */ + unsigned int s:16; /* S texture coord at top left */ + unsigned int t:16; /* T texture coord at top left */ + unsigned int dsdx:16;/* Change in S per change in X */ + unsigned int dtdy:16;/* Change in T per change in Y */ +} Gtexrect; + +/* + * Textured rectangles are 128 bits not 64 bits + */ +typedef struct { + unsigned long w0; + unsigned long w1; + unsigned long w2; + unsigned long w3; +} TexRect; +#endif + +#define MakeTexRect(xh,yh,flip,tile,xl,yl,s,t,dsdx,dtdy) \ + G_TEXRECT, xh, yh, 0, flip, 0, tile, xl, yl, s, t, dsdx, dtdy + +/* + * Generic Gfx Packet + */ +typedef struct { + uintptr_t w0; + uintptr_t w1; +} Gwords; + +/* + * This union is the fundamental type of the display list. + * It is, by law, exactly 64 bits in size. + * + * (Edit: except on 64-bit, where it is exactly 128 bit. On little-endian or + * 64-bit systems, only the 'words' member may be accessed; the rest of the + * structs don't have matching layouts for now.) + */ +typedef union { + Gwords words; +#if !defined(F3D_OLD) && IS_BIG_ENDIAN && !IS_64_BIT + Gdma dma; + Gtri tri; + Gline3D line; + Gpopmtx popmtx; + Gsegment segment; + GsetothermodeH setothermodeH; + GsetothermodeL setothermodeL; + Gtexture texture; + Gperspnorm perspnorm; + Gsetimg setimg; + Gsetcombine setcombine; + Gsetcolor setcolor; + Gfillrect fillrect; /* use for setscissor also */ + Gsettile settile; + Gloadtile loadtile; /* use for loadblock also, th is dxt */ + Gsettilesize settilesize; + Gloadtlut loadtlut; +#endif + long long int force_structure_alignment; +} Gfx; + +/* + * Macros to assemble the graphics display list + */ + +/* + * DMA macros + */ +#define gDma0p(pkt, c, s, l) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24); \ + _g->words.w1 = (uintptr_t)(s); \ +} + +#define gsDma0p(c, s, l) \ +{{ \ + _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24), (uintptr_t)(s) \ +}} + +#define gDma1p(pkt, c, s, l, p) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \ + _SHIFTL((l), 0, 16)); \ + _g->words.w1 = (uintptr_t)(s); \ +} + +#define gsDma1p(c, s, l, p) \ +{{ \ + (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \ + _SHIFTL((l), 0, 16)), \ + (uintptr_t)(s) \ +}} + +#define gDma2p(pkt, c, adrs, len, idx, ofs) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \ + _SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)); \ + _g->words.w1 = (uintptr_t)(adrs); \ +} +#define gsDma2p(c, adrs, len, idx, ofs) \ +{{ \ + (_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \ + _SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)), \ + (uintptr_t)(adrs) \ +}} + +#define gSPNoOp(pkt) gDma0p(pkt, G_SPNOOP, 0, 0) +#define gsSPNoOp() gsDma0p(G_SPNOOP, 0, 0) + +#ifdef F3DEX_GBI_2 +# define gSPMatrix(pkt, m, p) \ + gDma2p((pkt),G_MTX,(m),sizeof(Mtx),(p)^G_MTX_PUSH,0) +# define gsSPMatrix(m, p) \ + gsDma2p( G_MTX,(m),sizeof(Mtx),(p)^G_MTX_PUSH,0) +#else /* F3DEX_GBI_2 */ +# define gSPMatrix(pkt, m, p) gDma1p(pkt, G_MTX, m, sizeof(Mtx), p) +# define gsSPMatrix(m, p) gsDma1p(G_MTX, m, sizeof(Mtx), p) +#endif /* F3DEX_GBI_2 */ + +#if defined(F3DEX_GBI_2) +/* + * F3DEX_GBI_2: G_VTX GBI format was changed. + * + * +--------+----+---+---+----+------+-+ + * G_VTX | cmd:8 |0000| n:8 |0000|v0+n:7|0| + * +-+---+--+----+---+---+----+------+-+ + * | |seg| address | + * +-+---+-----------------------------+ + */ +# define gSPVertex(pkt, v, n, v0) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = \ + _SHIFTL(G_VTX,24,8)|_SHIFTL((n),12,8)|_SHIFTL((v0)+(n),1,7); \ + _g->words.w1 = (uintptr_t)(v); \ +} +# define gsSPVertex(v, n, v0) \ +{{ \ + (_SHIFTL(G_VTX,24,8)|_SHIFTL((n),12,8)|_SHIFTL((v0)+(n),1,7)), \ + (uintptr_t)(v) \ +}} +#elif (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +/* + * F3DEX_GBI: G_VTX GBI format was changed to support 64 vertice. + * + * +--------+--------+------+----------+ + * G_VTX | cmd:8 | v0:8 | n:6 |length:10 | + * +-+---+--+--------+------+----------+ + * | |seg| address | + * +-+---+-----------------------------+ + */ +# define gSPVertex(pkt, v, n, v0) \ + gDma1p((pkt),G_VTX,(v),((n)<<10)|(sizeof(Vtx)*(n)-1),(v0)*2) +# define gsSPVertex(v, n, v0) \ + gsDma1p(G_VTX,(v),((n)<<10)|(sizeof(Vtx)*(n)-1),(v0)*2) +#else +# define gSPVertex(pkt, v, n, v0) \ + gDma1p(pkt, G_VTX, v, sizeof(Vtx)*(n),((n)-1)<<4|(v0)) +# define gsSPVertex(v, n, v0) \ + gsDma1p(G_VTX, v, sizeof(Vtx)*(n), ((n)-1)<<4|(v0)) +#endif + + +#ifdef F3DEX_GBI_2 +# define gSPViewport(pkt, v) \ + gDma2p((pkt), G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT, 0) +# define gsSPViewport(v) \ + gsDma2p( G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT, 0) +#else /* F3DEX_GBI_2 */ +# define gSPViewport(pkt,v) \ + gDma1p((pkt), G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT) +# define gsSPViewport(v) \ + gsDma1p( G_MOVEMEM, (v), sizeof(Vp), G_MV_VIEWPORT) +#endif /* F3DEX_GBI_2 */ + +#define gSPDisplayList(pkt,dl) gDma1p(pkt,G_DL,dl,0,G_DL_PUSH) +#define gsSPDisplayList( dl) gsDma1p( G_DL,dl,0,G_DL_PUSH) + +#define gSPBranchList(pkt,dl) gDma1p(pkt,G_DL,dl,0,G_DL_NOPUSH) +#define gsSPBranchList( dl) gsDma1p( G_DL,dl,0,G_DL_NOPUSH) + +#define gSPSprite2DBase(pkt, s) gDma1p(pkt, G_SPRITE2D_BASE, s, sizeof(uSprite), 0) +#define gsSPSprite2DBase(s) gsDma1p(G_SPRITE2D_BASE, s, sizeof(uSprite), 0) + +/* + * RSP short command (no DMA required) macros + */ +#define gImmp0(pkt, c) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ +} + +#define gsImmp0(c) \ +{{ \ + _SHIFTL((c), 24, 8) \ +}} + +#define gImmp1(pkt, c, p0) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ + _g->words.w1 = (uintptr_t)(p0); \ +} + +#define gsImmp1(c, p0) \ +{{ \ + _SHIFTL((c), 24, 8), (uintptr_t)(p0) \ +}} + +#define gImmp2(pkt, c, p0, p1) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ + _g->words.w1 = _SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8); \ +} + +#define gsImmp2(c, p0, p1) \ +{{ \ + _SHIFTL((c), 24, 8), _SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8)\ +}} + +#define gImmp3(pkt, c, p0, p1, p2) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL((c), 24, 8); \ + _g->words.w1 = (_SHIFTL((p0), 16, 16) | _SHIFTL((p1), 8, 8) | \ + _SHIFTL((p2), 0, 8)); \ +} + +#define gsImmp3(c, p0, p1, p2) \ +{{ \ + _SHIFTL((c), 24, 8), (_SHIFTL((p0), 16, 16) | \ + _SHIFTL((p1), 8, 8) | _SHIFTL((p2), 0, 8))\ +}} + +#define gImmp21(pkt, c, p0, p1, dat) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | \ + _SHIFTL((p1), 0, 8)); \ + _g->words.w1 = (uintptr_t) (dat); \ +} + +#define gsImmp21(c, p0, p1, dat) \ +{{ \ + _SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | _SHIFTL((p1), 0, 8),\ + (uintptr_t) (dat) \ +}} + +#ifdef F3DEX_GBI_2 +#define gMoveWd(pkt, index, offset, data) \ + gDma1p((pkt), G_MOVEWORD, data, offset, index) +#define gsMoveWd( index, offset, data) \ + gsDma1p( G_MOVEWORD, data, offset, index) +#else /* F3DEX_GBI_2 */ +#define gMoveWd(pkt, index, offset, data) \ + gImmp21((pkt), G_MOVEWORD, offset, index, data) +#define gsMoveWd( index, offset, data) \ + gsImmp21( G_MOVEWORD, offset, index, data) +#endif /* F3DEX_GBI_2 */ + +/* Sprite immediate macros, there is also a sprite dma macro above */ + +#define gSPSprite2DScaleFlip(pkt, sx, sy, fx, fy) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SPRITE2D_SCALEFLIP, 24, 8) | \ + _SHIFTL((fx), 8, 8) | \ + _SHIFTL((fy), 0, 8)); \ + _g->words.w1 = (_SHIFTL((sx), 16, 16) | \ + _SHIFTL((sy), 0, 16)); \ +} + +#define gsSPSprite2DScaleFlip(sx, sy, fx, fy) \ +{{ \ + (_SHIFTL(G_SPRITE2D_SCALEFLIP, 24, 8) | \ + _SHIFTL((fx), 8, 8) | \ + _SHIFTL((fy), 0, 8)), \ + (_SHIFTL((sx), 16, 16) | \ + _SHIFTL((sy), 0, 16)) \ +}} + +#define gSPSprite2DDraw(pkt, px, py) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SPRITE2D_DRAW, 24, 8)); \ + _g->words.w1 = (_SHIFTL((px), 16, 16) | \ + _SHIFTL((py), 0, 16)); \ +} + +#define gsSPSprite2DDraw(px, py) \ +{{ \ + (_SHIFTL(G_SPRITE2D_DRAW, 24, 8)), \ + (_SHIFTL((px), 16, 16) | \ + _SHIFTL((py), 0, 16)) \ +}} + + +/* + * Note: the SP1Triangle() and line macros multiply the vertex indices + * by 10, this is an optimization for the microcode. + */ +#if (defined(F3DLP_GBI)||defined(F3DEX_GBI)) +# define __gsSP1Triangle_w1(v0, v1, v2) \ + (_SHIFTL((v0)*2,16,8)|_SHIFTL((v1)*2,8,8)|_SHIFTL((v2)*2,0,8)) +# define __gsSP1Triangle_w1f(v0, v1, v2, flag) \ + (((flag) == 0) ? __gsSP1Triangle_w1(v0, v1, v2): \ + ((flag) == 1) ? __gsSP1Triangle_w1(v1, v2, v0): \ + __gsSP1Triangle_w1(v2, v0, v1)) +# define __gsSPLine3D_w1(v0, v1, wd) \ + (_SHIFTL((v0)*2,16,8)|_SHIFT((v1)*2,8,8)|_SHIFT((wd),0,8)) +# define __gsSPLine3D_w1f(v0, v1, wd, flag) \ + (((flag) == 0) ? __gsSPLine3D_w1(v0, v1, wd): \ + __gsSPLine3D_w1(v1, v0, wd)) +# define __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag) \ + (((flag) == 0) ? __gsSP1Triangle_w1(v0, v1, v2): \ + ((flag) == 1) ? __gsSP1Triangle_w1(v1, v2, v3): \ + ((flag) == 2) ? __gsSP1Triangle_w1(v2, v3, v0): \ + __gsSP1Triangle_w1(v3, v0, v1)) +# define __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ + (((flag) == 0) ? __gsSP1Triangle_w1(v0, v2, v3): \ + ((flag) == 1) ? __gsSP1Triangle_w1(v1, v3, v0): \ + ((flag) == 2) ? __gsSP1Triangle_w1(v2, v0, v1): \ + __gsSP1Triangle_w1(v3, v1, v2)) +#else +# define __gsSP1Triangle_w1f(v0, v1, v2, flag) \ + (_SHIFTL((flag), 24,8)|_SHIFTL((v0)*10,16,8)| \ + _SHIFTL((v1)*10, 8,8)|_SHIFTL((v2)*10, 0,8)) +# define __gsSPLine3D_w1f(v0, v1, wd, flag) \ + (_SHIFTL((flag), 24,8)|_SHIFTL((v0)*10,16,8)| \ + _SHIFTL((v1)*10, 8,8)|_SHIFTL((wd), 0,8)) +#endif + +#ifdef F3DEX_GBI_2 +/*** + *** 1 Triangle + ***/ +#define gSP1Triangle(pkt, v0, v1, v2, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_TRI1, 24, 8)| \ + __gsSP1Triangle_w1f(v0, v1, v2, flag); \ + _g->words.w1 = 0; \ +} +#define gsSP1Triangle(v0, v1, v2, flag) \ +{{ \ + _SHIFTL(G_TRI1, 24, 8)|__gsSP1Triangle_w1f(v0, v1, v2, flag), \ + 0 \ +}} + +/*** + *** Line + ***/ +#define gSPLine3D(pkt, v0, v1, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8)| \ + __gsSPLine3D_w1f(v0, v1, 0, flag); \ + _g->words.w1 = 0; \ +} +#define gsSPLine3D(v0, v1, flag) \ +{{ \ + _SHIFTL(G_LINE3D, 24, 8)|__gsSPLine3D_w1f(v0, v1, 0, flag), \ + 0 \ +}} + +/*** + *** LineW + ***/ +/* these macros are the same as SPLine3D, except they have an + * additional parameter for width. The width is added to the "minimum" + * thickness, which is 1.5 pixels. The units for width are in + * half-pixel units, so a width of 1 translates to (.5 + 1.5) or + * a 2.0 pixels wide line. + */ +#define gSPLineW3D(pkt, v0, v1, wd, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8)| \ + __gsSPLine3D_w1f(v0, v1, wd, flag); \ + _g->words.w1 = 0; \ +} +#define gsSPLineW3D(v0, v1, wd, flag) \ +{{ \ + _SHIFTL(G_LINE3D, 24, 8)|__gsSPLine3D_w1f(v0, v1, wd, flag), \ + 0 \ +}} + +/*** + *** 1 Quadrangle + ***/ +#define gSP1Quadrangle(pkt, v0, v1, v2, v3, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_QUAD, 24, 8)| \ + __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)); \ + _g->words.w1 = __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag); \ +} + +#define gsSP1Quadrangle(v0, v1, v2, v3, flag) \ +{{ \ + (_SHIFTL(G_QUAD, 24, 8)| \ + __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)), \ + __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ +}} +#else /* F3DEX_GBI_2 */ + +/*** + *** 1 Triangle + ***/ +#define gSP1Triangle(pkt, v0, v1, v2, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_TRI1, 24, 8); \ + _g->words.w1 = __gsSP1Triangle_w1f(v0, v1, v2, flag); \ +} +#define gsSP1Triangle(v0, v1, v2, flag) \ +{{ \ + _SHIFTL(G_TRI1, 24, 8), \ + __gsSP1Triangle_w1f(v0, v1, v2, flag) \ +}} + +/*** + *** Line + ***/ +#define gSPLine3D(pkt, v0, v1, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8); \ + _g->words.w1 = __gsSPLine3D_w1f(v0, v1, 0, flag); \ +} +#define gsSPLine3D(v0, v1, flag) \ +{{ \ + _SHIFTL(G_LINE3D, 24, 8), \ + __gsSPLine3D_w1f(v0, v1, 0, flag) \ +}} + +/*** + *** LineW + ***/ +/* these macros are the same as SPLine3D, except they have an + * additional parameter for width. The width is added to the "minimum" + * thickness, which is 1.5 pixels. The units for width are in + * half-pixel units, so a width of 1 translates to (.5 + 1.5) or + * a 2.0 pixels wide line. + */ +#define gSPLineW3D(pkt, v0, v1, wd, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_LINE3D, 24, 8); \ + _g->words.w1 = __gsSPLine3D_w1f(v0, v1, wd, flag); \ +} +#define gsSPLineW3D(v0, v1, wd, flag) \ +{{ \ + _SHIFTL(G_LINE3D, 24, 8), \ + __gsSPLine3D_w1f(v0, v1, wd, flag) \ +}} + +/*** + *** 1 Quadrangle + ***/ +#define gSP1Quadrangle(pkt, v0, v1, v2, v3, flag) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TRI2, 24, 8)| \ + __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)); \ + _g->words.w1 = __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag); \ +} + +#define gsSP1Quadrangle(v0, v1, v2, v3, flag) \ +{{ \ + (_SHIFTL(G_TRI2, 24, 8)| \ + __gsSP1Quadrangle_w1f(v0, v1, v2, v3, flag)), \ + __gsSP1Quadrangle_w2f(v0, v1, v2, v3, flag) \ +}} +#endif /* F3DEX_GBI_2 */ + +#if (defined(F3DLP_GBI)||defined(F3DEX_GBI)) +/*** + *** 2 Triangles + ***/ +#define gSP2Triangles(pkt, v00, v01, v02, flag0, v10, v11, v12, flag1) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TRI2, 24, 8)| \ + __gsSP1Triangle_w1f(v00, v01, v02, flag0)); \ + _g->words.w1 = __gsSP1Triangle_w1f(v10, v11, v12, flag1); \ +} + +#define gsSP2Triangles(v00, v01, v02, flag0, v10, v11, v12, flag1) \ +{{ \ + (_SHIFTL(G_TRI2, 24, 8)| \ + __gsSP1Triangle_w1f(v00, v01, v02, flag0)), \ + __gsSP1Triangle_w1f(v10, v11, v12, flag1) \ +}} +#else +#define gSP2Triangles(pkt, v00, v01, v02, flag0, v10, v11, v12, flag1) \ +{ \ + gSP1Triangle(pkt, v00, v01, v02, flag0); \ + gSP1Triangle(pkt, v10, v11, v12, flag1); \ +} +#define gsSP2Triangles(v00, v01, v02, flag0, v10, v11, v12, flag1) \ + gsSP1Triangle(v00, v01, v02, flag0), \ + gsSP1Triangle(v10, v11, v12, flag1) +#endif /* F3DEX_GBI/F3DLP_GBI */ + +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +#define gSPCullDisplayList(pkt,vstart,vend) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | \ + _SHIFTL((vstart)*2, 0, 16); \ + _g->words.w1 = _SHIFTL((vend)*2, 0, 16); \ +} + +#define gsSPCullDisplayList(vstart,vend) \ +{{ \ + _SHIFTL(G_CULLDL, 24, 8) | _SHIFTL((vstart)*2, 0, 16), \ + _SHIFTL((vend)*2, 0, 16) \ +}} + +#else +#define gSPCullDisplayList(pkt,vstart,vend) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | \ + ((0x0f & (vstart))*40); \ + _g->words.w1 = (unsigned int)((0x0f & ((vend)+1))*40); \ +} + +#define gsSPCullDisplayList(vstart,vend) \ +{{ \ + _SHIFTL(G_CULLDL, 24, 8) | ((0x0f & (vstart))*40), \ + ((0x0f & ((vend)+1))*40) \ +}} +#endif + +#define gSPSegment(pkt, segment, base) \ + gMoveWd(pkt, G_MW_SEGMENT, (segment)*4, base) +#define gsSPSegment(segment, base) \ + gsMoveWd( G_MW_SEGMENT, (segment)*4, base) + +/* + * Clipping Macros + */ +#define FR_NEG_FRUSTRATIO_1 0x00000001 +#define FR_POS_FRUSTRATIO_1 0x0000ffff +#define FR_NEG_FRUSTRATIO_2 0x00000002 +#define FR_POS_FRUSTRATIO_2 0x0000fffe +#define FR_NEG_FRUSTRATIO_3 0x00000003 +#define FR_POS_FRUSTRATIO_3 0x0000fffd +#define FR_NEG_FRUSTRATIO_4 0x00000004 +#define FR_POS_FRUSTRATIO_4 0x0000fffc +#define FR_NEG_FRUSTRATIO_5 0x00000005 +#define FR_POS_FRUSTRATIO_5 0x0000fffb +#define FR_NEG_FRUSTRATIO_6 0x00000006 +#define FR_POS_FRUSTRATIO_6 0x0000fffa +/* + * r should be one of: FRUSTRATIO_1, FRUSTRATIO_2, FRUSTRATIO_3, ... FRUSTRATIO_6 + */ +#define gSPClipRatio(pkt, r) \ +{ \ + gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RNX, FR_NEG_##r); \ + gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RNY, FR_NEG_##r); \ + gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RPX, FR_POS_##r); \ + gMoveWd(pkt, G_MW_CLIP, G_MWO_CLIP_RPY, FR_POS_##r); \ +} + +#define gsSPClipRatio(r) \ + gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RNX, FR_NEG_##r), \ + gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RNY, FR_NEG_##r), \ + gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RPX, FR_POS_##r), \ + gsMoveWd(G_MW_CLIP, G_MWO_CLIP_RPY, FR_POS_##r) + +/* + * Insert values into Matrix + * + * where = element of matrix (byte offset) + * num = new element (32 bit value replacing 2 int or 2 frac matrix + * componants + */ +#ifdef F3DEX_GBI_2 +#define gSPInsertMatrix(pkt, where, num) \ + ERROR!! gSPInsertMatrix is no longer supported. +#define gsSPInsertMatrix(where, num) \ + ERROR!! gsSPInsertMatrix is no longer supported. +#else +#define gSPInsertMatrix(pkt, where, num) \ + gMoveWd(pkt, G_MW_MATRIX, where, num) +#define gsSPInsertMatrix(where, num) \ + gsMoveWd(G_MW_MATRIX, where, num) +#endif + +/* + * Load new matrix directly + * + * mptr = pointer to matrix + */ +#ifdef F3DEX_GBI_2 +#define gSPForceMatrix(pkt, mptr) \ +{ gDma2p((pkt),G_MOVEMEM,(mptr),sizeof(Mtx),G_MV_MATRIX,0); \ + gMoveWd((pkt), G_MW_FORCEMTX,0,0x00010000); \ +} +#define gsSPForceMatrix(mptr) \ + gsDma2p(G_MOVEMEM,(mptr),sizeof(Mtx),G_MV_MATRIX,0), \ + gsMoveWd(G_MW_FORCEMTX,0,0x00010000) + +#else /* F3DEX_GBI_2 */ +#define gSPForceMatrix(pkt, mptr) \ +{ \ + gDma1p(pkt, G_MOVEMEM, mptr, 16, G_MV_MATRIX_1); \ + gDma1p(pkt, G_MOVEMEM, (char *)(mptr)+16, 16, G_MV_MATRIX_2); \ + gDma1p(pkt, G_MOVEMEM, (char *)(mptr)+32, 16, G_MV_MATRIX_3); \ + gDma1p(pkt, G_MOVEMEM, (char *)(mptr)+48, 16, G_MV_MATRIX_4); \ +} +#define gsSPForceMatrix(mptr) \ + gsDma1p( G_MOVEMEM, mptr, 16, G_MV_MATRIX_1), \ + gsDma1p( G_MOVEMEM, (char *)(mptr)+16, 16, G_MV_MATRIX_2), \ + gsDma1p( G_MOVEMEM, (char *)(mptr)+32, 16, G_MV_MATRIX_3), \ + gsDma1p( G_MOVEMEM, (char *)(mptr)+48, 16, G_MV_MATRIX_4) +#endif /* F3DEX_GBI_2 */ + +/* + * Insert values into Points + * + * point = point number 0-15 + * where = which element of point to modify (byte offset into point) + * num = new value (32 bit) + */ +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +# define gSPModifyVertex(pkt, vtx, where, val) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_MODIFYVTX,24,8)| \ + _SHIFTL((where),16,8)|_SHIFTL((vtx)*2,0,16)); \ + _g->words.w1 = (unsigned int)(val); \ +} +# define gsSPModifyVertex(vtx, where, val) \ +{{ \ + _SHIFTL(G_MODIFYVTX,24,8)| \ + _SHIFTL((where),16,8)|_SHIFTL((vtx)*2,0,16), \ + (unsigned int)(val) \ +}} +#else +# define gSPModifyVertex(pkt, vtx, where, val) \ + gMoveWd(pkt, G_MW_POINTS, (vtx)*40+(where), val) +# define gsSPModifyVertex(vtx, where, val) \ + gsMoveWd(G_MW_POINTS, (vtx)*40+(where), val) +#endif + +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)) +/* + * gSPBranchLessZ Branch DL if (vtx.z) less than or equal (zval). + * + * dl = DL branch to + * vtx = Vertex + * zval = Screen depth + * near = Near plane + * far = Far plane + * flag = G_BZ_PERSP or G_BZ_ORTHO + */ + +#define G_BZ_PERSP 0 +#define G_BZ_ORTHO 1 + +#define G_DEPTOZSrg(zval, near, far, flag, zmin, zmax) \ +(((unsigned int)FTOFIX32(((flag) == G_BZ_PERSP ? \ + (1.0f-(float)(near)/(float)(zval)) / \ + (1.0f-(float)(near)/(float)(far )) : \ + ((float)(zval) - (float)(near)) / \ + ((float)(far ) - (float)(near))))) * \ + (((int)((zmax) - (zmin)))&~1) + (int)FTOFIX32(zmin)) + +#define G_DEPTOZS(zval, near, far, flag) \ + G_DEPTOZSrg(zval, near, far, flag, 0, G_MAXZ) + +#define gSPBranchLessZrg(pkt, dl, vtx, zval, near, far, flag, zmin, zmax) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ + _g->words.w1 = (uintptr_t)(dl); \ + _g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_BRANCH_Z,24,8)| \ + _SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12)); \ + _g->words.w1 = G_DEPTOZSrg(zval, near, far, flag, zmin, zmax); \ +} + +#define gsSPBranchLessZrg(dl, vtx, zval, near, far, flag, zmin, zmax) \ +{{ _SHIFTL(G_RDPHALF_1,24,8), \ + (uintptr_t)(dl), }}, \ +{{ _SHIFTL(G_BRANCH_Z,24,8)|_SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12),\ + G_DEPTOZSrg(zval, near, far, flag, zmin, zmax), }} + +#define gSPBranchLessZ(pkt, dl, vtx, zval, near, far, flag) \ + gSPBranchLessZrg(pkt, dl, vtx, zval, near, far, flag, 0, G_MAXZ) +#define gsSPBranchLessZ(dl, vtx, zval, near, far, flag) \ + gsSPBranchLessZrg(dl, vtx, zval, near, far, flag, 0, G_MAXZ) + +/* + * gSPBranchLessZraw Branch DL if (vtx.z) less than or equal (raw zval). + * + * dl = DL branch to + * vtx = Vertex + * zval = Raw value of screen depth + */ +#define gSPBranchLessZraw(pkt, dl, vtx, zval) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ + _g->words.w1 = (uintptr_t)(dl); \ + _g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_BRANCH_Z,24,8)| \ + _SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12)); \ + _g->words.w1 = (unsigned int)(zval); \ +} + +#define gsSPBranchLessZraw(dl, vtx, zval) \ +{{ _SHIFTL(G_RDPHALF_1,24,8), \ + (uintptr_t)(dl), }}, \ +{{ _SHIFTL(G_BRANCH_Z,24,8)|_SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12),\ + (unsigned int)(zval), }} + +/* + * gSPLoadUcode RSP loads specified ucode. + * + * uc_start = ucode text section start + * uc_dstart = ucode data section start + */ +#define gSPLoadUcodeEx(pkt, uc_start, uc_dstart, uc_dsize) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ + _g->words.w1 = (uintptr_t)(uc_dstart); \ + _g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(G_LOAD_UCODE,24,8)| \ + _SHIFTL((int)(uc_dsize)-1,0,16)); \ + _g->words.w1 = (uintptr_t)(uc_start); \ +} + +#define gsSPLoadUcodeEx(uc_start, uc_dstart, uc_dsize) \ +{{ _SHIFTL(G_RDPHALF_1,24,8), \ + (uintptr_t)(uc_dstart), }}, \ +{{ _SHIFTL(G_LOAD_UCODE,24,8)| \ + _SHIFTL((int)(uc_dsize)-1,0,16), \ + (uintptr_t)(uc_start), }} + +#define gSPLoadUcode(pkt, uc_start, uc_dstart) \ + gSPLoadUcodeEx((pkt), (uc_start), (uc_dstart), SP_UCODE_DATA_SIZE) +#define gsSPLoadUcode(uc_start, uc_dstart) \ + gsSPLoadUcodeEx((uc_start), (uc_dstart), SP_UCODE_DATA_SIZE) + +#define gSPLoadUcodeL(pkt, ucode) \ + gSPLoadUcode((pkt), OS_K0_TO_PHYSICAL(&ucode##TextStart), \ + OS_K0_TO_PHYSICAL(&ucode##DataStart)) +#define gsSPLoadUcodeL(ucode) \ + gsSPLoadUcode(OS_K0_TO_PHYSICAL(&ucode##TextStart), \ + OS_K0_TO_PHYSICAL(&ucode##DataStart)) +#endif + +#ifdef F3DEX_GBI_2 +/* + * gSPDma_io DMA to/from DMEM/IMEM for DEBUG. + */ +#define gSPDma_io(pkt, flag, dmem, dram, size) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = _SHIFTL(G_DMA_IO,24,8)|_SHIFTL((flag),23,1)| \ + _SHIFTL((dmem)/8,13,10)|_SHIFTL((size)-1,0,12); \ + _g->words.w1 = (uintptr_t)(dram); \ +} + +#define gsSPDma_io(flag, dmem, dram, size) \ +{{ \ + _SHIFTL(G_DMA_IO,24,8)|_SHIFTL((flag),23,1)| \ + _SHIFTL((dmem)/8,13,10)|_SHIFTL((size)-1,0,12), \ + (uintptr_t)(dram) \ +}} + +#define gSPDmaRead(pkt,dmem,dram,size) gSPDma_io((pkt),0,(dmem),(dram),(size)) +#define gsSPDmaRead(dmem,dram,size) gsSPDma_io(0,(dmem),(dram),(size)) +#define gSPDmaWrite(pkt,dmem,dram,size) gSPDma_io((pkt),1,(dmem),(dram),(size)) +#define gsSPDmaWrite(dmem,dram,size) gsSPDma_io(1,(dmem),(dram),(size)) +#endif + +/* + * Lighting Macros + */ +#ifdef F3DEX_GBI_2 +# define NUML(n) ((n)*24) +#else +# define NUML(n) (((n)+1)*32 + 0x80000000) +#endif +#define NUMLIGHTS_0 1 +#define NUMLIGHTS_1 1 +#define NUMLIGHTS_2 2 +#define NUMLIGHTS_3 3 +#define NUMLIGHTS_4 4 +#define NUMLIGHTS_5 5 +#define NUMLIGHTS_6 6 +#define NUMLIGHTS_7 7 +/* + * n should be one of: NUMLIGHTS_0, NUMLIGHTS_1, ..., NUMLIGHTS_7 + * NOTE: in addition to the number of directional lights specified, + * there is always 1 ambient light + */ +#define gSPNumLights(pkt, n) \ + gMoveWd(pkt, G_MW_NUMLIGHT, G_MWO_NUMLIGHT, NUML(n)) +#define gsSPNumLights(n) \ + gsMoveWd( G_MW_NUMLIGHT, G_MWO_NUMLIGHT, NUML(n)) + +#define LIGHT_1 1 +#define LIGHT_2 2 +#define LIGHT_3 3 +#define LIGHT_4 4 +#define LIGHT_5 5 +#define LIGHT_6 6 +#define LIGHT_7 7 +#define LIGHT_8 8 +/* + * l should point to a Light struct + * n should be one of: LIGHT_1, LIGHT_2, ..., LIGHT_8 + * NOTE: the highest numbered light is always the ambient light (eg if there are + * 3 directional lights defined: gsSPNumLights(NUMLIGHTS_3), then lights + * LIGHT_1 through LIGHT_3 will be the directional lights and light + * LIGHT_4 will be the ambient light. + */ +#ifdef F3DEX_GBI_2 +# define gSPLight(pkt, l, n) \ + gDma2p((pkt),G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,(n)*24+24) +# define gsSPLight(l, n) \ + gsDma2p( G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,(n)*24+24) +#else /* F3DEX_GBI_2 */ +# define gSPLight(pkt, l, n) \ + gDma1p(pkt, G_MOVEMEM, l, sizeof(Light),((n)-1)*2+G_MV_L0) +# define gsSPLight(l, n) \ + gsDma1p( G_MOVEMEM, l, sizeof(Light),((n)-1)*2+G_MV_L0) +#endif /* F3DEX_GBI_2 */ + +/* + * gSPLightColor changes color of light without recalculating light direction + * col is a 32 bit word with r,g,b,a (alpha is ignored) + * n should be one of LIGHT_1, LIGHT_2, ..., LIGHT_8 + */ +#define gSPLightColor(pkt, n, col) \ +{ \ + gMoveWd(pkt, G_MW_LIGHTCOL, G_MWO_a##n, col); \ + gMoveWd(pkt, G_MW_LIGHTCOL, G_MWO_b##n, col); \ +} +#define gsSPLightColor(n, col) \ + gsMoveWd(G_MW_LIGHTCOL, G_MWO_a##n, col), \ + gsMoveWd(G_MW_LIGHTCOL, G_MWO_b##n, col) + +/* These macros use a structure "name" which is init'd with the gdSPDefLights macros*/ + +#define gSPSetLights0(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_0); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.a,2); \ +} +#define gsSPSetLights0(name) \ + gsSPNumLights(NUMLIGHTS_0), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.a,2) + +#define gSPSetLights1(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_1); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.a,2); \ +} +#define gsSPSetLights1(name) \ + gsSPNumLights(NUMLIGHTS_1), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.a,2) + +#define gSPSetLights2(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_2); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.a,3); \ +} +#define gsSPSetLights2(name) \ + gsSPNumLights(NUMLIGHTS_2), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.a,3) + +#define gSPSetLights3(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_3); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.l[2],3); \ + gSPLight(pkt,&name.a,4); \ +} +#define gsSPSetLights3(name) \ + gsSPNumLights(NUMLIGHTS_3), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.l[2],3), \ + gsSPLight(&name.a,4) + +#define gSPSetLights4(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_4); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.l[2],3); \ + gSPLight(pkt,&name.l[3],4); \ + gSPLight(pkt,&name.a,5); \ +} +#define gsSPSetLights4(name) \ + gsSPNumLights(NUMLIGHTS_4), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.l[2],3), \ + gsSPLight(&name.l[3],4), \ + gsSPLight(&name.a,5) + +#define gSPSetLights5(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_5); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.l[2],3); \ + gSPLight(pkt,&name.l[3],4); \ + gSPLight(pkt,&name.l[4],5); \ + gSPLight(pkt,&name.a,6); \ +} + +#define gsSPSetLights5(name) \ + gsSPNumLights(NUMLIGHTS_5), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.l[2],3), \ + gsSPLight(&name.l[3],4), \ + gsSPLight(&name.l[4],5), \ + gsSPLight(&name.a,6) + +#define gSPSetLights6(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_6); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.l[2],3); \ + gSPLight(pkt,&name.l[3],4); \ + gSPLight(pkt,&name.l[4],5); \ + gSPLight(pkt,&name.l[5],6); \ + gSPLight(pkt,&name.a,7); \ +} + +#define gsSPSetLights6(name) \ + gsSPNumLights(NUMLIGHTS_6), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.l[2],3), \ + gsSPLight(&name.l[3],4), \ + gsSPLight(&name.l[4],5), \ + gsSPLight(&name.l[5],6), \ + gsSPLight(&name.a,7) + +#define gSPSetLights7(pkt,name) \ +{ \ + gSPNumLights(pkt,NUMLIGHTS_7); \ + gSPLight(pkt,&name.l[0],1); \ + gSPLight(pkt,&name.l[1],2); \ + gSPLight(pkt,&name.l[2],3); \ + gSPLight(pkt,&name.l[3],4); \ + gSPLight(pkt,&name.l[4],5); \ + gSPLight(pkt,&name.l[5],6); \ + gSPLight(pkt,&name.l[6],7); \ + gSPLight(pkt,&name.a,8); \ +} + +#define gsSPSetLights7(name) \ + gsSPNumLights(NUMLIGHTS_7), \ + gsSPLight(&name.l[0],1), \ + gsSPLight(&name.l[1],2), \ + gsSPLight(&name.l[2],3), \ + gsSPLight(&name.l[3],4), \ + gsSPLight(&name.l[4],5), \ + gsSPLight(&name.l[5],6), \ + gsSPLight(&name.l[6],7), \ + gsSPLight(&name.a,8) + +/* + * Reflection/Hiliting Macros + */ +#ifdef F3DEX_GBI_2 +# define gSPLookAtX(pkt, l) \ + gDma2p((pkt),G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATX) +# define gsSPLookAtX(l) \ + gsDma2p( G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATX) +# define gSPLookAtY(pkt, l) \ + gDma2p((pkt),G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATY) +# define gsSPLookAtY(l) \ + gsDma2p( G_MOVEMEM,(l),sizeof(Light),G_MV_LIGHT,G_MVO_LOOKATY) +#else /* F3DEX_GBI_2 */ +# define gSPLookAtX(pkt, l) \ + gDma1p(pkt, G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATX) +# define gsSPLookAtX(l) \ + gsDma1p( G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATX) +# define gSPLookAtY(pkt, l) \ + gDma1p(pkt, G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATY) +# define gsSPLookAtY(l) \ + gsDma1p( G_MOVEMEM, l, sizeof(Light),G_MV_LOOKATY) +#endif /* F3DEX_GBI_2 */ + +#define gSPLookAt(pkt, la) \ +{ \ + gSPLookAtX(pkt,la) \ + gSPLookAtY(pkt,(char *)(la)+16) \ +} +#define gsSPLookAt(la) \ + gsSPLookAtX(la), \ + gsSPLookAtY((char *)(la)+16) + +#define gDPSetHilite1Tile(pkt, tile, hilite, width, height) \ + gDPSetTileSize(pkt, tile, (hilite)->h.x1 & 0xfff, (hilite)->h.y1 & 0xfff, \ + ((((width)-1)*4)+(hilite)->h.x1) & 0xfff, ((((height)-1)*4)+(hilite)->h.y1) & 0xfff) + +#define gDPSetHilite2Tile(pkt, tile, hilite, width, height) \ + gDPSetTileSize(pkt, tile, (hilite)->h.x2 & 0xfff, (hilite)->h.y2 & 0xfff, \ + ((((width)-1)*4)+(hilite)->h.x2) & 0xfff, ((((height)-1)*4)+(hilite)->h.y2) & 0xfff) + + +/* + * FOG macros + * fm = z multiplier + * fo = z offset + * FOG FORMULA: alpha(fog) = (eyespace z) * fm + fo CLAMPED 0 to 255 + * note: (eyespace z) ranges -1 to 1 + * + * Alternate method of setting fog: + * min, max: range 0 to 1000: 0=nearplane, 1000=farplane + * min is where fog begins (usually less than max and often 0) + * max is where fog is thickest (usually 1000) + * + */ +#define gSPFogFactor(pkt, fm, fo) \ + gMoveWd(pkt, G_MW_FOG, G_MWO_FOG, \ + (_SHIFTL(fm,16,16) | _SHIFTL(fo,0,16))) + +#define gsSPFogFactor(fm, fo) \ + gsMoveWd(G_MW_FOG, G_MWO_FOG, \ + (_SHIFTL(fm,16,16) | _SHIFTL(fo,0,16))) + +#define gSPFogPosition(pkt, min, max) \ + gMoveWd(pkt, G_MW_FOG, G_MWO_FOG, \ + (_SHIFTL((128000/((max)-(min))),16,16) | \ + _SHIFTL(((500-(min))*256/((max)-(min))),0,16))) + +#define gsSPFogPosition(min, max) \ + gsMoveWd(G_MW_FOG, G_MWO_FOG, \ + (_SHIFTL((128000/((max)-(min))),16,16) | \ + _SHIFTL(((500-(min))*256/((max)-(min))),0,16))) + +#ifdef F3DEX_GBI_2 +/* + * Macros to turn texture on/off + */ +# define gSPTexture(pkt, s, t, level, tile, on) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8) | \ + _SHIFTL(BOWTIE_VAL,16,8) | \ + _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | \ + _SHIFTL((on),1,7)); \ + _g->words.w1 = (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)); \ +} +# define gsSPTexture(s, t, level, tile, on) \ +{{ \ + (_SHIFTL(G_TEXTURE,24,8) | _SHIFTL(BOWTIE_VAL,16,8) | \ + _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | _SHIFTL((on),1,7)),\ + (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)) \ +}} +/* + * Different version of SPTexture macro, has an additional parameter + * which is currently reserved in the microcode. + */ +# define gSPTextureL(pkt, s, t, level, xparam, tile, on) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8) | \ + _SHIFTL((xparam),16,8) | \ + _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | \ + _SHIFTL((on),1,7)); \ + _g->words.w1 = (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)); \ +} +# define gsSPTextureL(s, t, level, xparam, tile, on) \ +{{ \ + (_SHIFTL(G_TEXTURE,24,8) | _SHIFTL((xparam),16,8) | \ + _SHIFTL((level),11,3) | _SHIFTL((tile),8,3) | _SHIFTL((on),1,7)),\ + (_SHIFTL((s),16,16) | _SHIFTL((t),0,16)) \ +}} +#else +/* + * Macros to turn texture on/off + */ +# define gSPTexture(pkt, s, t, level, tile, on) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL(BOWTIE_VAL,16,8)|\ + _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)| \ + _SHIFTL((on),0,8)); \ + _g->words.w1 = (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)); \ +} +# define gsSPTexture(s, t, level, tile, on) \ +{{ \ + (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL(BOWTIE_VAL,16,8)| \ + _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)|_SHIFTL((on),0,8)), \ + (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)) \ +}} +/* + * Different version of SPTexture macro, has an additional parameter + * which is currently reserved in the microcode. + */ +# define gSPTextureL(pkt, s, t, level, xparam, tile, on) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL((xparam),16,8)| \ + _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)| \ + _SHIFTL((on),0,8)); \ + _g->words.w1 = (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)); \ +} +# define gsSPTextureL(s, t, level, xparam, tile, on) \ +{{ \ + (_SHIFTL(G_TEXTURE,24,8)|_SHIFTL((xparam),16,8)| \ + _SHIFTL((level),11,3)|_SHIFTL((tile),8,3)|_SHIFTL((on),0,8)), \ + (_SHIFTL((s),16,16)|_SHIFTL((t),0,16)) \ +}} +#endif + +#ifndef F3D_OLD +# define gSPPerspNormalize(pkt, s) gMoveWd(pkt, G_MW_PERSPNORM, 0, (s)) +# define gsSPPerspNormalize(s) gsMoveWd( G_MW_PERSPNORM, 0, (s)) +#else +# define gSPPerspNormalize(pkt, s) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_RDPHALF_1, 24, 8); \ + _g->words.w1 = (s); \ +} +# define gsSPPerspNormalize(s) \ +{{ \ + _SHIFTL(G_RDPHALF_1, 24, 8), \ + (s) \ +}} +#endif + +#ifdef F3DEX_GBI_2 +# define gSPPopMatrixN(pkt, n, num) gDma2p((pkt),G_POPMTX,(num)*64,64,2,0) +# define gsSPPopMatrixN(n, num) gsDma2p( G_POPMTX,(num)*64,64,2,0) +# define gSPPopMatrix(pkt, n) gSPPopMatrixN((pkt), (n), 1) +# define gsSPPopMatrix(n) gsSPPopMatrixN( (n), 1) +#else /* F3DEX_GBI_2 */ +# define gSPPopMatrix(pkt, n) gImmp1(pkt, G_POPMTX, n) +# define gsSPPopMatrix(n) gsImmp1( G_POPMTX, n) +#endif /* F3DEX_GBI_2 */ + +#define gSPEndDisplayList(pkt) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_ENDDL, 24, 8); \ + _g->words.w1 = 0; \ +} + +#define gsSPEndDisplayList() \ +{{ \ + _SHIFTL(G_ENDDL, 24, 8), 0 \ +}} + +#ifdef F3DEX_GBI_2 +/* + * One gSPGeometryMode(pkt,c,s) GBI is equal to these two GBIs. + * + * gSPClearGeometryMode(pkt,c) + * gSPSetGeometryMode(pkt,s) + * + * gSPLoadGeometryMode(pkt, word) sets GeometryMode directly. + */ +#define gSPGeometryMode(pkt, c, s) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = _SHIFTL(G_GEOMETRYMODE,24,8)|_SHIFTL(~(u32)(c),0,24);\ + _g->words.w1 = (u32)(s); \ +} + +#define gsSPGeometryMode(c, s) \ +{{ \ + (_SHIFTL(G_GEOMETRYMODE,24,8)|_SHIFTL(~(u32)(c),0,24)),(u32)(s) \ +}} +#define gSPSetGeometryMode(pkt, word) gSPGeometryMode((pkt),0,(word)) +#define gsSPSetGeometryMode(word) gsSPGeometryMode(0,(word)) +#define gSPClearGeometryMode(pkt, word) gSPGeometryMode((pkt),(word),0) +#define gsSPClearGeometryMode(word) gsSPGeometryMode((word),0) +#define gSPLoadGeometryMode(pkt, word) gSPGeometryMode((pkt),-1,(word)) +#define gsSPLoadGeometryMode(word) gsSPGeometryMode(-1,(word)) +#define gsSPGeometryModeSetFirst(c, s) gsSPGeometryMode(c, s) +#else /* F3DEX_GBI_2 */ +#define gSPSetGeometryMode(pkt, word) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETGEOMETRYMODE, 24, 8); \ + _g->words.w1 = (unsigned int)(word); \ +} + +#define gsSPSetGeometryMode(word) \ +{{ \ + _SHIFTL(G_SETGEOMETRYMODE, 24, 8), (unsigned int)(word) \ +}} + +#define gSPClearGeometryMode(pkt, word) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8); \ + _g->words.w1 = (unsigned int)(word); \ +} + +#define gsSPClearGeometryMode(word) \ +{{ \ + _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8), (unsigned int)(word) \ +}} + +/* + * gsSPGeometryMode + * In Fast3DEX2 it is better to use this, as the RSP geometry mode + * is able to be set and cleared in a single command. + */ +#define gsSPGeometryMode(c, s) \ + gsSPClearGeometryMode(c), \ + gsSPSetGeometryMode(s) +#define gsSPGeometryModeSetFirst(c, s) \ + gsSPSetGeometryMode(s), \ + gsSPClearGeometryMode(c) +#endif /* F3DEX_GBI_2 */ + +#ifdef F3DEX_GBI_2 +#define gSPSetOtherMode(pkt, cmd, sft, len, data) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + _g->words.w0 = (_SHIFTL(cmd,24,8)|_SHIFTL(32-(sft)-(len),8,8)| \ + _SHIFTL((len)-1,0,8)); \ + _g->words.w1 = (unsigned int)(data); \ +} + +#define gsSPSetOtherMode(cmd, sft, len, data) \ +{{ \ + _SHIFTL(cmd,24,8)|_SHIFTL(32-(sft)-(len),8,8)|_SHIFTL((len)-1,0,8), \ + (unsigned int)(data) \ +}} +#else +#define gSPSetOtherMode(pkt, cmd, sft, len, data) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | \ + _SHIFTL(len, 0, 8)); \ + _g->words.w1 = (unsigned int)(data); \ +} + +#define gsSPSetOtherMode(cmd, sft, len, data) \ +{{ \ + _SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | _SHIFTL(len, 0, 8), \ + (unsigned int)(data) \ +}} +#endif + +/* + * RDP setothermode register commands - register shadowed in RSP + */ +#define gDPPipelineMode(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_PIPELINE, 1, mode) +#define gsDPPipelineMode(mode) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_PIPELINE, 1, mode) + +#define gDPSetCycleType(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_CYCLETYPE, 2, type) +#define gsDPSetCycleType(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_CYCLETYPE, 2, type) + +#define gDPSetTexturePersp(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTPERSP, 1, type) +#define gsDPSetTexturePersp(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTPERSP, 1, type) + +#define gDPSetTextureDetail(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTDETAIL, 2, type) +#define gsDPSetTextureDetail(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTDETAIL, 2, type) + +#define gDPSetTextureLOD(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTLOD, 1, type) +#define gsDPSetTextureLOD(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTLOD, 1, type) + +#define gDPSetTextureLUT(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTLUT, 2, type) +#define gsDPSetTextureLUT(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTLUT, 2, type) + +#define gDPSetTextureFilter(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTFILT, 2, type) +#define gsDPSetTextureFilter(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTFILT, 2, type) + +#define gDPSetTextureConvert(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_TEXTCONV, 3, type) +#define gsDPSetTextureConvert(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_TEXTCONV, 3, type) + +#define gDPSetCombineKey(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_COMBKEY, 1, type) +#define gsDPSetCombineKey(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_COMBKEY, 1, type) + +#ifndef _HW_VERSION_1 +#define gDPSetColorDither(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_RGBDITHER, 2, mode) +#define gsDPSetColorDither(mode) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_RGBDITHER, 2, mode) +#else +#define gDPSetColorDither(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_COLORDITHER, 1, mode) +#define gsDPSetColorDither(mode) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_COLORDITHER, 1, mode) +#endif + +#ifndef _HW_VERSION_1 +#define gDPSetAlphaDither(pkt, mode) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode) +#define gsDPSetAlphaDither(mode) \ + gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode) +#endif + +/* 'blendmask' is not supported anymore. + * The bits are reserved for future use. + * Fri May 26 13:45:55 PDT 1995 + */ +#define gDPSetBlendMask(pkt, mask) gDPNoOp(pkt) +#define gsDPSetBlendMask(mask) gsDPNoOp() + +#define gDPSetAlphaCompare(pkt, type) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_ALPHACOMPARE, 2, type) +#define gsDPSetAlphaCompare(type) \ + gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_ALPHACOMPARE, 2, type) + +#define gDPSetDepthSource(pkt, src) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_ZSRCSEL, 1, src) +#define gsDPSetDepthSource(src) \ + gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_ZSRCSEL, 1, src) + +#define gDPSetRenderMode(pkt, c0, c1) \ + gSPSetOtherMode(pkt, G_SETOTHERMODE_L, G_MDSFT_RENDERMODE, 29, \ + (c0) | (c1)) +#define gsDPSetRenderMode(c0, c1) \ + gsSPSetOtherMode(G_SETOTHERMODE_L, G_MDSFT_RENDERMODE, 29, \ + (c0) | (c1)) + +#define gSetImage(pkt, cmd, fmt, siz, width, i) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \ + _SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12); \ + _g->words.w1 = (uintptr_t)(i); \ +} + +#define gsSetImage(cmd, fmt, siz, width, i) \ +{{ \ + _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \ + _SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12), \ + (uintptr_t)(i) \ +}} + +#define gDPSetColorImage(pkt, f, s, w, i) gSetImage(pkt, G_SETCIMG, f, s, w, i) +#define gsDPSetColorImage(f, s, w, i) gsSetImage(G_SETCIMG, f, s, w, i) + + +/* use these for new code */ +#define gDPSetDepthImage(pkt, i) gSetImage(pkt, G_SETZIMG, 0, 0, 1, i) +#define gsDPSetDepthImage(i) gsSetImage(G_SETZIMG, 0, 0, 1, i) +/* kept for compatibility */ +#define gDPSetMaskImage(pkt, i) gDPSetDepthImage(pkt, i) +#define gsDPSetMaskImage(i) gsDPSetDepthImage(i) + +#define gDPSetTextureImage(pkt, f, s, w, i) gSetImage(pkt, G_SETTIMG, f, s, w, i) +#define gsDPSetTextureImage(f, s, w, i) gsSetImage(G_SETTIMG, f, s, w, i) + +/* + * RDP macros + */ + +#define gDPSetCombine(pkt, muxs0, muxs1) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24);\ + _g->words.w1 = (unsigned int)(muxs1); \ +} + +#define gsDPSetCombine(muxs0, muxs1) \ +{{ \ + _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24), \ + (unsigned int)(muxs1) \ +}} + +#define GCCc0w0(saRGB0, mRGB0, saA0, mA0) \ + (_SHIFTL((saRGB0), 20, 4) | _SHIFTL((mRGB0), 15, 5) | \ + _SHIFTL((saA0), 12, 3) | _SHIFTL((mA0), 9, 3)) + +#define GCCc1w0(saRGB1, mRGB1) \ + (_SHIFTL((saRGB1), 5, 4) | _SHIFTL((mRGB1), 0, 5)) + +#define GCCc0w1(sbRGB0, aRGB0, sbA0, aA0) \ + (_SHIFTL((sbRGB0), 28, 4) | _SHIFTL((aRGB0), 15, 3) | \ + _SHIFTL((sbA0), 12, 3) | _SHIFTL((aA0), 9, 3)) + +#define GCCc1w1(sbRGB1, saA1, mA1, aRGB1, sbA1, aA1) \ + (_SHIFTL((sbRGB1), 24, 4) | _SHIFTL((saA1), 21, 3) | \ + _SHIFTL((mA1), 18, 3) | _SHIFTL((aRGB1), 6, 3) | \ + _SHIFTL((sbA1), 3, 3) | _SHIFTL((aA1), 0, 3)) + +#define gDPSetCombineLERP(pkt, a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, \ + a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETCOMBINE, 24, 8) | \ + _SHIFTL(GCCc0w0(G_CCMUX_##a0, G_CCMUX_##c0, \ + G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \ + GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), \ + 0, 24); \ + _g->words.w1 = (unsigned int)(GCCc0w1(G_CCMUX_##b0, \ + G_CCMUX_##d0, \ + G_ACMUX_##Ab0, \ + G_ACMUX_##Ad0) | \ + GCCc1w1(G_CCMUX_##b1, \ + G_ACMUX_##Aa1, \ + G_ACMUX_##Ac1, \ + G_CCMUX_##d1, \ + G_ACMUX_##Ab1, \ + G_ACMUX_##Ad1)); \ +} + +#define gsDPSetCombineLERP(a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, \ + a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \ +{{ \ + _SHIFTL(G_SETCOMBINE, 24, 8) | \ + _SHIFTL(GCCc0w0(G_CCMUX_##a0, G_CCMUX_##c0, \ + G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \ + GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), 0, 24), \ + (unsigned int)(GCCc0w1(G_CCMUX_##b0, G_CCMUX_##d0, \ + G_ACMUX_##Ab0, G_ACMUX_##Ad0) | \ + GCCc1w1(G_CCMUX_##b1, G_ACMUX_##Aa1, \ + G_ACMUX_##Ac1, G_CCMUX_##d1, \ + G_ACMUX_##Ab1, G_ACMUX_##Ad1)) \ +}} + +/* + * SetCombineMode macros are NOT redunant. It allow the C preprocessor + * to substitute single parameter which includes commas in the token and + * rescan for higher parameter count macro substitution. + * + * eg. gsDPSetCombineMode(G_CC_MODULATE, G_CC_MODULATE) turns into + * gsDPSetCombineLERP(TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0, + * TEXEL0, 0, SHADE, 0, TEXEL0, 0, SHADE, 0) + */ + +#define gDPSetCombineMode(pkt, a, b) gDPSetCombineLERP(pkt, a, b) +#define gsDPSetCombineMode(a, b) gsDPSetCombineLERP(a, b) + +#define gDPSetColor(pkt, c, d) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(c, 24, 8); \ + _g->words.w1 = (unsigned int)(d); \ +} + +#define gsDPSetColor(c, d) \ +{{ \ + _SHIFTL(c, 24, 8), (unsigned int)(d) \ +}} + +#define DPRGBColor(pkt, cmd, r, g, b, a) \ + gDPSetColor(pkt, cmd, \ + (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | \ + _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8))) +#define sDPRGBColor(cmd, r, g, b, a) \ + gsDPSetColor(cmd, \ + (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | \ + _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8))) + +#define gDPSetEnvColor(pkt, r, g, b, a) \ + DPRGBColor(pkt, G_SETENVCOLOR, r,g,b,a) +#define gsDPSetEnvColor(r, g, b, a) \ + sDPRGBColor(G_SETENVCOLOR, r,g,b,a) +#define gDPSetBlendColor(pkt, r, g, b, a) \ + DPRGBColor(pkt, G_SETBLENDCOLOR, r,g,b,a) +#define gsDPSetBlendColor(r, g, b, a) \ + sDPRGBColor(G_SETBLENDCOLOR, r,g,b,a) +#define gDPSetFogColor(pkt, r, g, b, a) \ + DPRGBColor(pkt, G_SETFOGCOLOR, r,g,b,a) +#define gsDPSetFogColor(r, g, b, a) \ + sDPRGBColor(G_SETFOGCOLOR, r,g,b,a) +#define gDPSetFillColor(pkt, d) \ + gDPSetColor(pkt, G_SETFILLCOLOR, (d)) +#define gsDPSetFillColor(d) \ + gsDPSetColor(G_SETFILLCOLOR, (d)) + +#define gDPSetPrimDepth(pkt, z, dz) \ + gDPSetColor(pkt, G_SETPRIMDEPTH, \ + _SHIFTL(z, 16, 16) | _SHIFTL(dz, 0, 16)) +#define gsDPSetPrimDepth(z, dz) \ + gsDPSetColor(G_SETPRIMDEPTH, _SHIFTL(z, 16, 16) | \ + _SHIFTL(dz, 0, 16)) + +#define gDPSetPrimColor(pkt, m, l, r, g, b, a) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | \ + _SHIFTL(m, 8, 8) | _SHIFTL(l, 0, 8)); \ + _g->words.w1 = (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | \ + _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8)); \ +} + +#define gsDPSetPrimColor(m, l, r, g, b, a) \ +{{ \ + (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | _SHIFTL(m, 8, 8) | \ + _SHIFTL(l, 0, 8)), \ + (_SHIFTL(r, 24, 8) | _SHIFTL(g, 16, 8) | _SHIFTL(b, 8, 8) | \ + _SHIFTL(a, 0, 8)) \ +}} + +/* + * gDPSetOtherMode (This is for expert user.) + * + * This command makes all othermode parameters set. + * Do not use this command in the same DL with another g*SPSetOtherMode DLs. + * + * [Usage] + * gDPSetOtherMode(pkt, modeA, modeB) + * + * 'modeA' is described all parameters of GroupA GBI command. + * 'modeB' is also described all parameters of GroupB GBI command. + * + * GroupA: + * gDPPipelineMode, gDPSetCycleType, gSPSetTexturePersp, + * gDPSetTextureDetail, gDPSetTextureLOD, gDPSetTextureLUT, + * gDPSetTextureFilter, gDPSetTextureConvert, gDPSetCombineKey, + * gDPSetColorDither, gDPSetAlphaDither + * + * GroupB: + * gDPSetAlphaCompare, gDPSetDepthSource, gDPSetRenderMode + * + * Use 'OR' operation to get modeA and modeB. + * + * modeA = G_PM_* | G_CYC_* | G_TP_* | G_TD_* | G_TL_* | G_TT_* | G_TF_* + * G_TC_* | G_CK_* | G_CD_* | G_AD_*; + * + * modeB = G_AC_* | G_ZS_* | G_RM_* | G_RM_*2; + */ +#define gDPSetOtherMode(pkt, mode0, mode1) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24);\ + _g->words.w1 = (unsigned int)(mode1); \ +} + +#define gsDPSetOtherMode(mode0, mode1) \ +{{ \ + _SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24), \ + (unsigned int)(mode1) \ +}} + +/* + * Texturing macros + */ + +/* These are also defined defined above for Sprite Microcode */ + +#define G_TX_LOADTILE 7 +#define G_TX_RENDERTILE 0 + +#define G_TX_NOMIRROR 0 +#define G_TX_WRAP 0 +#define G_TX_MIRROR 0x1 +#define G_TX_CLAMP 0x2 +#define G_TX_NOMASK 0 +#define G_TX_NOLOD 0 + + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +/* + * Dxt is the inverse of the number of 64-bit words in a line of + * the texture being loaded using the load_block command. If + * there are any 1's to the right of the 11th fractional bit, + * dxt should be rounded up. The following macros accomplish + * this. The 4b macros are a special case since 4-bit textures + * are loaded as 8-bit textures. Dxt is fixed point 1.11. RJM + */ +#define G_TX_DXT_FRAC 11 + +/* + * For RCP 2.0, the maximum number of texels that can be loaded + * using a load_block command is 2048. In order to load the total + * 4kB of Tmem, change the texel size when loading to be G_IM_SIZ_16b, + * then change the tile to the proper texel size after the load. + * The g*DPLoadTextureBlock macros already do this, so this change + * will be transparent if you use these macros. If you use + * the g*DPLoadBlock macros directly, you will need to handle this + * tile manipulation yourself. RJM. + */ +#ifdef _HW_VERSION_1 +#define G_TX_LDBLK_MAX_TXL 4095 +#else +#define G_TX_LDBLK_MAX_TXL 2047 +#endif /* _HW_VERSION_1 */ + +#define TXL2WORDS(txls, b_txl) MAX(1, ((txls)*(b_txl)/8)) +#define CALC_DXT(width, b_txl) \ + (((1 << G_TX_DXT_FRAC) + TXL2WORDS(width, b_txl) - 1) / \ + TXL2WORDS(width, b_txl)) + +#define TXL2WORDS_4b(txls) MAX(1, ((txls)/16)) +#define CALC_DXT_4b(width) \ + (((1 << G_TX_DXT_FRAC) + TXL2WORDS_4b(width) - 1) / \ + TXL2WORDS_4b(width)) + +#define gDPLoadTileGeneric(pkt, c, tile, uls, ult, lrs, lrt) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(c, 24, 8) | _SHIFTL(uls, 12, 12) | \ + _SHIFTL(ult, 0, 12); \ + _g->words.w1 = _SHIFTL(tile, 24, 3) | _SHIFTL(lrs, 12, 12) | \ + _SHIFTL(lrt, 0, 12); \ +} + +#define gsDPLoadTileGeneric(c, tile, uls, ult, lrs, lrt) \ +{{ \ + _SHIFTL(c, 24, 8) | _SHIFTL(uls, 12, 12) | _SHIFTL(ult, 0, 12), \ + _SHIFTL(tile, 24, 3) | _SHIFTL(lrs, 12, 12) | _SHIFTL(lrt, 0, 12)\ +}} + +#define gDPSetTileSize(pkt, t, uls, ult, lrs, lrt) \ + gDPLoadTileGeneric(pkt, G_SETTILESIZE, t, uls, ult, lrs, lrt) +#define gsDPSetTileSize(t, uls, ult, lrs, lrt) \ + gsDPLoadTileGeneric(G_SETTILESIZE, t, uls, ult, lrs, lrt) +#define gDPLoadTile(pkt, t, uls, ult, lrs, lrt) \ + gDPLoadTileGeneric(pkt, G_LOADTILE, t, uls, ult, lrs, lrt) +#define gsDPLoadTile(t, uls, ult, lrs, lrt) \ + gsDPLoadTileGeneric(G_LOADTILE, t, uls, ult, lrs, lrt) + +#define gDPSetTile(pkt, fmt, siz, line, tmem, tile, palette, cmt, \ + maskt, shiftt, cms, masks, shifts) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETTILE, 24, 8) | _SHIFTL(fmt, 21, 3) |\ + _SHIFTL(siz, 19, 2) | _SHIFTL(line, 9, 9) | \ + _SHIFTL(tmem, 0, 9); \ + _g->words.w1 = _SHIFTL(tile, 24, 3) | _SHIFTL(palette, 20, 4) | \ + _SHIFTL(cmt, 18, 2) | _SHIFTL(maskt, 14, 4) | \ + _SHIFTL(shiftt, 10, 4) |_SHIFTL(cms, 8, 2) | \ + _SHIFTL(masks, 4, 4) | _SHIFTL(shifts, 0, 4); \ +} + +#define gsDPSetTile(fmt, siz, line, tmem, tile, palette, cmt, \ + maskt, shiftt, cms, masks, shifts) \ +{{ \ + (_SHIFTL(G_SETTILE, 24, 8) | _SHIFTL(fmt, 21, 3) | \ + _SHIFTL(siz, 19, 2) | _SHIFTL(line, 9, 9) | _SHIFTL(tmem, 0, 9)),\ + (_SHIFTL(tile, 24, 3) | _SHIFTL(palette, 20, 4) | \ + _SHIFTL(cmt, 18, 2) | _SHIFTL(maskt, 14, 4) | \ + _SHIFTL(shiftt, 10, 4) | _SHIFTL(cms, 8, 2) | \ + _SHIFTL(masks, 4, 4) | _SHIFTL(shifts, 0, 4)) \ +}} + +/* + * For RCP 2.0, the maximum number of texels that can be loaded + * using a load_block command is 2048. In order to load the total + * 4kB of Tmem, change the texel size when loading to be G_IM_SIZ_16b, + * then change the tile to the proper texel size after the load. + * The g*DPLoadTextureBlock macros already do this, so this change + * will be transparent if you use these macros. If you use + * the g*DPLoadBlock macros directly, you will need to handle this + * tile manipulation yourself. RJM. + */ +#define gDPLoadBlock(pkt, tile, uls, ult, lrs, dxt) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_LOADBLOCK, 24, 8) | \ + _SHIFTL(uls, 12, 12) | _SHIFTL(ult, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | \ + _SHIFTL((MIN(lrs,G_TX_LDBLK_MAX_TXL)), 12, 12) |\ + _SHIFTL(dxt, 0, 12)); \ +} + +#define gsDPLoadBlock(tile, uls, ult, lrs, dxt) \ +{{ \ + (_SHIFTL(G_LOADBLOCK, 24, 8) | _SHIFTL(uls, 12, 12) | \ + _SHIFTL(ult, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | \ + _SHIFTL((MIN(lrs,G_TX_LDBLK_MAX_TXL)), 12, 12) | \ + _SHIFTL(dxt, 0, 12)) \ +}} + +#define gDPLoadTLUTCmd(pkt, tile, count) \ +{ \ + Gfx *_g = (Gfx *)pkt; \ + \ + _g->words.w0 = _SHIFTL(G_LOADTLUT, 24, 8); \ + _g->words.w1 = _SHIFTL((tile), 24, 3) | _SHIFTL((count), 14, 10);\ +} + +#define gsDPLoadTLUTCmd(tile, count) \ +{{ \ + _SHIFTL(G_LOADTLUT, 24, 8), \ + _SHIFTL((tile), 24, 3) | _SHIFTL((count), 14, 10) \ +}} + +#define gDPLoadTextureBlock(pkt, timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT) -1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES)+7)>>3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +#define gDPLoadTextureBlockYuv(pkt, timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT) -1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * 1)+7)>>3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* Load fix rww 27jun95 */ +/* The S at the end means odd lines are already word Swapped */ + +#define gDPLoadTextureBlockS(pkt, timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1,0); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES)+7)>>3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * Allow tmem address and render tile to be specified. + * The S at the end means odd lines are already word Swapped + */ +#define gDPLoadMultiBlockS(pkt, timg, tmem, rtile, fmt, siz, width, \ + height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1,0); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * siz##_LINE_BYTES)+7)>>3, tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + + +#define gDPLoadTextureBlockYuvS(pkt, timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1,0); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, \ + (((width) * 1)+7)>>3, 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * allows tmem address to be specified + */ +#define _gDPLoadTextureBlock(pkt, timg, tmem, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0, cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES)+7)>>3, \ + tmem, G_TX_RENDERTILE, pal, cmt, \ + maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * allows tmem address and render tile to be specified + */ +#define _gDPLoadTextureBlockTile(pkt, timg, tmem, rtile, fmt, siz, width, \ + height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0,\ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES)+7)>>3, \ + tmem, rtile, pal, cmt, \ + maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * allows tmem address and render tile to be specified + */ +#define gDPLoadMultiBlock(pkt, timg, tmem, rtile, fmt, siz, width, \ + height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz##_LOAD_BLOCK, 1, timg); \ + gDPSetTile(pkt, fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0,\ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, siz, (((width) * siz##_LINE_BYTES)+7)>>3, \ + tmem, rtile, pal, cmt, \ + maskt, shiftt, cms, masks, shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +#define gsDPLoadTextureBlock(timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, 0, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, \ + masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +/* Here is the static form of the pre-swapped texture block loading */ +/* See gDPLoadTextureBlockS() for reference. Basically, just don't + calculate DxT, use 0 */ + +#define gsDPLoadTextureBlockS(timg, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, 0 , \ + cmt, maskt,shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, 0 ),\ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +/* + * Allow tmem address to be specified + */ +#define _gsDPLoadTextureBlock(timg, tmem, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES)+7)>>3), tmem, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * Allow tmem address and render_tile to be specified + */ +#define _gsDPLoadTextureBlockTile(timg, tmem, rtile, fmt, siz, width, \ + height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * Allow tmem address and render_tile to be specified, useful when loading + * mutilple tiles at a time. + */ +#define gsDPLoadMultiBlock(timg, tmem, rtile, fmt, siz, width, \ + height, pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, \ + 0 , cmt, maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, \ + CALC_DXT(width, siz##_BYTES)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, \ + ((((width) * siz##_LINE_BYTES)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +/* + * Allows tmem and render tile to be specified. Useful when loading + * several tiles at a time. + * + * Here is the static form of the pre-swapped texture block loading + * See gDPLoadTextureBlockS() for reference. Basically, just don't + * calculate DxT, use 0 + */ + +#define gsDPLoadMultiBlockS(timg, tmem, rtile, fmt, siz, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, siz##_LOAD_BLOCK, 1, timg), \ + gsDPSetTile(fmt, siz##_LOAD_BLOCK, 0, tmem, G_TX_LOADTILE, 0 , \ + cmt, maskt,shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, \ + (((width)*(height) + siz##_INCR) >> siz##_SHIFT)-1, 0 ),\ + gsDPPipeSync(), \ + gsDPSetTile(fmt, siz, ((((width) * siz##_LINE_BYTES)+7)>>3), tmem,\ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +#define gDPLoadTextureBlock_4b(pkt, timg, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, \ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* Load fix rww 27jun95 */ +/* The S at the end means odd lines are already word Swapped */ + +#define gDPLoadTextureBlock_4bS(pkt, timg, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, \ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height)+3)>>2)-1, 0 ); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * 4-bit load block. Useful when loading multiple tiles + */ +#define gDPLoadMultiBlock_4b(pkt, timg, tmem, rtile, fmt, width, height,\ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, \ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +/* + * 4-bit load block. Allows tmem and render tile to be specified. Useful when + * loading multiple tiles. The S means odd lines are already word swapped. + */ +#define gDPLoadMultiBlock_4bS(pkt, timg, tmem, rtile, fmt, width, height,\ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, \ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height)+3)>>2)-1, 0 ); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + + +#define _gDPLoadTextureBlock_4b(pkt, timg, tmem, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, G_IM_SIZ_16b, 1, timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0, \ + cmt, maskt, shiftt, cms, masks, shifts); \ + gDPLoadSync(pkt); \ + gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0, \ + (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) \ +} + +#define gsDPLoadTextureBlock_4b(timg, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0 , cmt, \ + maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +#define gsDPLoadTextureBlock_4bS(timg, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0 , cmt, \ + maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1,0),\ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +/* + * 4-bit load block. Allows tmem address and render tile to be specified. + * Useful when loading multiple tiles. + */ +#define gsDPLoadMultiBlock_4b(timg, tmem, rtile, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0 , cmt, \ + maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * 4-bit load block. Allows tmem address and render tile to be specified. + * Useful when loading multiple tiles. S means odd lines are already swapped. + */ +#define gsDPLoadMultiBlock_4bS(timg, tmem, rtile, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0 , cmt, \ + maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1,0),\ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + + +/* + * Allows tmem address to be specified + */ +#define _gsDPLoadTextureBlock_4b(timg, tmem, fmt, width, height, \ + pal, cms, cmt, masks, maskt, shifts, shiftt) \ + \ + gsDPSetTextureImage(fmt, G_IM_SIZ_16b, 1, timg), \ + gsDPSetTile(fmt, G_IM_SIZ_16b, 0, tmem, G_TX_LOADTILE, 0 , cmt, \ + maskt, shiftt, cms, masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, (((width)*(height)+3)>>2)-1, \ + CALC_DXT_4b(width)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, ((((width)>>1)+7)>>3), tmem, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, \ + ((width)-1) << G_TEXTURE_IMAGE_FRAC, \ + ((height)-1) << G_TEXTURE_IMAGE_FRAC) + +#ifndef _HW_VERSION_1 + +#define gDPLoadTextureTile(pkt, timg, fmt, siz, width, height, \ + uls, ult, lrs, lrt, pal, \ + cms, cmt, masks, maskt, shifts, shiftt) \ +{ \ + gDPSetTextureImage(pkt, fmt, siz, width, timg); \ + gDPSetTile(pkt, fmt, siz, \ + (((((lrs)-(uls)+1) * siz##_TILE_BYTES)+7)>>3), 0, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPLoadSync(pkt); \ + gDPLoadTile( pkt, G_TX_LOADTILE, \ + (uls)<>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, \ + (uls)<>3), tmem, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPLoadSync(pkt); \ + gDPLoadTile( pkt, G_TX_LOADTILE, \ + (uls)<>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, \ + (uls)<>3), 0, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPLoadSync(), \ + gsDPLoadTile( G_TX_LOADTILE, \ + (uls)<>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks,\ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, \ + (uls)<>3), \ + tmem, G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, \ + masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadTile( G_TX_LOADTILE, \ + (uls)<>3), \ + tmem, rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, \ + (uls)<>1), timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_8b, \ + (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPLoadSync(pkt); \ + gDPLoadTile( pkt, G_TX_LOADTILE, \ + (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (ult)<<(G_TEXTURE_IMAGE_FRAC), \ + (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (lrt)<<(G_TEXTURE_IMAGE_FRAC)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, \ + masks, shifts); \ + gDPSetTileSize(pkt, G_TX_RENDERTILE, \ + (uls)<>1), timg); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_8b, \ + (((((lrs)-(uls)+1)>>1)+7)>>3), tmem, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPLoadSync(pkt); \ + gDPLoadTile( pkt, G_TX_LOADTILE, \ + (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (ult)<<(G_TEXTURE_IMAGE_FRAC), \ + (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (lrt)<<(G_TEXTURE_IMAGE_FRAC)); \ + gDPPipeSync(pkt); \ + gDPSetTile(pkt, fmt, G_IM_SIZ_4b, \ + (((((lrs)-(uls)+1)>>1)+7)>>3), tmem, \ + rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts); \ + gDPSetTileSize(pkt, rtile, \ + (uls)<>1), timg), \ + gsDPSetTile(fmt, G_IM_SIZ_8b, (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ + G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPLoadSync(), \ + gsDPLoadTile( G_TX_LOADTILE, \ + (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (ult)<<(G_TEXTURE_IMAGE_FRAC), \ + (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (lrt)<<(G_TEXTURE_IMAGE_FRAC)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, (((((lrs)-(uls)+1)>>1)+7)>>3), 0, \ + G_TX_RENDERTILE, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(G_TX_RENDERTILE, \ + (uls)<>1), timg), \ + gsDPSetTile(fmt, G_IM_SIZ_8b, (((((lrs)-(uls)+1)>>1)+7)>>3), \ + tmem, G_TX_LOADTILE, 0 , cmt, maskt, shiftt, cms, \ + masks, shifts), \ + gsDPLoadSync(), \ + gsDPLoadTile( G_TX_LOADTILE, \ + (uls)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (ult)<<(G_TEXTURE_IMAGE_FRAC), \ + (lrs)<<(G_TEXTURE_IMAGE_FRAC-1), \ + (lrt)<<(G_TEXTURE_IMAGE_FRAC)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt, G_IM_SIZ_4b, (((((lrs)-(uls)+1)>>1)+7)>>3), \ + tmem, rtile, pal, cmt, maskt, shiftt, cms, masks, \ + shifts), \ + gsDPSetTileSize(rtile, \ + (uls)<words.w0 = _SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((float)(ulx)*4.0F), 12, 12) | \ + _SHIFTL((int)((float)(uly)*4.0F), 0, 12); \ + _g->words.w1 = _SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)((float)(lrx)*4.0F), 12, 12) | \ + _SHIFTL((int)((float)(lry)*4.0F), 0, 12); \ +} + + +#define gDPSetScissorFrac(pkt, mode, ulx, uly, lrx, lry) \ +{ \ + Gfx *_g = (Gfx *)pkt; \ + \ + _g->words.w0 = _SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((ulx)), 12, 12) | \ + _SHIFTL((int)((uly)), 0, 12); \ + _g->words.w1 = _SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)((lrx)), 12, 12) | \ + _SHIFTL((int)((lry)), 0, 12); \ +} + +#define gsDPSetScissor(mode, ulx, uly, lrx, lry) \ +{{ \ + _SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((float)(ulx)*4.0F), 12, 12) | \ + _SHIFTL((int)((float)(uly)*4.0F), 0, 12), \ + _SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)((float)(lrx)*4.0F), 12, 12) | \ + _SHIFTL((int)((float)(lry)*4.0F), 0, 12) \ +}} + +#define gsDPSetScissorFrac(mode, ulx, uly, lrx, lry) \ +{{ \ + _SHIFTL(G_SETSCISSOR, 24, 8) | \ + _SHIFTL((int)((ulx)), 12, 12) | \ + _SHIFTL((int)((uly)), 0, 12), \ + _SHIFTL(mode, 24, 2) | \ + _SHIFTL((int)(lrx), 12, 12) | \ + _SHIFTL((int)(lry), 0, 12) \ +}} + +/* Fraction never used in fill */ +#ifdef F3DEX_GBI_2E +#define gDPFillRectangle(pkt, ulx, uly, lrx, lry) \ +{ \ + Gfx *_g0 = (Gfx *)(pkt), *_g1 = (Gfx *)(pkt); \ + _g0->words.w0 = _SHIFTL(G_FILLRECT, 24, 8) | \ + _SHIFTL((lrx), 2, 22); \ + _g0->words.w1 = _SHIFTL((lry), 2, 22); \ + _g1->words.w0 = _SHIFTL((ulx), 2, 22); \ + _g1->words.w1 = _SHIFTL((uly), 2, 22); \ +} +#define gsDPFillRectangle(ulx, uly, lrx, lry) \ +{{ \ + (_SHIFTL(G_FILLRECT, 24, 8) | _SHIFTL((lrx), 2, 22)), \ + _SHIFTL((lry), 2, 22), \ +}}, \ +{{ \ + _SHIFTL((ulx), 2, 22), \ + _SHIFTL((uly), 2, 22), \ +}} +#else +#define gDPFillRectangle(pkt, ulx, uly, lrx, lry) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_FILLRECT, 24, 8) | \ + _SHIFTL((lrx), 14, 10) | _SHIFTL((lry), 2, 10));\ + _g->words.w1 = (_SHIFTL((ulx), 14, 10) | _SHIFTL((uly), 2, 10));\ +} +#define gsDPFillRectangle(ulx, uly, lrx, lry) \ +{{ \ + (_SHIFTL(G_FILLRECT, 24, 8) | _SHIFTL((lrx), 14, 10) | \ + _SHIFTL((lry), 2, 10)), \ + (_SHIFTL((ulx), 14, 10) | _SHIFTL((uly), 2, 10)) \ +}} +#endif + +/* like gDPFillRectangle but accepts negative arguments */ +#ifndef F3DEX_GBI_2E +#define gDPScisFillRectangle(pkt, ulx, uly, lrx, lry) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_FILLRECT, 24, 8) | \ + _SHIFTL(MAX((lrx),0), 14, 10) | \ + _SHIFTL(MAX((lry),0), 2, 10)); \ + _g->words.w1 = (_SHIFTL(MAX((ulx),0), 14, 10) | \ + _SHIFTL(MAX((uly),0), 2, 10)); \ +} +#endif + +#define gDPSetConvert(pkt, k0, k1, k2, k3, k4, k5) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETCONVERT, 24, 8) | \ + _SHIFTL(k0, 13, 9) | _SHIFTL(k1, 4, 9) | \ + _SHIFTR(k2, 5, 4)); \ + _g->words.w1 = (_SHIFTL(k2, 27, 5) | _SHIFTL(k3, 18, 9) | \ + _SHIFTL(k4, 9, 9) | _SHIFTL(k5, 0, 9)); \ +} + +#define gsDPSetConvert(k0, k1, k2, k3, k4, k5) \ +{{ \ + (_SHIFTL(G_SETCONVERT, 24, 8) | \ + _SHIFTL(k0, 13, 9) | _SHIFTL(k1, 4, 9) | _SHIFTR(k2, 5, 4)), \ + (_SHIFTL(k2, 27, 5) | _SHIFTL(k3, 18, 9) | _SHIFTL(k4, 9, 9) | \ + _SHIFTL(k5, 0, 9)) \ +}} + +#define gDPSetKeyR(pkt, cR, sR, wR) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_SETKEYR, 24, 8); \ + _g->words.w1 = (_SHIFTL(wR, 16, 12) | _SHIFTL(cR, 8, 8) | \ + _SHIFTL(sR, 0, 8)); \ +} + +#define gsDPSetKeyR(cR, sR, wR) \ +{{ \ + _SHIFTL(G_SETKEYR, 24, 8), \ + _SHIFTL(wR, 16, 12) | _SHIFTL(cR, 8, 8) | _SHIFTL(sR, 0, 8) \ +}} + +#define gDPSetKeyGB(pkt, cG, sG, wG, cB, sB, wB) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETKEYGB, 24, 8) | \ + _SHIFTL(wG, 12, 12) | _SHIFTL(wB, 0, 12)); \ + _g->words.w1 = (_SHIFTL(cG, 24, 8) | _SHIFTL(sG, 16, 8) | \ + _SHIFTL(cB, 8, 8) | _SHIFTL(sB, 0, 8)); \ +} + +#define gsDPSetKeyGB(cG, sG, wG, cB, sB, wB) \ +{{ \ + (_SHIFTL(G_SETKEYGB, 24, 8) | _SHIFTL(wG, 12, 12) | \ + _SHIFTL(wB, 0, 12)), \ + (_SHIFTL(cG, 24, 8) | _SHIFTL(sG, 16, 8) | _SHIFTL(cB, 8, 8) | \ + _SHIFTL(sB, 0, 8)) \ +}} + +#define gDPNoParam(pkt, cmd) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(cmd, 24, 8); \ + _g->words.w1 = 0; \ +} + +#define gsDPNoParam(cmd) \ +{{ \ + _SHIFTL(cmd, 24, 8), 0 \ +}} + +#define gDPParam(pkt, cmd, param) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = _SHIFTL(cmd, 24, 8); \ + _g->words.w1 = (param); \ +} + +#define gsDPParam(cmd, param) \ +{{ \ + _SHIFTL(cmd, 24, 8), (param) \ +}} + +/* Notice that textured rectangles are 128-bit commands, therefore + * gsDPTextureRectangle() should not be used in display lists + * under normal circumstances (use gsSPTextureRectangle()). + * That is also why there is no gDPTextureRectangle() macros. + */ +#define gsDPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{{ \ + (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)), \ +}}, \ +{{ \ + _SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), \ + _SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) \ +}} + +#define gDPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + if (pkt); \ + _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + _g ++; \ + _g->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ + _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ +} + +#define gsDPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{{ \ + (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)), \ +}}, \ +{{ \ + _SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), \ + _SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) \ +}} + +#define gDPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + if (pkt); \ + _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + _g ++; \ + _g->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ + _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ +} + +#ifdef F3D_OLD +# define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \ + gImmp1(pkt, G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)));\ +} + +#define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ + {{(_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)),\ + (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12))}}, \ + gsImmp1(G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \ + gsImmp1(G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))) + +/* like gSPTextureRectangle but accepts negative position arguments */ +# define gSPScisTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | \ + _SHIFTL(MAX((s16)(xh),0), 12, 12) | \ + _SHIFTL(MAX((s16)(yh),0), 0, 12)); \ + _g->words.w1 = (_SHIFTL((tile), 24, 3) | \ + _SHIFTL(MAX((s16)(xl),0), 12, 12) | \ + _SHIFTL(MAX((s16)(yl),0), 0, 12)); \ + gImmp1(pkt, G_RDPHALF_2, \ + (_SHIFTL(((s) - \ + (((s16)(xl) < 0) ? \ + (((s16)(dsdx) < 0) ? \ + (MAX((((s16)(xl)*(s16)(dsdx))>>7),0)) : \ + (MIN((((s16)(xl)*(s16)(dsdx))>>7),0))) : 0)), \ + 16, 16) | \ + _SHIFTL(((t) - \ + (((yl) < 0) ? \ + (((s16)(dtdy) < 0) ? \ + (MAX((((s16)(yl)*(s16)(dtdy))>>7),0)) : \ + (MIN((((s16)(yl)*(s16)(dtdy))>>7),0))) : 0)), \ + 0, 16))); \ + gImmp1(pkt, G_RDPHALF_CONT, (_SHIFTL((dsdx), 16, 16) | \ + _SHIFTL((dtdy), 0, 16))); \ +} + +# define gsSPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ + {{(_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12))}}, \ + gsImmp1(G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \ + gsImmp1(G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))) + +# define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) |\ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \ + gImmp1(pkt, G_RDPHALF_CONT, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))); \ +} +#elif defined(F3DEX_GBI_2E) +# define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ +{ \ + Gfx *_g0 = (Gfx *)(pkt), *_g1 = (Gfx *)(pkt), *_g2 = (Gfx *)(pkt); \ + \ + _g0->words.w0 = _SHIFTL(G_TEXRECT, 24, 8) | \ + _SHIFTL((xh), 0, 24); \ + _g0->words.w1 = _SHIFTL((yh), 0, 24); \ + _g1->words.w0 = (_SHIFTL(tile, 24, 3) | _SHIFTL((xl), 0, 24)); \ + _g1->words.w1 = _SHIFTL((yl), 0, 24); \ + _g2->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ + _g2->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ +} + +# define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{{ \ + (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL((xh), 0, 24)), \ + _SHIFTL((yh), 0, 24), \ +}}, \ +{{ \ + (_SHIFTL((tile), 24, 3) | _SHIFTL((xl), 0, 24)), \ + _SHIFTL((yl), 0, 24), \ +}}, \ +{{ \ + _SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), \ + _SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) \ +}} + +# define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + Gfx *_g0 = (Gfx *)(pkt), *_g1 = (Gfx *)(pkt), *_g2 = (Gfx *)(pkt); \ + \ + _g0->words.w0 = _SHIFTL(G_TEXRECTFLIP, 24, 8) | \ + _SHIFTL((xh), 0, 24); \ + _g0->words.w1 = _SHIFTL((yh), 0, 24); \ + _g1->words.w0 = (_SHIFTL(tile, 24, 3) | _SHIFTL((xl), 0, 24)); \ + _g1->words.w1 = _SHIFTL((yl), 0, 24); \ + _g2->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ + _g2->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ +} +#else +# define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + gImmp1(pkt, G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \ + gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)));\ +} + +#define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ + {{(_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)),\ + (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12))}}, \ + gsImmp1(G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \ + gsImmp1(G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))) + +/* like gSPTextureRectangle but accepts negative position arguments */ +# define gSPScisTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECT, 24, 8) | \ + _SHIFTL(MAX((s16)(xh),0), 12, 12) | \ + _SHIFTL(MAX((s16)(yh),0), 0, 12)); \ + _g->words.w1 = (_SHIFTL((tile), 24, 3) | \ + _SHIFTL(MAX((s16)(xl),0), 12, 12) | \ + _SHIFTL(MAX((s16)(yl),0), 0, 12)); \ + gImmp1(pkt, G_RDPHALF_1, \ + (_SHIFTL(((s) - \ + (((s16)(xl) < 0) ? \ + (((s16)(dsdx) < 0) ? \ + (MAX((((s16)(xl)*(s16)(dsdx))>>7),0)) : \ + (MIN((((s16)(xl)*(s16)(dsdx))>>7),0))) : 0)), \ + 16, 16) | \ + _SHIFTL(((t) - \ + (((yl) < 0) ? \ + (((s16)(dtdy) < 0) ? \ + (MAX((((s16)(yl)*(s16)(dtdy))>>7),0)) : \ + (MIN((((s16)(yl)*(s16)(dtdy))>>7),0))) : 0)), \ + 0, 16))); \ + gImmp1(pkt, G_RDPHALF_2, (_SHIFTL((dsdx), 16, 16) | \ + _SHIFTL((dtdy), 0, 16))); \ +} + +# define gsSPTextureRectangleFlip(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ + {{(_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) | \ + _SHIFTL(yh, 0, 12)), \ + (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12))}}, \ + gsImmp1(G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))), \ + gsImmp1(G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))) + +# define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_TEXRECTFLIP, 24, 8) | _SHIFTL(xh, 12, 12) |\ + _SHIFTL(yh, 0, 12)); \ + _g->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | \ + _SHIFTL(yl, 0, 12)); \ + gImmp1(pkt, G_RDPHALF_1, (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16))); \ + gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))); \ +} +#endif + +#define gsDPWord(wordhi, wordlo) \ + gsImmp1(G_RDPHALF_1, (uintptr_t)(wordhi)), \ + gsImmp1(G_RDPHALF_2, (uintptr_t)(wordlo)) + +#define gDPWord(pkt, wordhi, wordlo) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + gImmp1(pkt, G_RDPHALF_1, (uintptr_t)(wordhi)); \ + gImmp1(pkt, G_RDPHALF_2, (uintptr_t)(wordlo)); \ +} + +#define gDPFullSync(pkt) gDPNoParam(pkt, G_RDPFULLSYNC) +#define gsDPFullSync() gsDPNoParam(G_RDPFULLSYNC) +#define gDPTileSync(pkt) gDPNoParam(pkt, G_RDPTILESYNC) +#define gsDPTileSync() gsDPNoParam(G_RDPTILESYNC) +#define gDPPipeSync(pkt) gDPNoParam(pkt, G_RDPPIPESYNC) +#define gsDPPipeSync() gsDPNoParam(G_RDPPIPESYNC) +#define gDPLoadSync(pkt) gDPNoParam(pkt, G_RDPLOADSYNC) +#define gsDPLoadSync() gsDPNoParam(G_RDPLOADSYNC) +#define gDPNoOp(pkt) gDPNoParam(pkt, G_NOOP) +#define gsDPNoOp() gsDPNoParam(G_NOOP) +#define gDPNoOpTag(pkt, tag) gDPParam(pkt, G_NOOP, tag) +#define gsDPNoOpTag(tag) gsDPParam(G_NOOP, tag) + +#if defined(F3DZEX_GBI_2) || defined(F3DZEX_NON_GBI_2) || defined(L3DZEX_GBI) +#include "gbi-poslight.h" +#endif + +#endif /* _LANGUAGE_C */ + + +#endif /* _GBI_H_ */ diff --git a/include/n64/PR/ucode.h b/include/n64/PR/ucode.h index 7ca86216f1..1407a3a03d 100644 --- a/include/n64/PR/ucode.h +++ b/include/n64/PR/ucode.h @@ -247,6 +247,13 @@ extern u64 gspL3DZEX2_PosLight_xbusTextStart[], extern u64 gspL3DZEX2_PosLight_xbusDataStart[], gspL3DZEX2_PosLight_xbusDataEnd[]; +/*========== F3DEX3 ==========*/ +/* FIFO version */ +extern u64 gspF3DEX3_fifoTextStart[], + gspF3DEX3_fifoTextEnd[]; +extern u64 gspF3DEX3_fifoDataStart[], + gspF3DEX3_fifoDataEnd[]; + /************************************************************************** * * decomp ucode names diff --git a/lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o b/lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o new file mode 100644 index 0000000000000000000000000000000000000000..bf3d1ecd428410dc431acb1408ea3ffd81d3749a GIT binary patch literal 7728 zcmdTp3sh7`miN8>(%tlX4Gp};Mjj1_8b%w@NSvIZB|vwofOd2eiB8gdR0LEEpyFgA z#9(yS4&Vl($xaeBM#)StF^R?`D}hZ6zSabEq9idV%IHKIV#ZI5VoZ2@U#p{=nR9mc zoIP{S7Sy|St8U$@x^?T;z18(OdASVBz+V#sdMw{oVXp(=0j7p1#)A}k;F&jLRHb$l<9>4CeU3@tmV2@ z^A9_)e9^^-5LqN&aV9`R^J=c!Dykj<+b>kjb=>~MM?f#0l4bQw(2DnfT3rlwaS7-( zkHO@GwZLJ0BCv(7&6R97Qv`ajMRvC^aKZ#?k7~Xks$vTrY8R-c#{zUDG8tk5sM~<8 zL-{?_hIB1P`0}Y@?%i|;$V{=`;ZI~EAa zylQ@tXjuzvhl%}-r~^i!ZPT%J;#r8)G=Scj1uEW!b3P5cx=8kmtbBoY%Ucvah=1_v z2&iAZ3gEbc>x;K+WiR9Y6shuDCMWm>IG<1hZ$~xAKcHTmb#3*4DzZ>yHWoQ>-G)Pr9gh)3Fn7TrT4fl|#QK0<2!Uy;AyrV{z9Y;@kX7sCy zaPKZVK9xP9VCly4*P6on|~jdJQs@yrerXucG+phjK!^Y$WRMO=|Qnoubp7b8Hs zV}Y<@7fyR_o&k@)Xi%N=j7uNxEoXF;IXQ~d=EgzAz%(J z5E#!PJseyp0G^vN=OIu_3+&1{@Jb8qKke`sSUcb}VPk zdV*Gz<+N5p5-nNwajOP8X~n9XX+Z#5vggUPO1XjK0C}e5y%eIK z6mA0TBg7A#0Ig@){&oKZu}pHv=BUI$V8y@4qtlWB zqTA)GO1oo^JR0>!U=w=e(K~lwp95@v)G@>*VDIz*Yz|}l8wVkF-2{k*q3e96aRAf$ zPzQPeLVXWm-&X)ERS>ti82f*R{m)|mJna8I+rRlV=5=hpl&lYzatz_p!mw~@yD^+B zobbzO653 z+bhOLebk8OLN$QrH$s+wYV-al_?BYs9cAyp7V*By!8^8%KK(HOlu z%`cC5xZ`Lu)gI=tHpO0E7Sm<<&L#i}M37jKk<=n9X+;&?X-< zHwX6U4N|NSC&k+1{3h5Z*#x^}v)jo@xg>2PG|;GHv+%xSr5HYyMD@25SuP2@C*qm@ zScmN{8q-@wr}wwhdbyNNEvTVWm(}2TW`~c94E0@Uj~N*KV)%1Wxl=CE7v!SAQ9Bzr zif7B7nH%_G2Eur6;PVU>X-z2z9G(KCRp$*HcdE$l$pwLao+Z0EZ=m0*B}bm<@zRzO;MS zz>}v3V(H2ymIGeOH^!m-ifR3OPtf`vFX8C1sbc#)R1Y+MXF-}@Wu)=jxoLiIDSZP17wQ`r zF|y=Bhxs7xAGz?7_uw%RrnJhd$oa19A)d34^9S;W&KoV{LTB%gh2zPE9&YG@kw+Ok zs;nDjfUqYV?}rVF4P!U9C8I8tg7pF1>rdTNTAjN{RA+Bmr2>06m9;yWp8U#-cV{xq zJk#!cg#r4)e%+8@)zYs1^+O}PmY&>MIuv8(sPDtXp(_TCv^2Xy`}}slXDCYd)X;aT zr^v2m*O1k0CR_VA3|%sqiBB%ZIjteFy=6G3HN?_as>o@|MmVqN^ORQL(gnFbq5;_L z0wm!%u2*cu_Op;A8ZG*#R&(zhdc?U(v7Pi6C$s6;Greu-mv~HHfa1q^R3SU_niwD3 zEyh3Fow%BNyEy|Ov6Abwtp4#$5Eg-^;m6k%KSDPEy2QJHNx$Q|9|%GT`{D>_(T05Z z;#tr=Udg=^Dt`?cwEZ6{eH2|o|3iK7np3f7+ePCT(ZhTRWX$Ii6FXhtVNbx+B)pf= zwn^i7E!ve-DH~<=?+?EzE#|eY$$0l%t4?oqBOEudzI8Dq5%rW!el6@HTE`J+_aqU0 zx`i3d7ayx88nIC1`)mwkViYbGCqlp zFW+Wu`|(d6eGrKL;S{vb4a9s;dz8qiK<|5>uxV`;G-U~u5JkHN4ls)f)x;pS<9&6F zsPT^MdRR+kW~ql+3B+vKgynBMY&4cFIY*>?tDfqo z>ZGO7dTPw(q$y68TKo@6a}YWk*b`tr~Ac^|8jE=j{*pwsUT!8iPi5w2-%Yzc$Cbj|Pf zLwlivuGyIl#zK_!Zyh}&-JP9u&FW-;m5U+>UiXyycQyTa*6U>H>Gjl?dy&dtt*3^n9BNpVC*6rY(U_Vh>3%E1N-vd9 zt*4_`N~H?4SxtL$$dh}Tsc*D^_Rh_rAJ4|}wSwWxf|^ACZgBXjpdq%q1`l4eqn_+6 zJNT7dgML>TiCLd5CF6Qxn)9V8xK3eRZ{ti5h|t72PN5Cgkj>5yKuse4@JnEf4Mg+v z`(FJM=t;ygM}|)u^>p0a+~HHkFgnib9X@R^(bTGf;ZufinwseyKBw1G2mjpgCB2TS zgfEBB84Xlll{-Cjy`Xvk=(x1!fa*o6yX#8`d%#7f$7I7D zZ;Nz#d_L+KLo@g$&>~%i(8qqQ)KAY&{2kU$&&;P8X-&Z_K}9p}>I>e3_P#bIFX*tV zXl;CcFcI&8st9v1SJ2U_SZ~lRXsCU1Zg8AkN9|j@!4$iOCb{#19zjc!y!pX<1vQ;9 zvmiL$uB9{bnu8PUY8otmGngZ=bg2B>;B341)1IKCclFUx^qWT~6wuMuW>S{cKKvE8diWw&H+&}IQS=|%htJsSMH7!PB-bED zGOIA=_(rrM9;vDlt&t+eo`)5mM`i35r@e69t8y8gO57?dP_d~lXd6J~ z+N!_a_7r~u3ZTST2}@wFW)tk_z&N@CwE@>=ltt4l=)m~B!)W{gX)YtpKBYZTFa|~I#^80n5TndXG+|8c7nQ|_ zD<35;$5?%Usl)Tm>K*C?V3qo*7+Xgg;h_!zl=lIl4d5i+2}=B<$M}}TIbIU21B$PN zbB4@B0bB~LvPL+SAu9BWpP8NjqfgbKZ#tD-3pPtuqs+dq%#mH&CO%nue%9SA3fRHx zz-C~Km4Omugni@R<<=Sr3q}m z2IiR}5$$fm_N{>T81_d9!h>tkKe+qJN*Dp*eZ=2q6+KaO=(=BR$;NBMxOpQa!5#V} zd>^r3nM6G<|B&E^aU#b5${PYNsy3qErp#-te+H95VjEMi{73W!^*@b|MS*QY87Z;z z-FW{SiO@MnPrkPpV^cR--D{;MKT4%1dpgM0bEU-An4{dw-qNEsm1Zg>!OIkklq90R0cJ+D5;T|(N+}Ve5{n|iU zMg^5IZXJ6fpG34y#5X4+x$1WX_6mzJ7Ay_ywJ%oua=sh=1{3SRFG%StXJk9jd!K$F485JIA1}(d5gb{b`83b=UcSv$qkqrNc39`RNm{N@4e+w z+UWCpHlSXbiS5{iz;vNJFx_5GgdU8CdZIQ>mEFYJc|_T#O&M|l>Fm{z=lac_);=K5 z;Xd-4yXl1aJstRL|6BQ)2p8r(5t;(vgM49>^;NbTT-(kZ)z);qU;Hc zyFZOS^UxIf+)8}MSTjZ0ACzqzeF*nR=*j`(JRmU#3c&hr4X9gQI-~zNYU_Q_vk?!< z@xdJO`Jfks2eQb!gZZA;W+3kjdef~CPwf3ocebML+IziBZJV0f=B@k@5NsD!itP#R5E;cjt*_vkvd(mFqAnXSA-JyTwU_VF|9 z_nWC`Z)m0_wM_>nsZUpgZ*2GuqnQ)<=kZt{-VxY1o+Yq7C9qt?n3pRGJS?h+Cj65? zg`T0A(W!w-y@fD)+5^iCI_itTc0&x&M$ZZS%Xo&cJt={w#;Zuo&eFhQTvzn=iGgyF zrJ3`30@eC3d|PS`)aY%*rnDRCiJ-KjKa%Os4J<()BD0YTEJfdG54Ja99J(9Zo6*O} ze7+~J#DMVW=D<=zBsqrd%k&y@6x*xxQ8cPxIr?wa#P)FuvAyM{zV>3&i85*0{mAV3ZI=EWW&;Rfr%K?8jq2{yvUGR%MgOGPGw^1tg+Op|cW8y+VgJauw1&igYVD ztdB&!KZNzXqI3TrlZ;83_czLCma6-l-W0+W^dFIO)3b95)5Vh2;+*0Y)x`^!iQ~kA z@@2IPmo2DD72Uq9*)t37@%ZM7D;HMRlvgeD{oP~$`G?RtSWvs59_nTGawPB=9s8UjrCR}a82YbNmf&r$DErR1% zJp#L!U6$6!R3-C=dEoc)sTSaW9lzD`XUhW1R{k^ow|pIcls_8X61%~2cVy}q(-`#_ zb?mO#wBFo!`fSO#KWr02Q6nzn?iR3pRAOXgt#(3zDBbHf5ppcmS5LZ-=gwG zRlizTS39S+xVjepwmxUsf}hl87uOd5J!++1p@vB{tC!XmmmsXIz77}PEY;#jFlhl& z!laU#8kkhQu&jL9qAHk_fA6e0lZs2q7cD6+!}{e5s$mjJd{S|3ZFPCcirR(vlgIxi z;jeKax!jbU>!y5eFhQ||QUZPz`Q6x)n1P#e3blsB7b>OTSC9DyU2J!#_SWYnztrUz zc4766JrB_dx5z?!t>DT}Jri%E`wYvs(aAw+j` zPD=Gn9tylo9~Ch{H|8+R%9sj2rJsV|rl(`N5q}W#&2*EW1uJf&v&SL+z)d2AA-ewr DklRY^ literal 0 HcmV?d00001 diff --git a/rspdata.inc.ld b/rspdata.inc.ld index 2e8f077f35..82c6634380 100644 --- a/rspdata.inc.ld +++ b/rspdata.inc.ld @@ -4,15 +4,18 @@ #endif #else /* Use one of the Fast3DEX series grucodes. */ #ifndef F3DZEX_GBI_2 - #if F3DEX2PL_GBI == 1 - BUILD_DIR/lib/gspF3DEX2_PosLight.fifo.o(.data); - #elif F3DEX_GBI_2 == 1 - lib/PR/f3dex2/fifo/gspF3DEX2.fifo.o(.data); - #elif F3DEX_GBI == 1 - lib/PR/f3dex/fifo/gspF3DEX.fifo.o(.data); - #endif + #if F3DEX_GBI_3 == 1 + #warning "reached ex3!" + lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.data); + #elif F3DEX2PL_GBI == 1 + BUILD_DIR/lib/gspF3DEX2_PosLight.fifo.o(.data); + #elif F3DEX_GBI_2 == 1 + lib/PR/f3dex2/fifo/gspF3DEX2.fifo.o(.data); + #elif F3DEX_GBI == 1 + lib/PR/f3dex/fifo/gspF3DEX.fifo.o(.data); + #endif #else /* Fast3DZEX */ - BUILD_DIR/lib/gspF3DZEX2_PosLight.fifo.o(.data); + BUILD_DIR/lib/gspF3DZEX2_PosLight.fifo.o(.data); #endif #endif diff --git a/rsptext.inc.ld b/rsptext.inc.ld index 5d5b9d69df..34347d339b 100644 --- a/rsptext.inc.ld +++ b/rsptext.inc.ld @@ -1,24 +1,33 @@ +/* + * PRIMARY MICROCODES + * These are the default microcode options that that majority of the game + * will render with by default. + */ + #ifndef F3DEX_GBI_SHARED #if SUPER3D_GBI == 1 lib/PR/super3d/fifo/gspSuper3D.o(.text); #endif #else /* Use one of the Fast3DEX series grucodes. */ #ifndef F3DZEX_GBI_2 - #if F3DEX2PL_GBI == 1 - BUILD_DIR/lib/gspF3DEX2_PosLight.fifo.o(.text); - #elif F3DEX_GBI_2 == 1 - lib/PR/f3dex2/fifo/gspF3DEX2.fifo.o(.text); - #elif F3DEX_GBI == 1 - lib/PR/f3dex/fifo/gspF3DEX.fifo.o(.text); + #if F3DEX_GBI_3 == 1 + lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.text*); + #elif F3DEX2PL_GBI == 1 + BUILD_DIR/lib/gspF3DEX2_PosLight.fifo.o(.text); + #elif F3DEX_GBI_2 == 1 + lib/PR/f3dex2/fifo/gspF3DEX2.fifo.o(.text); + #elif F3DEX_GBI == 1 + lib/PR/f3dex/fifo/gspF3DEX.fifo.o(.text); #endif #else /* Fast3DZEX */ - BUILD_DIR/lib/gspF3DZEX2_PosLight.fifo.o(.text); + BUILD_DIR/lib/gspF3DZEX2_PosLight.fifo.o(.text); #endif #endif /* - * LESS COMMON MICROCODES - * These are setup to be loaded by G_LOAD_UCODE + * SECONDARY MICROCODES + * These are secondary microcodes intended to be setup and loaded + * by the G_LOAD_UCODE (gSPLoadUCode/gSPLoadUCodeL) command. */ /* Fast3DEX NoN Text */ diff --git a/src/game/game_init.c b/src/game/game_init.c index 4d92e9aa18..b6f2d7b129 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -302,6 +302,11 @@ void create_gfx_task_structure(void) { gGfxSPTask->task.t.ucode_data = gspF3DEX2_PosLight_fifoDataStart; gGfxSPTask->task.t.ucode_size = ((u8 *) gspF3DEX2_PosLight_fifoTextEnd - (u8 *) gspF3DEX2_PosLight_fifoTextStart); gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspF3DEX2_PosLight_fifoDataEnd - (u8 *) gspF3DEX2_PosLight_fifoDataStart); +#elif F3DEX_GBI_3 + gGfxSPTask->task.t.ucode = gspF3DEX3_fifoTextStart; + gGfxSPTask->task.t.ucode_data = gspF3DEX3_fifoDataStart; + gGfxSPTask->task.t.ucode_size = ((u8 *) gspF3DEX3_fifoTextEnd - (u8 *) gspF3DEX3_fifoTextStart); + gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspF3DEX3_fifoDataEnd - (u8 *) gspF3DEX3_fifoDataStart); #elif F3DEX_GBI_2 gGfxSPTask->task.t.ucode = gspF3DEX2_fifoTextStart; gGfxSPTask->task.t.ucode_data = gspF3DEX2_fifoDataStart; diff --git a/src/goddard/renderer.c b/src/goddard/renderer.c index 90d9580797..0a41393d65 100644 --- a/src/goddard/renderer.c +++ b/src/goddard/renderer.c @@ -1851,10 +1851,10 @@ void gd_dl_lookat(struct ObjCamera *cam, f32 arg1, f32 arg2, f32 arg3, f32 arg4, lookat->l[1].l.dir[1] = LOOKAT_PACK(cam->unkE8[1][1]); lookat->l[1].l.dir[2] = LOOKAT_PACK(cam->unkE8[2][1]); +#ifndef F3DEX_GBI_3 lookat->l[0].l.col[0] = 0; lookat->l[0].l.col[1] = 0; lookat->l[0].l.col[2] = 0; - lookat->l[0].l.pad1 = 0; lookat->l[0].l.colc[0] = 0; lookat->l[0].l.colc[1] = 0; lookat->l[0].l.colc[2] = 0; @@ -1862,11 +1862,14 @@ void gd_dl_lookat(struct ObjCamera *cam, f32 arg1, f32 arg2, f32 arg3, f32 arg4, lookat->l[1].l.col[0] = 0; lookat->l[1].l.col[1] = 0x80; lookat->l[1].l.col[2] = 0; - lookat->l[1].l.pad1 = 0; lookat->l[1].l.colc[0] = 0; lookat->l[1].l.colc[1] = 0x80; lookat->l[1].l.colc[2] = 0; lookat->l[1].l.pad2 = 0; +#endif + + lookat->l[0].l.pad1 = 0; + lookat->l[1].l.pad1 = 0; lookat = &D_801BE790[0]; lookat->l[0].l.dir[0] = 1; @@ -1877,10 +1880,11 @@ void gd_dl_lookat(struct ObjCamera *cam, f32 arg1, f32 arg2, f32 arg3, f32 arg4, lookat->l[1].l.dir[1] = 1; lookat->l[1].l.dir[2] = 0; +#ifndef F3DEX_GBI_3 lookat->l[0].l.col[0] = 0; lookat->l[0].l.col[1] = 0; lookat->l[0].l.col[2] = 0; - lookat->l[0].l.pad1 = 0; + lookat->l[0].l.colc[0] = 0; lookat->l[0].l.colc[1] = 0; lookat->l[0].l.colc[2] = 0; @@ -1888,11 +1892,16 @@ void gd_dl_lookat(struct ObjCamera *cam, f32 arg1, f32 arg2, f32 arg3, f32 arg4, lookat->l[1].l.col[0] = 0; lookat->l[1].l.col[1] = 0x80; lookat->l[1].l.col[2] = 0; - lookat->l[1].l.pad1 = 0; + lookat->l[1].l.colc[0] = 0; lookat->l[1].l.colc[1] = 0x80; lookat->l[1].l.colc[2] = 0; lookat->l[1].l.pad2 = 0; +#endif + + lookat->l[0].l.pad1 = 0; + lookat->l[1].l.pad1 = 0; + gSPLookAt(next_gfx(), osVirtualToPhysical(&D_801BE7D0[gGdFrameBufNum])); next_mtx(); diff --git a/src/s2d_engine/init.h b/src/s2d_engine/init.h index c28e250f3e..c17a23e315 100644 --- a/src/s2d_engine/init.h +++ b/src/s2d_engine/init.h @@ -18,6 +18,9 @@ #elif F3DEX2PL_GBI #define zex_text gspF3DEX2_PosLight_fifoTextStart #define zex_data gspF3DEX2_PosLight_fifoDataStart +#elif F3DEX_GBI_3 + #define zex_text gspF3DEX3_fifoTextStart + #define zex_data gspF3DEX3_fifoDataStart #elif F3DEX_GBI_2 #define zex_text gspF3DEX2_fifoTextStart #define zex_data gspF3DEX2_fifoDataStart From 66e9de85b5f6c191beacf61920a8c5a3e2a8a7c2 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sun, 4 Feb 2024 18:13:19 -0500 Subject: [PATCH 02/30] F3DEX3 game code --- src/game/rendering_graph_node.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 7ea44b1527..2ff99bc9f2 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -52,6 +52,10 @@ ALIGNED16 Mat4 gMatStack[32]; ALIGNED16 Mtx *gMatStackFixed[32]; f32 sAspectRatio; +#ifdef F3DEX_GBI_3 +PlainVtx *camWorld; +#endif + /** * Animation nodes have state in global variables, so this struct captures * the animation state so a 'context switch' can be made when rendering the @@ -585,6 +589,10 @@ void geo_process_perspective(struct GraphNodePerspective *node) { gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH); +#ifdef F3DEX_GBI_3 + gSPCameraWorld(gDisplayListHead++, camWorld); +#endif + gCurGraphNodeCamFrustum = node; geo_process_node_and_siblings(node->fnNode.node.children); gCurGraphNodeCamFrustum = NULL; @@ -644,7 +652,7 @@ Lights1 defaultLight = gdSPDefLights1( 0x3F, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 ); -Vec3f globalLightDirection = { 0x28, 0x28, 0x28 }; +Vec3f globalLightDirection = { 0x49, 0x49, 0x49 }; void setup_global_light() { Lights1* curLight = (Lights1*)alloc_display_list(sizeof(Lights1)); @@ -698,7 +706,11 @@ void geo_process_camera(struct GraphNodeCamera *node) { gCurLookAt->l[1].l.dir[0] = (s8)(127.0f * -(*cameraMatrix)[0][1]); gCurLookAt->l[1].l.dir[1] = (s8)(127.0f * -(*cameraMatrix)[1][1]); gCurLookAt->l[1].l.dir[2] = (s8)(127.0f * -(*cameraMatrix)[2][1]); -#endif // F3DEX_GBI_2 +#endif + +#ifdef F3DEX_GBI_3 + gSPCameraWorld(gDisplayListHead++, camWorld); +#endif #if WORLD_SCALE > 1 // Make a copy of the view matrix and scale its translation based on WORLD_SCALE @@ -1358,6 +1370,19 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) gCurLookAt = (LookAt*)alloc_display_list(sizeof(LookAt)); bzero(gCurLookAt, sizeof(LookAt)); +#ifdef F3DEX_GBI_3 + camWorld = alloc_display_list(sizeof(PlainVtx)); + if (gCurGraphNodeCamera != NULL) { + camWorld->c.pos[0] = gCurGraphNodeCamera->pos[0]; + camWorld->c.pos[1] = gCurGraphNodeCamera->pos[1]; + camWorld->c.pos[2] = gCurGraphNodeCamera->pos[2]; + } else { + camWorld->c.pos[0] = 0; + camWorld->c.pos[1] = 0; + camWorld->c.pos[2] = 0; + } +#endif + gMatStackIndex = 0; gCurrAnimType = ANIM_TYPE_NONE; vec3s_set(viewport->vp.vtrans, node->x * 4, node->y * 4, 511); From 7b14af059f1920a6ae6ced15f17eeabfb4de9534 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sun, 4 Feb 2024 18:14:46 -0500 Subject: [PATCH 03/30] polish --- rspdata.inc.ld | 12 +++++++++--- rsptext.inc.ld | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/rspdata.inc.ld b/rspdata.inc.ld index 82c6634380..8a19440dd4 100644 --- a/rspdata.inc.ld +++ b/rspdata.inc.ld @@ -1,3 +1,9 @@ +/* + * PRIMARY MICROCODES + * These are the default microcode options that that majority of the game + * will render with by default. + */ + #ifndef F3DEX_GBI_SHARED #if SUPER3D_GBI == 1 lib/PR/super3d/fifo/gspSuper3D.o(.data); @@ -5,7 +11,6 @@ #else /* Use one of the Fast3DEX series grucodes. */ #ifndef F3DZEX_GBI_2 #if F3DEX_GBI_3 == 1 - #warning "reached ex3!" lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.data); #elif F3DEX2PL_GBI == 1 BUILD_DIR/lib/gspF3DEX2_PosLight.fifo.o(.data); @@ -20,8 +25,9 @@ #endif /* - * LESS COMMON MICROCODES - * These are setup to be loaded by G_LOAD_UCODE + * SECONDARY MICROCODES + * These are secondary microcodes intended to be setup and loaded + * by the G_LOAD_UCODE (gSPLoadUCode/gSPLoadUCodeL) command. */ /* Fast3DEX NoN Data */ diff --git a/rsptext.inc.ld b/rsptext.inc.ld index 34347d339b..f6344907f4 100644 --- a/rsptext.inc.ld +++ b/rsptext.inc.ld @@ -11,7 +11,7 @@ #else /* Use one of the Fast3DEX series grucodes. */ #ifndef F3DZEX_GBI_2 #if F3DEX_GBI_3 == 1 - lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.text*); + lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.text); #elif F3DEX2PL_GBI == 1 BUILD_DIR/lib/gspF3DEX2_PosLight.fifo.o(.text); #elif F3DEX_GBI_2 == 1 From b59b57ae0a101f5ee861dd4651fda46a59d5294a Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Mon, 5 Feb 2024 18:17:33 -0500 Subject: [PATCH 04/30] Add clarified warning and fix yield size --- Makefile | 2 +- include/n64/PR/sptask.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 353945779d..14fa9b23eb 100644 --- a/Makefile +++ b/Makefile @@ -120,7 +120,7 @@ else ifeq ($(GRUCODE),super3d) # Super3D DEFINES += SUPER3D_GBI=1 F3D_NEW=1 else ifeq ($(GRUCODE),f3dex3) # Fast3DEX3 DEFINES += F3DEX_GBI_3=1 F3DEX_GBI_SHARED=1 - $(warning Fast3DEX3 is experimental. Try at your own risk.) + $(warning Fast3DEX3 is experimental and as of February 4th, 2024 only fully works with LLE emulation (i.e. NOT PROJECT64 1.6). Try at your own risk and please inform your audience to avoid compatibility problems.) endif # TEXT ENGINES diff --git a/include/n64/PR/sptask.h b/include/n64/PR/sptask.h index 960cab9b04..af1a86d526 100644 --- a/include/n64/PR/sptask.h +++ b/include/n64/PR/sptask.h @@ -137,7 +137,7 @@ typedef u32 OSYieldResult; * boundary. The taskHdrPtr->t.yield_data_ptr must be set to point to the * buffer BEFORE the task is started. */ -#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)||defined(F3DEX_GBI_2)) +#if (defined(F3DEX_GBI)||defined(F3DLP_GBI)||defined(F3DEX_GBI_2))||defined(F3DEX_GBI_3) #define OS_YIELD_DATA_SIZE 0xc00 #else #define OS_YIELD_DATA_SIZE 0x900 From 3c860c7fb7ce01a518f90722276c5ce3af330698 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Mon, 5 Feb 2024 23:25:04 -0500 Subject: [PATCH 05/30] Add F3DEX3 performance counters --- src/boot/main.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ src/game/main.h | 22 ++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/boot/main.c b/src/boot/main.c index 9d812aadcb..1f3e2e346f 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -73,6 +73,16 @@ s8 gResetTimer = 0; s8 gNmiResetBarsTimer = 0; s8 gDebugLevelSelect = FALSE; +#if defined(F3DEX_GBI_3) +volatile u32 gRSPGfxRDPWaitCycles; +volatile u16 gRSPGfxCommandsSampledGclkActive; +volatile u16 gRSPGfxCommandCount; +volatile u16 gRSPGfxVertexCount; +volatile u16 gRSPGfxTriDrawCount; +volatile u32 gRSPGfxTriRequestCount; +volatile u16 gRSPGfxRectCount; +#endif + #ifdef VANILLA_DEBUG s8 gShowDebugText = FALSE; @@ -95,6 +105,46 @@ UNUSED void handle_debug_key_sequences(void) { } #endif +#ifdef F3DEX_GBI_3 +#ifdef F3DEX_GBI_3_DEBUG +static void display_rsp_counters(void) { + char buf[24]; + sprintf(buf, "RDP CYC %u", gRSPGfxRDPWaitCycles); + print_text(32, 32, buf); + sprintf(buf, "RDP GCLK %u", gRSPGfxCommandsSampledGclkActive); + print_text(32, 48, buf); + sprintf(buf, "RSP CMD %u", gRSPGfxCommandCount); + print_text(32, 64, buf); + sprintf(buf, "RSP VTX %u", gRSPGfxVertexCount); + print_text(32, 80, buf); + sprintf(buf, "RDP TRI %u", gRSPGfxTriDrawCount); + print_text(32, 96, buf); + sprintf(buf, "RSP TRI %u", gRSPGfxTriRequestCount); + print_text(32, 112, buf); + sprintf(buf, "RDP RCT %u", gRSPGfxRectCount); + print_text(32, 128, buf); + + sprintf(buf, "DMA: %s", osPiReadIo(SP_IMEM_START, NULL)); + print_text(32, 144, buf); +} +#endif + +static void collect_rsp_counters(void) { + F3DEX3YieldDataFooter* footer = (F3DEX3YieldDataFooter*)((u8*)gGfxSPTaskYieldBuffer + OS_YIELD_DATA_SIZE - sizeof(F3DEX3YieldDataFooter)); + osInvalDCache(footer, sizeof(F3DEX3YieldDataFooter)); + gRSPGfxRDPWaitCycles = footer->rdpWaitCycles; + gRSPGfxCommandsSampledGclkActive = footer->commandsSampledGclkActive; + gRSPGfxCommandCount = footer->commandCount; + gRSPGfxVertexCount = footer->vertexCount; + gRSPGfxTriDrawCount = footer->triDrawCount; + gRSPGfxTriRequestCount = footer->triRequestCount; + gRSPGfxRectCount = footer->rectCount; +#ifdef F3DEX_GBI_3_DEBUG + display_rsp_counters(); +#endif +} +#endif + void setup_mesg_queues(void) { osCreateMesgQueue(&gDmaMesgQueue, gDmaMesgBuf, ARRAY_COUNT(gDmaMesgBuf)); osCreateMesgQueue(&gSIEventMesgQueue, gSIEventMesgBuf, ARRAY_COUNT(gSIEventMesgBuf)); @@ -290,6 +340,9 @@ void handle_sp_complete(void) { // that needs to arrive before we can consider the task completely finished and // null out sCurrentDisplaySPTask. That happens in handle_dp_complete. profiler_rsp_completed(PROFILER_RSP_GFX); +#ifdef F3DEX_GBI_3 + collect_rsp_counters(); +#endif } } } diff --git a/src/game/main.h b/src/game/main.h index 2ee8000753..cb03020581 100644 --- a/src/game/main.h +++ b/src/game/main.h @@ -112,4 +112,26 @@ void dispatch_audio_sptask(struct SPTask *spTask); void exec_display_list(struct SPTask *spTask); void change_vi(OSViMode *mode, int width, int height); +#ifdef F3DEX_GBI_3 +typedef struct { + u32 rdpWaitCycles; + u16 commandsSampledGclkActive; + u16 commandCount; + u16 vertexCount; + u16 triDrawCount; + u32 triRequestCount:18; + u32 rectCount:14; + u32 taskdataptr; /* Not a perf counter */ + u32 ucode; /* Not a perf counter */ +} F3DEX3YieldDataFooter; + +extern volatile u32 gRSPGfxRDPWaitCycles; +extern volatile u16 gRSPGfxCommandsSampledGclkActive; +extern volatile u16 gRSPGfxCommandCount; +extern volatile u16 gRSPGfxVertexCount; +extern volatile u16 gRSPGfxTriDrawCount; +extern volatile u32 gRSPGfxTriRequestCount; +extern volatile u16 gRSPGfxRectCount; +#endif + #endif // MAIN_H From 1905cb3f7bbe242acbe88a3f2c63b4853d6523d6 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Wed, 7 Feb 2024 02:00:23 -0500 Subject: [PATCH 06/30] Fix F3DEX3 LightColor macro to patch up warnings --- include/n64/PR/gbi_f3dex3.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/n64/PR/gbi_f3dex3.h b/include/n64/PR/gbi_f3dex3.h index 3dbc364414..689d058ec7 100644 --- a/include/n64/PR/gbi_f3dex3.h +++ b/include/n64/PR/gbi_f3dex3.h @@ -3096,12 +3096,12 @@ _DW({ \ */ #define gSPLightColor(pkt, n, col) \ _DW({ \ - gMoveWd(pkt, G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 0, ((col) & 0xFFFFFF00)); \ - gMoveWd(pkt, G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 4, ((col) & 0xFFFFFF00)); \ + gMoveWd(pkt, G_MW_LIGHTCOL, ((((n) - 1) * 0x10) + 0), ((col) & 0xFFFFFF00)); \ + gMoveWd(pkt, G_MW_LIGHTCOL, ((((n) - 1) * 0x10) + 4), ((col) & 0xFFFFFF00)); \ }) #define gsSPLightColor(n, col) \ - gsMoveWd(G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 0, ((col) & 0xFFFFFF00)), \ - gsMoveWd(G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 4, ((col) & 0xFFFFFF00)) + gsMoveWd(G_MW_LIGHTCOL, ((((n) - 1) * 0x10) + 0), ((col) & 0xFFFFFF00)), \ + gsMoveWd(G_MW_LIGHTCOL, ((((n) - 1) * 0x10) + 4), ((col) & 0xFFFFFF00)) /* * Version for point lights. (col1 & 0xFF) must be set to the point light constant * factor (must be nonzero), and (col2 & 0xFF) must be set to the point light @@ -3110,12 +3110,12 @@ _DW({ \ */ #define _gSPLightColor2(pkt, n, col1, col2) \ _DW({\ - gMoveWd(pkt, G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 0, col1); \ - gMoveWd(pkt, G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 4, col2); \ + gMoveWd(pkt, G_MW_LIGHTCOL, ((((n) - 1) * 0x10) + 0), col1); \ + gMoveWd(pkt, G_MW_LIGHTCOL, ((((n) - 1) * 0x10) + 4), col2); \ }) #define _gsSPLightColor2(n, col1, col2) \ - gsMoveWd(G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 0, col1), \ - gsMoveWd(G_MW_LIGHTCOL, (((n) - 1) * 0x10) + 4, col2) + gsMoveWd(G_MW_LIGHTCOL, ((((n) - 1) * 0x10) + 0), col1), \ + gsMoveWd(G_MW_LIGHTCOL, ((((n) - 1) * 0x10) + 4), col2) /* From b9ddfe20f2ef171944f4d4ed3029aca3543d5a10 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Wed, 7 Feb 2024 02:04:27 -0500 Subject: [PATCH 07/30] reenable f3dzex as default, parallel-launcher as default for test target --- Makefile | 4 ++-- levels/entry.c | 2 +- src/game/area.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 14fa9b23eb..5dd088ad54 100644 --- a/Makefile +++ b/Makefile @@ -102,7 +102,7 @@ TARGET := sm64 # f3dzex - Newer, experimental microcode based on Fast3DEX2 used in Animal Crossing and Zelda 64. # f3dex3 - Upgraded Fast3DEX2. Great performance, but as of February 4th, 2024, it is only supported across LLE emulators and real hardware. # super3d - Extremely experimental version of Fast3D lacking many features and simplified routines for speed. -GRUCODE ?= f3dex3 +GRUCODE ?= f3dzex $(eval $(call validate-option,GRUCODE,f3dex f3dex2 f3dex2pl f3dzex super3d l3dex2 f3dex3)) ifeq ($(GRUCODE),f3dex) # Fast3DEX @@ -528,7 +528,7 @@ ifneq (,$(call find-command,armips)) else RSPASM := $(TOOLS_DIR)/armips endif -EMULATOR = mupen64plus +EMULATOR = parallel-launcher EMU_FLAGS = ifneq (,$(call find-command,wslview)) diff --git a/levels/entry.c b/levels/entry.c index 411a47f77e..7cd515676f 100644 --- a/levels/entry.c +++ b/levels/entry.c @@ -19,7 +19,7 @@ const LevelScript level_script_entry[] = { EXECUTE(/*seg*/ SEGMENT_GLOBAL_LEVEL_SCRIPT, /*script*/ _scriptsSegmentRomStart, /*scriptEnd*/ _scriptsSegmentRomEnd, /*entry*/ level_main_scripts_entry), #else SET_REG(/*value*/ 0), - EXECUTE(/*seg*/ SEGMENT_MENU_INTRO, /*script*/ _introSegmentRomStart, /*scriptEnd*/ _introSegmentRomEnd, /*entry*/ level_intro_splash_screen), + EXECUTE(/*seg*/ SEGMENT_MENU_INTRO, /*script*/ _introSegmentRomStart, /*scriptEnd*/ _introSegmentRomEnd, /*entry*/ level_intro_f3dex3_warning), #endif JUMP(/*target*/ level_script_entry), }; diff --git a/src/game/area.c b/src/game/area.c index 1e99763f29..a7ecb91002 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -54,7 +54,7 @@ Vp *gViewportClip = NULL; s16 gWarpTransDelay = 0; RGBA16FILL gFBSetColor = 0; RGBA16FILL gWarpTransFBSetColor = 0; -Color gWarpTransRed= 0; +Color gWarpTransRed = 0; Color gWarpTransGreen = 0; Color gWarpTransBlue = 0; s16 gCurrSaveFileNum = 1; From a9a1f106abb333201f04d8e0a15df5db036b9c3c Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Wed, 7 Feb 2024 02:11:09 -0500 Subject: [PATCH 08/30] opsie --- levels/entry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/levels/entry.c b/levels/entry.c index 7cd515676f..411a47f77e 100644 --- a/levels/entry.c +++ b/levels/entry.c @@ -19,7 +19,7 @@ const LevelScript level_script_entry[] = { EXECUTE(/*seg*/ SEGMENT_GLOBAL_LEVEL_SCRIPT, /*script*/ _scriptsSegmentRomStart, /*scriptEnd*/ _scriptsSegmentRomEnd, /*entry*/ level_main_scripts_entry), #else SET_REG(/*value*/ 0), - EXECUTE(/*seg*/ SEGMENT_MENU_INTRO, /*script*/ _introSegmentRomStart, /*scriptEnd*/ _introSegmentRomEnd, /*entry*/ level_intro_f3dex3_warning), + EXECUTE(/*seg*/ SEGMENT_MENU_INTRO, /*script*/ _introSegmentRomStart, /*scriptEnd*/ _introSegmentRomEnd, /*entry*/ level_intro_splash_screen), #endif JUMP(/*target*/ level_script_entry), }; From 1b9038f67483fb0587bd48e41c652908131463e3 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Wed, 7 Feb 2024 20:04:38 -0500 Subject: [PATCH 09/30] branding --- Makefile | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 5dd088ad54..0941417128 100644 --- a/Makefile +++ b/Makefile @@ -94,14 +94,14 @@ DEBUG_MAP_STACKTRACE_FLAG := -D DEBUG_MAP_STACKTRACE TARGET := sm64 - # GRUCODE - selects which RSP microcode to use. -# f3dex - Upgraded Fast3D. Offers worse performance than Fast3DEX2, but has a more precise z-buffer. -# f3dex2 - Upgraded Fast3DEX. Good performance and widely supported across almost all emulators. -# l3dex2 - Fast3DEX2 version that only renders in wireframe. -# f3dzex - Newer, experimental microcode based on Fast3DEX2 used in Animal Crossing and Zelda 64. -# f3dex3 - Upgraded Fast3DEX2. Great performance, but as of February 4th, 2024, it is only supported across LLE emulators and real hardware. +# f3dex - Upgraded Fast3D. Offers worse performance than F3DEX2, but has a more precise z-buffer. +# f3dex2 - Upgraded F3DEX. Good performance and widely supported across almost all emulators. +# l3dex2 - F3DEX2 version that only renders in wireframe. +# f3dzex - Newer, experimental microcode based on F3DEX2 used in Animal Crossing and Zelda 64. This is the HackerSM64 default. +# f3dex3 - Upgraded F3DEX2. Great performance, but as of February 4th, 2024, it is only supported across LLE emulators and real hardware. # super3d - Extremely experimental version of Fast3D lacking many features and simplified routines for speed. + GRUCODE ?= f3dzex $(eval $(call validate-option,GRUCODE,f3dex f3dex2 f3dex2pl f3dzex super3d l3dex2 f3dex3)) @@ -120,7 +120,8 @@ else ifeq ($(GRUCODE),super3d) # Super3D DEFINES += SUPER3D_GBI=1 F3D_NEW=1 else ifeq ($(GRUCODE),f3dex3) # Fast3DEX3 DEFINES += F3DEX_GBI_3=1 F3DEX_GBI_SHARED=1 - $(warning Fast3DEX3 is experimental and as of February 4th, 2024 only fully works with LLE emulation (i.e. NOT PROJECT64 1.6). Try at your own risk and please inform your audience to avoid compatibility problems.) + $(warning F3DEX3 is experimental, and as of February 4th, 2024, only fully works on a real Nintendo 64 or with low level emulation (LLE) (i.e. NOT PROJECT64 1.6). Try at your own risk and please inform your audience to avoid compatibility problems.) + $(warning Failure to change emulator settings CAN CAUSE YOUR GAME TO CRASH!) endif # TEXT ENGINES From 53a80377dbbb5b2ddd594927833e49ef4e242542 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Wed, 7 Feb 2024 22:15:48 -0500 Subject: [PATCH 10/30] Add credits for sauraen and I --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b97dc47225..5ecb669c46 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ This is a fork of the ultrasm64 repo by CrashOveride which includes the followin - **anonymous_moose**: porting falco's extended bounds to decomp - **tuxlovesyou**: `LOAD_MIO0_TEXTURE` macro and moral support - **devwizard**: the PJ64 pre-v3.0 detection part of the emulator detector +- **red**: F3DEX3 microcode implementation +- **Sauraen**: [F3DEX3](https://github.com/HackerN64/F3DEX3) microcode author Thanks to Frame#5375 and AloXado320 for also helping with silhouette stuff From b72d746e45da479e6276dd5734deeb108ae964cb Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Wed, 7 Feb 2024 22:15:59 -0500 Subject: [PATCH 11/30] . --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 5ecb669c46..e31c6a1e56 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,6 @@ Thanks to Frame#5375 and AloXado320 for also helping with silhouette stuff **Lighting Engine by Wiseguy** - Lighting Engine is available on a separate branch ([base/lighting-engine](https://github.com/Reonu/HackerSM64/tree/base/lighting-engine)). Instructions on how to use it are in the readme of that branch. -- Alternatively, the main repo has `Puppylights` available, which is a more lightweight, but limited lighting library intended to be used to modify existing light properties. You can look at `puppylights.c` to find out how to use it. **Puppycam** - Puppycam is available on the master branch now, you can toggle it in `config/config_camera.h`. * @@ -213,4 +212,4 @@ A: Theoretically, all yes. ## Installation help -Go read the original SM64 repo README.md +Go read the original SM64 repo README.md \ No newline at end of file From 354de8d9cbf1e29ad5fd3e90ca338fa81330cb58 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Fri, 9 Feb 2024 20:19:46 -0500 Subject: [PATCH 12/30] Debugging options --- lib/PR/f3dex3/fifo/gspF3DEX3.debug.fifo.o | Bin 0 -> 7728 bytes lib/PR/f3dex3/fifo/gspF3DEX3.glck.fifo.o | Bin 0 -> 7728 bytes rspdata.inc.ld | 8 +++++++- rsptext.inc.ld | 10 ++++++++-- 4 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 lib/PR/f3dex3/fifo/gspF3DEX3.debug.fifo.o create mode 100644 lib/PR/f3dex3/fifo/gspF3DEX3.glck.fifo.o diff --git a/lib/PR/f3dex3/fifo/gspF3DEX3.debug.fifo.o b/lib/PR/f3dex3/fifo/gspF3DEX3.debug.fifo.o new file mode 100644 index 0000000000000000000000000000000000000000..f3d0308de5463ce41c2eb722056dcedb6a0b1d71 GIT binary patch literal 7728 zcmdTp4OmpiwddabWq0A;l?CqN5-tmf8fzBONNm5d5@0toz*=o0(IyM{gMf+wRBRd{ z2BYt}0erz|(k7uXO4?v*evC;ffu6s=JSCB^Ccr_?+(P9N8IKjNUsDgrWnj_-U|VZ5Q5SoXF@R;+}tdNpA}`$LUNH) zR{}hnkIf0jYyGqkQ>=a?n}Kt0DuMtnoOQ2rgL|D9I(VFu87?7TK42CGI0@ z^zxmc)s{fCycCSOhhbdOIuNiv9{3{nmP)>xE5?5I=jusA zcz}*%E>lhdZ5!})DAW7fkWL%`TZ4wLWAp)@|EaAQM9utS*}4w+4h#QN*#I2UKHFyC z>*TW#t!n_ID;qST8|QNxL~XI!BJ=76(WCyH@j?8+OCz9t=_-Kp3K-=?>o)!}?nkj^ zmfPZjfCT50YT%8S2K8&ygR|~!UeH7r$=s%5C$7nK^Ij#N07F0$LT>Xcu-2)gi0j?k z+<*}2W&u}MA<60%3CR*}OvWZsCucj6A)2V-cH8GXt5K~nF zF_$(Gb44G0cF;o;XE)Krd41ouEr=rKN*}R!a+JjqM=ZVqrAz`6ncbu;&E!cW=~I@A zIyT0^Wtlu1=in;D*;tNw12k)PJ9W&xoBHRSrVcD;&3cqpl;yToLJBQi{$8sNI%&n~ z+-V^ITDs@4^h&jhR!q;?`5V5UR%8`8_W<%t%YQyhKRMC@`ia#4O>ZoyKWFmXxt;Gv z{ryiyN3_m~M$iG#O|0NwVLAzUJKOmFC${rP#ct5G9O56s{pGlFuNM1!Aor-Ma*J$t z&Q`yab@l4)9)Q-feE<4?gLp1AY-2R?An@{E)zN9G0I}`rRo3p@qmIV>5%{DYb@cX~ z*yjM>A9DDLwUq1oQ?$9+p(*%HNeW(My0O7ueu!)?qyUY0Xd z_4XzJ1!PconNzefujpk>iy2N5fQl9izlQMQu)?9PX_G1xjie#^^kGFO>Ar{d5_B`N z;j_#XIGdTG7$k!N4&>wD6|F;S8&Ek#@6anoS*w_2onn#oN|bECbNCuDW>?6GC^ysW zVI@L}AeIFcidiy~sG4CVQi@arNl=UqqhfNH6pO>6L^+~@dyFO}UP@5n9SH#o>{INL zL$Ny?OgA+Oz580;5$@|xfa_S^L2=(IxDi#(8{F+%Wz^m<}HF&I-k`rF`# z861i4?{K{c9C6g=;aoMu;r9jK61Bm%Y+ACVEMKvUlgSoOfnv8!CaqIIqX zsmf0}2l-@=uRu;x2gqwxh3t%y*L*&$jA!lG>inb-j3dY97LcPWd)Ylej@~0ktj)eR zS5AyOOdQ9WgD*?3x> z`nMmY^*uf!2GWM&92~9nR1aN|IJ)x34-83Y8!!E&dT0dg<`=aO42_+^lUa@8&{t@8 z{6DK6inZy;)dP!$E{i(yW!FNoyHWK17{@sBn;fwGjweUj3o;~)nOxXa7>pD2d(IChicX1;EYv1|=cfH#lPE$%T%ngSda>!t=g^$7Gn& zs;(yIyK;s^!Ai~_C>T0#wvr2-y+c+(Bo}&wp$ldaW$+MNH_8BEPbA(C8<`E`H?^gr zE-e7ty|~vOc&48O~`fvGy%sa+hsWNq=}Uhu(6gw+(#`ujNm`d=#%HY-e7S6XSQwiBIiLUL(BGoC%OzDRf%b ze6ts%#h`2WW)Jft33%zvEL& z#atY;k58qO=6c`-gtwOYTsvHuG)3GFWBk8I9_{er_!K(6e7mjfn?HMvAt1&F($GFP zkf=M`V`R<%M*lm6Pj9mVr$zrShIS1c;1(BYiAiq9`${ERyd%3F&{LIL=H*raiL!3S z@?X4sES6_msmd?&YVHBTS05p!8msa>(Mb3?N0b7aks7BOlx49-YR(aqDK4H`1NSL& z5V{%@l$8keb3Rv|M0i`S3-t3EXnO7|t{%`)SHT4w8}IDGDQK&T$(VQBN%XseB<8&` zI__>)gN@RdL+$aMUDu7D>DUkNNhxVE*iB?9)+wZGU8?L|(yc2^FV%YILd^FQa7 z7NyY9_8inBGs?wDqMz8_63wqhIB*N<7TV11B<4h$S9%|P#BL|*`#1x@+jMl#WAFm< z@_!Q*=5_zt+%PZySG{3AS}x|LPeCN0-+b^ZQA=!nxnAAI24btvZ!y5@B=(^wWsVR< zVh{BxD-nuaIf_RRh}@5%B7~&`O59+6OFBDQtq)Ktn^X!)CM|wWr0$GHmhlGE_rNE zGxd)a(%!kb^u5_w{;F{JvZN)kzZe|8D(Q&*j=_T$9jGU}$_{?&(4pT|M&dT)D5j1)*fT2dc(Ih4Lf= zt%~=BJd%z&Zp#aea~P;&t1p!1(9sl6e#k57X^O8PbeE*1GiDZs#yj+MMt*Z>fet9Ul+wRsekiXx!V3*V-NzuR{q~%$2kh z_Ubmna~&8*cVHadfpK*Q#?{Q9U~w4U)3>nr%Z4E-#-}pIp!+&7&h3zd!yOp^c3}M5 zf$?t##=ki41~ykYTJT`s4`mzIkdYy%cqV05&)05q;`%PiiDCm=7shQPvaJEvYF1^- zEa<@ay~Aw&8fh*g%|6ziESW>HZBytPUx;J#k}VjM2V^FUNcLfIImYS(TpgZ&-ssdO z0nh5EVr(64hWk4tVDAG`8^B4tBUn6S%y42HkM*)`fcZ{1XUIyHz|Cmc8sSu?%;=fl znUMsekJq5DI+b4sc58N{%D=ZH_N z*dDNhg5y7np%RBRL|xIb{pTCpVkESp8)q{v5a;&X~#Cedky;|1nItY z=r8=>u}T;L=^e!1;hCN=ox0{{TXSSiW8Sg}Qs7o&3cin6u}oqfQNKxkva$I$+wqatm+|adTsRN zyOZe2o({6@+yY{6Ok@5q5%)!tryA3!dg2J)2OpD`w7eEG`tmIXpKB-DqTRO@CQaar z$!@`ic65LozC8+gN0Y-beM-D+RN~|a#VVW7U#%cTke{T|v= zdnfwSkRP0pxrB(F-BiUm`G+S8h~vyevK3{rchE;Z__Pms>dDpqhKHxBK5wf6RP8)V z?VSh0(BFBQeAtysMmqbFCaC9$mCaFSB3qAoQD%p6A4Jz{`1aDFMW6Tt^Wk)4?1^8K zmz%be<9JVwJyAiPI)%ISZaRu{JkhBj zAD-5A9$>yTxpHEV`cIrjne>p&gP!2@DND%9gTCMlS2;QIiI1(D#CHyoxb@vPuZwi4 zrLGszkKP(6W3ok_uhXu_Hezldv9C8!b+4Pg{koU6(P#E-WU?prV;h6hrSjl(M>&yt zFh1&u**sPC5L@RFwojWg)k4zQt0PbMM|oTOfIN-+C~oPd7kaex!e1ll17{-Xntlsi z(;G>zeo#oS_WH=yGX}EvjDT-T%}n0ZUO0vA2~D^soj!U06#DckeAiezh3yZ@)=uxo zJ(9X|!8{L0+<`){{jvdd%SUJQKTYku_jxzrK{-B{OFkO(fpl*+d26u1+u97|%|Ty= z4HAi?zv=c?)LlofkE?CdQv2LhV0#W|yl-V3pj@Bytdec$GdxwblKRV5d0P+RI(qbA zd!8qqZ%49oN}k?_5jgsyH@{C=Ac~zmnFo%&Pu+apL=U)R4QRzOJiENwkN7REseI$q z=fZD|7iEok7QPQk_`XsoSAr3tAZM!s)USG!T*;{9VhpMeN~sLwk=yd+ z1?X=*l2#yR7@;@|_ahUg;S4^|jCniV@KSZTBpZclq~g~>quaoBE( zBl_4m!T%V~5xyra`1p7YiQBaxxCGY~yJKRoT;^%kyq;jSF#_M3nu9e)JF&BNQ$3Mb zJNhSCfxO^S^eM6$h2S#urS@QZ6UL>lVS6+B99hrw1ecl+KG7UpW{M`quzk5vM~-59 zl`)3K6s|yjuA122Ya#a6J=EV`f;v$~?Ie%dvju9O*F){In~C7dA%drXMEMFyl*dOR z{rMyk<73Nxg~W0<(p4h;0)!7DeN8hNi}YiWJ|5}gJ-$$k6ho~3{E$r=L#)_O#D3!4 z0*S85A<<<8WK2~d8B@mSY{Xj6=+H*4M!JWPZl!?r(Wv(auwG<3_x~}enAp7k!alP! z-RF#!FwW3_Mas*_$t}u|OV`MAN>)~vELtv)lMBn2*DhMVuxgU*@n_GTS$L<{KUZG0 zsJf=SYPtWPCKIS%hu6V_)(!Pgukx3pK?Dxe^Xdo|;tq z))DJM>o)O2@n>S4cvL(Z+Yn!8{Xw)N{_FTl_}3Qy0=9k~X8zxNIDFv6>3k>6L|iCa zzB1fm(EdaF&E%T@@;ev+;$ffk1`Xo)|7}7<`z;o3)O`one+S1f_uDz*VP*3{%Nf_k z=&s|pu`)}Dv+?nDnjiQ(URJZ>ny&g6moKjR@uIrgIkhF#weXMixyu)Rr#7dgw&b5t zvwB7ilWW#2t1T%-SX+G!F1b;v#gSn0LZpPrr8PA$xq4Aq`SQh8FuCBaS#u_rl$I}E zT2hAfD;8G6WR&>ilG@tp^3s*Hi|{9q|4qVQzW3hu zy|3T*2IihQGiT1soH=vmoZ0%^{5+25;BScoBbINeaMS^a0Mo)06Tl3nztLiWB%GhE zB+3$T3{I9K`C>WFQY6PliUBiR2v~#zG;7c*a}&T?3?}y@GNcE9vo?UU1B3&Capq9K zWIh*gm@fnp%$JRzy(bWF9&wwCAiWZ}m|`%yc`pPsLI_HWoC(EXaC5U6eomA@3&}-J zT?z1PJ~k&9ulLhJOtJcnYzEG~xd;NhaL&En4es?`=-_cqX1I)e`G8p%=)iJd95e(> z&=_#Qra%G&0`bBHc`Se|iC!ZZK9w!jpECa6O&Q;Zk>rQeB2Dr3v>8PJ7BE~%t`)j9 z3ywIke96tp5M8WZbtOSV^IDTlXsYBp3pc5OSMmgSAc_MO^RR z?goTNHygORBBveqjH_W#{gUy)y}RJ7QB~)$Q{I{Vnqu6mE6xv9uPj-+u{S$7>dO{up`dzd5BfGNsKkT}TKeo%w_sbDr zY+VT{d_+Tv^GE8JGv|Qlyhr`=Nhja$Oa~t2Qr=1-g)1*gv95#%rmsYu5iGN}evUlP zU4Gl%0KY^XcB3wSm2_S`F$O?0Z7v?88q9YAWF7|Y&?1TR9yY?E#S-8-DRUhLt+L3$ z^xmf|b^xtE@4-5rG@jOBorY{U?ISOo){&j3eKf%tMH43ZXefIt9U@1m!(Txwi!RZM zqF1ONVg32J^kMNa`moeT{nDRkme@{9=jG7S`R`Nzmrb;CK{c&dkWT#zs)?yAhnT7g zh`F?hm@E3|bAuk5IH!pw&hPuSZDABKSNe#>lcOw=IAZY?C}k3m$m}L%Std^+NuRPp z)Uh!REzjiHIEPjv&c<@gAD~%t+NopSJ=8z{40T{RYxZNbqAa(y5>jaCiuYS}&`B%S ziiu3z*0v?8m(xfhUUTK)@R`YDkX&`+ZNZ+c@v{TY+zt{r?o z>hFIrI-+$>GJ+0>Zc+vRD$_~G+ttSRKe>ZHCU%3a(nu#M5kgTTvwQAekz0>rkf*I2uAuR0p@2jG)>)X_V3 zVV{G1f6Q^j72xmi0&I=o`x^%#e#1mOyF=IcOcwyA_n{8-0)+b>#=b8BSgRmmYYF!M zEA~H!{qwQ^yL|uFGnhB<{Yt7aQpq(%DvKi`m7V5DvUuW;rYmTFbra{34YwD2?>0jE zM9^Ag&`)21{AXb<#k>Q@i^ALt;CUVA2 z{{-JwBD}@+4(wyz)i_1xj#A-m;1+;p^MH(Fw8`e!7t#ajh*vm)Hd5>59%*Ct@rsc||X4TFh{Y093SC__c%=hZPQWO`BAqXe15Mrw=PSN%uXpm!O-O z4WDPGz`4v6#UL3Ja3CKCuV@`w+kna`dWT*y%38%F>lBNuSE6JCp2OFPF}p%eM7f#f z3@Z^*1hFivP|T8e=M^*OEe;-Y@WEqvwj5b`!9UJKnCJ_BoT(wL zX@$WfQ-QP^e8Ceg4SD_c!eGD1lh*}bu-~R9$EFv$UgCiqixGk!rq>hu$-$W7(cc6= z%HT+Re~0TO;E1C>59g{O4!wx|uhZPSviW%-I-oIhtt~_Er=%Zp|0?Mz1 z*1z)@t?%&>F_1PC=iq3qr+VnB#L-nhesD-a+j#jW)k7m_H~(7u;LzBaJel1n4t<4o z$N$snp;()aTsydU=!&Q#Uv@1bdm2UWk8zBnzs>>6Z+UXGy&yx+IY>fgAK**-5d0!`dqm>$rWY2r>{dH~$4Z%`7#eS;%ro?PsRI)wX2F23M9bXe526-G_Vqp=WBVYY&O(>`kv^ut(6?x>M%2U02j{0QjLhWz&Vb6|M1Qg|y|{v32@`+v*& zFkM6cLwo2e7qe%-kj-O7FZT(Mu^&%L?sS8fKMB)P@LopSri>T$XjdjHIVh{&JouWj zRMfYo;@$IAbw;ZP;rM}#txF+=Xs2!o=wUz6JC8!UH-#88tlR`|3QdVFPQMLxMw`(d zQ_RId`-D_Fd7cMeM0i`7&$ZK)NmIlfFvkBozWI~a7y@E^Fb(Z< z1Btq;Jx1mXVD!IB`1Cd_a9Z^LVrbXEL2gNrmYC#rysuQE#XGX=K|NKu$L0N@RKlcmeDTKG@xgoXoQk%pn2dR^okYJkNMhbE zqvP*!HQ4yo2wx4Pf=nme?+SRr@YTRlgzH)xTOwc|UH9_?&|c)E>vrdWx$Jk;xZn$J zSy2idZO=hHGNW9aB>Kr6Ez$fMgahMHx6o$pATcM~ywV5gBX&Dc-^UvO-l3y=ABPu_ zm;alnFs}#J<%W6rzv>P1(Q+{_e+D7}{gy*tiCSXo%k}CuH4s~Uev1L#Ah8ceDRYG= z5_`B$S%pyS%27OmK*WOuN;yL7{-|k(K_S)yKJ?>K={q}Lr0X6!`~2tVgPa`n3=cH3{LDt`&$~p`&o)w1RW3EH$ye?`pJ;4NlX9;OVWp3%r#I5ks|%G1v{_C2a>?U+ zo2h@akoL~YrSH$d@>hk!S0pWo{rTYVHAzS8cMcx9
    yU3Ta*hYtO&G7`5jM@hx? z#5ETvQ*oWrhTg_mAQ7oaaGpjRt|MDrzXL59^Q#{LXKo<6@89$CpTJ1QJau&VjM+%X z&&wM=ZH}PheZJu{CJUWhRXBXw6iFv%`G(IM_0%aoGkn=-pc?6u;qzt_HCE*fUpAYm zk+qwmsCi!D@MV)g%|0J!?gKhL{TZM}nHui=1S0Np(;0C&aNC#GxM866CGL_ zDt|4MEAe!w{EN^WygyFg_gW~`!P7JMeG!_9_ex6kV`BH$?~{7GgGSRIqoa5B(NXl9 zM<*82(bi^Cmfk-6nXq>Fl2A8%cFe=*KkgVl>!_D4BF2nDgB;DR!I)!6wjmy^sgiBc z7z+zWn9rjzcgxeC`^R3D+w5X-tI8m=v2OE(8~6lpw*u%JK;zzSyx#VNcmqnnVy>iR zuur!Ip6|dox&!0r4veciFs^3)1dGG)o*u{IFB^uW7@x`*gYNIZIJZL*j&xxB+kx?K z2gbi082{qD8`xasXu*ShKay=+Lq>+6;+d3LJzu-siR-&0CyEVhT^P5G$hHPtt67yT zv!Mgy_YSl9Yoxh?H2Yb5vSbd)w#}jId?Aj_OSWK49*~(ZBH4$<g5oFOY&0ym>&YlPF8GNWgH zXGRi?K2d|d>NI{m*sa-(D*rBz)sNsb`uXyQ4el04N9dHsFPB6 zV|&033XcCAj`to|iW_!61>Fqay&Vn&K8G{h+M*PUQ&X{SNeAMxS$uQ%+Vdy}?ULPf z7eGmn;*rNkELKkL1diR4tpD&gQazg=*lm1kep(aQe*)Z7#WLFAq@CLV?=|d?5TyIp zqrdQj$17n3q<0a2muGsybn3dFZOxH6jd|;4NP*joDfm8O#WIO`RQ)dB*cAACYu((+o&=*zble6C$+i}u`Jm^6_u zCVK=Q+R*`WaZ!2 z6r;pB#*mitd8Fk-ANn_j3&R-Wy&#a&-#5M8h1+e?QQed3eMhtrX_#^CSiC!3Z$dZ92W8dhjs{#~eD9zl$#x=c_yBpi=_tzJWT%3B zcv{zakonf+>d8UsKY0da(nGckdV({iE+wxF`hqiE<>ct6KDKTW-#JL)Hgw;*F4Coz zx?Vy*dRw53b`5%v=Nq)^@lBW;NbDO8RNd#M@4Vqi_n@}%J#D08JaE4SKoZ%=Z zQV+&QJuzFRsUBkMJj(WIOQu>#I(v2Gnf@qmYaftja3963-SlFQmR|fzBz^E~BwgEY zp=*01>9r3F>9t-T*>=`I_MH{*ZK;{bo7xMfvOS>*_omaQ9+*m>S&i=+>!z~(LD|~r z1Gq<0S1y?61Bp9W2)17|plHMnz4w0aW;`e-26M^BgFcY%%O-CR7I<5mfxI>7 z%dkNrar8Ic(Tck3==E{6ZCYxdw;F8E1C95siUXAEQ=Zkb4Sj~Et5#8e*=ld=VO&R# z9&9i0r1PCfc23DN`!NDXU-Z`ZDGNlgvnTVwvG=K4&ztB0m#hJ;ScYepSNjnk*P6;V zPJ2H5)_6(Qm}lerpoH%$g>oer5ejm)IzauZN6D3pN-oB*3o)k7k+e#VL#vd^Kpwq4 zUtWm*)}v_!ayHIs{ls2drFxmHPinR;Q~!)@#?UWiKJ=mtp>|orY)@#H%rX14u~v8s z?|~7pwLN;>wp&}T+nwl7Hv~Y>Z5N%|S!xB^$B(dI{WP>UG)p(R%>bvU-%yNiZul;v zn;ZPM30NQ55!^h1C$KXuxKhR#SSSuYC~Jr=@`GT7k)v6$lY^B;E8+IG2UnU5)E|fK zrZ}RHog4i32^`^j(t=M+(2%&@3xi8>U9meS14cE<>Lpt5FCpM_+0$wl`s1`Z~5ZqtB7`Y)^2R3E`8?!R4lCava-N73KBt)oz8oTW3P_Z%kVJWW zB+{QxA~8O;++Rp6_aI#*(l12#5YpE)ld(uY7U|=WKHlRC#Yi#4>dz0^q%p*b{Y301 z-XoCcsvHtshW4zgkc=r~bT(qGXLM*I*C5@)NViJB`e@YqgIF&zo%{coR7`B%e`cTA zn(p&POBiS9KO^O3z^mD zUR+&MUbVvi50eShufyx$LFIHQK3-Ui>E&rEeG{E)0>pUAkRok$r zsyQDldyUoM%0L}uC6;uNS_?kl17%W6znEUM<@vyS_pyiBf zV{|w0+gX_<#M$`xI?WIK4KJ%%d0kiiOUjp2{djR*?cCau>RR~w`rH+ZzEhi1Qd{zm zs98OuhAA~`m)Dk*BCM^x4wv36)#6AnWf4-sl+v0Sm{PsCtbE0iDwtAm_w2b-N=nO@ zEGsF)`jv~SVG2roN=a>Pb$RKk+Qs-2$p0qcuW@0y+?1XBrhINNL9v8W5`LNdZtO|i zz)d-YTf^cDm(uWS#C(G;zB^p|?dK-H$tyAJ!s;7)9;TDNB@6F0!`V+ilWw8=2+Oz9 zv9TDQgZUPHi@$*Qt?8!j++C%rfBm*0Om}lmtokMo25-?vCMM{{9D$jQ$@sB;48KKB d$95xrKjxe1CO<1y+(PF_K>WU&L Date: Fri, 9 Feb 2024 20:20:05 -0500 Subject: [PATCH 13/30] ditto --- src/boot/main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/boot/main.c b/src/boot/main.c index 1f3e2e346f..5a07a86308 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -123,9 +123,6 @@ static void display_rsp_counters(void) { print_text(32, 112, buf); sprintf(buf, "RDP RCT %u", gRSPGfxRectCount); print_text(32, 128, buf); - - sprintf(buf, "DMA: %s", osPiReadIo(SP_IMEM_START, NULL)); - print_text(32, 144, buf); } #endif From be7bb241d7c87f0b15965d841dbc395f5f277b8e Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Fri, 9 Feb 2024 20:20:21 -0500 Subject: [PATCH 14/30] Updated README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e31c6a1e56..6ac4a3060f 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,9 @@ This is a fork of the ultrasm64 repo by CrashOveride which includes the followin Thanks to Frame#5375 and AloXado320 for also helping with silhouette stuff +**F3DEX3 by Sauraen** +- F3DEX3 adds several upgrades to the original F3DEX2 microcode. You can enable it by setting `grucode` equal to `f3dex3`. In code, this can be detected by checking for F3DEX_GBI_3 during build. A debug version can be enabled by defining `F3DEX_GBI_3_DEBUG` (via ccflag in the makefile) as `1` for increased profiling capability, or as `2` for increased profiling capability and a normals debugging tool. + **Lighting Engine by Wiseguy** - Lighting Engine is available on a separate branch ([base/lighting-engine](https://github.com/Reonu/HackerSM64/tree/base/lighting-engine)). Instructions on how to use it are in the readme of that branch. @@ -212,4 +215,4 @@ A: Theoretically, all yes. ## Installation help -Go read the original SM64 repo README.md \ No newline at end of file +Go read the original SM64 repo README.md From 0dc92dc512a12831ea2b06a754385aea05d70559 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sat, 10 Feb 2024 20:28:52 -0500 Subject: [PATCH 15/30] Remove F3DEX_GBI_3 define in gbi_f3dex3.h --- include/n64/PR/gbi_f3dex3.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/n64/PR/gbi_f3dex3.h b/include/n64/PR/gbi_f3dex3.h index 689d058ec7..364a539cdf 100644 --- a/include/n64/PR/gbi_f3dex3.h +++ b/include/n64/PR/gbi_f3dex3.h @@ -6,7 +6,6 @@ #define F3DEX3_H #define F3DEX_GBI_2 1 -#define F3DEX_GBI_3 1 #ifdef REQUIRE_SEMICOLONS_AFTER_GBI_COMMANDS /* OoT style, semicolons required after using macros, cleaner code. If modding From 45e217b6a52681d2544658ed4eaf068e7a1ffa2a Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sat, 10 Feb 2024 20:29:56 -0500 Subject: [PATCH 16/30] Enable debug features with F3DEX_GBI_3 instead of a separate define (removes F3DEX_GBI_3_DEBUG) --- rspdata.inc.ld | 30 ++++++++++++++---------------- rsptext.inc.ld | 32 +++++++++++++++----------------- src/boot/main.c | 4 ++-- 3 files changed, 31 insertions(+), 35 deletions(-) diff --git a/rspdata.inc.ld b/rspdata.inc.ld index 65f661a32d..55a1f99f22 100644 --- a/rspdata.inc.ld +++ b/rspdata.inc.ld @@ -10,22 +10,20 @@ #endif #else /* Use one of the Fast3DEX series grucodes. */ #ifndef F3DZEX_GBI_2 - #if F3DEX_GBI_3 == 1 - #if F3DEX_GBI_3_DEBUG == 1 // Debug w/ GLCK profiling - lib/PR/f3dex3/fifo/gspF3DEX3.glck.fifo.o(.data); - #elif F3DEX_GBI_3_DEBUG == 2 // Debug w/ GLCK profiling and normals - lib/PR/f3dex3/fifo/gspF3DEX3.debug.fifo.o(.data); - #else // Default - lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.data); - #endif - #elif F3DEX2PL_GBI == 1 - BUILD_DIR/lib/gspF3DEX2_PosLight.fifo.o(.data); - #elif F3DEX_GBI_2 == 1 - lib/PR/f3dex2/fifo/gspF3DEX2.fifo.o(.data); - #elif F3DEX_GBI == 1 - lib/PR/f3dex/fifo/gspF3DEX.fifo.o(.data); - #endif - #else /* Fast3DZEX */ + #if F3DEX_GBI_3 == 1 + lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.data); + #elif F3DEX_GBI_3 == 2 + lib/PR/f3dex3/fifo/gspF3DEX3.glck.fifo.o(.data); /* GLCK profiling */ + #elif F3DEX_GBI_3 == 3 + lib/PR/f3dex3/fifo/gspF3DEX3.debug.fifo.o(.data); /* Normals debugger + GLCK profiling */ + #elif F3DEX2PL_GBI == 1 + BUILD_DIR/lib/gspF3DEX2_PosLight.fifo.o(.data); + #elif F3DEX_GBI_2 == 1 + lib/PR/f3dex2/fifo/gspF3DEX2.fifo.o(.data); + #elif F3DEX_GBI == 1 + lib/PR/f3dex/fifo/gspF3DEX.fifo.o(.data); + #endif + #else /* F3DZEX */ BUILD_DIR/lib/gspF3DZEX2_PosLight.fifo.o(.data); #endif #endif diff --git a/rsptext.inc.ld b/rsptext.inc.ld index ac16b75ea4..a8dcc24886 100644 --- a/rsptext.inc.ld +++ b/rsptext.inc.ld @@ -10,24 +10,22 @@ #endif #else /* Use one of the Fast3DEX series grucodes. */ #ifndef F3DZEX_GBI_2 - #if F3DEX_GBI_3 == 1 - #if F3DEX_GBI_3_DEBUG == 1 // Debug w/ GLCK profiling - lib/PR/f3dex3/fifo/gspF3DEX3.glck.fifo.o(.text); - #elif F3DEX_GBI_3_DEBUG == 2 // Debug w/ GLCK profiling and normals - lib/PR/f3dex3/fifo/gspF3DEX3.debug.fifo.o(.text); - #else // Default - lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.data); - #endif - #elif F3DEX2PL_GBI == 1 + #if F3DEX_GBI_3 == 1 + lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.text); + #elif F3DEX_GBI_3 == 2 + lib/PR/f3dex3/fifo/gspF3DEX3.glck.fifo.o(.text); /* GLCK profiling */ + #elif F3DEX_GBI_3 == 3 + lib/PR/f3dex3/fifo/gspF3DEX3.debug.fifo.o(.text); /* Normals debugger + GLCK profiling */ + elif F3DEX2PL_GBI == 1 BUILD_DIR/lib/gspF3DEX2_PosLight.fifo.o(.text); - #elif F3DEX_GBI_2 == 1 - lib/PR/f3dex2/fifo/gspF3DEX2.fifo.o(.text); - #elif F3DEX_GBI == 1 - lib/PR/f3dex/fifo/gspF3DEX.fifo.o(.text); - #endif - #else /* Fast3DZEX */ - BUILD_DIR/lib/gspF3DZEX2_PosLight.fifo.o(.text); - #endif + #elif F3DEX_GBI_2 == 1 + lib/PR/f3dex2/fifo/gspF3DEX2.fifo.o(.text); + #elif F3DEX_GBI == 1 + lib/PR/f3dex/fifo/gspF3DEX.fifo.o(.text); + #endif + #else /* F3DZEX */ + BUILD_DIR/lib/gspF3DZEX2_PosLight.fifo.o(.text); + #endif #endif /* diff --git a/src/boot/main.c b/src/boot/main.c index 5a07a86308..8957866cd5 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -106,7 +106,7 @@ UNUSED void handle_debug_key_sequences(void) { #endif #ifdef F3DEX_GBI_3 -#ifdef F3DEX_GBI_3_DEBUG +#if F3DEX_GBI_3 > 1 static void display_rsp_counters(void) { char buf[24]; sprintf(buf, "RDP CYC %u", gRSPGfxRDPWaitCycles); @@ -136,7 +136,7 @@ static void collect_rsp_counters(void) { gRSPGfxTriDrawCount = footer->triDrawCount; gRSPGfxTriRequestCount = footer->triRequestCount; gRSPGfxRectCount = footer->rectCount; -#ifdef F3DEX_GBI_3_DEBUG +#if F3DEX_GBI_3 > 1 display_rsp_counters(); #endif } From c451d3a9232e15bea5f8b78d83eca5bfd0d3ad16 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sat, 10 Feb 2024 20:36:06 -0500 Subject: [PATCH 17/30] move ifdef --- src/boot/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot/main.c b/src/boot/main.c index 8957866cd5..1d580635bb 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -105,7 +105,6 @@ UNUSED void handle_debug_key_sequences(void) { } #endif -#ifdef F3DEX_GBI_3 #if F3DEX_GBI_3 > 1 static void display_rsp_counters(void) { char buf[24]; @@ -126,6 +125,7 @@ static void display_rsp_counters(void) { } #endif +#ifdef F3DEX_GBI_3 static void collect_rsp_counters(void) { F3DEX3YieldDataFooter* footer = (F3DEX3YieldDataFooter*)((u8*)gGfxSPTaskYieldBuffer + OS_YIELD_DATA_SIZE - sizeof(F3DEX3YieldDataFooter)); osInvalDCache(footer, sizeof(F3DEX3YieldDataFooter)); From 01d039f24a92c7faf81bef58b9c7a94c3d098b9d Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sat, 10 Feb 2024 20:44:12 -0500 Subject: [PATCH 18/30] small fixes --- rsptext.inc.ld | 2 +- src/boot/main.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/rsptext.inc.ld b/rsptext.inc.ld index a8dcc24886..e1c684b41a 100644 --- a/rsptext.inc.ld +++ b/rsptext.inc.ld @@ -16,7 +16,7 @@ lib/PR/f3dex3/fifo/gspF3DEX3.glck.fifo.o(.text); /* GLCK profiling */ #elif F3DEX_GBI_3 == 3 lib/PR/f3dex3/fifo/gspF3DEX3.debug.fifo.o(.text); /* Normals debugger + GLCK profiling */ - elif F3DEX2PL_GBI == 1 + #elif F3DEX2PL_GBI == 1 BUILD_DIR/lib/gspF3DEX2_PosLight.fifo.o(.text); #elif F3DEX_GBI_2 == 1 lib/PR/f3dex2/fifo/gspF3DEX2.fifo.o(.text); diff --git a/src/boot/main.c b/src/boot/main.c index 1d580635bb..9b49bf6ca4 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -106,6 +106,9 @@ UNUSED void handle_debug_key_sequences(void) { #endif #if F3DEX_GBI_3 > 1 + +#include "game/print.h" + static void display_rsp_counters(void) { char buf[24]; sprintf(buf, "RDP CYC %u", gRSPGfxRDPWaitCycles); From 65ab92dd3ebd92f398b48be5d69d2fc6662eab08 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sat, 10 Feb 2024 21:02:42 -0500 Subject: [PATCH 19/30] readme update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ac4a3060f..1b700bcd61 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ This is a fork of the ultrasm64 repo by CrashOveride which includes the followin Thanks to Frame#5375 and AloXado320 for also helping with silhouette stuff **F3DEX3 by Sauraen** -- F3DEX3 adds several upgrades to the original F3DEX2 microcode. You can enable it by setting `grucode` equal to `f3dex3`. In code, this can be detected by checking for F3DEX_GBI_3 during build. A debug version can be enabled by defining `F3DEX_GBI_3_DEBUG` (via ccflag in the makefile) as `1` for increased profiling capability, or as `2` for increased profiling capability and a normals debugging tool. +- F3DEX3 adds several upgrades to the original F3DEX2 microcode. You can enable it by setting `grucode` equal to `f3dex3`. In code, this can be detected by checking for F3DEX_GBI_3 during build. Variants of the F3DEX3 microcode can be enabled by defining `F3DEX_GBI_3`'s value as `2` or `3` (via ccflag in the makefile) for increased profiling capability, or increased profiling capability and a normals debugging tool respectively. Please read the [F3DEX3 README.md](https://github.com/HackerN64/F3DEX3/blob/main/README.md) before using. **Lighting Engine by Wiseguy** - Lighting Engine is available on a separate branch ([base/lighting-engine](https://github.com/Reonu/HackerSM64/tree/base/lighting-engine)). Instructions on how to use it are in the readme of that branch. From d3b0b090e89f27d71b3093b24effd1f749ce52a3 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sat, 10 Feb 2024 21:29:35 -0500 Subject: [PATCH 20/30] feedback --- src/boot/main.c | 3 +-- src/game/game_init.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/boot/main.c b/src/boot/main.c index 9b49bf6ca4..501f1688bd 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -73,7 +73,7 @@ s8 gResetTimer = 0; s8 gNmiResetBarsTimer = 0; s8 gDebugLevelSelect = FALSE; -#if defined(F3DEX_GBI_3) +#ifdef F3DEX_GBI_3 volatile u32 gRSPGfxRDPWaitCycles; volatile u16 gRSPGfxCommandsSampledGclkActive; volatile u16 gRSPGfxCommandCount; @@ -106,7 +106,6 @@ UNUSED void handle_debug_key_sequences(void) { #endif #if F3DEX_GBI_3 > 1 - #include "game/print.h" static void display_rsp_counters(void) { diff --git a/src/game/game_init.c b/src/game/game_init.c index b6f2d7b129..fb8c95cc90 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -287,42 +287,42 @@ void create_gfx_task_structure(void) { gGfxSPTask->task.t.ucode_data = gspL3DEX2_fifoDataStart; gGfxSPTask->task.t.ucode_size = ((u8 *) gspL3DEX2_fifoTextEnd - (u8 *) gspL3DEX2_fifoTextStart); gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspL3DEX2_fifoDataEnd - (u8 *) gspL3DEX2_fifoDataStart); -#elif F3DZEX_GBI_2 +#elif defined(F3DZEX_GBI_2) gGfxSPTask->task.t.ucode = gspF3DZEX2_PosLight_fifoTextStart; gGfxSPTask->task.t.ucode_data = gspF3DZEX2_PosLight_fifoDataStart; gGfxSPTask->task.t.ucode_size = ((u8 *) gspF3DZEX2_PosLight_fifoTextEnd - (u8 *) gspF3DZEX2_PosLight_fifoTextStart); gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspF3DZEX2_PosLight_fifoDataEnd - (u8 *) gspF3DZEX2_PosLight_fifoDataStart); -#elif F3DZEX_NON_GBI_2 +#elif defined(F3DZEX_NON_GBI_2) gGfxSPTask->task.t.ucode = gspF3DZEX2_NoN_PosLight_fifoTextStart; gGfxSPTask->task.t.ucode_data = gspF3DZEX2_NoN_PosLight_fifoDataStart; gGfxSPTask->task.t.ucode_size = ((u8 *) gspF3DZEX2_NoN_PosLight_fifoTextEnd - (u8 *) gspF3DZEX2_NoN_PosLight_fifoTextStart); gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspF3DZEX2_NoN_PosLight_fifoDataEnd - (u8 *) gspF3DZEX2_NoN_PosLight_fifoDataStart); -#elif F3DEX2PL_GBI +#elif defined(F3DEX2PL_GBI) gGfxSPTask->task.t.ucode = gspF3DEX2_PosLight_fifoTextStart; gGfxSPTask->task.t.ucode_data = gspF3DEX2_PosLight_fifoDataStart; gGfxSPTask->task.t.ucode_size = ((u8 *) gspF3DEX2_PosLight_fifoTextEnd - (u8 *) gspF3DEX2_PosLight_fifoTextStart); gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspF3DEX2_PosLight_fifoDataEnd - (u8 *) gspF3DEX2_PosLight_fifoDataStart); -#elif F3DEX_GBI_3 +#elif defined(F3DEX_GBI_3) gGfxSPTask->task.t.ucode = gspF3DEX3_fifoTextStart; gGfxSPTask->task.t.ucode_data = gspF3DEX3_fifoDataStart; gGfxSPTask->task.t.ucode_size = ((u8 *) gspF3DEX3_fifoTextEnd - (u8 *) gspF3DEX3_fifoTextStart); gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspF3DEX3_fifoDataEnd - (u8 *) gspF3DEX3_fifoDataStart); -#elif F3DEX_GBI_2 +#elif defined(F3DEX_GBI_2) gGfxSPTask->task.t.ucode = gspF3DEX2_fifoTextStart; gGfxSPTask->task.t.ucode_data = gspF3DEX2_fifoDataStart; gGfxSPTask->task.t.ucode_size = ((u8 *) gspF3DEX2_fifoTextEnd - (u8 *) gspF3DEX2_fifoTextStart); gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspF3DEX2_fifoDataEnd - (u8 *) gspF3DEX2_fifoDataStart); -#elif F3DEX_GBI +#elif defined(F3DEX_GBI) gGfxSPTask->task.t.ucode = gspF3DEX_fifoTextStart; gGfxSPTask->task.t.ucode_data = gspF3DEX_fifoDataStart; gGfxSPTask->task.t.ucode_size = ((u8 *) gspF3DEX_fifoTextEnd - (u8 *) gspF3DEX_fifoTextStart); gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspF3DEX_fifoDataEnd - (u8 *) gspF3DEX_fifoDataStart); -#elif SUPER3D_GBI +#elif defined(SUPER3D_GBI) gGfxSPTask->task.t.ucode = gspSuper3DTextStart; gGfxSPTask->task.t.ucode_data = gspSuper3DDataStart; gGfxSPTask->task.t.ucode_size = ((u8 *) gspSuper3DTextEnd - (u8 *) gspSuper3DTextStart); gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspSuper3DDataEnd - (u8 *) gspSuper3DDataStart); -#else +#else /* Fast3D */ gGfxSPTask->task.t.ucode = gspFast3D_fifoTextStart; gGfxSPTask->task.t.ucode_data = gspFast3D_fifoDataStart; gGfxSPTask->task.t.ucode_size = ((u8 *) gspFast3D_fifoTextEnd - (u8 *) gspFast3D_fifoTextStart); From 0d58f01decbc5bbef31d46cb089f0d11d5af4ae3 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sat, 10 Feb 2024 21:35:01 -0500 Subject: [PATCH 21/30] feedback --- src/s2d_engine/init.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/s2d_engine/init.h b/src/s2d_engine/init.h index c17a23e315..741fc58eea 100644 --- a/src/s2d_engine/init.h +++ b/src/s2d_engine/init.h @@ -9,19 +9,19 @@ #ifdef L3DEX2_ALONE #define zex_text gspL3DEX2_fifoTextStart #define zex_data gspL3DEX2_fifoDataStart -#elif F3DZEX_GBI_2 +#elif defined(F3DZEX_GBI_2) #define zex_text gspF3DZEX2_PosLight_fifoTextStart #define zex_data gspF3DZEX2_PosLight_fifoDataStart #elif F3DZEX_NON_GBI_2 #define zex_text gspF3DZEX2_NoN_PosLight_fifoTextStart #define zex_data gspF3DZEX2_NoN_PosLight_fifoDataStart -#elif F3DEX2PL_GBI +#elif defined(F3DEX2PL_GBI) #define zex_text gspF3DEX2_PosLight_fifoTextStart #define zex_data gspF3DEX2_PosLight_fifoDataStart -#elif F3DEX_GBI_3 +#elif defined(F3DEX_GBI_3) #define zex_text gspF3DEX3_fifoTextStart #define zex_data gspF3DEX3_fifoDataStart -#elif F3DEX_GBI_2 +#elif defined(F3DEX_GBI_2) #define zex_text gspF3DEX2_fifoTextStart #define zex_data gspF3DEX2_fifoDataStart #else From d0be4cc0e66589f56477e32b7e4a344ebffcba9d Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sat, 10 Feb 2024 21:38:57 -0500 Subject: [PATCH 22/30] address nit --- Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 0941417128..79aff85fbb 100644 --- a/Makefile +++ b/Makefile @@ -102,23 +102,23 @@ TARGET := sm64 # f3dex3 - Upgraded F3DEX2. Great performance, but as of February 4th, 2024, it is only supported across LLE emulators and real hardware. # super3d - Extremely experimental version of Fast3D lacking many features and simplified routines for speed. -GRUCODE ?= f3dzex -$(eval $(call validate-option,GRUCODE,f3dex f3dex2 f3dex2pl f3dzex super3d l3dex2 f3dex3)) +GRUCODE ?= f3dex3 +$(eval $(call validate-option,GRUCODE,f3dex f3dex2 l3dex2 f3dex2pl f3dzex super3d f3dex3)) -ifeq ($(GRUCODE),f3dex) # Fast3DEX +ifeq ($(GRUCODE),f3dex) # F3DEX DEFINES += F3DEX_GBI=1 F3DEX_GBI_SHARED=1 -else ifeq ($(GRUCODE),f3dex2) # Fast3DEX2 +else ifeq ($(GRUCODE),f3dex2) # F3DEX2 DEFINES += F3DEX_GBI_2=1 F3DEX_GBI_SHARED=1 -else ifeq ($(GRUCODE),l3dex2) # Line3DEX2 +else ifeq ($(GRUCODE),l3dex2) # L3DEX2 DEFINES += L3DEX2_GBI=1 L3DEX2_ALONE=1 F3DEX_GBI_2=1 F3DEX_GBI_SHARED=1 -else ifeq ($(GRUCODE),f3dex2pl) # Fast3DEX2_PosLight +else ifeq ($(GRUCODE),f3dex2pl) # F3DEX2_PosLight DEFINES += F3DEX2PL_GBI=1 F3DEX_GBI_2=1 F3DEX_GBI_SHARED=1 -else ifeq ($(GRUCODE),f3dzex) # Fast3DZEX (2.08J / Animal Forest - Dōbutsu no Mori) +else ifeq ($(GRUCODE),f3dzex) # F3DZEX (2.08J / Animal Forest - Dōbutsu no Mori) DEFINES += F3DZEX_NON_GBI_2=1 F3DEX_GBI_2=1 F3DEX_GBI_SHARED=1 else ifeq ($(GRUCODE),super3d) # Super3D $(warning Super3D is experimental. Try at your own risk.) DEFINES += SUPER3D_GBI=1 F3D_NEW=1 -else ifeq ($(GRUCODE),f3dex3) # Fast3DEX3 +else ifeq ($(GRUCODE),f3dex3) # F3DEX3 DEFINES += F3DEX_GBI_3=1 F3DEX_GBI_SHARED=1 $(warning F3DEX3 is experimental, and as of February 4th, 2024, only fully works on a real Nintendo 64 or with low level emulation (LLE) (i.e. NOT PROJECT64 1.6). Try at your own risk and please inform your audience to avoid compatibility problems.) $(warning Failure to change emulator settings CAN CAUSE YOUR GAME TO CRASH!) From f038e4b60d3c6a2b7d3499da2503dde2b1f75ea4 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sat, 10 Feb 2024 21:58:08 -0500 Subject: [PATCH 23/30] branding changes in rsp ld includes --- rspdata.inc.ld | 26 +++++++++++++------------- rsptext.inc.ld | 26 +++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/rspdata.inc.ld b/rspdata.inc.ld index 55a1f99f22..f674648561 100644 --- a/rspdata.inc.ld +++ b/rspdata.inc.ld @@ -8,7 +8,7 @@ #if SUPER3D_GBI == 1 lib/PR/super3d/fifo/gspSuper3D.o(.data); #endif -#else /* Use one of the Fast3DEX series grucodes. */ +#else /* Use one of the F3DEX series grucodes. */ #ifndef F3DZEX_GBI_2 #if F3DEX_GBI_3 == 1 lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.data); @@ -34,27 +34,27 @@ * by the G_LOAD_UCODE (gSPLoadUCode/gSPLoadUCodeL) command. */ -/* Fast3DEX NoN Data */ +/* F3DEX NoN Data */ #ifdef F3DEX_NON_GBI lib/PR/f3dex/fifo/gspF3DEX.NoN.fifo.o(.data); #endif -/* Fast3DLX Data */ +/* F3DLX Data */ #ifdef F3DLX_GBI lib/PR/f3dex/fifo/gspF3DLX.fifo.o(.data); #endif -/* Fast3DLX NoN Data */ +/* F3DLX NoN Data */ #ifdef F3DLX_NON_GBI lib/PR/f3dex/fifo/gspF3DLX.NoN.fifo.o(.data); #endif -/* Fast3DLX Rej Data */ +/* F3DLX Rej Data */ #ifdef F3DLX_REJ_GBI lib/PR/f3dex/fifo/gspF3DLX.Rej.fifo.o(.data); #endif -/* Line3DEX Data */ +/* L3DEX Data */ #ifdef L3DEX_GBI lib/PR/f3dex/fifo/gspL3DEX.fifo.o(.data); #endif @@ -64,34 +64,34 @@ lib/PR/s2dex/fifo/gspS2DEX.fifo.o(.data); #endif -/* Fast3DEX2 series */ +/* F3DEX2 series */ -/* Fast3DEX2 NoN Data */ +/* F3DEX2 NoN Data */ #ifdef F3DEX2_NON_GBI lib/PR/f3dex2/fifo/gspF3DEX2.NoN.fifo.o(.data); #endif -/* Fast3DZEX NoN Data */ +/* F3DZEX NoN Data */ #ifdef F3DZEX_NON_GBI_2 BUILD_DIR/lib/gspF3DZEX2.NoN_PosLight.fifo.o(.data); #endif -/* Fast3DEX2 Rej Data */ +/* F3DEX2 Rej Data */ #ifdef F3DEX2_REJ_GBI lib/PR/f3dex2/fifo/gspF3DEX2.Rej.fifo.o(.data); #endif -/* Fast3DLX2 Rej Data */ +/* F3DLX2 Rej Data */ #ifdef F3DLX2_REJ_GBI lib/PR/f3dex2/fifo/gspF3DLX2.Rej.fifo.o(.data); #endif -/* Line3DEX2 Data */ +/* L3DEX2 Data */ #ifdef L3DEX2_GBI lib/PR/f3dex2/fifo/gspL3DEX2.fifo.o(.data); #endif -/* Line3DZEX Data */ +/* L3DZEX Data */ #ifdef L3DZEX_GBI BUILD_DIR/lib/gspL3DZEX2_PosLight.fifo.o(.data); #endif diff --git a/rsptext.inc.ld b/rsptext.inc.ld index e1c684b41a..5073c67c14 100644 --- a/rsptext.inc.ld +++ b/rsptext.inc.ld @@ -8,7 +8,7 @@ #if SUPER3D_GBI == 1 lib/PR/super3d/fifo/gspSuper3D.o(.text); #endif -#else /* Use one of the Fast3DEX series grucodes. */ +#else /* Use one of the F3DEX series grucodes. */ #ifndef F3DZEX_GBI_2 #if F3DEX_GBI_3 == 1 lib/PR/f3dex3/fifo/gspF3DEX3.fifo.o(.text); @@ -34,27 +34,27 @@ * by the G_LOAD_UCODE (gSPLoadUCode/gSPLoadUCodeL) command. */ -/* Fast3DEX NoN Text */ +/* F3DEX NoN Text */ #ifdef F3DEX_NON_GBI lib/PR/f3dex/fifo/gspF3DEX.NoN.fifo.o(.text); #endif -/* Fast3DLX Text */ +/* F3DLX Text */ #ifdef F3DLX_GBI lib/PR/f3dex/fifo/gspF3DLX.fifo.o(.text); #endif -/* Fast3DLX NoN Text */ +/* F3DLX NoN Text */ #ifdef F3DLX_NON_GBI lib/PR/f3dex/fifo/gspF3DLX.NoN.fifo.o(.text); #endif -/* Fast3DLX Rej Text */ +/* F3DLX Rej Text */ #ifdef F3DLX_REJ_GBI lib/PR/f3dex/fifo/gspF3DLX.Rej.fifo.o(.text); #endif -/* Line3DEX Text */ +/* L3DEX Text */ #ifdef L3DEX_GBI lib/PR/f3dex/fifo/gspL3DEX.fifo.o(.text); #endif @@ -64,34 +64,34 @@ lib/PR/s2dex/fifo/gspS2DEX.fifo.o(.text); #endif -/* Fast3DEX2 series */ +/* F3DEX2 series */ -/* Fast3DEX2 NoN Text */ +/* F3DEX2 NoN Text */ #ifdef F3DEX2_NON_GBI lib/PR/f3dex2/fifo/gspF3DEX2.NoN.fifo.o(.text); #endif -/* Fast3DZEX NoN Text */ +/* F3DZEX NoN Text */ #ifdef F3DZEX_NON_GBI_2 BUILD_DIR/lib/gspF3DZEX2.NoN_PosLight.fifo.o(.text); #endif -/* Fast3DEX2 Rej Text */ +/* F3DEX2 Rej Text */ #ifdef F3DEX2_REJ_GBI lib/PR/f3dex2/fifo/gspF3DEX2.Rej.fifo.o(.text); #endif -/* Fast3DLX2 Rej Text */ +/* F3DLX2 Rej Text */ #ifdef F3DLX2_REJ_GBI lib/PR/f3dex2/fifo/gspF3DLX2.Rej.fifo.o(.text); #endif -/* Line3DEX2 Text */ +/* L3DEX2 Text */ #ifdef L3DEX2_GBI lib/PR/f3dex2/fifo/gspL3DEX2.fifo.o(.text); #endif -/* Line3DZEX Text */ +/* L3DZEX Text */ #ifdef L3DZEX_GBI BUILD_DIR/lib/gspL3DZEX2_PosLight.fifo.o(.text); #endif From f88e1e8b6c5895a782cd8a66ef8bd65f9d4c7d12 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sat, 10 Feb 2024 22:01:50 -0500 Subject: [PATCH 24/30] corrected --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 79aff85fbb..318726edd4 100644 --- a/Makefile +++ b/Makefile @@ -102,7 +102,7 @@ TARGET := sm64 # f3dex3 - Upgraded F3DEX2. Great performance, but as of February 4th, 2024, it is only supported across LLE emulators and real hardware. # super3d - Extremely experimental version of Fast3D lacking many features and simplified routines for speed. -GRUCODE ?= f3dex3 +GRUCODE ?= f3dzex $(eval $(call validate-option,GRUCODE,f3dex f3dex2 l3dex2 f3dex2pl f3dzex super3d f3dex3)) ifeq ($(GRUCODE),f3dex) # F3DEX From f8dfbf4ad992b57b5bae8f97e43f91167d10105c Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Mon, 12 Feb 2024 23:23:13 -0500 Subject: [PATCH 25/30] nit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b700bcd61..afe5b5f09c 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ This is a fork of the ultrasm64 repo by CrashOveride which includes the followin Thanks to Frame#5375 and AloXado320 for also helping with silhouette stuff **F3DEX3 by Sauraen** -- F3DEX3 adds several upgrades to the original F3DEX2 microcode. You can enable it by setting `grucode` equal to `f3dex3`. In code, this can be detected by checking for F3DEX_GBI_3 during build. Variants of the F3DEX3 microcode can be enabled by defining `F3DEX_GBI_3`'s value as `2` or `3` (via ccflag in the makefile) for increased profiling capability, or increased profiling capability and a normals debugging tool respectively. Please read the [F3DEX3 README.md](https://github.com/HackerN64/F3DEX3/blob/main/README.md) before using. +- F3DEX3 adds several upgrades to the original F3DEX2 microcode. You can enable it by setting the `GRUCODE` equal to `f3dex3`. In code, this can be detected by checking for F3DEX_GBI_3 during build. Variants of the F3DEX3 microcode can be enabled by defining `F3DEX_GBI_3`'s value as `2` or `3` (via the ccflag set for `GRUCODE=f3dex3` in the makefile) for increased profiling capability, or increased profiling capability and a normals debugging tool respectively. Please read the [F3DEX3 README.md](https://github.com/HackerN64/F3DEX3/blob/main/README.md) before using. **Lighting Engine by Wiseguy** - Lighting Engine is available on a separate branch ([base/lighting-engine](https://github.com/Reonu/HackerSM64/tree/base/lighting-engine)). Instructions on how to use it are in the readme of that branch. From d29eba97cfd29537db154994f6cc6da512b4d723 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Mon, 12 Feb 2024 23:26:57 -0500 Subject: [PATCH 26/30] nit 2: the sequel --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index afe5b5f09c..3c760690cf 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ This is a fork of the ultrasm64 repo by CrashOveride which includes the followin Thanks to Frame#5375 and AloXado320 for also helping with silhouette stuff **F3DEX3 by Sauraen** -- F3DEX3 adds several upgrades to the original F3DEX2 microcode. You can enable it by setting the `GRUCODE` equal to `f3dex3`. In code, this can be detected by checking for F3DEX_GBI_3 during build. Variants of the F3DEX3 microcode can be enabled by defining `F3DEX_GBI_3`'s value as `2` or `3` (via the ccflag set for `GRUCODE=f3dex3` in the makefile) for increased profiling capability, or increased profiling capability and a normals debugging tool respectively. Please read the [F3DEX3 README.md](https://github.com/HackerN64/F3DEX3/blob/main/README.md) before using. +- F3DEX3 adds several upgrades to the original F3DEX2 microcode. You can enable it by setting the `GRUCODE` makefile variable equal to `f3dex3`. In code, this can be detected by checking for F3DEX_GBI_3 being defined during build. Variants of the F3DEX3 microcode can be enabled by defining `F3DEX_GBI_3`'s value as `2` or `3` (via the ccflag set for `GRUCODE=f3dex3` in the makefile) for increased profiling capability, or increased profiling capability and a normals debugging tool respectively. Please read the [F3DEX3 README.md](https://github.com/HackerN64/F3DEX3/blob/main/README.md) before using. **Lighting Engine by Wiseguy** - Lighting Engine is available on a separate branch ([base/lighting-engine](https://github.com/Reonu/HackerSM64/tree/base/lighting-engine)). Instructions on how to use it are in the readme of that branch. From fb32b9d5499e7b33b84489b757b9c8c45f9da61c Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Wed, 14 Feb 2024 00:20:32 -0500 Subject: [PATCH 27/30] nit 3: the sequel to nit 2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 318726edd4..83a1d6a16c 100644 --- a/Makefile +++ b/Makefile @@ -103,7 +103,7 @@ TARGET := sm64 # super3d - Extremely experimental version of Fast3D lacking many features and simplified routines for speed. GRUCODE ?= f3dzex -$(eval $(call validate-option,GRUCODE,f3dex f3dex2 l3dex2 f3dex2pl f3dzex super3d f3dex3)) +$(eval $(call validate-option,GRUCODE,f3dex f3dex2 l3dex2 f3dex2pl f3dzex f3dex3 super3d)) ifeq ($(GRUCODE),f3dex) # F3DEX DEFINES += F3DEX_GBI=1 F3DEX_GBI_SHARED=1 From 74a794a979c52d75fc8d43c4645d8134718ad692 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Wed, 14 Feb 2024 00:27:21 -0500 Subject: [PATCH 28/30] holy shit how many takes does changing a comment take --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 83a1d6a16c..4fdae7e78e 100644 --- a/Makefile +++ b/Makefile @@ -99,11 +99,11 @@ TARGET := sm64 # f3dex2 - Upgraded F3DEX. Good performance and widely supported across almost all emulators. # l3dex2 - F3DEX2 version that only renders in wireframe. # f3dzex - Newer, experimental microcode based on F3DEX2 used in Animal Crossing and Zelda 64. This is the HackerSM64 default. -# f3dex3 - Upgraded F3DEX2. Great performance, but as of February 4th, 2024, it is only supported across LLE emulators and real hardware. # super3d - Extremely experimental version of Fast3D lacking many features and simplified routines for speed. +# f3dex3 - Upgraded F3DEX2. Great performance, but as of February 4th, 2024, it is only supported across LLE emulators and real hardware. GRUCODE ?= f3dzex -$(eval $(call validate-option,GRUCODE,f3dex f3dex2 l3dex2 f3dex2pl f3dzex f3dex3 super3d)) +$(eval $(call validate-option,GRUCODE,f3dex f3dex2 l3dex2 f3dex2pl f3dzex super3d f3dex3)) ifeq ($(GRUCODE),f3dex) # F3DEX DEFINES += F3DEX_GBI=1 F3DEX_GBI_SHARED=1 From e1d4a034bbba736a9dfcb7ecfeed0a965055fe2a Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Wed, 14 Feb 2024 00:31:31 -0500 Subject: [PATCH 29/30] remove experimental for zex --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4fdae7e78e..6eb273eebc 100644 --- a/Makefile +++ b/Makefile @@ -98,7 +98,7 @@ TARGET := sm64 # f3dex - Upgraded Fast3D. Offers worse performance than F3DEX2, but has a more precise z-buffer. # f3dex2 - Upgraded F3DEX. Good performance and widely supported across almost all emulators. # l3dex2 - F3DEX2 version that only renders in wireframe. -# f3dzex - Newer, experimental microcode based on F3DEX2 used in Animal Crossing and Zelda 64. This is the HackerSM64 default. +# f3dzex - Newer microcode based on F3DEX2 used in Animal Crossing and Zelda 64. This is the HackerSM64 default. # super3d - Extremely experimental version of Fast3D lacking many features and simplified routines for speed. # f3dex3 - Upgraded F3DEX2. Great performance, but as of February 4th, 2024, it is only supported across LLE emulators and real hardware. From 073be50514116e9d330a7a4890dbb500dcdf4729 Mon Sep 17 00:00:00 2001 From: mountainflaw <2198256-mountainflaw@users.noreply.gitlab.com> Date: Sun, 18 Feb 2024 22:11:50 -0500 Subject: [PATCH 30/30] use glakitustate for cam pos --- src/game/rendering_graph_node.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 2ff99bc9f2..b6c7c4ab50 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -1372,15 +1372,9 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) #ifdef F3DEX_GBI_3 camWorld = alloc_display_list(sizeof(PlainVtx)); - if (gCurGraphNodeCamera != NULL) { - camWorld->c.pos[0] = gCurGraphNodeCamera->pos[0]; - camWorld->c.pos[1] = gCurGraphNodeCamera->pos[1]; - camWorld->c.pos[2] = gCurGraphNodeCamera->pos[2]; - } else { - camWorld->c.pos[0] = 0; - camWorld->c.pos[1] = 0; - camWorld->c.pos[2] = 0; - } + camWorld->c.pos[0] = gLakituState.pos[0]; + camWorld->c.pos[1] = gLakituState.pos[1]; + camWorld->c.pos[2] = gLakituState.pos[2]; #endif gMatStackIndex = 0;