A frame rendering is achieved by creating a display list for everything that needs to be drawn for that frame. The completed display list is broken down into 4 different display lists:
- WORK_DISP - Seems to only branch directly to POLY_OPA_DISP
- POLY_OPA_DISP - Contains display lists for 3D polys/models without translucency(Opaque). Branches to POLY_XLU_DISP.
- POLY_XLU_DISP - Contains display lists for 3D polys/models with translucency. Branches to OVERLAY_DISP.
- OVERLAY_DISP - Contains display lists for 2D elements (like UI) that are overlaid over everything else.
These four display lists have their own buffers, which can be used to write display list commands programmatically. To do so, each has a "append start" pointer and "append end" pointer, as seen in the table below. The "append start" pointer points to the next free spot for display list commands. In order to append a new display list, you simply write your instructions starting at the "append start" pointer, then increment the pointer past your instructions. The "append end" pointer points to the address past the end of the remaining buffer. This pointer is used to append data for commands that are programmatically set during that frame. For example, the perspective and camera matrices (used to transform 3D models to a 2D space) change every frame. To add the matrix data, the "append end" address is decremented by 0x40 (the size of the matrix), then the matrix is stored at the new "append end" address.
Display list buffers should only be used to store instructions that cannot be pre-computed beforehand, since otherwise you'll be wasting CPU, time, and the limited buffer space.
At Game Struct + 0x00 within all Game States is a pointer to a struct located on the "graph" thread stack that contains data used to assist in rendering.
|0000||ptr||Working POLY_OPA_DISP start|
|0004||ptr||Working POLY_XLU_DISP start|
|0014||ptr||Working OVERLAY_DISP start|
|0038||OSMesg||?||Referenced by 005C OsMesgQueue|
|005C||OSMesgQueue||?||First OSMesg at 0038|
|Next 0x40 bytes transferred to RCP DMEM addr 0xFC0|
|0088||int||?, set to 1|
|008C||int||?, set to 4|
|0094||int||Microcode Length||Length in bytes of the microcode sequence referenced by 0090|
|0098||ptr||Microcode Ptr||?, possibly F3DZEX|
|009C||int||Microcode Length?||likely for for sequence referenced by 0098|
|00A0||ptr||Possibly DMEM Data Ptr||801145C0, likely transferred into DMEM.|
|00A4||int||?, set to 0x800||possibly DMEM transfer size?|
|00A8||ptr||?, set to 8016A240|
|00AC||int||?, set to 0x400|
|00B0||int||?, set to 80151640|
|00B4||int||?, set to 80169640|
|00B8||ptr||Completed WORK_DISP Start||branches to the DList task the RCP should be working on this cycle|
|00BC||int||Completed WORK_DISP Size|
|00C0||ptr||Unknown Buffer (0xC00) Start||mdump'ed as binary data. All 0s possibly due to emulation|
|00C4||int||Unknown Buffer (0xC00) Size|
|End RCP DMEM Transfer Struct|
|01B0||ptr||Working WORK_DISP Start|
|01BC||ptr||WORK_DISP append address||Used to append microcode instructions to the pipeline|
|01C0||ptr||WORK_DISP append end address||Used to store extra instruction data (matrix/movemem commands)|
|02A8||int||OVERLAY_DISP Size||0x2000 bytes|
|02B0||ptr||OVERLAY_DISP append address||Used to append microcode instructions to the pipeline|
|02B4||ptr||OVERLAY_DISP append end address||Used to store extra instruction data (matrix/movemem commands)|
|02B8||int||POLY_OPA_DISP Size||0xBF00 bytes|
|02C0||ptr||POLY_OPA_DISP append address||Used to append microcode instructions to the pipeline|
|02C4||ptr||POLY_OPA_DISP append end address||Used to store extra instruction data (matrix/movemem commands)|
|02C8||int||POLY_XLU_DISP Size||0x4000 bytes|
|02D0||ptr||POLY_XLU_DISP append address||Used to append microcode instructions to the pipeline|
|02D4||ptr||POLY_XLU_DISP append end address||Used to store extra instruction data (matrix/movemem commands)|
|02D8||int||Frame Counter 1||Used for swapping display list buffers|
|02E8||int||Frame Counter 2||Used for swapping framebuffers|