Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing for existence of the GTE #30

Open
Kingcom opened this issue Jan 17, 2016 · 21 comments
Open

Testing for existence of the GTE #30

Kingcom opened this issue Jan 17, 2016 · 21 comments

Comments

@Kingcom
Copy link

Kingcom commented Jan 17, 2016

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.

@jpd002
Copy link
Collaborator

jpd002 commented Jan 17, 2016

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.

@Kingcom
Copy link
Author

Kingcom commented Jan 17, 2016

Very nice! Can you maybe test what happens if you don't set the COP0 bit, too?

@unknownbrackets
Copy link
Owner

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]

@jpd002
Copy link
Collaborator

jpd002 commented Jan 17, 2016

@Kingcom If the bit is not set, the CPU throws a coprocessor unusable exception.

@jpd002
Copy link
Collaborator

jpd002 commented Jan 17, 2016

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.

@ramapcsx2
Copy link

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

@ramapcsx2
Copy link

@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

@ramapcsx2
Copy link

Regarding the MDEC, it's prolly the upper left here: https://i.imgur.com/gsxPq5i.jpg :)

@refractionpcsx2
Copy link

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

@ADormant
Copy link

By the way is it already known if PS2 has MDEC or not?

@refractionpcsx2
Copy link

Yeh MDEC would be interesting to know or if that is fused to another unit in some way.

@jpd002
Copy link
Collaborator

jpd002 commented Jan 21, 2016

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.

@jpd002
Copy link
Collaborator

jpd002 commented Jan 21, 2016

Thanks for the docs, @ADormant !

@unknownbrackets
Copy link
Owner

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]

@ramapcsx2
Copy link

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

@TheLastRar
Copy link

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

@refractionpcsx2
Copy link

Probably possible now on PCSX2, gregory has recently implemented IRX running support PCSX2/pcsx2@c00b427

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

@TheLastRar
Copy link

The tests I linked are pre-compiled PSX EXEs, which have a different header to IRX files.
PCSX2 crashes when trying to load them.

@refractionpcsx2
Copy link

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 :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants