[Scummvm-cvs-logs] CVS: scummvm/backends/ps2 smushio.cpp,NONE,1.1 DmaPipe.cpp,1.2,1.3 DmaPipe.h,1.2,1.3 Gs2dScreen.cpp,1.2,1.3 Gs2dScreen.h,1.2,1.3 GsDefs.h,1.2,1.3 asyncfio.cpp,1.2,1.3 asyncfio.h,1.2,1.3 fileio.cpp,1.2,1.3 fileio.h,1.2,1.3 ps2input.cpp,1.2,1.3 ps2input.h,1.2,1.3 ps2pad.cpp,1.2,1.3 ps2pad.h,1.2,1.3 savefile.cpp,1.2,1.3 savefile.h,1.3,1.4 sysdefs.h,1.2,1.3 systemps2.cpp,1.3,1.4 systemps2.h,1.2,1.3 libkbd.cpp,1.1,NONE sjpcm.h,1.1,NONE
Robert Göffringmann
lavosspawn at users.sourceforge.net
Wed May 4 20:07:15 CEST 2005
- Previous message: [Scummvm-cvs-logs] CVS: scummvm/backends/dc vmsave.cpp,1.26,1.27
- Next message: [Scummvm-cvs-logs] CVS: scummvm/gob game.cpp,1.19,1.20 goblin.cpp,1.14,1.15 init.cpp,1.9,1.10 mult.cpp,1.9,1.10 palanim.cpp,1.6,1.7
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/scummvm/scummvm/backends/ps2
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13669/backends/ps2
Modified Files:
DmaPipe.cpp DmaPipe.h Gs2dScreen.cpp Gs2dScreen.h GsDefs.h
asyncfio.cpp asyncfio.h fileio.cpp fileio.h ps2input.cpp
ps2input.h ps2pad.cpp ps2pad.h savefile.cpp savefile.h
sysdefs.h systemps2.cpp systemps2.h
Added Files:
smushio.cpp
Removed Files:
libkbd.cpp sjpcm.h
Log Message:
various PS2 system changes
--- NEW FILE: smushio.cpp ---
/* 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: /cvsroot/scummvm/scummvm/backends/ps2/smushio.cpp,v 1.1 2005/05/05 03:06:32 lavosspawn Exp $
*
*/
/*
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;
}
Index: DmaPipe.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/DmaPipe.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- DmaPipe.cpp 31 Mar 2005 07:50:32 -0000 1.2
+++ DmaPipe.cpp 5 May 2005 03:06:31 -0000 1.3
@@ -128,15 +128,15 @@
_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 @@
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 @@
// 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 @@
_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();
Index: DmaPipe.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/DmaPipe.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- DmaPipe.h 31 Mar 2005 07:50:32 -0000 1.2
+++ DmaPipe.h 5 May 2005 03:06:31 -0000 1.3
@@ -43,8 +43,8 @@
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 @@
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:
Index: Gs2dScreen.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/Gs2dScreen.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Gs2dScreen.cpp 31 Mar 2005 07:50:32 -0000 1.2
+++ Gs2dScreen.cpp 5 May 2005 03:06:31 -0000 1.3
@@ -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 @@
};
#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 @@
#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) }
+};
-int32 vblankHandler(int32 cause) {
+void sioprintf(const char *zFormat, ...);
+
+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 @@
_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 @@
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 @@
_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 @@
_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 @@
_dmaPipe->waitForDma();
}
_dmaPipe->uploadTex(_clutPtrs[TEXT], 64, 0, 0, GS_PSMCT32, _binaryClut, 8, 2);
+ _dmaPipe->flush();
free(buf);
}
@@ -221,33 +240,47 @@
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 @@
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 @@
_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 @@
_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::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 @@
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 @@
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 @@
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
+ do {
+ WaitSema(g_AnimSema);
+ } while (!g_RunAnim);
- _dmaPipe->setAlphaBlend(SOURCE_COLOR, ZERO_COLOR, SOURCE_ALPHA, DEST_COLOR, 0);
- yPos -= scrlSpeed;
- if (yPos <= -LINE_SPACE) {
- yPos += LINE_SPACE;
- texSta++;
- }
+ 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...
- float drawY = yPos;
+ // redraw the engine's last frame
+ _dmaPipe->flatRect(kFullScreen + 0, kFullScreen + 1, GS_RGBA(0, 0, 0, 0)); // clear screen
- for (int i = 0; i < texMax; i++) {
- uint8 texIdx = (texSta + i) & 0xF;
+ 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 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];
+ _dmaPipe->setAlphaBlend(SOURCE_COLOR, ZERO_COLOR, SOURCE_ALPHA, DEST_COLOR, 0);
+ yPos -= scrlSpeed;
+ if (yPos <= -LINE_SPACE) {
+ yPos += LINE_SPACE;
+ texSta++;
+ }
- 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);
- }
+ float drawY = yPos;
- 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));
+ for (int i = 0; i < texMax; i++) {
+ uint8 texIdx = (texSta + i) & 0xF;
- drawY += LINE_SPACE;
+ 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 @@
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);
Index: Gs2dScreen.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/Gs2dScreen.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Gs2dScreen.h 31 Mar 2005 07:50:32 -0000 1.2
+++ Gs2dScreen.h 5 May 2005 03:06:31 -0000 1.3
@@ -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 @@
GS_INTERLACED
};
-class DmaPipe;
+//class DmaPipe;
class Gs2dScreen {
public:
@@ -62,17 +60,15 @@
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 @@
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];
Index: GsDefs.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/GsDefs.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- GsDefs.h 31 Mar 2005 07:50:32 -0000 1.2
+++ GsDefs.h 5 May 2005 03:06:31 -0000 1.3
@@ -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))
Index: asyncfio.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/asyncfio.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- asyncfio.cpp 31 Mar 2005 07:50:32 -0000 1.2
+++ asyncfio.cpp 5 May 2005 03:06:31 -0000 1.3
@@ -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 @@
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 @@
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 @@
checkSync();
assert(fd < MAX_HANDLES);
_runningOp = _ioSlots + fd;
- fioRead(fd, dest, len);
+ fileXioRead(fd, (unsigned char*)dest, len);
SignalSema(_ioSema);
}
@@ -84,14 +94,26 @@
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 @@
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 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
Index: asyncfio.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/asyncfio.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- asyncfio.h 31 Mar 2005 07:50:32 -0000 1.2
+++ asyncfio.h 5 May 2005 03:06:31 -0000 1.3
@@ -30,13 +30,14 @@
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];
};
Index: fileio.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/fileio.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- fileio.cpp 31 Mar 2005 07:50:32 -0000 1.2
+++ fileio.cpp 5 May 2005 03:06:31 -0000 1.3
@@ -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);
-}
-
-int AccessFio::seek(int32 offset, int whence) {
- return fio.seek(_handle, offset, whence);
-}
-
-/*class AccessFioX : public AccessFio{
-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);
+Ps2File::Ps2File(int64 cacheId) {
+ _cacheId = cacheId;
}
-int AccessFioX::write(const void *src, uint32 size) {
- return fileXioWrite(_handle, (unsigned char*)src, size);
+Ps2File::~Ps2File(void) {
}
-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);
-private:
- void readDir(const char *path, TocNode **node, int level);
- TocNode *_rootNode;
- char _root[256];
- uint8 _rootLen;
-};
-
-class Ps2File {
+class Ps2ReadFile : public 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);
+ 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 checkCache(void);
- void syncCache(void);
- bool _cacheOp;
- bool _seekReset;
+ void cacheReadAhead(void);
+ void cacheReadSync(void);
+ int _fd, _sema;
+ uint8 *_cacheBuf;
+ bool _cacheOpRunning;
+ uint32 _filePos, _physFilePos, _cachePos;
+ uint32 _fileSize, _bytesInCache, _cacheOfs;
- 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;
}
-bool Ps2File::isOpen(void) {
- return (_handle != NULL);
+uint32 Ps2ReadFile::size(void) {
+ WaitSema(_sema);
+ uint32 res = _fileSize;
+ SignalSema(_sema);
+ return res;
}
-int Ps2File::seek(int32 offset, int origin) {
- assert(!_forWriting);
- syncCache();
- uint32 seekDest;
+bool Ps2ReadFile::eof(void) {
+ WaitSema(_sema);
+ bool res = (_filePos == _fileSize);
+ SignalSema(_sema);
+ return res;
+}
+
+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;
-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 (_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;
}
+
+ 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;
+ uint32 doCpy = (len > CACHE_SIZE - _bytesInCache) ? (CACHE_SIZE - _bytesInCache) : len;
+ if (doCpy) {
+ memcpy(_cacheBuf + _bytesInCache, srcBuf, doCpy);
+ _bytesInCache += doCpy;
+ srcBuf += doCpy;
+ size -= doCpy;
+ }
- 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);
+ 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;
}
-
- 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;
- }
+ _filePos += _bytesInCache;
+ _bytesInCache = 0;
}
}
- return srcBuf - (uint8*)src;
+ return len;
}
-uint32 Ps2File::tell(void) {
- if (_seekReset)
- seek(0, SEEK_SET);
- return _filePos;
+uint32 Ps2WriteFile::tell(void) {
+ return _bytesInCache + _filePos;
}
-uint32 Ps2File::size(void) {
- assert(!_forWriting);
- return _fSize;
+uint32 Ps2WriteFile::size(void) {
+ return tell();
}
-AccessFio *Ps2File::giveHandle(void) {
- assert(_handle);
- return _handle;
+int Ps2WriteFile::seek(int32 offset, int origin) {
+ printf("Seek(%d/%d) request on Ps2WriteFile\n", offset, origin);
+ SleepThread();
+ return 0;
+}
+
+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 @@
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 @@
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 @@
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 @@
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 @@
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();
}
Index: fileio.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/fileio.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- fileio.h 31 Mar 2005 07:50:32 -0000 1.2
+++ fileio.h 5 May 2005 03:06:31 -0000 1.3
@@ -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_fputs(const char *s, FILE *stream);
int ps2_fprintf(FILE *pOut, const char *zFormat, ...);
-AccessFio *fetchHandle(File *file);
-
#endif // __PS2FILE_IO__
+
Index: ps2input.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/ps2input.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- ps2input.cpp 31 Mar 2005 07:50:32 -0000 1.2
+++ ps2input.cpp 5 May 2005 03:06:31 -0000 1.3
@@ -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 @@
if (_kbdLoaded) {
if (PS2KbdInit() >= 0) {
PS2KbdSetReadmode(PS2KBD_READMODE_RAW);
- PS2KbdSetBlockingMode(PS2KBD_NONBLOCKING);
printf("PS2Kbd initialized\n");
} else {
printf("unable to initialize PS2Kbd!\n");
Index: ps2pad.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/ps2pad.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- ps2pad.cpp 31 Mar 2005 07:50:32 -0000 1.2
+++ ps2pad.cpp 5 May 2005 03:06:31 -0000 1.3
@@ -111,17 +111,9 @@
}
}
-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 @@
}
-
Index: ps2pad.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/ps2pad.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- ps2pad.h 31 Mar 2005 07:50:32 -0000 1.2
+++ ps2pad.h 5 May 2005 03:06:31 -0000 1.3
@@ -49,7 +49,7 @@
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;
Index: savefile.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/savefile.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- savefile.cpp 31 Mar 2005 07:50:32 -0000 1.2
+++ savefile.cpp 5 May 2005 03:06:31 -0000 1.3
@@ -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 @@
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 (ext && *ext)
+ sprintf(name, "%s.ucl", ext);
+ else
+ strcpy(name, "save.ucl");
+}
- 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);
+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;
+ sprintf(dirStr, "/ScummVM-%s/*", dir);
+ mcGetDir(0, 0, dirStr, 0, MAX_MC_ENTRIES, _mcDirList);
+ mcSync(0, NULL, &_mcEntries);
+ return (_mcEntries >= 0);
+ } else
+ return true;
+}
- if (!fileExists) {
- _screen->wantAnim(false);
- return NULL;
+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 @@
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 @@
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 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 @@
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;
-StdioSaveFile::StdioSaveFile(const char *filename, bool saveOrLoad) {
- _fh = ::fopen(filename, (saveOrLoad? "wb" : "rb"));
- _saving = saveOrLoad;
+ 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(void) {
- if (_fh)
- ::fclose(_fh);
+UclInSaveFile::~UclInSaveFile(void) {
+ if (_buf)
+ free(_buf);
+ _screen->wantAnim(false);
}
-bool StdioSaveFile::isOpen(void) const {
- return _fh != NULL;
+bool UclInSaveFile::ioFailed(void) {
+ return _ioFailed;
}
-uint32 StdioSaveFile::read(void *buf, uint32 cnt) {
- assert(!_saving);
- return ::fread(buf, 1, cnt, _fh);
+void UclInSaveFile::clearIOFailed(void) {
+ _ioFailed = false;
}
-uint32 StdioSaveFile::write(const void *buf, uint32 cnt) {
- assert(_saving);
- return ::fwrite(buf, 1, cnt, _fh);
+bool UclInSaveFile::eos(void) const {
+ return _bufPos == _bufSize;
}
-UclSaveFile::UclSaveFile(const char *filename, bool saveOrLoad, Gs2dScreen *screen) {
- _fh = ::fopen(filename, (saveOrLoad? "wb" : "rb"));
- _saving = saveOrLoad;
- _bufPos = 0;
- _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 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;
+}
- 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);
- }
+UclOutSaveFile::UclOutSaveFile(const char *filename, Gs2dScreen *screen) {
+ _screen = screen;
+ _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);
+ _ioFailed = true;
+ printf("UclOutSaveFile::flush failed!\n");
+ return -1;
}
-bool UclSaveFile::isOpen(void) const {
- return (_buf != NULL);
-}
-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;
}
+
Index: savefile.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/savefile.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- savefile.h 10 Apr 2005 15:13:36 -0000 1.3
+++ savefile.h 5 May 2005 03:06:31 -0000 1.4
@@ -32,42 +32,40 @@
};
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__
Index: sysdefs.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/sysdefs.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- sysdefs.h 31 Mar 2005 07:50:33 -0000 1.2
+++ sysdefs.h 5 May 2005 03:06:31 -0000 1.3
@@ -32,14 +32,16 @@
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)
Index: systemps2.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/systemps2.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- systemps2.cpp 1 Apr 2005 03:00:51 -0000 1.3
+++ systemps2.cpp 5 May 2005 03:06:31 -0000 1.4
@@ -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 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 @@
;
sio_puts("IOP synced.");
SifInitRpc(0);
- fioInit();
SifLoadFileInit();
cdvdInit(CDVD_INIT_NOWAIT);
#endif
@@ -141,11 +138,26 @@
}
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
WaitSema(g_TimerThreadSema);
if (_scummTimerProc)
_scummTimerProc(0);
- _screen->timerTick();
}
}
@@ -284,22 +301,59 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
#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;
Index: systemps2.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/systemps2.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- systemps2.h 31 Mar 2005 07:50:33 -0000 1.2
+++ systemps2.h 5 May 2005 03:06:32 -0000 1.3
@@ -93,7 +93,7 @@
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 @@
uint16 _width, _height;
Gs2dScreen *_screen;
- //PadMouse *_mouse;
Ps2Input *_input;
uint16 _oldMouseX, _oldMouseY;
--- libkbd.cpp DELETED ---
--- sjpcm.h DELETED ---
- Previous message: [Scummvm-cvs-logs] CVS: scummvm/backends/dc vmsave.cpp,1.26,1.27
- Next message: [Scummvm-cvs-logs] CVS: scummvm/gob game.cpp,1.19,1.20 goblin.cpp,1.14,1.15 init.cpp,1.9,1.10 mult.cpp,1.9,1.10 palanim.cpp,1.6,1.7
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Scummvm-git-logs
mailing list