1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-10 07:06:52 +02:00

GBA refactoring, optimizations

This commit is contained in:
Timur Gagiev
2020-08-13 22:23:09 +03:00
parent e7ffb928bf
commit c3141f851b
6 changed files with 562 additions and 552 deletions

View File

@@ -19,11 +19,13 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="common.iwram.cpp" />
<ClCompile Include="render.iwram.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="camera.h" />
<ClInclude Include="common.h" />
<ClInclude Include="level.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>

78
src/platform/gba/camera.h Normal file
View File

@@ -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

View File

@@ -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

317
src/platform/gba/level.h Normal file
View File

@@ -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

View File

@@ -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++;
}

View File

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