Open Kingcom opened 8 years ago
Came up with a very quick test case using the function you've provided (slightly modified to set bit 30 of COP0.r12):
#include <common-iop.h>
#include <stdio.h>
#include <tamtypes.h>
extern void LoadAverageCol(unsigned char*, unsigned char*, int, int, unsigned char*);
int _start(int argc, char **argv) {
printf("-- TEST BEGIN\n");
unsigned char inColor1[3] = { 0x00, 0xCC, 0x00 };
unsigned char inColor2[3] = { 0xAA, 0x00, 0xAA };
unsigned char outColor[3];
LoadAverageCol(inColor1, inColor2, 0x1000, 0x1000, outColor);
printf("outColor: %x, %x, %x\n",
outColor[0], outColor[1], outColor[2]);
LoadAverageCol(inColor1, inColor2, 0x800, 0x800, outColor);
printf("outColor: %x, %x, %x\n",
outColor[0], outColor[1], outColor[2]);
printf("-- TEST END\n");
return 0;
}
And this yields the following result:
-- TEST BEGIN
outColor: aa, cc, aa
outColor: 55, 66, 55
-- TEST END
Which seems to indicate that the IOP has the GTE. I will push a branch with the code later.
Very nice! Can you maybe test what happens if you don't set the COP0 bit, too?
Well, that's interesting. I guess that means we need a set of tests for all the GTE ops.
Do you know if there's any architecture docs for the GTE instructions? I'd probably want to create an "assembler" like with the VU.
-[Unknown]
@Kingcom If the bit is not set, the CPU throws a coprocessor unusable exception.
Here's the code for reference purposes: https://github.com/jpd002/ps2autotests/tree/gte_test/tests/cpu/gte.
For GTE instructions, there's this documentation that I know of, but I'm not sure about its completeness: http://psx.rules.org/gte.txt.
Thanks a lot you guys :) There's also confusion about the MDEC unit, which is physically in the CPU and talks to the GPU via DMA. I don't know much more but I wonder if that's also still in IOP. Chances are, it is. But this GTE finding helps a lot :)
@unknownbrackets I don't expect the IOP GTE to differ from a regular PSX. They use it in PSX mode, after all. People in the PSX dev scene would surely like it though. They're saying GTE isn't very well documented: http://www.psxdev.net/forum/viewtopic.php?f=70&t=551&start=40
Regarding the MDEC, it's prolly the upper left here: https://i.imgur.com/gsxPq5i.jpg :)
Thank you for finding this out guys :) I was pretty sure this was the case, had no proof of it though and subsequently got my addition of it in PCSX2, now I have no reason not to put it back in again for the long quest of PSX emulation :)
@jpd002 These GTE documentations are better @refractionpcsx2
http://problemkaputt.de/psx-spx.htm#geometrytransformationenginegte https://github.com/simias/psx-guide https://github.com/simias/pops-gte http://www.romhacking.net/documents/124/ https://github.com/ogamespec/psxdev https://sourceforge.net/projects/mednafen/
By the way is it already known if PS2 has MDEC or not?
Yeh MDEC would be interesting to know or if that is fused to another unit in some way.
Reading from 0x1F801824
(which is the MDEC1 register from what I can gather) after writing 0x80000000
(which should reset the MDEC) at that address gives 0x80040000
which appears to be the "initial" value for that register according to the documentation I've read.
I'm not quite familiar with the MDEC, but I'll see if I can come up with a better test.
Thanks for the docs, @ADormant !
I messed with sending some data to the MDEC control register and MDEC data register, and aside from reset, garbage also affects it.
The results are repeatable. For example, writing 0x01230001
to MDEC command/data changes control to 0x80040001
. This is exactly how Martin describes NOP operating. I'm not sure if it actually decodes macroblocks, etc., but there appears to be something there indeed. I'd guess it does function, but could be wrong.
And, 0x12345678
results in 0x84845678
for control. Which also makes sense, I think...
My test (using IOP_CFLAGS= -std=c99
):
#include <stdio.h>
#include <tamtypes.h>
static volatile u32 *MDEC_DATA = (volatile u32 *)0x1F801820;
static volatile u32 *MDEC_CONTROL = (volatile u32 *)0x1F801824;
int _start(int argc, char **argv) {
printf("-- TEST BEGIN\n");
printf("Control: %08x\n", *MDEC_CONTROL);
printf("Data: %08x\n", *MDEC_DATA);
*MDEC_CONTROL = 0x40000000;
printf("Control: %08x\n", *MDEC_CONTROL);
for (int i = 0; i < 10000000; ++i) {
if (*MDEC_CONTROL != 0x80040000) {
printf("Control changed: %08x\n", *MDEC_CONTROL);
break;
}
}
*MDEC_DATA = 0x12345678;
printf("Control: %08x\n", *MDEC_CONTROL);
printf("Data: %08x\n", *MDEC_DATA);
printf("Control: %08x\n", *MDEC_CONTROL);
printf("-- TEST END\n");
return 0;
}
-[Unknown]
The GTE test works in PCSX2 now :) There's total confusion how to handle hardware reads and writes though.
https://github.com/PCSX2/pcsx2/blob/master/pcsx2/ps2/Iop/IopHwRead.cpp#L310 https://github.com/PCSX2/pcsx2/blob/master/pcsx2/ps2/Iop/IopHwWrite.cpp#L513
DMAs are going to be for SIF2 to handle. You can invoke it with WriteFifoSingleWord() / ReadFifoSingleWord(); Unfortunately, nothing in SIF2 is tested. Total lack of documentation and tests..
Some more PS1 hardware tests http://psx.amidog.se/doku.php?id=psx:download:cpu http://psx.amidog.se/doku.php?id=psx:download:gpu http://psx.amidog.se/doku.php?id=psx:download:gte http://psx.amidog.se/doku.php?id=psx:download:misc
I don't know how feasible it is to run all of these on a PS2. But these tests have been used to compare PS1 emulators http://emulation.gametechwiki.com/index.php/PS1_Tests
Probably possible now on PCSX2, gregory has recently implemented IRX running support https://github.com/PCSX2/pcsx2/commit/c00b427efa9ec22c03e6ad1b6e3f0fe158616c94
this puts the EE idle and runs the IRX directly, we don't make the COP2 bit of the control registers mandatory for GTE support, so it will probably just work lol
The tests I linked are pre-compiled PSX EXEs, which have a different header to IRX files. PCSX2 crashes when trying to load them.
oh yeh, they're exe's, forgot about that, damn, nevermind, they would probably need to be put on a psx format cd and executed that way for pcsx2, invoking the ps1 emulation, but that's the only way they would execute currently :(
The PSX had a Geometry Transformation Engine as COP2 for basic linear algebra calculations. It would be interesting to know if it still exists on the PS2's IOP, or is potentually emulated in software.
To enable the GTE, you first need to set bit 30 of COP0.r12.
Here is some sample code for using it, which calculates the weighted average of two color vectors: http://pastebin.com/0S3wGed9 The signature for the function there is
void LoadAverageCol(unsigned char in1[3], unsigned char in2[3], long weight1, long weight2, unsigned char out[3]);
Note that the last parameter is passed on the stack.