Skip to content

Publish Dark Cloud's sound in ChronicleTwo's formats (audio framework, phase 1) - #226

Closed
SirFancyBacon wants to merge 9 commits into
TheMoonPeople:masterfrom
SirFancyBacon:audio-framework
Closed

SirFancyBacon wants to merge 9 commits into
TheMoonPeople:masterfrom
SirFancyBacon:audio-framework

Conversation

@SirFancyBacon

@SirFancyBacon SirFancyBacon commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Requires #220, TheMoonPeople/Kazarov#35 and TheMoonPeople/Kazarov#34. This branch is built on #220, and the Kazarov submodule is pinned to #34's commit (ac118f7, on top of #35). Merge those first; once they are merged I'll repin to Kazarov's merged commit.

The first commit proposes the audio framework (docs/AUDIO_FRAMEWORK.md): real 5.1 and 7.1 output with positioned sounds placed where they are, the PS2's sound as the reference, and Dark Cloud's audio extracted into ChronicleTwo's WAV and JSON formats, with everything not particular to Dark Cloud in Kazarov. The second commit is its phase 1, extraction.

What extraction publishes

dcdata extract, and the new dcdata publish-sound <data> for data extracted before, publish the sound packs beside the originals:

  • each distinct bank once, as sound/banks/<member>-<hash>.sound/bank.json and WAV samples, through Kazarov's converter;
  • each pack's sequences, as sequence JSON;
  • a <pack>.sound.json (kind: "sound_pack") per pack: its load lists in order, the slot and published file of each member, and each list's .cfg commands (core 0 reverb, effect table);
  • the global tables, sound/tbl/sqtbl.json and setbl.json.

On the PAL disc, the 497 bank loads of 218 packs come to 223 banks (186 MB of WAV), in about nine seconds. Empty dummy banks are left out, as the game skips them. tools/dcdata/sound_data.hpp reads the load lists, .cfg commands and tables as the game does.

The game still plays the originals. Switching it to the published files is phase 2.

Testing

  • SoundPublishRealData (with DC_DATA) compares everything published against the originals:
    • every bank: every program, note and velocity resolves to the same samples, PCM, loops and envelopes through Kazarov's JSON loader as through its raw reader;
    • every sequence: the same events;
    • every .cfg: what retail's own LoadSoundInfo reads (through a forwarder in port/include/stubs/snd.hpp, listed in docs/PC.md);
    • the effect table: what the port's reader reads.
  • All 497 bank loads, 193 sequence loads and 145 .cfg files match on both the PAL and NTSC discs. The only difference left is cosmetic: the raw reader keeps the end of a track's meta number (0x2F), which nothing reads.
  • Six unit tests for the readers, with fixtures made in code.
  • The full suite passes apart from the two GfxValidation cases, which need the validation layer; the pointer-truncation audit and flatpak_sources.py pass.
  • In game: the game loads and plays as before in stereo.

dcdata now links Kazarov's Rust extractor (cmake/KazarovRust.cmake), which
needs Corrosion, every crate in Kazarov's Cargo.lock, cxxbridge and FFmpeg.
The Flatpak's build sandbox has no network, so the manifest has to stage all
of them, as ChronicleTwo's does:

- modules for FFmpeg (kz-ffmpeg's LGPL configuration, static), Rust 1.99.0
  (rust-toolchain.toml's pin) and cxxbridge-cmd, for the build alone;
- port/flatpak/cargo-sources.json, written from Cargo.lock by
  port/flatpak/cargo_sources.py;
- Corrosion in flatpak-deps/, which port/CMakeLists.txt already hands
  FetchContent.

Kazarov installs its gameplay seed archive as bin/data.zip. Chronicle has no
gameplay documents, so the seed is empty, and a data.zip beside darkcloud
makes the read-only /app/bin/data the data root: the game aborted with
"/app/bin/data is empty" instead of asking for the disc. The module's cleanup
removes it.

flatpak_sources.py only read KazarovPort.cmake, so it passed without
Corrosion. It now also follows the Kazarov modules tools/dcdata includes and
checks cargo-sources.json against Cargo.lock.
PortLegacyTexturePath listed the data's files, which indexes the data and stops the program when there is none, so the texture tests' synthetic IMGs aborted with "no game data" (nine TexDecode cases). Before the data is indexed it now takes the raw path, which decodes such images from their bytes; DataReadIndexed asks without indexing.
The baked-texture work moved two low-bits sites in dataread.cpp and texture.cpp; the audit had not run since, because the Test step before it was failing. No round-trip site that can run is listed.
The README's Windows section links docs/WINDOWS.md, which Doxygen could not resolve because it does not read the file. The documentation job fails on any warning, so it failed on master; docs/WINDOWS.md is now an input, as docs/SWITCH.md is for the Switch section's link.
acquire-rust.ps1 unpacked Rust, rustfmt and Clippy, each a .tar.xz, with the
system tar. The tar Windows 10 ships reads no xz (Windows 11 23H2 added it)
and waits forever instead of failing, so a first build on Windows 10 hung.
7-Zip, which the Windows build already requires and acquire.ps1 unpacks
everything else with, unpacks the .xz and then the members the toolchain
needs from the .tar, which is removed afterwards.

Fixes TheMoonPeople#221.
GfxCachedTarget and the parameterised GfxColorWriteMask start a Vulkan
device, but neither is named GfxGpu*, so they ran without the gpu label and
failed on the Windows runner, which runs ctest -LE gpu and has no driver
(vkCreateInstance failed, -9). They are labelled as ChronicleTwo labels them.
Real 5.1 and 7.1 output with positioned sounds placed where they are, the PS2's sound as the reference, and Dark Cloud's audio extracted into ChronicleTwo's WAV and JSON formats, with what is not particular to Dark Cloud in Kazarov. Measurements of the disc's sound data, the plan in six phases, and the decisions taken on it.
Phase 1 of docs/AUDIO_FRAMEWORK.md. dcdata extract, and dcdata
publish-sound for data extracted before, publish the sound packs beside the
originals: each distinct bank once, as bank JSON and WAV samples, each
pack's sequences as sequence JSON, both through Kazarov's converter
(audio_publish_bank, audio_publish_sequence); a sound_pack document per
pack with its load lists in order, the slot and published file of each
member, and the list's .cfg commands; and the global volume tables. On the
PAL disc the 497 bank loads of 218 packs come to 223 banks, 186 MB of WAV,
in about nine seconds. tools/dcdata/sound_data.hpp reads the load lists,
.cfg commands and tables as the game does. The game still plays the
originals.

SoundPublishRealData checks every published bank and sequence against the
originals through Kazarov's raw reader (every program, note and velocity
resolves to the same samples, PCM and loops; every sequence to the same
events), each .cfg against retail's LoadSoundInfo, through a forwarder in
port/include/stubs/snd.hpp, and the effect table against the port's
reader. All match on the PAL and NTSC discs.

Kazarov is pinned to its chronicle-audio-publish branch (389100a), which
adds the two bridge functions.
Kazarov's audio_publish_bank and audio_publish_sequence now sit on top of the fixes to Kazarov's own CI (rustfmt, clippy and the CMake 4 graph tests).
Adubbz added a commit that referenced this pull request Oct 27, 2026
#230: the fishing line's springs divide by their length through vu0::Div, as the EE does, so a zero-length spring no longer produces NaNs. #186: autosave on each dungeon floor and resume there, with a game.autosave setting; the save's map number goes through CSaveData::GetMapNo/SetMapNo and the dungeon map numbers are defined once. #223: an item registry with traits, the item tables as gameplay documents datapacks can replace, and quest conditions by item ID, in port/src/item. #226: dcdata publish-sound and the sound tables it publishes, with LoadSoundInfo declared in game/snd.hpp.
Adubbz added a commit that referenced this pull request Oct 27, 2026
The publish-sound command and its sound tables, parsed with nlohmann json; left out of the integration commit.
Adubbz added a commit that referenced this pull request Oct 27, 2026
…e open PRs

The port no longer compiles ps2/: the game's code is forked into port/src/game and
port/include/game, and PORT_OVERRIDE is gone. ps2/ stays the byte-matching decomp.

- PS2-only code removed from the fork: MWCC pragmas, code the PC link discarded, SDK calls
  that do nothing on PC, dead conditionals.
- All port code brought to AGENTS.md and C++26: anonymous namespaces, nullptr, C++ casts,
  std containers and strings in place of fixed buffers and C strings, enum class, no goto,
  meaningful names, minimal comments, documented headers.
- Every function in a logical file: the platform layer is in port/src/<subsystem>
  (app, data, platform, render, input, ui, options, title, battlemenu, dialog, quest,
  item, text, localize, save); the old replacement units are merged into their game units;
  no *_port files, stub headers, linknames.cpp or linker aliases remain.
- Namespaces: dc::game for the game, dc::<subsystem> for the platform layer, dc::test for
  the tests. Only main, extern "C" entry points and the symbols Kazarov calls stay global.
- CI per platform: pc.yml (Linux, Windows, Flatpak), macos.yml and switch.yml, with the
  Switch toolchain image cached on ghcr.io. Kazarov compiles pipelines on first use on a
  CPU rasterizer, so lavapipe no longer runs test processes out of memory.
- Merged PRs, simplified and restyled: #186 (autosave on each dungeon floor and resume
  there), #220, #223 (item framework and gameplay documents), #226 (sound publishing),
  #227, #228, #229, #230 (the fishing line's springs divide as the EE does; supersedes
  #219 and #225).

Each step was gated on Windows: build, unit tests, and headless screenshots of ten game
modes, pixel-identical to master's build.

Co-authored-by: Alessandro Suha <plarpoon@zandark.eu>
Co-authored-by: Thomas Cantwell <cantwell.tom@gmail.com>
Co-authored-by: SirFancyBacon <m.johnsondelta@gmail.com>
Co-authored-by: IvanPerrella <ivan.perrella@gmail.com>
@Adubbz

Adubbz commented Oct 27, 2026

Copy link
Copy Markdown
Member

Merged into master in d3666bc, simplified and restyled for the forked port (port/src/game, dc:: namespaces). Thank you!

@Adubbz Adubbz closed this Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants