diff --git a/src/fixed/common.h b/src/fixed/common.h index b6532c1..1a68b4e 100644 --- a/src/fixed/common.h +++ b/src/fixed/common.h @@ -431,7 +431,7 @@ extern int32 fps; #define MAX_SAMPLES 180 #ifndef VIEW_DIST - #define VIEW_DIST (1024 * 16) + #define VIEW_DIST (1024 * 10) #endif #define FOV_SHIFT 3 @@ -607,8 +607,8 @@ struct Matrix struct RoomQuad { #ifdef __3DO__ - Index indices[4]; uint32 flags; + Index indices[4]; #else Index indices[4]; uint16 flags; @@ -618,8 +618,8 @@ struct RoomQuad struct MeshQuad { #ifdef __3DO__ - uint32 indices; uint32 flags; + uint32 indices; #else Index indices[4]; uint16 flags; @@ -629,9 +629,8 @@ struct MeshQuad struct RoomTriangle { #ifdef __3DO__ - Index indices[3]; - uint16 _unused; uint32 flags; + Index indices[4]; #else Index indices[3]; uint16 flags; @@ -641,8 +640,8 @@ struct RoomTriangle struct MeshTriangle { #ifdef __3DO__ - uint32 indices; uint32 flags; + uint32 indices; #else Index indices[3]; uint16 flags; @@ -1992,8 +1991,10 @@ struct IMA_STATE }; #if defined(MODEHW) + #define PERSPECTIVE_DZ(z) (z >> 4) + #define PERSPECTIVE(x, y, z) {\ - int32 dz = z >> 4;\ + int32 dz = PERSPECTIVE_DZ(z);\ if (dz >= DIV_TABLE_SIZE) dz = DIV_TABLE_SIZE - 1;\ int32 d = FixedInvU(dz);\ x = (x * d) >> 12;\ @@ -2008,9 +2009,10 @@ struct IMA_STATE y = d * (y >> 14) >> 12;\ } #elif defined(MODE4) + #define PERSPECTIVE_DZ(z) ((z >> 4) + (z >> 6)) + #define PERSPECTIVE(x, y, z) {\ - int32 dz = z >> 4;\ - dz += z >> 6;\ + int32 dz = PERSPECTIVE_DZ(z);\ if (dz >= DIV_TABLE_SIZE) dz = DIV_TABLE_SIZE - 1;\ int32 d = FixedInvU(dz);\ x = (x * d) >> 12;\ @@ -2147,6 +2149,7 @@ X_INLINE Matrix& matrixGet() X_INLINE void matrixPush() { + ASSERT(matrixPtr - matrixStack < MAX_MATRICES); memcpy(matrixPtr + 1, matrixPtr, sizeof(Matrix)); matrixPtr++; } diff --git a/src/fixed/room.h b/src/fixed/room.h index 830d371..8ac7e1e 100644 --- a/src/fixed/room.h +++ b/src/fixed/room.h @@ -421,19 +421,19 @@ bool Room::checkPortal(const Portal* portal) continue; } - if (z >= VIEW_MAX_F) + if (z > VIEW_MAX_F) { z = VIEW_MAX_F; zfar++; } - int32 dz = (z >> (FIXED_SHIFT + FOV_SHIFT + 1)); // TODO PROJ_SHIFT? + x >>= FIXED_SHIFT; + y >>= FIXED_SHIFT; + z >>= FIXED_SHIFT; + + int32 dz = PERSPECTIVE_DZ(z); if (dz > 0) { - x >>= FIXED_SHIFT; - y >>= FIXED_SHIFT; - z >>= FIXED_SHIFT; - PERSPECTIVE(x, y, z); x += FRAME_WIDTH >> 1; diff --git a/src/platform/3do/ccbMap3.s b/src/platform/3do/ccbMap3.s index 28daf2a..32ad50d 100644 --- a/src/platform/3do/ccbMap3.s +++ b/src/platform/3do/ccbMap3.s @@ -1,6 +1,8 @@ AREA |C$$code|, CODE, READONLY |x$codeseg| + INCLUDE common_asm.inc + EXPORT ccbMap3_asm ccbMap3_asm @@ -32,9 +34,6 @@ shift RN hs hddx RN ws hddy RN hs -FRAME_WIDTH EQU 320 -FRAME_HEIGHT EQU 240 - stmfd sp!, {r4-r6, lr} add face, face, #16 ; offset to ccb_XPos diff --git a/src/platform/3do/ccbMap4.s b/src/platform/3do/ccbMap4.s index ff4a207..5421022 100644 --- a/src/platform/3do/ccbMap4.s +++ b/src/platform/3do/ccbMap4.s @@ -1,6 +1,8 @@ AREA |C$$code|, CODE, READONLY |x$codeseg| + INCLUDE common_asm.inc + EXPORT ccbMap4_asm ccbMap4_asm @@ -37,9 +39,6 @@ ws RN r12 hs RN lr shift RN hs -FRAME_WIDTH EQU 320 -FRAME_HEIGHT EQU 240 - stmfd sp!, {r4-r8, lr} add face, face, #16 ; offset to ccb_XPos diff --git a/src/platform/3do/common_asm.inc b/src/platform/3do/common_asm.inc new file mode 100644 index 0000000..ac5f220 --- /dev/null +++ b/src/platform/3do/common_asm.inc @@ -0,0 +1,59 @@ + IMPORT matrixPtr + IMPORT viewportRel + IMPORT gVertices + IMPORT gFacesBase + IMPORT gOT + IMPORT gPaletteOffset + IMPORT shadeTable + IMPORT divTable + IMPORT level + +CCB_NOBLK EQU 0x00000010 +CCB_BGND EQU 0x00000020 +CCB_ACE EQU 0x00004000 +CCB_ACCW EQU 0x00020000 +CCB_ACW EQU 0x00040000 +CCB_ALSC EQU 0x00080000 +CCB_ACSC EQU 0x00100000 +CCB_YOXY EQU 0x00200000 +CCB_LDPLUT EQU 0x00800000 +CCB_LDPPMP EQU 0x01000000 +CCB_LDPRS EQU 0x02000000 +CCB_LDSIZE EQU 0x04000000 +CCB_PPABS EQU 0x08000000 +CCB_SPABS EQU 0x10000000 +CCB_NPABS EQU 0x20000000 +SIZE_OF_CCB EQU 68 + +FRAME_WIDTH EQU 320 +FRAME_HEIGHT EQU 240 + +FIXED_SHIFT EQU 14 +PROJ_SHIFT EQU 4 +LVL_TEX_OFFSET EQU (23 * 4) + +CLIP_SHIFT EQU 8 +CLIP_MASK EQU ((1 << CLIP_SHIFT) - 1) +CLIP_LEFT EQU (1 << 0) +CLIP_RIGHT EQU (1 << 1) +CLIP_TOP EQU (1 << 2) +CLIP_BOTTOM EQU (1 << 3) +CLIP_FAR EQU (1 << 4) +CLIP_NEAR EQU (1 << 5) + +FACE_MIP_SHIFT EQU 11 +MIP_DIST EQU (1024 * 5) +VIEW_DIST EQU (1024 * 10) ; max = DIV_TABLE_END << PROJ_SHIFT +FOG_SHIFT EQU 1 +FOG_MAX EQU VIEW_DIST +FOG_MIN EQU (FOG_MAX - (8192 >> FOG_SHIFT)) +VIEW_MIN_F EQU (256 << FIXED_SHIFT) +VIEW_MAX_F EQU (VIEW_DIST << FIXED_SHIFT) +OT_SHIFT EQU 4 +OT_SIZE EQU ((VIEW_MAX_F >> (FIXED_SHIFT + OT_SHIFT)) + 1) + +DIV_TABLE_END EQU (1025 - 1) +VIEW_MIN EQU (256 << CLIP_SHIFT) +VIEW_MAX EQU (VIEW_DIST << CLIP_SHIFT) + +MulManyVec3Mat33_F16 EQU (0x50000 + 2) \ No newline at end of file diff --git a/src/platform/3do/faceAddRoomQuads.s b/src/platform/3do/faceAddRoomQuads.s new file mode 100644 index 0000000..9620551 --- /dev/null +++ b/src/platform/3do/faceAddRoomQuads.s @@ -0,0 +1,260 @@ + AREA |C$$code|, CODE, READONLY +|x$codeseg| + + INCLUDE common_asm.inc + + EXPORT faceAddRoomQuads_asm + +faceAddRoomQuads_asm + +quadsArg RN r0 +countArg RN r1 + +flags RN quadsArg + +vx0 RN r2 +vy0 RN r3 + +vx1 RN r4 +vy1 RN r5 + +vx3 RN r6 +vy3 RN r7 + +vx2 RN r8 +vy2 RN r9 + +pixc RN r10 +tex RN r11 + +mask RN r12 +depth RN lr + +spQuads RN vx0 +spLast RN vx1 +spVertices RN vy3 +spOT RN vx2 +spShadeLUT RN vy2 +spTextures RN pixc +spFaceBase RN tex +spPalette RN mask + +face RN mask +faceBase RN mask +hv0 RN mask +hv1 RN vy2 + +i0 RN vy0 +i1 RN vy1 + +vz0 RN vy0 +vz1 RN vy1 +vz2 RN vy2 +vz3 RN vy3 + +vp0 RN vx0 +vp1 RN vx1 +vp2 RN vx2 +vp3 RN vx3 + +xpos RN vx0 +ypos RN vy0 +hdx0 RN vx1 +hdy0 RN vy1 +hdx1 RN vx2 +hdy1 RN vy2 +vdx0 RN vx3 +vdy0 RN vy3 +hddx RN hdx1 +hddy RN hdy1 + +nextPtr RN vy2 +dataPtr RN flags +plutPtr RN countArg + +tmp RN countArg +ot RN countArg +otTail RN depth + +shadeLUT RN pixc +fog RN pixc + +intensity RN vy2 +plutOffset RN vy2 +texIndex RN vy2 + +ws RN tex +hs RN depth +shift RN depth + +SP_QUADS EQU 0 +SP_LAST EQU 4 +SP_VERTICES EQU 8 +SP_OT EQU 12 +SP_SHADELUT EQU 16 +SP_TEXTURES EQU 20 +SP_FACEBASE EQU 24 +SP_PALETTE EQU 28 +SP_SIZE EQU 32 + + stmfd sp!, {r4-r11, lr} + sub sp, sp, #SP_SIZE + + add countArg, countArg, countArg, lsl #1 + add spLast, quadsArg, countArg, lsl #2 + ldr spVertices, =gVertices + ldr spOT, =gOT + ldr spShadeLUT, =shadeTable + ldr spTextures, =level + ldr spTextures, [spTextures, #LVL_TEX_OFFSET] + ldr spFaceBase, =gFacesBase + ldr spPalette, =gPaletteOffset + ldr spPalette, [spPalette] + + stmia sp, {quadsArg, spLast, spVertices, spOT, spShadeLUT, spTextures, spFaceBase, spPalette} + +loop ldmia sp, {spQuads, spLast, spVertices} + cmp spQuads, spLast + bge done + + ldmia spQuads!, {flags, i0, i1} + str spQuads, [sp, #SP_QUADS] + + ; get vertex pointers + add vp0, spVertices, i0, lsr #16 + mov i0, i0, lsl #16 + add vp1, spVertices, i0, lsr #16 + + add vp2, spVertices, i1, lsr #16 + mov i1, i1, lsl #16 + add vp3, spVertices, i1, lsr #16 + + ; read z value with clip mask + ldr vz0, [vp0, #8] + ldr vz1, [vp1, #8] + ldr vz2, [vp2, #8] + ldr vz3, [vp3, #8] + + ; check clipping + and mask, vz1, vz0 + and mask, vz2, mask + and mask, vz3, mask + tst mask, #CLIP_MASK + bne loop + + ; depth = max(vz0, vz1, vz2, vz3) (DEPTH_Q_MAX) + mov depth, vz0 + cmp depth, vz1 + movlt depth, vz1 + cmp depth, vz2 + movlt depth, vz2 + cmp depth, vz3 + movlt depth, vz3 + + ; (vx1 - vx0) * (vy3 - vy0) <= (vy1 - vy0) * (vx3 - vx0) + ldmia vp0, {vx0, vy0} + ldmia vp1, {vx1, vy1} + ldmia vp3, {vx3, vy3} + sub hdx0, vx1, vx0 + sub hdy0, vy1, vy0 + sub vdx0, vx3, vx0 + sub vdy0, vy3, vy0 + mul hv0, hdx0, vdy0 + mul hv1, hdy0, vdx0 + cmp hv0, hv1 + ble loop + + ; depth = max(0, depth) >> (CLIP_SHIFT + OT_SHIFT) + movs depth, depth, lsr #(CLIP_SHIFT + OT_SHIFT) + movmi depth, #0 + + ; fog = max(0, (depth - (FOG_MIN >> OT_SHIFT)) >> 1) + sub fog, depth, #(FOG_MIN >> OT_SHIFT) + movs fog, fog, asr #1 + movmi fog, #0 + + ; intensity = min(255, fog + ((flags >> (FACE_MIP_SHIFT + FACE_MIP_SHIFT)) & 0xFF)) >> 3 + mov intensity, flags, lsl #(32 - 8 - FACE_MIP_SHIFT - FACE_MIP_SHIFT) + add intensity, fog, intensity, lsr #(32 - 8) + cmp intensity, #255 + movcs intensity, #255 + mov intensity, intensity, lsr #3 + + add tmp, sp, #SP_OT + ldmia tmp, {ot, shadeLUT, tex, faceBase} + + ; pixc = shadeTable[intensity] + ldr pixc, [shadeLUT, intensity, lsl #2] + + ; get texture ptr (base or mip) + mov texIndex, flags + cmp depth, #(MIP_DIST >> OT_SHIFT) + movgt texIndex, flags, lsr #FACE_MIP_SHIFT + mov texIndex, texIndex, lsl #(32 - FACE_MIP_SHIFT) + mov texIndex, texIndex, lsr #(32 - FACE_MIP_SHIFT) + add texIndex, texIndex, texIndex, lsl #1 + add tex, tex, texIndex, lsl #2 + + ; faceAdd + cmp depth, #(OT_SIZE - 1) + movgt depth, #(OT_SIZE - 1) + add ot, ot, depth, lsl #3 ; mul by size of OT element + + mov depth, faceBase ; use depth reg as faceBase due face reg collision + + ldr face, [depth] + add nextPtr, face, #SIZE_OF_CCB + str nextPtr, [depth] + + ldmia ot, {nextPtr, otTail} + cmp nextPtr, #0 + moveq otTail, face + stmia ot, {face, otTail} + + ; ccb flags + ands flags, flags, #(1 << 30) + movne flags, #(CCB_BGND) + orr flags, flags, #(CCB_NOBLK) + orr flags, flags, #(CCB_ACE + CCB_ACCW + CCB_ACW + CCB_ALSC + CCB_ACSC + CCB_YOXY) + orr flags, flags, #(CCB_LDPLUT + CCB_LDPPMP + CCB_LDPRS + CCB_LDSIZE + CCB_PPABS + CCB_SPABS + CCB_NPABS) + + ; ccbMap4 + stmia face!, {flags, nextPtr} + ldmia tex, {dataPtr, plutPtr, shift} + + ldr plutOffset, [sp, #SP_PALETTE] + add plutPtr, plutPtr, plutOffset + + ldmia vp2, {vx2, vy2} + sub vx2, vx2, vx0 + sub vy2, vy2, vy0 + sub hdx1, vx2, vx3 + sub hdy1, vy2, vy3 + + and ws, shift, #0xFF + mov hs, shift, lsr #8 + + mov hdx0, hdx0, lsl ws + mov hdy0, hdy0, lsl ws + + mov vdx0, vdx0, lsl hs + mov vdy0, vdy0, lsl hs + + rsb hs, hs, #16 + rsb hddx, hdx0, hdx1, lsl ws + rsb hddy, hdy0, hdy1, lsl ws + mov hddx, hddx, asr hs + mov hddy, hddy, asr hs + + mov xpos, vx0, lsl #16 + mov ypos, vy0, lsl #16 + add xpos, xpos, #(FRAME_WIDTH << 15) + add ypos, ypos, #(FRAME_HEIGHT << 15) + + stmia face, {dataPtr, plutPtr, xpos, ypos, hdx0, hdy0, vdx0, vdy0, hddx, hddy, pixc} + + bl loop + +done add sp, sp, #SP_SIZE + ldmfd sp!, {r4-r11, pc} + END diff --git a/src/platform/3do/matrixLerp.s b/src/platform/3do/matrixLerp.s index 094d2ee..d66530a 100644 --- a/src/platform/3do/matrixLerp.s +++ b/src/platform/3do/matrixLerp.s @@ -1,8 +1,8 @@ AREA |C$$code|, CODE, READONLY |x$codeseg| - IMPORT matrixPtr - IMPORT divTable + INCLUDE common_asm.inc + EXPORT matrixLerp_asm n RN r0 diff --git a/src/platform/3do/projectVertices.s b/src/platform/3do/projectVertices.s index 54bf1f8..c632bac 100644 --- a/src/platform/3do/projectVertices.s +++ b/src/platform/3do/projectVertices.s @@ -1,10 +1,8 @@ AREA |C$$code|, CODE, READONLY |x$codeseg| - IMPORT matrixPtr - IMPORT viewportRel - IMPORT divTable - IMPORT gVertices + INCLUDE common_asm.inc + EXPORT projectVertices_asm vCount RN r0 @@ -25,23 +23,6 @@ last RN r10 vertex RN r11 divLUT RN lr -FIXED_SHIFT EQU 14 -PROJ_SHIFT EQU 4 -CLIP_SHIFT EQU 8 -CLIP_LEFT EQU (1 << 0) -CLIP_RIGHT EQU (1 << 1) -CLIP_TOP EQU (1 << 2) -CLIP_BOTTOM EQU (1 << 3) -CLIP_FAR EQU (1 << 4) -CLIP_NEAR EQU (1 << 5) - -DIV_TABLE_END EQU (1025 - 1) -VIEW_DIST EQU (1024 * 10) ; max = DIV_TABLE_END << PROJ_SHIFT -VIEW_MIN EQU (256 << CLIP_SHIFT) -VIEW_MAX EQU (VIEW_DIST << CLIP_SHIFT) - -MulManyVec3Mat33_F16 EQU (0x50000 + 2) - projectVertices_asm stmfd sp!, {r4-r11, lr} diff --git a/src/platform/3do/render_cel.cpp b/src/platform/3do/render_cel.cpp index d0f6bff..e500348 100644 --- a/src/platform/3do/render_cel.cpp +++ b/src/platform/3do/render_cel.cpp @@ -22,11 +22,14 @@ int32 gFacesCount; Vertex gVertices[MAX_VERTICES]; Face* gFaces; // MAX_FACES -Face* otFacesHead[OT_SIZE]; -Face* otFacesTail[OT_SIZE]; +Face* gFacesBase; -int32 otMin = OT_SIZE - 1; -int32 otMax = 0; +struct ListOT { + Face* head; + Face* tail; +}; + +ListOT gOT[OT_SIZE]; struct ViewportRel { int16 x0, y0; @@ -75,7 +78,7 @@ enum ShadeValue SHADE_24 = DUP16( PPMPC_MF_8 | PPMPC_SF_16 | PPMPC_2S_PDC ) // 1 + 8/16 }; -static const uint32 shadeTable[32] = { +extern "C" const uint32 shadeTable[32] = { SHADE_24, SHADE_24, SHADE_23, @@ -114,6 +117,7 @@ void renderInit() { gPalette = (uint16*)RAM_TEX; gFaces = (Face*)RAM_CEL; + gFacesBase = gFaces; Face* face = gFaces; for (int32 i = 0; i < MAX_FACES; i++, face++) @@ -164,10 +168,10 @@ int32 boxIsVisible(const AABBs* box) return rectIsVisible(&rect); } -X_INLINE bool checkBackface(const Vertex *a, const Vertex *b, const Vertex *c) +X_INLINE int32 cross(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) <= 0; + (c->x - a->x) * (b->y - a->y); } enum ClipFlags { @@ -181,12 +185,18 @@ enum ClipFlags { CLIP_NEAR = 1 << 5 }; +#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)) + #ifdef USE_ASM #define unpackRoom unpackRoom_asm #define unpackMesh unpackMesh_asm #define projectVertices projectVertices_asm #define ccbMap4 ccbMap4_asm #define ccbMap3 ccbMap3_asm + #define faceAddRoomQuads faceAddRoomQuads_asm extern "C" { void unpackRoom_asm(const RoomVertex* vertices, int32 vCount); @@ -194,6 +204,7 @@ enum ClipFlags { void projectVertices_asm(int32 vCount); void ccbMap4_asm(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, const Vertex* v3, uint32 shift); void ccbMap3_asm(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, uint32 shift); + void faceAddRoomQuads_asm(const RoomQuad* quads, int32 count); } #else #define unpackRoom unpackRoom_c @@ -201,6 +212,11 @@ enum ClipFlags { #define projectVertices projectVertices_c #define ccbMap4 ccbMap4_c #define ccbMap3 ccbMap3_c + #define faceAddRoomQuads faceAddRoomQuads_c + + Face* faceAdd(int32 depth); + void ccbSetTexture(uint32 flags, Face* face, const Texture* texture); + void ccbSetColor(uint32 flags, Face* face); void unpackRoom_c(const RoomVertex* vertices, int32 vCount) { @@ -305,7 +321,7 @@ void projectVertices_c(int32 vCount) } while (v < last); } -void ccbMap4_c(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, const Vertex* v3, uint32 shift) +X_INLINE void ccbMap4_c(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, const Vertex* v3, uint32 shift) { int32 x1 = v1->x; int32 y1 = v1->y; @@ -345,7 +361,7 @@ void ccbMap4_c(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, co #endif } -void ccbMap3_c(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, uint32 shift) +X_INLINE void ccbMap3_c(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, uint32 shift) { int32 x0 = v0->x; int32 y0 = v0->y; @@ -377,6 +393,57 @@ void ccbMap3_c(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, ui f->ccb_PIXC = SHADE_SHADOW; #endif } + +void faceAddRoomQuads_c(const RoomQuad* quads, int32 count) +{ + for (int32 i = 0; i < count; i++, quads++) + { + uint32 flags = quads->flags; + uint32* indices = (uint32*)quads->indices; + + uint32 i01 = indices[0]; + uint32 i23 = indices[1]; + + uint32 i0 = (i01 >> 16); + uint32 i1 = (i01 & 0xFFFF); + uint32 i2 = (i23 >> 16); + uint32 i3 = (i23 & 0xFFFF); + + const Vertex* v0 = (Vertex*)((uint8*)gVertices + i0); + const Vertex* v1 = (Vertex*)((uint8*)gVertices + i1); + const Vertex* v2 = (Vertex*)((uint8*)gVertices + i2); + const Vertex* v3 = (Vertex*)((uint8*)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) + continue; + + int32 depth = DEPTH_Q_MAX(c0, c1, c2, c3); + + if (cross(v0, v1, v3) <= 0) + continue; + + Face* f = faceAdd(depth); + + int32 fog = X_MAX(0, (depth - (FOG_MIN >> OT_SHIFT)) >> 1); + uint32 intensity = X_MIN(255, fog + ((flags >> (FACE_MIP_SHIFT + FACE_MIP_SHIFT)) & 0xFF)); + + f->ccb_PIXC = shadeTable[intensity >> 3]; + + uint32 texIndex = flags; + if (depth > (MIP_DIST >> OT_SHIFT)) { + texIndex >>= FACE_MIP_SHIFT; + } + const Texture* texture = level.textures + (texIndex & FACE_TEXTURE); + ccbSetTexture(flags, f, texture); + + ccbMap4(f, v0, v1, v2, v3, texture->shift); + } +} #endif bool transformBoxRect(const AABBs* box, RectMinMax* rect) @@ -454,29 +521,20 @@ void transformMesh(const MeshVertex* vertices, int32 vCount, const uint16* vInte gVerticesCount += vCount; } -#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)) - X_INLINE Face* faceAdd(int32 depth) { if (depth < 0) depth = 0; if (depth > OT_SIZE - 1) depth = OT_SIZE - 1; - if (depth < otMin) otMin = depth; - if (depth > otMax) otMax = depth; + Face* face = gFacesBase++; - Face* face = gFaces + gFacesCount++; - - if (otFacesHead[depth]) { - face->ccb_NextPtr = otFacesHead[depth]; + if (gOT[depth].head) { + face->ccb_NextPtr = gOT[depth].head; } else { - face->ccb_NextPtr = NULL; - otFacesTail[depth] = face; + gOT[depth].tail = face; } - otFacesHead[depth] = face; + gOT[depth].head = face; return face; } @@ -522,54 +580,6 @@ X_INLINE void ccbSetColor(uint32 flags, Face* face) face->ccb_SourcePtr = (CelData*)&gPalette[flags & 0xFF]; } -X_INLINE void faceAddRoomQuad(uint32 flags, const Index* indices) -{ - uint32 i01 = ((uint32*)indices)[0]; - uint32 i23 = ((uint32*)indices)[1]; - - uint32 i0 = (i01 >> 16); - uint32 i1 = (i01 & 0xFFFF); - uint32 i2 = (i23 >> 16); - uint32 i3 = (i23 & 0xFFFF); - - const Vertex* v0 = gVertices + i0; - const Vertex* v1 = gVertices + i1; - 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; - - int32 depth = DEPTH_Q_MAX(c0, c1, c2, c3); - - if (checkBackface(v0, v1, v3) == !(flags & FACE_CCW)) - return; - - Face* f = faceAdd(depth); - - uint32 intensity = (flags >> (FACE_MIP_SHIFT + FACE_MIP_SHIFT)) & 0xFF; - if (depth > (FOG_MIN >> OT_SHIFT)) { - intensity += (depth - (FOG_MIN >> OT_SHIFT)) >> 1; - intensity = X_MIN(intensity, 255); - } - - f->ccb_PIXC = shadeTable[intensity >> 3]; - - uint32 texIndex = flags; - if (depth > (MIP_DIST >> OT_SHIFT)) { - texIndex >>= FACE_MIP_SHIFT; - } - const Texture* texture = level.textures + (texIndex & FACE_TEXTURE); - ccbSetTexture(flags, f, texture); - - ccbMap4(f, v0, v1, v2, v3, texture->shift); -} - X_INLINE void faceAddRoomTriangle(uint32 flags, const Index* indices) { uint32 i01 = ((uint32*)indices)[0]; @@ -579,9 +589,9 @@ X_INLINE void faceAddRoomTriangle(uint32 flags, const Index* indices) uint32 i1 = (i01 & 0xFFFF); uint32 i2 = (i23 >> 16); - const Vertex* v0 = gVertices + i0; - const Vertex* v1 = gVertices + i1; - const Vertex* v2 = gVertices + i2; + const Vertex* v0 = (Vertex*)((uint8*)gVertices + i0); + const Vertex* v1 = (Vertex*)((uint8*)gVertices + i1); + const Vertex* v2 = (Vertex*)((uint8*)gVertices + i2); uint32 c0 = v0->z; uint32 c1 = v1->z; @@ -592,7 +602,7 @@ X_INLINE void faceAddRoomTriangle(uint32 flags, const Index* indices) int32 depth = DEPTH_T_MAX(c0, c1, c2); - if (checkBackface(v0, v1, v2) == !(flags & FACE_CCW)) + if (cross(v0, v1, v2) <= 0) return; Face* f = faceAdd(depth); @@ -635,7 +645,7 @@ X_INLINE void faceAddMeshQuad(uint32 flags, uint32 indices, uint32 shade) if ((c0 & c1 & c2 & c3) & CLIP_MASK) return; - if (checkBackface(v0, v1, v3) == !(flags & FACE_CCW)) // TODO (hdx0 * vdy0 - vdx0 * hdy0) <= 0 + if ((cross(v0, v1, v3) ^ flags) & FACE_CCW) // TODO (hdx0 * vdy0 - vdx0 * hdy0) <= 0 return; int32 depth = DEPTH_Q_AVG(v0->z, v1->z, v2->z, v3->z); @@ -666,7 +676,7 @@ X_INLINE void faceAddMeshTriangle(uint32 flags, uint32 indices, uint32 shade) if ((c0 & c1 & c2) & CLIP_MASK) return; - if (checkBackface(v0, v1, v2)) + if (cross(v0, v1, v2) <= 0) return; int32 depth = DEPTH_T_AVG(v0->z, v1->z, v2->z); @@ -700,7 +710,7 @@ X_INLINE void faceAddMeshQuadFlat(uint32 flags, uint32 indices, uint32 shade) if ((c0 & c1 & c2 & c3) & CLIP_MASK) return; - if (checkBackface(v0, v1, v3)) + if (cross(v0, v1, v3) <= 0) return; int32 depth = DEPTH_Q_AVG(v0->z, v1->z, v2->z, v3->z); @@ -730,7 +740,7 @@ X_INLINE void faceAddMeshTriangleFlat(uint32 flags, uint32 indices, uint32 shade if ((c0 & c1 & c2) & CLIP_MASK) return; - if (checkBackface(v0, v1, v2)) + if (cross(v0, v1, v2) <= 0) return; int32 depth = DEPTH_T_AVG(v0->z, v1->z, v2->z); @@ -745,6 +755,10 @@ X_INLINE void faceAddMeshTriangleFlat(uint32 flags, uint32 indices, uint32 shade void faceAddShadow(int32 x, int32 z, int32 sx, int32 sz) { + if (gFacesCount + 3 > MAX_FACES) + return; + gFacesCount += 3; + x <<= F16_SHIFT; z <<= F16_SHIFT; sx <<= F16_SHIFT; @@ -775,6 +789,7 @@ void faceAddSprite(int32 vx, int32 vy, int32 vz, int32 vg, int32 index) { if (gFacesCount >= MAX_FACES) return; + gFacesCount++; const Matrix &m = matrixGet(); @@ -789,8 +804,6 @@ void faceAddSprite(int32 vx, int32 vy, int32 vz, int32 vg, int32 index) 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); @@ -854,6 +867,10 @@ void faceAddSprite(int32 vx, int32 vy, int32 vz, int32 vg, int32 index) void faceAddGlyph(int32 vx, int32 vy, int32 index) { + if (gFacesCount >= MAX_FACES) + return; + gFacesCount++; + const Sprite* sprite = level.sprites + index; Face* f = faceAdd(0); @@ -880,16 +897,14 @@ void faceAddGlyph(int32 vx, int32 vy, int32 index) void faceAddRoom(const Room* room) { - const RoomQuad* quads = room->data.quads; + faceAddRoomQuads(room->data.quads, room->info->quadsCount); + const RoomTriangle* triangles = room->data.triangles; - - for (int32 i = 0; i < room->info->quadsCount; i++, quads++) { - faceAddRoomQuad(quads->flags, quads->indices); - } - for (int32 i = 0; i < room->info->trianglesCount; i++, triangles++) { faceAddRoomTriangle(triangles->flags, triangles->indices); } + + gFacesCount = gFacesBase - gFaces; } void faceAddMesh(const MeshQuad* rFaces, const MeshQuad* crFaces, const MeshTriangle* tFaces, const MeshTriangle* ctFaces, int32 rCount, int32 crCount, int32 tCount, int32 ctCount) @@ -916,6 +931,8 @@ void faceAddMesh(const MeshQuad* rFaces, const MeshQuad* crFaces, const MeshTria for (int32 i = 0; i < ctCount; i++) { faceAddMeshTriangleFlat(ctFaces[i].flags, ctFaces[i].indices, shade); } + + gFacesCount = gFacesBase - gFaces; } void flush() @@ -927,12 +944,12 @@ void flush() { PROFILE(CNT_FLUSH); - for (int32 i = otMax; i >= otMin; i--) + for (int32 i = OT_SIZE - 1; i >= 0; i--) { - if (!otFacesHead[i]) continue; + if (!gOT[i].head) continue; - Face *face = otFacesHead[i]; - otFacesHead[i] = NULL; + Face *face = gOT[i].head; + gOT[i].head = NULL; if (face) { @@ -943,13 +960,10 @@ void flush() facesHead = face; } - facesTail = otFacesTail[i]; + facesTail = gOT[i].tail; } } - otMin = OT_SIZE - 1; - otMax = 0; - if (facesHead) { LAST_CEL(facesTail); @@ -967,6 +981,7 @@ void flush() gVerticesCount = 0; gFacesCount = 0; + gFacesBase = gFaces; } void clear() diff --git a/src/platform/3do/unpackMesh.s b/src/platform/3do/unpackMesh.s index 9169e09..a3c9f61 100644 --- a/src/platform/3do/unpackMesh.s +++ b/src/platform/3do/unpackMesh.s @@ -1,7 +1,8 @@ AREA |C$$code|, CODE, READONLY |x$codeseg| - IMPORT gVertices + INCLUDE common_asm.inc + EXPORT unpackMesh_asm unpackMesh_asm diff --git a/src/platform/3do/unpackRoom.s b/src/platform/3do/unpackRoom.s index a7c977d..7852c89 100644 --- a/src/platform/3do/unpackRoom.s +++ b/src/platform/3do/unpackRoom.s @@ -1,8 +1,8 @@ AREA |C$$code|, CODE, READONLY |x$codeseg| - IMPORT cameraViewOffset - IMPORT gVertices + INCLUDE common_asm.inc + EXPORT unpackRoom_asm unpackRoom_asm diff --git a/src/platform/gba/packer/main.cpp b/src/platform/gba/packer/main.cpp index 17a3704..3e382d2 100644 --- a/src/platform/gba/packer/main.cpp +++ b/src/platform/gba/packer/main.cpp @@ -816,11 +816,11 @@ struct LevelPC void write(FileStream &f) const { + f.write(flags); f.write(indices[0]); f.write(indices[1]); f.write(indices[2]); f.write(indices[3]); - f.write(flags); } }; @@ -831,11 +831,11 @@ struct LevelPC void write(FileStream &f) const { + f.write(flags); f.write(indices[3]); f.write(indices[2]); f.write(indices[1]); f.write(indices[0]); - f.write(flags); } }; @@ -862,11 +862,11 @@ struct LevelPC void write(FileStream &f) const { + f.write(flags); f.write(indices[0]); f.write(indices[1]); f.write(indices[2]); f.write(_unused); - f.write(flags); } }; @@ -878,12 +878,12 @@ struct LevelPC void write(FileStream &f) const { + f.write(flags); uint8 unused = 0; f.write(unused); f.write(indices[2]); f.write(indices[1]); f.write(indices[0]); - f.write(flags); } }; @@ -3738,14 +3738,20 @@ struct LevelPC q.indices[2] = addRoomVertex(info.yTop, v2, true); q.indices[3] = addRoomVertex(info.yTop, v3, true); + ASSERT((int32)q.indices[0] * 12 < 0xFFFF); + ASSERT((int32)q.indices[1] * 12 < 0xFFFF); + ASSERT((int32)q.indices[2] * 12 < 0xFFFF); + ASSERT((int32)q.indices[3] * 12 < 0xFFFF); + RoomQuad3DO comp; - comp.indices[0] = q.indices[0]; - comp.indices[1] = q.indices[1]; - comp.indices[2] = q.indices[2]; - comp.indices[3] = q.indices[3]; + comp.indices[0] = q.indices[0] * 12; + comp.indices[1] = q.indices[1] * 12; + comp.indices[2] = q.indices[2] * 12; + comp.indices[3] = q.indices[3] * 12; comp.flags = q.flags; // add ccw flag and swap indices calcQuadFlip(comp); + ASSERT((comp.flags & FACE_CCW) == 0); // add intensity comp.flags |= (intensity << (FACE_MIP_SHIFT + FACE_MIP_SHIFT)); if (textures3DO[comp.flags & FACE_TEXTURE].pre0 & PRE0_BGND) { @@ -3777,10 +3783,14 @@ struct LevelPC t.indices[1] = addRoomVertex(info.yTop, v1, true); t.indices[2] = addRoomVertex(info.yTop, v2, true); + ASSERT((int32)t.indices[0] * 12 < 0xFFFF); + ASSERT((int32)t.indices[1] * 12 < 0xFFFF); + ASSERT((int32)t.indices[2] * 12 < 0xFFFF); + RoomTriangle3DO comp; - comp.indices[0] = t.indices[0]; - comp.indices[1] = t.indices[1]; - comp.indices[2] = t.indices[2]; + comp.indices[0] = t.indices[0] * 12; + comp.indices[1] = t.indices[1] * 12; + comp.indices[2] = t.indices[2] * 12; comp._unused = 0; comp.flags = t.flags; // add intensity