mirror of
https://github.com/XProger/OpenLara.git
synced 2025-09-09 20:50:53 +02:00
#15 async read/write for settings
This commit is contained in:
@@ -176,13 +176,6 @@ extern int osGetTime ();
|
||||
extern bool osJoyReady (int index);
|
||||
extern void osJoyVibrate (int index, float L, float R);
|
||||
|
||||
extern bool osCacheWrite (const char *name, const char *data, int size);
|
||||
extern Stream* osCacheRead (const char *name);
|
||||
|
||||
extern bool osSaveGame (const char *data, int size);
|
||||
extern Stream* osLoadGame ();
|
||||
|
||||
|
||||
struct Mutex {
|
||||
void *obj;
|
||||
|
||||
@@ -292,6 +285,7 @@ namespace Core {
|
||||
} support;
|
||||
|
||||
#define SETTINGS_VERSION 1
|
||||
#define SETTINGS_READING 0xFF
|
||||
|
||||
struct Settings {
|
||||
enum Quality { LOW, MEDIUM, HIGH };
|
||||
|
@@ -667,7 +667,7 @@ namespace Debug {
|
||||
|
||||
fwrite(&header, sizeof(header), 1, f);
|
||||
|
||||
Sound::VAG vag(new Stream(&level->soundData[level->soundOffsets[index]], dataSize));
|
||||
Sound::VAG vag(new Stream(NULL, &level->soundData[level->soundOffsets[index]], dataSize));
|
||||
Sound::Frame frames[4 * 28];
|
||||
while (int count = vag.decode(frames, 4 * 28))
|
||||
for (int i = 0; i < count; i++)
|
||||
|
@@ -3674,7 +3674,7 @@ namespace TR {
|
||||
case VER_TR2_PSX : size = soundSize[index]; break;
|
||||
default : ASSERT(false);
|
||||
}
|
||||
return new Stream(data, size);
|
||||
return new Stream(NULL, data, size);
|
||||
}
|
||||
|
||||
int getMeshByID(int id) const {
|
||||
|
60
src/game.h
60
src/game.h
@@ -12,6 +12,13 @@ ShaderCache *shaderCache;
|
||||
namespace Game {
|
||||
Level *level;
|
||||
Stream *nextLevel;
|
||||
|
||||
void startLevel(Stream *lvl) {
|
||||
delete level;
|
||||
level = new Level(*lvl);
|
||||
UI::game = level;
|
||||
delete lvl;
|
||||
}
|
||||
}
|
||||
|
||||
void loadAsync(Stream *stream, void *userData) {
|
||||
@@ -22,42 +29,38 @@ void loadAsync(Stream *stream, void *userData) {
|
||||
Game::nextLevel = stream;
|
||||
}
|
||||
|
||||
namespace Game {
|
||||
void startLevel(Stream *lvl) {
|
||||
delete level;
|
||||
level = new Level(*lvl);
|
||||
UI::game = level;
|
||||
delete lvl;
|
||||
}
|
||||
|
||||
void stopChannel(Sound::Sample *channel) {
|
||||
if (level) level->stopChannel(channel);
|
||||
}
|
||||
|
||||
void readSettings() {
|
||||
Stream *stream = osCacheRead("settings");
|
||||
if (!stream) return;
|
||||
void loadSettings(Stream *stream, void *userData) {
|
||||
if (stream) {
|
||||
uint8 version;
|
||||
stream->read(version);
|
||||
if (version == SETTINGS_VERSION && stream->size == sizeof(Core::Settings))
|
||||
stream->raw((char*)&Core::settings + 1, stream->size - 1); // read settings data right after version number
|
||||
delete stream;
|
||||
}
|
||||
|
||||
Core::settings.version = SETTINGS_VERSION;
|
||||
shaderCache = new ShaderCache();
|
||||
Game::startLevel((Stream*)userData);
|
||||
UI::init(Game::level);
|
||||
}
|
||||
|
||||
|
||||
namespace Game {
|
||||
|
||||
void stopChannel(Sound::Sample *channel) {
|
||||
if (level) level->stopChannel(channel);
|
||||
}
|
||||
|
||||
void init(Stream *lvl) {
|
||||
nextLevel = NULL;
|
||||
|
||||
Core::init();
|
||||
readSettings();
|
||||
|
||||
shaderCache = new ShaderCache();
|
||||
|
||||
UI::init(level);
|
||||
nextLevel = NULL;
|
||||
shaderCache = NULL;
|
||||
level = NULL;
|
||||
|
||||
Sound::callback = stopChannel;
|
||||
|
||||
level = NULL;
|
||||
startLevel(lvl);
|
||||
Core::init();
|
||||
Core::settings.version = SETTINGS_READING;
|
||||
Stream::cacheRead("settings", loadSettings, lvl);
|
||||
}
|
||||
|
||||
void init(const char *lvlName = NULL) {
|
||||
@@ -100,6 +103,10 @@ namespace Game {
|
||||
}
|
||||
|
||||
bool update() {
|
||||
// async load for settings
|
||||
if (Core::settings.version == SETTINGS_READING)
|
||||
return true;
|
||||
|
||||
PROFILE_MARKER("UPDATE");
|
||||
|
||||
if (!Core::update())
|
||||
@@ -155,6 +162,9 @@ namespace Game {
|
||||
}
|
||||
|
||||
void render() {
|
||||
if (Core::settings.version == SETTINGS_READING)
|
||||
return;
|
||||
|
||||
PROFILE_MARKER("RENDER");
|
||||
PROFILE_TIMING(Core::stats.tFrame);
|
||||
Core::beginFrame();
|
||||
|
@@ -130,7 +130,7 @@ struct Level : IGame {
|
||||
save->size = ptr - data;
|
||||
save->version = level.version & TR::VER_VERSION;
|
||||
|
||||
osSaveGame(data, int(ptr - data));
|
||||
//osSaveGame(new Stream("savegame", data, int(ptr - data)));
|
||||
delete[] data;
|
||||
|
||||
LOG("Ok\n");
|
||||
@@ -139,7 +139,7 @@ struct Level : IGame {
|
||||
virtual void loadGame(int slot) {
|
||||
LOG("Load Game... ");
|
||||
|
||||
Stream *stream = osLoadGame();
|
||||
Stream *stream = NULL;//osLoadGame();
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
@@ -237,7 +237,7 @@ struct Level : IGame {
|
||||
|
||||
Core::settings = settings;
|
||||
|
||||
osCacheWrite("settings", (char*)&settings, sizeof(settings));
|
||||
Stream::cacheWrite("settings", (char*)&settings, sizeof(settings));
|
||||
|
||||
if (rebuildShaders) {
|
||||
delete shaderCache;
|
||||
|
@@ -64,13 +64,83 @@ int osGetTime() {
|
||||
return (int)emscripten_get_now();
|
||||
}
|
||||
|
||||
bool osSave(const char *name, const void *data, int size) {
|
||||
// TODO cookie? idb?
|
||||
FILE *f = fopen(name, "wb");
|
||||
if (!f) return false;
|
||||
// cache & data
|
||||
const char *IDB = "db";
|
||||
|
||||
void onError(void *arg) {
|
||||
Stream *stream = (Stream*)arg;
|
||||
LOG("! IDB error for %s\n", stream->name);
|
||||
if (stream->callback)
|
||||
stream->callback(NULL, stream->userData);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
void onLoad(void *arg, void *data, int size) {
|
||||
Stream *stream = (Stream*)arg;
|
||||
|
||||
FILE *f = fopen(stream->name, "wb");
|
||||
fwrite(data, size, 1, f);
|
||||
fclose(f);
|
||||
return true;
|
||||
|
||||
stream->callback(new Stream(stream->name), stream->userData);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
void onLoadAndStore(void *arg, void *data, int size) {
|
||||
emscripten_idb_async_store(IDB, ((Stream*)arg)->name, data, size, NULL, NULL, onError);
|
||||
onLoad(arg, data, size);
|
||||
}
|
||||
|
||||
void onExists(void *arg, int exists) {
|
||||
if (exists)
|
||||
emscripten_idb_async_load(IDB, ((Stream*)arg)->name, arg, onLoad, onError);
|
||||
else
|
||||
emscripten_async_wget_data(((Stream*)arg)->name, arg, onLoadAndStore, onError);
|
||||
}
|
||||
|
||||
void osDownload(Stream *stream) {
|
||||
emscripten_idb_async_exists(IDB, stream->name, stream, onExists, onError);
|
||||
}
|
||||
|
||||
void onCacheStore(void *arg) {
|
||||
Stream *stream = (Stream*)arg;
|
||||
LOG("cache stored: %s\n", stream->name);
|
||||
if (stream->callback)
|
||||
stream->callback(new Stream(stream->name, NULL, 0), stream->userData);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
void onCacheLoad(void *arg, void *data, int size) {
|
||||
Stream *stream = (Stream*)arg;
|
||||
LOG("cache loaded: %s\n", stream->name);
|
||||
if (stream->callback)
|
||||
stream->callback(new Stream(stream->name, data, size), stream->userData);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
void onCacheError(void *arg) {
|
||||
Stream *stream = (Stream*)arg;
|
||||
LOG("! cache error: %s\n", stream->name);
|
||||
if (stream->callback)
|
||||
stream->callback(NULL, stream->userData);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
void osCacheWrite(Stream *stream) {
|
||||
emscripten_idb_async_store(IDB, stream->name, stream->data, stream->size, stream, onCacheStore, onCacheError);
|
||||
}
|
||||
|
||||
void osCacheRead(Stream *stream) {
|
||||
emscripten_idb_async_load(IDB, stream->name, stream, onCacheLoad, onCacheError);
|
||||
}
|
||||
|
||||
// memory card
|
||||
void osSaveGame(Stream *stream) {
|
||||
return osCacheWrite(stream);
|
||||
}
|
||||
|
||||
void osLoadGame(Stream *stream) {
|
||||
return osCacheRead(stream);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
@@ -79,7 +149,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
void EMSCRIPTEN_KEEPALIVE game_level_load(char *data, int size) {
|
||||
Game::startLevel(new Stream(data, size));
|
||||
Game::startLevel(new Stream(NULL, data, size));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,42 +349,6 @@ EM_BOOL mouseCallback(int eventType, const EmscriptenMouseEvent *e, void *userDa
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *IDB = "db";
|
||||
|
||||
void onError(void *arg) {
|
||||
Stream *stream = (Stream*)arg;
|
||||
LOG("! IDB error for %s\n", stream->name);
|
||||
stream->callback(NULL, stream->userData);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
void onLoad(void *arg, void *data, int size) {
|
||||
Stream *stream = (Stream*)arg;
|
||||
|
||||
FILE *f = fopen(stream->name, "wb");
|
||||
fwrite(data, size, 1, f);
|
||||
fclose(f);
|
||||
|
||||
stream->callback(new Stream(stream->name), stream->userData);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
void onLoadAndStore(void *arg, void *data, int size) {
|
||||
emscripten_idb_async_store(IDB, ((Stream*)arg)->name, data, size, NULL, NULL, onError);
|
||||
onLoad(arg, data, size);
|
||||
}
|
||||
|
||||
void onExists(void *arg, int exists) {
|
||||
if (exists)
|
||||
emscripten_idb_async_load(IDB, ((Stream*)arg)->name, arg, onLoad, onError);
|
||||
else
|
||||
emscripten_async_wget_data(((Stream*)arg)->name, arg, onLoadAndStore, onError);
|
||||
}
|
||||
|
||||
void osDownload(Stream *stream) {
|
||||
emscripten_idb_async_exists(IDB, stream->name, stream, onExists, onError);
|
||||
}
|
||||
|
||||
char Stream::cacheDir[255];
|
||||
char Stream::contentDir[255];
|
||||
|
||||
|
@@ -112,32 +112,50 @@ int osGetTime() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool osCacheWrite(const char *name, const char *data, int size) {
|
||||
void osCacheWrite(Stream *stream) {
|
||||
char path[255];
|
||||
strcpy(path, Stream::cacheDir);
|
||||
strcat(path, name);
|
||||
strcat(path, stream->name);
|
||||
FILE *f = fopen(path, "wb");
|
||||
if (!f) return false;
|
||||
fwrite(data, size, 1, f);
|
||||
fclose(f);
|
||||
return true;
|
||||
if (f) {
|
||||
fwrite(stream->data, 1, stream->size, f);
|
||||
fclose(f);
|
||||
if (stream->callback)
|
||||
stream->callback(new Stream(stream->name, NULL, 0), stream->userData);
|
||||
} else
|
||||
if (stream->callback)
|
||||
stream->callback(NULL, stream->userData);
|
||||
|
||||
delete stream;
|
||||
}
|
||||
|
||||
Stream* osCacheRead(const char *name) {
|
||||
void osCacheRead(Stream *stream) {
|
||||
char path[255];
|
||||
strcpy(path, Stream::cacheDir);
|
||||
strcat(path, name);
|
||||
if (!Stream::exists(path))
|
||||
return NULL;
|
||||
return new Stream(path);
|
||||
strcat(path, stream->name);
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
int size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
char *data = new char[size];
|
||||
fread(data, 1, size, f);
|
||||
fclose(f);
|
||||
if (stream->callback)
|
||||
stream->callback(new Stream(stream->name, data, size), stream->userData);
|
||||
delete[] data;
|
||||
} else
|
||||
if (stream->callback)
|
||||
stream->callback(NULL, stream->userData);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
bool osSaveGame(const char *data, int size) {
|
||||
return osCacheWrite("savegame", data, size);
|
||||
void osSaveGame(Stream *stream) {
|
||||
return osCacheWrite(stream);
|
||||
}
|
||||
|
||||
Stream* osLoadGame() {
|
||||
return osCacheRead("savegame");
|
||||
void osLoadGame(Stream *stream) {
|
||||
return osCacheRead(stream);
|
||||
}
|
||||
|
||||
// common input functions
|
||||
|
14
src/shader.h
14
src/shader.h
@@ -94,7 +94,7 @@ struct Shader {
|
||||
glGetProgramBinary(ID, size, NULL, &format, &data[8]);
|
||||
*(int*)(&data[0]) = format;
|
||||
*(int*)(&data[4]) = size;
|
||||
osCacheWrite(fileName, data, 8 + size);
|
||||
Stream::cacheWrite(fileName, data, 8 + size);
|
||||
delete[] data;
|
||||
#endif
|
||||
}
|
||||
@@ -144,8 +144,16 @@ struct Shader {
|
||||
return checkLink();
|
||||
}
|
||||
|
||||
bool linkBinary(const char *fileName) {
|
||||
Stream *stream = osCacheRead(fileName);
|
||||
bool linkBinary(const char *name) {
|
||||
// non-async code!
|
||||
char path[255];
|
||||
strcpy(path, Stream::cacheDir);
|
||||
strcat(path, name);
|
||||
|
||||
if (!Stream::exists(path))
|
||||
return false;
|
||||
|
||||
Stream *stream = new Stream(path);
|
||||
if (!stream)
|
||||
return false;
|
||||
|
||||
|
48
src/utils.h
48
src/utils.h
@@ -1131,6 +1131,17 @@ struct Box {
|
||||
}
|
||||
};
|
||||
|
||||
struct Stream;
|
||||
|
||||
extern void osCacheWrite (Stream *stream);
|
||||
extern void osCacheRead (Stream *stream);
|
||||
|
||||
extern void osSaveGame (Stream *stream);
|
||||
extern void osLoadGame (Stream *stream);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
extern void osDownload (Stream *stream);
|
||||
#endif
|
||||
|
||||
struct Stream {
|
||||
static char cacheDir[255];
|
||||
@@ -1147,7 +1158,12 @@ struct Stream {
|
||||
|
||||
enum Endian { eLittle, eBig } endian;
|
||||
|
||||
Stream(const void *data, int size) : callback(NULL), userData(NULL), f(NULL), data((char*)data), name(NULL), size(size), pos(0), endian(eLittle) {}
|
||||
Stream(const char *name, const void *data, int size) : callback(NULL), userData(NULL), f(NULL), data((char*)data), name(NULL), size(size), pos(0), endian(eLittle) {
|
||||
if (name) {
|
||||
this->name = new char[strlen(name) + 1];
|
||||
strcpy(this->name, name);
|
||||
}
|
||||
}
|
||||
|
||||
Stream(const char *name, Callback *callback = NULL, void *userData = NULL) : callback(callback), userData(userData), data(NULL), name(NULL), size(-1), pos(0), endian(eLittle) {
|
||||
if (contentDir[0] && (!cacheDir[0] || !strstr(name, cacheDir))) {
|
||||
@@ -1161,18 +1177,16 @@ struct Stream {
|
||||
|
||||
if (!f) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
this->name = new char[64];
|
||||
strcpy(this->name, name);
|
||||
|
||||
extern void osDownload(Stream *stream);
|
||||
if (name) {
|
||||
this->name = new char[strlen(name) + 1];
|
||||
strcpy(this->name, name);
|
||||
}
|
||||
osDownload(this);
|
||||
return;
|
||||
#else
|
||||
LOG("error loading file \"%s\"\n", name);
|
||||
if (callback) {
|
||||
callback(NULL, userData);
|
||||
delete this;
|
||||
return;
|
||||
} else {
|
||||
ASSERT(false);
|
||||
}
|
||||
@@ -1182,8 +1196,10 @@ struct Stream {
|
||||
size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
this->name = new char[strlen(name) + 1];
|
||||
strcpy(this->name, name);
|
||||
if (name) {
|
||||
this->name = new char[strlen(name) + 1];
|
||||
strcpy(this->name, name);
|
||||
}
|
||||
|
||||
if (callback)
|
||||
callback(this, userData);
|
||||
@@ -1195,6 +1211,20 @@ struct Stream {
|
||||
if (f) fclose(f);
|
||||
}
|
||||
|
||||
static void cacheRead(const char *name, Callback *callback = NULL, void *userData = NULL) {
|
||||
Stream *stream = new Stream(name, NULL, 0);
|
||||
stream->callback = callback;
|
||||
stream->userData = userData;
|
||||
osCacheRead(stream);
|
||||
}
|
||||
|
||||
static void cacheWrite(const char *name, const char *data, int size, Callback *callback = NULL, void *userData = NULL) {
|
||||
Stream *stream = new Stream(name, data, size);
|
||||
stream->callback = callback;
|
||||
stream->userData = userData;
|
||||
osCacheWrite(stream);
|
||||
}
|
||||
|
||||
static bool exists(const char *name) {
|
||||
FILE *f = fopen(name, "rb");
|
||||
if (!f)
|
||||
|
Reference in New Issue
Block a user