Skip to content

F3DEX Instruction Set

RenaKunisaki edited this page Apr 21, 2016 · 5 revisions

These are all known instructions interpreted by the [F3DEX] program. Many are not well understood. Much of this information is accumulated from various sources over the years. These names are probably not what most other sources use either.

Every instruction is 8 bytes; the first specifying the instruction itself, and the others being used/ignored depending on the instruction. Every instruction must be at an 8-byte-aligned RAM address.

##0x00: NOP: does nothing.

##0x01: Matrix: Set or multiply a matrix.

struct f3dex_matrix {
	uint8_t  opcode;     // 0x01
	uint8_t  unused : 5;
	uint8_t  push   : 1; //0=discard current mtx, 1=push current mtx
	uint8_t  mult   : 1; //0=multiply with current mtx, 1=replace current mtx
	uint8_t  mtx    : 1; //0=modelview mtx, 1=projection mtx
	uint16_t size;       //size of matrix data, always 0x0040
	rsp_ptr  address;    //location of matrix data.
};

The matrix data is 16 32-bit signed fixed-point scalars. The first half is the whole parts, and the second half is the fractional parts. (XXX what?)

0x02: unknown/invalid

0x03: Something to do with color/memory management.

0x04: LoadVtx: Load into vertex cache.

struct f3dex_loadvtx {
	uint8_t  opcode;     // 0x03
	uint8_t  index  : 7; //vtx cache index to load to.
	uint8_t  unused : 1;
	uint8_t  nVtxs  : 6; //number of vertices to load.
	uint16_t nBytes :10; //number of bytes to load (redundant?)
	rsp_ptr  src;        //address to load from.
};

Effectively nVtxs and nBytes together can be treated as a uint16_t which is numberOfVertices * 0x410.

0x05: unknown/invalid

0x06: CallList: Call a display list.

struct f3dex_call {
	uint8_t  opcode;     // 0x06
	uint8_t  unused[3];
	rsp_ptr  address;    //address to call.
};

0x07: unknown/invalid

0x08: unknown/invalid

0x09: Sprite2DBase

0xAF: LoadUCode: Load new microcode program.

0xB0: BranchZ

0xB1: Draw2Triangles

struct f3dex_tri2 {
	uint8_t  opcode;     // 0xB1
	uint8_t  tri1[3];    //first triangle
	uint8_t  unused;
	uint8_t  tri2[3];    //second triangle
};

Draw two triangles, which can be completely independent of eachother. The elements of tri1 and tri2 are indices into the vertex cache; specifically, the high 7 bits are the index, and the lowest bit seems to be unused.

0xB2: ModifyVertex

0xB3: RDPHalf1

0xB4: RDPHalf2

0xB5: DrawLine

struct f3dex_line {
	uint8_t  opcode;     // 0xB5
	uint8_t  unused[5];
	uint8_t  vtxs[2];
};

vtxs works the same as in Draw2Triangles.

0xB6: ClearGeometryMode

0xB7: SetGeometryMode

These set up various rendering parameters. More research is needed!

0xB8: EndList: Return from display list.

0xB9: SetOtherModeL

0xBA: SetOtherModeH

0xBB: unknown

0xBC: SetSegPtr: Set RSP segment pointers

struct f3dex_setsegptr {
	uint8_t  opcode;     // 0xBC
	uint16_t index;      //Table index * 4 (offset into segment memory)
	uint8_t  area;       //RSP RAM area to write to; 06 = segment table
	uint32_t ptr;        //The pointer to write
};

(XXX this is probably wildly incorrect)

0xBD: PopMtx: Pop matrix

struct f3dex_popmtx {
	uint8_t  opcode;     // 0xBD
	uint8_t  unused[6];
	uint8_t  which;      //0=modelview, 1=projection; upper bits likely unused
};

0xBE: CullDL

0xBF: DrawTriangle

Works just like Draw2Triangles, but only the tri2 field is used.

0xC0: RDPNOP

0xC8: TriFill

0xC9: TriFillZBuff

0xCA: TriTxtr

0xCB: TriTxtrZBuff

0xCC: TriShade

0xCD: TriShadeZBuff

0xCE: TriShadeTxtr

0xCF: TriShadeTxtrZBuff

0xE4: TexRect

struct f3dex_texrect {
	uint8_t  opcode;     // 0xE4
	uint16_t x1     :12; //top left X coord
	uint16_t y1     :12; //top left Y coord
	uint8_t  unused : 5;
	uint8_t  tile   : 3; //"tile descriptor index"
	uint16_t x2     :12; //bottom right X coord
	uint16_t y2     :12; //bottom right Y coord
	uint16_t S, T;       //top left texture cooords
	uint16_t SX, TY;     //change in S per change in X, and T per Y
};

Only case of an instruction being more than 8 bytes. Unsure what this actually does.

0xE5: TexRectFlip

0xE6: RDPLoadSync

0xE7: RDPPipeSync

0xE8: RDPTileSync

0xE9: RDPFullSync

0xEA: SetKeyGB

0xEB: SetKeyR

0xEC: SetConvert

0xED: SetScissor

0xEE: SetPrimDepth

0xEF: RDPSetOtherMode

0xF0: LoadTLUT: Load Texture LookUp Table

struct f3dex_loadtlut {
	uint8_t  opcode;     // 0xF0
	uint16_t S      :12; //Texture S coord
	uint16_t T      :12; //Texture T coord
	uint8_t  unused : 5;
	uint8_t  tile   : 3;
	uint32_t wtf    : 24; //"the s coordinate of the lower right corner of the texture tile and some sort of fixed point slope"
};

0xF2: SetTileSize

struct f3dex_settilesize {
	uint8_t  opcode;     // 0xF2
	uint16_t S1     :12; //Top left S coord
	uint16_t T1     :12; //Top left T coord
	uint8_t  unused : 5;
	uint8_t  tile   : 3;
	uint16_t S2     :12; //Bottom right S coord
	uint16_t T2     :12; //Bottom right T coord
};

0xF3: LoadBlock: Load texture data

Similar to LoadTLUT. Unclear how this works; the 5th byte seems to specify the texture width in pixels, minus one (e.g. 0x3F = 64).

0xF4: LoadTile

0xF5: SetTile: Set texture parameters

struct f3dex_settile { //byte  bits    comment
	uint8_t  opcode;     // 0  xxxxxxxx  0xF5
	uint8_t  format : 4; // 1  xxxx....
	uint8_t  size   : 2; // 1  ....xx..
	uint8_t  line   : 2; // 1  ......xx
	
	uint16_t tmem;       // 2  xxxxxxxx
	                     // 3  xxxxxxxx
	uint8_t  unused : 5; // 4  xxxxx...
	uint8_t  tile   : 3; // 4  .....xxx

	uint8_t  palette: 6; // 5  xxxxxx.. might only be 4 bits? unclear...
	uint8_t  TFlags : 2; // 5  ......xx

	uint8_t  TMask  : 6; // 6  xxxxxx..
	uint8_t  SFlags : 2; // 6  ......xx

	uint8_t  SMask  : 4; // 7  xxxx....
	uint8_t  SShift : 4; // 7  ....xxxx
};

0xF6: FillRect

struct f3dex_fillrect {
	uint8_t  opcode;     // 0xF6
	uint16_t xpos   :10;
	uint8_t  xfrac  : 2; //X position fraction
	uint8_t  unused;
	uint16_t ypos   :10;
	uint8_t  yfrac  : 2; //Y position fraction
};

My understanding is that the N64 renders with quarter-pixel accuracy (for antialiasing), so this probably specifies the pixel coordinate to draw at in the framebuffer. No idea what specifies the size; maybe two of these commands specify the corners?

0xF7: SetFillColor

0xF8: SetFogColor

0xF9: SetBlendColor

0xFA: SetPrimColor

0xFB: SetEnvColor

0xFC: SetCombine

struct f3dex_setcombine {
	uint8_t  opcode;     // 0xFC
	uint8_t  muxs0[3];
	uint8_t  muxs1[4];   //probably only 3 bytes after 1 unsued.
};

0xFD: SetTextureLoc: Set RSP address to load texture from

struct f3dex_settextureloc {
	uint8_t  opcode;     // 0xFD
	uint8_t  format : 3; //0=RGBA, 1=YUV, 2=CI, 3=IA, 4=I
	uint8_t  size   : 2;
	uint8_t  unused : 3;
	uint16_t width  :12; //always zero? notes say it's width
	rsp_ptr  address;    //address of image (64-byte aligned)
};

0xFE: SetZImg: Set Z-buffer image?

0xFF: SetCImg: Set clear image?

Clone this wiki locally