Merge branch 'master' of https://github.com/psx-spx/psx-spx.github.io
This commit is contained in:
commit
421668bbc0
@ -489,7 +489,8 @@ On power-up, the controllers are in digital mode (with analog inputs disabled).
|
||||
Analog mode can be (de-)activated manually by pushing the Analog button.
|
||||
Alternately, analog mode can be (de-)activated by software via rumble
|
||||
configuration commands (though that's supported only on newer pads; those with
|
||||
two rumble motors).<br/>
|
||||
two rumble motors). It is essential that emulators and any third-party hardware have a way of manually toggling analog mode, similar to original analog controllers, as certain games like Gran Turismo 1 will not attempt to enter analog mode on their own, even if they support analog controls and detect an analog controller.<br/>
|
||||
Since analog pads boot in digital mode and will return the same ID byte as digital controllers, the most common way of distinguishing between the 2 is to send a Dualshock-only command (Typically command 43h - enter/exit config mode) and seeing how the controller responds to it.<br/>
|
||||
The analog sticks are mechanically restricted to a "circular field of motion"
|
||||
(most joypads can reach "min/max" values only in "straight" horizontal or
|
||||
vertical directions, but not in "diagonal" directions).<br/>
|
||||
@ -604,6 +605,7 @@ slots.<br/>
|
||||
Discworld
|
||||
Discworld II: Missing Presumed...!?
|
||||
Discworld Noir
|
||||
Dracula - The Resurrection
|
||||
Dune 2000
|
||||
Final Doom
|
||||
Galaxian 3
|
||||
@ -636,7 +638,8 @@ slots.<br/>
|
||||
Z
|
||||
```
|
||||
Note: There are probably many more mouse compatible games.<br/>
|
||||
Plus: Dracula - The Resurrection<br/>
|
||||
Certain games, mostly FPS games such as Quake II and Doom, have players plug a standard digital/analog pad in port 1
|
||||
and a mouse in port 2. This way, players can use the mouse for aiming and shooting, while the pad can be used for moving, reloading, and so on.<br/>
|
||||
|
||||
#### Sony Mouse Component List
|
||||
PCB "TD-T41V/\, MITSUMI"<br/>
|
||||
@ -1354,20 +1357,6 @@ Entering configuration mode enables the DualShock rumble method and disables the
|
||||
xx=00h Stay in Normal mode
|
||||
xx=01h Enter Configuration mode
|
||||
```
|
||||
Caution: Additionally to activating configuration commands, entering config
|
||||
mode does also activate a Watchdog Timer which does reset the controller if
|
||||
there's been no communication for about 1 second or so. The watchdog timer
|
||||
remains active even when returning to normal mode via Exit Config command. The
|
||||
reset does disable and lock rumble motors, and switches the controller to
|
||||
Digital Mode (with LED=off, and analog inputs disabled). To prevent this, be
|
||||
sure to keep issuing joypad reads even when not needing user input (eg. while
|
||||
loading data from CDROM).<br/>
|
||||
Caution 2: A similar reset occurs when the user pushes the Analog button; this
|
||||
is causing rumble motors to be stopped and locked, and of course, the
|
||||
analog/digital state gets changed.<br/>
|
||||
Caution 3: If config commands were used, and the user does then push the analog
|
||||
button, then the 5Ah-byte gets replaced by 00h (ie. responses change from "HiZ
|
||||
id 5Ah ..." to "HiZ id 00h ...").<br/>
|
||||
|
||||
#### Config Mode - Command 42h "B" - Read Buttons AND analog inputs
|
||||
```
|
||||
@ -1478,12 +1467,30 @@ unknown. The command does not seem to be used by any games.<br/>
|
||||
These commands do return a bunch of 00h bytes. Purpose unknown. These commands
|
||||
do not seem to be used by any games.<br/>
|
||||
|
||||
#### Watchdog Timer
|
||||
Caution: Additionally to activating configuration commands, entering config
|
||||
mode does also activate a Watchdog Timer which does reset the controller if
|
||||
there's been no communication for about 1 second or so. The watchdog timer
|
||||
remains active even when returning to normal mode via Exit Config command. The
|
||||
reset does disable and lock rumble motors, and switches the controller to
|
||||
Digital Mode (with LED=off, and analog inputs disabled). To prevent this, be
|
||||
sure to keep issuing joypad reads even when not needing user input (eg. while
|
||||
loading data from CDROM).<br/>
|
||||
Caution 2: A similar reset occurs when the user pushes the Analog button; this
|
||||
is causing rumble motors to be stopped and locked, and of course, the
|
||||
analog/digital state gets changed.<br/>
|
||||
Caution 3: If config commands were used, and the user does then push the analog
|
||||
button, then the 5Ah-byte gets replaced by 00h (ie. responses change from "HiZ
|
||||
id 5Ah ..." to "HiZ id 00h ...").<br/>
|
||||
Caution 4: Most emulators do not emulate this watchdog functionality
|
||||
so any homebrew with analog pad support should ideally also be tested on hardware
|
||||
to make sure it doesn't accidentally trigger the watchdog<br/>
|
||||
|
||||
#### Note
|
||||
Rumble is a potentially annoying feature, so games that do support rumble
|
||||
should also include an option to disable it.<br/>
|
||||
|
||||
|
||||
|
||||
## Controllers - Dance Mats
|
||||
PSX Dance Mats are essentially normal joypads with uncommonly arranged buttons,
|
||||
the huge mats are meant to be put on the floor, so the user could step on them.<br/>
|
||||
|
@ -173,6 +173,7 @@ to read from the load destination register, then it would (usually) receive the
|
||||
OLD value of that register (unless an IRQ occurs between the load and next
|
||||
opcode, in that case the load would complete during IRQ handling, and so, the
|
||||
next opcode would receive the NEW value).<br/>
|
||||
MFC2/CFC2 also have a 1-instruction delay until the target register is loaded with its new value (more info in the GTE section).<br/>
|
||||
|
||||
#### Store instructions
|
||||
```
|
||||
@ -180,10 +181,15 @@ next opcode would receive the NEW value).<br/>
|
||||
sh rt,imm(rs) [imm+rs]=(rt AND FFFFh) ;store 16bit
|
||||
sw rt,imm(rs) [imm+rs]=rt ;store 32bit
|
||||
```
|
||||
Store operations are passed to the write-buffer, so they can execute within a
|
||||
single clock cycle (unless the write-buffer was full, in that case the CPU gets
|
||||
halted until there's room in the buffer). But, the PSX doesn't have a
|
||||
writebuffer...?<br/>
|
||||
Store operations are passed to the write-queue, so they can execute within a
|
||||
single clock cycle (unless the write-queue was full, in that case the CPU gets
|
||||
halted until there's room in the queue). For more information on the write-queue, visit [this page](https://psx-spx.consoledev.net/memorymap/#write-queue).<br/>
|
||||
|
||||
#### Caution - 8/16-bit writes to certain IO registers
|
||||
During an 8-bit or 16-bit store, all 32 bits of the GPR are placed on the bus.
|
||||
As such, when writing to certain 32-bit IO registers with an 8 or 16-bit store, it will behave like a 32-bit store, using the register's full value.
|
||||
The soundscope on some shells is known to rely on this, as it uses `sh` to write to certain DMA registers.
|
||||
If this is not properly emulated, the soundscope will hang, waiting for an interrupt that will never be fired.<br/>
|
||||
|
||||
#### Load/Store Alignment
|
||||
Halfword addresses must be aligned by 2, word addresses must be aligned by 4,
|
||||
@ -296,20 +302,20 @@ registers while the mul/div operation is busy will halt the CPU until the
|
||||
mul/div has completed. For multiply, the execution time depends on rs (ie.
|
||||
"small\*large" can be much faster than "large\*small").<br/>
|
||||
```
|
||||
__umul_execution_time_____________________________________________________
|
||||
__multu_execution_time_____________________________________________________
|
||||
Fast (6 cycles) rs = 00000000h..000007FFh
|
||||
Med (9 cycles) rs = 00000800h..000FFFFFh
|
||||
Slow (13 cycles) rs = 00100000h..FFFFFFFFh
|
||||
__smul_execution_time_____________________________________________________
|
||||
__mult_execution_time_____________________________________________________
|
||||
Fast (6 cycles) rs = 00000000h..000007FFh, or rs = FFFFF800h..FFFFFFFFh
|
||||
Med (9 cycles) rs = 00000800h..000FFFFFh, or rs = FFF00000h..FFFFF801h
|
||||
Slow (13 cycles) rs = 00100000h..7FFFFFFFh, or rs = 80000000h..FFF00001h
|
||||
__udiv/sdiv_execution_time________________________________________________
|
||||
__divu/div_execution_time________________________________________________
|
||||
Fixed (36 cycles) no matter of rs and rt values
|
||||
```
|
||||
For example, when executing "umul 123h,12345678h" and "mov r1,lo", one can
|
||||
For example, when executing "multu 123h,12345678h" and "mflo r1", one can
|
||||
insert up to six (cached) ALU opcodes, or read one value from PSX Main RAM
|
||||
(which has 6 cycle access time) between the "umul" and "mov" opcodes without
|
||||
(which has 6 cycle access time) between the "multu" and "mflo" opcodes without
|
||||
additional slowdown.<br/>
|
||||
The hardware does NOT generate exceptions on divide overflows, instead, divide
|
||||
errors are returning the following values:<br/>
|
||||
@ -320,8 +326,8 @@ errors are returning the following values:<br/>
|
||||
div -80000000h..-1 0 --> Rs +1
|
||||
div -80000000h -1 --> 0 -80000000h
|
||||
```
|
||||
For udiv, the result is more or less correct (as close to infinite as
|
||||
possible). For sdiv, the results are total garbage (about farthest away from
|
||||
For divu, the result is more or less correct (as close to infinite as
|
||||
possible). For div, the results are total garbage (about furthest away from
|
||||
the desired result as possible).<br/>
|
||||
Note: After accessing the lo/hi registers, there seems to be a strange rule
|
||||
that one should not touch the lo/hi registers in the next 2 cycles or so... not
|
||||
@ -430,8 +436,8 @@ one uncached opcode).<br/>
|
||||
beqz rx,dest ;alias for beq rx,r0,dest
|
||||
bnez rx,dest ;alias for bne rx,r0,dest
|
||||
b dest ;alias for beq r0,r0,dest (jump relative/spasm)
|
||||
bra dest ;alias for ...? (jump relative/gnu)
|
||||
bal dest ;alias for ...? (call relative/spasm)
|
||||
bra dest ;alias for bgez r0, r0, dest
|
||||
bal dest ;alias for bgezal r0, r0, dest
|
||||
```
|
||||
|
||||
#### Pseudo instructions (nocash/a22i)
|
||||
@ -587,11 +593,11 @@ Describes the most recently recognised exception<br/>
|
||||
#### cop0r12 - SR - System status register (R/W)
|
||||
```
|
||||
0 IEc Current Interrupt Enable (0=Disable, 1=Enable) ;rfe pops IUp here
|
||||
1 KUc Current Kernal/User Mode (0=Kernel, 1=User) ;rfe pops KUp here
|
||||
1 KUc Current Kernel/User Mode (0=Kernel, 1=User) ;rfe pops KUp here
|
||||
2 IEp Previous Interrupt Disable ;rfe pops IUo here
|
||||
3 KUp Previous Kernal/User Mode ;rfe pops KUo here
|
||||
3 KUp Previous Kernel/User Mode ;rfe pops KUo here
|
||||
4 IEo Old Interrupt Disable ;left unchanged by rfe
|
||||
5 KUo Old Kernal/User Mode ;left unchanged by rfe
|
||||
5 KUo Old Kernel/User Mode ;left unchanged by rfe
|
||||
6-7 - Not used (zero)
|
||||
8-15 Im 8 bit interrupt mask fields. When set the corresponding
|
||||
interrupts are allowed to cause an exception.
|
||||
@ -616,13 +622,13 @@ Describes the most recently recognised exception<br/>
|
||||
25 RE Reverse endianness (0=Normal endianness, 1=Reverse endianness)
|
||||
Reverses the byte order in which data is stored in
|
||||
memory. (lo-hi -> hi-lo)
|
||||
(Has affect only to User mode, not to Kernel mode) (?)
|
||||
(Affects only user mode, not kernel mode) (?)
|
||||
(The bit doesn't exist in PSX ?)
|
||||
26-27 - Not used (zero)
|
||||
28 CU0 COP0 Enable (0=Enable only in Kernal Mode, 1=Kernal and User Mode)
|
||||
29 CU1 COP1 Enable (0=Disable, 1=Enable) (none such in PSX)
|
||||
28 CU0 COP0 Enable (0=Enable only in Kernel Mode, 1=Kernel and User Mode)
|
||||
29 CU1 COP1 Enable (0=Disable, 1=Enable) (none in PSX)
|
||||
30 CU2 COP2 Enable (0=Disable, 1=Enable) (GTE in PSX)
|
||||
31 CU3 COP3 Enable (0=Disable, 1=Enable) (none such in PSX)
|
||||
31 CU3 COP3 Enable (0=Disable, 1=Enable) (none in PSX)
|
||||
```
|
||||
|
||||
#### cop0r14 - EPC - Return Address from Trap (R)
|
||||
@ -663,6 +669,10 @@ using the BIOS).<br/>
|
||||
Of course, the above exeption handling won't work in branch delays (where BD
|
||||
gets set to indicate that EPC was modified) (best workaround is not to use GTE
|
||||
commands in branch delays).<br/>
|
||||
Several games are known to rely on this, notably including the Crash Bandicoot trilogy,
|
||||
Jinx and Spyro the Dragon, all of which will render broken geometry
|
||||
if running on an emulator which doesn't emulate this,
|
||||
or if the installed interrupt service routine doesn't account for it.
|
||||
|
||||
#### cop0cmd=10h - RFE opcode - Prepare Return from Exception
|
||||
The RFE opcode moves some bits in cop0r12 (SR): bit2-3 are copied to bit0-1,
|
||||
@ -671,7 +681,7 @@ unchanged.<br/>
|
||||
The RFE opcode does NOT automatically jump to EPC. Instead, the exception
|
||||
handler must copy EPC into a register (usually R26 aka K0), and then jump to
|
||||
that address. Because of branch delays, that would look like so:<br/>
|
||||
```
|
||||
```x86asm
|
||||
mov k0,epc ;get return address
|
||||
push k0 ;save epc in memory (if you expect nested exceptions)
|
||||
... ;whatever (ie. process CAUSE)
|
||||
|
@ -14,7 +14,7 @@
|
||||
#### GTE Operation
|
||||
The GTE doesn't have any memory or I/O ports mapped to the CPU memory bus,
|
||||
instead, it's solely accessed via coprocessor opcodes:<br/>
|
||||
```
|
||||
```x86asm
|
||||
mov cop0r12,rt ;-enable/disable COP2 (GTE) via COP0 status register
|
||||
mov cop2r0-63,rt ;\write parameters to GTE registers
|
||||
mov cop2r0-31,[rs+imm] ;/
|
||||
@ -24,6 +24,11 @@ instead, it's solely accessed via coprocessor opcodes:<br/>
|
||||
jt cop2flg,dest ;-jump never ;\implemented (no exception), but,
|
||||
jf cop2flg,dest ;-jump always ;/flag seems to be always "false"
|
||||
```
|
||||
|
||||
#### GTE Load Delay Slots
|
||||
Using CFC2/MCF2 has a delay of 1 instruction until the GPR is loaded with its new value.
|
||||
Certain games are sensitive to this, with the notable example of Tekken 2
|
||||
which will be filled with broken geometry on emulators which don't emulate this properly.<br/>
|
||||
GTE (memory-?) load and store instructions have a delay of 2 instructions, for
|
||||
any GTE commands or operations accessing that register. Any? That's wrong!<br/>
|
||||
GTE instructions and functions should not be used in<br/>
|
||||
|
@ -141,8 +141,8 @@ be decoded using the following bitfield:
|
||||
28 1/0 gouraud / flat shading
|
||||
27 1/0 4 / 3 vertices
|
||||
26 1/0 textured / untextured
|
||||
25 1/0 semi transparent / solid
|
||||
24 1/0 texture blending
|
||||
25 1/0 semi-transparent / opaque
|
||||
24 1/0 raw texture / modulation
|
||||
23-0 rgb first color value.
|
||||
```
|
||||
|
||||
@ -154,8 +154,6 @@ If doing flat rendering, no further color will be sent. If doing gouraud shading
|
||||
there will be one more color per vertex sent, and the initial color will be the
|
||||
one for vertex 0.
|
||||
|
||||
If doing 3 or 4 vertices rendering, this will affect the total number of vertex sent.
|
||||
|
||||
If doing textured rendering, each vertex sent will also have a U/V texture coordinate
|
||||
attached to it, as well as a CLUT index.
|
||||
|
||||
@ -163,7 +161,7 @@ So each vertex data can be seen as the following set of words:
|
||||
```
|
||||
Color xxBBGGRR - optional, only present for gouraud shading
|
||||
Vertex YYYYXXXX - required, two signed 16 bits values
|
||||
UV ClutUUVV or PageUUVV - optional, only present for textured polygons
|
||||
UV ClutVVUU or PageVVUU - optional, only present for textured polygons
|
||||
```
|
||||
|
||||
The upper 16 bits of the first two UV words contain extra information. The first
|
||||
@ -184,33 +182,33 @@ And a quad with gouraud shading texture-blend will have the following structure:
|
||||
```
|
||||
2CR1G1B1
|
||||
Yyy1Xxx1
|
||||
ClutU1V1
|
||||
ClutV1U1
|
||||
00R2G2B2
|
||||
Yyy2Xxx2
|
||||
PageU2V2
|
||||
PageV2U2
|
||||
00R3G3B3
|
||||
Yyy3Xxx3
|
||||
0000U3V3
|
||||
0000V3U3
|
||||
00R4G4B4
|
||||
Yyy4Xxx4
|
||||
0000U4V4
|
||||
0000V4U4
|
||||
```
|
||||
|
||||
Some combination of these flags can be seen as nonsense however, but it's important
|
||||
to realize that the GPU will still process them properly. For instance, specifying
|
||||
gouraud shading without texture blending will force the user to send the colors for
|
||||
gouraud shading without modulation will force the user to send the colors for
|
||||
each vertex to satisfy the GPU's state machine, without them being actually used for
|
||||
the rendering.
|
||||
|
||||
#### Notes
|
||||
Polygons are displayed up to \<excluding\> their lower-right coordinates.<br/>
|
||||
Four-point polygons are internally processed as two Three-point polygons, the
|
||||
first consisting of Vertices 1,2,3, and the second of Vertices 2,3,4.<br/>
|
||||
Within the Three-point polygons, the ordering of the vertices is don't care at
|
||||
Quads are internally processed as two triangles, the
|
||||
first consisting of vertices 1,2,3, and the second of vertices 2,3,4. This is an important detail, as splitting the quad into triangles affects the way colours are interpolated.<br/>
|
||||
Within the triangle, the ordering of the vertices doesn't matter on
|
||||
the GPU side (a front-back check, based on clockwise or anti-clockwise
|
||||
ordering, can be implemented at the GTE side).<br/>
|
||||
Dither enable (in Texpage command) affects ONLY polygons that do use Gouraud
|
||||
Shading or Texture Blending.<br/>
|
||||
Dither enable (in Texpage command) affects ONLY polygons that do use gouraud
|
||||
shading or modulation.<br/>
|
||||
|
||||
## GPU Render Line Commands
|
||||
When the upper 3 bits of the first GP0 command are set to 2 (010), then the command can
|
||||
@ -220,7 +218,7 @@ be decoded using the following bitfield:
|
||||
31-29 010 line render
|
||||
28 1/0 gouraud / flat shading
|
||||
27 1/0 polyline / single line
|
||||
25 1/0 semi transparent / solid
|
||||
25 1/0 semi-transparent / opaque
|
||||
23-0 rgb first color value.
|
||||
```
|
||||
|
||||
@ -262,7 +260,8 @@ The Rectangle command can be decoded using the following bitfield:
|
||||
31-29 011 rectangle render
|
||||
28-27 sss rectangle size
|
||||
26 1/0 textured / untextured
|
||||
25 1/0 semi transparent / solid
|
||||
25 1/0 semi-transparent / opaque
|
||||
24 1/0 raw texture / modulation
|
||||
23-0 rgb first color value.
|
||||
```
|
||||
|
||||
@ -279,8 +278,8 @@ Therefore, the whole draw call can be seen as the following sequence of words:
|
||||
```
|
||||
Color ccBBGGRR - command + color; color is ignored when textured
|
||||
Vertex1 YYYYXXXX - required, indicates the upper left corner to render
|
||||
UV ClutUUVV - optional, only present for textured rectangles
|
||||
Vertex2 YYYYXXXX - optional, bottom right corner for variable sized rectangles
|
||||
UV ClutVVUU - optional, only present for textured rectangles
|
||||
Width+Height YsizXsiz - optional, dimensions for variable sized rectangles (max 1023x511)
|
||||
```
|
||||
|
||||
Unlike for Textured-Polygons, the "Texpage" must be set up separately for
|
||||
@ -336,7 +335,7 @@ single clock cycle), or if it's (slowly) processing them pixel by pixel?<br/>
|
||||
24-31 Command (in first paramter) (don't care in further parameters)
|
||||
```
|
||||
Caution: For untextured graphics, 8bit RGB values of FFh are brightest.
|
||||
However, for texture blending, 8bit values of 80h are brightest (values
|
||||
However, for modulation, 8bit values of 80h are brightest (values
|
||||
81h..FFh are "brighter than bright" allowing to make textures about twice as
|
||||
bright as than they were originially stored in memory; of course the results
|
||||
can't exceed the maximum brightness, ie. the 5bit values written to the
|
||||
@ -366,7 +365,7 @@ Specifies the location of the CLUT data within VRAM.<br/>
|
||||
```
|
||||
0-3 Texture page X Base (N*64) (ie. in 64-halfword steps) ;GPUSTAT.0-3
|
||||
4 Texture page Y Base (N*256) (ie. 0 or 256) ;GPUSTAT.4
|
||||
5-6 Semi Transparency (0=B/2+F/2, 1=B+F, 2=B-F, 3=B+F/4) ;GPUSTAT.5-6
|
||||
5-6 Semi-transparency (0=B/2+F/2, 1=B+F, 2=B-F, 3=B+F/4) ;GPUSTAT.5-6
|
||||
7-8 Texture page colors (0=4bit, 1=8bit, 2=15bit, 3=Reserved);GPUSTAT.7-8
|
||||
9 Dither 24bit to 15bit (0=Off/strip LSBs, 1=Dither Enabled) ;GPUSTAT.9
|
||||
10 Drawing to display area (0=Prohibited, 1=Allowed) ;GPUSTAT.10
|
||||
@ -748,16 +747,16 @@ registers.<br/>
|
||||
1-23 Unknown (seems to have no effect)
|
||||
```
|
||||
This feature seems to be intended for debugging purposes (most released games
|
||||
do contain program code for disabling textures, but do never execute it).<br/>
|
||||
GP1(09h) seems to be supported only on New GPUs. Old GPUs don't support it all,
|
||||
and there seem to be some Special/Prototype GPUs that use GP1(20h) instead of
|
||||
do contain program code for disabling textures, but never execute it).<br/>
|
||||
GP1(09h) seems to be supported only on New GPUs. Old GPUs don't support it at all,
|
||||
and there seem to be some special/prototype GPUs that use GP1(20h) instead of
|
||||
GP1(09h).<br/>
|
||||
|
||||
#### GP1(20h) - Special/Prototype Texture Disable
|
||||
```
|
||||
0-23 Unknown (501h=Texture Enable, 504h=Texture Disable, or so?)
|
||||
```
|
||||
Seems to be a used only on whatever arcade/prototype GPUs. New GPUs are using
|
||||
Seems to be used only on whatever arcade/prototype GPUs. New GPUs are using
|
||||
GP1(09h) instead of GP1(20h).<br/>
|
||||
|
||||
#### GP1(0Bh) - Unknown/Internal?
|
||||
@ -797,7 +796,7 @@ or if X1=260h, and Y1/Y2=A3h+/-N would work fine on most or all PAL TV Sets?<br/
|
||||
```
|
||||
0-3 Texture page X Base (N*64) ;GP0(E1h).0-3
|
||||
4 Texture page Y Base (N*256) (ie. 0 or 256) ;GP0(E1h).4
|
||||
5-6 Semi Transparency (0=B/2+F/2, 1=B+F, 2=B-F, 3=B+F/4) ;GP0(E1h).5-6
|
||||
5-6 Semi-transparency (0=B/2+F/2, 1=B+F, 2=B-F, 3=B+F/4) ;GP0(E1h).5-6
|
||||
7-8 Texture page colors (0=4bit, 1=8bit, 2=15bit, 3=Reserved)GP0(E1h).7-8
|
||||
9 Dither 24bit to 15bit (0=Off/strip LSBs, 1=Dither Enabled);GP0(E1h).9
|
||||
10 Drawing to display area (0=Prohibited, 1=Allowed) ;GP0(E1h).10
|
||||
@ -1087,10 +1086,10 @@ A texture is an image put on a polygon or sprite. The data of a texture can be
|
||||
stored in 3 different modes:<br/>
|
||||
```
|
||||
<B> 16bit Texture (Direct Color) ;(One 256x256 page = 128Kbytes)</B>
|
||||
0-4 Red (0..31) ;\Color 0000h = Fully-Transparent
|
||||
5-9 Green (0..31) ; Color 0001h..7FFFh = Non-Transparent
|
||||
10-14 Blue (0..31) ; Color 8000h..FFFFh = Semi-Transparent (*)
|
||||
15 Semi Transparency Flag ;/(*) or Non-Transparent for opaque commands
|
||||
0-4 Red (0..31) ;\Color 0000h = Fully-transparent
|
||||
5-9 Green (0..31) ; Color 0001h..7FFFh = Non-transparent
|
||||
10-14 Blue (0..31) ; Color 8000h..FFFFh = Semi-transparent (*)
|
||||
15 Semi-transparency Flag ;/(*) or Non-transparent for opaque commands
|
||||
<B> 8bit Texture (256 Color Palette) ;(One 256x256 page = 64Kbytes)</B>
|
||||
0-7 Palette index for 1st pixel (left)
|
||||
8-15 Palette index for 2nd pixel (right)
|
||||
@ -1116,10 +1115,10 @@ CLUT modes. The pixels of those images are used as indexes to this table. The
|
||||
clut is arranged in the frame buffer as a 256x1 image for the 8bit clut mode,
|
||||
and a 16x1 image for the 4bit clut mode.<br/>
|
||||
```
|
||||
0-4 Red (0..31) ;\Color 0000h = Fully-Transparent
|
||||
5-9 Green (0..31) ; Color 0001h..7FFFh = Non-Transparent
|
||||
10-14 Blue (0..31) ; Color 8000h..FFFFh = Semi-Transparent (*)
|
||||
15 Semi Transparency Flag ;/(*) or Non-Transparent for opaque commands
|
||||
0-4 Red (0..31) ;\Color 0000h = Fully-transparent
|
||||
5-9 Green (0..31) ; Color 0001h..7FFFh = Non-transparent
|
||||
10-14 Blue (0..31) ; Color 8000h..FFFFh = Semi-transparent (*)
|
||||
15 Semi-transparency Flag ;/(*) or Non-transparent for opaque commands
|
||||
```
|
||||
The clut data can be arranged in the frame buffer at X multiples of 16
|
||||
(X=0,16,32,48,etc) and anywhere in the Y range of 0-511.<br/>
|
||||
@ -1310,7 +1309,7 @@ vertical blanking/retrace).<br/>
|
||||
```
|
||||
0-23 Color for (first) Vertex (Not for Raw-Texture)
|
||||
24 Texture Mode (0=Blended, 1=Raw) (Textured-Polygon/Rect only)
|
||||
25 Semi Transparency (0=Off, 1=On) (All Render Types)
|
||||
25 Semi-transparency (0=Off, 1=On) (All Render Types)
|
||||
26 Texture Mapping (0=Off, 1=On) (Polygon/Rectangle only)
|
||||
27-28 Rect Size (0=Var, 1=1x1, 2=8x8, 3=16x16) (Rectangle only)
|
||||
27 Num Vertices (0=Triple, 1=Quad) (Polygon only)
|
||||
@ -1364,16 +1363,9 @@ resulting in the final 5bit R/G/B values.<br/>
|
||||
+3 -1 +2 -2 ;/(same as above, but shifted two pixels horizontally)
|
||||
```
|
||||
POLYGONs (triangles/quads) are dithered ONLY if they do use gouraud shading or
|
||||
texture blending.<br/>
|
||||
modulation.<br/>
|
||||
LINEs are dithered (no matter if they are mono or do use gouraud shading).<br/>
|
||||
RECTs are NOT dithered (no matter if they do use texture blending).<br/>
|
||||
|
||||
#### Shading information
|
||||
"Texture RGB values control the brightness of the individual colors ($00-$7f).
|
||||
A value of $80 in a color will take the former value as data." (What...?
|
||||
probably means the "double brightness" effect... or does it want to tell that
|
||||
ALL colors of 80h..FFh have only single brightness.. rather than reaching
|
||||
double brightness at FFh...?)<br/>
|
||||
RECTs are NOT dithered (no matter if they do use modulation or not).<br/>
|
||||
|
||||
#### Shading
|
||||
The GPU has a shading function, which will scale the color of a primitive to a
|
||||
@ -1383,20 +1375,33 @@ for the entire primitive. In Gouraud shading mode, a different brightness value
|
||||
can be given for each vertex of a primitive, and the brightness between these
|
||||
points is automatically interpolated.<br/>
|
||||
|
||||
#### Semi Transparency
|
||||
When semi transparency is set for a pixel, the GPU first reads the pixel it
|
||||
#### Semi-transparency
|
||||
When semi-transparency is set for a pixel, the GPU first reads the pixel it
|
||||
wants to write to, and then calculates the color it will write from the 2
|
||||
pixels according to the semitransparency mode selected. Processing speed is
|
||||
pixels according to the semi-transparency mode selected. Processing speed is
|
||||
lower in this mode because additional reading and calculating are necessary.
|
||||
There are 4 semitransparency modes in the GPU.<br/>
|
||||
There are 4 semi-transparency modes in the GPU.<br/>
|
||||
```
|
||||
B=Back (the old pixel read from the image in the frame buffer)
|
||||
F=Front (the new halftransparent pixel)
|
||||
B=Back (the old pixel read from the frame buffer)
|
||||
F=Front (the new semi-transparent pixel)
|
||||
* 0.5 x B + 0.5 x F ;aka B/2+F/2
|
||||
* 1.0 x B + 1.0 x F ;aka B+F
|
||||
* 1.0 x B - 1.0 x F ;aka B-F
|
||||
* 1.0 x B +0.25 x F ;aka B+F/4
|
||||
```
|
||||
For textured primitives using 4-bit or 8-bit textures, bit 15 of each CLUT entry acts as a semi-transparency flag and determines whether to apply semi-transparency to the pixel or not. If the semi-transparency flag is off, the new pixel is written to VRAM as-is.<br/>
|
||||
When using additive blending, if a channel's intensity is greater than 255, it gets clamped to 255 rather than being masked. Similarly, if using subtractive blending and a channel's intensity ends up being < 0, it's clamped to 0.<br/>
|
||||
|
||||
#### Modulation (also known as Texture Blending)
|
||||
Modulation is a colour effect that can be applied to textured primitives.
|
||||
For each pixel of the primitive it combines every colour channel of the fetched texel with the corresponding channel of the interpolated vertex colour according to this formula (Assuming all channels are 8-bit).<br/>
|
||||
```glsl
|
||||
finalChannel.rgb = (texel.rgb * vertexColour.rgb) / vec3(128.0)
|
||||
```
|
||||
Using modulation, one can either decrease (if the vertex colour channel value is < 128) or increase (if it's > 128) the intensity of each colour channel of the texel, which is helpful for implementing things such as brightness effects.<br/>
|
||||
Using a vertex colour of 0x808080 (ie all channels set to 128) is equivalent to not applying modulation to the primitive, as shown by the above formula.<br/>
|
||||
"Texture blending" is not meant to be confused with normal blending, ie an operation that merges the backbuffer colour with the incoming pixel and draws the resulting colour to the backbuffer.
|
||||
The PS1 has this capability to an extent, using semi-transparency.<br/>
|
||||
|
||||
#### Draw to display enable
|
||||
This will enable/disable any drawing to the area that is currently displayed.
|
||||
|
@ -885,6 +885,7 @@ the CPU clock, or less, depending on the Timer Divider). Possible values are:<br
|
||||
Before changing CLK\_MODE, F\_WAIT1 and F\_WAIT2 should be adjusted accordingly
|
||||
(see there for details). Note that many memory regions have waitstates, the
|
||||
full CPU speed can be reached mainly with code/data in WRAM.<br/>
|
||||
For emulator authors: Note that some Pocketstation software will expect bit 4 of CLK\_MODE to go from 0 to 1 rather than just polling it until it's 1. For this reason, emulating bit 4 as always being 1 can very likely break.<br/>
|
||||
|
||||
#### 0B000004h - CLK\_STOP - Clock stop (Sleep Mode)
|
||||
Stops the CPU until an interrupt occurs. The pocketstation doesn't have a
|
||||
@ -1398,7 +1399,35 @@ useful for setting up a custom SWI table in FLASH or in RAM. When doing that,
|
||||
one must restore the original setting before returning control to the GUI or to
|
||||
another executable (the setting isn't automatically restored).<br/>
|
||||
|
||||
#### SWI service routine
|
||||
The default SWI service routine is slightly finicky<br/>
|
||||
```arm
|
||||
push {r1-r12, lr} @ Backup SVC-mode registers
|
||||
mrs r12, spsr @ Old CPSR in r12
|
||||
nop
|
||||
|
||||
@ Check if we were previously in Thumb mode
|
||||
@ And adjust LR accordingly to fetch the SWI comment field
|
||||
tst r12, #0x20
|
||||
subeq lr, #2
|
||||
sub lr, #2
|
||||
|
||||
@ Fetch the comment field
|
||||
ldrh r12, [lr]
|
||||
and r12, #0xFF
|
||||
|
||||
@ Load function pointer for SWI handler and call it
|
||||
mov lr, #0xE0 ; Pointer to SWI table in LR
|
||||
ldr r11, [lr]
|
||||
add r11, r11, r12, lsl #2 @ r11 = &swi_table[comment]
|
||||
ldr r11, [r11] @ Get function pointer
|
||||
mov lr, pc @ Set LR to return address
|
||||
bx r11 @ Call SWI handler
|
||||
|
||||
@ Restore SVC regs, return from SWI service routine and restore SPSR into CPSR
|
||||
pop {r1-r12, pc}^
|
||||
```
|
||||
It's important that the SWI service routine use a 16-bit load to fetch the comment field, as most memory on the Pocketstation can't be safely read using `ldrb`. Any custom handler needs to do the same, otherwise it won't work on real hardware. Also, for emulator developers, be wary of the last `pop` as it abuses an ldm edge case (S bit set with r15 in rlist - restores registers properly and then does CPSR = SPSR)<br/>
|
||||
|
||||
## Pocketstation BU Command Summary
|
||||
The Pocketstation supports the standard Memory Card commands (Read Sector,
|
||||
@ -2060,7 +2089,7 @@ checking for TTY messages after the actual upload):<br/>
|
||||
With that ID, and with the XBOO-hardware being used, the game will be started
|
||||
with with "TTY+" in R0 (notifying it that the XBOO hardware is present, and
|
||||
that it needs to install special transmission handlers):<br/>
|
||||
```
|
||||
```arm
|
||||
;------------------
|
||||
.data?
|
||||
org 200h
|
||||
|
Loading…
Reference in New Issue
Block a user