scummvm/engines/saga2/rserver.cpp

221 lines
6.1 KiB
C++
Raw Normal View History

2021-05-17 18:47:39 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* aint32 with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
* Based on the original sources
* Faery Tale II -- The Halls of the Dead
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
*/
#define FORBIDDEN_SYMBOL_ALLOW_ALL // FIXME: Remove
2021-06-09 22:22:54 +00:00
#include "common/debug.h"
2021-05-17 18:47:39 +00:00
#include "saga2/std.h"
#include "saga2/dlist.h"
2021-06-01 20:24:39 +00:00
#include "saga2/ioerrors.h"
2021-06-01 22:16:29 +00:00
#include "saga2/hresmgr.h"
2021-06-01 20:24:39 +00:00
2021-05-17 18:47:39 +00:00
namespace Saga2 {
class ResourceRequest;
class ResourceServer : public DList {
HR_FILE *fHandle; // resource file handle
int32 lastSeekPos; // where drive head is
int32 actual; // bytes read so far
ResourceRequest *currentRequest;
public:
ResourceServer(HR_FILE *); // constructor
void service(void);
};
class ResourceRequest : public DNode {
public:
RHANDLE handle; // where to put the data
uint32 offset, // offset in file of data
length; // desired length of data
2021-06-13 14:56:52 +00:00
bool done; // true if load is finished
2021-05-17 18:47:39 +00:00
void *userData; // for app use
// Function to notify when request is done.
void (*notify)(ResourceRequest &);
ResourceRequest(DList &dl); // constructor
};
/* ===================================================================== *
Globals
* ===================================================================== */
ResourceServer *resourceServer; // resource server ptr
DList resourceRequestPool; // pool of messages
const int numResRequests = 32; // up to 32 messages allowed
/* ===================================================================== *
Member Functions
* ===================================================================== */
ResourceServer::ResourceServer(HR_FILE *fh) {
currentRequest = NULL;
fHandle = fh; // file handle
lastSeekPos = 0; // drive position
}
const int loadQuanta = 0x4000; // 16K
void ResourceServer::service(void) {
if (currentRequest == NULL) {
currentRequest = (ResourceRequest *)remHead();
if (currentRequest == NULL) return;
// seek to position in file
HR_SEEK(fHandle, currentRequest->offset, SEEK_SET);
// calculate final seek position
lastSeekPos = currentRequest->offset + currentRequest->length;
actual = 0; // bytes read so far
}
if (currentRequest->length > 0 // while there's data to read
&& *currentRequest->handle != NULL) { // and block not flushed
int32 loadSize = MIN<uint>(currentRequest->length, loadQuanta);
uint8 *buffer = (UBytePtr) * currentRequest->handle + actual;
// Read 16K worth of data, or however much is left.
if (HR_READ(buffer, loadSize, 1, fHandle) != 1)
error("Error reading resource");
buffer += loadSize;
currentRequest->length -= loadSize;
currentRequest->offset += loadSize;
actual += loadSize;
#if DEBUG
WriteStatusF(1, "Loaded: %8.8d", actual);
#endif
} else {
2021-06-13 14:56:52 +00:00
currentRequest->done = true;
2021-05-17 18:47:39 +00:00
resourceRequestPool.addTail(*currentRequest);
currentRequest = NULL;
// Mark handle as ready for use.
RHandleDoneLoading(currentRequest->handle); // mark handle as loaded
// Notify callback that resource is done loading
if (currentRequest->notify)
currentRequest->notify(*currentRequest);
currentRequest->notify = NULL;
}
}
ResourceRequest::ResourceRequest(DList &dl) {
notify = NULL;
dl.addTail(*this);
}
void RequestResource(
RHANDLE handle,
int32 offset,
int32 length,
// Function to notify when request is done.
void *notify,
void *userData) {
ResourceRequest *rr;
// Try to get a resource request. If none are available,
// then wait until one is avauilable.
for (;;) {
rr = (ResourceRequest *)
resourceRequestPool.remHead();
if (rr != NULL) break;
// Service resources until request is free
resourceServer->service();
}
RHandleStartLoading(handle);
2021-06-13 14:56:52 +00:00
rr->done = false;
2021-05-17 18:47:39 +00:00
rr->handle = handle;
rr->offset = offset;
rr->length = length;
rr->notify = (void (*)(ResourceRequest &))notify;
rr->userData = userData;
resourceServer->addTail(*rr);
}
void initServers(void) {
warning("STUB: initServers()");
#if 0
2021-05-17 18:47:39 +00:00
int16 i;
resourceServer = NEW_PRES ResourceServer(resFile->resFileHandle());
if (resourceServer == NULL) {
error("Unable to start up resource server!\n");
}
for (i = 0; i < numResRequests; i++) {
NEW_PRES ResourceRequest(resourceRequestPool);
}
#endif
2021-05-17 18:47:39 +00:00
}
void cleanupServers(void) {
ResourceRequest *rr;
if (resourceServer)
delete resourceServer;
resourceServer = NULL;
while ((rr = (ResourceRequest *)resourceRequestPool.remHead()))
delete rr;
}
void loadAsyncResources(void) {
debug(6, "STUB: loadAsyncResources()");
2021-06-09 21:12:10 +00:00
#if 0
2021-05-17 18:47:39 +00:00
resourceServer->service();
2021-06-09 21:12:10 +00:00
#endif
2021-05-17 18:47:39 +00:00
}
void syncResources(void) {
while (resourceServer->count() > 0)
resourceServer->service();
}
void *lockResource(RHANDLE h) {
if (h && *h) {
while (RHandleLoading(h)) resourceServer->service();
return RLockHandle(h);
}
return NULL;
}
void unlockResource(RHANDLE handle) {
RUnlockHandle(handle);
}
} // end if namespace Saga2