Page 1 of 1

Question about transition

Posted: May 24th, 2018, 5:08 am
by NITROYUASH
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?

Re: Question about transition

Posted: May 24th, 2018, 6:41 am
by Sblorgz
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.

Re: Question about transition

Posted: May 26th, 2018, 9:49 pm
by NITROYUASH
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

Re: Question about transition

Posted: May 27th, 2018, 2:02 am
by Sblorgz
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.

Re: Question about transition

Posted: June 22nd, 2018, 9:53 pm
by NITROYUASH
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

Re: Question about transition

Posted: June 23rd, 2018, 2:04 am
by Sblorgz
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.

Re: Question about transition

Posted: June 23rd, 2018, 2:34 am
by Shadow
Sony has some TILE examples in Psy-Q.

Re: Question about transition

Posted: June 23rd, 2018, 2:47 am
by NITROYUASH
Sblorgz
It's working! I forgot to create a second TILE. lol!
► Show Spoiler

Re: Question about transition

Posted: June 25th, 2018, 8:57 am
by NITROYUASH
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?

Re: Question about transition

Posted: June 25th, 2018, 6:19 pm
by Sblorgz
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().

Re: Question about transition

Posted: June 25th, 2018, 9:29 pm
by NITROYUASH
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);

Re: Question about transition

Posted: June 26th, 2018, 2:21 pm
by Sblorgz
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.

Re: Question about transition

Posted: June 26th, 2018, 8:51 pm
by NITROYUASH
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]);
	}
}

Re: Question about transition

Posted: June 26th, 2018, 10:57 pm
by Sblorgz
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.

Re: Question about transition

Posted: June 27th, 2018, 12:36 am
by NITROYUASH
tried everything, but...
Without ClearOTagR() tiles didn't work
._ .

Re: Question about transition

Posted: June 27th, 2018, 1:09 am
by Sblorgz
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.

Re: Question about transition

Posted: June 27th, 2018, 1:39 am
by NITROYUASH
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?

Re: Question about transition

Posted: June 27th, 2018, 2:13 am
by Sblorgz
Sure, send a pastebin link, it's easier to read.

Re: Question about transition

Posted: June 27th, 2018, 6:31 am
by NITROYUASH
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();
	}
}