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/
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
======

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 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.");

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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);
}
*/
}

View file

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

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) {
FILE *in = 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
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);

View file

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

View file

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

View file

@ -19,19 +19,98 @@
#include <stdio.h>
#include <stdint.h>
#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;
}

View file

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

View file

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

View file

@ -18,6 +18,8 @@
*/
#include <ctype.h>
#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<strlen(string); i++) string[i] = tolower(string[i]);
}
char **utilWrapText(char *text, uint16_t width) {
char **lines = NULL;
char *head = text;

View file

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