PS2SDK
PS2 Homebrew Libraries
main.c
1 #include <stdio.h>
2 #include <ioman.h>
3 #include <iox_stat.h>
4 #include <loadcore.h>
5 #include <sysclib.h>
6 #include <errno.h>
7 
8 #include "cdfs_iop.h"
9 
10 // 16 sectors worth of toc entry
11 #define MAX_FILES_PER_FOLDER 256
12 #define MAX_FILES_OPENED 4
13 #define MAX_FOLDERS_OPENED 4
14 #define MAX_BYTES_READ 16384
15 
16 #define DRIVER_UNIT_NAME "cdfs"
17 #define DRIVER_MAJOR_VERSION 2
18 #define DRIVER_MINOR_VERSION 2
19 
20 #define STRINGIFY(x) #x
21 #define TOSTRING(x) STRINGIFY(x)
22 #define DRIVER_DESC DRIVER_UNIT_NAME " Filedriver v" TOSTRING(DRIVER_MAJOR_VERSION) "." TOSTRING(DRIVER_MINOR_VERSION)
23 
24 IRX_ID(MODNAME, DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION);
25 
26 struct fdtable
27 {
28  iop_file_t *fd;
29  int fileSize;
30  int LBA;
31  int filePos;
32 };
33 
34 struct fodtable
35 {
36  iop_file_t *fd;
37  int files;
38  int filesIndex;
39  struct TocEntry entries[MAX_FILES_PER_FOLDER];
40 };
41 
42 // File Descriptors
43 static struct fdtable fd_table[MAX_FILES_OPENED];
44 static int fd_used[MAX_FILES_OPENED];
45 
46 // Folder Descriptors
47 static struct fodtable fod_table[MAX_FOLDERS_OPENED];
48 static int fod_used[MAX_FOLDERS_OPENED];
49 
50 // global variables
51 static int lastsector = -1;
52 static int last_bk = 0;
53 
54 /***********************************************
55 * *
56 * DRIVER FUNCTIONS *
57 * *
58 ***********************************************/
59 
60 static int fio_init(iop_device_t *driver)
61 {
62  printf("%s\n", driver->desc);
63  printf("Re-edited by fjtrujy\n");
64  printf("Original implementation\n");
65  printf("by A.Lee (aka Hiryu) & Nicholas Van Veen (aka Sjeep)\n");
66  printf("CDFS: Initializing '%s' file driver.\n", driver->name);
67 
68  cdfs_start();
69  return 0;
70 }
71 
72 static int fio_deinit(iop_device_t *f)
73 {
74  (void)f;
75 
76  DPRINTF("CDFS: fio_deinit called.\n");
77  DPRINTF(" kernel_fd.. %p\n", f);
78  return cdfs_finish();
79 }
80 
81 static int fio_open(iop_file_t *f, const char *name, int mode)
82 {
83  int j;
84  static struct TocEntry tocEntry;
85 
86  DPRINTF("CDFS: fio_open called.\n");
87  DPRINTF(" kernel_fd.. %p\n", f);
88  DPRINTF(" name....... %s %x\n", name, (int)name);
89  DPRINTF(" mode....... %d\n\n", mode);
90 
91  // Invalidate last sector cache if disk changed
92  if (cdfs_checkDiskChanged(CHANGED_FIO)) {
93  lastsector = -1;
94  last_bk = 0;
95  }
96 
97  // check if the file exists
98  if (!cdfs_findfile(name, &tocEntry)) {
99  printf("***** FILE %s CAN NOT FOUND ******\n\n", name);
100  return -EPERM;
101  }
102 
103  if (mode != O_RDONLY) {
104  printf("mode is different than O_RDONLY, expected %i, received %i\n\n", O_RDONLY, mode);
105  return -ENOENT;
106  }
107 
108  DPRINTF("CDFS: fio_open TocEntry info\n");
109  DPRINTF(" TocEntry....... %p\n", &tocEntry);
110  DPRINTF(" fileLBA........ %i\n", tocEntry.fileLBA);
111  DPRINTF(" fileSize....... %i\n", tocEntry.fileSize);
112  DPRINTF(" fileProperties. %i\n", tocEntry.fileProperties);
113  DPRINTF(" dateStamp...... %s\n", tocEntry.dateStamp);
114  DPRINTF(" filename....... %s\n", tocEntry.filename);
115 
116  // set up a new file descriptor
117  for (j = 0; j < MAX_FILES_OPENED; j++) {
118  if (fd_used[j] == 0)
119  break;
120  }
121 
122  if (j >= MAX_FILES_OPENED) {
123  printf("File descriptor overflow!!\n\n");
124  return -ESRCH;
125  }
126 
127  fd_used[j] = 1;
128  fd_table[j].fd = f;
129  fd_table[j].fileSize = tocEntry.fileSize;
130  fd_table[j].LBA = tocEntry.fileLBA;
131  fd_table[j].filePos = 0;
132 
133  f->privdata = (void *)j;
134 
135  return j;
136 }
137 
138 static int fio_close(iop_file_t *f)
139 {
140  int i;
141 
142  DPRINTF("CDFS: fio_close called.\n");
143  DPRINTF(" kernel fd.. %p\n\n", f);
144 
145  i = (int)f->privdata;
146 
147  if (i >= MAX_FILES_OPENED) {
148  printf("fio_close: ERROR: File does not appear to be open!\n");
149  return -EPERM;
150  }
151 
152  fd_used[i] = 0;
153 
154  return 0;
155 }
156 
157 static int fio_read(iop_file_t *f, void *buffer, int size)
158 {
159  int i;
160 
161  int start_sector;
162  int off_sector;
163  int num_sectors;
164 
165  int read = 0;
166  static u8 local_buffer[9 * 2048];
167 
168  DPRINTF("CDFS: fio_read called\n\n");
169  DPRINTF(" kernel_fd... %p\n", f);
170  DPRINTF(" buffer...... 0x%X\n", (int)buffer);
171  DPRINTF(" size........ %d\n\n", size);
172 
173  i = (int)f->privdata;
174 
175  if (i >= MAX_FILES_OPENED) {
176  printf("fio_read: ERROR: File does not appear to be open!\n");
177  return -EPERM;
178  }
179 
180  // A few sanity checks
181  if (fd_table[i].filePos > fd_table[i].fileSize) {
182  // We cant start reading from past the beginning of the file
183  return 0; // File exists but we couldnt read anything from it
184  }
185 
186  if ((fd_table[i].filePos + size) > fd_table[i].fileSize)
187  size = fd_table[i].fileSize - fd_table[i].filePos;
188 
189  if (size <= 0)
190  return 0;
191 
192  if (size > MAX_BYTES_READ)
193  size = MAX_BYTES_READ;
194 
195  // Now work out where we want to start reading from
196  start_sector = fd_table[i].LBA + (fd_table[i].filePos >> 11);
197  off_sector = (fd_table[i].filePos & 0x7FF);
198 
199  num_sectors = (off_sector + size);
200  num_sectors = (num_sectors >> 11) + ((num_sectors & 2047) != 0);
201 
202  DPRINTF("fio_read: read sectors %d to %d\n", start_sector, start_sector + num_sectors);
203 
204  // Skip a Sector for equal (use the last sector in buffer)
205  if (start_sector == lastsector) {
206  read = 1;
207  if (last_bk > 0)
208  memcpy(local_buffer, local_buffer + 2048 * (last_bk), 2048);
209  last_bk = 0;
210  }
211 
212  lastsector = start_sector + num_sectors - 1;
213  // Read the data (we only ever get 16KB max request at once)
214 
215  if (read == 0 || (read == 1 && num_sectors > 1)) {
216  if (!cdfs_readSect(start_sector + read, num_sectors - read, local_buffer + ((read) << 11))) {
217  DPRINTF("Couldn't Read from file for some reason\n");
218  }
219 
220  last_bk = num_sectors - 1;
221  }
222 
223  memcpy(buffer, local_buffer + off_sector, size);
224  fd_table[i].filePos += size;
225 
226  return (size);
227 }
228 
229 static int fio_write(iop_file_t *f, void *buffer, int size)
230 {
231  (void)f;
232  (void)buffer;
233 
234  if (size == 0)
235  return 0;
236  else {
237  printf("CDFS: dummy fio_write function called, this is not a re-writer xD");
238  return -EPERM;
239  }
240 }
241 
242 static int fio_lseek(iop_file_t *f, int offset, int whence)
243 {
244  int i;
245 
246  DPRINTF("CDFS: fio_lseek called.\n");
247  DPRINTF(" kernel_fd... %p\n", f);
248  DPRINTF(" offset...... %d\n", offset);
249  DPRINTF(" whence...... %d\n\n", whence);
250 
251  i = (int) f->privdata;
252 
253  if (i >= 16) {
254  DPRINTF("fio_lseek: ERROR: File does not appear to be open!\n");
255  return -EPERM;
256  }
257 
258  switch (whence) {
259  case SEEK_SET:
260  fd_table[i].filePos = offset;
261  break;
262 
263  case SEEK_CUR:
264  fd_table[i].filePos += offset;
265  break;
266 
267  case SEEK_END:
268  fd_table[i].filePos = fd_table[i].fileSize + offset;
269  break;
270 
271  default:
272  return -1;
273  }
274 
275  if (fd_table[i].filePos < 0)
276  fd_table[i].filePos = 0;
277 
278  if (fd_table[i].filePos > fd_table[i].fileSize)
279  fd_table[i].filePos = fd_table[i].fileSize;
280 
281  return fd_table[i].filePos;
282 }
283 
284 static int fio_openDir(iop_file_t *f, const char *path) {
285  int j;
286 
287  DPRINTF("CDFS: fio_openDir called.\n");
288  DPRINTF(" kernel_fd.. %p\n", f);
289  DPRINTF(" name....... %s\n", f->device->name);
290  DPRINTF(" mode....... %d\n\n", f->mode);
291  DPRINTF(" path....... %s\n\n", path);
292 
293  // set up a new file descriptor
294  for (j = 0; j < MAX_FOLDERS_OPENED; j++) {
295  if (fod_used[j] == 0)
296  break;
297  }
298 
299  if (j >= MAX_FOLDERS_OPENED)
300  return -ESRCH;
301 
302  fod_table[j].files = cdfs_getDir(path, fod_table[j].entries, MAX_FILES_PER_FOLDER);
303  if (fod_table[j].files < 0) {
304  printf("The path doesn't exist\n\n");
305  return -ENOENT;
306  }
307 
308  fod_table[j].filesIndex = 0;
309  fod_table[j].fd = f;
310  fod_used[j] = 1;
311 
312  DPRINTF("ITEMS %i\n\n", fod_table[j].files);
313 #ifdef DEBUG
314  int index = 0;
315  for (index=0; index < fod_table[j].files; index++) {
316  struct TocEntry tocEntry = fod_table[j].entries[index];
317 
318  DPRINTF("CDFS: fio_openDir index=%d TocEntry info\n", index);
319  DPRINTF(" TocEntry....... %p\n", &tocEntry);
320  DPRINTF(" fileLBA........ %i\n", tocEntry.fileLBA);
321  DPRINTF(" fileSize....... %i\n", tocEntry.fileSize);
322  DPRINTF(" fileProperties. %i\n", tocEntry.fileProperties);
323  DPRINTF(" dateStamp....... %s\n", tocEntry.dateStamp);
324  DPRINTF(" filename....... %s\n", tocEntry.filename);
325  }
326 #endif
327 
328  f->privdata = (void *)j;
329 
330  return j;
331 }
332 
333 static int fio_closeDir(iop_file_t *fd)
334 {
335  int i;
336 
337  DPRINTF("CDFS: fio_closeDir called.\n");
338  DPRINTF(" kernel_fd.. %p\n", fd);
339 
340  i = (int)fd->privdata;
341 
342  if (i >= MAX_FOLDERS_OPENED) {
343  printf("fio_close: ERROR: File does not appear to be open!\n");
344  return -EPERM;
345  }
346 
347  fod_used[i] = 0;
348  return 0;
349 }
350 
351 static int fio_dread(iop_file_t *fd, io_dirent_t *dirent)
352 {
353  int i;
354  int filesIndex;
355  struct TocEntry entry;
356 
357  DPRINTF("CDFS: fio_dread called.\n");
358  DPRINTF(" kernel_fd.. %p\n", fd);
359  DPRINTF(" mode....... %p\n\n", dirent);
360 
361  i = (int)fd->privdata;
362 
363  if (i >= MAX_FOLDERS_OPENED) {
364  printf("fio_dread: ERROR: Folder does not appear to be open!\n\n");
365  return -EPERM;
366  }
367 
368  filesIndex = fod_table[i].filesIndex;
369  if (filesIndex >= fod_table[i].files) {
370  printf("fio_dread: No more items pending to read!\n\n");
371  return -EPERM;
372  }
373 
374  entry = fod_table[i].entries[filesIndex];
375 
376  DPRINTF("fio_dread: fod_table index=%i, fileIndex=%i\n\n", i, filesIndex);
377  DPRINTF("fio_dread: entries=%i\n\n", fod_table[i].files);
378  DPRINTF("fio_dread: reading entry\n\n");
379  DPRINTF(" entry.. %p\n", &entry);
380  DPRINTF(" filesize....... %i\n\n", entry.fileSize);
381  DPRINTF(" filename....... %s\n\n", entry.filename);
382  DPRINTF(" fileproperties.. %i\n\n", entry.fileProperties);
383 
384  dirent->stat.mode = (entry.fileProperties == CDFS_FILEPROPERTY_DIR) ? FIO_SO_IFDIR : FIO_SO_IFREG;
385  dirent->stat.attr = entry.fileProperties;
386  dirent->stat.size = entry.fileSize;
387  memcpy(dirent->stat.ctime, entry.dateStamp, sizeof(entry.dateStamp));
388  memcpy(dirent->stat.atime, entry.dateStamp, sizeof(entry.dateStamp));
389  memcpy(dirent->stat.mtime, entry.dateStamp, sizeof(entry.dateStamp));
390  strncpy(dirent->name, entry.filename, sizeof(dirent->name));
391 
392  fod_table[i].filesIndex++;
393  return fod_table[i].filesIndex;
394 }
395 
396 static int fio_getstat(iop_file_t *fd, const char *name, io_stat_t *stat)
397 {
398  struct TocEntry entry;
399  int ret = -EPERM;
400 
401  (void)fd;
402 
403  DPRINTF("CDFS: fio_getstat called.\n");
404  DPRINTF(" kernel_fd.. %p\n", fd);
405  DPRINTF(" name....... %s\n\n", name);
406 
407  ret = cdfs_findfile(name, &entry);
408 
409  DPRINTF(" entry.. %p\n", &entry);
410  DPRINTF(" filesize....... %i\n\n", entry.fileSize);
411  DPRINTF(" filename....... %s\n\n", entry.filename);
412  DPRINTF(" fileproperties.. %i\n\n", entry.fileProperties);
413 
414  stat->mode = (entry.fileProperties == CDFS_FILEPROPERTY_DIR) ? FIO_SO_IFDIR : FIO_SO_IFREG;
415  stat->attr = entry.fileProperties;
416  stat->size = entry.fileSize;
417  memcpy(stat->ctime, entry.dateStamp, sizeof(entry.dateStamp));
418  memcpy(stat->atime, entry.dateStamp, sizeof(entry.dateStamp));
419  memcpy(stat->mtime, entry.dateStamp, sizeof(entry.dateStamp));
420 
421  return ret;
422 }
423 
424 IOMAN_RETURN_VALUE_IMPL(EIO);
425 
426 static iop_device_ops_t fio_ops = {
427  &fio_init, // init
428  &fio_deinit, // deinit
429  IOMAN_RETURN_VALUE(EIO), // format
430  &fio_open, // open
431  &fio_close, // close
432  &fio_read, // read
433  &fio_write, // write
434  &fio_lseek, // lseek
435  IOMAN_RETURN_VALUE(EIO), // ioctl
436  IOMAN_RETURN_VALUE(EIO), // remove
437  IOMAN_RETURN_VALUE(EIO), // mkdir
438  IOMAN_RETURN_VALUE(EIO), // rmdir
439  &fio_openDir, // dopen
440  &fio_closeDir, // dclose
441  &fio_dread, // dread
442  &fio_getstat, // getstat
443  IOMAN_RETURN_VALUE(EIO), // chstat
444 };
445 
446 static iop_device_t fio_driver = {
447  DRIVER_UNIT_NAME,
448  IOP_DT_FS,
449  DRIVER_MAJOR_VERSION,
450  DRIVER_DESC,
451  &fio_ops,
452 };
453 
454 int _start(int argc, char *argv[])
455 {
456  (void)argc;
457  (void)argv;
458 
459  // Prepare cache and read mode
460  cdfs_prepare();
461 
462  DelDrv(fio_driver.name);
463  if(AddDrv(&fio_driver) != 0) { return MODULE_NO_RESIDENT_END; }
464 
465  return MODULE_RESIDENT_END;
466 }
FIO_SO_IFREG
#define FIO_SO_IFREG
Definition: iox_stat.h:126
fdtable
Definition: main.c:26
TocEntry
Definition: cdfs_iop.h:13
_iop_file::privdata
void * privdata
Definition: ioman.h:61
sysclib.h
EPERM
#define EPERM
Definition: errno.h:21
_start
int _start(int argc, char *argv[])
Definition: main.c:46
EIO
#define EIO
Definition: errno.h:29
loadcore.h
fodtable
Definition: main.c:34
ENOENT
#define ENOENT
Definition: errno.h:23
_iop_file::mode
int mode
Definition: ioman.h:55
_iop_file
Definition: ioman.h:53
stdio.h
io_stat_t
Definition: io_common.h:47
ioman.h
FIO_SO_IFDIR
#define FIO_SO_IFDIR
Definition: iox_stat.h:128
ESRCH
#define ESRCH
Definition: errno.h:25
_iop_device_ops
Definition: ioman.h:79
io_dirent_t
Definition: io_common.h:58
_iop_file::device
struct _iop_device * device
Definition: ioman.h:59
_iop_device
Definition: ioman.h:64
iox_stat.h
errno.h