From 00b5269a50a7ca6a3877c4e50cad38091f67244d Mon Sep 17 00:00:00 2001 From: Azi Hassan Date: Sun, 1 Dec 2024 04:03:14 +0100 Subject: [PATCH 1/7] Remove 50% frames in diablo death and standby animations - remove all death animations for knights (blackd.clx) except for the south-facing one (because they all look similar) and turn knight monsters south after they die and before the animation is loaded --- .github/workflows/dreamcast.yml | 11 +++++- Dockerfile | 33 ++++++++++------- Source/CMakeLists.txt | 1 + Source/memory_stats.cpp | 63 +++++++++++++++++++++++++++++++++ Source/memory_stats.h | 11 ++++++ Source/monster.cpp | 36 +++++++++++++++++++ monstdat.patch | 11 ++++++ 7 files changed, 153 insertions(+), 13 deletions(-) create mode 100644 Source/memory_stats.cpp create mode 100644 Source/memory_stats.h create mode 100644 monstdat.patch diff --git a/.github/workflows/dreamcast.yml b/.github/workflows/dreamcast.yml index 3c929007ed4..7d5c94e9a0d 100644 --- a/.github/workflows/dreamcast.yml +++ b/.github/workflows/dreamcast.yml @@ -1,7 +1,7 @@ --- name: Sega Dreamcast -on: # yamllint disable-line rule:truthy +on: # yamllint disable-line rule:truthy push: branches: - master @@ -84,6 +84,15 @@ jobs: run: | source /opt/toolchains/dc/kos/environ.sh && cd build && kos-make + - name: Patch RAM-heavy assets + run: | + [ -e build/data/diabdat ] && \ + cp build/data/diabdat/monsters/snake/snakbl.trn build/data/diabdat/monsters/snake/snakb.trn && \ + cp blackd.clx build/data/diabdat/monsters/black/blackd.clx && \ + cp diablod.clx build/data/diabdat/monsters/diablo/diablod.clx && \ + cp diablon.clx build/data/diabdat/monsters/diablo/diablon.clx && \ + patch build/data/txt/monsters/monstdat.tsv -l -p0 < monstdat.patch + - name: Generate .cdi run: | source /opt/toolchains/dc/kos/environ.sh && \ diff --git a/Dockerfile b/Dockerfile index 6c327a9fa6f..b020bf32c59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ RUN git clone https://github.com/diasurgical/devilutionx-mpq-tools/ && \ RUN echo "Cloning project..." WORKDIR /opt/toolchains/dc/kos/ -RUN git clone -b dreamcast https://github.com/azihassan/devilutionX.git +RUN git clone -b fix/ISSUE-7-ram-limitations https://github.com/azihassan/devilutionX.git RUN echo "Uninstall kos-ports SDL 1.2..." RUN source /opt/toolchains/dc/kos/environ.sh && \ @@ -25,20 +25,21 @@ RUN git clone -b SDL-dreamhal--GLDC https://github.com/GPF/SDL-1.2 && \ cp include/* /usr/include/SDL/ WORKDIR /opt/toolchains/dc/kos/devilutionX -RUN echo "Downloading and unpacking spawn.mpq..." -RUN curl -LO https://raw.githubusercontent.com/d07RiV/diabloweb/3a5a51e84d5dab3cfd4fef661c46977b091aaa9c/spawn.mpq && \ - unpack_and_minify_mpq spawn.mpq && \ - rm spawn.mpq - RUN echo "Downloading and unpacking fonts.mpq..." RUN curl -LO https://github.com/diasurgical/devilutionx-assets/releases/download/v4/fonts.mpq && \ unpack_and_minify_mpq fonts.mpq && \ rm fonts.mpq -#WORKDIR /opt/toolchains/dc/kos/devilutionX -#RUN echo "Copying and unpacking diabdat.mpq..." -#COPY DIABDAT.MPQ . -#RUN unpack_and_minify_mpq DIABDAT.MPQ +#spawn version +#RUN echo "Downloading and unpacking spawn.mpq..." +#RUN curl -LO https://raw.githubusercontent.com/d07RiV/diabloweb/3a5a51e84d5dab3cfd4fef661c46977b091aaa9c/spawn.mpq && \ +# unpack_and_minify_mpq spawn.mpq && \ +# rm spawn.mpq + +#full version +RUN echo "Copying and unpacking diabdat.mpq..." +COPY DIABDAT.MPQ . +RUN unpack_and_minify_mpq DIABDAT.MPQ RUN echo "Configuring CMake..." RUN source /opt/toolchains/dc/kos/environ.sh && \ @@ -50,11 +51,19 @@ RUN source /opt/toolchains/dc/kos/environ.sh && \ RUN echo "Compiling..." RUN source /opt/toolchains/dc/kos/environ.sh && cd build && kos-make +RUN echo "Patching RAM-heavy assets..." +RUN [ -e build/data/diabdat ] && \ + cp build/data/diabdat/monsters/snake/snakbl.trn build/data/diabdat/monsters/snake/snakb.trn && \ + cp blackd.clx build/data/diabdat/monsters/black/blackd.clx && \ + cp diablod.clx build/data/diabdat/monsters/diablo/diablod.clx && \ + cp diablon.clx build/data/diabdat/monsters/diablo/diablon.clx && \ + patch build/data/txt/monsters/monstdat.tsv -l -p0 < monstdat.patch + RUN echo "Generating CDI" RUN source /opt/toolchains/dc/kos/environ.sh && \ - mv spawn build/data/spawn && \ + #mv spawn build/data/spawn && \ mv fonts/fonts/ build/data/fonts/ && \ - #mv diabdat build/data/diabdat && \ + mv diabdat build/data/diabdat && \ mkdcdisc -e build/devilutionx.elf -o build/devilutionx.cdi --name 'Diablo 1' -d build/data/ ENTRYPOINT ["sh", "-c", "source /opt/toolchains/dc/kos/environ.sh && \"$@\"", "-s"] diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index f291841044c..6372f9dd5a7 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -3,6 +3,7 @@ include(functions/devilutionx_library) include(functions/genex) set(libdevilutionx_SRCS + memory_stats.cpp appfat.cpp automap.cpp capture.cpp diff --git a/Source/memory_stats.cpp b/Source/memory_stats.cpp new file mode 100644 index 00000000000..4e31385240c --- /dev/null +++ b/Source/memory_stats.cpp @@ -0,0 +1,63 @@ +// DREAMCAST memory stats related code + +#include "memory_stats.h" + +#include + +#include +#include + +static unsigned long systemRam = 0x00000000; +static unsigned long elfOffset = 0x00000000; +static unsigned long stackSize = 0x00000000; + +extern unsigned long end; +extern unsigned long start; + +#define _end end +#define _start start +void print_VRAM_stats() +{ + pvr_mem_available(); +} + +void set_system_ram() +{ + systemRam = 0x8d000000 - 0x8c000000; + elfOffset = 0x8c000000; + + stackSize = (int)&_end - (int)&_start + ((int)&_start - elfOffset); +} + +unsigned long get_system_ram() +{ + return systemRam; +} + +unsigned long get_free_ram() +{ + struct mallinfo mi = mallinfo(); + return systemRam - (mi.usmblks + stackSize); +} + +void print_ram_stats() +{ + float sys_ram, free_ram, used_ram, pvr_ram; + sys_ram = (float)get_system_ram() / (float)(1024 * 1024); + free_ram = (float)get_free_ram() / (float)(1024 * 1024); + used_ram = (sys_ram - free_ram); + // pvr_ram = (float)pvr_mem_available() / (float)(1024*1024); + + printf("\n---------\nRAM stats (MB):\nTotal: %.2f, Free: %.2f, Used: %.2f, PVR: %.2f\n---------\n", sys_ram, free_ram, used_ram, pvr_ram); + // printf("\n---------\nRAM stats (MB):\nTotal: %.2f, Free: %.2f, Used: %.2f\n---------\n", sys_ram, free_ram, used_ram); +} + +void get_ram_stats(float *sys_ram, float *free_ram, float *used_ram, float *pvr_ram) +{ + *sys_ram = (float)get_system_ram() / (float)(1024 * 1024); + *free_ram = (float)get_free_ram() / (float)(1024 * 1024); + *used_ram = (*sys_ram - *free_ram); + if (pvr_ram) { + //*pvr_ram = (float)pvr_mem_available() / (float)(1024*1024); + } +} diff --git a/Source/memory_stats.h b/Source/memory_stats.h new file mode 100644 index 00000000000..895007b70fa --- /dev/null +++ b/Source/memory_stats.h @@ -0,0 +1,11 @@ +#ifndef __MEMORY_STATS_H__ +#define __MEMORY_STATS_H__ 1 + +void set_system_ram(); +void print_VRAM_stats(); +unsigned long get_system_ram(); +unsigned long get_free_ram(); +void print_ram_stats(); +void get_ram_stats(float *sys_ram, float *free_ram, float *used_ram, float *pvr_ram); + +#endif diff --git a/Source/monster.cpp b/Source/monster.cpp index cb7fb62530f..e026f752c29 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -54,6 +54,9 @@ #ifdef _DEBUG #include "debug.h" #endif +#ifdef __DREAMCAST__ +#include "memory_stats.h" +#endif namespace devilution { @@ -1441,6 +1444,14 @@ void ShrinkLeaderPacksize(const Monster &monster) void MonsterDeath(Monster &monster) { +#ifdef __DREAMCAST__ + // knights only have south death animation in the dreamcast port + // the death animations are similar because they show the knight rotate into the ground + // so I removed the other ones for less RAM usage (1018 kB down to 171 kB) + if (monster.type().type == MT_NBLACK || monster.type().type == MT_RTBLACK || monster.type().type == MT_BTBLACK || monster.type().type == MT_RBLACK) { + monster.direction = Direction::South; + } +#endif monster.var1++; if (monster.type().type == MT_DIABLO) { if (monster.position.tile.x < ViewPosition.x) { @@ -3449,6 +3460,15 @@ void InitMonsterGFX(CMonster &monsterType, MonsterSpritesData &&spritesData) GetMissileSpriteData(MissileGraphicID::DiabloApocalypseBoom).LoadGFX(); } +#ifdef __DREAMCAST__ +void print_memory_usage() +{ + set_system_ram(); + print_ram_stats(); + Log("\n\n\n"); +} +#endif + void InitAllMonsterGFX() { if (HeadlessMode) @@ -3467,6 +3487,10 @@ void InitAllMonsterGFX() CMonster &firstMonster = LevelMonsterTypes[monsterTypes[0]]; if (firstMonster.animData != nullptr) continue; +#ifdef __DREAMCAST__ + LogVerbose("Loading monster graphics: {:15s} x{:d}", firstMonster.data().spritePath(), monsterTypes.size()); + print_memory_usage(); +#endif MonsterSpritesData spritesData = LoadMonsterSpritesData(firstMonster.data()); const size_t spritesDataSize = spritesData.offsets[GetNumAnimsWithGraphics(firstMonster.data())]; for (size_t i = 1; i < monsterTypes.size(); ++i) { @@ -3475,6 +3499,9 @@ void InitAllMonsterGFX() InitMonsterGFX(LevelMonsterTypes[monsterTypes[i]], std::move(spritesDataCopy)); } LogVerbose("Loaded monster graphics: {:15s} {:>4d} KiB x{:d}", firstMonster.data().spritePath(), spritesDataSize / 1024, monsterTypes.size()); +#ifdef __DREAMCAST__ + print_memory_usage(); +#endif totalUniqueBytes += spritesDataSize; totalBytes += spritesDataSize * monsterTypes.size(); InitMonsterGFX(firstMonster, std::move(spritesData)); @@ -3795,6 +3822,15 @@ void MonsterDeath(Monster &monster, Direction md, bool sendmsg) if (monster.mode != MonsterMode::Petrified) { if (monster.type().type == MT_GOLEM) md = Direction::South; +#ifdef __DREAMCAST__ + // knights only have south death animation in the dreamcast port + // the death animations are similar because they show the knight rotate into the ground + // so I removed the other ones for less RAM usage (1018 kB down to 171 kB) + if (monster.type().type == MT_NBLACK || monster.type().type == MT_RTBLACK || monster.type().type == MT_BTBLACK || monster.type().type == MT_RBLACK) { + md = Direction::South; + monster.direction = Direction::South; + } +#endif NewMonsterAnim(monster, MonsterGraphic::Death, md, gGameLogicStep < GameLogicStep::ProcessMonsters ? AnimationDistributionFlags::ProcessAnimationPending : AnimationDistributionFlags::None); monster.mode = MonsterMode::Death; } else if (monster.isUnique()) { diff --git a/monstdat.patch b/monstdat.patch new file mode 100644 index 00000000000..cdab586d920 --- /dev/null +++ b/monstdat.patch @@ -0,0 +1,11 @@ +--- assets/txtdata/monsters/monstdat.tsv 2024-10-07 01:53:20.352087707 +0100 ++++ monstdat.tsv 2024-12-01 00:14:59.000000000 +0100 +@@ -109,7 +109,7 @@ + MT_CABALIST Cabalist mage\mage mage\cnselgd Retail 128 2000 true false 12,1,20,8,28,20 1,1,1,1,1,1 15 16 29 120 120 Counselor CAN_OPEN_DOOR 2 110 8 14 30 0 0 0 0 0 Demon RESIST_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING IMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING Bottom,Middle,Top 4929 + MT_ADVOCATE Advocate mage\mage mage\cnselbk Retail 128 2000 true false 12,1,20,8,28,20 1,1,1,1,1,1 16 16 30 145 145 Counselor CAN_OPEN_DOOR 3 120 8 15 25 0 0 0 0 0 Demon IMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING IMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING Bottom,Middle,Top 4968 + MT_GOLEM Golem golem\golem golem\golm Never 96 386 true false 0,16,12,0,12,20 1,1,1,1,1,1 1 1 12 1 1 Golem CAN_OPEN_DOOR 0 0 7 1 1 0 0 0 0 1 Demon 0 +-MT_DIABLO The Dark Lord diablo\diablo Never 160 2000 true true 16,6,16,6,16,16 1,1,1,1,1,1 26 26 45 3333 3333 Diablo KNOCKBACK,SEARCH,CAN_OPEN_DOOR 3 220 4 30 60 0 11 0 0 90 Demon IMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING IMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING Bottom,Middle,Top 31666 ++MT_DIABLO The Dark Lord diablo\diablo Never 160 2000 true true 8,6,16,6,8,16 1,1,1,1,2,1 26 26 45 3333 3333 Diablo KNOCKBACK,SEARCH,CAN_OPEN_DOOR 3 220 4 30 60 0 11 0 0 90 Demon IMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING IMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING Bottom,Middle,Top 31666 + MT_DARKMAGE The Arch-Litch Malignus darkmage\dmage darkmage\dmag Never 128 1060 true false 6,1,21,6,23,18 1,1,1,1,1,1 21 21 30 160 160 Counselor CAN_OPEN_DOOR 3 120 8 20 40 0 0 0 0 70 Demon RESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING IMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING Bottom,Middle,Top 4968 + MT_HELLBOAR Hellboar fork\fork newsfx\hboar Retail 188 800 false false 10,10,15,6,16,0 2,1,1,1,1,1 17 18 23 80 100 SkeletonMelee KNOCKBACK,SEARCH 2 70 7 16 24 0 0 0 0 60 Demon RESIST_FIRE,RESIST_LIGHTNING Bottom,Middle 750 + MT_STINGER Stinger scorp\scorp newsfx\stingr Retail 64 305 false false 10,10,12,6,15,0 2,1,1,1,1,1 17 18 22 30 40 SkeletonMelee 3 85 8 1 20 0 0 0 0 50 Animal RESIST_LIGHTNING Bottom 500 From 62d451ce2388a8c792417e94a9becef061e14b5f Mon Sep 17 00:00:00 2001 From: Azi Hassan Date: Sun, 1 Dec 2024 04:21:17 +0100 Subject: [PATCH 2/7] Only build memory_stats for the Dreamcast --- .github/workflows/dreamcast.yml | 14 ++++++++------ Dockerfile | 12 ++++++------ Source/CMakeLists.txt | 4 +++- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.github/workflows/dreamcast.yml b/.github/workflows/dreamcast.yml index 7d5c94e9a0d..06beb3e4708 100644 --- a/.github/workflows/dreamcast.yml +++ b/.github/workflows/dreamcast.yml @@ -84,14 +84,16 @@ jobs: run: | source /opt/toolchains/dc/kos/environ.sh && cd build && kos-make + # diabdat.mpq isn't available so this doesn't do anything, but I'll leave it here for documentation purposes - name: Patch RAM-heavy assets + if: ${{ hashFiles('DIABDAT.MPQ') != '' }} run: | - [ -e build/data/diabdat ] && \ - cp build/data/diabdat/monsters/snake/snakbl.trn build/data/diabdat/monsters/snake/snakb.trn && \ - cp blackd.clx build/data/diabdat/monsters/black/blackd.clx && \ - cp diablod.clx build/data/diabdat/monsters/diablo/diablod.clx && \ - cp diablon.clx build/data/diabdat/monsters/diablo/diablon.clx && \ - patch build/data/txt/monsters/monstdat.tsv -l -p0 < monstdat.patch + unpack_and_minify_mpq DIABDAT.MPQ && \ + cp diabdat/monsters/snake/snakbl.trn diabdat/monsters/snake/snakb.trn && \ + cp blackd.clx diabdat/monsters/black/blackd.clx && \ + cp diablod.clx diabdat/monsters/diablo/diablod.clx && \ + cp diablon.clx diabdat/monsters/diablo/diablon.clx && \ + patch build/data/txtdata/monsters/monstdat.tsv -l -p0 < monstdat.patch - name: Generate .cdi run: | diff --git a/Dockerfile b/Dockerfile index b020bf32c59..e1dd0e68984 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,12 +52,12 @@ RUN echo "Compiling..." RUN source /opt/toolchains/dc/kos/environ.sh && cd build && kos-make RUN echo "Patching RAM-heavy assets..." -RUN [ -e build/data/diabdat ] && \ - cp build/data/diabdat/monsters/snake/snakbl.trn build/data/diabdat/monsters/snake/snakb.trn && \ - cp blackd.clx build/data/diabdat/monsters/black/blackd.clx && \ - cp diablod.clx build/data/diabdat/monsters/diablo/diablod.clx && \ - cp diablon.clx build/data/diabdat/monsters/diablo/diablon.clx && \ - patch build/data/txt/monsters/monstdat.tsv -l -p0 < monstdat.patch +RUN [ -e diabdat ] && \ + cp diabdat/monsters/snake/snakbl.trn diabdat/monsters/snake/snakb.trn && \ + cp blackd.clx diabdat/monsters/black/blackd.clx && \ + cp diablod.clx diabdat/monsters/diablo/diablod.clx && \ + cp diablon.clx diabdat/monsters/diablo/diablon.clx && \ + patch build/data/txtdata/monsters/monstdat.tsv -l -p0 < monstdat.patch RUN echo "Generating CDI" RUN source /opt/toolchains/dc/kos/environ.sh && \ diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 6372f9dd5a7..804a38b9c43 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -3,7 +3,6 @@ include(functions/devilutionx_library) include(functions/genex) set(libdevilutionx_SRCS - memory_stats.cpp appfat.cpp automap.cpp capture.cpp @@ -282,6 +281,9 @@ if(DEVILUTIONX_SCREENSHOT_FORMAT STREQUAL DEVILUTIONX_SCREENSHOT_FORMAT_PNG) utils/surface_to_png.cpp ) endif() +if(PLATFORM_DREAMCAST) + list(APPEND libdevilutionx_SRCS memory_stats.cpp) +endif() add_devilutionx_library(libdevilutionx OBJECT ${libdevilutionx_SRCS}) target_include_directories(libdevilutionx PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) From cc044268c02f35ccc277447abb2d4c073b848ade Mon Sep 17 00:00:00 2001 From: Azi Hassan Date: Mon, 2 Dec 2024 02:40:31 +0100 Subject: [PATCH 3/7] Remove duplicated mage death animations --- .github/workflows/dreamcast.yml | 1 + Dockerfile | 1 + Source/monster.cpp | 31 ++++++++++++++++++------------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/.github/workflows/dreamcast.yml b/.github/workflows/dreamcast.yml index 06beb3e4708..39271b732b2 100644 --- a/.github/workflows/dreamcast.yml +++ b/.github/workflows/dreamcast.yml @@ -93,6 +93,7 @@ jobs: cp blackd.clx diabdat/monsters/black/blackd.clx && \ cp diablod.clx diabdat/monsters/diablo/diablod.clx && \ cp diablon.clx diabdat/monsters/diablo/diablon.clx && \ + cp maged.clx diabdat/monsters/mage/maged.clx && \ patch build/data/txtdata/monsters/monstdat.tsv -l -p0 < monstdat.patch - name: Generate .cdi diff --git a/Dockerfile b/Dockerfile index e1dd0e68984..e23700fbe61 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,6 +57,7 @@ RUN [ -e diabdat ] && \ cp blackd.clx diabdat/monsters/black/blackd.clx && \ cp diablod.clx diabdat/monsters/diablo/diablod.clx && \ cp diablon.clx diabdat/monsters/diablo/diablon.clx && \ + cp maged.clx diabdat/monsters/mage/maged.clx && \ patch build/data/txtdata/monsters/monstdat.tsv -l -p0 < monstdat.patch RUN echo "Generating CDI" diff --git a/Source/monster.cpp b/Source/monster.cpp index e026f752c29..e4f387a1655 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -118,6 +118,21 @@ size_t GetNumAnimsWithGraphics(const MonsterData &monsterData) return result; } +#ifdef __DREAMCAST__ +void ReorientMonsterToSouth(Monster &monster) +{ + // knights and mages only have the south facing death animation in the dreamcast port + // the death animations are similar because they show the monster rotate into the ground + // so I removed the other directions for less RAM usage + // 1018 kB down to 140 kB for the knights and + // 311 kB down to 40 kB for the mages + bool hasSouthDeathAnimationOnly = monster.type().type == MT_NBLACK || monster.type().type == MT_RTBLACK || monster.type().type == MT_BTBLACK || monster.type().type == MT_RBLACK || monster.type().type == MT_COUNSLR || monster.type().type == MT_MAGISTR || monster.type().type == MT_CABALIST || monster.type().type == MT_ADVOCATE; + if (hasSouthDeathAnimationOnly) { + monster.direction = Direction::South; + } +} +#endif + void InitMonsterTRN(CMonster &monst) { char path[64]; @@ -1445,12 +1460,7 @@ void ShrinkLeaderPacksize(const Monster &monster) void MonsterDeath(Monster &monster) { #ifdef __DREAMCAST__ - // knights only have south death animation in the dreamcast port - // the death animations are similar because they show the knight rotate into the ground - // so I removed the other ones for less RAM usage (1018 kB down to 171 kB) - if (monster.type().type == MT_NBLACK || monster.type().type == MT_RTBLACK || monster.type().type == MT_BTBLACK || monster.type().type == MT_RBLACK) { - monster.direction = Direction::South; - } + ReorientMonsterToSouth(monster); #endif monster.var1++; if (monster.type().type == MT_DIABLO) { @@ -3823,13 +3833,8 @@ void MonsterDeath(Monster &monster, Direction md, bool sendmsg) if (monster.type().type == MT_GOLEM) md = Direction::South; #ifdef __DREAMCAST__ - // knights only have south death animation in the dreamcast port - // the death animations are similar because they show the knight rotate into the ground - // so I removed the other ones for less RAM usage (1018 kB down to 171 kB) - if (monster.type().type == MT_NBLACK || monster.type().type == MT_RTBLACK || monster.type().type == MT_BTBLACK || monster.type().type == MT_RBLACK) { - md = Direction::South; - monster.direction = Direction::South; - } + md = Direction::South; + ReorientMonsterToSouth(monster); #endif NewMonsterAnim(monster, MonsterGraphic::Death, md, gGameLogicStep < GameLogicStep::ProcessMonsters ? AnimationDistributionFlags::ProcessAnimationPending : AnimationDistributionFlags::None); monster.mode = MonsterMode::Death; From aee5a446b0bd1e754f5d330916a71f0d279553d4 Mon Sep 17 00:00:00 2001 From: Azi Hassan Date: Wed, 4 Dec 2024 04:13:10 +0100 Subject: [PATCH 4/7] Remove temporary fix of missing TRN file --- .github/workflows/dreamcast.yml | 1 - Dockerfile | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/dreamcast.yml b/.github/workflows/dreamcast.yml index 39271b732b2..27ffc2aaf2f 100644 --- a/.github/workflows/dreamcast.yml +++ b/.github/workflows/dreamcast.yml @@ -89,7 +89,6 @@ jobs: if: ${{ hashFiles('DIABDAT.MPQ') != '' }} run: | unpack_and_minify_mpq DIABDAT.MPQ && \ - cp diabdat/monsters/snake/snakbl.trn diabdat/monsters/snake/snakb.trn && \ cp blackd.clx diabdat/monsters/black/blackd.clx && \ cp diablod.clx diabdat/monsters/diablo/diablod.clx && \ cp diablon.clx diabdat/monsters/diablo/diablon.clx && \ diff --git a/Dockerfile b/Dockerfile index e23700fbe61..0f0025dd592 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,7 +53,6 @@ RUN source /opt/toolchains/dc/kos/environ.sh && cd build && kos-make RUN echo "Patching RAM-heavy assets..." RUN [ -e diabdat ] && \ - cp diabdat/monsters/snake/snakbl.trn diabdat/monsters/snake/snakb.trn && \ cp blackd.clx diabdat/monsters/black/blackd.clx && \ cp diablod.clx diabdat/monsters/diablo/diablod.clx && \ cp diablon.clx diabdat/monsters/diablo/diablon.clx && \ From 0cf9ef3867bb6d10a49e8246420f3d0b5326412f Mon Sep 17 00:00:00 2001 From: Azi Hassan Date: Wed, 4 Dec 2024 04:13:58 +0100 Subject: [PATCH 5/7] Log RAM usage after level finishes loading --- Source/diablo.cpp | 10 ++++++++++ Source/monster.cpp | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index d8974ce86fc..2009e8a35a9 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -105,6 +105,9 @@ #ifdef GPERF_HEAP_FIRST_GAME_ITERATION #include #endif +#ifdef __DREAMCAST__ +#include "memory_stats.h" +#endif namespace devilution { @@ -2546,6 +2549,9 @@ int DiabloMain(int argc, char **argv) #ifdef _DEBUG SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG); #endif +#ifdef __DREAMCAST__ + set_system_ram(); +#endif DiabloParseFlags(argc, argv); InitKeymapActions(); @@ -3249,6 +3255,10 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir) CompleteProgress(); LoadGameLevelCalculateCursor(); +#ifdef __DREAMCAST__ + Log("Level loaded"); + print_ram_stats(); +#endif } bool game_loop(bool bStartup) diff --git a/Source/monster.cpp b/Source/monster.cpp index e4f387a1655..0409a31407a 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3473,7 +3473,6 @@ void InitMonsterGFX(CMonster &monsterType, MonsterSpritesData &&spritesData) #ifdef __DREAMCAST__ void print_memory_usage() { - set_system_ram(); print_ram_stats(); Log("\n\n\n"); } @@ -3498,7 +3497,7 @@ void InitAllMonsterGFX() if (firstMonster.animData != nullptr) continue; #ifdef __DREAMCAST__ - LogVerbose("Loading monster graphics: {:15s} x{:d}", firstMonster.data().spritePath(), monsterTypes.size()); + Log("Loading monster graphics: {:15s} x{:d}", firstMonster.data().spritePath(), monsterTypes.size()); print_memory_usage(); #endif MonsterSpritesData spritesData = LoadMonsterSpritesData(firstMonster.data()); From c2cfbb032fda5a9bec78422d243f76906dcbce10 Mon Sep 17 00:00:00 2001 From: Azi Hassan Date: Wed, 22 Jan 2025 20:39:45 +0100 Subject: [PATCH 6/7] Restore Diablo idle and death animations because the blackd.clx and maged.clx changes were enough for level 16 to load on 16 megs of RAM --- .github/workflows/dreamcast.yml | 2 -- Dockerfile | 2 -- 2 files changed, 4 deletions(-) diff --git a/.github/workflows/dreamcast.yml b/.github/workflows/dreamcast.yml index 27ffc2aaf2f..f782d561d72 100644 --- a/.github/workflows/dreamcast.yml +++ b/.github/workflows/dreamcast.yml @@ -90,8 +90,6 @@ jobs: run: | unpack_and_minify_mpq DIABDAT.MPQ && \ cp blackd.clx diabdat/monsters/black/blackd.clx && \ - cp diablod.clx diabdat/monsters/diablo/diablod.clx && \ - cp diablon.clx diabdat/monsters/diablo/diablon.clx && \ cp maged.clx diabdat/monsters/mage/maged.clx && \ patch build/data/txtdata/monsters/monstdat.tsv -l -p0 < monstdat.patch diff --git a/Dockerfile b/Dockerfile index 0f0025dd592..286881afc83 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,8 +54,6 @@ RUN source /opt/toolchains/dc/kos/environ.sh && cd build && kos-make RUN echo "Patching RAM-heavy assets..." RUN [ -e diabdat ] && \ cp blackd.clx diabdat/monsters/black/blackd.clx && \ - cp diablod.clx diabdat/monsters/diablo/diablod.clx && \ - cp diablon.clx diabdat/monsters/diablo/diablon.clx && \ cp maged.clx diabdat/monsters/mage/maged.clx && \ patch build/data/txtdata/monsters/monstdat.tsv -l -p0 < monstdat.patch From e29fb2b22e65e6cc6d948b684f084b7c1ce231dd Mon Sep 17 00:00:00 2001 From: Azi Hassan Date: Fri, 24 Jan 2025 01:48:43 +0100 Subject: [PATCH 7/7] Add CLX downgrading step for knights and mages --- .github/workflows/dreamcast.yml | 9 ++++++--- CMake/platforms/dreamcast.cmake | 4 ++-- Dockerfile | 9 ++++++--- monstdat.patch | 11 ----------- 4 files changed, 14 insertions(+), 19 deletions(-) delete mode 100644 monstdat.patch diff --git a/.github/workflows/dreamcast.yml b/.github/workflows/dreamcast.yml index f782d561d72..97dfefa97c3 100644 --- a/.github/workflows/dreamcast.yml +++ b/.github/workflows/dreamcast.yml @@ -89,9 +89,12 @@ jobs: if: ${{ hashFiles('DIABDAT.MPQ') != '' }} run: | unpack_and_minify_mpq DIABDAT.MPQ && \ - cp blackd.clx diabdat/monsters/black/blackd.clx && \ - cp maged.clx diabdat/monsters/mage/maged.clx && \ - patch build/data/txtdata/monsters/monstdat.tsv -l -p0 < monstdat.patch + curl -LO https://gist.github.com/azihassan/85a7bb8c49ff23fe4d8cf7cb9fdfc8c4/raw/d88f732c2dc44f9ee9f3d56dd942ff0b0b849811/clx.cpp && \ + g++ -std=c++11 clx.cpp && \ + ./a.out diabdat/monsters/black/blackd.clx && \ + ./a.out diabdat/monsters/mage/maged.clx && \ + mv diabdat/monsters/black/blackd.clx.stripped diabdat/monsters/black/blackd.clx && \ + mv diabdat/monsters/mage/maged.clx.stripped diabdat/monsters/mage/maged.clx - name: Generate .cdi run: | diff --git a/CMake/platforms/dreamcast.cmake b/CMake/platforms/dreamcast.cmake index 3161c23f131..3a40c147241 100644 --- a/CMake/platforms/dreamcast.cmake +++ b/CMake/platforms/dreamcast.cmake @@ -21,7 +21,7 @@ set(DEVILUTIONX_DISABLE_STRIP ON) set(DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/data/") set(BUILD_ASSETS_MPQ OFF) -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/threads-stub") +#list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/threads-stub") list(APPEND DEVILUTIONX_PLATFORM_COMPILE_DEFINITIONS __DREAMCAST__) add_compile_options(-fpermissive) @@ -47,4 +47,4 @@ set(JOY_BUTTON_START 3) set(SDL_INCLUDE_DIR /usr/include/SDL/) set(SDL_LIBRARY /usr/lib/libSDL.a) -add_compile_options(-flto=none) +#add_compile_options(-flto=none) diff --git a/Dockerfile b/Dockerfile index 286881afc83..bf27d4c16f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,9 +53,12 @@ RUN source /opt/toolchains/dc/kos/environ.sh && cd build && kos-make RUN echo "Patching RAM-heavy assets..." RUN [ -e diabdat ] && \ - cp blackd.clx diabdat/monsters/black/blackd.clx && \ - cp maged.clx diabdat/monsters/mage/maged.clx && \ - patch build/data/txtdata/monsters/monstdat.tsv -l -p0 < monstdat.patch + curl -LO https://gist.github.com/azihassan/85a7bb8c49ff23fe4d8cf7cb9fdfc8c4/raw/d88f732c2dc44f9ee9f3d56dd942ff0b0b849811/clx.cpp && \ + g++ -std=c++11 clx.cpp && \ + ./a.out diabdat/monsters/black/blackd.clx && \ + ./a.out diabdat/monsters/mage/maged.clx && \ + mv diabdat/monsters/black/blackd.clx.stripped diabdat/monsters/black/blackd.clx && \ + mv diabdat/monsters/mage/maged.clx.stripped diabdat/monsters/mage/maged.clx RUN echo "Generating CDI" RUN source /opt/toolchains/dc/kos/environ.sh && \ diff --git a/monstdat.patch b/monstdat.patch deleted file mode 100644 index cdab586d920..00000000000 --- a/monstdat.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- assets/txtdata/monsters/monstdat.tsv 2024-10-07 01:53:20.352087707 +0100 -+++ monstdat.tsv 2024-12-01 00:14:59.000000000 +0100 -@@ -109,7 +109,7 @@ - MT_CABALIST Cabalist mage\mage mage\cnselgd Retail 128 2000 true false 12,1,20,8,28,20 1,1,1,1,1,1 15 16 29 120 120 Counselor CAN_OPEN_DOOR 2 110 8 14 30 0 0 0 0 0 Demon RESIST_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING IMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING Bottom,Middle,Top 4929 - MT_ADVOCATE Advocate mage\mage mage\cnselbk Retail 128 2000 true false 12,1,20,8,28,20 1,1,1,1,1,1 16 16 30 145 145 Counselor CAN_OPEN_DOOR 3 120 8 15 25 0 0 0 0 0 Demon IMMUNE_MAGIC,RESIST_FIRE,IMMUNE_LIGHTNING IMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING Bottom,Middle,Top 4968 - MT_GOLEM Golem golem\golem golem\golm Never 96 386 true false 0,16,12,0,12,20 1,1,1,1,1,1 1 1 12 1 1 Golem CAN_OPEN_DOOR 0 0 7 1 1 0 0 0 0 1 Demon 0 --MT_DIABLO The Dark Lord diablo\diablo Never 160 2000 true true 16,6,16,6,16,16 1,1,1,1,1,1 26 26 45 3333 3333 Diablo KNOCKBACK,SEARCH,CAN_OPEN_DOOR 3 220 4 30 60 0 11 0 0 90 Demon IMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING IMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING Bottom,Middle,Top 31666 -+MT_DIABLO The Dark Lord diablo\diablo Never 160 2000 true true 8,6,16,6,8,16 1,1,1,1,2,1 26 26 45 3333 3333 Diablo KNOCKBACK,SEARCH,CAN_OPEN_DOOR 3 220 4 30 60 0 11 0 0 90 Demon IMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING IMMUNE_MAGIC,RESIST_FIRE,RESIST_LIGHTNING Bottom,Middle,Top 31666 - MT_DARKMAGE The Arch-Litch Malignus darkmage\dmage darkmage\dmag Never 128 1060 true false 6,1,21,6,23,18 1,1,1,1,1,1 21 21 30 160 160 Counselor CAN_OPEN_DOOR 3 120 8 20 40 0 0 0 0 70 Demon RESIST_MAGIC,RESIST_FIRE,RESIST_LIGHTNING IMMUNE_MAGIC,IMMUNE_FIRE,IMMUNE_LIGHTNING Bottom,Middle,Top 4968 - MT_HELLBOAR Hellboar fork\fork newsfx\hboar Retail 188 800 false false 10,10,15,6,16,0 2,1,1,1,1,1 17 18 23 80 100 SkeletonMelee KNOCKBACK,SEARCH 2 70 7 16 24 0 0 0 0 60 Demon RESIST_FIRE,RESIST_LIGHTNING Bottom,Middle 750 - MT_STINGER Stinger scorp\scorp newsfx\stingr Retail 64 305 false false 10,10,12,6,15,0 2,1,1,1,1,1 17 18 22 30 40 SkeletonMelee 3 85 8 1 20 0 0 0 0 50 Animal RESIST_LIGHTNING Bottom 500