Completed conversion from task-based code to event-based. Needs testing but now runs on DOS!

This commit is contained in:
Scott Duensing 2022-01-31 19:11:58 -06:00
parent ecf6d1f842
commit 114dd36513
64 changed files with 1928 additions and 1216 deletions

View file

@ -33,10 +33,13 @@ BINDIR = bin
# CFLAGS, LDFLAGS, CPPFLAGS, PREFIX can be overriden on CLI
CFLAGS := $(DEBUG)
#CFLAGS += -DALLEGRONOTAVAIL -DALLEGRONOTPROGS -DDZCOMM_SRC
CFLAGS += -I$(SRCDIR)/client/src -I$(SRCDIR)/client/src/system -I$(SRCDIR)/client/src/dos -I$(SRCDIR)/client/src/gui -I$(SRCDIR)/client/src/thirdparty
CFLAGS += -I$(SRCDIR)/shared -I$(SRCDIR)/shared/thirdparty
#CFLAGS += -I$(SRCDIR)/client/src/thirdparty/dzcomm -I$(SRCDIR)/client/src/thirdparty/dzcomm/include
CPPFLAGS :=
LDFLAGS :=
#LDFLAGS += -L$(SRCDIR)/client/src/thirdparty/dzcomm -ldzcom
PREFIX := /usr/local
TARGET_ARCH :=
@ -61,6 +64,7 @@ DEP := $(OBJ:.o=.d)
BIN := $(BINDIR)/$(TARGET)
-include $(DEP)
#obj/client/src/thirdparty/dzcomm/src/dos/djirqs.o
#$(info [${SRC}])
#$(info [${OBJ}])

View file

@ -27,6 +27,7 @@ mkdir -p \
obj/client/src/system \
obj/client/src/dos \
obj/client/src/gui \
obj/client/src/embedded \
obj/client/src/thirdparty/serial \
obj/shared/thirdparty/memwatch \
obj/shared/thirdparty/blowfish-api \

View file

@ -79,8 +79,10 @@ function outputLicense() {
pushd font/data
createEmbeddedBinary vga8x14 dat ../../client/src/embedded
popd
pushd client/data
createEmbeddedBinary mouse png ../../client/src/embedded
popd

View file

@ -29,6 +29,9 @@ QMAKE_CFLAGS += -O0
DEFINES *= CLIENT
UNUSED_CRAP = \
src/thirdparty/dzcomm/include/dzcomm.h
DOS_HEADERS = \
src/thirdparty/serial/serial.h
@ -68,9 +71,10 @@ HEADERS = \
$$SHARED/packets.h \
src/config.h \
$$SHARED/util.h \
src/embedded/vga8x14.h \
src/firstrun.h \
src/embedded/embedded.h \
src/gui/msgbox.h \
src/gui/timer.h \
src/hangup.h \
src/login.h \
src/menu.h \
src/network.h \
@ -84,13 +88,13 @@ HEADERS = \
src/system/surface.h \
src/system/taglist.h \
src/system/keyboard.h \
src/system/task.h \
src/system/timer.h \
$$SHARED/array.h \
$$SHARED/log.h \
src/system/mouse.h \
src/system/vesa.h \
src/system/os.h \
src/embedded/vga8x14.h \
src/embedded/mouse.h \
src/gui/listbox.h \
src/gui/terminal.h \
src/gui/updown.h \
@ -117,16 +121,11 @@ SOURCES = \
$$SHARED/packet.c \
$$SHARED/thirdparty/tiny-AES-c/aes.c \
$$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.c \
src/config.c \
$$SHARED/memory.c \
src/embedded/embedded.c \
src/firstrun.c \
src/gui/msgbox.c \
src/login.c \
src/menu.c \
src/network.c \
src/settings.c \
src/signup.c \
src/gui/timer.c \
src/hangup.c \
src/system/comport.c \
src/system/os.c \
src/system/surface.c \
@ -134,8 +133,6 @@ SOURCES = \
$$SHARED/util.c \
$$SHARED/array.c \
$$SHARED/log.c \
src/system/timer.c \
src/system/task.c \
src/gui/listbox.c \
src/gui/terminal.c \
src/gui/updown.c \
@ -152,8 +149,14 @@ SOURCES = \
src/gui/button.c \
src/gui/checkbox.c \
src/gui/label.c \
src/config.c \
src/main.c \
src/welcome.c
src/welcome.c \
src/login.c \
src/menu.c \
src/signup.c \
src/network.c \
src/settings.c
LIBS = \
-lSDL2 \

View file

@ -19,4 +19,4 @@
#define EMBED_HERE
#include "vga8x14.h"
#include "embedded/embedded.h"

View file

@ -18,23 +18,12 @@
*/
#ifndef TASK_H
#define TASK_H
#ifndef EMBEDDED_H
#define EMBEDDED_H
#include "os.h"
#include "widget.h"
#include "mouse.h"
#include "vga8x14.h"
typedef void (*taskFunction)(void *data);
uint8_t taskCreate(void (*function)(void *), void *data);
void taskProxy(WidgetT *widget);
void taskRun(void);
void taskShutdown(void);
void taskStartup(void);
void taskYield(void);
#endif // TASK_H
#endif // EMBEDDED_H

457
client/src/embedded/mouse.h Normal file
View file

@ -0,0 +1,457 @@
/*
* 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/>.
*
*/
#ifndef MOUSE_PNG_H
#define MOUSE_PNG_H
// ===== THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT =====
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#ifdef EMBED_HERE
unsigned char mouse_png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18,
0x08, 0x06, 0x00, 0x00, 0x00, 0xf3, 0xa0, 0x7d, 0x0c, 0x00, 0x00, 0x10,
0x66, 0x7a, 0x54, 0x58, 0x74, 0x52, 0x61, 0x77, 0x20, 0x70, 0x72, 0x6f,
0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x78,
0x69, 0x66, 0x00, 0x00, 0x78, 0xda, 0xc5, 0x9a, 0x5b, 0x76, 0x1b, 0x39,
0x12, 0x44, 0xff, 0xb1, 0x8a, 0x59, 0x02, 0xde, 0x8f, 0xe5, 0xe0, 0x91,
0x38, 0xa7, 0x77, 0x30, 0xcb, 0x9f, 0x9b, 0xa8, 0x22, 0x2d, 0xca, 0x94,
0x65, 0xbb, 0x3f, 0xc6, 0x6c, 0x89, 0xa5, 0x62, 0x15, 0x0a, 0xc8, 0x8c,
0x8c, 0xc8, 0x00, 0xdb, 0xc8, 0x7f, 0xff, 0xd9, 0xe6, 0x3f, 0xfc, 0x4b,
0xd6, 0x66, 0x13, 0x53, 0xa9, 0xb9, 0xe5, 0x6c, 0xf9, 0x17, 0x5b, 0x6c,
0xbe, 0x73, 0x50, 0xed, 0xf5, 0xaf, 0x9f, 0xdf, 0xce, 0xc6, 0xf3, 0xfb,
0xfe, 0xc3, 0x3e, 0x0e, 0x5e, 0xce, 0x1b, 0xf7, 0xb8, 0xc9, 0x73, 0x2a,
0xf0, 0x1e, 0xae, 0x3f, 0x6b, 0xbe, 0xcf, 0x0b, 0xe7, 0x3d, 0xd7, 0xfb,
0xfb, 0xfc, 0xbc, 0xc7, 0xe9, 0x9c, 0x4f, 0x1f, 0x06, 0x6a, 0x72, 0x7f,
0x30, 0x5e, 0x3f, 0xe8, 0xf7, 0x40, 0xbe, 0xde, 0x0f, 0x78, 0x4c, 0xe5,
0x7e, 0x50, 0x70, 0xd7, 0x03, 0xec, 0xba, 0x07, 0xea, 0xf7, 0x40, 0xc1,
0xdf, 0x4f, 0x8e, 0xd7, 0xdf, 0xe3, 0x7e, 0x72, 0x6e, 0xb5, 0x7c, 0x5c,
0xc2, 0x7a, 0x2c, 0xad, 0xde, 0x67, 0xea, 0xf5, 0x63, 0xf4, 0x57, 0x0c,
0xc5, 0xe7, 0x94, 0x5d, 0x89, 0xfc, 0x8e, 0xde, 0x96, 0x92, 0x1b, 0xc7,
0xd5, 0xdb, 0x58, 0x88, 0xdb, 0xd2, 0x89, 0xee, 0xe9, 0x9b, 0xde, 0x97,
0xc6, 0x35, 0xce, 0xe7, 0xbf, 0xcd, 0xe3, 0x52, 0xcf, 0x9c, 0xbc, 0x04,
0x17, 0xec, 0xf9, 0x5d, 0xaf, 0x59, 0x06, 0xfd, 0x71, 0xa1, 0xeb, 0xf9,
0xf3, 0x9b, 0x50, 0xe9, 0xa7, 0x1c, 0x87, 0x73, 0x26, 0x84, 0x72, 0xe2,
0x6b, 0x0d, 0x29, 0x63, 0x0a, 0xcc, 0xbc, 0xdd, 0xb1, 0x15, 0xfb, 0x8c,
0xe6, 0x4b, 0x6c, 0x9e, 0xe9, 0x7a, 0xff, 0xcf, 0xfc, 0xce, 0xb2, 0x6e,
0x38, 0xbc, 0xa4, 0xbb, 0xf7, 0x57, 0x18, 0x98, 0x0f, 0x4f, 0x72, 0xef,
0x60, 0x90, 0xe5, 0x3e, 0x1f, 0x3e, 0x65, 0x2f, 0x3f, 0xdf, 0xcf, 0x79,
0xf3, 0xf9, 0x03, 0x97, 0xde, 0xa7, 0xfb, 0xe4, 0xf4, 0xc3, 0x8c, 0x4a,
0x7c, 0x3e, 0xd8, 0xbf, 0xcc, 0xc8, 0xc5, 0x07, 0xe4, 0x9e, 0xe9, 0x7d,
0xfe, 0xec, 0xbd, 0xea, 0xde, 0x72, 0xad, 0xae, 0xc7, 0xcc, 0x92, 0xf3,
0xbd, 0xa8, 0xc7, 0x4a, 0x9c, 0x39, 0xa9, 0xdc, 0x6b, 0x28, 0x08, 0xce,
0x6d, 0x99, 0x57, 0xe1, 0x27, 0x71, 0x5c, 0xce, 0xab, 0xf1, 0xaa, 0x94,
0xcb, 0x04, 0x63, 0xcb, 0x4e, 0x3b, 0x78, 0x4d, 0xd7, 0x9c, 0x27, 0x95,
0x9b, 0x09, 0x2c, 0xd7, 0xdd, 0x36, 0x4e, 0xce, 0xc1, 0x74, 0x93, 0x39,
0x46, 0x2f, 0xbe, 0xf0, 0xee, 0xfd, 0x24, 0xeb, 0x7a, 0xae, 0x92, 0x8b,
0xe6, 0x67, 0xd0, 0xa4, 0x47, 0x7d, 0xb9, 0xed, 0x4b, 0x68, 0x61, 0x01,
0x01, 0x1f, 0x26, 0x50, 0x09, 0x9c, 0xf5, 0x7b, 0x9b, 0x7b, 0x2e, 0xee,
0x3c, 0xb7, 0x9d, 0xe7, 0x4d, 0xea, 0x6f, 0xd9, 0xe5, 0xb8, 0xd4, 0x3b,
0x06, 0x73, 0xdc, 0xf2, 0xed, 0xcb, 0xfc, 0xce, 0x45, 0xbf, 0x7a, 0xed,
0xad, 0xb5, 0xe4, 0x9c, 0x79, 0xd4, 0x0c, 0xb8, 0x60, 0x5e, 0x5e, 0x03,
0xce, 0x34, 0x34, 0x73, 0xfa, 0x9b, 0xcb, 0xc8, 0x88, 0xdb, 0x77, 0x50,
0xd3, 0x09, 0xf0, 0xe3, 0xf5, 0x0a, 0xc8, 0x3b, 0xb1, 0x81, 0x14, 0xa6,
0x13, 0xe6, 0xca, 0x02, 0xbb, 0x1d, 0xd7, 0x10, 0x23, 0xb9, 0x1f, 0xd8,
0x0a, 0x27, 0xd1, 0x81, 0xeb, 0x12, 0xef, 0x57, 0x71, 0xbb, 0xb2, 0xae,
0xfb, 0x75, 0xa0, 0xc8, 0xb3, 0x13, 0x93, 0xa1, 0x92, 0xa2, 0xb3, 0xd9,
0x85, 0xe4, 0xb2, 0xb3, 0xc5, 0xfb, 0xe2, 0x1c, 0x81, 0xac, 0x24, 0xa8,
0x3b, 0x5b, 0x7d, 0x88, 0x7e, 0x90, 0x01, 0x97, 0x92, 0x5f, 0x4c, 0xd2,
0xc7, 0x10, 0x32, 0xb9, 0xa1, 0x08, 0x78, 0xb4, 0xe1, 0x9e, 0xe2, 0xce,
0xb5, 0x3e, 0xf9, 0xeb, 0x3c, 0x2c, 0x49, 0x26, 0x52, 0xc8, 0xa1, 0x90,
0x9b, 0x16, 0x3a, 0xc9, 0x8a, 0x31, 0x81, 0x9f, 0x12, 0x2b, 0x18, 0xea,
0x29, 0xa4, 0x98, 0x52, 0xca, 0xa9, 0xa4, 0x9a, 0x5a, 0xea, 0x39, 0xe4,
0x68, 0xa8, 0xb0, 0x9c, 0x4b, 0x56, 0xba, 0xed, 0x25, 0x94, 0x58, 0x52,
0xc9, 0xa5, 0x94, 0x5a, 0x5a, 0xe9, 0x35, 0xd4, 0x58, 0x53, 0xcd, 0xb5,
0xd4, 0x5a, 0x5b, 0xed, 0xcd, 0xb7, 0x00, 0x1b, 0xa7, 0x46, 0x39, 0xb6,
0xda, 0x5a, 0xeb, 0x9d, 0x67, 0x76, 0x46, 0xee, 0xd9, 0x74, 0xae, 0xef,
0x9c, 0x19, 0x7e, 0x84, 0x11, 0x47, 0x1a, 0x79, 0x94, 0x51, 0x47, 0x1b,
0x7d, 0x02, 0x9f, 0x19, 0x67, 0x9a, 0x79, 0x96, 0x59, 0x67, 0x9b, 0x7d,
0xf9, 0x15, 0x16, 0x75, 0xbc, 0xf2, 0x2a, 0xab, 0xae, 0xb6, 0xba, 0x38,
0x01, 0x4a, 0x12, 0x25, 0x19, 0xc9, 0x52, 0xa4, 0x4a, 0x93, 0xbe, 0xc1,
0xda, 0x0e, 0x3b, 0xee, 0xb4, 0xf3, 0x2e, 0xbb, 0xee, 0xb6, 0xfb, 0x33,
0x6b, 0xee, 0x2e, 0xdb, 0xcf, 0xaf, 0x3f, 0xc8, 0x9a, 0xbb, 0xb3, 0xe6,
0x4f, 0xa6, 0xf4, 0xba, 0xf2, 0xcc, 0x1a, 0x67, 0x4b, 0xb9, 0xde, 0xcd,
0xc1, 0x0b, 0x83, 0x68, 0xce, 0xc8, 0x98, 0x8f, 0x8e, 0x8c, 0x17, 0xcd,
0x00, 0x80, 0xf6, 0x9a, 0x33, 0x5b, 0x5d, 0x8c, 0x5e, 0x33, 0xa7, 0x39,
0xb3, 0xcd, 0x53, 0x15, 0xc9, 0x33, 0xc9, 0xa4, 0xb9, 0x59, 0xce, 0x76,
0x97, 0x7d, 0x34, 0x21, 0x8a, 0xf3, 0x69, 0xbb, 0x67, 0xee, 0x7e, 0x64,
0xee, 0x8f, 0xf2, 0x66, 0x72, 0xfc, 0x65, 0xde, 0xfc, 0xef, 0x66, 0xce,
0x68, 0xea, 0xfe, 0x65, 0xe6, 0x4e, 0xde, 0x8c, 0xa4, 0x0f, 0x79, 0x7b,
0x93, 0xb5, 0xa5, 0xdc, 0x3c, 0x4f, 0xc6, 0xae, 0x2a, 0xd4, 0x98, 0xda,
0x40, 0xf5, 0xf1, 0xb9, 0xf0, 0xd8, 0xb8, 0xf5, 0xb8, 0x9a, 0x5d, 0xf2,
0xde, 0x65, 0xec, 0x6e, 0xfb, 0x5c, 0xbd, 0x89, 0x1b, 0xbd, 0x10, 0xe0,
0xde, 0x6b, 0x02, 0xfa, 0x73, 0x87, 0x24, 0x33, 0xc7, 0x54, 0x57, 0x4f,
0xd5, 0xcf, 0xd4, 0xfb, 0xd2, 0x09, 0x13, 0xef, 0x3e, 0x1c, 0xc1, 0x5c,
0x84, 0x75, 0x11, 0xae, 0x68, 0x58, 0x48, 0x2f, 0x4d, 0x92, 0xef, 0x4a,
0x80, 0x76, 0x34, 0xf1, 0x7d, 0xad, 0x22, 0x6d, 0x71, 0x5f, 0x5e, 0xe7,
0x67, 0xe7, 0x15, 0x4b, 0x0e, 0xb5, 0x27, 0x52, 0x52, 0x72, 0x76, 0x31,
0xf1, 0x5f, 0x49, 0xcd, 0x5f, 0x47, 0x4a, 0xd4, 0xe6, 0x71, 0xf0, 0x67,
0xef, 0xd9, 0xe9, 0xbb, 0x4b, 0xbb, 0x16, 0x27, 0x0d, 0xc2, 0xec, 0x66,
0xce, 0x01, 0xa1, 0xa7, 0x56, 0xe1, 0xfe, 0x2e, 0x3c, 0x75, 0x14, 0xe2,
0x02, 0x1a, 0x76, 0x49, 0xba, 0x7a, 0xef, 0xb6, 0x84, 0xd4, 0x06, 0x33,
0x18, 0x8e, 0x49, 0x6e, 0xe6, 0x54, 0x7d, 0xd7, 0x05, 0xd7, 0x91, 0xf2,
0x86, 0x02, 0x5a, 0xf2, 0x75, 0x9a, 0xb6, 0x56, 0x1b, 0xe3, 0x9a, 0xab,
0x0c, 0x0f, 0x4e, 0xcf, 0xb3, 0xe2, 0x9f, 0xbe, 0x9b, 0xe7, 0x09, 0x57,
0x53, 0x22, 0x65, 0x5b, 0xa6, 0x84, 0xbd, 0x7d, 0x24, 0xcc, 0xc8, 0xcb,
0x20, 0x07, 0x4d, 0x67, 0x06, 0x5a, 0x7c, 0xdf, 0xad, 0xfa, 0x21, 0xe7,
0xef, 0xd5, 0x66, 0xd9, 0x12, 0x9b, 0x64, 0x24, 0x84, 0xbf, 0x0d, 0xab,
0x6d, 0xdc, 0x18, 0x15, 0xa9, 0xd7, 0x8a, 0x6b, 0x91, 0xe5, 0xd6, 0x59,
0x16, 0xa3, 0x31, 0x34, 0x47, 0x3a, 0x5e, 0xd9, 0x9b, 0xb1, 0xd2, 0x3d,
0x9a, 0x94, 0xed, 0x7c, 0xa9, 0x69, 0xc4, 0xbc, 0x49, 0x40, 0x33, 0xdc,
0x53, 0xf3, 0x68, 0xb9, 0xec, 0x3c, 0x46, 0xaa, 0x92, 0x28, 0x31, 0xd2,
0x08, 0x17, 0x88, 0x9b, 0x5a, 0xad, 0x13, 0x76, 0x2c, 0x34, 0x22, 0x7b,
0xca, 0x68, 0x0c, 0x06, 0x2c, 0xd2, 0xb6, 0x00, 0x4e, 0x6a, 0x12, 0x7d,
0xc8, 0x6c, 0x6b, 0xd4, 0x6d, 0x08, 0x65, 0x63, 0x5d, 0xdb, 0xdb, 0x94,
0x47, 0x62, 0xd6, 0xb3, 0x74, 0x5f, 0x58, 0x1d, 0xf7, 0xf9, 0xdc, 0x53,
0x1c, 0x54, 0x41, 0x88, 0x00, 0x8b, 0x21, 0xdc, 0x52, 0xe5, 0x2c, 0x5c,
0x67, 0x25, 0xf3, 0x91, 0x87, 0x22, 0xa6, 0x42, 0x2b, 0x2e, 0x88, 0xcd,
0x65, 0xf0, 0x59, 0x4a, 0xdc, 0x7d, 0xa4, 0x55, 0xa7, 0x00, 0xa8, 0xb9,
0x52, 0xa3, 0xd6, 0x59, 0xad, 0xa3, 0x68, 0x6a, 0xcb, 0x64, 0xb5, 0x8f,
0x41, 0x5d, 0xae, 0xb9, 0xe1, 0x87, 0xd2, 0xc7, 0x8e, 0x7d, 0x0e, 0x28,
0x2c, 0x6e, 0x07, 0xc8, 0xd6, 0x30, 0xc9, 0x47, 0xca, 0x87, 0x21, 0x98,
0x65, 0x9e, 0xe2, 0x1b, 0x85, 0x95, 0x56, 0xab, 0x17, 0x4e, 0x56, 0x8f,
0xf5, 0xff, 0x9f, 0xb5, 0x26, 0xf3, 0x01, 0xe0, 0x32, 0xa7, 0x5e, 0xc5,
0xd0, 0x42, 0xbf, 0xa0, 0xc3, 0xd9, 0x06, 0xa1, 0xe8, 0x11, 0xa3, 0x64,
0x7d, 0x07, 0xad, 0x94, 0xfd, 0x16, 0xe3, 0xdb, 0xb6, 0x6b, 0x49, 0xa9,
0xb1, 0xcc, 0x08, 0x0d, 0x75, 0x32, 0x3f, 0x1b, 0xbd, 0x7b, 0x21, 0xf8,
0x23, 0x14, 0xba, 0xdb, 0x19, 0x39, 0x39, 0x2b, 0xb8, 0xb7, 0xb1, 0x6a,
0x06, 0xad, 0xac, 0xb4, 0x4b, 0x58, 0x30, 0x8b, 0xdb, 0x6e, 0xe8, 0xcc,
0xba, 0xd1, 0xac, 0xeb, 0xc8, 0xf9, 0xa4, 0x72, 0x77, 0x0d, 0x1e, 0xcf,
0xb3, 0x8b, 0x12, 0xf7, 0xd3, 0x79, 0x35, 0x05, 0x91, 0x05, 0x55, 0x2d,
0xe6, 0xbd, 0x73, 0x8d, 0x69, 0x53, 0xd4, 0x7b, 0x32, 0xb1, 0xba, 0x72,
0x5e, 0x4e, 0xab, 0xc5, 0x0e, 0x13, 0xd6, 0x4c, 0x62, 0x7b, 0xa3, 0x92,
0xba, 0x87, 0x22, 0x68, 0x80, 0x24, 0xc5, 0x1e, 0x60, 0xf5, 0x9c, 0x41,
0xe6, 0x29, 0x4d, 0xe2, 0x34, 0xbf, 0x29, 0x64, 0xf3, 0xb6, 0xb2, 0xcb,
0x0a, 0x07, 0xcf, 0x81, 0x46, 0x6d, 0xb6, 0x30, 0x57, 0x04, 0x7f, 0xd3,
0x53, 0x8a, 0xc0, 0x10, 0x36, 0x1d, 0x92, 0x6d, 0xdf, 0x9d, 0x60, 0xe5,
0x72, 0x42, 0xdd, 0xbc, 0x01, 0xc4, 0x4c, 0x72, 0x55, 0x5a, 0x5a, 0xe8,
0x10, 0x76, 0xa0, 0x76, 0x1d, 0xa0, 0xcc, 0x65, 0x7c, 0x4e, 0xb4, 0x93,
0x6b, 0x78, 0x42, 0x79, 0x0d, 0x1f, 0xf6, 0x19, 0xfe, 0xca, 0x1a, 0x4f,
0x68, 0xf9, 0x7a, 0xc2, 0x68, 0x00, 0x15, 0x8e, 0x64, 0xdd, 0x03, 0x2c,
0x75, 0x74, 0x20, 0xbb, 0x2e, 0xc0, 0x1d, 0x62, 0x5e, 0x99, 0x0a, 0x00,
0xc6, 0xe4, 0x7b, 0x4c, 0x94, 0x41, 0xbb, 0x44, 0x18, 0x32, 0x3a, 0xa9,
0xe0, 0x20, 0x74, 0x38, 0xfb, 0x24, 0xd1, 0x91, 0x26, 0x78, 0xfe, 0xa4,
0xd8, 0x95, 0x13, 0x7e, 0x5f, 0xb2, 0x4e, 0x81, 0xf2, 0x53, 0x1c, 0x54,
0x97, 0xfa, 0xa2, 0x22, 0xa9, 0xc1, 0xda, 0x20, 0x74, 0xee, 0x9d, 0xad,
0x43, 0x45, 0x92, 0x73, 0x5d, 0x08, 0x24, 0xeb, 0x75, 0xa8, 0x15, 0xa2,
0x96, 0x78, 0x6a, 0x0c, 0x8d, 0xcf, 0x14, 0xfb, 0x94, 0xee, 0x48, 0x28,
0x1b, 0x48, 0x57, 0xe5, 0x58, 0x2b, 0x48, 0x5f, 0xf0, 0x2d, 0x5c, 0x6d,
0x4b, 0x20, 0x10, 0x79, 0x12, 0x06, 0x7e, 0x8b, 0x78, 0xb4, 0x29, 0x1b,
0xcf, 0xac, 0xa9, 0x2b, 0x50, 0x61, 0x41, 0x56, 0xdf, 0xcb, 0x6b, 0x29,
0x12, 0xed, 0x59, 0x92, 0x53, 0xb2, 0x6e, 0x21, 0x0e, 0xa4, 0x87, 0xb0,
0x50, 0x77, 0x95, 0xd2, 0xfc, 0x48, 0xdb, 0xf9, 0x49, 0xdb, 0xe6, 0x57,
0xb4, 0x7c, 0x92, 0x77, 0x52, 0xa7, 0x64, 0xf1, 0xab, 0xe4, 0x69, 0x89,
0x68, 0xfe, 0x9a, 0x7f, 0x49, 0x1e, 0x95, 0xf4, 0xcb, 0xf4, 0x3d, 0xd3,
0xb8, 0x03, 0xa5, 0x32, 0x03, 0x8f, 0xaa, 0x66, 0x2a, 0x43, 0xf9, 0xa4,
0x95, 0x77, 0x58, 0xb1, 0x9d, 0x40, 0xd7, 0x95, 0x0a, 0x47, 0xac, 0x64,
0x86, 0x82, 0x5a, 0x39, 0x4a, 0xc1, 0x51, 0x49, 0x95, 0x25, 0xd2, 0x67,
0xf8, 0xb4, 0x52, 0x97, 0xb9, 0x64, 0xa3, 0x97, 0x9e, 0x93, 0xde, 0x9b,
0x51, 0xa9, 0x03, 0xab, 0x49, 0x0c, 0x83, 0xb5, 0x4c, 0x74, 0x16, 0x8b,
0x84, 0x9a, 0xe9, 0x3c, 0x07, 0x79, 0x57, 0x5b, 0x70, 0x06, 0x17, 0x16,
0xa7, 0x0e, 0x64, 0x86, 0xd4, 0x7f, 0xd6, 0x1e, 0xf3, 0x77, 0xe2, 0xf3,
0xb3, 0xf6, 0x98, 0x6f, 0x68, 0xeb, 0xb7, 0x59, 0xca, 0xbc, 0xa7, 0xa9,
0x5f, 0xb2, 0xd4, 0xdb, 0x77, 0xa3, 0xb0, 0x55, 0x0f, 0x75, 0x14, 0xe8,
0xd6, 0x1f, 0xe8, 0xe4, 0xd6, 0x9f, 0xf3, 0xcc, 0xaf, 0x14, 0xe8, 0x45,
0x80, 0xcc, 0xef, 0x28, 0x10, 0x59, 0x7c, 0xd5, 0xa0, 0x4b, 0x81, 0x0e,
0x3f, 0x3e, 0x24, 0xc8, 0x5c, 0x1a, 0x04, 0xe0, 0xfe, 0x4e, 0x85, 0x9e,
0x22, 0x64, 0xfe, 0xa5, 0x0a, 0x3d, 0x45, 0xc8, 0xe8, 0x6c, 0x7e, 0x4f,
0x87, 0x1e, 0x09, 0x64, 0x41, 0xf3, 0x62, 0xa6, 0x47, 0x12, 0x55, 0xd2,
0xcd, 0xc9, 0xe3, 0xab, 0xd6, 0xbc, 0xa6, 0xf0, 0x4e, 0x20, 0xde, 0xe7,
0x97, 0x29, 0x34, 0x5f, 0xe5, 0xf4, 0x56, 0x22, 0xfb, 0xd4, 0xa2, 0x87,
0x12, 0x5d, 0x3a, 0xf4, 0x50, 0xa1, 0xa7, 0x08, 0x99, 0xbf, 0x52, 0x21,
0xd8, 0x95, 0x62, 0x98, 0x64, 0x87, 0x10, 0x45, 0x1d, 0x2e, 0x1b, 0x6e,
0x6a, 0x99, 0xbc, 0xef, 0x95, 0xb2, 0x28, 0xb5, 0x6d, 0x8f, 0x69, 0x82,
0x9c, 0x74, 0x53, 0x8a, 0x43, 0x6f, 0x29, 0x46, 0xcc, 0x31, 0x0e, 0x17,
0x63, 0x56, 0xb9, 0xbb, 0xda, 0x30, 0x07, 0x6c, 0x99, 0xe9, 0x4e, 0x21,
0xc1, 0x89, 0xe5, 0x48, 0xc5, 0x99, 0x99, 0xd2, 0x8c, 0x03, 0xfa, 0x5c,
0x64, 0x93, 0x18, 0x45, 0x02, 0x14, 0x5d, 0x1c, 0x08, 0x14, 0x68, 0x83,
0x35, 0xe9, 0x5a, 0x17, 0x9c, 0x4b, 0xaa, 0x71, 0x84, 0x30, 0x3d, 0xfe,
0x60, 0xe2, 0xc2, 0x75, 0xea, 0x20, 0x8f, 0xb9, 0x4c, 0xdd, 0x92, 0x49,
0x06, 0x4b, 0x8b, 0x66, 0x61, 0x16, 0xa9, 0xcb, 0x11, 0x3a, 0xd5, 0x4c,
0x66, 0x9b, 0x96, 0x21, 0x4b, 0x01, 0xca, 0x7d, 0x43, 0x12, 0x73, 0xca,
0x76, 0x98, 0x85, 0xc4, 0xdc, 0x56, 0x50, 0x34, 0x2b, 0x25, 0x8c, 0x05,
0x9a, 0x4a, 0x94, 0x80, 0x1e, 0x36, 0xda, 0x63, 0xb2, 0x51, 0xa4, 0xcc,
0x53, 0xfd, 0x61, 0x25, 0xd0, 0xbb, 0xbb, 0xa3, 0x6d, 0xcf, 0x76, 0x82,
0x78, 0x7c, 0xaa, 0x74, 0x0f, 0x7e, 0x00, 0xe6, 0xb1, 0x18, 0x68, 0x2d,
0x59, 0x8c, 0x10, 0x62, 0x6a, 0xd8, 0x99, 0xda, 0x7d, 0xa5, 0xd3, 0x8e,
0xe6, 0xdf, 0xc9, 0xe2, 0x0f, 0x62, 0x35, 0xdf, 0xca, 0xe2, 0x77, 0xef,
0xb7, 0x6c, 0x9a, 0xf7, 0xba, 0xf9, 0xe7, 0xb2, 0x69, 0xde, 0xeb, 0xe6,
0x3e, 0x4f, 0x71, 0xb9, 0x4c, 0x6f, 0x31, 0xe6, 0x19, 0x2c, 0x83, 0xbb,
0xe2, 0x79, 0xd4, 0x8e, 0x7e, 0x7b, 0x51, 0x91, 0x8b, 0x9b, 0x7a, 0x44,
0x4e, 0xf7, 0x48, 0x53, 0x4c, 0xc9, 0x98, 0x29, 0xc4, 0x2e, 0x8a, 0x1d,
0x62, 0x05, 0xbb, 0xb8, 0x32, 0x48, 0x91, 0x44, 0x08, 0x49, 0x23, 0x4a,
0xbb, 0x63, 0x44, 0xe8, 0x76, 0x03, 0x63, 0x2b, 0x82, 0x8a, 0x10, 0x62,
0x46, 0x4e, 0xa1, 0x15, 0x7c, 0x1a, 0xc6, 0xa9, 0x43, 0x47, 0x1e, 0x1c,
0x31, 0xaf, 0x4c, 0x09, 0xa1, 0xb0, 0x58, 0x1f, 0xd8, 0x5a, 0xfc, 0xc2,
0x02, 0x0a, 0x45, 0xa7, 0x18, 0x77, 0x6d, 0x25, 0x3c, 0x24, 0x56, 0x0e,
0x6c, 0xd6, 0xde, 0x03, 0x9e, 0xd0, 0x21, 0xc5, 0x81, 0xa8, 0xe6, 0x59,
0x17, 0x26, 0x08, 0x4e, 0xdf, 0xa9, 0x40, 0xb5, 0xa9, 0xc1, 0x43, 0xd8,
0xb5, 0xd0, 0xeb, 0x1e, 0xb9, 0xc7, 0xd6, 0xd5, 0x48, 0x8d, 0x2d, 0x4a,
0xc0, 0x29, 0x54, 0x2c, 0xe0, 0x08, 0x56, 0xb3, 0xec, 0xe1, 0xfb, 0xc6,
0xe1, 0xbb, 0xd2, 0x36, 0xaf, 0xb5, 0x1d, 0xec, 0xf7, 0x20, 0xd8, 0xf0,
0xe2, 0x0a, 0x01, 0x1b, 0x76, 0x30, 0xa4, 0x9b, 0xa7, 0xbc, 0x9b, 0xc7,
0xc1, 0xfd, 0x3e, 0x9c, 0x6c, 0x92, 0xa3, 0x06, 0x70, 0x05, 0xa2, 0x1a,
0x61, 0x38, 0x3a, 0x10, 0x9b, 0x5b, 0xc2, 0xc4, 0x26, 0x72, 0x8d, 0x64,
0x86, 0x25, 0xb3, 0xe0, 0x10, 0x25, 0x5a, 0xaf, 0x98, 0x15, 0x5c, 0xb3,
0x81, 0x9d, 0xb7, 0x6e, 0x39, 0x2e, 0x1d, 0xa5, 0x5d, 0xb6, 0x32, 0xca,
0x56, 0x0e, 0xd1, 0x79, 0x62, 0x20, 0xaf, 0x2e, 0xb6, 0x06, 0xa7, 0x07,
0x1a, 0xa6, 0x2d, 0x8e, 0xd1, 0xb9, 0x6f, 0x2f, 0xbb, 0x8a, 0x2e, 0x4c,
0xec, 0xa4, 0x3d, 0x3e, 0xb8, 0xf1, 0x9d, 0x54, 0x61, 0x47, 0xff, 0x7a,
0x30, 0xa3, 0xa3, 0x7d, 0x1a, 0x4c, 0x49, 0xd9, 0x4b, 0x1b, 0x54, 0x67,
0x10, 0x58, 0x17, 0x82, 0x1d, 0x83, 0x1a, 0xa3, 0xcf, 0x1a, 0x6b, 0xf8,
0xd6, 0x97, 0xd0, 0x37, 0xe9, 0x86, 0x05, 0x39, 0xb5, 0x58, 0x7a, 0x60,
0xd8, 0x0c, 0xce, 0x97, 0x1a, 0xed, 0xa7, 0x37, 0x69, 0x6b, 0x57, 0xc5,
0x37, 0xfc, 0xb1, 0xec, 0xbe, 0xd8, 0xfc, 0x6a, 0xd4, 0xa9, 0xfd, 0x78,
0x98, 0xac, 0xc8, 0xf5, 0x37, 0xb7, 0xa0, 0xdf, 0xa4, 0xc3, 0xd1, 0x34,
0x9c, 0x12, 0x81, 0x8f, 0x54, 0x22, 0x9f, 0xed, 0xc9, 0xdf, 0x76, 0x27,
0xe6, 0x73, 0x7b, 0xf2, 0xa9, 0x3b, 0x39, 0x32, 0xf8, 0xcd, 0x5c, 0xe9,
0x5f, 0x66, 0x61, 0x46, 0x7b, 0xd0, 0x95, 0xdd, 0xcc, 0x7b, 0x11, 0x6f,
0x29, 0x36, 0xad, 0x85, 0xbe, 0x90, 0x57, 0x3a, 0x4e, 0xa2, 0x11, 0x6b,
0x5d, 0xb5, 0x7a, 0xfa, 0x2a, 0x48, 0xea, 0x23, 0xe9, 0x56, 0x41, 0x36,
0x5b, 0x26, 0x46, 0x00, 0xc5, 0xea, 0x16, 0x0d, 0xc0, 0x80, 0x79, 0x3d,
0xca, 0x54, 0x0a, 0xab, 0xed, 0xda, 0xc5, 0xa1, 0xb0, 0x09, 0x6a, 0x26,
0xe2, 0xdf, 0xf3, 0xa6, 0x79, 0x4f, 0x9c, 0x5f, 0xf1, 0x66, 0x69, 0x47,
0x3e, 0x76, 0x3a, 0x42, 0x09, 0xd5, 0xc3, 0x63, 0xc4, 0x8e, 0x2a, 0x35,
0xa7, 0x53, 0x90, 0x1d, 0xe9, 0xa8, 0xa0, 0xfe, 0x99, 0xc3, 0x1f, 0xb5,
0xa0, 0x3f, 0x3a, 0x50, 0xf3, 0xa6, 0x05, 0xa5, 0x35, 0xe9, 0xf1, 0x2d,
0x55, 0xa6, 0xcb, 0xa3, 0xb1, 0x32, 0xaa, 0xb9, 0xcf, 0xad, 0xde, 0xcc,
0x0d, 0x08, 0x61, 0x33, 0x23, 0x64, 0x72, 0x35, 0x2f, 0x1d, 0xb2, 0x71,
0x1e, 0x2a, 0xdb, 0xbe, 0x79, 0x16, 0xe9, 0xaa, 0x44, 0x1f, 0xb3, 0xee,
0x3b, 0x2e, 0x5d, 0x25, 0xc2, 0xea, 0x14, 0xb7, 0x40, 0x53, 0xfc, 0x01,
0x30, 0x3e, 0x2a, 0x5c, 0xcc, 0x4d, 0x4f, 0xb8, 0x8d, 0x7e, 0x9f, 0x90,
0x45, 0xa9, 0x6c, 0x6c, 0x22, 0xcc, 0x7b, 0xc8, 0xd7, 0xa2, 0xd0, 0x34,
0x1e, 0x25, 0x6b, 0x5d, 0x85, 0xa2, 0x3c, 0xc3, 0x15, 0x42, 0x63, 0xb4,
0xd0, 0x6a, 0x97, 0x01, 0x84, 0xaa, 0x74, 0x9f, 0xda, 0xd0, 0x64, 0xd3,
0x57, 0x0f, 0x65, 0x75, 0xd2, 0x45, 0x93, 0x22, 0x39, 0x8e, 0x9d, 0x7b,
0x6b, 0xa8, 0xce, 0x22, 0x75, 0x81, 0x60, 0xaa, 0x0b, 0xd4, 0xef, 0x6b,
0x4e, 0x3f, 0xa0, 0x1d, 0x3f, 0x72, 0xce, 0x01, 0xe8, 0x04, 0xe6, 0x78,
0x39, 0x80, 0x50, 0x43, 0x9e, 0x86, 0xfe, 0x2b, 0x86, 0xa5, 0x71, 0x86,
0x25, 0x68, 0xb1, 0x00, 0x0d, 0x04, 0xcb, 0xc8, 0xf0, 0x94, 0xaf, 0x70,
0xbb, 0x6d, 0x54, 0x6a, 0xf6, 0xa1, 0xc3, 0x7b, 0xb3, 0x8f, 0x09, 0x56,
0xb5, 0x21, 0x1c, 0x89, 0x5b, 0x74, 0xef, 0x49, 0xb3, 0x3a, 0xcf, 0xd2,
0x52, 0xa0, 0x63, 0xaa, 0x72, 0x0a, 0x42, 0xc8, 0xaf, 0x74, 0xf4, 0x03,
0xfe, 0x62, 0x4a, 0x93, 0xb5, 0x85, 0x19, 0x84, 0x16, 0x04, 0xef, 0xd9,
0x6a, 0x59, 0xd9, 0x7b, 0xa8, 0x5b, 0x9d, 0xd2, 0xce, 0x61, 0x9c, 0xcc,
0x35, 0x80, 0xd5, 0x9b, 0xe9, 0xe1, 0x1a, 0x98, 0x58, 0xe9, 0xc0, 0x3a,
0xea, 0xee, 0x1a, 0xea, 0x4d, 0xaf, 0x52, 0xd6, 0xe5, 0x74, 0x9b, 0xa3,
0x4c, 0x27, 0xba, 0xd3, 0x3e, 0x4c, 0xe5, 0xc3, 0x1d, 0xcc, 0xc3, 0x30,
0x91, 0x7b, 0x1a, 0x00, 0x27, 0xc5, 0xa0, 0xed, 0x0d, 0x6d, 0xe7, 0xb8,
0x42, 0xec, 0x49, 0x50, 0xaa, 0x28, 0x43, 0x88, 0x48, 0xc1, 0x3d, 0xf1,
0xe7, 0xf5, 0xc3, 0xad, 0x53, 0xd2, 0x13, 0xf5, 0x32, 0x8b, 0x89, 0x72,
0x9a, 0x68, 0x8c, 0x4d, 0x55, 0xef, 0xcb, 0xf4, 0x49, 0x8c, 0xa4, 0x51,
0xf7, 0x34, 0xb3, 0xca, 0xd2, 0xcb, 0x2d, 0xe7, 0x8e, 0x6b, 0x5d, 0xd7,
0xaa, 0xa0, 0xb9, 0x85, 0x39, 0x7e, 0x8d, 0xc3, 0x33, 0x0c, 0x7f, 0x8a,
0x6f, 0xf3, 0x95, 0xc5, 0x42, 0xee, 0xc6, 0xc7, 0x56, 0xf1, 0xd1, 0xe8,
0xd5, 0x45, 0xd2, 0xc7, 0x49, 0x7a, 0x15, 0x4a, 0x8b, 0x85, 0x0c, 0xaa,
0x93, 0x26, 0x62, 0x68, 0x7b, 0xdc, 0xc6, 0x42, 0x64, 0x71, 0xfb, 0x4f,
0x4e, 0x0a, 0x9e, 0x5a, 0xd5, 0xc4, 0x77, 0xf9, 0x82, 0xee, 0x9f, 0x04,
0x3d, 0x04, 0x6f, 0x60, 0xea, 0x58, 0xf4, 0x5e, 0x24, 0x8a, 0xf2, 0x41,
0xad, 0xf3, 0x86, 0x00, 0x9a, 0xf8, 0x31, 0x55, 0x0b, 0x91, 0xd2, 0x16,
0x60, 0x86, 0xda, 0x94, 0x12, 0xb9, 0x17, 0x17, 0xdd, 0x8a, 0x57, 0x65,
0xf7, 0x78, 0x5c, 0x6c, 0xac, 0x8b, 0x72, 0x7a, 0x26, 0xfc, 0x1a, 0xed,
0x2a, 0x2e, 0x0a, 0x0e, 0xda, 0x14, 0x9a, 0xf8, 0x29, 0x95, 0x2a, 0x21,
0x71, 0x40, 0x5e, 0x5a, 0xe9, 0xf4, 0x1f, 0x18, 0x01, 0xa2, 0xcc, 0xe2,
0x7a, 0x82, 0x8e, 0xd3, 0x42, 0xfa, 0x3b, 0xde, 0x00, 0x8c, 0x8a, 0xcd,
0x6a, 0x98, 0xdb, 0x1c, 0xd5, 0xc8, 0x82, 0xe3, 0x90, 0xbd, 0x28, 0xc8,
0x04, 0x56, 0x81, 0xde, 0xbf, 0x51, 0x40, 0xc0, 0xb9, 0xe7, 0x45, 0x17,
0xef, 0x93, 0x55, 0x0b, 0x0c, 0xfd, 0x21, 0x54, 0x44, 0xf2, 0xb4, 0xf3,
0xfe, 0x67, 0x23, 0x64, 0xbe, 0x70, 0x42, 0x20, 0x1b, 0x9c, 0x20, 0xa2,
0x9c, 0x81, 0x2e, 0x5c, 0x56, 0x4f, 0x19, 0x51, 0x5f, 0x21, 0xc2, 0xbd,
0x30, 0x2d, 0xd1, 0x15, 0xd1, 0x20, 0x39, 0x44, 0xb8, 0xfa, 0x6d, 0x2e,
0x43, 0xa8, 0x1b, 0x43, 0x08, 0x13, 0x1d, 0x2b, 0x9e, 0x91, 0x16, 0xa0,
0xab, 0xf6, 0x00, 0xfe, 0x7b, 0xd7, 0xc8, 0xa5, 0x90, 0xce, 0xe6, 0xc2,
0x74, 0x25, 0x2e, 0xdd, 0x7c, 0x5f, 0xfa, 0xc5, 0x62, 0xd5, 0xf2, 0xdb,
0x95, 0x7e, 0xa3, 0x74, 0xc3, 0x2d, 0x3c, 0xca, 0x37, 0x35, 0x35, 0x15,
0xeb, 0x43, 0x14, 0x97, 0xfa, 0xcb, 0xc5, 0xe0, 0x3c, 0x36, 0xcb, 0xd2,
0x56, 0x11, 0x51, 0xd9, 0x94, 0xf8, 0xb2, 0x97, 0xfd, 0xcc, 0xdd, 0x5f,
0xed, 0xc9, 0xa9, 0xdf, 0xf3, 0x6e, 0x1e, 0x07, 0x8f, 0x6e, 0xe5, 0x1b,
0x37, 0xf9, 0x68, 0x57, 0x7e, 0x82, 0xaa, 0xf9, 0xa2, 0x5f, 0xd9, 0xa1,
0x1c, 0xec, 0x79, 0x1a, 0x35, 0xfa, 0xbf, 0x40, 0xb3, 0xa4, 0x7d, 0xc9,
0xb2, 0xb2, 0xc3, 0x2b, 0xe3, 0xa8, 0x43, 0xc8, 0x09, 0xa5, 0x2d, 0xde,
0xa1, 0x57, 0x20, 0x43, 0xb4, 0x37, 0xa0, 0xfb, 0xb2, 0xf5, 0xf2, 0x8c,
0x54, 0x17, 0x45, 0xaf, 0xa2, 0xa8, 0xdf, 0x45, 0x91, 0xb8, 0x72, 0x79,
0x46, 0xb5, 0xec, 0xd4, 0xd8, 0xbd, 0xe7, 0x62, 0xed, 0xb5, 0xeb, 0x72,
0xfc, 0x5a, 0x78, 0x70, 0xc9, 0x4d, 0x52, 0xca, 0x51, 0x09, 0xe7, 0xe5,
0xa7, 0x36, 0x8b, 0x10, 0xb7, 0xee, 0xc2, 0x24, 0x24, 0x4f, 0x22, 0x44,
0xa7, 0xdf, 0xe5, 0x3d, 0x2c, 0x64, 0x8b, 0xe9, 0xf2, 0x90, 0xd9, 0x90,
0xe3, 0xb2, 0x92, 0x67, 0x20, 0xaf, 0x4d, 0x24, 0xe8, 0xc3, 0x10, 0x2d,
0x2d, 0xbe, 0x59, 0x46, 0x3f, 0xea, 0xb5, 0xb4, 0x30, 0x72, 0x5e, 0xba,
0xe3, 0xe2, 0x7c, 0xc4, 0x53, 0x26, 0x32, 0x9c, 0xf1, 0x49, 0x99, 0x35,
0x5c, 0xc4, 0x30, 0xcd, 0xc5, 0x0b, 0xe0, 0x70, 0x15, 0xbb, 0x33, 0x1d,
0x1b, 0x1d, 0x57, 0x49, 0xbd, 0xc5, 0xee, 0xe9, 0x2e, 0x75, 0xd7, 0x4d,
0xbb, 0x49, 0x8c, 0xa5, 0xee, 0xcd, 0x57, 0xfa, 0xdf, 0xc9, 0xa3, 0x81,
0xb6, 0xea, 0x04, 0x25, 0xc8, 0x3a, 0xa6, 0x76, 0x25, 0xc8, 0x91, 0xb6,
0x4e, 0x3c, 0xe6, 0x22, 0x32, 0xc0, 0x5d, 0xd6, 0x65, 0xf8, 0x46, 0x49,
0x88, 0xaf, 0xea, 0x84, 0x26, 0x21, 0xd2, 0xdd, 0x0e, 0xb8, 0x0d, 0x94,
0x46, 0x35, 0xa4, 0x42, 0x4f, 0x82, 0x88, 0xd1, 0x56, 0xaf, 0x35, 0x72,
0x2e, 0xc9, 0xe8, 0x17, 0x96, 0x4f, 0xa1, 0x40, 0xa4, 0xa5, 0x30, 0xb9,
0xfa, 0xdc, 0x8e, 0xb1, 0x8f, 0xbd, 0xe0, 0x4f, 0x3e, 0x7c, 0x28, 0xe0,
0xf1, 0x91, 0x78, 0x2f, 0xac, 0x32, 0x37, 0x99, 0x8d, 0x5f, 0xd3, 0x1d,
0x91, 0x7d, 0x9a, 0x59, 0xbd, 0xcc, 0x67, 0x57, 0x61, 0x1b, 0x80, 0x74,
0x9a, 0x54, 0xca, 0x0b, 0x37, 0xfa, 0x19, 0x7f, 0x1f, 0xe1, 0x07, 0x90,
0x84, 0x86, 0x1d, 0x8d, 0xb2, 0xba, 0x4b, 0x0d, 0x9a, 0x1c, 0xea, 0xb7,
0x80, 0xd5, 0xa0, 0x3d, 0x58, 0xfa, 0x18, 0x7c, 0xf8, 0xdc, 0x34, 0x09,
0xa8, 0x18, 0xd1, 0xc3, 0x75, 0x70, 0x86, 0xfe, 0x86, 0xe8, 0xd3, 0x89,
0x10, 0x6c, 0x81, 0x6d, 0x84, 0xda, 0x77, 0x63, 0x98, 0x4a, 0x1a, 0x03,
0x25, 0x95, 0x2c, 0x0c, 0x01, 0xeb, 0x45, 0x60, 0x75, 0x36, 0x62, 0x60,
0x3b, 0x69, 0xba, 0x0d, 0xa4, 0x73, 0x87, 0xac, 0xfa, 0x85, 0xae, 0xe6,
0xf4, 0x9b, 0xdf, 0x7e, 0xc4, 0x3a, 0xf3, 0x50, 0x84, 0x1f, 0x39, 0xf5,
0xc3, 0x14, 0xe5, 0xd0, 0x05, 0xad, 0x61, 0xe6, 0xa9, 0x05, 0xdd, 0xe9,
0xcb, 0x5e, 0xbd, 0x34, 0x2c, 0x83, 0xe8, 0x6e, 0x4a, 0x81, 0x96, 0xee,
0x94, 0x2e, 0xf3, 0xda, 0xc8, 0xd4, 0xc1, 0x99, 0x34, 0x40, 0x06, 0x36,
0x89, 0xe7, 0xd0, 0xef, 0xbc, 0x96, 0x61, 0x85, 0x18, 0x22, 0x4a, 0x9e,
0x12, 0xdf, 0x04, 0xda, 0xe5, 0x58, 0x6a, 0x9c, 0xa0, 0x10, 0x28, 0x52,
0xe5, 0x61, 0x97, 0x2e, 0xba, 0xc7, 0x5a, 0x90, 0x1a, 0x38, 0x95, 0xd4,
0xc5, 0xce, 0xcf, 0xbc, 0xda, 0x7c, 0x9c, 0x51, 0x68, 0x5a, 0x53, 0xe6,
0xf4, 0xfc, 0xd3, 0x6b, 0x7f, 0xa0, 0x05, 0x60, 0x9b, 0xba, 0x37, 0x4f,
0xaf, 0x06, 0x7c, 0x96, 0x7a, 0x3a, 0x00, 0x15, 0x15, 0x35, 0x4a, 0x52,
0xd4, 0x1f, 0x4e, 0xcc, 0xc3, 0x9f, 0x4b, 0x1a, 0x8e, 0x7f, 0x94, 0x98,
0x8f, 0x35, 0xd0, 0x0d, 0x84, 0xa7, 0x3b, 0xd8, 0x6d, 0x0f, 0x28, 0x59,
0xd0, 0x2c, 0x85, 0x53, 0x80, 0xb1, 0x23, 0xbc, 0xd2, 0x66, 0x9d, 0xf4,
0x8c, 0xba, 0x65, 0xf0, 0xd8, 0x86, 0xd0, 0xed, 0x93, 0xcc, 0xea, 0x86,
0xd0, 0xce, 0x5a, 0x96, 0x31, 0x2a, 0xbe, 0xbf, 0x2c, 0xbf, 0x81, 0x1e,
0xcd, 0x0c, 0x88, 0x8e, 0x5e, 0xf9, 0x13, 0x83, 0xce, 0x2c, 0x20, 0x31,
0x6f, 0x21, 0xbb, 0xe4, 0xb5, 0x1f, 0x8c, 0xd0, 0xf6, 0x50, 0x1b, 0xdc,
0xcf, 0xf7, 0x58, 0x2a, 0xd8, 0x3c, 0x95, 0xf9, 0xa3, 0xb9, 0xba, 0x11,
0x64, 0xfa, 0xa5, 0xe2, 0x99, 0x78, 0xe3, 0xa5, 0xe1, 0xb6, 0xaa, 0x91,
0xa5, 0x15, 0x83, 0xe0, 0x37, 0x5d, 0x35, 0xb9, 0x57, 0xf7, 0xa5, 0xdf,
0xf8, 0x53, 0xec, 0x9d, 0x36, 0x77, 0xfb, 0x5d, 0x10, 0x34, 0xf0, 0x32,
0x46, 0x0b, 0x54, 0x8d, 0x4a, 0x07, 0xda, 0x9f, 0xc8, 0x4d, 0xfa, 0xb8,
0x57, 0xfe, 0x6e, 0xab, 0x9c, 0x2b, 0xe9, 0xa8, 0xb9, 0xd6, 0x22, 0x3e,
0x09, 0xb4, 0xa0, 0x06, 0xb9, 0xe3, 0x27, 0x0a, 0x2d, 0x3c, 0x60, 0xae,
0xcd, 0x40, 0x04, 0xfa, 0x45, 0x60, 0xd3, 0x4d, 0x2a, 0x9a, 0xb3, 0xb6,
0xbd, 0x53, 0xbd, 0x2c, 0xc0, 0xaa, 0x4d, 0x48, 0x72, 0x52, 0xf7, 0x17,
0x73, 0x02, 0x27, 0x0b, 0x4c, 0xcf, 0xf0, 0x28, 0x49, 0x87, 0x2f, 0x7b,
0x92, 0xe8, 0xea, 0xe8, 0x60, 0xc0, 0xd0, 0xe7, 0xab, 0xd4, 0x2e, 0x49,
0x85, 0x5e, 0xb2, 0x08, 0xed, 0x2d, 0xe6, 0xb3, 0x83, 0xd3, 0x79, 0x3b,
0xbb, 0x4d, 0xc5, 0xbf, 0x9a, 0xbc, 0x2b, 0xcf, 0xfa, 0x25, 0xe2, 0x45,
0x75, 0xd4, 0x2d, 0xdd, 0x88, 0xa8, 0xf7, 0x60, 0xfe, 0x37, 0xaf, 0x5c,
0xb4, 0x02, 0xf1, 0x4c, 0x25, 0x1f, 0x59, 0xf1, 0x6c, 0x86, 0xc0, 0x87,
0x60, 0x11, 0x30, 0xc1, 0x15, 0xf4, 0xe8, 0x6e, 0xc2, 0x7b, 0x08, 0x7e,
0x72, 0x67, 0xca, 0x24, 0x99, 0x26, 0xc2, 0xc5, 0xaa, 0x2e, 0x3f, 0x65,
0xc5, 0x67, 0x23, 0x26, 0xc7, 0x48, 0xca, 0x44, 0x8b, 0xdf, 0x54, 0xe8,
0xbb, 0x26, 0x07, 0x12, 0x99, 0x00, 0x12, 0x58, 0x5b, 0xad, 0x37, 0x5a,
0x4f, 0x1e, 0xae, 0xd5, 0x2b, 0x89, 0xbc, 0xe6, 0x18, 0x6a, 0xd3, 0x92,
0xd4, 0x95, 0xeb, 0xa3, 0x29, 0x40, 0xcd, 0x68, 0xd6, 0x3e, 0x21, 0xd1,
0x71, 0x71, 0x65, 0x4a, 0x88, 0x24, 0xb2, 0xbc, 0x54, 0x45, 0xee, 0xdd,
0xb2, 0xa4, 0x65, 0x7b, 0xed, 0x96, 0x11, 0x7c, 0x18, 0x8f, 0x8a, 0xd3,
0xf6, 0x07, 0x57, 0xe0, 0xaa, 0x06, 0x59, 0x79, 0x13, 0x2c, 0x23, 0x11,
0xc1, 0xa7, 0xad, 0xfe, 0xaa, 0xed, 0xac, 0xbb, 0x43, 0x1e, 0xe9, 0x40,
0x4c, 0xcc, 0xad, 0x26, 0x6a, 0x80, 0xf0, 0x3d, 0xcf, 0xe6, 0x95, 0xdf,
0xfb, 0x29, 0x24, 0xba, 0xc5, 0x71, 0x35, 0x31, 0xb7, 0x98, 0x20, 0x25,
0x09, 0xa5, 0x42, 0xf7, 0xd2, 0xbe, 0xbf, 0x66, 0x31, 0x5f, 0x63, 0xe7,
0x57, 0x7d, 0xfe, 0xd5, 0xe6, 0x5f, 0xbd, 0xfb, 0xc5, 0xc8, 0xe6, 0xd9,
0xba, 0xf7, 0x45, 0x03, 0x97, 0xab, 0xca, 0x6d, 0xde, 0x3f, 0xf8, 0x98,
0xaa, 0xa9, 0xa2, 0x4e, 0x24, 0x1c, 0x46, 0x26, 0xe4, 0xfe, 0x99, 0x76,
0x6d, 0xdd, 0x48, 0x98, 0xee, 0x2f, 0x45, 0xd3, 0xf1, 0x7a, 0xd7, 0xd7,
0x83, 0xd0, 0xeb, 0x79, 0x96, 0x5a, 0x14, 0x92, 0x43, 0x88, 0x56, 0x18,
0x87, 0x39, 0x63, 0x9a, 0x03, 0x0d, 0xc3, 0xb5, 0xee, 0x07, 0xe9, 0xe2,
0xb0, 0xe6, 0x8c, 0x1f, 0xd0, 0x65, 0x5e, 0x60, 0xf6, 0xe5, 0x7b, 0xef,
0x2a, 0x59, 0x52, 0x28, 0xe5, 0x2d, 0x39, 0xa3, 0xeb, 0x03, 0x8f, 0x31,
0xd4, 0xdd, 0x07, 0xd7, 0xaa, 0xeb, 0xce, 0x28, 0x47, 0x74, 0xfd, 0xe6,
0x9c, 0x8a, 0x07, 0xdb, 0x54, 0x3e, 0xe9, 0xcf, 0x22, 0xfa, 0x9d, 0xbc,
0x78, 0x01, 0x62, 0x6e, 0x2f, 0x75, 0xc8, 0x34, 0xba, 0x47, 0xa0, 0x2f,
0x87, 0x30, 0xd6, 0x7d, 0x1a, 0xbb, 0xa3, 0x1f, 0xb8, 0xd3, 0xb0, 0x33,
0x6f, 0x70, 0x38, 0xa8, 0xbe, 0x4d, 0x24, 0xfd, 0xf9, 0xb8, 0x91, 0x90,
0xad, 0x5f, 0x65, 0xec, 0x39, 0x61, 0x00, 0xed, 0xb0, 0xc0, 0xc7, 0x61,
0xdd, 0xc3, 0xb9, 0x84, 0xe2, 0x4a, 0x4c, 0x92, 0x43, 0xc6, 0xe6, 0x67,
0x36, 0x56, 0x01, 0x52, 0x1f, 0x31, 0x4a, 0x4b, 0x17, 0x7e, 0xf5, 0x7f,
0x8d, 0x68, 0x9d, 0x00, 0x65, 0x27, 0x0b, 0x85, 0x9f, 0x0a, 0xef, 0x8c,
0x75, 0x86, 0xac, 0x48, 0xab, 0x40, 0x7d, 0xd9, 0x00, 0x67, 0xe2, 0xad,
0x8d, 0x21, 0xcd, 0xac, 0x2b, 0x96, 0x06, 0x92, 0x1f, 0xa6, 0x9d, 0x90,
0x46, 0x20, 0x45, 0x52, 0x72, 0x8c, 0xba, 0x91, 0xc2, 0x0d, 0x57, 0xcc,
0x40, 0x7b, 0xfc, 0x1c, 0x45, 0x6a, 0x8d, 0x7b, 0xcc, 0xff, 0x00, 0x59,
0x81, 0x84, 0x20, 0x42, 0x67, 0xd2, 0x1b, 0x00, 0x00, 0x01, 0x86, 0x69,
0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69,
0x6c, 0x65, 0x00, 0x00, 0x78, 0x9c, 0x7d, 0x91, 0x3d, 0x48, 0xc3, 0x40,
0x1c, 0xc5, 0x5f, 0x53, 0xa5, 0x52, 0x2b, 0x0e, 0x16, 0x11, 0x11, 0xc9,
0x50, 0x9d, 0x2c, 0x88, 0x8a, 0x08, 0x2e, 0x5a, 0x85, 0x22, 0x54, 0x08,
0xb5, 0x42, 0xab, 0x0e, 0x26, 0x97, 0x7e, 0x08, 0x4d, 0x1a, 0x92, 0x14,
0x17, 0x47, 0xc1, 0xb5, 0xe0, 0xe0, 0xc7, 0x62, 0xd5, 0xc1, 0xc5, 0x59,
0x57, 0x07, 0x57, 0x41, 0x10, 0xfc, 0x00, 0x71, 0x73, 0x73, 0x52, 0x74,
0x91, 0x12, 0xff, 0x97, 0x14, 0x5a, 0xc4, 0x7a, 0x70, 0xdc, 0x8f, 0x77,
0xf7, 0x1e, 0x77, 0xef, 0x00, 0xa1, 0x5a, 0x64, 0x9a, 0xd5, 0x36, 0x0a,
0x68, 0xba, 0x6d, 0x26, 0xe3, 0x31, 0x31, 0x9d, 0x59, 0x11, 0x03, 0xaf,
0x08, 0xa2, 0x13, 0xbd, 0x98, 0xc6, 0xa0, 0xcc, 0x2c, 0x63, 0x56, 0x92,
0x12, 0x68, 0x39, 0xbe, 0xee, 0xe1, 0xe3, 0xeb, 0x5d, 0x94, 0x67, 0xb5,
0x3e, 0xf7, 0xe7, 0xe8, 0x52, 0xb3, 0x16, 0x03, 0x7c, 0x22, 0xf1, 0x0c,
0x33, 0x4c, 0x9b, 0x78, 0x9d, 0x78, 0x72, 0xd3, 0x36, 0x38, 0xef, 0x13,
0x87, 0x59, 0x41, 0x56, 0x89, 0xcf, 0x89, 0x47, 0x4c, 0xba, 0x20, 0xf1,
0x23, 0xd7, 0x15, 0x8f, 0xdf, 0x38, 0xe7, 0x5d, 0x16, 0x78, 0x66, 0xd8,
0x4c, 0x25, 0xe7, 0x88, 0xc3, 0xc4, 0x62, 0xbe, 0x89, 0x95, 0x26, 0x66,
0x05, 0x53, 0x23, 0x9e, 0x20, 0x8e, 0xa8, 0x9a, 0x4e, 0xf9, 0x42, 0xda,
0x63, 0x95, 0xf3, 0x16, 0x67, 0xad, 0x58, 0x66, 0xf5, 0x7b, 0xf2, 0x17,
0x86, 0xb2, 0xfa, 0xf2, 0x12, 0xd7, 0x69, 0x0e, 0x20, 0x8e, 0x05, 0x2c,
0x42, 0x82, 0x08, 0x05, 0x65, 0x6c, 0xa0, 0x08, 0x1b, 0x51, 0x5a, 0x75,
0x52, 0x2c, 0x24, 0x69, 0x3f, 0xd6, 0xc2, 0xdf, 0xef, 0xfa, 0x25, 0x72,
0x29, 0xe4, 0xda, 0x00, 0x23, 0xc7, 0x3c, 0x4a, 0xd0, 0x20, 0xbb, 0x7e,
0xf0, 0x3f, 0xf8, 0xdd, 0xad, 0x95, 0x1b, 0x1f, 0xf3, 0x92, 0x42, 0x31,
0xa0, 0xfd, 0xc5, 0x71, 0x3e, 0x86, 0x80, 0xc0, 0x2e, 0x50, 0xab, 0x38,
0xce, 0xf7, 0xb1, 0xe3, 0xd4, 0x4e, 0x00, 0xff, 0x33, 0x70, 0xa5, 0x37,
0xfc, 0xa5, 0x2a, 0x30, 0xf5, 0x49, 0x7a, 0xa5, 0xa1, 0x45, 0x8e, 0x80,
0xee, 0x6d, 0xe0, 0xe2, 0xba, 0xa1, 0x29, 0x7b, 0xc0, 0xe5, 0x0e, 0xd0,
0xf7, 0x64, 0xc8, 0xa6, 0xec, 0x4a, 0x7e, 0x9a, 0x42, 0x2e, 0x07, 0xbc,
0x9f, 0xd1, 0x37, 0x65, 0x80, 0x9e, 0x5b, 0x20, 0xb8, 0xea, 0xf5, 0x56,
0xdf, 0xc7, 0xe9, 0x03, 0x90, 0xa2, 0xae, 0x12, 0x37, 0xc0, 0xc1, 0x21,
0x30, 0x9c, 0xa7, 0xec, 0xb5, 0x16, 0xef, 0xee, 0x68, 0xee, 0xed, 0xdf,
0x33, 0xf5, 0xfe, 0x7e, 0x00, 0xb6, 0x7a, 0x72, 0xc2, 0xb7, 0x19, 0xd7,
0x5a, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xf9, 0x43, 0xbb, 0x7f, 0x00, 0x00, 0x00, 0x09, 0x70,
0x48, 0x59, 0x73, 0x00, 0x00, 0x2e, 0x23, 0x00, 0x00, 0x2e, 0x23, 0x01,
0x78, 0xa5, 0x3f, 0x76, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45,
0x07, 0xe5, 0x0a, 0x0b, 0x17, 0x1e, 0x25, 0x91, 0xc0, 0xe1, 0x5c, 0x00,
0x00, 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65,
0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77,
0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0x0e, 0x17,
0x00, 0x00, 0x00, 0x8f, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0xa5, 0x92,
0x49, 0x0e, 0xc0, 0x20, 0x0c, 0x03, 0x1d, 0x8b, 0xff, 0x7f, 0xd9, 0x3d,
0x54, 0xdd, 0x21, 0x5b, 0x91, 0x10, 0x82, 0x90, 0x89, 0x21, 0x36, 0x00,
0x02, 0x84, 0xee, 0xe0, 0xbe, 0xd8, 0x5f, 0x40, 0x1f, 0x42, 0x00, 0x90,
0xd4, 0x86, 0x9c, 0x0a, 0xba, 0x10, 0xde, 0x37, 0x1d, 0x08, 0xdf, 0x07,
0x55, 0x08, 0x67, 0x87, 0x15, 0x08, 0x57, 0x81, 0x2c, 0x84, 0x5e, 0x30,
0x03, 0x61, 0x24, 0x31, 0x82, 0x30, 0xf3, 0x51, 0x1e, 0x84, 0xd9, 0x76,
0xad, 0x20, 0xac, 0x98, 0x66, 0x06, 0x61, 0xd5, 0xba, 0x6f, 0xc8, 0xf0,
0x2e, 0x9b, 0x45, 0x3e, 0xb0, 0xb9, 0x82, 0x23, 0xf1, 0xaa, 0xa6, 0xe5,
0x64, 0xbd, 0xaa, 0xd3, 0x85, 0x3d, 0x59, 0x93, 0x37, 0x27, 0x8c, 0xf4,
0x4c, 0x56, 0x5a, 0x09, 0x57, 0x95, 0xb3, 0x2a, 0x78, 0x7d, 0x52, 0xa7,
0x0b, 0x80, 0x01, 0x92, 0x1b, 0x7e, 0x6a, 0xf9, 0xdc, 0x18, 0x81, 0x6d,
0x42, 0x05, 0x1b, 0x88, 0xd3, 0x3f, 0x1e, 0x42, 0x28, 0x07, 0xad, 0x00,
0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
unsigned int mouse_png_len = 4907;
#else // EMBED_HERE
extern unsigned char mouse_png[];
extern unsigned int mouse_png_len;
#endif // EMBED_HERE
#pragma GCC diagnostic pop
#endif // MOUSE_PNG_H

View file

@ -1,138 +0,0 @@
/*
* 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/>.
*
*/
#include "config.h"
#include "log.h"
#include "memory.h"
#include "timer.h"
#include "task.h"
#include "network.h"
#include "settings.h"
#include "firstrun.h"
static uint8_t _firstRunRunning = 1;
static void firstRunFail(void);
static void taskFirstRun(void *data);
static void taskFirstRunHelper(void *data);
static void firstRunFail(void) {
netShutdown();
taskShutdown();
timerShutdown();
configShutdown();
osShutdown();
logClose();
memoryShutdown();
exit(1);
}
void firstRunCheckSetup(void) {
// ***TODO*** Check for needed files here.
mkdir("cache", 0777);
taskCreate(taskFirstRunHelper, NULL);
taskCreate(taskFirstRun, NULL);
taskRun();
}
static void taskFirstRun(void *data) {
int8_t comPort = -1;
int8_t r = 0;
(void)data;
logWrite("First Run Setup\n");
logWrite("===============\n\n");
// 0 1 2 3 4 5 6 7 8
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
logWrite("Welcome to the KangaWorld Client! Before you can connect to KangaWorld, Setup\n");
logWrite("needs to detect a compatible softmodem and download several files.\n\n");
logWrite("One moment while we check for a compatible softmodem...\n\n");
comPort = settingsScanComPorts();
if (comPort < 0) {
logWrite("Unable to detect a compatible softmodem! For assistance, visit:\n");
logWrite("https://Kanga.World\n");
firstRunFail();
}
logWrite("Compatible softmodem found on COM%d:! Connecting to KangaWorld...\n\n", comPort + 1);
logWrite("Initializing modem...\n");
r = netConnectStep1();
if (r == NETWORK_CONNECT_OPEN_FAILED) {
logWrite("Unable to open COM port! Please check settings.\n");
_firstRunRunning = 0;
return;
}
if (r == NETWORK_CONNECT_BAD_MODEM) {
logWrite("Modem does not support ENET! Please check settings.\n");
_firstRunRunning = 0;
return;
}
logWrite("Dialing modem...\n");
r = netConnectStep2();
if (r == NETWORK_CONNECT_NO_CARRIER) {
logWrite("Unable to connect to server! Please check settings or try later.\n");
_firstRunRunning = 0;
return;
}
if (r == NETWORK_CONNECT_BAD_ENCRYPTION) {
logWrite("Unable to negotiate encryption settings!\n");
_firstRunRunning = 0;
return;
}
if (r == NETWORK_CONNECT_BAD_SETTINGS) {
logWrite("Unable to fetch client settings!\n");
_firstRunRunning = 0;
return;
}
logWrite("Connected! Pre-caching needed files...\n");
logWrite("Disconnecting...\n");
netDisconnect();
_firstRunRunning = 0;
return;
}
static void taskFirstRunHelper(void *data) {
(void)data;
while (_firstRunRunning) {
timerUpdate();
taskYield();
}
}

View file

@ -77,7 +77,7 @@ static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_
// Fire callback on mouse up.
if (event == MOUSE_EVENT_LEFT_UP) {
if (b->clicked) b->clicked(widget);
if (b->clicked) guiPendingEventAdd(widget, b->clicked);
}
}

View file

@ -64,7 +64,7 @@ static void checkboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint1
// Toggle value.
checkboxValueSet(c, !checkboxValueGet(c));
// Fire callback on mouse up.
if (c->clicked) c->clicked(widget);
if (c->clicked) guiPendingEventAdd(widget, c->clicked);
}
}

View file

@ -22,10 +22,16 @@
#include "gui.h"
#include "embedded/vga8x14.h"
#include "widget.h"
#include "desktop.h"
#include "window.h"
#include "embedded/embedded.h"
typedef struct PendingEventsS {
WidgetT *widget;
widgetCallback callback;
} PendingEventsT;
int16_t _guiMetric[METRIC_COUNT];
@ -43,7 +49,17 @@ static uint8_t _guiLastWidgetLeftEvent = MOUSE_EVENT_NONE;
static WidgetT *_guiFocused = NULL;
static uint8_t _guiHasStopped = 0; // This starts as 0 even if the GUI hasn't been started.
static WidgetT ***_guiDeleteList = NULL;
static uint32_t _guiTimerValue = 0;
static uint32_t _guiTimerLast = 0;
static uint32_t _guiTimerHalfSecond = 0;
static uint32_t _guiTimerSecond = 0;
static uint32_t _guiTimerQuarterSecondTick = 0;
static uint32_t _guiTimerHalfSecondTick = 0;
static uint32_t _guiTimerSecondTick = 0;
static uint32_t _guiTimerQuarterSecondOn = 0;
static uint32_t _guiTimerHalfSecondOn = 0;
static uint32_t _guiTimerSecondOn = 0;
static PendingEventsT **_guiPendingEvents = NULL;
// Widget Magic Debug Info. Don't forget to change MagicE!
static char *_magicDebugNames[MAGIC_COUNT] = {
@ -191,6 +207,10 @@ void guiDelete(WidgetT **widget) {
// Since deleting happens in widget events, it's not safe to do it
// immediately. Instead, we make a list of what to delete and
// then process it before painting.
// This may be redundant now since there is a pending event list
// that is also handled in the paint event.
arrput(_guiDeleteList, widget);
}
@ -249,7 +269,6 @@ static void guiDeleteListItem(WidgetT **widget) {
if (plen == 1) {
// Erase the list.
arrfree(w->parent->children);
w->parent->children = NULL;
}
}
}
@ -259,7 +278,6 @@ static void guiDeleteListItem(WidgetT **widget) {
if (w == _guiFocused) _guiFocused = NULL;
// Delete us.
//logWrite("Deleting %s %p\n", _magicDebugNames[w->magic], w);
if (w->delMethod != NULL) w->delMethod(&w);
arrfree(w->children);
if (w->surface != NULL) {
@ -455,6 +473,14 @@ void guiMouseProcess(MouseT *mouse) {
void guiPaint(WidgetT *widget) {
// Process any pending events.
while (arrlen(_guiPendingEvents)) {
_guiPendingEvents[0]->callback(_guiPendingEvents[0]->widget);
DEL(_guiPendingEvents[0]);
arrdel(_guiPendingEvents, 0);
}
arrfree(_guiPendingEvents);
// Process any pending widget deletions.
guiDeleteList();
@ -512,6 +538,16 @@ void guiParentAndChildrenDirtySet(WidgetT *widget) {
}
void guiPendingEventAdd(WidgetT *widget, void *callback) {
PendingEventsT *p = NULL;
NEW(PendingEventsT, p);
p->callback = callback;
p->widget = widget;
arrput(_guiPendingEvents, p);
}
WidgetT *guiRootGet(void) {
return (WidgetT *)_guiDesktop;
}
@ -648,6 +684,86 @@ void guiStop(void) {
}
uint32_t guiTimerGet(void) {
return _guiTimerValue;
}
uint8_t guiTimerHalfSecondOn(void) {
return _guiTimerHalfSecondOn;
}
uint8_t guiTimerHalfSecondTick(void) {
return _guiTimerHalfSecondTick;
}
void guiTimerProcess(uint32_t rawClock) {
uint32_t delta;
_guiTimerValue = rawClock;
// Reset ticks.
_guiTimerQuarterSecondTick = 0;
_guiTimerHalfSecondTick = 0;
_guiTimerSecondTick = 0;
// Ensure we haven't rolled past midnight between calls.
if (_guiTimerValue >= _guiTimerLast) {
delta = _guiTimerValue - _guiTimerLast;
} else {
// Compensate for midnight rollover.
delta = (_guiTimerValue + TICKS_PER_DAY) - _guiTimerLast;
}
// Everything ticks off the quarter second.
if (delta > TICKS_PER_SECOND * 0.25) {
_guiTimerLast = _guiTimerValue;
// Quarter Second timer.
_guiTimerQuarterSecondOn = !_guiTimerQuarterSecondOn;
_guiTimerQuarterSecondTick = 1;
// Half Second timer.
if (--_guiTimerHalfSecond == 0) {
_guiTimerHalfSecond = 2;
_guiTimerHalfSecondOn = !_guiTimerHalfSecondOn;
_guiTimerHalfSecondTick = 1;
// Second timer
if (--_guiTimerSecond == 0) {
_guiTimerSecond = 2;
_guiTimerSecondOn = !_guiTimerSecondOn;
_guiTimerSecondTick = 1;
} // Second.
} // Half Second.
} // Quarter Second.
}
uint8_t guiTimerQuarterSecondOn(void) {
return _guiTimerQuarterSecondOn;
}
uint8_t guiTimerQuarterSecondTick(void) {
return _guiTimerQuarterSecondTick;
}
uint8_t guiTimerSecondOn(void) {
return _guiTimerSecondOn;
}
uint8_t guiTimerSecondTick(void) {
return _guiTimerSecondTick;
}
void *guiUserDataGet(WidgetT *widget) {
return widget->userData;
}

View file

@ -54,6 +54,7 @@ enum MagicE {
MAGIC_UPDOWN,
MAGIC_LISTBOX,
MAGIC_TERMINAL,
MAGIC_TIMER,
//MAGIC_DROPDOWN,
MAGIC_COUNT
};
@ -201,10 +202,19 @@ void guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *
void guiMouseProcess(MouseT *mouse);
void guiPaint(WidgetT *widget);
void guiParentAndChildrenDirtySet(WidgetT *widget);
void guiPendingEventAdd(WidgetT *widget, void *callback);
WidgetT *guiRootGet(void);
void guiShutdown(void);
DesktopT *guiStartup(void);
void guiStop(void);
uint32_t guiTimerGet(void);
uint8_t guiTimerHalfSecondOn(void);
uint8_t guiTimerHalfSecondTick(void);
void guiTimerProcess(uint32_t rawClock);
uint8_t guiTimerQuarterSecondOn(void);
uint8_t guiTimerQuarterSecondTick(void);
uint8_t guiTimerSecondOn(void);
uint8_t guiTimerSecondTick(void);
void *guiUserDataGet(WidgetT *widget);
void guiUserDataSet(WidgetT *widget, void *userData);
void guiWidgetAndChildrenDirtySet(WidgetT *widget);

View file

@ -26,6 +26,9 @@
#include "vesa.h"
static ImageT *imageNativeImageGet(unsigned char *raw, uint16_t x, uint16_t y);
ImageT *imageAllocate(uint16_t w, uint16_t h) {
uint16_t x;
uint16_t y;
@ -78,6 +81,20 @@ ImageT *imageCreate(uint16_t w, uint16_t h, ColorT color) {
}
ImageT *imageFromRAMLoad(uint8_t *buffer, size_t len) {
uint16_t x;
uint16_t y;
uint16_t n;
unsigned char *raw;
// Load image from RAM.
raw = stbi_load_from_memory((const unsigned char *)buffer, len, (int *)&x, (int *)&y, (int *)&n, 3);
if (!raw) return NULL;
return imageNativeImageGet(raw, x, y);
}
uint16_t imageHeightGet(ImageT *image) {
return image->height;
}
@ -104,14 +121,20 @@ ImageT *imageLoad(char *filename) {
uint16_t x;
uint16_t y;
uint16_t n;
uint32_t b;
unsigned char *raw;
ImageT *image;
// Load image from disk
raw = stbi_load(filename, (int *)&x, (int *)&y, (int *)&n, 3);
if (!raw) return NULL;
return imageNativeImageGet(raw, x, y);
}
static ImageT *imageNativeImageGet(unsigned char *raw, uint16_t x, uint16_t y) {
uint32_t b;
ImageT *image;
// Create native image.
image = imageAllocate(x, y);
if (!image) {

View file

@ -37,6 +37,7 @@ typedef struct ImageS {
ImageT *imageAllocate(uint16_t w, uint16_t h);
ImageT *imageCreate(uint16_t w, uint16_t h, ColorT color);
ImageT *imageFromRAMLoad(uint8_t *buffer, size_t len);
uint16_t imageHeightGet(ImageT *image);
uint8_t imageInfoGet(char *filename, uint16_t *width, uint16_t *height);
ImageT *imageLoad(char *filename);

View file

@ -95,7 +95,7 @@ static void labelMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t
// Fire callback on mouse up.
if (event == MOUSE_EVENT_LEFT_UP) {
if (l->clicked) l->clicked(widget);
if (l->clicked) guiPendingEventAdd(widget, l->clicked);
}
}

View file

@ -67,7 +67,7 @@ static void pictureMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16
// Fire callback on mouse up.
if (event == MOUSE_EVENT_LEFT_UP) {
if (p->clicked) p->clicked(widget);
if (p->clicked) guiPendingEventAdd(widget, p->clicked);
}
}

View file

@ -70,7 +70,7 @@ static void radioMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t
// Select us.
radioSelectedSet(r);
// Fire callback on mouse up.
if (r->clicked) r->clicked(widget);
if (r->clicked) guiPendingEventAdd(widget, r->clicked);
}
}

View file

@ -301,7 +301,7 @@ static void textboxPaint(WidgetT *widget, uint8_t enabled, RectT pos) {
free(draw);
// Draw cursor.
if (guiFocusGet() == widget && __timerQuarterSecondOn) {
if (guiFocusGet() == widget && guiTimerQuarterSecondOn()) {
caretPos = textX + fontWidthGet(_guiFont) * t->caret;
fontRender(_guiFont, cursor, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], caretPos, textY);
}

109
client/src/gui/timer.c Normal file
View file

@ -0,0 +1,109 @@
/*
* 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/>.
*
*/
#include "timer.h"
static void timerPaint(WidgetT *widget, uint8_t enabled, RectT pos);
WidgetT *timerInit(WidgetT *widget, widgetCallback timeout, uint16_t quarterSeconds) {
TimerT *t = (TimerT *)widget;
t->running = 1;
t->counter = 0;
t->quarterSeconds = quarterSeconds;
t->timeout = timeout;
t->base.paintMethod = timerPaint;
// We use the paint event to handle timer processing.
GUI_SET_FLAG(widget, WIDGET_FLAG_ALWAYS_PAINT);
return widget;
}
TimerT *timerNew(widgetCallback timeout, uint16_t quarterSeconds) {
TimerT *timer = (TimerT *)malloc(sizeof(TimerT));
WidgetT *widget = NULL;
if (!timer) return NULL;
widget = widgetInit(W(timer), MAGIC_TIMER, 0, 0, 0, 0, 0, 0, 0, 0);
if (!widget) {
free(timer);
return NULL;
}
timer = (TimerT *)timerInit((WidgetT *)timer, timeout, quarterSeconds);
if (!timer) {
free(timer);
return NULL;
}
return timer;
}
static void timerPaint(WidgetT *widget, uint8_t enabled, RectT pos) {
TimerT *t = (TimerT *)widget;
(void)enabled;
(void)pos;
// Do we care?
if (t->running) {
// Everything ticks off the quarter second.
if (guiTimerQuarterSecondTick()) t->counter++;
// We don't check for timeout inside the tick condition so that timers of 0 fire immediately.
if (t->counter >= t->quarterSeconds) {
// Timeout! Call user.
guiPendingEventAdd(widget, t->timeout);
t->counter = 0;
}
}
}
void timerQuarterSecondsSet(TimerT *timer, uint16_t quarterSeconds) {
timer->quarterSeconds = quarterSeconds;
timer->counter = 0;
}
void timerReset(TimerT *timer) {
timer->counter = 0;
}
void timerStart(TimerT *timer) {
timer->counter = 0;
timer->running = 1;
}
void timerStop(TimerT *timer) {
timer->running = 0;
}
void timerTimeoutSet(TimerT *timer, widgetCallback timeout) {
timer->timeout = timeout;
}

View file

@ -22,22 +22,26 @@
#define TIMER_H
#include "os.h"
#include "gui.h"
#include "widget.h"
extern uint8_t __timerQuarterSecondTick;
extern uint8_t __timerHalfSecondTick;
extern uint8_t __timerSecondTick;
extern uint8_t __timerQuarterSecondOn;
extern uint8_t __timerHalfSecondOn;
extern uint8_t __timerSecondOn;
typedef struct TimerS {
WidgetT base; // Must be first in every widget
widgetCallback timeout;
uint16_t quarterSeconds;
uint16_t counter;
uint8_t running;
} TimerT;
void timerShutdown(void);
void timerStartup(void);
void timerUpdate(void);
void timerQuarterSecondsWait(uint8_t quarterSeconds);
WidgetT *timerInit(WidgetT *widget, widgetCallback timeout, uint16_t quarterSeconds);
TimerT *timerNew(widgetCallback timeout, uint16_t quarterSeconds);
void timerQuarterSecondsSet(TimerT *timer, uint16_t quarterSeconds);
void timerReset(TimerT *timer);
void timerStart(TimerT *timer);
void timerStop(TimerT *timer);
void timerTimeoutSet(TimerT *timer, widgetCallback timeout);
#endif // TIMER_H

View file

@ -310,7 +310,7 @@ static void updownPaint(WidgetT *widget, uint8_t enabled, RectT pos) {
fontRender(_guiFont, draw, _guiColor[COLOR_UPDOWN_TEXT], _guiColor[COLOR_UPDOWN_BACKGROUND], textX, textY);
// Draw cursor.
if (guiFocusGet() == widget && __timerQuarterSecondOn) {
if (guiFocusGet() == widget && guiTimerQuarterSecondOn()) {
textX += (strlen(draw) - 1) * fontWidthGet(_guiFont);
fontRender(_guiFont, cursor, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], textX, textY);
}

107
client/src/hangup.c Normal file
View file

@ -0,0 +1,107 @@
/*
* 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/>.
*
*/
#include "window.h"
#include "label.h"
#include "timer.h"
#include "taglist.h"
#include "config.h"
#include "network.h"
#include "comport.h"
#include "hangup.h"
typedef enum HangupStateE {
S_START_HANGUP = 0,
S_WAITING
} HangupStateT;
static widgetCallback _done = NULL;
static WindowT *_winHangup = NULL;
static LabelT *_lblHangup = NULL;
static TimerT *_timProgress = NULL;
static HangupStateT _state = S_START_HANGUP;
static void timHangupProgress(WidgetT *widget);
void hangupShow(void *nextFunction) {
_done = (widgetCallback)nextFunction;
TagItemT uiDetecting[] = {
T_START,
T_WINDOW, O(_winHangup),
T_TITLE, P("Goodbye"),
T_WIDTH, 200, T_HEIGHT, 100,
T_LABEL, O(_lblHangup),
T_X, 41, T_Y, 25,
T_TITLE, P("Disconnecting!"),
T_LABEL, T_DONE,
T_TIMER, O(_timProgress),
T_EVENT, P(timHangupProgress),
T_VALUE, 0,
T_TIMER, T_DONE,
T_WINDOW, T_DONE,
T_END
};
// We can use a module-global variable instead of widget user data
// because there will never be more than one disconnect dialog on
// the screen at a time.
_state = S_START_HANGUP;
tagListRun(uiDetecting);
}
static void timHangupProgress(WidgetT *widget) {
PacketEncodeDataT encoded = { 0 };
TimerT *t = (TimerT *)widget;
switch (_state) {
case S_START_HANGUP:
// Tell server we're disconnecting.
encoded.packetType = PACKET_TYPE_CLIENT_SHUTDOWN;
encoded.control = PACKET_CONTROL_DAT;
encoded.channel = 0;
encoded.encrypt = 0;
packetEncode(__packetThreadData, &encoded, NULL, 0);
packetSend(__packetThreadData, &encoded);
// Snooze a bit for the packet to send.
_state = S_WAITING;
timerQuarterSecondsSet(t, 3 * 4);
break;
case S_WAITING:
// Shut down packet processing & COM port.
netShutdown();
comClose(__configData.serialCom - 1);
timerStop(t);
// On to the next dialog.
guiDelete(D(_winHangup));
_done(NULL);
break;
}
}

View file

@ -18,14 +18,14 @@
*/
#ifndef FIRSTRUN_H
#define FIRSTRUN_H
#ifndef HANGUP_H
#define HANGUP_H
#include "os.h"
void firstRunCheckSetup(void);
void hangupShow(void *nextFunction);
#endif // FIRSTRUN_H
#endif // HANGUP_H

View file

@ -32,9 +32,6 @@
#include "comport.h"
#define SECONDS_IN_DAY 86400
#define TICKS_PER_SECOND 18.2
#define TICKS_PER_DAY (SECONDS_IN_DAY * TICKS_PER_SECOND)
#define TIMER_INTERVAL (1000 / TICKS_PER_SECOND)
#define COM_BUFFER_SIZE 2048
@ -61,7 +58,7 @@ static uint8_t _ASCIIKeep = 0;
static uint8_t _scanCodeKeep = 0;
static uint8_t _keyPressed = 0;
static uint8_t _debounce = 0;
static long _timerTicks = 0;
static uint32_t _timerTicks = 0;
static SDL_TimerID _timerID = { 0 };
static ENetHost *_host = NULL;
static ENetPeer *_peer = NULL;
@ -86,10 +83,7 @@ static uint32_t timerCallback(uint32_t interval, void *param);
static void vbeScreenshot(void);
long biostime(int cmd, long newtime) {
(void)cmd;
(void)newtime;
uint32_t rawclock(void) {
return _timerTicks;
}

View file

@ -21,19 +21,25 @@
#include "textbox.h"
#include "button.h"
#include "msgbox.h"
#include "timer.h"
#include "runtime.h"
#include "config.h"
#include "comport.h"
#include "network.h"
#include "taglist.h"
#include "timer.h"
#include "task.h"
#include "login.h"
#include "signup.h"
#include "welcome.h"
#include "menu.h"
#include "hangup.h"
typedef enum LoginStateE {
S_START_LOGIN = 0,
S_WAIT_LOGIN
} LoginStateT;
static WindowT *_winLogin = NULL;
@ -42,40 +48,55 @@ static TextboxT *_txtPass = NULL;
static ButtonT *_btnCancel = NULL;
static ButtonT *_btnSignUp = NULL;
static ButtonT *_btnLogin = NULL;
static TimerT *_timProgress = NULL;
static LoginStateT _state = S_START_LOGIN;
static uint8_t _channel = 0;
static void btnCancelClick(WidgetT *widget);
static void btnLoginClick(WidgetT *widget);
static void btnSignUpClick(WidgetT *widget);
static void btnMsgBoxCancel(MsgBoxButtonT button);
static void btnMsgBoxContinue(MsgBoxButtonT button);
static void packetHandler(PacketDecodeDataT *packet);
static void setButtons(uint8_t enabled);
static void taskDisconnect(void *data);
static void taskLoginClick(void *data);
static void timLoginProgress(WidgetT *widget);
static void btnCancelClick(WidgetT *widget) {
(void)widget;
// ***TODO*** This should disable the entire dialog instead of just the buttons. Need to finish the Enable GUI code first.
setButtons(0);
msgBoxTwo("Cancel?", MSGBOX_ICON_QUESTION, "Cancel login?\n \nThis will disconnect you from the server.", "Okay", btnMsgBoxCancel, "Cancel", btnMsgBoxCancel);
}
static void btnLoginClick(WidgetT *widget) {
(void)widget;
setButtons(0);
_state = S_START_LOGIN;
timerQuarterSecondsSet(_timProgress, 0);
timerStart(_timProgress);
}
static void btnSignUpClick(WidgetT *widget) {
(void)widget;
netChannelRelease(_channel);
guiDelete(D(_winLogin));
taskCreate(taskSignUp, NULL);
signupShow();
}
static void btnMsgBoxCancel(MsgBoxButtonT button) {
if (button == MSGBOX_BUTTON_ONE) {
netChannelRelease(_channel);
guiDelete(D(_winLogin));
taskCreate(taskDisconnect, taskWelcome);
hangupShow(welcomeShow);
} else {
setButtons(1);
}
@ -89,24 +110,9 @@ static void btnMsgBoxContinue(MsgBoxButtonT button) {
}
static void setButtons(uint8_t enabled) {
widgetEnableSet(W(_btnCancel), enabled);
widgetEnableSet(W(_btnSignUp), enabled);
widgetEnableSet(W(_btnLogin), enabled);
}
void loginShow() {
static void taskDisconnect(void *nextTask) {
netDisconnect();
if (nextTask) taskCreate(taskWelcome, nextTask);
}
void taskLogin(void *data) {
(void)data;
// ***TODO*** We used to have a FORGOT PASSWORD button here, too.
// ***TODO*** We used to have a FORGOT PASSWORD link here, too.
TagItemT uiLogin[] = {
T_START,
@ -142,70 +148,88 @@ void taskLogin(void *data) {
T_BUTTON, O(_btnLogin),
T_TITLE, P("Login"),
T_X, 199, T_Y, 85,
T_CLICK, P(taskProxy),
T_USER_DATA, P(taskLoginClick),
T_CLICK, P(btnLoginClick),
T_BUTTON, T_DONE,
T_TIMER, O(_timProgress),
T_EVENT, P(timLoginProgress),
T_VALUE, 0,
T_ENABLED, 0,
T_TIMER, T_DONE,
T_WINDOW, T_DONE,
T_END
};
tagListRun(uiLogin);
_channel = netChannelGet(packetHandler);
}
static void taskLoginClick(void *data) {
char *packetData = NULL;
int8_t success = 0;
uint16_t length = 0;
int16_t timeout = 10;
PacketEncodeDataT encoded = { 0 };
PacketDecodeDataT *decoded = NULL;
static void packetHandler(PacketDecodeDataT *packet) {
char *packetData;
int8_t success;
(void)data;
// ***TODO*** This should disable the entire dialog instead of just the buttons. Need to finish the Enable GUI code first.
setButtons(0);
packetData = packetContentPack(&length, "ss", textboxValueGet(_txtUser), textboxValueGet(_txtPass));
// Send login request.
encoded.packetType = PACKET_TYPE_LOGIN;
encoded.control = PACKET_CONTROL_DAT;
encoded.channel = 0;
encoded.encrypt = 1;
packetEncode(__packetThreadData, &encoded, packetData, length);
packetSend(__packetThreadData, &encoded);
DEL(packetData);
// Wait for response.
do {
decoded = netGetPacket(0);
if (decoded) {
switch (decoded->packetType) {
switch (packet->packetType) {
case PACKET_TYPE_LOGIN_RESULT:
packetContentUnpack(decoded->data, "is", &success, &packetData);
packetContentUnpack(packet->data, "is", &success, &packetData);
logWrite("Login: %d %s\n", success, packetData);
if (success) {
netChannelRelease(_channel);
guiDelete(D(_winLogin));
taskCreate(taskMenu, NULL);
menuShow();
} else {
msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, packetData, "Okay", btnMsgBoxContinue);
}
DEL(packetData);
timeout = 0;
timerStop(_timProgress);
break;
default:
timerStop(_timProgress);
msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, "Unexpected packet received.", "Okay", btnMsgBoxContinue);
timeout = 0;
break;
}
packetDecodeDataDestroy(&decoded);
packetDecodeDataDestroy(&packet);
}
taskYield();
if (__timerQuarterSecondTick) timeout--;
} while (!guiHasStopped() && timeout > 0);
static void setButtons(uint8_t enabled) {
// ***TODO*** This should disable the entire dialog instead of just the buttons. Need to finish the Enable GUI code first.
widgetEnableSet(W(_btnCancel), enabled);
widgetEnableSet(W(_btnSignUp), enabled);
widgetEnableSet(W(_btnLogin), enabled);
}
static void timLoginProgress(WidgetT *widget) {
char *packetData;
uint16_t length;
PacketEncodeDataT encoded;
TimerT *t = (TimerT *)widget;
switch (_state) {
case S_START_LOGIN:
setButtons(0);
packetData = packetContentPack(&length, "ss", textboxValueGet(_txtUser), textboxValueGet(_txtPass));
// Send login request.
encoded.packetType = PACKET_TYPE_LOGIN;
encoded.control = PACKET_CONTROL_DAT;
encoded.channel = _channel;
encoded.encrypt = 1;
packetEncode(__packetThreadData, &encoded, packetData, length);
packetSend(__packetThreadData, &encoded);
DEL(packetData);
// Wait for response.
timerQuarterSecondsSet(t, 10 * 4);
_state = S_WAIT_LOGIN;
break;
case S_WAIT_LOGIN:
timerStop(t);
msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, "No response received.", "Okay", btnMsgBoxContinue);
break;
}
}

View file

@ -25,7 +25,7 @@
#include "os.h"
void taskLogin(void *data);
void loginShow(void);
#endif // LOGIN_H

View file

@ -40,71 +40,125 @@
#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 "comport.h"
#include "network.h"
#include "firstrun.h"
#include "timer.h"
#include "embedded/embedded.h"
#include "welcome.h"
#include "signup.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;
static void taskGuiEventLoop(void *data);
#ifndef __linux__
char *_logName = NULL;
#endif
static void taskGuiEventLoop(void *data) {
MouseT *mouse = NULL;
ImageT *pointer = NULL;
ColorT alpha = { 0 };
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[]);
(void)data;
pointer = imageLoad("data/mouse.png");
alpha = imagePixelGet(pointer, 5, 0);
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 {
timerUpdate();
mouse = mouseRead();
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);
guiMouseProcess(_mouse);
guiComposite();
imageRenderWithAlpha(pointer, mouse->x, mouse->y, alpha);
imageRenderWithAlpha(_pointer, _mouse->x, _mouse->y, _alpha);
vbeVBlankWait();
vbePresent();
taskYield();
} while (!guiHasStopped());
imageUnload(&pointer);
shutdown();
}
static uint8_t hasValidSettings(void) {
return (__configData.serialCom > 0 && __configData.serialCom < 5);
}
int main(int argc, char *argv[]) {
static void shutdown(void) {
#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
imageUnload(&_pointer);
netShutdown();
guiShutdown();
mouseShutdown();
surfaceShutdown();
vbeShutdown();
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");
@ -116,16 +170,10 @@ int main(int argc, char *argv[]) {
configShutdown();
logClose();
memoryShutdown();
return 0;
return 1;
}
}
timerStartup();
taskStartup();
// Perform "first run" setup tasks.
firstRunCheckSetup();
// Do we have the video mode they asked for?
if (vbeStartup(__configData.videoWidth, __configData.videoHeight, __configData.videoDepth)) {
configShutdown();
@ -137,42 +185,29 @@ int main(int argc, char *argv[]) {
surfaceStartup();
mouseStartup();
guiStartup();
// Do not call netStartup() here. It will be started when needed.
netStartup();
// taskCreate(taskSignUp, NULL);
taskCreate(taskWelcome, NULL);
taskCreate(taskGuiEventLoop, NULL);
taskRun();
netShutdown();
guiShutdown();
mouseShutdown();
surfaceShutdown();
vbeShutdown();
taskShutdown();
timerShutdown();
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.
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
_pointer = imageFromRAMLoad(mouse_png, mouse_png_len);
_alpha = imagePixelGet(_pointer, 5, 0);
return 0;
}
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();
} else {
// Run the setup.
settingsShow(checkSettings);
}
eventLoop();
return 0;
}

View file

@ -21,7 +21,6 @@
#include "menu.h"
void taskMenu(void *data) {
(void)data;
void menuShow(void) {
}

View file

@ -25,7 +25,7 @@
#include "os.h"
void taskMenu(void *data);
void menuShow(void);
#endif // MENU_H

View file

@ -19,7 +19,6 @@
#include "gui.h"
#include "task.h"
#include "comport.h"
#include "config.h"
#include "timer.h"
@ -28,174 +27,30 @@
#include "network.h"
typedef struct NetworkPacketS {
typedef struct NetworkChannelsS {
uint8_t key;
PacketDecodeDataT **value;
} NetworkPacketT;
netPacketHandler value;
} NetworkChannelsT;
static NetworkPacketT *_packets = NULL;
static netPacketHandler *_systemHandlers = NULL;
static NetworkChannelsT *_channels = NULL;
static uint8_t _netRunning = 0;
static uint8_t _netStarted = 0;
int8_t netConnectStep1(void) {
int32_t r = 0;
char buffer[1024] = { 0 };
// Open COM port.
r = comOpen(__configData.serialCom - 1, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
if (r != SER_SUCCESS) return NETWORK_CONNECT_OPEN_FAILED;
// Send a CR to clear anything in the modem.
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
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);
return NETWORK_CONNECT_BAD_MODEM;
}
// Flush COM port.
timerQuarterSecondsWait(4);
comReceiveBufferFlush(__configData.serialCom - 1);
return NETWORK_CONNECT_SUCCESS;
}
int8_t netConnectStep2(void) {
int32_t r = 0;
char buffer[1024] = { 0 };
PacketDecodeDataT *decoded = NULL;
PacketEncodeDataT encoded = { 0 };
uint8_t waiting = 1;
int16_t timeout = 0;
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);
return NETWORK_CONNECT_NO_CARRIER;
}
// Start packet handler and negotiate encryption.
netStartup();
packetEncryptionSetup(__packetThreadData);
timeout = 5;
do {
if (packetEncryptionReady()) break;
taskYield();
if (__timerSecondTick) timeout--;
} while (!guiHasStopped() && timeout >= 0);
if (timeout < 0) {
comClose(__configData.serialCom - 1);
return NETWORK_CONNECT_BAD_ENCRYPTION;
}
// ***TODO*** Should probably cleanly handle a full server here with some kind of SERVER_FULL packet.
// Wait for version and table packets to arrive.
timeout = 10;
do {
decoded = netGetPacket(0);
if (decoded) {
switch (decoded->packetType) {
case PACKET_TYPE_NUMBER:
// Store in number table.
shput(__runtimeData.integers, &decoded->data[4], (int32_t)decoded->data[0]);
// Reset timeout.
timeout = 10;
break;
case PACKET_TYPE_PROCEED:
waiting = 0;
break;
case PACKET_TYPE_STRING:
// Store in string table.
//logWrite("Storing [%s]=[%s]\n", decoded->data, &decoded->data[strlen(decoded->data) + 1]);
shput(__runtimeData.strings, decoded->data, strdup(&decoded->data[strlen(decoded->data) + 1]));
// Reset timeout.
timeout = 10;
break;
case PACKET_TYPE_VERSION:
packetContentUnpack(decoded->data, "i", &__runtimeData.protocolVersion);
// Do we need to update?
if (PACKET_PROTOCOL_VERSION == __runtimeData.protocolVersion) {
// Nope, we're good.
encoded.packetType = PACKET_TYPE_VERSION_OKAY;
} else {
// Version mismatch - upgrade time!
encoded.packetType = PACKET_TYPE_VERSION_BAD;
//***TODO***
}
encoded.control = PACKET_CONTROL_DAT;
encoded.channel = 0;
encoded.encrypt = 0;
packetEncode(__packetThreadData, &encoded, NULL, 0);
// Send GOOD or BAD.
packetSend(__packetThreadData, &encoded);
// Reset timeout.
timeout = 10;
break;
default:
logWrite("Unexpected packet received: %d\n", decoded->packetType);
break;
}
packetDecodeDataDestroy(&decoded);
}
taskYield();
if (__timerSecondTick) timeout--;
} while (!guiHasStopped() && timeout >= 0 && waiting);
if (timeout < 0) {
comClose(__configData.serialCom - 1);
return NETWORK_CONNECT_BAD_SETTINGS;
}
return NETWORK_CONNECT_SUCCESS;
}
void netDisconnect(void) {
PacketEncodeDataT encoded = { 0 };
int16_t timeout = 2;
// Tell server we're disconnecting.
encoded.packetType = PACKET_TYPE_CLIENT_SHUTDOWN;
encoded.control = PACKET_CONTROL_DAT;
encoded.channel = 0;
encoded.encrypt = 0;
packetEncode(__packetThreadData, &encoded, NULL, 0);
packetSend(__packetThreadData, &encoded);
// Snooze a bit for the packet to send.
while (timeout > 0) {
taskYield();
if (__timerQuarterSecondTick) timeout--;
}
// Shut down packet processing & COM port.
netShutdown();
comClose(__configData.serialCom - 1);
}
uint8_t netGetChannelFree(void) {
uint8_t channel = 0; // We reserve 0 for system stuff. Returning 0 means no channel was found.
uint8_t netChannelGet(netPacketHandler handler) {
uint8_t channel = 0;
uint16_t x = 0;
// We reserve 0 for system stuff.
// Returning 0 means no channel was found.
// Find first unused channel.
for (x=1; x<255; x++) {
if (hmgeti(_packets, x) < 0) {
if (hmgeti(_channels, x) < 0) {
channel = x;
hmput(_channels, x, handler);
break;
}
}
@ -204,23 +59,121 @@ uint8_t netGetChannelFree(void) {
}
PacketDecodeDataT *netGetPacket(uint8_t channel) {
int32_t r = 0;
PacketDecodeDataT *packet = NULL;
void netChannelRelease(uint8_t channel) {
hmdel(_channels, channel);
}
r = hmgeti(_packets, channel);
if (r < 0) return NULL;
if (arrlen(_packets[r].value) == 0) return NULL;
packet = _packets[r].value[0];
arrdel(_packets[r].value, 0);
return packet;
void netChannelSystemGet(netPacketHandler handler) {
arrput(_systemHandlers, handler);
}
void netChannelSystemRelease(netPacketHandler handler) {
uint16_t x;
for (x=0; x<arrlen(_systemHandlers); /* no increment */) {
if (_systemHandlers[x] == handler) {
arrdel(_systemHandlers, x);
} else {
x++;
}
}
}
void netPacketHandlerStart(void) {
_netRunning = 1;
}
void netPacketHandlerStop(void) {
if (_netRunning) {
_netRunning = 0;
// Return all channels.
while (hmlen(_channels)) hmdel(_channels, _channels[0].key);
hmfree(_channels);
// Return all system channels.
while (arrlen(_systemHandlers)) arrdel(_systemHandlers, 0);
arrfree(_systemHandlers);
}
}
void netProcess(void) {
int32_t r;
char buffer[1024];
PacketDecodeDataT *packet;
PacketDecodeDataT decoded;
PacketEncodeDataT encoded;
// ***TODO*** Detect disconnection. Maybe have callbacks registered that can notify tasks?
if (_netRunning) {
// Read pending bytes.
r = comRead(__configData.serialCom - 1, buffer, 1024);
// New data or not, process anything in the queue.
if (packetDecode(__packetThreadData, &decoded, buffer, r)) {
switch (decoded.packetType) {
case PACKET_TYPE_PING:
// Reply with PONG
encoded.control = PACKET_CONTROL_DAT;
encoded.packetType = PACKET_TYPE_PONG;
encoded.channel = 0;
encoded.encrypt = 0;
packetEncode(__packetThreadData, &encoded, NULL, 0);
packetSend(__packetThreadData, &encoded);
packetDecodeDataStaticDestroy(&decoded);
break;
default:
// Is this the system channel?
if (decoded.channel == 0) {
// Send it to all registered handlers.
for (r=0; r<arrlen(_systemHandlers); r++) {
// Copy the packet out.
NEW(PacketDecodeDataT, packet);
packet->channel = decoded.channel;
packet->length = decoded.length;
packet->packetType = decoded.packetType;
packet->data = (char *)malloc(decoded.length);
memcpy(packet->data, decoded.data, decoded.length);
// Send it to the subscriber.
_systemHandlers[r](packet);
}
} else {
// Does someone want this channel?
r = hmgeti(_channels, decoded.channel);
if (r >= 0) {
// Copy the packet out.
NEW(PacketDecodeDataT, packet);
packet->channel = decoded.channel;
packet->length = decoded.length;
packet->packetType = decoded.packetType;
packet->data = (char *)malloc(decoded.length);
memcpy(packet->data, decoded.data, decoded.length);
// Send it to the subscriber.
_channels[r].value(packet);
}
}
// Destroy our copy.
packetDecodeDataStaticDestroy(&decoded);
break;
}
}
} // _netRunning
}
void netShutdown(void) {
FILE *cache = NULL;
netPacketHandlerStop();
if (_netStarted) {
_netStarted = 0;
@ -230,7 +183,7 @@ void netShutdown(void) {
if (__runtimeData.integers) {
while (shlen(__runtimeData.integers) > 0) {
//logWrite("[%s]=[%d]\n", __runtimeData.integers[0].key, __runtimeData.integers[0].value);
fprintf(cache, "%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);
@ -255,8 +208,6 @@ void netShutdown(void) {
packetThreadDataDestroy(&__packetThreadData);
}
_netRunning = 0;
}
@ -264,7 +215,9 @@ void netStartup(void) {
FILE *cache = NULL;
char *line = NULL;
char *p = NULL;
char *temp = NULL;
if (!_netStarted) {
_netStarted = 1;
__packetThreadData = packetThreadDataCreate(NULL);
@ -289,6 +242,12 @@ void netStartup(void) {
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));
}
}
@ -310,85 +269,5 @@ void netStartup(void) {
free(line);
line = NULL;
}
taskCreate(taskNetwork, NULL);
}
void taskNetwork(void *data) {
int32_t r = 0;
char buffer[1024] = { 0 };
PacketDecodeDataT *packet = NULL;
PacketDecodeDataT decoded = { 0 };
PacketEncodeDataT encoded = { 0 };
(void)data;
_netRunning = 1;
do {
// ***TODO*** Detect disconnection. Maybe have callbacks registered that can notify tasks?
// Read pending bytes.
r = comRead(__configData.serialCom - 1, buffer, 1024);
// New data or not, process anything in the queue.
if (packetDecode(__packetThreadData, &decoded, buffer, r)) {
// Is this something we care about?
switch (decoded.packetType) {
case PACKET_TYPE_PING:
// Reply with PONG
encoded.control = PACKET_CONTROL_DAT;
encoded.packetType = PACKET_TYPE_PONG;
encoded.channel = 0;
encoded.encrypt = 0;
packetEncode(__packetThreadData, &encoded, NULL, 0);
packetSend(__packetThreadData, &encoded);
packetDecodeDataStaticDestroy(&decoded);
continue;
break;
default:
// Silences a warning.
break;
}
// Copy the packet out.
NEW(PacketDecodeDataT, packet);
packet->channel = decoded.channel;
packet->length = decoded.length;
packet->packetType = decoded.packetType;
packet->data = (char *)malloc(decoded.length);
memcpy(packet->data, decoded.data, decoded.length);
// Is there a list of packets for this channel already?
r = hmgeti(_packets, packet->channel);
if (r < 0) {
// No. Create dynamic array for this channel.
hmput(_packets, packet->channel, NULL);
r = hmgeti(_packets, packet->channel);
}
// Add new packet to existing list.
arrput(_packets[r].value, packet);
packetDecodeDataStaticDestroy(&decoded);
}
// Yield to UI.
taskYield();
} while (!guiHasStopped() && _netRunning);
// Free any unclaimed packets.
while (hmlenu(_packets) > 0) {
// Free any packets for this channel.
while (arrlenu(_packets[0].value) > 0) {
packetDecodeDataDestroy(&_packets[0].value[0]);
arrdel(_packets[0].value, 0);
}
arrfree(_packets[0].value);
hmdel(_packets, _packets[0].key);
}
hmfree(_packets);
}

View file

@ -25,23 +25,18 @@
#include "os.h"
#define NETWORK_CONNECT_SUCCESS 0
#define NETWORK_CONNECT_OPEN_FAILED 1
#define NETWORK_CONNECT_BAD_MODEM 2
#define NETWORK_CONNECT_NO_CARRIER 3
#define NETWORK_CONNECT_BAD_ENCRYPTION 4
#define NETWORK_CONNECT_BAD_SETTINGS 5
typedef void (*netPacketHandler)(PacketDecodeDataT *packet);
int8_t netConnectStep1(void);
int8_t netConnectStep2(void);
void netDisconnect(void);
uint8_t netGetChannelFree(void);
PacketDecodeDataT *netGetPacket(uint8_t channel);
uint8_t netChannelGet(netPacketHandler handler);
void netChannelRelease(uint8_t channel);
void netChannelSystemGet(netPacketHandler handler);
void netChannelSystemRelease(netPacketHandler handler);
void netPacketHandlerStart(void);
void netPacketHandlerStop(void);
void netProcess(void);
void netShutdown(void);
void netStartup(void);
void taskNetwork(void *data);
#endif // NETWORK_H

View file

@ -22,9 +22,7 @@
#include "welcome.h"
#include "taglist.h"
#include "task.h"
#include "comport.h"
#include "timer.h"
#include "config.h"
#include "window.h"
@ -34,6 +32,7 @@
#include "textbox.h"
#include "updown.h"
#include "label.h"
#include "timer.h"
#define GROUP_COM 1
@ -46,6 +45,14 @@
#define TITLE_LEN 80
typedef enum SettingsStateE {
S_START_SCAN = 0,
S_OPEN_COM,
S_WAIT_FOR_INIT,
S_SCAN_COMPLETE
} SettingsStateT;
typedef struct PortS {
uint8_t status;
char title[TITLE_LEN];
@ -55,19 +62,23 @@ typedef struct PortS {
} PortT;
static WindowT *_winDetecting;
static LabelT *_lblOneMoment;
static WindowT *_winSettings;
static FrameT *_frmComPorts;
static FrameT *_frmServer;
static ButtonT *_btnOkay;
static TextboxT *_txtServer;
static UpdownT *_updPort;
static PortT _port[4];
static widgetCallback _done;
static WindowT *_winDetecting = NULL;
static LabelT *_lblOneMoment = NULL;
static WindowT *_winSettings = NULL;
static FrameT *_frmComPorts = NULL;
static FrameT *_frmServer = NULL;
static ButtonT *_btnOkay = NULL;
static TextboxT *_txtServer = NULL;
static TimerT *_timProgress = NULL;
static UpdownT *_updPort = NULL;
static PortT _port[4] = { 0 };
static widgetCallback _done = NULL;
static SettingsStateT _state = S_START_SCAN;
static void btnOkayClick(WidgetT *widget);
static void settingsComShow(void);
static void timSettingsProgress(WidgetT *widget);
static void btnOkayClick(WidgetT *widget) {
@ -95,61 +106,9 @@ static void btnOkayClick(WidgetT *widget) {
}
int8_t settingsScanComPorts(void) {
char buffer[1024] = { 0 };
uint8_t selected = 1;
int32_t rc = 0;
uint32_t len = 0;
int8_t lastFound = -1;
void settingsShow(void *callback) {
// Scan the COM ports for a compatable modem.
for (int x=0; x<4; x++) {
rc = comOpen(x, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
if (rc == SER_SUCCESS) {
snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13);
comWrite(x, buffer, strlen(buffer));
timerQuarterSecondsWait(4);
len = comRead(x, buffer, 1023);
buffer[len] = 0;
if (strstr(buffer, "OK")) {
snprintf(_port[x].title, TITLE_LEN - 1, "COM%d - SoftModem Found!", x + 1);
_port[x].status = PORT_GOOD_MODEM;
_port[x].selected = selected;
_port[x].enabled = 1;
selected = 0;
lastFound = x;
} else {
if (strstr(buffer, "ERROR")) {
snprintf(_port[x].title, TITLE_LEN - 1, "COM%d - Incompatable Modem", x + 1);
_port[x].status = PORT_BAD_MODEM;
_port[x].selected = 0;
_port[x].enabled = 0;
} else {
snprintf(_port[x].title, TITLE_LEN - 1, "COM%d - No Modem", x + 1);
_port[x].status = PORT_NO_MODEM;
_port[x].selected = 0;
_port[x].enabled = 0;
}
}
comClose(x);
} else {
snprintf(_port[x].title, TITLE_LEN - 1, "COM%d - Not Present", x + 1);
_port[x].status = PORT_NONE;
_port[x].selected = 0;
_port[x].enabled = 0;
}
}
return lastFound;
}
void taskSettings(void *data) {
int32_t rc;
uint32_t len;
_done = (widgetCallback)data;
_done = (widgetCallback)callback;
TagItemT uiDetecting[] = {
T_START,
@ -160,14 +119,27 @@ void taskSettings(void *data) {
T_X, 25, T_Y, 25,
T_TITLE, P("One Moment Please!"),
T_LABEL, T_DONE,
T_TIMER, O(_timProgress),
T_EVENT, P(timSettingsProgress),
T_VALUE, 0,
T_TIMER, T_DONE,
T_WINDOW, T_DONE,
T_END
};
tagListRun(uiDetecting);
taskYield(); // Cause dialog to paint.
// We can use a module-global variable instead of widget user data
// because there will never be more than one settings dialog on
// the screen at a time.
_state = S_START_SCAN;
settingsScanComPorts();
tagListRun(uiDetecting);
}
static void settingsComShow(void) {
int32_t y;
uint32_t len;
guiDelete(D(_winDetecting));
@ -222,12 +194,88 @@ void taskSettings(void *data) {
}
// Add COM discovery to GUI.
rc = 0;
y = 0;
for (len=0; len<4; len++) {
_port[len].rdoCOM = radioNew(5, rc, _port[len].title, GROUP_COM);
_port[len].rdoCOM = radioNew(5, y, _port[len].title, GROUP_COM);
if (_port[len].selected) radioSelectedSet(_port[len].rdoCOM);
widgetEnableSet(W(_port[len].rdoCOM), _port[len].enabled);
guiAttach(W(_frmComPorts), W(_port[len].rdoCOM));
rc += 20;
y += 20;
}
}
static void timSettingsProgress(WidgetT *widget) {
char buffer[1024];
int32_t rc;
uint32_t len;
static uint8_t selected;
static int32_t com;
switch (_state) {
case S_START_SCAN:
com = 0;
selected = 1;
_state = S_OPEN_COM;
break;
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));
timerQuarterSecondsSet((TimerT *)widget, 4);
_state = S_WAIT_FOR_INIT;
} else {
snprintf(_port[com].title, TITLE_LEN - 1, "COM%d - Not Present", com + 1);
_port[com].status = PORT_NONE;
_port[com].selected = 0;
_port[com].enabled = 0;
com++;
if (com < 4) {
_state = S_OPEN_COM;
} else {
_state = S_SCAN_COMPLETE;
}
}
break;
case S_WAIT_FOR_INIT:
len = comRead(com, buffer, 1023);
buffer[len] = 0;
if (strstr(buffer, "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")) {
snprintf(_port[com].title, TITLE_LEN - 1, "COM%d - Incompatable Modem", com + 1);
_port[com].status = PORT_BAD_MODEM;
_port[com].selected = 0;
_port[com].enabled = 0;
} else {
snprintf(_port[com].title, TITLE_LEN - 1, "COM%d - No Modem", com + 1);
_port[com].status = PORT_NO_MODEM;
_port[com].selected = 0;
_port[com].enabled = 0;
}
}
comClose(com);
com++;
if (com < 4) {
_state = S_OPEN_COM;
} else {
_state = S_SCAN_COMPLETE;
}
timerQuarterSecondsSet((TimerT *)widget, 0);
break;
case S_SCAN_COMPLETE:
timerStop(_timProgress);
settingsComShow();
break;
}
}

View file

@ -25,8 +25,7 @@
#include "os.h"
int8_t settingsScanComPorts(void);
void taskSettings(void *data);
void settingsShow(void *callback);
#endif // SETTINGS_H

View file

@ -22,17 +22,22 @@
#include "button.h"
#include "label.h"
#include "msgbox.h"
#include "timer.h"
#include "network.h"
#include "runtime.h"
#include "taglist.h"
#include "timer.h"
#include "task.h"
#include "signup.h"
#include "login.h"
typedef enum SignUpStateE {
S_START_SIGNUP = 0,
S_SIGNUP_WAIT
} SignUpStateT;
static WindowT *_winSignUp = NULL;
static LabelT *_lblRequired = NULL;
static TextboxT *_txtEmail = NULL;
@ -43,13 +48,18 @@ static TextboxT *_txtPass1 = NULL;
static TextboxT *_txtPass2 = NULL;
static ButtonT *_btnCancel = NULL;
static ButtonT *_btnSignUp = NULL;
static TimerT *_timProgress = NULL;
static SignUpStateT _state = S_START_SIGNUP;
static uint8_t _channel = 0;
static void btnCancelClick(WidgetT *widget);
static void btnMsgBoxContinue(MsgBoxButtonT button);
static void btnMsgBoxFinish(MsgBoxButtonT button);
static void btnSignUpClick(WidgetT *widget);
static void packetHandler(PacketDecodeDataT *packet);
static void setButtons(uint8_t enabled);
static void taskSignUpClick(void *data);
static void timSignUpProgress(WidgetT *widget);
static uint8_t validateEmail(char *email);
static uint8_t validateEmailLetter(char c);
static uint8_t validateName(char *username);
@ -61,7 +71,8 @@ static void btnCancelClick(WidgetT *widget) {
(void)widget;
guiDelete(D(_winSignUp));
taskCreate(taskLogin, NULL);
netChannelRelease(_channel);
loginShow();
}
@ -76,7 +87,73 @@ static void btnMsgBoxFinish(MsgBoxButtonT button) {
(void)button;
guiDelete(D(_winSignUp));
taskCreate(taskLogin, NULL);
netChannelRelease(_channel);
loginShow();
}
static void btnSignUpClick(WidgetT *widget) {
(void)widget;
setButtons(0);
// Validate it. ***TODO*** These messages could be a lot better.
if (!validateEmail(textboxValueGet(_txtEmail))) {
msgBoxOne("Invalid E-Mail", MSGBOX_ICON_ERROR, "Please enter a valid E-mail address.", "Okay", btnMsgBoxContinue);
return;
}
if (!validateName(textboxValueGet(_txtFirst))) {
msgBoxOne("Invalid First Name", MSGBOX_ICON_ERROR, "Please enter a valid first name.", "Okay", btnMsgBoxContinue);
return;
}
if (!validateName(textboxValueGet(_txtLast))) {
msgBoxOne("Invalid Last Name", MSGBOX_ICON_ERROR, "Please enter a valid last name.", "Okay", btnMsgBoxContinue);
return;
}
if (strcmp(textboxValueGet(_txtPass1), textboxValueGet(_txtPass2)) != 0) {
msgBoxOne("Invalid Password", MSGBOX_ICON_ERROR, "Passwords must match.", "Okay", btnMsgBoxContinue);
return;
}
if (!validatePassword(textboxValueGet(_txtPass1))) {
msgBoxOne("Invalid Password", MSGBOX_ICON_ERROR, "Please enter a valid password.", "Okay", btnMsgBoxContinue);
return;
}
if (!validateUser(textboxValueGet(_txtUser))) {
msgBoxOne("Invalid User Name", MSGBOX_ICON_ERROR, "Please enter a valid user name.", "Okay", btnMsgBoxContinue);
return;
}
_state = S_START_SIGNUP;
timerQuarterSecondsSet(_timProgress, 0);
timerStart(_timProgress);
}
static void packetHandler(PacketDecodeDataT *packet) {
uint16_t length;
char *packetData;
// Reset timeout.
timerReset(_timProgress);
switch (packet->packetType) {
case PACKET_TYPE_SIGNUP_RESULT:
packetContentUnpack(packet->data, "is", &length, &packetData);
if (length) {
msgBoxOne("Success!", MSGBOX_ICON_INFORMATION, packetData, "Okay", btnMsgBoxFinish);
} else {
msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, packetData, "Okay", btnMsgBoxContinue);
}
DEL(packetData);
timerStop(_timProgress);
break;
default:
logWrite("Unexpected packet received: %d\n", packet->packetType);
break;
}
packetDecodeDataDestroy(&packet);
}
@ -86,9 +163,7 @@ static void setButtons(uint8_t enabled) {
}
void taskSignUp(void *data) {
(void)data;
void signupShow(void) {
TagItemT uiSignUp[] = {
T_START,
@ -160,57 +235,31 @@ void taskSignUp(void *data) {
T_BUTTON, O(_btnSignUp),
T_TITLE, P("Sign Up"),
T_X, 291, T_Y, 270,
T_CLICK, P(taskProxy),
T_USER_DATA, P(taskSignUpClick),
T_CLICK, P(btnSignUpClick),
T_BUTTON, T_DONE,
T_TIMER, O(_timProgress),
T_EVENT, P(timSignUpProgress),
T_VALUE, 0,
T_ENABLED, 0,
T_TIMER, T_DONE,
T_WINDOW, T_DONE,
T_END
};
tagListRun(uiSignUp);
_channel = netChannelGet(packetHandler);
}
static void taskSignUpClick(void *data) {
PacketEncodeDataT encoded = { 0 };
PacketDecodeDataT *decoded = NULL;
int16_t timeout = 10;
uint16_t length = 0;
char *packetData = NULL;
(void)data;
// ***TODO*** This should disable the entire dialog instead of just the buttons. Need to finish the Enable GUI code first.
setButtons(0);
// Validate it. ***TODO*** These messages could be a lot better.
if (!validateEmail(textboxValueGet(_txtEmail))) {
msgBoxOne("Invalid E-Mail", MSGBOX_ICON_ERROR, "Please enter a valid E-mail address.", "Okay", btnMsgBoxContinue);
return;
}
if (!validateName(textboxValueGet(_txtFirst))) {
msgBoxOne("Invalid First Name", MSGBOX_ICON_ERROR, "Please enter a valid first name.", "Okay", btnMsgBoxContinue);
return;
}
if (!validateName(textboxValueGet(_txtLast))) {
msgBoxOne("Invalid Last Name", MSGBOX_ICON_ERROR, "Please enter a valid last name.", "Okay", btnMsgBoxContinue);
return;
}
if (strcmp(textboxValueGet(_txtPass1), textboxValueGet(_txtPass2)) != 0) {
msgBoxOne("Invalid Password", MSGBOX_ICON_ERROR, "Passwords must match.", "Okay", btnMsgBoxContinue);
return;
}
if (!validatePassword(textboxValueGet(_txtPass1))) {
msgBoxOne("Invalid Password", MSGBOX_ICON_ERROR, "Please enter a valid password.", "Okay", btnMsgBoxContinue);
return;
}
if (!validateUser(textboxValueGet(_txtUser))) {
msgBoxOne("Invalid User Name", MSGBOX_ICON_ERROR, "Please enter a valid user name.", "Okay", btnMsgBoxContinue);
return;
}
static void timSignUpProgress(WidgetT *widget) {
PacketEncodeDataT encoded;
uint16_t length;
char *packetData;
TimerT *t = (TimerT *)widget;
switch (_state) {
case S_START_SIGNUP:
packetData = packetContentPack(&length, "sssss",
textboxValueGet(_txtEmail),
textboxValueGet(_txtFirst),
@ -222,39 +271,20 @@ static void taskSignUpClick(void *data) {
// Send signup request.
encoded.packetType = PACKET_TYPE_SIGNUP;
encoded.control = PACKET_CONTROL_DAT;
encoded.channel = 0;
encoded.channel = _channel;
encoded.encrypt = 1;
packetEncode(__packetThreadData, &encoded, packetData, length);
packetSend(__packetThreadData, &encoded);
DEL(packetData);
// Wait for response.
do {
decoded = netGetPacket(0);
if (decoded) {
switch (decoded->packetType) {
case PACKET_TYPE_SIGNUP_RESULT:
packetContentUnpack(decoded->data, "is", &length, &packetData);
if (length) {
msgBoxOne("Success!", MSGBOX_ICON_INFORMATION, packetData, "Okay", btnMsgBoxFinish);
} else {
msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, packetData, "Okay", btnMsgBoxContinue);
}
DEL(packetData);
timeout = 0;
timerQuarterSecondsSet(_timProgress, 10 * 4);
break;
default:
msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, "Unexpected packet received.", "Okay", btnMsgBoxContinue);
timeout = 0;
case S_SIGNUP_WAIT:
timerStop(t);
msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, "No response received.", "Okay", btnMsgBoxContinue);
break;
}
packetDecodeDataDestroy(&decoded);
}
taskYield();
if (__timerQuarterSecondTick) timeout--;
} while (!guiHasStopped() && timeout > 0);
}

View file

@ -25,7 +25,7 @@
#include "os.h"
void taskSignUp(void *data);
void signupShow(void);
#endif // SIGNUP_H

View file

@ -17,10 +17,8 @@
*
*/
#include "comport.h"
#include "timer.h"
#include "task.h"
#include "config.h"
@ -43,44 +41,65 @@ int comReceiveBufferFlush(int com) {
}
int comWaitWithTimeout(int com, char *buffer, int len, int quarterSeconds, char *expecting) {
int r;
int quarterTicks = 0;
int count = 0;
int bufferIndex = 0;
char data[2];
/*
TASKBEGIN(comWaitWithTimeout)
int32_t r;
uint32_t quarterTicks;
int32_t count;
int32_t bufferIndex;
char incoming[2];
ComWaitWithTimeoutT *args;
taskCode({
// Returns number of bytes read into buffer.
// Value is positive if "expect" was found.
// Value is negative if not found.
while (quarterTicks <= quarterSeconds) {
r = comRead(com, data, 1);
if (r == 1) {
buffer[bufferIndex++] = data[0];
buffer[bufferIndex] = 0;
if (data[0] == expecting[count]) {
count++;
if (count == (int)strlen(expecting)) {
logWrite("Entering comWaitWithTimeout\n");
self->args = (ComWaitWithTimeoutT *)data;
while (self->quarterTicks <= self->args->quarterSeconds) {
// logWrite("Calling comRead\n");
self->r = comRead(self->args->com, self->incoming, 1);
// logWrite("Back from comRead with %d\n", self->r);
if (self->r == 1) {
self->args->buffer[self->bufferIndex++] = self->incoming[0];
self->args->buffer[self->bufferIndex] = 0;
if (self->incoming[0] == self->args->expecting[self->count]) {
self->count++;
if (self->count == (int)strlen(self->args->expecting)) {
// Found our expect.
break;
}
} else {
count = 0;
self->count = 0;
}
if (bufferIndex == len - 1) {
if (self->bufferIndex == self->args->len - 1) {
// Out of buffer.
break;
}
} else {
}
// logWrite("Yielding from comWaitWithTimeout\n");
taskYield();
if (__timerQuarterSecondTick) quarterTicks++;
// logWrite("Back in comWaitWithTimeout\n");
if (__timerQuarterSecondTick) {
self->quarterTicks++;
logWrite("Tick\n");
}
}
if (count == (int)strlen(expecting)) {
return bufferIndex;
logWrite("Exiting comWaitWithTimeout\n");
if (self->count == (int)strlen(self->args->expecting)) {
self->args->result = self->bufferIndex;
}
return -bufferIndex;
}
self->args->result = -self->bufferIndex;
});
TASKEND
*/

View file

@ -26,6 +26,16 @@
#include "packet.h"
typedef struct ComWaitWithTimeoutS {
int32_t result;
uint8_t com;
char *buffer;
int32_t len;
uint32_t quarterSeconds;
char *expecting;
} ComWaitWithTimeoutT;
#ifdef __linux__
#define SER_SUCCESS 0
@ -35,7 +45,6 @@
#define SER_HANDSHAKING_RTSCTS 2
int comClose(int com);
int comOpen(int com, long bps, int dataBits, char parity, int stopBits, int handshaking);
int comRead(int com, char *data, int len);
@ -55,7 +64,6 @@ int comWrite(int com, const char *data, int len);
void comPacketSender(char *data, uint32_t length, void *userData);
int comReceiveBufferFlush(int com);
int comWaitWithTimeout(int com, char *buffer, int len, int quarterSeconds, char *expecting);
#endif // COMPORT_H

View file

@ -21,6 +21,16 @@
#include "os.h"
uint8_t osFileExists(char *filename) {
FILE *f = fopen(filename, "rb");
if (f) {
fclose(f);
return 1;
}
return 0;
}
void osShutdown(void) {
#ifdef __linux__
linuxOsShutdown();

View file

@ -27,6 +27,7 @@
// Common platform includes.
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
@ -37,12 +38,17 @@
#include <sys/stat.h>
#define SECONDS_IN_DAY 86400
#define TICKS_PER_SECOND 18.2
#define TICKS_PER_DAY (SECONDS_IN_DAY * TICKS_PER_SECOND)
#ifdef __linux__
#define BITS64
// Linux DOS replacements.
long biostime(int cmd, long newtime);
uint32_t rawclock(void);
// Linux support functions.
void linuxOsShutdown(void);
@ -75,8 +81,8 @@ void linuxOsStartup(void);
// Allocation helpers.
#define NEW(t,v) (v)=(t*)malloc(sizeof(t))
#define DEL(v) {free(v); v=NULL;}
#define NEW(t,v) (v)=(t*)calloc(1, sizeof(t))
#define DEL(v) { if (v) { free(v); v = NULL; } }
#define SUCCESS 1
#define FAIL 0
@ -93,6 +99,7 @@ typedef struct PacketThreadDataS PacketThreadDataT;
extern PacketThreadDataT *__packetThreadData; // Declared in main.c
uint8_t osFileExists(char *filename);
void osShutdown(void);
void osStartup(void);

View file

@ -32,6 +32,7 @@
#include "radio.h"
#include "terminal.h"
#include "textbox.h"
#include "timer.h"
#include "updown.h"
#include "window.h"
@ -166,6 +167,7 @@ static void tagListWidgetAttributeHandle(void) {
break;
case T_CLICK:
case T_EVENT:
click = (widgetCallback)v;
break;
@ -331,6 +333,13 @@ static void tagListWidgetAttributeHandle(void) {
textboxPasswordCharacterSet((TextboxT *)widget, mask);
break;
case T_TIMER:
if (hasValue && click) {
widget = W(timerNew(click, (uint32_t)valueInt));
if (!enabled) timerStop((TimerT *)widget);
}
break;
case T_UPDOWN:
widget = W(updownNew(pos.x, pos.y, minimum, maximum, step, title));
if (hasValue) updownValueSet((UpdownT *)widget, valueInt);

View file

@ -54,6 +54,7 @@ enum TagItemsE {
T_RADIOBUTTON,
T_TERMINAL,
T_TEXTBOX,
T_TIMER,
T_UPDOWN,
T_WINDOW,
@ -65,6 +66,7 @@ enum TagItemsE {
T_COLOR_BACKGROUND,
T_COLOR_FOREGROUND,
T_ENABLED,
T_EVENT,
T_FILENAME,
T_GROUP,
T_HEIGHT,

View file

@ -1,121 +0,0 @@
/*
* 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/>.
*
*/
#define MINICORO_IMPL
#define MCO_USE_ASM
//#define MCO_DEFAULT_STACK_SIZE 114688 // Default is 57344
#include "thirdparty/minicoro/minicoro.h"
#include "task.h"
#include "array.h"
typedef struct TaskS {
mco_coro *coroutine;
void (*function)(void *);
void *data;
} TaskT;
static TaskT **_taskList = NULL;
static void taskHandle(mco_coro* coroutine);
uint8_t taskCreate(void (*function)(void *), void *data) {
mco_desc desc = mco_desc_init(taskHandle, 0);
mco_result res = 0;
TaskT *task = (TaskT *)malloc(sizeof(TaskT));
if (task) {
task->function = function;
task->data = data;
desc.user_data = task;
res = mco_create(&task->coroutine, &desc);
if (res != MCO_SUCCESS) {
mco_destroy(task->coroutine);
free(task);
return 1; // Failed
}
arrput(_taskList, task);
}
return 1; // Failed
}
static void taskHandle(mco_coro* coroutine) {
TaskT *task = (TaskT *)mco_get_user_data(coroutine);
task->function(task->data);
}
void taskProxy(WidgetT *widget) {
taskFunction task = (taskFunction)guiUserDataGet(widget);
taskCreate(task, NULL);
}
void taskRun(void) {
uint16_t taskIndex = 0;
// Run until there are no more tasks.
while (arrlen(_taskList) > 0) {
// Run each task in order.
taskIndex = 0;
while (taskIndex < arrlen(_taskList)) {
// Run task.
mco_resume(_taskList[taskIndex]->coroutine);
// Did it finish?
if (mco_status(_taskList[taskIndex]->coroutine) == MCO_DEAD) {
// Task ended. Remove it.
mco_destroy(_taskList[taskIndex]->coroutine);
free(_taskList[taskIndex]);
arrdel(_taskList, taskIndex);
} else {
// Next task.
taskIndex++;
}
} // while each task
} // while tasks exist
arrfree(_taskList);
_taskList = NULL;
}
void taskShutdown(void) {
// Nada
}
void taskStartup(void) {
// Nada
}
void __attribute__ ((noinline)) taskYield(void) {
mco_yield(mco_running());
}

View file

@ -1,110 +0,0 @@
/*
* 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/>.
*
*/
#include "timer.h"
#include "task.h"
#include "gui.h"
#define SECONDS_IN_DAY 86400
#define TICKS_PER_SECOND 18.2
#define TICKS_PER_DAY (SECONDS_IN_DAY * TICKS_PER_SECOND)
uint8_t __timerQuarterSecondTick = 0;
uint8_t __timerHalfSecondTick = 0;
uint8_t __timerSecondTick = 0;
uint8_t __timerQuarterSecondOn = 0;
uint8_t __timerHalfSecondOn = 0;
uint8_t __timerSecondOn = 0;
static long _timerLast = 0;
static uint8_t _timerHalfSecond = 2;
static uint8_t _timerSecond = 2;
void timerShutdown(void) {
// Nothing yet.
}
void timerStartup(void) {
_timerLast = biostime(0, 0);
}
void timerUpdate(void) {
long now;
long delta;
now = biostime(0, 0);
// Reset ticks.
__timerQuarterSecondTick = 0;
__timerHalfSecondTick = 0;
__timerSecondTick = 0;
// Ensure we haven't rolled past midnight between calls.
if (now >= _timerLast) {
delta = now - _timerLast;
} else {
// Compensate for midnight rollover.
delta = (now + TICKS_PER_DAY) - _timerLast;
}
// Everything ticks off the quarter second.
if (delta > TICKS_PER_SECOND * 0.25) {
_timerLast = now;
// Quarter Second timer.
__timerQuarterSecondOn = !__timerQuarterSecondOn;
__timerQuarterSecondTick = 1;
// Half Second timer.
if (--_timerHalfSecond == 0) {
_timerHalfSecond = 2;
__timerHalfSecondOn = !__timerHalfSecondOn;
__timerHalfSecondTick = 1;
// Second timer
if (--_timerSecond == 0) {
_timerSecond = 2;
__timerSecondOn = !__timerSecondOn;
__timerSecondTick = 1;
} // Second.
} // Half Second.
} // Quarter Second.
}
void timerQuarterSecondsWait(uint8_t quarterSeconds) {
uint8_t counter = 0;
while (counter <= quarterSeconds && !guiHasStopped()) {
if (__timerQuarterSecondTick) {
counter++;
}
taskYield();
}
}

View file

@ -23,16 +23,29 @@
#include "login.h"
#include "taglist.h"
#include "task.h"
#include "config.h"
#include "comport.h"
#include "timer.h"
#include "network.h"
#include "runtime.h"
#include "window.h"
#include "picture.h"
#include "button.h"
#include "msgbox.h"
#include "timer.h"
typedef enum WelcomeStateE {
S_START_CONNECT = 0,
S_START_INIT_MODEM,
S_INIT_MODEM,
S_INIT_RESULT,
S_DIAL,
S_WAIT_FOR_BANNER,
S_WAIT_FOR_ENCRYPTION,
S_WAIT_FOR_DATA_TIMEOUT,
S_WAIT_FOR_ICON
} WelcomeStateT;
static WindowT *_winWelcome = NULL;
@ -43,15 +56,29 @@ static PictureT *_picConnect = NULL;
static ButtonT *_btnQuit = NULL;
static ButtonT *_btnSettings = NULL;
static ButtonT *_btnConnect = NULL;
static TimerT *_timProgress = NULL;
static WelcomeStateT _state = S_START_CONNECT;
static int16_t _timeoutCounter = 0;
static void taskConnectClick(void *data);
static void btnConnectClick(WidgetT *widget);
static void btnMsgBox(MsgBoxButtonT button);
static void btnMsgBoxQuit(MsgBoxButtonT button);
static void btnQuitClick(WidgetT *widget);
static void btnSettingsClick(WidgetT *widget);
static void packetHandler(PacketDecodeDataT *packet);
static void setButtons(uint8_t enabled);
static void settingsFinished(WidgetT *widget);
static void timWelcomeProgress(WidgetT *widget);
static void btnConnectClick(WidgetT *widget) {
(void)widget;
_state = S_START_CONNECT;
timerQuarterSecondsSet(_timProgress, 0);
timerStart(_timProgress);
}
static void btnMsgBox(MsgBoxButtonT button) {
@ -79,6 +106,7 @@ static void btnMsgBoxQuit(MsgBoxButtonT button) {
static void btnQuitClick(WidgetT *widget) {
(void)widget;
setButtons(0);
msgBoxTwo("Quit?", MSGBOX_ICON_QUESTION, "Exit to DOS?", "Okay", btnMsgBoxQuit, "Cancel", btnMsgBoxQuit);
}
@ -86,8 +114,69 @@ static void btnQuitClick(WidgetT *widget) {
static void btnSettingsClick(WidgetT *widget) {
(void)widget;
setButtons(0);
taskCreate(taskSettings, settingsFinished);
settingsShow(settingsFinished);
}
static void packetHandler(PacketDecodeDataT *packet) {
PacketEncodeDataT encoded;
char *temp;
// Reset timeout.
timerReset(_timProgress);
switch (packet->packetType) {
case PACKET_TYPE_NUMBER:
// Store in number table.
shput(__runtimeData.integers, &packet->data[4], (int32_t)packet->data[0]);
break;
case PACKET_TYPE_PROCEED:
// Connected! Show icon.
widgetVisibleSet(W(_picConnect), 1);
// Leave it up about 1.5 seconds.
timerQuarterSecondsSet(_timProgress, 6);
_state = S_WAIT_FOR_ICON;
break;
case PACKET_TYPE_STRING:
// Do we have this string already?
temp = shget(__runtimeData.strings, packet->data);
if (temp) {
DEL(temp);
shdel(__runtimeData.strings, packet->data);
}
// Store in string table.
shput(__runtimeData.strings, packet->data, strdup(&packet->data[strlen(packet->data) + 1]));
break;
case PACKET_TYPE_VERSION:
packetContentUnpack(packet->data, "i", &__runtimeData.protocolVersion);
// Do we need to update?
if (PACKET_PROTOCOL_VERSION == __runtimeData.protocolVersion) {
// Nope, we're good.
encoded.packetType = PACKET_TYPE_VERSION_OKAY;
} else {
// Version mismatch - upgrade time!
encoded.packetType = PACKET_TYPE_VERSION_BAD;
// ***TODO***
}
encoded.control = PACKET_CONTROL_DAT;
encoded.channel = 0;
encoded.encrypt = 0;
packetEncode(__packetThreadData, &encoded, NULL, 0);
// Send GOOD or BAD.
packetSend(__packetThreadData, &encoded);
break;
default:
logWrite("Unexpected packet received: %d\n", packet->packetType);
break;
}
packetDecodeDataDestroy(&packet);
}
@ -104,9 +193,7 @@ static void settingsFinished(WidgetT *widget) {
}
void taskWelcome(void *data) {
(void)data;
void welcomeShow(void) {
// 450x128 logo
@ -150,10 +237,14 @@ void taskWelcome(void *data) {
T_BUTTON, O(_btnConnect),
T_TITLE, P("Connect"),
T_X, 379, T_Y, 157,
T_CLICK, P(taskProxy),
T_USER_DATA, P(taskConnectClick),
T_CLICK, P(btnConnectClick),
T_ENABLED, (__configData.serialCom > 0 && strlen(__configData.serverHost) > 2) ? T_TRUE : T_FALSE,
T_BUTTON, T_DONE,
T_TIMER, O(_timProgress),
T_EVENT, P(timWelcomeProgress),
T_VALUE, 0,
T_ENABLED, 0,
T_TIMER, T_DONE,
T_WINDOW, T_DONE,
T_END
@ -163,59 +254,128 @@ void taskWelcome(void *data) {
}
static void taskConnectClick(void *data) {
static void timWelcomeProgress(WidgetT *widget) {
TimerT *t = (TimerT *)widget;
int32_t r = 0;
int16_t timeout = 0;
(void)data;
uint32_t len = 0;
static char buffer[1024] = { 0 };
static uint16_t offset = 0;
switch (_state) {
case S_START_CONNECT:
// Ghost all buttons.
widgetEnableSet(W(_btnConnect), 0);
widgetEnableSet(W(_btnSettings), 0);
widgetEnableSet(W(_btnQuit), 0);
// Hide welcome banner, show init.
widgetVisibleSet(W(_picLogo), 0);
widgetVisibleSet(W(_picInit), 1);
taskYield();
_state = S_START_INIT_MODEM;
break;
r = netConnectStep1();
if (r == NETWORK_CONNECT_OPEN_FAILED) {
case S_START_INIT_MODEM:
// Open COM port.
r = comOpen(__configData.serialCom - 1, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
if (r != SER_SUCCESS) {
timerStop(t);
msgBoxOne("COM Problem", MSGBOX_ICON_ERROR, "Unable to open COM port!\nPlease check settings.", "Okay", btnMsgBox);
return;
}
if (r == NETWORK_CONNECT_BAD_MODEM) {
msgBoxOne("Modem Problem", MSGBOX_ICON_ERROR, "Modem does not support ENET!\nPlease check settings.", "Okay", btnMsgBox);
return;
break;
}
// Send a CR to clear anything in the modem.
snprintf(buffer, 1023, "%c", 13);
comWrite(__configData.serialCom - 1, buffer, strlen(buffer));
timerQuarterSecondsSet(t, 4);
_state = S_INIT_MODEM;
break;
case S_INIT_MODEM:
// Just read anything to clear the buffer.
len = comRead(__configData.serialCom - 1, buffer, 1023);
// Send actual init
snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13);
comWrite(__configData.serialCom - 1, buffer, strlen(buffer));
_state = S_INIT_RESULT;
break;
case S_INIT_RESULT:
len = comRead(__configData.serialCom - 1, buffer, 1023);
buffer[len] = 0;
if (strstr(buffer, "OK") == NULL) {
comClose(__configData.serialCom - 1);
timerStop(t);
msgBoxOne("Modem Problem", MSGBOX_ICON_ERROR, "Modem does not support ENET!\nPlease check settings.", "Okay", btnMsgBox);
break;
}
// Show dialing, dial service.
widgetVisibleSet(W(_picDialing), 1);
taskYield();
timerQuarterSecondsSet(t, 0);
_state = S_DIAL;
break;
r = netConnectStep2();
if (r == NETWORK_CONNECT_NO_CARRIER) {
case S_DIAL:
snprintf(buffer, 1023, "ATDT%s:%d%c", __configData.serverHost, __configData.serverPort, 13);
comWrite(__configData.serialCom - 1, buffer, strlen(buffer));
timerQuarterSecondsSet(t, 0); // Run as fast as we can so we don't miss any data.
offset = 0;
_timeoutCounter = 7 * 4; // Seven seconds.
_state = S_WAIT_FOR_BANNER;
break;
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);
offset += len;
buffer[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) {
// Connect! Start packet handler and negotiate encryption.
netPacketHandlerStart();
packetEncryptionSetup(__packetThreadData);
// Watch system channel for packets.
netChannelSystemGet(packetHandler);
timerQuarterSecondsSet(t, 1);
_timeoutCounter = 5 * 4; // Five seconds.
_state = S_WAIT_FOR_ENCRYPTION;
break;
}
// Did we time out?
if (guiTimerQuarterSecondTick()) _timeoutCounter--;
if (_timeoutCounter == 0) {
comClose(__configData.serialCom - 1);
timerStop(t);
msgBoxOne("No Connection", MSGBOX_ICON_INFORMATION, "Unable to connect to server!\nPlease check settings or try later.", "Okay", btnMsgBox);
return;
}
if (r == NETWORK_CONNECT_BAD_ENCRYPTION) {
break;
case S_WAIT_FOR_ENCRYPTION:
if (packetEncryptionReady()) {
timerQuarterSecondsSet(t, 5 * 4);
_state = S_WAIT_FOR_DATA_TIMEOUT;
break;
}
// Did we time out?
_timeoutCounter--;
if (_timeoutCounter == 0) {
netPacketHandlerStop();
comClose(__configData.serialCom - 1);
timerStop(t);
msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to negotiate encryption settings!", "Okay", btnMsgBox);
return;
}
if (r == NETWORK_CONNECT_BAD_SETTINGS) {
break;
case S_WAIT_FOR_DATA_TIMEOUT:
netPacketHandlerStop();
comClose(__configData.serialCom - 1);
timerStop(t);
msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to fetch client settings!", "Okay", btnMsgBox);
return;
}
// Connected! Show icon.
widgetVisibleSet(W(_picConnect), 1);
timeout = 6; // Roughly 1.5 seconds.
while (timeout > 0 && !guiHasStopped()) {
taskYield();
if (__timerQuarterSecondTick) timeout--;
}
break;
case S_WAIT_FOR_ICON:
// Switch to Login window.
timerStop(t);
netChannelSystemRelease(packetHandler);
guiDelete(D(_winWelcome));
taskCreate(taskLogin, NULL);
loginShow();
break;
}
}

View file

@ -25,7 +25,7 @@
#include "os.h"
void taskWelcome(void *data);
void welcomeShow(void);
#endif // WELCOME_H

View file

@ -1,4 +1,4 @@
Title: Chat
Title: Discord
----

View file

@ -0,0 +1,5 @@
Title: Matrix
----
Redirect: https://matrix.to/#/#DosGame:matrix.kangaroopunch.com

View file

@ -0,0 +1 @@
Title: Chat

View file

@ -57,6 +57,7 @@ function kpApiUserLogin($username, $pass, &$response) {
// Find user by name instead of email.
$user = kirby()->users()->filterBy('name', $username)->first();
if ($user) {
// ***TODO*** Must be activated!
// Attempt to sign them in.
kirby()->auth()->login($user->email(), $pass);
// They don't need an actual Kirby session, so log them off.

View file

@ -23,6 +23,11 @@ return [
switch (get('command')) {
case 'API_AVAILABLE':
$response['result'] = 'true';
$response['reason'] = 'API Available.';
break;
case 'API_TEST':
kpApiTest($response);
break;

View file

@ -12,8 +12,8 @@
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"><?= $item->title() ?></a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<?php foreach($item->children()->listed()->flip() as $child): ?>
<li><a class="dropdown-item" href="<?= $child->url() ?>"><?= $child->year() ?> - <?= $child->title() ?></a></li>
<?php foreach($item->children()->listed() as $child): ?>
<li><a class="dropdown-item" href="<?= $child->url() ?>"><?= $child->title() ?></a></li>
<?php endforeach ?>
</ul>
</li>

View file

@ -0,0 +1,5 @@
<html>
<head>
<meta http-equiv="refresh" content="0; url=/" />
</head>
</html>

View file

@ -37,14 +37,7 @@ typedef void (*clientApi)(ClientThreadT *client, PacketDecodeDataT *data);
// Also update enum in packets.h!
clientApi clientApiMethod[PACKET_END_OF_SERVER_PACKETS - PACKET_END_OF_DUAL_PACKETS] = {
clientApiClientShutdown,
clientApiLogin,
clientApiPong,
clientApiSignup,
clientApiVersionBad,
clientApiVersionOkay
};
static clientApi _clientApiMethod[PACKET_TYPE_COUNT];
static uint8_t clientDequeuePacket(ClientThreadT *client);
@ -68,8 +61,8 @@ static uint8_t clientDequeuePacket(ClientThreadT *client) {
// New data or not, process anything in the queue.
if (packetDecode(client->packetThreadData, &decode, data, length)) {
if ((decode.packetType > PACKET_END_OF_DUAL_PACKETS) && (decode.packetType < PACKET_END_OF_SERVER_PACKETS)) {
clientApiMethod[decode.packetType - (PACKET_END_OF_DUAL_PACKETS + 1)](client, &decode);
if (_clientApiMethod[decode.packetType]) {
_clientApiMethod[decode.packetType](client, &decode);
} else {
consoleMessageQueue("%ld: Channel %d Unknown Packet %d\n", client->threadIndex, decode.channel, decode.packetType);
}
@ -103,6 +96,23 @@ void clientQueuePacket(ClientThreadT *client, uint8_t *data, uint32_t length) {
}
void clientShutdown(void) {
// Nothing yet.
}
void clientStartup(void) {
memset(_clientApiMethod, 0, sizeof(_clientApiMethod));
_clientApiMethod[PACKET_TYPE_CLIENT_SHUTDOWN] = clientApiClientShutdown;
_clientApiMethod[PACKET_TYPE_LOGIN] = clientApiLogin;
_clientApiMethod[PACKET_TYPE_PONG] = clientApiPong;
_clientApiMethod[PACKET_TYPE_SIGNUP] = clientApiSignup;
_clientApiMethod[PACKET_TYPE_VERSION_BAD] = clientApiVersionBad;
_clientApiMethod[PACKET_TYPE_VERSION_OKAY] = clientApiVersionOkay;
}
void *clientThread(void *data) {
ENetPeer *peer = (ENetPeer *)data;
@ -134,6 +144,7 @@ void *clientThread(void *data) {
packetSend(client->packetThreadData, &encoded);
DEL(packetData);
versionSent = 1;
consoleMessageQueue("PACKET_TYPE_VERSION sent.\n");
}
}

View file

@ -53,6 +53,8 @@ typedef struct ClientThreadS {
void clientQueuePacket(ClientThreadT *client, uint8_t *data, uint32_t length);
void clientShutdown(void);
void clientStartup(void);
void *clientThread(void *data);

View file

@ -56,7 +56,7 @@ void clientApiLogin(ClientThreadT *client, PacketDecodeDataT *data) {
// Build packet.
encoded.control = PACKET_CONTROL_DAT;
encoded.packetType = PACKET_TYPE_LOGIN_RESULT;
encoded.channel = 0;
encoded.channel = data->channel;
encoded.encrypt = 0;
packetEncode(client->packetThreadData, &encoded, packetData, length);
// Send it.

View file

@ -59,7 +59,7 @@ void clientApiSignup(ClientThreadT *client, PacketDecodeDataT *data) {
// Build packet.
encoded.control = PACKET_CONTROL_DAT;
encoded.packetType = PACKET_TYPE_SIGNUP_RESULT;
encoded.channel = 0;
encoded.channel = data->channel;
encoded.encrypt = 0;
packetEncode(client->packetThreadData, &encoded, packetData, length);
// Send it.

View file

@ -72,12 +72,13 @@ void clientApiVersionOkay(ClientThreadT *client, PacketDecodeDataT *data) {
// Build packet.
encoded.control = PACKET_CONTROL_DAT;
encoded.packetType = PACKET_TYPE_STRING;
encoded.channel = 0;
encoded.channel = data->channel;
encoded.encrypt = 0;
packetEncode(client->packetThreadData, &encoded, buffer, length);
// Send it.
packetSend(client->packetThreadData, &encoded);
DEL(buffer);
consoleMessageQueue("PACKET_TYPE_STRING [%s] sent.\n", strings[i].key);
}
restHelperConfigStringMapRelease(strings);
@ -111,22 +112,23 @@ void clientApiVersionOkay(ClientThreadT *client, PacketDecodeDataT *data) {
// Build packet.
encoded.control = PACKET_CONTROL_DAT;
encoded.packetType = PACKET_TYPE_NUMBER;
encoded.channel = 0;
encoded.channel = data->channel;
encoded.encrypt = 0;
packetEncode(client->packetThreadData, &encoded, buffer, length);
// Send it.
packetSend(client->packetThreadData, &encoded);
DEL(buffer);
consoleMessageQueue("PACKET_TYPE_NUMBER [%s] sent.\n", integers[i].key);
}
restHelperConfigIntegerMapRelease(integers);
// Build PROCEED packet.
encoded.control = PACKET_CONTROL_DAT;
encoded.packetType = PACKET_TYPE_PROCEED;
encoded.channel = 0;
encoded.channel = data->channel;
encoded.encrypt = 0;
packetEncode(client->packetThreadData, &encoded, NULL, 0);
// Send it.
packetSend(client->packetThreadData, &encoded);
consoleMessageQueue("PACKET_TYPE_PROCEED sent.\n");
}

View file

@ -109,6 +109,7 @@ int main(int argc, char *argv[]) {
settingsClientVersion = restHelperConfigIntegerGet(response, "clientVersion", 1);
restRelease(response);
clientStartup();
serverStartup(settingsPortNumber, settingsMaxClients);
logWrite("Server online.\n");
@ -121,6 +122,7 @@ int main(int argc, char *argv[]) {
// Wait for all running threads to shut down.
logWrite("Shutting down.\n");
serverShutdown();
clientShutdown();
// Shut down.
restShutdown();

View file

@ -276,6 +276,7 @@ void restShutdown(void) {
uint8_t restStartup(char *url, char *user, char *password) {
uint64_t i;
json_object *response;
curl_global_init(CURL_GLOBAL_ALL);
@ -299,6 +300,11 @@ uint8_t restStartup(char *url, char *user, char *password) {
_restUser = strdup(user);
_restPass = strdup(password);
// Is the remote server there?
response = restRequest("API_AVAILABLE", NULL);
if (!response) return FAIL;
restRelease(response);
return SUCCESS;
}

View file

@ -134,8 +134,9 @@ void *serverThread(void *data) {
// Tell the console.
enet_address_get_host_ip(&event.peer->address, buffer, 2047);
consoleMessageQueue("%ld: [%s] connected.\n", client->threadIndex, buffer);
// ***TODO*** Should probably cleanly handle a full server here with some kind of SERVER_FULL packet.
// Send banner to client.
packet = enet_packet_create("KPMPGSMKII\r", 11, ENET_PACKET_FLAG_RELIABLE);
packet = enet_packet_create("KPMPGSMKII\rOKAY\r", 16, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(event.peer, 0, packet);
break;

View file

@ -78,11 +78,11 @@ void logWrite(char *format, ...) {
vsnprintf(_logBuffer, _logBufferSize, format, args2);
}
#ifdef __linux__
//#ifdef __linux__
// Also output to stdout on Linux.
fprintf(stdout, "%s", _logBuffer);
fflush(stdout);
#endif
//#endif
if (_logCallback) _logCallback(_logBuffer);

View file

@ -78,7 +78,6 @@ char *packetContentPack(uint16_t *length, char *format, ...) {
static char work[PACKET_MAX] = { 0 };
char *result = NULL;
char *buffer = NULL;
int8_t value8 = 0;
int32_t value32 = 0;
*length = 0;
@ -123,7 +122,6 @@ char *packetContentPack(uint16_t *length, char *format, ...) {
void packetContentUnpack(char *buffer, char *format, ...) {
va_list args = { 0 };
char **string = NULL;
int8_t *value8 = NULL;
int32_t *value32 = NULL;
uint16_t length = 0;

View file

@ -31,22 +31,19 @@
// This enum is treated as BYTES in the code. Do not go over 255 entries.
// Also update array in client.c!
typedef enum PacketTypeE {
// Packets that can received by both server and client:
// These packets have to be first and in this order! Do not change them!
PACKET_TYPE_NONE = 0, // No packet.
PACKET_TYPE_DH_REQUEST,
PACKET_TYPE_DH_RESPONSE,
PACKET_END_OF_DUAL_PACKETS,
PACKET_TYPE_VERSION,
PACKET_TYPE_VERSION_BAD,
PACKET_TYPE_VERSION_OKAY,
// Packets received by only the server:
PACKET_TYPE_CLIENT_SHUTDOWN,
PACKET_TYPE_LOGIN,
PACKET_TYPE_PONG,
PACKET_TYPE_SIGNUP,
PACKET_TYPE_VERSION_BAD,
PACKET_TYPE_VERSION_OKAY,
PACKET_END_OF_SERVER_PACKETS,
// Packets received by only the client:
PACKET_TYPE_LOGIN_RESULT,
@ -56,7 +53,6 @@ typedef enum PacketTypeE {
PACKET_TYPE_SERVER_SHUTDOWN,
PACKET_TYPE_SIGNUP_RESULT,
PACKET_TYPE_STRING,
PACKET_TYPE_VERSION,
// How many packet types do we recognize?
PACKET_TYPE_COUNT

View file

@ -1,2 +1,4 @@
#!/bin/bash
${HOME}/code/dosbox-custom/dosbox-staging/build/dosbox -noprimaryconf -nolocalconf -conf test.conf &
#${HOME}/code/dosbox-custom/dosbox-staging/build/dosbox -noprimaryconf -nolocalconf -conf test.conf &
#dosbox -noprimaryconf -nolocalconf -conf test.conf &
${HOME}/bin/dosbox-staging-linux-v0.78.1/dosbox -noprimaryconf -nolocalconf -conf test.conf &