GPUSTAT and GPUREAD: Difference between revisions
| Revision as of 02:32, 23 October 2026 RemmyLee (CLAUDE.md, CONTEXT.md: the gate skips doc-slop's length and lede rules) | Revision as of 02:43, 23 October 2026 RemmyLee (GPU at register depth: GP0, GP1, GPUSTAT, VRAM, rendering, T-cache, video timing) | ||
| Line 1: | Line 1: | ||
| + | --- | ||
| + | title: GPUSTAT and GPUREAD | ||
| + | type: register | ||
| + | summary: Status register and read port of the GPU at 0x1F801814 and 0x1F801810. | ||
| + | category: Hardware | ||
| + | category: GPU | ||
| + | --- | ||
| + | |||
| + | ## Summary | ||
| + | |||
| + | The [GPU](/hardware/gpu/) has two I/O ports. A read from 0x1F801814 (GP1) returns the status register, called GPUSTAT here, and a read from 0x1F801810 (GP0) returns GPUREAD, which receives the data of GP0(C0h) and the registers selected by GP1(10h).[^spx-io] GPUSTAT shows most of the settings made by GP0(E1h), GP0(E6h) and [GP1 commands](/hardware/gpu/gp1/), together with the FIFO, DMA and interlace state.[^spx-stat] | ||
| + | |||
| + | Table: GPUSTAT fields | ||
| + | |||
| + | | Bits | Name | Content | Set by | | ||
| + | | --- | --- | --- | --- | | ||
| + | | 0 to 3 | TBX | Texture page X base (N x 64) | GP0(E1h) bits 0 to 3 | | ||
| + | | 4 | TBY | Texture page Y base 1 (N x 256) | GP0(E1h) bit 4 | | ||
| + | | 5 to 6 | ABR | Semi-transparency (0 = B/2+F/2, 1 = B+F, 2 = B-F, 3 = B+F/4) | GP0(E1h) bits 5 to 6 | | ||
| + | | 7 to 8 | TPF | Texture page colors (0 = 4-bit, 1 = 8-bit, 2 = 15-bit) | GP0(E1h) bits 7 to 8 | | ||
| + | | 9 | DTD | Dither 24-bit to 15-bit (0 = off, 1 = on) | GP0(E1h) bit 9 | | ||
| + | | 10 | DFE | Drawing to display area (0 = prohibited, 1 = allowed) | GP0(E1h) bit 10 | | ||
| + | | 11 | PBW | Set mask bit when drawing (0 = no, 1 = yes) | GP0(E6h) bit 0 | | ||
| + | | 12 | PBC | Draw pixels (0 = always, 1 = not to masked areas) | GP0(E6h) bit 1 | | ||
| + | | 13 | ODE2 | Interlace field (always 1 when interlace is off) | | | ||
| + | | 14 | | Flip screen horizontally (v1 GPU only) | GP1(08h) bit 7 | | ||
| + | | 15 | TBY2 | Texture page Y base 2 (N x 512, 2 MB VRAM only) | GP0(E1h) bit 11 | | ||
| + | | 16 | HDS2 | Horizontal resolution 2 (0 = per bits 17 to 18, 1 = 368) | GP1(08h) bit 6 | | ||
| + | | 17 to 18 | HDS | Horizontal resolution 1 (0 = 256, 1 = 320, 2 = 512, 3 = 640) | GP1(08h) bits 0 to 1 | | ||
| + | | 19 | VDS | Vertical resolution (0 = 240, 1 = 480 when bit 22 is set) | GP1(08h) bit 2 | | ||
| + | | 20 | NPB | Video mode (0 = NTSC 60Hz, 1 = PAL 50Hz) | GP1(08h) bit 3 | | ||
| + | | 21 | LBS | Display area color depth (0 = 15-bit, 1 = 24-bit) | GP1(08h) bit 4 | | ||
| + | | 22 | IRS | Vertical interlace (0 = off, 1 = on) | GP1(08h) bit 5 | | ||
| + | | 23 | DMSK | Display enable (0 = enabled, 1 = disabled) | GP1(03h) bit 0 | | ||
| + | | 24 | IRQ | Interrupt request IRQ1 (0 = off, 1 = request) | GP0(1Fh), GP1(02h) | | ||
| + | | 25 | DREQ | DMA or data request, by GP1(04h) direction | | | ||
| + | | 26 | IDLE | Ready to receive a command word (0 = no, 1 = ready) | | | ||
| + | | 27 | RFFL | GP0 read FIFO full (0 = no, 1 = full) | GP0(C0h) | | ||
| + | | 28 | WFEP | GP0 write FIFO empty (0 = no, 1 = empty) | | | ||
| + | | 29 to 30 | DMD | DMA direction (0 = off, 1 = WFNF, 2 = WFEP, 3 = RFFL) | GP1(04h) bits 0 to 1 | | ||
| + | | 31 | ODE | Drawing even or odd lines in interlace mode (0 = even or vertical blank, 1 = odd) | | | ||
| + | |||
| + | The bit names are those that psx-spx takes from the debug symbols of the PlayStation 2 SDK version 2.8, which emulates this register; some of them also appear in PlayStation libraries.[^spx-stat] The GPUSTAT value after GP1(00h) is 14802000h.[^spx-reset] | ||
| + | |||
| + | ## Data Request Bit | ||
| + | |||
| + | The meaning of bit 25 depends on the DMA direction set by GP1(04h):[^spx-stat] | ||
| + | |||
| + | Table: GPUSTAT bit 25 | ||
| + | |||
| + | | GP1(04h) | Bit 25 | | ||
| + | | --- | --- | | ||
| + | | 0 | Always 0 | | ||
| + | | 1 | GP0 write FIFO not full (0 = full, 1 = not full) | | ||
| + | | 2 | Same as bit 28 | | ||
| + | | 3 | Same as bit 27 | | ||
| + | |||
| + | Bit 25 is the DMA request signal. However, it is also useful for transfers by software and in particular for the FIFO state mode (direction 1).[^spx-ready] | ||
| + | |||
| + | ## Ready Bits | ||
| + | |||
| + | Bit 28 is cleared while a command is executing, that is, once the command and all its parameters have been received. For polygon and line commands, however, it is cleared as soon as the command word arrives and before the vertices are sent. Because DMA direction 2 uses this bit as its request, a DMA transfer would probably stall if the vertices of a polygon or line were sent in a separate DMA block.[^spx-ready] | ||
| + | |||
| + | Bit 27 is set after GP0(C0h) and its parameters have been sent, and it stays set until all data words have been read; DMA direction 3 uses it as its request.[^spx-ready] Bit 26 is set when the GPU can accept a new command. When it is clear, the GPU is waiting for more parameters or data, or it is busy. Bit 26 rises briefly after each primitive, so it cannot show when the GPU has finished a whole DMA chain of primitives.[^spx-ready] | ||
| + | |||
| + | In libgpu, DrawSync(0) blocks until all requests in the queue are finished and DrawSync(1) returns the number of requests remaining.[^lo818] | ||
| + | |||
| + | ## Interlace Field | ||
| + | |||
| + | In 480-line interlaced mode bit 31 changes with each field, and in 240-line mode it changes with each scanline. It is always 0 during vertical blanking.[^spx-stat] | ||
| + | |||
| + | Sony explains why the bit matters. In interlace mode the GPU draws only the even lines while the odd field is displayed and only the odd lines while the even field is displayed, so a single buffer can be drawn while it is shown. However, during the vertical blank the GPU always treats the field as even. Primitives drawn during the vertical blank, which in Z-sorted drawing are the background, therefore reach only the even lines, and half the background is not cleared.[^lo842][^lo843] | ||
| + | |||
| + | The remedy is to start drawing after the vertical blank has ended. Libgpu provides GetODE() for this, and the function was formally introduced in library version 3.7. GetODE() returns the field that the GPU recognizes, not the field of the current video output; during the vertical blank after VSyncCallback() it returns even.[^lo843] | ||
| + | |||
| + | ## GPUREAD | ||
| + | |||
| + | GPUREAD at 0x1F801810 returns the data of a VRAM-to-CPU transfer started by GP0(C0h), or the register latched by GP1(10h). It can also be read by DMA channel 2.[^spx-io] The [GP0 transfer page](/hardware/gpu/gp0-transfer/) and the [GP1 page](/hardware/gpu/gp1/) describe the two commands. | ||
| + | |||
| + | ## References | ||
| + | |||
| + | [^spx-io]: psx-spx. Graphics Processing Unit (GPU), GPU I/O Ports (0x1f801810, 0x1f801814). https://psx-spx.consoledev.net/graphicsprocessingunitgpu/#gpu-io-ports-dma-channels-commands-vram | ||
| + | [^spx-stat]: psx-spx. Graphics Processing Unit (GPU), GPU Status Register. https://psx-spx.consoledev.net/graphicsprocessingunitgpu/#gpu-status-register | ||
| + | [^spx-ready]: psx-spx. Graphics Processing Unit (GPU), Ready Bits. https://psx-spx.consoledev.net/graphicsprocessingunitgpu/#gpu-status-register | ||
| + | [^spx-reset]: psx-spx. Graphics Processing Unit (GPU), GP1(00h) - Reset GPU. https://psx-spx.consoledev.net/graphicsprocessingunitgpu/#gpu-display-control-commands-gp1 | ||
| + | [^lo818]: Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-18. | ||
| + | [^lo842]: Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-42. | ||
| + | [^lo843]: Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 8-43, Figure 8-25. | ||