292 lines
8.2 KiB
C
292 lines
8.2 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 "task.h"
|
|
#include "image.h"
|
|
#include "font.h"
|
|
#include "timer.h"
|
|
#include "gui.h"
|
|
#include "config.h"
|
|
#include "runtime.h"
|
|
|
|
#include "welcome.h"
|
|
|
|
|
|
PacketThreadDataT *__packetThreadData = NULL; // Exported in os.h
|
|
RuntimeDataT __runtimeData; // Exported in runtime.h
|
|
|
|
|
|
static void taskComDebugLoop(void *data);
|
|
static void taskGuiEventLoop(void *data);
|
|
|
|
|
|
#include "comport.h"
|
|
static void taskComDebugLoop(void *data) {
|
|
int32_t r;
|
|
int32_t x;
|
|
char buffer[1024];
|
|
|
|
(void)data;
|
|
|
|
// Open COM port.
|
|
logWrite("Opening COM\n");
|
|
r = comOpen(__configData.serialCom - 1, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
|
|
if (r != SER_SUCCESS) {
|
|
logWrite("Unable to open COM port! Please check settings.\n");
|
|
guiStop();
|
|
return;
|
|
}
|
|
// Send a CR to clear anything in the modem.
|
|
logWrite("Clearing modem buffer\n");
|
|
snprintf(buffer, 1023, "%c", 13);
|
|
comWrite(__configData.serialCom - 1, buffer, strlen(buffer));
|
|
// Wait roughly a second for anything.
|
|
comWaitWithTimeout(__configData.serialCom - 1, buffer, 1023, 4, "weExpectNothing");
|
|
// Send actual init
|
|
logWrite("Init modem\n");
|
|
snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13);
|
|
comWrite(__configData.serialCom - 1, buffer, strlen(buffer));
|
|
// Wait roughly a second for "OK".
|
|
r = comWaitWithTimeout(__configData.serialCom - 1, buffer, 1023, 4, "OK");
|
|
if (r <= 0) {
|
|
comClose(__configData.serialCom - 1);
|
|
logWrite("Modem does not support ENET! Please check settings.\n");
|
|
guiStop();
|
|
return;
|
|
}
|
|
logWrite("Modem OK\n");
|
|
// Flush COM port.
|
|
timerQuarterSecondsWait(4);
|
|
comReceiveBufferFlush(__configData.serialCom - 1);
|
|
|
|
// Show dialing, dial service.
|
|
logWrite("Dialing\n");
|
|
snprintf(buffer, 1023, "ATDT%s:%d%c", __configData.serverHost, __configData.serverPort, 13);
|
|
comWrite(__configData.serialCom - 1, buffer, strlen(buffer));
|
|
// Wait 7 seconds for welcome banner.
|
|
r = comWaitWithTimeout(__configData.serialCom - 1, buffer, 1023, 4 * 7, "KPMPGSMKII\r");
|
|
if (r <= 0) {
|
|
comClose(__configData.serialCom - 1);
|
|
logWrite("Unable to connect to server! Please check settings or try later.\n");
|
|
guiStop();
|
|
return;
|
|
}
|
|
|
|
// Connected! Show icon and negotiate session.
|
|
logWrite("Connected\n");
|
|
|
|
packetEncryptionSetup(__packetThreadData);
|
|
|
|
PacketEncodeDataT encoded = { 0 };
|
|
PacketDecodeDataT decoded = { 0 };
|
|
|
|
// Send it 10 times, waiting for a PONG between each.
|
|
for (x=0; x<10; x++) {
|
|
// Send PING.
|
|
logWrite("Sending PING %d\n", x);
|
|
encoded.control = PACKET_CONTROL_DAT;
|
|
encoded.packetType = PACKET_TYPE_PING;
|
|
encoded.channel = 1;
|
|
encoded.encrypt = 0;
|
|
packetEncode(__packetThreadData, &encoded, NULL, 0); // Must encode each packet - no reusing encoded data.
|
|
packetSend(__packetThreadData, &encoded);
|
|
// Wait for PONG.
|
|
while (!guiHasStopped()) {
|
|
r = comRead(__configData.serialCom - 1, buffer, 1);
|
|
if (r == 1) {
|
|
if (packetDecode(__packetThreadData, &decoded, buffer, 1)) {
|
|
if (decoded.packetType == PACKET_TYPE_PONG) {
|
|
logWrite("Received PONG\n");
|
|
break;
|
|
} else {
|
|
logWrite("Unexpected packet type received %d\n", decoded.packetType);
|
|
}
|
|
}
|
|
} else {
|
|
taskYield();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (guiHasStopped()) return;
|
|
|
|
// Send LOGIN.
|
|
logWrite("Sending LOGIN\n");
|
|
PacketTypeLoginT loginData;
|
|
strcpy(loginData.user, "Encryption");
|
|
strcpy(loginData.pass, "Works!");
|
|
encoded.control = PACKET_CONTROL_DAT;
|
|
encoded.packetType = PACKET_TYPE_LOGIN;
|
|
encoded.channel = 1;
|
|
encoded.encrypt = 1;
|
|
packetEncode(__packetThreadData, &encoded, (char *)&loginData, sizeof(PacketTypeLoginT)); // Must encode each packet - no reusing encoded data.
|
|
packetSend(__packetThreadData, &encoded);
|
|
|
|
// Send CLIENT_SHUTDOWN.
|
|
logWrite("Sending CLIENT_SHUTDOWN\n");
|
|
encoded.control = PACKET_CONTROL_DAT;
|
|
encoded.packetType = PACKET_TYPE_CLIENT_SHUTDOWN;
|
|
encoded.channel = 1;
|
|
encoded.encrypt = 0;
|
|
packetEncode(__packetThreadData, &encoded, NULL, 0);
|
|
packetSend(__packetThreadData, &encoded);
|
|
|
|
logWrite("Sleeping\n");
|
|
timerQuarterSecondsWait(8);
|
|
|
|
logWrite("COM closed\n");
|
|
comClose(__configData.serialCom - 1);
|
|
guiStop();
|
|
}
|
|
|
|
|
|
static void taskGuiEventLoop(void *data) {
|
|
MouseT *mouse = NULL;
|
|
ImageT *pointer = NULL;
|
|
ColorT alpha = { 0 };
|
|
|
|
(void)data;
|
|
|
|
pointer = imageLoad("data/mouse.png");
|
|
alpha = imagePixelGet(pointer, 5, 0);
|
|
|
|
do {
|
|
timerUpdate();
|
|
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();
|
|
taskYield();
|
|
} while (!guiHasStopped());
|
|
|
|
imageUnload(&pointer);
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
#ifndef __linux__
|
|
// On DOS, display the contets of the log now that we're back in text mode.
|
|
char *logName = NULL;
|
|
FILE *in = NULL;
|
|
#endif
|
|
|
|
memoryStartup(argv[0]);
|
|
logOpenByHandle(memoryLogHandleGet());
|
|
configStartup(argv[0]);
|
|
|
|
// 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 0;
|
|
}
|
|
}
|
|
|
|
// Do we have the video mode they asked for?
|
|
if (vbeStartup(__configData.videoWidth, __configData.videoHeight, __configData.videoDepth)) {
|
|
configShutdown();
|
|
logClose();
|
|
memoryShutdown();
|
|
return 1;
|
|
}
|
|
|
|
surfaceStartup();
|
|
mouseStartup();
|
|
timerStartup();
|
|
guiStartup();
|
|
taskStartup();
|
|
|
|
__packetThreadData = packetThreadDataCreate(NULL);
|
|
packetSenderRegister(comPacketSender);
|
|
|
|
//taskCreate(taskComDebugLoop, NULL);
|
|
taskCreate(taskWelcome, NULL);
|
|
taskCreate(taskGuiEventLoop, NULL);
|
|
|
|
taskRun();
|
|
|
|
packetThreadDataDestroy(&__packetThreadData);
|
|
|
|
taskShutdown();
|
|
guiShutdown();
|
|
timerShutdown();
|
|
mouseShutdown();
|
|
surfaceShutdown();
|
|
vbeShutdown();
|
|
configShutdown();
|
|
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.
|
|
logName = utilAppNameWithNewExtensionGet(argv[0], "log");
|
|
in = fopen(logName, "r");
|
|
if (in) {
|
|
while (!feof(in)) {
|
|
putc(fgetc(in), stdout);
|
|
}
|
|
fclose(in);
|
|
free(in);
|
|
}
|
|
free(logName);
|
|
_Exit(0);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|