CN | EN
Cross-platform C++ reimplementation and enhancement of MaichartConverter.
- Implement local lz4 decompression in replacement of Unity LZ4 library (currently used via UABE code paths and is not performance-critical)
- Add reverse asset export in
assetsworkflow (currently available inmaiconv media:png->ab,mp3->acb+awb,mp4->dat) - Separate 1P/2P Utage charts and append
(L)/(R)to output folder names andmaidata&title=
- C++20 + CMake + git submodule (runtime deps in third_party)
- CLI subcommands:
maiconv ma2maiconv simaimaiconv assetsmaiconv media
- Note transforms: rotate + tick shift
- Cross-platform: Windows / Linux / macOS
third_party/*: runtime third-party dependencies are managed by git submodules.- Test dependency
Catch2is also managed as a git submodule whenMAICONV_BUILD_TESTS=ON. - Required build submodules:
CLI11,tinyxml2(plusCatch2when tests are enabled).
git submodule update --init --recursive
cmake --preset default
cmake --build --preset default
ctest --preset defaultAudio and Video processing in maiconv media and maiconv assets uses external ffmpeg.
External ffmpeg executable requirements:
ffmpegshould be available inPATH, or setMAICONV_FFMPEGto an absolute executable path.ffprobeis optional (useful for manual diagnostics).
Required capabilities by feature:
dat/usm/crid -> mp4: supports VP9 IVF, H.264 Annex-B, and MPEG video streams; stream copy is attempted when possible, but an H.264 encoder (libx264or hardware alternative) is needed for transcode fallback.mp4 -> dat: requires a VP9 encoder (libvpx-vp9or hardware alternative) because MaiConv first transcodes to VP9 IVF.
Optional ffmpeg tuning settings (when your ffmpeg build supports them):
MAICONV_FFMPEG_HWACCEL: e.g.auto,cuda,d3d11va,qsvMAICONV_FFMPEG_H264_ENCODER: e.g.h264_nvenc,h264_qsv,h264_amf,libx264MAICONV_FFMPEG_VP9_ENCODER: e.g.vp9_qsv,libvpx-vp9MAICONV_FFMPEG_AUDIO_HWACCEL: audio ffmpeg path hwaccel hint (same values as above)MAICONV_FFMPEG_MP3_ENCODER: mp3 encoder for ffmpeg path (defaultlibmp3lame)- CLI
--gpuflag (forassetsandmedia audio|video): auto-enables GPU hints and encoder fallback without manual env vars
Notes:
- hwaccel hints are best-effort and real gains still depend on codec/driver support.
mp4 -> datdepends on VP9 encode throughput; GPU benefit depends on whether your ffmpeg provides a VP9 hardware encoder.--gpusetsMAICONV_FFMPEG_GPU=1and fillsMAICONV_FFMPEG_HWACCEL/AUDIO_HWACCEL=autoonly when they are unset, so explicit env vars still win.
PowerShell quick start (--gpu + explicit override):
# auto GPU hints
maiconv media video --input .\pv.mp4 --output .\pv.dat --gpu
# force your own choice (overrides --gpu defaults)
$env:MAICONV_FFMPEG_HWACCEL="cuda"
$env:MAICONV_FFMPEG_H264_ENCODER="h264_nvenc"
maiconv media video --input .\001145.dat --output .\pv.mp4 --gpuQuick checks:
ffmpeg -version
ffmpeg -hide_banner -encodersIf required encoders are missing, install an ffmpeg build that provides at least one H.264 encoder and one VP9 encoder (recommended baseline: libx264 + libvpx-vp9).
maiconv ma2 --input /path/to/sample.ma2 --format simai --output ./outmaiconv simai --input /path/to/maidata.txt --difficulty 3 --format ma2 --output ./outQuick commands:
Export all tracks:
maiconv assets --input /path/to/StreamingAssets --output ./Output --layout flatExport one or more ids (all difficulties):
maiconv assets --input /path/to/StreamingAssets --output ./Output --id 363,114514 --layout flatExport selected ids with selected difficulties:
maiconv assets --input /path/to/StreamingAssets --output ./Output --id 363,114514 --difficulty 2,3,7 --layout flatExport by regex filters:
maiconv assets --input /path/to/StreamingAssets --output ./Output --id '^11\\d{4}$' --difficulty '^[23]$' --layout flatExport tracks for specific version(s):
maiconv assets --input /path/to/StreamingAssets --output ./Output --version '23,^buddies\\s*plus$' --layout flatExport maidata.txt with display levels:
maiconv assets --input /path/to/StreamingAssets --output ./Output --format maidata --displayResume export and skip already completed tracks:
maiconv assets --input /path/to/StreamingAssets --output ./Output --layout flat --resumeGenerate placeholders for missing media:
maiconv assets --input /path/to/StreamingAssets --output ./Output --layout flat --dummyExport only selected output types:
maiconv assets --input /path/to/StreamingAssets --output ./Output --layout flat --types maidata.txt,track.mp3Selection rules:
- when
--idis omitted: export all tracks - when
--idis provided and--difficultyis omitted: export all difficulties for matched ids - when both are provided: export only matched difficulties for matched ids
--idand--difficultyaccept comma-separated filters, and each filter can be an exact number or a regex--versionaccepts comma-separated filters, and each filter can be a version id (number), version name, or a regex--difficultyuses exportedmaidatanumbering: standard charts are usually2..6, utage is7- for Utage tracks, when both
*_L.ma2and*_R.ma2exist in the same chart folder, MaiConv exports two outputs and appends(L)/(R)to both folder name andmaidata&title= --difficulty 7matches both(L)and(R)outputs for split Utage charts--resume(--skip-existing) skips tracks that already have complete exports, while keeping_Incompletetracks eligible for retry--typesaccepts comma-separated values:maidata.txt/track.mp3/bg.png/pv.mp4(aliases:chart|ma2,audio|music,cover|jacket|bg,video|movie|pv)
Folder discovery:
- audio:
SoundData - cover:
AssetBundleImages - video:
MovieData - override auto-detection when needed:
--music,--cover,--video
Dummy output spec:
- enable with
--dummy - if
track.mp3is missing: generate silenttrack.mp3using chart-derived duration - if
pv.mp4is missing andbg.pngexists: generate one-framepv.mp4frombg.png - if
pv.mp4is missing andbg.pngdoes not exist: generate one-frame blackpv.mp4
Fixed tags:
MISSING_AUDIO:track.mp3was dummy-generatedMISSING_VIDEO:pv.mp4was dummy-generatedSOURCE_BG_PNG: dummy video source isbg.pngBLACK_FRAME: dummy video source is a black frame
Machine-readable channels:
- progress line:
[dummy: <TAG>[,<TAG>...]] - warning line:
MAICONV_DUMMY:<musicId>:<TAG>
Convert ACB+AWB to MP3:
maiconv media audio --acb /path/to/music001944.acb --awb /path/to/music001944.awb --output ./track.mp3Pack MP3 into ACB+AWB:
maiconv media audio --input /path/to/track.mp3 --output-acb ./track.acb --output-awb ./track.awbConvert jacket between AB and image files:
maiconv media cover --input /path/to/UI_Jacket_001944.ab --output ./bg.png
maiconv media cover --input /path/to/bg.png --output ./bg.abConvert DAT/USM/CRID to MP4:
maiconv media video --input /path/to/001944.dat --output ./pv.mp4- VP9 IVF streams are transcoded to H.264 MP4.
- H.264 Annex-B / MPEG streams are remuxed first (
-c:v copy), then transcoded to H.264 only if remux fails.
Convert MP4 to DAT:
maiconv media video --input /path/to/pv.mp4 --output ./pv.datassets now supports both decoded files and original game asset naming:
- Audio input candidates:
music{dx_id}.mp3/.oggmusic{non_dx_id}.mp3/.oggmusic00{non_dx_4}.mp3/.oggmusic{dx_id}.acb/.awbmusic{non_dx_id}.acb/.awbmusic00{non_dx_4}.acb/.awb
- Cover input candidates:
UI_Jacket_*.png/.jpg/.jpegui_jacket_*.png/.jpg/.jpeg/.abAssetBundleImages/jacket/ui_jacket_*.png/.jpg/.jpeg/.abAssetBundleImages/jacket_s/ui_jacket_*_s.png/.jpg/.jpeg/.ab
- Video input candidates:
{id}.mp4/.dat/.usm/.crid{non_dx_id}.mp4/.dat/.usm/.crid- fallback based on
movieName/cueNameids inMusic.xml
For assets export, each song folder always contains maidata.txt, and media target names are:
{id_title}/
maidata.txt
track.mp3
bg.png
pv.mp4
track.mp3/bg.png/pv.mp4 may be missing when source media is unavailable (unless --dummy is used).
For split Utage tracks, output folder names become {id_title} (L) and {id_title} (R), and both maidata titles carry the same suffix.
When source media is in original game formats, assets converts them as follows:
acb + awb -> track.mp3(always transcoded by externalffmpeg)ab -> bg.png(embedded PNG extraction)dat/usm/crid -> pv.mp4- extracts/decrypts embedded USM/CRID video stream first
- VP9 IVF streams are transcoded to H.264 MP4
- H.264/MPEG streams try stream-copy remux first, then fall back to H.264 transcode
- if extraction/remux path fails, MaiConv falls back to direct
ffmpegtranscode from the source file
mp4 -> pv.dat- transcodes to VP9 IVF first (external
ffmpeg), then uses MaiConv's built-in C++ packer to emit DAT (@SFVpackets + compatible encryption) - requires external
ffmpegwithlibvpx-vp9encoder support
- transcodes to VP9 IVF first (external
Failure handling:
- if
movieNameisDEBUG_*, missing video is treated as optional - otherwise media conversion/missing files mark the track as
_Incomplete(or fail the command when--ignoreis not set)
assets --layout supports:
flat(default):{output}/{id_title}genre:{output}/{genre}/{id_title}version:{output}/{version}/{id_title}
assets --display switches lv_* export from chart constants like 13.8 to display levels like 13+.
- Unit tests: parser/composer/time/transform/assets/media
- Exit code:
0success,2failure. - Default output file names:
- Simai:
maidata.txt - Ma2:
result.ma2
- Simai: