mirror of
https://github.com/emu-russia/pureikyubu.git
synced 2025-04-02 10:42:15 -04:00
Docs: New TODO moved to EMU, old renamed to old_todo Docs: Old coding style is deprecated (old_style.txt) Docs: Removed mention about CubeDocumented and fixed old emails RE: boot.s, proved first asm line (lis instruction parameter) RE: Added PAL and NTSC Boot and IPL IDA files RE: Some work on NTSC IPL (identified many lib calls, including OS, GX) RE: Added EXI Bootrom descrambler by segher RE: GXInit RE: Internal GX lib structures (GXPrivate.h) RE: More details on lomem (OS versions) RE: OSInit and OS.c RE: OSAlloc (heap allocator) RE: Very first code of Metrowerk runtime (__start.c) Docs: Added copy of http://gcdev.narod.ru Source\Utils: Command processor (Cmd.c) Source\Utils: File wrapper Source\Utils: Gekko disasm cleaned up and ported to plain C Source\Utils: Double-linked lists Source\Utils: Ported old Profiler code Source\Utils: String utils
179 lines
7.6 KiB
Text
179 lines
7.6 KiB
Text
--------------------------------------------------------------------------
|
|
GC FIFO Details.
|
|
--------------------------------------------------------------------------
|
|
|
|
This document was created, after hard reversing of GX fifo module. It was
|
|
not easy to handle whole thing, but I made it :) Hope it will be useful
|
|
for all, who was stuck on GX fifo.
|
|
|
|
Send your comments or questions to ogamespec@gmail.com
|
|
|
|
--------------------------------------------------------------------------
|
|
|
|
Thats how I understand GC graphics fifo logic.
|
|
|
|
There are two fifos : CPU (PI) and GP (CP). They are both implemented as
|
|
hardware circular buffers, and each fifo has its own registers set.
|
|
|
|
CP registers are used to control GP fifo flow and PI registers are used
|
|
for CPU fifo.
|
|
|
|
Fifos can run in two modes: immediate and multibuffer. CPU fifo is used
|
|
together with GP fifo in multibuffer mode to imitate N64 double-buffered
|
|
display lists, for easy N64's games porting.
|
|
|
|
Immediate fifo mode is same as "linked" fifo mode.
|
|
|
|
Details of GP Fifo
|
|
------------------
|
|
|
|
Important detail : GP command proccessor (which is inside ArtX GP logic,
|
|
not 'CP' interface) always reading data by 32-byte chunks. Im pretty sure,
|
|
that it doesnt matter, when sent 32-byte "packet" is teared in middle
|
|
of it, as example 'float' vertex X-position data. GP will stalls all
|
|
commands execution, until it get full set of current primitive or its
|
|
parameters. I dont think, that it has cache for big primitives, like
|
|
triangle-strips, its just stalls, until dont get whole current vertex
|
|
data to render. But Im sure, emulators can collect whole single primitive
|
|
in accumulation buffer to draw it all at once - it will be much faster :)
|
|
|
|
The 'read idle' and 'command idle' bits are showing GP state. When GP
|
|
have no new data to read - 'read idle' is set. And when GP command processor
|
|
is not busy by drawing primitive, or executing command, 'command idle' is
|
|
set. When both bits are cleared, then GP is free and ready for action.
|
|
Note : 'read idle' can be set in breakpoint condition, when GP stalls
|
|
until breakpoint is not cleared.
|
|
|
|
If 'GP read' bit enabled in CP control register, GP logic starts to read
|
|
fifo data by 32-byte chunks, using CP read pointer. When CP read pointer
|
|
wraps 'top' address, it automatically changes back to 'base'. No interrupts
|
|
generated.
|
|
|
|
If 'GP link' bit enabled in CP CR, following features are become enabled :
|
|
breakpoint, low watermark and high watermark. These features are used only
|
|
in immediate ('linked') mode.
|
|
|
|
Conditions for immediate fifo mode :
|
|
|
|
Breakpoint : if CP read pointer reaches breakpoint address, CP generates
|
|
breakpoint interrupt. GP stops reading fifo data, until breakpoint is not
|
|
cleared. Actually this condition can be set even in multibuffer mode, but
|
|
there is no reason to use it.
|
|
|
|
Low watermark : if CP read pointer reaches low watermark address, CP
|
|
generates low watermark interrupt.
|
|
|
|
High watermark : if CP write pointer reaches high watermark address, CP
|
|
generates high watermark interrupt.
|
|
|
|
Watermarks are used to sync GP and CPU. When high watermark is asserted,
|
|
CPU is stopping to write any commands/data to fifo, until GP reading it.
|
|
And when GP reaches low watermark, CPU will continue to write data. It is
|
|
also used to protect fifo data to be overwritten by CPU. On real hardware
|
|
GP reading will never overdrive CPU writing, so they work finely together
|
|
in single circular fifo buffer.
|
|
|
|
When CP write pointer wraps its 'top' address, it automatically changes
|
|
back to 'base'. No interrupts generated. Actually CP write pointer is dummy
|
|
in fifo processing, because GP can only read data, its used only to
|
|
calculate CP fifo "stride" = wrptr - rdptr. I believe, CP write pointer
|
|
is always the same as PI write pointer in immediate mode.
|
|
|
|
All pointers should be 32-byte aligned, when set.
|
|
|
|
Details of CPU Fifo
|
|
-------------------
|
|
|
|
CPU Fifo is used only to write data. The application of CPU fifo is to
|
|
create display lists, while GP is executing others from CP fifo (in
|
|
multibuffer mode).
|
|
|
|
When CPU fifo wraps the top fifo buffer, special 'wrap' bit is setting
|
|
in PI write pointer register. When CPU writes any new fifo data after
|
|
wrap, this bit is cleared. No interrupts generated.
|
|
|
|
All pointers should be 32-byte aligned, when set.
|
|
|
|
Application of write gather buffer
|
|
----------------------------------
|
|
|
|
Write gather buffer is used to collect and then quickly blast 32-byte
|
|
memory chunks, during any CPU writes. Thats why all fifo's are aligned
|
|
to 32-byte boundary. See YAGCD or any other Gekko manuals for more
|
|
information about it.
|
|
|
|
There are two applications for gather buffer. In first case it is used
|
|
together with PI fifo, otherwise it is assigned to be "redirected" and
|
|
used for other purposes. When its pointed to 0x0C008000, its said, that
|
|
gather buffer is not redirected. Well, I havent seen yet, that gather
|
|
buffer was redirected by any programs, and you can think, that its used
|
|
only together with 0x0C008000.
|
|
|
|
So whats exactly 0x0C008000 (or 0xCC008000, when used with Dolphin OS) ?
|
|
Thats simply hardware "pointer to pointer". When you're writing any
|
|
data through the bus to this address, Flipper hardware (PI) is redirecting
|
|
all writes to PI write pointer, and controlling further fifo flow. So
|
|
programmer dont need to care about increasing pointers, wrapping fifo
|
|
from the top to begin etc.
|
|
|
|
--------------------------------------------------------------------------
|
|
|
|
Appendix : Hardware registers.
|
|
|
|
Related hardware registers and bit layouts (cut from Dolwin source code) :
|
|
|
|
// CP registers (16-bit access)
|
|
#define CP_SR (0x0C000000)
|
|
#define CP_CR (0x0C000002)
|
|
#define CP_CLR (0x0C000004)
|
|
#define CP_BASE (0x0C000020)
|
|
#define CP_TOP (0x0C000024)
|
|
#define CP_HIWMARK (0x0C000028)
|
|
#define CP_LOWMARK (0x0C00002C)
|
|
#define CP_CNT (0x0C000030)
|
|
#define CP_WRPTR (0x0C000034)
|
|
#define CP_RDPTR (0x0C000038)
|
|
#define CP_BPPTR (0x0C00003C)
|
|
|
|
// PI registers (32-bit access)
|
|
#define PI_BASE (0x0C00300C)
|
|
#define PI_TOP (0x0C003010)
|
|
#define PI_WRPTR (0x0C003014)
|
|
|
|
// CP status register
|
|
#define CP_SR_OVF (1 << 0)
|
|
#define CP_SR_UVF (1 << 1)
|
|
#define CP_SR_RD_IDLE (1 << 2) // read idle
|
|
#define CP_SR_CMD_IDLE (1 << 3) // command idle
|
|
#define CP_SR_BPINT (1 << 4)
|
|
|
|
// CP control register
|
|
#define CP_CR_RDEN (1 << 0)
|
|
#define CP_CR_BPCLR (1 << 1)
|
|
#define CP_CR_OVFEN (1 << 2)
|
|
#define CP_CR_UVFEN (1 << 3)
|
|
#define CP_CR_LINK (1 << 4)
|
|
#define CP_CR_BPEN (1 << 5)
|
|
|
|
// CP clear register
|
|
#define CP_CLR_OVFCLR (1 << 0)
|
|
#define CP_CLR_UVFCLR (1 << 1)
|
|
|
|
// PE status register
|
|
#define PE_SR_DONE (1 << 0)
|
|
#define PE_SR_TOKEN (1 << 1)
|
|
#define PE_SR_DONEMSK (1 << 2)
|
|
#define PE_SR_TOKENMSK (1 << 3)
|
|
|
|
// PI wrap bit
|
|
#define PI_WRPTR_WRAP (1 << 27)
|
|
|
|
--------------------------------------------------------------------------
|
|
|
|
Referencies :
|
|
|
|
gxfifo.txt - GX fifo module reversing.
|
|
tips.txt - For fifo emulation tips.
|
|
|
|
This document is maintaining by Dolwin team.
|
|
Last edited by org, 16 Aug 2004
|