diff --git a/LICENSE b/LICENSE index 5c2633d..bda2021 100644 --- a/LICENSE +++ b/LICENSE @@ -53,11 +53,6 @@ SDL2_image https://www.libsdl.org/ BSD 3-Clause -SHA256 ------- -https://github.com/ilvn/SHA256 -MIT - SQLite 3.4.2 ------------ https://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/distributions/1.2/repos/pkg-html/sqlite.html @@ -99,6 +94,24 @@ https://github.com/nothings/stb Public Domain +Pre-Cache Builder +================= + +MemWatch +-------- +http://www.linkdata.se/sourcecode/memwatch/ +GPL2 + +SHA256 +------ +https://github.com/ilvn/SHA256 +MIT + +stb_image.h +----------- +https://github.com/nothings/stb +Public Domain + Server ====== diff --git a/client/in/gui/wait.png b/client/in/gui/wait.png new file mode 100644 index 0000000..71dcca2 --- /dev/null +++ b/client/in/gui/wait.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b32a4de93aee2715bf176baa444fb9d3285b7f8a24f96668dbb5136db7e8e1d +size 5230 diff --git a/client/src/file.c b/client/src/file.c index c993886..101dfb8 100644 --- a/client/src/file.c +++ b/client/src/file.c @@ -57,6 +57,7 @@ static TimerT *_timTimer = NULL; static void btnMsgBoxOkay(MsgBoxButtonT button); static void fileCheckNext(void); +static void fileCurrentUpdate(uint8_t dontCallback); static void fileShowDialog(void); static void fileShowError(char *message); static void packetHandler(PacketDecodeDataT *packet); @@ -102,12 +103,47 @@ static void fileCheckNext(void) { uint8_t *packetData = NULL; uint16_t length = 0; uint32_t temp = 0; - uint8_t doRecheck = 0; char *shaPointer = NULL; static char *badSHA = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; BEGIN + fileCurrentUpdate(0); + if (_file) { + // Check next file. + temp = FILE_REQUEST_CHECK; + shaPointer = cacheSha256Get(_file); + if (!shaPointer) shaPointer = badSHA; + packetData = packetContentPack(&length, "iss", temp, shaPointer, _file); + encoded.control = PACKET_CONTROL_DAT; + encoded.packetType = PACKET_TYPE_FILE_REQUEST; + encoded.channel = _channel; + encoded.encrypt = 0; + packetEncode(__packetThreadData, &encoded, packetData, length); + packetSend(__packetThreadData, &encoded); + DEL(packetData); + } else { + // Finished with transfers. + if (_dialogVisible) guiDelete(D(_winFile)); + netChannelRelease(_channel); + _channel = 0; + } + + END +} + + +static void fileCurrentUpdate(uint8_t dontCallback) { + uint8_t doRecheck = 0; + + // This function is ugly and happened because a bunch of + // code got moved around and this was needed in multiple + // places. It updates several global variables. In short, + // if '_file' is not null after calling this, there is + // more to do. + + BEGIN + do { // This is ugly since both lists kind of depend on each other. doRecheck = 0; @@ -118,12 +154,8 @@ static void fileCheckNext(void) { if (arrlen(_fileList) == 0) { logWrite("End of file queue.\n"); arrfree(_fileList); - if (_dialogVisible) guiDelete(D(_winFile)); - netChannelRelease(_channel); - _channel = 0; return; } - // Get next queue entry. _currentLength = 0; _current = _fileList[0]; @@ -138,7 +170,7 @@ static void fileCheckNext(void) { logWrite("End of file list.\n"); arrfree(_current->files); // Call with NULL to signify end of transfers. - _current->callback(NULL); + if (!dontCallback) _current->callback(NULL); DEL(_current); // See if there's more. doRecheck = 1; @@ -150,19 +182,6 @@ static void fileCheckNext(void) { } } while (doRecheck); - // Check next file. - temp = FILE_REQUEST_CHECK; - shaPointer = cacheSha256Get(_file); - if (!shaPointer) shaPointer = badSHA; - packetData = packetContentPack(&length, "iss", temp, shaPointer, _file); - encoded.control = PACKET_CONTROL_DAT; - encoded.packetType = PACKET_TYPE_FILE_REQUEST; - encoded.channel = _channel; - encoded.encrypt = 0; - packetEncode(__packetThreadData, &encoded, packetData, length); - packetSend(__packetThreadData, &encoded); - DEL(packetData); - END } @@ -194,6 +213,9 @@ static void fileShowDialog(void) { static void fileShowError(char *message) { // ***TODO*** This should close all open windows. + // Reset a possibly busy mouse pointer. + guiMouseBusyClear(); + // Show error. This is fatal. if (_dialogVisible) guiDelete(D(_winFile)); netChannelRelease(_channel); @@ -293,20 +315,12 @@ static void timTimerTimeout(WidgetT *widget) { timerStop(_timTimer); // If we at least have some version of the file, try to continue. - while (arrlen(_fileList) > 0) { - while (arrlen(_fileList[0]->files) > 0) { - if (cacheFilenameGet(_fileList[0]->files[0])) { - arrdel(_fileList[0]->files, 0); - } else { - missing = 1; - } - } - // If we're good so far, call the callback. - if (!missing) _fileList[0]->callback(NULL); - arrfree(_fileList[0]->files); - arrdel(_fileList, 0); + while (_file) { + // Passing 'missing' prevents file completion callbacks from + // occurring when there are missing files. + fileCurrentUpdate(missing); + if (_file && !cacheFilenameGet(_file)) missing = 1; } - arrfree(_fileList); if (missing) fileShowError("Unable to download needed files."); diff --git a/client/src/gui/gui.c b/client/src/gui/gui.c index c0609de..1c27f41 100644 --- a/client/src/gui/gui.c +++ b/client/src/gui/gui.c @@ -80,6 +80,7 @@ static uint32_t _guiTimerHalfSecondOn = 0; static uint32_t _guiTimerSecondOn = 0; static PendingEventsT **_guiPendingEvents = NULL; static void **_guiPendingFrees = NULL; +static uint8_t _guiMouseBusyStack = 0; static void guiDeleteList(void); @@ -384,6 +385,26 @@ void guiKeyboardProcess(uint8_t ascii, uint8_t extended, uint8_t scancode, uint8 } +void guiMouseBusyClear() { + _guiMouseBusyStack = 0; +} + + +uint8_t guiMouseBusyGet() { + return _guiMouseBusyStack != 0; +} + + +void guiMouseBusyPop() { + if (_guiMouseBusyStack > 0) _guiMouseBusyStack--; +} + + +void guiMouseBusyPush() { + if (_guiMouseBusyStack < 255) _guiMouseBusyStack++; +} + + void guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *x, uint16_t *y) { RectT r; guiWidgetPositionOnScreenGet(widget, &r); diff --git a/client/src/gui/gui.h b/client/src/gui/gui.h index cc6e0f5..61ac570 100644 --- a/client/src/gui/gui.h +++ b/client/src/gui/gui.h @@ -202,6 +202,10 @@ uint8_t guiHasStopped(void); void guiKeyboardProcess(uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt); void guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *x, uint16_t *y); void guiMouseProcess(MouseT *mouse); +void guiMouseBusyClear(); +uint8_t guiMouseBusyGet(); +void guiMouseBusyPop(); +void guiMouseBusyPush(); void guiPaint(WidgetT *widget); void guiParentAndChildrenDirtySet(WidgetT *widget); void guiPendingEventAdd(WidgetT *widget, void *callback); diff --git a/client/src/gui/image.c b/client/src/gui/image.c index c562ca5..c81babc 100644 --- a/client/src/gui/image.c +++ b/client/src/gui/image.c @@ -97,7 +97,7 @@ void imageCacheIfNeeded(char *cacheFilename, char *sha256) { temp = (char *)malloc(strlen(cacheFilename) + 5); if (!temp) return; sprintf(temp, "%s.raw", cacheFilename); - rawSha = strdup(cacheSha256Get(temp)); + rawSha = cacheSha256Get(temp); if (!rawSha || strcmp(rawSha, sha256) != 0) { // The decompressed file either does not exist or the SHA does not match the file we're checking. logWrite("Unpacking %s - %s\n", cacheFilenameGet(cacheFilename), cacheFilename); diff --git a/client/src/hangup.c b/client/src/hangup.c index 6e3b05e..b3db036 100644 --- a/client/src/hangup.c +++ b/client/src/hangup.c @@ -92,6 +92,7 @@ static void timHangupProgress(WidgetT *widget) { // Snooze a bit for the packet to send. _state = S_WAITING; timerQuarterSecondsSet(t, 3 * 4); + guiMouseBusyPush(); break; case S_WAITING: @@ -102,6 +103,7 @@ static void timHangupProgress(WidgetT *widget) { // On to the next dialog. guiDelete(D(_winHangup)); _done(NULL); + guiMouseBusyPop(); break; } } diff --git a/client/src/login.c b/client/src/login.c index 15a945c..158a115 100644 --- a/client/src/login.c +++ b/client/src/login.c @@ -122,6 +122,7 @@ static void loginFilesReady(char *updatedFile) { runtimeDataUpdate(); } else { // End of cache update. Display UI. + guiMouseBusyPop(); runtimeDataLoad(); // ***TODO*** We used to have a FORGOT PASSWORD link here, too. @@ -191,6 +192,7 @@ void loginShow() { BEGIN + guiMouseBusyPush(); fileCacheCheck(loginFilesReady, fileList); END diff --git a/client/src/main.c b/client/src/main.c index 2dd594c..28cc092 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -60,9 +60,10 @@ PacketThreadDataT *__packetThreadData = NULL; // Exported in os.h -static MouseT *_mouse = NULL; -static ImageT *_pointer = NULL; -static ColorT _alpha = 0; +static MouseT *_mouse = NULL; +static ImageT *_pointer = NULL; +static ImageT *_hourglass = NULL; +static ColorT _alpha = 0; #ifndef __linux__ char *_logName = NULL; @@ -102,7 +103,11 @@ static void eventLoop(void) { } guiMouseProcess(_mouse); guiComposite(); - imageRenderWithAlpha(_pointer, _mouse->x, _mouse->y, _alpha); + if (guiMouseBusyGet()) { + imageRenderWithAlpha(_hourglass, _mouse->x, _mouse->y, _alpha); + } else { + imageRenderWithAlpha(_pointer, _mouse->x, _mouse->y, _alpha); + } vbeVBlankWait(); vbePresent(); } while (!guiHasStopped()); @@ -123,6 +128,7 @@ static void shutdown(void) { FILE *in = NULL; #endif + imageUnload(&_hourglass); imageUnload(&_pointer); netShutdown(); @@ -196,8 +202,9 @@ static uint8_t startup(int argc, char *argv[]) { guiStartup(); netStartup(); - _pointer = imageLoadCache("gui:mouse.png"); - _alpha = imagePixelGet(_pointer, 5, 0); + _hourglass = imageLoadCache("gui:wait.png"); + _pointer = imageLoadCache("gui:mouse.png"); + _alpha = imagePixelGet(_pointer, 5, 0); return 0; } diff --git a/client/src/menu.c b/client/src/menu.c index d763d49..ee2a77c 100644 --- a/client/src/menu.c +++ b/client/src/menu.c @@ -106,6 +106,7 @@ static void menuFilesReady(char *updatedFile) { } } else { // Show UI + guiMouseBusyPop(); x = vbeDisplayWidthGet() - 49; y = vbeDisplayHeightGet() - 49; @@ -152,11 +153,155 @@ void menuShow(void) { "menu:48logoff.png", "menu:48profile.png", "generated:games.dat", + + "games:d:descent:banner.png", + "games:d:descent:box2.png", + "games:d:descent:screen1.png", + "games:d:descent:screen2.png", + "games:d:descent:screen3.png", + "games:d:descent:screen4.png", + "games:d:descent:screen5.png", + "games:d:descent:screen6.png", + "games:d:descent:box1-thumb.png", + "games:d:descent:box1.png", + "games:d:descent:box2-thumb.png", + "games:d:descent:screen1-thumb.png", + "games:d:descent:screen2-thumb.png", + "games:d:descent:screen3-thumb.png", + "games:d:descent:screen4-thumb.png", + "games:d:descent:screen5-thumb.png", + "games:d:descent:screen6-thumb.png", + "games:d:dm:screen1.png", + "games:d:dm:screen2.png", + "games:d:dm:screen3.png", + "games:d:dm:screen4.png", + "games:d:dm:screen5.png", + "games:d:dm:screen6.png", + "games:d:dm:screen6-thumb.png", + "games:d:dm:screen5-thumb.png", + "games:d:dm:screen4-thumb.png", + "games:d:dm:screen3-thumb.png", + "games:d:dm:screen2-thumb.png", + "games:d:dm:screen1-thumb.png", + "games:d:dm:banner.png", + "games:t:tal:screen6.png", + "games:t:tal:screen5.png", + "games:t:tal:screen4.png", + "games:t:tal:screen3.png", + "games:t:tal:screen2.png", + "games:t:tal:screen1.png", + "games:t:tal:screen6-thumb.png", + "games:t:tal:screen5-thumb.png", + "games:t:tal:screen4-thumb.png", + "games:t:tal:screen3-thumb.png", + "games:t:tal:screen2-thumb.png", + "games:t:tal:screen1-thumb.png", + "games:t:tal:banner.png", + "games:t:tw2002:screen6.png", + "games:t:tw2002:screen5.png", + "games:t:tw2002:screen4.png", + "games:t:tw2002:screen3.png", + "games:t:tw2002:screen2.png", + "games:t:tw2002:screen1.png", + "games:t:tw2002:screen1-thumb.png", + "games:t:tw2002:screen2-thumb.png", + "games:t:tw2002:screen3-thumb.png", + "games:t:tw2002:screen4-thumb.png", + "games:t:tw2002:screen5-thumb.png", + "games:t:tw2002:screen6-thumb.png", + "games:t:tw2002:banner.png", + "games:b:bre:screen1.png", + "games:b:bre:screen2.png", + "games:b:bre:screen3.png", + "games:b:bre:screen4.png", + "games:b:bre:screen5.png", + "games:b:bre:screen1-thumb.png", + "games:b:bre:screen2-thumb.png", + "games:b:bre:screen3-thumb.png", + "games:b:bre:screen4-thumb.png", + "games:b:bre:screen5-thumb.png", + "games:b:bre:banner.png", + "games:f:fe:screen6.png", + "games:f:fe:screen5.png", + "games:f:fe:screen4.png", + "games:f:fe:screen3.png", + "games:f:fe:screen2.png", + "games:f:fe:screen1.png", + "games:f:fe:screen1-thumb.png", + "games:f:fe:screen2-thumb.png", + "games:f:fe:screen3-thumb.png", + "games:f:fe:screen4-thumb.png", + "games:f:fe:screen5-thumb.png", + "games:f:fe:screen6-thumb.png", + "games:f:fe:banner.png", + "games:f:fh:screen1.png", + "games:f:fh:screen2.png", + "games:f:fh:screen3.png", + "games:f:fh:screen4.png", + "games:f:fh:screen5.png", + "games:f:fh:screen6.png", + "games:f:fh:screen6-thumb.png", + "games:f:fh:screen5-thumb.png", + "games:f:fh:screen4-thumb.png", + "games:f:fh:screen3-thumb.png", + "games:f:fh:screen2-thumb.png", + "games:f:fh:screen1-thumb.png", + "games:f:fh:banner.png", + "games:g:gbkg:screen3.png", + "games:g:gbkg:screen2.png", + "games:g:gbkg:screen1.png", + "games:g:gbkg:screen1-thumb.png", + "games:g:gbkg:screen2-thumb.png", + "games:g:gbkg:screen3-thumb.png", + "games:g:gbkg:banner.png", + "games:g:gwar:screen1.png", + "games:g:gwar:screen2.png", + "games:g:gwar:screen3.png", + "games:g:gwar:screen4.png", + "games:g:gwar:screen5.png", + "games:g:gwar:screen6.png", + "games:g:gwar:screen6-thumb.png", + "games:g:gwar:screen5-thumb.png", + "games:g:gwar:screen4-thumb.png", + "games:g:gwar:screen3-thumb.png", + "games:g:gwar:screen2-thumb.png", + "games:g:gwar:screen1-thumb.png", + "games:g:gwar:banner.png", + "games:h:hackn:screen3.png", + "games:h:hackn:screen2.png", + "games:h:hackn:screen1.png", + "games:h:hackn:screen1-thumb.png", + "games:h:hackn:screen2-thumb.png", + "games:h:hackn:screen3-thumb.png", + "games:h:hackn:banner.png", + "games:o:odd:screen4.png", + "games:o:odd:screen3.png", + "games:o:odd:screen2.png", + "games:o:odd:screen1.png", + "games:o:odd:screen4-thumb.png", + "games:o:odd:screen3-thumb.png", + "games:o:odd:screen2-thumb.png", + "games:o:odd:screen1-thumb.png", + "games:o:odd:banner.png", + "games:s:sg:screen3.png", + "games:s:sg:screen2.png", + "games:s:sg:screen1.png", + "games:s:sg:screen3-thumb.png", + "games:s:sg:screen2-thumb.png", + "games:s:sg:screen1-thumb.png", + "games:s:sg:banner.png", + "games:s:sre:screen1.png", + "games:s:sre:screen1-thumb.png", + "games:s:sre:banner.png", + "browser:no-box.png", + "browser:no-screen.png", + NULL }; BEGIN + guiMouseBusyPush(); fileCacheCheck(menuFilesReady, fileList); END @@ -239,6 +384,7 @@ static void updateGameDatabase(void) { // Mark everything untouched. dbExecute("UPDATE games SET touced=0", NULL); + /* // Process latest downloaded game list. f = cacheFOpen("generated:games.dat", "rb"); if (f) { @@ -253,4 +399,5 @@ static void updateGameDatabase(void) { // Delete anything untouched. dbExecute("DELETE FROM games WHERE touced=0", NULL); } + */ } diff --git a/client/src/settings.c b/client/src/settings.c index 739bea5..23ca7f2 100644 --- a/client/src/settings.c +++ b/client/src/settings.c @@ -218,6 +218,7 @@ static void timSettingsProgress(WidgetT *widget) { com = 0; selected = 1; _state = S_OPEN_COM; + guiMouseBusyPush(); break; case S_OPEN_COM: @@ -276,6 +277,7 @@ static void timSettingsProgress(WidgetT *widget) { case S_SCAN_COMPLETE: timerStop(_timProgress); settingsComShow(); + guiMouseBusyPop(); break; } } diff --git a/client/src/system/cache.c b/client/src/system/cache.c index 0d63f51..839bc99 100644 --- a/client/src/system/cache.c +++ b/client/src/system/cache.c @@ -172,73 +172,6 @@ FILE *cacheFOpen(char *vpath, char *mode) { } -uint8_t cachePrePack(char *name, CachePreMakeListT *list) { - - FILE *in = NULL; - FILE *out = NULL; - uint16_t i = 0; - uint8_t result = SUCCESS; - uint32_t length = 0; - uint32_t total = 0; - uint32_t temp = 0; - int8_t buffer[8192] = { 0 }; - sha256_context ctx = { 0 }; - uint8_t hv[32] = { 0 }; - - // Prebuilt cache format: - // - Virtual Path (zero terminated) - // - x bytes hash - // - 4 bytes unsigned length of data - // - length bytes of data - // ... repeat for each file ... - // - 4 bytes length of entire cache (used for embedding cache data) - - out = fopen(name, "wb"); - if (out) { - while (list[i].filename != NULL) { - in = fopen(list[i].filename, "rb"); - if (in) { - // Get length of file. - fseek(in, 0, SEEK_END); - length = ftell(in); - fseek(in, 0, SEEK_SET); - // Generate SHA256. - sha256_init(&ctx); - do { - temp = fread(buffer, 1, sizeof(buffer), in); - if (temp) sha256_hash(&ctx, (uint8_t *)buffer, temp); - } while (temp > 0); - sha256_done(&ctx, hv); - fseek(in, 0, SEEK_SET); - // Write header. - temp = strlen(list[i].virtualPath) + 1; - fwrite(list[i].virtualPath, temp, 1, out); - fwrite(hv, sizeof(hv), 1, out); - fwrite(&length, sizeof(uint32_t), 1, out); - total += temp + sizeof(hv) + sizeof(uint32_t) + length; - // Copy data. - do { - temp = fread(buffer, 1, sizeof(buffer), in); - if (temp) fwrite(buffer, 1, temp, out); - } while (temp > 0); - fclose(in); - } else { - result = FAIL; - } - i++; - } - // Write length of entire block. - total += sizeof(uint32_t); - fwrite(&total, sizeof(uint32_t), 1, out); - fclose(out); - } else { - result = FAIL; - } - - return result; -} - - uint8_t cachePreUnpack(char *name) { FILE *in = NULL; FILE *out = NULL; diff --git a/client/src/system/cache.h b/client/src/system/cache.h index f6685bb..bfc160e 100644 --- a/client/src/system/cache.h +++ b/client/src/system/cache.h @@ -28,12 +28,6 @@ #define CACHE_VIRTUAL_PATH_MAX 512 // Should match setting in the server's client/file.h -typedef struct CachePreMakeListS { - char *filename; - char *virtualPath; -} CachePreMakeListT; - - uint8_t cacheDelete(char *virtualPath); uint8_t cacheEntryAdd(char *sha256, char *entryName, char *virtualPath); char *cacheEntryNameGet(char *virtualPath); @@ -41,7 +35,6 @@ uint8_t cacheExists(void); void cacheFClose(FILE *handle); char *cacheFilenameGet(char *virtualPath); FILE *cacheFOpen(char *vpath, char *mode); -uint8_t cachePrePack(char *name, CachePreMakeListT *list); uint8_t cachePreUnpack(char *name); char *cacheSha256Get(char *virtualPath); void cacheShutdown(void); diff --git a/client/src/welcome.c b/client/src/welcome.c index 321e2ac..fa7724a 100644 --- a/client/src/welcome.c +++ b/client/src/welcome.c @@ -256,6 +256,8 @@ static void timWelcomeProgress(WidgetT *widget) { switch (_state) { case S_START_CONNECT: + // Hourglass mouse. + guiMouseBusyPush(); // Ghost all buttons. widgetEnableSet(W(_btnConnect), 0); widgetEnableSet(W(_btnSettings), 0); @@ -271,6 +273,8 @@ static void timWelcomeProgress(WidgetT *widget) { r = comOpen(__configData.serialCom - 1, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS); if (r != SER_SUCCESS) { timerStop(t); + // Restore mouse. + guiMouseBusyPop(); msgBoxOne("COM Problem", MSGBOX_ICON_ERROR, "Unable to open COM port!\nPlease check settings.", "Okay", btnMsgBox); break; } @@ -296,6 +300,8 @@ static void timWelcomeProgress(WidgetT *widget) { if (strstr(buffer, "OK") == NULL) { comClose(__configData.serialCom - 1); timerStop(t); + // Restore mouse. + guiMouseBusyPop(); msgBoxOne("Modem Problem", MSGBOX_ICON_ERROR, "Modem does not support ENET!\nPlease check settings.", "Okay", btnMsgBox); break; } @@ -336,6 +342,8 @@ static void timWelcomeProgress(WidgetT *widget) { if (_timeoutCounter == 0) { comClose(__configData.serialCom - 1); timerStop(t); + // Restore mouse. + guiMouseBusyPop(); msgBoxOne("No Connection", MSGBOX_ICON_INFORMATION, "Unable to connect to server!\nPlease check settings or try later.", "Okay", btnMsgBox); } break; @@ -352,6 +360,8 @@ static void timWelcomeProgress(WidgetT *widget) { netPacketHandlerStop(); comClose(__configData.serialCom - 1); timerStop(t); + // Restore mouse. + guiMouseBusyPop(); msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to negotiate encryption settings!", "Okay", btnMsgBox); } break; @@ -360,6 +370,8 @@ static void timWelcomeProgress(WidgetT *widget) { netPacketHandlerStop(); comClose(__configData.serialCom - 1); timerStop(t); + // Restore mouse. + guiMouseBusyPop(); msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to fetch client settings!", "Okay", btnMsgBox); break; @@ -368,6 +380,8 @@ static void timWelcomeProgress(WidgetT *widget) { timerStop(t); netChannelSystemRelease(packetHandler); guiDelete(D(_winWelcome)); + // Restore mouse. + guiMouseBusyPop(); loginShow(); break; } diff --git a/precache/precache.pro b/precache/precache.pro index f4badad..ab911fb 100644 --- a/precache/precache.pro +++ b/precache/precache.pro @@ -24,7 +24,7 @@ DESTDIR = $$OUT_PWD/bin SHARED = $$PWD/../shared CLIENT = $$PWD/../client/src SYSTEM = $$CLIENT/system -THIRDP = $$CLIENT/thirdparty +THIRDP = $$SHARED/thirdparty INCLUDEPATH += \ $$CLIENT \ @@ -35,25 +35,10 @@ INCLUDEPATH += \ HEADERS = \ $$SHARED/stddclmr.h \ - $$SHARED/log.h \ - $$SHARED/util.h \ $$SHARED/thirdparty/memwatch/memwatch.h \ - $$THIRDP/SHA256/sha256.h \ - $$SYSTEM/surface.h \ - $$SYSTEM/os.h \ - $$SYSTEM/cache.h + $$THIRDP/SHA256/sha256.h SOURCES = \ $$SHARED/thirdparty/memwatch/memwatch.c \ - $$SHARED/log.c \ - $$SHARED/util.c \ $$THIRDP/SHA256/sha256.c \ - $$CLIENT/linux/linux.c \ - $$SYSTEM/surface.c \ - $$SYSTEM/os.c \ - $$SYSTEM/cache.c \ src/main.c - -LIBS = \ - -lSDL2 \ - -lSDL2_image diff --git a/precache/src/main.c b/precache/src/main.c index 3364c29..62e2d03 100644 --- a/precache/src/main.c +++ b/precache/src/main.c @@ -19,19 +19,98 @@ #include +#include #define MEMWATCH #include "memwatch/memwatch.h" -#include "cache.h" +#include "thirdparty/SHA256/sha256.h" #include "stddclmr.h" +#define SUCCESS 1 +#define FAIL 0 + + #define CLIENT "/home/scott/code/kpmpgsmkii/client/in/" #define FONT "/home/scott/code/kpmpgsmkii/font/out/" #define OUT "/home/scott/code/kpmpgsmkii/precache/out/" + +typedef struct CachePreMakeListS { + char *filename; + char *virtualPath; +} CachePreMakeListT; + + +uint8_t cachePrePack(char *name, CachePreMakeListT *list) { + + FILE *in = NULL; + FILE *out = NULL; + uint16_t i = 0; + uint8_t result = SUCCESS; + uint32_t length = 0; + uint32_t total = 0; + uint32_t temp = 0; + int8_t buffer[8192] = { 0 }; + sha256_context ctx = { 0 }; + uint8_t hv[32] = { 0 }; + + // Prebuilt cache format: + // - Virtual Path (zero terminated) + // - x bytes hash + // - 4 bytes unsigned length of data + // - length bytes of data + // ... repeat for each file ... + // - 4 bytes length of entire cache (used for embedding cache data) + + out = fopen(name, "wb"); + if (out) { + while (list[i].filename != NULL) { + in = fopen(list[i].filename, "rb"); + if (in) { + // Get length of file. + fseek(in, 0, SEEK_END); + length = ftell(in); + fseek(in, 0, SEEK_SET); + // Generate SHA256. + sha256_init(&ctx); + do { + temp = fread(buffer, 1, sizeof(buffer), in); + if (temp) sha256_hash(&ctx, (uint8_t *)buffer, temp); + } while (temp > 0); + sha256_done(&ctx, hv); + fseek(in, 0, SEEK_SET); + // Write header. + temp = strlen(list[i].virtualPath) + 1; + fwrite(list[i].virtualPath, temp, 1, out); + fwrite(hv, sizeof(hv), 1, out); + fwrite(&length, sizeof(uint32_t), 1, out); + total += temp + sizeof(hv) + sizeof(uint32_t) + length; + // Copy data. + do { + temp = fread(buffer, 1, sizeof(buffer), in); + if (temp) fwrite(buffer, 1, temp, out); + } while (temp > 0); + fclose(in); + } else { + result = FAIL; + } + i++; + } + // Write length of entire block. + total += sizeof(uint32_t); + fwrite(&total, sizeof(uint32_t), 1, out); + fclose(out); + } else { + result = FAIL; + } + + return result; +} + + int main(int argc, char *argv[]) { CachePreMakeListT list[] = { @@ -45,6 +124,7 @@ int main(int argc, char *argv[]) { { CLIENT"gui/mbiq32.png", "gui:question.png" }, { CLIENT"gui/mbiw32.png", "gui:warning.png" }, { CLIENT"gui/mouse.png", "gui:mouse.png" }, + { CLIENT"gui/wait.png", "gui:wait.png" }, { FONT"vga8x14.dat", "gui:vga8x14.dat" }, { NULL, NULL } }; @@ -55,7 +135,7 @@ int main(int argc, char *argv[]) { // Also run optipng -o7 on images. cachePrePack(OUT"client.pre", list); - cachePreUnpack(OUT"client.pre"); + //cachePreUnpack(OUT"client.pre"); return 0; } diff --git a/server/src/client/file.c b/server/src/client/file.c index f0cdc9f..5800600 100644 --- a/server/src/client/file.c +++ b/server/src/client/file.c @@ -179,6 +179,7 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT * static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *data) { uint32_t temp = 0; PacketEncodeDataT encoded = { 0 }; + uint32_t remaining = 0; uint16_t length = 0; uint8_t packetData[PACKET_MAX]; @@ -192,15 +193,16 @@ static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *d // Add file data. // ***TODO*** We can't send quite a full packet for some reason. - length = client->fileSize - ftell(client->handle); - if (length > PACKET_MAX - (10 + sizeof(int32_t))) { + remaining = client->fileSize - ftell(client->handle); + if (remaining > PACKET_MAX - (10 + sizeof(int32_t))) { // File is larger than a packet size. - logWrite("Sending file fraction %d bytes\n", length); length = PACKET_MAX - (10 + sizeof(int32_t)); // 4 for integer of response type. 10 more because a full PACKET_MAX causes issues. + logWrite("Sending file fraction %d bytes of %d remaining.\n", length, remaining); fread(&packetData[sizeof(int32_t)], length, 1, client->handle); } else { // File remains will fit in this packet. - logWrite("Sending file end %d bytes\n", length); + length = remaining; + logWrite("Sending file end %d bytes of %d remaining.\n", length, remaining); fread(&packetData[sizeof(int32_t)], length, 1, client->handle); fclose(client->handle); client->handle = NULL; diff --git a/server/src/database.c b/server/src/database.c index a34e8a6..b456ed6 100644 --- a/server/src/database.c +++ b/server/src/database.c @@ -24,6 +24,7 @@ #include "thirdparty/SHA256/sha256.h" +#include "util.h" #include "array.h" #include "console.h" #include "settings.h" @@ -372,14 +373,16 @@ DbGameT **dbGamesGet(void) { // Find screenshot and box image count from filesystem. x = 0; while (1) { - snprintf(filename, MAX_PATH, "%s/games/%c/%s/screen%d.png", __settingsFile, game->shortName[0], game->shortName, x + 1); + snprintf(filename, MAX_PATH, "%s/files/games/%c/%s/screen%d.png", __settingsFile, game->shortName[0], game->shortName, x + 1); + utilStringToLower(filename); if (!utilFileExists(filename)) break; x++; } game->screens = x; x = 0; while (1) { - snprintf(filename, MAX_PATH, "%s/games/%c/%s/box%d.png", __settingsFile, game->shortName[0], game->shortName, x + 1); + snprintf(filename, MAX_PATH, "%s/files/games/%c/%s/box%d.png", __settingsFile, game->shortName[0], game->shortName, x + 1); + utilStringToLower(filename); if (!utilFileExists(filename)) break; x++; } diff --git a/shared/util.c b/shared/util.c index b5877a7..0e7cfbb 100644 --- a/shared/util.c +++ b/shared/util.c @@ -18,6 +18,8 @@ */ +#include + #include "array.h" #include "util.h" @@ -117,6 +119,13 @@ uint8_t utilFileExists(char *filename) { } +void utilStringToLower(char *string) { + uint16_t i; + + for (i=0; i