mirror of https://github.com/PCSX2/pcsx2.git
854 lines
23 KiB
C
854 lines
23 KiB
C
/* Pcsx2 - Pc Ps2 Emulator
|
|
* Copyright (C) 2002-2008 Pcsx2 Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
/*
|
|
* Original code from libcdvd by Hiryu & Sjeep (C) 2002
|
|
* Modified by Florin for PCSX2 emu
|
|
* Fixed CdRead by linuzappz
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "CDVDiso.h"
|
|
#include "CDVDisodrv.h"
|
|
|
|
struct dir_toc_data{
|
|
unsigned int start_LBA;
|
|
unsigned int num_sectors;
|
|
unsigned int num_entries;
|
|
unsigned int current_entry;
|
|
unsigned int current_sector;
|
|
unsigned int current_sector_offset;
|
|
unsigned int inc_dirs;
|
|
unsigned char extension_list[128+1];
|
|
};
|
|
|
|
//static u8 cdVolDescriptor[2048];
|
|
static struct dir_toc_data getDirTocData;
|
|
static struct cdVolDesc CDVolDesc;
|
|
|
|
void _splitpath2(const char *constpath, char *dir, char *fname){
|
|
// 255 char max path-length is an ISO9660 restriction
|
|
// we must change this for Joliet or relaxed iso restriction support
|
|
static char pathcopy[1024+1];
|
|
|
|
char* slash;
|
|
|
|
strncpy(pathcopy, constpath, 1024);
|
|
|
|
slash = strrchr (pathcopy, '/');
|
|
|
|
// if the path doesn't contain a '/' then look for a '\'
|
|
if (!slash)
|
|
slash = strrchr (pathcopy, (int)'\\');
|
|
|
|
// if a slash was found
|
|
if (slash != NULL)
|
|
{
|
|
// null terminate the path
|
|
slash[0] = 0;
|
|
// and copy the path into 'dir'
|
|
strncpy(dir, pathcopy, 1024);
|
|
dir[255]=0;
|
|
|
|
// copy the filename into 'fname'
|
|
strncpy(fname, slash+1, 128);
|
|
fname[128]=0;
|
|
}
|
|
else
|
|
{
|
|
dir[0] = 0;
|
|
|
|
strncpy(fname, pathcopy, 128);
|
|
fname[128]=0;
|
|
}
|
|
|
|
}
|
|
|
|
// Used in findfile
|
|
int tolower(int c);
|
|
int strcasecmp(const char *s1, const char *s2){
|
|
while (*s1 != '\0' && tolower(*s1) == tolower(*s2))
|
|
{
|
|
s1++;
|
|
s2++;
|
|
}
|
|
|
|
return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
|
|
}
|
|
|
|
// Copy a TOC Entry from the CD native format to our tidier format
|
|
void TocEntryCopy(struct TocEntry* tocEntry, struct dirTocEntry* internalTocEntry){
|
|
int i;
|
|
int filenamelen;
|
|
|
|
tocEntry->fileSize = internalTocEntry->fileSize;
|
|
tocEntry->fileLBA = internalTocEntry->fileLBA;
|
|
tocEntry->fileProperties = internalTocEntry->fileProperties;
|
|
memcpy(tocEntry->date, internalTocEntry->dateStamp, 7);
|
|
|
|
if (CDVolDesc.filesystemType == 2){
|
|
// This is a Joliet Filesystem, so use Unicode to ISO string copy
|
|
|
|
filenamelen = internalTocEntry->filenameLength/2;
|
|
|
|
if (!(tocEntry->fileProperties & 0x02)){
|
|
// strip the ;1 from the filename
|
|
// filenamelen -= 2;//(Florin) nah, do not strip ;1
|
|
}
|
|
|
|
for (i=0; i < filenamelen; i++)
|
|
tocEntry->filename[i] = internalTocEntry->filename[(i<<1)+1];
|
|
|
|
tocEntry->filename[filenamelen] = 0;
|
|
}
|
|
else{
|
|
filenamelen = internalTocEntry->filenameLength;
|
|
|
|
if (!(tocEntry->fileProperties & 0x02)){
|
|
// strip the ;1 from the filename
|
|
// filenamelen -= 2;//(Florin) nah, do not strip ;1
|
|
}
|
|
|
|
// use normal string copy
|
|
strncpy(tocEntry->filename,internalTocEntry->filename,128);
|
|
tocEntry->filename[filenamelen] = 0;
|
|
}
|
|
}
|
|
|
|
// Check if a TOC Entry matches our extension list
|
|
int TocEntryCompare(char* filename, char* extensions){
|
|
static char ext_list[129];
|
|
|
|
char* token;
|
|
|
|
char* ext_point;
|
|
|
|
strncpy(ext_list,extensions,128);
|
|
ext_list[128]=0;
|
|
|
|
token = strtok( ext_list, " ," );
|
|
while( token != NULL )
|
|
{
|
|
// if 'token' matches extension of 'filename'
|
|
// then return a match
|
|
ext_point = strrchr(filename,'.');
|
|
|
|
if (strnicmp(ext_point, token, strlen(token)) == 0)
|
|
return (TRUE);
|
|
|
|
/* Get next token: */
|
|
token = strtok( NULL, " ," );
|
|
}
|
|
|
|
// If not match found then return FALSE
|
|
return (FALSE);
|
|
|
|
}
|
|
|
|
#define CD_SECS 60 /* seconds per minute */
|
|
#define CD_FRAMES 75 /* frames per second */
|
|
#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */
|
|
|
|
int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){
|
|
u32 i;
|
|
u8* buff;
|
|
int rmode;
|
|
|
|
switch (mode->datapattern) {
|
|
case CdSecS2048:
|
|
rmode = CDVD_MODE_2048; break;
|
|
case CdSecS2328:
|
|
rmode = CDVD_MODE_2328; break;
|
|
case CdSecS2340:
|
|
rmode = CDVD_MODE_2340; break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
for (i=0; i<sectors; i++){
|
|
if (CDVDreadTrack(lsn+i, rmode)==-1)
|
|
return 0;
|
|
buff = CDVDgetBuffer();
|
|
if (buff==NULL) return 0;
|
|
FreezeMMXRegs(1);
|
|
switch (mode->datapattern){
|
|
case CdSecS2048:
|
|
memcpy_fast((void*)((uptr)buf+2048*i), buff, 2048);break;//only data
|
|
case CdSecS2328:
|
|
memcpy_fast((void*)((uptr)buf+2328*i), buff, 2328);break;//without sync & head & sub
|
|
case CdSecS2340:
|
|
memcpy_fast((void*)((uptr)buf+2340*i), buff, 2340);break;//without sync
|
|
}
|
|
FreezeMMXRegs(0);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){
|
|
u32 i;
|
|
u8* buff;
|
|
|
|
for (i=lsn; i<(lsn+sectors); i++){
|
|
if (CDVDreadTrack(i, CDVD_MODE_2048)==-1)
|
|
return 0;
|
|
buff = CDVDgetBuffer();
|
|
if (buff==NULL) return 0;
|
|
|
|
// switch (mode->datapattern){
|
|
// case CdSecS2064:
|
|
((u32*)buf)[0] = i + 0x30000;
|
|
FreezeMMXRegs(1);
|
|
memcpy_fast((u8*)buf+12, buff, 2048);
|
|
FreezeMMXRegs(0);
|
|
buf = (char*)buf + 2064; break;
|
|
// default:
|
|
// return 0;
|
|
// }
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**************************************************************
|
|
* The functions below are not exported for normal file-system *
|
|
* operations, but are used by the file-system operations, and *
|
|
* may also be exported for use via RPC *
|
|
**************************************************************/
|
|
|
|
int CDVD_GetVolumeDescriptor(void){
|
|
// Read until we find the last valid Volume Descriptor
|
|
int volDescSector;
|
|
|
|
static struct cdVolDesc localVolDesc;
|
|
|
|
#ifdef DEBUG
|
|
SysPrintf("CDVD_GetVolumeDescriptor called\n");
|
|
#endif
|
|
|
|
for (volDescSector = 16; volDescSector<20; volDescSector++)
|
|
{
|
|
CdRead(volDescSector,1,&localVolDesc,&cdReadMode);
|
|
// CdSync(0x00);
|
|
|
|
// If this is still a volume Descriptor
|
|
if (strncmp(localVolDesc.volID, "CD001", 5) == 0)
|
|
{
|
|
if ((localVolDesc.filesystemType == 1) ||
|
|
(localVolDesc.filesystemType == 2))
|
|
{
|
|
FreezeMMXRegs(1);
|
|
memcpy_fast(&CDVolDesc, &localVolDesc, sizeof(struct cdVolDesc));
|
|
FreezeMMXRegs(0);
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (CDVolDesc.filesystemType == 1)
|
|
SysPrintf("CD FileSystem is ISO9660\n");
|
|
else if (CDVolDesc.filesystemType == 2)
|
|
SysPrintf("CD FileSystem is Joliet\n");
|
|
else SysPrintf("Could not detect CD FileSystem type\n");
|
|
#endif
|
|
// CdStop();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int CDVD_findfile(char* fname, struct TocEntry* tocEntry){
|
|
static char filename[128+1];
|
|
static char pathname[1024+1];
|
|
static char toc[2048];
|
|
char* dirname;
|
|
|
|
|
|
static struct TocEntry localTocEntry; // used for internal checking only
|
|
|
|
int found_dir;
|
|
|
|
int num_dir_sectors;
|
|
int current_sector;
|
|
|
|
int dir_lba;
|
|
|
|
struct dirTocEntry* tocEntryPointer;
|
|
|
|
#ifdef DEBUG
|
|
SysPrintf("CDVD_findfile called\n");
|
|
#endif
|
|
|
|
//make sure we have good cdReadMode
|
|
cdReadMode.trycount = 0;
|
|
cdReadMode.spindlctrl = CdSpinStm;
|
|
cdReadMode.datapattern = CdSecS2048;
|
|
|
|
_splitpath2(fname, pathname, filename);
|
|
|
|
// Find the TOC for a specific directory
|
|
if (CDVD_GetVolumeDescriptor() != TRUE){
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("Could not get CD Volume Descriptor\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
// Read the TOC of the root directory
|
|
if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("Couldn't Read from CD !\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
//CdSync(0x00);
|
|
|
|
// point the tocEntryPointer at the first real toc entry
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
|
|
num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix
|
|
current_sector = tocEntryPointer->fileLBA;
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
|
|
|
|
localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA;
|
|
// while (there are more dir names in the path)
|
|
dirname = strtok( pathname, "\\/" );
|
|
|
|
while( dirname != NULL )
|
|
{
|
|
found_dir = FALSE;
|
|
/*
|
|
while(tocEntryPointer->length > 0)
|
|
{
|
|
// while there are still more directory entries then search through
|
|
// for the one we want
|
|
|
|
if (tocEntryPointer->fileProperties & 0x02)
|
|
{
|
|
// Copy the CD format TOC Entry to our format
|
|
TocEntryCopy(&localTocEntry, tocEntryPointer);
|
|
|
|
// If this TOC Entry is a directory,
|
|
// then see if it has the right name
|
|
if (strcasecmp(dirname,localTocEntry.filename) == 0)
|
|
{
|
|
// if the name matches then we've found the directory
|
|
found_dir = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// point to the next entry
|
|
(char*)tocEntryPointer += tocEntryPointer->length;
|
|
}
|
|
*/
|
|
while(1)
|
|
{
|
|
if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048))
|
|
{
|
|
num_dir_sectors--;
|
|
|
|
if (num_dir_sectors > 0)
|
|
{
|
|
// If we've run out of entries, but arent on the last sector
|
|
// then load another sector
|
|
|
|
current_sector++;
|
|
if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE)
|
|
{
|
|
SysPrintf("Couldn't Read from CD !\n");
|
|
return -1;
|
|
}
|
|
// CdSync(0x00);
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
}
|
|
else
|
|
{
|
|
// Couldnt find the directory, and got to end of directory
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
if (tocEntryPointer->fileProperties & 0x02)
|
|
{
|
|
TocEntryCopy(&localTocEntry, tocEntryPointer);
|
|
|
|
// If this TOC Entry is a directory,
|
|
// then see if it has the right name
|
|
if (strcmp(dirname,localTocEntry.filename) == 0)
|
|
{
|
|
// if the name matches then we've found the directory
|
|
found_dir = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// point to the next entry
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
}
|
|
|
|
// If we havent found the directory name we wanted then fail
|
|
if (found_dir != TRUE)
|
|
{
|
|
SysPrintf("CDVD_findfile: could not find dir\n");
|
|
return -1;
|
|
}
|
|
|
|
// Get next directory name
|
|
dirname = strtok( NULL, "\\/" );
|
|
|
|
// Read the TOC of the found subdirectory
|
|
if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE)
|
|
{
|
|
SysPrintf("Couldn't Read from CD !\n");
|
|
return -1;
|
|
}
|
|
// CdSync(0x00);
|
|
|
|
num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; //round up fix
|
|
current_sector = localTocEntry.fileLBA;
|
|
|
|
// and point the tocEntryPointer at the first real toc entry
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
SysPrintf("CDVD_findfile: found dir, now looking for file\n");
|
|
#endif
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
|
|
num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix
|
|
dir_lba = tocEntryPointer->fileLBA;
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
|
|
while (num_dir_sectors > 0)
|
|
{
|
|
while(tocEntryPointer->length != 0)
|
|
{
|
|
// Copy the CD format TOC Entry to our format
|
|
TocEntryCopy(&localTocEntry, tocEntryPointer);
|
|
|
|
if ((strnicmp(localTocEntry.filename, filename, strlen(filename)) == 0) ||
|
|
((filename[strlen(filename)-2] == ';') &&
|
|
(localTocEntry.filename[strlen(localTocEntry.filename)-2] == ';') &&
|
|
(strnicmp(localTocEntry.filename, filename, strlen(filename)-2) == 0)))
|
|
{
|
|
// if the filename matches then copy the toc Entry
|
|
tocEntry->fileLBA = localTocEntry.fileLBA;
|
|
tocEntry->fileProperties = localTocEntry.fileProperties;
|
|
tocEntry->fileSize = localTocEntry.fileSize;
|
|
|
|
strcpy(tocEntry->filename, localTocEntry.filename);
|
|
memcpy(tocEntry->date, localTocEntry.date, 7);
|
|
|
|
#ifdef DEBUG
|
|
SysPrintf("CDVD_findfile: found file\n");
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
}
|
|
|
|
num_dir_sectors--;
|
|
|
|
if (num_dir_sectors > 0)
|
|
{
|
|
dir_lba++;
|
|
|
|
if (CdRead(dir_lba,1,toc,&cdReadMode) != TRUE){
|
|
SysPrintf("Couldn't Read from CD !\n");
|
|
return -1;
|
|
}
|
|
// CdSync(0x00);
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
SysPrintf("CDVD_findfile: could not find file\n");
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// This is the RPC-ready function which takes the request to start the tocEntry retrieval
|
|
int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs){
|
|
// int dir_depth = 1;
|
|
static char toc[2048];
|
|
char* dirname;
|
|
int found_dir;
|
|
int num_dir_sectors;
|
|
unsigned int toc_entry_num;
|
|
struct dirTocEntry* tocEntryPointer;
|
|
static struct TocEntry localTocEntry;
|
|
int current_sector;
|
|
|
|
// store the extension list statically for the retrieve function
|
|
strncpy(getDirTocData.extension_list, extensions, 128);
|
|
getDirTocData.extension_list[128]=0;
|
|
|
|
getDirTocData.inc_dirs = inc_dirs;
|
|
|
|
// Find the TOC for a specific directory
|
|
if (CDVD_GetVolumeDescriptor() != TRUE){
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("[RPC:cdvd] Could not get CD Volume Descriptor\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("[RPC:cdvd] Getting Directory Listing for: \"%s\"\n", pathname);
|
|
#endif
|
|
|
|
// Read the TOC of the root directory
|
|
if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("[RPC: ] Couldn't Read from CD !\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
//CdSync(0x00);
|
|
|
|
// point the tocEntryPointer at the first real toc entry
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
|
|
num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11;
|
|
current_sector = tocEntryPointer->fileLBA;
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
|
|
// use strtok to get the next dir name
|
|
|
|
// if there isnt one, then assume we want the LBA
|
|
// for the current one, and exit the while loop
|
|
|
|
// if there is another dir name then increment dir_depth
|
|
// and look through dir table entries until we find the right name
|
|
// if we dont find the right name
|
|
// before finding an entry at a higher level (lower num), then return nothing
|
|
|
|
localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA;
|
|
|
|
// while (there are more dir names in the path)
|
|
dirname = strtok( pathname, "\\/" );
|
|
while( dirname != NULL ){
|
|
found_dir = FALSE;
|
|
|
|
while(1){
|
|
if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) {
|
|
num_dir_sectors--;
|
|
|
|
if (num_dir_sectors > 0){
|
|
// If we've run out of entries, but arent on the last sector
|
|
// then load another sector
|
|
|
|
current_sector++;
|
|
if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE){
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("[RPC: ] Couldn't Read from CD !\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
//CdSync(0x00);
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
}
|
|
else{
|
|
// Couldnt find the directory, and got to end of directory
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (tocEntryPointer->fileProperties & 0x02){
|
|
TocEntryCopy(&localTocEntry, tocEntryPointer);
|
|
|
|
// If this TOC Entry is a directory,
|
|
// then see if it has the right name
|
|
if (strcmp(dirname,localTocEntry.filename) == 0){
|
|
// if the name matches then we've found the directory
|
|
found_dir = TRUE;
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("[RPC: ] Found directory %s in subdir at sector %d\n",dirname,current_sector);
|
|
RPC_LOG("[RPC: ] LBA of found subdirectory = %d\n",localTocEntry.fileLBA);
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
|
|
// point to the next entry
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
}
|
|
|
|
// If we havent found the directory name we wanted then fail
|
|
if (found_dir != TRUE)
|
|
return -1;
|
|
|
|
// Get next directory name
|
|
dirname = strtok( NULL, "\\/" );
|
|
|
|
// Read the TOC of the found subdirectory
|
|
if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE){
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("[RPC: ] Couldn't Read from CD !\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
//CdSync(0x00);
|
|
|
|
num_dir_sectors = (localTocEntry.fileSize+2047) >> 11;
|
|
current_sector = localTocEntry.fileLBA;
|
|
|
|
// and point the tocEntryPointer at the first real toc entry
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
}
|
|
|
|
// We know how much data we need to read in from the DirTocHeader
|
|
// but we need to read in at least 1 sector before we can get this value
|
|
|
|
// Now we need to COUNT the number of entries (dont do anything with info at this point)
|
|
// so set the tocEntryPointer to point to the first actual file entry
|
|
|
|
// This is a bit of a waste of reads since we're not actually copying the data out yet,
|
|
// but we dont know how big this TOC might be, so we cant allocate a specific size
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
|
|
// Need to STORE the start LBA and number of Sectors, for use by the retrieve func.
|
|
getDirTocData.start_LBA = localTocEntry.fileLBA;
|
|
getDirTocData.num_sectors = (tocEntryPointer->fileSize+2047) >> 11;
|
|
getDirTocData.num_entries = 0;
|
|
getDirTocData.current_entry = 0;
|
|
getDirTocData.current_sector = getDirTocData.start_LBA;
|
|
getDirTocData.current_sector_offset = 0;
|
|
|
|
num_dir_sectors = getDirTocData.num_sectors;
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
|
|
toc_entry_num=0;
|
|
|
|
while(1){
|
|
if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)){
|
|
// decrease the number of dirs remaining
|
|
num_dir_sectors--;
|
|
|
|
if (num_dir_sectors > 0){
|
|
// If we've run out of entries, but arent on the last sector
|
|
// then load another sector
|
|
getDirTocData.current_sector++;
|
|
|
|
if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("[RPC: ] Couldn't Read from CD !\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
//CdSync(0x00);
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
|
|
// continue;
|
|
}
|
|
else{
|
|
getDirTocData.num_entries = toc_entry_num;
|
|
getDirTocData.current_sector = getDirTocData.start_LBA;
|
|
return (toc_entry_num);
|
|
}
|
|
}
|
|
|
|
// We've found a file/dir in this directory
|
|
// now check if it matches our extension list (if there is one)
|
|
TocEntryCopy(&localTocEntry, tocEntryPointer);
|
|
|
|
if (localTocEntry.fileProperties & 0x02){
|
|
// If this is a subdir, then check if we want to include subdirs
|
|
if (getDirTocData.inc_dirs){
|
|
toc_entry_num++;
|
|
}
|
|
}
|
|
else{
|
|
if (strlen(getDirTocData.extension_list) > 0){
|
|
if (TocEntryCompare(localTocEntry.filename, getDirTocData.extension_list) == TRUE){
|
|
// increment the number of matching entries counter
|
|
toc_entry_num++;
|
|
}
|
|
}
|
|
else{
|
|
toc_entry_num++;
|
|
}
|
|
}
|
|
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
}
|
|
|
|
|
|
// THIS SHOULD BE UNREACHABLE -
|
|
// since we are trying to count ALL matching entries, rather than upto a limit
|
|
|
|
|
|
// STORE total number of TOC entries
|
|
getDirTocData.num_entries = toc_entry_num;
|
|
getDirTocData.current_sector = getDirTocData.start_LBA;
|
|
|
|
|
|
// we've reached the toc entry limit, so return how many we've done
|
|
return (toc_entry_num);
|
|
|
|
}
|
|
|
|
// This function can be called repeatedly after CDVD_GetDir_RPC_request to get the actual entries
|
|
// buffer (tocEntry) must be 18KB in size, and this will be filled with a maximum of 128 entries in one go
|
|
int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries){
|
|
static char toc[2048];
|
|
int toc_entry_num;
|
|
|
|
struct dirTocEntry* tocEntryPointer;
|
|
|
|
if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
//CdSync(0x00);
|
|
|
|
if (getDirTocData.current_entry == 0){
|
|
// if this is the first read then make sure we point to the first real entry
|
|
tocEntryPointer = (struct dirTocEntry*)toc;
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
|
|
|
|
|
getDirTocData.current_sector_offset = (char*)tocEntryPointer - toc;
|
|
}
|
|
else{
|
|
tocEntryPointer = (struct dirTocEntry*)(toc + getDirTocData.current_sector_offset);
|
|
}
|
|
|
|
if (req_entries > 128)
|
|
req_entries = 128;
|
|
|
|
for (toc_entry_num=0; toc_entry_num < req_entries;){
|
|
if ((tocEntryPointer->length == 0) || (getDirTocData.current_sector_offset >= 2048)){
|
|
// decrease the number of dirs remaining
|
|
getDirTocData.num_sectors--;
|
|
|
|
if (getDirTocData.num_sectors > 0){
|
|
// If we've run out of entries, but arent on the last sector
|
|
// then load another sector
|
|
getDirTocData.current_sector++;
|
|
|
|
if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){
|
|
#ifdef RPC_LOG
|
|
RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
//CdSync(0x00);
|
|
|
|
getDirTocData.current_sector_offset = 0;
|
|
tocEntryPointer = (struct dirTocEntry*)(toc + getDirTocData.current_sector_offset);
|
|
|
|
// continue;
|
|
}
|
|
else{
|
|
return (toc_entry_num);
|
|
}
|
|
}
|
|
|
|
// This must be incremented even if the filename doesnt match extension list
|
|
getDirTocData.current_entry++;
|
|
|
|
// We've found a file in this directory
|
|
// now check if it matches our extension list (if there is one)
|
|
|
|
// Copy the entry regardless, as it makes the comparison easier
|
|
// if it doesn't match then it will just be overwritten
|
|
TocEntryCopy(&tocEntry[toc_entry_num], tocEntryPointer);
|
|
|
|
if (tocEntry[toc_entry_num].fileProperties & 0x02){
|
|
// If this is a subdir, then check if we want to include subdirs
|
|
if (getDirTocData.inc_dirs) {
|
|
toc_entry_num++;
|
|
}
|
|
|
|
getDirTocData.current_sector_offset += tocEntryPointer->length;
|
|
tocEntryPointer = (struct dirTocEntry*)(toc + getDirTocData.current_sector_offset);
|
|
}
|
|
else{
|
|
if (strlen(getDirTocData.extension_list) > 0){
|
|
if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE){
|
|
// increment the number of matching entries counter
|
|
toc_entry_num++;
|
|
}
|
|
|
|
getDirTocData.current_sector_offset += tocEntryPointer->length;
|
|
tocEntryPointer = (struct dirTocEntry*)(toc + getDirTocData.current_sector_offset);
|
|
|
|
}
|
|
else{
|
|
toc_entry_num++;
|
|
getDirTocData.current_sector_offset += tocEntryPointer->length;
|
|
tocEntryPointer = (struct dirTocEntry*)(toc + getDirTocData.current_sector_offset);
|
|
}
|
|
}
|
|
/*
|
|
if (strlen(getDirTocData.extension_list) > 0)
|
|
{
|
|
if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE)
|
|
{
|
|
|
|
// increment this here, rather than in the main for loop
|
|
// since this should count the number of matching entries
|
|
toc_entry_num++;
|
|
}
|
|
|
|
getDirTocData.current_sector_offset += tocEntryPointer->length;
|
|
(char*)tocEntryPointer = toc + getDirTocData.current_sector_offset;
|
|
}
|
|
else
|
|
{
|
|
toc_entry_num++;
|
|
getDirTocData.current_sector_offset += tocEntryPointer->length;
|
|
(char*)tocEntryPointer = toc + getDirTocData.current_sector_offset;
|
|
}
|
|
*/
|
|
}
|
|
return (toc_entry_num);
|
|
}
|