KallistiOS git master
Independent SDK for the Sega Dreamcast
Loading...
Searching...
No Matches
vmufs.h
Go to the documentation of this file.
1/* KallistiOS ##version##
2
3 dc/vmufs.h
4 Copyright (C) 2003 Megan Potter
5
6*/
7
8/** \file dc/vmufs.h
9 \brief Low-level VMU filesystem driver.
10 \ingroup vfs_vmu
11
12 The VMU filesystem driver mounts itself on /vmu of the VFS. Each memory card
13 has its own subdirectory off of that directory (i.e, /vmu/a1 for slot 1 of
14 the first controller). VMUs themselves have no subdirectories, so the driver
15 itself is fairly simple.
16
17 Files on a VMU must be multiples of 512 bytes in size, and should have a
18 header attached so that they show up in the BIOS menu.
19
20 \author Megan Potter
21 \see dc/vmu_pkg.h
22 \see dc/fs_vmu.h
23*/
24
25#ifndef __DC_VMUFS_H
26#define __DC_VMUFS_H
27
28#include <sys/cdefs.h>
29__BEGIN_DECLS
30
31#include <dc/maple.h>
32
33/** \addtogroup vfs_vmu
34 @{
35*/
36
37/* \cond */
38#define __packed__ __attribute__((packed))
39/* \endcond */
40
41/** \brief BCD timestamp, used several places in the vmufs.
42 \headerfile dc/vmufs.h
43*/
44typedef struct {
45 uint8 cent; /**< \brief Century */
46 uint8 year; /**< \brief Year, within century */
47 uint8 month; /**< \brief Month of the year */
48 uint8 day; /**< \brief Day of the month */
49 uint8 hour; /**< \brief Hour of the day */
50 uint8 min; /**< \brief Minutes */
51 uint8 sec; /**< \brief Seconds */
52 uint8 dow; /**< \brief Day of week (0 = monday, etc) */
53} __packed__ vmu_timestamp_t;
54
55/** \brief VMU FS Root block layout.
56 \headerfile dc/vmufs.h
57*/
58typedef struct {
59 uint8 magic[16]; /**< \brief All should contain 0x55 */
60 uint8 use_custom; /**< \brief 0 = standard, 1 = custom */
61 uint8 custom_color[4];/**< \brief blue, green, red, alpha */
62 uint8 pad1[27]; /**< \brief All zeros */
63 vmu_timestamp_t timestamp; /**< \brief BCD timestamp */
64 uint8 pad2[8]; /**< \brief All zeros */
65 uint8 unk1[6]; /**< \brief ??? */
66 uint16 fat_loc; /**< \brief FAT location */
67 uint16 fat_size; /**< \brief FAT size in blocks */
68 uint16 dir_loc; /**< \brief Directory location */
69 uint16 dir_size; /**< \brief Directory size in blocks */
70 uint16 icon_shape; /**< \brief Icon shape for this VMS */
71 uint16 blk_cnt; /**< \brief Number of user blocks */
72 uint8 unk2[430]; /**< \brief ??? */
73} __packed__ vmu_root_t;
74
75/** \brief VMU FS Directory entries, 32 bytes each.
76 \headerfile dc/vmufs.h
77*/
78typedef struct {
79 uint8 filetype; /**< \brief 0x00 = no file; 0x33 = data; 0xcc = a game */
80 uint8 copyprotect; /**< \brief 0x00 = copyable; 0xff = copy protected */
81 uint16 firstblk; /**< \brief Location of the first block in the file */
82 char filename[12]; /**< \brief Note: there is no null terminator */
83 vmu_timestamp_t timestamp; /**< \brief File time */
84 uint16 filesize; /**< \brief Size of the file in blocks */
85 uint16 hdroff; /**< \brief Offset of header, in blocks from start of file */
86 uint8 dirty; /**< \brief See header notes */
87 uint8 pad1[3]; /**< \brief All zeros */
88} __packed__ vmu_dir_t;
89#undef __packed__
90
91/* Notes about the "dirty" field on vmu_dir_t :)
92
93 This byte should always be zero when written out to the VMU. What this
94 lets us do, though, is conserve on flash writes. If you only want to
95 modify one single file (which is the standard case) then re-writing all
96 of the dir blocks is a big waste. Instead, you should set the dirty flag
97 on the in-mem copy of the directory, and writing it back out will only
98 flush the containing block back to the VMU, setting it back to zero
99 in the process. Loaded blocks should always have zero here (though we
100 enforce that in the code to make sure) so it will be non-dirty by
101 default.
102 */
103
104
105/* ****************** Low level functions ******************** */
106
107/** \brief Fill in the date on a vmu_dir_t for writing.
108
109 \param d The directory to fill in the date on.
110*/
112
113/** \brief Reads a selected VMU's root block.
114
115 This function assumes the mutex is held.
116
117 \param dev The VMU to read from.
118 \param root_buf A buffer to hold the root block. You must allocate
119 this yourself before calling.
120 \retval -1 On failure.
121 \retval 0 On success.
122*/
124
125/** \brief Writes a selected VMU's root block.
126
127 This function assumes the mutex is held.
128
129 \param dev The VMU to write to.
130 \param root_buf The root block to write.
131 \retval -1 On failure.
132 \retval 0 On success.
133*/
135
136/** \brief Given a VMU's root block, return the amount of space in bytes
137 required to hold its directory.
138
139 \param root_buf The root block to check.
140 \return The amount of space, in bytes, needed.
141*/
143
144/** \brief Given a VMU's root block, return the amount of space in bytes
145 required to hold its FAT.
146
147 \param root_buf The root block to check.
148 \return The amount of space, in bytes, needed.
149*/
151
152/** \brief Given a selected VMU's root block, read its directory.
153
154 This function reads the directory of a given VMU root block. It assumes the
155 mutex is held. There must be at least the number of bytes returned by
156 vmufs_dir_blocks() available in the buffer for this to succeed.
157
158 \param dev The VMU to read.
159 \param root_buf The VMU's root block.
160 \param dir_buf The buffer to hold the directory. You must have
161 allocated this yourself.
162 \return 0 on success, <0 on failure.
163*/
165 vmu_dir_t * dir_buf);
166
167/** \brief Given a selected VMU's root block and dir blocks, write the dirty
168 dir blocks back to the VMU. Assumes the mutex is held.
169
170 \param dev The VMU to write to.
171 \param root The VMU's root block.
172 \param dir_buf The VMU's directory structure.
173 \return 0 on success, <0 on failure.
174*/
176 vmu_dir_t * dir_buf);
177
178/** \brief Given a selected VMU's root block, read its FAT.
179
180 This function reads the FAT of a VMU, given its root block. It assumes the
181 mutex is held. There must be at least the number of bytes returned by
182 vmufs_fat_blocks() available in the buffer for this to succeed.
183
184 \param dev The VMU to read from.
185 \param root The VMU's root block.
186 \param fat_buf The buffer to store the FAT into. You must
187 pre-allocate this.
188 \return 0 on success, <0 on failure.
189*/
190int vmufs_fat_read(maple_device_t * dev, vmu_root_t * root, uint16 * fat_buf);
191
192/** \brief Given a selected VMU's root block and its FAT, write the FAT blocks
193 back to the VMU.
194
195 This function assumes the mutex is held.
196
197 \param dev The VMU to write to.
198 \param root The VMU's root block.
199 \param fat_buf The buffer to write to the FAT.
200 \return 0 on success, <0 on failure.
201*/
202int vmufs_fat_write(maple_device_t * dev, vmu_root_t * root, uint16 * fat_buf);
203
204/** \brief Given a previously-read directory, locate a file by filename.
205
206 \param root The VMU root block.
207 \param dir The VMU directory.
208 \param fn The file to find (only checked up to 12 chars).
209 \return The index into the directory array on success, or
210 <0 on failure.
211*/
212int vmufs_dir_find(vmu_root_t * root, vmu_dir_t * dir, const char * fn);
213
214/** \brief Given a previously-read directory, add a new dirent to the dir.
215
216 Another file with the same name should not exist (delete it first if it
217 does). This function will not check for dupes!
218
219 \param root The VMU root block.
220 \param dir The VMU directory.
221 \param newdirent The new entry to add.
222 \return 0 on success, or <0 on failure. */
223int vmufs_dir_add(vmu_root_t * root, vmu_dir_t * dir, vmu_dir_t * newdirent);
224
225/** \brief Given a pointer to a directory struct and a previously loaded FAT,
226 load the indicated file from the VMU.
227
228 An appropriate amount of space must have been allocated previously in the
229 buffer. Assumes the mutex is held.
230
231 \param dev The VMU to read from.
232 \param fat The FAT of the VMU.
233 \param dirent The entry to read.
234 \param outbuf A buffer to write the data into. You must allocate
235 this yourself with the appropriate amount of space.
236 \return 0 on success, <0 on failure.
237*/
238int vmufs_file_read(maple_device_t * dev, uint16 * fat, vmu_dir_t * dirent, void * outbuf);
239
240/** \brief Given a pointer to a mostly-filled directory struct and a previously
241 loaded directory and FAT, write the indicated file to the VMU.
242
243 The named file should not exist in the directory already. The directory and
244 FAT will _not_ be sync'd back to the VMU, this must be done manually.
245 Assumes the mutex is held.
246
247 \param dev The VMU to write to.
248 \param root The VMU root block.
249 \param fat The FAT of the VMU.
250 \param dir The directory of the VMU.
251 \param newdirent The new entry to write.
252 \param filebuf The new file data.
253 \param size The size of the file in blocks (512-bytes each).
254 \return 0 on success, <0 on failure.
255*/
257 vmu_dir_t * dir, vmu_dir_t * newdirent, void * filebuf, int size);
258
259/** \brief Given a previously-read FAT and directory, delete the named file.
260
261 No changes are made to the VMU itself, just the in-memory structs.
262
263 \param root The VMU root block.
264 \param fat The FAT to be modified.
265 \param dir The directory to be modified.
266 \param fn The file name to be deleted.
267 \retval 0 On success.
268 \retval -1 If fn is not found.
269*/
270int vmufs_file_delete(vmu_root_t * root, uint16 * fat, vmu_dir_t * dir, const char *fn);
271
272/** \brief Given a previously-read FAT, return the number of blocks available
273 to write out new file data.
274
275 \param root The VMU root block.
276 \param fat The FAT to be examined.
277 \return The number of blocks available.
278*/
280
281/** \brief Given a previously-read directory, return the number of dirents
282 available for new files.
283
284 \param root The VMU root block.
285 \param dir The directory in question.
286 \return The number of entries available.
287*/
289
290/** \brief Lock the vmufs mutex.
291
292 This should be done before you attempt any low-level ops.
293
294 \retval 0 On success (no error conditions defined).
295*/
297
298/** \brief Unlock the vmufs mutex.
299
300 This should be done once you're done with any low-level ops.
301
302 \retval 0 On success (no error conditions defined).
303*/
305
306
307/* ****************** Higher level functions ******************** */
308
309/** \brief Read the directory from a VMU.
310
311 The output buffer will be allocated for you using malloc(), and the number
312 of entries will be returned. On failure, outbuf will not contain a dangling
313 buffer that needs to be freed (no further action required).
314
315 \param dev The VMU to read from.
316 \param outbuf A buffer that will be allocated where the directory
317 data will be placed.
318 \param outcnt The number of entries in outbuf.
319 \return 0 on success, or <0 on failure. */
320int vmufs_readdir(maple_device_t * dev, vmu_dir_t ** outbuf, int * outcnt);
321
322/** \brief Read a file from the VMU.
323
324 The output buffer will be allocated for you using malloc(), and the size of
325 the file will be returned. On failure, outbuf will not contain a dangling
326 buffer that needs to be freed (no further action required).
327
328 \param dev The VMU to read from.
329 \param fn The name of the file to read.
330 \param outbuf A buffer that will be allocated where the file data
331 will be placed.
332 \param outsize Storage for the size of the file, in bytes.
333 \return 0 on success, or <0 on failure.
334*/
335int vmufs_read(maple_device_t * dev, const char * fn, void ** outbuf, int * outsize);
336
337/** \brief Read a file from the VMU, using a pre-read dirent.
338
339 This function is faster to use than vmufs_read() if you already have done
340 the lookup, since it won't need to do that.
341
342 \param dev The VMU to read from.
343 \param dirent The entry to read.
344 \param outbuf A buffer that will be allocated where the file data
345 will be placed.
346 \param outsize Storage for the size of the file, in bytes.
347 \return 0 on success, <0 on failure.
348*/
349int vmufs_read_dirent(maple_device_t * dev, vmu_dir_t * dirent, void ** outbuf, int * outsize);
350
351/* Flags for vmufs_write */
352#define VMUFS_OVERWRITE 1 /**< \brief Overwrite existing files */
353#define VMUFS_VMUGAME 2 /**< \brief This file is a VMU game */
354#define VMUFS_NOCOPY 4 /**< \brief Set the no-copy flag */
355
356/** \brief Write a file to the VMU.
357
358 If the named file already exists, then the function checks 'flags'. If
359 VMUFS_OVERWRITE is set, then the old file is deleted first before the new
360 one is written (this all happens atomically). On partial failure, some data
361 blocks may have been written, but in general the card should not be damaged.
362
363 \param dev The VMU to write to.
364 \param fn The filename to write.
365 \param inbuf The data to write to the file.
366 \param insize The size of the file in bytes.
367 \param flags Flags for the write (i.e, VMUFS_OVERWRITE,
368 VMUFS_VMUGAME, VMUFS_NOCOPY).
369 \return 0 on success, or <0 for failure.
370*/
371int vmufs_write(maple_device_t * dev, const char * fn, void * inbuf, int insize, int flags);
372
373/** \brief Delete a file from the VMU.
374
375 \retval 0 On success.
376 \retval -1 If the file is not found.
377 \retval -2 On other failure.
378*/
379int vmufs_delete(maple_device_t * dev, const char * fn);
380
381/** \brief Return the number of user blocks free for file writing.
382
383 You should check this number before attempting to write.
384
385 \return The number of blocks free for writing.
386*/
388
389
390/** \brief Initialize vmufs.
391
392 Must be called before anything else is useful.
393
394 \retval 0 On success (no error conditions defined).
395*/
396int vmufs_init(void);
397
398/** \brief Shutdown vmufs.
399
400 Must be called after everything is finished.
401*/
403
404/** @} */
405
406__END_DECLS
407
408#endif /* __DC_VMUFS_H */
unsigned short uint16
16-bit unsigned integer
Definition types.h:34
unsigned char uint8
8-bit unsigned integer
Definition types.h:35
int vmufs_fat_write(maple_device_t *dev, vmu_root_t *root, uint16 *fat_buf)
Given a selected VMU's root block and its FAT, write the FAT blocks back to the VMU.
int vmufs_root_read(maple_device_t *dev, vmu_root_t *root_buf)
Reads a selected VMU's root block.
int vmufs_dir_blocks(vmu_root_t *root_buf)
Given a VMU's root block, return the amount of space in bytes required to hold its directory.
int vmufs_shutdown(void)
Shutdown vmufs.
int vmufs_dir_add(vmu_root_t *root, vmu_dir_t *dir, vmu_dir_t *newdirent)
Given a previously-read directory, add a new dirent to the dir.
int vmufs_dir_write(maple_device_t *dev, vmu_root_t *root, vmu_dir_t *dir_buf)
Given a selected VMU's root block and dir blocks, write the dirty dir blocks back to the VMU.
int vmufs_file_write(maple_device_t *dev, vmu_root_t *root, uint16 *fat, vmu_dir_t *dir, vmu_dir_t *newdirent, void *filebuf, int size)
Given a pointer to a mostly-filled directory struct and a previously loaded directory and FAT,...
int vmufs_fat_read(maple_device_t *dev, vmu_root_t *root, uint16 *fat_buf)
Given a selected VMU's root block, read its FAT.
int vmufs_mutex_lock(void)
Lock the vmufs mutex.
int vmufs_write(maple_device_t *dev, const char *fn, void *inbuf, int insize, int flags)
Write a file to the VMU.
int vmufs_delete(maple_device_t *dev, const char *fn)
Delete a file from the VMU.
int vmufs_readdir(maple_device_t *dev, vmu_dir_t **outbuf, int *outcnt)
Read the directory from a VMU.
int vmufs_free_blocks(maple_device_t *dev)
Return the number of user blocks free for file writing.
int vmufs_root_write(maple_device_t *dev, vmu_root_t *root_buf)
Writes a selected VMU's root block.
int vmufs_read_dirent(maple_device_t *dev, vmu_dir_t *dirent, void **outbuf, int *outsize)
Read a file from the VMU, using a pre-read dirent.
int vmufs_read(maple_device_t *dev, const char *fn, void **outbuf, int *outsize)
Read a file from the VMU.
int vmufs_file_delete(vmu_root_t *root, uint16 *fat, vmu_dir_t *dir, const char *fn)
Given a previously-read FAT and directory, delete the named file.
void vmufs_dir_fill_time(vmu_dir_t *d)
Fill in the date on a vmu_dir_t for writing.
int vmufs_dir_read(maple_device_t *dev, vmu_root_t *root_buf, vmu_dir_t *dir_buf)
Given a selected VMU's root block, read its directory.
int vmufs_init(void)
Initialize vmufs.
int vmufs_dir_free(vmu_root_t *root, vmu_dir_t *dir)
Given a previously-read directory, return the number of dirents available for new files.
int vmufs_file_read(maple_device_t *dev, uint16 *fat, vmu_dir_t *dirent, void *outbuf)
Given a pointer to a directory struct and a previously loaded FAT, load the indicated file from the V...
int vmufs_mutex_unlock(void)
Unlock the vmufs mutex.
int vmufs_fat_free(vmu_root_t *root, uint16 *fat)
Given a previously-read FAT, return the number of blocks available to write out new file data.
int vmufs_fat_blocks(vmu_root_t *root_buf)
Given a VMU's root block, return the amount of space in bytes required to hold its FAT.
int vmufs_dir_find(vmu_root_t *root, vmu_dir_t *dir, const char *fn)
Given a previously-read directory, locate a file by filename.
Maple Bus driver interface.
POSIX directory entry structure.
Definition dirent.h:62
One maple device.
Definition maple.h:270
VMU FS Directory entries, 32 bytes each.
Definition vmufs.h:78
uint8 dirty
See header notes.
Definition vmufs.h:86
uint16 filesize
Size of the file in blocks.
Definition vmufs.h:84
uint16 hdroff
Offset of header, in blocks from start of file.
Definition vmufs.h:85
uint8 copyprotect
0x00 = copyable; 0xff = copy protected
Definition vmufs.h:80
vmu_timestamp_t timestamp
File time.
Definition vmufs.h:83
uint16 firstblk
Location of the first block in the file.
Definition vmufs.h:81
uint8 filetype
0x00 = no file; 0x33 = data; 0xcc = a game
Definition vmufs.h:79
VMU FS Root block layout.
Definition vmufs.h:58
uint16 dir_size
Directory size in blocks.
Definition vmufs.h:69
uint16 fat_loc
FAT location.
Definition vmufs.h:66
uint8 use_custom
0 = standard, 1 = custom
Definition vmufs.h:60
uint16 dir_loc
Directory location.
Definition vmufs.h:68
uint16 fat_size
FAT size in blocks.
Definition vmufs.h:67
vmu_timestamp_t timestamp
BCD timestamp.
Definition vmufs.h:63
uint16 blk_cnt
Number of user blocks.
Definition vmufs.h:71
uint16 icon_shape
Icon shape for this VMS.
Definition vmufs.h:70
BCD timestamp, used several places in the vmufs.
Definition vmufs.h:44
uint8 dow
Day of week (0 = monday, etc)
Definition vmufs.h:52
uint8 sec
Seconds.
Definition vmufs.h:51
uint8 year
Year, within century.
Definition vmufs.h:46
uint8 month
Month of the year.
Definition vmufs.h:47
uint8 hour
Hour of the day.
Definition vmufs.h:49
uint8 cent
Century.
Definition vmufs.h:45
uint8 min
Minutes.
Definition vmufs.h:50
uint8 day
Day of the month.
Definition vmufs.h:48