PSB Shells, Types, Platforms - UlyssesWu/FreeMote GitHub Wiki
Shells
A PSB can be compressed/encrypted into a Shell
type, and a Shell
type can be decompressed/decrypted into a PSB (while PSB itself can still be encrypted).
MDF (pure)
M2 DeFlate file.
Header: mdf\0
Extensions: .mdf
Structure:
Position | Content | Value |
---|---|---|
0 | Signature | mdf\0 |
4 | original size | (uint) |
8 | Zlib compress header | 78 9C (fast) or 78 DA (optimal) |
10 | Zlib compressed content |
Solution:
EmtConvert pack -s MDF {file}
PsbDecompile {file}
PsBuild {file}
MFL/MZS/MXB
M2 FastLz/ZStandard/XMemCompress file.
Same as MDF, but use LZ77 (fastlz) or ZStandard or XMemCompress (MS Xbox) instead of deflate (zlib). They can also be applied with MT19937 stream encryption.
Header: mfl\0
, mzs\0
, mxb\0
MT19937 MDF/MFL/MZS/MXB
Must be decrypted with a key (not the PSB key
).
Extensions: .m
Key: usually hex string (length = 13 for most cases, can be different for M2 games, such as 9, and there could be any string rather than just hex), e.g. 523aad2de7132
, 38757621acf82
, ae3bb93923bf8
, Rj9Pegoh4
, 25G/xpvTbsb+6
Seed: key + file name, e.g. 523aad2de7132font_info.psb.m
, 38757621acf82voice_info.psb.m
Seed is actually used for generating MT19937 decrypt stream, therefore you must keep file name correct if you just provide key (-k
) instead of full seed (-s
). e.g. motion_info.psb.m
is a good name while motion_info_bak.psb.m
is bad because you should never change it.
If you use -k
, FreeMote just uses the current file name. Error occurs if you renamed the file.
Header: mdf\0
(mfl\0
etc.)
Structure:
Position | Content | Value |
---|---|---|
0 | Signature | mdf\0 |
4 | original size | (uint) |
8 | Zlib compress header | (Encrypted) |
10 | Zlib compressed content | (Encrypted) |
Solution:
EmtConvert mpack {file} -k {key} -l 131
note: -l (length) is the key buffer length (how many bytes generated from a key), usually 131, but could be any other value especially for M2 games (such as 97, 64)
PsbDecompile info-psb {file} -k {key} -l 131
(only for archive
PSB)
PsBuild info-psb {json file}
(only for archive
PSB)
LZ4
Compressed using LZ4 Frame. Can be directly decompressed with lz4.exe
(with Frame support).
Header: 0x184D2204
(LZ4 Frame header)
Extensions: .lz4, .psb
Solution:
EmtConvert pack -s LZ4 {file}
PsbDecompile {file}
PsBuild {file}
PSZ
Bascially same as MDF(pure).
Header: PSZ\0
Extensions: .psz
Structure:
Position | Content | Value |
---|---|---|
0 | Signature | PSZ\0 |
4 | compressed size | (int) |
8 | original size | (uint) |
12 | none | (int)0 |
16 | Zlib compress header | 78 9C (fast) or 78 DA (optimal) |
18 | Zlib compressed content |
Solution:
EmtConvert pack -s PSZ {file}
PsbDecompile {file}
PsBuild {file}
Types
PSBs for different purposes have different content structures. FreeMote identifies their types, extract and convert the contents to common formats.
Type ID: found in PSB object (root)\id
.
Archive
Type ID: archive
Extensions: .psb.m (normal PSB with MDF(MT19937) shell)
FreeMote.PsbType: ArchiveInfo
To unpack/repack, always use PsbDecompile info-psb xxx_info.psb.m
or PsBuild info-psb xxx_info.psb.m.json
rather than PsbDecompile info-psb xxx_info.psb
or PsBuild xxx_info.psb.m.json
. It's DIFFERENT. And always keep file name correct (see MDF(MT19937) for reason).
You have to find the key from the game's binary files. It's impossible to get the key just from body.bin or info.psb.m files.
PsBuild xxx_info.psb.m.json
: Only generatexxx_info.psb.m
,xxx_body.bin
will not be built.PsBuild info-psb xxx_info.psb.m.json
: Generate bothxxx_info.psb.m
andxxx_body.bin
.- You can not unpack/repack
xxx_body.bin
withoutxxx_info.psb.m
! - Same logic for
PsbDecompile
andPsbDecompile info-psb
.
{name}_info.psb.m
Shell Type: MDF(MT19937)
used as (file name/position/file length) index of {name}_body.bin
Solution:
PsbDecompile info-psb {file} -k {key} -l 131
{name}_body.bin
Plain combination of many PSB files. It's not directly handled by FreeMote tools (always use corresponding info.psb.m
).
Extensions: .bin
Shell Type: MDF(MT19937)
Solution:
Automatically extracted when extracting info.psb.m
with PsbDecompile info-psb
.
if use PsbDecompile info-psb {file} -k {key} -l 131 -a
, all psb.m
files in body.bin
will be decompiled to json.
EmtConvert mdf {.m file} -k {key} -l 131
(for single .m file)
Script (Scn)
Type ID: (none) (WTF M2?)
Extensions: .scn
FreeMote.PsbType: Scn
Image
Type ID: image
Extensions: .psb
FreeMote.PsbType: Tachie
Images (Pimg)
Type ID: (none)
Extensions: .pimg
FreeMote.PsbType: Pimg
Motion
Type ID: motion
Extensions: .psb, .mtn
FreeMote.PsbType: Motion
Motion Source (Mmo)
Type ID: motion
Extensions: .mmo, .emtproj
FreeMote.PsbType: Mmo
Sound Archive
Type ID: sound_archive
Extensions: .psb
FreeMote.PsbType: SoundArchive
Font
Type ID: font
Extensions: .psb
FreeMote.PsbType: BmpFont
Map
Type ID: map
Extensions: .psb(.m)
FreeMote.PsbType: Map
Platforms
PSB for different platforms uses different resource formats.
Spec ID: found in PSB object (root)\spec
.
Currently supported platforms (Spec ID/ FreeMote.PsbSpec):
- common: Unity games
- krkr: Kirikiri games
- win: DirectX games
- ems: WebGL games with emscripten
- psp: PSP
- vita: PSV
- ps4: PS4
- nx: NSwitch
- citra: 3DS
- and: Android
For EMT (motion) PSB, use PsBuild port -p {specID}
to convert platforms between common, win, krkr, ems. Other platforms will not be supported.