aboutsummaryrefslogtreecommitdiff
path: root/backends/ps2
diff options
context:
space:
mode:
authorRobert Göffringmann2005-05-05 03:06:32 +0000
committerRobert Göffringmann2005-05-05 03:06:32 +0000
commit4120ae9921cfb135777a4fb25e98545a7038e7aa (patch)
tree129eea6e1f132b726c92dc653a6e828185703f2e /backends/ps2
parent38c9a40c22c9017b4e43b1c5670ba569da94dee8 (diff)
downloadscummvm-rg350-4120ae9921cfb135777a4fb25e98545a7038e7aa.tar.gz
scummvm-rg350-4120ae9921cfb135777a4fb25e98545a7038e7aa.tar.bz2
scummvm-rg350-4120ae9921cfb135777a4fb25e98545a7038e7aa.zip
various PS2 system changes
svn-id: r17912
Diffstat (limited to 'backends/ps2')
-rw-r--r--backends/ps2/DmaPipe.cpp37
-rw-r--r--backends/ps2/DmaPipe.h3
-rw-r--r--backends/ps2/Gs2dScreen.cpp359
-rw-r--r--backends/ps2/Gs2dScreen.h15
-rw-r--r--backends/ps2/GsDefs.h11
-rw-r--r--backends/ps2/asyncfio.cpp50
-rw-r--r--backends/ps2/asyncfio.h5
-rw-r--r--backends/ps2/fileio.cpp655
-rw-r--r--backends/ps2/fileio.h47
-rw-r--r--backends/ps2/libkbd.cpp191
-rw-r--r--backends/ps2/ps2input.cpp3
-rw-r--r--backends/ps2/ps2pad.cpp15
-rw-r--r--backends/ps2/ps2pad.h2
-rw-r--r--backends/ps2/savefile.cpp540
-rw-r--r--backends/ps2/savefile.h34
-rw-r--r--backends/ps2/sjpcm.h56
-rw-r--r--backends/ps2/smushio.cpp376
-rw-r--r--backends/ps2/sysdefs.h6
-rw-r--r--backends/ps2/systemps2.cpp179
-rw-r--r--backends/ps2/systemps2.h3
20 files changed, 1453 insertions, 1134 deletions
diff --git a/backends/ps2/DmaPipe.cpp b/backends/ps2/DmaPipe.cpp
index c59b6f5020..383ffe9102 100644
--- a/backends/ps2/DmaPipe.cpp
+++ b/backends/ps2/DmaPipe.cpp
@@ -128,15 +128,15 @@ void DmaPipe::setTex(uint32 tex, uint32 texBufWidth, uint8 texPowW, uint8 texPow
_pipes[_curPipe]->setReg( GPR_CLAMP_1, 0);
}
-void DmaPipe::textureRect(uint16 x1, uint16 y1, uint16 u1, uint16 v1, uint16 x2, uint16 y2, uint16 u2, uint16 v2, uint16 z, uint32 colour) {
+void DmaPipe::textureRect(const GsVertex *p1, const GsVertex *p2, const TexVertex *t1, const TexVertex *t2) {
checkSpace(4);
_pipes[_curPipe]->setGifRegListTag( 6, 0xffffffffff535310);
_pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_SPRITE, 0, 1, 0, 1, 0, 1, 0, 0),
- GS_SET_COLQ(colour));
- _pipes[_curPipe]->setListReg( GS_SET_UV(u1, v1),
- GS_SET_XYZ(x1, y1, z));
- _pipes[_curPipe]->setListReg( GS_SET_UV(u2, v2),
- GS_SET_XYZ(x2, y2, z));
+ GS_SET_COLQ(GS_RGBA(0x80, 0x80, 0x80, 0x80)));
+ _pipes[_curPipe]->setListReg( GS_SET_UV(t1->u, t1->v),
+ GS_SET_XYZ(p1->x, p1->y, p1->z));
+ _pipes[_curPipe]->setListReg( GS_SET_UV(t2->u, t2->v),
+ GS_SET_XYZ(p2->x, p2->y, p2->z));
}
void DmaPipe::textureRect(const GsVertex *p1, const GsVertex *p2, const GsVertex *p3, const GsVertex *p4, const TexVertex *t1, const TexVertex *t2, const TexVertex *t3, const TexVertex *t4, uint32 rgba) {
@@ -155,18 +155,6 @@ void DmaPipe::textureRect(const GsVertex *p1, const GsVertex *p2, const GsVertex
GS_SET_XYZ(p4->x, p4->y, p4->z));
}
-/*void DmaPipe::flatRect(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint16 x3, uint16 y3, uint16 x4, uint16 y4, uint16 z, uint32 rgba) {
- checkSpace(4);
- _pipes[_curPipe]->setGifRegListTag( 6, 0xffffffffff555510);
- //_pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_TRIANGLESTRIP, 0, 0, 0, 1, 0, 0, 0, 0),
- _pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_TRIANGLESTRIP, 0, 0, 0, 0, 0, 0, 0, 0),
- GS_SET_COLQ(rgba));
- _pipes[_curPipe]->setListReg( GS_SET_XYZ(x2, y2, z),
- GS_SET_XYZ(x1, y1, z));
- _pipes[_curPipe]->setListReg( GS_SET_XYZ(x3, y3, z),
- GS_SET_XYZ(x4, y4, z));
-}*/
-
void DmaPipe::flatRect(const GsVertex *p1, const GsVertex *p2, const GsVertex *p3, const GsVertex *p4, uint32 rgba) {
checkSpace(4);
_pipes[_curPipe]->setGifRegListTag( 6, 0xffffffffff555510);
@@ -205,10 +193,7 @@ void DmaPipe::setConfig(uint8 prModeCont, uint8 dither, uint8 colClamp) {
// set some defaults
// alpha blending formula: (A-B) * C + D
- // set: A = source pixel, b = 0, C = source alpha, D = destination pixel, fix = don't care
- //_pipes[_curPipe]->setReg(GPR_ALPHA_1, GS_SET_ALPHA(SOURCE_COLOR, ZERO_COLOR, SOURCE_ALPHA, DEST_COLOR, 0));
- // set: A = source pixel, b = dest pixel, C = source alpha, D = destination pixel, fix = don't care
- //_pipes[_curPipe]->setReg( GPR_ALPHA_1, GS_SET_ALPHA(SOURCE_COLOR, DEST_COLOR, SOURCE_ALPHA, DEST_COLOR, 0x7F));
+ // set: A = dest pixel, b = 0, C = source alpha, D = source pixel, fix = don't care
_pipes[_curPipe]->setReg(GPR_ALPHA_1, GS_SET_ALPHA(DEST_COLOR, ZERO_COLOR, SOURCE_ALPHA, SOURCE_COLOR, 0));
_pipes[_curPipe]->setReg( GPR_PRIM, 0);
@@ -233,6 +218,14 @@ void DmaPipe::setDrawBuffer(uint64 base, uint64 width, uint8 pixelFmt, uint64 ma
_pipes[_curPipe]->setReg( GPR_FRAME_1, GS_SET_FRAME(base / 8192, width / 64, pixelFmt, mask));
}
+void DmaPipe::setFinishEvent(void) {
+ checkSpace(3);
+ // make GS generate a FINISH interrupt when it's done.
+ _pipes[_curPipe]->setGifLoopTag(2);
+ _pipes[_curPipe]->setReg( GPR_FINISH, 1);
+ _pipes[_curPipe]->setReg( GPR_SIGNAL, 1);
+}
+
void DmaPipe::checkSpace(uint32 needed) {
if (_pipes[_curPipe]->spaceLeft() < (needed << 1))
flush();
diff --git a/backends/ps2/DmaPipe.h b/backends/ps2/DmaPipe.h
index e032182eae..eebd0f75fa 100644
--- a/backends/ps2/DmaPipe.h
+++ b/backends/ps2/DmaPipe.h
@@ -43,8 +43,8 @@ public:
void uploadTex(uint32 dest, uint16 bufWidth, uint16 destOfsX, uint16 destOfsY, uint8 pixelFmt, const void *src, uint16 width, uint16 height);
void setTex(uint32 tex, uint32 texBufWidth, uint8 texPowW, uint8 texPowH, uint8 texPixFmt, uint32 clut, uint8 csm, uint32 clutBufWidth, uint32 clutPixFmt);
void setDrawBuffer(uint64 base, uint64 width, uint8 pixelFmt, uint64 mask);
- void textureRect(uint16 x1, uint16 y1, uint16 u1, uint16 v1, uint16 x2, uint16 y2, uint16 u2, uint16 v2, uint16 z, uint32 colour);
void textureRect(const GsVertex *p1, const GsVertex *p2, const GsVertex *p3, const GsVertex *p4, const TexVertex *t1, const TexVertex *t2, const TexVertex *t3, const TexVertex *t4, uint32 rgba);
+ void textureRect(const GsVertex *p1, const GsVertex *p2, const TexVertex *t1, const TexVertex *t2);
void flatRect(const GsVertex *p1, const GsVertex *p2, const GsVertex *p3, const GsVertex *p4, uint32 rgba);
void flatRect(const GsVertex *p1, const GsVertex *p2, uint32 rgba);
@@ -52,6 +52,7 @@ public:
void setConfig(uint8 prModeCont, uint8 dither, uint8 colClamp);
void setScissorRect(uint64 x1, uint64 y1, uint64 x2, uint64 y2);
void setAlphaBlend(AlphaBlendColor a, AlphaBlendColor b, AlphaBlendAlpha c, AlphaBlendColor d, uint8 fix);
+ void setFinishEvent(void);
void flush(void);
void waitForDma(void);
private:
diff --git a/backends/ps2/Gs2dScreen.cpp b/backends/ps2/Gs2dScreen.cpp
index c2e547ff2e..274367847e 100644
--- a/backends/ps2/Gs2dScreen.cpp
+++ b/backends/ps2/Gs2dScreen.cpp
@@ -25,10 +25,9 @@
#include <string.h>
#include <assert.h>
#include <fileio.h>
-#include <math.h> // for sqrt()
+#include <math.h>
#include "DmaPipe.h"
#include "GsDefs.h"
-#include <sio.h>
enum Buffers {
SCREEN = 0,
@@ -37,7 +36,7 @@ enum Buffers {
};
#define DEFAULT_PAL_X 175
-#define DEFAULT_PAL_Y 40
+#define DEFAULT_PAL_Y 60
#define DEFAULT_NTSC_X 165
#define DEFAULT_NTSC_Y 45
#define ORG_X 256
@@ -47,52 +46,72 @@ enum Buffers {
#define TEX_POW 10
#define SCALE(x) ((x) << 4)
-#define COORD_XY(x, y) SCALE((x) + ORG_X), SCALE((y) + ORG_Y)
-#define COORD_UV(u, v) SCALE(u), SCALE(v)
-
-/*#define COORD_X1(x) SCALE((x) + ORG_X + GS_RECT_OFFSET)
-#define COORD_Y1(y) SCALE((y) + ORG_Y + GS_RECT_OFFSET)
-#define COORD_X2(x) SCALE((x) + ORG_X - GS_RECT_OFFSET)
-#define COORD_Y2(y) SCALE((y) + ORG_Y - GS_RECT_OFFSET)
-#define COORD_XY1(x, y) COORD_X1(x), COORD_Y1(y)
-#define COORD_XY2(x, y) COORD_X2(x), COORD_Y2(y)*/
#define M_SIZE 128
#define M_POW 7
#define PI 3.1415926535897932384626433832795
-static volatile uint32 g_VblankCmd, g_DmacCmd;
+static volatile uint32 g_VblankCmd = 0, g_DmacCmd = 0;
+static int g_VblankSema, g_DmacSema, g_AnimSema;
+static bool g_RunAnim = false;
+static GsVertex kFullScreen[2];
+static TexVertex kMouseTex[2] = {
+ { SCALE(1), SCALE(1) },
+ { SCALE(M_SIZE), SCALE(M_SIZE) }
+};
+
+void sioprintf(const char *zFormat, ...);
-int32 vblankHandler(int32 cause) {
+int vblankStartHandler(int cause) {
// start of VBlank period
if (g_VblankCmd) { // is there a new image waiting?
GS_DISPFB1 = g_VblankCmd; // show it.
g_VblankCmd = 0;
+ iSignalSema(g_VblankSema);
}
return 0;
}
-int32 dmacHandler(int32 channel) {
+int dmacHandler(int channel) {
if (g_DmacCmd && (channel == 2)) { // GS DMA transfer finished,
g_VblankCmd = g_DmacCmd; // we want to show the image
g_DmacCmd = 0; // when the next vblank occurs
+ iSignalSema(g_DmacSema);
}
return 0;
}
+int vblankEndHandler(int cause) {
+ if (g_RunAnim)
+ iSignalSema(g_AnimSema);
+ return 0;
+}
+
void createAnimThread(Gs2dScreen *screen);
Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode tvMode) {
- g_DmacCmd = g_VblankCmd = 0;
- AddIntcHandler(INT_VBLANK_START, vblankHandler, 0);
- AddDmacHandler(2, dmacHandler, 0); // 2 = 2nd dma channel = EE <-> GS
+ ee_sema_t newSema;
+ newSema.init_count = 1;
+ newSema.max_count = 1;
+ g_VblankSema = CreateSema(&newSema);
+ g_DmacSema = CreateSema(&newSema);
+ _screenSema = CreateSema(&newSema);
+ newSema.init_count = 0;
+ newSema.max_count = 255;
+ g_AnimSema = CreateSema(&newSema);
+ assert((g_VblankSema >= 0) && (g_DmacSema >= 0) && (_screenSema >= 0) && (g_AnimSema >= 0));
+
+ AddIntcHandler(INT_VBLANK_START, vblankStartHandler, 0);
+ AddIntcHandler(INT_VBLANK_END, vblankEndHandler, 0);
+ AddDmacHandler(2, dmacHandler, 0);
_dmaPipe = new DmaPipe(0x2000);
EnableIntc(INT_VBLANK_START);
- EnableDmac(2);
+ EnableIntc(INT_VBLANK_END);
+ EnableDmac(2);
_width = width;
_height = height;
@@ -103,8 +122,7 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode tvMode) {
_clut = (uint32*)memalign(64, 256 * 4);
memset(_screenBuf, 0, _width * _height);
- for (uint32 cnt = 0; cnt < 256; cnt++)
- _clut[cnt] = GS_RGBA(0, 0, 0, 0x80);
+ memset(_clut, 0, 256 * sizeof(uint32));
clearOverlay();
if (tvMode == TV_DONT_CARE) {
@@ -117,9 +135,20 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode tvMode) {
printf("Setting up %s mode\n", (_videoMode == TV_PAL) ? "PAL" : "NTSC");
- // set screen size, 640x576 for pal, 640x448 for ntsc
+ // set screen size, 640x544 for pal, 640x448 for ntsc
_tvWidth = 640;
- _tvHeight = ((_videoMode == TV_PAL) ? 576 : 448);
+ _tvHeight = ((_videoMode == TV_PAL) ? 544 : 448);
+ kFullScreen[0].z = kFullScreen[1].z = 0;
+ kFullScreen[0].x = ORIGIN_X;
+ kFullScreen[0].y = ORIGIN_Y;
+ kFullScreen[1].x = SCALE(_tvWidth) + ORIGIN_X;
+ kFullScreen[1].y = SCALE(_tvHeight) + ORIGIN_Y;
+ _blitCoords[0] = kFullScreen[0];
+ _blitCoords[1] = kFullScreen[1];
+ _texCoords[0].u = SCALE(1);
+ _texCoords[0].v = SCALE(1);
+ _texCoords[1].u = SCALE(_width);
+ _texCoords[1].v = SCALE(_height);
uint32 tvFrameSize = _tvWidth * _tvHeight * 4; // 32 bits per pixel
@@ -142,10 +171,11 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode tvMode) {
_shakePos = 0;
// setup hardware now.
- GS_CSR = GS_SET_CSR(0, 0, 0, 0, 0, 1, 0);
+ GS_CSR = CSR_RESET; // Reset GS
asm ("sync.p");
+
GS_CSR = 0;
- GsPutIMR(0xFF00);
+ GsPutIMR(0x7F00);
uint16 dispPosX, dispPosY;
@@ -171,25 +201,13 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode tvMode) {
_dmaPipe->setConfig(1, 0, 1);
_dmaPipe->setScissorRect(0, 0, _tvWidth - 1, _tvHeight - 1);
_dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0);
+ _dmaPipe->flush();
_clutChanged = _screenChanged = _overlayChanged = true;
+
updateScreen();
createAnimTextures();
-
- ee_sema_t newSema;
- newSema.init_count = 1;
- newSema.max_count = 1;
- _screenSema = CreateSema(&newSema);
-
- newSema.init_count = 0;
- _timerSema = CreateSema(&newSema);
-
- if ((_screenSema < 0) || (_timerSema < 0)) {
- printf("Can't create semaphores.\n");
- SleepThread();
- }
-
createAnimThread(this);
}
@@ -214,6 +232,7 @@ void Gs2dScreen::createAnimTextures(void) {
_dmaPipe->waitForDma();
}
_dmaPipe->uploadTex(_clutPtrs[TEXT], 64, 0, 0, GS_PSMCT32, _binaryClut, 8, 2);
+ _dmaPipe->flush();
free(buf);
}
@@ -221,33 +240,47 @@ void Gs2dScreen::newScreenSize(uint16 width, uint16 height) {
if ((width == _width) && (height == _height))
return;
- printf("New screen size %d/%d\n", width, height);
+ WaitSema(g_DmacSema);
+ WaitSema(g_VblankSema);
+
_dmaPipe->flush();
_screenChanged = _overlayChanged = false;
_width = width;
_height = height;
_pitch = (width + 127) & ~127;
- waitForImage(); // if there's a frame waiting to be shown, wait for vblank handler
- // now malloc new buffers
+ // malloc new buffers
free(_screenBuf);
free(_overlayBuf);
_screenBuf = (uint8*)memalign(64, _width * _height);
- memset(_screenBuf, 0, _width * height);
_overlayBuf = (uint16*)memalign(64, _width * _height * 2);
+ memset(_screenBuf, 0, _width * height);
memset(_overlayBuf, 0, _width * height * 2);
- _screenChanged = _overlayChanged = true;
+ memset(_clut, 0, 256 * sizeof(uint32));
+ // clear video ram
+ _dmaPipe->uploadTex(_clutPtrs[MOUSE], 64, 0, 0, GS_PSMCT32, _clut, 16, 16);
+ _dmaPipe->uploadTex(_clutPtrs[SCREEN], 64, 0, 0, GS_PSMCT32, _clut, 16, 16);
+ _dmaPipe->uploadTex(_texPtrs[SCREEN], _width, 0, 0, GS_PSMCT16, _overlayBuf, _width, _height);
+ _dmaPipe->flush();
+ _dmaPipe->waitForDma();
+
+ _clutChanged = _screenChanged = _overlayChanged = false;
+
+ _texCoords[1].u = SCALE(_width);
+ _texCoords[1].v = SCALE(_height);
_mouseScaleX = (_tvWidth << 8) / _width;
_mouseScaleY = (_tvHeight << 8) / _height;
setMouseXy(_width / 2, _height / 2);
- printf("done\n");
+
+ SignalSema(g_VblankSema);
+ SignalSema(g_DmacSema);
}
void Gs2dScreen::copyScreenRect(const uint8 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h) {
- waitForDma();
-
assert((x + w <= _width) && (y + h <= _height));
+
+ WaitSema(g_DmacSema);
uint8 *dest = _screenBuf + y * _width + x;
for (uint16 cnt = 0; cnt < h; cnt++) {
memcpy(dest, buf, w);
@@ -255,25 +288,23 @@ void Gs2dScreen::copyScreenRect(const uint8 *buf, uint16 pitch, uint16 x, uint16
dest += _width;
}
_screenChanged = true;
+ SignalSema(g_DmacSema);
}
void Gs2dScreen::setPalette(const uint32 *pal, uint8 start, uint16 num) {
- waitForDma();
-
assert(start + num <= 256);
+
+ WaitSema(g_DmacSema);
for (uint16 cnt = 0; cnt < num; cnt++) {
uint16 dest = start + cnt;
- dest = (dest & 0x7) | ((dest & 0x8) << 1) | ((dest & 0x10) >> 1) | (dest & 0xE0); // rearrange like the GS expects it
+ dest = (dest & 0xE7) | ((dest & 0x8) << 1) | ((dest & 0x10) >> 1); // rearrange like the GS expects it
_clut[dest] = pal[cnt] & 0xFFFFFF;
}
_clutChanged = true;
+ SignalSema(g_DmacSema);
}
void Gs2dScreen::updateScreen(void) {
- /* we can't draw more than 50 images on PAL and 60 on NTSC, wait until the other buffer is shown.
- especcially necessary for BS2 which does hundreds of updateScreen()s per second */
- waitForImage();
-
WaitSema(_screenSema);
if (_clutChanged) {
@@ -288,22 +319,7 @@ void Gs2dScreen::updateScreen(void) {
_dmaPipe->uploadTex(_clutPtrs[SCREEN], 64, 0, 0, GS_PSMCT32, _clut, 16, 16);
}
- drawScreen();
-
- g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler
- _dmaPipe->flush();
- _curDrawBuf ^= 1;
- _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0);
- SignalSema(_screenSema);
-}
-
-void Gs2dScreen::drawScreen(void) {
- static GsVertex fullScreen[2] = {
- { COORD_XY(0, 0), SCALE(0) },
- { COORD_XY(_tvWidth, _tvHeight), SCALE(0) }
- };
-
- _dmaPipe->flatRect(fullScreen + 0, fullScreen + 1, GS_RGBA(0, 0, 0, 0)); // clear screen
+ _dmaPipe->flatRect(kFullScreen + 0, kFullScreen + 1, GS_RGBA(0, 0, 0, 0)); // clear screen
if (_showOverlay) {
if (_overlayChanged) {
@@ -311,27 +327,36 @@ void Gs2dScreen::drawScreen(void) {
_overlayChanged = false;
}
_dmaPipe->setTex(_texPtrs[SCREEN], _width, TEX_POW, TEX_POW, GS_PSMCT16, 0, 0, 0, 0);
- _dmaPipe->textureRect(COORD_XY(0, 0), COORD_UV(1, 1),
- COORD_XY(_tvWidth, _tvHeight), COORD_UV(_width, _height), 0, GS_RGBA(0x80, 0x80, 0x80, 0x80));
+ _dmaPipe->textureRect(kFullScreen + 0, kFullScreen + 1, _texCoords + 0, _texCoords + 1);
} else {
if (_screenChanged) {
_dmaPipe->uploadTex(_texPtrs[SCREEN], _pitch, 0, 0, GS_PSMT8, _screenBuf, _width, _height);
_screenChanged = false;
}
_dmaPipe->setTex(_texPtrs[SCREEN], _pitch, TEX_POW, TEX_POW, GS_PSMT8, _clutPtrs[SCREEN], 0, 64, GS_PSMCT32);
- _dmaPipe->textureRect(COORD_XY(0, -_shakePos), COORD_UV(1, 1),
- COORD_XY(_tvWidth, _tvHeight - _shakePos), COORD_UV(_width, _height), 0, GS_RGBA(0x80, 0x80, 0x80, 0x80));
+ _dmaPipe->textureRect(_blitCoords + 0, _blitCoords + 1, _texCoords + 0, _texCoords + 1);
}
if (_showMouse) {
+ GsVertex mouseCoords[2];
+ mouseCoords[0].x = (((_mouseX - _hotSpotX) * _mouseScaleX + 8) >> 4) + ORIGIN_X;
+ mouseCoords[0].y = (((_mouseY - _hotSpotY) * _mouseScaleY + 8) >> 4) + ORIGIN_Y;
+ mouseCoords[1].x = mouseCoords[0].x + (((M_SIZE * _mouseScaleX) + 8) >> 4);
+ mouseCoords[1].y = mouseCoords[0].y + (((M_SIZE * _mouseScaleY) + 8) >> 4);
+ mouseCoords[0].z = mouseCoords[1].z = 0;
+
_dmaPipe->setTex(_texPtrs[MOUSE], M_SIZE, M_POW, M_POW, GS_PSMT8H, _clutPtrs[MOUSE], 0, 64, GS_PSMCT32);
- uint16 mpX1 = (((_mouseX - _hotSpotX) * _mouseScaleX + 128) >> 4) + ORIGIN_X;
- uint16 mpY1 = (((_mouseY - _hotSpotY) * _mouseScaleY + 128) >> 4) + ORIGIN_Y;
- uint16 mpX2 = mpX1 + ((M_SIZE * _mouseScaleX + 128) >> 4);
- uint16 mpY2 = mpY1 + ((M_SIZE * _mouseScaleY + 128) >> 4);
- _dmaPipe->textureRect(mpX1, mpY1, COORD_UV(0, 0),
- mpX2, mpY2, COORD_UV(M_SIZE - 1, M_SIZE - 1), 0, GS_RGBA(0x80, 0x80, 0x80, 0x80));
+ _dmaPipe->textureRect(mouseCoords + 0, mouseCoords + 1, kMouseTex + 0, kMouseTex + 1);
}
+
+ WaitSema(g_DmacSema); // wait for dma transfer, if there's one running
+ WaitSema(g_VblankSema); // wait if there's already an image waiting for vblank
+
+ g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler
+ _dmaPipe->flush();
+ _curDrawBuf ^= 1;
+ _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0);
+ SignalSema(_screenSema);
}
void Gs2dScreen::showOverlay(void) {
@@ -346,11 +371,12 @@ void Gs2dScreen::hideOverlay(void) {
void Gs2dScreen::setShakePos(int shake) {
_shakePos = (shake * _mouseScaleY) >> 8;
+ _blitCoords[0].y = SCALE(_shakePos) + ORIGIN_Y;
+ _blitCoords[1].y = SCALE(_tvHeight + _shakePos) + ORIGIN_Y;
}
void Gs2dScreen::copyOverlayRect(const uint16 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h) {
- waitForDma();
-
+ WaitSema(g_DmacSema);
_overlayChanged = true;
uint16 *dest = _overlayBuf + y * _width + x;
for (uint32 cnt = 0; cnt < h; cnt++) {
@@ -358,21 +384,22 @@ void Gs2dScreen::copyOverlayRect(const uint16 *buf, uint16 pitch, uint16 x, uint
dest += _width;
buf += pitch;
}
+ SignalSema(g_DmacSema);
}
void Gs2dScreen::clearOverlay(void) {
- waitForDma();
-
+ WaitSema(g_DmacSema);
_overlayChanged = true;
// first convert our clut to 16 bit RGBA for the overlay...
uint16 palette[256];
for (uint32 cnt = 0; cnt < 256; cnt++) {
- uint32 rgba = _clut[(cnt & 0x7) | ((cnt & 0x8) << 1) | ((cnt & 0x10) >> 1) | (cnt & 0xE0)];
+ uint32 rgba = _clut[(cnt & 0xE7) | ((cnt & 0x8) << 1) | ((cnt & 0x10) >> 1)];
palette[cnt] = ((rgba >> 3) & 0x1F) | (((rgba >> 11) & 0x1F) << 5) | (((rgba >> 19) & 0x1F) << 10);
}
// now copy the current screen over
for (uint32 cnt = 0; cnt < _width * _height; cnt++)
_overlayBuf[cnt] = palette[_screenBuf[cnt]];
+ SignalSema(g_DmacSema);
}
void Gs2dScreen::grabOverlay(uint16 *buf, uint16 pitch) {
@@ -398,30 +425,12 @@ void Gs2dScreen::setMouseOverlay(const uint8 *buf, uint16 width, uint16 height,
for (int cnt = 0; cnt < height; cnt++)
memcpy(bufCopy + cnt * M_SIZE, buf + cnt * width, width);
- _dmaPipe->uploadTex( _texPtrs[MOUSE], M_SIZE, 0, 0, GS_PSMT8H, bufCopy, M_SIZE, M_SIZE);
+ _dmaPipe->uploadTex( _texPtrs[MOUSE], M_SIZE, 0, 0, GS_PSMT8H, bufCopy, M_SIZE, M_SIZE);
_dmaPipe->flush();
_dmaPipe->waitForDma(); // make sure all data has been transferred when we free bufCopy
free(bufCopy);
}
-void Gs2dScreen::waitForDma(void) {
- // wait until dma transfer finished
- while (g_DmacCmd)
- ;
-}
-
-void Gs2dScreen::waitForImage(void) {
- /* if there's an image waiting to be shown on next vblank, wait for it.
- however, first we must wait for the dma transfer (if running) as it will
- result in a new image */
- waitForDma();
- while (g_VblankCmd)
- ;
- /* both waitForImage and waitForDma should only get called by the main thread,
- so they may be implemented as busy waits, as both the timer- and sound-thread have
- a higher priority than this one. There's no thread we could switch to anyways... */
-}
-
void Gs2dScreen::showMouse(bool show) {
_showMouse = show;
}
@@ -435,94 +444,103 @@ uint8 Gs2dScreen::tvMode(void) {
return _videoMode;
}
+void Gs2dScreen::wantAnim(bool runIt) {
+ g_RunAnim = runIt;
+}
+
#define LINE_SPACE 20
#define SCRL_TIME 8
#define V 1000
#define Z_TRANSL 65
-void Gs2dScreen::wantAnim(bool runIt) {
- _runAnim = runIt;
-}
-
void Gs2dScreen::animThread(void) {
// animate zeros and ones while game accesses memory card, etc.
- _runAnim = false;
+ g_RunAnim = false;
float yPos = 0.0;
uint8 texSta = 0;
float scrlSpeed = (_videoMode == TV_PAL) ? (_tvHeight / (SCRL_TIME * 50.0)) : (_tvHeight / (SCRL_TIME * 60.0));
uint8 texMax = (_tvHeight / LINE_SPACE) + (ORG_Y / LINE_SPACE);
TexVertex texNodes[4] = {
- { COORD_UV( 0, 0) }, { COORD_UV( 0, 14) },
- { COORD_UV(128, 0) }, { COORD_UV(128, 14) }
+ { SCALE(1), SCALE(1) }, { SCALE(1), SCALE(14) },
+ { SCALE(128), SCALE(1) }, { SCALE(128), SCALE(14) }
};
float angleStep = ((2 * PI) / _tvHeight);
while (1) {
- WaitSema(_timerSema);
- if (_runAnim && !g_DmacCmd && !g_VblankCmd) {
- if (PollSema(_screenSema) > 0) {
- drawScreen(); // draw the last screen the engine did again
-
- _dmaPipe->setAlphaBlend(SOURCE_COLOR, ZERO_COLOR, SOURCE_ALPHA, DEST_COLOR, 0);
- yPos -= scrlSpeed;
- if (yPos <= -LINE_SPACE) {
- yPos += LINE_SPACE;
- texSta++;
- }
+ do {
+ WaitSema(g_AnimSema);
+ } while (!g_RunAnim);
+
+ if (PollSema(_screenSema) > 0) { // make sure no thread is currently drawing
+ WaitSema(g_DmacSema); // dma transfers have to be finished
+ WaitSema(g_VblankSema); // wait for image, if there is one...
+
+ // redraw the engine's last frame
+ _dmaPipe->flatRect(kFullScreen + 0, kFullScreen + 1, GS_RGBA(0, 0, 0, 0)); // clear screen
+
+ if (_showOverlay) {
+ _dmaPipe->setTex(_texPtrs[SCREEN], _width, TEX_POW, TEX_POW, GS_PSMCT16, 0, 0, 0, 0);
+ _dmaPipe->textureRect(kFullScreen + 0, kFullScreen + 1, _texCoords + 0, _texCoords + 1);
+ } else {
+ _dmaPipe->setTex(_texPtrs[SCREEN], _pitch, TEX_POW, TEX_POW, GS_PSMT8, _clutPtrs[SCREEN], 0, 64, GS_PSMCT32);
+ _dmaPipe->textureRect(_blitCoords + 0, _blitCoords + 1, _texCoords + 0, _texCoords + 1);
+ }
- float drawY = yPos;
-
- for (int i = 0; i < texMax; i++) {
- uint8 texIdx = (texSta + i) & 0xF;
-
- float x[4] = { -64.0, -64.0, 64.0, 64.0 };
- float y[4];
- y[0] = y[2] = drawY - _tvHeight / 2 - LINE_SPACE / 2;
- y[1] = y[3] = y[0] + LINE_SPACE;
- float z[4] = { 0.0, 0.0, 0.0, 0.0 };
- GsVertex nodes[4];
-
- float angle = PI / 2 + angleStep * drawY;
- float rotSin = sinf(angle);
- float rotCos = cosf(angle);
- for (int coord = 0; coord < 4; coord++) {
- z[coord] = rotCos * x[coord];
- x[coord] = rotSin * x[coord];
-
- nodes[coord].z = 0;
- nodes[coord].x = (uint16)(((V * x[coord]) / (z[coord] + V + Z_TRANSL)) * 16);
- nodes[coord].y = (uint16)(((V * y[coord]) / (z[coord] + V + Z_TRANSL)) * 16);
- nodes[coord].x += SCALE(_tvWidth - 80 + ORG_X);
- nodes[coord].y += SCALE(_tvHeight / 2 + ORG_Y);
- }
-
- uint32 texPtr = _texPtrs[TEXT] + 128 * 16 * 4 * (texIdx >> 1);
- if (texIdx & 1)
- _dmaPipe->setTex(_texPtrs[TEXT], 128, 7, 4, GS_PSMT4HL, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
- else
- _dmaPipe->setTex(_texPtrs[TEXT], 128, 7, 4, GS_PSMT4HH, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
-
- _dmaPipe->textureRect(nodes + 0, nodes + 1, nodes + 2, nodes + 3,
- texNodes + 0, texNodes + 1, texNodes + 2, texNodes + 3, GS_RGBA(0x80, 0x80, 0x80, 0x80));
-
- drawY += LINE_SPACE;
+ _dmaPipe->setAlphaBlend(SOURCE_COLOR, ZERO_COLOR, SOURCE_ALPHA, DEST_COLOR, 0);
+ yPos -= scrlSpeed;
+ if (yPos <= -LINE_SPACE) {
+ yPos += LINE_SPACE;
+ texSta++;
+ }
+
+ float drawY = yPos;
+
+ for (int i = 0; i < texMax; i++) {
+ uint8 texIdx = (texSta + i) & 0xF;
+
+ float x[4] = { -64.0, -64.0, 64.0, 64.0 };
+ float y[4];
+ y[0] = y[2] = drawY - _tvHeight / 2 - LINE_SPACE / 2;
+ y[1] = y[3] = y[0] + LINE_SPACE;
+ float z[4];
+ GsVertex nodes[4];
+
+ float angle = PI / 2 + angleStep * drawY;
+ float rotSin = sinf(angle);
+ float rotCos = cosf(angle);
+ for (int coord = 0; coord < 4; coord++) {
+ z[coord] = rotCos * x[coord];
+ x[coord] = rotSin * x[coord];
+
+ nodes[coord].z = 0;
+ nodes[coord].x = (uint16)(((V * x[coord]) / (z[coord] + V + Z_TRANSL)) * 16);
+ nodes[coord].y = (uint16)(((V * y[coord]) / (z[coord] + V + Z_TRANSL)) * 16);
+ nodes[coord].x += SCALE(_tvWidth - 80 + ORG_X);
+ nodes[coord].y += SCALE(_tvHeight / 2 + ORG_Y);
}
- g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler
- _dmaPipe->flush();
- _curDrawBuf ^= 1;
- _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0);
- _dmaPipe->setAlphaBlend(DEST_COLOR, ZERO_COLOR, SOURCE_ALPHA, SOURCE_COLOR, 0);
- SignalSema(_screenSema);
+
+ uint32 texPtr = _texPtrs[TEXT] + 128 * 16 * 4 * (texIdx >> 1);
+ if (texIdx & 1)
+ _dmaPipe->setTex(_texPtrs[TEXT], 128, 7, 4, GS_PSMT4HL, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
+ else
+ _dmaPipe->setTex(_texPtrs[TEXT], 128, 7, 4, GS_PSMT4HH, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
+
+ _dmaPipe->textureRect(nodes + 0, nodes + 1, nodes + 2, nodes + 3,
+ texNodes + 0, texNodes + 1, texNodes + 2, texNodes + 3, GS_RGBA(0x80, 0x80, 0x80, 0x80));
+
+ drawY += LINE_SPACE;
}
+ g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler
+ _dmaPipe->flush();
+ _curDrawBuf ^= 1;
+ _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0);
+ _dmaPipe->setAlphaBlend(DEST_COLOR, ZERO_COLOR, SOURCE_ALPHA, SOURCE_COLOR, 0);
+
+ SignalSema(_screenSema);
}
}
}
-void Gs2dScreen::timerTick(void) {
- if (_runAnim)
- SignalSema(_timerSema);
-}
-
void runAnimThread(Gs2dScreen *param) {
param->animThread();
}
@@ -533,11 +551,10 @@ void createAnimThread(Gs2dScreen *screen) {
ee_thread_t animThread, thisThread;
ReferThreadStatus(GetThreadId(), &thisThread);
- animThread.initial_priority = thisThread.current_priority - 1;
+ animThread.initial_priority = thisThread.current_priority - 3;
animThread.stack = malloc(ANIM_STACK_SIZE);
animThread.stack_size = ANIM_STACK_SIZE;
animThread.func = (void *)runAnimThread;
- //animThread.gp_reg = _gp; for some reason _gp is always NULL
asm("move %0, $gp\n": "=r"(animThread.gp_reg));
int tid = CreateThread(&animThread);
diff --git a/backends/ps2/Gs2dScreen.h b/backends/ps2/Gs2dScreen.h
index 95ae2b522c..7f011b5a8a 100644
--- a/backends/ps2/Gs2dScreen.h
+++ b/backends/ps2/Gs2dScreen.h
@@ -23,9 +23,7 @@
#define __GS2DSCREEN_H__
#include "sysdefs.h"
-
-#define SUPPORT_STUPID_OVERLAYS
-
+#include "backends/ps2/DmaPipe.h"
enum TVMode {
TV_DONT_CARE = 0,
TV_PAL,
@@ -37,7 +35,7 @@ enum GsInterlace {
GS_INTERLACED
};
-class DmaPipe;
+//class DmaPipe;
class Gs2dScreen {
public:
@@ -62,17 +60,15 @@ public:
void setShakePos(int shake);
void animThread(void);
- void timerTick(void);
void wantAnim(bool runIt);
private:
void createAnimTextures(void);
- void drawScreen(void);
- static inline void waitForDma(void);
- static inline void waitForImage(void);
DmaPipe *_dmaPipe;
uint8 _videoMode;
uint16 _tvWidth, _tvHeight;
+ GsVertex _blitCoords[2];
+ TexVertex _texCoords[2];
uint8 _curDrawBuf;
uint32 _frameBufPtr[2]; //
@@ -91,8 +87,7 @@ private:
uint8 *_screenBuf;
uint32 *_clut;
- bool _runAnim;
- int _timerSema, _screenSema;
+ int _screenSema;
static const uint32 _binaryClut[16];
static const uint8 _binaryData[4 * 14 * 2];
static const uint16 _binaryPattern[16];
diff --git a/backends/ps2/GsDefs.h b/backends/ps2/GsDefs.h
index c744eeaa2b..e3966b3a3b 100644
--- a/backends/ps2/GsDefs.h
+++ b/backends/ps2/GsDefs.h
@@ -34,9 +34,14 @@
#define GS_DISPLAY1 *((volatile uint64*)0x12000080)
#define GS_BGCOLOUR *((volatile uint64*)0x120000E0)
-#define GS_SET_CSR(signal, finish, hsint, vsint, flush, reset, field) \
- ((signal) | ((finish) << 1) | ((hsint) << 2) | ((vsint) << 3) | \
- ((flush) << 8) | ((reset) << 9) | ((field) << 13))
+enum GS_CSR_FIELDS {
+ CSR_SIGNAL = 1 << 0,
+ CSR_FINISH = 1 << 1,
+ CSR_HSYNC = 1 << 2,
+ CSR_VSYNC = 1 << 3,
+ CSR_FLUSH = 1 << 8,
+ CSR_RESET = 1 << 9
+};
#define GS_SET_PMODE(readC1, readC2, alphaSel, alphaOut, alphaBlend, alphaFixed) \
((readC1) | ((readC2) << 1) | ((alphaSel) << 5) | ((alphaOut) << 6) | ((alphaBlend) << 7) | ((alphaFixed) << 8))
diff --git a/backends/ps2/asyncfio.cpp b/backends/ps2/asyncfio.cpp
index 605f6c9aa5..9d6c27b3c3 100644
--- a/backends/ps2/asyncfio.cpp
+++ b/backends/ps2/asyncfio.cpp
@@ -25,12 +25,15 @@
#include <fileio.h>
#include <assert.h>
#include <string.h>
+#include <fileXio_rpc.h>
+
+#define DEFAULT_MODE (FIO_S_IRUSR | FIO_S_IWUSR | FIO_S_IRGRP | FIO_S_IWGRP | FIO_S_IROTH | FIO_S_IWOTH)
extern void sioprintf(const char *zFormat, ...);
AsyncFio::AsyncFio(void) {
_runningOp = NULL;
- memset(_ioSlots, 0, MAX_HANDLES * sizeof(int));
+ memset((int *)_ioSlots, 0, MAX_HANDLES * sizeof(int));
ee_sema_t newSema;
newSema.init_count = 1;
newSema.max_count = 1;
@@ -45,9 +48,9 @@ int AsyncFio::open(const char *name, int ioMode) {
WaitSema(_ioSema);
checkSync();
int res;
- fioOpen(name, ioMode);
- int fioRes = fioSync(FIO_WAIT, &res);
- if (fioRes != FIO_COMPLETE) {
+ fileXioOpen(name, ioMode, DEFAULT_MODE);
+ int fioRes = fileXioWaitAsync(FXIO_WAIT, &res);
+ if (fioRes != FXIO_COMPLETE) {
sioprintf("ERROR: fioOpen(%s, %X):\n", name, ioMode);
sioprintf(" fioSync returned %d, open res = %d\n", fioRes, res);
SleepThread();
@@ -59,13 +62,20 @@ int AsyncFio::open(const char *name, int ioMode) {
void AsyncFio::close(int handle) {
WaitSema(_ioSema);
checkSync();
- fioClose(handle);
+ fileXioClose(handle);
+ int res;
+ assert(fileXioWaitAsync(FXIO_WAIT, &res) == FXIO_COMPLETE);
+ if (res != 0) {
+ sioprintf("ERROR: fileXioClose failed, EC %d", res);
+ SleepThread();
+ }
+ _ioSlots[handle] = 0;
SignalSema(_ioSema);
}
void AsyncFio::checkSync(void) {
if (_runningOp) {
- assert(fioSync(FIO_WAIT, _runningOp) == FIO_COMPLETE);
+ assert(fileXioWaitAsync(FXIO_WAIT, (int *)_runningOp) == FXIO_COMPLETE);
_runningOp = NULL;
}
}
@@ -75,7 +85,7 @@ void AsyncFio::read(int fd, void *dest, unsigned int len) {
checkSync();
assert(fd < MAX_HANDLES);
_runningOp = _ioSlots + fd;
- fioRead(fd, dest, len);
+ fileXioRead(fd, (unsigned char*)dest, len);
SignalSema(_ioSema);
}
@@ -84,14 +94,26 @@ void AsyncFio::write(int fd, const void *src, unsigned int len) {
checkSync();
assert(fd < MAX_HANDLES);
_runningOp = _ioSlots + fd;
- fioWrite(fd, (unsigned char*)src, len);
+ fileXioWrite(fd, (unsigned char*)src, len);
SignalSema(_ioSema);
}
int AsyncFio::seek(int fd, int offset, int whence) {
WaitSema(_ioSema);
checkSync();
- int res = fioLseek(fd, offset, whence);
+ fileXioLseek(fd, offset, whence);
+ int res;
+ assert(fileXioWaitAsync(FXIO_WAIT, &res) == FXIO_COMPLETE);
+ SignalSema(_ioSema);
+ return res;
+}
+
+int AsyncFio::mkdir(const char *name) {
+ WaitSema(_ioSema);
+ checkSync();
+ fileXioMkdir(name, DEFAULT_MODE);
+ int res;
+ assert(fileXioWaitAsync(FXIO_WAIT, &res) == FXIO_COMPLETE);
SignalSema(_ioSema);
return res;
}
@@ -100,15 +122,17 @@ int AsyncFio::sync(int fd) {
WaitSema(_ioSema);
if (_runningOp == _ioSlots + fd)
checkSync();
+ int res = _ioSlots[fd];
+ _ioSlots[fd] = 0;
SignalSema(_ioSema);
- return _ioSlots[fd];
+ return res;
}
bool AsyncFio::poll(int fd) {
bool retVal = false;
- if (PollSema(_ioSema) > 0) {
+ if (PollSema(_ioSema) >= 0) {
if (_runningOp == _ioSlots + fd) {
- if (fioSync(FIO_NOWAIT, _runningOp) == FIO_COMPLETE) {
+ if (fileXioWaitAsync(FXIO_NOWAIT, (int *)_runningOp) == FXIO_COMPLETE) {
_runningOp = NULL;
retVal = true;
} else
@@ -124,7 +148,7 @@ bool AsyncFio::fioAvail(void) {
bool retVal = false;
if (PollSema(_ioSema) > 0) {
if (_runningOp) {
- if (fioSync(FIO_NOWAIT, _runningOp) == FIO_COMPLETE) {
+ if (fileXioWaitAsync(FXIO_NOWAIT, (int *)_runningOp) == FXIO_COMPLETE) {
_runningOp = NULL;
retVal = true;
} else
diff --git a/backends/ps2/asyncfio.h b/backends/ps2/asyncfio.h
index 3518126168..765b7eb74f 100644
--- a/backends/ps2/asyncfio.h
+++ b/backends/ps2/asyncfio.h
@@ -30,13 +30,14 @@ public:
void read(int fd, void *dest, unsigned int len);
void write(int fd, const void *src, unsigned int len);
int seek(int fd, int offset, int whence);
+ int mkdir(const char *name);
int sync(int fd);
bool poll(int fd);
bool fioAvail(void);
private:
void checkSync(void);
int _ioSema;
- int *_runningOp;
- int _ioSlots[MAX_HANDLES];
+ volatile int * volatile _runningOp;
+ volatile int _ioSlots[MAX_HANDLES];
};
diff --git a/backends/ps2/fileio.cpp b/backends/ps2/fileio.cpp
index 360666e741..f8d86712e5 100644
--- a/backends/ps2/fileio.cpp
+++ b/backends/ps2/fileio.cpp
@@ -26,385 +26,367 @@
#include <fileio.h>
#include <assert.h>
#include <string.h>
-//#include <fileXio_rpc.h>
#include <cdvd_rpc.h>
#include "backends/ps2/asyncfio.h"
#include "base/engine.h"
#include "common/file.h"
-#define CACHE_BUF_SIZE (2048 * 16)
-#define MAX_CACHED_FILES 8
-
-//#define DEFAULT_MODE (FIO_S_IRUSR | FIO_S_IWUSR | FIO_S_IRGRP | FIO_S_IWGRP | FIO_S_IROTH | FIO_S_IWOTH)
+#define CACHE_SIZE (2048 * 32)
+#define MAX_READ_STEP (2048 * 16)
+#define MAX_CACHED_FILES 6
+#define CACHE_READ_THRESHOLD (16 * 2048)
+#define CACHE_FILL_MIN (2048 * 24)
extern void sioprintf(const char *zFormat, ...);
AsyncFio fio;
-AccessFio::AccessFio(void) {
- _handle = -1;
-}
-
-AccessFio::~AccessFio(void) {
- if (_handle >= 0)
- fio.close(_handle);
-}
-
-int32 AccessFio::sync(void) {
- return fio.sync(_handle);
-}
-
-bool AccessFio::poll(void) {
- return fio.poll(_handle);
-}
-
-bool AccessFio::fioAvail(void) {
- return fio.fioAvail();
-}
-
-bool AccessFio::open(const char *name, int mode) {
- _handle = fio.open(name, mode);
- return (_handle >= 0);
-}
-
-void AccessFio::read(void *dest, uint32 size) {
- fio.read(_handle, dest, size);
-}
-
-void AccessFio::write(const void *src, uint32 size) {
- fio.write(_handle, src, size);
+Ps2File::Ps2File(int64 cacheId) {
+ _cacheId = cacheId;
}
-int AccessFio::seek(int32 offset, int whence) {
- return fio.seek(_handle, offset, whence);
+Ps2File::~Ps2File(void) {
}
-/*class AccessFioX : public AccessFio{
+class Ps2ReadFile : public Ps2File {
public:
- AccessFioX(void);
- virtual ~AccessFioX(void);
- virtual bool open(const char *name, int mode);
- virtual int read(void *dest, uint32 size);
- virtual int write(const void *src, uint32 size);
- virtual int seek(int32 offset, int whence);
- virtual void sync(int32 *res);
-};
-
-AccessFioX::AccessFioX(void) {
- _handle = -1;
-}
-
-AccessFioX::~AccessFioX(void) {
- if (_handle >= 0)
- fileXioClose(_handle);
-}
-
-void AccessFioX::sync(int32 *res) {
- assert(false);
-}
-
-bool AccessFioX::open(const char *name, int mode) {
- _handle = fileXioOpen(name, mode, DEFAULT_MODE);
- return (_handle >= 0);
-}
-
-int AccessFioX::read(void *dest, uint32 size) {
- return fileXioRead(_handle, (unsigned char*)dest, size);
-}
-
-int AccessFioX::write(const void *src, uint32 size) {
- return fileXioWrite(_handle, (unsigned char*)src, size);
-}
-
-int AccessFioX::seek(int32 offset, int whence) {
- return fileXioLseek(_handle, offset, whence);
-}*/
-
-struct TocNode {
- char name[64];
- TocNode *next, *sub;
- bool isDir;
- uint8 nameLen;
-};
-
-class TocManager {
-public:
- TocManager(void);
- ~TocManager(void);
- void readEntries(const char *root);
- int64 fileExists(const char *name);
- bool haveEntries(void);
+ Ps2ReadFile(int64 cacheId);
+ virtual ~Ps2ReadFile(void);
+ virtual bool open(const char *name);
+ virtual uint32 read(void *dest, uint32 len);
+ virtual uint32 write(const void *src, uint32 len);
+ virtual uint32 tell(void);
+ virtual uint32 size(void);
+ virtual int seek(int32 offset, int origin);
+ virtual bool eof(void);
private:
- void readDir(const char *path, TocNode **node, int level);
- TocNode *_rootNode;
- char _root[256];
- uint8 _rootLen;
-};
+ void cacheReadAhead(void);
+ void cacheReadSync(void);
+ int _fd, _sema;
+ uint8 *_cacheBuf;
+ bool _cacheOpRunning;
+ uint32 _filePos, _physFilePos, _cachePos;
+ uint32 _fileSize, _bytesInCache, _cacheOfs;
-class Ps2File {
-public:
- Ps2File(int64 cacheId);
- ~Ps2File(void);
- bool open(const char *name, int ioMode);
- bool isOpen(void);
- uint32 read(void *dest, uint32 size);
- uint32 write(const void *src, uint32 size);
- uint32 tell(void);
- uint32 size(void);
- int seek(int32 offset, int origin);
- bool eof(void);
- AccessFio *giveHandle(void);
- int64 _cacheId;
- void setSeekReset(void);
-private:
- void checkCache(void);
- void syncCache(void);
- bool _cacheOp;
- bool _seekReset;
-
- bool _forWriting;
- AccessFio *_handle;
- uint8 *_cacheBuf, *_cachePos;
- uint32 _filePos;
- uint32 _cacheBytesLeft;
- uint32 _fSize;
uint32 _readBytesBlock;
};
-Ps2File::Ps2File(int64 cacheId) {
- _handle = NULL;
- _cachePos = _cacheBuf = (uint8*)malloc(CACHE_BUF_SIZE);
- _fSize = _filePos = _cacheBytesLeft = 0;
- _forWriting = false;
+Ps2ReadFile::Ps2ReadFile(int64 cacheId) : Ps2File(cacheId) {
+ _fd = -1;
+ _cacheBuf = (uint8*)memalign(64, CACHE_SIZE);
+
+ _cacheOpRunning = 0;
+ _filePos = _physFilePos = _cachePos = 0;
+ _fileSize = _bytesInCache = _cacheOfs = 0;
+ _cacheOpRunning = false;
_readBytesBlock = 0;
- _cacheOp = false;
- _cacheId = cacheId;
- _seekReset = false;
+
+ ee_sema_t newSema;
+ newSema.init_count = 1;
+ newSema.max_count = 1;
+ _sema = CreateSema(&newSema);
+ assert(_sema >= 0);
}
-Ps2File::~Ps2File(void) {
- if (_handle != NULL) {
- syncCache();
- if (_forWriting && (_cachePos != _cacheBuf)) {
- _handle->write(_cacheBuf, _cachePos - _cacheBuf);
- int res = _handle->sync();
- if (res != (_cachePos - _cacheBuf)) {
- // Fixme: writing operation failed and we noticed
- // too late to return an error to the engine.
- printf("ERROR: flushing the cache on fclose() failed!\n");
- }
- }
- delete _handle;
- }
+Ps2ReadFile::~Ps2ReadFile(void) {
+ if (_cacheOpRunning)
+ cacheReadSync();
free(_cacheBuf);
+ if (_fd >= 0)
+ fio.close(_fd);
+ DeleteSema(_sema);
}
-bool Ps2File::open(const char *name, int ioMode) {
- //if (strncmp(name, "pfs0", 4) == 0)
- // _handle = new AccessFioX();
- //else
- _handle = new AccessFio();
-
- if (_handle->open(name, ioMode)) {
- if (ioMode == O_RDONLY) {
- _fSize = _handle->seek(0, SEEK_END);
- _handle->seek(0, SEEK_SET);
- } else {
- _cacheBytesLeft = CACHE_BUF_SIZE;
- _forWriting = true;
- }
+bool Ps2ReadFile::open(const char *name) {
+ assert(_fd < 0);
+ _fd = fio.open(name, O_RDONLY);
+ if (_fd >= 0) {
+ _fileSize = fio.seek(_fd, 0, SEEK_END);
+ fio.seek(_fd, 0, SEEK_SET);
return true;
- } else {
- delete _handle;
- _handle = NULL;
+ } else
return false;
- }
}
-void Ps2File::setSeekReset(void) {
- _seekReset = true;
+uint32 Ps2ReadFile::tell(void) {
+ WaitSema(_sema);
+ uint32 res = _filePos;
+ SignalSema(_sema);
+ return res;
+}
+
+uint32 Ps2ReadFile::size(void) {
+ WaitSema(_sema);
+ uint32 res = _fileSize;
+ SignalSema(_sema);
+ return res;
}
-bool Ps2File::isOpen(void) {
- return (_handle != NULL);
+bool Ps2ReadFile::eof(void) {
+ WaitSema(_sema);
+ bool res = (_filePos == _fileSize);
+ SignalSema(_sema);
+ return res;
}
-int Ps2File::seek(int32 offset, int origin) {
- assert(!_forWriting);
- syncCache();
- uint32 seekDest;
+int Ps2ReadFile::seek(int32 offset, int origin) {
+ WaitSema(_sema);
+ int seekDest;
+ int res = -1;
switch (origin) {
case SEEK_SET:
seekDest = offset;
break;
case SEEK_CUR:
- if (_seekReset)
- seekDest = offset;
- else
- seekDest = _filePos + offset;
+ seekDest = _filePos + offset;
break;
case SEEK_END:
- seekDest = _fSize + offset;
+ seekDest = _fileSize + offset;
break;
default:
- return -1;
+ seekDest = -1;
+ break;
}
- _seekReset = false;
- if (seekDest <= _fSize) {
- if ((seekDest >= _filePos) && (seekDest < _filePos + _cacheBytesLeft)) {
- uint32 cacheOffset = (seekDest - _filePos);
- _cacheBytesLeft -= cacheOffset;
- _cachePos += cacheOffset;
- } else {
- _handle->seek(seekDest, SEEK_SET);
- _cacheBytesLeft = 0;
- }
+ if ((seekDest >= 0) && (seekDest <= _fileSize)) {
_filePos = seekDest;
- _readBytesBlock = 0;
- return 0;
- } else
- return -1;
+ res = 0;
+ }
+ SignalSema(_sema);
+ return res;
}
-bool Ps2File::eof(void) {
- if ((!_forWriting) && (_filePos == _fSize))
- return true;
- else
- return false;
-}
+void Ps2ReadFile::cacheReadAhead(void) {
+ if (_cacheOpRunning) {
+ // there's already some cache read running
+ if (fio.poll(_fd)) // did it finish?
+ cacheReadSync(); // yes.
+ }
+ if ((!_cacheOpRunning) && (_readBytesBlock >= CACHE_READ_THRESHOLD) && fio.fioAvail()) {
+ // the engine seems to do sequential reads and there are no other I/Os going on. read ahead.
+ uint32 cachePosEnd = _cachePos + _bytesInCache;
+
+ if (_cachePos > _filePos)
+ return; // there was a seek in the meantime, don't cache.
+ if (cachePosEnd - _filePos >= CACHE_FILL_MIN)
+ return; // cache is full enough.
+ if (cachePosEnd == _fileSize)
+ return; // can't read beyond EOF.
+
+ assert(cachePosEnd < _fileSize);
+
+ if (_cachePos + _bytesInCache <= _filePos) {
+ _cacheOfs = _bytesInCache = 0;
+ _cachePos = cachePosEnd = _filePos;
+ assert(_filePos == _physFilePos);
+ } else {
+ uint32 cacheDiff = _filePos - _cachePos;
+ assert(_bytesInCache >= cacheDiff);
+ _bytesInCache -= cacheDiff;
+ _cachePos += cacheDiff;
+ _cacheOfs = (_cacheOfs + cacheDiff) % CACHE_SIZE;
+ }
-void Ps2File::checkCache(void) {
- if (!_forWriting) {
- if (_readBytesBlock > 32768) {
- if (_cacheBytesLeft <= (CACHE_BUF_SIZE / 4)) {
- if (_cacheBytesLeft && (_cachePos != _cacheBuf)) {
- memmove(_cacheBuf, _cachePos, _cacheBytesLeft);
- }
- _cachePos = _cacheBuf;
- _handle->read(_cacheBuf + _cacheBytesLeft, CACHE_BUF_SIZE - _cacheBytesLeft);
- _cacheOp = true;
+ if (_physFilePos != cachePosEnd) {
+ sioprintf("unexpected _physFilePos %d cache %d %d", _physFilePos, _cacheOfs, _bytesInCache);
+ _physFilePos = fio.seek(_fd, cachePosEnd, SEEK_SET);
+ if (_physFilePos != cachePosEnd) {
+ sioprintf("cache seek error: seek to %d instead of %d, fs = %d", _physFilePos, cachePosEnd, _fileSize);
+ return;
}
- }
+ }
+
+ uint32 cacheDest = (_cacheOfs + _bytesInCache) % CACHE_SIZE;
+ uint32 cacheRead = CACHE_SIZE - _bytesInCache;
+ if (cacheDest + cacheRead > CACHE_SIZE)
+ cacheRead = CACHE_SIZE - cacheDest;
+ if (cacheRead > MAX_READ_STEP)
+ cacheRead = MAX_READ_STEP;
+
+ assert(cacheRead);
+
+ _cacheOpRunning = true;
+ fio.read(_fd, _cacheBuf + cacheDest, cacheRead);
}
}
-void Ps2File::syncCache(void) {
- if ((!_forWriting) && _cacheOp) {
- int cacheRes = _handle->sync();
- assert(cacheRes >= 0);
- _cacheBytesLeft += cacheRes;
- _cacheOp = false;
+void Ps2ReadFile::cacheReadSync(void) {
+ if (_cacheOpRunning) {
+ int res = fio.sync(_fd);
+ assert(res >= 0);
+ _bytesInCache += res;
+ _physFilePos += res;
+ _cacheOpRunning = false;
}
}
-uint32 Ps2File::read(void *dest, uint32 size) {
- assert(!_forWriting);
- syncCache();
- if (_seekReset)
- seek(0, SEEK_SET);
- _readBytesBlock += size;
-
+uint32 Ps2ReadFile::read(void *dest, uint32 len) {
+ WaitSema(_sema);
uint8 *destBuf = (uint8*)dest;
- while (size) {
- if (_cacheBytesLeft != 0) {
- uint32 doCopy = (size >= _cacheBytesLeft) ? _cacheBytesLeft : size;
- memcpy(destBuf, _cachePos, doCopy);
- size -= doCopy;
- _cacheBytesLeft -= doCopy;
- _cachePos += doCopy;
- destBuf += doCopy;
- _filePos += doCopy;
- }
- if (size > 0) {
- assert(_cacheBytesLeft == 0);
- if (size >= CACHE_BUF_SIZE) {
- int readRes;
- do {
- _handle->read(destBuf, size);
- readRes = _handle->sync();
- _filePos += readRes;
- destBuf += readRes;
- size -= readRes;
- } while (size && readRes);
- if (size)
- printf("read operation failed, %d bytes left to read\n", size);
- return destBuf - (uint8*)dest;
- } else {
- uint32 doRead = size;
- if ((doRead < 2048) && (_cacheId >= 0))
- doRead = 2048;
- memset(_cacheBuf, 'A', 0x20);
- _handle->read(_cacheBuf, doRead);
- _cacheBytesLeft = _handle->sync();
- _cachePos = _cacheBuf;
- if (_cacheBytesLeft == 0) {
- return destBuf - (uint8*)dest;
- }
+ if ((_filePos < _cachePos) || (_filePos + len > _cachePos + _bytesInCache))
+ cacheReadSync(); // we have to read from CD, sync cache.
+
+ while (len) {
+ if ((_filePos >= _cachePos) && (_filePos < _cachePos + _bytesInCache)) { // read from cache
+ uint32 staPos = (_cacheOfs + (_filePos - _cachePos)) % CACHE_SIZE;
+ uint32 cpyLen = _bytesInCache - (_filePos - _cachePos);
+ if (cpyLen > len)
+ cpyLen = len;
+ if (staPos + cpyLen > CACHE_SIZE)
+ cpyLen = CACHE_SIZE - staPos;
+
+ assert(cpyLen);
+ memcpy(destBuf, _cacheBuf + staPos, cpyLen);
+ _filePos += cpyLen;
+ destBuf += cpyLen;
+ _readBytesBlock += len;
+ len -= cpyLen;
+ } else { // cache miss
+ assert(!_cacheOpRunning);
+ if (_physFilePos != _filePos) {
+ if ((_filePos < _physFilePos) || (_filePos > _physFilePos + (CACHE_SIZE / 2)))
+ _readBytesBlock = 0; // reset cache hit count
+
+ if (fio.seek(_fd, _filePos, SEEK_SET) == _filePos)
+ _physFilePos = _filePos;
+ else
+ break; // read beyond EOF
}
+ assert(_physFilePos == _filePos);
+ int doRead = (len > MAX_READ_STEP) ? MAX_READ_STEP : len;
+ if (doRead < 2048)
+ doRead = 2048;
+
+ fio.read(_fd, _cacheBuf, doRead);
+ _cachePos = _filePos;
+ _cacheOfs = 0;
+ _bytesInCache = fio.sync(_fd);
+ _physFilePos = _filePos + _bytesInCache;
+ if (!_bytesInCache)
+ break; // EOF
}
}
- checkCache();
+ cacheReadAhead();
+ SignalSema(_sema);
return destBuf - (uint8*)dest;
}
-uint32 Ps2File::write(const void *src, uint32 size) {
- assert(_forWriting && (!_seekReset));
- const uint8 *srcBuf = (const uint8*)src;
+uint32 Ps2ReadFile::write(const void *src, uint32 len) {
+ sioprintf("write request on Ps2ReadFile!");
+ SleepThread();
+ return 0;
+}
+
+class Ps2WriteFile : public Ps2File {
+public:
+ Ps2WriteFile(int64 cacheId);
+ virtual ~Ps2WriteFile(void);
+ virtual bool open(const char *name);
+ virtual uint32 read(void *dest, uint32 len);
+ virtual uint32 write(const void *src, uint32 len);
+ virtual uint32 tell(void);
+ virtual uint32 size(void);
+ virtual int seek(int32 offset, int origin);
+ virtual bool eof(void);
+private:
+ int _fd;
+ uint8 *_cacheBuf;
+ uint32 _filePos, _bytesInCache;
+};
+
+Ps2WriteFile::Ps2WriteFile(int64 cacheId) : Ps2File(cacheId) {
+ _fd = -1;
+ _cacheBuf = (uint8*)malloc(CACHE_SIZE);
+ _filePos = _bytesInCache = 0;
+}
+
+Ps2WriteFile::~Ps2WriteFile(void) {
+ if ((_fd >= 0) && (_bytesInCache)) {
+ fio.write(_fd, _cacheBuf, _bytesInCache);
+ int wrRes = fio.sync(_fd);
+ if (wrRes != _bytesInCache) // too late to return an error
+ printf("Cache flush on fclose(): Unable to write %d cached bytes to mc, only %d bytes written\n", _bytesInCache, wrRes);
+ }
+ if (_fd >= 0)
+ fio.close(_fd);
+ free(_cacheBuf);
+}
+
+bool Ps2WriteFile::open(const char *name) {
+ _fd = fio.open(name, O_WRONLY | O_CREAT | O_TRUNC);
+ return (_fd >= 0);
+}
+uint32 Ps2WriteFile::read(void *dest, uint32 len) {
+ printf("ERROR: Read request on Ps2WriteFile\n");
+ SleepThread();
+ return 0;
+}
+
+uint32 Ps2WriteFile::write(const void *src, uint32 len) {
+ uint32 size = len;
+ uint8 *srcBuf = (uint8*)src;
while (size) {
- uint32 doWrite = (size > _cacheBytesLeft) ? _cacheBytesLeft : size;
- memcpy(_cachePos, srcBuf, doWrite);
- _cachePos += doWrite;
- _cacheBytesLeft -= doWrite;
- size -= doWrite;
- srcBuf += doWrite;
- _filePos += doWrite;
-
- if (_cacheBytesLeft == 0) {
- _handle->write(_cacheBuf, CACHE_BUF_SIZE);
- int res = _handle->sync();
- if (res == CACHE_BUF_SIZE) {
- _cachePos = _cacheBuf;
- _cacheBytesLeft = CACHE_BUF_SIZE;
- } else {
- printf("cache write operation failed, only %d bytes written\n", res);
- return 0;
- }
+ uint32 doCpy = (len > CACHE_SIZE - _bytesInCache) ? (CACHE_SIZE - _bytesInCache) : len;
+ if (doCpy) {
+ memcpy(_cacheBuf + _bytesInCache, srcBuf, doCpy);
+ _bytesInCache += doCpy;
+ srcBuf += doCpy;
+ size -= doCpy;
+ }
- if (size >= CACHE_BUF_SIZE) {
- int writeRes;
- do {
- _handle->write(srcBuf, size);
- writeRes = _handle->sync();
- _filePos += writeRes;
- srcBuf += writeRes;
- size -= writeRes;
- } while (size && writeRes);
- if (size)
- printf("write operation failed, %d bytes left to write\n", size);
- return srcBuf - (uint8*)src;
+ if (_bytesInCache == CACHE_SIZE) {
+ fio.write(_fd, _cacheBuf, _bytesInCache);
+ int wrRes = fio.sync(_fd);
+ if (wrRes != _bytesInCache) {
+ printf("Unable to flush %d cached bytes to memory card!\n", _bytesInCache);
+ return 0;
}
+ _filePos += _bytesInCache;
+ _bytesInCache = 0;
}
}
- return srcBuf - (uint8*)src;
+ return len;
+}
+
+uint32 Ps2WriteFile::tell(void) {
+ return _bytesInCache + _filePos;
}
-uint32 Ps2File::tell(void) {
- if (_seekReset)
- seek(0, SEEK_SET);
- return _filePos;
+uint32 Ps2WriteFile::size(void) {
+ return tell();
}
-uint32 Ps2File::size(void) {
- assert(!_forWriting);
- return _fSize;
+int Ps2WriteFile::seek(int32 offset, int origin) {
+ printf("Seek(%d/%d) request on Ps2WriteFile\n", offset, origin);
+ SleepThread();
+ return 0;
}
-AccessFio *Ps2File::giveHandle(void) {
- assert(_handle);
- return _handle;
+bool Ps2WriteFile::eof(void) {
+ return true;
}
+struct TocNode {
+ char name[64];
+ TocNode *next, *sub;
+ bool isDir;
+ uint8 nameLen;
+};
+
+class TocManager {
+public:
+ TocManager(void);
+ ~TocManager(void);
+ void readEntries(const char *root);
+ int64 fileExists(const char *name);
+ bool haveEntries(void);
+private:
+ void readDir(const char *path, TocNode **node, int level);
+ TocNode *_rootNode;
+ char _root[256];
+ uint8 _rootLen;
+};
+
TocManager tocManager;
struct FioHandleCache {
@@ -415,12 +397,8 @@ struct FioHandleCache {
static FioHandleCache *cacheListStart = NULL;
static FioHandleCache *cacheListEnd = NULL;
static int cacheListLen = 0;
+static int openFileCount = 0;
static int cacheListSema = -1;
-static bool wantHandleCaching = true;
-
-extern void ps2_disableHandleCaching(void) {
- wantHandleCaching = false;
-}
Ps2File *findInCache(int64 id);
@@ -435,42 +413,44 @@ FILE *ps2_fopen(const char *fname, const char *mode) {
if (!tocManager.haveEntries() && g_engine) // read the TOC the first time the engine opens a file
tocManager.readEntries(g_engine->getGameDataPath());
- int fioMode = 0;
- switch(*mode) {
- case 'r':
- fioMode = O_RDONLY;
- break;
- case 'w':
- fioMode = O_WRONLY | O_CREAT | O_TRUNC;
- break;
- default:
- printf("unsupported mode \"%s\" for file \"%s\"\n", mode, fname);
- return NULL;
+ if (((mode[0] != 'r') && (mode[0] != 'w')) || ((mode[1] != '\0') && (mode[1] != 'b'))) {
+ printf("unsupported mode \"%s\" for file \"%s\"\n", mode, fname);
+ return NULL;
}
+
+ bool rdOnly = (mode[0] == 'r');
+
int64 cacheId = -1;
- if ((fioMode == O_RDONLY) && tocManager.haveEntries())
+ if (rdOnly && tocManager.haveEntries())
cacheId = tocManager.fileExists(fname);
if (cacheId != 0) {
Ps2File *file = findInCache(cacheId);
- if (file)
+ if (file) {
+ //sioprintf("open from cache: %s (%d) [%d]\n", fname, cacheId, file->_handle->_handle);
return (FILE*)file;
-
- if ((mode[1] != 'b') && (mode[1] != '\0')) {
- printf("unsupported mode \"%s\" for file \"%s\"\n", mode, fname);
- return NULL;
}
- file = new Ps2File(cacheId);
- if (file->open(fname, fioMode))
+
+ if (rdOnly) {
+ // smush files need a quite different caching behaviour than normal data files
+ if (strstr(fname, ".san") || strstr(fname, ".SAN") || strstr(fname, ".San"))
+ file = new Ps2SmushFile(cacheId);
+ else
+ file = new Ps2ReadFile(cacheId);
+ } else
+ file = new Ps2WriteFile(cacheId);
+
+ if (file->open(fname)) {
+ openFileCount++;
return (FILE*)file;
- else
+ } else
delete file;
}
return NULL;
}
void checkCacheListLen(void) {
- while (cacheListLen > MAX_CACHED_FILES) {
+ while ((cacheListLen > MAX_CACHED_FILES) || ((openFileCount > 13) && cacheListLen)) {
assert(cacheListEnd && cacheListStart);
delete cacheListEnd->file;
cacheListEnd->prev->next = NULL;
@@ -478,21 +458,24 @@ void checkCacheListLen(void) {
cacheListEnd = cacheListEnd->prev;
delete temp;
cacheListLen--;
+ openFileCount--;
}
}
int ps2_fclose(FILE *stream) {
Ps2File *file = (Ps2File*)stream;
- if ((file->_cacheId > 0) && wantHandleCaching) { // this is a file on the CD, could be smart to cache it
+ if (file->_cacheId > 0) { // this is a file on the CD, could be smart to cache it
FioHandleCache *newHandle = new FioHandleCache;
newHandle->file = file;
- file->setSeekReset();
+ file->seek(0, SEEK_SET);
WaitSema(cacheListSema);
if (!cacheListEnd) {
+ assert(!cacheListStart);
newHandle->prev = newHandle->next = NULL;
cacheListEnd = cacheListStart = newHandle;
} else {
+ assert(cacheListStart);
newHandle->prev = NULL;
newHandle->next = cacheListStart;
cacheListStart->prev = newHandle;
@@ -501,13 +484,15 @@ int ps2_fclose(FILE *stream) {
cacheListLen++;
checkCacheListLen();
SignalSema(cacheListSema);
- } else
+ } else {
+ openFileCount--;
delete file;
+ }
return 0;
}
Ps2File *findInCache(int64 id) {
- if ((id <= 0) || !wantHandleCaching)
+ if (id <= 0)
return NULL;
WaitSema(cacheListSema);
FioHandleCache *node = cacheListStart;
@@ -537,11 +522,11 @@ int ps2_fseek(FILE *stream, long offset, int origin) {
return ((Ps2File*)stream)->seek(offset, origin);
}
-long ps2_ftell(FILE *stream) {
+uint32 ps2_ftell(FILE *stream) {
return ((Ps2File*)stream)->tell();
}
-long ps2_fsize(FILE *stream) {
+uint32 ps2_fsize(FILE *stream) {
return ((Ps2File*)stream)->size();
}
diff --git a/backends/ps2/fileio.h b/backends/ps2/fileio.h
index 8b9fd431fd..fc10ad8bd8 100644
--- a/backends/ps2/fileio.h
+++ b/backends/ps2/fileio.h
@@ -24,30 +24,44 @@
#include "scummsys.h"
-class AccessFio {
+class Ps2File {
public:
- AccessFio(void);
- virtual ~AccessFio(void);
- virtual bool open(const char *name, int mode);
- virtual void read(void *dest, uint32 size);
- virtual void write(const void *src, uint32 size);
- virtual int seek(int32 offset, int whence);
- virtual int32 sync(void);
- virtual bool poll(void);
- virtual bool fioAvail(void);
-protected:
- int _handle;
+ Ps2File(int64 cacheId);
+ virtual ~Ps2File(void);
+ virtual bool open(const char *name) = 0;
+ virtual uint32 read(void *dest, uint32 len) = 0;
+ virtual uint32 write(const void *src, uint32 len) = 0;
+ virtual uint32 tell(void) = 0;
+ virtual uint32 size(void) = 0;
+ virtual int seek(int32 offset, int origin) = 0;
+ virtual bool eof(void) = 0;
+ int64 _cacheId;
+private:
};
-class File;
+class Ps2SmushFile : public Ps2File {
+public:
+ Ps2SmushFile(int64 cacheId);
+ virtual ~Ps2SmushFile(void);
+ virtual bool open(const char *name);
+ virtual uint32 read(void *dest, uint32 len);
+ virtual uint32 write(const void *src, uint32 len);
+ virtual uint32 tell(void);
+ virtual uint32 size(void);
+ virtual int seek(int32 offset, int origin);
+ virtual bool eof(void);
+private:
+ uint32 _filePos, _fileSize;
+ int _id;
+};
FILE *ps2_fopen(const char *fname, const char *mode);
int ps2_fclose(FILE *stream);
int ps2_fflush(FILE *stream);
int ps2_fseek(FILE *stream, long offset, int origin);
-long ps2_ftell(FILE *stream);
+uint32 ps2_ftell(FILE *stream);
int ps2_feof(FILE *stream);
-long ps2_fsize(FILE *stream);
+uint32 ps2_fsize(FILE *stream);
size_t ps2_fread(void *buf, size_t r, size_t n, FILE *stream);
int ps2_fgetc(FILE *stream);
@@ -58,6 +72,5 @@ int ps2_fputc(int c, FILE *stream);
int ps2_fputs(const char *s, FILE *stream);
int ps2_fprintf(FILE *pOut, const char *zFormat, ...);
-AccessFio *fetchHandle(File *file);
-
#endif // __PS2FILE_IO__
+
diff --git a/backends/ps2/libkbd.cpp b/backends/ps2/libkbd.cpp
deleted file mode 100644
index e8b9c1ad41..0000000000
--- a/backends/ps2/libkbd.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
-# _____ ___ ____ ___ ____
-# ____| | ____| | | |____|
-# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
-#-----------------------------------------------------------------------
-# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
-# Licenced under Academic Free License version 2.0
-# Review ps2sdk README & LICENSE files for further details.
-#
-# $Id$
-# USB Keyboard Driver for PS2
-*/
-
-
-/* *
- * This is the normal Ps2Kbd EE Sourcecode, slightly changed
- * and merged into ScummVM's source to work with its
- * asynchronous fio.
- *
- */
-
-
-#include <tamtypes.h>
-#include <fileio.h>
-#include "libkbd.h"
-#include "backends/ps2/asyncfio.h"
-
-static int kbd_fd = -1;
-static int curr_blockmode = PS2KBD_NONBLOCKING;
-static int curr_readmode = PS2KBD_READMODE_NORMAL;
-
-extern AsyncFio fio;
-
-int PS2KbdInit(void)
-/* Initialise the keyboard library */
-{
- if(kbd_fd >= 0) /* Already initialised */
- {
- return 0;
- }
-
- kbd_fd = fio.open(PS2KBD_DEVFILE, 0);
- if(kbd_fd < 0)
- {
- return 0;
- }
-
- return 1;
-}
-
-int PS2KbdRead(char *key)
-/* Reads 1 character from the keyboard */
-{
- if((kbd_fd >= 0) && (curr_readmode == PS2KBD_READMODE_NORMAL))
- {
- fio.read(kbd_fd, key, 1);
- return fio.sync(kbd_fd);
- }
-
- return 0;
-}
-
-int PS2KbdReadRaw(PS2KbdRawKey *key)
-/* Reads 1 raw character from the keyboard */
-{
- if((kbd_fd >= 0) && (curr_readmode == PS2KBD_READMODE_RAW))
- {
- fio.read(kbd_fd, key, 2);
- return fio.sync(kbd_fd) / 2;
- }
-
- return 0;
-}
-
-int PS2KbdSetReadmode(u32 readmode)
-/* Sets the read mode to normal or raw */
-{
- if((kbd_fd >= 0) && (curr_readmode != readmode))
- {
- curr_readmode = readmode;
- return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETREADMODE, &readmode);
- }
- return 0;
-}
-
-int PS2KbdSetBlockingMode(u32 blockmode)
-/* Sets the blocking mode on or off */
-{
- if((kbd_fd >= 0) && (curr_blockmode != blockmode))
- {
- return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETBLOCKMODE, &blockmode);
- }
-
- return 0;
-}
-
-int PS2KbdSetRepeatRate(u32 repeat)
-/* Sets the repeat rate in millseconds */
-{
- if(kbd_fd >= 0)
- {
- return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETREPEATRATE, &repeat);
- }
- return 0;
-}
-
-int PS2KbdSetLeds(u8 leds)
-/* Sets all connected keyboards leds */
-{
- if(kbd_fd >= 0)
- {
- return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETLEDS, &leds);
- }
- return 0;
-}
-
-int PS2KbdSetKeymap(PS2KbdKeyMap *keymaps)
-/* Sets the current keymap */
-{
- if(kbd_fd >= 0)
- {
- return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETKEYMAP, keymaps);
- }
- return 0;
-}
-
-int PS2KbdSetCtrlmap(u8 *ctrlmap)
-/* Sets the control key mappings */
-{
- if(kbd_fd >= 0)
- {
- return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETCTRLMAP, ctrlmap);
- }
- return 0;
-}
-
-int PS2KbdSetAltmap(u8 *altmap)
-/* Sets the alt key mappings */
-{
- if(kbd_fd >= 0)
- {
- return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETALTMAP, altmap);
- }
- return 0;
-}
-
-int PS2KbdSetSpecialmap(u8 *special)
-/* Sets the special key mappings */
-{
- if(kbd_fd >= 0)
- {
- return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETSPECIALMAP, special);
- }
- return 0;
-}
-
-int PS2KbdFlushBuffer(void)
-/* Flushes the keyboard buffer */
-{
- int dummy;
-
- if(kbd_fd >= 0)
- {
- return fioIoctl(kbd_fd, PS2KBD_IOCTL_FLUSHBUFFER, &dummy);
- }
- return 0;
-}
-
-int PS2KbdResetKeymap(void)
-/* Resets the keymap to the default US mapping */
-{
- int dummy;
-
- if(kbd_fd >= 0)
- {
- return fioIoctl(kbd_fd, PS2KBD_IOCTL_RESETKEYMAP, &dummy);
- }
- return 0;
-}
-
-int PS2KbdClose(void)
-/* Close down the keyboard library */
-{
- if(kbd_fd >= 0)
- {
- fio.close(kbd_fd);
- kbd_fd = -1;
- }
-
- return 1;
-}
diff --git a/backends/ps2/ps2input.cpp b/backends/ps2/ps2input.cpp
index 9fbf411b6e..f2092a4030 100644
--- a/backends/ps2/ps2input.cpp
+++ b/backends/ps2/ps2input.cpp
@@ -23,7 +23,7 @@
#include <malloc.h>
#include <assert.h>
#include <libmouse.h>
-#include <libkbd.h>
+#include "backends/ps2/rpckbd.h"
#include "backends/ps2/ps2input.h"
#include "backends/ps2/ps2pad.h"
#include "backends/ps2/systemps2.h"
@@ -54,7 +54,6 @@ Ps2Input::Ps2Input(OSystem_PS2 *system, bool mouseLoaded, bool kbdLoaded) {
if (_kbdLoaded) {
if (PS2KbdInit() >= 0) {
PS2KbdSetReadmode(PS2KBD_READMODE_RAW);
- PS2KbdSetBlockingMode(PS2KBD_NONBLOCKING);
printf("PS2Kbd initialized\n");
} else {
printf("unable to initialize PS2Kbd!\n");
diff --git a/backends/ps2/ps2pad.cpp b/backends/ps2/ps2pad.cpp
index 76a6d8658c..599030f489 100644
--- a/backends/ps2/ps2pad.cpp
+++ b/backends/ps2/ps2pad.cpp
@@ -111,17 +111,9 @@ void Ps2Pad::initPad(void) {
}
}
-bool Ps2Pad::checkPadReady(int port, int slot, uint32 wait, uint32 *waitRes) {
- int state;
- for (uint32 cnt = 0; cnt < wait; cnt++) {
- state = padGetState(port, slot);
- if ((state == PAD_STATE_STABLE) || (state == PAD_STATE_FINDCTP1)) {
- if (waitRes)
- *waitRes = cnt;
- return true;
- }
- }
- return false;
+bool Ps2Pad::checkPadReady(int port, int slot) {
+ int state = padGetState(port, slot);
+ return (state == PAD_STATE_STABLE) || (state == PAD_STATE_FINDCTP1);
}
bool Ps2Pad::padAlive(void) {
@@ -152,4 +144,3 @@ void Ps2Pad::readPad(uint16 *pbuttons, int16 *joyh, int16 *joyv) {
}
-
diff --git a/backends/ps2/ps2pad.h b/backends/ps2/ps2pad.h
index 1e1eb08e87..12baebdc3f 100644
--- a/backends/ps2/ps2pad.h
+++ b/backends/ps2/ps2pad.h
@@ -49,7 +49,7 @@ public:
void readPad(uint16 *pbuttons, int16 *joyh, int16 *joyv);
private:
void initPad(void);
- bool checkPadReady(int port, int slot, uint32 wait = 1, uint32 *waitRes = NULL);
+ bool checkPadReady(int port, int slot);
OSystem_PS2 *_system;
int _port, _slot;
diff --git a/backends/ps2/savefile.cpp b/backends/ps2/savefile.cpp
index 78def68d7b..1449c94510 100644
--- a/backends/ps2/savefile.cpp
+++ b/backends/ps2/savefile.cpp
@@ -19,9 +19,6 @@
*
*/
-#include "backends/ps2/savefile.h"
-#include "backends/ps2/Gs2dScreen.h"
-
#include <tamtypes.h>
#include <kernel.h>
#include <sifrpc.h>
@@ -29,69 +26,76 @@
#include <fileio.h>
#include <malloc.h>
#include <ucl/ucl.h>
+#include "backends/ps2/savefile.h"
+#include "backends/ps2/Gs2dScreen.h"
+#include "backends/ps2/asyncfio.h"
+#include "backends/ps2/systemps2.h"
#include "scummsys.h"
-class StdioSaveFile : public SaveFile {
+extern AsyncFio fio;
+
+class UclOutSaveFile : public Common::WriteStream {
public:
- StdioSaveFile(const char *filename, bool saveOrLoad);
- virtual ~StdioSaveFile();
- virtual bool isOpen() const;
- virtual uint32 read(void *buf, uint32 cnt);
- virtual uint32 write(const void *buf, uint32 cnt);
+ UclOutSaveFile(const char *filename, Gs2dScreen *screen);
+ virtual ~UclOutSaveFile(void);
+ virtual uint32 write(const void *ptr, uint32 size);
+ virtual int flush(void);
+ virtual bool ioFailed(void);
+ virtual void clearIOFailed(void);
private:
- FILE *_fh;
- bool _saving;
+ Gs2dScreen *_screen;
+ int _fd;
+ uint8 *_buf;
+ uint32 _bufSize, _bufPos;
+ bool _ioFailed;
};
-class UclSaveFile : public SaveFile {
+class UclInSaveFile : public Common::ReadStream {
public:
- UclSaveFile(const char *filename, bool saveOrLoad, Gs2dScreen *screen);
- virtual ~UclSaveFile();
- virtual bool isOpen() const;
- virtual uint32 read(void *buf, uint32 cnt);
- virtual uint32 write(const void *buf, uint32 cnt);
+ UclInSaveFile(const char *filename, Gs2dScreen *screen);
+ virtual ~UclInSaveFile(void);
+ virtual bool eos(void) const;
+ virtual uint32 read(void *ptr, uint32 size);
+ virtual bool ioFailed(void);
+ virtual void clearIOFailed(void);
private:
Gs2dScreen *_screen;
- FILE *_fh;
- bool _saving;
uint8 *_buf;
uint32 _bufSize, _bufPos;
+ bool _ioFailed;
};
-#define ARRAY_ENTRIES 16
-static mcTable mcDir[ARRAY_ENTRIES] __attribute__((aligned(64)));
-static int mcEntries;
-static bool mcNeedUpdate = true;
+#define MAX_MC_ENTRIES 16
-Ps2SaveFileManager::Ps2SaveFileManager(const char *path, SaveMode mode, Gs2dScreen *screen) {
+Ps2SaveFileManager::Ps2SaveFileManager(OSystem_PS2 *system, Gs2dScreen *screen) {
+ _system = system;
_screen = screen;
- if (mcInit(MC_TYPE_MC) < 0) {
- printf("Can't init libmc!\n");
- SleepThread();
- }
-
- if (path)
- strcpy(_savePath, path);
- else
- _savePath[0] = '\0';
+ assert(mcInit(MC_TYPE_MC) >= 0);
+
+ _mcDirList = (mcTable*)memalign(64, MAX_MC_ENTRIES * sizeof(mcTable));
+ _mcDirName[0] = '\0';
+ _mcCheckTime = 0;
+ _mcNeedsUpdate = true;
+
+ int mcCheckCount;
+ int res = -10;
+ for (int mcCheckCount = 0; mcCheckCount < 3; mcCheckCount++) {
+ /* retry mcGetInfo 3 times. It slows down startup without mc considerably,
+ but cheap 3rd party memory cards apparently fail to get detected once in a while */
- _mode = mode;
- if (mode == TO_HOST) {
- printf("saving to host:/\n");
- } else if (mode == TO_MC) {
int mcType, mcFree, mcFormat, res;
mcGetInfo(0, 0, &mcType, &mcFree, &mcFormat);
mcSync(0, NULL, &res);
- if ((res == 0) || (res == -1)) // mc okay
+ if ((res == 0) || (res == -1)) { // mc okay
+ _mcPresent = true;
printf("MC okay, result = %d. Type %d, Free %d, Format %d\n", res, mcType, mcFree, mcFormat);
- else
+ checkMainDirectory();
+ break;
+ } else {
+ _mcPresent = false;
printf("MC failed, not present or not formatted, code %d\n", res);
- } else {
- printf("HDD not implemented yet\n");
- SleepThread();
+ }
}
-
- checkMainDirectory();
}
Ps2SaveFileManager::~Ps2SaveFileManager(void) {
@@ -100,130 +104,177 @@ Ps2SaveFileManager::~Ps2SaveFileManager(void) {
void Ps2SaveFileManager::checkMainDirectory(void) {
// verify that the main directory (scummvm config + icon) exists
int ret;
- mcGetDir(0, 0, "/ScummVM/*", 0, ARRAY_ENTRIES, mcDir);
+ mcGetDir(0, 0, "/ScummVM/*", 0, MAX_MC_ENTRIES, _mcDirList);
mcSync(0, NULL, &ret);
printf("/ScummVM/* res = %d\n", ret);
if (ret <= 0) { // assume directory doesn't exist
printf("Dir doesn't exist\n");
- fioMkdir("mc0:ScummVM");
- FILE *outf = fopen("mc0:ScummVM/scummvm.icn", "wb");
- if (outf) {
+ fio.mkdir("mc0:ScummVM");
+ int fd = fio.open("mc0:ScummVM/scummvm.icn", O_WRONLY | O_CREAT | O_TRUNC);
+ if (fd >= 0) {
uint16 icoSize;
uint16 *icoBuf = decompressIconData(&icoSize);
- fwrite(icoBuf, 2, icoSize, outf);
- fclose(outf);
- printf(".icn written\n");
+ fio.write(fd, icoBuf, icoSize * 2);
+ fio.sync(fd);
free(icoBuf);
-
+ fio.close(fd);
+ printf(".icn written\n");
setupIcon("mc0:ScummVM/icon.sys", "scummvm.icn", "ScummVM", "Configuration");
} else
printf("unable to write icon data\n");
}
}
-SaveFile *Ps2SaveFileManager::openSavefile(const char *filename, bool saveOrLoad) {
- char *defaultExt = "SAVE";
- char nameBase[256];
- strcpy(nameBase, filename);
- char *ext = strchr(nameBase, '.');
- if (ext) {
+void Ps2SaveFileManager::splitPath(const char *fileName, char *dir, char *name) {
+ strcpy(dir, fileName);
+ char *ext = strchr(dir, '.');
+ if (ext) {
*ext = '\0';
ext++;
- if (!*ext)
- ext = defaultExt;
- } else
- ext = defaultExt;
-
- if (_mode == TO_HOST) {
- char hostName[256];
- sprintf(hostName, "%s%s", _savePath, filename);
- SaveFile *res = new StdioSaveFile(hostName, saveOrLoad);
- if (!res->isOpen()) {
- printf("unable to open savefile %s for %s\n", hostName, saveOrLoad ? "saving" : "loading");
- delete res;
- return NULL;
- }
- printf("Savefile %s opened for %s\n", hostName, saveOrLoad ? "saving" : "loading");
- return res;
- } else if (_mode == TO_MC) {
- _screen->wantAnim(true);
+ }
+ if (ext && *ext)
+ sprintf(name, "%s.ucl", ext);
+ else
+ strcpy(name, "save.ucl");
+}
+
+bool Ps2SaveFileManager::mcReadyForDir(const char *dir) {
+ if (_mcNeedsUpdate || ((_system->getMillis() - _mcCheckTime) > 1000) || !_mcPresent) {
+ // check if memory card was exchanged/removed in the meantime
int mcType, mcFree, mcFormat, mcResult;
mcGetInfo(0, 0, &mcType, &mcFree, &mcFormat);
mcSync(0, NULL, &mcResult);
- if (mcResult == -1) // memory card was exchanged
- mcNeedUpdate = true;
- else if (mcResult != 0) {
- printf("Memory card is not ready\n");
- return NULL;
+ if (mcResult != 0) { // memory card was exchanged
+ _mcNeedsUpdate = true;
+ if (mcResult != -1) {
+ _mcPresent = false;
+ printf("MC not found, error code %d\n", mcResult);
+ return false;
+ }
}
-
+ _mcPresent = true;
+ }
+ if (_mcNeedsUpdate || strcmp(_mcDirName, dir)) {
+ strcpy(_mcDirName, dir);
char dirStr[256];
- sprintf(dirStr, "/ScummVM-%s/*", nameBase);
- if (saveOrLoad) { // saving
- mcGetDir(0, 0, dirStr, 0, ARRAY_ENTRIES, mcDir);
- mcSync(0, NULL, &mcEntries);
- mcNeedUpdate = true;
- if (mcEntries <= 0) { // directory is empty or doesn't exist.
- sprintf(dirStr, "mc0:ScummVM-%s", nameBase);
- printf("Creating directory %s\n", dirStr);
- if (mcEntries < 0) { // directory doesn't exist
- if (fioMkdir(dirStr) < 0) {
- printf("unable to create directory %s\n", dirStr);
- _screen->wantAnim(false);
- return NULL; // unable to create directory
- }
- }
- char icoSysDest[256], saveDesc[256];
- sprintf(icoSysDest, "%s/icon.sys", dirStr);
- strcpy(saveDesc, nameBase);
- if ((saveDesc[0] >= 'a') && (saveDesc[0] <= 'z'))
- saveDesc[0] += 'A' - 'a';
- setupIcon(icoSysDest, "../ScummVM/scummvm.icn", saveDesc, "Savegames");
- }
- } else {
- // scumm engine tries to open hundreds of files to search for savegames.
- if (mcNeedUpdate) {
- mcGetDir(0, 0, dirStr, 0, ARRAY_ENTRIES, mcDir);
- mcSync(0, NULL, &mcEntries);
- mcNeedUpdate = false;
- }
- bool fileExists = false;
- char searchName[32];
- sprintf(searchName, "%s.bin", ext);
- for (int cnt = 0; (cnt < mcEntries) && !fileExists; cnt++)
- if (strcmp(searchName, (char*)mcDir[cnt].name) == 0)
- fileExists = true;
-
- if (!fileExists) {
- _screen->wantAnim(false);
- return NULL;
+ sprintf(dirStr, "/ScummVM-%s/*", dir);
+ mcGetDir(0, 0, dirStr, 0, MAX_MC_ENTRIES, _mcDirList);
+ mcSync(0, NULL, &_mcEntries);
+ return (_mcEntries >= 0);
+ } else
+ return true;
+}
+
+InSaveFile *Ps2SaveFileManager::openForLoading(const char *filename) {
+ _screen->wantAnim(true);
+
+ char dir[256], name[256];
+ splitPath(filename, dir, name);
+ if (mcReadyForDir(dir)) {
+ bool fileExists = false;
+ for (int i = 0; i < _mcEntries; i++)
+ if (strcmp(name, (char*)_mcDirList[i].name) == 0)
+ fileExists = true;
+ if (fileExists) {
+ char fullName[256];
+ sprintf(fullName, "mc0:ScummVM-%s/%s", dir, name);
+ UclInSaveFile *file = new UclInSaveFile(fullName, _screen);
+ if (file) {
+ if (!file->ioFailed()) {
+ return (InSaveFile*)file;
+ } else
+ delete file;
}
- }
- sprintf(dirStr, "mc0:ScummVM-%s/%s.bin", nameBase, ext);
- SaveFile *file = new UclSaveFile(dirStr, saveOrLoad, _screen);
- if (!file->isOpen()) {
- printf("unable to open savefile %s for %s\n", dirStr, saveOrLoad ? "saving" : "loading");
- delete file;
- _screen->wantAnim(false);
- return NULL;
- }
- return file;
- } else {
- printf("HDD not implemented yet\n");
- return NULL;
+ } else
+ printf("file %s (%s) doesn't exist\n", filename, name);
}
+ _screen->wantAnim(false);
+ return NULL;
}
-void Ps2SaveFileManager::listSavefiles(const char * /* prefix */, bool *marks, int num) {
- memset(marks, true, num * sizeof(bool));
+OutSaveFile *Ps2SaveFileManager::openForSaving(const char *filename) {
+ _screen->wantAnim(true);
+ char dir[256], name[256];
+ splitPath(filename, dir, name);
+
+ if (!mcReadyForDir(dir)) {
+ if (_mcPresent) { // directory doesn't seem to exist yet
+ char fullPath[256];
+ sprintf(fullPath, "mc0:ScummVM-%s", dir);
+ fio.mkdir(fullPath);
+
+ char icoSysDest[256], saveDesc[256];
+ sprintf(icoSysDest, "%s/icon.sys", fullPath);
+ strcpy(saveDesc, dir);
+ if ((saveDesc[0] >= 'a') && (saveDesc[0] <= 'z'))
+ saveDesc[0] += 'A' - 'a';
+ setupIcon(icoSysDest, "../ScummVM/scummvm.icn", saveDesc, "Savegames");
+ }
+ }
+
+ if (_mcPresent) {
+ char fullPath[256];
+ sprintf(fullPath, "mc0:ScummVM-%s/%s", dir, name);
+ UclOutSaveFile *file = new UclOutSaveFile(fullPath, _screen);
+ if (!file->ioFailed()) {
+ // we're creating a file, mc will have to be updated next time
+ _mcNeedsUpdate = true;
+ return (OutSaveFile*)file;
+ } else
+ delete file;
+ }
+
+ _screen->wantAnim(false);
+ return NULL;
}
-const char *Ps2SaveFileManager::getSavePath(void) const {
- return _savePath;
+void Ps2SaveFileManager::listSavefiles(const char *prefix, bool *marks, int num) {
+ _screen->wantAnim(true);
+
+ int mcType, mcFree, mcFormat, mcResult;
+ mcGetInfo(0, 0, &mcType, &mcFree, &mcFormat);
+ mcSync(0, NULL, &mcResult);
+
+ memset(marks, false, num * sizeof(bool));
+
+ if ((mcResult == 0) || (mcResult == -1)) {
+ // there's a memory card in the slot.
+ if (mcResult == -1)
+ _mcNeedsUpdate = true;
+
+ mcTable *mcEntries = (mcTable*)memalign(64, sizeof(mcTable) * MAX_MC_ENTRIES);
+
+ char dirStr[256], ext[256], mcSearchStr[256];
+ strcpy(dirStr, prefix);
+ char *pos = strchr(dirStr, '.');
+ if (pos) {
+ strcpy(ext, pos + 1);
+ *pos = '\0';
+ } else
+ ext[0] = '\0';
+ sprintf(mcSearchStr, "/ScummVM-%s/%s*", dirStr, ext);
+
+ int numEntries;
+ mcGetDir(0, 0, mcSearchStr, 0, MAX_MC_ENTRIES, mcEntries);
+ mcSync(0, NULL, &numEntries);
+
+ int searchLen = strlen(ext);
+ for (int i = 0; i < numEntries; i++)
+ if ((((char*)mcEntries[i].name)[0] != '.') && stricmp((char*)mcEntries[i].name, "icon.sys")) {
+ char *stopCh;
+ int destNum = (int)strtoul((char*)mcEntries[i].name + searchLen, &stopCh, 10);
+ if ((!stopCh) || strcmp(stopCh, ".ucl"))
+ printf("unexpected end %s in name %s, search %s\n", stopCh, (char*)mcEntries[i].name, prefix);
+ if (destNum < num)
+ marks[destNum] = true;
+ }
+ free(mcEntries);
+ }
+ _screen->wantAnim(false);
}
-void Ps2SaveFileManager::setSavePath(const char *path) {
- strcpy(_savePath, path);
+const char *Ps2SaveFileManager::getSavePath(void) const {
+ return "mc0:";
}
bool Ps2SaveFileManager::setupIcon(const char *dest, const char *ico, const char *descr1, const char *descr2) {
@@ -231,9 +282,14 @@ bool Ps2SaveFileManager::setupIcon(const char *dest, const char *ico, const char
memset(&icon_sys, 0, sizeof(mcIcon));
memcpy(icon_sys.head, "PS2D", 4);
char title[256];
- sprintf(title, "%s\n%s", descr1, descr2);
+ if (!stricmp("SAVEGAME", descr1)) { // these are broken sword 1 savegames
+ sprintf(title, "BSword1\n%s", descr2);
+ icon_sys.nlOffset = 8;
+ } else {
+ sprintf(title, "%s\n%s", descr1, descr2);
+ icon_sys.nlOffset = strlen(descr1) + 1;
+ }
strcpy_sjis((short*)&(icon_sys.title), title);
- icon_sys.nlOffset = strlen(descr1) + 1;
icon_sys.trans = 0x10;
memcpy(icon_sys.bgCol, _bgcolor, sizeof(_bgcolor));
memcpy(icon_sys.lightDir, _lightdir, sizeof(_lightdir));
@@ -243,11 +299,12 @@ bool Ps2SaveFileManager::setupIcon(const char *dest, const char *ico, const char
strcpy((char*)icon_sys.copy, ico);
strcpy((char*)icon_sys.del, ico);
- FILE *outf = fopen(dest, "wb");
- if (outf) {
- fwrite(&icon_sys, 1, sizeof(icon_sys), outf);
- fclose(outf);
- return true;
+ int fd = fio.open(dest, O_WRONLY | O_CREAT | O_TRUNC);
+ if (fd >= 0) {
+ fio.write(fd, &icon_sys, sizeof(icon_sys));
+ int res = fio.sync(fd);
+ fio.close(fd);
+ return (res == sizeof(icon_sys));
} else
return false;
}
@@ -256,7 +313,7 @@ uint16 *Ps2SaveFileManager::decompressIconData(uint16 *size) {
uint16 inPos = 1;
uint16 *rleData = (uint16*)_rleIcoData;
uint16 resSize = rleData[0];
- uint16 *resData = (uint16*)malloc(resSize * sizeof(uint16*));
+ uint16 *resData = (uint16*)malloc(resSize * sizeof(uint16));
uint16 outPos = 0;
while (outPos < resSize) {
uint16 len = rleData[inPos++];
@@ -271,105 +328,148 @@ uint16 *Ps2SaveFileManager::decompressIconData(uint16 *size) {
return resData;
}
+UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen) {
+ _screen = screen;
+ int fd = fio.open(filename, O_RDONLY);
+ _buf = NULL;
+ _bufSize = _bufPos = 0;
+ _ioFailed = false;
+
+ if (fd >= 0) {
+ int srcSize = fio.seek(fd, 0, SEEK_END);
+ fio.seek(fd, 0, SEEK_SET);
+ if (srcSize > 4) {
+ int res;
+ uint8 *tmpBuf = (uint8*)malloc(srcSize);
+ fio.read(fd, tmpBuf, srcSize);
+ res = fio.sync(fd);
+ if (res == srcSize) {
+ uint32 resLen = _bufSize = *(uint32*)tmpBuf;
+ _buf = (uint8*)malloc(_bufSize + 2048);
+ res = ucl_nrv2e_decompress_8(tmpBuf + 4, srcSize - 4, _buf, &resLen, NULL);
+ if ((res < 0) || (resLen != _bufSize)) {
+ printf("Unable to decompress file %s (%d -> %d) error code %d\n", filename, srcSize, _bufSize, res);
+ free(_buf);
+ _buf = NULL;
+ _bufSize = 0;
+ }
+ }
+ free(tmpBuf);
+ }
+ if (!_buf) {
+ printf("Invalid savegame %s\n", filename);
+ _ioFailed = true;
+ }
+ fio.close(fd);
+ }
+}
-StdioSaveFile::StdioSaveFile(const char *filename, bool saveOrLoad) {
- _fh = ::fopen(filename, (saveOrLoad? "wb" : "rb"));
- _saving = saveOrLoad;
+UclInSaveFile::~UclInSaveFile(void) {
+ if (_buf)
+ free(_buf);
+ _screen->wantAnim(false);
}
-StdioSaveFile::~StdioSaveFile(void) {
- if (_fh)
- ::fclose(_fh);
+bool UclInSaveFile::ioFailed(void) {
+ return _ioFailed;
}
-bool StdioSaveFile::isOpen(void) const {
- return _fh != NULL;
+void UclInSaveFile::clearIOFailed(void) {
+ _ioFailed = false;
}
-uint32 StdioSaveFile::read(void *buf, uint32 cnt) {
- assert(!_saving);
- return ::fread(buf, 1, cnt, _fh);
+bool UclInSaveFile::eos(void) const {
+ return _bufPos == _bufSize;
}
-uint32 StdioSaveFile::write(const void *buf, uint32 cnt) {
- assert(_saving);
- return ::fwrite(buf, 1, cnt, _fh);
+uint32 UclInSaveFile::read(void *ptr, uint32 size) {
+ uint32 bytesRemain = _bufSize - _bufPos;
+ if (size > bytesRemain) {
+ size = bytesRemain;
+ _ioFailed = true;
+ }
+ memcpy(ptr, _buf + _bufPos, size);
+ _bufPos += size;
+ return size;
}
-UclSaveFile::UclSaveFile(const char *filename, bool saveOrLoad, Gs2dScreen *screen) {
- _fh = ::fopen(filename, (saveOrLoad? "wb" : "rb"));
- _saving = saveOrLoad;
- _bufPos = 0;
+UclOutSaveFile::UclOutSaveFile(const char *filename, Gs2dScreen *screen) {
_screen = screen;
- if (_fh) {
- if (_saving) {
- _buf = (uint8*)malloc(65536);
- _bufSize = 65536;
- } else {
- uint32 srcSize = ::fsize(_fh);
- uint8 *srcBuf = (uint8*)malloc(srcSize);
- int res = ::fread(srcBuf, 1, srcSize, _fh);
- assert(res == srcSize);
-
- uint32 resLen = _bufSize = *(uint32*)srcBuf;
- _buf = (uint8*)malloc(_bufSize + 2048);
- res = ucl_nrv2e_decompress_8(srcBuf + 4, srcSize - 4, _buf, &resLen, NULL);
- if ((res < 0) || (resLen != _bufSize)) {
- printf("Unable to decompress file %s (%d -> %d) error code %d\n", filename, srcSize, _bufSize, res);
- free(_buf);
- _buf = NULL;
- _bufSize = 0;
- }
- ::fclose(_fh);
- _fh = NULL;
- free(srcBuf);
- }
+ _bufPos = 0;
+ _fd = fio.open(filename, O_WRONLY | O_CREAT | O_TRUNC);
+ if (_fd >= 0) {
+ _bufSize = 65536;
+ _buf = (uint8*)malloc(_bufSize);
+ _ioFailed = false;
} else {
- printf("Savefile %s doesn't exist\n", filename);
+ _ioFailed = true;
+ _bufSize = 0;
_buf = NULL;
}
}
-UclSaveFile::~UclSaveFile(void) {
- if (_saving) {
+UclOutSaveFile::~UclOutSaveFile(void) {
+ if (_buf) {
+ if (flush() < 0)
+ printf("~UclOutSaveFile: Flush failed!\n");
+ free(_buf);
+ }
+ if (_fd >= 0)
+ fio.close(_fd);
+ _screen->wantAnim(false);
+}
+
+bool UclOutSaveFile::ioFailed(void) {
+ return _ioFailed;
+}
+
+void UclOutSaveFile::clearIOFailed(void) {
+ _ioFailed = false;
+}
+
+int UclOutSaveFile::flush(void) {
+ if (_bufPos == 0)
+ return 0; // no data to flush
+ if (_buf) {
uint8 *compBuf = (uint8*)malloc(_bufPos * 2);
uint32 compSize = _bufPos * 2;
int res = ucl_nrv2e_99_compress(_buf, _bufPos, compBuf, &compSize, NULL, 10, NULL, NULL);
if (res >= 0) {
- fwrite(&_bufPos, 1, 4, _fh);
- fwrite(compBuf, 1, compSize, _fh);
- } else {
- printf("unable to compress %d bytes of savedata, errorcode %d\n", _bufPos, res);
+ fio.write(_fd, &_bufPos, 4);
+ if (fio.sync(_fd) == 4) {
+ fio.write(_fd, compBuf, compSize);
+ if (fio.sync(_fd) != compSize)
+ res = -1;
+ } else
+ res = -1;
+ } else
+ printf("Unable to compress %d bytes of savedata, errorcode %d\n", _bufPos, res);
+ free(compBuf);
+
+ if (res >= 0) {
+ _bufPos = 0;
+ return 0;
}
- free(compBuf);
}
- if (_buf)
- free(_buf);
- if (_fh)
- ::fclose(_fh);
- _screen->wantAnim(false);
-}
-
-bool UclSaveFile::isOpen(void) const {
- return (_buf != NULL);
+ _ioFailed = true;
+ printf("UclOutSaveFile::flush failed!\n");
+ return -1;
}
-uint32 UclSaveFile::read(void *buf, uint32 cnt) {
- assert(!_saving);
- uint32 numBytes = (cnt > _bufSize - _bufPos) ? (_bufSize - _bufPos) : cnt;
- memcpy(buf, _buf + _bufPos, numBytes);
- _bufPos += numBytes;
- return numBytes;
-}
-uint32 UclSaveFile::write(const void *buf, uint32 cnt) {
- assert(_saving);
- if (_bufSize - _bufPos < cnt) {
- _bufSize += (cnt > 65536) ? cnt : 65536;
+uint32 UclOutSaveFile::write(const void *ptr, uint32 size) {
+ assert(_bufPos <= _bufSize);
+ uint32 bytesFree = _bufSize - _bufPos;
+ if (bytesFree < size) {
+ uint32 allocBytes = (size > 32 * 1024) ? size : 32 * 1024;
+ _bufSize += allocBytes;
_buf = (uint8*)realloc(_buf, _bufSize);
+ bytesFree = _bufSize - _bufPos;
}
- memcpy(_buf + _bufPos, buf, cnt);
- _bufPos += cnt;
- return cnt;
+ assert(bytesFree >= size);
+ memcpy(_buf + _bufPos, ptr, size);
+ _bufPos += size;
+ return size;
}
+
diff --git a/backends/ps2/savefile.h b/backends/ps2/savefile.h
index 25133e90dc..66d27f1bbb 100644
--- a/backends/ps2/savefile.h
+++ b/backends/ps2/savefile.h
@@ -32,42 +32,40 @@ enum SaveMode {
};
class Gs2dScreen;
+class OSystem_PS2;
class Ps2SaveFileManager : public SaveFileManager {
public:
- Ps2SaveFileManager(const char *path, SaveMode mode, Gs2dScreen *screen);
+ Ps2SaveFileManager(OSystem_PS2 *system, Gs2dScreen *screen);
virtual ~Ps2SaveFileManager();
-
- virtual SaveFile *openForSaving(const char *filename) {
- return openSavefile(filename, true);
- }
- virtual SaveFile *openForLoading(const char *filename) {
- return openSavefile(filename, false);
- }
-
- virtual void listSavefiles(const char * /* prefix */, bool *marks, int num);
+ virtual InSaveFile *openForLoading(const char *filename);
+ virtual OutSaveFile *openForSaving(const char *filename);
+ virtual void listSavefiles(const char *prefix, bool *marks, int num);
/** Get the path to the save game directory. */
virtual const char *getSavePath() const;
-
- void setSavePath(const char *path);
+private:
static bool setupIcon(const char *dest, const char *ico, const char *descr1, const char *descr2);
+ bool mcReadyForDir(const char *dir);
+
void checkMainDirectory(void);
-private:
+ void splitPath(const char *fileName, char *dir, char *name);
uint16 *decompressIconData(uint16 *size);
Gs2dScreen *_screen;
+ OSystem_PS2 *_system;
- static const uint8 _rleIcoData[14018];
- SaveMode _mode;
- char _savePath[256];
+ mcTable *_mcDirList;
+ int _mcEntries;
+ char _mcDirName[256];
+ bool _mcNeedsUpdate, _mcPresent;
+ uint32 _mcCheckTime;
+ static const uint8 _rleIcoData[14018];
static const iconIVECTOR _bgcolor[4];
static const iconFVECTOR _lightdir[3], _lightcol[3], _ambient;
-
- SaveFile *openSavefile(const char *filename, bool saveOrLoad);
};
#endif // __PS2_SAVEFILE__
diff --git a/backends/ps2/sjpcm.h b/backends/ps2/sjpcm.h
deleted file mode 100644
index d6cf95ec86..0000000000
--- a/backends/ps2/sjpcm.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- -----------------------------------------------------------------------
- sjpcm.h - SjPCM EE-side prototypes. (c) Nick Van Veen (aka Sjeep), 2002
- -----------------------------------------------------------------------
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#ifndef _SJPCM_H
-#define _SJPCM_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SJPCM_IRX 0xB0110C5
-#define SJPCM_PUTS 0x01
-#define SJPCM_INIT 0x02
-#define SJPCM_PLAY 0x03
-#define SJPCM_PAUSE 0x04
-#define SJPCM_SETVOL 0x05
-#define SJPCM_ENQUEUE 0x06
-#define SJPCM_CLEARBUFF 0x07
-#define SJPCM_QUIT 0x08
-#define SJPCM_GETAVAIL 0x09
-#define SJPCM_GETBUFFD 0x10
-
-void SjPCM_Puts(char *format, ...);
-int SjPCM_Init(int sync);
-void SjPCM_Enqueue(short *left, short *right, int size, int wait);
-void SjPCM_Play();
-void SjPCM_Pause();
-void SjPCM_Setvol(unsigned int volume);
-void SjPCM_Clearbuff();
-int SjPCM_Available();
-int SjPCM_Buffered();
-void SjPCM_Quit();
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _SJPCM_H
diff --git a/backends/ps2/smushio.cpp b/backends/ps2/smushio.cpp
new file mode 100644
index 0000000000..ef7c9f4517
--- /dev/null
+++ b/backends/ps2/smushio.cpp
@@ -0,0 +1,376 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2005 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+/*
+ The Smush player uses at least two handles for accessing the same SMUSH file,
+ to avoid threading issues. One handle for video, one for audio apparently.
+ Each of the handles always skips the data that the other one read before
+ (or will read later).
+
+ This behaviour makes it difficult to do read ahead caching without reading
+ any given file twice, so this class tries to "reunite" the read accesses and
+ do the necessary caching.
+*/
+
+#include "backends/ps2/fileio.h"
+#include "backends/ps2/asyncfio.h"
+#include <kernel.h>
+#include <assert.h>
+#include <string.h>
+#include <sio.h>
+
+extern AsyncFio fio;
+extern void sioprintf(const char *zFormat, ...);
+
+#define SMUSH_CACHE_SIZE (5 * 1024 * 1024)
+#define READ_STEP (32 * 1024)
+#define SMUSH_IN_USE -2
+
+class SmushReader {
+public:
+ SmushReader(void);
+ ~SmushReader(void);
+ int open(const char *name);
+ void close(void);
+ uint32 read(void *dest, uint32 from, uint32 len);
+ void virtSeek(uint32 from, uint32 to);
+ uint32 size(void);
+ bool keepOpened(void);
+private:
+ void processCache(bool sync);
+ char _fname[256];
+ int _sema, _fd, _refCount;
+ uint8 *_cacheBuf;
+ volatile uint32 _cacheFilePos, _bytesInCache, _fileSize, _cacheBufOfs;
+ volatile uint32 _lastRead[2];
+ volatile bool _cacheOp;
+};
+
+SmushReader::SmushReader(void) {
+ _cacheBuf = NULL;
+ _fd = -1;
+ _refCount = 0;
+
+ ee_sema_t newSema;
+ newSema.init_count = 1;
+ newSema.max_count = 1;
+ _sema = CreateSema(&newSema);
+ assert(_sema >= 0);
+}
+
+SmushReader::~SmushReader(void) {
+ DeleteSema(_sema);
+}
+
+int SmushReader::open(const char *name) {
+ WaitSema(_sema);
+ if (_refCount) {
+ if (stricmp(_fname, name)) {
+ sioprintf("SmushReader is already open to file\n%s\nGot open request for %s", _fname, name);
+ SignalSema(_sema);
+ return SMUSH_IN_USE;
+ }
+ } else {
+ assert(_fd < 0);
+ _fd = fio.open(name, O_RDONLY);
+ if (_fd < 0) {
+ SignalSema(_sema);
+ return -1;
+ }
+ _fileSize = fio.seek(_fd, 0, SEEK_END);
+ fio.seek(_fd, 0, SEEK_SET);
+
+ _cacheBuf = (uint8*)malloc(SMUSH_CACHE_SIZE);
+ if (!_cacheBuf) {
+ sioprintf("Smush Reader ran out of memory");
+ fio.close(_fd);
+ _fd = -1;
+ SignalSema(_sema);
+ return -1;
+ }
+ _lastRead[0] = _lastRead[1] = 0;
+ _cacheBufOfs = _bytesInCache = _cacheFilePos = 0;
+ fio.read(_fd, _cacheBuf, READ_STEP);
+ _cacheOp = true;
+ strcpy(_fname, name);
+ }
+ _refCount++;
+ sioprintf("SmushReader %s ref count %d", _fname, _refCount);
+ SignalSema(_sema);
+ return 0;
+}
+
+void SmushReader::close(void) {
+ WaitSema(_sema);
+ sioprintf("Closing Ref to %s", _fname);
+ assert(_refCount > 0);
+ _refCount--;
+ if (!_refCount) {
+ sioprintf("SmushReader: All references to %s closed", _fname);
+ processCache(true);
+ _fname[0] = '\0';
+ fio.close(_fd);
+ _fd = -1;
+ free(_cacheBuf);
+ _cacheBuf = NULL;
+ }
+ SignalSema(_sema);
+}
+
+#define MIN(a, b) ((a < b) ? (a) : (b))
+
+void SmushReader::processCache(bool sync) {
+ if (_cacheOp) {
+ if (sync || fio.poll(_fd)) { // has the transfer finished or were we told to wait for it to finish?
+ int rdRes = fio.sync(_fd);
+ assert(rdRes >= 0);
+ _bytesInCache += rdRes;
+ _cacheOp = false;
+ }
+ } else if (!sync) {
+ if (_cacheFilePos + _bytesInCache == _fileSize)
+ return;
+
+ uint32 rdPos = MIN(_lastRead[0], _lastRead[1]);
+
+ int cacheOfs = (rdPos - _cacheFilePos) & ~0xF; // we'd like to keep the buffer aligned to 16 bytes
+ if (cacheOfs < 0) {
+ sioprintf("ERROR: smush cache too far ahead!");
+ return;
+ }
+
+ if (_bytesInCache - cacheOfs < SMUSH_CACHE_SIZE - READ_STEP) {
+ // we want to do some more reading
+ if (_bytesInCache > cacheOfs) {
+ _bytesInCache -= cacheOfs;
+ _cacheBufOfs += cacheOfs;
+ _cacheFilePos += cacheOfs;
+ } else {
+ sioprintf("cache underrun!");
+ _bytesInCache = 0;
+ _cacheBufOfs = 0;
+ _cacheFilePos = rdPos;
+ }
+
+ uint32 bufEndPos = (_cacheBufOfs + _bytesInCache) % SMUSH_CACHE_SIZE;
+ uint32 readLen = SMUSH_CACHE_SIZE - bufEndPos;
+ if (readLen > READ_STEP)
+ readLen = READ_STEP;
+
+ fio.read(_fd, _cacheBuf + bufEndPos, readLen);
+ _cacheOp = true;
+ }
+ }
+}
+
+uint32 SmushReader::read(void *dest, uint32 from, uint32 len) {
+ uint8 *destBuf = (uint8*)dest;
+ WaitSema(_sema);
+ if ((from >= _cacheFilePos) && (from + len <= _cacheFilePos + _bytesInCache))
+ processCache(false);
+ else {
+ processCache(true); // we'll have to read, sync cache before.
+ }
+ uint32 readEnds = from + len;
+ if (from == _lastRead[0])
+ _lastRead[0] += len;
+ else if (from == _lastRead[1])
+ _lastRead[1] += len;
+ else {
+ if ((_lastRead[0] > readEnds) && (_lastRead[1] < readEnds)) {
+ _lastRead[1] = readEnds;
+ } else if ((_lastRead[0] < readEnds) && (_lastRead[1] > readEnds)) {
+ _lastRead[0] = readEnds;
+ } else {
+ if ((_lastRead[0] < readEnds) && (_lastRead[1] < readEnds)) {
+ if (_lastRead[0] < _lastRead[1])
+ _lastRead[0] = readEnds;
+ else
+ _lastRead[1] = readEnds;
+ } else
+ sioprintf("unexpected readend: %d / %d => %d", _lastRead[0], _lastRead[1], readEnds);
+ }
+ }
+
+ while (len) {
+ while (len && (from >= _cacheFilePos) && (from < _cacheFilePos + _bytesInCache)) {
+ uint32 cpyOfs = ((from - _cacheFilePos) + _cacheBufOfs) % SMUSH_CACHE_SIZE;
+ uint32 cpyLen = _bytesInCache - (from - _cacheFilePos);
+ if (cpyLen > len)
+ cpyLen = len;
+ if (cpyOfs + cpyLen > SMUSH_CACHE_SIZE)
+ cpyLen = SMUSH_CACHE_SIZE - cpyOfs;
+ memcpy(destBuf, _cacheBuf + cpyOfs, cpyLen);
+ destBuf += cpyLen;
+ from += cpyLen;
+ len -= cpyLen;
+ }
+ if (len) {
+ sioprintf("Smush cache missed: read %d -> %d, cache %d -> %d", from, len, _cacheFilePos, _bytesInCache);
+ assert(fio.seek(_fd, 0, SEEK_CUR) == _cacheFilePos + _bytesInCache);
+ fio.seek(_fd, from, SEEK_SET);
+ int rdRes;
+ do {
+ fio.read(_fd, destBuf, len);
+ rdRes = fio.sync(_fd);
+ destBuf += rdRes;
+ from += rdRes;
+ len -= rdRes;
+ } while (len && rdRes);
+ fio.seek(_fd, _cacheFilePos + _bytesInCache, SEEK_SET);
+ break;
+ }
+ }
+ processCache(false);
+ SignalSema(_sema);
+ return destBuf - (uint8*)dest;
+}
+
+void SmushReader::virtSeek(uint32 from, uint32 to) {
+ WaitSema(_sema);
+ if (_lastRead[0] == from)
+ _lastRead[0] = to;
+ else if (_lastRead[1] == from)
+ _lastRead[1] = to;
+ SignalSema(_sema);
+}
+
+uint32 SmushReader::size(void) {
+ assert(_fd >= 0);
+ return _fileSize;
+}
+
+bool SmushReader::keepOpened(void) {
+ return _refCount > 0;
+}
+
+#define MAX_READERS 3
+
+static SmushReader *g_smushReaders[MAX_READERS] = { NULL, NULL, NULL };
+
+static int g_openSema = -1;
+
+Ps2SmushFile::Ps2SmushFile(int64 cacheId) : Ps2File(cacheId) {
+ _filePos = _fileSize = 0;
+ _id = -1;
+ if (g_openSema < 0) {
+ ee_sema_t newSema;
+ newSema.init_count = 1;
+ newSema.max_count = 1;
+ g_openSema = CreateSema(&newSema);
+ assert(g_openSema >= 0);
+ }
+}
+
+Ps2SmushFile::~Ps2SmushFile(void) {
+ WaitSema(g_openSema);
+ if (_id >= 0) {
+ g_smushReaders[_id]->close();
+ if (!g_smushReaders[_id]->keepOpened()) {
+ delete g_smushReaders[_id];
+ g_smushReaders[_id] = NULL;
+ }
+ }
+ SignalSema(g_openSema);
+}
+
+bool Ps2SmushFile::open(const char *name) {
+ WaitSema(g_openSema);
+ int opSlot = MAX_READERS;
+ for (int i = 0; i < MAX_READERS; i++) {
+ if (g_smushReaders[i]) {
+ sioprintf("attaching to reader in slot %d", i);
+ if (g_smushReaders[i]->open(name) == 0) {
+ _id = i;
+ _fileSize = g_smushReaders[i]->size();
+ sioprintf("attach ok");
+ break;
+ }
+ } else if (opSlot == MAX_READERS)
+ opSlot = i;
+ }
+ if (_id < 0) { // smush file wasn't opened before
+ sioprintf("creating new reader in slot %d", opSlot);
+ if (opSlot < MAX_READERS) {
+ g_smushReaders[opSlot] = new SmushReader();
+ if (g_smushReaders[opSlot]->open(name) == 0) {
+ _id = opSlot;
+ _fileSize = g_smushReaders[opSlot]->size();
+ } else {
+ // can't open file
+ delete g_smushReaders[opSlot];
+ g_smushReaders[opSlot] = NULL;
+ }
+ } else
+ printf("Ran out of reader slots\n");
+ }
+ SignalSema(g_openSema);
+ return (_id >= 0);
+}
+
+uint32 Ps2SmushFile::read(void *dest, uint32 len) {
+ int res = g_smushReaders[_id]->read(dest, _filePos, len);
+ _filePos += res;
+ return res;
+}
+
+uint32 Ps2SmushFile::write(const void *src, uint32 len) {
+ printf("ERROR: Received write request on Smush reader\n");
+ SleepThread();
+ return 0;
+}
+
+uint32 Ps2SmushFile::tell(void) {
+ return _filePos;
+}
+
+uint32 Ps2SmushFile::size(void) {
+ return _fileSize;
+}
+
+int Ps2SmushFile::seek(int32 offset, int origin) {
+ int32 res;
+ switch (origin) {
+ case SEEK_SET:
+ res = offset;
+ break;
+ case SEEK_CUR:
+ res = _filePos + offset;
+ break;
+ case SEEK_END:
+ res = _fileSize + offset;
+ break;
+ default:
+ return -1;
+ }
+ if ((res >= 0) && (res <= _fileSize)) {
+ if (offset != 0)
+ g_smushReaders[_id]->virtSeek(_filePos, res);
+ _filePos = res;
+ return 0;
+ }
+ return -1;
+}
+
+bool Ps2SmushFile::eof(void) {
+ return _filePos == _fileSize;
+}
+
diff --git a/backends/ps2/sysdefs.h b/backends/ps2/sysdefs.h
index a00230a26e..50502283f4 100644
--- a/backends/ps2/sysdefs.h
+++ b/backends/ps2/sysdefs.h
@@ -32,14 +32,16 @@ typedef signed int int32;
typedef signed long int64;
enum Interrupts {
+ INT_GS = 0,
INT_VBLANK_START = 2,
+ INT_VBLANK_END = 3,
INT_TIMER0 = 9
};
// dma 2 registers
#define D2_CHCR (*(volatile uint32*)0x1000A000)
-#define D2_QWC (*(volatile uint32*)0x1000A020) // D2_SIZE
-#define D2_TADR (*(volatile uint32*)0x1000A030) // D2_TAG
+#define D2_QWC (*(volatile uint32*)0x1000A020)
+#define D2_TADR (*(volatile uint32*)0x1000A030)
#define D2_MADR (*(volatile uint32*)0x1000A010)
#define D2_ASR1 (*(volatile uint32*)0x1000A050)
#define D2_ASR0 (*(volatile uint32*)0x1000A040)
diff --git a/backends/ps2/systemps2.cpp b/backends/ps2/systemps2.cpp
index 64636baf48..8e30d1f7bc 100644
--- a/backends/ps2/systemps2.cpp
+++ b/backends/ps2/systemps2.cpp
@@ -28,7 +28,6 @@
#include <loadfile.h>
#include <malloc.h>
#include <assert.h>
-#include <fileio.h>
#include <iopcontrol.h>
#include <iopheap.h>
#include "scummsys.h"
@@ -37,7 +36,7 @@
#include "backends/ps2/systemps2.h"
#include "backends/ps2/Gs2dScreen.h"
#include "backends/ps2/ps2input.h"
-#include "sjpcm.h"
+#include <sjpcm.h>
#include <cdvd_rpc.h>
#include "backends/ps2/savefile.h"
#include "common/file.h"
@@ -45,13 +44,14 @@
#include <libmc.h>
#include "backends/ps2/cd.h"
#include <sio.h>
+#include <fileXio_rpc.h>
#define TIMER_STACK_SIZE (1024 * 32)
#define SOUND_STACK_SIZE (1024 * 32)
#define SMP_PER_BLOCK 800
#define FROM_BCD(a) ((a >> 4) * 10 + (a & 0xF))
-
-#define CHECK_STACK_USAGE
+#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)
#ifdef USE_PS2LINK
#define IRX_PREFIX "host:"
@@ -61,13 +61,14 @@
#define IRX_SUFFIX ";1"
#endif
-static volatile int32 g_TimerThreadSema = -1;
-static volatile int32 g_SoundThreadSema = -1;
+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;
extern void NORETURN CDECL error(const char *s, ...);
-static OSystem_PS2 *g_systemPs2 = NULL;
+OSystem_PS2 *g_systemPs2 = NULL;
void readRtcTime(void);
@@ -94,12 +95,9 @@ extern "C" int scummvm_main(int argc, char *argv[]);
extern "C" int main(int argc, char *argv[]) {
SifInitRpc(0);
-#ifdef USE_PS2LINK
- fioInit();
-#else // reset the IOP if this is a CD build
+#ifndef USE_PS2LINK // reset the IOP if this is a CD build
cdvdInit(CDVD_EXIT);
cdvdExit();
- fioExit();
SifExitIopHeap();
SifLoadFileExit();
SifExitRpc();
@@ -109,7 +107,6 @@ extern "C" int main(int argc, char *argv[]) {
;
sio_puts("IOP synced.");
SifInitRpc(0);
- fioInit();
SifLoadFileInit();
cdvdInit(CDVD_INIT_NOWAIT);
#endif
@@ -141,11 +138,26 @@ extern "C" int main(int argc, char *argv[]) {
}
s32 timerInterruptHandler(s32 cause) {
- msecCount += 10;
+ msecCount += (((uint64)256 * CLK_DIVIS) << 32) / (BUS_CLOCK / 1000);
T0_MODE = 0xDC2; // same value as in initialization.
iSignalSema(g_SoundThreadSema);
iSignalSema(g_TimerThreadSema);
+
+ if (g_MainWakeUp) {
+ g_MainWakeUp -= 10;
+ if (g_MainWakeUp <= 0) {
+ iSignalSema(g_MainWaitSema);
+ g_MainWakeUp = 0;
+ }
+ }
+ if (g_TimerWakeUp) {
+ g_TimerWakeUp -= 10;
+ if (g_TimerWakeUp <= 0) {
+ iSignalSema(g_TimerWaitSema);
+ g_TimerWakeUp = 0;
+ }
+ }
return 0;
}
@@ -189,7 +201,7 @@ OSystem_PS2::OSystem_PS2(void) {
sioprintf("Initializing LibCDVD.");
int res = CDVD_Init();
- sioprintf("result = %d\n", res);
+ sioprintf("result = %d", res);
_timerTid = _soundTid = -1;
_mouseVisible = false;
@@ -197,14 +209,18 @@ OSystem_PS2::OSystem_PS2(void) {
sioprintf("reading RTC");
readRtcTime();
- sioprintf("Setting non-blocking fio");
- fioSetBlockMode(FIO_NOWAIT); // asynchronous file i/o
+ sioprintf("Initializing FXIO");
+ if (fileXioInit() < 0) {
+ sioprintf("Can't init fileXio\n");
+ SleepThread();
+ }
+ fileXioSetBlockMode(FXIO_NOWAIT);
sioprintf("Starting SavefileManager");
- _saveManager = new Ps2SaveFileManager(NULL, TO_MC, _screen);
+ _saveManager = new Ps2SaveFileManager(this, _screen);
- _soundBuf = (int16*)malloc(SMP_PER_BLOCK * 2 * sizeof(int16));
- _soundBuf2 = (int16*)malloc(SMP_PER_BLOCK * sizeof(int16));
+ _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);
@@ -217,9 +233,6 @@ OSystem_PS2::~OSystem_PS2(void) {
}
void OSystem_PS2::initTimer(void) {
- // this has to be set before the timer interrupt handler gets called
- g_systemPs2 = this;
-
// first setup the two threads that get activated by the timer:
// the timerthread and the soundthread
ee_sema_t threadSema;
@@ -233,9 +246,7 @@ void OSystem_PS2::initTimer(void) {
ReferThreadStatus(GetThreadId(), &thisThread);
_timerStack = (uint8*)malloc(TIMER_STACK_SIZE);
- memset(_timerStack, 0xE7, TIMER_STACK_SIZE);
_soundStack = (uint8*)malloc(SOUND_STACK_SIZE);
- memset(_soundStack, 0xE7, SOUND_STACK_SIZE);
// give timer thread a higher priority than main thread
timerThread.initial_priority = thisThread.current_priority - 1;
@@ -260,12 +271,19 @@ void OSystem_PS2::initTimer(void) {
StartThread(_timerTid, this);
StartThread(_soundTid, this);
+ // these semaphores are used for OSystem::delay()
+ threadSema.init_count = 0;
+ threadSema.max_count = 1;
+ g_MainWaitSema = CreateSema(&threadSema);
+ g_TimerWaitSema = CreateSema(&threadSema);
+ assert((g_MainWaitSema >= 0) && (g_TimerWaitSema >= 0));
+
// threads done, start the interrupt handler
- AddIntcHandler( INT_TIMER0, timerInterruptHandler, 0); // 0=first handler, 9 = cause = timer0
+ AddIntcHandler( INT_TIMER0, timerInterruptHandler, 0); // 0=first handler
EnableIntc(INT_TIMER0);
T0_HOLD = 0;
T0_COUNT = 0;
- T0_COMP = 5859; // (busclock / 256) / 5859 = ~ 100.0064
+ T0_COMP = CLK_DIVIS; // (busclock / 256) / 5859 = ~ 100.0064
T0_MODE = TIMER_MODE( 2, 0, 0, 0, 1, 1, 1, 0, 1, 1);
}
@@ -274,7 +292,6 @@ void OSystem_PS2::timerThread(void) {
WaitSema(g_TimerThreadSema);
if (_scummTimerProc)
_scummTimerProc(0);
- _screen->timerTick();
}
}
@@ -284,22 +301,59 @@ void OSystem_PS2::soundThread(void) {
soundSema.max_count = 1;
_soundSema = CreateSema(&soundSema);
assert(_soundSema >= 0);
+
+ int bufferedSamples = 0;
+ int cycles = 0;
while (1) {
WaitSema(g_SoundThreadSema);
+
+ if (!(cycles & 31))
+ bufferedSamples = SjPCM_Buffered();
+ else
+ bufferedSamples -= 480;
+ cycles++;
WaitSema(_soundSema);
if (_scummSoundProc) {
- while (SjPCM_Buffered() <= 4 * SMP_PER_BLOCK) {
- // call sound mixer
- _scummSoundProc(_scummSoundParam, (uint8*)_soundBuf, SMP_PER_BLOCK * 2 * sizeof(int16));
- // split data into 2 buffers, L and R
- _soundBuf2[0] = _soundBuf[1];
- for (uint32 cnt = 1; cnt < SMP_PER_BLOCK; cnt++) {
- _soundBuf[cnt] = _soundBuf[cnt << 1];
- _soundBuf2[cnt] = _soundBuf[(cnt << 1) | 1];
- }
+ if (bufferedSamples <= 8 * 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));
+
+ // demux data into 2 buffers, L and R
+ __asm__ (
+ "move $t2, %1\n\t" // dest buffer right
+ "move $t3, %0\n\t" // dest buffer left
+ "lui $t8, 0x7000\n\t" // muxed buffer, fixed at 0x70000000
+ "addiu $t9, $0, 100\n\t" // number of loops
+ "mtsab $0, 2\n\t" // set qword shift = 2 byte
+
+ "loop:\n\t"
+ " lq $t4, 0($t8)\n\t" // load 8 muxed samples
+ " lq $t5, 16($t8)\n\t" // load 8 more muxed samples
+
+ " qfsrv $t6, $0, $t4\n\t" // shift right for second
+ " qfsrv $t7, $0, $t5\n\t" // packing step (right channel)
+
+ " ppach $t4, $t5, $t4\n\t" // combine left channel data
+ " ppach $t6, $t7, $t6\n\t" // right channel data
+
+ " sq $t4, 0($t3)\n\t" // write back
+ " sq $t6, 0($t2)\n\t" //
+
+ " addiu $t9, -1\n\t" // decrement loop counter
+ " addiu $t2, 16\n\t" // increment pointers
+ " addiu $t3, 16\n\t"
+ " addiu $t8, 32\n\t"
+ " bnez $t9, loop\n\t" // loop
+ : // outputs
+ : "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*)_soundBuf, (short int*)_soundBuf2, SMP_PER_BLOCK, 1);
+ SjPCM_Enqueue((short int*)_soundBufL, (short int*)_soundBufR, SMP_PER_BLOCK, 0);
+ bufferedSamples += SMP_PER_BLOCK;
}
}
SignalSema(_soundSema);
@@ -321,25 +375,27 @@ bool OSystem_PS2::loadModules(void) {
sioprintf("Cannot load module: PADMAN (%d)\n", res);
else if ((res = SifLoadModule("rom0:LIBSD", 0, NULL)) < 0)
sioprintf("Cannot load module: LIBSD (%d)\n", res);
+#ifndef USE_PS2LINK
+ else if ((res = SifLoadModule(IRX_PREFIX "IOMANX.IRX" IRX_SUFFIX, 0, NULL)) < 0)
+ sioprintf("Cannot load module: IOMANX.IRX (%d)\n", res);
+#endif
+ else if ((res = SifLoadModule(IRX_PREFIX "FILEXIO.IRX" IRX_SUFFIX, 0, NULL)) < 0)
+ sioprintf("Cannot load module: FILEXIO.IRX (%d)\n", res);
else if ((res = SifLoadModule(IRX_PREFIX "CDVD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
sioprintf("Cannot load module CDVD.IRX (%d)\n", res);
else if ((res = SifLoadModule(IRX_PREFIX "SJPCM.IRX" IRX_SUFFIX, 0, NULL)) < 0)
sioprintf("Cannot load module: SJPCM.IRX (%d)\n", res);
else {
- sioprintf("modules loaded\n");
+ sioprintf("modules loaded");
if ((res = SifLoadModule(IRX_PREFIX "USBD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
sioprintf("Cannot load module: USBD.IRX (%d)\n", res);
-#ifndef USE_PS2LINK
- else if ((res = SifLoadModule(IRX_PREFIX "IOMANX.IRX" IRX_SUFFIX, 0, NULL)) < 0)
- sioprintf("Cannot load module: IOMANX.IRX (%d)\n", res);
-#endif
else {
if ((res = SifLoadModule(IRX_PREFIX "PS2MOUSE.IRX" IRX_SUFFIX, 0, NULL)) < 0)
sioprintf("Cannot load module: PS2MOUSE.IRX (%d)\n", res);
else
_useMouse = true;
- if ((res = SifLoadModule(IRX_PREFIX "PS2KBD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
- sioprintf("Cannot load module: PS2KBD.IRX (%d)\n", res);
+ if ((res = SifLoadModule(IRX_PREFIX "RPCKBD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
+ sioprintf("Cannot load module: RPCKBD.IRX (%d)\n", res);
else
_useKbd = true;
}
@@ -377,9 +433,9 @@ void OSystem_PS2::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
buf -= y * pitch;
y = 0;
}
- if (w > x + _width)
+ if (x + w > _width)
w = _width - x;
- if (h > y + _height)
+ 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);
@@ -390,14 +446,25 @@ void OSystem_PS2::updateScreen(void) {
}
uint32 OSystem_PS2::getMillis(void) {
- return (uint32)msecCount;
+ return (uint32)(msecCount >> 32);
}
void OSystem_PS2::delayMillis(uint msecs) {
- uint64 endTime = msecCount + msecs;
+ if (msecs == 0)
+ return;
- while (endTime > msecCount) {
- // idle
+ int tid = GetThreadId();
+ if (tid == _soundTid) {
+ sioprintf("ERROR: delayMillis() from sound thread!");
+ return;
+ }
+
+ if (tid == _timerTid) {
+ g_TimerWakeUp = (int32)msecs;
+ WaitSema(g_TimerWaitSema);
+ } else {
+ g_MainWakeUp = (int32)msecs;
+ WaitSema(g_MainWaitSema);
}
}
@@ -565,12 +632,12 @@ void OSystem_PS2::quit(void) {
static uint32 g_timeSecs;
static uint8 g_day, g_month, g_year;
-static uint64 g_lastTimeCheck;
+static uint32 g_lastTimeCheck;
void readRtcTime(void) {
struct CdClock cdClock;
CDVD_ReadClock(&cdClock);
- g_lastTimeCheck = msecCount;
+ g_lastTimeCheck = (uint32)(msecCount >> 32);
if (cdClock.stat)
printf("Unable to read RTC time.\n");
@@ -585,7 +652,7 @@ void readRtcTime(void) {
g_day, g_month, g_year + 2000);
}
-time_t time(time_t *p) {
+extern time_t time(time_t *p) {
time_t blah;
memset(&blah, 0, sizeof(time_t));
return blah;
@@ -593,11 +660,11 @@ time_t time(time_t *p) {
#define SECONDS_PER_DAY (24 * 60 * 60)
-struct tm *localtime(const time_t *p) {
- uint32 currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
+extern struct tm *localtime(const time_t *p) {
+ uint32 currentSecs = g_timeSecs + ((msecCount >> 32) - g_lastTimeCheck) / 1000;
if (currentSecs >= SECONDS_PER_DAY) {
readRtcTime();
- currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
+ currentSecs = g_timeSecs + ((msecCount >> 32) - g_lastTimeCheck) / 1000;
}
static struct tm retStruct;
diff --git a/backends/ps2/systemps2.h b/backends/ps2/systemps2.h
index 169ffb9088..942cf1b851 100644
--- a/backends/ps2/systemps2.h
+++ b/backends/ps2/systemps2.h
@@ -93,7 +93,7 @@ private:
volatile OSystem::TimerProc _scummTimerProc;
volatile OSystem::SoundProc _scummSoundProc;
void *_scummSoundParam;
- int16 *_soundBuf, *_soundBuf2;
+ int16 *_soundBufL, *_soundBufR;
int _soundSema;
void initTimer(void);
@@ -107,7 +107,6 @@ private:
uint16 _width, _height;
Gs2dScreen *_screen;
- //PadMouse *_mouse;
Ps2Input *_input;
uint16 _oldMouseX, _oldMouseY;