aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorspicyjpeg <thatspicyjpeg@gmail.com>2023-06-20 15:13:11 +0200
committerspicyjpeg <thatspicyjpeg@gmail.com>2023-06-20 15:13:11 +0200
commitd23024ceeb8e7f04b0a3bde7a0db41ae5e4fd06d (patch)
tree03342eb22041fb7343c034e376489295e2a78a19
parent79a966486615e60be3a37d278945dc3dd0fd933b (diff)
Split off libsmd from n00bdemo into separate library
-rw-r--r--doc/cmake_reference.md3
-rw-r--r--examples/demos/n00bdemo/disp.c2
-rw-r--r--examples/demos/n00bdemo/lightdemo.c326
-rw-r--r--examples/demos/n00bdemo/logo.c242
-rw-r--r--examples/demos/n00bdemo/main.c360
-rw-r--r--examples/demos/n00bdemo/smd.h68
-rw-r--r--libpsn00b/cmake/internal_setup.cmake1
-rw-r--r--libpsn00b/include/psxapi.h2
-rw-r--r--libpsn00b/include/smd/smd.h85
-rw-r--r--libpsn00b/include/smd/smd_s.inc (renamed from examples/demos/n00bdemo/smd_s.h)5
-rw-r--r--libpsn00b/smd/smd.s (renamed from examples/demos/n00bdemo/smd.s)332
-rw-r--r--libpsn00b/smd/smd_cel.s (renamed from examples/demos/n00bdemo/smd_cel.s)371
-rw-r--r--libpsn00b/smd/smd_flat.s (renamed from examples/demos/n00bdemo/smd_flat.s)279
-rw-r--r--libpsn00b/smd/smdparser.s (renamed from examples/demos/n00bdemo/smdparser.s)63
14 files changed, 1086 insertions, 1053 deletions
diff --git a/doc/cmake_reference.md b/doc/cmake_reference.md
index ef3f5dc..169a7e6 100644
--- a/doc/cmake_reference.md
+++ b/doc/cmake_reference.md
@@ -76,6 +76,7 @@ the following targets are defined:
- `psxsio`
- `psxetc`
- `psxapi`
+- `smd`
- `lzp`
- `c`
@@ -394,4 +395,4 @@ CMake's `add_custom_command()` and `add_custom_target()` to convert models and
generate LZP archives as part of the build pipeline.
-----------------------------------------
-_Last updated on 2022-12-18 by spicyjpeg_
+_Last updated on 2023-06-20 by spicyjpeg_
diff --git a/examples/demos/n00bdemo/disp.c b/examples/demos/n00bdemo/disp.c
index a43a1d6..2e02a9d 100644
--- a/examples/demos/n00bdemo/disp.c
+++ b/examples/demos/n00bdemo/disp.c
@@ -3,7 +3,7 @@
#include <psxgpu.h>
#include <psxgte.h>
#include <inline_c.h>
-#include "smd.h"
+#include <smd/smd.h>
#include "disp.h"
DISPENV disp;
diff --git a/examples/demos/n00bdemo/lightdemo.c b/examples/demos/n00bdemo/lightdemo.c
index 5afd5c8..26da9ef 100644
--- a/examples/demos/n00bdemo/lightdemo.c
+++ b/examples/demos/n00bdemo/lightdemo.c
@@ -3,8 +3,8 @@
#include <psxgte.h>
#include <psxgpu.h>
#include <inline_c.h>
+#include <smd/smd.h>
#include "disp.h"
-#include "smd.h"
extern MATRIX lgt_colmtx;
@@ -14,227 +14,227 @@ extern SMD *o_lightbulb;
void sort_overlay(int showlotl);
void lightdemo() {
-
+
/*
The point lighting demo is perhaps the most impressive part of
n00bDEMO. A more streamlined version of this demo where you control
various attributes of the light source such as position, intensity
and color might be made as a dedicated example program in the future.
-
+
The point lighting trick is actually not that too complicated. You
basically calculate the distance and direction vector of two points
which are the light source and the vertex of a polygon.
-
+
Calculating the normal whose result can later be used to calculate
the distance between two points is achieved with:
-
+
vec_dir.vx = lgt_point.vx - pri_vert.vx;
vec_dir.vy = lgt_point.vy - pri_vert.vy;
vec_dir.vz = lgt_point.vz - pri_vert.vz;
-
+
The intensity is calculated with (this might not be accurate but this
is faster than applying a square root):
-
+
i = 4096 - ( (
- (vec_dir.vx*vec_dir.vx) +
- (vec_dir.vy*vec_dir.vy) +
+ (vec_dir.vx*vec_dir.vx) +
+ (vec_dir.vy*vec_dir.vy) +
(vec_dir.vz*vec_dir.vz) ) >> 7 );
-
+
// Clip minimum intensity
if( i < 0 )
i = 0;
-
+
This intensity value is then used to set the color of the light source
through the light color matrix.
-
+
col_mtx.m[0][0] = i;
col_mtx.m[1][0] = i;
col_mtx.m[2][0] = i;
gte_SetColorMatrix( &col_mtx );
-
+
The direction vector can then be used as the direction of the light
source. It is recommended to normalize it first to prevent possible
overflow related issues.
-
+
VectorNormalS( &vec_dir, &vec_norm );
-
+
lgt_mtx.m[0][0] = vec_norm.vx;
lgt_mtx.m[0][1] = vec_norm.vy;
lgt_mtx.m[0][2] = vec_norm.vz;
-
+
gte_SetLightMatrix( &lgt_mtx );
-
+
This operation is then performed for each point of a polygon to
achieve a nice smooth shaded point lighting effect. The macros used
are still the same as doing light source calculation with the GTE
the normal way.
-
+
3D geometry still requires normal data as with most lighting
processing operations. 'Flat' normals (faces with a single normal
vector) work best on flat surfaces while 'smooth' normals (faces with
normals on each point) work best on round or curved surfaces.
-
+
*/
-
+
int i,p_ang;
-
+
SC_OT s_ot;
-
+
SVECTOR rot;
VECTOR pos;
SMD_PRIM s_pri;
-
+
VECTOR l_point;
SVECTOR nrm;
-
+
MATRIX lmtx,llmtx,omtx;
-
+
SVECTOR orot = { 0 };
-
+
int timeout = SCENE_TIME;
-
+
// Set clear color to black
setRGB0( &draw, 0, 0, 0 );
-
+
// Base values for the environment geometry
setVector( &pos, 0, 0, 600 );
setVector( &rot, 512, 0, 0 );
-
+
// Set base tpage value for the SMD drawing routines
smdSetBaseTPage( 0x200 );
-
+
// Set back or ambient color to black for pure darkness
gte_SetBackColor( 0, 0, 0 );
-
+
memset( &llmtx, 0, sizeof(MATRIX) );
-
-
+
+
// demo loop
while( 1 ) {
-
+
char buff[32];
-
+
RotMatrix( &rot, &mtx );
TransMatrix( &mtx, &pos );
-
+
rot.vy += 4;
-
+
gte_SetRotMatrix( &mtx );
gte_SetTransMatrix( &mtx );
-
-
+
+
setVector( &l_point, (icos( p_ang )>>2)>>2, -350+(icos( p_ang<<1 )>>4), (isin( p_ang )>>2)>>2 );
p_ang += 16;
-
-
+
+
// Begin parsing the SMD data of the environment
OpenSMD( o_world );
-
+
// Prototype point lighting renderer
while( ReadSMD( &s_pri ) ) {
-
+
VECTOR v_dir;
SVECTOR v_nrm;
VECTOR v_sqr;
-
+
int flg;
-
+
if( s_pri.prim_id.texture ) {
-
+
POLY_GT4 *pri;
-
+
// Perform standard rotate, translate and perspective
// transformation of the geometry
pri = (POLY_GT4*)nextpri;
-
- gte_ldv3(
+
+ gte_ldv3(
&o_world->p_verts[s_pri.v0],
&o_world->p_verts[s_pri.v1],
&o_world->p_verts[s_pri.v2] );
-
+
gte_rtpt();
-
+
gte_nclip(); // Backface culling
-
+
gte_stopz( &flg );
-
+
if( flg < 0 )
continue;
-
+
gte_stsxy3( &pri->x0, &pri->x1, &pri->x2 );
-
+
gte_ldv0( &o_world->p_verts[s_pri.v3] );
gte_rtps();
-
+
gte_avsz4(); // Depth sort
gte_stotz( &flg );
-
+
if( (flg>>2) >= OT_LEN )
continue;
-
+
gte_stsxy( &pri->x3 );
-
-
+
+
// Load base color of polygon to GTE
gte_ldrgb( &s_pri.r0 );
-
+
// Load normal of polygon
gte_ldv0( &o_world->p_norms[s_pri.n0] );
-
+
// Calculate the direction between the vertex of the
// polygon and the light source
v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v0].vx;
v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v0].vy;
v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v0].vz;
-
+
// Calculate distance and light intensity using square
i = 4096 - ( (
- (v_dir.vx*v_dir.vx) +
- (v_dir.vy*v_dir.vy) +
+ (v_dir.vx*v_dir.vx) +
+ (v_dir.vy*v_dir.vy) +
(v_dir.vz*v_dir.vz) ) >> 7 );
-
+
// Clip minimum intensity
if( i < 0 )
i = 0;
-
+
// Set intensity to color matrix
llmtx.m[0][0] = i;
llmtx.m[1][0] = i;
llmtx.m[2][0] = i;
gte_SetColorMatrix( &llmtx );
-
+
// Normalize light direction and set it to light matrix
VectorNormalS( &v_dir, &v_nrm );
lmtx.m[0][0] = v_nrm.vx;
lmtx.m[0][1] = v_nrm.vy;
lmtx.m[0][2] = v_nrm.vz;
gte_SetLightMatrix( &lmtx );
-
+
// Calculate (output is retrieved through gte_strgb)
gte_nccs();
-
-
+
+
// Repeat process for the next 3 vertices
v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v1].vx;
v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v1].vy;
v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v1].vz;
-
+
i = 4096 - ( (
- (v_dir.vx*v_dir.vx) +
- (v_dir.vy*v_dir.vy) +
+ (v_dir.vx*v_dir.vx) +
+ (v_dir.vy*v_dir.vy) +
(v_dir.vz*v_dir.vz) ) >> 7 );
-
+
if( i < 0 )
i = 0;
-
-
+
+
llmtx.m[0][0] = i;
llmtx.m[1][0] = i;
llmtx.m[2][0] = i;
-
+
gte_strgb( &pri->r0 );
-
+
gte_SetColorMatrix( &llmtx );
VectorNormalS( &v_dir, &v_nrm );
lmtx.m[0][0] = v_nrm.vx;
@@ -242,25 +242,25 @@ void lightdemo() {
lmtx.m[0][2] = v_nrm.vz;
gte_SetLightMatrix( &lmtx );
gte_nccs();
-
+
v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v2].vx;
v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v2].vy;
v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v2].vz;
-
+
i = 4096 - ( (
- (v_dir.vx*v_dir.vx) +
- (v_dir.vy*v_dir.vy) +
+ (v_dir.vx*v_dir.vx) +
+ (v_dir.vy*v_dir.vy) +
(v_dir.vz*v_dir.vz) ) >> 7 );
-
+
if( i < 0 )
i = 0;
-
+
llmtx.m[0][0] = i;
llmtx.m[1][0] = i;
llmtx.m[2][0] = i;
-
+
gte_strgb( &pri->r1 );
-
+
gte_SetColorMatrix( &llmtx );
VectorNormalS( &v_dir, &v_nrm );
lmtx.m[0][0] = v_nrm.vx;
@@ -268,25 +268,25 @@ void lightdemo() {
lmtx.m[0][2] = v_nrm.vz;
gte_SetLightMatrix( &lmtx );
gte_nccs();
-
+
v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v3].vx;
v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v3].vy;
v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v3].vz;
-
+
i = 4096 - ( (
- (v_dir.vx*v_dir.vx) +
- (v_dir.vy*v_dir.vy) +
+ (v_dir.vx*v_dir.vx) +
+ (v_dir.vy*v_dir.vy) +
(v_dir.vz*v_dir.vz) ) >> 7 );
-
+
if( i < 0 )
i = 0;
-
+
llmtx.m[0][0] = i;
llmtx.m[1][0] = i;
llmtx.m[2][0] = i;
-
+
gte_strgb( &pri->r2 );
-
+
gte_SetColorMatrix( &llmtx );
VectorNormalS( &v_dir, &v_nrm );
lmtx.m[0][0] = v_nrm.vx;
@@ -294,70 +294,70 @@ void lightdemo() {
lmtx.m[0][2] = v_nrm.vz;
gte_SetLightMatrix( &lmtx );
gte_nccs();
-
- setUV4( pri,
+
+ setUV4( pri,
s_pri.tu0, s_pri.tv0,
- s_pri.tu1, s_pri.tv1,
+ s_pri.tu1, s_pri.tv1,
s_pri.tu2, s_pri.tv2,
s_pri.tu3, s_pri.tv3 );
-
+
pri->tpage = s_pri.tpage;
pri->clut = s_pri.clut;
-
+
setPolyGT4( pri );
addPrim( ot[db]+(flg>>2), pri );
nextpri += sizeof(POLY_GT4);
-
+
gte_strgb( &pri->r3 );
-
+
} else {
-
+
POLY_G4 *pri;
-
+
pri = (POLY_G4*)nextpri;
-
- gte_ldv3(
+
+ gte_ldv3(
&o_world->p_verts[s_pri.v0],
&o_world->p_verts[s_pri.v1],
&o_world->p_verts[s_pri.v2] );
-
+
gte_rtpt();
-
+
gte_nclip();
-
+
gte_stopz( &flg );
-
+
if( flg < 0 )
continue;
-
+
gte_stsxy3( &pri->x0, &pri->x1, &pri->x2 );
-
+
gte_ldv0( &o_world->p_verts[s_pri.v3] );
gte_rtps();
-
+
gte_avsz4();
gte_stotz( &flg );
-
+
if( (flg>>2) >= OT_LEN )
continue;
-
+
gte_stsxy( &pri->x3 );
-
+
gte_ldrgb( &s_pri.r0 );
gte_ldv0( &o_world->p_norms[s_pri.n0] );
-
+
v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v0].vx;
v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v0].vy;
v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v0].vz;
-
+
i = 4096 - ( (
- (v_dir.vx*v_dir.vx) +
- (v_dir.vy*v_dir.vy) +
+ (v_dir.vx*v_dir.vx) +
+ (v_dir.vy*v_dir.vy) +
(v_dir.vz*v_dir.vz) ) >> 7 );
-
+
if( i < 0 )
i = 0;
-
+
llmtx.m[0][0] = i;
llmtx.m[1][0] = i;
llmtx.m[2][0] = i;
@@ -368,26 +368,26 @@ void lightdemo() {
lmtx.m[0][2] = v_nrm.vz;
gte_SetLightMatrix( &lmtx );
gte_nccs();
-
-
+
+
v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v1].vx;
v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v1].vy;
v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v1].vz;
-
+
i = 4096 - ( (
- (v_dir.vx*v_dir.vx) +
- (v_dir.vy*v_dir.vy) +
+ (v_dir.vx*v_dir.vx) +
+ (v_dir.vy*v_dir.vy) +
(v_dir.vz*v_dir.vz) ) >> 7 );
-
+
if( i < 0 )
i = 0;
-
+
llmtx.m[0][0] = i;
llmtx.m[1][0] = i;
llmtx.m[2][0] = i;
-
+
gte_strgb( &pri->r0 );
-
+
gte_SetColorMatrix( &llmtx );
VectorNormalS( &v_dir, &v_nrm );
lmtx.m[0][0] = v_nrm.vx;
@@ -395,25 +395,25 @@ void lightdemo() {
lmtx.m[0][2] = v_nrm.vz;
gte_SetLightMatrix( &lmtx );
gte_nccs();
-
+
v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v2].vx;
v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v2].vy;
v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v2].vz;
-
+
i = 4096 - ( (
- (v_dir.vx*v_dir.vx) +
- (v_dir.vy*v_dir.vy) +
+ (v_dir.vx*v_dir.vx) +
+ (v_dir.vy*v_dir.vy) +
(v_dir.vz*v_dir.vz) ) >> 7 );
-
+
if( i < 0 )
i = 0;
-
+
llmtx.m[0][0] = i;
llmtx.m[1][0] = i;
llmtx.m[2][0] = i;
-
+
gte_strgb( &pri->r1 );
-
+
gte_SetColorMatrix( &llmtx );
VectorNormalS( &v_dir, &v_nrm );
lmtx.m[0][0] = v_nrm.vx;
@@ -421,25 +421,25 @@ void lightdemo() {
lmtx.m[0][2] = v_nrm.vz;
gte_SetLightMatrix( &lmtx );
gte_nccs();
-
+
v_dir.vx = l_point.vx - o_world->p_verts[s_pri.v3].vx;
v_dir.vy = l_point.vy - o_world->p_verts[s_pri.v3].vy;
v_dir.vz = l_point.vz - o_world->p_verts[s_pri.v3].vz;
-
+
i = 4096 - ( (
- (v_dir.vx*v_dir.vx) +
- (v_dir.vy*v_dir.vy) +
+ (v_dir.vx*v_dir.vx) +
+ (v_dir.vy*v_dir.vy) +
(v_dir.vz*v_dir.vz) ) >> 7 );
-
+
if( i < 0 )
i = 0;
-
+
llmtx.m[0][0] = i;
llmtx.m[1][0] = i;
llmtx.m[2][0] = i;
-
+
gte_strgb( &pri->r2 );
-
+
gte_SetColorMatrix( &llmtx );
VectorNormalS( &v_dir, &v_nrm );
lmtx.m[0][0] = v_nrm.vx;
@@ -447,49 +447,49 @@ void lightdemo() {
lmtx.m[0][2] = v_nrm.vz;
gte_SetLightMatrix( &lmtx );
gte_nccs();
-
+
setPolyG4( pri );
addPrim( ot[db]+(flg>>2), pri );
-
+
nextpri += sizeof(POLY_G4);
-
+
gte_strgb( &pri->r3 );
-
+
}
-
+
}
-
-
+
+
// Sort the light bulb to represent the position of the light source
orot.vx += 32;
orot.vy += 32;
orot.vz += 32;
-
+
RotMatrix( &orot, &omtx );
TransMatrix( &omtx, &l_point );
-
+
CompMatrixLV( &mtx, &omtx, &mtx );
gte_SetRotMatrix( &mtx );
gte_SetTransMatrix( &mtx );
-
+
s_ot.ot = ot[db];
s_ot.otlen = OT_LEN;
s_ot.zdiv = 2;
s_ot.zoff = 0;
-
+
nextpri = smdSortModel( &s_ot, nextpri, o_lightbulb );
-
+
// Sort overlay and display
sort_overlay( 1 );
-
+
display();
-
+
timeout--;
if( timeout < 0 )
break;
-
+
}
-
+
} \ No newline at end of file
diff --git a/examples/demos/n00bdemo/logo.c b/examples/demos/n00bdemo/logo.c
index 784c9e1..c6faf51 100644
--- a/examples/demos/n00bdemo/logo.c
+++ b/examples/demos/n00bdemo/logo.c
@@ -5,7 +5,7 @@
#include <psxgte.h>
#include <psxgpu.h>
#include <inline_c.h>
-#include "smd.h"
+#include <smd/smd.h>
#include <lzp/lzp.h>
#include "disp.h"
@@ -54,29 +54,29 @@ typedef struct {
extern NODE _end[];
void DumpHeap() {
-
+
NODE *n = _end;
-
+
printf( "--\n" );
-
+
while( 1 ) {
-
- printf( "B:%08p P:%08p N:%08p SZ:%d BS:%d\n",
- n, n->prev, n->next, n->size,
+
+ printf( "B:%08p P:%08p N:%08p SZ:%d BS:%d\n",
+ n, n->prev, n->next, n->size,
((unsigned int)n->next - (unsigned int)n) );
-
+
if ( !n->next )
break;
-
+
n = (NODE*)n->next;
-
+
}
-
+
}
void intro() {
-
+
SVECTOR quad_coords[] = {
{ -100, -100, 0, 0 },
{ 100, -100, 0, 0 },
@@ -85,18 +85,18 @@ void intro() {
};
PARTICLE stars[MAX_STARS];
-
+
VECTOR mpos;
SVECTOR mrot,trot;
SC_OT s_ot;
-
+
SMD *o_disk, *o_star, *o_text, *o_psn00b, *o_n00blogo;
-
+
int i,count = 0;
-
+
int logo_scale;
int logo_rot;
-
+
int logo_yvel;
int logo_ypos;
int logo_step;
@@ -104,10 +104,10 @@ void intro() {
int logo_svel;
int logo_count = 0;
int logo_tscale;
-
+
int logo_n00b_spin;
int logo_fade = 0;
-
+
struct {
int step;
int yvel;
@@ -129,7 +129,7 @@ void intro() {
3072,
0
};
-
+
struct {
VECTOR pos;
int scale;
@@ -139,180 +139,180 @@ void intro() {
ONE,
1024
};
-
-
+
+
i = lzpSearchFile( "mtekdisk", lz_resources );
o_disk = (SMD*)malloc( lzpFileSize( lz_resources, i ) );
lzpUnpackFile( o_disk, lz_resources, i );
smdInitData( o_disk );
-
+
i = lzpSearchFile( "mtektext", lz_resources );
o_text = (SMD*)malloc( lzpFileSize( lz_resources, i ) );
lzpUnpackFile( o_text, lz_resources, i );
smdInitData( o_text );
-
+
i = lzpSearchFile( "starsprite", lz_resources );
o_star = (SMD*)malloc( lzpFileSize( lz_resources, i ) );
lzpUnpackFile( o_star, lz_resources, i );
smdInitData( o_star );
-
+
i = lzpSearchFile( "psn00blogo", lz_resources );
o_psn00b = (SMD*)malloc( lzpFileSize( lz_resources, i ) );
lzpUnpackFile( o_psn00b, lz_resources, i );
smdInitData( o_psn00b );
-
+
i = lzpSearchFile( "n00blogo", lz_resources );
o_n00blogo = (SMD*)malloc( lzpFileSize( lz_resources, i ) );
lzpUnpackFile( o_n00blogo, lz_resources, i );
smdInitData( o_n00blogo );
-
+
//DumpHeap();
-
-
+
+
// Set some Scarlet global parameters
smdSetBaseTPage( 0x200 );
-
+
// Change clear color
setRGB0( &draw, 255, 255, 255 );
-
+
setVector( &trot, 0, 0, 0 );
-
-
+
+
// Initialize stars
for( i=0; i<MAX_STARS; i++ ) {
-
+
stars[i].x = ONE*(-200+(rand()%400));
stars[i].y = ONE*(80+(rand()%100));
-
+
stars[i].yvel = -(rand()%32768);
stars[i].xvel = -(ONE*(10-(rand()%20)));
-
+
stars[i].scale = 2048+(rand()%2048);
stars[i].rot = ONE*(rand()%4096);
stars[i].rotv = ONE*(-40+(rand()%80));
-
+
}
-
+
logo_n00b_spin = ONE+1024;
-
+
while( logo_count < 1320 ) {
-
+
if( logo_count < 700 ) {
-
+
if( logo_count > 360 ) {
mtek.spin -= mtek.spinvel;
mtek.spinvel += 1280;
}
-
+
setVector( &mpos, 0, -(mtek.ypos>>12)-20, 400 );
setVector( &mrot, 0, mtek.spin>>12, mtek.rot>>12 );
-
+
RotMatrix( &mrot, &mtx );
TransMatrix( &mtx, &mpos );
setVector( &mpos, mtek.scale, mtek.scale, 4096 );
ScaleMatrix( &mtx, &mpos );
-
+
gte_SetRotMatrix( &mtx );
gte_SetTransMatrix( &mtx );
-
+
nextpri = smdSortModelFlat( ot[db]+10, nextpri, o_disk );
-
+
if( mtek.step > 0 ) {
-
+
setVector( &mpos, 0, 180, 400 );
TransMatrix( &mtx, &mpos );
gte_SetTransMatrix( &mtx );
-
+
nextpri = smdSortModelFlat( ot[db]+8, nextpri, o_text );
-
+
if( logo_count < 480 ) {
-
+
SVECTOR srot;
-
+
for( i=0; i<MAX_STARS; i++ ) {
-
+
setVector( &mpos, stars[i].x>>12, stars[i].y>>12, 320 );
setVector( &srot, 0, 0, stars[i].rot>>12 );
-
+
stars[i].x += stars[i].xvel;
stars[i].y += stars[i].yvel;
-
+
stars[i].yvel += 512;
stars[i].rot += stars[i].rotv;
-
+
RotMatrix( &srot, &mtx );
TransMatrix( &mtx, &mpos );
-
+
setVector( &mpos, stars[i].scale, stars[i].scale, 4096 );
ScaleMatrix( &mtx, &mpos );
-
+
gte_SetRotMatrix( &mtx );
gte_SetTransMatrix( &mtx );
-
+
nextpri = smdSortModelFlat( ot[db]+6, nextpri, o_star );
-
+
}
-
+
}
-
+
}
-
+
if( !mtek.step ) {
mtek.rot -= ONE*20;
} else if( mtek.step == 1 ) {
mtek.rot += ( -mtek.rot )>>4;
}
-
-
+
+
if( mtek.step < 2 ) {
mtek.scale += (ONE-mtek.scale )>>5;
mtek.yvel += 512;
mtek.ypos -= mtek.yvel;
}
-
-
+
+
if( ( mtek.ypos <= 0 ) && ( mtek.yvel > 0 ) ) {
mtek.yvel = -ONE*6;
mtek.step++;
}
-
+
// Does the transition effect
if( logo_count > 480 ) {
-
+
TILE *rect = (TILE*)nextpri;
-
+
mtek.trot += 16;
-
+
setTile( rect );
setXY0( rect, 0, 0 );
setWH( rect, 640, 511 );
setRGB0( rect, 0, 0, 0 );
addPrim( ot[db]+4, rect );
nextpri += sizeof(TILE);
-
+
setVector( &mrot, 0, 0, mtek.trot );
setVector( &mpos, mtek.tscale, mtek.tscale, 4096 );
-
+
RotMatrix( &mrot, &mtx );
ScaleMatrix( &mtx, &mpos );
-
+
gte_SetRotMatrix( &mtx );
-
+
for( i=0; i<6; i++ ) {
-
+
MASKP_F4 *pol4 = (MASKP_F4*)nextpri;
-
+
setVector( &mpos, -100+(100*(i%3)), -60+(120*(i/3)), 160 );
TransMatrix( &mtx, &mpos );
gte_SetTransMatrix( &mtx );
-
+
pol4->tag = 0x08000000;
pol4->tpage = 0xe1000020;
pol4->mask1 = 0xe6000001;
pol4->mask2 = 0xe6000002;
pol4->code = 0x2A;
-
+
gte_ldv3( &quad_coords[0], &quad_coords[1], &quad_coords[2] );
gte_rtpt();
gte_stsxy0( &pol4->x0 );
@@ -320,111 +320,111 @@ void intro() {
gte_rtps();
gte_stsxy3( &pol4->x1, &pol4->x2, &pol4->x3 );
setRGB0( pol4, 0, 0, 0 );
-
+
addPrim( ot[db]+4, pol4 );
nextpri += sizeof(MASKP_F4);
-
+
}
-
+
mtek.tscale += ( -mtek.tscale )>>6;
-
+
}
-
+
} else {
-
+
setRGB0( &draw, 0, 0, 0 );
-
+
}
-
+
if( logo_count >= 480 ) {
-
+
if( logo_count > 840 ) {
-
+
psn00b.pos.vx += ((ONE*-450)-psn00b.pos.vx)>>4;
psn00b.pos.vy += ((ONE*350)-psn00b.pos.vy)>>4;
-
+
setVector( &mpos, 0, 0, 600 );
mpos.vx = psn00b.pos.vx>>12;
mpos.vy = psn00b.pos.vy>>12;
-
+
psn00b.scale += ( 1536-psn00b.scale )>>4;
-
+
setVector( &mrot, 0, 0, 0 );
-
+
RotMatrix( &mrot, &mtx );
TransMatrix( &mtx, &mpos );
-
+
setVector( &mpos, psn00b.scale, psn00b.scale, ONE );
-
+
ScaleMatrix( &mtx, &mpos );
-
+
} else {
-
+
setVector( &mpos, 0, 0, 600 );
setVector( &mrot, 0, logo_n00b_spin, 0 );
-
+
RotMatrix( &mrot, &mtx );
TransMatrix( &mtx, &mpos );
-
+
logo_n00b_spin += ( -logo_n00b_spin )>>6;
-
+
}
-
+
gte_SetRotMatrix( &mtx );
gte_SetTransMatrix( &mtx );
-
+
nextpri = smdSortModelFlat( ot[db]+3, nextpri, o_psn00b );
-
+
if( logo_count > 900 ) {
-
+
setVector( &mpos, 0, 0, 250 );
setVector( &mrot, psn00b.scarlet_spin, 0, 0 );
-
+
RotMatrix( &mrot, &mtx );
TransMatrix( &mtx, &mpos );
-
+
gte_SetRotMatrix( &mtx );
gte_SetTransMatrix( &mtx );
-
+
nextpri = smdSortModelFlat( ot[db]+3, nextpri, o_n00blogo );
-
+
psn00b.scarlet_spin += ( -psn00b.scarlet_spin )>>6;
-
+
}
-
+
}
-
+
if( logo_count > 1200 ) {
-
+
FADERECT *fade = (FADERECT*)nextpri;
-
+
fade->tag = 0x04000000;
fade->tpage = 0xe1000040;
fade->code = 0x62;
-
+
setRGB0( fade, logo_fade, logo_fade, logo_fade );
setXY0( fade, 0, 0 );
setWH( fade, 640, 480 );
addPrim( ot[db]+2, fade );
-
+
if( logo_fade < 250 ) {
logo_fade += 4;
}
-
+
nextpri += sizeof(FADERECT);
-
+
}
-
+
display();
-
+
logo_count++;
-
+
}
-
+
free( o_disk );
free( o_text );
free( o_star );
free( o_psn00b );
free( o_n00blogo );
-
+
}
diff --git a/examples/demos/n00bdemo/main.c b/examples/demos/n00bdemo/main.c
index 55dbbc4..d607495 100644
--- a/examples/demos/n00bdemo/main.c
+++ b/examples/demos/n00bdemo/main.c
@@ -1,4 +1,4 @@
-/*
+/*
* LibPSn00b Example Programs
*
* n00bDEMO Source Code
@@ -41,8 +41,8 @@
#include <string.h>
#include <lzp/lzp.h>
#include <lzp/lzqlp.h>
+#include <smd/smd.h>
-#include "smd.h"
#include "data.h"
#include "disp.h"
#include "logo.h"
@@ -119,16 +119,16 @@ 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.
*/
@@ -136,241 +136,241 @@ void loadTextures() {
int *ttim,j;
QLP_HEAD *tex_buff;
TIM_IMAGE tim;
-
+
i = lzpSearchFile( "textures", lz_resources );
tex_buff = (QLP_HEAD*)malloc( lzpFileSize( lz_resources, i ) );
lzpUnpackFile( tex_buff, lz_resources, i );
-
+
for( j=0; j<qlpFileCount( tex_buff )-4; j++ ) {
-
+
if( !GetTimInfo( (u_long*)qlpFileAddr( j, tex_buff ), &tim ) ) {
-
+
UploadTIM( &tim );
-
+
}
-
+
}
-
-
- GetTimInfo( (u_long*)qlpFileAddr(
+
+
+ GetTimInfo( (u_long*)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( (u_long*)qlpFileAddr(
+
+
+ GetTimInfo( (u_long*)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( (u_long*)qlpFileAddr(
+
+
+ GetTimInfo( (u_long*)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( (u_long*)qlpFileAddr(
+
+
+ GetTimInfo( (u_long*)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 );
-
+
free( tex_buff );
}
-
+
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() {
// Init display
initDisplay();
timerSetup();
-
+
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_STP initialized and set by setDrawStp().
-
+
The DR_STP 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_STP, drawing semi-transparent primitives using
additive blending but color is all zero to make it completely invisible
@@ -380,96 +380,96 @@ void stencilstuff() {
drawing the scene that will be 'below' the mask layer.
*/
int timeout = SCENE_TIME;
-
+
int spin=0;
-
+
DR_STP *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_STP*)nextpri;
setDrawStp( mask, 1, 0 );
addPrim( ot[db]+20, mask );
nextpri += sizeof(DR_STP);
-
-
+
+
// Sort the stars
setVector( &rot, 0, 0, spin<<2 );
- setVector( &pos,
- (isin(spin<<2)*icos(spin))>>16,
+ 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,
+ 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_STP*)nextpri;
setDrawStp( mask, 0, 1 );
addPrim( ot[db]+18, mask );
nextpri += sizeof(DR_STP);
-
+
// Sort rectangle that fills the screen
rect = (TILE*)nextpri;
setTile( rect );
@@ -478,119 +478,119 @@ void stencilstuff() {
setRGB0( rect, 128, 0, 255 );
addPrim( ot[db]+17, rect );
nextpri += sizeof(TILE);
-
-
+
+
// Clear all mask settings
mask = (DR_STP*)nextpri;
setDrawStp( mask, 0, 0 );
addPrim( ot[db]+15, mask );
nextpri += sizeof(DR_STP);
-
+
// 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
+ 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
@@ -598,101 +598,101 @@ void genPlasma(char *out, int count);
char *sortPlasma(u_long *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 count = 0;
int bheight[16] = { 0 };
-
+
TILE *tile = (TILE*)nextpri;
draw.isbg = 0;
-
+
while( 1 ) {
-
+
int comp = 0;
-
+
for( int 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
timer_counter = 100;
while( 1 ) {
-
+
lightdemo();
bungirldemo();
stencilstuff();
hatkidstuff();
plasmastuff();
-
+
}
return 0;
diff --git a/examples/demos/n00bdemo/smd.h b/examples/demos/n00bdemo/smd.h
deleted file mode 100644
index 4306534..0000000
--- a/examples/demos/n00bdemo/smd.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef _SMD_H
-#define _SMD_H
-
-typedef struct {
- u_long *ot;
- short otlen;
- unsigned char zdiv,zoff;
-} SC_OT;
-
-typedef struct {
- char id[3];
- unsigned char version;
- unsigned short flags;
- unsigned short n_verts;
- unsigned short n_norms;
- unsigned short n_prims;
- SVECTOR *p_verts;
- SVECTOR *p_norms;
- void *p_prims;
-} SMD;
-
-typedef struct {
- unsigned char type:2;
- unsigned char l_type:2;
- unsigned char c_type:1;
- unsigned char texture:1;
- unsigned char blend:2;
- unsigned char zoff:4;
- unsigned char nocull:1;
- unsigned char mask:1;
- unsigned char texwin:2;
- unsigned char texoff:2;
- unsigned char reserved:6;
- unsigned char len;
-} SMD_PRI_TYPE;
-
-typedef struct {
- SMD_PRI_TYPE prim_id;
- unsigned short v0,v1,v2,v3; // Vertex indices
- unsigned short n0,n1,n2,n3; // Normal indices
- unsigned char r0,g0,b0,code; // RGB0
- unsigned char r1,g1,b1,p0; // RGB1
- unsigned char r2,g2,b2,p1; // RGB2
- unsigned char r3,g3,b3,p2; // RGB3
- unsigned char tu0,tv0;
- unsigned char tu1,tv1;
- unsigned char tu2,tv2;
- unsigned char tu3,tv3;
- unsigned short tpage,clut;
-} SMD_PRIM;
-
-
-int OpenSMD(void *smd);
-SMD_PRIM *ReadSMD(SMD_PRIM *pri);
-
-void scSetClipRect(int x0, int y0, int x1, int y1);
-
-SMD *smdInitData(void *data);
-void smdSetBaseTPage(unsigned short tpage);
-
-char *smdSortModel(SC_OT *ot, char* pribuff, SMD *smd);
-char *smdSortModelFlat(u_long *ot, char* pribuff, SMD *smd);
-
-void smdSetCelTex(unsigned short tpage, unsigned short clut);
-void smdSetCelParam(int udiv, int vdiv, unsigned int col);
-char *smdSortModelCel(SC_OT *ot, char* pribuff, SMD *smd);
-
-#endif \ No newline at end of file
diff --git a/libpsn00b/cmake/internal_setup.cmake b/libpsn00b/cmake/internal_setup.cmake
index e24595a..c3bb2dc 100644
--- a/libpsn00b/cmake/internal_setup.cmake
+++ b/libpsn00b/cmake/internal_setup.cmake
@@ -51,6 +51,7 @@ set(
psxsio
psxetc
psxapi
+ smd
lzp
c
)
diff --git a/libpsn00b/include/psxapi.h b/libpsn00b/include/psxapi.h
index 5bb2b6f..67fa51a 100644
--- a/libpsn00b/include/psxapi.h
+++ b/libpsn00b/include/psxapi.h
@@ -310,7 +310,7 @@ int LoadExec(const char *path, int argc, const char **argv);
void FlushCache(void);
void ResetEntryInt(void);
-void HookEntryInt(jmp_buf buf);
+void HookEntryInt(const JumpBuffer *buf);
void ReturnFromException(void);
int SetConf(int evcb, int tcb, uint32_t sp);
diff --git a/libpsn00b/include/smd/smd.h b/libpsn00b/include/smd/smd.h
new file mode 100644
index 0000000..658f7fa
--- /dev/null
+++ b/libpsn00b/include/smd/smd.h
@@ -0,0 +1,85 @@
+/*
+ * PSn00bSDK .SMD model parser library
+ * (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <psxgte.h>
+
+/* Structure definitions */
+
+typedef struct {
+ uint32_t *ot;
+ int16_t otlen;
+ uint8_t zdiv,zoff;
+} SC_OT;
+
+typedef struct {
+ char id[3];
+ uint8_t version;
+ uint16_t flags;
+ uint16_t n_verts;
+ uint16_t n_norms;
+ uint16_t n_prims;
+ SVECTOR *p_verts;
+ SVECTOR *p_norms;
+ void *p_prims;
+} SMD;
+
+typedef struct {
+ uint8_t type : 2;
+ uint8_t l_type : 2;
+ uint8_t c_type : 1;
+ uint8_t texture : 1;
+ uint8_t blend : 2;
+ uint8_t zoff : 4;
+ uint8_t nocull : 1;
+ uint8_t mask : 1;
+ uint8_t texwin : 2;
+ uint8_t texoff : 2;
+ uint8_t reserved : 6;
+ uint8_t len;
+} SMD_PRI_TYPE;
+
+typedef struct {
+ SMD_PRI_TYPE prim_id;
+
+ uint16_t v0,v1,v2,v3; // Vertex indices
+ uint16_t n0,n1,n2,n3; // Normal indices
+ uint8_t r0,g0,b0,code; // RGB0
+ uint8_t r1,g1,b1,p0; // RGB1
+ uint8_t r2,g2,b2,p1; // RGB2
+ uint8_t r3,g3,b3,p2; // RGB3
+ uint8_t tu0,tv0;
+ uint8_t tu1,tv1;
+ uint8_t tu2,tv2;
+ uint8_t tu3,tv3;
+ uint16_t tpage,clut;
+} SMD_PRIM;
+
+/* API */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int OpenSMD(const void *smd);
+SMD_PRIM *ReadSMD(SMD_PRIM *pri);
+
+void scSetClipRect(int x0, int y0, int x1, int y1);
+
+SMD *smdInitData(const void *data);
+void smdSetBaseTPage(uint16_t tpage);
+
+uint8_t *smdSortModel(SC_OT *ot, uint8_t *pribuff, SMD *smd);
+uint8_t *smdSortModelFlat(uint32_t *ot, uint8_t *pribuff, SMD *smd);
+
+void smdSetCelTex(uint16_t tpage, uint16_t clut);
+void smdSetCelParam(int udiv, int vdiv, unsigned int col);
+uint8_t *smdSortModelCel(SC_OT *ot, uint8_t *pribuff, SMD *smd);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/demos/n00bdemo/smd_s.h b/libpsn00b/include/smd/smd_s.inc
index 4dca4dd..827e9e3 100644
--- a/examples/demos/n00bdemo/smd_s.h
+++ b/libpsn00b/include/smd/smd_s.inc
@@ -1,3 +1,6 @@
+# PSn00bSDK .SMD model parser library
+# (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed
+
.set OT_ADDR, 0
.set OT_LEN, 4
.set OT_ZDIV, 8
@@ -332,5 +335,5 @@
nop
ori $s3, CLIP_BOTTOM
.no_clip_b_y3_q:
-
+
.endm
diff --git a/examples/demos/n00bdemo/smd.s b/libpsn00b/smd/smd.s
index d25f760..3c87a5e 100644
--- a/examples/demos/n00bdemo/smd.s
+++ b/libpsn00b/smd/smd.s
@@ -1,35 +1,37 @@
+# PSn00bSDK .SMD model parser library
+# (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed
+
.set noreorder
.include "gtereg.inc"
.include "inline_s.inc"
-.include "smd_s.h"
-
-
-.section .text
+.include "smd/smd_s.inc"
# Currently does not do header checks
+.section .text.smdInitData, "ax", @progbits
.global smdInitData
.type smdInitData, @function
+
smdInitData:
-
lw $a1, SMD_HEAD_PVERTS($a0) # Initialize header pointers
lw $a2, SMD_HEAD_PNORMS($a0)
lw $a3, SMD_HEAD_PPRIMS($a0)
-
+
addu $a1, $a0
addu $a2, $a0
addu $a3, $a0
-
+
sw $a1, SMD_HEAD_PVERTS($a0)
sw $a2, SMD_HEAD_PNORMS($a0)
sw $a3, SMD_HEAD_PPRIMS($a0)
-
+
jr $ra
move $v0, $a0
-
-
+
+.section .text.scSetClipRect, "ax", @progbits
.global scSetClipRect
.type scSetClipRect, @function
+
scSetClipRect:
sll $a1, 16
or $a0, $a1
@@ -39,50 +41,51 @@ scSetClipRect:
sw $a0, 0( $a1 )
jr $ra
sw $a2, 4( $a1 )
-
-
+
+.section .text.smdSetBaseTPage, "ax", @progbits
.global smdSetBaseTPage
.type smdSetBaseTPage, @function
+
smdSetBaseTPage:
la $v0, _smd_tpage_base
jr $ra
sw $a0, 0($v0)
-
-
+
+.section .text.smdSortModel, "ax", @progbits
.global smdSortModel
.type smdSortModel, @function
+
smdSortModel:
-
# a0 - Pointer SC_OT structure
# a1 - Pointer to next primitive
# a2 - Pointer to SMD data address
# v0 - New pointer of primitive buffer (return)
-
+
addiu $sp, -16
sw $s0, 0($sp)
sw $s1, 4($sp)
sw $s2, 8($sp)
sw $s3, 12($sp)
-
+
la $v0, _sc_clip
lw $t8, 0($v0)
lw $t9, 4($v0)
-
+
lw $t0, OT_LEN($a0)
lw $a0, OT_ADDR($a0)
lw $t1, SMD_HEAD_PVERTS($a2)
lw $t2, SMD_HEAD_PNORMS($a2)
lw $t3, SMD_HEAD_PPRIMS($a2)
-
+
.sort_loop:
nop
lw $a3, 0($t3) # Get primitive ID word
move $t4, $t3
-
+
beqz $a3, .exit # Check if terminator (just zero)
addiu $t4, 4
-
+
lhu $t5, 0( $t4 ) # Load vertices
lhu $t6, 2( $t4 )
lhu $t7, 4( $t4 )
@@ -98,38 +101,38 @@ smdSortModel:
lwc2 C2_VZ1 , 4( $t6 )
lwc2 C2_VXY2, 0( $t7 )
lwc2 C2_VZ2 , 4( $t7 )
-
+
srl $v1, $a3, 24 # Get primitive size
addu $t3, $v1 # Step main pointer to next primitive
-
+
RTPT
-
+
cfc2 $v0, C2_FLAG # Get GTE flag value
nop
-
+
bltz $v0, .skip_prim # Skip primitive if Z overflow
andi $v0, $a3, 0x3
-
+
NCLIP # Backface culling
-
+
srl $v1, $a3, 12
andi $v1, 1
-
+
bnez $v1, .no_culling
nop
-
+
mfc2 $v1, C2_MAC0
nop
bltz $v1, .skip_prim
nop
-
+
.no_culling:
beq $v0, 0x1, .prim_tri # If primitive is a triangle
nop
beq $v0, 0x2, .prim_quad # If primitive is a quad
nop
-
+
b .skip_prim
nop
@@ -140,25 +143,25 @@ smdSortModel:
addiu $t4, 8 # Advance from indices
AVSZ3 # Calculate average Z
-
+
srl $v0, $t0, 16 # Get Z divisor from OT_LEN value
andi $v0, 0xff
-
+
mfc2 $t5, C2_OTZ # Get AVSZ3 result
-
+
sra $v1, $t0, 24 # Get Z offset from OT_LEN value
-
+
srl $t5, $v0 # Apply divisor and offset
sub $t5, $v1
-
+
blez $t5, .skip_prim # Skip primitive if less than zero
andi $v1, $t0, 0xffff
bge $t5, $v1, .skip_prim # Skip primitive if greater than OT length
sll $t5, 2
addu $t5, $a0 # Append OTZ to OT address
-
+
ClipTestTri
-
+
and $v0, $s0, $s1 # v0 & v1
beqz $v0, .do_draw
and $v0, $s1, $s2 # v1 & v2
@@ -168,10 +171,10 @@ smdSortModel:
nop
b .skip_prim
nop
-
+
.do_draw:
-
-
+
+
srl $v0, $a3, 2 # Lighting enabled?
andi $v0, 0x3
bnez $v0, .F3_light
@@ -180,18 +183,18 @@ smdSortModel:
andi $v0, $a3, 0x10 # Gouraud shaded
bnez $v0, .F3_gouraud
nop
-
+
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F3_textured
nop
-
+
lw $v0, 0( $t4 ) # Flat color, no lighting
lui $v1, 0x2000
or $v0, $v1
-
+
b .sort_F3_pri
sw $v0, POLYF3_rgbc( $a1 )
-
+
.F3_gouraud:
lw $v0, 0($t4)
@@ -213,30 +216,30 @@ smdSortModel:
or $v0, $v1
sw $v0, POLYFT3_rgbc( $a1 )
addiu $t4, 4
-
+
lhu $v0, 0( $t4 ) # Load texture coordinates
lhu $v1, 2( $t4 )
sh $v0, POLYFT3_uv0( $a1 )
lhu $v0, 4( $t4 )
sh $v1, POLYFT3_uv1( $a1 )
sh $v0, POLYFT3_uv2( $a1 )
-
+
lw $v0, 8( $t4 ) # Tpage + CLUT
nop
andi $v1, $v0, 0xffff
sh $v1, POLYFT3_tpage( $a1 )
srl $v0, 16
-
+
b .sort_FT3_pri
sh $v0, POLYFT3_clut( $a1 )
-
+
.F3_light:
-
+
lhu $v0, 0( $t4 ) # Load normal 0
-
+
srl $v1, $a3, 2
andi $v1, $v1, 0x3
-
+
sll $v0, 3
addu $v0, $t2
lwc2 C2_VXY0, 0( $v0 )
@@ -244,26 +247,26 @@ smdSortModel:
beq $v1, 0x2, .F3_light_smt
nop
-
+
lw $v0, 4( $t4 )
lui $v1, 0x2000
or $v0, $v1
mtc2 $v0, C2_RGB
-
+
addiu $t4, 8
nop
-
+
NCCS
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F3_light_tex
nop
-
+
swc2 C2_RGB2, POLYF3_rgbc( $a1 )
-
+
b .sort_F3_pri
nop
-
+
.F3_light_tex:
lhu $v0, 0( $t4 ) # Load texture coordinates
@@ -272,23 +275,23 @@ smdSortModel:
lhu $v0, 4( $t4 )
sh $v1, POLYFT3_uv1( $a1 )
sh $v0, POLYFT3_uv2( $a1 )
-
+
lw $v1, 8( $t4 )
nop
andi $v0, $v1, 0xffff
sh $v0, POLYFT3_tpage( $a1 )
srl $v0, $v1, 16
sh $v0, POLYFT3_clut( $a1 )
-
+
mfc2 $v0, C2_RGB2
lui $v1, 0x2400
or $v0, $v1
-
+
b .sort_FT3_pri
sw $v0, POLYFT3_rgbc( $a1 )
-
+
.F3_light_smt:
-
+
lhu $v0, 2( $t4 ) # Load normals 1 and 2
lhu $v1, 4( $t4 )
sll $v0, 3
@@ -303,20 +306,20 @@ smdSortModel:
lui $v1, 0x3000 # Load color
or $v0, $v1
mtc2 $v0, C2_RGB
-
+
addiu $t4, 12
nop
-
+
NCCT
-
+
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F3_light_tex_smt
nop
-
+
swc2 C2_RGB0, POLYG3_rgbc0( $a1 )
swc2 C2_RGB1, POLYG3_rgbc1( $a1 )
swc2 C2_RGB2, POLYG3_rgbc2( $a1 )
-
+
b .sort_G3_pri
nop
@@ -328,21 +331,21 @@ smdSortModel:
lhu $v0, 4( $t4 )
sh $v1, POLYGT3_uv1( $a1 )
sh $v0, POLYGT3_uv2( $a1 )
-
+
lw $v1, 8( $t4 )
nop
andi $v0, $v1, 0xffff
sh $v0, POLYGT3_tpage( $a1 )
srl $v0, $v1, 16
sh $v0, POLYGT3_clut( $a1 )
-
+
mfc2 $v0, C2_RGB0
lui $v1, 0x3400
or $v0, $v1
-
+
swc2 C2_RGB1, POLYGT3_rgbc1( $a1 )
swc2 C2_RGB2, POLYGT3_rgbc2( $a1 )
-
+
b .sort_GT3_pri
sw $v0, POLYGT3_rgbc0( $a1 )
@@ -351,7 +354,7 @@ smdSortModel:
swc2 C2_SXY0, POLYF3_xy0($a1)
swc2 C2_SXY1, POLYF3_xy1($a1)
swc2 C2_SXY2, POLYF3_xy2($a1)
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -361,7 +364,7 @@ smdSortModel:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYF3_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0500
@@ -379,21 +382,21 @@ smdSortModel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYF3_len
-
+
.sort_FT3_pri:
swc2 C2_SXY0, POLYFT3_xy0( $a1 )
swc2 C2_SXY1, POLYFT3_xy1( $a1 )
swc2 C2_SXY2, POLYFT3_xy2( $a1 )
-
+
.set noat
lui $v1, 0x0700
@@ -411,21 +414,21 @@ smdSortModel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYFT3_len
-
+
.sort_G3_pri:
swc2 C2_SXY0, POLYG3_xy0( $a1 )
swc2 C2_SXY1, POLYG3_xy1( $a1 )
swc2 C2_SXY2, POLYG3_xy2( $a1 )
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -435,7 +438,7 @@ smdSortModel:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYG3_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0700
@@ -453,21 +456,21 @@ smdSortModel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYG3_len
-
+
.sort_GT3_pri:
swc2 C2_SXY0, POLYGT3_xy0( $a1 )
swc2 C2_SXY1, POLYGT3_xy1( $a1 )
swc2 C2_SXY2, POLYGT3_xy2( $a1 )
-
+
.set noat
lui $v1, 0x0900
@@ -485,17 +488,17 @@ smdSortModel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYGT3_len
## Quads
-
+
.prim_quad: # Quad processing
mfc2 $t6, C2_SXY0 # Retrieve first projected vertex
@@ -506,38 +509,38 @@ smdSortModel:
addu $t5, $t1
lwc2 C2_VXY0, 0( $t5 )
lwc2 C2_VZ0 , 4( $t5 )
-
+
nRTPS
-
+
cfc2 $v1, C2_FLAG # Get GTE flag value
-
+
srl $v0, $t0, 16 # Get Z divisor from OT_LEN value
-
+
bltz $v1, .skip_prim
nop
-
+
AVSZ4
-
+
andi $v0, 0xff
-
+
mfc2 $t5, C2_OTZ
-
+
sra $v1, $t0, 24 # Get Z offset from OT_LEN value
-
+
srl $t5, $v0 # Apply divisor and offset
sub $t5, $v1
-
+
blez $t5, .skip_prim # Skip primitive if less than zero
andi $v1, $t0, 0xffff
bge $t5, $v1, .skip_prim # Skip primitive if greater than OT length
sll $t5, 2
addu $t5, $a0 # Append OTZ to OT address
-
+
# no touch:
# a0, a1, a2, a3, t0, t1, t2, t3, t4, t5(ot), t6(sxy0)
-
+
ClipTestQuad
-
+
and $v0, $s0, $s1 # v0 & v1
beqz $v0, .do_draw_q
and $v0, $s1, $s2 # v1 & v2
@@ -553,29 +556,29 @@ smdSortModel:
nop
b .skip_prim
nop
-
+
.do_draw_q:
srl $v0, $a3, 2 # Lighting enabled?
andi $v0, 0x3
bnez $v0, .F4_light
nop
-
+
andi $v0, $a3, 0x10 # Gouraud quad
bnez $v0, .F4_gouraud
nop
-
+
andi $v0, $a3, 0x20 # Textured quad
bnez $v0, .F4_textured
nop
-
+
lw $v0, 0($t4)
lui $v1, 0x2800
or $v0, $v1
-
+
b .sort_F4_pri
sw $v0, POLYF4_rgbc($a1)
-
+
.F4_gouraud:
lw $v0, 0($t4)
@@ -591,15 +594,15 @@ smdSortModel:
sw $v0, POLYG4_rgbc2($a1)
b .sort_G4_pri
sw $v1, POLYG4_rgbc3($a1)
-
+
.F4_textured:
-
+
lw $v0, 0($t4)
lui $v1, 0x2c00
or $v0, $v1
sw $v0, POLYFT4_rgbc( $a1 )
addiu $t4, 4
-
+
lhu $v0, 0($t4) # Load texture coordinates
lhu $v1, 2($t4)
sh $v0, POLYFT4_uv0( $a1 )
@@ -608,23 +611,23 @@ smdSortModel:
lhu $v1, 6( $t4 )
sh $v0, POLYFT4_uv2( $a1 )
sh $v1, POLYFT4_uv3( $a1 )
-
+
lw $v1, 8( $t4 )
nop
andi $v0, $v1, 0xffff
sh $v0, POLYFT4_tpage( $a1 )
srl $v0, $v1, 16
-
+
b .sort_FT4_pri
sh $v0, POLYFT4_clut($a1)
-
+
.F4_light:
lhu $v0, 0( $t4 ) # Load normal 0
-
+
srl $v1, $a3, 2
andi $v1, $v1, 0x3
-
+
sll $v0, 3
addu $v0, $t2
lwc2 C2_VXY0, 0( $v0 )
@@ -632,26 +635,26 @@ smdSortModel:
beq $v1, 0x2, .F4_light_smt
nop
-
+
lw $v0, 4( $t4 )
lui $v1, 0x2800
or $v0, $v1
mtc2 $v0, C2_RGB
-
+
addiu $t4, 8
nop
-
+
NCCS
-
+
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F4_light_tex
nop
swc2 C2_RGB2, POLYF4_rgbc( $a1 )
-
+
b .sort_F4_pri
nop
-
+
.F4_light_tex:
lhu $v0, 0( $t4 ) # Load texture coordinates
@@ -662,21 +665,21 @@ smdSortModel:
lhu $v1, 6( $t4 )
sh $v0, POLYFT4_uv2( $a1 )
sh $v1, POLYFT4_uv3( $a1 )
-
+
lw $v1, 8( $t4 )
nop
andi $v0, $v1, 0xffff
sh $v0, POLYFT4_tpage( $a1 )
srl $v0, $v1, 16
sh $v0, POLYFT4_clut( $a1 )
-
+
mfc2 $v0, C2_RGB2
lui $v1, 0x2c00
or $v0, $v1
-
+
b .sort_FT4_pri
sw $v0, POLYFT4_rgbc( $a1 )
-
+
.F4_light_smt:
lhu $v0, 2( $t4 ) # Load normals 1 and 2
@@ -689,38 +692,38 @@ smdSortModel:
lwc2 C2_VZ1 , 4( $v0 )
lwc2 C2_VXY2, 0( $v1 )
lwc2 C2_VZ2 , 4( $v1 )
-
+
lw $v0, 8( $t4 )
lui $v1, 0x3800 # Load color
or $v0, $v1
mtc2 $v0, C2_RGB
-
+
nNCCT
-
+
lhu $v0, 6( $t4 ) # Load normal 3
-
+
addiu $t4, 12
-
+
sll $v0, 3
addu $v0, $t2
lwc2 C2_VXY0, 0( $v0 )
lwc2 C2_VZ0 , 4( $v0 )
-
+
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F4_light_tex_smt
nop
-
+
swc2 C2_RGB0, POLYG4_rgbc0( $a1 )
swc2 C2_RGB1, POLYG4_rgbc1( $a1 )
swc2 C2_RGB2, POLYG4_rgbc2( $a1 )
-
+
nNCCS
-
+
swc2 C2_RGB2, POLYG4_rgbc3( $a1 )
-
+
b .sort_G4_pri
nop
-
+
.F4_light_tex_smt:
mfc2 $v0, C2_RGB0
@@ -729,9 +732,9 @@ smdSortModel:
sw $v0, POLYGT4_rgbc0( $a1 )
swc2 C2_RGB1, POLYGT4_rgbc1( $a1 )
swc2 C2_RGB2, POLYGT4_rgbc2( $a1 )
-
+
NCCS
-
+
lhu $v0, 0( $t4 ) # Load texture coordinates
lhu $v1, 2( $t4 )
sh $v0, POLYGT4_uv0( $a1 )
@@ -743,21 +746,21 @@ smdSortModel:
lw $v1, 8( $t4 )
swc2 C2_RGB2, POLYGT4_rgbc3( $a1 )
-
+
andi $v0, $v1, 0xffff
sh $v0, POLYGT4_tpage( $a1 )
srl $v0, $v1, 16
-
+
b .sort_GT4_pri
sh $v0, POLYGT4_clut( $a1 )
-
+
.sort_F4_pri:
sw $t6, POLYF4_xy0($a1)
swc2 C2_SXY0, POLYF4_xy1($a1)
swc2 C2_SXY1, POLYF4_xy2($a1)
swc2 C2_SXY2, POLYF4_xy3($a1)
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -767,7 +770,7 @@ smdSortModel:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYF4_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0600
@@ -785,22 +788,22 @@ smdSortModel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYF4_len
-
+
.sort_FT4_pri:
sw $t6, POLYFT4_xy0($a1)
swc2 C2_SXY0, POLYFT4_xy1($a1)
swc2 C2_SXY1, POLYFT4_xy2($a1)
swc2 C2_SXY2, POLYFT4_xy3($a1)
-
+
.set noat
lui $v1, 0x0900
@@ -818,22 +821,22 @@ smdSortModel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYFT4_len
-
+
.sort_G4_pri:
sw $t6, POLYG4_xy0($a1)
swc2 C2_SXY0, POLYG4_xy1($a1)
swc2 C2_SXY1, POLYG4_xy2($a1)
swc2 C2_SXY2, POLYG4_xy3($a1)
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -843,7 +846,7 @@ smdSortModel:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYG4_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0900
@@ -861,22 +864,22 @@ smdSortModel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYG4_len
-
+
.sort_GT4_pri:
sw $t6, POLYGT4_xy0($a1)
swc2 C2_SXY0, POLYGT4_xy1($a1)
swc2 C2_SXY1, POLYGT4_xy2($a1)
swc2 C2_SXY2, POLYGT4_xy3($a1)
-
+
.set noat
lui $v1, 0x0c00
@@ -894,20 +897,20 @@ smdSortModel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYGT4_len
-
+
.skip_prim:
b .sort_loop
nop
-
+
.exit:
lw $s0, 0( $sp )
@@ -917,8 +920,9 @@ smdSortModel:
addiu $sp, 16
jr $ra
move $v0, $a1
-
-
+
+.section .bss._smd_tpage_base, "w"
.comm _smd_tpage_base, 4, 4
+.section .bss._sc_clip, "w"
.comm _sc_clip, 8, 4
diff --git a/examples/demos/n00bdemo/smd_cel.s b/libpsn00b/smd/smd_cel.s
index 383f043..8a39f01 100644
--- a/examples/demos/n00bdemo/smd_cel.s
+++ b/libpsn00b/smd/smd_cel.s
@@ -1,14 +1,16 @@
+# PSn00bSDK .SMD model parser library
+# (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed
+
.set noreorder
.include "gtereg.inc"
.include "inline_s.inc"
-.include "smd_s.h"
-
+.include "smd/smd_s.inc"
-.section .text
-
+.section .text.smdSetCelTex, "ax", @progbits
.global smdSetCelTex
.type smdSetCelTex, @function
+
smdSetCelTex:
# a0 - TPage value
# a1 - CLUT value
@@ -18,11 +20,11 @@ smdSetCelTex:
or $a0, $a1
jr $ra
sw $a0, 0($v0)
-
-
-
+
+.section .text.smdSetCelParam, "ax", @progbits
.global smdSetCelParam
.type smdSetCelParam, @function
+
smdSetCelParam:
# a0 - Shading texture U offset
# a1 - Shading texture V offset
@@ -38,42 +40,42 @@ smdSetCelParam:
or $a3, $v1
jr $ra
sw $a2, 0($v0)
-
-
+
+.section .text.smdSortModelCel, "ax", @progbits
.global smdSortModelCel
.type smdSortModelCel, @function
+
smdSortModelCel:
-
# a0 - Pointer SC_OT structure
# a1 - Pointer to next primitive
# a2 - Pointer to SMD data address
# v0 - New pointer of primitive buffer (return)
-
+
addiu $sp, -16
sw $s0, 0($sp)
sw $s1, 4($sp)
sw $s2, 8($sp)
sw $s3, 12($sp)
-
+
la $v0, _sc_clip
lw $t8, 0($v0)
lw $t9, 4($v0)
-
+
lw $t0, OT_LEN($a0)
lw $a0, OT_ADDR($a0)
lw $t1, SMD_HEAD_PVERTS($a2)
lw $t2, SMD_HEAD_PNORMS($a2)
lw $t3, SMD_HEAD_PPRIMS($a2)
-
+
.sort_loop:
nop
lw $a3, 0($t3) # Get primitive ID word
move $t4, $t3
-
+
beqz $a3, .exit # Check if terminator (just zero)
addiu $t4, 4
-
+
lhu $t5, 0( $t4 ) # Load vertices
lhu $t6, 2( $t4 )
lhu $t7, 4( $t4 )
@@ -89,38 +91,38 @@ smdSortModelCel:
lwc2 C2_VZ1 , 4( $t6 )
lwc2 C2_VXY2, 0( $t7 )
lwc2 C2_VZ2 , 4( $t7 )
-
+
srl $v1, $a3, 24 # Get primitive size
addu $t3, $v1 # Step main pointer to next primitive
-
+
RTPT
-
+
cfc2 $v0, C2_FLAG # Get GTE flag value
nop
-
+
bltz $v0, .skip_prim # Skip primitive if Z overflow
andi $v0, $a3, 0x3
-
+
NCLIP # Backface culling
-
+
srl $v1, $a3, 12
andi $v1, 1
-
+
bnez $v1, .no_culling
nop
-
+
mfc2 $v1, C2_MAC0
nop
bltz $v1, .skip_prim
nop
-
+
.no_culling:
beq $v0, 0x1, .prim_tri # If primitive is a triangle
nop
beq $v0, 0x2, .prim_quad # If primitive is a quad
nop
-
+
b .skip_prim
nop
@@ -131,25 +133,25 @@ smdSortModelCel:
addiu $t4, 8 # Advance from indices
AVSZ3 # Calculate average Z
-
+
srl $v0, $t0, 16 # Get Z divisor from OT_LEN value
andi $v0, 0xff
-
+
mfc2 $t5, C2_OTZ # Get AVSZ3 result
-
+
sra $v1, $t0, 24 # Get Z offset from OT_LEN value
-
+
srl $t5, $v0 # Apply divisor and offset
sub $t5, $v1
-
+
blez $t5, .skip_prim # Skip primitive if less than zero
andi $v1, $t0, 0xffff
bge $t5, $v1, .skip_prim # Skip primitive if greater than OT length
sll $t5, 2
addu $t5, $a0 # Append OTZ to OT address
-
+
ClipTestTri
-
+
and $v0, $s0, $s1 # v0 & v1
beqz $v0, .do_draw
and $v0, $s1, $s2 # v1 & v2
@@ -159,10 +161,10 @@ smdSortModelCel:
nop
b .skip_prim
nop
-
+
.do_draw:
-
-
+
+
srl $v0, $a3, 2 # Lighting enabled?
andi $v0, 0x3
bnez $v0, .F3_light
@@ -171,18 +173,18 @@ smdSortModelCel:
andi $v0, $a3, 0x10 # Gouraud shaded
bnez $v0, .F3_gouraud
nop
-
+
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F3_textured
nop
-
+
lw $v0, 0( $t4 ) # Flat color, no lighting
lui $v1, 0x2000
or $v0, $v1
-
+
b .sort_F3_pri
sw $v0, POLYF3_rgbc( $a1 )
-
+
.F3_gouraud:
lw $v0, 0($t4)
@@ -204,30 +206,30 @@ smdSortModelCel:
or $v0, $v1
sw $v0, POLYFT3_rgbc( $a1 )
addiu $t4, 4
-
+
lhu $v0, 0( $t4 ) # Load texture coordinates
lhu $v1, 2( $t4 )
sh $v0, POLYFT3_uv0( $a1 )
lhu $v0, 4( $t4 )
sh $v1, POLYFT3_uv1( $a1 )
sh $v0, POLYFT3_uv2( $a1 )
-
+
lw $v0, 8( $t4 ) # Tpage + CLUT
nop
andi $v1, $v0, 0xffff
sh $v1, POLYFT3_tpage( $a1 )
srl $v0, 16
-
+
b .sort_FT3_pri
sh $v0, POLYFT3_clut( $a1 )
-
+
.F3_light:
-
+
lhu $v0, 0( $t4 ) # Load normal 0
-
+
srl $v1, $a3, 2
andi $v1, $v1, 0x3
-
+
sll $v0, 3
addu $v0, $t2
lwc2 C2_VXY0, 0( $v0 )
@@ -235,26 +237,26 @@ smdSortModelCel:
beq $v1, 0x2, .F3_light_smt
nop
-
+
lw $v0, 4( $t4 )
lui $v1, 0x2000
or $v0, $v1
mtc2 $v0, C2_RGB
-
+
addiu $t4, 8
nop
-
+
NCCS
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F3_light_tex
nop
-
+
swc2 C2_RGB2, POLYF3_rgbc( $a1 )
-
+
b .sort_F3_pri
nop
-
+
.F3_light_tex:
lhu $v0, 0( $t4 ) # Load texture coordinates
@@ -263,23 +265,23 @@ smdSortModelCel:
lhu $v0, 4( $t4 )
sh $v1, POLYFT3_uv1( $a1 )
sh $v0, POLYFT3_uv2( $a1 )
-
+
lw $v1, 8( $t4 )
nop
andi $v0, $v1, 0xffff
sh $v0, POLYFT3_tpage( $a1 )
srl $v0, $v1, 16
sh $v0, POLYFT3_clut( $a1 )
-
+
mfc2 $v0, C2_RGB2
lui $v1, 0x2400
or $v0, $v1
-
+
b .sort_FT3_pri
sw $v0, POLYFT3_rgbc( $a1 )
-
+
.F3_light_smt:
-
+
lhu $v0, 2($t4) # Load normals 1 and 2
lhu $v1, 4($t4)
sll $v0, 3
@@ -293,32 +295,32 @@ smdSortModelCel:
lwc2 C2_VXY2, 0($v1)
lwc2 C2_VZ2 , 4($v1)
mtc2 $v0, C2_RGB
-
+
swc2 C2_SXY0, POLYFT3_xy0($a1)
swc2 C2_SXY1, POLYFT3_xy1($a1)
swc2 C2_SXY2, POLYFT3_xy2($a1)
-
+
la $v0, _smd_cel_tpage # Load cel shader TPage and CLUT values
lw $v0, 0($v0)
-
+
NCT
-
+
andi $v1, $v0, 0xffff
sh $v1, POLYFT3_tpage($a1)
srl $v1, $v0, 16
sh $v1, POLYFT3_clut($a1)
-
+
# Usable regs: v0, v1, at, t6, t7
-
+
.set noat
-
+
la $at, _smd_cel_param # Load cel shader parameters
lhu $at, 0($at)
-
+
mfc2 $t7, C2_RGB0 # Get first shaded color
andi $v1, $at, 0xff # Get U divisor value
andi $t7, 0xffff # Only keep R and G colors
-
+
andi $v0, $t7, 0xff # U0
srl $v0, $v1
sb $v0, POLYFT3_uv0($a1)
@@ -326,7 +328,7 @@ smdSortModelCel:
srl $v1, $at, 8
srl $v0, $v1
sb $v0, POLYFT3_uv0+1($a1)
-
+
mfc2 $t7, C2_RGB1
andi $v1, $at, 0xff
andi $t7, 0xffff
@@ -337,7 +339,7 @@ smdSortModelCel:
srl $v1, $at, 8
srl $v0, $v1
sb $v0, POLYFT3_uv1+1($a1)
-
+
mfc2 $t7, C2_RGB2
andi $v1, $at, 0xff
andi $t7, 0xffff
@@ -348,16 +350,16 @@ smdSortModelCel:
srl $v1, $at, 8
srl $v0, $v1
sb $v0, POLYFT3_uv2+1($a1)
-
+
la $v0, _smd_cel_col
lw $v0, 0($v0)
lui $v1, 0x2600
or $v0, $v1
sw $v0, POLYFT3_rgbc($a1)
-
+
lw $t7, 8($t4)
addiu $t4, 12
-
+
lui $v1, 0x0700
lw $v0, 0($t5)
lui $at, 0xff00
@@ -373,21 +375,21 @@ smdSortModelCel:
and $v0, $at
or $v0, $v1
sw $v0, 0($t5)
-
+
lui $v0, 0x8000
or $a1, $v0
addiu $a1, POLYFT3_len
-
+
.set at
-
+
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F3_light_tex_smt
nop
-
+
#swc2 C2_RGB0, POLYG3_rgbc0( $a1 )
#swc2 C2_RGB1, POLYG3_rgbc1( $a1 )
#swc2 C2_RGB2, POLYG3_rgbc2( $a1 )
-
+
lui $v0, 0x2000
or $t7, $v0
b .sort_F3_pri
@@ -401,17 +403,17 @@ smdSortModelCel:
lhu $v0, 4( $t4 )
sh $v1, POLYFT3_uv1( $a1 )
sh $v0, POLYFT3_uv2( $a1 )
-
+
lw $v1, 8( $t4 )
nop
andi $v0, $v1, 0xffff
sh $v0, POLYFT3_tpage( $a1 )
srl $v0, $v1, 16
sh $v0, POLYFT3_clut( $a1 )
-
+
lui $v1, 0x2400
or $t7, $v1
-
+
b .sort_FT3_pri
sw $t7, POLYFT3_rgbc( $a1 )
@@ -420,7 +422,7 @@ smdSortModelCel:
swc2 C2_SXY0, POLYF3_xy0($a1)
swc2 C2_SXY1, POLYF3_xy1($a1)
swc2 C2_SXY2, POLYF3_xy2($a1)
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -430,7 +432,7 @@ smdSortModelCel:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYF3_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0500
@@ -448,21 +450,21 @@ smdSortModelCel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYF3_len
-
+
.sort_FT3_pri:
swc2 C2_SXY0, POLYFT3_xy0( $a1 )
swc2 C2_SXY1, POLYFT3_xy1( $a1 )
swc2 C2_SXY2, POLYFT3_xy2( $a1 )
-
+
.set noat
lui $v1, 0x0700
@@ -480,21 +482,21 @@ smdSortModelCel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYFT3_len
-
+
.sort_G3_pri:
swc2 C2_SXY0, POLYG3_xy0( $a1 )
swc2 C2_SXY1, POLYG3_xy1( $a1 )
swc2 C2_SXY2, POLYG3_xy2( $a1 )
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -504,7 +506,7 @@ smdSortModelCel:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYG3_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0700
@@ -522,21 +524,21 @@ smdSortModelCel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYG3_len
-
+
.sort_GT3_pri:
swc2 C2_SXY0, POLYGT3_xy0( $a1 )
swc2 C2_SXY1, POLYGT3_xy1( $a1 )
swc2 C2_SXY2, POLYGT3_xy2( $a1 )
-
+
.set noat
lui $v1, 0x0900
@@ -554,17 +556,17 @@ smdSortModelCel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYGT3_len
## Quads
-
+
.prim_quad: # Quad processing
mfc2 $t6, C2_SXY0 # Retrieve first projected vertex
@@ -575,38 +577,38 @@ smdSortModelCel:
addu $t5, $t1
lwc2 C2_VXY0, 0( $t5 )
lwc2 C2_VZ0 , 4( $t5 )
-
+
nRTPS
-
+
cfc2 $v1, C2_FLAG # Get GTE flag value
-
+
srl $v0, $t0, 16 # Get Z divisor from OT_LEN value
-
+
bltz $v1, .skip_prim
nop
-
+
AVSZ4
-
+
andi $v0, 0xff
-
+
mfc2 $t5, C2_OTZ
-
+
sra $v1, $t0, 24 # Get Z offset from OT_LEN value
-
+
srl $t5, $v0 # Apply divisor and offset
sub $t5, $v1
-
+
blez $t5, .skip_prim # Skip primitive if less than zero
andi $v1, $t0, 0xffff
bge $t5, $v1, .skip_prim # Skip primitive if greater than OT length
sll $t5, 2
addu $t5, $a0 # Append OTZ to OT address
-
+
# no touch:
# a0, a1, a2, a3, t0, t1, t2, t3, t4, t5(ot), t6(sxy0)
-
+
ClipTestQuad
-
+
and $v0, $s0, $s1 # v0 & v1
beqz $v0, .do_draw_q
and $v0, $s1, $s2 # v1 & v2
@@ -622,29 +624,29 @@ smdSortModelCel:
nop
b .skip_prim
nop
-
+
.do_draw_q:
srl $v0, $a3, 2 # Lighting enabled?
andi $v0, 0x3
bnez $v0, .F4_light
nop
-
+
andi $v0, $a3, 0x10 # Gouraud quad
bnez $v0, .F4_gouraud
nop
-
+
andi $v0, $a3, 0x20 # Textured quad
bnez $v0, .F4_textured
nop
-
+
lw $v0, 0($t4)
lui $v1, 0x2800
or $v0, $v1
-
+
b .sort_F4_pri
sw $v0, POLYF4_rgbc($a1)
-
+
.F4_gouraud:
lw $v0, 0($t4)
@@ -660,15 +662,15 @@ smdSortModelCel:
sw $v0, POLYG4_rgbc2($a1)
b .sort_G4_pri
sw $v1, POLYG4_rgbc3($a1)
-
+
.F4_textured:
-
+
lw $v0, 0($t4)
lui $v1, 0x2c00
or $v0, $v1
sw $v0, POLYFT4_rgbc( $a1 )
addiu $t4, 4
-
+
lhu $v0, 0($t4) # Load texture coordinates
lhu $v1, 2($t4)
sh $v0, POLYFT4_uv0( $a1 )
@@ -677,23 +679,23 @@ smdSortModelCel:
lhu $v1, 6( $t4 )
sh $v0, POLYFT4_uv2( $a1 )
sh $v1, POLYFT4_uv3( $a1 )
-
+
lw $v1, 8( $t4 )
nop
andi $v0, $v1, 0xffff
sh $v0, POLYFT4_tpage( $a1 )
srl $v0, $v1, 16
-
+
b .sort_FT4_pri
sh $v0, POLYFT4_clut($a1)
-
+
.F4_light:
lhu $v0, 0( $t4 ) # Load normal 0
-
+
srl $v1, $a3, 2
andi $v1, $v1, 0x3
-
+
sll $v0, 3
addu $v0, $t2
lwc2 C2_VXY0, 0( $v0 )
@@ -701,26 +703,26 @@ smdSortModelCel:
beq $v1, 0x2, .F4_light_smt
nop
-
+
lw $v0, 4( $t4 )
lui $v1, 0x2800
or $v0, $v1
mtc2 $v0, C2_RGB
-
+
addiu $t4, 8
nop
-
+
NCS
-
+
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F4_light_tex
nop
swc2 C2_RGB2, POLYF4_rgbc( $a1 )
-
+
b .sort_F4_pri
nop
-
+
.F4_light_tex:
lhu $v0, 0( $t4 ) # Load texture coordinates
@@ -731,22 +733,22 @@ smdSortModelCel:
lhu $v1, 6( $t4 )
sh $v0, POLYFT4_uv2( $a1 )
sh $v1, POLYFT4_uv3( $a1 )
-
+
lw $v1, 8( $t4 )
nop
andi $v0, $v1, 0xffff
sh $v0, POLYFT4_tpage( $a1 )
srl $v0, $v1, 16
sh $v0, POLYFT4_clut( $a1 )
-
+
mfc2 $v0, C2_RGB2
lui $v1, 0x2c00
or $v0, $v1
-
+
b .sort_FT4_pri
nop
sw $v0, POLYFT4_rgbc( $a1 )
-
+
.F4_light_smt:
lhu $v0, 2( $t4 ) # Load normals 1 and 2
@@ -759,33 +761,33 @@ smdSortModelCel:
lwc2 C2_VZ1 , 4( $v0 )
lwc2 C2_VXY2, 0( $v1 )
lwc2 C2_VZ2 , 4( $v1 )
-
+
sw $t6, POLYFT4_xy0($a1)
swc2 C2_SXY0, POLYFT4_xy1($a1)
swc2 C2_SXY1, POLYFT4_xy2($a1)
swc2 C2_SXY2, POLYFT4_xy3($a1)
-
+
la $v0, _smd_cel_tpage # Load cel shader TPage and CLUT values
lw $v0, 0($v0)
-
+
NCT
-
+
andi $v1, $v0, 0xffff
sh $v1, POLYFT4_tpage($a1)
srl $v1, $v0, 16
sh $v1, POLYFT4_clut($a1)
-
+
# Usable regs: v0, v1, at, t7
-
+
.set noat
-
+
la $at, _smd_cel_param # Load cel shader parameters
lhu $at, 0($at)
-
+
mfc2 $t7, C2_RGB0
andi $v1, $at, 0xff # Get U divisor value
andi $t7, 0xffff # Only keep R and G colors
-
+
andi $v0, $t7, 0xff # U0
srl $v0, $v1
sb $v0, POLYFT4_uv0($a1)
@@ -793,7 +795,7 @@ smdSortModelCel:
srl $v1, $at, 8
srl $v0, $v1
sb $v0, POLYFT4_uv0+1($a1)
-
+
mfc2 $t7, C2_RGB1
andi $v1, $at, 0xff
andi $t7, 0xffff
@@ -804,7 +806,7 @@ smdSortModelCel:
srl $v1, $at, 8
srl $v0, $v1
sb $v0, POLYFT4_uv1+1($a1)
-
+
mfc2 $t7, C2_RGB2
andi $v1, $at, 0xff
andi $t7, 0xffff
@@ -815,24 +817,24 @@ smdSortModelCel:
srl $v1, $at, 8
srl $v0, $v1
sb $v0, POLYFT4_uv2+1($a1)
-
+
la $v0, _smd_cel_col
lw $v0, 0($v0)
lui $v1, 0x2E00
or $v0, $v1
sw $v0, POLYFT4_rgbc($a1)
-
+
lw $t7, 8($t4)
-
+
lhu $v0, 6($t4) # Load normal 3
addiu $t4, 12
sll $v0, 3
addu $v0, $t2
lwc2 C2_VXY0, 0( $v0 )
lwc2 C2_VZ0 , 4( $v0 )
-
+
nNCS
-
+
mfc2 $s0, C2_RGB2
andi $v1, $at, 0xff
andi $s0, 0xffff
@@ -843,7 +845,7 @@ smdSortModelCel:
srl $v1, $at, 8
srl $v0, $v1
sb $v0, POLYFT4_uv3+1($a1)
-
+
lui $v1, 0x0900
lw $v0, 0($t5)
lui $at, 0xff00
@@ -859,24 +861,24 @@ smdSortModelCel:
and $v0, $at
or $v0, $v1
sw $v0, 0($t5)
-
+
lui $v0, 0x8000
or $a1, $v0
addiu $a1, POLYFT4_len
-
+
.set at
-
+
andi $v0, $a3, 0x20 # Textured quad
bnez $v0, .F4_light_tex_smt
nop
-
+
lui $v0, 0x2800
or $t7, $v0
b .sort_F4_pri
sw $t7, POLYF4_rgbc($a1)
-
+
.F4_light_tex_smt:
-
+
lhu $v0, 0($t4) # Load texture coordinates
lhu $v1, 2($t4)
sh $v0, POLYFT4_uv0($a1)
@@ -887,25 +889,25 @@ smdSortModelCel:
sh $v1, POLYFT4_uv3($a1)
lw $v1, 8($t4)
-
+
lui $v0, 0x2E00
or $t7, $v0
sw $t7, POLYFT4_rgbc($a1)
-
+
andi $v0, $v1, 0xffff
sh $v0, POLYFT4_tpage($a1)
srl $v0, $v1, 16
-
+
b .sort_FT4_pri
sh $v0, POLYFT4_clut($a1)
-
+
.sort_F4_pri:
sw $t6, POLYF4_xy0($a1)
swc2 C2_SXY0, POLYF4_xy1($a1)
swc2 C2_SXY1, POLYF4_xy2($a1)
swc2 C2_SXY2, POLYF4_xy3($a1)
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -915,7 +917,7 @@ smdSortModelCel:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYF4_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0600
@@ -933,22 +935,22 @@ smdSortModelCel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYF4_len
-
+
.sort_FT4_pri:
sw $t6, POLYFT4_xy0($a1)
swc2 C2_SXY0, POLYFT4_xy1($a1)
swc2 C2_SXY1, POLYFT4_xy2($a1)
swc2 C2_SXY2, POLYFT4_xy3($a1)
-
+
.set noat
lui $v1, 0x0900
@@ -966,22 +968,22 @@ smdSortModelCel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYFT4_len
-
+
.sort_G4_pri:
sw $t6, POLYG4_xy0($a1)
swc2 C2_SXY0, POLYG4_xy1($a1)
swc2 C2_SXY1, POLYG4_xy2($a1)
swc2 C2_SXY2, POLYG4_xy3($a1)
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -991,7 +993,7 @@ smdSortModelCel:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYG4_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0900
@@ -1009,22 +1011,22 @@ smdSortModelCel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYG4_len
-
+
.sort_GT4_pri:
sw $t6, POLYGT4_xy0($a1)
swc2 C2_SXY0, POLYGT4_xy1($a1)
swc2 C2_SXY1, POLYGT4_xy2($a1)
swc2 C2_SXY2, POLYGT4_xy3($a1)
-
+
.set noat
lui $v1, 0x0c00
@@ -1042,20 +1044,20 @@ smdSortModelCel:
and $v0, $at
or $v0, $a1
sw $v0, 0($t5)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYGT4_len
-
+
.skip_prim:
b .sort_loop
nop
-
+
.exit:
lw $s0, 0( $sp )
@@ -1065,9 +1067,12 @@ smdSortModelCel:
addiu $sp, 16
jr $ra
move $v0, $a1
-
+.section .bss._smd_cel_col, "w"
.comm _smd_cel_col, 4, 4 # STP shading polygon color
+
+.section .bss._smd_cel_param, "w"
.comm _smd_cel_param, 4, 4 # U divisor, V divisor, shading clip
-.comm _smd_cel_tpage, 4, 4 # CEL shader texture page & CLUT
+.section .bss._smd_cel_tpage, "w"
+.comm _smd_cel_tpage, 4, 4 # CEL shader texture page & CLUT
diff --git a/examples/demos/n00bdemo/smd_flat.s b/libpsn00b/smd/smd_flat.s
index 4b47be4..843b8d3 100644
--- a/examples/demos/n00bdemo/smd_flat.s
+++ b/libpsn00b/smd/smd_flat.s
@@ -1,43 +1,45 @@
+# PSn00bSDK .SMD model parser library
+# (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed
+
.set noreorder
.include "gtereg.inc"
.include "inline_s.inc"
-.include "smd_s.h"
-
-
-.section .text
+.include "smd/smd_s.inc"
+.section .text.smdSortModelFlat, "ax", @progbits
.global smdSortModelFlat
.type smdSortModelFlat, @function
+
smdSortModelFlat:
# a0 - Pointer SC_OT structure
# a1 - Pointer to next primitive
# a2 - Pointer to SMD data address
# v0 - New pointer of primitive buffer (return)
-
+
addiu $sp, -16
sw $s0, 0( $sp )
sw $s1, 4( $sp )
sw $s2, 8( $sp )
sw $s3, 12( $sp )
-
+
la $v0, _sc_clip
lw $t8, 0($v0)
lw $t9, 4($v0)
-
+
lw $t1, SMD_HEAD_PVERTS( $a2 )
lw $t2, SMD_HEAD_PNORMS( $a2 )
lw $t3, SMD_HEAD_PPRIMS( $a2 )
-
+
.sort_loop:
nop
lw $a3, 0($t3) # Get primitive ID word
move $t4, $t3
-
+
beqz $a3, .exit # Check if terminator (just zero)
addiu $t4, 4
-
+
lhu $t5, 0( $t4 ) # Load vertices
lhu $t6, 2( $t4 )
lhu $t7, 4( $t4 )
@@ -53,32 +55,32 @@ smdSortModelFlat:
lwc2 C2_VZ1 , 4( $t6 )
lwc2 C2_VXY2, 0( $t7 )
lwc2 C2_VZ2 , 4( $t7 )
-
+
srl $v1, $a3, 24 # Get primitive size
addu $t3, $v1 # Step main pointer to next primitive
-
+
RTPT
-
+
cfc2 $v0, C2_FLAG # Get GTE flag value
nop
-
+
bltz $v0, .skip_prim # Skip primitive if Z overflow
nop
-
+
#NCLIP # Backface culling
-
+
#mfc2 $v1, C2_MAC0
-
+
andi $v0, $a3, 0x3
-
+
#bltz $v1, .skip_prim
#nop
-
+
beq $v0, 0x1, .prim_tri # If primitive is a triangle
nop
beq $v0, 0x2, .prim_quad # If primitive is a quad
nop
-
+
b .skip_prim
nop
@@ -89,9 +91,9 @@ smdSortModelFlat:
addiu $t4, 8 # Advance from indices
#AVSZ3 # Calculate average Z
-
+
ClipTestTri
-
+
and $v0, $s0, $s1 # v0 & v1
beqz $v0, .do_draw
and $v0, $s1, $s2 # v1 & v2
@@ -101,9 +103,9 @@ smdSortModelFlat:
nop
b .skip_prim
nop
-
+
.do_draw:
-
+
#srl $v0, $a3, 2 # Lighting enabled?
#andi $v0, 0x3
#bnez $v0, .F3_light
@@ -112,18 +114,18 @@ smdSortModelFlat:
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F3_textured
nop
-
+
andi $v0, $a3, 0x10 # Gouraud shaded
bnez $v0, .F3_gouraud
nop
-
+
lw $v0, 0( $t4 ) # Flat color, no lighting
lui $v1, 0x2000
or $v0, $v1
-
+
b .sort_F3_pri
sw $v0, POLYF3_rgbc( $a1 )
-
+
.F3_textured:
lw $v0, 0( $t4 ) # Flat color, no lighting
@@ -131,23 +133,23 @@ smdSortModelFlat:
or $v0, $v1
sw $v0, POLYFT3_rgbc( $a1 )
addiu $t4, 4
-
+
lhu $v0, 0( $t4 ) # Load texture coordinates
lhu $v1, 2( $t4 )
sh $v0, POLYFT3_uv0( $a1 )
lhu $v0, 4( $t4 )
sh $v1, POLYFT3_uv1( $a1 )
sh $v0, POLYFT3_uv2( $a1 )
-
+
lw $v0, 8( $t4 ) # Tpage + CLUT
nop
andi $v1, $v0, 0xffff
sh $v1, POLYFT3_tpage( $a1 )
srl $v0, 16
-
+
b .sort_FT3_pri
sh $v0, POLYFT3_clut( $a1 )
-
+
.F3_gouraud:
lw $v0, 0($t4)
lw $v1, 4($t4)
@@ -160,14 +162,14 @@ smdSortModelFlat:
sw $v1, POLYG3_rgbc1($a1)
b .sort_G3_pri
sw $v0, POLYG3_rgbc2($a1)
-
+
#.F3_light:
-
+
#lhu $v0, 0( $t4 ) # Load normal 0
-
+
#srl $v1, $a3, 2
#andi $v1, $v1, 0x3
-
+
#sll $v0, 3
#addu $v0, $t2
#lwc2 C2_VXY0, 0( $v0 )
@@ -175,26 +177,26 @@ smdSortModelFlat:
#beq $v1, 0x2, .F3_light_smt
#nop
-
+
#lw $v0, 4( $t4 )
#lui $v1, 0x2000
#or $v0, $v1
#mtc2 $v0, C2_RGB
-
+
#addiu $t4, 8
#nop
-
+
#NCCS
#andi $v0, $a3, 0x20 # Textured triangle
#bnez $v0, .F3_light_tex
#nop
-
+
#swc2 C2_RGB2, POLYF3_rgbc( $a1 )
-
+
#b .sort_F3_pri
#nop
-
+
#.F3_light_tex:
#lhu $v0, 0( $t4 ) # Load texture coordinates
@@ -203,23 +205,23 @@ smdSortModelFlat:
#lhu $v0, 4( $t4 )
#sh $v1, POLYFT3_uv1( $a1 )
#sh $v0, POLYFT3_uv2( $a1 )
-
+
#lw $v1, 8( $t4 )
#nop
#andi $v0, $v1, 0xffff
#sh $v0, POLYFT3_tpage( $a1 )
#srl $v0, $v1, 16
#sh $v0, POLYFT3_clut( $a1 )
-
+
#mfc2 $v0, C2_RGB2
#lui $v1, 0x2400
#or $v0, $v1
-
+
#b .sort_FT3_pri
#sw $v0, POLYFT3_rgbc( $a1 )
-
+
#.F3_light_smt:
-
+
#lhu $v0, 2( $t4 ) # Load normals 1 and 2
#lhu $v1, 4( $t4 )
#sll $v0, 3
@@ -234,20 +236,20 @@ smdSortModelFlat:
#lui $v1, 0x3000 # Load color
#or $v0, $v1
#mtc2 $v0, C2_RGB
-
+
#addiu $t4, 12
#nop
-
+
#NCCT
-
+
#andi $v0, $a3, 0x20 # Textured triangle
#bnez $v0, .F3_light_tex_smt
#nop
-
+
#swc2 C2_RGB0, POLYG3_rgbc0( $a1 )
#swc2 C2_RGB1, POLYG3_rgbc1( $a1 )
#swc2 C2_RGB2, POLYG3_rgbc2( $a1 )
-
+
#b .sort_G3_pri
#nop
@@ -259,21 +261,21 @@ smdSortModelFlat:
# lhu $v0, 4( $t4 )
# sh $v1, POLYGT3_uv1( $a1 )
# sh $v0, POLYGT3_uv2( $a1 )
-
+
# lw $v1, 8( $t4 )
# nop
# andi $v0, $v1, 0xffff
# sh $v0, POLYGT3_tpage( $a1 )
# srl $v0, $v1, 16
# sh $v0, POLYGT3_clut( $a1 )
-
+
# mfc2 $v0, C2_RGB0
# lui $v1, 0x3400
# or $v0, $v1
-
+
# swc2 C2_RGB1, POLYGT3_rgbc1( $a1 )
# swc2 C2_RGB2, POLYGT3_rgbc2( $a1 )
-
+
# b .sort_GT3_pri
# sw $v0, POLYGT3_rgbc0( $a1 )
@@ -282,7 +284,7 @@ smdSortModelFlat:
swc2 C2_SXY0, POLYF3_xy0($a1)
swc2 C2_SXY1, POLYF3_xy1($a1)
swc2 C2_SXY2, POLYF3_xy2($a1)
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -292,7 +294,7 @@ smdSortModelFlat:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYF3_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0500
@@ -310,21 +312,21 @@ smdSortModelFlat:
and $v0, $at
or $v0, $a1
sw $v0, 0($a0)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYF3_len
-
+
.sort_FT3_pri:
swc2 C2_SXY0, POLYFT3_xy0( $a1 )
swc2 C2_SXY1, POLYFT3_xy1( $a1 )
swc2 C2_SXY2, POLYFT3_xy2( $a1 )
-
+
.set noat
lui $v1, 0x0700
@@ -342,21 +344,21 @@ smdSortModelFlat:
and $v0, $at
or $v0, $a1
sw $v0, 0($a0)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYFT3_len
-
+
.sort_G3_pri:
swc2 C2_SXY0, POLYG3_xy0( $a1 )
swc2 C2_SXY1, POLYG3_xy1( $a1 )
swc2 C2_SXY2, POLYG3_xy2( $a1 )
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -366,7 +368,7 @@ smdSortModelFlat:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYG3_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0700
@@ -384,21 +386,21 @@ smdSortModelFlat:
and $v0, $at
or $v0, $a1
sw $v0, 0($a0)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYG3_len
-
+
.sort_GT3_pri:
swc2 C2_SXY0, POLYGT3_xy0( $a1 )
swc2 C2_SXY1, POLYGT3_xy1( $a1 )
swc2 C2_SXY2, POLYGT3_xy2( $a1 )
-
+
.set noat
lui $v1, 0x0900
@@ -416,17 +418,17 @@ smdSortModelFlat:
and $v0, $at
or $v0, $a1
sw $v0, 0($a0)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYGT3_len
## Quads
-
+
.prim_quad: # Quad processing
mfc2 $t6, C2_SXY0 # Retrieve first projected vertex
@@ -437,18 +439,18 @@ smdSortModelFlat:
addu $t5, $t1
lwc2 C2_VXY0, 0( $t5 )
lwc2 C2_VZ0 , 4( $t5 )
-
+
nRTPS
-
+
cfc2 $v1, C2_FLAG # Get GTE flag value
-
+
nop
-
+
bltz $v1, .skip_prim
nop
-
+
ClipTestQuad
-
+
and $v0, $s0, $s1 # v0 & v1
beqz $v0, .do_draw_q
and $v0, $s1, $s2 # v1 & v2
@@ -464,37 +466,37 @@ smdSortModelFlat:
nop
b .skip_prim
nop
-
+
.do_draw_q:
srl $v0, $a3, 2 # Lighting enabled?
andi $v0, 0x3
bnez $v0, .F4_light
nop
-
+
andi $v0, $a3, 0x10 # Gouraud quad
bnez $v0, .F4_gouraud
nop
-
+
andi $v0, $a3, 0x20 # Textured quad
bnez $v0, .F4_textured
nop
-
+
lw $v0, 0($t4)
lui $v1, 0x2800
or $v0, $v1
-
+
b .sort_F4_pri
sw $v0, POLYF4_rgbc($a1)
.F4_textured:
-
+
lw $v0, 0($t4)
lui $v1, 0x2c00
or $v0, $v1
sw $v0, POLYFT4_rgbc( $a1 )
addiu $t4, 4
-
+
lhu $v0, 0($t4) # Load texture coordinates
lhu $v1, 2($t4)
sh $v0, POLYFT4_uv0( $a1 )
@@ -503,16 +505,16 @@ smdSortModelFlat:
lhu $v1, 6( $t4 )
sh $v0, POLYFT4_uv2( $a1 )
sh $v1, POLYFT4_uv3( $a1 )
-
+
lw $v1, 8( $t4 )
nop
andi $v0, $v1, 0xffff
sh $v0, POLYFT4_tpage( $a1 )
srl $v0, $v1, 16
-
+
b .sort_FT4_pri
sh $v0, POLYFT4_clut($a1)
-
+
.F4_gouraud:
lw $v0, 0($t4)
@@ -528,15 +530,15 @@ smdSortModelFlat:
sw $v0, POLYG4_rgbc2($a1)
b .sort_G4_pri
sw $v1, POLYG4_rgbc3($a1)
-
+
.F4_light:
lhu $v0, 0( $t4 ) # Load normal 0
-
+
srl $v1, $a3, 2
andi $v1, $v1, 0x3
-
+
sll $v0, 3
addu $v0, $t2
lwc2 C2_VXY0, 0( $v0 )
@@ -544,26 +546,26 @@ smdSortModelFlat:
beq $v1, 0x2, .F4_light_smt
nop
-
+
lw $v0, 4( $t4 )
lui $v1, 0x2800
or $v0, $v1
mtc2 $v0, C2_RGB
-
+
addiu $t4, 8
nop
-
+
NCCS
-
+
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F4_light_tex
nop
swc2 C2_RGB2, POLYF4_rgbc( $a1 )
-
+
b .sort_F4_pri
nop
-
+
.F4_light_tex:
lhu $v0, 0( $t4 ) # Load texture coordinates
@@ -574,21 +576,21 @@ smdSortModelFlat:
lhu $v1, 6( $t4 )
sh $v0, POLYFT4_uv2( $a1 )
sh $v1, POLYFT4_uv3( $a1 )
-
+
lw $v1, 8( $t4 )
nop
andi $v0, $v1, 0xffff
sh $v0, POLYFT4_tpage( $a1 )
srl $v0, $v1, 16
sh $v0, POLYFT4_clut( $a1 )
-
+
mfc2 $v0, C2_RGB2
lui $v1, 0x2c00
or $v0, $v1
-
+
b .sort_FT4_pri
sw $v0, POLYFT4_rgbc( $a1 )
-
+
.F4_light_smt:
lhu $v0, 2( $t4 ) # Load normals 1 and 2
@@ -601,38 +603,38 @@ smdSortModelFlat:
lwc2 C2_VZ1 , 4( $v0 )
lwc2 C2_VXY2, 0( $v1 )
lwc2 C2_VZ2 , 4( $v1 )
-
+
lw $v0, 8( $t4 )
lui $v1, 0x3800 # Load color
or $v0, $v1
mtc2 $v0, C2_RGB
-
+
nNCCT
-
+
lhu $v0, 6( $t4 ) # Load normal 3
-
+
addiu $t4, 12
-
+
sll $v0, 3
addu $v0, $t2
lwc2 C2_VXY0, 0( $v0 )
lwc2 C2_VZ0 , 4( $v0 )
-
+
andi $v0, $a3, 0x20 # Textured triangle
bnez $v0, .F4_light_tex_smt
nop
-
+
swc2 C2_RGB0, POLYG4_rgbc0( $a1 )
swc2 C2_RGB1, POLYG4_rgbc1( $a1 )
swc2 C2_RGB2, POLYG4_rgbc2( $a1 )
-
+
nNCCS
-
+
swc2 C2_RGB2, POLYG4_rgbc3( $a1 )
-
+
b .sort_G4_pri
nop
-
+
.F4_light_tex_smt:
mfc2 $v0, C2_RGB0
@@ -641,9 +643,9 @@ smdSortModelFlat:
sw $v0, POLYGT4_rgbc0( $a1 )
swc2 C2_RGB1, POLYGT4_rgbc1( $a1 )
swc2 C2_RGB2, POLYGT4_rgbc2( $a1 )
-
+
NCCS
-
+
lhu $v0, 0( $t4 ) # Load texture coordinates
lhu $v1, 2( $t4 )
sh $v0, POLYGT4_uv0( $a1 )
@@ -655,21 +657,21 @@ smdSortModelFlat:
lw $v1, 8( $t4 )
swc2 C2_RGB2, POLYGT4_rgbc3( $a1 )
-
+
andi $v0, $v1, 0xffff
sh $v0, POLYGT4_tpage( $a1 )
srl $v0, $v1, 16
-
+
b .sort_GT4_pri
sh $v0, POLYGT4_clut( $a1 )
-
+
.sort_F4_pri:
sw $t6, POLYF4_xy0($a1)
swc2 C2_SXY0, POLYF4_xy1($a1)
swc2 C2_SXY1, POLYF4_xy2($a1)
swc2 C2_SXY2, POLYF4_xy3($a1)
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -679,7 +681,7 @@ smdSortModelFlat:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYF4_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0600
@@ -697,22 +699,22 @@ smdSortModelFlat:
and $v0, $at
or $v0, $a1
sw $v0, 0($a0)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYF4_len
-
+
.sort_FT4_pri:
sw $t6, POLYFT4_xy0($a1)
swc2 C2_SXY0, POLYFT4_xy1($a1)
swc2 C2_SXY1, POLYFT4_xy2($a1)
swc2 C2_SXY2, POLYFT4_xy3($a1)
-
+
.set noat
lui $v1, 0x0900
@@ -730,22 +732,22 @@ smdSortModelFlat:
and $v0, $at
or $v0, $a1
sw $v0, 0($a0)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYFT4_len
-
+
.sort_G4_pri:
sw $t6, POLYG4_xy0($a1)
swc2 C2_SXY0, POLYG4_xy1($a1)
swc2 C2_SXY1, POLYG4_xy2($a1)
swc2 C2_SXY2, POLYG4_xy3($a1)
-
+
la $v0, _smd_tpage_base
lhu $v0, 0($v0)
srl $v1, $a3, 6 # Get blend mode
@@ -755,7 +757,7 @@ smdSortModelFlat:
lui $v1, 0xe100
or $v0, $v1
sw $v0, POLYG4_tpage($a1) # Store TPage
-
+
.set noat
lui $v1, 0x0900
@@ -773,22 +775,22 @@ smdSortModelFlat:
and $v0, $at
or $v0, $a1
sw $v0, 0($a0)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYG4_len
-
+
.sort_GT4_pri:
sw $t6, POLYGT4_xy0($a1)
swc2 C2_SXY0, POLYGT4_xy1($a1)
swc2 C2_SXY1, POLYGT4_xy2($a1)
swc2 C2_SXY2, POLYGT4_xy3($a1)
-
+
.set noat
lui $v1, 0x0c00
@@ -806,20 +808,20 @@ smdSortModelFlat:
and $v0, $at
or $v0, $a1
sw $v0, 0($a0)
-
+
.set at
lui $v0, 0x8000
or $a1, $v0
-
+
b .sort_loop
addiu $a1, POLYGT4_len
-
+
.skip_prim:
b .sort_loop
nop
-
+
.exit:
lw $s0, 0( $sp )
@@ -829,4 +831,3 @@ smdSortModelFlat:
addiu $sp, 16
jr $ra
move $v0, $a1
- \ No newline at end of file
diff --git a/examples/demos/n00bdemo/smdparser.s b/libpsn00b/smd/smdparser.s
index 379690f..656e509 100644
--- a/examples/demos/n00bdemo/smdparser.s
+++ b/libpsn00b/smd/smdparser.s
@@ -1,6 +1,9 @@
+# PSn00bSDK .SMD model parser library
+# (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed
+
.set noreorder
-.include "smd_s.h"
+.include "smd/smd_s.inc"
.set SMD_PRI_ID, 0
.set SMD_PRI_v0, 4
@@ -22,108 +25,106 @@
.set SMD_PRI_tpage, 44
.set SMD_PRI_clut, 46
-.section .text
-
-
-.comm _smd_parse_addr, 4, 4
-
-
+.section .text.OpenSMD, "ax", @progbits
.global OpenSMD
.type OpenSMD, @function
+
OpenSMD:
lw $v0, SMD_HEAD_ID($a0)
li $v1, 0x01444d53
-
+
bne $v0, $v1, .not_smd
nop
-
+
lw $v0, SMD_HEAD_PPRIMS($a0)
la $v1, _smd_parse_addr
sw $v0, 0($v1)
-
+
jr $ra
lhu $v0, SMD_HEAD_NPRIMS($a0)
-
+
.not_smd:
jr $ra
move $v0, $0
-
-
+
+.section .text.ReadSMD, "ax", @progbits
.global ReadSMD
.type ReadSMD, @function
-ReadSMD:
+ReadSMD:
la $v0, _smd_parse_addr
lw $v0, 0($v0)
nop
-
+
lw $a2, 0($v0) # Load primitive ID
addiu $a1, $v0, 4
-
+
sw $a2, SMD_PRI_ID($a0)
-
+
beqz $a2, $end_prim
nop
-
+
srl $v1, $a2, 24 # Get primitive size
addu $v0, $v1
la $v1, _smd_parse_addr
sw $v0, 0($v1)
-
+
lw $v0, 0($a1) # Copy vertex coords
lw $v1, 4($a1)
sw $v0, SMD_PRI_v0($a0)
sw $v1, SMD_PRI_v2($a0)
addiu $a1, 8
-
+
srl $v0, $a2, 2 # Lighting enabled?
andi $v0, 0x3
bnez $v0, $light
nop
-
+
b $no_light
nop
-
+
$light:
srl $v1, $a2, 2
lw $v0, 0($a1) # Copy vertex coords
andi $v1, 0x3
sw $v0, SMD_PRI_n0($a0)
-
+
bne $v1, 0x2, $light_flat
addiu $a1, 4
-
+
lw $v1, 0($a1)
addiu $a1, 4
sw $v1, SMD_PRI_n2($a0)
$light_flat:
$no_light:
-
+
lw $v0, 0($a1)
nop
sw $v0, SMD_PRI_rgbc0($a0)
addiu $a1, 4
-
+
srl $v0, $a2, 5
andi $v0, 0x1
beqz $v0, $not_textured
nop
-
+
lw $v0, 0($a1)
lw $v1, 4($a1)
sw $v0, SMD_PRI_tuv0($a0)
lw $v0, 8($a1)
sw $v1, SMD_PRI_tuv2($a0)
sw $v0, SMD_PRI_tpage($a0)
-
+
$not_textured:
-
+
jr $ra
move $v0, $a0
-
+
$end_prim:
jr $ra
move $v0, $0
- \ No newline at end of file
+
+.section .bss._smd_parse_addr, "w"
+.comm _smd_parse_addr, 4, 4