scummvm/backends/platform/ps2/irxboot.cpp
2008-07-17 15:56:24 +00:00

219 lines
6.9 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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$
* $Id$
*
*/
#include <kernel.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sifrpc.h>
#include <loadfile.h>
#include <malloc.h>
#include "backends/platform/ps2/irxboot.h"
#include "backends/platform/ps2/ps2debug.h"
static const char hddArg[] = "-o" "\0" "8" "\0" "-n" "\0" "20";
static const char pfsArg[] = "-m" "\0" "2" "\0" "-o" "\0" "32" "\0" "-n" "\0" "72"; // "\0" "-debug";
IrxFile irxFiles[] = {
{ "SIO2MAN", BIOS, NOTHING, NULL, 0 },
{ "MCMAN", BIOS, NOTHING, NULL, 0 },
{ "MCSERV", BIOS, NOTHING, NULL, 0 },
{ "PADMAN", BIOS, NOTHING, NULL, 0 },
{ "LIBSD", BIOS, NOTHING, NULL, 0 },
{ "IOMANX.IRX", SYSTEM /*| NOT_HOST*/, NOTHING, NULL, 0 }, // already loaded by ps2link
{ "FILEXIO.IRX", SYSTEM, NOTHING, NULL, 0 },
{ "CODYVDFS.IRX", SYSTEM, NOTHING, NULL, 0 },
{ "SJPCM.IRX", SYSTEM, NOTHING, NULL, 0 },
{ "USBD.IRX", USB | OPTIONAL | DEPENDANCY, USB_DRIVER, NULL, 0 },
{ "PS2MOUSE.IRX", USB | OPTIONAL, MOUSE_DRIVER, NULL, 0 },
{ "RPCKBD.IRX", USB | OPTIONAL, KBD_DRIVER, NULL, 0 },
{ "USBHDFSD.IRX", USB | OPTIONAL, MASS_DRIVER, NULL, 0 },
{ "PS2DEV9.IRX", HDD | OPTIONAL | DEPENDANCY, HDD_DRIVER, NULL, 0 },
{ "PS2ATAD.IRX", HDD | OPTIONAL | DEPENDANCY, HDD_DRIVER, NULL, 0 },
{ "PS2HDD.IRX", HDD | OPTIONAL | DEPENDANCY, HDD_DRIVER, hddArg, sizeof(hddArg) },
{ "PS2FS.IRX", HDD | OPTIONAL | DEPENDANCY, HDD_DRIVER, pfsArg, sizeof(pfsArg) },
{ "POWEROFF.IRX", HDD | OPTIONAL | DEPENDANCY, HDD_DRIVER, NULL, 0 }
};
static const int numIrxFiles = sizeof(irxFiles) / sizeof(irxFiles[0]);
BootDevice detectBootPath(const char *elfPath, char *bootPath) {
BootDevice device;
if (strncasecmp(elfPath, "cdrom0:", 7) == 0)
device = CDROM;
else if (strncasecmp(elfPath, "host", 4) == 0)
device = HOST;
else
device = OTHER;
sioprintf("elf path: %s, device %d\n", elfPath, device);
strcpy(bootPath, elfPath);
char *pathPos = bootPath;
char seperator;
if (device == CDROM) {
// CDVD uses '\' as seperator
while (*pathPos) {
if (*pathPos == '/')
*pathPos = '\\';
pathPos++;
}
seperator = '\\';
} else {
// all the other devices use '/'
while (*pathPos) {
if (*pathPos == '\\')
*pathPos = '/';
pathPos++;
}
seperator = '/';
}
pathPos = strrchr(bootPath, seperator);
if (!pathPos)
pathPos = strchr(bootPath, ':');
if (pathPos) {
if ((pathPos[0] == ':') && (device == CDROM)) {
pathPos[1] = '\\';
pathPos[2] = '\0';
} else
pathPos[1] = '\0';
sioprintf("done. IRX path: \"%s\"\n", bootPath);
} else {
sioprintf("path not recognized, default to host.\n");
strcpy(bootPath, "host:");
device = UNKNOWN;
}
return device;
}
int loadIrxModules(int device, const char *irxPath, IrxReference **modules) {
IrxReference *resModules = (IrxReference *)malloc(numIrxFiles * sizeof(IrxReference));
IrxReference *curModule = resModules;
for (int i = 0; i < numIrxFiles; i++) {
curModule->fileRef = irxFiles + i;
if ((device == HOST) && (irxFiles[i].flags & NOT_HOST))
continue;
if ((irxFiles[i].flags & TYPEMASK) == BIOS) {
curModule->loc = IRX_FILE;
curModule->path = (char *)malloc(32);
sprintf(curModule->path, "rom0:%s", irxFiles[i].name);
curModule->buffer = NULL;
curModule->size = 0;
curModule->argSize = 0;
curModule->args = NULL;
curModule->errorCode = 0;
} else {
curModule->loc = IRX_BUFFER;
curModule->path = (char *)malloc(256);
sprintf(curModule->path, "%s%s%s", irxPath, irxFiles[i].name, (device == CDROM) ? ";1" : "");
int fd = fioOpen(curModule->path, O_RDONLY);
if (fd < 0) {
// IRX not found
sioprintf("Can't open %s: %d\n", curModule->path, fd);
// we keep the error code of the path where we originally expected the file
curModule->errorCode = fd;
// try cdrom root directory
sprintf(curModule->path, "cdrom0:\\%s;1", irxFiles[i].name);
fd = fioOpen(curModule->path, O_RDONLY);
if (fd < 0) {
// still not found, try host:
sioprintf("Can't open %s: %d\n", curModule->path, fd);
sprintf(curModule->path, "host:%s", irxFiles[i].name);
fd = fioOpen(curModule->path, O_RDONLY);
if (fd < 0) {
// we simply can't find it.
sioprintf("Can't open %s: %d\n", curModule->path, fd);
// restore the path where we originally expected the file, for error message (later, after boot up)
sprintf(curModule->path, "%s%s%s", irxPath, irxFiles[i].name, (device == CDROM) ? ";1" : "");
}
}
}
if (fd >= 0) {
curModule->size = fioLseek(fd, 0, SEEK_END);
fioLseek(fd, 0, SEEK_SET);
curModule->buffer = (uint8 *)memalign(64, (curModule->size + 63) & ~63);
fioRead(fd, curModule->buffer, curModule->size);
curModule->argSize = irxFiles[i].argSize;
curModule->args = irxFiles[i].args;
curModule->errorCode = 0;
fioClose(fd);
} else {
if (irxFiles[i].flags & DEPENDANCY) {
// other modules depend on this one.
// kill the modules we already loaded, if they depend on the one that failed.
IrxReference *pos = resModules;
while (pos < curModule) {
if ((pos->fileRef->flags & TYPEMASK) == (irxFiles[i].flags & TYPEMASK)) {
if (pos->path)
free(pos->path);
if (pos->buffer)
free(pos->buffer);
IrxReference *copyPos = pos;
while (copyPos < curModule) {
copyPos[0] = copyPos[1];
copyPos++;
}
curModule--;
} else
pos++;
}
// and skip any remaining modules that depend on the missing one, too.
while ((i < numIrxFiles - 1) && ((irxFiles[i + 1].flags & TYPEMASK) == (curModule->fileRef->flags & TYPEMASK)))
i++;
// the module that actually failed (curModule) is kept in the array for displaying an error message
}
curModule->size = 0;
curModule->buffer = NULL;
curModule->argSize = 0;
curModule->args = NULL;
}
}
curModule++;
}
*modules = resModules;
sioprintf("List of %d modules:\n", curModule - resModules);
for (int i = 0; i < curModule - resModules; i++)
sioprintf("%s\n", resModules[i].path);
return curModule - resModules;
}