1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-04 20:27:39 +02:00

GBA precise UVs, reduce buffers size

This commit is contained in:
Timur Gagiev
2020-08-23 07:11:11 +03:00
parent 20678ce60c
commit 1b1cef1490
5 changed files with 159 additions and 73 deletions

View File

@@ -24,6 +24,7 @@
//#define USE_MODE_5 //#define USE_MODE_5
//#define DEBUG_OVERDRAW //#define DEBUG_OVERDRAW
//#define DEBUG_FACES
#define SCALE 1 #define SCALE 1
@@ -223,10 +224,10 @@ struct EntityDesc { // 32 bytes
struct Texture { struct Texture {
uint16 attribute; uint16 attribute;
uint16 tile:14, :2; uint16 tile:14, :2;
uint8 xh0, x0, yh0, y0; uint32 uv0;
uint8 xh1, x1, yh1, y1; uint32 uv1;
uint8 xh2, x2, yh2, y2; uint32 uv2;
uint8 xh3, x3, yh3, y3; uint32 uv3;
}; };
struct Sprite { struct Sprite {
@@ -253,7 +254,7 @@ struct Rect {
struct Vertex { struct Vertex {
int16 x, y, z; int16 x, y, z;
uint8 g, clip; uint8 g, clip;
uint8 u, v; uint32 uv;
}; };
struct Face { struct Face {
@@ -269,8 +270,8 @@ struct Face {
#define MAX_MATRICES 8 #define MAX_MATRICES 8
#define MAX_MODELS 64 #define MAX_MODELS 64
#define MAX_ENTITY 190 #define MAX_ENTITY 190
#define MAX_VERTICES 1024 #define MAX_VERTICES 850
#define MAX_FACES 384 #define MAX_FACES 220
#define FOG_SHIFT 2 #define FOG_SHIFT 2
#define FOG_MAX (10 * 1024) #define FOG_MAX (10 * 1024)
#define FOG_MIN (FOG_MAX - (8192 >> FOG_SHIFT)) #define FOG_MIN (FOG_MAX - (8192 >> FOG_SHIFT))

Binary file not shown.

View File

@@ -6,20 +6,20 @@
// level file data ------------------- // level file data -------------------
uint32 tilesCount; uint32 tilesCount;
const uint8* tiles[15]; extern const uint8* tiles[15];
#if defined(USE_MODE_5) || defined(_WIN32) #if defined(USE_MODE_5) || defined(_WIN32)
ALIGN4 uint16 palette[256]; ALIGN4 uint16 palette[256];
#endif #endif
ALIGN4 uint8 lightmap[256 * 32]; extern uint8 lightmap[256 * 32];
uint16 roomsCount; uint16 roomsCount;
const uint16* floors; const uint16* floors;
uint32 texturesCount; uint32 texturesCount;
const Texture* textures; extern const Texture* textures;
const Sprite* sprites; const Sprite* sprites;
@@ -85,45 +85,48 @@ int32 entityLara;
extern uint32 gVerticesCount; extern uint32 gVerticesCount;
extern Rect clip; extern Rect clip;
void readLevel(const uint8 *data) { // TODO non-hardcode level loader void readLevel(const uint8 *data) { // TODO non-hardcode level loader, added *_OFF alignment bytes
tilesCount = *((uint32*)(data + 4)); tilesCount = *((uint32*)(data + 4));
for (uint32 i = 0; i < tilesCount; i++) { for (uint32 i = 0; i < tilesCount; i++) {
tiles[i] = data + 8 + 256 * 256 * i; tiles[i] = data + 8 + 256 * 256 * i;
} }
#define MDL_OFF 2
#define ENT_OFF 2
roomsCount = *((uint16*)(data + 720908)); roomsCount = *((uint16*)(data + 720908));
const Room* roomsPtr = (Room*)(data + 720908 + 2); const Room* roomsPtr = (Room*)(data + 720908 + 2);
floors = (uint16*)(data + 899492 + 4); floors = (uint16*)(data + 899492 + 4);
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; meshData = data + 908172 + 4;
meshOffsets = (uint32*)(data + 975724 + 4); meshOffsets = (uint32*)(data + 975724 + 4);
nodes = (int32*)(data + 990318); nodes = (int32*)(data + 990318);
modelsCount = *((uint32*)(data + 1270666)); modelsCount = *((uint32*)(data + 1270666 + MDL_OFF));
const uint8* modelsPtr = (uint8*)(data + 1270666 + 4); const uint8* modelsPtr = (uint8*)(data + 1270666 + 4 + MDL_OFF);
entitiesCount = *((uint32*)(data + 1319252)); texturesCount = *((uint32*)(data + 1271686 + MDL_OFF));
entities = (Entity*)(data + 1319252 + 4); textures = (Texture*)(data + 1271686 + 4 + MDL_OFF);
sprites = (Sprite*)(data + 1289634 + MDL_OFF);
spritesSeqCount = *((uint32*)(data + 1292130 + MDL_OFF));
spritesSeq = (SpriteSeq*)(data + 1292130 + 4 + MDL_OFF);
entitiesCount = *((uint32*)(data + 1319252 + MDL_OFF + ENT_OFF));
entities = (Entity*)(data + 1319252 + 4 + MDL_OFF + ENT_OFF);
// prepare lightmap // prepare lightmap
const uint8* f_lightmap = data + 1320576; const uint8* f_lightmap = data + 1320576 + MDL_OFF + ENT_OFF;
memcpy(lightmap, f_lightmap, sizeof(lightmap)); memcpy(lightmap, f_lightmap, sizeof(lightmap));
// prepare palette // prepare palette
#if !(defined(USE_MODE_5) || defined(_WIN32)) #if !(defined(USE_MODE_5) || defined(_WIN32))
uint16 palette[256]; uint16 palette[256];
#endif #endif
const uint8* f_palette = data + 1328768; const uint8* f_palette = data + 1328768 + MDL_OFF + ENT_OFF;
const uint8* p = f_palette; const uint8* p = f_palette;

View File

@@ -42,10 +42,87 @@ void update(int32 frames) {
} }
} }
#ifdef WIN32
extern Vertex gVertices[MAX_VERTICES];
INLINE int32 classify(const Vertex* v) {
return (v->x < clip.x0 ? 1 : 0) |
(v->x > clip.x1 ? 2 : 0) |
(v->y < clip.y0 ? 4 : 0) |
(v->y > clip.y1 ? 8 : 0);
}
void drawTest() {
static Rect testClip = { 0, 0, FRAME_WIDTH, FRAME_HEIGHT };
static int32 testTile = 707; // 712
int dx = 0;
int dy = 0;
if (GetAsyncKeyState(VK_LEFT)) dx--;
if (GetAsyncKeyState(VK_RIGHT)) dx++;
if (GetAsyncKeyState(VK_UP)) dy--;
if (GetAsyncKeyState(VK_DOWN)) dy++;
if (GetAsyncKeyState('T')) {
testClip.x0 += dx;
testClip.y0 += dy;
}
if (GetAsyncKeyState('B')) {
testClip.x1 += dx;
testClip.y1 += dy;
}
if (GetAsyncKeyState('U')) {
testTile += dx;
if (testTile < 0) testTile = 0;
if (testTile >= texturesCount) testTile = texturesCount - 1;
}
clip = testClip;
gVertices[0].x = 50 + 50;
gVertices[0].y = 50;
gVertices[1].x = FRAME_WIDTH - 50 - 50;
gVertices[1].y = 50;
gVertices[2].x = FRAME_WIDTH - 50;
gVertices[2].y = FRAME_HEIGHT - 50;
gVertices[3].x = 50;
gVertices[3].y = FRAME_HEIGHT - 50;
for (int i = 0; i < 4; i++) {
gVertices[i].z = 100;
gVertices[i].g = 128;
gVertices[i].clip = classify(gVertices + i);
}
gVerticesCount = 4;
Index indices[] = { 0, 1, 2, 3, 0, 2, 3 };
faceAddQuad(testTile, indices, 0);
for (int y = 0; y < FRAME_HEIGHT; y++) {
for (int x = 0; x < FRAME_WIDTH; x++) {
if (x == clip.x0 || x == clip.x1 - 1 || y == clip.y0 || y == clip.y1 - 1)
fb[y * FRAME_WIDTH + x] = 255;
}
}
flush();
Sleep(16);
}
#endif
void render() { void render() {
clear(); clear();
drawRooms(); drawRooms();
//drawTest();
drawNumber(fps, FRAME_WIDTH, 16); drawNumber(fps, FRAME_WIDTH, 16);
} }
@@ -112,7 +189,7 @@ void vblank() {
int main(void) { int main(void) {
#ifdef _WIN32 #ifdef _WIN32
{ {
FILE *f = fopen("C:/Projects/TR/TR1_ANDROID/LEVEL1.PHD", "rb"); FILE *f = fopen("data/LEVEL1.PHD", "rb");
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
int32 size = ftell(f); int32 size = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);

View File

@@ -17,9 +17,11 @@ uint16 divTable[DIV_TABLE_SIZE];
extern uint16 palette[256]; extern uint16 palette[256];
#endif #endif
extern uint8 lightmap[256 * 32]; uint8 lightmap[256 * 32];
extern const uint8* tiles[15];
extern const Texture* textures; const uint8* tiles[15];
const Texture* textures;
uint32 gVerticesCount = 0; uint32 gVerticesCount = 0;
Vertex gVertices[MAX_VERTICES]; Vertex gVertices[MAX_VERTICES];
@@ -33,7 +35,6 @@ uint16 mipMask;
Rect clip; Rect clip;
const int16 sin_table[] = { // 1025 const int16 sin_table[] = { // 1025
0x0000, 0x0019, 0x0032, 0x004B, 0x0065, 0x007E, 0x0097, 0x00B0, 0x0000, 0x0019, 0x0032, 0x004B, 0x0065, 0x007E, 0x0097, 0x00B0,
0x00C9, 0x00E2, 0x00FB, 0x0114, 0x012E, 0x0147, 0x0160, 0x0179, 0x00C9, 0x00E2, 0x00FB, 0x0114, 0x012E, 0x0147, 0x0160, 0x0179,
@@ -275,8 +276,7 @@ INLINE void swap(T &a, T &b) {
} }
INLINE bool checkBackface(const Vertex *a, const Vertex *b, const Vertex *c) { INLINE bool checkBackface(const Vertex *a, const Vertex *b, const Vertex *c) {
return (b->x - a->x) * (c->y - a->y) - return (b->x - a->x) * (c->y - a->y) <= (c->x - a->x) * (b->y - a->y);
(c->x - a->x) * (b->y - a->y) <= 0;
} }
INLINE void sortVertices(Vertex *&t, Vertex *&m, Vertex *&b) { INLINE void sortVertices(Vertex *&t, Vertex *&m, Vertex *&b) {
@@ -334,14 +334,25 @@ void transform(const vec3s &v, int32 vg) {
res.g = vg >> 8; res.g = vg >> 8;
z >>= FOV_SHIFT; z >>= FOV_SHIFT;
x = (x / z) + (FRAME_WIDTH / 2);
y = (y / z) + (FRAME_HEIGHT / 2); #if 0
x >>= 12;
y >>= 12;
z >>= 12;
uint32 iz = FixedInvU(z);
x = (x * iz) >> 16;
y = (y * iz) >> 16;
#else
x = (x / z);
y = (y / z);
#endif
//x = clamp(x, -0x7FFF, 0x7FFF); //x = clamp(x, -0x7FFF, 0x7FFF);
//y = clamp(y, -0x7FFF, 0x7FFF); //y = clamp(y, -0x7FFF, 0x7FFF);
res.x = x; res.x = x + (FRAME_WIDTH / 2);
res.y = y; res.y = y + (FRAME_HEIGHT / 2);
res.z = fogZ; res.z = fogZ;
res.clip = classify(&res); res.clip = classify(&res);
} }
@@ -416,7 +427,7 @@ struct Edge {
h = v2->y - v1->y; h = v2->y - v1->y;
x = v1->x << 16; x = v1->x << 16;
g = v1->g << 16; g = v1->g << 16;
t = (v1->u << 24) | (v1->v << 8); t = (v1->uv >> 16) | (v1->uv << 16); // TODO preprocess
if (h > 1) { if (h > 1) {
uint32 d = FixedInvU(h); uint32 d = FixedInvU(h);
@@ -424,10 +435,10 @@ struct Edge {
dx = d * (v2->x - v1->x); dx = d * (v2->x - v1->x);
dg = d * (v2->g - v1->g); dg = d * (v2->g - v1->g);
int32 du = d * (v2->u - v1->u); int32 du = d * ((v2->uv & 0xFFFF) - (v1->uv & 0xFFFF));
int32 dv = d * (v2->v - v1->v); int32 dv = d * ((v2->uv >> 16) - (v1->uv >> 16));
dt = ((du << 8) & 0xFFFF0000) | int16(dv >> 8); dt = (du & 0xFFFF0000) | int16(dv >> 16);
} }
return true; return true;
@@ -708,12 +719,9 @@ void drawTriangle(const Face* face) {
palIndex = 0xFFFF; palIndex = 0xFFFF;
curTile = tiles[tex.tile]; curTile = tiles[tex.tile];
if (!clipped) { if (!clipped) {
v1->u = tex.x0; v1->uv = tex.uv0;
v1->v = tex.y0; v2->uv = tex.uv1;
v2->u = tex.x1; v3->uv = tex.uv2;
v2->v = tex.y1;
v3->u = tex.x2;
v3->v = tex.y2;
} }
} }
@@ -779,15 +787,12 @@ void drawQuad(const Face* face) {
const Texture &tex = textures[palIndex]; const Texture &tex = textures[palIndex];
palIndex = 0xFFFF; palIndex = 0xFFFF;
curTile = tiles[tex.tile]; curTile = tiles[tex.tile];
if (!clipped) { if (!clipped) {
v1->u = tex.x0; v1->uv = tex.uv0;
v1->v = tex.y0; v2->uv = tex.uv1;
v2->u = tex.x1; v3->uv = tex.uv2;
v2->v = tex.y1; v4->uv = tex.uv3;
v3->u = tex.x2;
v3->v = tex.y2;
v4->u = tex.x3;
v4->v = tex.y3;
} }
} }
@@ -930,7 +935,7 @@ void drawGlyph(const Sprite *sprite, int32 x, int32 y) {
} }
void faceAddPolyClip(uint16 flags, Vertex** poly, int32 pCount, int32 depth) { void faceAddPolyClip(uint16 flags, Vertex** poly, int32 pCount, int32 depth) {
#define LERP(a,b,t) (b + ((a - b) * t >> 16)) #define LERP(a,b,t) ((b) + (((a) - (b)) * t >> 16))
#define CLIP_AXIS(X, Y, edge, output) {\ #define CLIP_AXIS(X, Y, edge, output) {\
uint32 t = ((edge - b->X) << 16) / (a->X - b->X);\ uint32 t = ((edge - b->X) << 16) / (a->X - b->X);\
@@ -938,8 +943,7 @@ void faceAddPolyClip(uint16 flags, Vertex** poly, int32 pCount, int32 depth) {
v->X = edge;\ v->X = edge;\
v->Y = LERP(a->Y, b->Y, t);\ v->Y = LERP(a->Y, b->Y, t);\
v->z = LERP(a->z, b->z, t);\ v->z = LERP(a->z, b->z, t);\
v->u = LERP(a->u, b->u, t);\ v->uv = (LERP(a->uv & 0xFFFF, b->uv & 0xFFFF, t)) | (LERP(a->uv >> 16, b->uv >> 16, t) << 16);\
v->v = LERP(a->v, b->v, t);\
v->g = LERP(a->g, b->g, t);\ v->g = LERP(a->g, b->g, t);\
} }
@@ -969,15 +973,11 @@ void faceAddPolyClip(uint16 flags, Vertex** poly, int32 pCount, int32 depth) {
if (!(flags & FACE_COLORED)) { if (!(flags & FACE_COLORED)) {
const Texture &tex = textures[flags & FACE_TEXTURE]; const Texture &tex = textures[flags & FACE_TEXTURE];
curTile = tiles[tex.tile]; curTile = tiles[tex.tile];
poly[0]->u = tex.x0; poly[0]->uv = tex.uv0;
poly[0]->v = tex.y0; poly[1]->uv = tex.uv1;
poly[1]->u = tex.x1; poly[2]->uv = tex.uv2;
poly[1]->v = tex.y1;
poly[2]->u = tex.x2;
poly[2]->v = tex.y2;
if (pCount == 4) { if (pCount == 4) {
poly[3]->u = tex.x3; poly[3]->uv = tex.uv3;
poly[3]->v = tex.y3;
} }
} }
@@ -1103,7 +1103,9 @@ void faceSort(Face** faces, int32 L, int32 R) {
if (R > i) faceSort(faces, i, R); if (R > i) faceSort(faces, i, R);
} }
//int32 gFacesCountMax, gVerticesCountMax; #ifdef DEBUG_FACES
int32 gFacesCountMax, gVerticesCountMax;
#endif
void flush() { void flush() {
if (gFacesCount) { if (gFacesCount) {
@@ -1129,17 +1131,20 @@ void flush() {
} }
} }
//if (gFacesCount > gFacesCountMax) gFacesCountMax = gFacesCount; #ifdef DEBUG_FACES
//if (gVerticesCount > gVerticesCountMax) gVerticesCountMax = gVerticesCount; if (gFacesCount > gFacesCountMax) gFacesCountMax = gFacesCount;
//printf("%d %d\n", gFacesCountMax, gVerticesCountMax); if (gVerticesCount > gVerticesCountMax) gVerticesCountMax = gVerticesCount;
printf("%d %d\n", gFacesCountMax, gVerticesCountMax);
#endif
gVerticesCount = 0; gVerticesCount = 0;
gFacesCount = 0; gFacesCount = 0;
} }
void initRender() { void initRender() {
divTable[0] = 0; divTable[0] = 0xFFFF;
for (uint32 i = 1; i < DIV_TABLE_SIZE; i++) { divTable[1] = 0xFFFF;
for (uint32 i = 2; i < DIV_TABLE_SIZE; i++) {
divTable[i] = (1 << 16) / i; divTable[i] = (1 << 16) / i;
} }
} }