Question about transition

Graphic based area of development (Graphics Processing Unit), including the Geometry Transform Engine (GTE), TIM, STR (MDEC), etc.
Post Reply
User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Question about transition

Post by NITROYUASH » May 24th, 2018, 5:08 am

Hi PSXDEV :>

I want to do smooth transition between screens, but i have no idea how it works.
Can you explain how it works in PS1?

Sblorgz
Curious PSXDEV User
Curious PSXDEV User
Posts: 22
Joined: May 18, 2015

Post by Sblorgz » May 24th, 2018, 6:41 am

You would use a TILE + DMODE primitive that covers the whole screen, create the DMODE as subtractive color, then change the TILE RGB to change fade transition. RGB = 255 means the mask will make the screen fully black, RGB = 0 makes the screen visible again.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » May 26th, 2018, 9:49 pm

Okay, after 2 days of mistakes, i'm still don't get it how it works.
Did i miss something?

Code: Select all

void TileTest () {

	DR_MODE dr_prim;
	TILE	tl_prim;

	FntLoad(960, 256);
	FntOpen(0, 0, SCREENXRES, SCREENYRES, 0, 512);

	SetTile16(&tl_prim);
	SetDrawMode(&dr_prim, 0, 0, GetTPage(0, 0, 0, 0), 0);
	SetSemiTrans(&tl_prim, 0);
	MargePrim(&dr_prim, &tl_prim);

	setRGB0(&tl_prim, 128, 128, 128);

	setXY0(&tl_prim, CENTERX, CENTERY);
	setWH (&tl_prim, 64, 64);
	
	while (1) {
		PrepDisp();
		sp_cursor();

		FntPrint("\n\n             %c TILE Test %c", cursor[pos], cursor[pos]);

		AddPrim(&myOT[ActiveBuffer], &tl_prim);

		Display();
	}
}
EPSXE crash:
► Show Spoiler

Sblorgz
Curious PSXDEV User
Curious PSXDEV User
Posts: 22
Joined: May 18, 2015

Post by Sblorgz » May 27th, 2018, 2:02 am

That's because you need two primitives, one per draw environment. Also, you need to set the transparency flag on TILEs otherwise blending won't trigger.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » June 22nd, 2018, 9:53 pm

alright, i'm back and ready for educating :)

so, where i can find some good examples how TILEs working? It's seems that my code isn't working (still no tiles).

Code: Select all

// Loading basic PS1 libraries
#include <sys/types.h>
#include <libgte.h>
#include <libgpu.h>
#include <libetc.h>
#include <stdlib.h>
#include <stdio.h>

#define OT_LENGTH	12				// OT precision/size
#define OT_ENTRIES	1<<OT_LENGTH
#define MAX_PRIMS	16384			// Primitive area size

// Screen resolution
#define SCREENXRES	320
#define SCREENYRES	240

// Calculate center of screen
#define CENTERX		SCREENXRES/2
#define CENTERY		SCREENYRES/2

// Stuff for display and rendering
DISPENV 	disp;
DRAWENV 	draw;
RECT		ClearRect	={ 0, 0, SCREENXRES, SCREENYRES };

u_long		myOT[2][OT_ENTRIES];	// Ordering table (contains pointers to primitives)
u_long		myPrims[2][MAX_PRIMS];	// Primitive list (can contain various primitive types)
u_long		*myPrimPtr=0;			// Next primitive pointer
int		ActivePage=0;	

// Spinning cursor
static char 		pos=0;
static char		cur_frame=0;
char 			cursor[4]={'/','-','\\','i'};

int main();
void Init();
void sp_cursor();

int main() {
	
	DR_MODE 	dr_prim;
	TILE		tl_prim;
	
	long	i, p, t, OTz, OTc, Flag, nclip;
	int		NumPrims;
	
	int		r, g, b;

	Init();

	FntLoad(960, 256);
	FntOpen(0, 0, SCREENXRES, SCREENYRES, 0, 512);

	SetTile(&tl_prim);
	SetDrawMode(&dr_prim, 0, 0, GetTPage(0, 0, 0, 0), 0);
	SetSemiTrans(&tl_prim, 1);
	MargePrim(&dr_prim, &tl_prim);

	setRGB0(&tl_prim, 128, 128, 128);
	setXY0(&tl_prim, 120, 120);
	setWH (&tl_prim, 64, 64);
	
	while (1) {

		// Toggle buffer index
		ActivePage = (ActivePage + 1) & 1;

		// Clear the current OT
		ClearOTagR(&myOT[ActivePage][0], OT_ENTRIES);

		sp_cursor();
		FntPrint("\n\n             %c TILE Test %c", cursor[pos], cursor[pos]);
		
		AddPrim(&myOT[ActivePage][OTc], &dr_prim);

		// Prepare to switch buffers
		SetDefDispEnv(&disp, 0, 256*ActivePage, SCREENXRES, SCREENYRES);
		SetDefDrawEnv(&draw, 0, 256*(1-ActivePage), SCREENXRES, SCREENYRES);

		// Wait for all drawing to finish and wait for VSync
		while(DrawSync(1));
		VSync(0);
		
		if (PadRead(0) & PADRright) r++;
		if (PadRead(0) & PADRup) g++;
		if (PadRead(0) & PADRdown) b++;
		
		if (PadRead(0) & PADL1) r--;
		if (PadRead(0) & PADL2) g--;
		if (PadRead(0) & PADR1) b--;
		
		// Switch display buffers
		PutDispEnv(&disp);
		PutDrawEnv(&draw);
		
		// Clear the drawing buffer before drawing the next frame
		ClearRect.y = 256*(1-ActivePage);
		ClearImage(&ClearRect, 0, 0, 0);
		
		// Begin drawing the new frame
		DrawOTag(&myOT[ActivePage][OT_ENTRIES-1]);
		FntFlush(0);
		
		SetDispMask(1);

	}

}

void Init() {
	
	// Reset the GPU and initialize the controller
	ResetGraph(0);
	PadInit(0);
	SetVideoMode(0);
	
	// Init font system
	FntLoad(960, 0);
	FntOpen(0, 0, SCREENXRES, SCREENYRES, 0, 512);
	
	// Initialize and setup the GTE
	InitGeom();
	SetGeomOffset(CENTERX, CENTERY);
	SetGeomScreen(CENTERX);
	
	
	// Set the display and draw environments
	SetDefDispEnv(&disp, 0, 0, SCREENXRES, SCREENYRES);
	SetDefDrawEnv(&draw, 0, 256, SCREENXRES, SCREENYRES);
	
	
	// Set the new display/drawing environments
	VSync(0);
	PutDispEnv(&disp);
	PutDrawEnv(&draw);
	ClearImage(&ClearRect, 0, 0, 0);
	
}

void sp_cursor() {
	cur_frame++;
	if (cur_frame >= 8) {
		cur_frame = 0;
		pos = (pos+1) % 4;
	}
}
► Show Spoiler

Sblorgz
Curious PSXDEV User
Curious PSXDEV User
Posts: 22
Joined: May 18, 2015

Post by Sblorgz » June 23rd, 2018, 2:04 am

You still have only one primitive for each type, you need two per frame: they have to be different or otherwise DMA will commit suicide. Also you aren't setting any blending mode in DR_MODE.

User avatar
Shadow
Verified
Admin / PSXDEV
Admin / PSXDEV
Posts: 2670
Joined: Dec 31, 2012
PlayStation Model: H2000/5502
Discord: Shadow^PSXDEV

Post by Shadow » June 23rd, 2018, 2:34 am

Sony has some TILE examples in Psy-Q.
Development Console: SCPH-5502 with 8MB RAM, MM3 Modchip, PAL 60 Colour Modification (for NTSC), PSIO Switch Board, DB-9 breakout headers for both RGB and Serial output and an Xplorer with CAETLA 0.34.

PlayStation Development PC: Windows 98 SE, Pentium 3 at 400MHz, 128MB SDRAM, DTL-H2000, DTL-H2010, DTL-H201A, DTL-S2020 (with 4GB SCSI-2 HDD), 21" Sony G420, CD-R burner, 3.25" and 5.25" Floppy Diskette Drives, ZIP 100 Diskette Drive and an IBM Model M keyboard.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » June 23rd, 2018, 2:47 am

Sblorgz
It's working! I forgot to create a second TILE. lol!
► Show Spoiler

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » June 25th, 2018, 8:57 am

Transition effect is working, but i have yet another trouble.

If i'm loading some sprites/textures/etc, there is high chance to crash the game or get some graphical garbage on the screen. But sometimes everything is fine o_o'''

Code: Select all

void TileTest () {

	DR_MODE 	dr_prim;
	TILE		tl_prim;
	TILE		tl_prim_2;
	
	int rt = 255, gt = 255, bt = 255;

	FntLoad(960, 256);
	FntOpen(0, 0, SCREENXRES, SCREENYRES, 0, 512);

	SetTile(&tl_prim);
	SetDrawMode(&dr_prim, 0, 0, GetTPage(0, 2, 0, 0), 0);
	SetSemiTrans(&tl_prim, 1);

	setXY0(&tl_prim, 0, 0);
	setWH (&tl_prim, SCREENXRES, SCREENYRES);

	MargePrim(&dr_prim, &tl_prim_2);

	STARTSCR[0] = PrepDataSPR(MenuSCRTim[2], CENTERX, CENTERY, 128, 128, 128);
	STARTSCR[0].w = 256;
	STARTSCR[1].w = 64;
	STARTSCR[1] = PrepDataSPR(MenuSCRTim[2], CENTERX+256, CENTERY, 128, 128, 128);
	STARTSCR[1].tpage = (GetTPage(2,0,256,240))+5;
	START_TEXT = PrepDataSPR(MenuSCRTim[1], CENTERX, CENTERY+75, 128, 128, 128);
	
	while (1) {
		//PrepDisp();

		//PrepDisp ->
		ActiveBuffer = GsGetActiveBuff();
		GsSetWorkBase((PACKET*)GPUPacketArea[ActiveBuffer]);
		GsClearOt(0, 0, &myOT[ActiveBuffer][0]);
		// <-
		
		setRGB0(&tl_prim, rt, gt, bt);

		AddPrim((u_long *)&myOT[ActiveBuffer][0], &tl_prim);
		AddPrim((u_long *)&myOT[ActiveBuffer][0], &tl_prim_2);
		AddPrim((u_long *)&myOT[ActiveBuffer][0], &dr_prim);
		
		GsSortSprite(&START_TEXT, &myOT[ActiveBuffer][0], 0);
		GsSortSprite(&STARTSCR[0], &myOT[ActiveBuffer][0], 0);
		GsSortSprite(&STARTSCR[1], &myOT[ActiveBuffer][0], 0);

		if (PadRead(0) & PADL1) rt++, gt++, bt++;
		if (PadRead(0) & PADR1) rt--, gt--, bt--;
		if (PadRead(0) & PADselect) rt = 0, gt = 0, bt = 0;
		if (PadRead(0) & PADstart) rt = 255, gt = 255, bt = 255;

		DrawOTag((u_long *)&myOT[ActiveBuffer][0]);

		//Display();

		//Display ->
		VSync(0);

		GsSwapDispBuff();
		GsSortClear(0, 0, 0, &myOT[ActiveBuffer][0]);
		GsDrawOt(&myOT[ActiveBuffer][0]);
		// <-
	}
}
► Show Spoiler
Did i miss something important again?

Sblorgz
Curious PSXDEV User
Curious PSXDEV User
Posts: 22
Joined: May 18, 2015

Post by Sblorgz » June 25th, 2018, 6:19 pm

You're still doing it incorrectly, you need something like this:

Code: Select all

// declaration
TILE t[2];
DR_MODE m[2];
[...]
// inside draw loop
AddPrim((u_long *)&myOT[ActiveBuffer][0], &t[ActiveBuffer]);
AddPrim((u_long *)&myOT[ActiveBuffer][0], &m[ActiveBuffer]);
Also don't bother with MargePrim(), it's pretty much broken when two primitives are not consecutive in memory. On top of that, there's no need for DrawOTag() if you already have GsDrawOt().

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » June 25th, 2018, 9:29 pm

And TILE/DR attributes need to be like this (without MergePrim), right?

Code: Select all

	SetTile(&tile[2]);
	SetDrawMode(&dr_prim[2], 0, 0, GetTPage(0, 2, 0, 0), 0);
	SetSemiTrans(&tile[2], 1);

	setRGB0(&tile[2], 128, 128, 128);
	setXY0(&tile[2], 0, 0);
	setWH (&tile[2], SCREENXRES, SCREENYRES);

Sblorgz
Curious PSXDEV User
Curious PSXDEV User
Posts: 22
Joined: May 18, 2015

Post by Sblorgz » June 26th, 2018, 2:21 pm

Try a better solution like a loop to initialize those primitives:

Code: Select all

// after declaration
for(i = 0; i < 2; i++)
{
	setTile(&tile[i]);
	setDrawMode(&dr_prim[i], 0, 0, getTPage(0, 2, 0, 0), 0);
	setSemiTrans(&tile[i], 1);

	setRGB0(&tile[i], 128, 128, 128);
	setXY0(&tile[i], 0, 0);
	setWH (&tile[i], SCREENXRES, SCREENYRES);
}
//draw loop goes here
Remember to use macros instead of functions (they all start with a lowercase letter), they tend to bloat the binary a bit, but they provide a good boost in performance.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » June 26th, 2018, 8:51 pm

Huh. Without ClearOTagR() tiles didn't work (invisible?).
Of course with ClearOTag all screen is clearing except TILE's.

Tile test code:

Code: Select all

void TileTest () {

	DR_MODE 	dr_prim[2];
	TILE		tile[2];
	
	int rt = 0, gt = 0, bt = 0;
	int i;

	for(i = 0; i < 2; i++)
	{
		SetTile(&tile[i]);
		SetDrawMode(&dr_prim[i], 0, 0, getTPage(0, 0, 0, 0), 0);
		SetSemiTrans(&tile[i], 0);

		setXY0(&tile[i], 220, 64);
		setWH (&tile[i], SCREENXRES/4, SCREENYRES/4);
	}

	FntLoad(960, 256);
	FntOpen(0, 0, SCREENXRES, SCREENYRES, 0, 512);

	STARTSCR[0] = PrepDataSPR(MenuSCRTim[2], CENTERX, CENTERY, 128, 128, 128);
	STARTSCR[0].w = 256;
	
	while (1) {
		ActiveBuffer = GsGetActiveBuff();
		GsSetWorkBase((PACKET*)GPUPacketArea[ActiveBuffer]);
		GsClearOt(0, 0, &myOT[ActiveBuffer][0]);
		
		ClearOTagR((u_long *)&myOT[ActiveBuffer][0], OT_ENTRIES);

		for(i = 0; i < 2; i++) {
			setRGB0(&tile[i], rt, gt, bt);
		}

		AddPrim((u_long *)&myOT[ActiveBuffer][0], &tile[ActiveBuffer]);
		AddPrim((u_long *)&myOT[ActiveBuffer][0], &dr_prim[ActiveBuffer]);

		GsSortSprite(&STARTSCR[0], &myOT[ActiveBuffer][0], 0);

		if (PadRead(0) & PADL1) rt++, gt++, bt++;
		if (PadRead(0) & PADR1) rt--, gt--, bt--;
		if (PadRead(0) & PADselect) rt = 0, gt = 0, bt = 0;
		if (PadRead(0) & PADstart) rt = 255, gt = 255, bt = 255;
		if (PadRead(0) & PADRright) break;
		
		if (rt < 1 || gt < 1 || bt < 1) rt = gt = bt = 0;
		if (rt > 255 || gt > 255 || bt > 255) rt = gt = bt = 255;

		FntFlush(-1);
		VSync(0);
		GsSwapDispBuff();
		GsSortClear(0, 0, 0, &myOT[ActiveBuffer][0]);
		GsDrawOt(&myOT[ActiveBuffer][0]);
	}
}

Sblorgz
Curious PSXDEV User
Curious PSXDEV User
Posts: 22
Joined: May 18, 2015

Post by Sblorgz » June 26th, 2018, 10:57 pm

You have a call to ClearOTagR() that isn't necessary because it's already in GsClearOt(). Also do not update both TILE primitives' RGB channels, only redefine those for the current buffer TILE or otherwise you will get glitches with colors jumping around.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » June 27th, 2018, 12:36 am

tried everything, but...
Without ClearOTagR() tiles didn't work
._ .

Sblorgz
Curious PSXDEV User
Curious PSXDEV User
Posts: 22
Joined: May 18, 2015

Post by Sblorgz » June 27th, 2018, 1:09 am

You can't mix libgpu and libgs unless you know exactly what the latter does internally. With that said, I think you are missing quite a few initialization points for libgs internals, like OTag definitions for size and ot starting pointers. Functions such as GsClearOt require a GsOT structure for myOt, which in your code was declared as a simple u_long. Posting the whole thing again instead of snippets would help in figuring out what you're missing.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » June 27th, 2018, 1:39 am

Posting the whole thing again instead of snippets would help in figuring out what you're missing.
I will sent my project in your PM, okay?

Sblorgz
Curious PSXDEV User
Curious PSXDEV User
Posts: 22
Joined: May 18, 2015

Post by Sblorgz » June 27th, 2018, 2:13 am

Sure, send a pastebin link, it's easier to read.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » June 27th, 2018, 6:31 am

We found a solution. Perhaps it will be useful for someone :)

Code: Select all

void TileTest () {

	DR_MODE 	dr_prim[2];
	TILE		tile[2];
	
	int rt = 255, gt = 255, bt = 255;
	int i;

	for(i = 0; i < 2; i++)
	{
		SetTile(&tile[i]);
		SetDrawMode(&dr_prim[i], 0, 0, getTPage(0, 2, 0, 0), 0);
		SetSemiTrans(&tile[i], 1);

		setXY0(&tile[i], 0, 0);
		setWH (&tile[i], SCREENXRES, SCREENYRES);
	}

	FntLoad(960, 256);
	FntOpen(0, 0, SCREENXRES, SCREENYRES, 0, 512);
	
	while (1) {
		PrepDisp();
		
		for(i = 0; i < 2; i++) setRGB0(&tile[i], rt, gt, bt);

		sp_cursor();

		FntPrint("\n\n             %c TILE Test %c", cursor[pos], cursor[pos]);
		FntPrint("\n\n         R:%d  G:%d  B:%d  ", rt, gt, bt);

		AddPrim((u_long *)myOT[ActiveBuffer][0].org, &tile[ActiveBuffer]);
		AddPrim((u_long *)myOT[ActiveBuffer][0].org, &dr_prim[ActiveBuffer]);

		if (PadRead(0) & PADL1) rt++, gt++, bt++;
		if (PadRead(0) & PADR1) rt--, gt--, bt--;
		if (PadRead(0) & PADselect) rt = 0, gt = 0, bt = 0;
		if (PadRead(0) & PADstart) rt = 255, gt = 255, bt = 255;
		
		if (rt < 1 || gt < 1 || bt < 1) rt = gt = bt = 0;
		if (rt > 255 || gt > 255 || bt > 255) rt = gt = bt = 255;

		Display();
	}
}

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests