/* * 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 . * */ /* * To Do: * * - Replace any direct data manipulation from outside a class with methods to handle it * - More widget states: Ghosted (underway) * - Methods that can change the width of a widget (such as setTitle) need to repaint the parent window as well * - Metrics, colors, etc. should be defined in each widget and not in GUI * - Widgets should support a "changed" callback that can cancel the change * - Use LabelT in all widgets that have a label * - Find a light grey to replace white widget data areas * - No thumb in listbox scrollbar * - Layout container widgets! * - Fix variable names. something = local; _something = file global; __something = project global */ #include "stddclmr.h" #include "os.h" #include "vesa.h" #include "surface.h" #include "mouse.h" #include "keyboard.h" #include "image.h" #include "font.h" #include "gui.h" #include "config.h" #include "runtime.h" #include "comport.h" #include "network.h" #include "timer.h" #include "welcome.h" #include "settings.h" PacketThreadDataT *__packetThreadData = NULL; // Exported in os.h RuntimeDataT __runtimeData; // Exported in runtime.h static MouseT *_mouse = NULL; static ImageT *_pointer = NULL; static ColorT _alpha = 0; #ifndef __linux__ char *_logName = NULL; #endif static void checkSettings(void); static void eventLoop(void); static uint8_t hasValidSettings(void); static void shutdown(void); static uint8_t startup(int argc, char *argv[]); static void tableLoad(void); static void tableSave(void); static void checkSettings(void) { // Do we have a valid COM port? if (!hasValidSettings()) { logWrite("No compatible modem found. Cannot continue.\n"); guiStop(); return; } welcomeShow(); eventLoop(); } static void eventLoop(void) { // Main Event Loop. do { netProcess(); guiTimerProcess(rawclock()); _mouse = mouseRead(); if (keyHit()) { guiKeyboardProcess(keyASCIIGet(), keyExtendedGet(), keyScanCodeGet(), keyShiftGet(), keyControlGet(), keyAltGet()); //logWrite("Key '%d' Extended '%d' Scancode '%d' Shift '%d' Control '%d' Alt '%d'\n", keyASCIIGet(), keyExtended(), keyScanCode(), keyShift(), keyControl(), keyAlt()); if (keyASCIIGet() == 27) guiStop(); } guiMouseProcess(_mouse); guiComposite(); imageRenderWithAlpha(_pointer, _mouse->x, _mouse->y, _alpha); vbeVBlankWait(); vbePresent(); } while (!guiHasStopped()); shutdown(); } static uint8_t hasValidSettings(void) { // Returning false sends us immediately to the settings dialog. return (__configData.serialCom > 0 && __configData.serialCom < 5); } static void shutdown(void) { #ifndef __linux__ // On DOS, display the contets of the log now that we're back in text mode. FILE *in = NULL; #endif imageUnload(&_pointer); tableSave(); netShutdown(); guiShutdown(); mouseShutdown(); surfaceShutdown(); vbeShutdown(); cacheShutdown(); configShutdown(); osShutdown(); logClose(); memoryShutdown(); #ifndef __linux__ //***TODO*** Why the frack does this not work?! textmode(C80); // On DOS, display the contets of the log now that we're back in text mode. in = fopen(_logName, "r"); if (in) { while (!feof(in)) { putc(fgetc(in), stdout); } fclose(in); free(in); } free(_logName); _Exit(0); #endif } static uint8_t startup(int argc, char *argv[]) { memoryStartup(argv[0]); logOpenByHandle(memoryLogHandleGet()); osStartup(); configStartup(argv[0]); #ifndef __linux__ _logName = utilAppNameWithNewExtensionGet(argv[0], "log"); #endif // 0 1 2 3 4 5 6 7 8 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 logWrite("%s", "Kangaroo Punch MultiPlayer DOS Game Client Mark II\n"); logWrite("%s", "Copyright (C) 2020-2021 Scott Duensing scott@kangaroopunch.com\n\n"); if (argc > 1) { if (strcmp(argv[1], "/?") == 0) { vbeInfoShow(); configShutdown(); logClose(); memoryShutdown(); return 1; } } // Do we have the video mode they asked for? if (vbeStartup(__configData.videoWidth, __configData.videoHeight, __configData.videoDepth)) { configShutdown(); logClose(); memoryShutdown(); return 1; } cacheStartup(argv[0]); surfaceStartup(); mouseStartup(); guiStartup(); netStartup(); _pointer = imageLoad(cacheFilenameGet("gui:mouse.png")); _alpha = imagePixelGet(_pointer, 5, 0); tableLoad(); return 0; } static void tableLoad(void) { FILE *cache = NULL; char *line = NULL; char *p = NULL; char *temp = NULL; __runtimeData.integers = NULL; __runtimeData.strings = NULL; __runtimeData.protocolVersion = 0; sh_new_strdup(__runtimeData.integers); sh_new_strdup(__runtimeData.strings); // ***TODO*** Default initial tables line = (char *)malloc(4096); if (line) { // Load string cache. cache = cacheFOpen("data:strings.dat", "rt"); if (cache) { while (fscanf(cache, "%s\n", line) != EOF) { p = strstr(line, "="); if (p) { *p = 0; p++; // Do we have this string already? temp = shget(__runtimeData.strings, line); if (temp) { DEL(temp); shdel(__runtimeData.strings, line); } shput(__runtimeData.strings, line, strdup(p)); } } cacheFClose(cache); } // Load integer cache. cache = cacheFOpen("data:integers.dat", "rt"); if (cache) { while (fscanf(cache, "%s\n", line) != EOF) { p = strstr(line, "="); if (p) { *p = 0; p++; shput(__runtimeData.integers, line, atol(p)); } } cacheFClose(cache); } free(line); line = NULL; } } static void tableSave(void) { FILE *cache = NULL; // Save & free integer table. cache = cacheFOpen("data:integers.dat", "wt"); if (cache) { if (__runtimeData.integers) { while (shlen(__runtimeData.integers) > 0) { //logWrite("[%s]=[%d]\n", __runtimeData.integers[0].key, __runtimeData.integers[0].value); fprintf(cache, "%s=%ld\n", __runtimeData.integers[0].key, (long)__runtimeData.integers[0].value); shdel(__runtimeData.integers, __runtimeData.integers[0].key); } shfree(__runtimeData.integers); } cacheFClose(cache); } // Save & free string table. cache = cacheFOpen("data:strings.dat", "wt"); if (cache) { if (__runtimeData.strings) { while (shlen(__runtimeData.strings) > 0) { //logWrite("[%s]=[%s]\n", __runtimeData.strings[0].key, __runtimeData.strings[0].value); fprintf(cache, "%s=%s\n", __runtimeData.strings[0].key, __runtimeData.strings[0].value); DEL(__runtimeData.strings[0].value); shdel(__runtimeData.strings, __runtimeData.strings[0].key); } shfree(__runtimeData.strings); } cacheFClose(cache); } } extern void browserShow(void); int main(int argc, char *argv[]) { if (startup(argc, argv)) return 1; // Perform "first run" setup tasks or start the client? if (hasValidSettings()) { // We have what we need, start the client. //welcomeShow(); browserShow(); eventLoop(); } else { // Run the setup. settingsShow(checkSettings); } return 0; }