diff options
Diffstat (limited to 'examples/demos/n00bdemo/main.c')
| -rw-r--r-- | examples/demos/n00bdemo/main.c | 650 |
1 files changed, 650 insertions, 0 deletions
diff --git a/examples/demos/n00bdemo/main.c b/examples/demos/n00bdemo/main.c new file mode 100644 index 0000000..a6eb57e --- /dev/null +++ b/examples/demos/n00bdemo/main.c @@ -0,0 +1,650 @@ +/* + * LibPSn00b Example Programs + * + * n00bDEMO Source Code + * 2019 Meido-Tek Productions / PSn00bSDK Project + * + * To build, simply run make. Make sure you have the lzpack tool accessible + * through your PATH environment variable. + * + * Demo by Lameguy64 + * + * Changelog: + * + * Apr 4, 2019 - Some code clean-up and added more comments. + * + * Mar 20, 2019 - Initial completed version. + * + */ + +#include <sys/fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <psxetc.h> +#include <psxgte.h> +#include <psxgpu.h> +#include <psxspu.h> +#include <inline_c.h> +#include <string.h> +#include <lzp.h> +#include <lzqlp.h> + +#include "malloc.h" +#include "smd.h" +#include "data.h" +#include "disp.h" +#include "logo.h" +#include "plasma_tbl.h" + + +// Standard light color matrix +MATRIX lgt_colmtx = { + //#1,#2,#3 + ONE, 0, 0, // R + ONE, 0, 0, // G + ONE, 0, 0 // B +}; + +// SMD data global pointers +SMD *o_rbowshade; +SMD *o_world, *o_lightbulb; +SMD *o_timerift, *o_star; +SMD *o_hatkid,*o_bungirl;; + +// TPage and CLUT globals +unsigned short lamelotl_tpage,psn00b_tpage; +unsigned short font_tpage,font_clut; +SPRT llotl_sprite; +SPRT psn00b_sprite; + + +// Some function definition +void sort_overlay(int showlotl); +void lightdemo(); + + +void UploadTIM(TIM_IMAGE *tim) { + + /* + Very simple texture upload function + */ + + LoadImage( tim->prect, tim->paddr ); + + if( tim->mode & 0x8 ) + LoadImage( tim->crect, tim->caddr ); + +} + +void loadTextures() { + + /* + Unpack textures from an embedded LZP archive and upload them to VRAM. + */ + int i; + int *tex_buff,*ttim,j; + TIM_IMAGE tim; + + i = lzpSearchFile( "textures", lz_resources ); + tex_buff = (int*)malloc( lzpFileSize( lz_resources, i ) ); + lzpUnpackFile( tex_buff, lz_resources, i ); + + + for( j=0; j<qlpFileCount( tex_buff )-4; j++ ) { + + if( !GetTimInfo( (unsigned int*)qlpFileAddr( j, tex_buff ), &tim ) ) { + + UploadTIM( &tim ); + + } + + } + + + GetTimInfo( (unsigned int*)qlpFileAddr( + qlpFindFile( "n00blogo", tex_buff ), tex_buff ), &tim ); + + UploadTIM( &tim ); + + psn00b_tpage = getTPage( 0, 0, tim.prect->x, tim.prect->y )|0x200; + setSprt( &psn00b_sprite ); + setClut( &psn00b_sprite, tim.crect->x, tim.crect->y ); + setWH( &psn00b_sprite, tim.prect->w<<2, tim.prect->h ); + setUV0( &psn00b_sprite, (tim.prect->x%64)<<2, tim.prect->y ); + setRGB0( &psn00b_sprite, 128, 128, 128 ); + + + GetTimInfo( (unsigned int*)qlpFileAddr( + qlpFindFile( "lamelotl", tex_buff ), tex_buff ), &tim ); + + UploadTIM( &tim ); + + lamelotl_tpage = getTPage( 0, 0, tim.prect->x, tim.prect->y )|0x200; + setSprt( &llotl_sprite ); + setClut( &llotl_sprite, tim.crect->x, tim.crect->y ); + setWH( &llotl_sprite, tim.prect->w<<2, tim.prect->h ); + setUV0( &llotl_sprite, 0, 0 ); + setRGB0( &llotl_sprite, 128, 128, 128 ); + + + GetTimInfo( (unsigned int*)qlpFileAddr( + qlpFindFile( "celmap", tex_buff ), tex_buff ), &tim ); + + UploadTIM( &tim ); + + smdSetCelTex( getTPage( 0, 2, tim.prect->x, tim.prect->y )|0x200, + getClut( tim.crect->x, tim.crect->y ) ); + smdSetCelParam( 3, 3, 0x4f4f4f ); + + + GetTimInfo( (unsigned int*)qlpFileAddr( + qlpFindFile( "font", tex_buff ), tex_buff ), &tim ); + + UploadTIM( &tim ); + + font_tpage = getTPage( 0, 1, tim.prect->x, tim.prect->y )|0x200; + font_clut = getClut( tim.crect->x, tim.crect->y ); + +} + +void unpackModels() { + + /* + Unpack model data from an embedded LZP archive. + */ + + int i; + + i = lzpSearchFile( "rbowshade", lz_resources ); + o_rbowshade = (SMD*)malloc( lzpFileSize( lz_resources, i ) ); + lzpUnpackFile( o_rbowshade, lz_resources, i ); + smdInitData( o_rbowshade ); + + i = lzpSearchFile( "bungirl", lz_resources ); + o_bungirl = (SMD*)malloc( lzpFileSize( lz_resources, i ) ); + lzpUnpackFile( o_bungirl, lz_resources, i ); + smdInitData( o_bungirl ); + + i = lzpSearchFile( "lightworld", lz_resources ); + o_world = (SMD*)malloc( lzpFileSize( lz_resources, i ) ); + lzpUnpackFile( o_world, lz_resources, i ); + smdInitData( o_world ); + + i = lzpSearchFile( "lightbulb", lz_resources ); + o_lightbulb = (SMD*)malloc( lzpFileSize( lz_resources, i ) ); + lzpUnpackFile( o_lightbulb, lz_resources, i ); + smdInitData( o_lightbulb ); + + i = lzpSearchFile( "timerift", lz_resources ); + o_timerift = (SMD*)malloc( lzpFileSize( lz_resources, i ) ); + lzpUnpackFile( o_timerift, lz_resources, i ); + smdInitData( o_timerift ); + + i = lzpSearchFile( "starmask", lz_resources ); + o_star = (SMD*)malloc( lzpFileSize( lz_resources, i ) ); + lzpUnpackFile( o_star, lz_resources, i ); + smdInitData( o_star ); + + i = lzpSearchFile( "hatkid", lz_resources ); + o_hatkid = (SMD*)malloc( lzpFileSize( lz_resources, i ) ); + lzpUnpackFile( o_hatkid, lz_resources, i ); + smdInitData( o_hatkid ); + +} + +void init() { + + int i; + + // Init display + initDisplay(); + + FntLoad( 960, 0 ); + + // Just to remove all sound + SpuInit(); + + // Load all textures + loadTextures(); + +} + +// Bungirl stuff +void bungirldemo() { + + /* + The bunny girl demo is just a simple demonstration of rendering a 1390 + polygon 3D model of a bunny girl with lighting using SMD drawing routines + from Scarlet Engine. + */ + + SC_OT s_ot; + + MATRIX lmtx; + + SVECTOR rot,brot,srot; + VECTOR pos; + + int timeout = SCENE_TIME; + + // Set clear color + setRGB0( &draw, 63, 0, 127 ); + + // Set tpage base value for SMD drawing routines + smdSetBaseTPage( 0x200 ); + + // Set initial rotation values + setVector( &rot, 192, 0, 0 ); + setVector( &brot, 0, 0, 128 ); + setVector( &srot, 0, 0, 0 ); + + // Set lighting color matrix + gte_SetColorMatrix( &lgt_colmtx ); + + // Set 'backside' or ambient light color + gte_SetBackColor( 113, 113, 113 ); + + + // Demo loop + while( 1 ) { + + // Bungirl position + setVector( &pos, 0, 50, 350 ); + + TransMatrix( &mtx, &pos ); + RotMatrix( &brot, &mtx ); + + // Calculate light matrix + lmtx.m[0][0] = isin( -brot.vy<<2 ); + lmtx.m[0][1] = -2048; + lmtx.m[0][2] = icos( -brot.vy<<2 ); + + MulMatrix0( &lmtx, &mtx, &lmtx ); + + // Set matrices + gte_SetRotMatrix( &mtx ); + gte_SetTransMatrix( &mtx ); + gte_SetLightMatrix( &lmtx ); + + // Sort the bungirl model + s_ot.ot = ot[db]; + s_ot.otlen = OT_LEN; + s_ot.zdiv = 1; + s_ot.zoff = 0; + nextpri = smdSortModel( &s_ot, nextpri, o_bungirl ); + + + // Sort the rotating rainbow background + setVector( &pos, 0, 0, 200 ); + + TransMatrix( &mtx, &pos ); + RotMatrix( &srot, &mtx ); + + gte_SetRotMatrix( &mtx ); + gte_SetTransMatrix( &mtx ); + nextpri = smdSortModelFlat( ot[db]+(OT_LEN-1), nextpri, o_rbowshade ); + + brot.vy += 8; + srot.vz += 4; + + + // Sort overlay then display + sort_overlay( 0 ); + + display(); + + timeout--; + if( timeout < 0 ) + break; + + } + +} + +// Stencil effect stuff +void stencilstuff() { + + /* + The stencil demo is achieved by utilizing the mask bit setting + primitive GP0(E6h). The structure of this primitive is defined as + DR_MASK initialized and set by setDrawMask(). These are not available + in Sony's SDK by default. + + The DR_MASK primitive controls mask bit operations for drawing + primitives such as setting mask bits on every pixel drawn or mask + bit test where pixels won't be drawn on pixels with the mask bit set. + It applies to most graphics drawing primitives except VRAM fill. + The mask bits are stored in the 16th bit of each pixel drawn. + + The semi-transparency bits of a texture always carry over as mask + bits in textured primitives. The only way to clear mask bits is by + using VRAM fill commands or drawing primitives with the set mask + bit operation disabled. + + The stencil effect featured in this demo is achieved by enabling set + mask bit with DR_MASK, drawing semi-transparent primitives using + additive blending but color is all zero to make it completely invisible + but is enough to update the mask bits, disable mask set bit but enable + mask test with DR_MASK and then drawing a rectangle that fills the + entire screen. Semi-transparency mask in textures must not be used when + drawing the scene that will be 'below' the mask layer. + */ + int timeout = SCENE_TIME; + + int spin=0; + + DR_MASK *mask; + TILE *rect; + + SC_OT s_ot; + + SVECTOR rot; + SVECTOR srot; + VECTOR pos; + + // Set clear color + setRGB0( &draw, 127, 0, 63 ); + + // Set tpage base value for SMD drawing routines + smdSetBaseTPage( 0x200 ); + + // Base rotation coordinates + setVector( &rot, 0, 0, 0 ); + setVector( &srot, 0, 0, 0 ); + + // Set perspective + gte_SetGeomScreen( 320 ); + + + // Demo loop + while( timeout > 0 ) { + + + // Draw the timerift background + setVector( &rot, 0, spin, 0 ); + setVector( &pos, 0, 0, 0 ); + + TransMatrix( &mtx, &pos ); + RotMatrix( &rot, &mtx ); + + gte_SetRotMatrix( &mtx ); + gte_SetTransMatrix( &mtx ); + + s_ot.ot = ot[db]; + s_ot.otlen = 32; + s_ot.zdiv = 2; + s_ot.zoff = 20; + + nextpri = smdSortModelFlat( ot[db]+(OT_LEN-1), nextpri, o_timerift ); + + + // Sort mask primitive that enables setting mask bits + mask = (DR_MASK*)nextpri; + setDrawMask( mask, 1, 0 ); + addPrim( ot[db]+20, mask ); + nextpri += sizeof(DR_MASK); + + + // Sort the stars + setVector( &rot, 0, 0, spin<<2 ); + setVector( &pos, + (isin(spin<<2)*icos(spin))>>16, + (icos(spin<<2)*isin(spin))>>16, 400 ); + + TransMatrix( &mtx, &pos ); + RotMatrix( &rot, &mtx ); + + gte_SetRotMatrix( &mtx ); + gte_SetTransMatrix( &mtx ); + + nextpri = smdSortModelFlat( ot[db]+19, nextpri, o_star ); + + setVector( &rot, 0, 0, -spin<<2 ); + setVector( &pos, + (isin(-spin<<2)*icos(-spin))>>16, + (icos(-spin<<2)*isin(-spin))>>16, 400 ); + + TransMatrix( &mtx, &pos ); + RotMatrix( &rot, &mtx ); + + gte_SetRotMatrix( &mtx ); + gte_SetTransMatrix( &mtx ); + + nextpri = smdSortModelFlat( ot[db]+19, nextpri, o_star ); + + + // Sort mask primitive that enables mask bit test + mask = (DR_MASK*)nextpri; + setDrawMask( mask, 0, 1 ); + addPrim( ot[db]+18, mask ); + nextpri += sizeof(DR_MASK); + + + // Sort rectangle that fills the screen + rect = (TILE*)nextpri; + setTile( rect ); + setXY0( rect, 0, 0 ); + setWH( rect, 640, 511 ); + setRGB0( rect, 128, 0, 255 ); + addPrim( ot[db]+17, rect ); + nextpri += sizeof(TILE); + + + // Clear all mask settings + mask = (DR_MASK*)nextpri; + setDrawMask( mask, 0, 0 ); + addPrim( ot[db]+15, mask ); + nextpri += sizeof(DR_MASK); + + + // Sort overlay then display + sort_overlay( 0 ); + + display(); + + spin += 4; + timeout--; + } + +} + +// Orbiting around cel-shaded hatkid stuff +void hatkidstuff() { + + /* + The cel-shading effect works in a similar manner as conventional + per-vertex light source calculation except the color values are used + in a different manner. The resulting color values are divided down + using bit shifts to fit as texture coordinates (usually within the + range of 0-31) which are then used to map to a shading map which is a + simple texture of 3 to 4 shading levels. This technique is very similar + to how cel-shading is achieved on the Gamecube except all the vertex to + texture coordinate conversion is all done on the GX itself. + + To achieve this effect on untextured and textured polygons seamlessly + the shading map is drawn over the original unshaded polygons of the + model as semi-transparent polygons with subtractive blending. The + shading map had to be inverted for this effect to work properly since + blending is subtractive and not multiplicative after all. + */ + + int timeout = SCENE_TIME; + int spin=0; + + SC_OT s_ot; + + MATRIX lmtx; + + SVECTOR rot; + VECTOR pos; + + // Set clear color + setRGB0( &draw, 127, 0, 63 ); + + // Sets base TPage value for SMD drawing routines + smdSetBaseTPage( 0x200 ); + + setVector( &rot, 0, 0, 0 ); + + // Set light color matrix + gte_SetColorMatrix( &lgt_colmtx ); + + // Set back/ambient color to black (required for good cel-shading) + gte_SetBackColor( 0, 0, 0 ); + + gte_SetGeomScreen( 320 ); + + // Demo loop + while( timeout > 0 ) { + + // Sort 3D timerift background + setVector( &rot, spin, spin, spin>>1 ); + setVector( &pos, 0, 0, 0 ); + + TransMatrix( &mtx, &pos ); + RotMatrix( &rot, &mtx ); + + // Fixed light source direction + lmtx.m[0][0] = -2048; + lmtx.m[0][1] = -2048; + lmtx.m[0][2] = -2048; + + // Multiply by rotation matrix to make it relative to the camera rotation + MulMatrix0( &lmtx, &mtx, &lmtx ); + + gte_SetLightMatrix( &lmtx ); + gte_SetRotMatrix( &mtx ); + gte_SetTransMatrix( &mtx ); + + nextpri = smdSortModelFlat( ot[db]+(OT_LEN-1), nextpri, o_timerift ); + + + // Sort the cel-shaded hatkid + setVector( &pos, 0, 0, 600 ); + TransMatrix( &mtx, &pos ); + gte_SetTransMatrix( &mtx ); + + s_ot.ot = ot[db]; + s_ot.otlen = 250; + s_ot.zdiv = 1; + s_ot.zoff = 0; + + nextpri = smdSortModelCel( &s_ot, nextpri, o_hatkid ); + + + // Sort overlay then display + sort_overlay( 1 ); + display(); + + spin += 8; + timeout--; + + } + +} + +// Plasma stuff +void genPlasma(char *out, int count); +char *sortPlasma(int *ot, char *pri, char *map); + +void plasmastuff() { + + DR_TPAGE* tp; + char plasbuff[1271]; + + int pcount = 0; + int timeout = SCENE_TIME; + + while( timeout > 0 ) { + + genPlasma( plasbuff, pcount ); + nextpri = sortPlasma( ot[db]+1, nextpri, plasbuff ); + + sort_overlay( 1 ); + + display(); + timeout--; + pcount++; + + } + +} + +// Simple stripe transition effect +void transition() { + + int i,count,comp; + int bheight[16] = { 0 }; + + TILE *tile = (TILE*)nextpri; + draw.isbg = 0; + + while( 1 ) { + + comp = 0; + + for( i=0; i<16; i++ ) { + + if( bheight[i] > 0 ) { + + + setTile( tile ); + setXY0( tile, 0, 32*i ); + setRGB0( tile, 0, 151, 255 ); + setWH( tile, 640, bheight[i] ); + addPrim( ot[db], tile ); + tile++; + + if( bheight[i] < 32 ) + bheight[i]++; + else + comp++; + + } + + } + + if( bheight[count>>1] == 0 ) + bheight[count>>1] = 1; + + display(); + count++; + + if( comp >= 16 ) + break; + + } + + DrawSync(0); + + draw.isbg = 1; + +} + +int main(int argc, const char *argv[]) { + + // Init + init(); + + // Do transition + transition(); + + // Do Meido-Tek, PSn00bSDK and n00bDEMO logo intros + intro(); + + // Unpack model data + unpackModels(); + + // Demo sequence loop + while( 1 ) { + + lightdemo(); + bungirldemo(); + stencilstuff(); + hatkidstuff(); + plasmastuff(); + + } + + return 0; +}
\ No newline at end of file |
