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.
Random
Several official programs for handling CVM files are known to exist. Actual usage is not entirely known.
rofstoko.exe - ? Seemingly used to change existing data and perhaps conversion of some file types.
rofsedit.exe - ?
rofsgen.exe - ?
rofsbld.exe - ?
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.
Abyss - A tiny custom tool made by darthi8nt for beating up the TO7BTL.cvm file from Tales Of The Abyss. It looks to be only for that specific file and no others.
VF4EXt_n_reb - Another tool from darthi8nt. Same deal as with Abyss, but for VF4STRMS.cvm on Virtua Fighter 4.
Structure
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)
--
0x0000-0xb7ff
- ROFS version
- GAME TITLE and PUBLISHER_NAME etc.
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
:DATA FIRST
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.