From 5fb48871913d54f0b8a1917bfcbea50f728980eb Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 28 Mar 2024 17:39:10 +1100 Subject: [PATCH] PS1: Use a little bit less memory --- src/Animations.c | 25 ++-- src/EnvRenderer.c | 10 +- src/ExtMath.c | 2 +- src/Game.h | 2 +- src/Graphics_Dreamcast.c | 2 +- src/Particle.c | 274 ++++++++++++++++++++------------------- src/TexturePack.h | 4 +- 7 files changed, 166 insertions(+), 153 deletions(-) diff --git a/src/Animations.c b/src/Animations.c index 9c469dd64..29196f6ff 100644 --- a/src/Animations.c +++ b/src/Animations.c @@ -12,7 +12,12 @@ #include "Options.h" #include "Logger.h" -#define LIQUID_ANIM_MAX 64 +#ifdef CC_BUILD_LOWMEM + #define LIQUID_ANIM_MAX 16 +#else + #define LIQUID_ANIM_MAX 64 +#endif + #define WATER_TEX_LOC 14 #define LAVA_TEX_LOC 30 static void Animations_Update(int loc, struct Bitmap* bmp, int stride); @@ -292,20 +297,20 @@ static void Animations_Clear(void) { } static void Animations_Validate(void) { - struct AnimationData data; + struct AnimationData* data; int maxX, maxY, tileX, tileY; int i, j; anims_validated = true; for (i = 0; i < anims_count; i++) { - data = anims_list[i]; + data = &anims_list[i]; - maxX = data.frameX + data.frameSize * data.statesCount; - maxY = data.frameY + data.frameSize; - tileX = Atlas2D_TileX(data.texLoc); - tileY = Atlas2D_TileY(data.texLoc); + maxX = data->frameX + data->frameSize * data->statesCount; + maxY = data->frameY + data->frameSize; + tileX = Atlas2D_TileX(data->texLoc); + tileY = Atlas2D_TileY(data->texLoc); - if (data.frameSize > Atlas2D.TileSize || tileY >= Atlas2D.RowsCount) { + if (data->frameSize > Atlas2D.TileSize || tileY >= Atlas2D.RowsCount) { Chat_Add2("&cAnimation frames for tile (%i, %i) are bigger than the size of a tile in terrain.png", &tileX, &tileY); } else if (maxX > anims_bmp.width || maxY > anims_bmp.height) { Chat_Add2("&cSome of the animation frames for tile (%i, %i) are at coordinates outside animations.png", &tileX, &tileY); @@ -313,8 +318,8 @@ static void Animations_Validate(void) { /* if user has water/lava animations in their default.zip, disable built-in */ /* However, 'usewateranim' and 'uselavaanim' files should always disable use */ /* of custom water/lava animations, even when they exist in animations.png */ - if (data.texLoc == LAVA_TEX_LOC && !alwaysLavaAnim) useLavaAnim = false; - if (data.texLoc == WATER_TEX_LOC && !alwaysWaterAnim) useWaterAnim = false; + if (data->texLoc == LAVA_TEX_LOC && !alwaysLavaAnim) useLavaAnim = false; + if (data->texLoc == WATER_TEX_LOC && !alwaysWaterAnim) useWaterAnim = false; continue; } diff --git a/src/EnvRenderer.c b/src/EnvRenderer.c index 453d504e9..5e5cafbff 100644 --- a/src/EnvRenderer.c +++ b/src/EnvRenderer.c @@ -73,7 +73,7 @@ static void UpdateFogMinimal(float fogDensity) { /* Exp fog mode: f = e^(-density*coord) */ /* Solve coord for f = 0.05 (good approx for fog end) */ /* i.e. log(0.05) = -density * coord */ - #define LOG_005 -2.99573227355399 + #define LOG_005 -2.99573227355399f dist = (int)(LOG_005 / -fogDensity); Game_SetViewDistance(min(dist, Game_UserViewDistance)); @@ -83,7 +83,7 @@ static void UpdateFogMinimal(float fogDensity) { } static void UpdateFogNormal(float fogDensity, PackedCol fogColor) { - double density; + float density; if (fogDensity != 0.0f) { Gfx_SetFogMode(FOG_EXP); @@ -96,10 +96,10 @@ static void UpdateFogNormal(float fogDensity, PackedCol fogColor) { 0.99=z/end --> z=end*0.99 therefore d = -ln(0.01)/(end*0.99) */ - #define LOG_001 -4.60517018598809 + #define LOG_001 -4.60517018598809f - density = -(LOG_001) / (Game_ViewDistance * 0.99); - Gfx_SetFogDensity((float)density); + density = -LOG_001 / (Game_ViewDistance * 0.99f); + Gfx_SetFogDensity(density); } else { Gfx_SetFogMode(FOG_LINEAR); Gfx_SetFogEnd((float)Game_ViewDistance); diff --git a/src/ExtMath.c b/src/ExtMath.c index 6196c6785..28f8a1a81 100644 --- a/src/ExtMath.c +++ b/src/ExtMath.c @@ -94,7 +94,7 @@ cc_bool Math_IsPowOf2(int value) { #define RND_MASK ((1ULL << 48) - 1) void Random_SeedFromCurrentTime(RNGState* rnd) { - TimeMS now = DateTime_CurrentUTC_MS(); + cc_uint64 now = Stopwatch_Measure(); Random_Seed(rnd, (int)now); } diff --git a/src/Game.h b/src/Game.h index 6001cac5b..a3f2c7bd6 100644 --- a/src/Game.h +++ b/src/Game.h @@ -26,7 +26,7 @@ extern cc_string Game_Mppass; #if defined CC_BUILD_N64 #define DEFAULT_VIEWDIST 20 -#elif defined CC_BUILD_NDS +#elif defined CC_BUILD_NDS || defined CC_BUILD_PS1 #define DEFAULT_VIEWDIST 192 #else #define DEFAULT_VIEWDIST 512 diff --git a/src/Graphics_Dreamcast.c b/src/Graphics_Dreamcast.c index af8e53a7a..1dceb9dd1 100644 --- a/src/Graphics_Dreamcast.c +++ b/src/Graphics_Dreamcast.c @@ -543,4 +543,4 @@ void Gfx_EndFrame(void) { void Gfx_OnWindowResize(void) { glViewport(0, 0, Game.Width, Game.Height); } -#endif \ No newline at end of file +#endif diff --git a/src/Particle.c b/src/Particle.c index 4c3e3b81c..3228758d3 100644 --- a/src/Particle.c +++ b/src/Particle.c @@ -187,6 +187,30 @@ static void Rain_Tick(double delta) { } } +void Particles_RainSnowEffect(float x, float y, float z) { + struct Particle* p; + int i, type; + + for (i = 0; i < 2; i++) { + if (rain_count == PARTICLES_MAX) Rain_RemoveAt(0); + p = &rain_Particles[rain_count++]; + + p->velocity.x = Random_Float(&rnd) * 0.8f - 0.4f; /* [-0.4, 0.4] */ + p->velocity.z = Random_Float(&rnd) * 0.8f - 0.4f; + p->velocity.y = Random_Float(&rnd) + 0.4f; + + p->lastPos.x = x + Random_Float(&rnd); /* [0.0, 1.0] */ + p->lastPos.y = y + Random_Float(&rnd) * 0.1f + 0.01f; + p->lastPos.z = z + Random_Float(&rnd); + + p->nextPos = p->lastPos; + p->lifetime = 40.0f; + + type = Random_Next(&rnd, 30); + p->size = type >= 28 ? 2 : (type >= 25 ? 4 : 3); + } +} + /*########################################################################################################################* *------------------------------------------------------Terrain particle---------------------------------------------------* @@ -291,9 +315,92 @@ static void Terrain_Tick(double delta) { } } +void Particles_BreakBlockEffect(IVec3 coords, BlockID old, BlockID now) { + struct TerrainParticle* p; + TextureLoc loc; + int texIndex; + TextureRec baseRec, rec; + Vec3 origin, minBB, maxBB; + + /* texture UV variables */ + float uScale, vScale, maxU2, maxV2; + int minX, minZ, maxX, maxZ; + int minU, minV, maxU, maxV; + int maxUsedU, maxUsedV; + + /* per-particle variables */ + float cellX, cellY, cellZ; + Vec3 cell; + int x, y, z, type; + + if (now != BLOCK_AIR || Blocks.Draw[old] == DRAW_GAS) return; + IVec3_ToVec3(&origin, &coords); + loc = Block_Tex(old, FACE_XMIN); + + baseRec = Atlas1D_TexRec(loc, 1, &texIndex); + uScale = (1.0f/16.0f); vScale = (1.0f/16.0f) * Atlas1D.InvTileSize; + + minBB = Blocks.MinBB[old]; maxBB = Blocks.MaxBB[old]; + minX = (int)(minBB.x * 16); maxX = (int)(maxBB.x * 16); + minZ = (int)(minBB.z * 16); maxZ = (int)(maxBB.z * 16); + + minU = min(minX, minZ); minV = (int)(16 - maxBB.y * 16); + maxU = min(maxX, maxZ); maxV = (int)(16 - minBB.y * 16); + /* This way we can avoid creating particles which outside the bounds and need to be clamped */ + maxUsedU = maxU; maxUsedV = maxV; + if (minU < 12 && maxU > 12) maxUsedU = 12; + if (minV < 12 && maxV > 12) maxUsedV = 12; + + #define GRID_SIZE 4 + /* gridOffset gives the centre of the cell on a grid */ + #define CELL_CENTRE ((1.0f / GRID_SIZE) * 0.5f) + + maxU2 = baseRec.U1 + maxU * uScale; + maxV2 = baseRec.V1 + maxV * vScale; + for (x = 0; x < GRID_SIZE; x++) { + for (y = 0; y < GRID_SIZE; y++) { + for (z = 0; z < GRID_SIZE; z++) { + + cellX = (float)x / GRID_SIZE; cellY = (float)y / GRID_SIZE; cellZ = (float)z / GRID_SIZE; + cell = Vec3_Create3(CELL_CENTRE + cellX, CELL_CENTRE / 2 + cellY, CELL_CENTRE + cellZ); + if (cell.x < minBB.x || cell.x > maxBB.x || cell.y < minBB.y + || cell.y > maxBB.y || cell.z < minBB.z || cell.z > maxBB.z) continue; + + if (terrain_count == PARTICLES_MAX) Terrain_RemoveAt(0); + p = &terrain_particles[terrain_count++]; + + /* centre random offset around [-0.2, 0.2] */ + p->base.velocity.x = CELL_CENTRE + (cellX - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f); + p->base.velocity.y = CELL_CENTRE + (cellY - 0.0f) + (Random_Float(&rnd) * 0.4f - 0.2f); + p->base.velocity.z = CELL_CENTRE + (cellZ - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f); + + rec = baseRec; + rec.U1 = baseRec.U1 + Random_Range(&rnd, minU, maxUsedU) * uScale; + rec.V1 = baseRec.V1 + Random_Range(&rnd, minV, maxUsedV) * vScale; + rec.U2 = rec.U1 + 4 * uScale; + rec.V2 = rec.V1 + 4 * vScale; + rec.U2 = min(rec.U2, maxU2) - 0.01f * uScale; + rec.V2 = min(rec.V2, maxV2) - 0.01f * vScale; + + Vec3_Add(&p->base.lastPos, &origin, &cell); + p->base.nextPos = p->base.lastPos; + p->base.lifetime = 0.3f + Random_Float(&rnd) * 1.2f; + + p->rec = rec; + p->texLoc = loc; + p->block = old; + type = Random_Next(&rnd, 30); + p->base.size = type >= 28 ? 12 : (type >= 25 ? 10 : 8); + } + } + } +} + + /*########################################################################################################################* *-------------------------------------------------------Custom particle---------------------------------------------------* *#########################################################################################################################*/ +#ifdef CC_BUILD_NETWORKING struct CustomParticle { struct Particle base; int effectId; @@ -388,139 +495,6 @@ static void Custom_Tick(double delta) { } } - -/*########################################################################################################################* -*--------------------------------------------------------Particles--------------------------------------------------------* -*#########################################################################################################################*/ -void Particles_Render(float t) { - if (!terrain_count && !rain_count && !custom_count) return; - - if (Gfx.LostContext) return; - if (!particles_VB) - particles_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, PARTICLES_MAX * 4); - - Gfx_SetAlphaTest(true); - - Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); - Terrain_Render(t); - Rain_Render(t); - Custom_Render(t); - - Gfx_SetAlphaTest(false); -} - -static void Particles_Tick(struct ScheduledTask* task) { - double delta = task->interval; - Terrain_Tick(delta); - Rain_Tick(delta); - Custom_Tick(delta); -} - -void Particles_BreakBlockEffect(IVec3 coords, BlockID old, BlockID now) { - struct TerrainParticle* p; - TextureLoc loc; - int texIndex; - TextureRec baseRec, rec; - Vec3 origin, minBB, maxBB; - - /* texture UV variables */ - float uScale, vScale, maxU2, maxV2; - int minX, minZ, maxX, maxZ; - int minU, minV, maxU, maxV; - int maxUsedU, maxUsedV; - - /* per-particle variables */ - float cellX, cellY, cellZ; - Vec3 cell; - int x, y, z, type; - - if (now != BLOCK_AIR || Blocks.Draw[old] == DRAW_GAS) return; - IVec3_ToVec3(&origin, &coords); - loc = Block_Tex(old, FACE_XMIN); - - baseRec = Atlas1D_TexRec(loc, 1, &texIndex); - uScale = (1.0f/16.0f); vScale = (1.0f/16.0f) * Atlas1D.InvTileSize; - - minBB = Blocks.MinBB[old]; maxBB = Blocks.MaxBB[old]; - minX = (int)(minBB.x * 16); maxX = (int)(maxBB.x * 16); - minZ = (int)(minBB.z * 16); maxZ = (int)(maxBB.z * 16); - - minU = min(minX, minZ); minV = (int)(16 - maxBB.y * 16); - maxU = min(maxX, maxZ); maxV = (int)(16 - minBB.y * 16); - /* This way we can avoid creating particles which outside the bounds and need to be clamped */ - maxUsedU = maxU; maxUsedV = maxV; - if (minU < 12 && maxU > 12) maxUsedU = 12; - if (minV < 12 && maxV > 12) maxUsedV = 12; - - #define GRID_SIZE 4 - /* gridOffset gives the centre of the cell on a grid */ - #define CELL_CENTRE ((1.0f / GRID_SIZE) * 0.5f) - - maxU2 = baseRec.U1 + maxU * uScale; - maxV2 = baseRec.V1 + maxV * vScale; - for (x = 0; x < GRID_SIZE; x++) { - for (y = 0; y < GRID_SIZE; y++) { - for (z = 0; z < GRID_SIZE; z++) { - - cellX = (float)x / GRID_SIZE; cellY = (float)y / GRID_SIZE; cellZ = (float)z / GRID_SIZE; - cell = Vec3_Create3(CELL_CENTRE + cellX, CELL_CENTRE / 2 + cellY, CELL_CENTRE + cellZ); - if (cell.x < minBB.x || cell.x > maxBB.x || cell.y < minBB.y - || cell.y > maxBB.y || cell.z < minBB.z || cell.z > maxBB.z) continue; - - if (terrain_count == PARTICLES_MAX) Terrain_RemoveAt(0); - p = &terrain_particles[terrain_count++]; - - /* centre random offset around [-0.2, 0.2] */ - p->base.velocity.x = CELL_CENTRE + (cellX - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f); - p->base.velocity.y = CELL_CENTRE + (cellY - 0.0f) + (Random_Float(&rnd) * 0.4f - 0.2f); - p->base.velocity.z = CELL_CENTRE + (cellZ - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f); - - rec = baseRec; - rec.U1 = baseRec.U1 + Random_Range(&rnd, minU, maxUsedU) * uScale; - rec.V1 = baseRec.V1 + Random_Range(&rnd, minV, maxUsedV) * vScale; - rec.U2 = rec.U1 + 4 * uScale; - rec.V2 = rec.V1 + 4 * vScale; - rec.U2 = min(rec.U2, maxU2) - 0.01f * uScale; - rec.V2 = min(rec.V2, maxV2) - 0.01f * vScale; - - Vec3_Add(&p->base.lastPos, &origin, &cell); - p->base.nextPos = p->base.lastPos; - p->base.lifetime = 0.3f + Random_Float(&rnd) * 1.2f; - - p->rec = rec; - p->texLoc = loc; - p->block = old; - type = Random_Next(&rnd, 30); - p->base.size = type >= 28 ? 12 : (type >= 25 ? 10 : 8); - } - } - } -} - -void Particles_RainSnowEffect(float x, float y, float z) { - struct Particle* p; - int i, type; - - for (i = 0; i < 2; i++) { - if (rain_count == PARTICLES_MAX) Rain_RemoveAt(0); - p = &rain_Particles[rain_count++]; - - p->velocity.x = Random_Float(&rnd) * 0.8f - 0.4f; /* [-0.4, 0.4] */ - p->velocity.z = Random_Float(&rnd) * 0.8f - 0.4f; - p->velocity.y = Random_Float(&rnd) + 0.4f; - - p->lastPos.x = x + Random_Float(&rnd); /* [0.0, 1.0] */ - p->lastPos.y = y + Random_Float(&rnd) * 0.1f + 0.01f; - p->lastPos.z = z + Random_Float(&rnd); - - p->nextPos = p->lastPos; - p->lifetime = 40.0f; - - type = Random_Next(&rnd, 30); - p->size = type >= 28 ? 2 : (type >= 25 ? 4 : 3); - } -} - void Particles_CustomEffect(int effectID, float x, float y, float z, float originX, float originY, float originZ) { struct CustomParticle* p; struct CustomParticleEffect* e = &Particles_CustomEffects[effectID]; @@ -568,6 +542,40 @@ void Particles_CustomEffect(int effectID, float x, float y, float z, float origi if (IntersectsBlock(&p->base, CustomParticle_CanPass)) custom_count--; } } +#else +static int custom_count; + +static void Custom_Render(float t) { } +static void Custom_Tick(double delta) { } +#endif + + +/*########################################################################################################################* +*--------------------------------------------------------Particles--------------------------------------------------------* +*#########################################################################################################################*/ +void Particles_Render(float t) { + if (!terrain_count && !rain_count && !custom_count) return; + + if (Gfx.LostContext) return; + if (!particles_VB) + particles_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, PARTICLES_MAX * 4); + + Gfx_SetAlphaTest(true); + + Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); + Terrain_Render(t); + Rain_Render(t); + Custom_Render(t); + + Gfx_SetAlphaTest(false); +} + +static void Particles_Tick(struct ScheduledTask* task) { + double delta = task->interval; + Terrain_Tick(delta); + Rain_Tick(delta); + Custom_Tick(delta); +} /*########################################################################################################################* diff --git a/src/TexturePack.h b/src/TexturePack.h index e4858b128..781e38043 100644 --- a/src/TexturePack.h +++ b/src/TexturePack.h @@ -20,9 +20,9 @@ extern struct IGameComponent Textures_Component; #define ATLAS2D_SHIFT 4 /* Maximum supported number of rows in the atlas. */ #ifdef EXTENDED_TEXTURES -#define ATLAS2D_MAX_ROWS_COUNT 32 + #define ATLAS2D_MAX_ROWS_COUNT 32 #else -#define ATLAS2D_MAX_ROWS_COUNT 16 + #define ATLAS2D_MAX_ROWS_COUNT 16 #endif /* Maximum possible number of 1D terrain atlases. (worst case, each 1D atlas only has 1 tile) */ #define ATLAS1D_MAX_ATLASES (ATLAS2D_TILES_PER_ROW * ATLAS2D_MAX_ROWS_COUNT)