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);
}
}
}