From c3141f851b94e196a97576e4209e314285077a4e Mon Sep 17 00:00:00 2001 From: Timur Gagiev Date: Thu, 13 Aug 2020 22:23:09 +0300 Subject: [PATCH] GBA refactoring, optimizations --- src/platform/gba/OpenLara.vcxproj | 4 +- src/platform/gba/camera.h | 78 ++++ src/platform/gba/common.h | 42 +- src/platform/gba/level.h | 317 ++++++++++++++ src/platform/gba/main.cpp | 410 +----------------- .../{common.iwram.cpp => render.iwram.cpp} | 263 ++++++----- 6 files changed, 562 insertions(+), 552 deletions(-) create mode 100644 src/platform/gba/camera.h create mode 100644 src/platform/gba/level.h rename src/platform/gba/{common.iwram.cpp => render.iwram.cpp} (82%) diff --git a/src/platform/gba/OpenLara.vcxproj b/src/platform/gba/OpenLara.vcxproj index fca9492..24ee864 100644 --- a/src/platform/gba/OpenLara.vcxproj +++ b/src/platform/gba/OpenLara.vcxproj @@ -19,11 +19,13 @@ - + + + 15.0 diff --git a/src/platform/gba/camera.h b/src/platform/gba/camera.h new file mode 100644 index 0000000..bd47f12 --- /dev/null +++ b/src/platform/gba/camera.h @@ -0,0 +1,78 @@ +#ifndef H_CAMERA +#define H_CAMERA + +#include "common.h" + +uint16 camRotY = 16 << 8; + +int32 camSinY; +int32 camCosY; + +int32 camX = 75162; +int32 camY = 3072 - 1024; +int32 camZ = 5000; + +Rect clip; + +#ifdef _WIN32 + #define CAM_SPEED (1 << 2) + #define CAM_ROT_SPEED (1 << 2) +#else + #define CAM_SPEED (1 << 6) + #define CAM_ROT_SPEED (1 << 8) +#endif + +void updateCamera() { + if (keys[IK_LEFT]) camRotY -= CAM_ROT_SPEED; + if (keys[IK_RIGHT]) camRotY += CAM_ROT_SPEED; + + { + ALIGN4 ObjAffineSource src; + ALIGN4 ObjAffineDest dst; + + src.sX = 0x0100; + src.sY = 0x0100; + src.theta = camRotY; + + ObjAffineSet(&src, &dst, 1, 2); + + camCosY = dst.pd << 8; + camSinY = dst.pc << 8; + } + + int32 dx = camSinY; + int32 dz = camCosY; + + dx *= CAM_SPEED; + dz *= CAM_SPEED; + + dx >>= 16; + dz >>= 16; + + if (keys[IK_UP]) { + camX += int32(dx); + camZ += int32(dz); + } + + if (keys[IK_DOWN]) { + camX -= int32(dx); + camZ -= int32(dz); + } + + if (keys[IK_L]) { + camX -= int32(dz); + camZ += int32(dx); + } + + if (keys[IK_R]) { + camX += int32(dz); + camZ -= int32(dx); + } + + if (keys[IK_A]) camY -= CAM_SPEED; + if (keys[IK_B]) camY += CAM_SPEED; + + clip = { 0, 0, FRAME_WIDTH, FRAME_HEIGHT }; +} + +#endif \ No newline at end of file diff --git a/src/platform/gba/common.h b/src/platform/gba/common.h index da6c4ed..de6e0ee 100644 --- a/src/platform/gba/common.h +++ b/src/platform/gba/common.h @@ -38,7 +38,16 @@ #define PIXEL_SIZE 2 #endif -#define WND_SCALE 4 +#ifdef _WIN32 + #define INLINE inline + + #define MyDiv(Number, Divisor) ((Number) / (Divisor)) +#else + #define INLINE __attribute__((always_inline)) inline + + #define MyDiv(Number, Divisor) ((Number) / (Divisor)) + //#define MyDiv(Number, Divisor) Div(Number, Divisor) +#endif typedef signed char int8; typedef signed short int16; @@ -56,16 +65,6 @@ typedef int16 Index; #define RAD2DEG (180.0f / PI) #ifdef _WIN32 - extern uint8* LEVEL1_PHD; - - extern uint32 VRAM[WIDTH * HEIGHT]; - - #ifdef USE_MODE_5 - extern uint16 fb[WIDTH * HEIGHT]; - #else - extern uint8 fb[WIDTH * HEIGHT]; - #endif - #define IWRAM_CODE #define EWRAM_DATA @@ -99,8 +98,6 @@ typedef int16 Index; #else #define ALIGN4 __attribute__ ((aligned (4))) - - extern uint32 fb; #endif enum InputKey { @@ -225,7 +222,7 @@ struct Sprite { int16 l, t, r, b; }; -struct SpriteSequence { +struct SpriteSeq { uint16 type; uint16 unused; int16 sCount; @@ -240,9 +237,9 @@ struct Rect { }; struct Vertex { - int16 x, y; - int16 z; - uint8 u, v, g, clip; + int16 x, y, z; + uint8 g, clip; + uint8 u, v; }; struct Face { @@ -263,7 +260,16 @@ struct Face { #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) -void drawGlyph(int32 index, int32 x, int32 y); +void drawGlyph(const Sprite *sprite, int32 x, int32 y); +void drawNumber(int32 number, int32 x, int32 y); + void clear(); +void transform(int32 vx, int32 vy, int32 vz, int32 vg, int32 x, int32 y, int32 z); +void faceAddTriangle(uint16 flags, const Index* indices, int32 startVertex); +void faceAddQuad(uint16 flags, const Index* indices, int32 startVertex); +void flush(); +void initRender(); + +void readLevel(const uint8 *data); #endif \ No newline at end of file diff --git a/src/platform/gba/level.h b/src/platform/gba/level.h new file mode 100644 index 0000000..f1e3154 --- /dev/null +++ b/src/platform/gba/level.h @@ -0,0 +1,317 @@ +#ifndef H_LEVEL +#define H_LEVEL + +#include "common.h" +#include "camera.h" + +// level file data ------------------- +uint32 tilesCount; +const uint8* tiles[15]; + +#if defined(USE_MODE_5) || defined(_WIN32) + ALIGN4 uint16 palette[256]; +#endif + +ALIGN4 uint8 lightmap[256 * 32]; + +uint16 roomsCount; +const Room* rooms; + +uint32 texturesCount; +const Texture* textures; + +const Sprite* sprites; + +uint32 spritesSeqCount; +const SpriteSeq* spritesSeq; + +const uint8* meshData; +const uint32* meshOffsets; + +const int32* nodes; +const Model* models; +// ----------------------------------- + +struct RoomDesc { + int32 x, z; + uint16 vCount; + uint16 qCount; + uint16 tCount; + uint16 pCount; + const Room::Vertex* vertices; + const Quad* quads; + const Triangle* triangles; + const Room::Portal* portals; +}; + +EWRAM_DATA RoomDesc roomDescs[64]; + +#define SEQ_GLYPH_ID 190 +int32 seqGlyphs; + +extern uint32 gVerticesCount; + +void readLevel(const uint8 *data) { // TODO non-hardcode level loader + tilesCount = *((uint32*)(data + 4)); + for (uint32 i = 0; i < tilesCount; i++) { + tiles[i] = data + 8 + 256 * 256 * i; + } + + roomsCount = *((uint16*)(data + 720908)); + rooms = (Room*)(data + 720908 + 2); + + texturesCount = *((uint32*)(data + 1271686)); + textures = (Texture*)(data + 1271686 + 4); + + sprites = (Sprite*)(data + 1289634); + + spritesSeqCount = *((uint32*)(data + 1292130)); + spritesSeq = (SpriteSeq*)(data + 1292130 + 4); + + meshData = data + 908172 + 4; + meshOffsets = (uint32*)(data + 975724 + 4); + + nodes = (int32*)(data + 990318); + + models = (Model*)(data + 1270670); + +// prepare lightmap + const uint8* f_lightmap = data + 1320576; + memcpy(lightmap, f_lightmap, sizeof(lightmap)); + +// prepare palette +#if !(defined(USE_MODE_5) || defined(_WIN32)) + uint16 palette[256]; +#endif + const uint8* f_palette = data + 1328768; + + const uint8* p = f_palette; + + for (int i = 0; i < 256; i++) { + palette[i] = (p[0] >> 1) | ((p[1] >> 1) << 5) | ((p[2] >> 1) << 10); + p += 3; + } + +#ifndef _WIN32 + #ifndef USE_MODE_5 + SetPalette(palette); + #endif +#endif + +// prepare glyphs + for (uint32 i = 0; i < spritesSeqCount; i++) { + if (spritesSeq[i].type == SEQ_GLYPH_ID) { + seqGlyphs = i; + break; + } + } + +// prepare rooms + uint8 *ptr = (uint8*)rooms; + + for (uint16 roomIndex = 0; roomIndex < roomsCount; roomIndex++) { + const Room *room = (Room*)ptr; + ptr += sizeof(Room); + + uint32 dataSize; + memcpy(&dataSize, &room->dataSize, sizeof(dataSize)); + uint8* skipPtr = ptr + dataSize * 2; + + RoomDesc &desc = roomDescs[roomIndex]; + + // offset + memcpy(&desc.x, &room->info.x, sizeof(room->info.x)); + memcpy(&desc.z, &room->info.z, sizeof(room->info.z)); + + // vertices + desc.vCount = *((uint16*)ptr); + ptr += 2; + desc.vertices = (Room::Vertex*)ptr; + ptr += sizeof(Room::Vertex) * desc.vCount; + + // quads + desc.qCount = *((uint16*)ptr); + ptr += 2; + desc.quads = (Quad*)ptr; + ptr += sizeof(Quad) * desc.qCount; + + // triangles + desc.tCount = *((uint16*)ptr); + ptr += 2; + desc.triangles = (Triangle*)ptr; + ptr += sizeof(Triangle) * desc.tCount; + + ptr = skipPtr; + + // portals + desc.pCount = *((uint16*)ptr); + ptr += 2; + desc.portals = (Room::Portal*)ptr; + ptr += sizeof(Room::Portal) * desc.pCount; + + uint16 zSectors = *((uint16*)ptr); + ptr += 2; + uint16 xSectors = *((uint16*)ptr); + ptr += 2; + //sectors = (Room::Sector*)sectors; + ptr += sizeof(Room::Sector) * zSectors * xSectors; + + //ambient = *((uint16*)ptr); + ptr += 2; + + uint16 lightsCount = *((uint16*)ptr); + ptr += 2; + //lights = (Room::Light*)ptr; + ptr += sizeof(Room::Light) * lightsCount; + + uint16 meshesCount = *((uint16*)ptr); + ptr += 2; + //meshes = (Room::Mesh*)ptr; + ptr += sizeof(Room::Mesh) * meshesCount; + + ptr += 2 + 2; // skip alternateRoom and flags + } +} + +void drawRoom(int16 roomIndex) { + RoomDesc &room = roomDescs[roomIndex]; + + int32 dx = -camX + room.x; + int32 dy = -camY; + int32 dz = -camZ + room.z; + + int32 startVertex = gVerticesCount; + + const Room::Vertex* vertices = room.vertices; + for (uint16 i = 0; i < room.vCount; i++) { + const Room::Vertex &v = vertices[i]; + transform(v.x, v.y, v.z, v.lighting, dx, dy, dz); + } + + const Quad* quads = room.quads; + for (uint16 i = 0; i < room.qCount; i++) { + faceAddQuad(quads[i].flags, quads[i].indices, startVertex); + } + + const Triangle* triangles = room.triangles; + for (uint16 i = 0; i < room.tCount; i++) { + faceAddTriangle(triangles[i].flags, triangles[i].indices, startVertex); + } +} + +void drawMesh(int16 meshIndex, int32 x, int32 y, int32 z) { + uint32 offset = meshOffsets[meshIndex]; + const uint8* ptr = meshData + offset; + + ptr += 2 * 5; // skip [cx, cy, cz, radius, flags] + + int16 vCount = *(int16*)ptr; ptr += 2; + const int16* vertices = (int16*)ptr; + ptr += vCount * 3 * sizeof(int16); + + int16 nCount = *(int16*)ptr; ptr += 2; + //const int16* normals = (int16*)ptr; + if (nCount > 0) { // normals + ptr += nCount * 3 * sizeof(int16); + } else { // intensity + ptr += vCount * sizeof(int16); + } + + int16 rCount = *(int16*)ptr; ptr += 2; + Quad* rFaces = (Quad*)ptr; ptr += rCount * sizeof(Quad); + + int16 tCount = *(int16*)ptr; ptr += 2; + Triangle* tFaces = (Triangle*)ptr; ptr += tCount * sizeof(Triangle); + + int16 crCount = *(int16*)ptr; ptr += 2; + Quad* crFaces = (Quad*)ptr; ptr += crCount * sizeof(Quad); + + int16 ctCount = *(int16*)ptr; ptr += 2; + Triangle* ctFaces = (Triangle*)ptr; ptr += ctCount * sizeof(Triangle); + + int32 startVertex = gVerticesCount; + + int32 dx = x - camX; + int32 dy = y - camY; + int32 dz = z - camZ; + + const int16* v = vertices; + for (uint16 i = 0; i < vCount; i++) { + transform(v[0], v[1], v[2], 4096, dx, dy, dz); + v += 3; + } + + for (int i = 0; i < rCount; i++) { + faceAddQuad(rFaces[i].flags, rFaces[i].indices, startVertex); + } + + for (int i = 0; i < crCount; i++) { + faceAddQuad(crFaces[i].flags | FACE_COLORED, crFaces[i].indices, startVertex); + } + + for (int i = 0; i < tCount; i++) { + faceAddTriangle(tFaces[i].flags, tFaces[i].indices, startVertex); + } + + for (int i = 0; i < ctCount; i++) { + faceAddTriangle(ctFaces[i].flags | FACE_COLORED, ctFaces[i].indices, startVertex); + } +} + +void drawModel(int32 modelIndex, int32 x, int32 y, int32 z) { + const Model* model = models + modelIndex; + + // non-aligned access + uint32 node, frame; + memcpy(&node, &model->node, sizeof(node)); + memcpy(&frame, &model->frame, sizeof(frame)); + + Node bones[32]; + memcpy(bones, nodes + node, (model->mCount - 1) * sizeof(Node)); + + const Node* n = bones; + + struct StackItem { + int32 x, y, z; + } stack[4]; + StackItem *s = stack; + + drawMesh(model->mStart, x, y, z); + + for (int i = 1; i < model->mCount; i++) { + if (n->flags & 1) { + s--; + x = s->x; + y = s->y; + z = s->z; + } + + if (n->flags & 2) { + s->x = x; + s->y = y; + s->z = z; + s++; + } + + x += n->x; + y += n->y; + z += n->z; + n++; + + drawMesh(model->mStart + i, x, y, z); + } +} + +void drawNumber(int32 number, int32 x, int32 y) { + const int32 widths[] = { 12, 8, 10, 10, 10, 10, 10, 10, 10, 10 }; + + const Sprite *glyphSprites = sprites + spritesSeq[seqGlyphs].sStart; + + while (number > 0) { + x -= widths[number % 10]; + drawGlyph(glyphSprites + 52 + (number % 10), x, y); + number /= 10; + } +} + +#endif diff --git a/src/platform/gba/main.cpp b/src/platform/gba/main.cpp index 305a8fc..1ced7cf 100644 --- a/src/platform/gba/main.cpp +++ b/src/platform/gba/main.cpp @@ -12,397 +12,28 @@ #include "LEVEL1_PHD.h" #endif -#include "common.h" - //#define PROFILE -#if defined(USE_MODE_5) || defined(_WIN32) -extern uint16 palette[256]; -#endif - -extern uint8 lightmap[256 * 32]; - -extern Vertex gVertices[MAX_VERTICES]; -extern uint32 gVerticesCount; - -extern Face gFaces[MAX_FACES]; -extern int32 gFacesCount; - -extern Rect clip; - -extern const uint8* tiles[15]; - -extern const uint8* curTile; -uint32 tilesCount; - -extern int32 fps; - -uint16 camRotY = 16 << 8; - -extern int32 camSinY; -extern int32 camCosY; - -extern int32 camX; -extern int32 camY; -extern int32 camZ; - -extern uint16 roomsCount; -extern const Room* rooms; - -extern uint32 texturesCount; -extern const Texture* textures; - -extern const Sprite* sprites; - -extern uint32 spriteSequencesCount; -extern const SpriteSequence* spriteSequences; - -extern int32 seqGlyphs; - -extern const uint8* meshData; -extern const uint32* meshOffsets; - -extern const int32* nodes; -extern const Model* models; - -extern void transform(int32 vx, int32 vy, int32 vz, int32 vg, int32 x, int32 y, int32 z); -extern void faceAddTriangle(uint16 flags, const Index* indices, int32 startVertex); -extern void faceAddQuad(uint16 flags, const Index* indices, int32 startVertex); -extern void flush(); -extern void initRender(); - -void drawRoom(int16 roomIndex) { - const Room *room = rooms; - - //Room::Portal *portals; - uint16 portalsCount; - - //Room::Sector* sectors; - uint16 zSectors, xSectors; - - //uint16 ambient; - - //Room::Light* lights; - uint16 lightsCount; - - //Room::Mesh* meshes; - uint16 meshesCount; - - uint8 *ptr = (uint8*)room; - - while (roomIndex--) { - uint32 dataSize; - memcpy(&dataSize, &room->dataSize, sizeof(dataSize)); - ptr += sizeof(Room) + dataSize * 2; - - portalsCount = *((uint16*)ptr); - ptr += 2; - //portals = (Room::Portal*)ptr; - ptr += sizeof(Room::Portal) * portalsCount; - - zSectors = *((uint16*)ptr); - ptr += 2; - xSectors = *((uint16*)ptr); - ptr += 2; - //sectors = (Room::Sector*)sectors; - ptr += sizeof(Room::Sector) * zSectors * xSectors; - - //ambient = *((uint16*)ptr); - ptr += 2; - - lightsCount = *((uint16*)ptr); - ptr += 2; - //lights = (Room::Light*)ptr; - ptr += sizeof(Room::Light) * lightsCount; - - meshesCount = *((uint16*)ptr); - ptr += 2; - //meshes = (Room::Mesh*)ptr; - ptr += sizeof(Room::Mesh) * meshesCount; - - ptr += 2 + 2; // skip alternateRoom and flags - - room = (Room*)ptr; - } - - ptr += sizeof(Room); - - uint16 vCount = *((uint16*)ptr); - ptr += 2; - Room::Vertex* vertices = (Room::Vertex*)ptr; - ptr += sizeof(Room::Vertex) * vCount; - - // non-aligned data - int32 roomX; - int32 roomZ; - memcpy(&roomX, &room->info.x, sizeof(roomX)); - memcpy(&roomZ, &room->info.z, sizeof(roomZ)); - - int32 dx = -camX + roomX; - int32 dy = -camY; - int32 dz = -camZ + roomZ; - - int32 startVertex = gVerticesCount; - - for (uint16 i = 0; i < vCount; i++) { - const Room::Vertex &v = vertices[i]; - transform(v.x, v.y, v.z, v.lighting, dx, dy, dz); - } - - uint16 qCount = *((uint16*)ptr); - ptr += 2; - Quad* quads = (Quad*)ptr; - ptr += sizeof(Quad) * qCount; - - for (uint16 i = 0; i < qCount; i++) { - faceAddQuad(quads[i].flags, quads[i].indices, startVertex); - } - - uint16 tCount = *((uint16*)ptr); - ptr += 2; - Triangle* triangles = (Triangle*)ptr; - ptr += sizeof(Triangle) * tCount; - - for (uint16 i = 0; i < tCount; i++) { - faceAddTriangle(triangles[i].flags, triangles[i].indices, startVertex); - } -} - -void drawMesh(int16 meshIndex, int32 x, int32 y, int32 z) { - uint32 offset = meshOffsets[meshIndex]; - const uint8* ptr = meshData + offset; - - //int16 cx = *(int16*)ptr; ptr += 2; - //int16 cy = *(int16*)ptr; ptr += 2; - //int16 cz = *(int16*)ptr; ptr += 2; - //int16 r = *(int16*)ptr; ptr += 2; - //ptr += 2; // skip flags - ptr += 2 * 5; - - int16 vCount = *(int16*)ptr; ptr += 2; - const int16* vertices = (int16*)ptr; - ptr += vCount * 3 * sizeof(int16); - - int16 nCount = *(int16*)ptr; ptr += 2; - //const int16* normals = (int16*)ptr; - if (nCount > 0) { // normals - ptr += nCount * 3 * sizeof(int16); - } else { // intensity - ptr += vCount * sizeof(int16); - } - - int16 rCount = *(int16*)ptr; ptr += 2; - Quad* rFaces = (Quad*)ptr; ptr += rCount * sizeof(Quad); - - int16 tCount = *(int16*)ptr; ptr += 2; - Triangle* tFaces = (Triangle*)ptr; ptr += tCount * sizeof(Triangle); - - int16 crCount = *(int16*)ptr; ptr += 2; - Quad* crFaces = (Quad*)ptr; ptr += crCount * sizeof(Quad); - - int16 ctCount = *(int16*)ptr; ptr += 2; - Triangle* ctFaces = (Triangle*)ptr; ptr += ctCount * sizeof(Triangle); - - int32 startVertex = gVerticesCount; - - int32 dx = x - camX; - int32 dy = y - camY; - int32 dz = z - camZ; - - const int16* v = vertices; - for (uint16 i = 0; i < vCount; i++) { - transform(v[0], v[1], v[2], 4096, dx, dy, dz); - v += 3; - } - - for (int i = 0; i < rCount; i++) { - faceAddQuad(rFaces[i].flags, rFaces[i].indices, startVertex); - } - - for (int i = 0; i < crCount; i++) { - faceAddQuad(crFaces[i].flags | FACE_COLORED, crFaces[i].indices, startVertex); - } - - for (int i = 0; i < tCount; i++) { - faceAddTriangle(tFaces[i].flags, tFaces[i].indices, startVertex); - } - - for (int i = 0; i < ctCount; i++) { - faceAddTriangle(ctFaces[i].flags | FACE_COLORED, ctFaces[i].indices, startVertex); - } -} - -void drawModel(int32 modelIndex, int32 x, int32 y, int32 z) { - const Model* model = models + modelIndex; - - // non-aligned access - uint32 node, frame; - memcpy(&node, &model->node, sizeof(node)); - memcpy(&frame, &model->frame, sizeof(frame)); - - Node bones[32]; - memcpy(bones, nodes + node, (model->mCount - 1) * sizeof(Node)); - - const Node* n = bones; - - struct StackItem { - int32 x, y, z; - } stack[4]; - StackItem *s = stack; - - drawMesh(model->mStart, x, y, z); - - for (int i = 1; i < model->mCount; i++) { - if (n->flags & 1) { - s--; - x = s->x; - y = s->y; - z = s->z; - } - - if (n->flags & 2) { - s->x = x; - s->y = y; - s->z = z; - s++; - } - - x += n->x; - y += n->y; - z += n->z; - n++; - - drawMesh(model->mStart + i, x, y, z); - } -} - -void readLevel(const uint8 *data) { - tilesCount = *((uint32*)(data + 4)); - for (uint32 i = 0; i < tilesCount; i++) { - tiles[i] = data + 8 + 256 * 256 * i; - } - - roomsCount = *((uint16*)(data + 720908)); - rooms = (Room*)(data + 720908 + 2); - - texturesCount = *((uint32*)(data + 1271686)); - textures = (Texture*)(data + 1271686 + 4); - - sprites = (Sprite*)(data + 1289634); - - spriteSequencesCount = *((uint32*)(data + 1292130)); - spriteSequences = (SpriteSequence*)(data + 1292130 + 4); - - for (uint32 i = 0; i < spriteSequencesCount; i++) { - if (spriteSequences[i].type == 190) { - seqGlyphs = i; - break; - } - } - - meshData = data + 908172 + 4; - meshOffsets = (uint32*)(data + 975724 + 4); - - nodes = (int32*)(data + 990318); - - models = (Model*)(data + 1270670); - - const uint8* f_lightmap = data + 1320576; - memcpy(lightmap, f_lightmap, sizeof(lightmap)); - -#if !(defined(USE_MODE_5) || defined(_WIN32)) - uint16 palette[256]; -#endif - - const uint8* f_palette = data + 1328768; - - const uint8* p = f_palette; - - for (int i = 0; i < 256; i++) { - palette[i] = (p[0] >> 1) | ((p[1] >> 1) << 5) | ((p[2] >> 1) << 10); - p += 3; - } - -#ifndef _WIN32 - palette[1] = RGB8(0, 255, 0); - - #ifndef USE_MODE_5 - SetPalette(palette); - #endif -#endif -} +#include "common.h" +#include "level.h" #ifdef _WIN32 - #define CAM_SPEED (1 << 3) - #define CAM_ROT_SPEED (1 << 3) + uint8* LEVEL1_PHD; + + uint32 SCREEN[WIDTH * HEIGHT]; + + extern uint8 fb[WIDTH * HEIGHT * 2]; + + #define WND_SCALE 4 #else - #define CAM_SPEED (1 << 6) - #define CAM_ROT_SPEED (1 << 8) + extern uint32 fb; #endif +bool keys[IK_MAX] = {}; -void updateCamera() { - if (keys[IK_LEFT]) camRotY -= CAM_ROT_SPEED; - if (keys[IK_RIGHT]) camRotY += CAM_ROT_SPEED; - - { - ALIGN4 ObjAffineSource src; - ALIGN4 ObjAffineDest dst; - - src.sX = 0x0100; - src.sY = 0x0100; - src.theta = camRotY; - - ObjAffineSet(&src, &dst, 1, 2); - - camCosY = dst.pd << 8; - camSinY = dst.pc << 8; - } - - int32 dx = camSinY; - int32 dz = camCosY; - - dx *= CAM_SPEED; - dz *= CAM_SPEED; - - dx >>= 16; - dz >>= 16; - - if (keys[IK_UP]) { - camX += int32(dx); - camZ += int32(dz); - } - - if (keys[IK_DOWN]) { - camX -= int32(dx); - camZ -= int32(dz); - } - - if (keys[IK_L]) { - camX -= int32(dz); - camZ += int32(dx); - } - - if (keys[IK_R]) { - camX += int32(dz); - camZ -= int32(dx); - } - - if (keys[IK_A]) camY -= CAM_SPEED; - if (keys[IK_B]) camY += CAM_SPEED; - - clip = { 0, 0, FRAME_WIDTH, FRAME_HEIGHT }; -} - -void drawNumber(int32 number, int32 x, int32 y) { - const int32 widths[] = { 12, 8, 10, 10, 10, 10, 10, 10, 10, 10 }; - - while (number > 0) { - x -= widths[number % 10]; - drawGlyph(52 + (number % 10), x, y); - number /= 10; - } -} +int32 fps; +int32 frameIndex = 0; +int32 fpsCounter = 0; void update(int32 frames) { for (int32 i = 0; i < frames; i++) { @@ -429,18 +60,18 @@ HDC hDC; void VBlankIntrWait() { #ifdef USE_MODE_5 for (int i = 0; i < WIDTH * HEIGHT; i++) { - uint16 c = fb[i]; - VRAM[i] = (((c << 3) & 0xFF) << 16) | ((((c >> 5) << 3) & 0xFF) << 8) | ((c >> 10 << 3) & 0xFF) | 0xFF000000; + uint16 c = ((uint16*)fb)[i]; + SCREEN[i] = (((c << 3) & 0xFF) << 16) | ((((c >> 5) << 3) & 0xFF) << 8) | ((c >> 10 << 3) & 0xFF) | 0xFF000000; } #else for (int i = 0; i < WIDTH * HEIGHT; i++) { - uint16 c = palette[fb[i]]; - VRAM[i] = (((c << 3) & 0xFF) << 16) | ((((c >> 5) << 3) & 0xFF) << 8) | ((c >> 10 << 3) & 0xFF) | 0xFF000000; + uint16 c = palette[((uint8*)fb)[i]]; + SCREEN[i] = (((c << 3) & 0xFF) << 16) | ((((c >> 5) << 3) & 0xFF) << 8) | ((c >> 10 << 3) & 0xFF) | 0xFF000000; } #endif const BITMAPINFO bmi = { sizeof(BITMAPINFOHEADER), WIDTH, -HEIGHT, 1, 32, BI_RGB, 0, 0, 0, 0, 0 }; - StretchDIBits(hDC, 0, 0, 240 * WND_SCALE, 160 * WND_SCALE, 0, 0, WIDTH, HEIGHT, VRAM, &bmi, DIB_RGB_COLORS, SRCCOPY); + StretchDIBits(hDC, 0, 0, 240 * WND_SCALE, 160 * WND_SCALE, 0, 0, WIDTH, HEIGHT, SCREEN, &bmi, DIB_RGB_COLORS, SRCCOPY); } LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -473,9 +104,6 @@ LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { } #endif -int32 frameIndex = 0; -int32 fpsCounter = 0; - void vblank() { frameIndex++; } diff --git a/src/platform/gba/common.iwram.cpp b/src/platform/gba/render.iwram.cpp similarity index 82% rename from src/platform/gba/common.iwram.cpp rename to src/platform/gba/render.iwram.cpp index 8b33a6e..b632d0e 100644 --- a/src/platform/gba/common.iwram.cpp +++ b/src/platform/gba/render.iwram.cpp @@ -5,87 +5,36 @@ uint16 divTable[DIV_TABLE_SIZE]; #ifdef _WIN32 - uint8* LEVEL1_PHD; - - uint32 VRAM[WIDTH * HEIGHT]; - - #ifdef USE_MODE_5 - uint16 fb[WIDTH * HEIGHT]; - #else - uint8 fb[WIDTH * HEIGHT]; - #endif - - #define MyDiv(Number, Divisor) ((Number) / (Divisor)) + uint8 fb[WIDTH * HEIGHT * 2]; #else uint32 fb = VRAM; - - #define MyDiv(Number, Divisor) ((Number) / (Divisor)) - //#define MyDiv(Number, Divisor) Div(Number, Divisor) #endif #define FixedInvS(x) ((x < 0) ? -divTable[abs(x)] : divTable[x]) #define FixedInvU(x) divTable[x] -bool keys[IK_MAX] = {}; - #if defined(USE_MODE_5) || defined(_WIN32) -uint16 palette[256]; + extern uint16 palette[256]; #endif -uint8 lightmap[256 * 32]; +extern uint8 lightmap[256 * 32]; +extern const uint8* tiles[15]; +extern const Texture* textures; + +extern Rect clip; +extern int32 camSinY; +extern int32 camCosY; -Vertex gVertices[MAX_VERTICES]; uint32 gVerticesCount = 0; +EWRAM_DATA Vertex gVertices[MAX_VERTICES]; -EWRAM_DATA Face gFaces[MAX_FACES]; int32 gFacesCount = 0; - -Rect clip; - -const uint8* tiles[15]; +Face gFaces[MAX_FACES]; +Face* gFacesSorted[MAX_FACES]; const uint8* curTile; - uint16 mipMask; -int32 fps; - -int32 camSinY; -int32 camCosY; - -int32 camX = 75162; -int32 camY = 3072 - 1024; -int32 camZ = 5000; - -Vertex* Ledges[4]; -Vertex* Redges[4]; -int32 Lindex, Rindex; - -uint16 roomsCount; -const Room* rooms; - -uint32 texturesCount; -const Texture* textures; - -const Sprite* sprites; - -uint32 spriteSequencesCount; -const SpriteSequence* spriteSequences; - -int32 seqGlyphs; - -const uint8* meshData; -const uint32* meshOffsets; - -const int32* nodes; -const Model* models; - -#ifdef WIN32 - #define INLINE inline -#else - #define INLINE __attribute__((always_inline)) inline -#endif - int32 clamp(int32 x, int32 a, int32 b) { return x < a ? a : (x > b ? b : x); } @@ -261,6 +210,24 @@ struct Edge { return true; } + + void build(int32 start, int32 count, int32 t, int32 b, int32 incr) { + vert[index = 0] = gVertices + start + b; + + for (int i = 1; i < count; i++) { + b = (b + incr) % count; + + Vertex *v = gVertices + start + b; + + if (vert[index]->x != v->x || vert[index]->y != v->y) { + vert[++index] = v; + } + + if (b == t) { + break; + } + } + } }; INLINE void scanlineG(uint16* buffer, int32 x1, int32 x2, uint8 palIndex, uint32 g, int32 dgdx) { @@ -317,6 +284,8 @@ INLINE void scanlineG(uint16* buffer, int32 x1, int32 x2, uint8 palIndex, uint32 *(uint16*)pixel = p; pixel += 1; } + + if (p == 0xFFFFFFFF) return; } if (x2 & 1) @@ -388,6 +357,8 @@ INLINE void scanlineGT(uint16* buffer, int32 x1, int32 x2, uint32 g, uint32 t, i *(uint16*)pixel = p; pixel += 1; } + + if (p == 0xFFFFFFFF) return; } if (x2 & 1) @@ -565,7 +536,6 @@ void drawTriangle(uint16 flags, int32 start, const int8* indices) void drawQuad(uint16 flags, int32 start, const int8* indices) { Vertex *v1, *v2, *v3, *v4; - bool clipped = indices[0] == indices[1]; if (clipped) { @@ -587,14 +557,14 @@ void drawQuad(uint16 flags, int32 start, const int8* indices) { palIndex = 0xFFFF; curTile = tiles[tex.tile]; if (!clipped) { - v1->u = int32(tex.x0); - v1->v = int32(tex.y0); - v2->u = int32(tex.x1); - v2->v = int32(tex.y1); - v3->u = int32(tex.x2); - v3->v = int32(tex.y2); - v4->u = int32(tex.x3); - v4->v = int32(tex.y3); + v1->u = tex.x0; + v1->v = tex.y0; + v2->u = tex.x1; + v2->v = tex.y1; + v3->u = tex.x2; + v3->v = tex.y2; + v4->u = tex.x3; + v4->v = tex.y3; } } @@ -687,28 +657,9 @@ void drawPoly(uint16 flags, int32 start, int32 count) { } Edge L, R; - L.vert[L.index = 0] = gVertices + start + b; - R.vert[R.index = 0] = gVertices + start + b; - for (int i = 0; i < count; i++) { - int32 idx = (b + count + i) % count; - - L.vert[++L.index] = gVertices + start + idx; - - if (idx == t) { - break; - } - } - - for (int i = 0; i < count; i++) { - int32 idx = (b + count - i) % count; - - R.vert[++R.index] = gVertices + start + idx; - - if (idx == t) { - break; - } - } + L.build(start, count, t, b, count + 1); + R.build(start, count, t, b, count - 1); Vertex *v1 = gVertices + start + t; @@ -719,9 +670,7 @@ void drawPoly(uint16 flags, int32 start, int32 count) { } } -void drawGlyph(int32 index, int32 x, int32 y) { - const Sprite* sprite = sprites + spriteSequences[seqGlyphs].sStart + index; - +void drawGlyph(const Sprite *sprite, int32 x, int32 y) { int32 w = sprite->r - sprite->l; int32 h = sprite->b - sprite->t; @@ -730,12 +679,25 @@ void drawGlyph(int32 index, int32 x, int32 y) { int32 ix = x + sprite->l; int32 iy = y + sprite->t; - uint16* ptr = (uint16*)fb + iy * (WIDTH / PIXEL_SIZE) + (ix >> 1); + uint16* ptr = (uint16*)fb + iy * (WIDTH / PIXEL_SIZE); + +#ifdef USE_MODE_5 + ptr += ix; +#else + ptr += ix >> 1; +#endif const uint8* glyphData = tiles[sprite->tile] + 256 * sprite->v + sprite->u; while (h--) { + #ifdef USE_MODE_5 + for (int i = 0; i < w; i++) { + if (glyphData[i] == 0) continue; + + ptr[i] = palette[glyphData[i]]; + } + #else const uint8* p = glyphData; for (int i = 0; i < (w / 2); i++) { @@ -751,14 +713,14 @@ void drawGlyph(int32 index, int32 x, int32 y) { p += 2; } + #endif ptr += WIDTH / PIXEL_SIZE; glyphData += 256; } } -void faceAddPolyClip(uint16 flags, Vertex** poly, int32 pCount) -{ +void faceAddPolyClip(uint16 flags, Vertex** poly, int32 pCount) { #define LERP(a,b,t) (b + ((a - b) * t >> 16)) #define CLIP_AXIS(x, y, edge, output) {\ @@ -798,15 +760,15 @@ void faceAddPolyClip(uint16 flags, Vertex** poly, int32 pCount) if (!(flags & FACE_COLORED)) { const Texture &tex = textures[flags & FACE_TEXTURE]; curTile = tiles[tex.tile]; - poly[0]->u = int32(tex.x0); - poly[0]->v = int32(tex.y0); - poly[1]->u = int32(tex.x1); - poly[1]->v = int32(tex.y1); - poly[2]->u = int32(tex.x2); - poly[2]->v = int32(tex.y2); + poly[0]->u = tex.x0; + poly[0]->v = tex.y0; + poly[1]->u = tex.x1; + poly[1]->v = tex.y1; + poly[2]->u = tex.x2; + poly[2]->v = tex.y2; if (pCount == 4) { - poly[3]->u = int32(tex.x3); - poly[3]->v = int32(tex.y3); + poly[3]->u = tex.x3; + poly[3]->v = tex.y3; } } @@ -828,23 +790,24 @@ void faceAddPolyClip(uint16 flags, Vertex** poly, int32 pCount) int32 y1 = clip.y1; CLIP_VERTEX(y, x, y0, y1, &tmp, output); - Face &f = gFaces[gFacesCount++]; - f.flags = flags; - f.start = gVerticesCount; - f.indices[0] = count; - f.indices[1] = count; - /* + Face *f = gFaces + gFacesCount; + gFacesSorted[gFacesCount++] = f; + f->flags = flags; + f->start = gVerticesCount; + f->indices[0] = count; + f->indices[1] = count; + if (count == 3) { - f.flags |= FACE_TRIANGLE; - f.depth = (output[0].z + output[1].z + output[2].z) / 3; + f->flags |= FACE_TRIANGLE; + f->depth = (output[0].z + output[1].z + output[2].z) / 3; } else if (count == 4) { - f.depth = (output[0].z + output[1].z + output[2].z + output[3].z) >> 2; - } else*/ { + f->depth = (output[0].z + output[1].z + output[2].z + output[3].z) >> 2; + } else { int32 depth = output[0].z; for (int32 i = 1; i < count; i++) { depth = (depth + output[i].z) >> 1; } - f.depth = depth; + f->depth = depth; } gVerticesCount += count; @@ -874,14 +837,15 @@ void faceAddQuad(uint16 flags, const Index* indices, int32 startVertex) { Vertex* poly[4] = { v1, v2, v3, v4 }; faceAddPolyClip(flags, poly, 4); } else { - Face &f = gFaces[gFacesCount++]; - f.flags = flags; - f.depth = (v1->z + v2->z + v3->z + v4->z) >> 2; - f.start = startVertex + indices[0]; - f.indices[0] = 0; - f.indices[1] = indices[1] - indices[0]; - f.indices[2] = indices[2] - indices[0]; - f.indices[3] = indices[3] - indices[0]; + Face *f = gFaces + gFacesCount; + gFacesSorted[gFacesCount++] = f; + f->flags = flags; + f->depth = (v1->z + v2->z + v3->z + v4->z) >> 2; + f->start = startVertex + indices[0]; + f->indices[0] = 0; + f->indices[1] = indices[1] - indices[0]; + f->indices[2] = indices[2] - indices[0]; + f->indices[3] = indices[3] - indices[0]; } } @@ -908,41 +872,56 @@ void faceAddTriangle(uint16 flags, const Index* indices, int32 startVertex) { Vertex* poly[3] = { v1, v2, v3 }; faceAddPolyClip(flags, poly, 3); } else { - Face &f = gFaces[gFacesCount++]; - f.flags = flags | FACE_TRIANGLE; - f.depth = (v1->z + v2->z + v3->z) / 3; - f.start = startVertex + indices[0]; - f.indices[0] = 0; - f.indices[1] = indices[1] - indices[0]; - f.indices[2] = indices[2] - indices[0]; + Face *f = gFaces + gFacesCount; + gFacesSorted[gFacesCount++] = f; + f->flags = flags | FACE_TRIANGLE; + f->depth = (v1->z + v2->z + v3->z) / 3; + f->start = startVertex + indices[0]; + f->indices[0] = 0; + f->indices[1] = indices[1] - indices[0]; + f->indices[2] = indices[2] - indices[0]; } } -int faceCmp(const void *a, const void *b) { - return ((Face*)b)->depth - ((Face*)a)->depth; +void faceSort(Face** faces, int32 L, int32 R) { + int32 i = L; + int32 j = R; + int16 depth = faces[(i + j) >> 1]->depth; + + while (i <= j) { + while (faces[i]->depth > depth) i++; + while (faces[j]->depth < depth) j--; + + if (i <= j) { + swap(faces[i++], faces[j--]); + } + }; + + if (L < j) faceSort(faces, L, j); + if (R > i) faceSort(faces, i, R); } //int32 gFacesCountMax, gVerticesCountMax; void flush() { if (gFacesCount) { - qsort(gFaces, gFacesCount, sizeof(Face), faceCmp); + faceSort(gFacesSorted, 0, gFacesCount - 1); //const uint16 mips[] = { 0xFFFF, 0xFEFE, 0xFCFC, 0xF8F8 }; for (int32 i = 0; i < gFacesCount; i++) { - const Face &f = gFaces[i]; + const Face *f = gFacesSorted[i]; // TODO //mipMask = mips[MIN(3, f.depth / 2048)]; - if (f.flags & FACE_TRIANGLE) { - drawTriangle(f.flags, f.start, f.indices); + if (f->flags & FACE_TRIANGLE) { + drawTriangle(f->flags, f->start, f->indices); } else { - if (f.indices[0] == f.indices[1] /* && f.indices[0] > 4 */) { - drawPoly(f.flags, f.start, f.indices[0]); + if (f->indices[0] == f->indices[1] /* && f.indices[0] > 4 */) { + drawPoly(f->flags, f->start, f->indices[0]); } else { - drawQuad(f.flags, f.start, f.indices); + drawQuad(f->flags, f->start, f->indices); } } }