diff --git a/FONTS b/FONTS
new file mode 100644
index 0000000..b7daedb
--- /dev/null
+++ b/FONTS
@@ -0,0 +1,35 @@
+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 .
+
+
+
+* vga8x??.png are the standard DOS fonts, from the DOSbox project.
+ Copyright (C) 2002-2004 The DOSBox Team
+
+* vga4x8.png contains a miniature, half-size font for low-resolution
+ displays. This is based on the Atari-Small font by Tom Fine. The
+ original font was standard ASCII only; this has been extended to the
+ full Extended ASCII range with scaled-down versions of the full-size
+ DOS font. Original copyright notice:
+
+ Copyright (c) 1999, Thomas A. Fine
+
+ License to copy, modify, and distribute for both commercial and
+ non-commercial use is herby granted, provided this notice
+ is preserved.
+
+ Email to my last name at head.cfa.harvard.edu
+ http://hea-www.harvard.edu/~fine/
diff --git a/client/src/file.c b/client/src/file.c
index 5841d07..ccb18ec 100644
--- a/client/src/file.c
+++ b/client/src/file.c
@@ -25,8 +25,12 @@
#include "taglist.h"
#include "window.h"
#include "label.h"
+#include "timer.h"
+#include "msgbox.h"
#include "file.h"
+#include "hangup.h"
+#include "welcome.h"
// All this queue nonsense allows you to request more
@@ -47,12 +51,21 @@ static char *_file = NULL;
static FILE *_handle = NULL;
static WindowT *_winFile = NULL;
static LabelT *_lblFile = NULL;
+static TimerT *_timTimer = NULL;
+static void btnMsgBoxOkay(MsgBoxButtonT button);
static void fileCheckNext(void);
static void fileShowDialog(void);
static void fileShowError(char *message);
static void packetHandler(PacketDecodeDataT *packet);
+static void timTimerTimeout(WidgetT *widget);
+
+
+static void btnMsgBoxOkay(MsgBoxButtonT button) {
+ (void)button;
+ hangupShow(welcomeShow);
+}
void fileCacheCheck(fileCallback callback, char *vpaths[]) {
@@ -155,6 +168,11 @@ static void fileShowDialog(void) {
T_X, 41, T_Y, 25,
T_TITLE, P("Downloading..."),
T_LABEL, T_DONE,
+ T_TIMER, O(_timTimer),
+ T_EVENT, P(timTimerTimeout),
+ T_VALUE, 4 * 5,
+ T_ENABLED, 1,
+ T_TIMER, T_DONE,
T_WINDOW, T_DONE,
T_END
};
@@ -165,9 +183,12 @@ static void fileShowDialog(void) {
static void fileShowError(char *message) {
- // ***TODO*** Handle error. This is fatal.
+ // ***TODO*** This should close all open windows.
+
+ // Show error. This is fatal.
if (_dialogVisible) guiDelete(D(_winFile));
netChannelRelease(_channel);
+ msgBoxOne("Uh Oh!", MSGBOX_ICON_QUESTION, message, "Okay", btnMsgBoxOkay);
}
@@ -200,7 +221,6 @@ static void packetHandler(PacketDecodeDataT *packet) {
break;
case FILE_RESPONSE_DATA:
- // Get file size.
logWrite("Got FILE_RESPONSE_DATA\n");
// Receive new file data.
if (!_dialogVisible) fileShowDialog();
@@ -239,9 +259,39 @@ static void packetHandler(PacketDecodeDataT *packet) {
packetSend(__packetThreadData, &encoded);
DEL(packetData);
}
+ // Reset timeout timer.
+ timerReset(_timTimer);
break;
}
}
packetDecodeDataDestroy(&packet);
}
+
+
+static void timTimerTimeout(WidgetT *widget) {
+ uint8_t missing = 0;
+
+ (void)widget;
+
+ // Download timed out.
+ timerStop(_timTimer);
+
+ // If we at least have some version of the file, try to continue.
+ while (arrlen(_fileList) > 0) {
+ while (arrlen(_fileList[0]->files) > 0) {
+ if (cacheFilenameGet(_fileList[0]->files[0])) {
+ arrdel(_fileList[0]->files, 0);
+ } else {
+ missing = 1;
+ }
+ }
+ // If we're good so far, call the callback.
+ if (!missing) _fileList[0]->callback();
+ arrfree(_fileList[0]->files);
+ arrdel(_fileList, 0);
+ }
+ arrfree(_fileList);
+
+ if (missing) fileShowError("Unable to download needed files.");
+}
diff --git a/client/src/gui/font.c b/client/src/gui/font.c
index 4b48d09..e2bdb42 100644
--- a/client/src/gui/font.c
+++ b/client/src/gui/font.c
@@ -96,8 +96,9 @@ void fontRender(FontT *font, char *string, ColorT foreground, ColorT background,
uint8_t data;
uint8_t character;
uint8_t c;
+ uint8_t odd;
- //***TODO*** This only handles 8xY fonts.
+ //***TODO*** This only handles 4xY and 8xY fonts.
for (c=0; cspan;
cy = character / font->span;
- // Find offset byte based on font bits.
- offset = cy * font->span * font->height + cx;
+ // Half byte or full byte font?
+ if (font->width == 4) {
+ // Half Byte.
- // Draw out 8 lines.
- yp = y;
- for (yl=0; ylheight; yl++) {
- // We do 8 pixels unrolled hoping it's fast.
- data = font->bits[offset];
- offset += font->span;
- surfacePutPixel(x, yp, data & 0x80 ? foreground : background);
- surfacePutPixel(x + 1, yp, data & 0x40 ? foreground : background);
- surfacePutPixel(x + 2, yp, data & 0x20 ? foreground : background);
- surfacePutPixel(x + 3, yp, data & 0x10 ? foreground : background);
- surfacePutPixel(x + 4, yp, data & 0x08 ? foreground : background);
- surfacePutPixel(x + 5, yp, data & 0x04 ? foreground : background);
- surfacePutPixel(x + 6, yp, data & 0x02 ? foreground : background);
- surfacePutPixel(x + 7, yp, data & 0x01 ? foreground : background);
- yp++;
+ // Which half of the byte do we want?
+ odd = ((cx & 1) == 1);
+
+ // Find offset byte based on font bits.
+ offset = cy * (font->span / 2) * font->height + cx * ((float)font->width / 8.0f);
+
+ for (yl=0; ylheight; yl++) {
+ data = font->bits[offset];
+ offset += (font->span / 2);
+
+ if (odd) {
+ surfacePutPixel(x, yp, data & 0x08 ? foreground : background);
+ surfacePutPixel(x + 1, yp, data & 0x04 ? foreground : background);
+ surfacePutPixel(x + 2, yp, data & 0x02 ? foreground : background);
+ surfacePutPixel(x + 3, yp, data & 0x01 ? foreground : background);
+ } else {
+ surfacePutPixel(x, yp, data & 0x80 ? foreground : background);
+ surfacePutPixel(x + 1, yp, data & 0x40 ? foreground : background);
+ surfacePutPixel(x + 2, yp, data & 0x20 ? foreground : background);
+ surfacePutPixel(x + 3, yp, data & 0x10 ? foreground : background);
+ }
+ }
+ } else {
+ // Full Byte.
+
+ // Find offset byte based on font bits.
+ offset = cy * font->span * font->height + cx;
+
+ // Draw out 8 lines.
+ yp = y;
+ for (yl=0; ylheight; yl++) {
+ // We do 8 pixels unrolled hoping it's fast.
+ data = font->bits[offset];
+ offset += font->span;
+#ifndef FONT_DEBUGGING
+ surfacePutPixel(x, yp, data & 0x80 ? foreground : background);
+ surfacePutPixel(x + 1, yp, data & 0x40 ? foreground : background);
+ surfacePutPixel(x + 2, yp, data & 0x20 ? foreground : background);
+ surfacePutPixel(x + 3, yp, data & 0x10 ? foreground : background);
+ surfacePutPixel(x + 4, yp, data & 0x08 ? foreground : background);
+ surfacePutPixel(x + 5, yp, data & 0x04 ? foreground : background);
+ surfacePutPixel(x + 6, yp, data & 0x02 ? foreground : background);
+ surfacePutPixel(x + 7, yp, data & 0x01 ? foreground : background);
+#endif
+ yp++;
+ }
}
x += font->width;
diff --git a/client/src/system/cache.c b/client/src/system/cache.c
index 2264a18..600ee2f 100644
--- a/client/src/system/cache.c
+++ b/client/src/system/cache.c
@@ -260,6 +260,7 @@ static char *cacheFieldGet(char *virtualPath, uint8_t field) {
if (osFileExists(index)) {
in = fopen(index, "rt");
if (in) {
+ // Be sure the fread is the last conditional so it short-circuts properly.
while (result == NULL && (fgets(buffer, 2048, in) != 0)) {
name = strstr(buffer, " ");
*name = 0;
diff --git a/font/font.pro b/font/font.pro
index eeb06ef..4b2fcf3 100644
--- a/font/font.pro
+++ b/font/font.pro
@@ -22,16 +22,26 @@ CONFIG += console
DESTDIR = $$OUT_PWD/bin
SHARED = $$PWD/../shared
+CLIENT = $$PWD/../client/src
+SYSTEM = $$CLIENT/system
+GUI = $$CLIENT/gui
+
+DEFINES += FONT_DEBUGGING
INCLUDEPATH += \
$$SHARED \
- $$SHARED/thirdparty
+ $$SHARED/thirdparty \
+ $$CLIENT \
+ $$SYSTEM \
+ $$GUI
HEADERS = \
$$SHARED/stddclmr.h \
$$SHARED/thirdparty/memwatch/memwatch.h \
- $$SHARED/thirdparty/stb_image.h
+ $$SHARED/thirdparty/stb_image.h \
+ $$GUI/font.h
SOURCES = \
$$SHARED/thirdparty/memwatch/memwatch.c \
+ $$GUI/font.c \
src/main.c
diff --git a/font/in/vga4x8.png b/font/in/vga4x8.png
new file mode 100644
index 0000000..579fd48
--- /dev/null
+++ b/font/in/vga4x8.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b4c2a6fe844525cdd4abddd2c7aa2d6d73ec667dd82aee10e8a9c62e2f367d8b
+size 18029
diff --git a/font/src/main.c b/font/src/main.c
index 9dabeb9..9212673 100644
--- a/font/src/main.c
+++ b/font/src/main.c
@@ -27,9 +27,56 @@
#define STBI_ONLY_PNG
#include "stb_image.h"
+#include "font.h"
#include "stddclmr.h"
+void drawChar(FontT *font, char c);
+void makeFont(char *source, char *target, int pixelsW, int pixelsH, int charsW, int charCount);
+void test(char *fontfile);
+
+
+void drawChar(FontT *font, char c) {
+ uint8_t cx;
+ uint8_t cy;
+ uint16_t offset;
+ uint8_t yl;
+ uint8_t data;
+ uint8_t odd;
+ uint16_t t;
+
+ // Find character position in font grid.
+ cx = c % font->span;
+ cy = c / font->span;
+
+ // Which half of the byte do we want?
+ odd = ((cx & 1) == 1);
+
+ // Find offset byte based on font bits.
+ offset = cy * (font->span / 2) * font->height;
+ t = cx * ((float)font->width / 8.0f);
+ offset += t;
+
+ for (yl=0; ylheight; yl++) {
+ data = font->bits[offset];
+ offset += (font->span / 2);
+
+ if (odd) {
+ printf("%c", data & 0x08 ? '#' : ' ');
+ printf("%c", data & 0x04 ? '#' : ' ');
+ printf("%c", data & 0x02 ? '#' : ' ');
+ printf("%c", data & 0x01 ? '#' : ' ');
+ } else {
+ printf("%c", data & 0x80 ? '#' : ' ');
+ printf("%c", data & 0x40 ? '#' : ' ');
+ printf("%c", data & 0x20 ? '#' : ' ');
+ printf("%c", data & 0x10 ? '#' : ' ');
+ }
+ printf("\n");
+ }
+}
+
+
void makeFont(char *source, char *target, int pixelsW, int pixelsH, int charsW, int charCount) {
unsigned char *font = NULL;
unsigned char data = 0;
@@ -53,10 +100,10 @@ void makeFont(char *source, char *target, int pixelsW, int pixelsH, int charsW,
}
// Provide some metadata for enhancement later.
- 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
+ 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 - 1, out); // Number of characters - 1
// Convert bitmap to actual bits.
for (y=0; y