1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-13 16:44:50 +02:00

GBA objects and animations, remove MODE4 code

This commit is contained in:
XProger
2021-02-22 14:18:48 +03:00
parent 5690d64901
commit 310e8c9dc0
6 changed files with 913 additions and 866 deletions

View File

@@ -3,8 +3,8 @@
#include "common.h" #include "common.h"
#define CAM_SPEED (1 << 2) #define CAM_SPEED (1 << 3)
#define CAM_ROT_SPEED (1 << 8) #define CAM_ROT_SPEED (1 << 9)
#define CAM_ROT_X_MAX int16(85 * 0x8000 / 180) #define CAM_ROT_X_MAX int16(85 * 0x8000 / 180)
struct Camera { struct Camera {
@@ -19,6 +19,9 @@ struct Camera {
rotX = 0; rotX = 0;
rotY = 16 << 8; rotY = 16 << 8;
//rotX = -0x1000;
//rotY = int16(0x8000);
} }
void update() { void update() {
@@ -29,7 +32,7 @@ struct Camera {
rotX = clamp(rotX, -CAM_ROT_X_MAX, CAM_ROT_X_MAX); rotX = clamp(rotX, -CAM_ROT_X_MAX, CAM_ROT_X_MAX);
matrixSetView(pos, rotX, rotY); matrixSetView(pos.x, pos.y, pos.z, rotX, rotY);
Matrix &m = matrixGet(); Matrix &m = matrixGet();
@@ -57,7 +60,7 @@ struct Camera {
pos.z -= m[2].z * CAM_SPEED >> 10; pos.z -= m[2].z * CAM_SPEED >> 10;
} }
room = getRoomIndex(room, pos); room = getRoomIndex(room, &pos);
} }
}; };

View File

@@ -1,9 +1,9 @@
#include "common.h" #include "common.h"
vec3i viewPos; uint16 divTable[DIV_TABLE_SIZE]; // IWRAM 0.5 kb
vec3i viewPos;
extern Matrix matrixStack[MAX_MATRICES]; Matrix matrixStack[MAX_MATRICES];
extern int32 matrixStackIndex; int32 matrixStackIndex = 0;
const int16 sin_table[1025] = { // IWRAM 2 kb const int16 sin_table[1025] = { // IWRAM 2 kb
0x0000, 0x0019, 0x0032, 0x004B, 0x0065, 0x007E, 0x0097, 0x00B0, 0x0000, 0x0019, 0x0032, 0x004B, 0x0065, 0x007E, 0x0097, 0x00B0,
@@ -160,76 +160,171 @@ int32 clamp(int32 x, int32 a, int32 b) {
return x < a ? a : (x > b ? b : x); return x < a ? a : (x > b ? b : x);
} }
Matrix& matrixGet() { void initLUT() {
divTable[0] = 0xFFFF;
divTable[1] = 0xFFFF;
for (uint32 i = 2; i < DIV_TABLE_SIZE; i++) {
divTable[i] = (1 << 16) / i;
}
}
Matrix& matrixGet()
{
return matrixStack[matrixStackIndex]; return matrixStack[matrixStackIndex];
} }
void matrixPush() { void matrixPush()
#if defined(_WIN32) {
if (matrixStackIndex >= MAX_MATRICES - 1) { ASSERT(matrixStackIndex < MAX_MATRICES - 1);
DebugBreak();
return;
}
#endif
Matrix &a = matrixStack[matrixStackIndex++]; Matrix &a = matrixStack[matrixStackIndex++];
Matrix &b = matrixStack[matrixStackIndex]; Matrix &b = matrixStack[matrixStackIndex];
memcpy(b, a, sizeof(Matrix)); memcpy(b, a, sizeof(Matrix));
} }
void matrixPop() { void matrixPop()
#if defined(_WIN32) {
if (matrixStackIndex <= 0) { ASSERT(matrixStackIndex > 0);
DebugBreak();
return;
}
#endif
matrixStackIndex--; matrixStackIndex--;
} }
void matrixTranslate(const vec3i &offset) { void matrixTranslate(int32 x, int32 y, int32 z)
{
Matrix &m = matrixGet(); Matrix &m = matrixGet();
m[0].w += DP33(m[0], offset); vec3i offset(x, y, z);
m[1].w += DP33(m[1], offset); m[0][3] += DP33(m[0], offset);
m[2].w += DP33(m[2], offset); m[1][3] += DP33(m[1], offset);
m[2][3] += DP33(m[2], offset);
} }
void matrixTranslateAbs(const vec3i &offset) { void matrixTranslateAbs(int32 x, int32 y, int32 z)
{
vec3i d; vec3i d;
d.x = offset.x - viewPos.x; d.x = x - viewPos.x;
d.y = offset.y - viewPos.y; d.y = y - viewPos.y;
d.z = offset.z - viewPos.z; d.z = z - viewPos.z;
Matrix &m = matrixGet(); Matrix &m = matrixGet();
m[0].w = DP33(m[0], d); m[0][3] = DP33(m[0], d);
m[1].w = DP33(m[1], d); m[1][3] = DP33(m[1], d);
m[2].w = DP33(m[2], d); m[2][3] = DP33(m[2], d);
} }
void matrixRotate(int16 rotX, int16 rotY, int16 rotZ) {} void matrixRotateX(int32 angle)
{
int32 s = phd_sin(angle);
int32 c = phd_cos(angle);
void matrixSetView(const vec3i &pos, int16 rotX, int16 rotY) { Matrix &m = matrixGet();
int32 sx = phd_sin(rotX); int32 a, b;
int32 cx = phd_cos(rotX);
int32 sy = phd_sin(rotY); a = c * m[0][1] + s * m[0][2];
int32 cy = phd_cos(rotY); b = c * m[0][2] - s * m[0][1];
m[0][1] = a >> FIXED_SHIFT;
m[0][2] = b >> FIXED_SHIFT;
a = c * m[1][1] + s * m[1][2];
b = c * m[1][2] - s * m[1][1];
m[1][1] = a >> FIXED_SHIFT;
m[1][2] = b >> FIXED_SHIFT;
a = c * m[2][1] + s * m[2][2];
b = c * m[2][2] - s * m[2][1];
m[2][1] = a >> FIXED_SHIFT;
m[2][2] = b >> FIXED_SHIFT;
}
void matrixRotateY(int32 angle)
{
int32 s = phd_sin(angle);
int32 c = phd_cos(angle);
Matrix &m = matrixGet();
int32 a, b;
a = c * m[0][0] - s * m[0][2];
b = c * m[0][2] + s * m[0][0];
m[0][0] = a >> FIXED_SHIFT;
m[0][2] = b >> FIXED_SHIFT;
a = c * m[1][0] - s * m[1][2];
b = c * m[1][2] + s * m[1][0];
m[1][0] = a >> FIXED_SHIFT;
m[1][2] = b >> FIXED_SHIFT;
a = c * m[2][0] - s * m[2][2];
b = c * m[2][2] + s * m[2][0];
m[2][0] = a >> FIXED_SHIFT;
m[2][2] = b >> FIXED_SHIFT;
}
void matrixRotateZ(int32 angle)
{
int32 s = phd_sin(angle);
int32 c = phd_cos(angle);
Matrix &m = matrixGet();
int32 a, b;
a = c * m[0][0] + s * m[0][1];
b = c * m[0][1] - s * m[0][0];
m[0][0] = a >> FIXED_SHIFT;
m[0][1] = b >> FIXED_SHIFT;
a = c * m[1][0] + s * m[1][1];
b = c * m[1][1] - s * m[1][0];
m[1][0] = a >> FIXED_SHIFT;
m[1][1] = b >> FIXED_SHIFT;
a = c * m[2][0] + s * m[2][1];
b = c * m[2][1] - s * m[2][0];
m[2][0] = a >> FIXED_SHIFT;
m[2][1] = b >> FIXED_SHIFT;
}
void matrixRotateYXZ(int32 angleX, int32 angleY, int32 angleZ)
{
if (angleY) matrixRotateY(angleY);
if (angleX) matrixRotateX(angleX);
if (angleZ) matrixRotateZ(angleZ);
}
void matrixFrame(int32 x, int32 y, int32 z, uint16* angles)
{
int32 angleX = (angles[1] & 0x3FF0) << 2;
int32 angleY = (angles[1] & 0x000F) << 12 | (angles[0] & 0xFC00) >> 4;
int32 angleZ = (angles[0] & 0x03FF) << 6;
matrixTranslate(x, y, z);
matrixRotateYXZ(angleX, angleY, angleZ);
}
void matrixSetView(int32 x, int32 y, int32 z, int32 angleX, int32 angleY)
{
int32 sx = phd_sin(angleX);
int32 cx = phd_cos(angleX);
int32 sy = phd_sin(angleY);
int32 cy = phd_cos(angleY);
Matrix &m = matrixGet(); Matrix &m = matrixGet();
m[0].x = cy; m[0][0] = cy;
m[0].y = 0; m[0][1] = 0;
m[0].z = -sy; m[0][2] = -sy;
m[0].w = pos.x; m[0][3] = x;
m[1].x = (sx * sy) >> FIXED_SHIFT; m[1][0] = (sx * sy) >> FIXED_SHIFT;
m[1].y = cx; m[1][1] = cx;
m[1].z = (sx * cy) >> FIXED_SHIFT; m[1][2] = (sx * cy) >> FIXED_SHIFT;
m[1].w = pos.y; m[1][3] = y;
m[2].x = (cx * sy) >> FIXED_SHIFT; m[2][0] = (cx * sy) >> FIXED_SHIFT;
m[2].y = -sx; m[2][1] = -sx;
m[2].z = (cx * cy) >> FIXED_SHIFT; m[2][2] = (cx * cy) >> FIXED_SHIFT;
m[2].w = pos.z; m[2][3] = z;
viewPos = pos; viewPos.x = x;
viewPos.y = y;
viewPos.z = z;
} }

View File

@@ -22,47 +22,25 @@
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <assert.h> #include <limits.h>
//#define DEBUG_OVERDRAW //#define DEBUG_OVERDRAW
//#define DEBUG_FACES //#define DEBUG_FACES
//#define USE_MODE_5 1
#define USE_MODE_4 1
#define SCALE 1
#if defined(__TNS__) #if defined(__TNS__)
#define WIDTH SCREEN_WIDTH #define WIDTH SCREEN_WIDTH
#define HEIGHT SCREEN_HEIGHT #define HEIGHT SCREEN_HEIGHT
#define FRAME_WIDTH (WIDTH/SCALE) #define FRAME_WIDTH WIDTH
#define FRAME_HEIGHT (HEIGHT/SCALE) #define FRAME_HEIGHT HEIGHT
#define FOV_SHIFT 8 #define FOV_SHIFT 8
#else #else
#ifdef USE_MODE_5 #define WIDTH 160
#define WIDTH 160 #define HEIGHT 128
#define HEIGHT 128 #define FRAME_WIDTH 160
#define FRAME_WIDTH 160 #define FRAME_HEIGHT 128
#define FRAME_HEIGHT 128 #define FOV_SHIFT 7
#define FOV_SHIFT 7
#elif USE_MODE_4
#define WIDTH 240
#define HEIGHT 160
#define FRAME_WIDTH (WIDTH/SCALE)
#define FRAME_HEIGHT (HEIGHT/SCALE)
#define FOV_SHIFT 7
#else
#error
#endif
#endif
#ifdef USE_MODE_5
#define PIXEL_SIZE 1
#else
#define PIXEL_SIZE 2
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
@@ -116,6 +94,12 @@ typedef int16 Index;
#define ALIGN4 __attribute__((aligned(4))) #define ALIGN4 __attribute__((aligned(4)))
#endif #endif
#if defined(_WIN32)
#define ASSERT(x) { if (!(x)) { DebugBreak(); } }
#else
#define ASSERT(x)
#endif
#ifdef PROFILE #ifdef PROFILE
#if defined(_WIN32) #if defined(_WIN32)
@@ -189,6 +173,11 @@ struct vec3s {
struct vec4i { struct vec4i {
int32 x, y, z, w; int32 x, y, z, w;
INLINE int32& operator [] (int32 index) const {
ASSERT(index >= 0 && index <= 3);
return ((int32*)this)[index];
}
}; };
typedef vec4i Matrix[3]; typedef vec4i Matrix[3];
@@ -203,12 +192,16 @@ struct Triangle {
uint16 flags; uint16 flags;
}; };
struct Room { struct Box {
struct Info { int16 minX;
int32 x, z; int16 maxX;
int32 yBottom, yTop; int16 minY;
}; int16 maxY;
int16 minZ;
int16 maxZ;
};
struct RoomInfo {
struct Vertex { struct Vertex {
vec3s pos; vec3s pos;
uint16 lighting; uint16 lighting;
@@ -242,14 +235,17 @@ struct Room {
}; };
struct Mesh { struct Mesh {
// int32 x, y, z; int16 pos[6]; // TODO align struct (int32 x, y, z)
// uint16 rotation; int16 rotation;
// uint16 intensity; uint16 intensity;
// uint16 meshID; uint16 staticMeshId;
uint8 dummy[18];
}; };
Info info; int32 x;
int32 z;
int32 yBottom;
int32 yTop;
uint32 dataSize; uint32 dataSize;
/* /*
uint16 vCount; uint16 vCount;
@@ -275,39 +271,89 @@ struct Model {
uint32 type; uint32 type;
uint16 mCount; uint16 mCount;
uint16 mStart; uint16 mStart;
uint32 node; uint32 nodeIndex;
uint32 frame; uint32 frameIndex;
uint16 animation; uint16 animIndex;
uint16 paddding; uint16 _padding;
}; };
#define FILE_MODEL_SIZE (sizeof(Model) - 2) // -padding #define FILE_MODEL_SIZE (sizeof(Model) - 2) // -padding
struct Entity { struct StaticMesh {
uint16 type; int32 id;
uint16 room; uint16 meshIndex;
vec3i pos; Box vbox;
int16 rotation; Box cbox;
uint16 flags; uint16 flags;
}; };
struct EntityDesc { // 32 bytes struct ItemInfo { // 24
uint16 type; uint16 type;
uint16 flags; int16 room;
vec3i pos; vec3i pos;
int16 angleY;
uint16 intensity;
vec3s rot; union {
uint8 state; struct {
uint8 targetState; uint16 gravity:1; // TODO
};
uint16 value;
} flags;
uint8 vSpeed; uint16 _padding;
uint8 hSpeed; };
uint8 room;
uint8 modelIndex; #define FILE_ITEM_SIZE (sizeof(ItemInfo) - 2)
struct Item : ItemInfo { // 24 + 20 = 44
int16 angleX;
int16 angleZ;
uint16 vSpeed;
uint16 hSpeed;
uint16 animIndex; uint16 animIndex;
uint16 frameIndex; uint16 frameIndex;
uint8 state;
uint8 nextState;
uint8 goalState;
uint8 timer;
uint16 health;
uint8 nextItem;
uint8 nextActive;
};
struct Anim {
uint32 frameOffset;
uint8 frameRate;
uint8 frameSize;
uint16 state;
int32 speed;
int32 accel;
uint16 frameBegin;
uint16 frameEnd;
uint16 nextAnimIndex;
uint16 nextFrameIndex;
uint16 scCount;
uint16 scOffset;
uint16 acCount;
uint16 animCommand;
};
struct Frame {
Box box;
vec3s pos;
uint16 angles[1];
}; };
struct Texture { struct Texture {
@@ -352,7 +398,7 @@ union UV {
struct VertexUV { struct VertexUV {
Vertex v; Vertex v;
UV t; UV t;
}; };
struct Face { struct Face {
@@ -371,12 +417,19 @@ struct Face {
extern uint32 dbg_poly_count; extern uint32 dbg_poly_count;
#endif #endif
#define DIV_TABLE_SIZE 256
#define FixedInvS(x) ((x < 0) ? -divTable[abs(x)] : divTable[x])
#define FixedInvU(x) divTable[x]
extern uint16 divTable[DIV_TABLE_SIZE];
#define FIXED_SHIFT 14 #define FIXED_SHIFT 14
#define MAX_MATRICES 8 #define MAX_MATRICES 8
#define MAX_MODELS 64 #define MAX_MODELS 64
#define MAX_ENTITY 190 #define MAX_ITEMS 256
#define MAX_VERTICES 1024 #define MAX_MESHES 50
#define MAX_VERTICES 2048
#define MAX_FACES 512 #define MAX_FACES 512
#define FOG_SHIFT 1 #define FOG_SHIFT 1
#define FOG_MAX (10 * 1024) #define FOG_MAX (10 * 1024)
@@ -390,6 +443,10 @@ struct Face {
#define FACE_FLAT 0x1000 #define FACE_FLAT 0x1000
#define FACE_TEXTURE 0x0FFF #define FACE_TEXTURE 0x0FFF
#define NO_ROOM 0xFF
#define NO_ITEM 0xFF
#define NO_MODEL 0xFF
#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b))
#define SQR(x) ((x) * (x)) #define SQR(x) ((x) * (x))
@@ -397,31 +454,47 @@ struct Face {
#define DP43(a,b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z + (a).w) #define DP43(a,b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z + (a).w)
#define DP33(a,b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z) #define DP33(a,b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z)
#define ITEM_LARA 0
#define ITEM_WOLF 7
#define ITEM_BEAR 8
#define ITEM_BAT 9
#define ITEM_CRYSTAL 83
extern vec3i viewPos;
extern Matrix matrixStack[MAX_MATRICES];
extern int32 matrixStackIndex;
int32 clamp(int32 x, int32 a, int32 b); int32 clamp(int32 x, int32 a, int32 b);
int32 phd_sin(int32 x); int32 phd_sin(int32 x);
int32 phd_cos(int32 x); int32 phd_cos(int32 x);
void initLUT();
Matrix& matrixGet(); Matrix& matrixGet();
void matrixPush(); void matrixPush();
void matrixPop(); void matrixPop();
void matrixTranslate(const vec3i &offset); void matrixTranslate(int32 x, int32 y, int32 z);
void matrixTranslateAbs(const vec3i &offset); void matrixTranslateAbs(int32 x, int32 y, int32 z);
void matrixRotate(int16 rotX, int16 rotY, int16 rotZ); void matrixRotateX(int32 angle);
void matrixSetView(const vec3i &pos, int16 rotX, int16 rotY); void matrixRotateY(int32 angle);
void matrixRotateZ(int32 angle);
void matrixRotateYXZ(int32 angleX, int32 angleY, int32 angleZ);
void matrixFrame(int32 x, int32 y, int32 z, uint16* angles);
void matrixSetView(int32 x, int32 y, int32 z, int32 angleX, int32 angleY);
void drawGlyph(const Sprite *sprite, int32 x, int32 y); void drawGlyph(const Sprite *sprite, int32 x, int32 y);
void clear(); void clear();
void transform_room(const Room::Vertex* vertices, int32 vCount); bool boxIsVisible(const Box* box);
void transform_mesh(const vec3s* vertices, int32 vCount); void transformRoom(const RoomInfo::Vertex* vertices, int32 vCount);
void faceAdd_room(const Quad* quads, int32 qCount, const Triangle* triangles, int32 tCount, int32 startVertex); void transformMesh(const vec3s* vertices, int32 vCount, uint16 intensity);
void faceAdd_mesh(const Quad* rFaces, const Quad* crFaces, const Triangle* tFaces, const Triangle* ctFaces, int32 rCount, int32 crCount, int32 tCount, int32 ctCount, int32 startVertex); void faceAddRoom(const Quad* quads, int32 qCount, const Triangle* triangles, int32 tCount, int32 startVertex);
void faceAddMesh(const Quad* rFaces, const Quad* crFaces, const Triangle* tFaces, const Triangle* ctFaces, int32 rCount, int32 crCount, int32 tCount, int32 ctCount, int32 startVertex);
void flush(); void flush();
void initRender();
void readLevel(const uint8 *data); void readLevel(const uint8 *data);
const Room::Sector* getSector(int32 roomIndex, int32 x, int32 z); const RoomInfo::Sector* getSector(int32 roomIndex, int32 x, int32 z);
int32 getRoomIndex(int32 roomIndex, const vec3i &pos); int32 getRoomIndex(int32 roomIndex, const vec3i* pos);
#endif #endif

View File

@@ -4,72 +4,82 @@
#include "common.h" #include "common.h"
#include "camera.h" #include "camera.h"
#define GRAVITY 6
// level file data ------------------- // level file data -------------------
uint32 tilesCount; int32 tilesCount;
extern const uint8* tiles; extern const uint8* tiles;
#if defined(USE_MODE_5) || defined(_WIN32) extern uint16 palette[256];
extern uint16 palette[256];
#endif
extern uint8 lightmap[256 * 32]; extern uint8 lightmap[256 * 32];
uint16 roomsCount;
const uint16* floors; const uint16* floors;
uint32 texturesCount; int32 texturesCount;
extern const Texture* textures; extern const Texture* textures;
const Sprite* sprites; const Sprite* sprites;
uint32 spritesSeqCount; int32 spritesSeqCount;
const SpriteSeq* spritesSeq; const SpriteSeq* spritesSeq;
const uint8* meshData; const uint8* meshData;
const uint32* meshOffsets; const int32* meshOffsets;
const int32* nodes; const int32* nodesPtr;
uint32 modelsCount; int32 animsCount;
const Anim* anims;
int32 framesCount;
const uint16* frames;
int32 modelsCount;
EWRAM_DATA Model models[MAX_MODELS]; EWRAM_DATA Model models[MAX_MODELS];
EWRAM_DATA int16 modelsMap[MAX_ENTITY]; EWRAM_DATA uint8 modelsMap[MAX_ITEMS];
EWRAM_DATA uint8 staticMeshesMap[MAX_MESHES];
uint32 entitiesCount; int32 staticMeshesCount;
const Entity* entities; const StaticMesh* staticMeshes;
int32 itemsCount;
EWRAM_DATA Item items[MAX_ITEMS];
// ----------------------------------- // -----------------------------------
struct RoomDesc { struct Room {
Rect clip; Rect clip;
uint8 firstItem;
bool visible; bool visible;
// TODO leave in ROM
int32 x, z; int32 x, z;
uint16 vCount; uint16 vCount;
uint16 qCount; uint16 qCount;
uint16 tCount; uint16 tCount;
uint16 pCount; uint16 pCount;
uint16 lCount;
uint16 mCount;
uint16 zSectors; uint16 zSectors;
uint16 xSectors; uint16 xSectors;
const Room::Vertex* vertices; uint16 ambient;
const Quad* quads;
const Triangle* triangles;
const Room::Portal* portals;
const Room::Sector* sectors;
INLINE void reset() { const RoomInfo::Vertex* vertices;
visible = false; const Quad* quads;
clip = { FRAME_WIDTH, FRAME_HEIGHT, 0, 0 }; const Triangle* triangles;
} const RoomInfo::Portal* portals;
const RoomInfo::Sector* sectors;
const RoomInfo::Light* lights;
const RoomInfo::Mesh* meshes;
}; };
EWRAM_DATA RoomDesc rooms[64]; int16 roomsCount;
EWRAM_DATA Room rooms[64];
int32 firstActive = NO_ITEM;
int32 visRoomsCount; int32 visRoomsCount;
int32 visRooms[16]; int32 visRooms[16];
#define ROOM_VISIBLE (1 << 15) #define ROOM_VISIBLE (1 << 15)
#define ENTITY_LARA 0
#define SEQ_GLYPH 190 #define SEQ_GLYPH 190
enum FloorType { enum FloorType {
@@ -80,51 +90,145 @@ enum FloorType {
}; };
int32 seqGlyphs; int32 seqGlyphs;
int32 entityLara;
extern uint32 gVerticesCount; extern uint32 gVerticesCount;
extern Rect clip; extern Rect clip;
void roomReset(int32 roomIndex)
{
Room* room = rooms + roomIndex;
room->visible = false;
room->clip = { FRAME_WIDTH, FRAME_HEIGHT, 0, 0 };
}
void roomItemAdd(int32 roomIndex, int32 itemIndex)
{
ASSERT(items[itemIndex].nextItem == NO_ITEM);
Room* room = rooms + roomIndex;
items[itemIndex].nextItem = room->firstItem;
room->firstItem = itemIndex;
}
void roomItemRemove(int32 roomIndex, int32 itemIndex)
{
Room* room = rooms + roomIndex;
int32 prevIndex = NO_ITEM;
int32 index = room->firstItem;
while (index != NO_ITEM)
{
int32 next = items[index].nextItem;
if (index == itemIndex)
{
items[index].nextItem = NO_ITEM;
if (prevIndex == NO_ITEM) {
room->firstItem = next;
} else {
items[prevIndex].nextItem = next;
}
break;
}
prevIndex = index;
index = next;
}
}
void activateItem(int32 itemIndex)
{
items[itemIndex].nextActive = firstActive;
firstActive = itemIndex;
}
void deactivateItem(int32 itemIndex)
{
int32 prevIndex = NO_ITEM;
int32 index = firstActive;
while (index != NO_ITEM)
{
int32 next = items[index].nextActive;
if (index == itemIndex)
{
items[index].nextItem = NO_ITEM;
if (prevIndex == NO_ITEM) {
firstActive = next;
} else {
items[prevIndex].nextActive = next;
}
break;
}
prevIndex = index;
index = next;
}
}
void readLevel(const uint8 *data) { // TODO non-hardcode level loader, added *_OFF alignment bytes void readLevel(const uint8 *data) { // TODO non-hardcode level loader, added *_OFF alignment bytes
tilesCount = *((uint32*)(data + 4)); tilesCount = *((int32*)(data + 4));
tiles = data + 8; tiles = data + 8;
#define MDL_OFF 2 #define MDL_OFF 2
#define ENT_OFF 2 #define ITM_OFF 2
roomsCount = *((uint16*)(data + 720908)); roomsCount = *((int16*)(data + 720908));
const Room* roomsPtr = (Room*)(data + 720908 + 2); const RoomInfo* roomsPtr = (RoomInfo*)(data + 720908 + 2);
floors = (uint16*)(data + 899492 + 4); floors = (uint16*)(data + 899492 + 4);
meshData = data + 908172 + 4; meshData = data + 908172 + 4;
meshOffsets = (uint32*)(data + 975724 + 4); meshOffsets = (int32*)(data + 975724 + 4);
nodes = (int32*)(data + 990318); animsCount = *((int32*)(data + 976596));
anims = (Anim*)(data + 976596 + 4);
ASSERT((intptr_t)anims % 4 == 0);
modelsCount = *((uint32*)(data + 1270666 + MDL_OFF)); framesCount = *((int32*)(data + 992990));
frames = (uint16*)(data + 992990 + 4);
ASSERT((intptr_t)frames % 2 == 0);
nodesPtr = (int32*)(data + 990318);
modelsCount = *((int32*)(data + 1270666 + MDL_OFF));
const uint8* modelsPtr = (uint8*)(data + 1270666 + 4 + MDL_OFF); const uint8* modelsPtr = (uint8*)(data + 1270666 + 4 + MDL_OFF);
ASSERT((intptr_t)modelsPtr % 4 == 0);
texturesCount = *((uint32*)(data + 1271686 + MDL_OFF)); staticMeshesCount = *((int32*)(data + 1271426 + MDL_OFF));
staticMeshes = (StaticMesh*)(data + 1271426 + 4 + MDL_OFF);
ASSERT((intptr_t)staticMeshes % 4 == 0);
texturesCount = *((int32*)(data + 1271686 + MDL_OFF));
textures = (Texture*)(data + 1271686 + 4 + MDL_OFF); textures = (Texture*)(data + 1271686 + 4 + MDL_OFF);
sprites = (Sprite*)(data + 1289634 + MDL_OFF); sprites = (Sprite*)(data + 1289634 + MDL_OFF);
spritesSeqCount = *((uint32*)(data + 1292130 + MDL_OFF)); spritesSeqCount = *((int32*)(data + 1292130 + MDL_OFF));
spritesSeq = (SpriteSeq*)(data + 1292130 + 4 + MDL_OFF); spritesSeq = (SpriteSeq*)(data + 1292130 + 4 + MDL_OFF);
entitiesCount = *((uint32*)(data + 1319252 + MDL_OFF + ENT_OFF)); itemsCount = *((int32*)(data + 1319252 + MDL_OFF + ITM_OFF));
entities = (Entity*)(data + 1319252 + 4 + MDL_OFF + ENT_OFF); const uint8* itemsPtr = (data + 1319252 + 4 + MDL_OFF + ITM_OFF);
for (int32 i = 0; i < itemsCount; i++) {
memcpy(items + i, itemsPtr, FILE_ITEM_SIZE);
itemsPtr += FILE_ITEM_SIZE;
}
// prepare lightmap // prepare lightmap
const uint8* f_lightmap = data + 1320576 + MDL_OFF + ENT_OFF; const uint8* f_lightmap = data + 1320576 + MDL_OFF + ITM_OFF;
memcpy(lightmap, f_lightmap, sizeof(lightmap)); memcpy(lightmap, f_lightmap, sizeof(lightmap));
// prepare palette // prepare palette
#if !(defined(USE_MODE_5) || defined(_WIN32)) const uint8* f_palette = data + 1328768 + MDL_OFF + ITM_OFF;
uint16 palette[256];
#endif
const uint8* f_palette = data + 1328768 + MDL_OFF + ENT_OFF;
const uint8* p = f_palette; const uint8* p = f_palette;
@@ -137,59 +241,33 @@ void readLevel(const uint8 *data) { // TODO non-hardcode level loader, added *_O
#endif #endif
p += 3; p += 3;
} }
#if defined(__GBA__) || defined(__TNS__)
#ifndef USE_MODE_5
SetPalette(palette);
#endif
#endif
// prepare models
for (uint32 i = 0; i < modelsCount; i++) {
dmaCopy(modelsPtr, models + i, sizeof(Model)); // sizeof(Model) is faster than FILE_MODEL_SIZE
modelsPtr += FILE_MODEL_SIZE;
modelsMap[models[i].type] = i;
}
// prepare entities
for (uint32 i = 0; i < entitiesCount; i++) {
if (entities[i].type == ENTITY_LARA) {
entityLara = i;
break;
}
}
// prepare glyphs
for (uint32 i = 0; i < spritesSeqCount; i++) {
if (spritesSeq[i].type == SEQ_GLYPH) {
seqGlyphs = i;
break;
}
}
// prepare rooms // prepare rooms
uint8 *ptr = (uint8*)roomsPtr; uint8 *ptr = (uint8*)roomsPtr;
for (uint16 roomIndex = 0; roomIndex < roomsCount; roomIndex++) { for (int32 roomIndex = 0; roomIndex < roomsCount; roomIndex++)
const Room *room = (Room*)ptr; {
ptr += sizeof(Room); const RoomInfo *room = (RoomInfo*)ptr;
ptr += sizeof(RoomInfo);
uint32 dataSize; uint32 dataSize;
memcpy(&dataSize, &room->dataSize, sizeof(dataSize)); memcpy(&dataSize, &room->dataSize, sizeof(dataSize));
uint8* skipPtr = ptr + dataSize * 2; uint8* skipPtr = ptr + dataSize * 2;
RoomDesc &desc = rooms[roomIndex]; Room &desc = rooms[roomIndex];
desc.reset(); roomReset(roomIndex);
desc.firstItem = NO_ITEM;
// offset // offset
memcpy(&desc.x, &room->info.x, sizeof(room->info.x)); memcpy(&desc.x, &room->x, sizeof(room->x));
memcpy(&desc.z, &room->info.z, sizeof(room->info.z)); memcpy(&desc.z, &room->z, sizeof(room->z));
// vertices // vertices
desc.vCount = *((uint16*)ptr); desc.vCount = *((uint16*)ptr);
ptr += 2; ptr += 2;
desc.vertices = (Room::Vertex*)ptr; desc.vertices = (RoomInfo::Vertex*)ptr;
ptr += sizeof(Room::Vertex) * desc.vCount; ptr += sizeof(RoomInfo::Vertex) * desc.vCount;
// quads // quads
desc.qCount = *((uint16*)ptr); desc.qCount = *((uint16*)ptr);
@@ -208,38 +286,99 @@ void readLevel(const uint8 *data) { // TODO non-hardcode level loader, added *_O
// portals // portals
desc.pCount = *((uint16*)ptr); desc.pCount = *((uint16*)ptr);
ptr += 2; ptr += 2;
desc.portals = (Room::Portal*)ptr; desc.portals = (RoomInfo::Portal*)ptr;
ptr += sizeof(Room::Portal) * desc.pCount; ptr += sizeof(RoomInfo::Portal) * desc.pCount;
desc.zSectors = *((uint16*)ptr); desc.zSectors = *((uint16*)ptr);
ptr += 2; ptr += 2;
desc.xSectors = *((uint16*)ptr); desc.xSectors = *((uint16*)ptr);
ptr += 2; ptr += 2;
desc.sectors = (Room::Sector*)ptr; desc.sectors = (RoomInfo::Sector*)ptr;
ptr += sizeof(Room::Sector) * desc.zSectors * desc.xSectors; ptr += sizeof(RoomInfo::Sector) * desc.zSectors * desc.xSectors;
//ambient = *((uint16*)ptr); desc.ambient = *((uint16*)ptr);
ptr += 2; ptr += 2;
uint16 lightsCount = *((uint16*)ptr); desc.lCount = *((uint16*)ptr);
ptr += 2; ptr += 2;
//lights = (Room::Light*)ptr; desc.lights = (RoomInfo::Light*)ptr;
ptr += sizeof(Room::Light) * lightsCount; ptr += sizeof(RoomInfo::Light) * desc.lCount;
uint16 meshesCount = *((uint16*)ptr); desc.mCount = *((uint16*)ptr);
ptr += 2; ptr += 2;
//meshes = (Room::Mesh*)ptr; desc.meshes = (RoomInfo::Mesh*)ptr;
ptr += sizeof(Room::Mesh) * meshesCount; ptr += sizeof(RoomInfo::Mesh) * desc.mCount;
ptr += 2 + 2; // skip alternateRoom and flags ptr += 2 + 2; // skip alternateRoom and flags
} }
// prepare models
memset(modelsMap, 0xFF, sizeof(modelsMap));
for (int32 i = 0; i < modelsCount; i++)
{
memcpy(models + i, modelsPtr, sizeof(Model)); // sizeof(Model) is faster than FILE_MODEL_SIZE
modelsPtr += FILE_MODEL_SIZE;
modelsMap[models[i].type] = i;
}
// prepare static meshes
memset(staticMeshesMap, 0xFF, sizeof(staticMeshesMap));
for (int32 i = 0; i < staticMeshesCount; i++)
{
staticMeshesMap[staticMeshes[i].id] = i;
}
// prepare items
for (int32 i = 0; i < itemsCount; i++) {
Item* item = items + i;
item->angleX = 0;
item->angleZ = 0;
item->vSpeed = 0;
item->hSpeed = 0;
item->nextItem = NO_ITEM;
item->nextActive = NO_ITEM;
item->animIndex = models[modelsMap[item->type]].animIndex;
item->frameIndex = anims[item->animIndex].frameBegin;
item->state = anims[item->animIndex].state;
item->nextState = item->state;
item->goalState = item->state;
item->intensity = 4096; // TODO lighting
item->flags.gravity = 0;
if (item->room > -1) {
roomItemAdd(item->room, i);
}
if (item->type == ITEM_LARA) {
activateItem(i);
}
// TODO remove
if (item->type == ITEM_WOLF ||
item->type == ITEM_BEAR ||
item->type == ITEM_BAT ||
item->type == ITEM_CRYSTAL)
{
activateItem(i);
}
}
// prepare glyphs
for (int32 i = 0; i < spritesSeqCount; i++) {
if (spritesSeq[i].type == SEQ_GLYPH) {
seqGlyphs = i;
break;
}
}
camera.init(); camera.init();
camera.room = entities[entityLara].room; camera.room = 0;
} }
void drawMesh(int16 meshIndex) { void drawMesh(int16 meshIndex, uint16 intensity) {
uint32 offset = meshOffsets[meshIndex]; int32 offset = meshOffsets[meshIndex];
const uint8* ptr = meshData + offset; const uint8* ptr = meshData + offset;
ptr += 2 * 5; // skip [cx, cy, cz, radius, flags] ptr += 2 * 5; // skip [cx, cy, cz, radius, flags]
@@ -271,52 +410,67 @@ void drawMesh(int16 meshIndex) {
int32 startVertex = gVerticesCount; int32 startVertex = gVerticesCount;
PROFILE_START(); PROFILE_START();
transform_mesh(vertices, vCount); transformMesh(vertices, vCount, intensity);
PROFILE_STOP(dbg_transform); PROFILE_STOP(dbg_transform);
PROFILE_START(); PROFILE_START();
faceAdd_mesh(rFaces, crFaces, tFaces, ctFaces, rCount, crCount, tCount, ctCount, startVertex); faceAddMesh(rFaces, crFaces, tFaces, ctFaces, rCount, crCount, tCount, ctCount, startVertex);
PROFILE_STOP(dbg_poly); PROFILE_STOP(dbg_poly);
} }
void drawModel(int32 modelIndex) { Frame* getFrame(const Item* item, const Model* model)
const Model* model = models + modelIndex; {
const Anim* anim = anims + item->animIndex;
// non-aligned access int32 frameSize = sizeof(Frame) / 2 + model->mCount * 2;
uint32 node, frame; int32 frameIndex = (item->frameIndex - anim->frameBegin) / anim->frameRate;//* FixedInvU(anim->frameRate) >> 16;
memcpy(&node, &model->node, sizeof(node));
memcpy(&frame, &model->frame, sizeof(frame));
Node bones[32]; return (Frame*)(frames + anim->frameOffset / 2 + frameIndex * frameSize);
memcpy(bones, nodes + node, (model->mCount - 1) * sizeof(Node));
const Node* n = bones;
drawMesh(model->mStart);
for (int i = 1; i < model->mCount; i++) {
if (n->flags & 1) {
matrixPop();
}
if (n->flags & 2) {
matrixPush();
}
matrixTranslate(n->pos);
n++;
drawMesh(model->mStart + i);
}
} }
void drawEntity(int32 entityIndex) { void drawItem(const Item* item) {
const Entity &e = entities[entityIndex]; int32 modelIndex = modelsMap[item->type];
if (modelIndex == NO_MODEL) {
return; // TODO sprite items
}
const Model* model = models + modelIndex;
if (model->mCount == 1 && meshOffsets[model->mStart] == 0) return;
Frame* frame = getFrame(item, model);
uint16* frameAngles = frame->angles + 1;
matrixPush(); matrixPush();
matrixTranslateAbs(vec3i(e.pos.x, e.pos.y - 512, e.pos.z)); // TODO animation matrixTranslateAbs(item->pos.x, item->pos.y, item->pos.z);
matrixRotateYXZ(item->angleX, item->angleY, item->angleZ);
drawModel(modelsMap[e.type]); if (boxIsVisible(&frame->box)) {
// non-aligned access (TODO)
uint32 nodeIndex;
memcpy(&nodeIndex, &model->nodeIndex, sizeof(nodeIndex));
Node nodes[32];
memcpy(nodes, nodesPtr + nodeIndex, (model->mCount - 1) * sizeof(Node));
const Node* node = nodes;
matrixFrame(frame->pos.x, frame->pos.y, frame->pos.z, frameAngles);
drawMesh(model->mStart, item->intensity);
for (int32 i = 1; i < model->mCount; i++)
{
if (node->flags & 1) matrixPop();
if (node->flags & 2) matrixPush();
frameAngles += 2;
matrixFrame(node->pos.x, node->pos.y, node->pos.z, frameAngles);
drawMesh(model->mStart + i, item->intensity);
node++;
}
}
matrixPop(); matrixPop();
} }
@@ -333,39 +487,62 @@ void drawNumber(int32 number, int32 x, int32 y) {
} }
} }
extern vec3i viewPos; void drawRoom(int32 roomIndex) {
extern Vertex gVertices[MAX_VERTICES]; const Room* room = rooms + roomIndex;
void drawRoom(int16 roomIndex) { clip = room->clip;
RoomDesc &room = rooms[roomIndex];
clip = room.clip;
int32 startVertex = gVerticesCount; int32 startVertex = gVerticesCount;
matrixPush(); matrixPush();
matrixTranslateAbs(vec3i(room.x, 0, room.z)); matrixTranslateAbs(room->x, 0, room->z);
PROFILE_START(); PROFILE_START();
transform_room(room.vertices, room.vCount); transformRoom(room->vertices, room->vCount);
PROFILE_STOP(dbg_transform); PROFILE_STOP(dbg_transform);
matrixPop(); matrixPop();
PROFILE_START(); PROFILE_START();
faceAdd_room(room.quads, room.qCount, room.triangles, room.tCount, startVertex); faceAddRoom(room->quads, room->qCount, room->triangles, room->tCount, startVertex);
if (roomIndex == entityLara) { // TODO draw all entities in the room
drawEntity(entityLara); for (int32 i = 0; i < room->mCount; i++)
{
const RoomInfo::Mesh* mesh = room->meshes + i;
const StaticMesh* staticMesh = staticMeshes + staticMeshesMap[mesh->staticMeshId];
if (!(staticMesh->flags & 2)) continue; // invisible
// TODO align RoomInfo::Mesh (room relative int16?)
vec3i pos;
memcpy(&pos, &mesh->pos, sizeof(pos));
matrixPush();
matrixTranslateAbs(pos.x, pos.y, pos.z);
matrixRotateY(mesh->rotation);
if (boxIsVisible(&staticMesh->vbox)) {
drawMesh(staticMesh->meshIndex, mesh->intensity);
}
matrixPop();
}
int32 itemIndex = room->firstItem;
while (itemIndex != NO_ITEM)
{
drawItem(items + itemIndex);
itemIndex = items[itemIndex].nextItem;
} }
PROFILE_STOP(dbg_poly); PROFILE_STOP(dbg_poly);
room.reset(); roomReset(roomIndex);
flush(); flush();
} }
const Room::Sector* getSector(int32 roomIndex, int32 x, int32 z) { const RoomInfo::Sector* getSector(int32 roomIndex, int32 x, int32 z) {
RoomDesc &room = rooms[roomIndex]; Room &room = rooms[roomIndex];
int32 sx = clamp((x - room.x) >> 10, 0, room.xSectors - 1); int32 sx = clamp((x - room.x) >> 10, 0, room.xSectors - 1);
int32 sz = clamp((z - room.z) >> 10, 0, room.zSectors - 1); int32 sz = clamp((z - room.z) >> 10, 0, room.zSectors - 1);
@@ -373,8 +550,8 @@ const Room::Sector* getSector(int32 roomIndex, int32 x, int32 z) {
return room.sectors + sx * room.zSectors + sz; return room.sectors + sx * room.zSectors + sz;
} }
int32 getRoomIndex(int32 roomIndex, const vec3i &pos) { int32 getRoomIndex(int32 roomIndex, const vec3i* pos) {
const Room::Sector *sector = getSector(roomIndex, pos.x, pos.z); const RoomInfo::Sector *sector = getSector(roomIndex, pos->x, pos->z);
if (sector->floorIndex) { if (sector->floorIndex) {
const uint16 *data = floors + sector->floorIndex; const uint16 *data = floors + sector->floorIndex;
@@ -395,28 +572,28 @@ int32 getRoomIndex(int32 roomIndex, const vec3i &pos) {
} }
} }
while (sector->roomAbove != 0xFF && pos.y < (sector->ceiling << 8)) { while (sector->roomAbove != NO_ROOM && pos->y < (sector->ceiling << 8)) {
roomIndex = sector->roomAbove; roomIndex = sector->roomAbove;
sector = getSector(roomIndex, pos.x, pos.z); sector = getSector(roomIndex, pos->x, pos->z);
} }
while (sector->roomBelow != 0xFF && pos.y >= (sector->floor << 8)) { while (sector->roomBelow != 0xFF && pos->y >= (sector->floor << 8)) {
roomIndex = sector->roomBelow; roomIndex = sector->roomBelow;
sector = getSector(roomIndex, pos.x, pos.z); sector = getSector(roomIndex, pos->x, pos->z);
} }
return roomIndex; return roomIndex;
} }
bool checkPortal(int32 roomIndex, const Room::Portal &portal) { bool checkPortal(int32 roomIndex, const RoomInfo::Portal* portal) {
RoomDesc &room = rooms[roomIndex]; Room &room = rooms[roomIndex];
vec3i d; vec3i d;
d.x = portal.v[0].x - camera.pos.x + room.x; d.x = portal->v[0].x - camera.pos.x + room.x;
d.y = portal.v[0].y - camera.pos.y; d.y = portal->v[0].y - camera.pos.y;
d.z = portal.v[0].z - camera.pos.z + room.z; d.z = portal->v[0].z - camera.pos.z + room.z;
if (DP33(portal.n, d) >= 0) { if (DP33(portal->n, d) >= 0) {
return false; return false;
} }
@@ -432,7 +609,7 @@ bool checkPortal(int32 roomIndex, const Room::Portal &portal) {
vec3i pv[4]; vec3i pv[4];
for (int32 i = 0; i < 4; i++) { for (int32 i = 0; i < 4; i++) {
const vec3s &v = portal.v[i]; const vec3s &v = portal->v[i];
int32 x = DP43(m[0], v); int32 x = DP43(m[0], v);
int32 y = DP43(m[1], v); int32 y = DP43(m[1], v);
@@ -503,7 +680,7 @@ bool checkPortal(int32 roomIndex, const Room::Portal &portal) {
if (x0 >= x1 || y0 >= y1) return false; if (x0 >= x1 || y0 >= y1) return false;
RoomDesc &nextRoom = rooms[portal.roomIndex]; Room &nextRoom = rooms[portal->roomIndex];
if (x0 < nextRoom.clip.x0) nextRoom.clip.x0 = x0; if (x0 < nextRoom.clip.x0) nextRoom.clip.x0 = x0;
if (x1 > nextRoom.clip.x1) nextRoom.clip.x1 = x1; if (x1 > nextRoom.clip.x1) nextRoom.clip.x1 = x1;
@@ -512,38 +689,123 @@ bool checkPortal(int32 roomIndex, const Room::Portal &portal) {
if (!nextRoom.visible) { if (!nextRoom.visible) {
nextRoom.visible = true; nextRoom.visible = true;
visRooms[visRoomsCount++] = portal.roomIndex; visRooms[visRoomsCount++] = portal->roomIndex;
} }
return true; return true;
} }
void getVisibleRooms(int32 roomIndex) { void getVisibleRooms(int32 roomIndex)
RoomDesc &room = rooms[roomIndex]; {
const Room* room = rooms + roomIndex;
matrixPush(); matrixPush();
matrixTranslateAbs(vec3i(room.x, 0, room.z)); matrixTranslateAbs(room->x, 0, room->z);
for (int32 i = 0; i < room.pCount; i++) { for (int32 i = 0; i < room->pCount; i++)
const Room::Portal &portal = room.portals[i]; {
if (checkPortal(roomIndex, portal)) { const RoomInfo::Portal* portal = room->portals + i;
getVisibleRooms(portal.roomIndex);
if (checkPortal(roomIndex, portal))
{
getVisibleRooms(portal->roomIndex);
} }
} }
matrixPop(); matrixPop();
} }
void drawRooms() { void drawRooms()
{
rooms[camera.room].clip = { 0, 0, FRAME_WIDTH, FRAME_HEIGHT }; rooms[camera.room].clip = { 0, 0, FRAME_WIDTH, FRAME_HEIGHT };
visRoomsCount = 0; visRoomsCount = 0;
visRooms[visRoomsCount++] = camera.room; visRooms[visRoomsCount++] = camera.room;
getVisibleRooms(camera.room); getVisibleRooms(camera.room);
while (visRoomsCount--) { while (visRoomsCount--)
{
drawRoom(visRooms[visRoomsCount]); drawRoom(visRooms[visRoomsCount]);
} }
} }
void move(Item* item, const Anim* anim)
{
int32 speed = anim->speed;
if (item->flags.gravity)
{
speed += anim->accel * (item->frameIndex - anim->frameBegin - 1);
item->hSpeed -= speed >> 16;
speed += anim->accel;
item->hSpeed += speed >> 16;
item->vSpeed += (item->vSpeed < 128) ? GRAVITY : 1;
item->pos.y += item->vSpeed;
} else {
speed += anim->accel * (item->frameIndex - anim->frameBegin);
item->hSpeed = speed >> 16;
}
item->pos.x += phd_sin(item->angleY) * item->hSpeed >> FIXED_SHIFT;
item->pos.z += phd_cos(item->angleY) * item->hSpeed >> FIXED_SHIFT;
}
void animChange(Item* item, const Anim* anim)
{
if (!anim->scCount) return;
// check state change
}
void animCommand(bool fx, Item* item, const Anim* anim)
{
if (!anim->acCount) return;
// check animation command
}
const Anim* animSet(Item* item, int32 animIndex, int32 frameIndex)
{
item->animIndex = animIndex;
item->frameIndex = frameIndex;
item->state = anims[animIndex].state;
return anims + animIndex;
}
void animUpdate(Item* item)
{
const Anim* anim = anims + item->animIndex;
item->frameIndex++;
animChange(item, anim);
if (item->frameIndex > anim->frameEnd)
{
animCommand(false, item, anim);
anim = animSet(item, anim->nextAnimIndex, anim->nextFrameIndex);
}
animCommand(true, item, anim);
//move(item, anim);
}
void updateItems()
{
int32 itemIndex = firstActive;
while (itemIndex != NO_ITEM)
{
Item* item = items + itemIndex;
if (modelsMap[item->type] != NO_MODEL) {
animUpdate(item);
}
itemIndex = item->nextActive;
}
}
#endif #endif

View File

@@ -7,7 +7,7 @@
uint32 SCREEN[WIDTH * HEIGHT]; uint32 SCREEN[WIDTH * HEIGHT];
extern uint8 fb[WIDTH * HEIGHT * 2]; extern uint16 fb[WIDTH * HEIGHT];
LARGE_INTEGER g_timer; LARGE_INTEGER g_timer;
LARGE_INTEGER g_current; LARGE_INTEGER g_current;
@@ -20,7 +20,7 @@
#elif defined(__TNS__) #elif defined(__TNS__)
uint8* LEVEL1_PHD; uint8* LEVEL1_PHD;
extern uint8 fb[WIDTH * HEIGHT]; extern uint16 fb[WIDTH * HEIGHT];
unsigned int osTime; unsigned int osTime;
volatile unsigned int *timerBUS; volatile unsigned int *timerBUS;
@@ -95,6 +95,7 @@ int32 fpsCounter = 0;
void update(int32 frames) { void update(int32 frames) {
for (int32 i = 0; i < frames; i++) { for (int32 i = 0; i < frames; i++) {
updateItems();
camera.update(); camera.update();
} }
} }
@@ -212,9 +213,8 @@ void render() {
drawNumber(dbg_poly, FRAME_WIDTH, 48); drawNumber(dbg_poly, FRAME_WIDTH, 48);
drawNumber(dbg_sort, FRAME_WIDTH, 64); drawNumber(dbg_sort, FRAME_WIDTH, 64);
drawNumber(dbg_flush, FRAME_WIDTH, 80); drawNumber(dbg_flush, FRAME_WIDTH, 80);
drawNumber(dbg_transform + dbg_poly + dbg_sort + dbg_flush, FRAME_WIDTH, 96); drawNumber(dbg_vert_count, FRAME_WIDTH, 96);
drawNumber(dbg_vert_count, FRAME_WIDTH, 120); drawNumber(dbg_poly_count, FRAME_WIDTH, 112);
drawNumber(dbg_poly_count, FRAME_WIDTH, 136);
#endif #endif
#endif #endif
@@ -226,22 +226,10 @@ void render() {
HDC hDC; HDC hDC;
void blit() { void blit() {
#ifdef USE_MODE_5 for (int i = 0; i < WIDTH * HEIGHT; i++) {
for (int i = 0; i < WIDTH * HEIGHT; i++) { uint16 c = ((uint16*)fb)[i];
uint16 c = ((uint16*)fb)[i]; SCREEN[i] = (((c << 3) & 0xFF) << 16) | ((((c >> 5) << 3) & 0xFF) << 8) | ((c >> 10 << 3) & 0xFF) | 0xFF000000;
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++) {
#ifdef DEBUG_OVERDRAW
uint8 c = ((uint8*)fb)[i];
SCREEN[i] = c | (c << 8) | (c << 16) | 0xFF000000;
#else
uint16 c = palette[((uint8*)fb)[i]];
SCREEN[i] = (((c << 3) & 0xFF) << 16) | ((((c >> 5) << 3) & 0xFF) << 8) | ((c >> 10 << 3) & 0xFF) | 0xFF000000;
#endif
}
#endif
const BITMAPINFO bmi = { sizeof(BITMAPINFOHEADER), WIDTH, -HEIGHT, 1, 32, BI_RGB, 0, 0, 0, 0, 0 }; 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, SCREEN, &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);
@@ -305,13 +293,11 @@ int main(void) {
} }
#elif defined(__GBA__) #elif defined(__GBA__)
// set low latency mode via WAITCNT register (thanks to GValiente) // set low latency mode via WAITCNT register (thanks to GValiente)
#define BIT_SET(y, flag) (y |= (flag)) #define REG_WAITCNT_NV *(u16*)(REG_BASE + 0x0204)
#define REG_WAITCNT_NV *(u16*)(REG_BASE + 0x0204) REG_WAITCNT_NV |= (0x0008 | 0x0010 | 0x4000);
BIT_SET(REG_WAITCNT_NV, 0x0008 | 0x0010 | 0x4000);
#endif #endif
initRender(); initLUT();
readLevel(LEVEL1_PHD); readLevel(LEVEL1_PHD);
@@ -330,8 +316,8 @@ int main(void) {
MSG msg; MSG msg;
int startTime = GetTickCount(); int startTime = GetTickCount() - 33;
int lastTime = -16; int lastFrame = 0;
do { do {
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
@@ -339,9 +325,9 @@ int main(void) {
DispatchMessage(&msg); DispatchMessage(&msg);
} else { } else {
int time = GetTickCount() - startTime; int frame = (GetTickCount() - startTime) / 33;
update((time - lastTime) / 16); update(frame - lastFrame);
lastTime = time; lastFrame = frame;
render(); render();
@@ -356,17 +342,10 @@ int main(void) {
uint16 mode = BG2_ON | BACKBUFFER; uint16 mode = BG2_ON | BACKBUFFER;
#ifdef USE_MODE_5 mode |= MODE_5;
mode |= MODE_5;
REG_BG2PA = 256 - 64 - 16 - 4 - 1; REG_BG2PA = 256 - 64 - 16 - 4 - 1;
REG_BG2PD = 256 - 48 - 2; REG_BG2PD = 256 - 48 - 2;
#else
mode |= MODE_4;
REG_BG2PA = 256 / SCALE;
REG_BG2PD = 256 / SCALE;
#endif
int32 lastFrameIndex = -1; int32 lastFrameIndex = -1;
@@ -387,7 +366,7 @@ int main(void) {
keys[IK_L] = (key & KEY_L); keys[IK_L] = (key & KEY_L);
keys[IK_R] = (key & KEY_R); keys[IK_R] = (key & KEY_R);
int32 frame = frameIndex; int32 frame = frameIndex / 2;
update(frame - lastFrameIndex); update(frame - lastFrameIndex);
lastFrameIndex = frame; lastFrameIndex = frame;
@@ -396,7 +375,7 @@ int main(void) {
fpsCounter++; fpsCounter++;
if (frameIndex >= 60) { if (frameIndex >= 60) {
frameIndex -= 60; frameIndex -= 60;
lastFrameIndex -= 60; lastFrameIndex -= 30;
fps = fpsCounter; fps = fpsCounter;

View File

@@ -1,36 +1,28 @@
#include "common.h" #include "common.h"
#define DIV_TABLE_SIZE 256
uint16 divTable[DIV_TABLE_SIZE]; // IWRAM 0.5 kb
#if defined(_WIN32) #if defined(_WIN32)
uint8 fb[WIDTH * HEIGHT * 2]; uint16 fb[WIDTH * HEIGHT];
#elif defined(__GBA__) #elif defined(__GBA__)
uint32 fb = VRAM; uint32 fb = VRAM;
#elif defined(__TNS__) #elif defined(__TNS__)
uint8 fb[WIDTH * HEIGHT]; uint16 fb[WIDTH * HEIGHT];
#endif #endif
#define FixedInvS(x) ((x < 0) ? -divTable[abs(x)] : divTable[x]) #define PAL_COLOR_TRANSP 0x0000
#define FixedInvU(x) divTable[x] #define PAL_COLOR_BLACK 0x0421
#if defined(USE_MODE_5) || defined(_WIN32) uint16 palette[256]; // IWRAM 0.5 kb
uint16 palette[256]; uint8 lightmap[256 * 32]; // IWRAM 8 kb
#endif const uint8* ft_lightmap;
uint8 lightmap[256 * 32]; // IWRAM 8 kb
uint8* ft_lightmap;
const uint8* tiles;
const uint8* tile;
const Texture* textures; const Texture* textures;
const uint8* tiles;
const uint8* tile;
uint32 gVerticesCount = 0; uint32 gVerticesCount = 0;
int32 gFacesCount = 0; int32 gFacesCount = 0;
EWRAM_DATA Vertex gVertices[MAX_VERTICES]; // EWRAM 8 kb EWRAM_DATA Vertex gVertices[MAX_VERTICES]; // EWRAM 16 kb
EWRAM_DATA Face* gFacesSorted[MAX_FACES]; // EWRAM 2 kb EWRAM_DATA Face* gFacesSorted[MAX_FACES]; // EWRAM 2 kb
EWRAM_DATA Face gFaces[MAX_FACES]; // EWRAM 5 kb EWRAM_DATA Face gFaces[MAX_FACES]; // EWRAM 5 kb
@@ -38,9 +30,6 @@ EWRAM_DATA Face gFaces[MAX_FACES]; // EWRAM 5 kb
Rect clip; Rect clip;
Matrix matrixStack[MAX_MATRICES];
int32 matrixStackIndex = 0;
template <class T> template <class T>
INLINE void swap(T &a, T &b) { INLINE void swap(T &a, T &b) {
T tmp = a; T tmp = a;
@@ -52,12 +41,6 @@ INLINE bool checkBackface(const Vertex *a, const Vertex *b, const Vertex *c) {
return (b->x - a->x) * (c->y - a->y) <= (c->x - a->x) * (b->y - a->y); return (b->x - a->x) * (c->y - a->y) <= (c->x - a->x) * (b->y - a->y);
} }
INLINE void sortVertices(VertexUV *&t, VertexUV *&m, VertexUV *&b) {
if (t->v.y > m->v.y) swap(t, m);
if (t->v.y > b->v.y) swap(t, b);
if (m->v.y > b->v.y) swap(m, b);
}
INLINE int32 classify(const Vertex* v) { INLINE int32 classify(const Vertex* v) {
return (v->x < clip.x0 ? 1 : 0) | return (v->x < clip.x0 ? 1 : 0) |
(v->x > clip.x1 ? 2 : 0) | (v->x > clip.x1 ? 2 : 0) |
@@ -65,14 +48,68 @@ INLINE int32 classify(const Vertex* v) {
(v->y > clip.y1 ? 8 : 0); (v->y > clip.y1 ? 8 : 0);
} }
void transform(const vec3s &v, int32 vg) { bool boxIsVisible(const Box* box)
#if defined(_WIN32) {
if (gVerticesCount >= MAX_VERTICES) { const Matrix &m = matrixGet();
DebugBreak();
return; if (m[2][3] >= VIEW_MAX_F) {
return false;
} }
#endif
const Matrix &m = matrixStack[matrixStackIndex]; if (m[2][3] < VIEW_MIN_F) { // TODO large objects
return false;
}
const vec3i v[8] {
{ box->minX, box->minY, box->minZ },
{ box->maxX, box->minY, box->minZ },
{ box->minX, box->maxY, box->minZ },
{ box->maxX, box->maxY, box->minZ },
{ box->minX, box->minY, box->maxZ },
{ box->maxX, box->minY, box->maxZ },
{ box->minX, box->maxY, box->maxZ },
{ box->maxX, box->maxY, box->maxZ }
};
Rect rect = { INT_MAX, INT_MAX, INT_MIN, INT_MIN };
for (int32 i = 0; i < 8; i++) {
int32 z = DP43(m[2], v[i]);
if (z < VIEW_MIN_F || z >= VIEW_MAX_F) { // TODO znear clip
continue;
}
int32 x = DP43(m[0], v[i]);
int32 y = DP43(m[1], v[i]);
z >>= FOV_SHIFT;
x = (x / z);
y = (y / z);
if (x < rect.x0) rect.x0 = x;
if (x > rect.x1) rect.x1 = x;
if (y < rect.y0) rect.y0 = y;
if (y > rect.y1) rect.y1 = y;
}
rect.x0 += (FRAME_WIDTH / 2);
rect.y0 += (FRAME_HEIGHT / 2);
rect.x1 += (FRAME_WIDTH / 2);
rect.y1 += (FRAME_HEIGHT / 2);
return !(rect.x0 > rect.x1 ||
rect.x0 > clip.x1 ||
rect.x1 < clip.x0 ||
rect.y0 > clip.y1 ||
rect.y1 < clip.y0);
}
void transform(const vec3s &v, int32 vg) {
ASSERT(gVerticesCount < MAX_VERTICES);
const Matrix &m = matrixGet();
Vertex &res = gVertices[gVerticesCount++]; Vertex &res = gVertices[gVerticesCount++];
@@ -110,7 +147,7 @@ void transform(const vec3s &v, int32 vg) {
res.clip = classify(&res); res.clip = classify(&res);
} }
void transform_room(const Room::Vertex* vertex, int32 vCount) void transformRoom(const RoomInfo::Vertex* vertex, int32 vCount)
{ {
for (int32 i = 0; i < vCount; i++) for (int32 i = 0; i < vCount; i++)
{ {
@@ -119,10 +156,10 @@ void transform_room(const Room::Vertex* vertex, int32 vCount)
} }
} }
void transform_mesh(const vec3s* vertices, int32 vCount) void transformMesh(const vec3s* vertices, int32 vCount, uint16 intensity)
{ {
for (int32 i = 0; i < vCount; i++) { for (int32 i = 0; i < vCount; i++) {
transform(*vertices++, 4096); transform(*vertices++, intensity);
} }
} }
@@ -263,40 +300,15 @@ VertexUV* clipPoly(VertexUV* poly, VertexUV* tmp, int32 &pCount) {
#define FETCH_GT_PAL() 32 #define FETCH_GT_PAL() 32
#define FETCH_G_PAL(palIndex) 32 #define FETCH_G_PAL(palIndex) 32
#else #else
#define FETCH_T() tile[(t & 0xFF00) | (t >> 24)]
#define FETCH_GT() lightmap[(g & 0x1F00) | FETCH_T()]
#define FETCH_FT() ft_lightmap[FETCH_T()]
INLINE uint32 FETCH_FT2(uint32 &t, uint32 dtdx) { #define FETCH_T() tile[(t & 0xFF00) | (t >> 24)]
uint32 p = FETCH_FT(); #define FETCH_G() lightmap[(g & 0x1F00) | palIndex]
t += dtdx; #define FETCH_GT() lightmap[(g & 0x1F00) | FETCH_T()]
p |= FETCH_FT() << 8; #define FETCH_FT() ft_lightmap[FETCH_T()]
t += dtdx;
return p;
}
INLINE uint32 FETCH_GT2(uint32 &g, uint32 &t, uint32 dgdx, uint32 dtdx) { #define PUT_PIXEL_GT() { uint16 p = palette[FETCH_GT()]; if (p) *pixel = p; }
#if 0 #define PUT_PIXEL_FT() { uint16 p = palette[FETCH_FT()]; if (p) *pixel = p; }
uint32 light = g & 0x1F00; #define PUT_PIXEL_G() { *pixel = palette[FETCH_G()]; }
uint32 p = lightmap[light | FETCH_T()];
t += dtdx;
p |= lightmap[light | FETCH_T()] << 8;
t += dtdx;
g += dgdx;
return p;
#else
uint32 p = FETCH_GT();
t += dtdx;
p |= FETCH_GT() << 8;
t += dtdx;
g += dgdx;
return p;
#endif
}
#define FETCH_G(palIndex) lightmap[(g & 0x1F00) | palIndex]
#define FETCH_GT_PAL() palette[FETCH_GT()]
#define FETCH_G_PAL(palIndex) palette[FETCH_G(palIndex)]
#endif #endif
struct Edge { struct Edge {
@@ -427,426 +439,70 @@ struct Edge {
}; };
INLINE void scanlineG(uint16* buffer, int32 x1, int32 x2, uint8 palIndex, uint32 g, uint32 dgdx) { INLINE void scanlineG(uint16* buffer, int32 x1, int32 x2, uint8 palIndex, uint32 g, uint32 dgdx) {
#if defined(USE_MODE_5) uint16* pixel = buffer + x1;
uint16* pixel = buffer + x1;
if (x1 & 1) { int32 width = x2 - x1;
*pixel++ = FETCH_G_PAL(palIndex);
g += dgdx;
x1++;
if (x1 >= x2) { dgdx <<= 1;
return;
}
}
int32 width2 = (x2 - x1) >> 1; while (width--) {
PUT_PIXEL_G();
dgdx <<= 1; pixel++;
while (width2--) {
uint32 p = FETCH_G_PAL(palIndex);
g += dgdx;
*(uint32*)pixel = p | (p << 16);
pixel += 2;
}
if (x2 & 1) {
*pixel++ = FETCH_G_PAL(palIndex);
}
#elif defined(USE_MODE_4)
if (x1 & 1)
{
uint16 &p = *(uint16*)((uint8*)buffer + x1 - 1);
p = (p & 0x00FF) | (FETCH_G(palIndex) << 8);
g += dgdx;
x1++;
}
int32 width = (x2 - x1) >> 1;
uint16* pixel = (uint16*)((uint8*)buffer + x1);
dgdx <<= 1;
if (width && (x1 & 3))
{
uint16 p = FETCH_G(palIndex);
*pixel++ = p | (FETCH_G(palIndex) << 8);
g += dgdx;
if (width) {
width--; width--;
PUT_PIXEL_G();
pixel++;
} }
while (width-- > 0) g += dgdx;
{ }
uint32 p = FETCH_G(palIndex);
p |= (FETCH_G(palIndex) << 8);
g += dgdx;
if (width-- > 0)
{
p |= (FETCH_G(palIndex) << 16);
p |= (FETCH_G(palIndex) << 24);
g += dgdx;
*(uint32*)pixel = p;
pixel += 2;
} else {
*(uint16*)pixel = p;
pixel += 1;
}
}
if (x2 & 1)
{
*pixel = (*pixel & 0xFF00) | FETCH_G(palIndex);
}
#else
if (x1 & 1)
{
*((uint8*)buffer + x1) = FETCH_G(palIndex);
g += dgdx;
x1++;
}
int32 width = (x2 - x1) >> 1;
uint16* pixel = (uint16*)((uint8*)buffer + x1);
dgdx <<= 1;
if (width && (x1 & 3))
{
uint16 p = FETCH_G(palIndex);
*pixel++ = p | (FETCH_G(palIndex) << 8);
g += dgdx;
width--;
}
while (width-- > 0)
{
uint32 p = FETCH_G(palIndex);
p |= (FETCH_G(palIndex) << 8);
g += dgdx;
if (width-- > 0)
{
p |= (FETCH_G(palIndex) << 16);
p |= (FETCH_G(palIndex) << 24);
g += dgdx;
*(uint32*)pixel = p;
pixel += 2;
} else {
*(uint16*)pixel = p;
pixel += 1;
}
}
if (x2 & 1)
{
*((uint8*)pixel) = FETCH_G(palIndex);
}
#endif
} }
INLINE void scanlineGT(uint16* buffer, int32 x1, int32 x2, uint32 g, uint32 t, uint32 dgdx, uint32 dtdx) { INLINE void scanlineGT(uint16* buffer, int32 x1, int32 x2, uint32 g, uint32 t, uint32 dgdx, uint32 dtdx) {
#if defined(USE_MODE_5) uint16* pixel = buffer + x1;
uint16* pixel = buffer + x1;
if (x1 & 1) { int32 width = x2 - x1;
*pixel++ = FETCH_GT_PAL();
t += dtdx;
g += dgdx;
x1++;
if (x1 >= x2) { dgdx <<= 1;
return;
}
}
int32 width2 = (x2 - x1) >> 1; while (width--) {
PUT_PIXEL_GT();
pixel++;
t += dtdx;
dgdx <<= 1; if (width) {
while (width2--) {
uint32 p = FETCH_GT_PAL();
t += dtdx;
p |= FETCH_GT_PAL() << 16;
t += dtdx;
g += dgdx;
*(uint32*)pixel = p;
pixel += 2;
}
if (x2 & 1) {
*pixel++ = FETCH_GT_PAL();
}
#elif defined(USE_MODE_4)
uint8* pixel = (uint8*)buffer + x1;
// align to 2
if (x1 & 1)
{
pixel--;
*(uint16*)pixel = *pixel | (FETCH_GT() << 8);
pixel += 2;
t += dtdx;
g += dgdx;
x1++;
}
int32 width = (x2 - x1) >> 1;
dgdx <<= 1;
// align to 4
if (width && (x1 & 3))
{
*(uint16*)pixel = FETCH_GT2(g, t, dgdx, dtdx);
pixel += 2;
width--; width--;
} PUT_PIXEL_GT();
pixel++;
// fast line
if (width > 0)
{
while (width)
{
uint32 p = FETCH_GT2(g, t, dgdx, dtdx);
if (width > 1) {
// write 4 px
p |= (FETCH_GT2(g, t, dgdx, dtdx) << 16);
*(uint32*)pixel = p;
pixel += 4;
width -= 2;
continue;
}
// write 2 px, end of fast line
*(uint16*)pixel = p;
pixel += 2;
width -= 1;
}
}
// write 1 px, end of scanline
if (x2 & 1)
{
*(uint16*)pixel = (*(uint16*)pixel & 0xFF00) | FETCH_GT();
}
#else
if (x1 & 1)
{
*((uint8*)buffer + x1) = FETCH_GT();
t += dtdx; t += dtdx;
g += dgdx;
x1++;
} }
int32 width = (x2 - x1) >> 1; g += dgdx;
uint16* pixel = (uint16*)((uint8*)buffer + x1); }
dgdx <<= 1;
if (width && (x1 & 3))
{
uint16 p = FETCH_GT();
t += dtdx;
*pixel++ = p | (FETCH_GT() << 8);
t += dtdx;
g += dgdx;
width--;
}
while (width-- > 0)
{
uint32 p = FETCH_GT();
t += dtdx;
p |= (FETCH_GT() << 8);
t += dtdx;
g += dgdx;
if (width-- > 0)
{
p |= (FETCH_GT() << 16);
t += dtdx;
p |= (FETCH_GT() << 24);
t += dtdx;
g += dgdx;
*(uint32*)pixel = p;
pixel += 2;
} else {
*(uint16*)pixel = p;
pixel += 1;
}
}
if (x2 & 1)
{
*((uint8*)pixel) = FETCH_GT();
}
#endif
} }
INLINE void scanlineFT(uint16* buffer, int32 x1, int32 x2, uint32 t, uint32 dtdx) { INLINE void scanlineFT(uint16* buffer, int32 x1, int32 x2, uint32 t, uint32 dtdx) {
#if defined(USE_MODE_5) uint16* pixel = buffer + x1;
uint16* pixel = buffer + x1;
if (x1 & 1) { int32 width = x2 - x1;
*pixel++ = FETCH_GT_PAL();
t += dtdx;
g += dgdx;
x1++;
if (x1 >= x2) { while (width--) {
return; PUT_PIXEL_FT();
} pixel++;
} t += dtdx;
int32 width2 = (x2 - x1) >> 1; if (width) {
dgdx <<= 1;
while (width2--) {
uint32 p = FETCH_GT_PAL();
t += dtdx;
p |= FETCH_GT_PAL() << 16;
t += dtdx;
g += dgdx;
*(uint32*)pixel = p;
pixel += 2;
}
if (x2 & 1) {
*pixel++ = FETCH_GT_PAL();
}
#elif defined(USE_MODE_4)
uint8* pixel = (uint8*)buffer + x1;
// align to 2
if (x1 & 1)
{
pixel--;
*(uint16*)pixel = *pixel | (FETCH_FT() << 8);
pixel += 2;
t += dtdx;
x1++;
}
int32 width = (x2 - x1) >> 1;
// align to 4
if (width && (x1 & 3))
{
*(uint16*)pixel = FETCH_FT2(t, dtdx);
pixel += 2;
width--; width--;
} PUT_PIXEL_FT();
pixel++;
// fast line
if (width > 0)
{
while (width)
{
uint32 p = FETCH_FT2(t, dtdx);
if (width > 1) {
// write 4 px
p |= (FETCH_FT2(t, dtdx) << 16);
*(uint32*)pixel = p;
pixel += 4;
width -= 2;
continue;
}
// write 2 px, end of fast line
*(uint16*)pixel = p;
pixel += 2;
width -= 1;
}
}
// write 1 px, end of scanline
if (x2 & 1)
{
*(uint16*)pixel = (*(uint16*)pixel & 0xFF00) | FETCH_FT();
}
#else
if (x1 & 1)
{
*((uint8*)buffer + x1) = FETCH_GT();
t += dtdx; t += dtdx;
g += dgdx;
x1++;
} }
}
int32 width = (x2 - x1) >> 1;
uint16* pixel = (uint16*)((uint8*)buffer + x1);
dgdx <<= 1;
if (width && (x1 & 3))
{
uint16 p = FETCH_GT();
t += dtdx;
*pixel++ = p | (FETCH_GT() << 8);
t += dtdx;
g += dgdx;
width--;
}
while (width-- > 0)
{
uint32 p = FETCH_GT();
t += dtdx;
p |= (FETCH_GT() << 8);
t += dtdx;
g += dgdx;
if (width-- > 0)
{
p |= (FETCH_GT() << 16);
t += dtdx;
p |= (FETCH_GT() << 24);
t += dtdx;
g += dgdx;
*(uint32*)pixel = p;
pixel += 2;
} else {
*(uint16*)pixel = p;
pixel += 1;
}
}
if (x2 & 1)
{
*((uint8*)pixel) = FETCH_GT();
}
#endif
} }
void rasterizeG(int16 y, int32 palIndex, Edge &L, Edge &R) { void rasterizeG(int16 y, int32 palIndex, Edge &L, Edge &R) {
uint16 *buffer = (uint16*)fb + y * (WIDTH / PIXEL_SIZE); uint16 *buffer = (uint16*)fb + y * WIDTH;
while (1) while (1)
{ {
@@ -884,7 +540,7 @@ void rasterizeG(int16 y, int32 palIndex, Edge &L, Edge &R) {
scanlineG(buffer, x1, x2, palIndex, L.g >> 8, dgdx); scanlineG(buffer, x1, x2, palIndex, L.g >> 8, dgdx);
} }
buffer += WIDTH / PIXEL_SIZE; buffer += WIDTH;
L.stepG(); L.stepG();
R.stepG(); R.stepG();
@@ -893,7 +549,7 @@ void rasterizeG(int16 y, int32 palIndex, Edge &L, Edge &R) {
} }
void rasterizeGT(int16 y, Edge &L, Edge &R) { void rasterizeGT(int16 y, Edge &L, Edge &R) {
uint16 *buffer = (uint16*)fb + y * (WIDTH / PIXEL_SIZE); uint16 *buffer = (uint16*)fb + y * WIDTH;
while (1) while (1)
{ {
@@ -935,7 +591,7 @@ void rasterizeGT(int16 y, Edge &L, Edge &R) {
scanlineGT(buffer, x1, x2, L.g >> 8, L.t.uv, dgdx, dtdx); scanlineGT(buffer, x1, x2, L.g >> 8, L.t.uv, dgdx, dtdx);
}; };
buffer += WIDTH / PIXEL_SIZE; buffer += WIDTH;
L.stepGT(); L.stepGT();
R.stepGT(); R.stepGT();
@@ -944,7 +600,7 @@ void rasterizeGT(int16 y, Edge &L, Edge &R) {
} }
void rasterizeFT(int16 y, Edge &L, Edge &R) { void rasterizeFT(int16 y, Edge &L, Edge &R) {
uint16 *buffer = (uint16*)fb + y * (WIDTH / PIXEL_SIZE); uint16 *buffer = (uint16*)fb + y * WIDTH;
ft_lightmap = &lightmap[(L.vert[0]->v.g << 8) & 0x1F00]; ft_lightmap = &lightmap[(L.vert[0]->v.g << 8) & 0x1F00];
@@ -986,7 +642,7 @@ void rasterizeFT(int16 y, Edge &L, Edge &R) {
scanlineFT(buffer, x1, x2, L.t.uv, dtdx); scanlineFT(buffer, x1, x2, L.t.uv, dtdx);
}; };
buffer += WIDTH / PIXEL_SIZE; buffer += WIDTH;
L.stepFT(); L.stepFT();
R.stepFT(); R.stepFT();
@@ -999,7 +655,9 @@ void drawTriangle(const Face* face, VertexUV *v) {
*v2 = v + 1, *v2 = v + 1,
*v3 = v + 2; *v3 = v + 2;
sortVertices(v1, v2, v3); if (v1->v.y > v2->v.y) swap(v1, v2);
if (v1->v.y > v3->v.y) swap(v1, v3);
if (v2->v.y > v3->v.y) swap(v2, v3);
int32 temp = (v2->v.y - v1->v.y) * FixedInvU(v3->v.y - v1->v.y); int32 temp = (v2->v.y - v1->v.y) * FixedInvU(v3->v.y - v1->v.y);
@@ -1020,9 +678,7 @@ void drawTriangle(const Face* face, VertexUV *v) {
L.vert[0] = v3; L.vert[0] = v3;
L.vert[1] = v1; L.vert[1] = v1;
L.index = 1; L.index = 1;
} } else {
else
{
L.vert[0] = v3; L.vert[0] = v3;
L.vert[1] = v2; L.vert[1] = v2;
L.vert[2] = v1; L.vert[2] = v1;
@@ -1049,23 +705,35 @@ void drawQuad(const Face* face, VertexUV *v) {
*v3 = v + 2, *v3 = v + 2,
*v4 = v + 3; *v4 = v + 3;
int32 minY = 0x7FFF;
int32 maxY = -0x7FFF;
int32 t = 0, b = 0;
VertexUV* poly[8] = { v1, v2, v3, v4, v1, v2, v3, v4 }; VertexUV* poly[8] = { v1, v2, v3, v4, v1, v2, v3, v4 };
for (int32 i = 0; i < 4; i++) { int32 t, b;
VertexUV *v = poly[i];
if (v->v.y < minY) { if (v1->v.y < v2->v.y) {
minY = v->v.y; if (v1->v.y < v3->v.y) {
t = i; t = (v1->v.y < v4->v.y) ? 0 : 3;
} else {
t = (v3->v.y < v4->v.y) ? 2 : 3;
} }
} else {
if (v2->v.y < v3->v.y) {
t = (v2->v.y < v4->v.y) ? 1 : 3;
} else {
t = (v3->v.y < v4->v.y) ? 2 : 3;
}
}
if (v->v.y > maxY) { if (v1->v.y > v2->v.y) {
maxY = v->v.y; if (v1->v.y > v3->v.y) {
b = i; b = (v1->v.y > v4->v.y) ? 0 : 3;
} else {
b = (v3->v.y > v4->v.y) ? 2 : 3;
}
} else {
if (v2->v.y > v3->v.y) {
b = (v2->v.y > v4->v.y) ? 1 : 3;
} else {
b = (v3->v.y > v4->v.y) ? 2 : 3;
} }
} }
@@ -1163,53 +831,28 @@ void drawGlyph(const Sprite *sprite, int32 x, int32 y) {
int32 ix = x + sprite->l; int32 ix = x + sprite->l;
int32 iy = y + sprite->t; int32 iy = y + sprite->t;
uint16* ptr = (uint16*)fb + iy * (WIDTH / PIXEL_SIZE); uint16* ptr = (uint16*)fb + iy * WIDTH;
#ifdef USE_MODE_5
ptr += ix; ptr += ix;
#else
ptr += ix >> 1;
#endif
const uint8* glyphData = tiles + (sprite->tile << 16) + 256 * sprite->v + sprite->u; const uint8* glyphData = tiles + (sprite->tile << 16) + 256 * sprite->v + sprite->u;
while (h--) while (h--)
{ {
#ifdef USE_MODE_5
for (int32 i = 0; i < w; i++) { for (int32 i = 0; i < w; i++) {
if (glyphData[i] == 0) continue; if (glyphData[i] == 0) continue;
ptr[i] = palette[glyphData[i]]; ptr[i] = palette[glyphData[i]];
} }
#else
const uint8* p = glyphData;
for (int32 i = 0; i < (w / 2); i++) { ptr += WIDTH;
if (p[0] || p[1]) {
uint16 d = ptr[i];
if (p[0]) d = (d & 0xFF00) | p[0];
if (p[1]) d = (d & 0x00FF) | (p[1] << 8);
ptr[i] = d;
}
p += 2;
}
#endif
ptr += WIDTH / PIXEL_SIZE;
glyphData += 256; glyphData += 256;
} }
} }
void faceAddQuad(uint32 flags, const Index* indices, int32 startVertex) { void faceAddQuad(uint32 flags, const Index* indices, int32 startVertex) {
#if defined(_WIN32) ASSERT(gFacesCount < MAX_FACES);
if (gFacesCount >= MAX_FACES) {
DebugBreak();
}
#endif
Vertex* v = gVertices + startVertex; Vertex* v = gVertices + startVertex;
Vertex* v1 = v + indices[0]; Vertex* v1 = v + indices[0];
Vertex* v2 = v + indices[1]; Vertex* v2 = v + indices[1];
@@ -1247,11 +890,8 @@ void faceAddQuad(uint32 flags, const Index* indices, int32 startVertex) {
} }
void faceAddTriangle(uint32 flags, const Index* indices, int32 startVertex) { void faceAddTriangle(uint32 flags, const Index* indices, int32 startVertex) {
#if defined(_WIN32) ASSERT(gFacesCount < MAX_FACES);
if (gFacesCount >= MAX_FACES) {
DebugBreak();
}
#endif
Vertex* v = gVertices + startVertex; Vertex* v = gVertices + startVertex;
Vertex* v1 = v + indices[0]; Vertex* v1 = v + indices[0];
Vertex* v2 = v + indices[1]; Vertex* v2 = v + indices[1];
@@ -1286,7 +926,7 @@ void faceAddTriangle(uint32 flags, const Index* indices, int32 startVertex) {
f->indices[2] = indices[2] - indices[0]; f->indices[2] = indices[2] - indices[0];
} }
void faceAdd_room(const Quad* quads, int32 qCount, const Triangle* triangles, int32 tCount, int32 startVertex) void faceAddRoom(const Quad* quads, int32 qCount, const Triangle* triangles, int32 tCount, int32 startVertex)
{ {
for (uint16 i = 0; i < qCount; i++) { for (uint16 i = 0; i < qCount; i++) {
faceAddQuad(quads[i].flags, quads[i].indices, startVertex); faceAddQuad(quads[i].flags, quads[i].indices, startVertex);
@@ -1297,7 +937,7 @@ void faceAdd_room(const Quad* quads, int32 qCount, const Triangle* triangles, in
} }
} }
void faceAdd_mesh(const Quad* rFaces, const Quad* crFaces, const Triangle* tFaces, const Triangle* ctFaces, int32 rCount, int32 crCount, int32 tCount, int32 ctCount, int32 startVertex) void faceAddMesh(const Quad* rFaces, const Quad* crFaces, const Triangle* tFaces, const Triangle* ctFaces, int32 rCount, int32 crCount, int32 tCount, int32 ctCount, int32 startVertex)
{ {
for (int i = 0; i < rCount; i++) { for (int i = 0; i < rCount; i++) {
faceAddQuad(rFaces[i].flags, rFaces[i].indices, startVertex); faceAddQuad(rFaces[i].flags, rFaces[i].indices, startVertex);
@@ -1359,6 +999,9 @@ void flush() {
v[1].t.uv = tex.uv1; v[1].t.uv = tex.uv1;
v[2].t.uv = tex.uv2; v[2].t.uv = tex.uv2;
v[3].t.uv = tex.uv3; v[3].t.uv = tex.uv3;
palette[0] = (tex.attribute == 1) ? PAL_COLOR_TRANSP : PAL_COLOR_BLACK;
} else {
palette[0] = PAL_COLOR_BLACK;
} }
Vertex *p = gVertices + face->start; Vertex *p = gVertices + face->start;
@@ -1397,14 +1040,6 @@ void flush() {
gFacesCount = 0; gFacesCount = 0;
} }
void initRender() {
divTable[0] = 0xFFFF;
divTable[1] = 0xFFFF;
for (uint32 i = 2; i < DIV_TABLE_SIZE; i++) {
divTable[i] = (1 << 16) / i;
}
}
void dmaClear(uint32 *dst, uint32 count) { void dmaClear(uint32 *dst, uint32 count) {
#ifdef __GBA__ #ifdef __GBA__
vu32 value = 0; vu32 value = 0;
@@ -1417,5 +1052,5 @@ void dmaClear(uint32 *dst, uint32 count) {
} }
void clear() { void clear() {
dmaClear((uint32*)fb, (WIDTH * HEIGHT) >> PIXEL_SIZE); dmaClear((uint32*)fb, (WIDTH * HEIGHT) >> 1);
} }