This commit is contained in:
Nicolas Pixel Noble 2022-08-28 18:50:41 -07:00
commit 421668bbc0
5 changed files with 148 additions and 92 deletions

View File

@ -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/>

View File

@ -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)

View File

@ -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/>

View File

@ -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.
```
@ -277,10 +276,10 @@ The `size` parameter can be seen as the following enum:
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
Color ccBBGGRR - command + color; color is ignored when textured
Vertex1 YYYYXXXX - required, indicates the upper left corner to render
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.

View File

@ -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