313 lines
7.7 KiB
C
313 lines
7.7 KiB
C
/*
|
|
* 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 <https://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
* 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;
|
|
}
|