aboutsummaryrefslogtreecommitdiff
path: root/backends/ps2/smushio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/ps2/smushio.cpp')
-rw-r--r--backends/ps2/smushio.cpp376
1 files changed, 0 insertions, 376 deletions
diff --git a/backends/ps2/smushio.cpp b/backends/ps2/smushio.cpp
deleted file mode 100644
index 84efcbbcd1..0000000000
--- a/backends/ps2/smushio.cpp
+++ /dev/null
@@ -1,376 +0,0 @@
-/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $Header$
- *
- */
-
-/*
- The Smush player uses at least two handles for accessing the same SMUSH file,
- to avoid threading issues. One handle for video, one for audio apparently.
- Each of the handles always skips the data that the other one read before
- (or will read later).
-
- This behaviour makes it difficult to do read ahead caching without reading
- any given file twice, so this class tries to "reunite" the read accesses and
- do the necessary caching.
-*/
-
-#include "backends/ps2/fileio.h"
-#include "backends/ps2/asyncfio.h"
-#include <kernel.h>
-#include <assert.h>
-#include <string.h>
-#include <sio.h>
-
-extern AsyncFio fio;
-extern void sioprintf(const char *zFormat, ...);
-
-#define SMUSH_CACHE_SIZE (5 * 1024 * 1024)
-#define READ_STEP (32 * 1024)
-#define SMUSH_IN_USE -2
-
-class SmushReader {
-public:
- SmushReader(void);
- ~SmushReader(void);
- int open(const char *name);
- void close(void);
- uint32 read(void *dest, uint32 from, uint32 len);
- void virtSeek(uint32 from, uint32 to);
- uint32 size(void);
- bool keepOpened(void);
-private:
- void processCache(bool sync);
- char _fname[256];
- int _sema, _fd, _refCount;
- uint8 *_cacheBuf;
- volatile uint32 _cacheFilePos, _bytesInCache, _fileSize, _cacheBufOfs;
- volatile uint32 _lastRead[2];
- volatile bool _cacheOp;
-};
-
-SmushReader::SmushReader(void) {
- _cacheBuf = NULL;
- _fd = -1;
- _refCount = 0;
-
- ee_sema_t newSema;
- newSema.init_count = 1;
- newSema.max_count = 1;
- _sema = CreateSema(&newSema);
- assert(_sema >= 0);
-}
-
-SmushReader::~SmushReader(void) {
- DeleteSema(_sema);
-}
-
-int SmushReader::open(const char *name) {
- WaitSema(_sema);
- if (_refCount) {
- if (stricmp(_fname, name)) {
- sioprintf("SmushReader is already open to file\n%s\nGot open request for %s", _fname, name);
- SignalSema(_sema);
- return SMUSH_IN_USE;
- }
- } else {
- assert(_fd < 0);
- _fd = fio.open(name, O_RDONLY);
- if (_fd < 0) {
- SignalSema(_sema);
- return -1;
- }
- _fileSize = fio.seek(_fd, 0, SEEK_END);
- fio.seek(_fd, 0, SEEK_SET);
-
- _cacheBuf = (uint8*)malloc(SMUSH_CACHE_SIZE);
- if (!_cacheBuf) {
- sioprintf("Smush Reader ran out of memory");
- fio.close(_fd);
- _fd = -1;
- SignalSema(_sema);
- return -1;
- }
- _lastRead[0] = _lastRead[1] = 0;
- _cacheBufOfs = _bytesInCache = _cacheFilePos = 0;
- fio.read(_fd, _cacheBuf, READ_STEP);
- _cacheOp = true;
- strcpy(_fname, name);
- }
- _refCount++;
- sioprintf("SmushReader %s ref count %d", _fname, _refCount);
- SignalSema(_sema);
- return 0;
-}
-
-void SmushReader::close(void) {
- WaitSema(_sema);
- sioprintf("Closing Ref to %s", _fname);
- assert(_refCount > 0);
- _refCount--;
- if (!_refCount) {
- sioprintf("SmushReader: All references to %s closed", _fname);
- processCache(true);
- _fname[0] = '\0';
- fio.close(_fd);
- _fd = -1;
- free(_cacheBuf);
- _cacheBuf = NULL;
- }
- SignalSema(_sema);
-}
-
-#define MIN(a, b) ((a < b) ? (a) : (b))
-
-void SmushReader::processCache(bool sync) {
- if (_cacheOp) {
- if (sync || fio.poll(_fd)) { // has the transfer finished or were we told to wait for it to finish?
- int rdRes = fio.sync(_fd);
- assert(rdRes >= 0);
- _bytesInCache += rdRes;
- _cacheOp = false;
- }
- } else if (!sync) {
- if (_cacheFilePos + _bytesInCache == _fileSize)
- return;
-
- uint32 rdPos = MIN(_lastRead[0], _lastRead[1]);
-
- int cacheOfs = (rdPos - _cacheFilePos) & ~0xF; // we'd like to keep the buffer aligned to 16 bytes
- if (cacheOfs < 0) {
- sioprintf("ERROR: smush cache too far ahead!");
- return;
- }
-
- if (_bytesInCache - cacheOfs < SMUSH_CACHE_SIZE - READ_STEP) {
- // we want to do some more reading
- if (_bytesInCache > cacheOfs) {
- _bytesInCache -= cacheOfs;
- _cacheBufOfs += cacheOfs;
- _cacheFilePos += cacheOfs;
- } else {
- sioprintf("cache underrun!");
- _bytesInCache = 0;
- _cacheBufOfs = 0;
- _cacheFilePos = rdPos;
- }
-
- uint32 bufEndPos = (_cacheBufOfs + _bytesInCache) % SMUSH_CACHE_SIZE;
- uint32 readLen = SMUSH_CACHE_SIZE - bufEndPos;
- if (readLen > READ_STEP)
- readLen = READ_STEP;
-
- fio.read(_fd, _cacheBuf + bufEndPos, readLen);
- _cacheOp = true;
- }
- }
-}
-
-uint32 SmushReader::read(void *dest, uint32 from, uint32 len) {
- uint8 *destBuf = (uint8*)dest;
- WaitSema(_sema);
- if ((from >= _cacheFilePos) && (from + len <= _cacheFilePos + _bytesInCache))
- processCache(false);
- else {
- processCache(true); // we'll have to read, sync cache before.
- }
- uint32 readEnds = from + len;
- if (from == _lastRead[0])
- _lastRead[0] += len;
- else if (from == _lastRead[1])
- _lastRead[1] += len;
- else {
- if ((_lastRead[0] > readEnds) && (_lastRead[1] < readEnds)) {
- _lastRead[1] = readEnds;
- } else if ((_lastRead[0] < readEnds) && (_lastRead[1] > readEnds)) {
- _lastRead[0] = readEnds;
- } else {
- if ((_lastRead[0] < readEnds) && (_lastRead[1] < readEnds)) {
- if (_lastRead[0] < _lastRead[1])
- _lastRead[0] = readEnds;
- else
- _lastRead[1] = readEnds;
- } else
- sioprintf("unexpected readend: %d / %d => %d", _lastRead[0], _lastRead[1], readEnds);
- }
- }
-
- while (len) {
- while (len && (from >= _cacheFilePos) && (from < _cacheFilePos + _bytesInCache)) {
- uint32 cpyOfs = ((from - _cacheFilePos) + _cacheBufOfs) % SMUSH_CACHE_SIZE;
- uint32 cpyLen = _bytesInCache - (from - _cacheFilePos);
- if (cpyLen > len)
- cpyLen = len;
- if (cpyOfs + cpyLen > SMUSH_CACHE_SIZE)
- cpyLen = SMUSH_CACHE_SIZE - cpyOfs;
- memcpy(destBuf, _cacheBuf + cpyOfs, cpyLen);
- destBuf += cpyLen;
- from += cpyLen;
- len -= cpyLen;
- }
- if (len) {
- sioprintf("Smush cache missed: read %d -> %d, cache %d -> %d", from, len, _cacheFilePos, _bytesInCache);
- assert(fio.seek(_fd, 0, SEEK_CUR) == _cacheFilePos + _bytesInCache);
- fio.seek(_fd, from, SEEK_SET);
- int rdRes;
- do {
- fio.read(_fd, destBuf, len);
- rdRes = fio.sync(_fd);
- destBuf += rdRes;
- from += rdRes;
- len -= rdRes;
- } while (len && rdRes);
- fio.seek(_fd, _cacheFilePos + _bytesInCache, SEEK_SET);
- break;
- }
- }
- processCache(false);
- SignalSema(_sema);
- return destBuf - (uint8*)dest;
-}
-
-void SmushReader::virtSeek(uint32 from, uint32 to) {
- WaitSema(_sema);
- if (_lastRead[0] == from)
- _lastRead[0] = to;
- else if (_lastRead[1] == from)
- _lastRead[1] = to;
- SignalSema(_sema);
-}
-
-uint32 SmushReader::size(void) {
- assert(_fd >= 0);
- return _fileSize;
-}
-
-bool SmushReader::keepOpened(void) {
- return _refCount > 0;
-}
-
-#define MAX_READERS 3
-
-static SmushReader *g_smushReaders[MAX_READERS] = { NULL, NULL, NULL };
-
-static int g_openSema = -1;
-
-Ps2SmushFile::Ps2SmushFile(int64 cacheId) : Ps2File(cacheId) {
- _filePos = _fileSize = 0;
- _id = -1;
- if (g_openSema < 0) {
- ee_sema_t newSema;
- newSema.init_count = 1;
- newSema.max_count = 1;
- g_openSema = CreateSema(&newSema);
- assert(g_openSema >= 0);
- }
-}
-
-Ps2SmushFile::~Ps2SmushFile(void) {
- WaitSema(g_openSema);
- if (_id >= 0) {
- g_smushReaders[_id]->close();
- if (!g_smushReaders[_id]->keepOpened()) {
- delete g_smushReaders[_id];
- g_smushReaders[_id] = NULL;
- }
- }
- SignalSema(g_openSema);
-}
-
-bool Ps2SmushFile::open(const char *name) {
- WaitSema(g_openSema);
- int opSlot = MAX_READERS;
- for (int i = 0; i < MAX_READERS; i++) {
- if (g_smushReaders[i]) {
- sioprintf("attaching to reader in slot %d", i);
- if (g_smushReaders[i]->open(name) == 0) {
- _id = i;
- _fileSize = g_smushReaders[i]->size();
- sioprintf("attach ok");
- break;
- }
- } else if (opSlot == MAX_READERS)
- opSlot = i;
- }
- if (_id < 0) { // smush file wasn't opened before
- sioprintf("creating new reader in slot %d", opSlot);
- if (opSlot < MAX_READERS) {
- g_smushReaders[opSlot] = new SmushReader();
- if (g_smushReaders[opSlot]->open(name) == 0) {
- _id = opSlot;
- _fileSize = g_smushReaders[opSlot]->size();
- } else {
- // can't open file
- delete g_smushReaders[opSlot];
- g_smushReaders[opSlot] = NULL;
- }
- } else
- printf("Ran out of reader slots\n");
- }
- SignalSema(g_openSema);
- return (_id >= 0);
-}
-
-uint32 Ps2SmushFile::read(void *dest, uint32 len) {
- int res = g_smushReaders[_id]->read(dest, _filePos, len);
- _filePos += res;
- return res;
-}
-
-uint32 Ps2SmushFile::write(const void *src, uint32 len) {
- printf("ERROR: Received write request on Smush reader\n");
- SleepThread();
- return 0;
-}
-
-uint32 Ps2SmushFile::tell(void) {
- return _filePos;
-}
-
-uint32 Ps2SmushFile::size(void) {
- return _fileSize;
-}
-
-int Ps2SmushFile::seek(int32 offset, int origin) {
- int32 res;
- switch (origin) {
- case SEEK_SET:
- res = offset;
- break;
- case SEEK_CUR:
- res = _filePos + offset;
- break;
- case SEEK_END:
- res = _fileSize + offset;
- break;
- default:
- return -1;
- }
- if ((res >= 0) && (res <= _fileSize)) {
- if (offset != 0)
- g_smushReaders[_id]->virtSeek(_filePos, res);
- _filePos = res;
- return 0;
- }
- return -1;
-}
-
-bool Ps2SmushFile::eof(void) {
- return _filePos == _fileSize;
-}
-