How to split view

Graphic based area of development (Graphics Processing Unit), including the Geometry Transform Engine (GTE), TIM, STR (MDEC), etc.
Post Reply
Xavi92
Verified
C Programming Expert
C Programming Expert
Posts: 161
Joined: Oct 06, 2012
PlayStation Model: SCPH-5502
Contact:

How to split view

Post by Xavi92 » February 12th, 2018, 5:26 am

Hello everyone

My WIP video game "Airport" will feature a 2-player mode, where screen is split horizontally. My intention was to perform the following steps:

1. Modify drawing environment to the left half of the screen;
2. Draw everything related to player 1's view.
3. Modify drawing environment to the right half of the screen.
4. Draw everything related to player 2's view.
5. Modify drawing environment to occupy the whole screen.
6. Draw common GUI elements (clock, score, etc.)
7. Go to step 1.

All instructions are being passed to the DMA, even modifying the drawing environment. While it works perfevtly under emulation, it makes screen flickering under real HW. I discovered the following statement on Nocash's PSX specs:
GP0(E3h..E5h) do not take up space in the FIFO, so they are probably executed immediately (even if there're still other commands in the FIFO). Best use them only if you are sure that the FIFO is empty (otherwise the new Drawing Area settings might accidently affect older Rendering Commands in the FIFO).
I've tried inserting NOPs (GP0(00h)) both before and after without success. See source code here:
Game.c (see GameGraphics())
https://github.com/XaviDCR92/Airport/bl ... rce/Game.c
https://github.com/XaviDCR92/psxsdk-201 ... /src/gpu.c

Any ideas?

Thanks for reading,
Xavi

User avatar
LameGuy64
Verified
Psy-Q Enthusiast
Psy-Q Enthusiast
Posts: 388
Joined: Apr 10, 2013
I am a: Hobbyist Game Developer
Motto: Commercial or not, play it!
PlayStation Model: H2000/7000
Location: Philippines
Contact:

Post by LameGuy64 » February 12th, 2018, 11:48 am

I haven't really tried split screen rendering myself but I believe the easiest method to achieve it is to have 2 OTs for each view, each OT starting with a DR_AREA (command 0x10) packet to set the draw area for each view. You can then link the 2 OTs together and draw both OTs once.
Please don't forget to include my name if you share my work around. Credit where it is due.

Dev. Console: SCPH-7000 with SCPH-7501 ROM, MM3, PAL color fix, Direct AV ports, DB-9 port for Serial I/O, and a Xplorer FX with Caetla 0.35.

DTL-H2000 PC: Dell Optiplex GX110, Windows 98SE & Windows XP, Pentium III 933MHz, 384MB SDRAM, ATI Radeon 7000 VE 64MB, Soundblaster Audigy, 40GB Seagate HDD, Hitachi Lite-on CD-RW Drive, ZIP 250 and 3.5" Floppy.

Xavi92
Verified
C Programming Expert
C Programming Expert
Posts: 161
Joined: Oct 06, 2012
PlayStation Model: SCPH-5502
Contact:

Post by Xavi92 » February 15th, 2018, 3:59 am

AFAIK, GPU command GP1(0x10) returns read-only information about the GPU, according to nocash's specs:

GP1(10h) - Get GPU Info
GP1(11h..1Fh) - Mirrors of GP1(10h), Get GPU Info
After sending the command, the result can be read (immediately) from GPUREAD register (there's no NOP or other delay required) (namely GPUSTAT.Bit27 is used only for VRAM-Reads, but NOT for GPU-Info-Reads, so do not try to wait for that flag).

0-23 Select Information which is to be retrieved (via following GPUREAD)

On Old 180pin GPUs, following values can be selected:

00h-01h = Returns Nothing (old value in GPUREAD remains unchanged)
02h = Read Texture Window setting ;GP0(E2h) ;20bit/MSBs=Nothing
03h = Read Draw area top left ;GP0(E3h) ;19bit/MSBs=Nothing
04h = Read Draw area bottom right ;GP0(E4h) ;19bit/MSBs=Nothing
05h = Read Draw offset ;GP0(E5h) ;22bit
06h-07h = Returns Nothing (old value in GPUREAD remains unchanged)
08h-FFFFFFh = Mirrors of 00h..07h

On New 208pin GPUs, following values can be selected:

00h-01h = Returns Nothing (old value in GPUREAD remains unchanged)
02h = Read Texture Window setting ;GP0(E2h) ;20bit/MSBs=Nothing
03h = Read Draw area top left ;GP0(E3h) ;20bit/MSBs=Nothing
04h = Read Draw area bottom right ;GP0(E4h) ;20bit/MSBs=Nothing
05h = Read Draw offset ;GP0(E5h) ;22bit
06h = Returns Nothing (old value in GPUREAD remains unchanged)
07h = Read GPU Type (usually 2) ;see "GPU Versions" chapter
08h = Unknown (Returns 00000000h) (lightgun on some GPUs?)
09h-0Fh = Returns Nothing (old value in GPUREAD remains unchanged)
10h-FFFFFFh = Mirrors of 00h..0Fh
On the other hand, using 2 linked OTs starting with GP1(10h) would be pretty much the same as using a bigger one with 2 GP1(10h), if I understood correctly. Actually, that would be what I'm already doing, but using the following GPU commands instead:

Code: Select all

void GsSetDrawEnv_DMA(GsDrawEnv* drawenv)
{
	unsigned int orig_pos = linked_list_pos;

    //GsDrawListPIO();

    linked_list[linked_list_pos++] = 0x05000000;
    
	linked_list[linked_list_pos++] = (0xE1 << 24) |(drawenv->draw_on_display>=1)<<10|(drawenv->dither>=1)<<9;
	linked_list[linked_list_pos++] = (0xE2 << 24);
	linked_list[linked_list_pos++] = ((0xE3 << 24) | (drawenv->x & 0x7FF) | ((drawenv->y & 0x3FF) << 10));
	linked_list[linked_list_pos++] = ((0xE4 << 24) | ((drawenv->x + drawenv->w - 1) & 0x3FF) | (((drawenv->y + drawenv->h - 1) & 0x3FF) << 10));
	linked_list[linked_list_pos++] = ((0xE5 << 24) | ((drawenv->x) & 0x7FF) | (((drawenv->y ) & 0x7FF) << 11));
	
	linked_list[orig_pos] |= ((unsigned int)&linked_list[linked_list_pos]) & 0xffffff;

	GsCurDrawEnvW = drawenv->w;
	GsCurDrawEnvH = drawenv->h;
}

User avatar
gwald
Verified
Net Yaroze Enthusiast
Net Yaroze Enthusiast
Posts: 282
Joined: Sep 18, 2013
I am a: programmer/DBA
PlayStation Model: Net Yaroze
Contact:

Post by gwald » February 17th, 2018, 8:44 pm

Hola colega!


Your splitscreen function looks wrong to me, but i haven't used that SDK.
https://github.com/XaviDCR92/Airport/bl ... Gfx.c#L882

Looks too simple to work :shrug

Code: Select all

case PLAYER_TWO:
			DrawEnv.x = X_SCREEN_RESOLUTION >> 1;
			DrawEnv.w = X_SCREEN_RESOLUTION >> 1;
break;
you should set correct x,Y and w,H on both players


From memory on my net yaroze game, you need 2 order Table & 2 packet lists per screen (2splits + 1 hud = 3 screens) and I also configured 3 DrawEnv

so,

PutDrawEnv(&Env[buf]); // set up top half for drawing
setpacket(packet[buf]);
SetView P1 view
draw P1

if player2, then
{
PutDrawEnv(&Env[buf+2]); // set up bottom half for drawing
setpacket(packet[buf+2]);
SetView P2 view
draw P2
}

PutDrawEnv(&HudEnv[buf]); // set up fullscreen or top screen or whatever for drawing HUD
setpacket(hudPacket[buf]);
SetView reset view to ID matrix // i think sprites ignore the 3D stuff.. i can't remember tho
draw Hud

wait for draw sync maybe vsync too
swap display buffer

PITA, to get working, but just do a screen at a time, it's a cool effect and it's fun!
[BBvideo=560,315]https://www.youtube.com/watch?v=37n_fBhRUY0[/BBvideo]

Saludos :dance

Xavi92
Verified
C Programming Expert
C Programming Expert
Posts: 161
Joined: Oct 06, 2012
PlayStation Model: SCPH-5502
Contact:

Post by Xavi92 » February 24th, 2018, 4:30 am

Aren't you waiting for GPU to finish each time you call "draw p#"? It looks like you are telling the GPU to draw even if the previous screen (e.g.: player 1) hasn't been fully rendered yet. Could you please provide source code for that?

User avatar
gwald
Verified
Net Yaroze Enthusiast
Net Yaroze Enthusiast
Posts: 282
Joined: Sep 18, 2013
I am a: programmer/DBA
PlayStation Model: Net Yaroze
Contact:

Post by gwald » February 27th, 2018, 3:19 pm

Xavi92 wrote: February 24th, 2018, 4:30 am Aren't you waiting for GPU to finish each time you call "draw p#"? It looks like you are telling the GPU to draw even if the previous screen (e.g.: player 1) hasn't been fully rendered yet.
No wait, it's splitscreen, the different parts of the screen get drawn at the same time.. you're just drawing to different places on screen.
Then when the draw list is finished it's DMA'ed to GPU on swapbuffer.
There's only one place to wait, as per normal.
Xavi92 wrote: February 24th, 2018, 4:30 am Could you please provide source code for that?
ahh.. I've packed it up ages ago, I'll have to go though a few harddrives... but it's not that hard..
Just try with 2 screen's then add the 3rd as per the pseudo code
I haven't looked at PSXSDK, so don't even know if it can :shrug

But reading your original post, sounds like you have split screen working, just a flickering problem.. which means your doing something extra, ie wait or swapping, when you don't need to, or your new draw env properties aren't correct, like I pointed out before.

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests