File download error handling added. 4-bit fonts added.

This commit is contained in:
Scott Duensing 2022-02-17 19:55:19 -06:00
parent d15b264ef6
commit 7149a0d33c
8 changed files with 222 additions and 31 deletions

35
FONTS Normal file
View file

@ -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 <https://www.gnu.org/licenses/>.
* 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/

View file

@ -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.");
}

View file

@ -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; c<strlen(string); c++) {
character = string[c];
@ -106,24 +107,56 @@ void fontRender(FontT *font, char *string, ColorT foreground, ColorT background,
cx = character % font->span;
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; yl<font->height; 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; yl<font->height; 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; yl<font->height; 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;

View file

@ -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;

View file

@ -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

BIN
font/in/vga4x8.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -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; yl<font->height; 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<h; y++) {
@ -78,13 +125,25 @@ void makeFont(char *source, char *target, int pixelsW, int pixelsH, int charsW,
}
void test(char *fontfile) {
FontT *font = fontLoad(fontfile);
printf("Solid Smile\n"); drawChar(font, 0x02);
printf("Question Mark\n"); drawChar(font, '?');
printf("x\n"); drawChar(font, 'x');
fontUnload(&font);
}
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
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);
makeFont("/home/scott/code/kpmpgsmkii/font/in/vga4x8.png", "/home/scott/code/kpmpgsmkii/font/out/vga4x8.dat", 4, 8, 16, 256);
makeFont("/home/scott/code/kpmpgsmkii/font/in/vga8x8.png", "/home/scott/code/kpmpgsmkii/font/out/vga8x8.dat", 8, 8, 16, 256);
makeFont("/home/scott/code/kpmpgsmkii/font/in/vga8x14.png", "/home/scott/code/kpmpgsmkii/font/out/vga8x14.dat", 8, 14, 16, 256);
makeFont("/home/scott/code/kpmpgsmkii/font/in/vga8x16.png", "/home/scott/code/kpmpgsmkii/font/out/vga8x16.dat", 8, 16, 16, 256);
test("/home/scott/code/kpmpgsmkii/font/out/vga4x8.dat");
return 0;
}

View file

@ -21,10 +21,10 @@ TEMPLATE = subdirs
CONFIG *= ORDERED
SUBDIRS = \
client
# client \
# server
# precache
# font
font
# primes
OTHER_FILES = \