diff --git a/CMakeLists.txt b/CMakeLists.txt index ffd4d7d..564dd67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,8 @@ project( psn00bsdk_add_executable(template STATIC main.c) -psn00bsdk_target_incbin(template PRIVATE tim_player128 player128.tim) +psn00bsdk_target_incbin(template PRIVATE tim_player_f player_f.tim) +psn00bsdk_target_incbin(template PRIVATE tim_player_b player_b.tim) psn00bsdk_target_incbin(template PRIVATE tim_player16bpp player128-16.tim) psn00bsdk_target_incbin(template PRIVATE tim_shambler shambler128.tim) psn00bsdk_target_incbin(template PRIVATE mdl_player player.ps1mdl) diff --git a/main.c b/main.c index d3c54af..2fbcb65 100644 --- a/main.c +++ b/main.c @@ -42,12 +42,14 @@ u_long ot[2][OTLEN]; // Ordering tables, two arrays for double buffering. These char primbuff[2][32768]; // Primitive buffer, just a raw buffer of bytes to use as a pool for primitives char *nextpri; -extern u_long tim_player128[]; +extern u_long tim_player_f[]; +extern u_long tim_player_b[]; extern u_long tim_player16bpp[]; extern u_long tim_shambler[]; extern u_long mdl_player[]; -TIM_IMAGE playerTex; +// The player texture is divided into two pieces, so that each part is aligned to their own texture page +TIM_IMAGE playerFrontTex, playerBackTex; TIM_IMAGE shamblerTex; ps1mdl_t model; @@ -119,15 +121,16 @@ void init(void) nextpri = primbuff[0]; - loadTexture(tim_player128, &playerTex); - loadTexture(tim_player16bpp, &playerTex); + loadTexture(tim_player_f, &playerFrontTex); + loadTexture(tim_player_b, &playerBackTex); + //loadTexture(tim_player16bpp, &playerFrontTex); loadTexture(tim_shambler, &shamblerTex); loadModel(mdl_player, &model); // Set texture page for the entire drawing environment. Nice in some cases perhaps, but not what we need. - //draw[0].tpage = getTPage(playerTex.mode & 0x3, 0, playerTex.prect->x, playerTex.prect->y); - //draw[1].tpage = getTPage(playerTex.mode & 0x3, 0, playerTex.prect->x, playerTex.prect->y); + //draw[0].tpage = getTPage(playerFrontTex.mode & 0x3, 0, playerFrontTex.prect->x, playerFrontTex.prect->y); + //draw[1].tpage = getTPage(playerFrontTex.mode & 0x3, 0, playerFrontTex.prect->x, playerFrontTex.prect->y); } // Display function @@ -208,6 +211,34 @@ void addTexturedTriangle(int x0, int y0, int x1, int y1, int x2, int y2, short u nextpri += sizeof(POLY_FT3); } +void addGouraudTexturedTriangle( + int x0, int y0, int x1, int y1, int x2, int y2, unsigned char depth, + unsigned int rgb0, unsigned int rgb1, unsigned int rgb2, + short u0, short v0, short u1, short v1, short u2, short v2, TIM_IMAGE *img) +{ + if (img == NULL) + { + addColoredTriangle(x0, y0, x1, y1, x2, y2, rgb0, rgb1, rgb2, depth); + return; + } + + short uoffs = (img->prect->x % 64) << (2 - (img->mode & 0x3)); + short voffs = (img->prect->y & 0xFF); + + POLY_GT3 *poly = (POLY_GT3*)nextpri; + setPolyGT3(poly); + setXY3(poly, x0, y0, x1, y1, x2, y2); + setUV3(poly, uoffs + u0, voffs + v0, uoffs + u1, voffs + v1, uoffs + u2, voffs + v2); + setRGB0(poly, (rgb0 >> 16) & 0xFF, (rgb0 >> 8) & 0xFF, rgb0 & 0xFF); + setRGB1(poly, (rgb1 >> 16) & 0xFF, (rgb1 >> 8) & 0xFF, rgb1 & 0xFF); + setRGB2(poly, (rgb2 >> 16) & 0xFF, (rgb2 >> 8) & 0xFF, rgb2 & 0xFF); + setClut(poly, img->crect->x, img->crect->y); + setTPage(poly, img->mode & 0x3, 0, img->prect->x, img->prect->y); + + addPrim(ot[db] + depth, poly); + nextpri += sizeof(POLY_GT3); +} + void addTexturedSprite(int x, int y, int w, int h, TIM_IMAGE *img) { short uoffs = (img->prect->x % 64) << (2 - (img->mode & 0x3)); @@ -250,7 +281,7 @@ static int fakeLight(const int *norm) const int light[3] = { ONE, 0, 0 }; int lit = dot(norm, light) >> 4; // Calculate light intensity and normalize to [-256..255] lit = lit < 0 ? 0 : lit; // Clamp to [0..255] - lit += 32; // Add some ambient light + lit += 48; // Add some ambient light lit = lit > 255 ? 255 : lit; // Clamp to [0..255] again return lit << 16 | lit << 8 | lit; } @@ -262,7 +293,7 @@ void drawStuff(int counter) // Print the obligatory hello world and counter to show that the // program isn't locking up to the last created text stream FntPrint(-1, "COUNTER=%d, SIN=%d\n", counter, isin(counter)); - FntPrint(-1, "Image x %d y %d w %d h %d mode 0x%x\n", playerTex.prect->x, playerTex.prect->y, playerTex.prect->w, playerTex.prect->h, playerTex.mode); + FntPrint(-1, "Image x %d y %d w %d h %d mode 0x%x\n", playerFrontTex.prect->x, playerFrontTex.prect->y, playerFrontTex.prect->w, playerFrontTex.prect->h, playerFrontTex.mode); FntPrint(-1, "Model: %d tris, %d verts\n", model.header->triangleCount, model.header->vertexCount); // Draw the last created text stream @@ -278,6 +309,10 @@ void drawStuff(int counter) ps1mdl_vertex_t *v0 = &model.vertices[tri->vertexIndex[0] + vertOffs]; ps1mdl_vertex_t *v1 = &model.vertices[tri->vertexIndex[1] + vertOffs]; ps1mdl_vertex_t *v2 = &model.vertices[tri->vertexIndex[2] + vertOffs]; + + ps1mdl_texcoord_t *tc0 = &model.texCoords[tri->vertexIndex[0]]; + ps1mdl_texcoord_t *tc1 = &model.texCoords[tri->vertexIndex[1]]; + ps1mdl_texcoord_t *tc2 = &model.texCoords[tri->vertexIndex[2]]; // Use normal indices to generate a greyscale value. Good for just giving the polygons some gradients. unsigned int n0 = v0->normalIndex, n1 = v1->normalIndex, n2 = v2->normalIndex; @@ -298,7 +333,18 @@ void drawStuff(int counter) // Normally you'd have GTE do this but we're just going for a quick hack now unsigned short depth = ((unsigned short)v0->position[1] + (unsigned short)v1->position[1] + (unsigned short)v2->position[1]) / 3; - addColoredTriangle(v0->position[0], 240 - v0->position[2], v1->position[0], 240 - v1->position[2], v2->position[0], 240 - v2->position[2], rgb0, rgb1, rgb2, (unsigned char)depth); + // Since we have the texture split into two parts, we need to correct the UVs that are *not* on the seam, instead of the other way round + short u0 = !tri->frontFace && !tc0->onSeam ? tc0->u - (model.header->skinWidth >> 1) : tc0->u; + short u1 = !tri->frontFace && !tc1->onSeam ? tc1->u - (model.header->skinWidth >> 1) : tc1->u; + short u2 = !tri->frontFace && !tc2->onSeam ? tc2->u - (model.header->skinWidth >> 1) : tc2->u; + + addGouraudTexturedTriangle( + v0->position[0], 240 - v0->position[2], + v1->position[0], 240 - v1->position[2], + v2->position[0], 240 - v2->position[2], + (unsigned char)depth, + rgb0, rgb1, rgb2, + u0, tc0->v, u1, tc1->v, u2, tc2->v, tri->frontFace ? &playerFrontTex : &playerBackTex); } return; @@ -312,8 +358,8 @@ void drawStuff(int counter) addTile(128, 160, 48, 48, r, g, b); addColoredTriangle(260, 140, 220, 220, 300, 220, 0xFF0000, 0x00FF00, 0x0000FF, 0); - addTexturedTriangle(260, 40, 220, 120, 300, 120, 0, 94, 74, 124, 58, 1, &playerTex); - addTexturedSprite(20, 140, 80, 80, &playerTex); + addTexturedTriangle(260, 40, 220, 120, 300, 120, 0, 94, 74, 124, 58, 1, &playerFrontTex); + addTexturedSprite(20, 140, 80, 80, &playerFrontTex); addTexturedSprite(80, 40, 154, 114, &shamblerTex); } diff --git a/player.ps1mdl b/player.ps1mdl index 1feabe9..66890da 100644 Binary files a/player.ps1mdl and b/player.ps1mdl differ diff --git a/player.tim b/player.tim new file mode 100644 index 0000000..355ec5e Binary files /dev/null and b/player.tim differ diff --git a/player_b.tim b/player_b.tim new file mode 100644 index 0000000..0a1346d Binary files /dev/null and b/player_b.tim differ diff --git a/player_f.tim b/player_f.tim new file mode 100644 index 0000000..93181ae Binary files /dev/null and b/player_f.tim differ diff --git a/ps1mdl.h b/ps1mdl.h index 3ceb71e..ee87a83 100644 --- a/ps1mdl.h +++ b/ps1mdl.h @@ -10,19 +10,25 @@ typedef struct int ident; int version; + unsigned short skinWidth; + unsigned short skinHeight; + unsigned short vertexCount; unsigned short triangleCount; unsigned short frameCount; + + unsigned short pad; } ps1mdl_header_t; typedef struct { - char onSeam; + short onSeam; short u, v; } ps1mdl_texcoord_t; typedef struct { + short frontFace; unsigned short vertexIndex[3]; } ps1mdl_triangle_t; @@ -32,12 +38,12 @@ typedef struct unsigned char normalIndex; } ps1mdl_vertex_t; -typedef struct +typedef struct { - ps1mdl_header_t *header; - ps1mdl_texcoord_t *texCoords; - ps1mdl_triangle_t *triangles; - ps1mdl_vertex_t *vertices; + ps1mdl_header_t* header; + ps1mdl_texcoord_t* texCoords; + ps1mdl_triangle_t* triangles; + ps1mdl_vertex_t* vertices; } ps1mdl_t; #ifdef __cplusplus