Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

codyvdfs.c

/* ScummVM - Scumm Interpreter
 * Copyright (C) 2005-2006 The ScummVM project
 *
 * 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.
 *
 * $URL: https://svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-9-1/backends/ps2/iop/CoDyVDfs/iop/codyvdfs.c $
 * $Id: codyvdfs.c 22973 2006-06-07 06:51:45Z lavosspawn $
 *
 */

#include <types.h>
#include <defs.h>
#include <irx.h>
#include <sys/stat.h>

#include <stdio.h>
#include <sysclib.h>
#include <sysmem.h>
#include <thbase.h>
#include <iomanX.h>

#include <io_common.h>
#include <errno.h>

#include "fiofs.h"
#include "codyvdfs.h"
#include "../common/codyvdirx.h"

#define DBG_PRINTF printf

char cachedDir[256];
int cachedDirLba, cachedDirOfs, cachedDirSize;
static uint8 cacheBuf[2340];

int mediaType, fsRootLba, fsRootSize;

int verifyDriveReady(void) {
      int res;
      u32 trayStat;
      res = CdTrayReq(CdTrayCheck, &trayStat);
      if ((mediaType == DISC_UNKNOWN) || (res == 0) || (trayStat == 1)) {
            // media was exchanged
            if (checkDiscReady(100) == 0) // wait up to 1 second
                  return initDisc();
            else {
                  mediaType = DISC_UNKNOWN;
                  return -1; // drive still not ready
            }
      }
    if (mediaType == DISC_NONE)
            return -1;
      return 0;
}

int cacheEnterDir(ISODirectoryRecord *dir) {
      CdRMode rmode = { 16, 0, CdSect2048, 0 };
      char *cacheName;
      cachedDirLba = READ_ARRAY32(dir->lba);
      cachedDirSize = READ_ARRAY32(dir->size);
      cachedDirOfs = 0;
      cacheName = cachedDir + strlen(cachedDir);
      memcpy(cacheName, dir->name, dir->len_fi);
    cacheName[dir->len_fi] = '/';
      cacheName[dir->len_fi + 1] = '\0';  
      return cdReadSectors(cachedDirLba, 1, cacheBuf, &rmode);
}

int initRootCache(void) {
      CdRMode rmode = { 16, 0, CdSect2048, 0 };
      ISODirectoryRecord *root = (ISODirectoryRecord*)cacheBuf;

      if (cdReadSectors(fsRootLba, 1, cacheBuf, &rmode) == 0) {
            cachedDir[0] = '\0';
            fsRootSize = READ_ARRAY32(root->size);
            cachedDirLba = fsRootLba;
            cachedDirOfs = 0;
            cachedDirSize = fsRootSize;
            if (READ_ARRAY32(root->lba) == fsRootLba)
                  return 0;
      }
      DBG_PRINTF("Can't read root directory table in sector %d\n", fsRootLba);
      mediaType = DISC_NONE;
      return -1;
}

ISODirectoryRecord *findEntryInCache(const char *name, int nameLen) {
      int i;
      CdRMode rmode = { 16, 0, CdSect2048, 0 };
      ISODirectoryRecord *entry;
      for (i = 0; i < NUM_SECTORS(cachedDirSize); i++) {
            entry = (ISODirectoryRecord *)cacheBuf;
            if (i != cachedDirOfs) {
                  if (cdReadSectors(cachedDirLba + i, 1, cacheBuf, &rmode) < 0)
                        return NULL;
            cachedDirOfs = i;
            }

            while (entry->len_dr && ((uint8*)entry < cacheBuf + SECTOR_SIZE)) {
                  if ((entry->len_fi > 2) && (entry->name[entry->len_fi - 2] == ';') && (entry->name[entry->len_fi - 1] == '1')) {
                        if ((nameLen == entry->len_fi - 2) && (strnicmp(name, entry->name, entry->len_fi - 2) == 0))
                              return entry;
                  } else {
                        if ((nameLen == entry->len_fi) && (strnicmp(name, entry->name, entry->len_fi) == 0))
                              return entry;
                  }
                  entry = (ISODirectoryRecord *)( (uint8*)entry + entry->len_dr );
            }
      }
    return NULL;
}

ISODirectoryRecord *findPath(const char *path) {
      ISODirectoryRecord *pathPos;
      const char *tok;

      if (path[0] == '/')
            path++;

      if (strnicmp(cachedDir, path, strlen(cachedDir)) == 0)
            path += strlen(cachedDir); // requested path is somewhere in our cache
      else
            initRootCache(); // not cached, we start again at the cd root

      if (path[0] == '/')
            path++;

      if (!path[0]) { // open root dir
            if (cachedDirOfs)
                  initRootCache();
            return (ISODirectoryRecord *)cacheBuf;
      }
      
      do {
            tok = strchr(path, '/');
            if (tok)
                  pathPos = findEntryInCache(path, tok - path);
            else
                  pathPos = findEntryInCache(path, strlen(path));

            if (pathPos && tok && tok[1] && IS_DIR(pathPos))
                  if (cacheEnterDir(pathPos) < 0)
                        return NULL;

            path = tok + 1;
      } while (pathPos && tok && tok[1]);
      return pathPos;
}

int checkDiscReady(int retries) {
      if (retries == -1) {
            if (CdDiskReady(0) == 2) // block until drive ready, should always return 2
                  return 0;
      } else {
            do {
                  if (CdDiskReady(1) == 2)
                        return 0;
                  DelayThread(10 * 1000);
            } while (--retries >= 0);
      }
      return -1;
}


int initDisc(void) {
      int type, sector, discType;
      ISOPvd *pvd;
      CdRMode rmode = { 16, 0, CdSect2048, 0 };
      ISOPathTableRecord *rootRec;

      if (checkDiscReady(0) < 0) {
            printf("disc not ready\n");
            mediaType = DISC_UNKNOWN; // retry later
            return -1;
      }

      do {  // wait until drive detected disc type
            type = CdGetDiskType();
            if (DISC_NOT_READY(type))
                  DelayThread(10 * 1000);
      } while (DISC_NOT_READY(type));

      if (type == CdDiskIllegal) {
            printf("Illegal disc type\n");
            mediaType = DISC_NONE;
            return -1;
      }
      if (type == CdDiskNone) {
            printf("Tray empty\n");
            mediaType = DISC_NONE;
            return -1;
      }

      discType = DISC_DVD;
      switch (type) {
            case CdDiskCDPS1:
            case CdDiskCDDAPS1:
            case CdDiskCDPS2:
            case CdDiskCDDAPS2:
            case CdDiskCDDA:
                  discType = DISC_MODE2;
                  rmode.datapattern = CdSect2340;
            default:
                  break;
      }

      for (sector = 16; sector < 32; sector++) {
            printf("sec %d\n", sector);
            if (cdReadSectors(sector, 1, cacheBuf, &rmode) == 0) {
                  if (discType == DISC_DVD)
                        pvd = (ISOPvd *)cacheBuf;
                  else {
                        switch (cacheBuf[3]) {
                              case 1:
                                    discType = DISC_MODE1;
                                    printf("Disc: Mode1\n");
                                    pvd = (ISOPvd*)(cacheBuf + 4);
                                    break;
                              case 2:
                                    discType = DISC_MODE2;
                                    printf("Disc: Mode2\n");
                                    pvd = (ISOPvd*)(cacheBuf + 12);
                                    break;
                              default:
                                    DBG_PRINTF("Unknown Sector Type %02X\n", cacheBuf[3]);
                                    return -1;
                        }
                  }
                  rmode.datapattern = CdSect2048;
                  if ((pvd->type == 1) && (memcmp(pvd->identifier, "CD001", 5) == 0)) { // found ISO9660 PVD
                        DBG_PRINTF("Found ISO9660 PVD in sector %d\n", sector);

                        DBG_PRINTF("reading path table from sector %d\n", pvd->pathTablePos);
                        if (cdReadSectors(pvd->pathTablePos, 1, cacheBuf, &rmode) < 0) {
                              DBG_PRINTF("Can't read path table\n");
                              return -1;
                        }

                        rootRec = (ISOPathTableRecord *)cacheBuf;
                        if ((rootRec->len_di != 1) || (rootRec->name[0] != 0)) {
                              DBG_PRINTF("Root entry missing: %02X - %02X\n", rootRec->len_di, rootRec->name[0]);
                              return -1;
                        }

                        fsRootLba = READ_ARRAY32(rootRec->lba); // this points to the root record

                        mediaType = discType;
                        DBG_PRINTF("Root directory in sector %d\n", fsRootLba);
                return initRootCache();
                  }
            }
      }
      mediaType = DISC_NONE;
      // PVD not found
      return -1;
}

int cdReadSectors(int lba, int num, void *dest, CdRMode *rmode) {
      int err;
      if (CdRead(lba, num, dest, rmode) == 1) {
            CdSync(0);
            err = CdGetError();
            return (err > 0) ? -err : err;
      }
      return -0xFF;
}

int cd_dummy(void) {
      printf("cd_dummy called!\n");
      return -1;
}

int cd_init(iop_device_t *dev) {
      printf("FS init\n");
      memset(cachedDir, 0, 256);
      cachedDirLba = cachedDirOfs = 0;
      mediaType = DISC_UNKNOWN;
      return 0;
}

iop_device_ops_t FS_ops = {
    (void *) cd_init,
    (void *) cd_dummy,
    (void *) cd_dummy,
    (void *) cd_open,
    (void *) cd_close,
    (void *) cd_read,
    (void *) cd_dummy,
    (void *) cd_lseek,
    (void *) cd_dummy,
    (void *) cd_dummy,
    (void *) cd_dummy,
    (void *) cd_dummy,
    (void *) cd_dopen,
    (void *) cd_dclose,
    (void *) cd_dread,
    (void *) cd_dummy,
    (void *) cd_dummy,
};

#define FS_NAME "cdfs"
#define FS_DESC "CD-ROM"

iop_device_t fsdriver = {
    FS_NAME,
    IOP_DT_FS | IOP_DT_FSEXT,
    1,
    FS_DESC,
    &FS_ops
};

int _start(void) {
    printf("CoDyVDfs v0.01\n");

      CdInit(1);
    DelDrv(FS_NAME);
    AddDrv(&fsdriver);

      initRpc();
      initFio();
    return(0);
}

int strnicmp(const char *s1, const char *s2, int n) {
      if (n) {
            do {
                  if (tolower(*s1) != tolower(*s2))
                        return tolower(*s1) - tolower(*s2);
                  if (*s1++ == '\0')
                        break;
                  s2++;
            } while (--n);
      }
      return 0;
}


Generated by  Doxygen 1.6.0   Back to index