|
The VMS flash memory contains 128 kilobytes of storage. These are divided into 256 blocks of 512 bytes each. Of these blocks, 200 are available for user files. The rest of the blocks contain filesystem information, or are simply not used at all. The allocation of the 256 blocks is as follows:
The Directory, FAT and Root block are system files. They are not listed in the Directory, but do appear in the FAT. The Root block is always block 255. The start block of the FAT and Directory can be found in the Root block, see below. The root block (block 255) contains information such as:
0x000-0x00f : All these bytes contain 0x55 to indicate a properly formatted card. 0x010 : custom VMS colour (1 = use custom colours below, 0 = standard colour) 0x011 : VMS colour blue component 0x012 : VMS colour green component 0x013 : VMS colour red component 0x014 : VMS colour alpha component (use 100 for semi-transparent, 255 for opaque) 0x015-0x02f : not used (all zeroes) 0x030-0x037 : BCD timestamp (see Directory below) 0x038-0x03f : not used (all zeroes) ... 0x046-0x047 : 16 bit int (little endian) : location of FAT (254) 0x048-0x049 : 16 bit int (little endian) : size of FAT in blocks (1) 0x04a-0x04b : 16 bit int (little endian) : location of directory (253) 0x04c-0x04d : 16 bit int (little endian) : size of directory in blocks (13) 0x04e-0x04f : 16 bit int (little endian) : icon shape for this VMS (0-123) 0x050-0x051 : 16 bit int (little endian) : number of user blocks (200) ... The File Allocation Table works similar to a MS-DOS FAT16 File Allocation Table. It serves two purposes; it indicates which blocks are unallocated, and it links the blocks of a file together. Each of the 256 blocks have an entry in this table consisting of a 16-bit integer value (little endian). The entry for block 0 is stored first in the FAT, and the entry for block 255 is stored last. The entry is interpreted like this: 0xfffc : This block is unallocated 0xfffa : This block is allocated to a file, and is the last block in that file 0x00-0xff : This block is allocated to a file, and is not the last block in that fileIn the last case, the actual value of the entry indicates the next block in the file. This way, if the number of the first block of a file is known, the subsequent blocks can be found by traversing the FAT. The number of the first block can be found in the Directory if it is a user file, or in the Super block if it is a system file. Note that mini-game files are allocated starting at block 0 and upwards, while a data file is allocated starting at block 199 selecting the highest available free block. This is probably because a mini-game should be able to run directly from the flash, and thus needs to be placed in a linear memory space starting at a known address (i.e. 0). Although block 200 through 240 are marked as "free" in the FAT, they can not be used for anything. The Directory lists all the user files stored in the VMS. The Directory consists of a sequence of 32-byte entries each potentially describing a file. When the VMS is formatted, enough space is allocated to the Directory file to accommodate 200 entries. This is enough, since each file must be at least one block long, and there are only 200 blocks available for user files. The actual blocks making up the Directory can be found using the Root block and the FAT, although it should be safe to assume that the Directory has been allocated to blocks 241 through 253; 253 being the first block of the Directory, and 241 the last. An entry in the directory is either all NUL-bytes (denoting an unused entry), or a structure describing a file. This structure looks as follows: 0x00 : 8 bit int : file type (0x00 = no file, 0x33 = data, 0xcc = game) 0x01 : 8 bit int : copy protect (0x00 = copy ok, 0xff = copy protected) 0x02-0x03 : 16 bit int (little endian) : location of first block 0x04-0x0f : ASCII string : filename (12 characters) 0x10-0x17 : BCD timestamp (see below) : file creation time 0x18-0x19 : 16 bit int (little endian) : file size (in blocks) 0x1a-0x1b : 16 bit int (little endian) : offset of header (in blocks) from file start 0x1c-0x1f : unused (all zero)The file creation time is stored as a sequence of BCD (Binary Coded Decimal) bytes. Each byte represents a number between 0 and 99. The meaning of the bytes are as follows:
The software for the "Nexus 4 meg" 3rd party memory card can transfer the contents of the memory card flashrom to a PC and storing it in a file designated a "DCM-file". This is basically just a raw memory dump of the entire flashrom, however it must be noted that order of the bytes have been reversed in groups of 4. This means that the first byte of the file is actually the fourth byte of the flashrom, the second byte in the file is the third byte of the flashrom and so on. "DCI-files" are another Nexus specific file format. A DCI-file contains only the blocks of a single file. The first 32 bytes of the file is the directory entry for the file (see above), exactly as it appears in the flashrom (no byte swapping). The "location of first block" field should be ignored when reading. After the first 32 bytes each block of the file follows, in order. The blocks are byte-swapped just like in a DCM-file. All VMS files should contain
a standard header which is used by the file managers in the VMS and in the DC
boot ROM to display information about the file. (ICONDATA files
use a somewhat simplified headers since they are not shown in the DC boot ROM
file manager.) For data files, the header is stored at the very beginning of the
file. For game files, it begins in the second block of the file (offset
$200). This fact should be reflected by the header offset field in the VMS directory,
which should contain 1 for game files, and 0 for data files. This is the contents of the header:
The CRC should be computed on the entire file, including header and data payload, but excluding any padding in the final block. When calcukating the CRC, set the CRC field itself to 0 to avoid miscalculating the CRC for the header. The CRC calculation algorithm is as follows (C code): int calcCRC(const unsigned char *buf, int size) { int i, c, n = 0; for (i = 0; i < size; i++) { n ^= (buf[i]<<8); for (c = 0; c < 8; c++) if (n & 0x8000) n = (n << 1) ^ 4129; else n = (n << 1); } return n & 0xffff; } The palette consists of 16 16-bit little endian integers, one for each colour in the palette. Each integer consists of four four-bit fields:
The header should contain at least one icon bitmap for the file. If an animated icon is desired, up to three bitmaps can be used (set the field at offset $40 accordingly). The bitmaps are stored directly after each other, starting at offset $80. The bitmaps contain one nybble per pixel. Each byte thus represents two horizontally adjacent pixels, the high nybble being the left one and the low nybble being the right one. Each complete bitmap contains 1024 (32 * 32) nybbles, or 512 bytes. The header can optionally contain a 72×56 pixel image shown as a graphic eyecatch for the file in the DC boot ROM file manager. The graphic data for the eyecatch is stored immediately after the last icon bitmap. There are four possible visual modes, selected with the field at offset $44:
|