482 lines
12 KiB
C
482 lines
12 KiB
C
/*
|
|
* 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/>.
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
* To Do:
|
|
*
|
|
* - Replace any direct data manipulation from outside a class with methods to handle it
|
|
* - More widget states: Ghosted, hidden
|
|
* - Methods that can change the width of a widget (such as setTitle) need to repaint the parent window as well
|
|
* - Metrics, colors, etc. should be defined in each widget and not in GUI
|
|
* - Widgets should support a "changed" callback that can cancel the change
|
|
* - Use LabelT in all widgets that have a label
|
|
* - Find a light grey to replace white widget data areas
|
|
* - No thumb in listbox scrollbar
|
|
* - Window dragging is being screwball
|
|
*
|
|
* - Random crash on exit - looks memwatch / task related - hasn't happened on DOS yet
|
|
*/
|
|
|
|
|
|
#include "stddclmr.h"
|
|
#include "os.h"
|
|
#include "vesa.h"
|
|
#include "surface.h"
|
|
#include "mouse.h"
|
|
#include "keyboard.h"
|
|
#include "task.h"
|
|
#include "image.h"
|
|
#include "font.h"
|
|
#include "timer.h"
|
|
|
|
#include "gui.h"
|
|
#include "widget.h"
|
|
#include "desktop.h"
|
|
#include "window.h"
|
|
#include "button.h"
|
|
#include "label.h"
|
|
#include "checkbox.h"
|
|
#include "radio.h"
|
|
#include "picture.h"
|
|
#include "frame.h"
|
|
#include "textbox.h"
|
|
#include "updown.h"
|
|
#include "listbox.h"
|
|
#include "terminal.h"
|
|
|
|
#include "taglist.h"
|
|
|
|
|
|
static TerminalT *t1 = NULL;
|
|
static uint8_t lastKey = 0;
|
|
|
|
|
|
static void buttonClick(WidgetT *widget);
|
|
static void mainLoop(void *data);
|
|
//static void test(void *data);
|
|
static void testTagList(void *data);
|
|
static void testTerminal(void *data);
|
|
static void widgetDebugDraw(WidgetT *widget, uint8_t debugToggle);
|
|
|
|
|
|
static void buttonClick(WidgetT *widget) {
|
|
logWrite("'%s' was clicked.\n", ((ButtonT *)widget)->title);
|
|
}
|
|
|
|
|
|
static void mainLoop(void *data) {
|
|
MouseT *mouse = NULL;
|
|
ImageT *pointer = NULL;
|
|
ColorT alpha;
|
|
int8_t key = 0;
|
|
int8_t debugState = 0;
|
|
|
|
(void)data;
|
|
|
|
pointer = imageLoad("mouse.png");
|
|
alpha = imagePixelGet(pointer, 5, 0);
|
|
|
|
do {
|
|
timerUpdate();
|
|
mouse = mouseRead();
|
|
if (keyHit()) {
|
|
key = keyASCIIGet();
|
|
lastKey = key; //***DEBUG***
|
|
guiKeyboardProcess(keyASCIIGet(), keyExtendedGet(), keyScanCodeGet(), keyShiftGet(), keyControlGet(), keyAltGet());
|
|
//logWrite("Key '%d' Extended '%d' Scancode '%d' Shift '%d' Control '%d' Alt '%d'\n", key, keyExtended(), keyScanCode(), keyShift(), keyControl(), keyAlt());
|
|
} else {
|
|
key = 0;
|
|
}
|
|
guiMouseProcess(mouse);
|
|
guiComposite();
|
|
imageRenderWithAlpha(pointer, mouse->x, mouse->y, alpha);
|
|
|
|
if (key == '=') guiWidgetTreeDump(guiRootGet(), 0);
|
|
if (key == '+') {
|
|
debugState++;
|
|
if (debugState > 2) debugState = 0;
|
|
}
|
|
if (debugState > 0) widgetDebugDraw(guiRootGet(), debugState - 1);
|
|
//if (timerHalfSecondOn) guiDrawRectangle(0, 0, vbeSurfaceWidthGet() - 1, vbeSurfaceHeightGet() - 1, vbeMakeColor(255, 255, 255));
|
|
|
|
vbeVBlankWait();
|
|
vbePresent();
|
|
taskYield();
|
|
} while (key != 27); // Exit on ESC.
|
|
|
|
imageUnload(&pointer);
|
|
}
|
|
|
|
|
|
/*
|
|
static void test(void *data) {
|
|
DesktopT *desktop = (DesktopT *)guiRootGet();
|
|
WindowT *w1 = NULL;
|
|
WindowT *w2 = NULL;
|
|
WindowT *w3 = NULL;
|
|
WindowT *w4 = NULL;
|
|
ButtonT *b1 = NULL;
|
|
LabelT *l1 = NULL;
|
|
CheckboxT *c1 = NULL;
|
|
RadioT *r1a = NULL;
|
|
RadioT *r2a = NULL;
|
|
RadioT *r3a = NULL;
|
|
RadioT *r1b = NULL;
|
|
RadioT *r2b = NULL;
|
|
RadioT *r3b = NULL;
|
|
PictureT *p1 = NULL;
|
|
FrameT *f1 = NULL;
|
|
TextboxT *tb1 = NULL;
|
|
TextboxT *tb2 = NULL;
|
|
UpdownT *u1 = NULL;
|
|
ListboxT *lb1 = NULL;
|
|
|
|
(void)data;
|
|
|
|
// Windows
|
|
w1 = windowNew(300, 25, 300, 200, "Window 1");
|
|
guiAttach(W(desktop), W(w1));
|
|
w2 = windowNew(150, 150, 300, 200, "Window 2");
|
|
guiAttach(W(desktop), W(w2));
|
|
w3 = windowNew(300, 300, 300, 200, "Window 3");
|
|
guiAttach(W(desktop), W(w3));
|
|
w4 = windowNew(10, 10, 7 + 8 + (80 * 8), 26 + 8 + (24 * 14), "Terminal");
|
|
guiAttach(W(desktop), W(w4));
|
|
|
|
// Window 1
|
|
p1 = pictureNew(0, 0, "kanga.png");
|
|
guiAttach(W(w1), W(p1));
|
|
lb1 = listboxNew(155, 10, 120, 140, "List Box");
|
|
listboxItemAdd(lb1, "One");
|
|
listboxItemAdd(lb1, "Two");
|
|
listboxItemAdd(lb1, "Three");
|
|
listboxItemAdd(lb1, "Four");
|
|
listboxItemAdd(lb1, "Five");
|
|
listboxItemAdd(lb1, "Six");
|
|
listboxItemAdd(lb1, "Seven");
|
|
listboxItemAdd(lb1, "Eight");
|
|
listboxItemAdd(lb1, "Nine");
|
|
listboxItemAdd(lb1, "Ten");
|
|
listboxStepSet(lb1, 3);
|
|
guiAttach(W(w1), W(lb1));
|
|
|
|
// Window 2
|
|
r1a = radioNew(10, 10, "Radio 1a", 1);
|
|
guiAttach(W(w2), W(r1a));
|
|
r2a = radioNew(20 + widgetWidthGet(W(r1a)), 10, "Radio 2a", 1);
|
|
guiAttach(W(w2), W(r2a));
|
|
r3a = radioNew(30 + widgetWidthGet(W(r1a)) + widgetWidthGet(W(r2a)), 10, "Radio 3a", 1);
|
|
guiAttach(W(w2), W(r3a));
|
|
r1b = radioNew(10, 35, "Radio 1b", 2);
|
|
guiAttach(W(w2), W(r1b));
|
|
r2b = radioNew(20 + widgetWidthGet(W(r1b)), 35, "Radio 2b", 2);
|
|
guiAttach(W(w2), W(r2b));
|
|
r3b = radioNew(30 + widgetWidthGet(W(r1b)) + widgetWidthGet(W(r2b)), 35, "Radio 3b", 2);
|
|
guiAttach(W(w2), W(r3b));
|
|
radioSelectedSet(r1a);
|
|
radioSelectedSet(r2b);
|
|
tb1 = textboxNew(10, 60, 265, "Test Textbox");
|
|
textboxValueSet(tb1, "Really long text string to edit!");
|
|
guiAttach(W(w2), W(tb1));
|
|
tb2 = textboxNew(10, 85, 265, "Test Textbox");
|
|
textboxValueSet(tb2, "Short string.");
|
|
guiAttach(W(w2), W(tb2));
|
|
u1 = updownNew(10, 110, 0, 1024, 5, "UpDown");
|
|
guiAttach(W(w2), W(u1));
|
|
|
|
// Window 3
|
|
f1 = frameNew(10, 5, 175, 125, "Test Frame");
|
|
guiAttach(W(w3), W(f1));
|
|
b1 = buttonNew(0, 0, "Test Button", buttonClick);
|
|
guiAttach(W(f1), W(b1));
|
|
l1 = labelNew(10, 40, "Test Label");
|
|
guiAttach(W(f1), W(l1));
|
|
c1 = checkboxNew(10, 65, "Test Checkbox");
|
|
guiAttach(W(f1), W(c1));
|
|
|
|
// Window 4 - Terminal
|
|
t1 = terminalNew(0, 0, 80, 24);
|
|
guiAttach(W(w4), W(t1));
|
|
|
|
taskCreate(testTerminal, "terminalTest");
|
|
}
|
|
*/
|
|
|
|
|
|
static void testTagList(void *data) {
|
|
WindowT *w1 = NULL;
|
|
WindowT *w2 = NULL;
|
|
WindowT *w3 = NULL;
|
|
WindowT *w4 = NULL;
|
|
ButtonT *b1 = NULL;
|
|
LabelT *l1 = NULL;
|
|
CheckboxT *c1 = NULL;
|
|
RadioT *r1a = NULL;
|
|
RadioT *r2a = NULL;
|
|
RadioT *r3a = NULL;
|
|
RadioT *r1b = NULL;
|
|
RadioT *r2b = NULL;
|
|
RadioT *r3b = NULL;
|
|
PictureT *p1 = NULL;
|
|
FrameT *f1 = NULL;
|
|
TextboxT *tb1 = NULL;
|
|
TextboxT *tb2 = NULL;
|
|
UpdownT *u1 = NULL;
|
|
ListboxT *lb1 = NULL;
|
|
|
|
(void)data;
|
|
|
|
TagItemT ui[] = {
|
|
T_START,
|
|
|
|
T_WINDOW, O(w1),
|
|
T_TITLE, P("Window 1"),
|
|
T_X, 300, T_Y, 25, T_WIDTH, 300, T_HEIGHT, 200,
|
|
T_PICTURE, O(p1),
|
|
T_X, 0, T_Y, 0,
|
|
T_FILENAME, P("kanga.png"),
|
|
T_PICTURE, T_DONE,
|
|
T_LISTBOX, O(lb1),
|
|
T_TITLE, P("Listbox"),
|
|
T_X, 155, T_Y, 10, T_WIDTH, 120, T_HEIGHT, 140,
|
|
T_ITEM, P("One"),
|
|
T_ITEM, P("Two"),
|
|
T_ITEM, P("Three"),
|
|
T_ITEM, P("Four"),
|
|
T_ITEM, P("Five"),
|
|
T_ITEM, P("Six"),
|
|
T_ITEM, P("Seven"),
|
|
T_ITEM, P("Eight"),
|
|
T_ITEM, P("Nine"),
|
|
T_ITEM, P("Ten"),
|
|
T_STEP, 3,
|
|
T_LISTBOX, T_DONE,
|
|
T_WINDOW, T_DONE,
|
|
|
|
T_WINDOW, O(w2),
|
|
T_TITLE, P("Window 2"),
|
|
T_X, 150, T_Y, 150, T_WIDTH, 300, T_HEIGHT, 200,
|
|
T_RADIOBUTTON, O(r1a),
|
|
T_TITLE, P("Radio 1a"),
|
|
T_X, 10, T_Y, 10,
|
|
T_GROUP, 1,
|
|
T_SELECTED, 1,
|
|
T_RADIOBUTTON, T_DONE,
|
|
T_RADIOBUTTON, O(r2a),
|
|
T_TITLE, P("Radio 2a"),
|
|
T_X, 20 + 80, T_Y, 10,
|
|
T_GROUP, 1,
|
|
T_RADIOBUTTON, T_DONE,
|
|
T_RADIOBUTTON, O(r3a),
|
|
T_TITLE, P("Radio 3a"),
|
|
T_X, 30 + 80 * 2, T_Y, 10,
|
|
T_GROUP, 1,
|
|
T_RADIOBUTTON, T_DONE,
|
|
T_RADIOBUTTON, O(r1b),
|
|
T_TITLE, P("Radio 1b"),
|
|
T_X, 10, T_Y, 35,
|
|
T_GROUP, 2,
|
|
T_RADIOBUTTON, T_DONE,
|
|
T_RADIOBUTTON, O(r2b),
|
|
T_TITLE, P("Radio 2b"),
|
|
T_X, 20 + 80, T_Y, 35,
|
|
T_GROUP, 2,
|
|
T_SELECTED, 1,
|
|
T_RADIOBUTTON, T_DONE,
|
|
T_RADIOBUTTON, O(r3b),
|
|
T_TITLE, P("Radio 3b"),
|
|
T_X, 30 + 80 * 2, T_Y, 35,
|
|
T_GROUP, 2,
|
|
T_RADIOBUTTON, T_DONE,
|
|
T_TEXTBOX, O(tb1),
|
|
T_TITLE, P("Test Textbox"),
|
|
T_X, 10, T_Y, 60, T_WIDTH, 265,
|
|
T_VALUE, P("Really long text string to edit!"),
|
|
T_TEXTBOX, T_DONE,
|
|
T_TEXTBOX, O(tb2),
|
|
T_TITLE, P("Test Textbox"),
|
|
T_X, 10, T_Y, 85, T_WIDTH, 265,
|
|
T_VALUE, P("Short String."),
|
|
T_TEXTBOX, T_DONE,
|
|
T_UPDOWN, O(u1),
|
|
T_TITLE, P("UpDown"),
|
|
T_X, 10, T_Y, 120,
|
|
T_MINIMUM, 0, T_MAXIMUM, 1024, T_STEP, 5,
|
|
T_UPDOWN, T_DONE,
|
|
T_WINDOW, T_DONE,
|
|
|
|
T_WINDOW, O(w3),
|
|
T_TITLE, P("Window 3"),
|
|
T_X, 300, T_Y, 300, T_WIDTH, 300, T_HEIGHT, 200,
|
|
T_FRAME, O(f1),
|
|
T_TITLE, P("Test Frame"),
|
|
T_X, 10, T_Y, 5, T_WIDTH, 175, T_HEIGHT, 125,
|
|
T_BUTTON, O(b1),
|
|
T_TITLE, P("Test Button"),
|
|
T_X, 0, T_Y, 0,
|
|
T_CLICK, P(buttonClick),
|
|
T_BUTTON, T_DONE,
|
|
T_LABEL, O(l1),
|
|
T_TITLE, P("Test Label"),
|
|
T_X, 10, T_Y, 40,
|
|
T_LABEL, T_DONE,
|
|
T_CHECKBOX, O(c1),
|
|
T_TITLE, P("Test Checkbox"),
|
|
T_X, 10, T_Y, 65,
|
|
T_CHECKBOX, T_DONE,
|
|
T_FRAME, T_DONE,
|
|
T_WINDOW, T_DONE,
|
|
|
|
T_WINDOW, O(w4),
|
|
T_TITLE, P("Terminal"),
|
|
T_X, 10, T_Y, 10, T_WIDTH, 7 + 8 + (80 * 8), T_HEIGHT, 26 + 8 + (24 * 14),
|
|
T_TERMINAL, O(t1),
|
|
T_X, 0, T_Y, 0, T_WIDTH, 80, T_HEIGHT, 24,
|
|
T_TERMINAL, T_DONE,
|
|
T_WINDOW, T_DONE,
|
|
|
|
T_END
|
|
};
|
|
|
|
tagListRun(ui);
|
|
|
|
taskCreate(testTerminal, "terminalTest");
|
|
}
|
|
|
|
|
|
static void testTerminal(void *data) {
|
|
FILE *in = NULL;
|
|
char *buffer = NULL;
|
|
uint16_t length = 0;
|
|
|
|
(void)data;
|
|
|
|
// Load ANSI file for terminal test.
|
|
in = fopen("kanga.ans", "rt");
|
|
fseek(in, 0, SEEK_END);
|
|
length = ftell(in);
|
|
fseek(in, 0, SEEK_SET);
|
|
buffer = (char *)malloc(length + 1);
|
|
fread(buffer, 1, length, in);
|
|
fclose(in);
|
|
buffer[length] = 0;
|
|
|
|
terminalStringPrint(t1, buffer);
|
|
|
|
free(buffer);
|
|
}
|
|
|
|
|
|
static void widgetDebugDraw(WidgetT *widget, uint8_t debugToggle) {
|
|
size_t len = arrlenu(widget->children);
|
|
size_t i;
|
|
RectT r;
|
|
|
|
if (debugToggle) {
|
|
// Clipping region (blue)
|
|
guiWidgetBoundsDrawableOnScreenGet(widget, &r);
|
|
surfaceRectangleDraw(r.x, r.y, r.x + r.w, r.y + r.h, vbeColorMake(0, 0, 255));
|
|
} else {
|
|
// Widget border (red)
|
|
guiWidgetPositionOnScreenGet(widget, &r);
|
|
surfaceRectangleDraw(r.x, r.y, r.x + widget->pos.w, r.y + widget->pos.h, vbeColorMake(255, 0, 0));
|
|
}
|
|
|
|
if (len > 0) {
|
|
for (i=0; i<len; i++) {
|
|
widgetDebugDraw(widget->children[i], debugToggle);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
uint16_t xResolution = 0;
|
|
uint16_t yResolution = 0;
|
|
uint16_t colorDepth = 0;
|
|
char logName[32] = { "log.log" };
|
|
char *c = NULL;
|
|
int16_t x = strlen(argv[0]);
|
|
|
|
memoryStartup();
|
|
|
|
// 0 1 2 3 4 5 6 7 8
|
|
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
printf("Kangaroo Punch MultiPlayer DOS Game Client Mark II\n");
|
|
printf("Copyright (C) 2020-2021 Scott Duensing scott@kangaroopunch.com\n\n");
|
|
fflush(stdout);
|
|
|
|
// Find last portion of filename.
|
|
while (x > 0) {
|
|
if (argv[0][x] == '/' || argv[0][x] == '\\') break;
|
|
x--;
|
|
}
|
|
if (strlen(argv[0]) - x < 32) {
|
|
// Replace any extension with ".log"
|
|
strncpy(logName, &argv[0][x + 1], 31);
|
|
c = strstr(logName, ".");
|
|
if (c) *c = 0;
|
|
strncat(logName, ".log", 31);
|
|
}
|
|
|
|
logOpen(logName, 0);
|
|
|
|
// Command line needs to have the desired resolution and color depth on it.
|
|
if (argc != 4) {
|
|
vbeInfoShow();
|
|
fflush(stdout);
|
|
memoryShutdown();
|
|
return 0;
|
|
}
|
|
xResolution = atoi(argv[1]);
|
|
yResolution = atoi(argv[2]);
|
|
colorDepth = atoi(argv[3]);
|
|
|
|
// Do we have the video mode they asked for?
|
|
if (vbeStartup(xResolution, yResolution, colorDepth)) {
|
|
fflush(stdout);
|
|
memoryShutdown();
|
|
return 1;
|
|
}
|
|
|
|
surfaceStartup();
|
|
mouseStartup();
|
|
timerStartup();
|
|
guiStartup();
|
|
taskStartup();
|
|
|
|
taskCreate(testTagList, "testTagList");
|
|
taskCreate(mainLoop, "mainLoop");
|
|
taskRun();
|
|
|
|
taskShutdown();
|
|
guiShutdown();
|
|
timerShutdown();
|
|
mouseShutdown();
|
|
surfaceShutdown();
|
|
vbeShutdown();
|
|
|
|
logClose();
|
|
|
|
memoryShutdown();
|
|
|
|
return 0;
|
|
}
|