Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/dreamcast.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: Sega Dreamcast

on: # yamllint disable-line rule:truthy
on: # yamllint disable-line rule:truthy
push:
branches:
- master
Expand Down Expand Up @@ -84,6 +84,18 @@ 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: |
unpack_and_minify_mpq DIABDAT.MPQ && \
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: |
source /opt/toolchains/dc/kos/environ.sh && \
Expand Down
4 changes: 2 additions & 2 deletions CMake/platforms/dreamcast.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
34 changes: 22 additions & 12 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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 && \
Expand All @@ -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 && \
Expand All @@ -50,11 +51,20 @@ 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 diabdat ] && \
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 && \
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"]
3 changes: 3 additions & 0 deletions Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -281,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})
Expand Down
10 changes: 10 additions & 0 deletions Source/diablo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@
#ifdef GPERF_HEAP_FIRST_GAME_ITERATION
#include <gperftools/heap-profiler.h>
#endif
#ifdef __DREAMCAST__
#include "memory_stats.h"
#endif

namespace devilution {

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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)
Expand Down
63 changes: 63 additions & 0 deletions Source/memory_stats.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// DREAMCAST memory stats related code

#include "memory_stats.h"

#include <dc/pvr.h>

#include <malloc.h>
#include <stdio.h>

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);
}
}
11 changes: 11 additions & 0 deletions Source/memory_stats.h
Original file line number Diff line number Diff line change
@@ -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
40 changes: 40 additions & 0 deletions Source/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
#ifdef _DEBUG
#include "debug.h"
#endif
#ifdef __DREAMCAST__
#include "memory_stats.h"
#endif

namespace devilution {

Expand Down Expand Up @@ -115,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];
Expand Down Expand Up @@ -1441,6 +1459,9 @@ void ShrinkLeaderPacksize(const Monster &monster)

void MonsterDeath(Monster &monster)
{
#ifdef __DREAMCAST__
ReorientMonsterToSouth(monster);
#endif
monster.var1++;
if (monster.type().type == MT_DIABLO) {
if (monster.position.tile.x < ViewPosition.x) {
Expand Down Expand Up @@ -3449,6 +3470,14 @@ void InitMonsterGFX(CMonster &monsterType, MonsterSpritesData &&spritesData)
GetMissileSpriteData(MissileGraphicID::DiabloApocalypseBoom).LoadGFX();
}

#ifdef __DREAMCAST__
void print_memory_usage()
{
print_ram_stats();
Log("\n\n\n");
}
#endif

void InitAllMonsterGFX()
{
if (HeadlessMode)
Expand All @@ -3467,6 +3496,10 @@ void InitAllMonsterGFX()
CMonster &firstMonster = LevelMonsterTypes[monsterTypes[0]];
if (firstMonster.animData != nullptr)
continue;
#ifdef __DREAMCAST__
Log("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) {
Expand All @@ -3475,6 +3508,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));
Expand Down Expand Up @@ -3795,6 +3831,10 @@ void MonsterDeath(Monster &monster, Direction md, bool sendmsg)
if (monster.mode != MonsterMode::Petrified) {
if (monster.type().type == MT_GOLEM)
md = Direction::South;
#ifdef __DREAMCAST__
md = Direction::South;
ReorientMonsterToSouth(monster);
#endif
NewMonsterAnim(monster, MonsterGraphic::Death, md, gGameLogicStep < GameLogicStep::ProcessMonsters ? AnimationDistributionFlags::ProcessAnimationPending : AnimationDistributionFlags::None);
monster.mode = MonsterMode::Death;
} else if (monster.isUnique()) {
Expand Down