test(prog_field): Update to reflect new findings.

This commit is contained in:
Ty Lamontagne
2022-06-13 20:44:47 -04:00
parent d8a7a89aec
commit 883437dee3
4 changed files with 66 additions and 65 deletions

View File

@@ -1,6 +1,6 @@
EE_OBJS = prog_field.o
EE_BIN = prog_field.elf
EE_LIBS = -lkernel -lgraph
EE_LIBS = -lkernel
all: $(EE_BIN)

View File

@@ -1,29 +1,35 @@
# Progressive Field
## Description
Checks the behaviour of FIELD in the GS CSR register when the PCRT is set to progressive.
Checks the behaviour of FIELD(in CSR) when the CMOD(in SMODE1)
and VFP(in SYNCHV) bits are changed.
## PCSX2 Behaviour
FIELD would alternate, just as if the PCRT was set to interlaced.
PCSX2 would swap FIELD unconditionally, this caused some progressive games to
bounce.
This caused some progressive games to bounce.
After the original progressive hardware test, PCSX2 would look at the interlace bit of SMODE2.
If the bit was not set (progressive), PCSX2 would set FIELD, otherwise it would swap.
This was later found to be incorrect behaviour.
## Findings
When the video mode is set to progressive, FIELD is set.
The original finding determined that when the video mode is set to progressive, FIELD is set.
Turns out, the SMODE2 interlace bit has no control over FIELD behaviour.
The actual behaviour is determined by CMOD (bits 13 & 14 in SMODE1)
and VFP (bottom bits in SYNCV)
![img](https://i.imgur.com/dsFYHm5.jpg)
## Related PR(s) or Issue(s)
https://github.com/PCSX2/pcsx2/pull/6256
https://github.com/PCSX2/pcsx2/pull/6342
## Expected Results
This 30 times:
```
FIELD Prev 2000 Field New 2000
```
When testing CMOD 1, odd VFPs should say `FIELD IS CHANGING`
In the case that the PCRT mode was set to interlaced, the expected result would be this, 15 times:
```
FIELD Prev 0 Field New 2000
FIELD Prev 2000 Field New 0
```
When testing CMOD 0, no matter the VFP, it should say `FIELD IS NOT CHANGING`

View File

@@ -1,68 +1,63 @@
#include <kernel.h>
#include <stdio.h>
#include <graph.h>
#include <draw.h>
#include <gs_psm.h>
#define INTC_STAT (*(volatile u32 *)0x1000F000)
#define GSCSR (*(volatile u64 *)0x12001000)
#define SYNCV (*(volatile u64 *)0x12000060)
#define SMODE1 (*(volatile u64 *)0x12000010)
void setup_gs()
static inline void wait_intc_vsync()
{
framebuffer_t fb;
fb.address = graph_vram_allocate(640, 448, GS_PSM_24, GRAPH_ALIGN_PAGE);
fb.psm = GS_PSM_24;
fb.width = 640;
fb.height = 480;
INTC_STAT = 0xC;
while (!(INTC_STAT & 0x8))
;
}
graph_initialize(fb.address, fb.width, fb.height, fb.psm, 0, 0);
return;
void test_gs_field()
{
for (int i = 0; i <= 9; i++)
{
printf(" Checking VFP %d\n", i);
// Bottom bits of SYNCV are the VFP
SYNCV = 0xC7800003000000LL + i;
// Wait for two vsyncs here, otherwise our current_field could be
// wrong.
wait_intc_vsync();
wait_intc_vsync();
u32 current_field = GSCSR & 0x2000;
for (u32 j = 0; j < 5; j++)
{
wait_intc_vsync();
if (current_field != (GSCSR & 0x2000))
{
goto field_changed;
}
}
printf(" FIELD IS NOT CHANGING\n");
continue;
field_changed:
printf(" FIELD IS CHANGING\n");
}
}
int main(void)
{
setup_gs();
wait_intc_vsync();
INTC_STAT = 0xC;
while (!(INTC_STAT & 0x8))
{
}
INTC_STAT = 0xC;
while (!(INTC_STAT & 0x8))
{
}
// Set the mode to progressive
graph_set_mode(GRAPH_MODE_NONINTERLACED, GRAPH_MODE_NTSC, 0, 0);
// Clear V-blank start and V-blank end interrupts
INTC_STAT = 0xC;
// Wait for V-blank end interrupt
while (!(INTC_STAT & 0x8))
{
}
// Enable the VSync interrupt
// Enable VSYNC event
GSCSR = 0x8;
for(int i = 0; i < 30; i++)
{
// Clear V-blank start and V-blank end interrupts
INTC_STAT = 0xC;
// Read FIELD
u32 start_odd = GSCSR & 0x2000;
// Wait for V-blank end interrupt
while (!(INTC_STAT & 0x8))
{
}
// Read FIELD again
u32 end_odd = GSCSR & 0x2000;
printf("FIELD Prev %x Field New %x\n", start_odd, end_odd);
}
printf("Checking FIELD when CMOD is set to 1\n");
SMODE1 |= (1 << 13);
test_gs_field();
printf("Checking FIELD when CMOD is set to 0\n");
SMODE1 &= ~(2 << 13);
test_gs_field();
SleepThread();
}

Binary file not shown.