Skip to content

PSB Shells, Types, Platforms

Ulysses edited this page Dec 11, 2024 · 26 revisions

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

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)

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 generate xxx_info.psb.m, xxx_body.bin will not be built.
  • PsBuild info-psb xxx_info.psb.m.json: Generate both xxx_info.psb.m and xxx_body.bin.
  • You can not unpack/repack xxx_body.bin without xxx_info.psb.m!
  • Same logic for PsbDecompile and PsbDecompile 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.