RetroArch/ps2/compat_files/fileXio_cdvd.c
Francisco Javier Trujillo Mata b1846ee449 [PS2] CDFS Improvements
2019-03-16 15:32:11 +01:00

200 lines
4.6 KiB
C

#include <stdio.h>
#include <tamtypes.h>
#include <kernel.h>
#include <string.h>
#include <time.h>
#include <sifrpc.h>
#include <sys/fcntl.h>
#include <cdvd_rpc.h>
#include <fileXio_cdvd.h>
#include <libcdvd-common.h>
#include "ps2_devices.h"
#include "ps2_descriptor.h"
/* I dont know why but this line is totally needed */
static SifRpcClientData_t clientInit __attribute__ ((aligned(64)));
static int comp_entries_by_filename(const void *elem1, const void *elem2)
{
return strcmp(((entries*)elem1)->filename, ((entries*)elem2)->filename);
}
static int ps2_cdDiscValid(void) //returns 1 if disc valid, else returns 0
{
int cdmode = sceCdGetDiskType();
switch (cdmode) {
case SCECdPSCD:
case SCECdPSCDDA:
case SCECdPS2CD:
case SCECdPS2CDDA:
case SCECdPS2DVD:
case SCECdCDDA:
case SCECdDVDV:
return 1;
case SCECdNODISC:
case SCECdDETCT:
case SCECdDETCTCD:
case SCECdDETCTDVDS:
case SCECdDETCTDVDD:
case SCECdUNKNOWN:
case SCECdIllegalMedia:
default:
return 0;
}
}
static u64 cd_Timer(void)
{
return (clock() / (CLOCKS_PER_SEC / 1000));
}
static void ps2_cdStop(void)
{
CDVD_Stop();
sceCdSync(0);
}
static int prepareCDVD(void)
{
u64 wait_start;
int cdmode = sceCdGetDiskType();
if (sceCdGetDiskType() <= SCECdUNKNOWN) {
wait_start = cd_Timer();
while ((cd_Timer() < wait_start + 500) && !ps2_cdDiscValid()) {
if (cdmode == SCECdNODISC)
return 0;
}
if (cdmode == SCECdNODISC)
return 0;
if ((cdmode < SCECdPSCD) || (cdmode > SCECdPS2DVD)) {
ps2_cdStop();
return 0;
}
}
return 1;
}
static int listcdvd(const char *path, entries *FileEntry)
{
static struct TocEntry TocEntryList[FILEENTRY_SIZE];
char dir[1025];
int i, n;
int t = 0;
int first_file_index;
strcpy(dir, &path[5]);
// Directories first...
CDVD_FlushCache();
n = CDVD_GetDir(dir, NULL, CDVD_GET_DIRS_ONLY, TocEntryList, FILEENTRY_SIZE, dir);
for (i = 0; i < n; i++) {
if (TocEntryList[i].fileProperties & 0x02 && (!strcmp(
TocEntryList[i].filename, ".") || !strcmp(
TocEntryList[i].filename, "..")))
continue; // Skip pseudopaths "." and ".."
FileEntry[t].dircheck = 1;
strcpy(FileEntry[t].filename, TocEntryList[i].filename);
t++;
if (t >= FILEENTRY_SIZE - 2) {
break;
}
}
qsort(FileEntry, t, sizeof(entries), comp_entries_by_filename);
first_file_index = t;
// Now files only
CDVD_FlushCache();
n = CDVD_GetDir(dir, NULL, CDVD_GET_FILES_ONLY, TocEntryList, FILEENTRY_SIZE, dir);
for (i = 0; i < n; i++) {
if (TocEntryList[i].fileProperties & 0x02 && (!strcmp(
TocEntryList[i].filename, ".") || !strcmp(
TocEntryList[i].filename, "..")))
continue; // Skip pseudopaths "." and ".."
FileEntry[t].dircheck = 0;
strcpy(FileEntry[t].filename, TocEntryList[i].filename);
t++;
if (t >= FILEENTRY_SIZE - 2) {
break;
}
}
qsort(FileEntry + first_file_index, t - first_file_index, sizeof(entries), comp_entries_by_filename);
return t;
}
static int fileXioCDDread(int fd, iox_dirent_t *dirent)
{
DescriptorTranslation *descriptor = __ps2_fd_grab(fd);
if (descriptor && descriptor->current_folder_position < descriptor->items) {
strcpy(dirent->name, descriptor->FileEntry[descriptor->current_folder_position].filename);
if (descriptor->FileEntry[descriptor->current_folder_position].dircheck) {
dirent->stat.mode = FIO_S_IFDIR;
} else {
dirent->stat.mode = FIO_S_IFREG;
}
descriptor->current_folder_position++;
} else {
descriptor->current_folder_position = 0;
return 0;
}
return 1;
}
static int fileXioCDDopen(const char *name)
{
int fd = -1;
if (prepareCDVD()){
fd = __ps2_acquire_descriptor();
DescriptorTranslation *descriptor = __ps2_fd_grab(fd);
descriptor->current_folder_position = 0;
descriptor->items = listcdvd(name, descriptor->FileEntry);
}
return fd;
}
int ps2fileXioDopen(const char *name)
{
enum BootDeviceIDs deviceID = getBootDeviceID((char *)name);
int fd = -1;
if (deviceID == BOOT_DEVICE_CDFS) {
fd = fileXioCDDopen(name);
} else {
fd = fileXioDopen(name);
}
return fd;
}
int ps2fileXioDread(int fd, iox_dirent_t *dirent)
{
if (is_fd_valid(fd)) {
return fileXioCDDread(fd, dirent);
} else {
return fileXioDread(fd, dirent);
}
}
int ps2fileXioDclose(int fd)
{
if (is_fd_valid(fd)) {
return __ps2_release_descriptor(fd);
} else {
return fileXioDclose(fd);
}
}