From f477ee15d02ef88960f98cbf6442b915ca2759af Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Mon, 25 Apr 2022 21:30:04 -0500 Subject: [PATCH] Dynamic screenshot display working in browser. --- client/client.pro | 1 + client/src/browser.c | 268 ++++++++++++++++++++++++++++-------- client/src/browser.h | 1 + client/src/file.c | 38 ++++- client/src/file.h | 1 + client/src/gui/gui.c | 2 + client/src/gui/listbox.c | 38 ++++- client/src/gui/listbox.h | 10 +- client/src/gui/picture.c | 15 ++ client/src/gui/picture.h | 1 + client/src/menu.c | 64 ++------- client/src/menu.h | 1 + client/src/runtime.c | 57 +++----- client/src/settings.c | 13 +- client/src/system/network.c | 5 + client/src/system/network.h | 1 + client/src/system/os.c | 3 + client/src/system/os.h | 6 +- client/src/welcome.c | 27 ++-- shared/game.c | 41 ++++++ shared/game.h | 4 + shared/util.c | 37 +++++ shared/util.h | 2 + 23 files changed, 460 insertions(+), 176 deletions(-) create mode 100644 shared/game.c diff --git a/client/client.pro b/client/client.pro index 1333108..b4ecce5 100644 --- a/client/client.pro +++ b/client/client.pro @@ -131,6 +131,7 @@ SOURCES = \ $$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.c \ $$SHARED/thirdparty/SHA256/sha256.c \ $$SHARED/memory.c \ + ../shared/game.c \ src/browser.c \ src/file.c \ src/gui/msgbox.c \ diff --git a/client/src/browser.c b/client/src/browser.c index ed142ad..d877d86 100644 --- a/client/src/browser.c +++ b/client/src/browser.c @@ -33,6 +33,8 @@ #include "db.h" #include "network.h" #include "util.h" +#include "game.h" +#include "file.h" static WindowT *_winBrowser = NULL; @@ -50,17 +52,11 @@ static ListboxT *_lstDescription = NULL; static ButtonT *_btnScreensTab = NULL; static FrameT *_fraScreens = NULL; -static PictureT *_picThumb1 = NULL; -static PictureT *_picThumb2 = NULL; -static PictureT *_picThumb3 = NULL; -static PictureT *_picThumb4 = NULL; -static PictureT *_picThumb5 = NULL; -static PictureT *_picThumb6 = NULL; +static PictureT *_picThumb[6]; static ButtonT *_btnBoxTab = NULL; static FrameT *_fraBox = NULL; -static PictureT *_picBox1 = NULL; -static PictureT *_picBox2 = NULL; +static PictureT *_picBox[2]; static ButtonT *_btnInfoTab = NULL; static FrameT *_fraInfo = NULL; @@ -69,14 +65,22 @@ static ListboxT *_lstInfo = NULL; static uint8_t _channel = 0; static char *_lastSearchText = NULL; +static GameT _selectedGame = { 0 }; + -static void browserHide(void); static void btnTabClick(WidgetT *widget); +static void fraBoxShow(void); +static void fraDescriptionShow(void); +static void fraInfoShow(void); +static void fraScreensShow(void); +static void fraScreensReady(char *file); static void packetHandler(PacketDecodeDataT *packet); +static void tabsBusySet(uint8_t busy); static void timSearchUpdate(WidgetT *widget); +static void updateSelectedGame(void); -static void browserHide(void) { +void browserHide(void) { timerStop(_timSearchUpdate); DEL(_lastSearchText); netChannelRelease(_channel); @@ -106,7 +110,7 @@ void browserShow(void) { T_TITLE, P("Search"), T_TEXTBOX, O(_txtSearch), - T_TITLE, P("Game, Publisher, or Developer:"), + T_TITLE, P("Filter:"), T_X, 5, T_Y, 3, T_WIDTH, 490, T_LENGTH, 255, @@ -155,38 +159,33 @@ void browserShow(void) { T_TITLE, P("Screenshots"), T_VISIBLE, T_FALSE, - T_PICTURE, O(_picThumb1), // Thumbs are 160x100 + T_PICTURE, O(_picThumb[0]), // Thumbs are 160x100 T_X, 1, T_Y, 5, T_CACHENAME, P("browser:no-screen.png"), T_PICTURE, T_DONE, - T_PICTURE, O(_picThumb2), + T_PICTURE, O(_picThumb[1]), T_X, 167, T_Y, 5, T_CACHENAME, P("browser:no-screen.png"), - T_VISIBLE, T_FALSE, T_PICTURE, T_DONE, - T_PICTURE, O(_picThumb3), + T_PICTURE, O(_picThumb[2]), T_X, 333, T_Y, 5, T_CACHENAME, P("browser:no-screen.png"), - T_VISIBLE, T_FALSE, T_PICTURE, T_DONE, - T_PICTURE, O(_picThumb4), + T_PICTURE, O(_picThumb[3]), T_X, 1, T_Y, 116, T_CACHENAME, P("browser:no-screen.png"), - T_VISIBLE, T_FALSE, T_PICTURE, T_DONE, - T_PICTURE, O(_picThumb5), + T_PICTURE, O(_picThumb[4]), T_X, 167, T_Y, 116, T_CACHENAME, P("browser:no-screen.png"), - T_VISIBLE, T_FALSE, T_PICTURE, T_DONE, - T_PICTURE, O(_picThumb6), + T_PICTURE, O(_picThumb[5]), T_X, 333, T_Y, 116, T_CACHENAME, P("browser:no-screen.png"), - T_VISIBLE, T_FALSE, T_PICTURE, T_DONE, - T_FRAME, T_DONE, + T_FRAME, T_DONE, // BOX T_BUTTON, O(_btnBoxTab), @@ -201,17 +200,16 @@ void browserShow(void) { T_TITLE, P("Packaging"), T_VISIBLE, T_FALSE, - T_PICTURE, O(_picBox1), // Thumbs are 240x210 + T_PICTURE, O(_picBox[0]), // Thumbs are 240x210 T_X, 1, T_Y, 5, T_CACHENAME, P("browser:no-box.png"), T_PICTURE, T_DONE, - T_PICTURE, O(_picBox2), + T_PICTURE, O(_picBox[1]), T_X, 250, T_Y, 5, T_CACHENAME, P("browser:no-box.png"), - T_VISIBLE, T_FALSE, T_PICTURE, T_DONE, - T_FRAME, T_DONE, + T_FRAME, T_DONE, // INFO T_BUTTON, O(_btnInfoTab), @@ -247,7 +245,7 @@ void browserShow(void) { guiFocusSet(W(_txtSearch)); _channel = netChannelGet(packetHandler); - _lastSearchText = strdup(""); + _lastSearchText = strdup("x"); /* guiDebugAreaShow(W(_fraSearch)); @@ -288,17 +286,101 @@ void browserShow(void) { static void btnTabClick(WidgetT *widget) { + tabsBusySet(1); + + // Hide everything. widgetVisibleSet(W(_fraBox), 0); widgetVisibleSet(W(_fraDescription), 0); widgetVisibleSet(W(_fraInfo), 0); widgetVisibleSet(W(_fraScreens), 0); widgetVisibleSet(W(_fraSearch), 0); - if (widget == W(_btnBoxTab)) widgetVisibleSet(W(_fraBox), 1); - if (widget == W(_btnDescriptionTab)) widgetVisibleSet(W(_fraDescription), 1); - if (widget == W(_btnInfoTab)) widgetVisibleSet(W(_fraInfo), 1); - if (widget == W(_btnScreensTab)) widgetVisibleSet(W(_fraScreens), 1); - if (widget == W(_btnSearchTab)) widgetVisibleSet(W(_fraSearch), 1); + updateSelectedGame(); + + // Show selected frame. + if (widget == W(_btnBoxTab)) fraBoxShow(); + if (widget == W(_btnDescriptionTab)) fraDescriptionShow(); + if (widget == W(_btnInfoTab)) fraInfoShow(); + if (widget == W(_btnScreensTab)) fraScreensShow(); + if (widget == W(_btnSearchTab)) { + widgetVisibleSet(W(_fraSearch), 1); + tabsBusySet(0); + } +} + + +static void fraBoxShow(void) { + widgetVisibleSet(W(_fraBox), 1); + tabsBusySet(0); +} + + +static void fraDescriptionShow(void) { + widgetVisibleSet(W(_fraDescription), 1); + tabsBusySet(0); +} + + +static void fraInfoShow(void) { + widgetVisibleSet(W(_fraInfo), 1); + tabsBusySet(0); +} + + +static void fraScreensShow(void) { + char **fileList = NULL; + char *temp; + uint8_t i; + + // Build list of screen filenames needed. + for (i=0; i<_selectedGame.screens; i++) { + temp = utilCreateString("games:%c:%s:screen%d.png", _selectedGame.shortName[0], _selectedGame.shortName, i + 1); + utilStringToLower(temp); + arrput(fileList, temp); + temp = utilCreateString("games:%c:%s:screen%d-thumb.png", _selectedGame.shortName[0], _selectedGame.shortName, i + 1); + utilStringToLower(temp); + arrput(fileList, temp); + } + + if (fileList) { + fileCacheCheckArr(fraScreensReady, fileList); + } else { + fraScreensReady(NULL); + } +} + + +static void fraScreensReady(char *file) { + + uint8_t i; + + // Is this a file update notice? If so, exit. + if (file) return; + + // Are there screenshots? + if (_selectedGame.screens == 0) { + // Nope. + pictureReplace(_picThumb[0], "browser:no-screen.png"); + for (i=1; i<6; i++) { + widgetVisibleSet(W(_picThumb[i]), 0); + } + } else { + for (i=0; i<6; i++) { + if (i < _selectedGame.screens) { + snprintf(_scratch, SCRATCH_SIZE, "games:%c:%s:screen%d-thumb.png", _selectedGame.shortName[0], _selectedGame.shortName, i + 1); + utilStringToLower(_scratch); + logWrite("Loading screen: %s\n", _scratch); + pictureReplace(_picThumb[i], _scratch); + widgetVisibleSet(W(_picThumb[i]), 1); + } else { + widgetVisibleSet(W(_picThumb[i]), 0); + } + } + } + + // Display us. + widgetVisibleSet(W(_fraScreens), 1); + tabsBusySet(0); } @@ -307,39 +389,113 @@ static void packetHandler(PacketDecodeDataT *packet) { } +static void tabsBusySet(uint8_t busy) { + uint8_t enabled = busy ? 0 : 1; + + if (busy) { + guiMouseBusyPush(); + } else { + guiMouseBusyPop(); + } + + widgetEnableSet(W(_btnSearchTab), enabled); + widgetEnableSet(W(_btnDescriptionTab), enabled); + widgetEnableSet(W(_btnScreensTab), enabled); + widgetEnableSet(W(_btnBoxTab), enabled); + widgetEnableSet(W(_btnInfoTab), enabled); +} + + static void timSearchUpdate(WidgetT *widget) { char ***records = NULL; char **fields = NULL; uint16_t count = 0; - char query[258]; // 255 search characters, two %'s, and the terminating null. (void)widget; - // Are there more than two characters in the search field? - if (textboxValueGet(_txtSearch) && strlen(textboxValueGet(_txtSearch)) > 2) { - // Did the search contents change? - if (strcmp(_lastSearchText, textboxValueGet(_txtSearch))) { - // Remember what was in the search box. - DEL(_lastSearchText); - _lastSearchText = strdup(textboxValueGet(_txtSearch)); - // Clear current search results. - listboxItemsClear(_lstResults); - // Execute search. - snprintf(query, 258, "%%%s%%", _lastSearchText); + // Did the search contents change? + if (strcmp(_lastSearchText, textboxValueGet(_txtSearch))) { + // Remember what was in the search box. + DEL(_lastSearchText); + _lastSearchText = strdup(textboxValueGet(_txtSearch)); + // Clear current search results. + listboxItemsClear(_lstResults); + // Is there something in the search field? + if (textboxValueGet(_txtSearch) && strlen(textboxValueGet(_txtSearch)) > 0) { + // Yes. Filter based on what is in the search field. + snprintf(_scratch, SCRATCH_SIZE, "%%%s%%", _lastSearchText); dbQueryMultiple(&records, - "SELECT title FROM games WHERE " - "title LIKE ? OR developer LIKE ? OR publisher LIKE ? " + "SELECT ROWID, title FROM games WHERE " + "title LIKE ? " "ORDER BY title", - "vvv", - query, - query, - query); - // Did we get anything? + "v", + _scratch); + } else { + // No. Display ALL games. + dbQueryMultiple(&records, + "SELECT ROWID, title FROM games " + "ORDER BY title", + NULL); + } + // Did we get anything? + if (records) { + for (count = 0; count < arrlen(records); count++) { + fields = records[count]; + listboxItemAddWithData(_lstResults, fields[1], atol(fields[0])); + } + dbResultRelease(&records); + } + // Ghost or enable tab buttons depending on if the listbox has an item highlighted or not. + count = listboxItemsCountGet(_lstResults) > 0; // Reusing count. + widgetEnableSet(W(_btnDescriptionTab), count); + widgetEnableSet(W(_btnScreensTab), count); + widgetEnableSet(W(_btnBoxTab), count); + widgetEnableSet(W(_btnInfoTab), count); + } +} + + +static void updateSelectedGame(void) { + char ***records = NULL; + char **fields = NULL; + + // If a game is selected... + if (listboxItemsCountGet(_lstResults) > 0) { + // Is it a different game? + if (listboxDataGet(_lstResults) != _selectedGame.ROWID) { + // Clear last loadead game. + gameClear(&_selectedGame); + + logWrite("Loading game details: %d = '%s'\n", listboxDataGet(_lstResults), listboxValueGet(_lstResults)); + + // Load the details from the SQL database. + dbQueryMultiple(&records, + "SELECT title, publisher, developer, description, " + "releaseDate, rating, series, origin, shortName, " + "worksWith, type, maxPlayers, joinable, screens, " + "boxes, ROWID " + "FROM games WHERE " + "ROWID=?", + "i", + listboxDataGet(_lstResults)); if (records) { - for (count = 0; count < arrlen(records); count++) { - fields = records[count]; - listboxItemAdd(_lstResults, fields[0]); - } + fields = records[0]; + _selectedGame.title = strdup(fields[0]); + _selectedGame.publisher = strdup(fields[1]); + _selectedGame.developer = strdup(fields[2]); + _selectedGame.description = strdup(fields[3]); + _selectedGame.releaseDate = strdup(fields[4]); + _selectedGame.rating = strdup(fields[5]); + _selectedGame.series = strdup(fields[6]); + _selectedGame.origin = strdup(fields[7]); + _selectedGame.shortName = strdup(fields[8]); + _selectedGame.worksWith = strdup(fields[9]); + _selectedGame.type = atoi(fields[10]); + _selectedGame.maxPlayers = atoi(fields[11]); + _selectedGame.joinable = atoi(fields[12]); + _selectedGame.screens = atoi(fields[13]); + _selectedGame.boxes = atoi(fields[14]); + _selectedGame.ROWID = atol(fields[15]); dbResultRelease(&records); } } diff --git a/client/src/browser.h b/client/src/browser.h index 36ba7d4..3a3c8bf 100644 --- a/client/src/browser.h +++ b/client/src/browser.h @@ -25,6 +25,7 @@ #include "os.h" +void browserHide(void); void browserShow(void); diff --git a/client/src/file.c b/client/src/file.c index 101dfb8..cd42138 100644 --- a/client/src/file.c +++ b/client/src/file.c @@ -70,20 +70,46 @@ static void btnMsgBoxOkay(MsgBoxButtonT button) { } +// List of character array. void fileCacheCheck(fileCallback callback, char *vpaths[]) { + uint16_t i = 0; + char **files = NULL; + + // Used during development & debugging. + if (!netPacketHandlerIsRunning()) { + callback(NULL); + return; + } + + BEGIN + + while (vpaths[i] != NULL) { + arrput(files, strdup(vpaths[i])); + i++; + } + + fileCacheCheckArr(callback, files); + + END +} + + +// List of dynamic array. +void fileCacheCheckArr(fileCallback callback, char **vpathArr) { FileListT *newList = NULL; - uint16_t i = 0; + + // Used during development & debugging. + if (!netPacketHandlerIsRunning()) { + callback(NULL); + return; + } BEGIN // Add new entries to anything already in the queue. NEW(FileListT, newList); newList->callback = callback; - newList->files = NULL; - while (vpaths[i] != NULL) { - arrput(newList->files, strdup(vpaths[i])); - i++; - } + newList->files = vpathArr; arrput(_fileList, newList); // New queue? diff --git a/client/src/file.h b/client/src/file.h index d153f02..58e699d 100644 --- a/client/src/file.h +++ b/client/src/file.h @@ -29,6 +29,7 @@ typedef void (*fileCallback)(char *updatedFile); void fileCacheCheck(fileCallback callback, char *vpaths[]); +void fileCacheCheckArr(fileCallback callback, char **vpathArr); #endif // FILE_H diff --git a/client/src/gui/gui.c b/client/src/gui/gui.c index 1c27f41..cb9782c 100644 --- a/client/src/gui/gui.c +++ b/client/src/gui/gui.c @@ -218,6 +218,7 @@ void guiDelayedFree(void **pointer) { // Delayed Free allows freeing of data that may be in use by the // GUI system at a safe time. (After compositing.) arrput(_guiPendingFrees, *pointer); + *pointer = NULL; } @@ -230,6 +231,7 @@ void guiDelete(WidgetT **widget) { // that is also handled in the paint event. arrput(_guiDeleteList, widget); + *widget = NULL; } diff --git a/client/src/gui/listbox.c b/client/src/gui/listbox.c index b6d5ee7..1b03ab5 100644 --- a/client/src/gui/listbox.c +++ b/client/src/gui/listbox.c @@ -42,6 +42,11 @@ static void listboxScrollUp(ListboxT *listbox); static void listboxSizesRecalculate(ListboxT *listbox); +uint32_t listboxDataGet(ListboxT *listbox) { + return listbox->values[listbox->selected]->data; +} + + static void listboxDel(WidgetT **widget) { ListboxT *l = (ListboxT *)*widget; @@ -83,7 +88,19 @@ WidgetT *listboxInit(WidgetT *widget, char *title) { void listboxItemAdd(ListboxT *listbox, char *item) { - arrput(listbox->values, strdup(item)); + listboxItemAddWithData(listbox, item, 0); +} + + +void listboxItemAddWithData(ListboxT *listbox, char *item, uint32_t data) { + ListboxItemT *i; + + NEW(ListboxItemT, i); + + i->text = strdup(item); + i->data = data; + arrput(listbox->values, i); + GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY); } @@ -94,7 +111,8 @@ void listboxItemRemove(ListboxT *listbox, char *item) { if (len > 0) { for (x=0; xvalues[x]) == 0) { + if (strcmp(item, listbox->values[x]->text) == 0) { + DEL(listbox->values[x]->text); DEL(listbox->values[x]); arrdel(listbox->values, x); if (listbox->selected > len || listbox->selected > 0) listbox->selected--; @@ -108,12 +126,20 @@ void listboxItemRemove(ListboxT *listbox, char *item) { void listboxItemsClear(ListboxT *listbox) { while (arrlen(listbox->values) > 0) { + DEL(listbox->values[0]->text); DEL(listbox->values[0]); arrdel(listbox->values, 0); } arrfree(listbox->values); listbox->selected = 0; + + GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY); +} + + +uint16_t listboxItemsCountGet(ListboxT *listbox) { + return arrlen(listbox->values); } @@ -278,9 +304,9 @@ static void listboxPaint(WidgetT *widget, uint8_t enabled, RectT pos) { for (i=0; iselected) { surfaceRectangleFilledDraw(pos.x + __guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING], o, pos.x + _valueWidth - __guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING], o + fontHeightGet(__guiFont) - 1, __guiColor[COLOR_LISTBOX_SELECTED_BACKGROUND]); - fontRender(__guiFont, l->values[l->offset + i], __guiColor[COLOR_LISTBOX_SELECTED_TEXT], __guiColor[COLOR_LISTBOX_SELECTED_BACKGROUND], pos.x + 1 + __guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING], o); + fontRender(__guiFont, l->values[l->offset + i]->text, __guiColor[COLOR_LISTBOX_SELECTED_TEXT], __guiColor[COLOR_LISTBOX_SELECTED_BACKGROUND], pos.x + 1 + __guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING], o); } else { - fontRender(__guiFont, l->values[l->offset + i], __guiColor[COLOR_LISTBOX_TEXT], __guiColor[COLOR_LISTBOX_BACKGROUND], pos.x + 1 + __guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING], o); + fontRender(__guiFont, l->values[l->offset + i]->text, __guiColor[COLOR_LISTBOX_TEXT], __guiColor[COLOR_LISTBOX_BACKGROUND], pos.x + 1 + __guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING], o); } o += fontHeightGet(__guiFont); } @@ -389,7 +415,7 @@ void listboxTitleSet(ListboxT *listbox, char *title) { char *listboxValueGet(ListboxT *listbox) { - return listbox->values[listbox->selected]; + return listbox->values[listbox->selected]->text; } @@ -399,7 +425,7 @@ void listboxValueSet(ListboxT *listbox, char *value) { if (len > 0) { for (x=0; xvalues[x]) == 0) { + if (strcmp(value, listbox->values[x]->text) == 0) { listbox->selected = x; GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY); break; diff --git a/client/src/gui/listbox.h b/client/src/gui/listbox.h index 165ac87..f405060 100644 --- a/client/src/gui/listbox.h +++ b/client/src/gui/listbox.h @@ -26,22 +26,30 @@ #include "widget.h" +typedef struct ListboxItemS { + char *text; + uint32_t data; +} ListboxItemT; + typedef struct ListboxS { WidgetT base; // Must be first in every widget char *title; - char **values; + ListboxItemT **values; uint16_t selected; // values[offset + selected] int32_t step; int32_t offset; } ListboxT; +uint32_t listboxDataGet(ListboxT *listbox); uint16_t listboxIndexGet(ListboxT *listbox); void listboxIndexSet(ListboxT *listbox, uint16_t index); WidgetT *listboxInit(WidgetT *widget, char *title); void listboxItemAdd(ListboxT *listbox, char *item); +void listboxItemAddWithData(ListboxT *listbox, char *item, uint32_t data); void listboxItemRemove(ListboxT *listbox, char *item); void listboxItemsClear(ListboxT *listbox); +uint16_t listboxItemsCountGet(ListboxT *listbox); ListboxT *listboxNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title); void listboxStepSet(ListboxT *listbox, int32_t step); void listboxTitleSet(ListboxT *listbox, char *title); diff --git a/client/src/gui/picture.c b/client/src/gui/picture.c index f11db64..4a09a14 100644 --- a/client/src/gui/picture.c +++ b/client/src/gui/picture.c @@ -117,6 +117,21 @@ static void picturePaint(WidgetT *widget, uint8_t enabled, RectT pos) { } +void pictureReplace(PictureT *picture, char *filename) { + ImageT *newImage = NULL; + + newImage = imageLoadCache(filename); + if (newImage) { + DEL(picture->filename); + picture->filename = strdup(filename); + imageUnload(&picture->image); + picture->image = newImage; + GUI_SET_FLAG(W(picture), WIDGET_FLAG_DIRTY); + } + +} + + void pictureZoomSet(PictureT *picture, PictureZoomT zoom) { picture->zoom = zoom; GUI_SET_FLAG(W(picture), WIDGET_FLAG_DIRTY); diff --git a/client/src/gui/picture.h b/client/src/gui/picture.h index 48ec614..3404c77 100644 --- a/client/src/gui/picture.h +++ b/client/src/gui/picture.h @@ -45,6 +45,7 @@ typedef struct PictureS { void pictureClickHandlerSet(PictureT *picture, widgetCallback callback); WidgetT *pictureInit(WidgetT *widget, char *filename); PictureT *pictureNew(uint16_t x, uint16_t y, char *filename); +void pictureReplace(PictureT *picture, char *filename); void pictureZoomSet(PictureT *picture, PictureZoomT zoom); diff --git a/client/src/menu.c b/client/src/menu.c index da5ad6e..4108d71 100644 --- a/client/src/menu.c +++ b/client/src/menu.c @@ -145,6 +145,16 @@ static void menuFilesReady(char *updatedFile) { } +void menuHide(void) { + guiDelete(D(_picChat)); + guiDelete(D(_picEmail)); + guiDelete(D(_picForums)); + guiDelete(D(_picGames)); + guiDelete(D(_picLogoff)); + guiDelete(D(_picProfile)); +} + + void menuShow(void) { char *fileList[] = { "menu:48chat.png", @@ -154,6 +164,9 @@ void menuShow(void) { "menu:48logoff.png", "menu:48profile.png", "generated:games.dat", + "browser:no-box.png", + "browser:no-screen.png", + // "browser:no-banner.png", // LOAD THE WORLD! This is for debugging the browser. "games:d:descent:banner.png", @@ -295,8 +308,6 @@ void menuShow(void) { "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 }; @@ -357,44 +368,6 @@ static void picProfileClick(WidgetT *widget) { } -uint8_t utilFromFileReadByte(FILE *f, uint8_t *result) { - unsigned char c; - - // Get next byte. - c = fgetc(f); - // End of file? - if (feof(f)) return FAIL; - // Add to result. - *result = c; - return SUCCESS; -} - - -uint8_t utilFromFileReadString(FILE *f, char **result) { - unsigned char c; - char buffer[GAME_MAX_DESCRIPTION]; - uint16_t x = 0; - - // Something already in 'result'? - DEL(*result); - - while (1) { - // Get next byte. - c = fgetc(f); - // End of file? - if (feof(f)) return FAIL; - // Add to result. - buffer[x++] = c; - buffer[x] = 0; - // End of string? - if (c == 0) { - *result = strdup(buffer); - return SUCCESS; - } - } -} - - /* static */ void updateGameDatabase(void) { FILE *f = NULL; uint8_t result; @@ -491,16 +464,7 @@ uint8_t utilFromFileReadString(FILE *f, char **result) { dbExecute("DELETE FROM games WHERE touched=0", NULL); // Free 'game'. - DEL(game.title); - DEL(game.publisher); - DEL(game.developer); - DEL(game.description); - DEL(game.releaseDate); - DEL(game.rating); - DEL(game.series); - DEL(game.origin); - DEL(game.shortName); - DEL(game.worksWith); + gameClear(&game); //***TODO*** Did we have problems updating the game database? if (result == FAIL) { diff --git a/client/src/menu.h b/client/src/menu.h index eaeb502..22342a4 100644 --- a/client/src/menu.h +++ b/client/src/menu.h @@ -25,6 +25,7 @@ #include "os.h" +void menuHide(void); void menuShow(void); diff --git a/client/src/runtime.c b/client/src/runtime.c index dfa3f37..e0f7b23 100644 --- a/client/src/runtime.c +++ b/client/src/runtime.c @@ -55,50 +55,37 @@ void runtimeDataLoad(void) { void runtimeDataUpdate(void) { FILE *f; - uint8_t c; - char name[33]; - char data[1025]; - uint8_t which = 0; // 0 = Reading name, 1 = Reading data. - uint16_t x = 0; + char *name = NULL; + char *data = NULL; + uint8_t result = FAIL; f = cacheFOpen("generated:client.dat", "rb"); if (f) { while (1) { - // Get next byte. - c = fgetc(f); - // End of file? - if (feof(f)) break; - // End of string? - if (c == 0) { - if (which == 0) { - // Got the name, move on to data. - which++; - name[x] = 0; - x = 0; - } else { - // Got data. Write both to database and start over. - which = 0; - data[x] = 0; - x = 0; - dbExecute( - "REPLACE INTO data (name, data) VALUES (?, ?)", - "vv", - name, data - ); - } - continue; - } - // Got byte. - if (which == 0) { - name[x++] = c; - } else { - data[x++] = c; + // If this first read fails, we're out of data. Any other read fails, we have problems. + if (!utilFromFileReadString(f, &name)) { + result = SUCCESS; + break; } + if (!utilFromFileReadString(f, &data)) break; + // Write this to the database. + dbExecute( + "REPLACE INTO data (name, data) VALUES (?, ?)", + "vv", + name, data + ); + DEL(name); + DEL(data); } cacheFClose(f); } - runtimeDataLoad(); + //***TODO*** Did we have problems updating the runtime data? + if (result == FAIL) { + // Do something here. + } else { + runtimeDataLoad(); + } } diff --git a/client/src/settings.c b/client/src/settings.c index 23ca7f2..fe9d7e3 100644 --- a/client/src/settings.c +++ b/client/src/settings.c @@ -206,7 +206,6 @@ static void settingsComShow(void) { static void timSettingsProgress(WidgetT *widget) { - char buffer[1024]; int32_t rc; uint32_t len; @@ -224,8 +223,8 @@ static void timSettingsProgress(WidgetT *widget) { case S_OPEN_COM: rc = comOpen(com, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS); if (rc == SER_SUCCESS) { - snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13); - comWrite(com, buffer, strlen(buffer)); + snprintf(_scratch, SCRATCH_SIZE, "%s%c", "AT+SOCK1", 13); + comWrite(com, _scratch, strlen(_scratch)); timerQuarterSecondsSet((TimerT *)widget, 4); _state = S_WAIT_FOR_INIT; } else { @@ -243,16 +242,16 @@ static void timSettingsProgress(WidgetT *widget) { break; case S_WAIT_FOR_INIT: - len = comRead(com, buffer, 1023); - buffer[len] = 0; - if (strstr(buffer, "OK")) { + len = comRead(com, _scratch, SCRATCH_SIZE); + _scratch[len] = 0; + if (strstr(_scratch, "OK")) { snprintf(_port[com].title, TITLE_LEN - 1, "COM%d - Modem Found!", com + 1); _port[com].status = PORT_GOOD_MODEM; _port[com].selected = selected; _port[com].enabled = 1; selected = 0; } else { - if (strstr(buffer, "ERROR")) { + if (strstr(_scratch, "ERROR")) { snprintf(_port[com].title, TITLE_LEN - 1, "COM%d - Incompatable Modem", com + 1); _port[com].status = PORT_BAD_MODEM; _port[com].selected = 0; diff --git a/client/src/system/network.c b/client/src/system/network.c index 902a22f..13b87ae 100644 --- a/client/src/system/network.c +++ b/client/src/system/network.c @@ -82,6 +82,11 @@ void netChannelSystemRelease(netPacketHandler handler) { } +uint8_t netPacketHandlerIsRunning(void) { + return _netRunning; +} + + void netPacketHandlerStart(void) { _netRunning = 1; } diff --git a/client/src/system/network.h b/client/src/system/network.h index e12e0fd..fffcd75 100644 --- a/client/src/system/network.h +++ b/client/src/system/network.h @@ -32,6 +32,7 @@ uint8_t netChannelGet(netPacketHandler handler); void netChannelRelease(uint8_t channel); void netChannelSystemGet(netPacketHandler handler); void netChannelSystemRelease(netPacketHandler handler); +uint8_t netPacketHandlerIsRunning(void); void netPacketHandlerStart(void); void netPacketHandlerStop(void); void netProcess(void); diff --git a/client/src/system/os.c b/client/src/system/os.c index 7fa6f42..6460217 100644 --- a/client/src/system/os.c +++ b/client/src/system/os.c @@ -21,6 +21,9 @@ #include "os.h" +char _scratch[SCRATCH_SIZE]; + + uint8_t osFileExists(char *filename) { FILE *f = fopen(filename, "rb"); if (f) { diff --git a/client/src/system/os.h b/client/src/system/os.h index 83dd743..066fa6e 100644 --- a/client/src/system/os.h +++ b/client/src/system/os.h @@ -42,7 +42,8 @@ #define TICKS_PER_SECOND 18.2 #define TICKS_PER_DAY (SECONDS_IN_DAY * TICKS_PER_SECOND) -#define OS_PATH_MAX 256 +#define OS_PATH_MAX 256 +#define SCRATCH_SIZE 4096 #ifdef __linux__ @@ -79,11 +80,14 @@ void linuxOsStartup(void); #include "packet.h" #include "cache.h" + #ifndef PacketThreadDataT typedef struct PacketThreadDataS PacketThreadDataT; #endif + extern PacketThreadDataT *__packetThreadData; // Declared in main.c +extern char _scratch[SCRATCH_SIZE]; // Declared in os.c uint8_t osFileExists(char *filename); diff --git a/client/src/welcome.c b/client/src/welcome.c index fa7724a..313f8b7 100644 --- a/client/src/welcome.c +++ b/client/src/welcome.c @@ -249,7 +249,6 @@ static void timWelcomeProgress(WidgetT *widget) { TimerT *t = (TimerT *)widget; int32_t r = 0; uint32_t len = 0; - static char buffer[1024] = { 0 }; static uint16_t offset = 0; BEGIN @@ -279,25 +278,25 @@ static void timWelcomeProgress(WidgetT *widget) { break; } // Send a CR to clear anything in the modem. - snprintf(buffer, 1023, "%c", 13); - comWrite(__configData.serialCom - 1, buffer, strlen(buffer)); + snprintf(_scratch, SCRATCH_SIZE, "%c", 13); + comWrite(__configData.serialCom - 1, _scratch, strlen(_scratch)); timerQuarterSecondsSet(t, 4); _state = S_INIT_MODEM; break; case S_INIT_MODEM: // Just read anything to clear the buffer. - comRead(__configData.serialCom - 1, buffer, 1023); + comRead(__configData.serialCom - 1, _scratch, SCRATCH_SIZE); // Send actual init - snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13); - comWrite(__configData.serialCom - 1, buffer, strlen(buffer)); + snprintf(_scratch, SCRATCH_SIZE, "%s%c", "AT+SOCK1", 13); + comWrite(__configData.serialCom - 1, _scratch, strlen(_scratch)); _state = S_INIT_RESULT; break; case S_INIT_RESULT: - len = comRead(__configData.serialCom - 1, buffer, 1023); - buffer[len] = 0; - if (strstr(buffer, "OK") == NULL) { + len = comRead(__configData.serialCom - 1, _scratch, SCRATCH_SIZE); + _scratch[len] = 0; + if (strstr(_scratch, "OK") == NULL) { comClose(__configData.serialCom - 1); timerStop(t); // Restore mouse. @@ -312,8 +311,8 @@ static void timWelcomeProgress(WidgetT *widget) { break; case S_DIAL: - snprintf(buffer, 1023, "ATDT%s:%d%c", __configData.serverHost, __configData.serverPort, 13); - comWrite(__configData.serialCom - 1, buffer, strlen(buffer)); + snprintf(_scratch, SCRATCH_SIZE, "ATDT%s:%d%c", __configData.serverHost, __configData.serverPort, 13); + comWrite(__configData.serialCom - 1, _scratch, strlen(_scratch)); timerQuarterSecondsSet(t, 0); // Run as fast as we can so we don't miss any data. offset = 0; _timeoutCounter = 7 * 4; // Seven seconds. @@ -322,11 +321,11 @@ static void timWelcomeProgress(WidgetT *widget) { case S_WAIT_FOR_BANNER: // Process incoming bytes one at a time so we don't accidentally eat the first packet after the banner. - len = comRead(__configData.serialCom - 1, &buffer[offset], 1); + len = comRead(__configData.serialCom - 1, &_scratch[offset], 1); offset += len; - buffer[offset] = 0; + _scratch[offset] = 0; // ***TODO*** Should probably cleanly handle a full server here with some kind of SERVER_FULL packet. - if (strstr(buffer, "KPMPGSMKII\rOKAY\r") != NULL) { + if (strstr(_scratch, "KPMPGSMKII\rOKAY\r") != NULL) { // Connect! Start packet handler and negotiate encryption. netPacketHandlerStart(); packetEncryptionSetup(__packetThreadData); diff --git a/shared/game.c b/shared/game.c new file mode 100644 index 0000000..a6f838b --- /dev/null +++ b/shared/game.c @@ -0,0 +1,41 @@ +/* + * Kangaroo Punch MultiPlayer Game Server Mark II + * Copyright (C) 2020-2021 Scott Duensing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#include "game.h" + + +void gameClear(GameT *game) { + DEL(game->title); + DEL(game->publisher); + DEL(game->developer); + DEL(game->description); + DEL(game->releaseDate); + DEL(game->rating); + DEL(game->series); + DEL(game->origin); + DEL(game->shortName); + DEL(game->worksWith); + game->type = GAME_TYPE_UNKNOWN; + game->maxPlayers = 0; + game->joinable = 0; + game->screens = 0; + game->boxes = 0; + game->ROWID = 0; +} diff --git a/shared/game.h b/shared/game.h index 6d63bea..aad71f9 100644 --- a/shared/game.h +++ b/shared/game.h @@ -53,7 +53,11 @@ typedef struct GameS { // Data type in DAT file sent to client. uint8_t joinable; // 1 uint8_t screens; // 1 uint8_t boxes; // 1 + uint64_t ROWID; // Provided by SQLite. } GameT; +void gameClear(GameT *game); + + #endif // GAME_H diff --git a/shared/util.c b/shared/util.c index 0e7cfbb..5b433af 100644 --- a/shared/util.c +++ b/shared/util.c @@ -119,6 +119,43 @@ uint8_t utilFileExists(char *filename) { } +uint8_t utilFromFileReadByte(FILE *f, uint8_t *result) { + unsigned char c; + + // Get next byte. + c = fgetc(f); + // End of file? + if (feof(f)) return FAIL; + // Add to result. + *result = c; + return SUCCESS; +} + + +uint8_t utilFromFileReadString(FILE *f, char **result) { + unsigned char c; + uint16_t x = 0; + + // Something already in 'result'? + DEL(*result); + + while (1) { + // Get next byte. + c = fgetc(f); + // End of file? + if (feof(f)) return FAIL; + // Add to result. + _scratch[x++] = c; + _scratch[x] = 0; + // End of string? + if (c == 0) { + *result = strdup(_scratch); + return SUCCESS; + } + } +} + + void utilStringToLower(char *string) { uint16_t i; diff --git a/shared/util.h b/shared/util.h index 4735416..30b3e28 100644 --- a/shared/util.h +++ b/shared/util.h @@ -31,6 +31,8 @@ char *utilCreateString(char *format, ...); char *utilCreateStringVArgs(char *format, va_list args); void utilDie(const char *why, ...); uint8_t utilFileExists(char *filename); +uint8_t utilFromFileReadByte(FILE *f, uint8_t *result); +uint8_t utilFromFileReadString(FILE *f, char **result); void utilStringToLower(char *string); char **utilWrapText(char *text, uint16_t width);