From Wiki -
Jump to: navigation, search

ROFS is a bulk data file structure developed by CRI Middleware Co., Ltd. It is greatly built off of the ISO-9660 standard. These are easily identified as having the file name extension of CVM.


Several official programs for handling CVM files are known to exist. Usage is not known and guessed below.

    rofstoko.exe - ? Seemingly used to change existing data and perhaps conversion of some file types.
    rofsedit.exe - ?
    rofsgen.exe  - ?
    rofsbld.exe  - ? Most likely the program used to compile an ROFS structure from a list of files.
    rofsview.exe - ?

There are a few homemade programs created for interacting with CVM filesystems with various limited functionality.

Apache3 - Badly named but effective for extracting the contents of a CVM (and several other disc image types such as GCM). It can also replace files inside the image. Has entirely no capacity to create new files from scratch.

apache3_setup.exe v3.10.6 beta

Daemon Tools (and some other disc mounting software) - If a 0x1800 block is removed from the start of the file, it can be mounted as a disc image. Other mounting utilities may not cooperate.

VF4EXt_n_reb - A tool from darthi8nt. For VF4STRMS.cvm on Virtua Fighter 4.



This information is incomplete and may by itself not be of much help. Note also that it may not apply to all containers of this format being that there are known to be incompatible revisions.


As the format is built on top of the original Yellow Book standard, the file storage itself is well documented. Since both ISO and IEC are greedy bastards a relevant item to look up is ECMA-119. The ==Logical Block Size== is 2048 bytes.

At least two versions exist, perhaps not compatible with each other. One is ROFSROFSBLD Ver.1.52 2003-06-09, another is ROFSROFSBLD Ver.1.23 2001-10-17.

From: XeNTaX - ROFS Compression?Encryption? Method

    ROFS , By turning off the 0x1800 byte from the forefront of the file (header), and change the extension to .iso, Daemon tools can mount it.
    With the header where 0x1800 is gone, then it seems that its retained with the file system ( ISO9660 )
    ROFS (CVM) file format memo
    B = byte (8bit)
    W = word (16bit)
    L = long word (32bit)
    - ROFS version
    offset 0xb800
    1W: first data length = A
    1L: START address START (little endian)
    1L: START address START (big endian)
    1L: FAT SIZE (little endian)
    1L: FAT SIZE (big endian)
    1B: 0x68??
    1B: data length X
    XB: ?? (date?)
    4B: 01 00 00 01 ??
    2B: 01 00 or 01 01
    01 01 as for the FAT SIZE-related data end?
    1W: next data length = B
    here byte become A. Reading B Byte next, it processes.  
    However, because completely it has become the same contents as A in regard to data which is read next, 
    as for meaning in regard to data of B you do          not understand well. For verification?
    offset 0xb800 + A + B
    1W: data length C
    1L: START address START (little endian)
    1L: START address START (big endian)
    FILE START address = 0x800*START + 0x1800
    1L: file size (little endian)
    1L: file size (big endian)
    1B: 0x68 ??
    1B: data length Y
    YB: ?? (date?)
    4B: 01 00 00 01 ??
    1B: file name length Z
    ZB: file name
    2B: 3B 31 (flag?)
    0 fill are done
    last 1W: In case of data length of following data D
    0x0000, it adjusts the length of the following data and is packed (?)There is a place where it is done. The data other than
    0x00 appears to has the necessity to search.  
    The quantities of all to here byte become C. Reading D Byte next, it processes. 
    However, it adjusts and is packed (?)When it was done, data length stops being agreeable.  
    After returning to DATA FIRST, to FAT SIZE + 0x1800 it repeats processing.

From: XeNTaX - - ROFS Compression?Encryption? Method

struct ROFSRootEntry
int Offset;
short Unknown;
std::string Name;

struct ROFSEntry
unsigned short EntrySize; // Entry Header Size
unsigned int Address; // File start offset
unsigned int Size; // File Size
unsigned char Unk0[10];
unsigned short Unk;
std::string Name;

if I remember correctly the root entries are a listing of all directories in the file. 
from there the rofsentry structure is used to navigate the actual directory and file structure. 
a flag in the rofsentry structure tells if the entry is a directory(0x02) or a file(0x01) but I don't know 
where that was ^_^; when the entry is a directory the offset leads to another listing of directories 
or files. the file is padded to 4096 or 2048 I don't remember. (directories always have "." and ".." entries)

First read the root entries at offset ??? load them into memory and use that to get the entire 
file list(with rofsentry structure) it is just a bunch of interconnecting nodes.

Partial List of Games

Playstation 2

Arcana Heart


Odin Sphere

Persona 3

Persona 3 FES

Persona 4

Sakura Taisen V

Sonic Gems Collection

Sonic Heroes

Tales of Symphonia

Tales of the Abyss

Virtua Fighter 4

Virtua Fighter 4 Evolution