1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-11 07:34:33 +02:00

#370 3DO 16-bit room vertices (reduce level data size), use MulManyVec4Mat44_F16 instead of MulManyVec3Mat33DivZ_F16, minor fix for z-clipping and gaps, fix animations and aiming, remove debug data from executable

This commit is contained in:
XProger
2021-11-17 08:27:13 +03:00
parent 2c2ded837d
commit efde681ab5
9 changed files with 535 additions and 439 deletions

View File

@@ -847,34 +847,35 @@ void matrixFrame(const vec3s &pos, const uint32* angles)
matrixRotateYXZ(aX, aY, aZ);
}
#ifndef USE_MATRIX_ASM
#ifdef IWRAM_MATRIX_LERP
void matrixLerp(const Matrix &n, int32 multiplier, int32 divider);
void matrixLerp_c(const Matrix &n, int32 pmul, int32 pdiv);
#else
void matrixLerp(const Matrix &n, int32 multiplier, int32 divider)
void matrixLerp_c(const Matrix &n, int32 pmul, int32 pdiv)
{
Matrix &m = matrixGet();
if ((divider == 2) || ((divider == 4) && (multiplier == 2))) {
if ((pdiv == 2) || ((pdiv == 4) && (pmul == 2))) {
LERP_MATRIX(LERP_1_2);
} else if (divider == 4) {
} else if (pdiv == 4) {
if (multiplier == 1) {
if (pmul == 1) {
LERP_MATRIX(LERP_1_4);
} else {
LERP_MATRIX(LERP_3_4);
}
} else if (divider == 3) {
} else if (pdiv == 3) {
if (multiplier == 1) {
if (pmul == 1) {
LERP_MATRIX(LERP_1_3);
} else {
LERP_MATRIX(LERP_2_3);
}
} else if (divider == 5) {
} else if (pdiv == 5) {
switch (multiplier)
switch (pmul)
{
case 4 : LERP_MATRIX(LERP_4_5); break;
case 3 : LERP_MATRIX(LERP_3_5); break;
@@ -883,10 +884,12 @@ void matrixLerp(const Matrix &n, int32 multiplier, int32 divider)
}
} else {
int32 t = pmul * FixedInvU(pdiv) >> 8;
LERP_MATRIX(LERP_SLOW);
}
}
#endif
#endif
void matrixFrameLerp(const vec3s &pos, const uint32* anglesA, const uint32* anglesB, int32 delta, int32 rate)
{
@@ -942,6 +945,13 @@ void matrixSetIdentity()
m.e21 = 0;
m.e22 = 0x4000;
m.e23 = 0;
#ifdef __3DO__
m.e30 = 0;
m.e31 = 0;
m.e32 = 0;
m.e33 = 0x4000;
#endif
}
void matrixSetView(const vec3i &pos, int32 angleX, int32 angleY)
@@ -968,6 +978,13 @@ void matrixSetView(const vec3i &pos, int32 angleX, int32 angleY)
m.e22 = (cx * cy) >> FIXED_SHIFT;
m.e23 = 0;
#ifdef __3DO__
m.e30 = 0;
m.e31 = 0;
m.e32 = 0;
m.e33 = 0x4000;
#endif
cameraViewPos = pos;
cameraViewOffset = _vec3i(0, 0, 0);
}

View File

@@ -37,7 +37,7 @@
#include <mem.h>
#elif defined(__3DO__)
#define MODEHW
//#define USE_DIV_TABLE // 4k of DRAM
#define USE_DIV_TABLE // 4k of DRAM
#define CPU_BIG_ENDIAN
#define BLOCK_SIZE_DRAM (32 * 1024)
@@ -47,7 +47,7 @@
#define SND_BUFFER_SIZE (4 * BLOCK_SIZE_CD)
#define SND_BUFFERS 4
#define MAX_RAM_LVL (BLOCK_SIZE_DRAM * 31) // 35 for LEVEL10C! >_<
#define MAX_RAM_LVL (BLOCK_SIZE_DRAM * 31) // 34 for LEVEL10C! >_<
#define MAX_RAM_TEX (BLOCK_SIZE_VRAM * 44)
#define MAX_RAM_CEL (MAX_FACES * sizeof(CCB))
#define MAX_RAM_SND (SND_BUFFERS * SND_BUFFER_SIZE)
@@ -76,7 +76,6 @@
#include <celutils.h>
#include <timerutils.h>
#include <hardware.h>
//#include <filefunctions.h>
#else
#error unsupported platform
#endif
@@ -125,6 +124,7 @@
#define IWRAM_MATRIX_LERP
// the maximum of active enemies
// #define MAX_ENEMIES 3
#define VIS_DIST (1024 * 10)
#endif
#ifdef __3DO__
@@ -134,13 +134,13 @@
#define LOD_TRAP_FLOOR
// disable matrix interpolation
//#define NO_ANIM_LERP
#define ANIM_LERP_ANGLE
// the maximum navigation iterations per simulation tick
#define NAV_STEPS 1
// the maximum of active enemies
#define MAX_ENEMIES 3
// set the maximum number of simultaneously played channels
#define SND_CHANNELS 4
#define VIS_DIST (1024 * 10)
#endif
#ifndef NAV_STEPS
@@ -428,16 +428,20 @@ extern int32 fps;
#define MAX_DYN_SECTORS (1024*3)
#define MAX_SAMPLES 180
#ifndef VIS_DIST
#define VIS_DIST (1024 * 16)
#endif
#define FOV_SHIFT 3
#define FOG_SHIFT 1
#define FOG_MAX (10 * 1024)
#define FOG_MAX VIS_DIST
#define FOG_MIN (FOG_MAX - (8192 >> FOG_SHIFT))
#define VIEW_MIN_F (32 << FIXED_SHIFT)
#define VIEW_MIN_F (256 << FIXED_SHIFT)
#define VIEW_MAX_F (FOG_MAX << FIXED_SHIFT)
#define FRUSTUM_FAR_X 5 << 10
#define FRUSTUM_FAR_Y 3 << 10
#define FRUSTUM_FAR_Z 9 << 10
#define FRUSTUM_FAR_X (5 << 10)
#define FRUSTUM_FAR_Y (3 << 10)
#define FRUSTUM_FAR_Z (9 << 10)
#define FACE_TRIANGLE 0x8000
#define FACE_COLORED 0x4000
@@ -592,10 +596,10 @@ struct vec4i {
struct Matrix
{
#ifdef __3DO__
int32 e00, e10, e20;
int32 e01, e11, e21;
int32 e02, e12, e22;
int32 e03, e13, e23;
int32 e00, e10, e20, e30;
int32 e01, e11, e21, e31;
int32 e02, e12, e22, e32;
int32 e03, e13, e23, e33;
#else
int32 e00, e01, e02, e03;
int32 e10, e11, e12, e13;
@@ -850,11 +854,8 @@ struct Room {
const Sector* getWaterSector(int32 x, int32 z) const;
Room* getRoom(int32 x, int32 y, int32 z);
bool collideStatic(CollisionInfo &cinfo, const vec3i &p, int32 height);
#ifdef __3DO__
bool checkPortal(const Portal* portal, vec3i* points);
#else
bool checkPortal(const Portal* portal);
#endif
Room** addVisibleRoom(Room** list);
Room** addNearRoom(Room** list, int32 x, int32 y, int32 z);
Room** getNearRooms(const vec3i &pos, int32 radius, int32 height);
@@ -1910,8 +1911,8 @@ struct CollisionInfo
struct Box
{
int8 minZ, maxZ;
int8 minX, maxX;
uint8 minZ, maxZ;
uint8 minX, maxX;
int16 floor;
uint16 overlap;
};
@@ -1996,16 +1997,13 @@ struct IMA_STATE
int32 idx;
};
/*
#define PERSPECTIVE(x, y, z) {\
x = (x / (z >> 7));\
y = (y / (z >> 6));\
}
*/
#if defined(MODEHW)
#define PERSPECTIVE(x, y, z) {\
x = (x << 6) / (z >> 2);\
y = (y << 6) / (z >> 2);\
int32 dz = z >> 4;\
if (dz >= DIV_TABLE_SIZE) dz = DIV_TABLE_SIZE - 1;\
int32 d = FixedInvU(dz);\
x = (x * d) >> 12;\
y = (y * d) >> 12;\
}
#elif defined(MODE13)
#define PERSPECTIVE(x, y, z) {\
@@ -2116,27 +2114,39 @@ vec3i boxPushOut(const AABBs &a, const AABBs &b);
y = (((uint16*)(a))[1] & 0x000F) << 12 | (((uint16*)(a))[0] & 0xFC00) >> 4;\
z = (((uint16*)(a))[0] & 0x03FF) << 6;
#define LERP_1_2(a, b, mul, div) a = (b + a) >> 1
#define LERP_1_3(a, b, mul, div) a = a + ((b - a) / 3)
#define LERP_2_3(a, b, mul, div) a = b - ((b - a) / 3)
#define LERP_1_4(a, b, mul, div) a = a + ((b - a) >> 2)
#define LERP_3_4(a, b, mul, div) a = b - ((b - a) >> 2)
#define LERP_1_5(a, b, mul, div) a = a + ((b - a) / 5)
#define LERP_2_5(a, b, mul, div) a = a + ((b - a) * 2 / 5)
#define LERP_3_5(a, b, mul, div) a = b - ((b - a) * 2 / 5)
#define LERP_4_5(a, b, mul, div) a = b - ((b - a) / 5)
#define LERP_SLOW(a, b, mul, div) a = a + ((b - a) * mul / div)
#define USE_MATRIX_ASM
#define LERP_ROW(lerp_func, a, b, mul, div) \
lerp_func(a##0, b##0, mul, div); \
lerp_func(a##1, b##1, mul, div); \
lerp_func(a##2, b##2, mul, div); \
lerp_func(a##3, b##3, mul, div);
#ifdef USE_MATRIX_ASM
extern "C" void matrixLerp_asm(const Matrix &n, int32 pmul, int32 pdiv);
#define matrixLerp matrixLerp_asm
#else
#define LERP_1_2(a, b) a = (b + a) >> 1
#define LERP_1_3(a, b) a = a + (b - a) / 3
#define LERP_2_3(a, b) a = b - (b - a) / 3
#define LERP_1_4(a, b) a = a + ((b - a) >> 2)
#define LERP_3_4(a, b) a = b - ((b - a) >> 2)
#define LERP_1_5(a, b) a = a + (b - a) / 5
#define LERP_2_5(a, b) a = a + ((b - a) << 1) / 5
#define LERP_3_5(a, b) a = b - ((b - a) << 1) / 5
#define LERP_4_5(a, b) a = b - (b - a) / 5
#define LERP_SLOW(a, b) a = a + ((b - a) * t >> 8)
#define LERP_ROW(lerp_func, a, b, row) \
lerp_func(a.e##row##0, b.e##row##0); \
lerp_func(a.e##row##1, b.e##row##1); \
lerp_func(a.e##row##2, b.e##row##2); \
lerp_func(a.e##row##3, b.e##row##3);
#define LERP_MATRIX(lerp_func) \
LERP_ROW(lerp_func, m.e0, n.e0, multiplier, divider); \
LERP_ROW(lerp_func, m.e1, n.e1, multiplier, divider); \
LERP_ROW(lerp_func, m.e2, n.e2, multiplier, divider);
LERP_ROW(lerp_func, m, n, 0); \
LERP_ROW(lerp_func, m, n, 1); \
LERP_ROW(lerp_func, m, n, 2);
void matrixLerp_c(const Matrix &n, int32 pmul, int32 pdiv);
#define matrixLerp matrixLerp_c
#endif
X_INLINE Matrix& matrixGet()
{
@@ -2181,7 +2191,6 @@ void matrixRotateY(int32 angle);
void matrixRotateZ(int32 angle);
void matrixRotateYXZ(int32 angleX, int32 angleY, int32 angleZ);
void matrixRotateZXY(int32 angleX, int32 angleY, int32 angleZ);
void matrixLerp(const Matrix &n, int32 multiplier, int32 divider);
void matrixFrame(const vec3s &pos, const uint32* angles);
void matrixFrameLerp(const vec3s &pos, const uint32* anglesA, const uint32* anglesB, int32 delta, int32 rate);
void matrixSetIdentity();
@@ -2196,9 +2205,8 @@ void setPaletteIndex(int32 index);
void clear();
int32 rectIsVisible(const RectMinMax* rect);
int32 boxIsVisible(const AABBs* box);
void transform(vec3i* points, int32 count);
bool transformBoxRect(const AABBs* box, RectMinMax* rect);
void transformRoom(const RoomVertex* vertices, int32 vCount, bool underwater);
void transformRoom(const Room* room);
void transformMesh(const MeshVertex* vertices, int32 vCount, const uint16* vIntensity, const vec3s* vNormal);
void faceAddQuad(uint32 flags, const Index* indices);
void faceAddTriangle(uint32 flags, const Index* indices);

View File

@@ -494,9 +494,7 @@ void drawLaraNodes(const ItemObj* lara, const AnimFrame* frameA)
matrixTranslate(node->pos.x, node->pos.y, node->pos.z);
node++;
if (arm->useBasis) { // hands are rotated relative to the basis
#ifndef __3DO__ // TODO_3DO
matrixSetBasis(matrixGet(), basis);
#endif
matrixRotateYXZ(arm->angle.x, arm->angle.y, arm->angle.z);
}
matrixFrame(_vec3s(0, 0, 0), anglesArm[i]++);
@@ -628,9 +626,7 @@ void drawLaraNodesLerp(const ItemObj* lara, const AnimFrame* frameA, const AnimF
matrixTranslate(node->pos.x, node->pos.y, node->pos.z);
node++;
if (arm->useBasis) { // hands are rotated relative to the basis
#ifndef __3DO__ // TODO_3DO
matrixSetBasis(matrixGet(), basis);
#endif
matrixRotateYXZ(arm->angle.x, arm->angle.y, arm->angle.z);
}
@@ -769,9 +765,9 @@ void drawRoom(const Room* room, Camera* camera)
int32 rz = info->z << 8;
matrixPush();
matrixTranslateAbs(info->x << 8, 0, info->z << 8);
matrixTranslateAbs(info->x << 8, info->yTop, info->z << 8);
camera->updateFrustum(info->x << 8, 0, info->z << 8);
camera->updateFrustum(info->x << 8, info->yTop, info->z << 8);
setPaletteIndex(ROOM_FLAG_WATER(info->flags) ? 1 : 0);
@@ -802,7 +798,7 @@ void drawRoom(const Room* room, Camera* camera)
{
PROFILE(CNT_TRANSFORM);
transformRoom(data.vertices, info->verticesCount, ROOM_FLAG_WATER(info->flags));
transformRoom(room);
}
{

View File

@@ -368,180 +368,6 @@ bool Room::collideStatic(CollisionInfo &cinfo, const vec3i &p, int32 height)
return false;
}
#ifdef __3DO__
bool Room::checkPortal(const Portal* portal, vec3i* points)
{
int32 x0 = clip.x1;
int32 y0 = clip.y1;
int32 x1 = clip.x0;
int32 y1 = clip.y0;
int32 znear = 0, zfar = 0;
for (int32 i = 0; i < 4; i++)
{
int32 x = points[i].x;
int32 y = points[i].y;
int32 z = points[i].z;
if (z <= 0) {
points[i].x = -points[i].x;
points[i].y = -points[i].y;
znear++;
continue;
}
if (z >= (VIEW_MAX_F >> FIXED_SHIFT)) {
zfar++;
}
x += FRAME_WIDTH >> 1;
y += FRAME_HEIGHT >> 1;
if (x < x0) x0 = x;
if (x > x1) x1 = x;
if (y < y0) y0 = y;
if (y > y1) y1 = y;
}
if (znear == 4 || zfar == 4)
return false;
if (znear)
{
const vec3i *a = points;
const vec3i *b = points + 3;
for (int32 i = 0; i < 4; i++)
{
if ((a->z <= 0) ^ (b->z <= 0))
{
if (a->x < 0 && b->x < 0) {
x0 = 0;
} else if (a->x > 0 && b->x > 0) {
x1 = FRAME_WIDTH;
} else {
x0 = 0;
x1 = FRAME_WIDTH;
}
if (a->y < 0 && b->y < 0) {
y0 = 0;
} else if (a->y > 0 && b->y > 0) {
y1 = FRAME_HEIGHT;
} else {
y0 = 0;
y1 = FRAME_HEIGHT;
}
}
b = a;
a++;
}
}
if (x0 < clip.x0) x0 = clip.x0;
if (x1 > clip.x1) x1 = clip.x1;
if (y0 < clip.y0) y0 = clip.y0;
if (y1 > clip.y1) y1 = clip.y1;
if (x0 >= x1 || y0 >= y1)
return false;
Room* nextRoom = rooms + portal->roomIndex;
if (x0 < nextRoom->clip.x0) nextRoom->clip.x0 = x0;
if (x1 > nextRoom->clip.x1) nextRoom->clip.x1 = x1;
if (y0 < nextRoom->clip.y0) nextRoom->clip.y0 = y0;
if (y1 > nextRoom->clip.y1) nextRoom->clip.y1 = y1;
return true;
}
Room** Room::addVisibleRoom(Room** list)
{
uint32 vis[MAX_PORTALS];
vec3i vertices[MAX_PORTALS * 4];
int32 cx = cameraViewPos.x - (info->x << 8);
int32 cy = cameraViewPos.y;
int32 cz = cameraViewPos.z - (info->z << 8);
const Portal* portal = data.portals;
vec3i* v = (vec3i*)vertices;
int32 vCount = 0;
for (int32 i = 0; i < info->portalsCount; i++, portal++)
{
int32 axis = 0;
int32 x = (portal->v[0].x - cx) << F16_SHIFT;
if (x >= 0) axis |= (2 << 0);
if (x < 0) axis |= (1 << 0);
int32 y = (portal->v[0].y - cy) << F16_SHIFT;
if (y >= 0) axis |= (2 << 2);
if (y < 0) axis |= (1 << 2);
int32 z = (portal->v[0].z - cz) << F16_SHIFT;
if (z >= 0) axis |= (2 << 4);
if (z < 0) axis |= (1 << 4);
vis[i] = (portal->normalMask & axis);
if (!vis[i])
continue;
v->x = x;
v->y = y;
v->z = z;
v++;
v->x = (portal->v[1].x - cx) << F16_SHIFT;
v->y = (portal->v[1].y - cy) << F16_SHIFT;
v->z = (portal->v[1].z - cz) << F16_SHIFT;
v++;
v->x = (portal->v[2].x - cx) << F16_SHIFT;
v->y = (portal->v[2].y - cy) << F16_SHIFT;
v->z = (portal->v[2].z - cz) << F16_SHIFT;
v++;
v->x = (portal->v[3].x - cx) << F16_SHIFT;
v->y = (portal->v[3].y - cy) << F16_SHIFT;
v->z = (portal->v[3].z - cz) << F16_SHIFT;
v++;
vCount += 4;
}
if (!vCount)
return list;
transform((vec3i*)vertices, vCount);
portal = data.portals;
v = (vec3i*)vertices;
for (int32 i = 0; i < info->portalsCount; i++, portal++)
{
if (!vis[i])
continue;
if (checkPortal(portal, v))
{
Room* nextRoom = rooms + portal->roomIndex;
list = nextRoom->addVisibleRoom(list);
if (!nextRoom->visible)
{
nextRoom->visible = true;
*list++ = nextRoom;
}
}
v += 4;
}
return list;
}
#else
bool Room::checkPortal(const Portal* portal)
{
vec3i d;
@@ -555,11 +381,11 @@ bool Room::checkPortal(const Portal* portal)
#ifdef __3DO__
int32 axis = 0;
if (d.x > 0) axis |= (2 << 0);
if (d.x >= 0) axis |= (2 << 0);
if (d.x < 0) axis |= (1 << 0);
if (d.y > 0) axis |= (2 << 2);
if (d.y >= 0) axis |= (2 << 2);
if (d.y < 0) axis |= (1 << 2);
if (d.z > 0) axis |= (2 << 4);
if (d.z >= 0) axis |= (2 << 4);
if (d.z < 0) axis |= (1 << 4);
if (!(portal->normalMask & axis))
@@ -602,7 +428,13 @@ bool Room::checkPortal(const Portal* portal)
}
int32 dz = (z >> (FIXED_SHIFT + FOV_SHIFT + 1));
if (dz > 0) {
#ifdef __3DO__
x >>= FIXED_SHIFT;
y >>= FIXED_SHIFT;
z >>= FIXED_SHIFT;
#endif
PERSPECTIVE(x, y, z);
x += FRAME_WIDTH >> 1;
y += FRAME_HEIGHT >> 1;
@@ -696,7 +528,6 @@ Room** Room::addVisibleRoom(Room** list)
return list;
}
#endif
Room** Room::getVisibleRooms()
{

View File

@@ -21,7 +21,7 @@ CXXFLAGS = $(CFLAGS)
ASFLAGS = -BI -i $(SDK)/include/3do
INCPATH = -I $(SDK)/include/3do -I $(SDK)/include/ttl -I ../../fixed
LIBPATH = $(SDK)/lib
LDFLAGS = -aif -reloc -ro-base 0 -sym $(EXENAME).sym -libpath $(LIBPATH)
LDFLAGS = -aif -reloc -ro-base 0 -libpath $(LIBPATH) -nodebug -remove -info Sizes
STARTUP = $(LIBPATH)/cstartup.o
LIBS = \

View File

@@ -0,0 +1,132 @@
AREA |C$$code|, CODE, READONLY
|x$codeseg|
IMPORT matrixPtr
IMPORT divTable
EXPORT matrixLerp_asm
n RN r0
pmul RN r1
pdiv RN r2
m0 RN r3
m1 RN r4
m2 RN r5
n0 RN r6
n1 RN r12
n2 RN lr
tmp RN r4
m RN r7
MACRO
next_row
add m, m, #16
add n, n, #16
MEND
MACRO
load
ldmia m, {m0, m1, m2}
ldmia n, {n0, n1, n2}
MEND
MACRO
store
stmia m, {m0, m1, m2}
MEND
MACRO ; a = (a + b) / 2
_1_2
load
add m0, m0, n0
add m1, m1, n1
add m2, m2, n2
mov m0, m0, asr #1
mov m1, m1, asr #1
mov m2, m2, asr #1
store
MEND
MACRO ; a = a + (b - a) / 4
_1_4
load
sub n0, n0, m0
sub n1, n1, m1
sub n2, n2, m2
add m0, m0, n0, asr #2
add m1, m1, n1, asr #2
add m2, m2, n2, asr #2
store
MEND
MACRO ; a = b - (b - a) / 4
_3_4
load
sub m0, n0, m0
sub m1, n1, m1
sub m2, n2, m2
sub m0, n0, m0, asr #2
sub m1, n1, m1, asr #2
sub m2, n2, m2, asr #2
store
MEND
MACRO ; a = a + (b - a) * mul / div
_X_Y
load
sub n0, n0, m0
sub n1, n1, m1
sub n2, n2, m2
mul n0, pmul, n0
mul n1, pmul, n1
mul n2, pmul, n2
add m0, m0, n0, asr #8
add m1, m1, n1, asr #8
add m2, m2, n2, asr #8
store
MEND
MACRO ; transposed (3x4)
lerp $func
$func ; e00, e10, e20
next_row
$func ; e01, e11, e21
next_row
$func ; e02, e12, e22
next_row
$func ; e03, e13, e23
b done
MEND
matrixLerp_asm
stmfd sp!, {r4-r7, lr}
ldr m, =matrixPtr
ldr m, [m]
check_2
cmp pdiv, #2
beq m1_d2
check_4
cmp pdiv, #4
bne mX_dY
cmp pmul, #1
beq m1_d4
cmp pmul, #2
beq m1_d2 ; 2/4 = 1/2
b m3_d4
mX_dY
ldr tmp, =divTable
ldr tmp, [tmp, pdiv, lsl #2]
mul tmp, pmul, tmp
mov pmul, tmp, asr #8
lerp _X_Y
m1_d2
lerp _1_2
m1_d4
lerp _1_4
m3_d4
lerp _3_4
done ldmfd sp!, {r4-r7, pc}
END

View File

@@ -1,8 +1,10 @@
#include "common.h"
//#define DEBUG_CLIPPING
struct Vertex
{
int32 x, y, z; // for rooms z = (depth << CLIP_SHIFT) | ClipFlags
int32 x, y, z, w; // for rooms z = (depth << CLIP_SHIFT) | ClipFlags
};
uint16* gPalette;
@@ -28,9 +30,7 @@ int32 otMax = 0;
RectMinMax viewportRel;
bool enableAlphaTest;
bool enableClipping;
bool secondPalette;
#define SHADOW_OPACITY 3 // 50%
#define MIP_DIST (1024 * 5)
@@ -174,24 +174,29 @@ enum ClipFlags {
CLIP_NEAR = 1 << 5
};
X_INLINE int32 classify(const Vertex* v, int32 x0, int32 y0, int32 x1, int32 y1)
X_INLINE int32 classify(int32 x, int32 y, int32 x0, int32 y0, int32 x1, int32 y1)
{
return (v->x < x0 ? CLIP_LEFT : 0) |
(v->x > x1 ? CLIP_RIGHT : 0) |
(v->y < y0 ? CLIP_TOP : 0) |
(v->y > y1 ? CLIP_BOTTOM : 0);
return (x < x0 ? CLIP_LEFT : 0) |
(x > x1 ? CLIP_RIGHT : 0) |
(y < y0 ? CLIP_TOP : 0) |
(y > y1 ? CLIP_BOTTOM : 0);
}
void transform(vec3i* points, int32 count)
X_INLINE void transform(Vertex* points, int32 count)
{
mmv3m33d desc;
desc.dest =
desc.src = (vec3f16*)points;
desc.mat = (mat33f16*)&matrixGet();
desc.n = 1 << 8;
desc.count = count;
Matrix& m = matrixGet();
int32 mx = m.e03;
int32 my = m.e13;
int32 mz = m.e23;
m.e03 >>= FIXED_SHIFT;
m.e13 >>= FIXED_SHIFT;
m.e23 >>= FIXED_SHIFT;
MulManyVec3Mat33DivZ_F16(&desc);
MulManyVec4Mat44_F16((vec4f16*)points, (vec4f16*)points, *(mat44f16*)&matrixGet(), count);
m.e03 = mx;
m.e13 = my;
m.e23 = mz;
}
bool transformBoxRect(const AABBs* box, RectMinMax* rect)
@@ -202,27 +207,23 @@ bool transformBoxRect(const AABBs* box, RectMinMax* rect)
return false;
}
int32 cx = Dot3_F16(*(vec3f16*)&m.e03, *(vec3f16*)&m.e00) >> DOT_SHIFT; // dot(pos, right)
int32 cy = Dot3_F16(*(vec3f16*)&m.e03, *(vec3f16*)&m.e01) >> DOT_SHIFT; // dot(pos, up)
int32 cz = Dot3_F16(*(vec3f16*)&m.e03, *(vec3f16*)&m.e02) >> DOT_SHIFT; // dot(pos, dir)
AABBi b;
b.minX = (box->minX << F16_SHIFT) + cx;
b.maxX = (box->maxX << F16_SHIFT) + cx;
b.minY = (box->minY << F16_SHIFT) + cy;
b.maxY = (box->maxY << F16_SHIFT) + cy;
b.minZ = (box->minZ << F16_SHIFT) + cz;
b.maxZ = (box->maxZ << F16_SHIFT) + cz;
b.minX = (box->minX << F16_SHIFT);
b.maxX = (box->maxX << F16_SHIFT);
b.minY = (box->minY << F16_SHIFT);
b.maxY = (box->maxY << F16_SHIFT);
b.minZ = (box->minZ << F16_SHIFT);
b.maxZ = (box->maxZ << F16_SHIFT);
vec3i v[8] = {
{ b.minX, b.minY, b.minZ },
{ b.maxX, b.minY, b.minZ },
{ b.minX, b.maxY, b.minZ },
{ b.maxX, b.maxY, b.minZ },
{ b.minX, b.minY, b.maxZ },
{ b.maxX, b.minY, b.maxZ },
{ b.minX, b.maxY, b.maxZ },
{ b.maxX, b.maxY, b.maxZ }
Vertex v[8] = {
{ b.minX, b.minY, b.minZ, 1 << 16 },
{ b.maxX, b.minY, b.minZ, 1 << 16 },
{ b.minX, b.maxY, b.minZ, 1 << 16 },
{ b.maxX, b.maxY, b.minZ, 1 << 16 },
{ b.minX, b.minY, b.maxZ, 1 << 16 },
{ b.maxX, b.minY, b.maxZ, 1 << 16 },
{ b.minX, b.maxY, b.maxZ, 1 << 16 },
{ b.maxX, b.maxY, b.maxZ, 1 << 16 }
};
transform(v, 8);
@@ -231,16 +232,19 @@ bool transformBoxRect(const AABBs* box, RectMinMax* rect)
for (int32 i = 0; i < 8; i++)
{
if (v[i].z <= 0)
return false;
int32 x = v[i].x;
int32 y = v[i].y;
int32 z = v[i].z;
if (v[i].z >= (VIEW_MAX_F >> FIXED_SHIFT))
if (z < (VIEW_MIN_F >> FIXED_SHIFT) || z >= (VIEW_MAX_F >> FIXED_SHIFT))
continue;
if (v[i].x < rect->x0) rect->x0 = v[i].x;
if (v[i].x > rect->x1) rect->x1 = v[i].x;
if (v[i].y < rect->y0) rect->y0 = v[i].y;
if (v[i].y > rect->y1) rect->y1 = v[i].y;
PERSPECTIVE(x, 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);
@@ -256,48 +260,54 @@ bool transformBoxRect(const AABBs* box, RectMinMax* rect)
#ifdef USE_ASM
#define unpackRoom unpackRoom_asm
#define unpackMesh unpackMesh_asm
extern void unpackRoom_asm(const RoomVertex* vertices, int32 vCount);
extern void unpackMesh_asm(const MeshVertex* vertices, int32 vCount);
//#define ccbMap4 ccbMap4_asm
extern "C" void unpackRoom_asm(const RoomVertex* vertices, int32 vCount);
extern "C" void unpackMesh_asm(const MeshVertex* vertices, int32 vCount);
//extern "C" void ccbMap4_asm(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, const Vertex* v3, uint32 shift);
#else
#define unpackRoom unpackRoom_c
#define unpackMesh unpackMesh_c
void unpackRoom_c(const RoomVertex* vertices, int32 vCount)
{
int32 cx = cameraViewOffset.x << F16_SHIFT;
int32 cy = cameraViewOffset.y << F16_SHIFT;
int32 cz = cameraViewOffset.z << F16_SHIFT;
Vertex* res = gVertices;
uint32 *v32 = (uint32*)vertices;
for (int32 i = 0; i < vCount; i += 2)
for (int32 i = 0; i < vCount; i += 4)
{
uint32 a = *v32++;
uint32 b = *v32++;
res->x = cx + ((a & 0xFF00) << 4);
res->y = cy + (int32(a) >> 16 << 2);
res->z = cz + ((a & 0xFF) << 12);
uint32 n0 = *v32++;
uint32 n1 = *v32++;
res->x = (n0 << 12) & 0x1F000;
res->y = (n0 << 5) & 0xFC00;
res->z = (n0 << 1) & 0x1F000;
res->w = 1 << 16;
res++;
res->x = cx + ((b & 0xFF00) << 4);
res->y = cy + (int32(b) >> 16 << 2);
res->z = cz + ((b & 0xFF) << 12);
res->x = (n0 >> 4) & 0x1F000;
res->y = (n0 >> 11) & 0xFC00;
res->z = (n0 >> 15) & 0x1F000;
res->w = 1 << 16;
res++;
res->x = (n1 << 12) & 0x1F000;
res->y = (n1 << 5) & 0xFC00;
res->z = (n1 << 1) & 0x1F000;
res->w = 1 << 16;
res++;
res->x = (n1 >> 4) & 0x1F000;
res->y = (n1 >> 11) & 0xFC00;
res->z = (n1 >> 15) & 0x1F000;
res->w = 1 << 16;
res++;
}
}
void unpackMesh_c(const MeshVertex* vertices, int32 vCount)
{
Matrix &m = matrixGet();
// TODO_3DO normalize 3x3 interpolated matrix or get cameraViewOffset for the general case somehow
// TODO_3DO MulVec3Mat33_F16 (transposed?)
int32 cx = Dot3_F16(*(vec3f16*)&m.e03, *(vec3f16*)&m.e00) >> DOT_SHIFT; // dot(pos, right)
int32 cy = Dot3_F16(*(vec3f16*)&m.e03, *(vec3f16*)&m.e01) >> DOT_SHIFT; // dot(pos, up)
int32 cz = Dot3_F16(*(vec3f16*)&m.e03, *(vec3f16*)&m.e02) >> DOT_SHIFT; // dot(pos, dir)
uint32 *v32 = (uint32*)vertices;
Vertex* res = gVertices;
@@ -308,24 +318,30 @@ void unpackMesh_c(const MeshVertex* vertices, int32 vCount)
uint32 n1 = *v32++;
uint32 n2 = *v32++;
res->x = cx + int16(n0 >> 16);
res->y = cy + int16(n0);
res->z = cz + int16(n1 >> 16);
res->x = int16(n0 >> 16);
res->y = int16(n0);
res->z = int16(n1 >> 16);
res->w = 1 << 16;
res++;
res->x = cx + int16(n1);
res->y = cy + int16(n2 >> 16);
res->z = cz + int16(n2);
res->x = int16(n1);
res->y = int16(n2 >> 16);
res->z = int16(n2);
res->w = 1 << 16;
res++;
}
}
#endif
void transformRoom(const RoomVertex* vertices, int32 vCount, bool underwater)
void transformRoom(const Room* room)
{
unpackRoom(vertices, vCount);
int32 vCount = room->info->verticesCount;
if (vCount <= 0)
return;
transform((vec3i*)gVertices, vCount);
unpackRoom(room->data.vertices, vCount);
transform(gVertices, vCount);
int32 x0 = viewportRel.x0;
int32 y0 = viewportRel.y0;
@@ -336,17 +352,27 @@ void transformRoom(const RoomVertex* vertices, int32 vCount, bool underwater)
for (int32 i = 0; i < vCount; i++, res++)
{
if (res->z < (VIEW_MIN_F >> FIXED_SHIFT)) {
res->z = ((VIEW_MIN_F >> FIXED_SHIFT) << CLIP_SHIFT) | CLIP_NEAR;
} else if (res->z >= (VIEW_MAX_F >> FIXED_SHIFT)) {
res->z = ((VIEW_MAX_F >> FIXED_SHIFT) << CLIP_SHIFT) | CLIP_FAR;
} else {
res->z = (res->z << CLIP_SHIFT) | classify(res, x0, y0, x1, y1);
}
int32 x = res->x;
int32 y = res->y;
int32 z = res->z;
int32 clip = 0;
if (z < (VIEW_MIN_F >> FIXED_SHIFT)) {
z = (VIEW_MIN_F >> FIXED_SHIFT);
clip = CLIP_NEAR;
} else if (z > (VIEW_MAX_F >> FIXED_SHIFT)) {
z = (VIEW_MAX_F >> FIXED_SHIFT);
clip = CLIP_FAR;
}
if (viewport.x0 == 0 && viewport.y0 == 0)
return;
PERSPECTIVE(x, y, z);
clip |= classify(x, y, x0, y0, x1, y1);
res->x = x;
res->y = y;
res->z = (z << CLIP_SHIFT) | clip;
}
gVerticesCount += vCount;
}
@@ -355,13 +381,44 @@ void transformMesh(const MeshVertex* vertices, int32 vCount, const uint16* vInte
{
unpackMesh(vertices, vCount);
transform((vec3i*)gVertices, vCount);
transform(gVertices, vCount);
int32 x0 = viewportRel.x0;
int32 y0 = viewportRel.y0;
int32 x1 = viewportRel.x1;
int32 y1 = viewportRel.y1;
Vertex* res = gVertices;
for (int32 i = 0; i < vCount; i++, res++)
{
int32 x = res->x;
int32 y = res->y;
int32 z = res->z;
int32 clip = 0;
if (z < (VIEW_MIN_F >> FIXED_SHIFT)) {
z = (VIEW_MIN_F >> FIXED_SHIFT);
clip = CLIP_NEAR;
} else if (z >= (VIEW_MAX_F >> FIXED_SHIFT)) {
z = (VIEW_MAX_F >> FIXED_SHIFT);
clip = CLIP_FAR;
}
PERSPECTIVE(x, y, z);
clip |= classify(x, y, x0, y0, x1, y1);
res->x = x;
res->y = y;
res->z = (z << CLIP_SHIFT) | clip;
}
gVerticesCount += vCount;
}
#define DEPTH_T_AVG(z0,z1,z2) ((z0 + z1 + z2 + z2) >> (2 + OT_SHIFT))
#define DEPTH_Q_AVG(z0,z1,z2,z3) ((z0 + z1 + z2 + z3) >> (2 + OT_SHIFT))
#define DEPTH_T_AVG(z0,z1,z2) ((z0 + z1 + z2 + z2) >> (2 + CLIP_SHIFT + OT_SHIFT))
#define DEPTH_Q_AVG(z0,z1,z2,z3) ((z0 + z1 + z2 + z3) >> (2 + CLIP_SHIFT + OT_SHIFT))
#define DEPTH_T_MAX(z0,z1,z2) (X_MAX(z0, X_MAX(z1, z2)) >> (CLIP_SHIFT + OT_SHIFT))
#define DEPTH_Q_MAX(z0,z1,z2,z3) (X_MAX(z0, X_MAX(z1, X_MAX(z2, z3))) >> (CLIP_SHIFT + OT_SHIFT))
@@ -430,14 +487,14 @@ X_INLINE void ccbSetColor(uint32 flags, Face* face)
X_INLINE void ccbMap4(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, const Vertex* v3, uint32 shift)
{
int32 x0 = v0->x;
int32 y0 = v0->y;
int32 x1 = v1->x;
int32 y1 = v1->y;
int32 x2 = v2->x;
int32 y2 = v2->y;
int32 x3 = v3->x;
int32 y3 = v3->y;
int32 x2 = v2->x;
int32 y2 = v2->y;
int32 x0 = v0->x;
int32 y0 = v0->y;
uint32 ws = shift & 0xFF;
uint32 hs = shift >> 8;
@@ -449,17 +506,22 @@ X_INLINE void ccbMap4(Face* f, const Vertex* v0, const Vertex* v1, const Vertex*
int32 vdx0 = (x3 - x0) << hs;
int32 vdy0 = (y3 - y0) << hs;
hs = 16 - hs;
int32 hddx = (hdx1 - hdx0) >> hs;
int32 hddy = (hdy1 - hdy0) >> hs;
f->ccb_XPos = (x0 << 16) + (((FRAME_WIDTH >> 1) << 16) + 32768);
f->ccb_YPos = (y0 << 16) + (((FRAME_HEIGHT >> 1) << 16) + 32768);
f->ccb_HDX = hdx0;
f->ccb_HDY = hdy0;
f->ccb_VDX = vdx0;
f->ccb_VDY = vdy0;
f->ccb_HDDX = hddx;
f->ccb_HDDY = hddy;
f->ccb_XPos = (x0 + (FRAME_WIDTH >> 1)) << 16;
f->ccb_YPos = (y0 + (FRAME_HEIGHT >> 1)) << 16;
hs = 16 - hs;
f->ccb_HDDX = (hdx1 - hdx0) >> hs;
f->ccb_HDDY = (hdy1 - hdy0) >> hs;
#ifdef DEBUG_CLIPPING
f->ccb_PIXC = SHADE_SHADOW;
#endif
}
X_INLINE void ccbMap3(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, uint32 shift)
@@ -479,17 +541,20 @@ X_INLINE void ccbMap3(Face* f, const Vertex* v0, const Vertex* v1, const Vertex*
int32 vdx0 = (x2 - x0) << hs;
int32 vdy0 = (y2 - y0) << hs;
f->ccb_XPos = (x0 << 16) + (((FRAME_WIDTH >> 1) << 16) + 32768);
f->ccb_YPos = (y0 << 16) + (((FRAME_HEIGHT >> 1) << 16) + 32768);
f->ccb_HDX = hdx0;
f->ccb_HDY = hdy0;
f->ccb_VDX = vdx0;
f->ccb_VDY = vdy0;
f->ccb_XPos = (x0 + (FRAME_WIDTH >> 1)) << 16;
f->ccb_YPos = (y0 + (FRAME_HEIGHT >> 1)) << 16;
hs = 16 - hs;
f->ccb_HDDX = -hdx0 >> hs;
f->ccb_HDDY = -hdy0 >> hs;
#ifdef DEBUG_CLIPPING
f->ccb_PIXC = SHADE_SHADOW;
#endif
}
X_INLINE void faceAddRoomQuad(uint32 flags, const Index* indices)
@@ -515,9 +580,6 @@ X_INLINE void faceAddRoomQuad(uint32 flags, const Index* indices)
if ((c0 & c1 & c2 & c3) & CLIP_MASK)
return;
if ((c0 & CLIP_NEAR) || (c1 & CLIP_NEAR) || (c2 & CLIP_NEAR) || (c3 & CLIP_NEAR))
return;
int32 depth = DEPTH_Q_MAX(c0, c1, c2, c3);
if (checkBackface(v0, v1, v3) == !(flags & FACE_CCW))
@@ -563,9 +625,6 @@ X_INLINE void faceAddRoomTriangle(uint32 flags, const Index* indices)
if ((c0 & c1 & c2) & CLIP_MASK)
return;
if ((c0 & CLIP_NEAR) || (c1 & CLIP_NEAR) || (c2 & CLIP_NEAR))
return;
int32 depth = DEPTH_T_MAX(c0, c1, c2);
if (checkBackface(v0, v1, v2) == !(flags & FACE_CCW))
@@ -603,6 +662,14 @@ X_INLINE void faceAddMeshQuad(uint32 flags, uint32 indices, uint32 shade)
const Vertex* v2 = gVertices + i2;
const Vertex* v3 = gVertices + i3;
uint32 c0 = v0->z;
uint32 c1 = v1->z;
uint32 c2 = v2->z;
uint32 c3 = v3->z;
if ((c0 & c1 & c2 & c3) & CLIP_MASK)
return;
if (checkBackface(v0, v1, v3) == !(flags & FACE_CCW)) // TODO (hdx0 * vdy0 - vdx0 * hdy0) <= 0
return;
@@ -627,6 +694,13 @@ X_INLINE void faceAddMeshTriangle(uint32 flags, uint32 indices, uint32 shade)
const Vertex* v1 = gVertices + i1;
const Vertex* v2 = gVertices + i2;
uint32 c0 = v0->z;
uint32 c1 = v1->z;
uint32 c2 = v2->z;
if ((c0 & c1 & c2) & CLIP_MASK)
return;
if (checkBackface(v0, v1, v2))
return;
@@ -653,6 +727,14 @@ X_INLINE void faceAddMeshQuadFlat(uint32 flags, uint32 indices, uint32 shade)
const Vertex* v2 = gVertices + i2;
const Vertex* v3 = gVertices + i3;
uint32 c0 = v0->z;
uint32 c1 = v1->z;
uint32 c2 = v2->z;
uint32 c3 = v3->z;
if ((c0 & c1 & c2 & c3) & CLIP_MASK)
return;
if (checkBackface(v0, v1, v3))
return;
@@ -676,6 +758,13 @@ X_INLINE void faceAddMeshTriangleFlat(uint32 flags, uint32 indices, uint32 shade
const Vertex* v1 = gVertices + i1;
const Vertex* v2 = gVertices + i2;
uint32 c0 = v0->z;
uint32 c1 = v1->z;
uint32 c2 = v2->z;
if ((c0 & c1 & c2) & CLIP_MASK)
return;
if (checkBackface(v0, v1, v2))
return;
@@ -724,38 +813,50 @@ void faceAddSprite(int32 vx, int32 vy, int32 vz, int32 vg, int32 index)
const Matrix &m = matrixGet();
vec3i v;
v.x = (vx - cameraViewPos.x) << F16_SHIFT;
v.y = (vy - cameraViewPos.y) << F16_SHIFT;
v.z = (vz - cameraViewPos.z) << F16_SHIFT;
vx -= cameraViewPos.x;
vy -= cameraViewPos.y;
vz -= cameraViewPos.z;
MulVec3Mat33DivZ_F16(*(vec3f16*)&v, *(vec3f16*)&v, *(mat33f16*)&m, 1 << 8);
int32 z = DP33(m.e20, m.e21, m.e22, vx, vy, vz);
if (v.z < (VIEW_MIN_F >> FIXED_SHIFT) || v.z >= (VIEW_MAX_F >> FIXED_SHIFT))
if (z < VIEW_MIN_F || z >= VIEW_MAX_F)
{
return;
}
ASSERT(gFacesCount < MAX_FACES);
int32 x = DP33(m.e00, m.e01, m.e02, vx, vy, vz);
int32 y = DP33(m.e10, m.e11, m.e12, vx, vy, vz);
x >>= FIXED_SHIFT;
y >>= FIXED_SHIFT;
z >>= FIXED_SHIFT;
PERSPECTIVE(x, y, z);
const Sprite* sprite = level.sprites + index;
int32 d = (1 << 20) / v.z;
int32 d = (1 << 20) / z;
int32 x0 = sprite->l * d >> 12;
int32 y0 = sprite->t * d >> 12;
int32 x1 = sprite->r * d >> 12;
int32 y1 = sprite->b * d >> 12;
if (x0 == x1) return;
int32 y0 = sprite->t * d >> 12;
int32 y1 = sprite->b * d >> 12;
if (y0 == y1) return;
x0 += v.x;
x1 += v.x;
y0 += v.y;
y1 += v.y;
x0 += x;
x1 += x;
y0 += y;
y1 += y;
if (x0 >= viewportRel.x1) return;
if (y0 >= viewportRel.y1) return;
if (x1 <= viewportRel.x0) return;
if (y1 <= viewportRel.y0) return;
int32 depth = X_MAX(0, v.z - 128) >> OT_SHIFT; // depth hack
int32 depth = X_MAX(0, z - 128) >> OT_SHIFT; // depth hack
Face* f = faceAdd(depth);

View File

@@ -1,68 +1,52 @@
AREA |C$$code|, CODE, READONLY
|x$codeseg|
IMPORT matrixPtr
IMPORT gVertices
EXPORT unpackMesh_asm__FPC10MeshVertexl
EXPORT unpackMesh_asm
unpackMesh_asm__FPC10MeshVertexl
unpackMesh_asm
vertices RN r0
vptr RN r5
vCount RN r1
cx RN r8
cy RN r9
cz RN r10
vx0 RN r1
vy0 RN r2
vz0 RN r3
vw0 RN r4
vx1 RN r5
vy1 RN r6
vz1 RN r7
vw1 RN r8
n0 RN vy0
n1 RN vx1
n2 RN vz1
res RN r12
last RN lr
n0 RN r3
n1 RN r5
n2 RN r7
res RN r1
DOT3_F16 EQU 0x5000C
stmfd sp!, {r4-r10, lr}
add last, vertices, vCount, lsl #2
add last, last, vCount, lsl #1
mov vptr, vertices ; save vertices ptr
ldr r4, =matrixPtr
ldr r7, [r4] ; &m.e00
add r4, r7, #36 ; &m.e03
mov r0, r4
add r1, r7, #24 ; &m.e02
swi DOT3_F16
mov cz, r0, asr #10
mov r0, r4
add r1, r7, #12 ; &m.e01
swi DOT3_F16
mov cy, r0, asr #10
mov r0, r4
mov r1, r7 ; &m.e00
swi DOT3_F16
mov cx, r0, asr #10
mov vertices, vptr ; restore vertices ptr
stmfd sp!, {r4-r8, lr}
ldr res, =gVertices
; last = vertices + vCount * 6
add vCount, vCount, vCount, lsl #1
add last, vertices, vCount, lsl #1
mov vw0, #(1 << 16)
mov vw1, #(1 << 16)
loop ldmia vertices!, {n0, n1, n2} ; load two encoded vertices
cmp vertices, last
add r2, cx, n0, asr #16 ; x
mov vx0, n0, asr #16 ; x
mov n0, n0, lsl #16
add r3, cy, n0, asr #16 ; y
mov vy0, n0, asr #16 ; y
add r4, cz, n1, asr #16 ; z
mov vz0, n1, asr #16 ; z
mov n1, n1, lsl #16
add r5, cx, n1, asr #16 ; x
mov vx1, n1, asr #16 ; x
add r6, cy, n2, asr #16 ; y
mov vy1, n2, asr #16 ; y
mov n2, n2, lsl #16
add r7, cz, n2, asr #16 ; z
mov vz1, n2, asr #16 ; z
stmia res!, {r2, r3, r4, r5, r6, r7}
stmia res!, {vx0, vy0, vz0, vw0, vx1, vy1, vz1, vw1}
blt loop
ldmfd sp!, {r4-r10, pc}
ldmfd sp!, {r4-r8, pc}
END

View File

@@ -3,48 +3,75 @@
IMPORT cameraViewOffset
IMPORT gVertices
EXPORT unpackRoom_asm__FPC10RoomVertexl
EXPORT unpackRoom_asm
unpackRoom_asm__FPC10RoomVertexl
unpackRoom_asm
vertices RN r0
vCount RN r1
cx RN r2
cy RN r3
cz RN r4
res RN r5
vx0 RN r1
vy0 RN r2
vz0 RN r3
vw0 RN r4
vx1 RN r5
vy1 RN r6
vz1 RN r7
vw1 RN r8
vx2 RN vx0
vy2 RN vy0
vz2 RN vz0
vw2 RN vw0
vx3 RN vx1
vy3 RN vy1
vz3 RN vz1
vw3 RN vw1
n0 RN vz1
n1 RN r9
maskH RN r10
maskV RN r11
res RN r12
last RN lr
stmfd sp!, {r4-r11, lr}
ldr r2, =cameraViewOffset
ldr res, =gVertices
add last, vertices, vCount, lsl #2
ldmfd r2, {cx, cy, cz}
mov cx, cx, lsl #2
mov cy, cy, lsl #2
mov cz, cz, lsl #2
add last, vertices, vCount, lsl #1 ; last = vertices + vCount * 2
mov vw0, #(1 << 16) ; vw2
mov vw1, #(1 << 16) ; vw3
mov maskH, #0x1F000
mov maskV, #0xFC00
loop ldmia vertices!, {r9, r11} ; load two encoded vertices
loop ldmia vertices!, {n0, n1} ; load four encoded vertices
cmp vertices, last
; n0 = z1:5, y1:6, x1:5, z0:5, y0:6, x0:5
; n0 = z3:5, y3:6, x3:5, z2:5, y2:6, x2:5
; 1st vertex
and r6, r9, #0xFF00 ; decode x
mov r7, r9, asr #16 ; decode y (signed)
and r8, r9, #0xFF ; decode z
add r6, cx, r6, lsl #4
add r7, cy, r7, asl #2
add r8, cz, r8, lsl #12
and vx0, maskH, n0, lsl #12 ; decode x0
and vy0, maskV, n0, lsl #5 ; decode y0
and vz0, maskH, n0, lsl #1 ; decode z0
; 2nd vertex
and r9, r11, #0xFF00 ; decode x
mov r10, r11, asr #16 ; decode y (signed)
and r11, r11, #0xFF ; decode z
add r9, cx, r9, lsl #4
add r10, cy, r10, asl #2
add r11, cz, r11, lsl #12
and vx1, maskH, n0, lsr #4 ; decode x0
and vy1, maskV, n0, lsr #11 ; decode y0
and vz1, maskH, n0, lsr #15 ; decode z0
; store
stmia res!, {r6, r7, r8, r9, r10, r11}
stmia res!, {vx0, vy0, vz0, vw0, vx1, vy1, vz1, vw1}
; 3rd vertex
and vx2, maskH, n1, lsl #12 ; decode x0
and vy2, maskV, n1, lsl #5 ; decode y0
and vz2, maskH, n1, lsl #1 ; decode z0
; 4th vertex
and vx3, maskH, n1, lsr #4 ; decode x0
and vy3, maskV, n1, lsr #11 ; decode y0
and vz3, maskH, n1, lsr #15 ; decode z0
; store
stmia res!, {vx2, vy2, vz2, vw2, vx3, vy3, vz3, vw3}
blt loop
ldmfd sp!, {r4-r11, pc}