1
0
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:
XProger
2018-02-26 01:50:23 +03:00
parent e6f2deb7a4
commit 60141f8681
9 changed files with 200 additions and 106 deletions

View File

@@ -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 };

View File

@@ -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++)

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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;

View File

@@ -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];

View File

@@ -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

View File

@@ -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;

View File

@@ -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)