From a5f1d132761a3779c351e4139ed251fe3586be1e Mon Sep 17 00:00:00 2001 From: XProger Date: Fri, 31 Dec 2021 07:54:57 +0300 Subject: [PATCH] #368 underwater room caustics ARM --- src/fixed/common.cpp | 47 ++++++++ src/fixed/common.h | 131 ++++++++++++++++++++ src/fixed/draw.h | 32 ++--- src/fixed/game.h | 19 +++ src/fixed/inventory.h | 149 ++++++++++------------- src/fixed/lara.h | 3 +- src/fixed/level.h | 7 +- src/platform/3do/main.cpp | 38 +----- src/platform/3do/render_cel.cpp | 12 +- src/platform/gba/common_asm.inc | 7 +- src/platform/gba/main.cpp | 66 ++++------- src/platform/gba/packer/main.cpp | 1 + src/platform/gba/render.iwram.cpp | 83 +++++++++++-- src/platform/gba/transformMesh.s | 2 +- src/platform/gba/transformRoom.s | 38 +++--- src/platform/gba/transformRoomUW.s | 184 +++++++++++++++++++++++++++++ 16 files changed, 582 insertions(+), 237 deletions(-) create mode 100644 src/platform/gba/transformRoomUW.s diff --git a/src/fixed/common.cpp b/src/fixed/common.cpp index d13956d2..1b4176e9 100644 --- a/src/fixed/common.cpp +++ b/src/fixed/common.cpp @@ -17,8 +17,55 @@ EWRAM_DATA Settings gSettings; EWRAM_DATA int32 gCurTrack; EWRAM_DATA int32 gAnimTexFrame; +int32 gLightAmbient; +int32 gRandTable[MAX_RAND_TABLE]; +int32 gCaustics[MAX_CAUSTICS]; +int32 gCausticsFrame; + EWRAM_DATA ExtraInfoLara playersExtra[MAX_PLAYERS]; +#ifdef __GBA__ + #include "TRACKS_IMA.h" + #include "TITLE_PKD.h" + #include "GYM_PKD.h" + #include "LEVEL1_PKD.h" + #include "LEVEL2_PKD.h" + + #define LEVEL_INFO(name, title, track, secrets) { #name, name##_PKD, title, track, secrets } +#else + #define LEVEL_INFO(name, title, track, secrets) { #name, NULL, title, track, secrets } +#endif + +const LevelInfo gLevelInfo[LVL_MAX] = { +// TR1 + LEVEL_INFO( TITLE , STR_EMPTY , TRACK_TR1_TITLE , 0 ), + LEVEL_INFO( GYM , STR_TR1_GYM , TRACK_NONE , 0 ), + LEVEL_INFO( LEVEL1 , STR_TR1_LEVEL1 , TRACK_TR1_CAVES , 3 ), + LEVEL_INFO( LEVEL2 , STR_TR1_LEVEL2 , TRACK_TR1_CAVES , 3 ), + //LEVEL_INFO( LEVEL3A , STR_TR1_LEVEL3A , TRACK_TR1_CAVES , 5 ), + //LEVEL_INFO( LEVEL3B , STR_TR1_LEVEL3B , TRACK_TR1_CAVES , 3 ), + //LEVEL_INFO( CUT1 , STR_EMPTY , TRACK_TR1_CUT_1 , 0 ), + //LEVEL_INFO( LEVEL4 , STR_TR1_LEVEL4 , TRACK_TR1_WIND , 4 ), + //LEVEL_INFO( LEVEL5 , STR_TR1_LEVEL5 , TRACK_TR1_WIND , 3 ), + //LEVEL_INFO( LEVEL6 , STR_TR1_LEVEL6 , TRACK_TR1_WIND , 3 ), + //LEVEL_INFO( LEVEL7A , STR_TR1_LEVEL7A , TRACK_TR1_CISTERN , 3 ), + //LEVEL_INFO( LEVEL7B , STR_TR1_LEVEL7B , TRACK_TR1_CISTERN , 2 ), + //LEVEL_INFO( CUT2 , STR_EMPTY , TRACK_TR1_CUT_2 , 0 ), + //LEVEL_INFO( LEVEL8A , STR_TR1_LEVEL8A , TRACK_TR1_WIND , 3 ), + //LEVEL_INFO( LEVEL8B , STR_TR1_LEVEL8B , TRACK_TR1_WIND , 3 ), + //LEVEL_INFO( LEVEL8C , STR_TR1_LEVEL8C , TRACK_TR1_WIND , 1 ), + //LEVEL_INFO( LEVEL10A , STR_TR1_LEVEL10A , TRACK_TR1_CISTERN , 3 ), + //LEVEL_INFO( CUT3 , STR_EMPTY , TRACK_TR1_CUT_3 , 0 ), + //LEVEL_INFO( LEVEL10B , STR_TR1_LEVEL10B , TRACK_TR1_PYRAMID , 3 ), + //LEVEL_INFO( CUT4 , STR_EMPTY , TRACK_TR1_CUT_4 , 0 ), + //LEVEL_INFO( LEVEL10C , STR_TR1_LEVEL10C , TRACK_TR1_PYRAMID , 3 ), + //LEVEL_INFO( EGYPT , STR_TR1_EGYPT , TRACK_TR1_WIND , 3 ), + //LEVEL_INFO( CAT , STR_TR1_CAT , TRACK_TR1_WIND , 4 ), + //LEVEL_INFO( END , STR_TR1_END , TRACK_TR1_WIND , 2 ) +}; + +LevelID gLevelID = LVL_TR1_GYM; + #ifdef PROFILING uint32 gCounters[CNT_MAX]; #endif diff --git a/src/fixed/common.h b/src/fixed/common.h index b21ea9f7..136342ee 100644 --- a/src/fixed/common.h +++ b/src/fixed/common.h @@ -2049,6 +2049,132 @@ struct IMA_STATE } #endif +enum StringID +{ + STR_EMPTY, + STR_PASSPORT, + STR_COMPASS, + STR_HOME, + STR_MAP, + STR_DETAIL, + STR_SOUND, + STR_CONTROLS, + STR_GAMMA, + STR_PISTOLS, + STR_SHOTGUN, + STR_MAGNUMS, + STR_UZIS, + STR_AMMO_PISTOLS, + STR_AMMO_SHOTGUN, + STR_AMMO_MAGNUMS, + STR_AMMO_UZIS, + STR_EXPLOSIVE, + STR_MEDIKIT_SMALL, + STR_MEDIKIT_BIG, + STR_PUZZLE, + STR_PUZZLE_GOLD_IDOL, + STR_PUZZLE_GOLD_BAR, + STR_PUZZLE_COG, + STR_PUZZLE_FUSE, + STR_PUZZLE_ANKH, + STR_PUZZLE_HORUS, + STR_PUZZLE_ANUBIS, + STR_PUZZLE_SCARAB, + STR_PUZZLE_PYRAMID, + STR_LEADBAR, + STR_KEY, + STR_KEY_SILVER, + STR_KEY_RUSTY, + STR_KEY_GOLD, + STR_KEY_SAPPHIRE, + STR_KEY_NEPTUNE, + STR_KEY_ATLAS, + STR_KEY_DAMOCLES, + STR_KEY_THOR, + STR_KEY_ORNATE, + STR_SCION, +// TR1 levels + STR_TR1_GYM, + STR_TR1_LEVEL1, + STR_TR1_LEVEL2, + STR_TR1_LEVEL3A, + STR_TR1_LEVEL3B, + STR_TR1_LEVEL4, + STR_TR1_LEVEL5, + STR_TR1_LEVEL6, + STR_TR1_LEVEL7A, + STR_TR1_LEVEL7B, + STR_TR1_LEVEL8A, + STR_TR1_LEVEL8B, + STR_TR1_LEVEL8C, + STR_TR1_LEVEL10A, + STR_TR1_LEVEL10B, + STR_TR1_LEVEL10C, + STR_TR1_EGYPT, + STR_TR1_CAT, + STR_TR1_END, + STR_TR1_END2, + STR_MAX +}; + +enum TrackID +{ + TRACK_NONE = -1, +// TR1 + TRACK_TR1_TITLE = 2, + TRACK_TR1_CAVES = 5, + TRACK_TR1_SECRET = 13, + TRACK_TR1_CISTERN = 57, + TRACK_TR1_WIND = 58, + TRACK_TR1_PYRAMID = 59, + TRACK_TR1_CUT_1 = 23, + TRACK_TR1_CUT_2 = 25, + TRACK_TR1_CUT_3 = 24, + TRACK_TR1_CUT_4 = 22 +}; + +struct LevelInfo +{ + const char* name; + const void* data; + StringID title; + TrackID track; + uint8 secrets; +}; + +enum LevelID +{ + LVL_TR1_TITLE, + LVL_TR1_GYM, + LVL_TR1_1, + LVL_TR1_2, + //LVL_TR1_3A, + //LVL_TR1_3B, + //LVL_TR1_CUT_1, + //LVL_TR1_4, + //LVL_TR1_5, + //LVL_TR1_6, + //LVL_TR1_7A, + //LVL_TR1_7B, + //LVL_TR1_CUT_2, + //LVL_TR1_8A, + //LVL_TR1_8B, + //LVL_TR1_8C, + //LVL_TR1_10A, + //LVL_TR1_CUT_3, + //LVL_TR1_10B, + //LVL_TR1_CUT_4, + //LVL_TR1_10C, + //LVL_TR1_EGYPT, + //LVL_TR1_CAT, + //LVL_TR1_END, + //LVL_TR1_END2, + LVL_MAX +}; + +extern const LevelInfo gLevelInfo[LVL_MAX]; +extern LevelID gLevelID; + // renderer internal extern uint32 keys; extern RectMinMax viewport; @@ -2067,6 +2193,11 @@ extern Settings gSettings; extern int32 gCurTrack; extern int32 gAnimTexFrame; +extern int32 gLightAmbient; +extern int32 gRandTable[MAX_RAND_TABLE]; +extern int32 gCaustics[MAX_CAUSTICS]; +extern int32 gCausticsFrame; + extern const FloorData* gLastFloorData; extern FloorData gLastFloorSlant; diff --git a/src/fixed/draw.h b/src/fixed/draw.h index 709fccd0..9dc666fa 100644 --- a/src/fixed/draw.h +++ b/src/fixed/draw.h @@ -4,23 +4,17 @@ #include "common.h" #include "item.h" -int32 lightAmbient; - -int32 randTable[MAX_RAND_TABLE]; -int32 caustics[MAX_CAUSTICS]; -int32 causticsFrame; - void drawInit() { for (int32 i = 0; i < MAX_RAND_TABLE; i++) { - randTable[i] = (rand_draw() >> 5) - 511; + gRandTable[i] = (rand_draw() >> 5) - 511; } for (int32 i = 0; i < MAX_CAUSTICS; i++) { int16 rot = i * (ANGLE_90 * 4) / MAX_CAUSTICS; - caustics[i] = sin(rot) * 768 >> FIXED_SHIFT; + gCaustics[i] = sin(rot) * 768 >> FIXED_SHIFT; } } @@ -33,12 +27,12 @@ void calcLightingDynamic(const Room* room, const vec3i &point) { const RoomInfo* info = room->info; - lightAmbient = (info->ambient << 5); + gLightAmbient = (info->ambient << 5); if (!info->lightsCount) return; - lightAmbient = 8191 - lightAmbient; + gLightAmbient = 8191 - gLightAmbient; int32 maxLum = 0; for (int i = 0; i < info->lightsCount; i++) @@ -57,34 +51,34 @@ void calcLightingDynamic(const Room* room, const vec3i &point) int32 dist = dot(d, d) >> 12; int32 att = X_SQR(radius) >> 12; - int32 lum = (intensity * att) / (dist + att) + lightAmbient; + int32 lum = (intensity * att) / (dist + att) + gLightAmbient; if (lum > maxLum) { maxLum = lum; } } - lightAmbient = 8191 - ((maxLum + lightAmbient) >> 1); + gLightAmbient = 8191 - ((maxLum + gLightAmbient) >> 1); Matrix &m = matrixGet(); int32 fogZ = m.e23 >> FIXED_SHIFT; if (fogZ > FOG_MIN) { - lightAmbient += (fogZ - FOG_MIN) << FOG_SHIFT; - lightAmbient = X_MIN(lightAmbient, 8191); + gLightAmbient += (fogZ - FOG_MIN) << FOG_SHIFT; + gLightAmbient = X_MIN(gLightAmbient, 8191); } } void calcLightingStatic(int32 intensity) { - lightAmbient = intensity - 4096; + gLightAmbient = intensity - 4096; Matrix &m = matrixGet(); int32 fogZ = m.e23 >> FIXED_SHIFT; if (fogZ > FOG_MIN) { - lightAmbient += (fogZ - FOG_MIN) << FOG_SHIFT; - lightAmbient = X_MIN(lightAmbient, 8191); + gLightAmbient += (fogZ - FOG_MIN) << FOG_SHIFT; + gLightAmbient = X_MIN(gLightAmbient, 8191); } } @@ -212,12 +206,12 @@ void drawFlash(const ExtraInfoLara::Arm::Flash &flash) matrixTranslateRel(0, flash.offset, 55); matrixRotateYXZ(-ANGLE_90, 0, flash.angle); - int32 tmp = lightAmbient; + int32 tmp = gLightAmbient; calcLightingStatic(flash.intensity); drawMesh(level.models[ITEM_MUZZLE_FLASH].start); - lightAmbient = tmp; + gLightAmbient = tmp; matrixPop(); } diff --git a/src/fixed/game.h b/src/fixed/game.h index 8f5ba6b6..9b17d33a 100644 --- a/src/fixed/game.h +++ b/src/fixed/game.h @@ -9,6 +9,17 @@ #include "nav.h" #include "level.h" +LevelID gNextLevel = LVL_MAX; + +void nextLevel() +{ + if (gLevelID == LVL_TR1_2) { + gNextLevel = LVL_TR1_GYM; + return; + } + gNextLevel = LevelID(gLevelID + 1); +} + struct Game { void init(const char* name) @@ -152,6 +163,14 @@ struct Game { PROFILE(CNT_UPDATE); + if (gNextLevel != LVL_MAX) + { + gLevelID = gNextLevel; + gNextLevel = LVL_MAX; + startLevel(gLevelInfo[gLevelID].name); + frames = 1; + } + if (frames > MAX_UPDATE_FRAMES) { frames = MAX_UPDATE_FRAMES; } diff --git a/src/fixed/inventory.h b/src/fixed/inventory.h index d5103cf5..c5f607df 100644 --- a/src/fixed/inventory.h +++ b/src/fixed/inventory.h @@ -3,93 +3,70 @@ #include "common.h" -enum StringID { - STR_PASSPORT - , STR_COMPASS - , STR_HOME - , STR_MAP - , STR_DETAIL - , STR_SOUND - , STR_CONTROLS - , STR_GAMMA - , STR_PISTOLS - , STR_SHOTGUN - , STR_MAGNUMS - , STR_UZIS - , STR_AMMO_PISTOLS - , STR_AMMO_SHOTGUN - , STR_AMMO_MAGNUMS - , STR_AMMO_UZIS - , STR_EXPLOSIVE - , STR_MEDIKIT_SMALL - , STR_MEDIKIT_BIG - , STR_PUZZLE - , STR_PUZZLE_GOLD_IDOL - , STR_PUZZLE_GOLD_BAR - , STR_PUZZLE_COG - , STR_PUZZLE_FUSE - , STR_PUZZLE_ANKH - , STR_PUZZLE_HORUS - , STR_PUZZLE_ANUBIS - , STR_PUZZLE_SCARAB - , STR_PUZZLE_PYRAMID - , STR_LEADBAR - , STR_KEY - , STR_KEY_SILVER - , STR_KEY_RUSTY - , STR_KEY_GOLD - , STR_KEY_SAPPHIRE - , STR_KEY_NEPTUNE - , STR_KEY_ATLAS - , STR_KEY_DAMOCLES - , STR_KEY_THOR - , STR_KEY_ORNATE - , STR_SCION - , STR_MAX -}; - const char* InvNames[STR_MAX] = { - "Game" - , "Compass" - , "Lara's Home" - , "Map" - , "Detail Levels" - , "Sound" - , "Controls" - , "Gamma" - , "Pistols" - , "Shotgun" - , "Magnums" - , "Uzis" - , "Pistol Clips" - , "Shotgun Shells" - , "Magnum Clips" - , "Uzi Clips" - , "Explosive" - , "Small Medi Pack" - , "Large Medi Pack" - , "Puzzle" - , "Gold Idol" - , "Gold Bar" - , "Machine Cog" - , "Fuse" - , "Ankh" - , "Eye of Horus" - , "Seal of Anubis" - , "Scarab" - , "Pyramid Key" - , "Lead Bar" - , "Key" - , "Silver Key" - , "Rusty Key" - , "Gold Key" - , "Sapphire Key" - , "Neptune Key" - , "Atlas Key" - , "Damocles Key" - , "Thor Key" - , "Ornate Key" - , "Scion" + "", + "Game", + "Compass", + "Lara's Home", + "Map", + "Detail Levels", + "Sound", + "Controls", + "Gamma", + "Pistols", + "Shotgun", + "Magnums", + "Uzis", + "Pistol Clips", + "Shotgun Shells", + "Magnum Clips", + "Uzi Clips", + "Explosive", + "Small Medi Pack", + "Large Medi Pack", + "Puzzle", + "Gold Idol", + "Gold Bar", + "Machine Cog", + "Fuse", + "Ankh", + "Eye of Horus", + "Seal of Anubis", + "Scarab", + "Pyramid Key", + "Lead Bar", + "Key", + "Silver Key", + "Rusty Key", + "Gold Key", + "Sapphire Key", + "Neptune Key", + "Atlas Key", + "Damocles Key", + "Thor Key", + "Ornate Key", + "Scion", +// TR1 levels + "Lara's Home", + "Caves", + "City of Vilcabamba", + "Lost Valley", + "Tomb of Qualopec", + "St. Francis' Folly", + "Colosseum", + "Palace Midas", + "The Cistern", + "Tomb of Tihocan", + "City of Khamoon", + "Obelisk of Khamoon", + "Sanctuary of the Scion", + "Natla's Mines", + "Atlantis", + "The Great Pyramid", + "Return to Egypt", + "Temple of the Cat", + "Atlantean Stronghold", + "The Hive" }; enum InvSlot { diff --git a/src/fixed/lara.h b/src/fixed/lara.h index 839ef1ba..8e818d1b 100644 --- a/src/fixed/lara.h +++ b/src/fixed/lara.h @@ -2686,8 +2686,7 @@ struct Lara : ItemObj setWeaponState(WEAPON_STATE_FREE); meshSwap(ITEM_LARA, 0xFFFFFFFF); - extern int32 gLevelID; - bool isHome = gLevelID == 0; + bool isHome = gLevelID == LVL_TR1_GYM; if (isHome) { meshSwap(ITEM_LARA_SPEC, JOINT_MASK_UPPER | JOINT_MASK_LOWER); diff --git a/src/fixed/level.h b/src/fixed/level.h index 0590444b..9fb475d5 100644 --- a/src/fixed/level.h +++ b/src/fixed/level.h @@ -160,7 +160,7 @@ void animTexturesShift() void updateLevel(int32 frames) { - causticsFrame += frames; + gCausticsFrame += frames; gAnimTexFrame += frames; while (gAnimTexFrame > 5) @@ -172,10 +172,7 @@ void updateLevel(int32 frames) int32 getAmbientTrack() { - extern int32 gLevelID; - if (gLevelID == 0) - return -1; - return 5; + return gLevelInfo[gLevelID].track; } #endif diff --git a/src/platform/3do/main.cpp b/src/platform/3do/main.cpp index 7f967c6f..4f9e3aa4 100644 --- a/src/platform/3do/main.cpp +++ b/src/platform/3do/main.cpp @@ -231,27 +231,6 @@ void* readFile(char* fileName, void* buffer, int32 bufferSize) return ptr; } -int32 gLevelID = 0; - -static const char* gLevelNames[] = { - "GYM", - "LEVEL1", - "LEVEL2", -// "LEVEL3A", -// "LEVEL3B", -// "LEVEL4", -// "LEVEL5", -// "LEVEL6", -// "LEVEL7A", -// "LEVEL7B", -// "LEVEL8A", -// "LEVEL8B", -// "LEVEL8C", -// "LEVEL10A", -// "LEVEL10B", -// "LEVEL10C" -}; - void* osLoadLevel(const char* name) { char buf[32]; @@ -268,13 +247,6 @@ void* osLoadLevel(const char* name) uint32 frame; uint32 lastFrame; -int32 reqNextLevel = -1; - -void nextLevel() -{ - reqNextLevel = (gLevelID + 1) % (sizeof(gLevelNames) / sizeof(gLevelNames[0])); -} - int main(int argc, char *argv[]) { printf("OpenLara 3DO\n"); @@ -317,7 +289,7 @@ int main(int argc, char *argv[]) sndInit(); - game.init(gLevelNames[gLevelID]); + game.init(gLevelInfo[gLevelID].name); AvailMem(&memInfoVRAM, MEMTYPE_DRAM); printf("DRAM: %d\n", memInfoVRAM.minfo_SysFree); @@ -358,14 +330,6 @@ int main(int argc, char *argv[]) nextLevel(); } - if (reqNextLevel > -1) - { - gLevelID = reqNextLevel; - reqNextLevel = -1; - game.startLevel(gLevelNames[gLevelID]); - lastFrame = frame - 1; - } - if ((keys & IK_A) && (keys & IK_C)) // respawn { players[0]->restore(); diff --git a/src/platform/3do/render_cel.cpp b/src/platform/3do/render_cel.cpp index 149f42b5..68dff104 100644 --- a/src/platform/3do/render_cel.cpp +++ b/src/platform/3do/render_cel.cpp @@ -11,10 +11,6 @@ struct Vertex uint16* gPalette; // offset to the default or underwater PLUTs extern Level level; -extern int32 lightAmbient; -extern int32 randTable[MAX_RAND_TABLE]; -extern int32 caustics[MAX_CAUSTICS]; -extern int32 causticsFrame; int32 gVerticesCount; int32 gFacesCount; @@ -1040,8 +1036,6 @@ void renderGlyph(int32 vx, int32 vy, int32 index) void faceAddRoom(const Room* room) { -// const int SIZE = 10; Face* face = gFacesBase; for (int32 i = 0; i < SIZE; i++) { - if (room->info->quadsCount) { faceAddRoomQuads(room->data.quads, room->info->quadsCount); } @@ -1050,7 +1044,6 @@ void faceAddRoom(const Room* room) faceAddRoomTriangles(room->data.triangles, room->info->trianglesCount); } -// gFacesBase = face; } memset(gOT, 0, sizeof(gOT)); #ifdef CHECK_LIMITS gFacesCount = gFacesBase - gFaces; #endif @@ -1058,9 +1051,7 @@ void faceAddRoom(const Room* room) void faceAddMesh(const MeshQuad* rFaces, const MeshQuad* crFaces, const MeshTriangle* tFaces, const MeshTriangle* ctFaces, int32 rCount, int32 crCount, int32 tCount, int32 ctCount, int32 intensity) { -// const int SIZE = 10; Face* face = gFacesBase; for (int32 i = 0; i < SIZE; i++) { - - uint32 shade = shadeTable[X_CLAMP((lightAmbient + intensity) >> 8, 0, 31)]; + uint32 shade = shadeTable[X_CLAMP((gLightAmbient + intensity) >> 8, 0, 31)]; if (rCount) { faceAddMeshQuads(rFaces, rCount, shade); @@ -1078,7 +1069,6 @@ void faceAddMesh(const MeshQuad* rFaces, const MeshQuad* crFaces, const MeshTria faceAddMeshTrianglesFlat(ctFaces, ctCount, shade); } -// gFacesBase = face; } memset(gOT, 0, sizeof(gOT)); #ifdef CHECK_LIMITS gFacesCount = gFacesBase - gFaces; #endif diff --git a/src/platform/gba/common_asm.inc b/src/platform/gba/common_asm.inc index 03831d3a..5e2a1184 100644 --- a/src/platform/gba/common_asm.inc +++ b/src/platform/gba/common_asm.inc @@ -48,12 +48,15 @@ FOG_MAX = VIEW_DIST FOG_MIN = (FOG_MAX - (8192 >> FOG_SHIFT)) VIEW_MIN = (64) VIEW_MAX = (VIEW_DIST) -VIEW_OFF = 2048 +VIEW_OFF = 4096 VIEW_MIN_F = (VIEW_MIN << FIXED_SHIFT) VIEW_MAX_F = (VIEW_MAX << FIXED_SHIFT) VIEW_OFF_F = (VIEW_OFF << FIXED_SHIFT) +MAX_CAUSTICS = 32 +MAX_RAND_TABLE = 32 + MIN_INT32 = 0x80000000 MAX_INT32 = 0x7FFFFFFF @@ -75,7 +78,7 @@ MAX_INT32 = 0x7FFFFFFF .macro tex index, uv and \index, \uv, #0xFF00 - orr \index, \uv, lsr #24 // index = t.v * 256 + t.u + orr \index, \uv, lsr #24 // index = v * 256 + u ldrb \index, [TILE, \index] .endm diff --git a/src/platform/gba/main.cpp b/src/platform/gba/main.cpp index 45d0daa6..bc9be8d0 100644 --- a/src/platform/gba/main.cpp +++ b/src/platform/gba/main.cpp @@ -1,12 +1,6 @@ #if defined(_WIN32) || defined(__DOS__) const void* TRACKS_IMA; const void* levelData; -#elif defined(__GBA__) - #include "TRACKS_IMA.h" - #include "LEVEL1_PKD.h" - const void* levelData = LEVEL1_PKD; -#elif defined(__TNS__) - const void* levelData; #endif #include "game.h" @@ -456,34 +450,6 @@ void vblank() { #endif -int32 gLevelID = 1; - -static const char* gLevelNames[] = { - "GYM", - "LEVEL1", - "LEVEL2", -// "LEVEL3A", -// "LEVEL3B", -// "LEVEL4", -// "LEVEL5", -// "LEVEL6", -// "LEVEL7A", -// "LEVEL7B", -// "LEVEL8A", -// "LEVEL8B", -// "LEVEL8C", -// "LEVEL10A", -// "LEVEL10B", -// "LEVEL10C" -}; - -int32 reqNextLevel = -1; - -void nextLevel() -{ - reqNextLevel = (gLevelID + 1) % (sizeof(gLevelNames) / sizeof(gLevelNames[0])); -} - void* osLoadLevel(const char* name) { sndStop(); @@ -538,8 +504,18 @@ void* osLoadLevel(const char* name) } #endif } -#endif + return (void*)levelData; +#elif defined(__GBA__) + for (int32 i = 0; i < LVL_MAX; i++) + { + if (strcmp(name, gLevelInfo[i].name) == 0) + return (void*)gLevelInfo[i].data; + } + + gLevelID = LVL_TR1_TITLE; + return (void*)gLevelInfo[gLevelID].data; +#endif } int main(void) { @@ -558,7 +534,7 @@ int main(void) { soundInit(); - game.init(gLevelNames[gLevelID]); + game.init(gLevelInfo[gLevelID].name); MSG msg; @@ -576,10 +552,9 @@ int main(void) { if ((keys & IK_SELECT) && !(oldKeys & IK_SELECT)) { - gLevelID = (gLevelID + 1) % (sizeof(gLevelNames) / sizeof(gLevelNames[0])); - game.startLevel(gLevelNames[gLevelID]); - lastFrame = frame - 1; + nextLevel(); } + oldKeys = keys; int32 count = frame - lastFrame; @@ -633,7 +608,7 @@ int main(void) { rumbleInit(); soundInit(); - game.init(gLevelNames[gLevelID]); + game.init(gLevelInfo[gLevelID].name); uint16 mode = DCNT_BG2 | DCNT_PAGE; @@ -642,12 +617,14 @@ int main(void) { REG_BG2PD = (1 << 8); int32 lastFrameIndex = -1; + uint32 oldKeys = 0; while (1) { rumbleUpdate(); { // input + oldKeys = keys; keys = 0; key_poll(); if (key_is_down(KEY_UP)) keys |= IK_UP; @@ -662,6 +639,11 @@ int main(void) { if (key_is_down(KEY_SELECT)) keys |= IK_SELECT; } + if ((keys & IK_SELECT) && !(oldKeys & IK_SELECT)) + { + nextLevel(); + } + int32 frame = frameIndex / 2; game.update(frame - lastFrameIndex); lastFrameIndex = frame; @@ -694,7 +676,7 @@ int main(void) { timerInit(); inputInit(); - game.init(gLevelNames[gLevelID]); + game.init(gLevelInfo[gLevelID].name); int startTime = GetTickCount(); int lastTime = -16; @@ -730,7 +712,7 @@ int main(void) { videoAcquire(); inputAcquire(); - game.init(gLevelNames[gLevelID]); + game.init(gLevelInfo[gLevelID].name); int32 lastFrameIndex = -1; diff --git a/src/platform/gba/packer/main.cpp b/src/platform/gba/packer/main.cpp index 6168e4a8..ac520c38 100644 --- a/src/platform/gba/packer/main.cpp +++ b/src/platform/gba/packer/main.cpp @@ -4577,6 +4577,7 @@ struct LevelPC const char* levelNames[] = { #if 1 + "TITLE", "GYM", "LEVEL1", "LEVEL2", diff --git a/src/platform/gba/render.iwram.cpp b/src/platform/gba/render.iwram.cpp index 29641feb..f9effe6a 100644 --- a/src/platform/gba/render.iwram.cpp +++ b/src/platform/gba/render.iwram.cpp @@ -61,10 +61,6 @@ ViewportRel viewportRel; extern uint8 lightmap[256 * 32]; extern Level level; -extern int32 lightAmbient; -extern int32 randTable[MAX_RAND_TABLE]; -extern int32 caustics[MAX_CAUSTICS]; -extern int32 causticsFrame; const uint8* tile; @@ -137,6 +133,7 @@ X_INLINE Face* faceAdd(int32 depth) #ifdef USE_ASM #define transformRoom transformRoom_asm + #define transformRoomUW transformRoomUW_asm #define transformMesh transformMesh_asm #define faceAddRoomQuads faceAddRoomQuads_asm #define faceAddRoomTriangles faceAddRoomTriangles_asm @@ -144,7 +141,8 @@ X_INLINE Face* faceAdd(int32 depth) #define faceAddMeshTriangles faceAddMeshTriangles_asm extern "C" { - void transformRoom_asm(const RoomVertex* vertices, int32 count, bool underwater); + void transformRoom_asm(const RoomVertex* vertices, int32 count); + void transformRoomUW_asm(const RoomVertex* vertices, int32 count); void transformMesh_asm(const MeshVertex* vertices, int32 count, int32 intensity); void faceAddRoomQuads_asm(const RoomQuad* polys, int32 count); void faceAddRoomTriangles_asm(const RoomTriangle* polys, int32 count); @@ -153,13 +151,14 @@ X_INLINE Face* faceAdd(int32 depth) } #else #define transformRoom transformRoom_c + #define transformRoomUW transformRoomUW_c #define transformMesh transformMesh_c #define faceAddRoomQuads faceAddRoomQuads_c #define faceAddRoomTriangles faceAddRoomTriangles_c #define faceAddMeshQuads faceAddMeshQuads_c #define faceAddMeshTriangles faceAddMeshTriangles_c -void transformRoom_c(const RoomVertex* vertices, int32 count, bool underwater) +void transformRoom_c(const RoomVertex* vertices, int32 count) { Vertex* res = gVerticesBase; @@ -189,11 +188,69 @@ void transformRoom_c(const RoomVertex* vertices, int32 count, bool underwater) z = VIEW_MAX_F; } - if (underwater) { - int32 causticsValue = caustics[(randTable[i & (MAX_RAND_TABLE - 1)] + causticsFrame) & (MAX_CAUSTICS - 1)]; - vg = X_CLAMP(vg + causticsValue, 0, 8191); + x >>= FIXED_SHIFT; + y >>= FIXED_SHIFT; + z >>= FIXED_SHIFT; + + if (z > FOG_MIN) + { + vg += (z - FOG_MIN) << FOG_SHIFT; + if (vg > 8191) { + vg = 8191; + } + } + + PERSPECTIVE(x, y, z); + + x += (FRAME_WIDTH >> 1); + y += (FRAME_HEIGHT >> 1); + + if (x < viewport.x0) clip |= CLIP_LEFT; + if (x > viewport.x1) clip |= CLIP_RIGHT; + if (y < viewport.y0) clip |= CLIP_TOP; + if (y > viewport.y1) clip |= CLIP_BOTTOM; + + res->x = x; + res->y = y; + res->z = z; + res->g = vg >> 8; + res->clip = clip; + } +} + +void transformRoomUW_c(const RoomVertex* vertices, int32 count) +{ + Vertex* res = gVerticesBase; + + for (int32 i = 0; i < count; i++, res++) + { + uint32 value = *(uint32*)(vertices++); + + int32 vx = (value & (0xFF)) << 10; + int32 vy = (value & (0xFF << 8)); + int32 vz = (value & (0xFF << 16)) >> 6; + int32 vg = (value & (0xFF << 24)) >> (24 - 5); + + const Matrix &m = matrixGet(); + int32 x = DP43(m.e00, m.e01, m.e02, m.e03, vx, vy, vz); + int32 y = DP43(m.e10, m.e11, m.e12, m.e13, vx, vy, vz); + int32 z = DP43(m.e20, m.e21, m.e22, m.e23, vx, vy, vz); + + uint32 clip = 0; + + if (z <= VIEW_MIN_F) { + clip = CLIP_NEAR; + z = VIEW_MIN_F; } + if (z >= VIEW_MAX_F) { + clip = CLIP_FAR; + z = VIEW_MAX_F; + } + + int32 causticsValue = gCaustics[(gRandTable[i & (MAX_RAND_TABLE - 1)] + gCausticsFrame) & (MAX_CAUSTICS - 1)]; + vg = X_CLAMP(vg + causticsValue, 0, 8191); + x >>= FIXED_SHIFT; y >>= FIXED_SHIFT; z >>= FIXED_SHIFT; @@ -228,7 +285,7 @@ void transformMesh_c(const MeshVertex* vertices, int32 count, int32 intensity) { Vertex* res = gVerticesBase; - int32 vg = X_CLAMP((intensity + lightAmbient) >> 8, 0, 31); + int32 vg = X_CLAMP((intensity + gLightAmbient) >> 8, 0, 31); for (int32 i = 0; i < count; i++, res++) { @@ -974,7 +1031,11 @@ void renderRoom(const Room* room) { PROFILE(CNT_TRANSFORM); - transformRoom(room->data.vertices, vCount, ROOM_FLAG_WATER(room->info->flags)); + if (ROOM_FLAG_WATER(room->info->flags)) { + transformRoomUW(room->data.vertices, vCount); + } else { + transformRoom(room->data.vertices, vCount); + } } { diff --git a/src/platform/gba/transformMesh.s b/src/platform/gba/transformMesh.s index ca555509..914c360a 100644 --- a/src/platform/gba/transformMesh.s +++ b/src/platform/gba/transformMesh.s @@ -34,7 +34,7 @@ transformMesh_asm: ldr res, =gVerticesBase ldr res, [res] - ldr ambient, =lightAmbient + ldr ambient, =gLightAmbient ldr ambient, [ambient] add vg, ambient, intensity mov vg, vg, asr #8 diff --git a/src/platform/gba/transformRoom.s b/src/platform/gba/transformRoom.s index 1c350918..8270d423 100644 --- a/src/platform/gba/transformRoom.s +++ b/src/platform/gba/transformRoom.s @@ -2,7 +2,7 @@ vertices .req r0 count .req r1 -underwater .req r2 +m .req r2 v .req r3 vx .req r4 vy .req r5 @@ -17,11 +17,9 @@ z .req r12 res .req lr t .req y -spMat .req x -spMinXY .req y -spMaxXY .req z +spMinXY .req x +spMaxXY .req y -m .req underwater mask .req x vp .req vx minXY .req vx @@ -31,10 +29,9 @@ DIVLUT .req my dz .req mz fog .req mz -SP_MAT = 0 -SP_MINXY = 4 -SP_MAXXY = 8 -SP_SIZE = 12 +SP_MINXY = 0 +SP_MAXXY = 4 +SP_SIZE = 8 .global transformRoom_asm transformRoom_asm: @@ -43,18 +40,17 @@ transformRoom_asm: ldr res, =gVerticesBase ldr res, [res] - ldr spMat, =matrixPtr - ldr spMat, [spMat] - add spMat, #(12 * 4) + ldr m, =matrixPtr + ldr m, [m] ldr vp, =viewportRel ldmia vp, {spMinXY, spMaxXY} - stmfd sp!, {spMat, spMinXY, spMaxXY} + stmfd sp!, {spMinXY, spMaxXY} - // preload matrix, mask and z-row - mov m, spMat + // preload mask, matrix and z-row mov mask, #(0xFF << 10) + add m, #(12 * 4) ldmdb m!, {mx, my, mz, z} .loop: @@ -94,8 +90,6 @@ transformRoom_asm: mla x, mz, vz, x mov x, x, asr #FIXED_SHIFT - // TODO caustics - // fog cmp z, #FOG_MIN subgt fog, z, #FOG_MIN @@ -124,7 +118,7 @@ transformRoom_asm: mov y, y, asr #(16 - PROJ_SHIFT) // viewport clipping - ldmia sp, {m, minXY, maxXY} // preload matrix + ldmia sp, {minXY, maxXY} cmp x, minXY, asr #16 orrle vg, vg, #CLIP_LEFT @@ -147,12 +141,14 @@ transformRoom_asm: strh y, [res, #VERTEX_Y] strh z, [res, #VERTEX_Z] - mov mask, #(0xFF << 10) // preload mask - ldmdb m!, {mx, my, mz, z} // preload z-row + // preload mask, matrix and z-row + mov mask, #(0xFF << 10) + add m, #(12 * 4) + ldmdb m!, {mx, my, mz, z} .skip: strh vg, [res, #VERTEX_G] - + add res, #8 subs count, #1 bne .loop diff --git a/src/platform/gba/transformRoomUW.s b/src/platform/gba/transformRoomUW.s new file mode 100644 index 00000000..9c54ea3d --- /dev/null +++ b/src/platform/gba/transformRoomUW.s @@ -0,0 +1,184 @@ +#include "common_asm.inc" + +vertices .req r0 +count .req r1 +m .req r2 +v .req r3 +vx .req r4 +vy .req r5 +vz .req r6 +vg .req v +mx .req r7 +my .req r8 +mz .req r9 +x .req r10 +y .req r11 +z .req r12 +res .req lr +t .req y + +spMinXY .req mx +spMaxXY .req my +spFrame .req mz +spCaustLUT .req x +spRandLUT .req y + +mask .req x +vp .req vx +minXY .req vx +maxXY .req vy + +DIVLUT .req my +dz .req mz +fog .req mz + +frame .req vx +caust .req vy +rand .req vz +tmp .req mx + +SP_MINXY = 0 +SP_MAXXY = 4 +SP_FRAME = 8 +SP_CAUST = 12 +SP_RAND = 16 +SP_SIZE = 20 + +.global transformRoomUW_asm +transformRoomUW_asm: + stmfd sp!, {r4-r11, lr} + + ldr res, =gVerticesBase + ldr res, [res] + + ldr m, =matrixPtr + ldr m, [m] + + ldr vp, =viewportRel + ldmia vp, {spMinXY, spMaxXY} + + ldr spFrame, =gCausticsFrame + ldr spFrame, [spFrame] + + ldr spCaustLUT, =gCaustics + ldr spRandLUT, =gRandTable + + stmfd sp!, {spMinXY, spMaxXY, spFrame, spCaustLUT, spRandLUT} + + // preload mask, matrix and z-row + mov mask, #(0xFF << 10) + add m, #(12 * 4) + ldmdb m!, {mx, my, mz, z} + +.loop: + // unpack vertex + ldmia vertices!, {v} + + and vz, mask, v, lsr #6 + and vy, v, #0xFF00 + and vx, mask, v, lsl #10 + + // transform z + mla t, mx, vx, z + mla t, my, vy, t + mla t, mz, vz, t + mov t, t, asr #FIXED_SHIFT + + // skip if vertex is out of z-range + add t, t, #VIEW_OFF + cmp t, #(VIEW_OFF + VIEW_OFF + VIEW_MAX) + movhi vg, #(CLIP_NEAR + CLIP_FAR) + bhi .skip + + and vg, mask, v, lsr #14 + sub z, t, #VIEW_OFF + + // transform y + ldmdb m!, {mx, my, mz, y} + mla y, mx, vx, y + mla y, my, vy, y + mla y, mz, vz, y + mov y, y, asr #FIXED_SHIFT + + // transform x + ldmdb m!, {mx, my, mz, x} + mla x, mx, vx, x + mla x, my, vy, x + mla x, mz, vz, x + mov x, x, asr #FIXED_SHIFT + + // caustics + add tmp, sp, #SP_FRAME + ldmia tmp, {frame, caust, rand} + and tmp, count, #(MAX_RAND_TABLE - 1) + ldr rand, [rand, tmp, lsl #2] + add rand, rand, frame + and rand, rand, #(MAX_CAUSTICS - 1) + ldr caust, [caust, rand, lsl #2] + add vg, vg, caust, lsl #5 + + // fog + cmp z, #FOG_MIN + subgt fog, z, #FOG_MIN + addgt vg, fog, lsl #6 + mov vg, vg, lsr #13 + cmp vg, #31 + movgt vg, #31 + + // z clipping + cmp z, #VIEW_MIN + movle z, #VIEW_MIN + orrle vg, vg, #CLIP_NEAR + cmp z, #VIEW_MAX + movge z, #VIEW_MAX + orrge vg, vg, #CLIP_FAR + + // project + mov dz, z, lsr #6 + add dz, dz, z, lsr #4 + mov dz, dz, lsl #1 + mov DIVLUT, #DIVLUT_ADDR + ldrh dz, [DIVLUT, dz] + mul x, dz, x + mul y, dz, y + mov x, x, asr #(16 - PROJ_SHIFT) + mov y, y, asr #(16 - PROJ_SHIFT) + + // viewport clipping + ldmia sp, {minXY, maxXY} + + cmp x, minXY, asr #16 + orrle vg, vg, #CLIP_LEFT + cmp x, maxXY, asr #16 + orrge vg, vg, #CLIP_RIGHT + + mov minXY, minXY, lsl #16 + mov maxXY, maxXY, lsl #16 + + cmp y, minXY, asr #16 + orrle vg, vg, #CLIP_TOP + cmp y, maxXY, asr #16 + orrge vg, vg, #CLIP_BOTTOM + + add x, x, #(FRAME_WIDTH >> 1) + add y, y, #(FRAME_HEIGHT >> 1) + + // store the result + strh x, [res, #VERTEX_X] + strh y, [res, #VERTEX_Y] + strh z, [res, #VERTEX_Z] + + // preload mask, matrix and z-row + mov mask, #(0xFF << 10) + add m, #(12 * 4) + ldmdb m!, {mx, my, mz, z} + +.skip: + strh vg, [res, #VERTEX_G] + + add res, #8 + subs count, #1 + bne .loop + + add sp, sp, #SP_SIZE + ldmfd sp!, {r4-r11, pc}