Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6f7ff49
gfx: enable shaderDemoteToHelperInvocation, which the shaders need
Oct 7, 2026
1d7cbce
Localization: game text from JSON, TrueType message font, Language op…
Oct 7, 2026
4b26dd5
Localization: TrueType text keeps the bitmaps' outline and shadow
JefferyRose Oct 7, 2026
cbc7499
wip: Options text through the modular options/ screen
JefferyRose Oct 7, 2026
5f7b5f4
wip: cast shadow taps
JefferyRose Oct 7, 2026
6b1dd60
lang: add keys for new settings, drop stale tab help
claude Oct 7, 2026
6afc601
wip: cast shadow also for the system text style
claude Oct 7, 2026
88db9b5
Localization: TrueType shadow is cast down and right with a soft fall…
claude Oct 7, 2026
1c18b60
Localization: Text Shadow setting (Soft or Deep) on the Display page
claude Oct 7, 2026
499707a
Localization: soft shadow is a blurred, denser cast
claude Oct 7, 2026
5985e0f
Localization: soft shadow is more opaque
claude Oct 7, 2026
01e446b
Localization: soft shadow is more transparent
claude Oct 7, 2026
30f048b
Localization: glyphs are uploaded at once, not through the recorded d…
claude Oct 7, 2026
1f735fb
Flatpak: stb_truetype.h is a build source, as the audio decoders are,…
claude Oct 7, 2026
a99cf8b
Localization: the table outline is the same cast shadow as the other …
claude Oct 7, 2026
9ffdb15
Button symbols: PS4/PS5/Xbox/Switch/keyboard glyph atlases for the fo…
Oct 8, 2026
272646b
Localization: the message font and the language files work out of the…
Oct 8, 2026
aedcaee
docs: refer to LOCALIZATION.md in backticks, as the other docs are
Oct 8, 2026
084e822
Button symbols: the PS5 style is drawn from the new button pack
Oct 8, 2026
7113bb4
Text and symbol shadow: two sliders from none to dark
Oct 8, 2026
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ AGENTS.md
/save/
/soundtrack/

# The game's message files exported as JSON (darkcloud --export-text, docs/LOCALIZATION.md): the
# disc's own text, never committed.
/lang-export/

# Flatpak builds (docs/FLATPAK.md)
/.flatpak-builder/
/build-dir/
Expand Down
4 changes: 4 additions & 0 deletions CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ drkm9743

[Artists]
Carbon

[Message font]
Dayuppy
Moonbunny
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ and `JOBS=N` controls parallelism on every platform.
`chronicle.flatpak`; `docs/FLATPAK.md` covers installing it. It needs your own PAL disc: the first
start asks for the disc image and extracts the game's files from it.

### Translations and the message font

Game text can come from JSON language files (one per language, laid out as Minecraft's are) and be drawn from a
TrueType font so it stays sharp at any window size. The first start writes the language files from your own
game data; the Dark Cloud community font is bundled. See `docs/LOCALIZATION.md`.

## Repository layout

- `ps2/src`, `ps2/include`: matching game sources and headers.
Expand Down
39 changes: 39 additions & 0 deletions docs/GLYPHS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Button symbols

The game draws pad symbols in its text (the font's icons) and in a few textures. With `input.glyphs` `"new"`
(the default) the port draws redrawn symbols for the device in use instead; `"original"` keeps the PS2's art.
Options > Controls has both settings.

| config.json | values | meaning |
|---|---|---|
| `input.glyphs` | `new`, `original` | the redrawn symbols, or the game's own |
| `input.glyph_device` | `auto`, `ps4`, `ps5`, `xbox`, `switch`, `keyboard` | whose symbols: `auto` follows the device touched last (keyboard or mouse, otherwise the first gamepad's make; PS4 until something is touched); the others force one |

The keyboard style shows the key or mouse button the player bound to the action (`input.bindings`), the PS4 symbol
where the art has none for that key. Face buttons follow their position on the pad (the game's Cross is the bottom
button: A on Xbox, B on Switch).

## Where they are drawn

- Font icons (`ClsMes::DrawGaijiFont`, `port/src/clsmes.cpp`): the pad codes -0x300 to -0x2F4 (`{select}`, `{start}`,
`{L1}` to `{R2}`, `{circle}`, `{triangle}`, `{cross}`, `{square}`, `{dpad}`...). Every message and menu that names a
button uses them.
- Symbols painted into textures (`port/src/glyph_draw.cpp`, table `kBaked`): the name entry's L1/R1 hints (`nametemp`), the
character board's tab hints (`perbrd`) and the cutscene skip prompt (`pause_e`, `skip_bord`). Draws of these rectangles
(`RectSprite`, `port/src/snd.cpp`) are replaced by, or overlaid with, the symbol.
- Symbols on other textures the port has not found yet are still the game's: `DC_SPRITE_TRACE=1` prints each texture
rectangle a sprite draws (stderr) and `DC_TEXTURE_DUMP=<dir>` writes every texture the game loads as a PNG, which is
how the table was made. Add the box to `kBaked`.

## Files

`glyphs/` beside the executable (or in the save folder, which wins): `glyphs.json` and one atlas PNG per style. The
json gives each symbol's rectangle in its atlas; `reference` is the atlas size of a round face button. A symbol is
drawn scaled so a round button fills the height of its slot. `tools/glyphs/build_glyphs.py --src <art folder>` builds
them from the source art (P4Gamepad/Retro, P5Gamepad/Retro, XGamepad/Alt 2, SGamepad/Retro, Keyboard_Mouse/Dark);
Xbox's Menu button and the keyboard style's cursor-key clusters are composed by the tool. The atlases are read with
stb_image (a pinned download, as stb_truetype is).

The PS5 style is drawn from a flat pack of 64 px buttons (`ps5_a_butt.png`, `ps5_lstick_all.png`...):
`tools/glyphs/build_glyphs.py --ps5-pack <folder>` rebuilds only `ps5.png` and its entry in `glyphs.json`, leaving the
other styles. The pack's A, B, X and Y are Cross, Circle, Square and Triangle; L3 and R3 are its plain stick icons.
308 changes: 308 additions & 0 deletions docs/LOCALIZATION.md

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions docs/PC.md
Original file line number Diff line number Diff line change
Expand Up @@ -1197,8 +1197,9 @@ characters in it, and its own accents only.

`GameTextEncode` turns UTF-8 into codes. Curly quotes and dashes become the
font's own; any other character the font lacks, and any byte that is not
UTF-8, becomes `?` and is counted. `{N}` writes code N as it is, for control
codes and icons, and `{{` a `{`; `GameTextDecode` writes the same form, so
UTF-8, becomes `?` and is counted. A control code or icon is written in braces by its name (`{page}`, `{cyan}`, `{L1}`,
`{value3}`; the list is in LOCALIZATION.md) or by its number, `{N}`, and `{{` is a `{`;
`GameTextDecode` writes the name where there is one, else the number, so
any message reads back and encodes to the same codes. `GameTextFile` lays
texts out as a message file for `ClsMes::SetBuff`. `GameText` is one piece of
text drawn as the menus draw their help line (`InitMenuMesSet`'s
Expand All @@ -1207,7 +1208,7 @@ the text, `SetColour` a `FontColor`, then `Draw(x, y, alpha)` from a menu's
draw function; `Width` gives its width for aligning a value.

Both have retail's fixed sizes. A window lays out at most `MES_WIN_LINE_MAX`
(720) characters, counting the end and what a `{N}` name, value or system
(720) characters, counting the end and what a `{name1}`, `{value}` or `{insert1}` name, value or system
message code expands to; retail's `SetMesWinTbl` writes on past the table, so
the port's (`port/src/clsmes.cpp`) takes no more, and `GameText::Set` gives back
-1, draws nothing and has a width of 0 for a text that did not fit. A line past
Expand All @@ -1217,6 +1218,9 @@ without one does. A message file is s16 throughout: an id is -0x8000 to
the last message by id may extend beyond that range. `GameTextFile::Set`
gives back -1 and leaves the file as it was where either would not hold.

The text of retail's message files can be replaced from JSON, one file per language, with the
disc's text as the fallback: see `docs/LOCALIZATION.md`.

## The Options screen

The game's Options screen, from the title, the town menu and the dungeon menu,
Expand Down
2 changes: 1 addition & 1 deletion docs/port/truncations.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ recovered, as `CCharacter::ClothStep` does with `PortImagePointer`) fixes the ro

| site | function | state | class | expression | origin | use |
|---|---|---|---|---|---|---|
| port/src/dataread.cpp:184 | LoadFileBG | port | low-bits | `reinterpret_cast < std :: uintptr_t >(buffer)` | parameter | test |
| port/src/dataread.cpp:208 | LoadFileBG | port | low-bits | `reinterpret_cast < std :: uintptr_t >(buffer)` | parameter | test |
| port/src/edit_in.cpp:1761 | LoadData | port | low-bits | `(intptr_t)func_point[i].parts` | field | index: InteriorParts[(int)(intptr_t)func_point[i].parts] |
| port/src/editloop_init.cpp:405 | EditInit | port | low-bits | `reinterpret_cast < std :: intptr_t >(EdNPCReadBuffer)` | global pointer | store: read_misalign |
| port/src/texture_buffer.cpp:14 | CTextureManager::SetBuffer | port | low-bits | `reinterpret_cast < std :: uintptr_t >(this->buffer)` | field | store: misalignment |
Expand Down
37 changes: 35 additions & 2 deletions port/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ else()
file(DOWNLOAD https://raw.githubusercontent.com/nothings/stb/2c980bb59875b0d32144a71867fbdebb2f77cd20/stb_vorbis.c
${AUDIO_DECODER_DIR}/stb_vorbis.c EXPECTED_HASH SHA256=4c7cb2ff1f7011e9d67950446b7eb9ca044f2e464d76bfbb0b84dd2e23e65636)
endif()
# The message font's rasterizer (platform/ttffont.cpp): a single-file library, public domain or MIT, at a pinned
# commit. Flatpak has it as a source, since its build sandbox has no network; other builds fetch the same file.
if(EXISTS ${CMAKE_SOURCE_DIR}/stb_truetype/stb_truetype.h)
set(TTF_DIR ${CMAKE_SOURCE_DIR}/stb_truetype)
else()
set(TTF_DIR ${CMAKE_BINARY_DIR}/stb_truetype)
file(DOWNLOAD https://raw.githubusercontent.com/nothings/stb/2c980bb59875b0d32144a71867fbdebb2f77cd20/stb_truetype.h
${TTF_DIR}/stb_truetype.h EXPECTED_HASH SHA256=ecd30b05e0dd4fea3a13c26810dd9e1992dc379049482c393d5a19e6b5090aab)
endif()
# The button symbols' PNG atlases (platform/glyphs.cpp): the same library family at the same pinned commit, a
# Flatpak source beside stb_truetype.h, or fetched.
if(NOT EXISTS ${TTF_DIR}/stb_image.h)
file(DOWNLOAD https://raw.githubusercontent.com/nothings/stb/2c980bb59875b0d32144a71867fbdebb2f77cd20/stb_image.h
${TTF_DIR}/stb_image.h EXPECTED_HASH SHA256=594c2fe35d49488b4382dbfaec8f98366defca819d916ac95becf3e75f4200b3)
endif()

set(PS2_DIR ${CMAKE_SOURCE_DIR}/ps2/src)
set(PORT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
Expand Down Expand Up @@ -213,12 +228,12 @@ file(CONFIGURE OUTPUT ${SHADER_HEADER_DIR}/options/credits.hpp
CONTENT "#pragma once\ninline constexpr const char *kCredits[] = {${credit_names}};\n")

add_library(dc_host OBJECT ${HOST_SOURCES} ${SHADER_HEADERS})
target_include_directories(dc_host PRIVATE ${PORT_DIR} ${SHADER_HEADER_DIR} ${AUDIO_DECODER_DIR})
target_include_directories(dc_host PRIVATE ${PORT_DIR} ${SHADER_HEADER_DIR} ${AUDIO_DECODER_DIR} ${TTF_DIR})
target_link_libraries(dc_host PRIVATE SDL3::SDL3 Vulkan::Vulkan nlohmann_json::nlohmann_json)
target_compile_options(dc_host PRIVATE -Wall -ffunction-sections -fdata-sections)

add_library(dc_port OBJECT ${PORT_LIB_SOURCES})
target_link_libraries(dc_port PRIVATE dc_options SDL3::SDL3 Vulkan::Vulkan)
target_link_libraries(dc_port PRIVATE dc_options SDL3::SDL3 Vulkan::Vulkan nlohmann_json::nlohmann_json)
# Replacement units reach the host side as "gfx/gfx.hpp", "platform/window.hpp".
target_include_directories(dc_port PRIVATE ${PORT_DIR} ${SHADER_HEADER_DIR})
# The game's headers trip a few warnings that only describe how MWCC's source
Expand Down Expand Up @@ -269,6 +284,24 @@ endif()
include(GNUInstallDirs)
install(TARGETS darkcloud RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

# The strings the port draws itself, translated (docs/LOCALIZATION.md): lang/ beside the executable, where the
# game reads its language files.
add_custom_target(dc_lang
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/lang $<TARGET_FILE_DIR:darkcloud>/lang
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/tools/font/DarkCloudCompendium.ttf
$<TARGET_FILE_DIR:darkcloud>/lang/font.ttf
COMMENT "Copying the port's translated strings and message font")
add_dependencies(darkcloud dc_lang)
install(DIRECTORY lang/ DESTINATION ${CMAKE_INSTALL_BINDIR}/lang)
install(FILES ${CMAKE_SOURCE_DIR}/tools/font/DarkCloudCompendium.ttf DESTINATION ${CMAKE_INSTALL_BINDIR}/lang RENAME font.ttf)

# The button symbols (docs/GLYPHS.md): glyphs/ beside the executable. Rebuilt from art by tools/glyphs/build_glyphs.py.
add_custom_target(dc_glyphs
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/glyphs $<TARGET_FILE_DIR:darkcloud>/glyphs
COMMENT "Copying the button symbols")
add_dependencies(darkcloud dc_glyphs)
install(DIRECTORY glyphs/ DESTINATION ${CMAKE_INSTALL_BINDIR}/glyphs)

# The tests use an installed GoogleTest, or fetch one at configure time; a build with neither turns them off.
option(DC_BUILD_TESTS "Build darkcloud_tests" ON)
if(DC_BUILD_TESTS)
Expand Down
8 changes: 8 additions & 0 deletions port/flatpak/org.themoonpeople.Chronicle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,11 @@ modules:
url: https://raw.githubusercontent.com/nothings/stb/2c980bb59875b0d32144a71867fbdebb2f77cd20/stb_vorbis.c
sha256: 4c7cb2ff1f7011e9d67950446b7eb9ca044f2e464d76bfbb0b84dd2e23e65636
dest: audio_decoders
- type: file
url: https://raw.githubusercontent.com/nothings/stb/2c980bb59875b0d32144a71867fbdebb2f77cd20/stb_truetype.h
sha256: ecd30b05e0dd4fea3a13c26810dd9e1992dc379049482c393d5a19e6b5090aab
dest: stb_truetype
- type: file
url: https://raw.githubusercontent.com/nothings/stb/2c980bb59875b0d32144a71867fbdebb2f77cd20/stb_image.h
sha256: 594c2fe35d49488b4382dbfaec8f98366defca819d916ac95becf3e75f4200b3
dest: stb_truetype
Loading
Loading