File download error handling added. 4-bit fonts added.
This commit is contained in:
parent
d15b264ef6
commit
7149a0d33c
8 changed files with 222 additions and 31 deletions
35
FONTS
Normal file
35
FONTS
Normal 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/
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
BIN
font/in/vga4x8.png
(Stored with Git LFS)
Normal file
Binary file not shown.
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -21,10 +21,10 @@ TEMPLATE = subdirs
|
|||
CONFIG *= ORDERED
|
||||
|
||||
SUBDIRS = \
|
||||
client
|
||||
# client \
|
||||
# server
|
||||
# precache
|
||||
# font
|
||||
font
|
||||
# primes
|
||||
|
||||
OTHER_FILES = \
|
||||
|
|
Loading…
Add table
Reference in a new issue