Mouse busy pointer support. File transfer bug fixed.

This commit is contained in:
Scott Duensing 2022-04-16 19:59:12 -05:00
parent 794bd96d3f
commit 88369132e3
20 changed files with 378 additions and 143 deletions

23
LICENSE
View file

@ -53,11 +53,6 @@ SDL2_image
https://www.libsdl.org/ https://www.libsdl.org/
BSD 3-Clause BSD 3-Clause
SHA256
------
https://github.com/ilvn/SHA256
MIT
SQLite 3.4.2 SQLite 3.4.2
------------ ------------
https://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/distributions/1.2/repos/pkg-html/sqlite.html 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 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 Server
====== ======

BIN
client/in/gui/wait.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -57,6 +57,7 @@ static TimerT *_timTimer = NULL;
static void btnMsgBoxOkay(MsgBoxButtonT button); static void btnMsgBoxOkay(MsgBoxButtonT button);
static void fileCheckNext(void); static void fileCheckNext(void);
static void fileCurrentUpdate(uint8_t dontCallback);
static void fileShowDialog(void); static void fileShowDialog(void);
static void fileShowError(char *message); static void fileShowError(char *message);
static void packetHandler(PacketDecodeDataT *packet); static void packetHandler(PacketDecodeDataT *packet);
@ -102,12 +103,47 @@ static void fileCheckNext(void) {
uint8_t *packetData = NULL; uint8_t *packetData = NULL;
uint16_t length = 0; uint16_t length = 0;
uint32_t temp = 0; uint32_t temp = 0;
uint8_t doRecheck = 0;
char *shaPointer = NULL; char *shaPointer = NULL;
static char *badSHA = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; static char *badSHA = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
BEGIN 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 { do {
// This is ugly since both lists kind of depend on each other. // This is ugly since both lists kind of depend on each other.
doRecheck = 0; doRecheck = 0;
@ -118,12 +154,8 @@ static void fileCheckNext(void) {
if (arrlen(_fileList) == 0) { if (arrlen(_fileList) == 0) {
logWrite("End of file queue.\n"); logWrite("End of file queue.\n");
arrfree(_fileList); arrfree(_fileList);
if (_dialogVisible) guiDelete(D(_winFile));
netChannelRelease(_channel);
_channel = 0;
return; return;
} }
// Get next queue entry. // Get next queue entry.
_currentLength = 0; _currentLength = 0;
_current = _fileList[0]; _current = _fileList[0];
@ -138,7 +170,7 @@ static void fileCheckNext(void) {
logWrite("End of file list.\n"); logWrite("End of file list.\n");
arrfree(_current->files); arrfree(_current->files);
// Call with NULL to signify end of transfers. // Call with NULL to signify end of transfers.
_current->callback(NULL); if (!dontCallback) _current->callback(NULL);
DEL(_current); DEL(_current);
// See if there's more. // See if there's more.
doRecheck = 1; doRecheck = 1;
@ -150,19 +182,6 @@ static void fileCheckNext(void) {
} }
} while (doRecheck); } 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 END
} }
@ -194,6 +213,9 @@ static void fileShowDialog(void) {
static void fileShowError(char *message) { static void fileShowError(char *message) {
// ***TODO*** This should close all open windows. // ***TODO*** This should close all open windows.
// Reset a possibly busy mouse pointer.
guiMouseBusyClear();
// Show error. This is fatal. // Show error. This is fatal.
if (_dialogVisible) guiDelete(D(_winFile)); if (_dialogVisible) guiDelete(D(_winFile));
netChannelRelease(_channel); netChannelRelease(_channel);
@ -293,20 +315,12 @@ static void timTimerTimeout(WidgetT *widget) {
timerStop(_timTimer); timerStop(_timTimer);
// If we at least have some version of the file, try to continue. // If we at least have some version of the file, try to continue.
while (arrlen(_fileList) > 0) { while (_file) {
while (arrlen(_fileList[0]->files) > 0) { // Passing 'missing' prevents file completion callbacks from
if (cacheFilenameGet(_fileList[0]->files[0])) { // occurring when there are missing files.
arrdel(_fileList[0]->files, 0); fileCurrentUpdate(missing);
} else { if (_file && !cacheFilenameGet(_file)) missing = 1;
missing = 1;
}
}
// If we're good so far, call the callback.
if (!missing) _fileList[0]->callback(NULL);
arrfree(_fileList[0]->files);
arrdel(_fileList, 0);
} }
arrfree(_fileList);
if (missing) fileShowError("Unable to download needed files."); if (missing) fileShowError("Unable to download needed files.");

View file

@ -80,6 +80,7 @@ static uint32_t _guiTimerHalfSecondOn = 0;
static uint32_t _guiTimerSecondOn = 0; static uint32_t _guiTimerSecondOn = 0;
static PendingEventsT **_guiPendingEvents = NULL; static PendingEventsT **_guiPendingEvents = NULL;
static void **_guiPendingFrees = NULL; static void **_guiPendingFrees = NULL;
static uint8_t _guiMouseBusyStack = 0;
static void guiDeleteList(void); 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) { void guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *x, uint16_t *y) {
RectT r; RectT r;
guiWidgetPositionOnScreenGet(widget, &r); guiWidgetPositionOnScreenGet(widget, &r);

View file

@ -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 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 guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *x, uint16_t *y);
void guiMouseProcess(MouseT *mouse); void guiMouseProcess(MouseT *mouse);
void guiMouseBusyClear();
uint8_t guiMouseBusyGet();
void guiMouseBusyPop();
void guiMouseBusyPush();
void guiPaint(WidgetT *widget); void guiPaint(WidgetT *widget);
void guiParentAndChildrenDirtySet(WidgetT *widget); void guiParentAndChildrenDirtySet(WidgetT *widget);
void guiPendingEventAdd(WidgetT *widget, void *callback); void guiPendingEventAdd(WidgetT *widget, void *callback);

View file

@ -97,7 +97,7 @@ void imageCacheIfNeeded(char *cacheFilename, char *sha256) {
temp = (char *)malloc(strlen(cacheFilename) + 5); temp = (char *)malloc(strlen(cacheFilename) + 5);
if (!temp) return; if (!temp) return;
sprintf(temp, "%s.raw", cacheFilename); sprintf(temp, "%s.raw", cacheFilename);
rawSha = strdup(cacheSha256Get(temp)); rawSha = cacheSha256Get(temp);
if (!rawSha || strcmp(rawSha, sha256) != 0) { if (!rawSha || strcmp(rawSha, sha256) != 0) {
// The decompressed file either does not exist or the SHA does not match the file we're checking. // 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); logWrite("Unpacking %s - %s\n", cacheFilenameGet(cacheFilename), cacheFilename);

View file

@ -92,6 +92,7 @@ static void timHangupProgress(WidgetT *widget) {
// Snooze a bit for the packet to send. // Snooze a bit for the packet to send.
_state = S_WAITING; _state = S_WAITING;
timerQuarterSecondsSet(t, 3 * 4); timerQuarterSecondsSet(t, 3 * 4);
guiMouseBusyPush();
break; break;
case S_WAITING: case S_WAITING:
@ -102,6 +103,7 @@ static void timHangupProgress(WidgetT *widget) {
// On to the next dialog. // On to the next dialog.
guiDelete(D(_winHangup)); guiDelete(D(_winHangup));
_done(NULL); _done(NULL);
guiMouseBusyPop();
break; break;
} }
} }

View file

@ -122,6 +122,7 @@ static void loginFilesReady(char *updatedFile) {
runtimeDataUpdate(); runtimeDataUpdate();
} else { } else {
// End of cache update. Display UI. // End of cache update. Display UI.
guiMouseBusyPop();
runtimeDataLoad(); runtimeDataLoad();
// ***TODO*** We used to have a FORGOT PASSWORD link here, too. // ***TODO*** We used to have a FORGOT PASSWORD link here, too.
@ -191,6 +192,7 @@ void loginShow() {
BEGIN BEGIN
guiMouseBusyPush();
fileCacheCheck(loginFilesReady, fileList); fileCacheCheck(loginFilesReady, fileList);
END END

View file

@ -60,9 +60,10 @@
PacketThreadDataT *__packetThreadData = NULL; // Exported in os.h PacketThreadDataT *__packetThreadData = NULL; // Exported in os.h
static MouseT *_mouse = NULL; static MouseT *_mouse = NULL;
static ImageT *_pointer = NULL; static ImageT *_pointer = NULL;
static ColorT _alpha = 0; static ImageT *_hourglass = NULL;
static ColorT _alpha = 0;
#ifndef __linux__ #ifndef __linux__
char *_logName = NULL; char *_logName = NULL;
@ -102,7 +103,11 @@ static void eventLoop(void) {
} }
guiMouseProcess(_mouse); guiMouseProcess(_mouse);
guiComposite(); 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(); vbeVBlankWait();
vbePresent(); vbePresent();
} while (!guiHasStopped()); } while (!guiHasStopped());
@ -123,6 +128,7 @@ static void shutdown(void) {
FILE *in = NULL; FILE *in = NULL;
#endif #endif
imageUnload(&_hourglass);
imageUnload(&_pointer); imageUnload(&_pointer);
netShutdown(); netShutdown();
@ -196,8 +202,9 @@ static uint8_t startup(int argc, char *argv[]) {
guiStartup(); guiStartup();
netStartup(); netStartup();
_pointer = imageLoadCache("gui:mouse.png"); _hourglass = imageLoadCache("gui:wait.png");
_alpha = imagePixelGet(_pointer, 5, 0); _pointer = imageLoadCache("gui:mouse.png");
_alpha = imagePixelGet(_pointer, 5, 0);
return 0; return 0;
} }

View file

@ -106,6 +106,7 @@ static void menuFilesReady(char *updatedFile) {
} }
} else { } else {
// Show UI // Show UI
guiMouseBusyPop();
x = vbeDisplayWidthGet() - 49; x = vbeDisplayWidthGet() - 49;
y = vbeDisplayHeightGet() - 49; y = vbeDisplayHeightGet() - 49;
@ -152,11 +153,155 @@ void menuShow(void) {
"menu:48logoff.png", "menu:48logoff.png",
"menu:48profile.png", "menu:48profile.png",
"generated:games.dat", "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 NULL
}; };
BEGIN BEGIN
guiMouseBusyPush();
fileCacheCheck(menuFilesReady, fileList); fileCacheCheck(menuFilesReady, fileList);
END END
@ -239,6 +384,7 @@ static void updateGameDatabase(void) {
// Mark everything untouched. // Mark everything untouched.
dbExecute("UPDATE games SET touced=0", NULL); dbExecute("UPDATE games SET touced=0", NULL);
/*
// Process latest downloaded game list. // Process latest downloaded game list.
f = cacheFOpen("generated:games.dat", "rb"); f = cacheFOpen("generated:games.dat", "rb");
if (f) { if (f) {
@ -253,4 +399,5 @@ static void updateGameDatabase(void) {
// Delete anything untouched. // Delete anything untouched.
dbExecute("DELETE FROM games WHERE touced=0", NULL); dbExecute("DELETE FROM games WHERE touced=0", NULL);
} }
*/
} }

View file

@ -218,6 +218,7 @@ static void timSettingsProgress(WidgetT *widget) {
com = 0; com = 0;
selected = 1; selected = 1;
_state = S_OPEN_COM; _state = S_OPEN_COM;
guiMouseBusyPush();
break; break;
case S_OPEN_COM: case S_OPEN_COM:
@ -276,6 +277,7 @@ static void timSettingsProgress(WidgetT *widget) {
case S_SCAN_COMPLETE: case S_SCAN_COMPLETE:
timerStop(_timProgress); timerStop(_timProgress);
settingsComShow(); settingsComShow();
guiMouseBusyPop();
break; break;
} }
} }

View file

@ -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) { uint8_t cachePreUnpack(char *name) {
FILE *in = NULL; FILE *in = NULL;
FILE *out = NULL; FILE *out = NULL;

View file

@ -28,12 +28,6 @@
#define CACHE_VIRTUAL_PATH_MAX 512 // Should match setting in the server's client/file.h #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 cacheDelete(char *virtualPath);
uint8_t cacheEntryAdd(char *sha256, char *entryName, char *virtualPath); uint8_t cacheEntryAdd(char *sha256, char *entryName, char *virtualPath);
char *cacheEntryNameGet(char *virtualPath); char *cacheEntryNameGet(char *virtualPath);
@ -41,7 +35,6 @@ uint8_t cacheExists(void);
void cacheFClose(FILE *handle); void cacheFClose(FILE *handle);
char *cacheFilenameGet(char *virtualPath); char *cacheFilenameGet(char *virtualPath);
FILE *cacheFOpen(char *vpath, char *mode); FILE *cacheFOpen(char *vpath, char *mode);
uint8_t cachePrePack(char *name, CachePreMakeListT *list);
uint8_t cachePreUnpack(char *name); uint8_t cachePreUnpack(char *name);
char *cacheSha256Get(char *virtualPath); char *cacheSha256Get(char *virtualPath);
void cacheShutdown(void); void cacheShutdown(void);

View file

@ -256,6 +256,8 @@ static void timWelcomeProgress(WidgetT *widget) {
switch (_state) { switch (_state) {
case S_START_CONNECT: case S_START_CONNECT:
// Hourglass mouse.
guiMouseBusyPush();
// Ghost all buttons. // Ghost all buttons.
widgetEnableSet(W(_btnConnect), 0); widgetEnableSet(W(_btnConnect), 0);
widgetEnableSet(W(_btnSettings), 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); r = comOpen(__configData.serialCom - 1, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
if (r != SER_SUCCESS) { if (r != SER_SUCCESS) {
timerStop(t); timerStop(t);
// Restore mouse.
guiMouseBusyPop();
msgBoxOne("COM Problem", MSGBOX_ICON_ERROR, "Unable to open COM port!\nPlease check settings.", "Okay", btnMsgBox); msgBoxOne("COM Problem", MSGBOX_ICON_ERROR, "Unable to open COM port!\nPlease check settings.", "Okay", btnMsgBox);
break; break;
} }
@ -296,6 +300,8 @@ static void timWelcomeProgress(WidgetT *widget) {
if (strstr(buffer, "OK") == NULL) { if (strstr(buffer, "OK") == NULL) {
comClose(__configData.serialCom - 1); comClose(__configData.serialCom - 1);
timerStop(t); timerStop(t);
// Restore mouse.
guiMouseBusyPop();
msgBoxOne("Modem Problem", MSGBOX_ICON_ERROR, "Modem does not support ENET!\nPlease check settings.", "Okay", btnMsgBox); msgBoxOne("Modem Problem", MSGBOX_ICON_ERROR, "Modem does not support ENET!\nPlease check settings.", "Okay", btnMsgBox);
break; break;
} }
@ -336,6 +342,8 @@ static void timWelcomeProgress(WidgetT *widget) {
if (_timeoutCounter == 0) { if (_timeoutCounter == 0) {
comClose(__configData.serialCom - 1); comClose(__configData.serialCom - 1);
timerStop(t); timerStop(t);
// Restore mouse.
guiMouseBusyPop();
msgBoxOne("No Connection", MSGBOX_ICON_INFORMATION, "Unable to connect to server!\nPlease check settings or try later.", "Okay", btnMsgBox); msgBoxOne("No Connection", MSGBOX_ICON_INFORMATION, "Unable to connect to server!\nPlease check settings or try later.", "Okay", btnMsgBox);
} }
break; break;
@ -352,6 +360,8 @@ static void timWelcomeProgress(WidgetT *widget) {
netPacketHandlerStop(); netPacketHandlerStop();
comClose(__configData.serialCom - 1); comClose(__configData.serialCom - 1);
timerStop(t); timerStop(t);
// Restore mouse.
guiMouseBusyPop();
msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to negotiate encryption settings!", "Okay", btnMsgBox); msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to negotiate encryption settings!", "Okay", btnMsgBox);
} }
break; break;
@ -360,6 +370,8 @@ static void timWelcomeProgress(WidgetT *widget) {
netPacketHandlerStop(); netPacketHandlerStop();
comClose(__configData.serialCom - 1); comClose(__configData.serialCom - 1);
timerStop(t); timerStop(t);
// Restore mouse.
guiMouseBusyPop();
msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to fetch client settings!", "Okay", btnMsgBox); msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to fetch client settings!", "Okay", btnMsgBox);
break; break;
@ -368,6 +380,8 @@ static void timWelcomeProgress(WidgetT *widget) {
timerStop(t); timerStop(t);
netChannelSystemRelease(packetHandler); netChannelSystemRelease(packetHandler);
guiDelete(D(_winWelcome)); guiDelete(D(_winWelcome));
// Restore mouse.
guiMouseBusyPop();
loginShow(); loginShow();
break; break;
} }

View file

@ -24,7 +24,7 @@ DESTDIR = $$OUT_PWD/bin
SHARED = $$PWD/../shared SHARED = $$PWD/../shared
CLIENT = $$PWD/../client/src CLIENT = $$PWD/../client/src
SYSTEM = $$CLIENT/system SYSTEM = $$CLIENT/system
THIRDP = $$CLIENT/thirdparty THIRDP = $$SHARED/thirdparty
INCLUDEPATH += \ INCLUDEPATH += \
$$CLIENT \ $$CLIENT \
@ -35,25 +35,10 @@ INCLUDEPATH += \
HEADERS = \ HEADERS = \
$$SHARED/stddclmr.h \ $$SHARED/stddclmr.h \
$$SHARED/log.h \
$$SHARED/util.h \
$$SHARED/thirdparty/memwatch/memwatch.h \ $$SHARED/thirdparty/memwatch/memwatch.h \
$$THIRDP/SHA256/sha256.h \ $$THIRDP/SHA256/sha256.h
$$SYSTEM/surface.h \
$$SYSTEM/os.h \
$$SYSTEM/cache.h
SOURCES = \ SOURCES = \
$$SHARED/thirdparty/memwatch/memwatch.c \ $$SHARED/thirdparty/memwatch/memwatch.c \
$$SHARED/log.c \
$$SHARED/util.c \
$$THIRDP/SHA256/sha256.c \ $$THIRDP/SHA256/sha256.c \
$$CLIENT/linux/linux.c \
$$SYSTEM/surface.c \
$$SYSTEM/os.c \
$$SYSTEM/cache.c \
src/main.c src/main.c
LIBS = \
-lSDL2 \
-lSDL2_image

View file

@ -19,19 +19,98 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#define MEMWATCH #define MEMWATCH
#include "memwatch/memwatch.h" #include "memwatch/memwatch.h"
#include "cache.h" #include "thirdparty/SHA256/sha256.h"
#include "stddclmr.h" #include "stddclmr.h"
#define SUCCESS 1
#define FAIL 0
#define CLIENT "/home/scott/code/kpmpgsmkii/client/in/" #define CLIENT "/home/scott/code/kpmpgsmkii/client/in/"
#define FONT "/home/scott/code/kpmpgsmkii/font/out/" #define FONT "/home/scott/code/kpmpgsmkii/font/out/"
#define OUT "/home/scott/code/kpmpgsmkii/precache/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[]) { int main(int argc, char *argv[]) {
CachePreMakeListT list[] = { CachePreMakeListT list[] = {
@ -45,6 +124,7 @@ int main(int argc, char *argv[]) {
{ CLIENT"gui/mbiq32.png", "gui:question.png" }, { CLIENT"gui/mbiq32.png", "gui:question.png" },
{ CLIENT"gui/mbiw32.png", "gui:warning.png" }, { CLIENT"gui/mbiw32.png", "gui:warning.png" },
{ CLIENT"gui/mouse.png", "gui:mouse.png" }, { CLIENT"gui/mouse.png", "gui:mouse.png" },
{ CLIENT"gui/wait.png", "gui:wait.png" },
{ FONT"vga8x14.dat", "gui:vga8x14.dat" }, { FONT"vga8x14.dat", "gui:vga8x14.dat" },
{ NULL, NULL } { NULL, NULL }
}; };
@ -55,7 +135,7 @@ int main(int argc, char *argv[]) {
// Also run optipng -o7 on images. // Also run optipng -o7 on images.
cachePrePack(OUT"client.pre", list); cachePrePack(OUT"client.pre", list);
cachePreUnpack(OUT"client.pre"); //cachePreUnpack(OUT"client.pre");
return 0; return 0;
} }

View file

@ -179,6 +179,7 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *data) { static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *data) {
uint32_t temp = 0; uint32_t temp = 0;
PacketEncodeDataT encoded = { 0 }; PacketEncodeDataT encoded = { 0 };
uint32_t remaining = 0;
uint16_t length = 0; uint16_t length = 0;
uint8_t packetData[PACKET_MAX]; uint8_t packetData[PACKET_MAX];
@ -192,15 +193,16 @@ static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *d
// Add file data. // Add file data.
// ***TODO*** We can't send quite a full packet for some reason. // ***TODO*** We can't send quite a full packet for some reason.
length = client->fileSize - ftell(client->handle); remaining = client->fileSize - ftell(client->handle);
if (length > PACKET_MAX - (10 + sizeof(int32_t))) { if (remaining > PACKET_MAX - (10 + sizeof(int32_t))) {
// File is larger than a packet size. // 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. 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); fread(&packetData[sizeof(int32_t)], length, 1, client->handle);
} else { } else {
// File remains will fit in this packet. // 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); fread(&packetData[sizeof(int32_t)], length, 1, client->handle);
fclose(client->handle); fclose(client->handle);
client->handle = NULL; client->handle = NULL;

View file

@ -24,6 +24,7 @@
#include "thirdparty/SHA256/sha256.h" #include "thirdparty/SHA256/sha256.h"
#include "util.h"
#include "array.h" #include "array.h"
#include "console.h" #include "console.h"
#include "settings.h" #include "settings.h"
@ -372,14 +373,16 @@ DbGameT **dbGamesGet(void) {
// Find screenshot and box image count from filesystem. // Find screenshot and box image count from filesystem.
x = 0; x = 0;
while (1) { 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; if (!utilFileExists(filename)) break;
x++; x++;
} }
game->screens = x; game->screens = x;
x = 0; x = 0;
while (1) { 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; if (!utilFileExists(filename)) break;
x++; x++;
} }

View file

@ -18,6 +18,8 @@
*/ */
#include <ctype.h>
#include "array.h" #include "array.h"
#include "util.h" #include "util.h"
@ -117,6 +119,13 @@ uint8_t utilFileExists(char *filename) {
} }
void utilStringToLower(char *string) {
uint16_t i;
for (i=0; i<strlen(string); i++) string[i] = tolower(string[i]);
}
char **utilWrapText(char *text, uint16_t width) { char **utilWrapText(char *text, uint16_t width) {
char **lines = NULL; char **lines = NULL;
char *head = text; char *head = text;

View file

@ -31,6 +31,7 @@ char *utilCreateString(char *format, ...);
char *utilCreateStringVArgs(char *format, va_list args); char *utilCreateStringVArgs(char *format, va_list args);
void utilDie(const char *why, ...); void utilDie(const char *why, ...);
uint8_t utilFileExists(char *filename); uint8_t utilFileExists(char *filename);
void utilStringToLower(char *string);
char **utilWrapText(char *text, uint16_t width); char **utilWrapText(char *text, uint16_t width);