1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-03-13 23:59:41 +01: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"
#define CAM_SPEED (1 << 2)
#define CAM_ROT_SPEED (1 << 8)
#define CAM_SPEED (1 << 3)
#define CAM_ROT_SPEED (1 << 9)
#define CAM_ROT_X_MAX int16(85 * 0x8000 / 180)
struct Camera {
@ -19,6 +19,9 @@ struct Camera {
rotX = 0;
rotY = 16 << 8;
//rotX = -0x1000;
//rotY = int16(0x8000);
}
void update() {
@ -29,7 +32,7 @@ struct Camera {
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();
@ -57,7 +60,7 @@ struct Camera {
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"
vec3i viewPos;
extern Matrix matrixStack[MAX_MATRICES];
extern int32 matrixStackIndex;
uint16 divTable[DIV_TABLE_SIZE]; // IWRAM 0.5 kb
vec3i viewPos;
Matrix matrixStack[MAX_MATRICES];
int32 matrixStackIndex = 0;
const int16 sin_table[1025] = { // IWRAM 2 kb
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);
}
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];
}
void matrixPush() {
#if defined(_WIN32)
if (matrixStackIndex >= MAX_MATRICES - 1) {
DebugBreak();
return;
}
#endif
void matrixPush()
{
ASSERT(matrixStackIndex < MAX_MATRICES - 1);
Matrix &a = matrixStack[matrixStackIndex++];
Matrix &b = matrixStack[matrixStackIndex];
memcpy(b, a, sizeof(Matrix));
}
void matrixPop() {
#if defined(_WIN32)
if (matrixStackIndex <= 0) {
DebugBreak();
return;
}
#endif
void matrixPop()
{
ASSERT(matrixStackIndex > 0);
matrixStackIndex--;
}
void matrixTranslate(const vec3i &offset) {
void matrixTranslate(int32 x, int32 y, int32 z)
{
Matrix &m = matrixGet();
m[0].w += DP33(m[0], offset);
m[1].w += DP33(m[1], offset);
m[2].w += DP33(m[2], offset);
vec3i offset(x, y, z);
m[0][3] += DP33(m[0], 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;
d.x = offset.x - viewPos.x;
d.y = offset.y - viewPos.y;
d.z = offset.z - viewPos.z;
d.x = x - viewPos.x;
d.y = y - viewPos.y;
d.z = z - viewPos.z;
Matrix &m = matrixGet();
m[0].w = DP33(m[0], d);
m[1].w = DP33(m[1], d);
m[2].w = DP33(m[2], d);
m[0][3] = DP33(m[0], d);
m[1][3] = DP33(m[1], 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) {
int32 sx = phd_sin(rotX);
int32 cx = phd_cos(rotX);
int32 sy = phd_sin(rotY);
int32 cy = phd_cos(rotY);
Matrix &m = matrixGet();
int32 a, b;
a = c * m[0][1] + s * m[0][2];
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();
m[0].x = cy;
m[0].y = 0;
m[0].z = -sy;
m[0].w = pos.x;
m[0][0] = cy;
m[0][1] = 0;
m[0][2] = -sy;
m[0][3] = x;
m[1].x = (sx * sy) >> FIXED_SHIFT;
m[1].y = cx;
m[1].z = (sx * cy) >> FIXED_SHIFT;
m[1].w = pos.y;
m[1][0] = (sx * sy) >> FIXED_SHIFT;
m[1][1] = cx;
m[1][2] = (sx * cy) >> FIXED_SHIFT;
m[1][3] = y;
m[2].x = (cx * sy) >> FIXED_SHIFT;
m[2].y = -sx;
m[2].z = (cx * cy) >> FIXED_SHIFT;
m[2].w = pos.z;
m[2][0] = (cx * sy) >> FIXED_SHIFT;
m[2][1] = -sx;
m[2][2] = (cx * cy) >> FIXED_SHIFT;
m[2][3] = z;
viewPos = pos;
viewPos.x = x;
viewPos.y = y;
viewPos.z = z;
}

View File

@ -22,47 +22,25 @@
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <limits.h>
//#define DEBUG_OVERDRAW
//#define DEBUG_FACES
//#define USE_MODE_5 1
#define USE_MODE_4 1
#define SCALE 1
#if defined(__TNS__)
#define WIDTH SCREEN_WIDTH
#define HEIGHT SCREEN_HEIGHT
#define FRAME_WIDTH (WIDTH/SCALE)
#define FRAME_HEIGHT (HEIGHT/SCALE)
#define FRAME_WIDTH WIDTH
#define FRAME_HEIGHT HEIGHT
#define FOV_SHIFT 8
#else
#ifdef USE_MODE_5
#define WIDTH 160
#define HEIGHT 128
#define FRAME_WIDTH 160
#define FRAME_HEIGHT 128
#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
#define WIDTH 160
#define HEIGHT 128
#define FRAME_WIDTH 160
#define FRAME_HEIGHT 128
#define FOV_SHIFT 7
#endif
#if defined(_WIN32)
@ -116,6 +94,12 @@ typedef int16 Index;
#define ALIGN4 __attribute__((aligned(4)))
#endif
#if defined(_WIN32)
#define ASSERT(x) { if (!(x)) { DebugBreak(); } }
#else
#define ASSERT(x)
#endif
#ifdef PROFILE
#if defined(_WIN32)
@ -189,6 +173,11 @@ struct vec3s {
struct vec4i {
int32 x, y, z, w;
INLINE int32& operator [] (int32 index) const {
ASSERT(index >= 0 && index <= 3);
return ((int32*)this)[index];
}
};
typedef vec4i Matrix[3];
@ -203,12 +192,16 @@ struct Triangle {
uint16 flags;
};
struct Room {
struct Info {
int32 x, z;
int32 yBottom, yTop;
};
struct Box {
int16 minX;
int16 maxX;
int16 minY;
int16 maxY;
int16 minZ;
int16 maxZ;
};
struct RoomInfo {
struct Vertex {
vec3s pos;
uint16 lighting;
@ -242,14 +235,17 @@ struct Room {
};
struct Mesh {
// int32 x, y, z;
// uint16 rotation;
// uint16 intensity;
// uint16 meshID;
uint8 dummy[18];
int16 pos[6]; // TODO align struct (int32 x, y, z)
int16 rotation;
uint16 intensity;
uint16 staticMeshId;
};
Info info;
int32 x;
int32 z;
int32 yBottom;
int32 yTop;
uint32 dataSize;
/*
uint16 vCount;
@ -275,39 +271,89 @@ struct Model {
uint32 type;
uint16 mCount;
uint16 mStart;
uint32 node;
uint32 frame;
uint16 animation;
uint16 paddding;
uint32 nodeIndex;
uint32 frameIndex;
uint16 animIndex;
uint16 _padding;
};
#define FILE_MODEL_SIZE (sizeof(Model) - 2) // -padding
struct Entity {
uint16 type;
uint16 room;
vec3i pos;
int16 rotation;
uint16 flags;
struct StaticMesh {
int32 id;
uint16 meshIndex;
Box vbox;
Box cbox;
uint16 flags;
};
struct EntityDesc { // 32 bytes
struct ItemInfo { // 24
uint16 type;
uint16 flags;
int16 room;
vec3i pos;
int16 angleY;
uint16 intensity;
vec3s rot;
uint8 state;
uint8 targetState;
union {
struct {
uint16 gravity:1; // TODO
};
uint16 value;
} flags;
uint8 vSpeed;
uint8 hSpeed;
uint8 room;
uint8 modelIndex;
uint16 _padding;
};
#define FILE_ITEM_SIZE (sizeof(ItemInfo) - 2)
struct Item : ItemInfo { // 24 + 20 = 44
int16 angleX;
int16 angleZ;
uint16 vSpeed;
uint16 hSpeed;
uint16 animIndex;
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 {
@ -352,7 +398,7 @@ union UV {
struct VertexUV {
Vertex v;
UV t;
UV t;
};
struct Face {
@ -371,12 +417,19 @@ struct Face {
extern uint32 dbg_poly_count;
#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 MAX_MATRICES 8
#define MAX_MODELS 64
#define MAX_ENTITY 190
#define MAX_VERTICES 1024
#define MAX_ITEMS 256
#define MAX_MESHES 50
#define MAX_VERTICES 2048
#define MAX_FACES 512
#define FOG_SHIFT 1
#define FOG_MAX (10 * 1024)
@ -390,6 +443,10 @@ struct Face {
#define FACE_FLAT 0x1000
#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 MAX(a,b) ((a) > (b) ? (a) : (b))
#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 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 phd_sin(int32 x);
int32 phd_cos(int32 x);
void initLUT();
Matrix& matrixGet();
void matrixPush();
void matrixPop();
void matrixTranslate(const vec3i &offset);
void matrixTranslateAbs(const vec3i &offset);
void matrixRotate(int16 rotX, int16 rotY, int16 rotZ);
void matrixSetView(const vec3i &pos, int16 rotX, int16 rotY);
void matrixTranslate(int32 x, int32 y, int32 z);
void matrixTranslateAbs(int32 x, int32 y, int32 z);
void matrixRotateX(int32 angle);
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 clear();
void transform_room(const Room::Vertex* vertices, int32 vCount);
void transform_mesh(const vec3s* vertices, int32 vCount);
void faceAdd_room(const Quad* quads, int32 qCount, const Triangle* triangles, int32 tCount, int32 startVertex);
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);
bool boxIsVisible(const Box* box);
void transformRoom(const RoomInfo::Vertex* vertices, int32 vCount);
void transformMesh(const vec3s* vertices, int32 vCount, uint16 intensity);
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 initRender();
void readLevel(const uint8 *data);
const Room::Sector* getSector(int32 roomIndex, int32 x, int32 z);
int32 getRoomIndex(int32 roomIndex, const vec3i &pos);
const RoomInfo::Sector* getSector(int32 roomIndex, int32 x, int32 z);
int32 getRoomIndex(int32 roomIndex, const vec3i* pos);
#endif

View File

@ -4,72 +4,82 @@
#include "common.h"
#include "camera.h"
#define GRAVITY 6
// level file data -------------------
uint32 tilesCount;
int32 tilesCount;
extern const uint8* tiles;
#if defined(USE_MODE_5) || defined(_WIN32)
extern uint16 palette[256];
#endif
extern uint16 palette[256];
extern uint8 lightmap[256 * 32];
uint16 roomsCount;
const uint16* floors;
uint32 texturesCount;
int32 texturesCount;
extern const Texture* textures;
const Sprite* sprites;
uint32 spritesSeqCount;
int32 spritesSeqCount;
const SpriteSeq* spritesSeq;
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 int16 modelsMap[MAX_ENTITY];
EWRAM_DATA uint8 modelsMap[MAX_ITEMS];
EWRAM_DATA uint8 staticMeshesMap[MAX_MESHES];
uint32 entitiesCount;
const Entity* entities;
int32 staticMeshesCount;
const StaticMesh* staticMeshes;
int32 itemsCount;
EWRAM_DATA Item items[MAX_ITEMS];
// -----------------------------------
struct RoomDesc {
struct Room {
Rect clip;
uint8 firstItem;
bool visible;
// TODO leave in ROM
int32 x, z;
uint16 vCount;
uint16 qCount;
uint16 tCount;
uint16 pCount;
uint16 lCount;
uint16 mCount;
uint16 zSectors;
uint16 xSectors;
const Room::Vertex* vertices;
const Quad* quads;
const Triangle* triangles;
const Room::Portal* portals;
const Room::Sector* sectors;
uint16 ambient;
INLINE void reset() {
visible = false;
clip = { FRAME_WIDTH, FRAME_HEIGHT, 0, 0 };
}
const RoomInfo::Vertex* vertices;
const Quad* quads;
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 visRooms[16];
#define ROOM_VISIBLE (1 << 15)
#define ENTITY_LARA 0
#define SEQ_GLYPH 190
enum FloorType {
@ -80,51 +90,145 @@ enum FloorType {
};
int32 seqGlyphs;
int32 entityLara;
extern uint32 gVerticesCount;
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
tilesCount = *((uint32*)(data + 4));
tilesCount = *((int32*)(data + 4));
tiles = data + 8;
#define MDL_OFF 2
#define ENT_OFF 2
#define ITM_OFF 2
roomsCount = *((uint16*)(data + 720908));
const Room* roomsPtr = (Room*)(data + 720908 + 2);
roomsCount = *((int16*)(data + 720908));
const RoomInfo* roomsPtr = (RoomInfo*)(data + 720908 + 2);
floors = (uint16*)(data + 899492 + 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);
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);
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);
entitiesCount = *((uint32*)(data + 1319252 + MDL_OFF + ENT_OFF));
entities = (Entity*)(data + 1319252 + 4 + MDL_OFF + ENT_OFF);
itemsCount = *((int32*)(data + 1319252 + MDL_OFF + ITM_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
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));
// prepare palette
#if !(defined(USE_MODE_5) || defined(_WIN32))
uint16 palette[256];
#endif
const uint8* f_palette = data + 1328768 + MDL_OFF + ENT_OFF;
const uint8* f_palette = data + 1328768 + MDL_OFF + ITM_OFF;
const uint8* p = f_palette;
@ -137,59 +241,33 @@ void readLevel(const uint8 *data) { // TODO non-hardcode level loader, added *_O
#endif
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
uint8 *ptr = (uint8*)roomsPtr;
for (uint16 roomIndex = 0; roomIndex < roomsCount; roomIndex++) {
const Room *room = (Room*)ptr;
ptr += sizeof(Room);
for (int32 roomIndex = 0; roomIndex < roomsCount; roomIndex++)
{
const RoomInfo *room = (RoomInfo*)ptr;
ptr += sizeof(RoomInfo);
uint32 dataSize;
memcpy(&dataSize, &room->dataSize, sizeof(dataSize));
uint8* skipPtr = ptr + dataSize * 2;
RoomDesc &desc = rooms[roomIndex];
desc.reset();
Room &desc = rooms[roomIndex];
roomReset(roomIndex);
desc.firstItem = NO_ITEM;
// offset
memcpy(&desc.x, &room->info.x, sizeof(room->info.x));
memcpy(&desc.z, &room->info.z, sizeof(room->info.z));
memcpy(&desc.x, &room->x, sizeof(room->x));
memcpy(&desc.z, &room->z, sizeof(room->z));
// vertices
desc.vCount = *((uint16*)ptr);
ptr += 2;
desc.vertices = (Room::Vertex*)ptr;
ptr += sizeof(Room::Vertex) * desc.vCount;
desc.vertices = (RoomInfo::Vertex*)ptr;
ptr += sizeof(RoomInfo::Vertex) * desc.vCount;
// quads
desc.qCount = *((uint16*)ptr);
@ -208,38 +286,99 @@ void readLevel(const uint8 *data) { // TODO non-hardcode level loader, added *_O
// portals
desc.pCount = *((uint16*)ptr);
ptr += 2;
desc.portals = (Room::Portal*)ptr;
ptr += sizeof(Room::Portal) * desc.pCount;
desc.portals = (RoomInfo::Portal*)ptr;
ptr += sizeof(RoomInfo::Portal) * desc.pCount;
desc.zSectors = *((uint16*)ptr);
ptr += 2;
desc.xSectors = *((uint16*)ptr);
ptr += 2;
desc.sectors = (Room::Sector*)ptr;
ptr += sizeof(Room::Sector) * desc.zSectors * desc.xSectors;
desc.sectors = (RoomInfo::Sector*)ptr;
ptr += sizeof(RoomInfo::Sector) * desc.zSectors * desc.xSectors;
//ambient = *((uint16*)ptr);
desc.ambient = *((uint16*)ptr);
ptr += 2;
uint16 lightsCount = *((uint16*)ptr);
desc.lCount = *((uint16*)ptr);
ptr += 2;
//lights = (Room::Light*)ptr;
ptr += sizeof(Room::Light) * lightsCount;
desc.lights = (RoomInfo::Light*)ptr;
ptr += sizeof(RoomInfo::Light) * desc.lCount;
uint16 meshesCount = *((uint16*)ptr);
desc.mCount = *((uint16*)ptr);
ptr += 2;
//meshes = (Room::Mesh*)ptr;
ptr += sizeof(Room::Mesh) * meshesCount;
desc.meshes = (RoomInfo::Mesh*)ptr;
ptr += sizeof(RoomInfo::Mesh) * desc.mCount;
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.room = entities[entityLara].room;
camera.room = 0;
}
void drawMesh(int16 meshIndex) {
uint32 offset = meshOffsets[meshIndex];
void drawMesh(int16 meshIndex, uint16 intensity) {
int32 offset = meshOffsets[meshIndex];
const uint8* ptr = meshData + offset;
ptr += 2 * 5; // skip [cx, cy, cz, radius, flags]
@ -271,52 +410,67 @@ void drawMesh(int16 meshIndex) {
int32 startVertex = gVerticesCount;
PROFILE_START();
transform_mesh(vertices, vCount);
transformMesh(vertices, vCount, intensity);
PROFILE_STOP(dbg_transform);
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);
}
void drawModel(int32 modelIndex) {
const Model* model = models + modelIndex;
Frame* getFrame(const Item* item, const Model* model)
{
const Anim* anim = anims + item->animIndex;
// non-aligned access
uint32 node, frame;
memcpy(&node, &model->node, sizeof(node));
memcpy(&frame, &model->frame, sizeof(frame));
int32 frameSize = sizeof(Frame) / 2 + model->mCount * 2;
int32 frameIndex = (item->frameIndex - anim->frameBegin) / anim->frameRate;//* FixedInvU(anim->frameRate) >> 16;
Node bones[32];
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);
}
return (Frame*)(frames + anim->frameOffset / 2 + frameIndex * frameSize);
}
void drawEntity(int32 entityIndex) {
const Entity &e = entities[entityIndex];
void drawItem(const Item* item) {
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();
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();
}
@ -333,39 +487,62 @@ void drawNumber(int32 number, int32 x, int32 y) {
}
}
extern vec3i viewPos;
extern Vertex gVertices[MAX_VERTICES];
void drawRoom(int32 roomIndex) {
const Room* room = rooms + roomIndex;
void drawRoom(int16 roomIndex) {
RoomDesc &room = rooms[roomIndex];
clip = room.clip;
clip = room->clip;
int32 startVertex = gVerticesCount;
matrixPush();
matrixTranslateAbs(vec3i(room.x, 0, room.z));
matrixTranslateAbs(room->x, 0, room->z);
PROFILE_START();
transform_room(room.vertices, room.vCount);
transformRoom(room->vertices, room->vCount);
PROFILE_STOP(dbg_transform);
matrixPop();
PROFILE_START();
faceAdd_room(room.quads, room.qCount, room.triangles, room.tCount, startVertex);
if (roomIndex == entityLara) { // TODO draw all entities in the room
drawEntity(entityLara);
faceAddRoom(room->quads, room->qCount, room->triangles, room->tCount, startVertex);
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);
room.reset();
roomReset(roomIndex);
flush();
}
const Room::Sector* getSector(int32 roomIndex, int32 x, int32 z) {
RoomDesc &room = rooms[roomIndex];
const RoomInfo::Sector* getSector(int32 roomIndex, int32 x, int32 z) {
Room &room = rooms[roomIndex];
int32 sx = clamp((x - room.x) >> 10, 0, room.xSectors - 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;
}
int32 getRoomIndex(int32 roomIndex, const vec3i &pos) {
const Room::Sector *sector = getSector(roomIndex, pos.x, pos.z);
int32 getRoomIndex(int32 roomIndex, const vec3i* pos) {
const RoomInfo::Sector *sector = getSector(roomIndex, pos->x, pos->z);
if (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;
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;
sector = getSector(roomIndex, pos.x, pos.z);
sector = getSector(roomIndex, pos->x, pos->z);
}
return roomIndex;
}
bool checkPortal(int32 roomIndex, const Room::Portal &portal) {
RoomDesc &room = rooms[roomIndex];
bool checkPortal(int32 roomIndex, const RoomInfo::Portal* portal) {
Room &room = rooms[roomIndex];
vec3i d;
d.x = portal.v[0].x - camera.pos.x + room.x;
d.y = portal.v[0].y - camera.pos.y;
d.z = portal.v[0].z - camera.pos.z + room.z;
d.x = portal->v[0].x - camera.pos.x + room.x;
d.y = portal->v[0].y - camera.pos.y;
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;
}
@ -432,7 +609,7 @@ bool checkPortal(int32 roomIndex, const Room::Portal &portal) {
vec3i pv[4];
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 y = DP43(m[1], v);
@ -503,7 +680,7 @@ bool checkPortal(int32 roomIndex, const Room::Portal &portal) {
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 (x1 > nextRoom.clip.x1) nextRoom.clip.x1 = x1;
@ -512,38 +689,123 @@ bool checkPortal(int32 roomIndex, const Room::Portal &portal) {
if (!nextRoom.visible) {
nextRoom.visible = true;
visRooms[visRoomsCount++] = portal.roomIndex;
visRooms[visRoomsCount++] = portal->roomIndex;
}
return true;
}
void getVisibleRooms(int32 roomIndex) {
RoomDesc &room = rooms[roomIndex];
void getVisibleRooms(int32 roomIndex)
{
const Room* room = rooms + roomIndex;
matrixPush();
matrixTranslateAbs(vec3i(room.x, 0, room.z));
matrixTranslateAbs(room->x, 0, room->z);
for (int32 i = 0; i < room.pCount; i++) {
const Room::Portal &portal = room.portals[i];
if (checkPortal(roomIndex, portal)) {
getVisibleRooms(portal.roomIndex);
for (int32 i = 0; i < room->pCount; i++)
{
const RoomInfo::Portal* portal = room->portals + i;
if (checkPortal(roomIndex, portal))
{
getVisibleRooms(portal->roomIndex);
}
}
matrixPop();
}
void drawRooms() {
void drawRooms()
{
rooms[camera.room].clip = { 0, 0, FRAME_WIDTH, FRAME_HEIGHT };
visRoomsCount = 0;
visRooms[visRoomsCount++] = camera.room;
getVisibleRooms(camera.room);
while (visRoomsCount--) {
while (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

View File

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

View File

@ -1,36 +1,28 @@
#include "common.h"
#define DIV_TABLE_SIZE 256
uint16 divTable[DIV_TABLE_SIZE]; // IWRAM 0.5 kb
#if defined(_WIN32)
uint8 fb[WIDTH * HEIGHT * 2];
uint16 fb[WIDTH * HEIGHT];
#elif defined(__GBA__)
uint32 fb = VRAM;
#elif defined(__TNS__)
uint8 fb[WIDTH * HEIGHT];
uint16 fb[WIDTH * HEIGHT];
#endif
#define FixedInvS(x) ((x < 0) ? -divTable[abs(x)] : divTable[x])
#define FixedInvU(x) divTable[x]
#define PAL_COLOR_TRANSP 0x0000
#define PAL_COLOR_BLACK 0x0421
#if defined(USE_MODE_5) || defined(_WIN32)
uint16 palette[256];
#endif
uint8 lightmap[256 * 32]; // IWRAM 8 kb
uint8* ft_lightmap;
const uint8* tiles;
const uint8* tile;
uint16 palette[256]; // IWRAM 0.5 kb
uint8 lightmap[256 * 32]; // IWRAM 8 kb
const uint8* ft_lightmap;
const Texture* textures;
const uint8* tiles;
const uint8* tile;
uint32 gVerticesCount = 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 gFaces[MAX_FACES]; // EWRAM 5 kb
@ -38,9 +30,6 @@ EWRAM_DATA Face gFaces[MAX_FACES]; // EWRAM 5 kb
Rect clip;
Matrix matrixStack[MAX_MATRICES];
int32 matrixStackIndex = 0;
template <class T>
INLINE void swap(T &a, T &b) {
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);
}
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) {
return (v->x < clip.x0 ? 1 : 0) |
(v->x > clip.x1 ? 2 : 0) |
@ -65,14 +48,68 @@ INLINE int32 classify(const Vertex* v) {
(v->y > clip.y1 ? 8 : 0);
}
void transform(const vec3s &v, int32 vg) {
#if defined(_WIN32)
if (gVerticesCount >= MAX_VERTICES) {
DebugBreak();
return;
bool boxIsVisible(const Box* box)
{
const Matrix &m = matrixGet();
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++];
@ -110,7 +147,7 @@ void transform(const vec3s &v, int32 vg) {
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++)
{
@ -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++) {
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_G_PAL(palIndex) 32
#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) {
uint32 p = FETCH_FT();
t += dtdx;
p |= FETCH_FT() << 8;
t += dtdx;
return p;
}
#define FETCH_T() tile[(t & 0xFF00) | (t >> 24)]
#define FETCH_G() lightmap[(g & 0x1F00) | palIndex]
#define FETCH_GT() lightmap[(g & 0x1F00) | FETCH_T()]
#define FETCH_FT() ft_lightmap[FETCH_T()]
INLINE uint32 FETCH_GT2(uint32 &g, uint32 &t, uint32 dgdx, uint32 dtdx) {
#if 0
uint32 light = g & 0x1F00;
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)]
#define PUT_PIXEL_GT() { uint16 p = palette[FETCH_GT()]; if (p) *pixel = p; }
#define PUT_PIXEL_FT() { uint16 p = palette[FETCH_FT()]; if (p) *pixel = p; }
#define PUT_PIXEL_G() { *pixel = palette[FETCH_G()]; }
#endif
struct Edge {
@ -427,426 +439,70 @@ struct Edge {
};
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) {
*pixel++ = FETCH_G_PAL(palIndex);
g += dgdx;
x1++;
int32 width = x2 - x1;
if (x1 >= x2) {
return;
}
}
dgdx <<= 1;
int32 width2 = (x2 - x1) >> 1;
dgdx <<= 1;
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;
while (width--) {
PUT_PIXEL_G();
pixel++;
if (width) {
width--;
PUT_PIXEL_G();
pixel++;
}
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)
{
*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
g += dgdx;
}
}
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) {
*pixel++ = FETCH_GT_PAL();
t += dtdx;
g += dgdx;
x1++;
int32 width = x2 - x1;
if (x1 >= x2) {
return;
}
}
dgdx <<= 1;
int32 width2 = (x2 - x1) >> 1;
while (width--) {
PUT_PIXEL_GT();
pixel++;
t += dtdx;
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_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;
if (width) {
width--;
}
// 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();
PUT_PIXEL_GT();
pixel++;
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
g += dgdx;
}
}
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) {
*pixel++ = FETCH_GT_PAL();
t += dtdx;
g += dgdx;
x1++;
int32 width = x2 - x1;
if (x1 >= x2) {
return;
}
}
while (width--) {
PUT_PIXEL_FT();
pixel++;
t += dtdx;
int32 width2 = (x2 - x1) >> 1;
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;
if (width) {
width--;
}
// 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();
PUT_PIXEL_FT();
pixel++;
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) {
uint16 *buffer = (uint16*)fb + y * (WIDTH / PIXEL_SIZE);
uint16 *buffer = (uint16*)fb + y * WIDTH;
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);
}
buffer += WIDTH / PIXEL_SIZE;
buffer += WIDTH;
L.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) {
uint16 *buffer = (uint16*)fb + y * (WIDTH / PIXEL_SIZE);
uint16 *buffer = (uint16*)fb + y * WIDTH;
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);
};
buffer += WIDTH / PIXEL_SIZE;
buffer += WIDTH;
L.stepGT();
R.stepGT();
@ -944,7 +600,7 @@ void rasterizeGT(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];
@ -986,7 +642,7 @@ void rasterizeFT(int16 y, Edge &L, Edge &R) {
scanlineFT(buffer, x1, x2, L.t.uv, dtdx);
};
buffer += WIDTH / PIXEL_SIZE;
buffer += WIDTH;
L.stepFT();
R.stepFT();
@ -999,7 +655,9 @@ void drawTriangle(const Face* face, VertexUV *v) {
*v2 = v + 1,
*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);
@ -1020,9 +678,7 @@ void drawTriangle(const Face* face, VertexUV *v) {
L.vert[0] = v3;
L.vert[1] = v1;
L.index = 1;
}
else
{
} else {
L.vert[0] = v3;
L.vert[1] = v2;
L.vert[2] = v1;
@ -1049,23 +705,35 @@ void drawQuad(const Face* face, VertexUV *v) {
*v3 = v + 2,
*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 };
for (int32 i = 0; i < 4; i++) {
VertexUV *v = poly[i];
int32 t, b;
if (v->v.y < minY) {
minY = v->v.y;
t = i;
if (v1->v.y < v2->v.y) {
if (v1->v.y < v3->v.y) {
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) {
maxY = v->v.y;
b = i;
if (v1->v.y > v2->v.y) {
if (v1->v.y > v3->v.y) {
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 iy = y + sprite->t;
uint16* ptr = (uint16*)fb + iy * (WIDTH / PIXEL_SIZE);
uint16* ptr = (uint16*)fb + iy * WIDTH;
#ifdef USE_MODE_5
ptr += ix;
#else
ptr += ix >> 1;
#endif
const uint8* glyphData = tiles + (sprite->tile << 16) + 256 * sprite->v + sprite->u;
while (h--)
{
#ifdef USE_MODE_5
for (int32 i = 0; i < w; i++) {
if (glyphData[i] == 0) continue;
ptr[i] = palette[glyphData[i]];
}
#else
const uint8* p = glyphData;
for (int32 i = 0; i < (w / 2); i++) {
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;
ptr += WIDTH;
glyphData += 256;
}
}
void faceAddQuad(uint32 flags, const Index* indices, int32 startVertex) {
#if defined(_WIN32)
if (gFacesCount >= MAX_FACES) {
DebugBreak();
}
#endif
ASSERT(gFacesCount < MAX_FACES);
Vertex* v = gVertices + startVertex;
Vertex* v1 = v + indices[0];
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) {
#if defined(_WIN32)
if (gFacesCount >= MAX_FACES) {
DebugBreak();
}
#endif
ASSERT(gFacesCount < MAX_FACES);
Vertex* v = gVertices + startVertex;
Vertex* v1 = v + indices[0];
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];
}
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++) {
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++) {
faceAddQuad(rFaces[i].flags, rFaces[i].indices, startVertex);
@ -1359,6 +999,9 @@ void flush() {
v[1].t.uv = tex.uv1;
v[2].t.uv = tex.uv2;
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;
@ -1397,14 +1040,6 @@ void flush() {
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) {
#ifdef __GBA__
vu32 value = 0;
@ -1417,5 +1052,5 @@ void dmaClear(uint32 *dst, uint32 count) {
}
void clear() {
dmaClear((uint32*)fb, (WIDTH * HEIGHT) >> PIXEL_SIZE);
dmaClear((uint32*)fb, (WIDTH * HEIGHT) >> 1);
}