Working on First Run Setup.

This commit is contained in:
Scott Duensing 2022-01-18 20:59:22 -06:00
parent 1beebe629c
commit ecf6d1f842
40 changed files with 1133 additions and 369 deletions

1
.gitattributes vendored
View file

@ -3,3 +3,4 @@
*.xcf filter=lfs diff=lfs merge=lfs -text
*.odg filter=lfs diff=lfs merge=lfs -text
*.xlsx filter=lfs diff=lfs merge=lfs -text
*.dat filter=lfs diff=lfs merge=lfs -text

86
buildPrerequisites.sh Executable file
View file

@ -0,0 +1,86 @@
#!/bin/bash -ex
#
# 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/>.
#
function createEmbeddedBinary() {
local BINFILE=$1
local BINEXTENSION=$2
local TARGETDIR=$3
local SOURCEFILE="$3/${1,,}.h"
local BLOCKER="${1^^}_${2^^}_H"
outputLicense > ${SOURCEFILE}
outputHeader ${BLOCKER} >> ${SOURCEFILE}
printf "\n#ifdef EMBED_HERE\n\n" >> ${SOURCEFILE}
xxd -i ${BINFILE}.${BINEXTENSION} >> ${SOURCEFILE}
printf "\n#else // EMBED_HERE\n\n" >> ${SOURCEFILE}
printf "extern unsigned char ${BINFILE}_${BINEXTENSION}[];\n" >> ${SOURCEFILE}
printf "extern unsigned int ${BINFILE}_${BINEXTENSION}_len;\n" >> ${SOURCEFILE}
printf "\n#endif // EMBED_HERE\n\n" >> ${SOURCEFILE}
outputFooter ${BLOCKER} >> ${SOURCEFILE}
}
function outputFooter() {
local BLOCKER=$1
printf "\n#pragma GCC diagnostic pop\n\n\n#endif // ${BLOCKER}\n"
}
function outputHeader() {
local BLOCKER=$1
printf "\n\n#ifndef ${BLOCKER}\n#define ${BLOCKER}\n\n\n"
printf "// ===== THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT =====\n\n\n"
printf "#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wunused-variable\"\n"
}
function outputLicense() {
cat <<-LICENSE
/*
* 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/>.
*
*/
LICENSE
}
pushd font/data
createEmbeddedBinary vga8x14 dat ../../client/src/embedded
popd

View file

@ -68,6 +68,8 @@ HEADERS = \
$$SHARED/packets.h \
src/config.h \
$$SHARED/util.h \
src/embedded/vga8x14.h \
src/firstrun.h \
src/gui/msgbox.h \
src/login.h \
src/menu.h \
@ -117,6 +119,8 @@ SOURCES = \
$$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 \
@ -158,10 +162,8 @@ LIBS = \
OTHER_FILES = \
$$DOS_HEADERS \
$$DOS_SOURCES \
../Makefile.djgpp \
../build.sh \
../test.sh \
../test.conf \
postBuild.sh
QMAKE_POST_LINK = $$PWD/postBuild.sh "$$PWD" "$$DESTDIR"
DISTFILES +=

View file

@ -0,0 +1,22 @@
/*
* 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 EMBED_HERE
#include "vga8x14.h"

View file

@ -0,0 +1,347 @@
/*
* 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 VGA8X14_DAT_H
#define VGA8X14_DAT_H
// ===== THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT =====
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#ifdef EMBED_HERE
unsigned char vga8x14_dat[] = {
0x08, 0x0e, 0x10, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7e, 0x7e, 0x00, 0x00, 0x18, 0x18, 0x00, 0xff, 0x00, 0xff, 0x1e,
0x3c, 0x3f, 0x7f, 0x18, 0x00, 0x81, 0xff, 0x6c, 0x10, 0x3c, 0x3c, 0x00,
0xff, 0x00, 0xff, 0x0e, 0x66, 0x33, 0x63, 0x18, 0x00, 0xa5, 0xdb, 0xfe,
0x38, 0x3c, 0x7e, 0x00, 0xff, 0x3c, 0xc3, 0x1a, 0x66, 0x3f, 0x7f, 0xdb,
0x00, 0x81, 0xff, 0xfe, 0x7c, 0xe7, 0xff, 0x18, 0xe7, 0x66, 0x99, 0x32,
0x66, 0x30, 0x63, 0x3c, 0x00, 0x81, 0xff, 0xfe, 0xfe, 0xe7, 0xff, 0x3c,
0xc3, 0x42, 0xbd, 0x78, 0x3c, 0x30, 0x63, 0xe7, 0x00, 0xbd, 0xc3, 0xfe,
0x7c, 0xe7, 0x7e, 0x3c, 0xc3, 0x42, 0xbd, 0xcc, 0x18, 0x30, 0x63, 0x3c,
0x00, 0x99, 0xe7, 0x7c, 0x38, 0x18, 0x18, 0x18, 0xe7, 0x66, 0x99, 0xcc,
0x7e, 0x70, 0x67, 0xdb, 0x00, 0x81, 0xff, 0x38, 0x10, 0x18, 0x18, 0x00,
0xff, 0x3c, 0xc3, 0xcc, 0x18, 0xf0, 0xe7, 0x18, 0x00, 0x7e, 0x7e, 0x10,
0x00, 0x3c, 0x3c, 0x00, 0xff, 0x00, 0xff, 0x78, 0x18, 0xe0, 0xe6, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00,
0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x18, 0x66,
0x7f, 0xc6, 0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc0, 0x06, 0x3c, 0x66, 0xdb, 0x60, 0x00, 0x3c, 0x3c, 0x18, 0x00, 0x00,
0x00, 0x00, 0x10, 0xfe, 0xe0, 0x0e, 0x7e, 0x66, 0xdb, 0x38, 0x00, 0x7e,
0x7e, 0x18, 0x18, 0x30, 0x00, 0x28, 0x38, 0xfe, 0xf8, 0x3e, 0x18, 0x66,
0xdb, 0x6c, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x60, 0xc0, 0x6c, 0x38, 0x7c,
0xfe, 0xfe, 0x18, 0x66, 0x7b, 0xc6, 0x00, 0x18, 0x18, 0x18, 0xfe, 0xfe,
0xc0, 0xfe, 0x7c, 0x7c, 0xf8, 0x3e, 0x18, 0x66, 0x1b, 0xc6, 0x00, 0x18,
0x18, 0x18, 0x0c, 0x60, 0xc0, 0x6c, 0x7c, 0x38, 0xe0, 0x0e, 0x7e, 0x00,
0x1b, 0x6c, 0xfe, 0x7e, 0x18, 0x7e, 0x18, 0x30, 0xfe, 0x28, 0xfe, 0x38,
0xc0, 0x06, 0x3c, 0x66, 0x1b, 0x38, 0xfe, 0x3c, 0x18, 0x3c, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x10, 0x80, 0x02, 0x18, 0x66, 0x1b, 0x0c, 0xfe, 0x18,
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc6, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x6c, 0x7c, 0x00, 0x38, 0x30,
0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3c, 0x66, 0x6c,
0xc6, 0x00, 0x6c, 0x30, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
0x00, 0x3c, 0x24, 0xfe, 0xc2, 0xc2, 0x6c, 0x60, 0x30, 0x0c, 0x66, 0x18,
0x00, 0x00, 0x00, 0x0c, 0x00, 0x3c, 0x00, 0x6c, 0xc0, 0xc6, 0x38, 0x00,
0x30, 0x0c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x6c,
0x7c, 0x0c, 0x76, 0x00, 0x30, 0x0c, 0xff, 0x7e, 0x00, 0xfe, 0x00, 0x30,
0x00, 0x18, 0x00, 0x6c, 0x06, 0x18, 0xdc, 0x00, 0x30, 0x0c, 0x3c, 0x18,
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xfe, 0x86, 0x30, 0xcc, 0x00,
0x30, 0x0c, 0x66, 0x18, 0x18, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x6c,
0xc6, 0x66, 0xcc, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x18, 0x80,
0x00, 0x18, 0x00, 0x6c, 0x7c, 0xc6, 0x76, 0x00, 0x0c, 0x30, 0x00, 0x00,
0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7c, 0x18, 0x7c, 0x7c, 0x0c, 0xfe, 0x38, 0xfe, 0x7c, 0x7c, 0x00, 0x00,
0x06, 0x00, 0x60, 0x7c, 0xc6, 0x38, 0xc6, 0xc6, 0x1c, 0xc0, 0x60, 0xc6,
0xc6, 0xc6, 0x18, 0x18, 0x0c, 0x00, 0x30, 0xc6, 0xce, 0x78, 0x06, 0x06,
0x3c, 0xc0, 0xc0, 0x06, 0xc6, 0xc6, 0x18, 0x18, 0x18, 0x00, 0x18, 0xc6,
0xde, 0x18, 0x0c, 0x06, 0x6c, 0xc0, 0xc0, 0x0c, 0xc6, 0xc6, 0x00, 0x00,
0x30, 0x7e, 0x0c, 0x0c, 0xf6, 0x18, 0x18, 0x3c, 0xcc, 0xfc, 0xfc, 0x18,
0x7c, 0x7e, 0x00, 0x00, 0x60, 0x00, 0x06, 0x18, 0xe6, 0x18, 0x30, 0x06,
0xfe, 0x06, 0xc6, 0x30, 0xc6, 0x06, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x18,
0xc6, 0x18, 0x60, 0x06, 0x0c, 0x06, 0xc6, 0x30, 0xc6, 0x06, 0x18, 0x18,
0x18, 0x7e, 0x18, 0x00, 0xc6, 0x18, 0xc6, 0xc6, 0x0c, 0xc6, 0xc6, 0x30,
0xc6, 0x0c, 0x18, 0x18, 0x0c, 0x00, 0x30, 0x18, 0x7c, 0x7e, 0xfe, 0x7c,
0x1e, 0x7c, 0x7c, 0x30, 0x7c, 0x78, 0x00, 0x30, 0x06, 0x00, 0x60, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0xfc, 0x3c,
0xf8, 0xfe, 0xfe, 0x3c, 0xc6, 0x3c, 0x1e, 0xe6, 0xf0, 0xc6, 0xc6, 0x38,
0xc6, 0x38, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x66, 0xc6, 0x18, 0x0c, 0x66,
0x60, 0xee, 0xe6, 0x6c, 0xc6, 0x6c, 0x66, 0xc2, 0x66, 0x62, 0x62, 0xc2,
0xc6, 0x18, 0x0c, 0x6c, 0x60, 0xfe, 0xf6, 0xc6, 0xde, 0xc6, 0x66, 0xc0,
0x66, 0x68, 0x68, 0xc0, 0xc6, 0x18, 0x0c, 0x6c, 0x60, 0xfe, 0xfe, 0xc6,
0xde, 0xc6, 0x7c, 0xc0, 0x66, 0x78, 0x78, 0xc0, 0xfe, 0x18, 0x0c, 0x78,
0x60, 0xd6, 0xde, 0xc6, 0xde, 0xfe, 0x66, 0xc0, 0x66, 0x68, 0x68, 0xde,
0xc6, 0x18, 0x0c, 0x6c, 0x60, 0xc6, 0xce, 0xc6, 0xdc, 0xc6, 0x66, 0xc2,
0x66, 0x62, 0x60, 0xc6, 0xc6, 0x18, 0xcc, 0x6c, 0x62, 0xc6, 0xc6, 0xc6,
0xc0, 0xc6, 0x66, 0x66, 0x6c, 0x66, 0x60, 0x66, 0xc6, 0x18, 0xcc, 0x66,
0x66, 0xc6, 0xc6, 0x6c, 0x7c, 0xc6, 0xfc, 0x3c, 0xf8, 0xfe, 0xf0, 0x3a,
0xc6, 0x3c, 0x78, 0xe6, 0xfe, 0xc6, 0xc6, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x00, 0xfc, 0x7c, 0xfc, 0x7c, 0x7e, 0xc6, 0xc6, 0xc6,
0xc6, 0x66, 0xfe, 0x3c, 0x80, 0x3c, 0x6c, 0x00, 0x66, 0xc6, 0x66, 0xc6,
0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0x66, 0xc6, 0x30, 0xc0, 0x0c, 0xc6, 0x00,
0x66, 0xc6, 0x66, 0xc6, 0x5a, 0xc6, 0xc6, 0xc6, 0x6c, 0x66, 0x8c, 0x30,
0xe0, 0x0c, 0x00, 0x00, 0x66, 0xc6, 0x66, 0x60, 0x18, 0xc6, 0xc6, 0xc6,
0x38, 0x66, 0x18, 0x30, 0x70, 0x0c, 0x00, 0x00, 0x7c, 0xc6, 0x7c, 0x38,
0x18, 0xc6, 0xc6, 0xd6, 0x38, 0x3c, 0x30, 0x30, 0x38, 0x0c, 0x00, 0x00,
0x60, 0xd6, 0x6c, 0x0c, 0x18, 0xc6, 0xc6, 0xd6, 0x38, 0x18, 0x60, 0x30,
0x1c, 0x0c, 0x00, 0x00, 0x60, 0xde, 0x66, 0xc6, 0x18, 0xc6, 0x6c, 0xfe,
0x6c, 0x18, 0xc2, 0x30, 0x0e, 0x0c, 0x00, 0x00, 0x60, 0x7c, 0x66, 0xc6,
0x18, 0xc6, 0x38, 0x7c, 0xc6, 0x18, 0xc6, 0x30, 0x06, 0x0c, 0x00, 0x00,
0xf0, 0x0c, 0xe6, 0x7c, 0x3c, 0x7c, 0x10, 0x6c, 0xc6, 0x3c, 0xfe, 0x3c,
0x02, 0x3c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0xe0, 0x00, 0x1c, 0x00, 0x38, 0x00, 0xe0, 0x18, 0x06, 0xe0,
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0c, 0x00, 0x6c, 0x00,
0x60, 0x18, 0x06, 0x60, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
0x0c, 0x00, 0x64, 0x00, 0x60, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x00,
0x00, 0x78, 0x78, 0x7c, 0x3c, 0x7c, 0x60, 0x76, 0x6c, 0x38, 0x0e, 0x66,
0x18, 0xec, 0xdc, 0x7c, 0x00, 0x0c, 0x6c, 0xc6, 0x6c, 0xc6, 0xf0, 0xcc,
0x76, 0x18, 0x06, 0x6c, 0x18, 0xfe, 0x66, 0xc6, 0x00, 0x7c, 0x66, 0xc0,
0xcc, 0xfe, 0x60, 0xcc, 0x66, 0x18, 0x06, 0x78, 0x18, 0xd6, 0x66, 0xc6,
0x00, 0xcc, 0x66, 0xc0, 0xcc, 0xc0, 0x60, 0xcc, 0x66, 0x18, 0x06, 0x6c,
0x18, 0xd6, 0x66, 0xc6, 0x00, 0xcc, 0x66, 0xc6, 0xcc, 0xc6, 0x60, 0x7c,
0x66, 0x18, 0x06, 0x66, 0x18, 0xd6, 0x66, 0xc6, 0x00, 0x76, 0x7c, 0x7c,
0x76, 0x7c, 0xf0, 0x0c, 0xe6, 0x3c, 0x66, 0xe6, 0x3c, 0xc6, 0x66, 0x7c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x66, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x18, 0x70, 0x76, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x18, 0x18, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00, 0x10, 0xdc, 0x76, 0xdc, 0x7c,
0xfc, 0xcc, 0x66, 0xc6, 0xc6, 0xc6, 0xfe, 0x18, 0x18, 0x18, 0x00, 0x38,
0x66, 0xcc, 0x76, 0xc6, 0x30, 0xcc, 0x66, 0xc6, 0x6c, 0xc6, 0xcc, 0x70,
0x00, 0x0e, 0x00, 0x6c, 0x66, 0xcc, 0x66, 0x70, 0x30, 0xcc, 0x66, 0xd6,
0x38, 0xc6, 0x18, 0x18, 0x18, 0x18, 0x00, 0xc6, 0x66, 0xcc, 0x60, 0x1c,
0x30, 0xcc, 0x66, 0xd6, 0x38, 0xc6, 0x30, 0x18, 0x18, 0x18, 0x00, 0xc6,
0x7c, 0x7c, 0x60, 0xc6, 0x36, 0xcc, 0x3c, 0xfe, 0x6c, 0x7e, 0x66, 0x18,
0x18, 0x18, 0x00, 0xfe, 0x60, 0x0c, 0xf0, 0x7c, 0x1c, 0x76, 0x18, 0x6c,
0xc6, 0x06, 0xfe, 0x0e, 0x18, 0x70, 0x00, 0x00, 0x60, 0x0c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xf0, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
0x00, 0x00, 0x0c, 0x10, 0x00, 0x60, 0x38, 0x00, 0x10, 0x00, 0x60, 0x00,
0x18, 0x60, 0xc6, 0x6c, 0x3c, 0xcc, 0x18, 0x38, 0xcc, 0x30, 0x6c, 0x00,
0x38, 0xcc, 0x30, 0x66, 0x3c, 0x30, 0xc6, 0x38, 0x66, 0xcc, 0x30, 0x6c,
0xcc, 0x18, 0x38, 0x00, 0x6c, 0xcc, 0x18, 0x66, 0x66, 0x18, 0x10, 0x00,
0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x38, 0xc0, 0xcc, 0x7c, 0x78, 0x78, 0x78, 0x78, 0x66,
0x7c, 0x7c, 0x7c, 0x38, 0x38, 0x38, 0x6c, 0x6c, 0xc0, 0xcc, 0xc6, 0x0c,
0x0c, 0x0c, 0x0c, 0x60, 0xc6, 0xc6, 0xc6, 0x18, 0x18, 0x18, 0xc6, 0xc6,
0xc2, 0xcc, 0xfe, 0x7c, 0x7c, 0x7c, 0x7c, 0x66, 0xfe, 0xfe, 0xfe, 0x18,
0x18, 0x18, 0xc6, 0xc6, 0x66, 0xcc, 0xc0, 0xcc, 0xcc, 0xcc, 0xcc, 0x3c,
0xc0, 0xc0, 0xc0, 0x18, 0x18, 0x18, 0xfe, 0xfe, 0x3c, 0xcc, 0xc6, 0xcc,
0xcc, 0xcc, 0xcc, 0x0c, 0xc6, 0xc6, 0xc6, 0x18, 0x18, 0x18, 0xc6, 0xc6,
0x0c, 0x76, 0x7c, 0x76, 0x76, 0x76, 0x76, 0x06, 0x7c, 0x7c, 0x7c, 0x3c,
0x3c, 0x3c, 0xc6, 0xc6, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10,
0x00, 0x60, 0x30, 0x60, 0x00, 0xc6, 0xc6, 0x18, 0x38, 0x00, 0xf8, 0x0e,
0x60, 0x00, 0x3e, 0x38, 0xc6, 0x30, 0x78, 0x30, 0xc6, 0xc6, 0xc6, 0x18,
0x6c, 0x66, 0xcc, 0x1b, 0x00, 0x00, 0x6c, 0x6c, 0xc6, 0x18, 0xcc, 0x18,
0xc6, 0x38, 0x00, 0x3c, 0x64, 0x66, 0xcc, 0x18, 0xfe, 0xcc, 0xcc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0x66, 0x60, 0x3c, 0xf8, 0x18,
0x66, 0x76, 0xcc, 0x7c, 0x7c, 0x7c, 0xcc, 0xcc, 0xc6, 0xc6, 0xc6, 0x60,
0xf0, 0x18, 0xc4, 0x18, 0x60, 0x36, 0xfe, 0xc6, 0xc6, 0xc6, 0xcc, 0xcc,
0xc6, 0xc6, 0xc6, 0x60, 0x60, 0x7e, 0xcc, 0x7e, 0x7c, 0x7e, 0xcc, 0xc6,
0xc6, 0xc6, 0xcc, 0xcc, 0xc6, 0xc6, 0xc6, 0x66, 0x60, 0x18, 0xde, 0x18,
0x60, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xcc, 0xc6, 0xc6, 0xc6, 0x3c,
0x60, 0x7e, 0xcc, 0x18, 0x66, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xcc,
0x7e, 0x6c, 0xc6, 0x18, 0xe6, 0x18, 0xcc, 0x18, 0xfe, 0x6e, 0xce, 0x7c,
0x7c, 0x7c, 0x76, 0x76, 0x06, 0x38, 0x7c, 0x18, 0xfc, 0x18, 0xc6, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x18, 0x18, 0x00, 0xdc, 0x3c, 0x38,
0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x30, 0x18, 0x30, 0x30,
0x76, 0x00, 0x6c, 0x6c, 0x30, 0x00, 0x00, 0xc0, 0xc0, 0x18, 0x00, 0x00,
0x60, 0x30, 0x60, 0x60, 0xdc, 0xc6, 0x6c, 0x6c, 0x30, 0x00, 0x00, 0xc6,
0xc6, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x3e, 0x38,
0x00, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x36, 0xd8, 0x78, 0x38, 0x7c, 0xcc,
0xdc, 0xf6, 0x00, 0x00, 0x30, 0x00, 0x00, 0xd8, 0xd8, 0x18, 0x6c, 0x6c,
0x0c, 0x18, 0xc6, 0xcc, 0x66, 0xfe, 0x7e, 0x7c, 0x30, 0xfe, 0xfe, 0x30,
0x30, 0x18, 0xd8, 0x36, 0x7c, 0x18, 0xc6, 0xcc, 0x66, 0xde, 0x00, 0x00,
0x60, 0xc0, 0x06, 0x60, 0x66, 0x3c, 0x6c, 0x6c, 0xcc, 0x18, 0xc6, 0xcc,
0x66, 0xce, 0x00, 0x00, 0xc6, 0xc0, 0x06, 0xdc, 0xce, 0x3c, 0x36, 0xd8,
0xcc, 0x18, 0xc6, 0xcc, 0x66, 0xc6, 0x00, 0x00, 0xc6, 0xc0, 0x06, 0x86,
0x9e, 0x3c, 0x00, 0x00, 0x76, 0x3c, 0x7c, 0x76, 0x66, 0xc6, 0x00, 0x00,
0x7c, 0x00, 0x00, 0x0c, 0x3e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x55, 0xdd, 0x18,
0x18, 0x18, 0x36, 0x00, 0x00, 0x36, 0x36, 0x00, 0x36, 0x36, 0x18, 0x00,
0x44, 0xaa, 0x77, 0x18, 0x18, 0x18, 0x36, 0x00, 0x00, 0x36, 0x36, 0x00,
0x36, 0x36, 0x18, 0x00, 0x11, 0x55, 0xdd, 0x18, 0x18, 0x18, 0x36, 0x00,
0x00, 0x36, 0x36, 0x00, 0x36, 0x36, 0x18, 0x00, 0x44, 0xaa, 0x77, 0x18,
0x18, 0x18, 0x36, 0x00, 0x00, 0x36, 0x36, 0x00, 0x36, 0x36, 0x18, 0x00,
0x11, 0x55, 0xdd, 0x18, 0x18, 0x18, 0x36, 0x00, 0x00, 0x36, 0x36, 0x00,
0x36, 0x36, 0x18, 0x00, 0x44, 0xaa, 0x77, 0x18, 0x18, 0xf8, 0x36, 0x00,
0xf8, 0xf6, 0x36, 0xfe, 0xf6, 0x36, 0xf8, 0x00, 0x11, 0x55, 0xdd, 0x18,
0x18, 0x18, 0x36, 0x00, 0x18, 0x06, 0x36, 0x06, 0x06, 0x36, 0x18, 0x00,
0x44, 0xaa, 0x77, 0x18, 0xf8, 0xf8, 0xf6, 0xfe, 0xf8, 0xf6, 0x36, 0xf6,
0xfe, 0xfe, 0xf8, 0xf8, 0x11, 0x55, 0xdd, 0x18, 0x18, 0x18, 0x36, 0x36,
0x18, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x18, 0x44, 0xaa, 0x77, 0x18,
0x18, 0x18, 0x36, 0x36, 0x18, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x18,
0x11, 0x55, 0xdd, 0x18, 0x18, 0x18, 0x36, 0x36, 0x18, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x18, 0x44, 0xaa, 0x77, 0x18, 0x18, 0x18, 0x36, 0x36,
0x18, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x18, 0x11, 0x55, 0xdd, 0x18,
0x18, 0x18, 0x36, 0x36, 0x18, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x18,
0x44, 0xaa, 0x77, 0x18, 0x18, 0x18, 0x36, 0x36, 0x18, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, 0x18, 0x18, 0x36,
0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x18, 0x18, 0x18, 0x00, 0x18,
0x00, 0x18, 0x18, 0x36, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x18,
0x18, 0x18, 0x00, 0x18, 0x00, 0x18, 0x18, 0x36, 0x36, 0x00, 0x36, 0x00,
0x36, 0x00, 0x36, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, 0x18, 0x18, 0x36,
0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x18, 0x18, 0x18, 0x00, 0x18,
0x00, 0x18, 0x18, 0x36, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x18,
0x18, 0x18, 0x00, 0x18, 0x00, 0x18, 0x1f, 0x36, 0x37, 0x3f, 0xf7, 0xff,
0x37, 0xff, 0xf7, 0xff, 0x18, 0x18, 0x00, 0x18, 0x00, 0x18, 0x18, 0x36,
0x30, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x1f,
0xff, 0xff, 0x1f, 0x37, 0x3f, 0x37, 0xff, 0xf7, 0x37, 0xff, 0xf7, 0xff,
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x36, 0x00, 0x36, 0x00, 0x36,
0x36, 0x00, 0x36, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x36,
0x00, 0x36, 0x00, 0x36, 0x36, 0x00, 0x36, 0x00, 0x00, 0x00, 0x18, 0x18,
0x00, 0x18, 0x18, 0x36, 0x00, 0x36, 0x00, 0x36, 0x36, 0x00, 0x36, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x36, 0x00, 0x36, 0x00, 0x36,
0x36, 0x00, 0x36, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x36,
0x00, 0x36, 0x00, 0x36, 0x36, 0x00, 0x36, 0x00, 0x00, 0x00, 0x18, 0x18,
0x00, 0x18, 0x18, 0x36, 0x00, 0x36, 0x00, 0x36, 0x36, 0x00, 0x36, 0x00,
0x36, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00, 0x36, 0x18, 0x18, 0x00, 0xff,
0x00, 0xf0, 0x0f, 0xff, 0x36, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00, 0x36,
0x18, 0x18, 0x00, 0xff, 0x00, 0xf0, 0x0f, 0xff, 0x36, 0x00, 0x00, 0x36,
0x18, 0x00, 0x00, 0x36, 0x18, 0x18, 0x00, 0xff, 0x00, 0xf0, 0x0f, 0xff,
0x36, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00, 0x36, 0x18, 0x18, 0x00, 0xff,
0x00, 0xf0, 0x0f, 0xff, 0x36, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00, 0x36,
0x18, 0x18, 0x00, 0xff, 0x00, 0xf0, 0x0f, 0xff, 0x36, 0xff, 0x00, 0x36,
0x1f, 0x1f, 0x00, 0x36, 0xff, 0x18, 0x00, 0xff, 0x00, 0xf0, 0x0f, 0xff,
0x36, 0x00, 0x00, 0x36, 0x18, 0x18, 0x00, 0x36, 0x18, 0x18, 0x00, 0xff,
0x00, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x1f, 0x1f, 0x3f, 0xff,
0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf0, 0x0f, 0x00, 0x00, 0x18, 0x36, 0x00,
0x00, 0x18, 0x36, 0x36, 0x18, 0x00, 0x18, 0xff, 0xff, 0xf0, 0x0f, 0x00,
0x00, 0x18, 0x36, 0x00, 0x00, 0x18, 0x36, 0x36, 0x18, 0x00, 0x18, 0xff,
0xff, 0xf0, 0x0f, 0x00, 0x00, 0x18, 0x36, 0x00, 0x00, 0x18, 0x36, 0x36,
0x18, 0x00, 0x18, 0xff, 0xff, 0xf0, 0x0f, 0x00, 0x00, 0x18, 0x36, 0x00,
0x00, 0x18, 0x36, 0x36, 0x18, 0x00, 0x18, 0xff, 0xff, 0xf0, 0x0f, 0x00,
0x00, 0x18, 0x36, 0x00, 0x00, 0x18, 0x36, 0x36, 0x18, 0x00, 0x18, 0xff,
0xff, 0xf0, 0x0f, 0x00, 0x00, 0x18, 0x36, 0x00, 0x00, 0x18, 0x36, 0x36,
0x18, 0x00, 0x18, 0xff, 0xff, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00,
0x7e, 0x38, 0x38, 0x1e, 0x00, 0x03, 0x1c, 0x00, 0x00, 0x00, 0xc6, 0x00,
0xc6, 0x00, 0x00, 0x00, 0x18, 0x6c, 0x6c, 0x30, 0x00, 0x06, 0x30, 0x7c,
0x00, 0x7c, 0xc6, 0xfe, 0x60, 0x00, 0x66, 0x76, 0x3c, 0xc6, 0xc6, 0x18,
0x00, 0x7e, 0x60, 0xc6, 0x76, 0xc6, 0xc0, 0x6c, 0x30, 0x7e, 0x66, 0xdc,
0x66, 0xc6, 0xc6, 0x0c, 0x7e, 0xdb, 0x60, 0xc6, 0xdc, 0xfc, 0xc0, 0x6c,
0x18, 0xd8, 0x66, 0x18, 0x66, 0xfe, 0xc6, 0x3e, 0xdb, 0xdb, 0x7c, 0xc6,
0xd8, 0xc6, 0xc0, 0x6c, 0x30, 0xd8, 0x66, 0x18, 0x66, 0xc6, 0x6c, 0x66,
0xdb, 0xf3, 0x60, 0xc6, 0xd8, 0xc6, 0xc0, 0x6c, 0x60, 0xd8, 0x7c, 0x18,
0x3c, 0xc6, 0x6c, 0x66, 0x7e, 0x7e, 0x60, 0xc6, 0xdc, 0xfc, 0xc0, 0x6c,
0xc6, 0xd8, 0x60, 0x18, 0x18, 0x6c, 0x6c, 0x66, 0x00, 0x60, 0x30, 0xc6,
0x76, 0xc0, 0xc0, 0x6c, 0xfe, 0x70, 0x60, 0x18, 0x7e, 0x38, 0xee, 0x3c,
0x00, 0xc0, 0x1c, 0xc6, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x00, 0x00, 0x38, 0x00, 0x00, 0x0f, 0xd8, 0x70, 0x00, 0x00,
0x00, 0x00, 0x30, 0x0c, 0x0e, 0x18, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x0c,
0x6c, 0xd8, 0x00, 0x00, 0xfe, 0x18, 0x18, 0x18, 0x1b, 0x18, 0x18, 0x00,
0x6c, 0x00, 0x00, 0x0c, 0x6c, 0x30, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x30,
0x1b, 0x18, 0x18, 0x76, 0x38, 0x00, 0x00, 0x0c, 0x6c, 0x60, 0x7c, 0x00,
0x00, 0x7e, 0x06, 0x60, 0x18, 0x18, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x0c,
0x6c, 0xc8, 0x7c, 0x00, 0xfe, 0x18, 0x0c, 0x30, 0x18, 0x18, 0x7e, 0x00,
0x00, 0x18, 0x00, 0x0c, 0x6c, 0xf8, 0x7c, 0x00, 0x00, 0x18, 0x18, 0x18,
0x18, 0x18, 0x00, 0x76, 0x00, 0x18, 0x18, 0xec, 0x00, 0x00, 0x7c, 0x00,
0x00, 0x00, 0x30, 0x0c, 0x18, 0xd8, 0x18, 0xdc, 0x00, 0x00, 0x00, 0x6c,
0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x18, 0xd8, 0x18, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0xff, 0x7e, 0x7e,
0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned int vga8x14_dat_len = 3588;
#else // EMBED_HERE
extern unsigned char vga8x14_dat[];
extern unsigned int vga8x14_dat_len;
#endif // EMBED_HERE
#pragma GCC diagnostic pop
#endif // VGA8X14_DAT_H

138
client/src/firstrun.c Normal file
View file

@ -0,0 +1,138 @@
/*
* 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();
}
}

31
client/src/firstrun.h Normal file
View file

@ -0,0 +1,31 @@
/*
* 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 FIRSTRUN_H
#define FIRSTRUN_H
#include "os.h"
void firstRunCheckSetup(void);
#endif // FIRSTRUN_H

View file

@ -22,6 +22,36 @@
#include "surface.h"
FontT *fontFromRAMLoad(uint8_t *pointer) {
FontT *font = NULL;
uint32_t size = 0;
font = (FontT *)malloc(sizeof(FontT));
if (!font) {
return NULL;
}
font->width = pointer[0]; // Width of character in pixels
font->height = pointer[1]; // Height of character in pixels
font->span = pointer[2]; // Width of atlas in characters
font->count = pointer[3]; // Number of characters in atlas - 1
font->widthPixels = font->width * font->span; // Width of atlas in pixels
font->heightPixels = font->height * ((font->count + 1) / font->span); // Height of atlas in pixels
size = font->widthPixels * font->heightPixels / 8; // Bits required to store atlas
font->bits = (uint8_t *)malloc(size);
if (!font->bits) {
DEL(font);
return NULL;
}
memcpy(font->bits, &pointer[4], size);
return font;
}
uint16_t fontHeightGet(FontT *font) {
return font->height;
}
@ -29,37 +59,29 @@ uint16_t fontHeightGet(FontT *font) {
FontT *fontLoad(char *filename) {
FILE *in = NULL;
uint16_t size = 0;
size_t size = 0;
uint8_t *buffer = NULL;
FontT *font = NULL;
in = fopen(filename, "rb");
if (!in) return NULL;
font = (FontT *)malloc(sizeof(FontT));
if (!font) {
fseek(in, 0, SEEK_END);
size = ftell(in);
fseek(in, 0, SEEK_SET);
buffer = (uint8_t *)malloc(size);
if (!buffer) {
fclose(in);
return NULL;
}
font->width = fgetc(in);
font->height = fgetc(in);
font->span = fgetc(in);
font->count = fgetc(in);
font->widthPixels = font->width * font->span;
font->heightPixels = font->height * (font->count / font->span);
size = font->widthPixels * font->heightPixels;
font->bits = (uint8_t *)malloc(size);
if (!font->bits) {
free(font);
fread(buffer, size, 1, in);
fclose(in);
return NULL;
}
fread(font->bits, size, 1, in);
font = fontFromRAMLoad(buffer);
fclose(in);
DEL(buffer);
return font;
}

View file

@ -37,6 +37,7 @@ typedef struct FontS {
} FontT;
FontT *fontFromRAMLoad(uint8_t *pointer);
uint16_t fontHeightGet(FontT *font);
FontT *fontLoad(char *filename);
void fontRender(FontT *font, char *string, ColorT foreground, ColorT background, uint16_t x, uint16_t y);

View file

@ -22,6 +22,7 @@
#include "gui.h"
#include "embedded/vga8x14.h"
#include "widget.h"
#include "desktop.h"
#include "window.h"
@ -29,9 +30,6 @@
int16_t _guiMetric[METRIC_COUNT];
ColorT _guiColor[COLOR_COUNT];
FontT *_guiFont8 = NULL;
FontT *_guiFont14 = NULL;
FontT *_guiFont16 = NULL;
FontT *_guiFont = NULL;
WidgetT *_guiDragWidget = NULL;
uint16_t _guiDragOffsetX = 0;
@ -43,7 +41,7 @@ static DesktopT *_guiDesktop = NULL;
static WidgetT *_guiLastWidgetLeft = NULL;
static uint8_t _guiLastWidgetLeftEvent = MOUSE_EVENT_NONE;
static WidgetT *_guiFocused = NULL;
static uint8_t _guiHasStopped = 0;
static uint8_t _guiHasStopped = 0; // This starts as 0 even if the GUI hasn't been started.
static WidgetT ***_guiDeleteList = NULL;
@ -521,10 +519,7 @@ WidgetT *guiRootGet(void) {
void guiShutdown(void) {
// Unload fonts.
fontUnload(&_guiFont16);
fontUnload(&_guiFont14);
fontUnload(&_guiFont8);
_guiFont = NULL;
fontUnload(&_guiFont);
// Delete all widgets in GUI tree.
guiDelete((WidgetT **)&_guiDesktop);
@ -631,12 +626,8 @@ DesktopT *guiStartup(void) {
_guiColor[COLOR_LISTBOX_ARROWS_ACTIVE] = vbeColorMake(168, 168, 168);
_guiColor[COLOR_LISTBOX_ARROWS_INACTIVE] = vbeColorMake( 80, 84, 80);
// Load all font sizes.
_guiFont8 = fontLoad("data/vga8x8.dat");
_guiFont14 = fontLoad("data/vga8x14.dat");
_guiFont16 = fontLoad("data/vga8x16.dat");
_guiFont = _guiFont14; // Font to use for widgets.
// Load font.
_guiFont = fontFromRAMLoad(vga8x14_dat);
// Create desktop and return it. Remember it for later.
_guiDesktop = desktopNew();

View file

@ -182,9 +182,6 @@ typedef struct WindowS WindowT;
extern int16_t _guiMetric[METRIC_COUNT];
extern ColorT _guiColor[COLOR_COUNT];
extern FontT *_guiFont;
extern FontT *_guiFont8;
extern FontT *_guiFont14;
extern FontT *_guiFont16;
extern WidgetT *_guiDragWidget;
extern uint16_t _guiDragOffsetX;
extern uint16_t _guiDragOffsetY;

View file

@ -82,6 +82,7 @@ static void comBufferShow(void);
static void comModem(uint8_t c);
static void processEvent(void);
static void processNetworkEvent(void);
static uint32_t timerCallback(uint32_t interval, void *param);
static void vbeScreenshot(void);
@ -379,6 +380,28 @@ void keyStartup(void) {
}
void linuxOsShutdown(void) {
// Stop timer.
SDL_RemoveTimer(_timerID);
// Stop network.
enet_deinitialize();
SDL_Quit();
}
void linuxOsStartup(void) {
SDL_Init(SDL_INIT_EVERYTHING);
// And networking/serial startup.
enet_initialize();
// We do timer startup here, too.
_timerID = SDL_AddTimer(TIMER_INTERVAL, timerCallback, NULL);
}
void mouseShutdown(void) {
// Eh, don't care.
}
@ -463,8 +486,6 @@ static void processEvent(void) {
break;
}
}
processNetworkEvent();
}
@ -472,7 +493,7 @@ static void processNetworkEvent(void) {
ENetEvent event = { 0 };
if (_host) {
while (enet_host_service(_host, &event, 1) > 0) {
while (enet_host_service(_host, &event, 0) > 0) {
switch (event.type) {
case ENET_EVENT_TYPE_CONNECT:
_connected = 1;
@ -497,9 +518,11 @@ static void processNetworkEvent(void) {
}
uint32_t timerCallback(uint32_t interval, void *param) {
static uint32_t timerCallback(uint32_t interval, void *param) {
(void)param;
processNetworkEvent();
_timerTicks++;
if (_timerTicks > TICKS_PER_DAY) {
_timerTicks = 0;
@ -550,15 +573,8 @@ void vbePresent(void) {
SDL_RenderCopy(_renderer, _texture, NULL, NULL);
SDL_RenderPresent(_renderer);
if (_host) {
// Throttle this to some sane frame rate by checking for network events.
for (temp=0; temp<32; temp++) {
processNetworkEvent();
}
} else {
// No network activity. Just sleep.
// Throttle this to some sane frame rate.
SDL_Delay(32);
}
if (_takeScreenshot) {
_takeScreenshot = 0;
@ -620,14 +636,6 @@ int16_t vbeShutdown(void) {
_window = NULL;
}
// Stop network.
enet_deinitialize();
// Stop timer.
SDL_RemoveTimer(_timerID);
SDL_Quit();
return 0;
}
@ -638,8 +646,6 @@ uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
_windowScale = 3;
SDL_Init(SDL_INIT_EVERYTHING);
_window = SDL_CreateWindow("GUI Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, xRes, yRes, SDL_WINDOW_ALLOW_HIGHDPI);
_surface = SDL_GetWindowSurface(_window);
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
@ -651,12 +657,6 @@ uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
_width = xRes;
_height = yRes;
// We do timer startup here, too.
_timerID = SDL_AddTimer(TIMER_INTERVAL, timerCallback, NULL);
// And networking/serial startup.
enet_initialize();
return 0;
}

View file

@ -97,26 +97,7 @@ static void setButtons(uint8_t enabled) {
static void taskDisconnect(void *nextTask) {
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);
netDisconnect();
if (nextTask) taskCreate(taskWelcome, nextTask);
}

View file

@ -48,6 +48,8 @@
#include "config.h"
#include "runtime.h"
#include "comport.h"
#include "network.h"
#include "firstrun.h"
#include "welcome.h"
#include "signup.h"
@ -92,10 +94,6 @@ static void taskGuiEventLoop(void *data) {
int main(int argc, char *argv[]) {
FILE *cache = NULL;
char *line = NULL;
char *p = NULL;
#ifndef __linux__
// On DOS, display the contets of the log now that we're back in text mode.
char *logName = NULL;
@ -104,6 +102,7 @@ int main(int argc, char *argv[]) {
memoryStartup(argv[0]);
logOpenByHandle(memoryLogHandleGet());
osStartup();
configStartup(argv[0]);
// 0 1 2 3 4 5 6 7 8
@ -121,6 +120,12 @@ int main(int argc, char *argv[]) {
}
}
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();
@ -131,54 +136,8 @@ int main(int argc, char *argv[]) {
surfaceStartup();
mouseStartup();
timerStartup();
guiStartup();
taskStartup();
__packetThreadData = packetThreadDataCreate(NULL);
packetSenderRegister(comPacketSender);
__runtimeData.integers = NULL;
__runtimeData.strings = NULL;
__runtimeData.protocolVersion = 0;
sh_new_strdup(__runtimeData.integers);
sh_new_strdup(__runtimeData.strings);
// ***TODO*** Default initial tables
mkdir("cache", 0777);
line = (char *)malloc(4096);
if (line) {
// Load string cache.
cache = fopen("cache/string.dat", "rt");
if (cache) {
while (fscanf(cache, "%s\n", line) != EOF) {
p = strstr(line, "=");
if (p) {
*p = 0;
p++;
shput(__runtimeData.strings, line, strdup(p));
}
}
fclose(cache);
}
// Load integer cache.
cache = fopen("cache/integer.dat", "rt");
if (cache) {
while (fscanf(cache, "%s\n", line) != EOF) {
p = strstr(line, "=");
if (p) {
*p = 0;
p++;
shput(__runtimeData.integers, line, atol(p));
}
}
fclose(cache);
}
free(line);
line = NULL;
}
// Do not call netStartup() here. It will be started when needed.
// taskCreate(taskSignUp, NULL);
taskCreate(taskWelcome, NULL);
@ -186,44 +145,15 @@ int main(int argc, char *argv[]) {
taskRun();
// Save & free integer table.
cache = fopen("cache/integer.dat", "wt");
if (cache) {
if (__runtimeData.integers) {
while (shlen(__runtimeData.integers) > 0) {
//logWrite("[%s]=[%d]\n", __runtimeData.integers[0].key, __runtimeData.integers[0].value);
fprintf(cache, "%s=%d\n", __runtimeData.integers[0].key, __runtimeData.integers[0].value);
shdel(__runtimeData.integers, __runtimeData.integers[0].key);
}
shfree(__runtimeData.integers);
}
fclose(cache);
}
// Save & free string table.
cache = fopen("cache/string.dat", "wt");
if (cache) {
if (__runtimeData.strings) {
while (shlen(__runtimeData.strings) > 0) {
//logWrite("[%s]=[%s]\n", __runtimeData.strings[0].key, __runtimeData.strings[0].value);
fprintf(cache, "%s=%s\n", __runtimeData.strings[0].key, __runtimeData.strings[0].value);
DEL(__runtimeData.strings[0].value);
shdel(__runtimeData.strings, __runtimeData.strings[0].key);
}
shfree(__runtimeData.strings);
}
fclose(cache);
}
packetThreadDataDestroy(&__packetThreadData);
taskShutdown();
netShutdown();
guiShutdown();
timerShutdown();
mouseShutdown();
surfaceShutdown();
vbeShutdown();
taskShutdown();
timerShutdown();
configShutdown();
osShutdown();
logClose();
memoryShutdown();

View file

@ -23,6 +23,7 @@
#include "comport.h"
#include "config.h"
#include "timer.h"
#include "runtime.h"
#include "network.h"
@ -35,6 +36,157 @@ typedef struct NetworkPacketS {
static NetworkPacketT *_packets = 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) {
@ -67,11 +219,98 @@ PacketDecodeDataT *netGetPacket(uint8_t channel) {
void netShutdown(void) {
FILE *cache = NULL;
if (_netStarted) {
_netStarted = 0;
// Save & free integer table.
cache = fopen("cache/integer.dat", "wt");
if (cache) {
if (__runtimeData.integers) {
while (shlen(__runtimeData.integers) > 0) {
//logWrite("[%s]=[%d]\n", __runtimeData.integers[0].key, __runtimeData.integers[0].value);
fprintf(cache, "%s=%d\n", __runtimeData.integers[0].key, __runtimeData.integers[0].value);
shdel(__runtimeData.integers, __runtimeData.integers[0].key);
}
shfree(__runtimeData.integers);
}
fclose(cache);
}
// Save & free string table.
cache = fopen("cache/string.dat", "wt");
if (cache) {
if (__runtimeData.strings) {
while (shlen(__runtimeData.strings) > 0) {
//logWrite("[%s]=[%s]\n", __runtimeData.strings[0].key, __runtimeData.strings[0].value);
fprintf(cache, "%s=%s\n", __runtimeData.strings[0].key, __runtimeData.strings[0].value);
DEL(__runtimeData.strings[0].value);
shdel(__runtimeData.strings, __runtimeData.strings[0].key);
}
shfree(__runtimeData.strings);
}
fclose(cache);
}
packetThreadDataDestroy(&__packetThreadData);
}
_netRunning = 0;
}
void netStartup(void) {
FILE *cache = NULL;
char *line = NULL;
char *p = NULL;
_netStarted = 1;
__packetThreadData = packetThreadDataCreate(NULL);
packetSenderRegister(comPacketSender);
__runtimeData.integers = NULL;
__runtimeData.strings = NULL;
__runtimeData.protocolVersion = 0;
sh_new_strdup(__runtimeData.integers);
sh_new_strdup(__runtimeData.strings);
// ***TODO*** Default initial tables
line = (char *)malloc(4096);
if (line) {
// Load string cache.
cache = fopen("cache/string.dat", "rt");
if (cache) {
while (fscanf(cache, "%s\n", line) != EOF) {
p = strstr(line, "=");
if (p) {
*p = 0;
p++;
shput(__runtimeData.strings, line, strdup(p));
}
}
fclose(cache);
}
// Load integer cache.
cache = fopen("cache/integer.dat", "rt");
if (cache) {
while (fscanf(cache, "%s\n", line) != EOF) {
p = strstr(line, "=");
if (p) {
*p = 0;
p++;
shput(__runtimeData.integers, line, atol(p));
}
}
fclose(cache);
}
free(line);
line = NULL;
}
taskCreate(taskNetwork, NULL);
}

View file

@ -25,6 +25,17 @@
#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
int8_t netConnectStep1(void);
int8_t netConnectStep2(void);
void netDisconnect(void);
uint8_t netGetChannelFree(void);
PacketDecodeDataT *netGetPacket(uint8_t channel);
void netShutdown(void);

View file

@ -95,30 +95,12 @@ static void btnOkayClick(WidgetT *widget) {
}
void taskSettings(void *data) {
int32_t rc;
uint32_t len;
char buffer[1024];
int8_t settingsScanComPorts(void) {
char buffer[1024] = { 0 };
uint8_t selected = 1;
_done = (widgetCallback)data;
TagItemT uiDetecting[] = {
T_START,
T_WINDOW, O(_winDetecting),
T_TITLE, P("Detecting Modems"),
T_WIDTH, 200, T_HEIGHT, 100,
T_LABEL, O(_lblOneMoment),
T_X, 25, T_Y, 25,
T_TITLE, P("One Moment Please!"),
T_LABEL, T_DONE,
T_WINDOW, T_DONE,
T_END
};
tagListRun(uiDetecting);
taskYield(); // Cause dialog to paint.
int32_t rc = 0;
uint32_t len = 0;
int8_t lastFound = -1;
// Scan the COM ports for a compatable modem.
for (int x=0; x<4; x++) {
@ -135,6 +117,7 @@ void taskSettings(void *data) {
_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);
@ -157,6 +140,35 @@ void taskSettings(void *data) {
}
}
return lastFound;
}
void taskSettings(void *data) {
int32_t rc;
uint32_t len;
_done = (widgetCallback)data;
TagItemT uiDetecting[] = {
T_START,
T_WINDOW, O(_winDetecting),
T_TITLE, P("Detecting Modems"),
T_WIDTH, 200, T_HEIGHT, 100,
T_LABEL, O(_lblOneMoment),
T_X, 25, T_Y, 25,
T_TITLE, P("One Moment Please!"),
T_LABEL, T_DONE,
T_WINDOW, T_DONE,
T_END
};
tagListRun(uiDetecting);
taskYield(); // Cause dialog to paint.
settingsScanComPorts();
guiDelete(D(_winDetecting));
TagItemT uiSettings[] = {

View file

@ -25,6 +25,7 @@
#include "os.h"
int8_t settingsScanComPorts(void);
void taskSettings(void *data);

View file

@ -21,3 +21,15 @@
#include "os.h"
void osShutdown(void) {
#ifdef __linux__
linuxOsShutdown();
#endif
}
void osStartup(void) {
#ifdef __linux__
linuxOsStartup();
#endif
}

View file

@ -44,6 +44,10 @@
// Linux DOS replacements.
long biostime(int cmd, long newtime);
// Linux support functions.
void linuxOsShutdown(void);
void linuxOsStartup(void);
#else
#define BITS32
@ -74,6 +78,9 @@ long biostime(int cmd, long newtime);
#define NEW(t,v) (v)=(t*)malloc(sizeof(t))
#define DEL(v) {free(v); v=NULL;}
#define SUCCESS 1
#define FAIL 0
// Some helper defines.
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))
#define HIGH_BYTE(b) ((uint8_t)(((b) & 0xFF00) >> 8))
@ -86,4 +93,8 @@ typedef struct PacketThreadDataS PacketThreadDataT;
extern PacketThreadDataT *__packetThreadData; // Declared in main.c
void osShutdown(void);
void osStartup(void);
#endif // OS_H

View file

@ -28,7 +28,6 @@
#include "comport.h"
#include "timer.h"
#include "network.h"
#include "runtime.h"
#include "window.h"
#include "picture.h"
@ -78,156 +77,6 @@ static void btnMsgBoxQuit(MsgBoxButtonT button) {
}
static void taskConnectClick(void *data) {
int32_t r = 0;
char buffer[1024] = { 0 };
PacketDecodeDataT *decoded = NULL;
PacketEncodeDataT encoded = { 0 };
int16_t timeout = 0;
uint8_t waiting = 1;
(void)data;
// 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();
// Open COM port.
r = comOpen(__configData.serialCom - 1, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
if (r != SER_SUCCESS) {
msgBoxOne("COM Problem", MSGBOX_ICON_ERROR, "Unable to open COM port!\nPlease check settings.", "Okay", btnMsgBox);
return;
}
// 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);
msgBoxOne("Modem Problem", MSGBOX_ICON_ERROR, "Modem does not support ENET!\nPlease check settings.", "Okay", btnMsgBox);
return;
}
// Flush COM port.
timerQuarterSecondsWait(4);
comReceiveBufferFlush(__configData.serialCom - 1);
// Show dialing, dial service.
widgetVisibleSet(W(_picDialing), 1);
taskYield();
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);
msgBoxOne("No Connection", MSGBOX_ICON_INFORMATION, "Unable to connect to server!\nPlease check settings or try later.", "Okay", btnMsgBox);
return;
}
// 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);
msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to negotiate encryption settings!", "Okay", btnMsgBox);
return;
}
// ***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);
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--;
}
// Switch to Login window.
guiDelete(D(_winWelcome));
taskCreate(taskLogin, NULL);
}
static void btnQuitClick(WidgetT *widget) {
(void)widget;
setButtons(0);
@ -312,3 +161,61 @@ void taskWelcome(void *data) {
tagListRun(uiWelcome);
}
static void taskConnectClick(void *data) {
int32_t r = 0;
int16_t timeout = 0;
(void)data;
// 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();
r = netConnectStep1();
if (r == NETWORK_CONNECT_OPEN_FAILED) {
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;
}
// Show dialing, dial service.
widgetVisibleSet(W(_picDialing), 1);
taskYield();
r = netConnectStep2();
if (r == NETWORK_CONNECT_NO_CARRIER) {
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) {
msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to negotiate encryption settings!", "Okay", btnMsgBox);
return;
}
if (r == NETWORK_CONNECT_BAD_SETTINGS) {
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--;
}
// Switch to Login window.
guiDelete(D(_winWelcome));
taskCreate(taskLogin, NULL);
}

BIN
font/data/vga8x14.dat (Stored with Git LFS) Normal file

Binary file not shown.

BIN
font/data/vga8x16.dat (Stored with Git LFS) Normal file

Binary file not shown.

BIN
font/data/vga8x8.dat (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -53,8 +53,8 @@ void makeFont(char *source, char *target, int pixelsW, int pixelsH, int charsW,
}
// Provide some metadata for enhancement later.
fputc(pixelsW, out); // Width of characters
fputc(pixelsH, out); // Height of characters
fputc(pixelsW, out); // Width of characters in pixels
fputc(pixelsH, out); // Height of characters in pixels
fputc(charsW, out); // Number of characters per row
fputc(charCount, out); // Number of characters - 1
@ -82,9 +82,9 @@ int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
makeFont("/home/scott/code/kpmpgsmkii/font/data/vga8x8.png", "/home/scott/code/kpmpgsmkii/bin/data/vga8x8.dat", 8, 8, 16, 255);
makeFont("/home/scott/code/kpmpgsmkii/font/data/vga8x14.png", "/home/scott/code/kpmpgsmkii/bin/data/vga8x14.dat", 8, 14, 16, 255);
makeFont("/home/scott/code/kpmpgsmkii/font/data/vga8x16.png", "/home/scott/code/kpmpgsmkii/bin/data/vga8x16.dat", 8, 16, 16, 255);
makeFont("/home/scott/code/kpmpgsmkii/font/assets/vga8x8.png", "/home/scott/code/kpmpgsmkii/font/data/vga8x8.dat", 8, 8, 16, 255);
makeFont("/home/scott/code/kpmpgsmkii/font/assets/vga8x14.png", "/home/scott/code/kpmpgsmkii/font/data/vga8x14.dat", 8, 14, 16, 255);
makeFont("/home/scott/code/kpmpgsmkii/font/assets/vga8x16.png", "/home/scott/code/kpmpgsmkii/font/data/vga8x16.dat", 8, 16, 16, 255);
return 0;
}

View file

@ -16,11 +16,23 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
TEMPLATE = subdirs
CONFIG *= ORDERED
SUBDIRS = \
client \
server
# font \
# font
# primes
OTHER_FILES = \
.gitattributes \
.gitignore \
buildPrerequisites.sh \
LICENSE \
Makefile.djgpp \
build.sh \
get-sql.sh \
test.conf \
test.sh

View file

@ -221,14 +221,15 @@ json_object *restRequest(char *command, char *format, ...) {
//logWrite("Request: %s\n", json_object_to_json_string_ext(request, JSON_C_TO_STRING_PRETTY));
response = restUrlPost(request);
json_object_put(request);
logWrite("Response: %s\n", json_object_to_json_string_ext(response, JSON_C_TO_STRING_PRETTY));
//logWrite("Response: %s\n", json_object_to_json_string_ext(response, JSON_C_TO_STRING_PRETTY));
if (response) {
string = (char *)json_object_get_string(json_object_object_get(response, "result"));
result = (string[0] == 't' || string[0] == 'T') ? 1 : 0;
if (result) {
if (!result) {
logWrite("restRequest: %s\n", json_object_get_string(json_object_object_get(response, "reason")));
json_object_put(response);
response = NULL;
}
} else {
logWrite("restRequest: No response.\n");