aboutsummaryrefslogtreecommitdiff
path: root/backends/ps2/systemps2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/ps2/systemps2.cpp')
-rw-r--r--backends/ps2/systemps2.cpp332
1 files changed, 228 insertions, 104 deletions
diff --git a/backends/ps2/systemps2.cpp b/backends/ps2/systemps2.cpp
index 96913132c4..27b88d30ea 100644
--- a/backends/ps2/systemps2.cpp
+++ b/backends/ps2/systemps2.cpp
@@ -43,6 +43,7 @@
#include "common/file.h"
#include "backends/ps2/sysdefs.h"
#include <libmc.h>
+#include <libpad.h>
#include "backends/ps2/cd.h"
#include <sio.h>
#include <fileXio_rpc.h>
@@ -53,8 +54,8 @@
#define SOUND_STACK_SIZE (1024 * 32)
#define SMP_PER_BLOCK 800
#define FROM_BCD(a) ((a >> 4) * 10 + (a & 0xF))
-#define BUS_CLOCK (150 * 1000 * 1000) // 150 Mhz Bus clock
-#define CLK_DIVIS 5859 // the timer IRQ handler gets called (BUS_CLOCK / 256) / CLK_DIVIS times per second (~100 times)
+#define BUS_CLOCK 147456000 // bus clock, a little less than 150 mhz
+#define CLK_DIVIS 5760 // the timer IRQ handler gets called (BUS_CLOCK / 256) / CLK_DIVIS times per second (100 times)
#ifdef USE_PS2LINK
#define IRX_PREFIX "host:"
@@ -67,14 +68,14 @@
static int g_TimerThreadSema = -1, g_SoundThreadSema = -1;
static int g_MainWaitSema = -1, g_TimerWaitSema = -1;
static volatile int32 g_MainWakeUp = 0, g_TimerWakeUp = 0;
-static volatile uint64 msecCount = 0;
+static volatile uint32 msecCount = 0;
OSystem_PS2 *g_systemPs2 = NULL;
-void readRtcTime(void);
-
int gBitFormat = 555;
+#define FOREVER 2147483647
+
namespace Graphics {
extern const NewFont g_sysfont;
};
@@ -84,7 +85,7 @@ void sioprintf(const char *zFormat, ...) {
char resStr[2048];
va_start(ap,zFormat);
- int res = vsnprintf(resStr, 2048, zFormat, ap);
+ vsnprintf(resStr, 2048, zFormat, ap);
va_end(ap);
sio_puts(resStr);
@@ -113,7 +114,7 @@ extern "C" int main(int argc, char *argv[]) {
sio_puts("IOP synced.");
SifInitRpc(0);
SifLoadFileInit();
- cdvdInit(CDVD_INIT_NOWAIT);
+ cdvdInit(CDVD_INIT_NOWAIT);
#endif
ee_thread_t thisThread;
@@ -143,8 +144,8 @@ extern "C" int main(int argc, char *argv[]) {
}
s32 timerInterruptHandler(s32 cause) {
- msecCount += (((uint64)256 * CLK_DIVIS) << 32) / (BUS_CLOCK / 1000);
T0_MODE = 0xDC2; // same value as in initialization.
+ msecCount += 10;
iSignalSema(g_SoundThreadSema);
iSignalSema(g_TimerThreadSema);
@@ -175,54 +176,66 @@ void systemSoundThread(OSystem_PS2 *system) {
}
OSystem_PS2::OSystem_PS2(void) {
- sioprintf("OSystem_PS2 constructor\n");
-
_soundStack = _timerStack = NULL;
_scummTimerProc = NULL;
_scummSoundProc = NULL;
_scummSoundParam = NULL;
+ _printY = 0;
+ _msgClearTime = 0;
+ _systemQuit = false;
_screen = new Gs2dScreen(320, 200, TV_DONT_CARE);
- _width = 320;
- _height = 200;
- sioprintf("Initializing timer\n");
+ sioprintf("Initializing system...");
initTimer();
_screen->wantAnim(true);
- char errorStr[256];
- if (!loadModules(errorStr))
- fatalError(errorStr);
+ sioprintf("Loading IOP modules...");
+ loadModules();
- sioprintf("Initializing SjPCM");
- if (SjPCM_Init(0) < 0)
- fatalError("SjPCM Bind failed");
+ int res;
+ if ((res = SjPCM_Init(0)) < 0) {
+ msgPrintf(FOREVER, "SjPCM Bind failed: %d", res);
+ quit();
+ }
- if (CDVD_Init() != 0)
- fatalError("CDVD_Init failed");
+ if ((res = CDVD_Init()) != 0) {
+ msgPrintf(FOREVER, "CDVD Init failed: %d", res);
+ quit();
+ }
+
+ if ((res = fileXioInit()) < 0) {
+ msgPrintf(FOREVER, "FXIO Init failed: %d", res);
+ quit();
+ }
+ fileXioSetBlockMode(FXIO_NOWAIT);
_mouseVisible = false;
sioprintf("reading RTC");
readRtcTime();
- sioprintf("Initializing FXIO");
- if (fileXioInit() < 0)
- fatalError("Can't init fileXio");
-
- fileXioSetBlockMode(FXIO_NOWAIT);
-
sioprintf("Starting SavefileManager");
_saveManager = new Ps2SaveFileManager(this, _screen);
- _soundBufL = (int16*)malloc(SMP_PER_BLOCK * sizeof(int16));
- _soundBufR = (int16*)malloc(SMP_PER_BLOCK * sizeof(int16));
-
sioprintf("Initializing ps2Input");
_input = new Ps2Input(this, _useMouse, _useKbd);
+#ifdef _REC_MUTEX_
+ _mutex = new Ps2Mutex[MAX_MUTEXES];
+
+ ee_sema_t newSema;
+ newSema.init_count = 1;
+ newSema.max_count = 1;
+ _mutexSema = CreateSema(&newSema);
+ for (int i = 0; i < MAX_MUTEXES; i++) {
+ _mutex[i].sema = -1;
+ _mutex[i].count = _mutex[i].owner = 0;
+ }
+#endif
_screen->wantAnim(false);
+ _screen->clearScreen();
}
OSystem_PS2::~OSystem_PS2(void) {
@@ -267,7 +280,7 @@ void OSystem_PS2::initTimer(void) {
StartThread(_timerTid, this);
StartThread(_soundTid, this);
- // these semaphores are used for OSystem::delay()
+ // these semaphores are used for OSystem::delayMillis()
threadSema.init_count = 0;
threadSema.max_count = 1;
g_MainWaitSema = CreateSema(&threadSema);
@@ -275,20 +288,22 @@ void OSystem_PS2::initTimer(void) {
assert((g_MainWaitSema >= 0) && (g_TimerWaitSema >= 0));
// threads done, start the interrupt handler
- AddIntcHandler( INT_TIMER0, timerInterruptHandler, 0); // 0=first handler
+ _intrId = AddIntcHandler( INT_TIMER0, timerInterruptHandler, 0); // 0=first handler
+ assert(_intrId >= 0);
EnableIntc(INT_TIMER0);
T0_HOLD = 0;
T0_COUNT = 0;
- T0_COMP = CLK_DIVIS; // (busclock / 256) / 5859 = ~ 100.0064
+ T0_COMP = CLK_DIVIS; // (BUS_CLOCK / 256) / CLK_DIVIS = 100
T0_MODE = TIMER_MODE( 2, 0, 0, 0, 1, 1, 1, 0, 1, 1);
}
void OSystem_PS2::timerThread(void) {
- while (1) {
+ while (!_systemQuit) {
WaitSema(g_TimerThreadSema);
if (_scummTimerProc)
_scummTimerProc(0);
}
+ ExitThread();
}
void OSystem_PS2::soundThread(void) {
@@ -298,9 +313,12 @@ void OSystem_PS2::soundThread(void) {
_soundSema = CreateSema(&soundSema);
assert(_soundSema >= 0);
+ int16 *soundBufL = (int16*)memalign(64, SMP_PER_BLOCK * sizeof(int16) * 2);
+ int16 *soundBufR = soundBufL + SMP_PER_BLOCK;
+
int bufferedSamples = 0;
int cycles = 0;
- while (1) {
+ while (!_systemQuit) {
WaitSema(g_SoundThreadSema);
if (!(cycles & 31))
@@ -311,7 +329,7 @@ void OSystem_PS2::soundThread(void) {
WaitSema(_soundSema);
if (_scummSoundProc) {
- if (bufferedSamples <= 8 * SMP_PER_BLOCK) {
+ if (bufferedSamples <= 4 * SMP_PER_BLOCK) {
// we have to produce more samples, call sound mixer
// the scratchpad at 0x70000000 is used as temporary soundbuffer
_scummSoundProc(_scummSoundParam, (uint8*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16));
@@ -343,20 +361,25 @@ void OSystem_PS2::soundThread(void) {
" addiu $t8, 32\n\t"
" bnez $t9, loop\n\t" // loop
: // outputs
- : "r"(_soundBufL), "r"(_soundBufR) // inputs
+ : "r"(soundBufL), "r"(soundBufR) // inputs
// : "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "$t9" // destroyed
: "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25" // destroyed
);
// and feed it into the SPU
- SjPCM_Enqueue((short int*)_soundBufL, (short int*)_soundBufR, SMP_PER_BLOCK, 0);
+ // non-blocking call, the function will return before the buffer's content
+ // was transferred.
+ SjPCM_Enqueue((short int*)soundBufL, (short int*)soundBufR, SMP_PER_BLOCK, 0);
bufferedSamples += SMP_PER_BLOCK;
}
}
SignalSema(_soundSema);
}
+ free(soundBufL);
+ DeleteSema(_soundSema);
+ ExitThread();
}
-char *irxModules[] = {
+const char *irxModules[] = {
"rom0:SIO2MAN",
"rom0:MCMAN",
"rom0:MCSERV",
@@ -370,40 +393,37 @@ char *irxModules[] = {
IRX_PREFIX "SJPCM.IRX" IRX_SUFFIX
};
-bool OSystem_PS2::loadModules(char *errorStr) {
+void OSystem_PS2::loadModules(void) {
- _useHdd = _useMouse = _useKbd = false;
+ _useMouse = _useKbd = false;
int res;
for (int i = 0; i < ARRAYSIZE(irxModules); i++) {
if ((res = SifLoadModule(irxModules[i], 0, NULL)) < 0) {
- sprintf(errorStr, "Can't load module %s (%d)", irxModules[i], res);
- return false;
+ msgPrintf(FOREVER, "Unable to load module %s, Error %d", irxModules[i], res);
+ _screen->wantAnim(false);
+ updateScreen();
+ SleepThread();
}
}
- printf("Modules loaded\n");
+
// now try to load optional IRXs
- if ((res = SifLoadModule(IRX_PREFIX "USBD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
- sioprintf("Cannot load module: USBD.IRX (%d)\n", res);
- else {
+ if ((res = SifLoadModule(IRX_PREFIX "USBD.IRX" IRX_SUFFIX, 0, NULL)) >= 0) {
if ((res = SifLoadModule(IRX_PREFIX "PS2MOUSE.IRX" IRX_SUFFIX, 0, NULL)) < 0)
- sioprintf("Cannot load module: PS2MOUSE.IRX (%d)\n", res);
+ sioprintf("Cannot load module: PS2MOUSE.IRX (%d)", res);
else
_useMouse = true;
if ((res = SifLoadModule(IRX_PREFIX "RPCKBD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
- sioprintf("Cannot load module: RPCKBD.IRX (%d)\n", res);
+ sioprintf("Cannot load module: RPCKBD.IRX (%d)", res);
else
_useKbd = true;
}
- sioprintf("Modules: UsbMouse %sloaded, UsbKbd %sloaded, Hdd %sloaded.", _useMouse ? "" : "not ", _useKbd ? "" : "not ", _useHdd ? "" : "not ");
- return true;
+ sioprintf("Modules: UsbMouse %sloaded, UsbKbd %sloaded.", _useMouse ? "" : "not ", _useKbd ? "" : "not ");
}
void OSystem_PS2::initSize(uint width, uint height, int overscale) {
printf("initializing new size: (%d/%d)...", width, height);
_screen->newScreenSize(width, height);
- _width = width;
- _height = height;
_screen->setMouseXy(width / 2, height / 2);
_input->newRange(0, 0, width - 1, height - 1);
_input->warpTo(width / 2, height / 2);
@@ -422,30 +442,24 @@ void OSystem_PS2::grabPalette(byte *colors, uint start, uint num) {
}
void OSystem_PS2::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
- if (x < 0) {
- w += x;
- buf -= x;
- x = 0;
- }
- if (y < 0) {
- h += y;
- buf -= y * pitch;
- y = 0;
- }
- if (x + w > _width)
- w = _width - x;
- if (y + h > _height)
- h = _height - y;
- if ((w > 0) && (h > 0))
- _screen->copyScreenRect((const uint8*)buf, (uint16)pitch, (uint16)x, (uint16)y, (uint16)w, (uint16)h);
+ _screen->copyScreenRect((const uint8*)buf, pitch, x, y, w, h);
+}
+
+bool OSystem_PS2::grabRawScreen(Graphics::Surface *surf) {
+ _screen->grabScreen(surf);
+ return true;
}
void OSystem_PS2::updateScreen(void) {
+ if (_msgClearTime && (_msgClearTime < getMillis())) {
+ _screen->clearPrintfOverlay();
+ _msgClearTime = 0;
+ }
_screen->updateScreen();
}
uint32 OSystem_PS2::getMillis(void) {
- return (uint32)(msecCount >> 32);
+ return msecCount;
}
void OSystem_PS2::delayMillis(uint msecs) {
@@ -500,6 +514,7 @@ Common::SaveFileManager *OSystem_PS2::getSavefileManager(void) {
return _saveManager;
}
+#ifndef _REC_MUTEX_
OSystem::MutexRef OSystem_PS2::createMutex(void) {
ee_sema_t newSema;
newSema.init_count = 1;
@@ -521,6 +536,68 @@ void OSystem_PS2::unlockMutex(MutexRef mutex) {
void OSystem_PS2::deleteMutex(MutexRef mutex) {
DeleteSema((int)mutex);
}
+#else
+OSystem::MutexRef OSystem_PS2::createMutex(void) {
+ WaitSema(_mutexSema);
+ Ps2Mutex *mutex = NULL;
+ for (int i = 0; i < MAX_MUTEXES; i++)
+ if (_mutex[i].sema < 0) {
+ mutex = _mutex + i;
+ break;
+ }
+ if (mutex) {
+ ee_sema_t newSema;
+ newSema.init_count = 1;
+ newSema.max_count = 1;
+ mutex->sema = CreateSema(&newSema);
+ mutex->owner = mutex->count = 0;
+ } else
+ printf("OSystem_PS2::createMutex: ran out of Mutex slots!\n");
+ SignalSema(_mutexSema);
+ return (OSystem::MutexRef)mutex;
+}
+
+void OSystem_PS2::lockMutex(MutexRef mutex) {
+ WaitSema(_mutexSema);
+ Ps2Mutex *sysMutex = (Ps2Mutex*)mutex;
+ int tid = GetThreadId();
+ assert(tid != 0);
+ if (sysMutex->owner && (sysMutex->owner == tid))
+ sysMutex->count++;
+ else {
+ SignalSema(_mutexSema);
+ WaitSema(sysMutex->sema);
+ WaitSema(_mutexSema);
+ sysMutex->owner = tid;
+ sysMutex->count = 0;
+ }
+ SignalSema(_mutexSema);
+}
+
+void OSystem_PS2::unlockMutex(MutexRef mutex) {
+ WaitSema(_mutexSema);
+ Ps2Mutex *sysMutex = (Ps2Mutex*)mutex;
+ int tid = GetThreadId();
+ if (sysMutex->owner && sysMutex->count && (sysMutex->owner == tid))
+ sysMutex->count--;
+ else {
+ assert(sysMutex->count == 0);
+ SignalSema(sysMutex->sema);
+ sysMutex->owner = 0;
+ }
+ SignalSema(_mutexSema);
+}
+
+void OSystem_PS2::deleteMutex(MutexRef mutex) {
+ WaitSema(_mutexSema);
+ Ps2Mutex *sysMutex = (Ps2Mutex*)mutex;
+ if (sysMutex->owner || sysMutex->count)
+ printf("WARNING: Deleting LOCKED mutex!\n");
+ DeleteSema(sysMutex->sema);
+ sysMutex->sema = -1;
+ SignalSema(_mutexSema);
+}
+#endif
void OSystem_PS2::setShakePos(int shakeOffset) {
_screen->setShakePos(shakeOffset);
@@ -615,40 +692,90 @@ void OSystem_PS2::colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b) {
}
int16 OSystem_PS2::getHeight(void) {
- return _height;
+ return _screen->getHeight();
}
int16 OSystem_PS2::getWidth(void) {
- return _width;
+ return _screen->getWidth();
}
-void OSystem_PS2::quit(void) {
- printf("OSystem_PS2::quit\n");
- clearSoundCallback();
- setTimerCallback(NULL, 0);
- SleepThread();
-}
+void OSystem_PS2::msgPrintf(int millis, char *format, ...) {
+ va_list ap;
+ char resStr[1024];
+ memset(resStr, 0, 1024);
+
+ va_start(ap, format);
+ vsnprintf(resStr, 1023, format, ap);
+ va_end(ap);
+
+ uint16 posY = 2;
+ int maxWidth = 0;
-void OSystem_PS2::fatalError(char *errorStr) {
- sioprintf("ERROR: %s", errorStr);
- printf("ERROR: %s\n", errorStr);
Graphics::Surface surf;
surf.create(300, 200, 1);
- Common::String str(errorStr);
- Graphics::g_sysfont.drawString(&surf, str, 0, 0, 300, 0xFF);
- uint32 palette[256];
- palette[0] = 0x00400000;
- for (int i = 1; i < 256; i++)
- palette[i] = 0xFFFFFFFF;
+ char *lnSta = resStr;
+ while (*lnSta && (posY < 180)) {
+ char *lnEnd = lnSta;
+ while ((*lnEnd) && (*lnEnd != '\n'))
+ lnEnd++;
+ *lnEnd = '\0';
+
+ Common::String str(lnSta);
+ int width = Graphics::g_sysfont.getStringWidth(str);
+ if (width > maxWidth)
+ maxWidth = width;
+ int posX = (300 - width) / 2;
+ Graphics::g_sysfont.drawString(&surf, str, posX, posY, 300 - posX, 1);
+ posY += 14;
+
+ lnSta = lnEnd + 1;
+ }
- _screen->setPalette(palette, 0, 256);
- _screen->hideOverlay();
- _screen->wantAnim(false);
+ uint8 *scrBuf = (uint8*)memalign(64, 320 * 200);
+ memset(scrBuf, 4, 320 * 200);
- _screen->copyScreenRect((uint8*)surf.getBasePtr(0, 0), surf.pitch, 10, 10, 300, 100);
- _screen->updateScreen();
- SleepThread();
+ uint8 *dstPos = scrBuf + ((200 - posY) >> 1) * 320 + (320 - maxWidth) / 2;
+ for (int y = 0; y < posY; y++) {
+ uint8 *srcPos = (uint8*)surf.getBasePtr((300 - maxWidth) / 2, y);
+ for (int x = 0; x < maxWidth; x++)
+ dstPos[x] = srcPos[x] + 5;
+ dstPos += 320;
+ }
+ surf.free();
+ _screen->copyPrintfOverlay(scrBuf);
+ free(scrBuf);
+ _msgClearTime = millis + getMillis();
+}
+
+void OSystem_PS2::quit(void) {
+ sioprintf("OSystem_PS2::quit");
+ clearSoundCallback();
+ setTimerCallback(NULL, 0);
+ _screen->wantAnim(false);
+ _systemQuit = true;
+ ee_thread_t statSound, statTimer;
+ do { // wait until both threads called ExitThread()
+ ReferThreadStatus(_timerTid, &statTimer);
+ ReferThreadStatus(_soundTid, &statSound);
+ } while ((statSound.status != 0x10) || (statTimer.status != 0x10));
+ DeleteThread(_timerTid);
+ DeleteThread(_soundTid);
+ free(_timerStack);
+ free(_soundStack);
+ DisableIntc(INT_TIMER0);
+ RemoveIntcHandler(INT_TIMER0, _intrId);
+
+ _saveManager->quit();
+ _screen->quit();
+
+ padEnd(); // stop pad library
+ cdvdInit(CDVD_EXIT);
+ cdvdExit();
+ SifExitIopHeap();
+ SifLoadFileExit();
+ SifExitRpc();
+ LoadExecPS2("cdrom0:\\SCUMMVM.ELF", 0, NULL); // resets the console and executes the ELF
}
static uint32 g_timeSecs;
@@ -687,13 +814,13 @@ void buildNewDate(int dayDiff) {
#define SECONDS_PER_DAY (24 * 60 * 60)
-void readRtcTime(void) {
+void OSystem_PS2::readRtcTime(void) {
struct CdClock cdClock;
CDVD_ReadClock(&cdClock);
- g_lastTimeCheck = (uint32)(msecCount >> 32);
+ g_lastTimeCheck = msecCount;
if (cdClock.stat) {
- printf("Unable to read RTC time, EC: %d\n", cdClock.stat);
+ msgPrintf(5000, "Unable to read RTC time, EC: %d\n", cdClock.stat);
g_day = g_month = 1;
g_year = 0;
g_timeSecs = 0;
@@ -717,7 +844,6 @@ void readRtcTime(void) {
buildNewDate(+1);
timeSecs -= SECONDS_PER_DAY;
}
-
g_timeSecs = (uint32)timeSecs;
}
@@ -726,17 +852,15 @@ void readRtcTime(void) {
}
extern time_t time(time_t *p) {
- time_t blah;
- memset(&blah, 0, sizeof(time_t));
- return blah;
+ return (time_t)g_timeSecs;
}
extern struct tm *localtime(const time_t *p) {
- uint32 currentSecs = g_timeSecs + ((msecCount >> 32) - g_lastTimeCheck) / 1000;
+ uint32 currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
if (currentSecs >= SECONDS_PER_DAY) {
buildNewDate(+1);
- g_timeSecs -= SECONDS_PER_DAY;
- currentSecs = g_timeSecs + ((msecCount >> 32) - g_lastTimeCheck) / 1000;
+ g_lastTimeCheck += SECONDS_PER_DAY * 1000;
+ currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
}
static struct tm retStruct;
@@ -747,7 +871,7 @@ extern struct tm *localtime(const time_t *p) {
retStruct.tm_sec = currentSecs % 60;
retStruct.tm_year = g_year + 100;
retStruct.tm_mday = g_day;
- retStruct.tm_mon = g_month;
+ retStruct.tm_mon = g_month - 1;
// tm_wday, tm_yday and tm_isdst are zero for now
return &retStruct;
}