2021-07-25 13:06:55 +02:00
// Demo the different settings for pixel and primitive semi-transparency
//
2021-07-25 17:39:20 +02:00
// Schnappy 07-2021
2021-07-25 13:06:55 +02:00
# include <sys/types.h>
# include <stdio.h>
# include <libgte.h>
# include <libetc.h>
# include <libgpu.h>
# include <libapi.h>
# define VMODE 0 // Video Mode : 0 : NTSC, 1: PAL
# define SCREENXRES 320 // Screen width
# define SCREENYRES 240 // Screen height
# define CENTERX SCREENXRES / 2 // Center of screen on x
# define CENTERY SCREENYRES / 2 // Center of screen on y
# define MARGINX 16 // margins for text display
# define MARGINY 16
# define OTLEN 8 // Ordering Table Length
DISPENV disp [ 2 ] ; // Double buffered DISPENV and DRAWENV
DRAWENV draw [ 2 ] ;
u_long ot [ 2 ] [ OTLEN ] ; // double ordering table of length 8 * 32 = 256 bits / 32 bytes
char primbuff [ 2 ] [ 32768 ] ; // double primitive buffer of length 32768 * 8 = 262.144 bits / 32,768 Kbytes
char * nextpri = primbuff [ 0 ] ; // pointer to the next primitive in primbuff. Initially, points to the first bit of primbuff[0]
short db = 0 ; // index of which buffer is used, values 0, 1
// RGB pixels are 16bpp, 5b Red, 5b Green, 5b Blue, 1b STP (semi-transparency)
// See http://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf, p.183
typedef struct RGB_PIX {
u_int R : 5 , G : 5 , B : 5 , STP : 1 ;
} RGB_PIX ;
// TIM's pixel data
// See http://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf, p.182
typedef struct PIXEL {
u_long bnum ;
u_short DX , DY ;
u_short W , H ;
RGB_PIX data [ ] ;
} PIXEL ;
// TIM's CLUT section - exists only in 4/8bpp TIMs
// See See http://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf, p.181
typedef struct CLUT {
u_long bnum ;
u_short DX , DY ;
u_short W , H ;
u_short clut [ ] ;
} CLUT ;
// 4/8bpp TIM files have CLUT
typedef struct TIM_FILE_CLUT {
u_long ID ;
u_long flag ;
u_long clut ;
PIXEL pixel [ ] ;
} TIM_FILE_CLUT ;
// 16/24bpp TIM files have not CLUT member
// See See http://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf, p.179
typedef struct TIM_FILE {
u_long ID ;
u_long flag ;
PIXEL pixel [ ] ;
} TIM_FILE ;
// If we were using C++, we could use templates
//~ struct EmbeddedClut { u_long clut; };
//~ struct NoEmbeddedClut { };
//~ template<has_clut>
//~ struct TIM_FILE {
//~ u_long ID;
//~ u_long flag;
//~ std::conditional<has_clut, EmbeddedClut, NoEmbeddedClut> clut;
//~ PIXEL pixel[];
//~ };
// 16bpp TIM
// STP set on black pixels ( STP, B, R, G == 1, 0, 0 ,0)
extern TIM_FILE _binary_TIM_stpOnBlack_tim_start ;
// STP set on non black pixels ( STP, B, R, G == 1, !0, !0 ,!0)
extern TIM_FILE _binary_TIM_stpOnNonBlack_tim_start ;
// STP set on image's alpha channnel ( STP, B, R, G == 1, a, a ,a)
extern TIM_FILE _binary_TIM_stpOnAlphaI_tim_start ;
// STP set on 8bpp TIM's CLUT index 0 ( STP, B, R, G == 1, i, i, i)
extern TIM_FILE _binary_TIM_stpOnColIndex_tim_start ;
// Store in an array so we can iterate over it
TIM_FILE * timFiles [ 4 ] ;
TIM_IMAGE timImages [ 4 ] ;
// Number of primitives to draw
# define NUM_PRIM 4
// Primitive stp flag : 0 == off, 1 == on
char stpFlag = 0 ;
void LoadTexture ( TIM_FILE * tim , TIM_IMAGE * tparam ) { // This part is from Lameguy64's tutorial series : lameguy64.net/svn/pstutorials/chapter1/3-textures.html login/pw: annoyingmous
OpenTIM ( ( u_long * ) tim ) ; // Open the tim binary data, feed it the address of the data in memory
ReadTIM ( tparam ) ; // This read the header of the TIM data and sets the corresponding members of the TIM_IMAGE structure
LoadImage ( tparam - > prect , tparam - > paddr ) ; // Transfer the data from memory to VRAM at position prect.x, prect.y
DrawSync ( 0 ) ; // Wait for the drawing to end
if ( tparam - > mode & 0x8 ) { // check 4th bit // If 4th bit == 1, TIM has a CLUT
LoadImage ( tparam - > crect , tparam - > caddr ) ; // Load it to VRAM at position crect.x, crect.y
DrawSync ( 0 ) ; // Wait for drawing to end
}
}
void init ( void )
{
ResetGraph ( 0 ) ;
// Initialize and setup the GTE
InitGeom ( ) ;
SetGeomOffset ( 0 , 0 ) ;
SetGeomScreen ( CENTERX ) ;
SetDefDispEnv ( & disp [ 0 ] , 0 , 0 , SCREENXRES , SCREENYRES ) ;
SetDefDispEnv ( & disp [ 1 ] , 0 , SCREENYRES , SCREENXRES , SCREENYRES ) ;
SetDefDrawEnv ( & draw [ 0 ] , 0 , SCREENYRES , SCREENXRES , SCREENYRES ) ;
SetDefDrawEnv ( & draw [ 1 ] , 0 , 0 , SCREENXRES , SCREENYRES ) ;
if ( VMODE )
{
SetVideoMode ( MODE_PAL ) ;
disp [ 0 ] . screen . y + = 8 ;
disp [ 1 ] . screen . y + = 8 ;
}
SetDispMask ( 1 ) ; // Display on screen
setRGB0 ( & draw [ 0 ] , 255 , 0 , 128 ) ;
setRGB0 ( & draw [ 1 ] , 255 , 0 , 128 ) ;
draw [ 0 ] . isbg = 1 ;
draw [ 1 ] . isbg = 1 ;
PutDispEnv ( & disp [ db ] ) ;
PutDrawEnv ( & draw [ db ] ) ;
FntLoad ( 960 , 0 ) ;
FntOpen ( MARGINX , MARGINY , SCREENXRES - MARGINX * 2 , SCREENXRES - MARGINY * 2 , 0 , 512 ) ;
}
void display ( void )
{
DrawSync ( 0 ) ;
VSync ( 0 ) ;
PutDispEnv ( & disp [ db ] ) ;
PutDrawEnv ( & draw [ db ] ) ;
DrawOTag ( & ot [ db ] [ OTLEN - 1 ] ) ;
db = ! db ;
nextpri = primbuff [ db ] ;
}
int main ( void )
{
// Populate array with pointers to TIM data
timFiles [ 0 ] = & _binary_TIM_stpOnBlack_tim_start ;
timFiles [ 1 ] = & _binary_TIM_stpOnNonBlack_tim_start ;
timFiles [ 2 ] = & _binary_TIM_stpOnAlphaI_tim_start ;
timFiles [ 3 ] = & _binary_TIM_stpOnColIndex_tim_start ;
// Init Disp/Draw, double buffer, font
init ( ) ;
// Init proto pad
PadInit ( 0 ) ;
int pad , oldPad ;
2021-07-25 17:39:20 +02:00
// Pointer to a POLY_G4
POLY_FT4 * poly [ 4 ] = { 0 } ;
2021-07-25 13:06:55 +02:00
SVECTOR VertPos [ 4 ] = { // Set initial vertices position relative to 0,0 - see here : https://psx.arthus.net/docs/poly_f4.jpg
{ - 32 , - 32 , 1 } , // Vert 1
{ - 32 , 32 , 1 } , // Vert 2
{ 32 , - 32 , 1 } , // Vert 3
{ 32 , 32 , 1 } // Vert 4
} ;
2021-07-25 17:39:20 +02:00
VECTOR transVector = { SCREENXRES / 3 , SCREENYRES / 4 , 128 , 0 } ; // Initialize translation vector {x, y, z, pad}
SVECTOR rotVector = { 0 } ; // Initialize rotation vector {x, y, z}
2021-07-25 13:06:55 +02:00
// Load textures to VRAM
2021-07-25 17:39:20 +02:00
for ( char tim = 0 ; tim < NUM_PRIM ; tim + + ) {
2021-07-25 13:06:55 +02:00
LoadTexture ( timFiles [ tim ] , & timImages [ tim ] ) ;
}
while ( 1 )
{
2021-07-25 17:39:20 +02:00
MATRIX Work ;
2021-07-25 13:06:55 +02:00
// Clear OT
ClearOTagR ( ot [ db ] , OTLEN ) ;
// Use a temporary work matrix
// Set Trans/Rot vectors to work matrix
2021-07-25 17:39:20 +02:00
RotMatrix ( & rotVector , & Work ) ; // Apply rotation matrix
TransMatrix ( & Work , & transVector ) ; // Apply translation matrix
2021-07-25 13:06:55 +02:00
SetRotMatrix ( & Work ) ; // Set default rotation matrix
SetTransMatrix ( & Work ) ; // Set default transformation matrix
// Draw NUM_PRIM primitives
for ( int i = 0 ; i < NUM_PRIM ; i + + ) {
long p , flag ;
// Draw prims with an offset base on iteration number
2021-07-25 17:39:20 +02:00
transVector . vx = SCREENXRES / NUM_PRIM + ( i * ( SCREENXRES / NUM_PRIM + 32 ) ) ;
transVector . vy = SCREENYRES / NUM_PRIM ;
2021-07-25 13:06:55 +02:00
if ( i > = 2 ) {
2021-07-25 17:39:20 +02:00
transVector . vx = SCREENXRES / NUM_PRIM + ( ( i - 2 ) * ( SCREENXRES / NUM_PRIM + 32 ) ) ;
transVector . vy = SCREENYRES / 2 + 24 ;
2021-07-25 13:06:55 +02:00
}
2021-07-25 17:39:20 +02:00
TransMatrix ( & Work , & transVector ) ;
2021-07-25 13:06:55 +02:00
SetTransMatrix ( & Work ) ;
// Set poly
poly [ i ] = ( POLY_FT4 * ) nextpri ; // Set poly to point to the address of the next primitiv in the buffer
setPolyFT4 ( poly [ i ] ) ; // Initialize poly as a POLY_F4
// Get texture page
poly [ i ] - > tpage = getTPage ( timImages [ i ] . mode & 0x3 ,
0 ,
// Get Tpage coordinates from the TIM_IMAGE mode and prect members.
timImages [ i ] . prect - > x ,
timImages [ i ] . prect - > y ) ;
// If 8/4bpp, get CLUT
if ( ( timImages [ i ] . mode & 0x3 ) < 2 ) {
setClut ( poly [ i ] ,
timImages [ i ] . crect - > x ,
timImages [ i ] . crect - > y
) ;
}
setRGB0 ( poly [ i ] , 128 , 128 , 128 ) ; // Set poly color (neutra here)
SetSemiTrans ( poly [ i ] , stpFlag ) ;
RotTransPers4 (
& VertPos [ 0 ] , & VertPos [ 1 ] , & VertPos [ 2 ] , & VertPos [ 3 ] ,
( long * ) & poly [ i ] - > x0 , ( long * ) & poly [ i ] - > x1 , ( long * ) & poly [ i ] - > x2 , ( long * ) & poly [ i ] - > x3 ,
& p ,
& flag
) ; // Perform coordinate and perspective transformation for 4 vertices
setUV4 ( poly [ i ] , 0 , 0 , 0 , 144 , 144 , 0 , 144 , 144 ) ; // Set UV coordinates in order Top Left, Bottom Left, Top Right, Bottom Right
// Add poly to the Ordering table
addPrim ( ot [ db ] , poly [ i ] ) ;
// Increment nextpri address with size of a POLY_F4 struct
nextpri + = sizeof ( POLY_FT4 ) ;
}
// Get pad input
pad = PadRead ( 0 ) ;
// If select button is used
if ( pad & PADselect & & ! ( pad & oldPad ) ) {
// Flip STP flag
stpFlag = ! stpFlag ;
// Set flag to avoir misfire
oldPad = pad ;
}
// Reset flag when button released
if ( ! ( pad & PADselect ) ) {
oldPad = 0 ;
}
FntPrint ( " Hello semi-transparency ! \n Prim STP (push Select) : %d \n \n \n \n \n \n \n \n \n \n \n \n " , stpFlag ) ;
FntPrint ( " stp on black stp on non-black \n \n \n \n \n \n \n \n \n \n \n \n " ) ;
FntPrint ( " stp on non-black stp on col index " ) ;
FntFlush ( - 1 ) ;
display ( ) ;
}
return 0 ;
}