Initial commit
This commit is contained in:
commit
7d2d0c2fc3
44 changed files with 21337 additions and 0 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.png filter=lfs diff=lfs merge=lfs -text
|
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
build-*
|
||||||
|
*~
|
||||||
|
*.user
|
||||||
|
|
||||||
|
client/bin/
|
||||||
|
client/obj/
|
||||||
|
client/retired/
|
BIN
Icon.png
(Stored with Git LFS)
Normal file
BIN
Icon.png
(Stored with Git LFS)
Normal file
Binary file not shown.
35
LICENSE
Normal file
35
LICENSE
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
Kangaroo Punch Multi Player 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/>.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Licenses Used By:
|
||||||
|
|
||||||
|
|
||||||
|
Client
|
||||||
|
======
|
||||||
|
|
||||||
|
stb_ds.h
|
||||||
|
https://github.com/nothings/stb
|
||||||
|
Public Domain
|
||||||
|
|
||||||
|
stb_leakcheck.h
|
||||||
|
https://github.com/nothings/stb
|
||||||
|
Public Domain
|
||||||
|
|
||||||
|
stb_image.h
|
||||||
|
https://github.com/nothings/stb
|
||||||
|
Public Domain
|
118
client/Makefile.djgpp
Normal file
118
client/Makefile.djgpp
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
#
|
||||||
|
# Kangaroo Punch Multi Player 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
# General
|
||||||
|
CC = gcc
|
||||||
|
LD = gcc
|
||||||
|
RM = rm -rf
|
||||||
|
RMDIR = rmdir
|
||||||
|
INSTALL = install
|
||||||
|
DEBUG = -g
|
||||||
|
|
||||||
|
## CHANGE THIS ##
|
||||||
|
TARGET = client
|
||||||
|
SRCDIR = src
|
||||||
|
OBJDIR = obj
|
||||||
|
BINDIR = bin
|
||||||
|
## CHANGE THIS ##
|
||||||
|
|
||||||
|
# CFLAGS, LDFLAGS, CPPFLAGS, PREFIX can be overriden on CLI
|
||||||
|
CFLAGS := $(DEBUG) -I$(SRCDIR) -I$(SRCDIR)/dos -I$(SRCDIR)/gui -I$(SRCDIR)/thirdparty
|
||||||
|
CPPFLAGS :=
|
||||||
|
LDFLAGS :=
|
||||||
|
PREFIX := /usr/local
|
||||||
|
TARGET_ARCH :=
|
||||||
|
|
||||||
|
|
||||||
|
# Compiler Flags
|
||||||
|
ALL_CFLAGS := $(CFLAGS)
|
||||||
|
ALL_CFLAGS += -Wall -O2
|
||||||
|
|
||||||
|
# Preprocessor Flags
|
||||||
|
ALL_CPPFLAGS := $(CPPFLAGS)
|
||||||
|
|
||||||
|
# Linker Flags
|
||||||
|
ALL_LDFLAGS := $(LDFLAGS)
|
||||||
|
ALL_LDLIBS := -lc
|
||||||
|
|
||||||
|
|
||||||
|
# Source, Binaries, Dependencies
|
||||||
|
SRC := $(shell find $(SRCDIR) -type f -name '*.c' | grep -v '/linux/')
|
||||||
|
OBJ := $(patsubst $(SRCDIR)/%,$(OBJDIR)/%,$(SRC:.c=.o))
|
||||||
|
DEP := $(OBJ:.o=.d)
|
||||||
|
BIN := $(BINDIR)/$(TARGET)
|
||||||
|
-include $(DEP)
|
||||||
|
|
||||||
|
|
||||||
|
# Verbosity Control, ala automake
|
||||||
|
V = 0
|
||||||
|
|
||||||
|
# Verbosity for CC
|
||||||
|
REAL_CC := $(CC)
|
||||||
|
CC_0 = @echo "CC $<"; $(REAL_CC)
|
||||||
|
CC_1 = $(REAL_CC)
|
||||||
|
CC = $(CC_$(V))
|
||||||
|
|
||||||
|
# Verbosity for LD
|
||||||
|
REAL_LD := $(LD)
|
||||||
|
LD_0 = @echo "LD $@"; $(REAL_LD)
|
||||||
|
LD_1 = $(REAL_LD)
|
||||||
|
LD = $(LD_$(V))
|
||||||
|
|
||||||
|
# Verbosity for RM
|
||||||
|
REAL_RM := $(RM)
|
||||||
|
RM_0 = @echo "Cleaning..."; $(REAL_RM)
|
||||||
|
RM_1 = $(REAL_RM)
|
||||||
|
RM = $(RM_$(V))
|
||||||
|
|
||||||
|
# Verbosity for RMDIR
|
||||||
|
REAL_RMDIR := $(RMDIR)
|
||||||
|
RMDIR_0 = @$(REAL_RMDIR)
|
||||||
|
RMDIR_1 = $(REAL_RMDIR)
|
||||||
|
RMDIR = $(RMDIR_$(V))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Build Rules
|
||||||
|
.PHONY: clean
|
||||||
|
.DEFAULT_GOAL := all
|
||||||
|
|
||||||
|
all: setup $(BIN)
|
||||||
|
setup: dir
|
||||||
|
remake: clean all
|
||||||
|
|
||||||
|
dir:
|
||||||
|
@mkdir -p $(OBJDIR)
|
||||||
|
@mkdir -p $(BINDIR)
|
||||||
|
|
||||||
|
|
||||||
|
$(BIN): $(OBJ)
|
||||||
|
$(LD) $(ALL_LDFLAGS) $^ $(ALL_LDLIBS) -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||||
|
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) -c -MMD -MP -o $@ $<
|
||||||
|
|
||||||
|
|
||||||
|
install: $(BIN)
|
||||||
|
$(INSTALL) -d $(PREFIX)/bin
|
||||||
|
$(INSTALL) $(BIN) $(PREFIX)/bin
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(OBJ) $(DEP) $(BIN)
|
||||||
|
$(RMDIR) $(OBJDIR) $(BINDIR) 2> /dev/null; true
|
||||||
|
|
25
client/build.sh
Executable file
25
client/build.sh
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# Kangaroo Punch Multi Player 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
mkdir -p bin obj/dos obj/gui
|
||||||
|
source /opt/cross/djgpp/setenv
|
||||||
|
make -f Makefile.djgpp
|
||||||
|
rm bin/client
|
||||||
|
cp data/* bin/.
|
82
client/client.pro
Normal file
82
client/client.pro
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#
|
||||||
|
# Kangaroo Punch Multi Player 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
TEMPLATE = app
|
||||||
|
CONFIG -= qt
|
||||||
|
|
||||||
|
DESTDIR = $$OUT_PWD/bin
|
||||||
|
|
||||||
|
DOS_HEADERS =
|
||||||
|
|
||||||
|
DOS_SOURCES = \
|
||||||
|
src/dos/mouse.c \
|
||||||
|
src/dos/vesa.c
|
||||||
|
|
||||||
|
LINUX_INCLUDES = \
|
||||||
|
$$PWD/src/linux
|
||||||
|
|
||||||
|
LINUX_HEADERS =
|
||||||
|
|
||||||
|
LINUX_SOURCES = \
|
||||||
|
src/linux/linux.c
|
||||||
|
|
||||||
|
INCLUDEPATH += \
|
||||||
|
$$LINUX_INCLUDES \
|
||||||
|
$$PWD/src \
|
||||||
|
$$PWD/src/gui \
|
||||||
|
$$PWD/src/thirdparty
|
||||||
|
|
||||||
|
HEADERS = \
|
||||||
|
$$LINUX_HEADERS \
|
||||||
|
src/thirdparty/stb_ds.h \
|
||||||
|
src/thirdparty/stb_leakcheck.h \
|
||||||
|
src/thirdparty/stb_image.h \
|
||||||
|
src/gui/array.h \
|
||||||
|
src/gui/font.h \
|
||||||
|
src/gui/desktop.h \
|
||||||
|
src/gui/gui.h \
|
||||||
|
src/gui/widget.h \
|
||||||
|
src/gui/window.h \
|
||||||
|
src/gui/log.h \
|
||||||
|
src/gui/memory.h \
|
||||||
|
src/gui/mouse.h \
|
||||||
|
src/gui/vesa.h \
|
||||||
|
src/gui/image.h \
|
||||||
|
src/gui/os.h
|
||||||
|
|
||||||
|
SOURCES = \
|
||||||
|
$$LINUX_SOURCES \
|
||||||
|
src/gui/array.c \
|
||||||
|
src/gui/font.c \
|
||||||
|
src/gui/desktop.c \
|
||||||
|
src/gui/gui.c \
|
||||||
|
src/gui/widget.c \
|
||||||
|
src/gui/window.c \
|
||||||
|
src/gui/image.c \
|
||||||
|
src/gui/log.c \
|
||||||
|
src/gui/memory.c \
|
||||||
|
src/main.c
|
||||||
|
|
||||||
|
LIBS = \
|
||||||
|
-lSDL2
|
||||||
|
|
||||||
|
OTHER_FILES = \
|
||||||
|
Makefile.djgpp \
|
||||||
|
$$DOS_HEADERS \
|
||||||
|
$$DOS_SOURCES \
|
||||||
|
build.sh
|
BIN
client/data/mouse.png
(Stored with Git LFS)
Normal file
BIN
client/data/mouse.png
(Stored with Git LFS)
Normal file
Binary file not shown.
102
client/src/dos/mouse.c
Normal file
102
client/src/dos/mouse.c
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 "mouse.h"
|
||||||
|
#include "vesa.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Based on http://www.brackeen.com/vga/source/djgpp20/mouse.c.html
|
||||||
|
|
||||||
|
|
||||||
|
#define MOUSE_INT 0x33
|
||||||
|
|
||||||
|
#define MOUSE_RESET 0x00
|
||||||
|
#define MOUSE_STATUS 0x03
|
||||||
|
#define MOUSE_GETMOTION 0x0B
|
||||||
|
|
||||||
|
#define MOUSE_LEFT_BUTTON 0x01
|
||||||
|
#define MOUSE_RIGHT_BUTTON 0x02
|
||||||
|
#define MOUSE_MIDDLE_BUTTON 0x04
|
||||||
|
|
||||||
|
|
||||||
|
static MouseT _mouse;
|
||||||
|
|
||||||
|
|
||||||
|
MouseT *mouseRead(void) {
|
||||||
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
int16_t dx;
|
||||||
|
int16_t dy;
|
||||||
|
union REGS regs;
|
||||||
|
|
||||||
|
regs.x.ax = MOUSE_GETMOTION;
|
||||||
|
int86(MOUSE_INT, ®s, ®s);
|
||||||
|
dx = regs.x.cx; // Temporary assignment changes values to signed.
|
||||||
|
dy = regs.x.dx; // Don't skip this step. :-)
|
||||||
|
x = _mouse.x + dx;
|
||||||
|
y = _mouse.y + dy;
|
||||||
|
if (x < 0) x = 0;
|
||||||
|
if (x > _mouse.w - 1) x = _mouse.w - 1;
|
||||||
|
if (y < 0) y = 0;
|
||||||
|
if (y > _mouse.h - 1) y = _mouse.h - 1;
|
||||||
|
_mouse.x = (uint16_t)x;
|
||||||
|
_mouse.y = (uint16_t)y;
|
||||||
|
|
||||||
|
_mouse.buttonLeftWasDown = _mouse.buttonLeft;
|
||||||
|
_mouse.buttonRightWasDown = _mouse.buttonRight;
|
||||||
|
_mouse.buttonMiddleWasDown = _mouse.buttonMiddle;
|
||||||
|
|
||||||
|
regs.x.ax = MOUSE_STATUS;
|
||||||
|
int86(MOUSE_INT, ®s, ®s);
|
||||||
|
_mouse.buttonLeft = ((regs.x.bx & MOUSE_LEFT_BUTTON) > 0);
|
||||||
|
_mouse.buttonRight = ((regs.x.bx & MOUSE_RIGHT_BUTTON) > 0);
|
||||||
|
_mouse.buttonMiddle = ((regs.x.bx & MOUSE_MIDDLE_BUTTON) > 0);
|
||||||
|
|
||||||
|
return &_mouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mouseShutdown(void) {
|
||||||
|
// Nothing to do in DOS
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int16_t mouseStartup(void) {
|
||||||
|
union REGS regs;
|
||||||
|
|
||||||
|
regs.x.ax = MOUSE_RESET;
|
||||||
|
int86(MOUSE_INT, ®s, ®s);
|
||||||
|
_mouse.active = regs.x.ax;
|
||||||
|
_mouse.buttonCount = regs.x.bx == 0x0002 ? 2 : 3;
|
||||||
|
_mouse.buttonLeft = 0;
|
||||||
|
_mouse.buttonRight = 0;
|
||||||
|
_mouse.buttonMiddle = 0;
|
||||||
|
_mouse.buttonLeftWasDown = 0;
|
||||||
|
_mouse.buttonRightWasDown = 0;
|
||||||
|
_mouse.buttonMiddleWasDown = 0;
|
||||||
|
_mouse.x = 0;
|
||||||
|
_mouse.y = 0;
|
||||||
|
_mouse.w = vbeDisplayWidthGet();
|
||||||
|
_mouse.h = vbeDisplayHeightGet();
|
||||||
|
|
||||||
|
mouseRead();
|
||||||
|
|
||||||
|
return _mouse.active;
|
||||||
|
}
|
817
client/src/dos/vesa.c
Normal file
817
client/src/dos/vesa.c
Normal file
|
@ -0,0 +1,817 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 "os.h"
|
||||||
|
|
||||||
|
#include "vesa.h"
|
||||||
|
|
||||||
|
|
||||||
|
// http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html
|
||||||
|
|
||||||
|
|
||||||
|
// These are all we support
|
||||||
|
#define VBE_MM_PACKED 4
|
||||||
|
#define VBE_MM_DCOLOR 6
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct VBEInfoS {
|
||||||
|
char vbeSignature[4]; // 'VESA' 4 byte signature
|
||||||
|
int16_t vbeVersion; // VBE version number
|
||||||
|
char *oemStringPtr; // Pointer to OEM string
|
||||||
|
uint32_t capabilities; // Capabilities of video card
|
||||||
|
uint16_t *videoModePtr; // Pointer to supported modes
|
||||||
|
uint16_t totalMemory; // Number of 64kb memory blocks
|
||||||
|
// added for VBE 2.0
|
||||||
|
uint16_t oemSoftwareRev; // OEM Software revision number
|
||||||
|
char *oemVendorNamePtr; // Pointer to Vendor Name string
|
||||||
|
char *oemProductNamePtr; // Pointer to Product Name string
|
||||||
|
char *oemProductRevPtr; // Pointer to Product Revision str
|
||||||
|
char reserved[222]; // Pad to 256 byte block size
|
||||||
|
char oemData[256]; // Scratch pad for OEM data
|
||||||
|
} __attribute__ ((packed)) VBEInfoT;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct VBEModeInfoS {
|
||||||
|
// Mandatory information for all VBE revisions:
|
||||||
|
uint16_t modeAttributes; // mode attributes
|
||||||
|
uint8_t winAAttributes; // window A attributes
|
||||||
|
uint8_t winBAttributes; // window B attributes
|
||||||
|
uint16_t winGranularity; // window granularity
|
||||||
|
uint16_t winSize; // window size
|
||||||
|
uint16_t winASegment; // window A start segment
|
||||||
|
uint16_t winBSegment; // window B start segment
|
||||||
|
uint32_t winFuncPtr; // pointer to window function
|
||||||
|
uint16_t bytesPerScanLine; // bytes per scan line
|
||||||
|
// Mandatory information for VBE 1.2 and above:
|
||||||
|
uint16_t xResolution; // horizontal resolution in pixels or chars
|
||||||
|
uint16_t yResolution; // vertical resolution in pixels or chars
|
||||||
|
uint8_t xCharSize; // character cell width in pixels
|
||||||
|
uint8_t yCharSize; // character cell height in pixels
|
||||||
|
uint8_t numberOfPlanes; // number of memory planes
|
||||||
|
uint8_t bitsPerPixel; // bits per pixel
|
||||||
|
uint8_t numberOfBanks; // number of banks
|
||||||
|
uint8_t memoryModel; // memory model type
|
||||||
|
uint8_t bankSize; // bank size in KB
|
||||||
|
uint8_t numberOfImagePages; // number of images
|
||||||
|
uint8_t reserved; // reserved for page function
|
||||||
|
// Direct Color fields (required for direct/6 and YUV/7 memory models)
|
||||||
|
uint8_t redMaskSize; // size of direct color red mask in bits
|
||||||
|
uint8_t redFieldPosition; // bit position of lsb of red mask
|
||||||
|
uint8_t greenMaskSize; // size of direct color green mask in bits
|
||||||
|
uint8_t greenFieldPosition; // bit position of lsb of green mask
|
||||||
|
uint8_t blueMaskSize; // size of direct color blue mask in bits
|
||||||
|
uint8_t blueFieldPosition; // bit position of lsb of blue mask
|
||||||
|
uint8_t rsvdMaskSize; // size of direct color reserved mask in bits
|
||||||
|
uint8_t rsvdFieldPosition; // bit position of lsb of reserved mask
|
||||||
|
uint8_t directColorModeInfo; // direct color mode attributes
|
||||||
|
// Mandatory information for VBE 2.0 and above:
|
||||||
|
uint32_t physBasePtr; // physical address for flat frame buffer
|
||||||
|
uint32_t offScreenMemOffset; // pointer to start of off screen memory
|
||||||
|
uint16_t offScreenMemSize; // amount of off screen memory in 1k units
|
||||||
|
char reservedBuf[206];
|
||||||
|
} __attribute__ ((packed)) VBEModeInfoT;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct PModeInterfaceS {
|
||||||
|
int16_t setWindow;
|
||||||
|
int16_t setDisplayStart;
|
||||||
|
int16_t setPalette;
|
||||||
|
int16_t ioInfo;
|
||||||
|
} __attribute__ ((packed)) PModeInterfaceT;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct VBESurfaceS {
|
||||||
|
uint32_t lfbLinearAddress;
|
||||||
|
uint16_t lfbSelector;
|
||||||
|
void *lfbNearPtr;
|
||||||
|
uint32_t lfbMemSize;
|
||||||
|
uint16_t xResolution;
|
||||||
|
uint16_t yResolution;
|
||||||
|
uint32_t bitsPerPixel;
|
||||||
|
uint16_t virtualXResolution;
|
||||||
|
uint32_t bytesPerPixel;
|
||||||
|
uint32_t screenBytes;
|
||||||
|
uint32_t screenDWords;
|
||||||
|
uint32_t centerX;
|
||||||
|
uint32_t centerY;
|
||||||
|
uint16_t numberOfOffscreens;
|
||||||
|
uint8_t vbeBoolean;
|
||||||
|
uint8_t vbeInitBoolean;
|
||||||
|
int32_t ioSegment;
|
||||||
|
uint32_t ioLinear;
|
||||||
|
uint32_t rMask;
|
||||||
|
uint32_t gMask;
|
||||||
|
uint32_t bMask;
|
||||||
|
uint32_t aMask;
|
||||||
|
uint8_t rShift;
|
||||||
|
uint8_t gShift;
|
||||||
|
uint8_t bShift;
|
||||||
|
uint8_t aShift;
|
||||||
|
uint8_t rPos;
|
||||||
|
uint8_t gPos;
|
||||||
|
uint8_t bPos;
|
||||||
|
uint8_t aPos;
|
||||||
|
} VBESurfaceT;
|
||||||
|
|
||||||
|
|
||||||
|
VBEInfoT *vbeGetInfo(void);
|
||||||
|
VBEModeInfoT *vbeGetModeInfo(uint16_t vbeModeNumber);
|
||||||
|
VBEModeInfoT *vbeGetModeInfoPtr(void);
|
||||||
|
void *vbeGetPmodeInterface(void);
|
||||||
|
VBESurfaceT *vbeGetVBESurfacePtr(void);
|
||||||
|
VBESurfaceT *vbeModeInit(uint16_t xRes, uint16_t yRes, uint8_t bpp);
|
||||||
|
void vbePresent(void);
|
||||||
|
uint16_t vbeSelectModeNumber(uint16_t xRes, uint16_t yRes, uint8_t bpp);
|
||||||
|
void vbeSetDisplayStart(uint32_t pixel, uint32_t scanline);
|
||||||
|
VBESurfaceT *vbeSetMode(uint16_t vbeModeNumber);
|
||||||
|
uint16_t vbeSetScanlineLength(uint16_t pixelLength);
|
||||||
|
|
||||||
|
void (*vbePutPixel)(uint16_t x, uint16_t y, PixelT pixel);
|
||||||
|
|
||||||
|
static void (*pmVBESetDisplayStart)(void);
|
||||||
|
|
||||||
|
|
||||||
|
static void vbeCreatePalette(void);
|
||||||
|
static uint8_t vbeIsDesiredMode(void);
|
||||||
|
static void vbePutPixel8(uint16_t x, uint16_t y, PixelT pixel);
|
||||||
|
static void vbePutPixel16(uint16_t x, uint16_t y, PixelT pixel);
|
||||||
|
static void vbePutPixel32(uint16_t x, uint16_t y, PixelT pixel);
|
||||||
|
|
||||||
|
|
||||||
|
static VBESurfaceT _vbeSurface;
|
||||||
|
static VBEInfoT _vbeInfo;
|
||||||
|
static VBEModeInfoT _vbeModeInfo;
|
||||||
|
static PModeInterfaceT *_pmodeInterfacePtr;
|
||||||
|
static uint32_t *_yTable;
|
||||||
|
static SurfaceT *_activeSurface;
|
||||||
|
static SurfaceT *_offScreenSurface;
|
||||||
|
|
||||||
|
|
||||||
|
static void vbeCreatePalette(void) {
|
||||||
|
uint8_t color = 0;
|
||||||
|
uint8_t red;
|
||||||
|
uint8_t green;
|
||||||
|
uint8_t blue;
|
||||||
|
|
||||||
|
// Create palette for 3:3:2 true color emulation
|
||||||
|
for (red = 4; red < 68; red += 8) {
|
||||||
|
for (green = 4; green < 68; green += 8) {
|
||||||
|
for (blue = 4; blue < 68; blue += 16) {
|
||||||
|
outportb(0x3C8, color);
|
||||||
|
outportb(0x3C9, red);
|
||||||
|
outportb(0x3C9, green);
|
||||||
|
outportb(0x3C9, blue);
|
||||||
|
color++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t vbeDisplayDepthGet(void) {
|
||||||
|
return _vbeSurface.bitsPerPixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t vbeDisplayHeightGet(void) {
|
||||||
|
return _vbeSurface.yResolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t vbeDisplayWidthGet(void) {
|
||||||
|
return _vbeSurface.xResolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VBEInfoT *vbeGetInfo(void) {
|
||||||
|
uint16_t counter = 0;
|
||||||
|
uint16_t offset = 0;
|
||||||
|
uint16_t vbeMode = 0xFFFF;
|
||||||
|
uint16_t *vbeModeList = 0;
|
||||||
|
__dpmi_regs r;
|
||||||
|
|
||||||
|
// we want VBE 2.0+ info
|
||||||
|
memcpy(_vbeInfo.vbeSignature, "VBE2", 4);
|
||||||
|
|
||||||
|
// request info
|
||||||
|
r.x.ax = 0x4F00;
|
||||||
|
r.x.di = __tb & 0x0F;
|
||||||
|
r.x.es = (__tb >> 4) & 0xFFFF;
|
||||||
|
dosmemput(&_vbeInfo, sizeof(VBEInfoT), __tb);
|
||||||
|
__dpmi_int(0x10, &r);
|
||||||
|
if (r.x.ax != 0x004F) return NULL;
|
||||||
|
dosmemget(__tb, sizeof(VBEInfoT), &_vbeInfo);
|
||||||
|
|
||||||
|
if (strncmp(_vbeInfo.vbeSignature, "VESA", 4) != 0) return NULL; // VESA ?
|
||||||
|
|
||||||
|
// get the videomode list
|
||||||
|
do {
|
||||||
|
dosmemget(((((long)_vbeInfo.videoModePtr >> 16) & 0xFFFF) << 4) + ((long)_vbeInfo.videoModePtr & 0xFFFF) + (counter * sizeof(short)), sizeof(short), &vbeMode);
|
||||||
|
counter++;
|
||||||
|
} while (vbeMode != 0xFFFF);
|
||||||
|
vbeModeList = malloc((counter + 1) * sizeof(short));
|
||||||
|
|
||||||
|
counter = 0;
|
||||||
|
do {
|
||||||
|
dosmemget(((((long)_vbeInfo.videoModePtr >> 16) & 0xFFFF) << 4) + ((long)_vbeInfo.videoModePtr & 0xFFFF) + (counter * sizeof(short)), sizeof(short), &vbeModeList[counter]);
|
||||||
|
counter++;
|
||||||
|
} while (vbeModeList[counter - 1] != 0xFFFF);
|
||||||
|
_vbeInfo.videoModePtr = vbeModeList;
|
||||||
|
|
||||||
|
// get the OEM string
|
||||||
|
counter = 0;
|
||||||
|
do {
|
||||||
|
dosmemget(((((long)_vbeInfo.oemStringPtr >> 16) & 0xFFFF) << 4) + ((long)_vbeInfo.oemStringPtr & 0xFFFF) + counter, sizeof(char), &_vbeInfo.oemData[counter]);
|
||||||
|
counter++;
|
||||||
|
} while (_vbeInfo.oemData[counter - 1] != 0);
|
||||||
|
_vbeInfo.oemStringPtr = &_vbeInfo.oemData[0];
|
||||||
|
offset = counter;
|
||||||
|
|
||||||
|
if (_vbeInfo.vbeVersion >= 0x0200) {
|
||||||
|
// get the vendor name
|
||||||
|
counter = 0;
|
||||||
|
do {
|
||||||
|
dosmemget(((((long)_vbeInfo.oemVendorNamePtr >> 16) & 0xFFFF) << 4) + ((long)_vbeInfo.oemVendorNamePtr & 0xFFFF) + counter, sizeof(char), &_vbeInfo.oemData[counter + offset]);
|
||||||
|
counter++;
|
||||||
|
} while (_vbeInfo.oemData[counter + offset - 1] != 0);
|
||||||
|
_vbeInfo.oemVendorNamePtr = &_vbeInfo.oemData[offset];
|
||||||
|
offset = offset + counter;
|
||||||
|
|
||||||
|
// get the product name
|
||||||
|
counter = 0;
|
||||||
|
do {
|
||||||
|
dosmemget(((((long)_vbeInfo.oemProductNamePtr >> 16) & 0xFFFF) << 4) + ((long)_vbeInfo.oemProductNamePtr & 0xFFFF) + counter, sizeof(char), &_vbeInfo.oemData[counter + offset]);
|
||||||
|
counter++;
|
||||||
|
} while (_vbeInfo.oemData[counter + offset - 1] != 0);
|
||||||
|
_vbeInfo.oemProductNamePtr = &_vbeInfo.oemData[offset];
|
||||||
|
offset = offset + counter;
|
||||||
|
|
||||||
|
//get the product revision
|
||||||
|
counter = 0;
|
||||||
|
do {
|
||||||
|
dosmemget(((((long)_vbeInfo.oemProductRevPtr >> 16) & 0xFFFF) << 4) + ((long)_vbeInfo.oemProductRevPtr & 0xFFFF) + counter, sizeof(char), &_vbeInfo.oemData[counter + offset]);
|
||||||
|
counter++;
|
||||||
|
} while (_vbeInfo.oemData[counter + offset - 1] != 0);
|
||||||
|
_vbeInfo.oemProductRevPtr = &_vbeInfo.oemData[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
_vbeSurface.vbeBoolean = 1;
|
||||||
|
|
||||||
|
return(&_vbeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VBEModeInfoT *vbeGetModeInfo(uint16_t vbeModeNumber) {
|
||||||
|
__dpmi_regs r;
|
||||||
|
|
||||||
|
if (_vbeSurface.vbeBoolean == 0) return NULL;
|
||||||
|
|
||||||
|
r.x.ax = 0x4F01;
|
||||||
|
r.x.cx = vbeModeNumber;
|
||||||
|
r.x.di = __tb & 0x0F;
|
||||||
|
r.x.es = (__tb >> 4) & 0xFFFF;
|
||||||
|
__dpmi_int(0x10, &r);
|
||||||
|
|
||||||
|
if (r.x.ax != 0x004F) return NULL;
|
||||||
|
|
||||||
|
dosmemget(__tb, sizeof(VBEModeInfoT), &_vbeModeInfo);
|
||||||
|
|
||||||
|
// Fake 3:3:2 true color for packed modes.
|
||||||
|
if (_vbeModeInfo.bitsPerPixel == 8) {
|
||||||
|
_vbeModeInfo.blueMaskSize = 2;
|
||||||
|
_vbeModeInfo.greenMaskSize = 3;
|
||||||
|
_vbeModeInfo.redMaskSize = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_vbeModeInfo.bitsPerPixel == 16) {
|
||||||
|
// for buggy VBE implementations
|
||||||
|
_vbeModeInfo.bitsPerPixel = _vbeModeInfo.redMaskSize + _vbeModeInfo.greenMaskSize + _vbeModeInfo.blueMaskSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(&_vbeModeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VBEModeInfoT *vbeGetModeInfoPtr(void) {
|
||||||
|
return(&_vbeModeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *vbeGetPmodeInterface(void) {
|
||||||
|
__dpmi_regs r;
|
||||||
|
__dpmi_meminfo m;
|
||||||
|
uint16_t *ptr;
|
||||||
|
|
||||||
|
// only available in VBE 2.0+
|
||||||
|
if (_vbeInfo.vbeVersion < 0x200) return NULL;
|
||||||
|
|
||||||
|
r.x.ax = 0x4F0A;
|
||||||
|
r.x.bx = 0;
|
||||||
|
__dpmi_int(0x10, &r);
|
||||||
|
if (r.x.ax != 0x004F) return NULL;
|
||||||
|
|
||||||
|
// copy interface
|
||||||
|
_pmodeInterfacePtr = (PModeInterfaceT *)malloc(r.x.cx);
|
||||||
|
dosmemget((r.x.es * 16) + r.x.di, r.x.cx, _pmodeInterfacePtr);
|
||||||
|
_go32_dpmi_lock_data(_pmodeInterfacePtr, r.x.cx);
|
||||||
|
|
||||||
|
// need memory-mapped IO?
|
||||||
|
if (_pmodeInterfacePtr->ioInfo) {
|
||||||
|
printf("\nGot IOInfo\n");
|
||||||
|
ptr = (uint16_t *)((char *)_pmodeInterfacePtr + _pmodeInterfacePtr->ioInfo);
|
||||||
|
// skip the port table...
|
||||||
|
while (*ptr != 0xFFFF)
|
||||||
|
ptr++;
|
||||||
|
ptr++;
|
||||||
|
// ...and get descriptor
|
||||||
|
if (*ptr != 0xFFFF) {
|
||||||
|
m.address = *((uint32_t *)ptr);
|
||||||
|
m.size = *(ptr + 2);
|
||||||
|
if (__dpmi_physical_address_mapping(&m) != 0) return NULL;
|
||||||
|
_vbeSurface.ioLinear = m.address;
|
||||||
|
__dpmi_lock_linear_region(&m);
|
||||||
|
_vbeSurface.ioSegment = __dpmi_allocate_ldt_descriptors(1);
|
||||||
|
if (_vbeSurface.ioSegment < 0) {
|
||||||
|
__dpmi_unlock_linear_region(&m);
|
||||||
|
__dpmi_free_physical_address_mapping(&m);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
__dpmi_set_segment_base_address(_vbeSurface.ioSegment, _vbeSurface.ioLinear);
|
||||||
|
__dpmi_set_segment_limit(_vbeSurface.ioSegment, m.size - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pmVBESetDisplayStart = (void *)((char *)_pmodeInterfacePtr + _pmodeInterfacePtr->setDisplayStart);
|
||||||
|
|
||||||
|
return pmVBESetDisplayStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VBESurfaceT *vbeGetVBESurfacePtr(void) {
|
||||||
|
return(&_vbeSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t vbeIsDesiredMode(void) {
|
||||||
|
// This is a custom filter to remove modes not supported by the calling application.
|
||||||
|
|
||||||
|
// Must be linear.
|
||||||
|
if (((_vbeModeInfo.modeAttributes) & (1<<7)) >> 7) {
|
||||||
|
// Packed or Direct Color mode.
|
||||||
|
if (_vbeModeInfo.memoryModel == VBE_MM_PACKED || _vbeModeInfo.memoryModel == VBE_MM_DCOLOR) {
|
||||||
|
// Resolution minimum of 640x480.
|
||||||
|
if (_vbeModeInfo.xResolution >= 640 && _vbeModeInfo.yResolution >= 480) {
|
||||||
|
// Multiple of 8
|
||||||
|
if (DIVISIBLE_BY_EIGHT(_vbeModeInfo.xResolution) && DIVISIBLE_BY_EIGHT(_vbeModeInfo.yResolution)) {
|
||||||
|
// Valid mode!
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rejected!
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PixelT vbeMakePixel(uint8_t red, uint8_t green, uint8_t blue) {
|
||||||
|
return
|
||||||
|
(((red >> _vbeSurface.rShift) << _vbeSurface.rPos) & _vbeSurface.rMask) |
|
||||||
|
(((green >> _vbeSurface.gShift) << _vbeSurface.gPos) & _vbeSurface.gMask) |
|
||||||
|
(((blue >> _vbeSurface.bShift) << _vbeSurface.bPos) & _vbeSurface.bMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VBESurfaceT *vbeModeInit(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
|
||||||
|
uint16_t vbeModeNumber;
|
||||||
|
__dpmi_meminfo m;
|
||||||
|
|
||||||
|
if (_vbeSurface.vbeBoolean == 0) return NULL;
|
||||||
|
if (_vbeSurface.vbeInitBoolean == 0) return NULL;
|
||||||
|
|
||||||
|
m.size = (_vbeInfo.totalMemory * 64 * 1024);
|
||||||
|
m.address = _vbeSurface.lfbLinearAddress;
|
||||||
|
__dpmi_unlock_linear_region(&m);
|
||||||
|
__dpmi_free_physical_address_mapping(&m);
|
||||||
|
__dpmi_free_ldt_descriptor(_vbeSurface.lfbSelector);
|
||||||
|
|
||||||
|
_vbeSurface.vbeInitBoolean = 0;
|
||||||
|
|
||||||
|
if ((vbeModeNumber = vbeSelectModeNumber(xRes, yRes, bpp)) == 0) return NULL;
|
||||||
|
|
||||||
|
vbeModeNumber |= 0x8000;
|
||||||
|
if (vbeSetMode(vbeModeNumber) == NULL) return NULL;
|
||||||
|
|
||||||
|
return(&_vbeSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbePresent(void) {
|
||||||
|
_movedatal(_my_ds(), (int32_t)_offScreenSurface->buffer.bits32, _vbeSurface.lfbSelector, 0x0, _vbeSurface.screenDWords);
|
||||||
|
//memset(_offScreenSurface->buffer.bits8, 0, _offScreenSurface->bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void vbePutPixel8(uint16_t x, uint16_t y, PixelT pixel) {
|
||||||
|
//_farpokeb(_vbeSurface.lfbSelector, _yTable[y] + x, (uint8_t)pixel);
|
||||||
|
_activeSurface->buffer.bits8[y * _activeSurface->width + x] = (uint8_t)pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void vbePutPixel16(uint16_t x, uint16_t y, PixelT pixel) {
|
||||||
|
//_farpokew(_vbeSurface.lfbSelector, _yTable[y] + (x << 1), (uint16_t)pixel);
|
||||||
|
_activeSurface->buffer.bits16[y * _activeSurface->width + x] = (uint16_t)pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void vbePutPixel32(uint16_t x, uint16_t y, PixelT pixel) {
|
||||||
|
//_farpokel(_vbeSurface.lfbSelector, _yTable[y] + (x << 2), pixel);
|
||||||
|
_activeSurface->buffer.bits32[y * _activeSurface->width + x] = pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t vbeSelectModeNumber(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
|
||||||
|
uint16_t counter;
|
||||||
|
|
||||||
|
if (_vbeSurface.vbeBoolean == 0) return(0);
|
||||||
|
|
||||||
|
for (counter = 0; ; counter++) {
|
||||||
|
if (_vbeInfo.videoModePtr[counter] == 0xFFFF) return(0);
|
||||||
|
vbeGetModeInfo(_vbeInfo.videoModePtr[counter]);
|
||||||
|
if (vbeIsDesiredMode()) {
|
||||||
|
if (_vbeModeInfo.xResolution == xRes && _vbeModeInfo.yResolution == yRes && _vbeModeInfo.bitsPerPixel == bpp)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(_vbeInfo.videoModePtr[counter]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeSetDisplayStart(uint32_t pixel, uint32_t scanline) {
|
||||||
|
__dpmi_regs r;
|
||||||
|
int32_t address;
|
||||||
|
int32_t selector;
|
||||||
|
|
||||||
|
if (pmVBESetDisplayStart) {
|
||||||
|
address = (_yTable[scanline] + (pixel * _vbeSurface.bytesPerPixel)) >> 2;
|
||||||
|
selector = (_vbeSurface.ioSegment) ? _vbeSurface.ioSegment : _my_ds();
|
||||||
|
asm(
|
||||||
|
" pushw %%es ; "
|
||||||
|
" movw %w1, %%es ; " // set the IO segment
|
||||||
|
" call *%0 ; " // call the VESA function
|
||||||
|
" popw %%es "
|
||||||
|
: // no outputs
|
||||||
|
|
||||||
|
: "S"(pmVBESetDisplayStart), // function pointer in esi
|
||||||
|
"a"(selector), // IO segment in eax
|
||||||
|
"b"(0x0080), // mode in ebx
|
||||||
|
"c"(address & 0xFFFF), // low word of address in ecx
|
||||||
|
"d"((address >> 16)) // high word of address in edx
|
||||||
|
|
||||||
|
: "memory", "%edi", "%cc" // touches edi and flags
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.x.ax = 0x4F07;
|
||||||
|
r.x.bx = 0x0080;
|
||||||
|
r.x.cx = pixel;
|
||||||
|
r.x.dx = scanline;
|
||||||
|
__dpmi_int(0x10, &r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VBESurfaceT *vbeSetMode(uint16_t vbeModeNumber) {
|
||||||
|
__dpmi_regs r;
|
||||||
|
__dpmi_meminfo m;
|
||||||
|
uint32_t counter;
|
||||||
|
|
||||||
|
if (_vbeSurface.vbeBoolean == 0) return NULL;
|
||||||
|
if (_vbeSurface.vbeInitBoolean == 1) return NULL;
|
||||||
|
if (vbeGetModeInfo(vbeModeNumber) == 0) return NULL;
|
||||||
|
|
||||||
|
// create lookup table for putPixel routines
|
||||||
|
if (_yTable) free(_yTable);
|
||||||
|
if ((_yTable = malloc(4 * (_vbeModeInfo.yResolution + 1))) == 0) return NULL;
|
||||||
|
for (counter = 0; counter <= _vbeModeInfo.yResolution; counter++) {
|
||||||
|
_yTable[counter] = _vbeModeInfo.xResolution * counter;// * ((_vbeModeInfo.bitsPerPixel + 1) / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// request frame buffer
|
||||||
|
r.x.ax = 0x4F02;
|
||||||
|
r.x.bx = (vbeModeNumber | 0x4000);
|
||||||
|
__dpmi_int(0x10, &r);
|
||||||
|
if (r.x.ax != 0x004F) return(0);
|
||||||
|
|
||||||
|
m.size = (_vbeInfo.totalMemory * 64 * 1024);
|
||||||
|
m.address = _vbeModeInfo.physBasePtr;
|
||||||
|
__dpmi_physical_address_mapping(&m);
|
||||||
|
__dpmi_lock_linear_region(&m);
|
||||||
|
|
||||||
|
_vbeSurface.lfbLinearAddress = m.address;
|
||||||
|
_vbeSurface.lfbSelector = __dpmi_allocate_ldt_descriptors(1);
|
||||||
|
|
||||||
|
__dpmi_set_segment_base_address(_vbeSurface.lfbSelector, _vbeSurface.lfbLinearAddress);
|
||||||
|
__dpmi_set_segment_limit(_vbeSurface.lfbSelector, (_vbeInfo.totalMemory * 64 * 1024) - 1);
|
||||||
|
|
||||||
|
_vbeSurface.lfbNearPtr = (void *)(_vbeSurface.lfbLinearAddress + __djgpp_conventional_base);
|
||||||
|
_vbeSurface.xResolution = _vbeModeInfo.xResolution;
|
||||||
|
_vbeSurface.yResolution = _vbeModeInfo.yResolution;
|
||||||
|
_vbeSurface.bitsPerPixel = _vbeModeInfo.bitsPerPixel;
|
||||||
|
_vbeSurface.virtualXResolution = _vbeModeInfo.xResolution;
|
||||||
|
_vbeSurface.bytesPerPixel = (_vbeModeInfo.bitsPerPixel + 1) / 8;
|
||||||
|
_vbeSurface.centerX = _vbeSurface.virtualXResolution / 2;
|
||||||
|
_vbeSurface.centerY = _vbeSurface.yResolution / 2;
|
||||||
|
_vbeSurface.numberOfOffscreens = vbeSetScanlineLength(_vbeModeInfo.xResolution) / _vbeModeInfo.yResolution;
|
||||||
|
_vbeSurface.vbeInitBoolean = 1;
|
||||||
|
_vbeSurface.screenBytes = (_vbeSurface.xResolution * _vbeSurface.yResolution * _vbeSurface.bytesPerPixel);
|
||||||
|
_vbeSurface.screenDWords = _vbeSurface.screenBytes / 4;
|
||||||
|
_vbeSurface.lfbMemSize = (_vbeSurface.xResolution * _vbeSurface.yResolution * _vbeSurface.bytesPerPixel) / 1024 + _vbeModeInfo.offScreenMemSize;
|
||||||
|
|
||||||
|
for (counter = 0; counter < (_vbeSurface.lfbMemSize * 1024); counter++) {
|
||||||
|
_farpokeb(_vbeSurface.lfbSelector, counter, 0x0); // clear Lfb
|
||||||
|
}
|
||||||
|
|
||||||
|
_offScreenSurface = vbeSurfaceCreate(_vbeSurface.xResolution, _vbeSurface.yResolution);
|
||||||
|
|
||||||
|
if (_vbeModeInfo.memoryModel == VBE_MM_PACKED) {
|
||||||
|
vbeCreatePalette();
|
||||||
|
|
||||||
|
_vbeModeInfo.redFieldPosition = 5;
|
||||||
|
_vbeModeInfo.greenFieldPosition = 2;
|
||||||
|
_vbeModeInfo.blueFieldPosition = 0;
|
||||||
|
_vbeModeInfo.rsvdFieldPosition = 7;
|
||||||
|
|
||||||
|
_vbeModeInfo.redMaskSize = 3;
|
||||||
|
_vbeModeInfo.greenMaskSize = 3;
|
||||||
|
_vbeModeInfo.blueMaskSize = 2;
|
||||||
|
_vbeModeInfo.rsvdMaskSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_vbeSurface.rMask = ((1UL << _vbeModeInfo.redMaskSize) - 1) << _vbeModeInfo.redFieldPosition;
|
||||||
|
_vbeSurface.gMask = ((1UL << _vbeModeInfo.greenMaskSize) - 1) << _vbeModeInfo.greenFieldPosition;
|
||||||
|
_vbeSurface.bMask = ((1UL << _vbeModeInfo.blueMaskSize) - 1) << _vbeModeInfo.blueFieldPosition;
|
||||||
|
_vbeSurface.aMask = ((1UL << _vbeModeInfo.rsvdMaskSize) - 1) << _vbeModeInfo.rsvdFieldPosition;
|
||||||
|
|
||||||
|
_vbeSurface.rShift = 8 - _vbeModeInfo.redMaskSize;
|
||||||
|
_vbeSurface.gShift = 8 - _vbeModeInfo.greenMaskSize;
|
||||||
|
_vbeSurface.bShift = 8 - _vbeModeInfo.blueMaskSize;
|
||||||
|
_vbeSurface.aShift = 8 - _vbeModeInfo.rsvdMaskSize;
|
||||||
|
|
||||||
|
_vbeSurface.rPos = _vbeModeInfo.redFieldPosition;
|
||||||
|
_vbeSurface.gPos = _vbeModeInfo.greenFieldPosition;
|
||||||
|
_vbeSurface.bPos = _vbeModeInfo.blueFieldPosition;
|
||||||
|
_vbeSurface.aPos = _vbeModeInfo.rsvdFieldPosition;
|
||||||
|
|
||||||
|
if (_vbeSurface.bitsPerPixel == 8) vbePutPixel = vbePutPixel8;
|
||||||
|
if (_vbeSurface.bitsPerPixel == 16) vbePutPixel = vbePutPixel16;
|
||||||
|
if (_vbeSurface.bitsPerPixel == 15) vbePutPixel = vbePutPixel16;
|
||||||
|
if (_vbeSurface.bitsPerPixel == 32) vbePutPixel = vbePutPixel32;
|
||||||
|
|
||||||
|
return(&_vbeSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t vbeSetScanlineLength(uint16_t pixelLength) {
|
||||||
|
__dpmi_regs r;
|
||||||
|
|
||||||
|
if (_vbeSurface.vbeBoolean == 0) return(0);
|
||||||
|
|
||||||
|
r.x.ax = 0x4F06;
|
||||||
|
r.x.bx = 0x0000;
|
||||||
|
r.x.cx = pixelLength;
|
||||||
|
__dpmi_int(0x10, &r);
|
||||||
|
if(r.h.ah != 0) return(0);
|
||||||
|
if(r.x.cx != pixelLength) return(0);
|
||||||
|
|
||||||
|
_vbeSurface.virtualXResolution = pixelLength;
|
||||||
|
|
||||||
|
return(r.x.dx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int16_t vbeShowInfo(void) {
|
||||||
|
int8_t counter;
|
||||||
|
|
||||||
|
// 0 1 2 3 4 5 6 7 8
|
||||||
|
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||||
|
printf("VBE 2.0 driver v1.0 (c) 2021, Scott Duensing <scott@kangaroopunch.com>\n");
|
||||||
|
printf("Based on: VBE 2.0 driver v1.0 (c) 1999, Tobias Koch <tobias.koch@gmail.com>\n\n");
|
||||||
|
|
||||||
|
if (vbeGetInfo() == NULL) {
|
||||||
|
printf("No VESA BIOS Extensions found.\n\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
printf(
|
||||||
|
"Video Memory - %d KB\n"
|
||||||
|
"VBE Version - %d.%d detected\n"
|
||||||
|
"OEM Specification - %s\n",
|
||||||
|
_vbeInfo.totalMemory * 64,
|
||||||
|
_vbeInfo.vbeVersion >> 8, _vbeInfo.vbeVersion & 0x00FF,
|
||||||
|
_vbeInfo.oemStringPtr);
|
||||||
|
|
||||||
|
if (_vbeInfo.vbeVersion >= 0x0200) {
|
||||||
|
printf(
|
||||||
|
"OEM Software Revision - %d.%d\n"
|
||||||
|
"OEM Vendor Name - %s\n"
|
||||||
|
"OEM Product Name - %s\n"
|
||||||
|
"OEM Product Revision - %s\n"
|
||||||
|
"Protected Mode Interface - %s\n\n",
|
||||||
|
_vbeInfo.oemSoftwareRev >> 8, _vbeInfo.oemSoftwareRev & 0x00FF,
|
||||||
|
_vbeInfo.oemVendorNamePtr,
|
||||||
|
_vbeInfo.oemProductNamePtr,
|
||||||
|
_vbeInfo.oemProductRevPtr,
|
||||||
|
vbeGetPmodeInterface() ? "Found" : "Missing");
|
||||||
|
} else {
|
||||||
|
printf("VESA BIOS Extension 2.0 or better required!\n\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (counter=0; ; counter++) {
|
||||||
|
if (_vbeInfo.videoModePtr[counter] == 0xFFFF) break;
|
||||||
|
vbeGetModeInfo(_vbeInfo.videoModePtr[counter]);
|
||||||
|
if (vbeIsDesiredMode()) {
|
||||||
|
printf("Mode %Xh - %4d x %4d x %2d - RGB %d:%d:%d - %s\n",
|
||||||
|
_vbeInfo.videoModePtr[counter],
|
||||||
|
_vbeModeInfo.xResolution,
|
||||||
|
_vbeModeInfo.yResolution,
|
||||||
|
_vbeModeInfo.bitsPerPixel,
|
||||||
|
_vbeModeInfo.redMaskSize,
|
||||||
|
_vbeModeInfo.greenMaskSize,
|
||||||
|
_vbeModeInfo.blueMaskSize,
|
||||||
|
(_vbeModeInfo.memoryModel / 2) - 2 ? "DCOLOR" : "PACKED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int16_t vbeShutdown(void) {
|
||||||
|
__dpmi_regs r;
|
||||||
|
__dpmi_meminfo m;
|
||||||
|
|
||||||
|
if (_vbeSurface.vbeInitBoolean == 0) {
|
||||||
|
r.x.ax = 0x03; // make sure we're in 3h
|
||||||
|
__dpmi_int(0x10, &r); // for buggy vesa implementations
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_yTable) free(_yTable);
|
||||||
|
|
||||||
|
// free mapping etc.
|
||||||
|
m.size = (_vbeInfo.totalMemory * 64 * 1024);
|
||||||
|
m.address = _vbeSurface.lfbLinearAddress;
|
||||||
|
__dpmi_unlock_linear_region(&m);
|
||||||
|
__dpmi_free_physical_address_mapping(&m);
|
||||||
|
__dpmi_free_ldt_descriptor(_vbeSurface.lfbSelector);
|
||||||
|
|
||||||
|
// get rid of PMI interface
|
||||||
|
if (_pmodeInterfacePtr) free(_pmodeInterfacePtr);
|
||||||
|
if (_vbeSurface.ioSegment) {
|
||||||
|
m.address = _vbeSurface.ioLinear;
|
||||||
|
__dpmi_free_physical_address_mapping(&m);
|
||||||
|
__dpmi_free_ldt_descriptor(_vbeSurface.ioSegment);
|
||||||
|
}
|
||||||
|
|
||||||
|
vbeSurfaceDestroy(&_offScreenSurface);
|
||||||
|
|
||||||
|
// return do DOS
|
||||||
|
r.x.ax = 0x03;
|
||||||
|
__dpmi_int(0x10, &r);
|
||||||
|
|
||||||
|
// deinit VBE surface
|
||||||
|
_vbeSurface.vbeInitBoolean = 0;
|
||||||
|
_vbeSurface.vbeBoolean = 0;
|
||||||
|
|
||||||
|
// dealloc mode list
|
||||||
|
free(_vbeInfo.videoModePtr);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
|
||||||
|
uint16_t vbeModeNumber;
|
||||||
|
|
||||||
|
if (vbeGetInfo() == NULL) {
|
||||||
|
printf("No VESA BIOS Extensions found.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_vbeInfo.vbeVersion < 0x0200) {
|
||||||
|
printf("VBE Version 2.0 or better required.\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
vbeGetPmodeInterface();
|
||||||
|
|
||||||
|
if ((vbeModeNumber = vbeSelectModeNumber(xRes, yRes, bpp)) == 0) {
|
||||||
|
printf("No appropriate video mode available.\n");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vbeSetMode(vbeModeNumber) == NULL) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeSurfaceBlit(SurfaceT *source, uint16_t x, uint16_t y) {
|
||||||
|
uint16_t y1;
|
||||||
|
size_t offsetTarget;
|
||||||
|
size_t offsetSource;
|
||||||
|
|
||||||
|
if (x == 0 && y == 0 && _activeSurface->width == source->width && _activeSurface->height == source->height) {
|
||||||
|
// Direct blit of entire surface.
|
||||||
|
memcpy(_activeSurface->buffer.bits8, source->buffer.bits8, source->bytes);
|
||||||
|
} else {
|
||||||
|
// Blit into larger surface.
|
||||||
|
offsetTarget = y * _activeSurface->scanline + x * _vbeSurface.bytesPerPixel;
|
||||||
|
offsetSource = 0;
|
||||||
|
for (y1=y; y1<y+source->height; y1++) {
|
||||||
|
memcpy(&_activeSurface->buffer.bits8[offsetTarget], &source->buffer.bits8[offsetSource], source->scanline);
|
||||||
|
offsetTarget += _activeSurface->scanline;
|
||||||
|
offsetSource += source->scanline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeSurfaceClear(PixelT color) {
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
|
||||||
|
for (y=0; y<_activeSurface->height; y++) {
|
||||||
|
for (x=0; x<_activeSurface->width; x++) {
|
||||||
|
vbePutPixel(x, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SurfaceT *vbeSurfaceCreate(uint16_t width, uint16_t height) {
|
||||||
|
SurfaceT *surface = (SurfaceT *)malloc(sizeof(SurfaceT));
|
||||||
|
|
||||||
|
if (!surface) return NULL;
|
||||||
|
|
||||||
|
surface->width = width;
|
||||||
|
surface->height = height;
|
||||||
|
surface->scanline = width * _vbeSurface.bytesPerPixel;
|
||||||
|
surface->bytes = surface->scanline * height;
|
||||||
|
|
||||||
|
surface->buffer.bits8 = malloc(surface->bytes);
|
||||||
|
if (!surface->buffer.bits8) {
|
||||||
|
free(surface);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(surface->buffer.bits8, 0, surface->bytes);
|
||||||
|
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeSurfaceDestroy(SurfaceT **surface) {
|
||||||
|
SurfaceT *s = *surface;
|
||||||
|
|
||||||
|
free(s->buffer.bits8);
|
||||||
|
free(s);
|
||||||
|
s = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeSurfaceSet(SurfaceT *surface) {
|
||||||
|
if (surface) {
|
||||||
|
_activeSurface = surface;
|
||||||
|
} else {
|
||||||
|
_activeSurface = _offScreenSurface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeWaitVBlank(void) {
|
||||||
|
while(inportb(0x3DA) & 8);
|
||||||
|
while(!(inportb(0x3DA) & 8));
|
||||||
|
}
|
22
client/src/gui/array.c
Normal file
22
client/src/gui/array.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 STB_DS_IMPLEMENTATION
|
||||||
|
#include "stb_ds.h"
|
28
client/src/gui/array.h
Normal file
28
client/src/gui/array.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 ARRAY_H
|
||||||
|
#define ARRAY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "stb_ds.h"
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ARRAY_H
|
81
client/src/gui/desktop.c
Normal file
81
client/src/gui/desktop.c
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 "desktop.h"
|
||||||
|
|
||||||
|
|
||||||
|
void desktopDel(WidgetT **widget) {
|
||||||
|
DesktopT *d = (DesktopT *)*widget;
|
||||||
|
|
||||||
|
vbeSurfaceDestroy(&d->base.surface);
|
||||||
|
free(d);
|
||||||
|
d = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WidgetT *desktopInit(WidgetT *desktop) {
|
||||||
|
DesktopT *d = (DesktopT *)desktop;
|
||||||
|
|
||||||
|
d->base.magic = MAGIC_DESKTOP;
|
||||||
|
d->base.w = vbeDisplayWidthGet();
|
||||||
|
d->base.h = vbeDisplayHeightGet();
|
||||||
|
d->base.delMethod = desktopDel;
|
||||||
|
d->base.paintMethod = desktopPaint;
|
||||||
|
d->dragOffsetX = 0;
|
||||||
|
d->dragOffsetY = 0;
|
||||||
|
d->dragWidget = NULL;
|
||||||
|
|
||||||
|
d->base.surface = vbeSurfaceCreate(d->base.w, d->base.h);
|
||||||
|
if (!d->base.surface) {
|
||||||
|
free(d);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DesktopT *desktopNew(void) {
|
||||||
|
DesktopT *desktop = (DesktopT *)malloc(sizeof(DesktopT));
|
||||||
|
WidgetT *widget = NULL;
|
||||||
|
|
||||||
|
if (!desktop) return NULL;
|
||||||
|
|
||||||
|
widget = widgetInit((WidgetT *)desktop);
|
||||||
|
if (!widget) {
|
||||||
|
free(desktop);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
desktop = (DesktopT *)desktopInit((WidgetT *)desktop);
|
||||||
|
|
||||||
|
return desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void desktopPaint(WidgetT *desktop) {
|
||||||
|
DesktopT *d = (DesktopT *)desktop;
|
||||||
|
|
||||||
|
if (d->base.dirty) {
|
||||||
|
vbeSurfaceSet(d->base.surface);
|
||||||
|
vbeSurfaceClear(_guiColor[COLOR_DESKTOP]);
|
||||||
|
d->base.dirty = 0;
|
||||||
|
}
|
||||||
|
}
|
43
client/src/gui/desktop.h
Normal file
43
client/src/gui/desktop.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 DESKTOP_H
|
||||||
|
#define DESKTOP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "gui.h"
|
||||||
|
#include "widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct DesktopS {
|
||||||
|
WidgetT base; // Must be first in every widget
|
||||||
|
uint16_t dragOffsetX;
|
||||||
|
uint16_t dragOffsetY;
|
||||||
|
WidgetT *dragWidget;
|
||||||
|
} DesktopT;
|
||||||
|
|
||||||
|
|
||||||
|
void desktopDel(WidgetT **widget);
|
||||||
|
WidgetT *desktopInit(WidgetT *desktop);
|
||||||
|
DesktopT *desktopNew(void);
|
||||||
|
void desktopPaint(WidgetT *desktop);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DESKTOP_H
|
104
client/src/gui/font.c
Normal file
104
client/src/gui/font.c
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 "font.h"
|
||||||
|
|
||||||
|
|
||||||
|
FontT *fontLoad(char *filename) {
|
||||||
|
FILE *in = NULL;
|
||||||
|
uint16_t size = 0;
|
||||||
|
FontT *font = NULL;
|
||||||
|
|
||||||
|
in = fopen(filename, "rb");
|
||||||
|
if (!in) return NULL;
|
||||||
|
|
||||||
|
font = (FontT *)malloc(sizeof(FontT));
|
||||||
|
if (!font) {
|
||||||
|
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);
|
||||||
|
fclose(in);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(font->bits, size, 1, in);
|
||||||
|
|
||||||
|
fclose(in);
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void fontRender(FontT *font, uint8_t character, PixelT foreground, PixelT background, uint16_t x, uint16_t y) {
|
||||||
|
uint8_t cx;
|
||||||
|
uint8_t cy;
|
||||||
|
uint16_t offset;
|
||||||
|
uint8_t yl;
|
||||||
|
uint16_t yp;
|
||||||
|
uint8_t data;
|
||||||
|
|
||||||
|
//***TODO*** This only handles 8x8 fonts.
|
||||||
|
|
||||||
|
// Find character position in font grid.
|
||||||
|
cx = character % font->span;
|
||||||
|
cy = character / font->span;
|
||||||
|
|
||||||
|
// Find offset byte based on font bits.
|
||||||
|
offset = cy * font->span * font->height + cx;
|
||||||
|
|
||||||
|
// Draw out 8 lines.
|
||||||
|
yp = y;
|
||||||
|
for (yl=0; yl<8; yl++) {
|
||||||
|
// We do 8 pixels unrolled hoping it's fast.
|
||||||
|
data = font->bits[offset];
|
||||||
|
offset += font->span;
|
||||||
|
vbePutPixel(x, yp, data & 0x80 ? foreground : background);
|
||||||
|
vbePutPixel(x + 1, yp, data & 0x40 ? foreground : background);
|
||||||
|
vbePutPixel(x + 2, yp, data & 0x20 ? foreground : background);
|
||||||
|
vbePutPixel(x + 3, yp, data & 0x10 ? foreground : background);
|
||||||
|
vbePutPixel(x + 4, yp, data & 0x08 ? foreground : background);
|
||||||
|
vbePutPixel(x + 5, yp, data & 0x04 ? foreground : background);
|
||||||
|
vbePutPixel(x + 6, yp, data & 0x02 ? foreground : background);
|
||||||
|
vbePutPixel(x + 7, yp, data & 0x01 ? foreground : background);
|
||||||
|
yp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void fontUnload(FontT **font) {
|
||||||
|
FontT *f = *font;
|
||||||
|
|
||||||
|
free(f->bits);
|
||||||
|
free(f);
|
||||||
|
f = NULL;
|
||||||
|
}
|
45
client/src/gui/font.h
Normal file
45
client/src/gui/font.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 FONT_H
|
||||||
|
#define FONT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
#include "vesa.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct FontS {
|
||||||
|
uint8_t width; // Width of each character in pixels.
|
||||||
|
uint8_t height; // Height of each character in pixels.
|
||||||
|
uint8_t span; // Number of characters per line in font data.
|
||||||
|
uint8_t count; // Number of characters in font, minus 1.
|
||||||
|
uint16_t widthPixels; // Width of line of font data in pixels/bits.
|
||||||
|
uint16_t heightPixels; // Number of lines of font data in pixels/bits.
|
||||||
|
uint8_t *bits; // Actual font bits.
|
||||||
|
} FontT;
|
||||||
|
|
||||||
|
|
||||||
|
FontT *fontLoad(char *filename);
|
||||||
|
void fontRender(FontT *font, uint8_t character, PixelT foreground, PixelT background, uint16_t x, uint16_t y);
|
||||||
|
void fontUnload(FontT **font);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FONT_H
|
312
client/src/gui/gui.c
Normal file
312
client/src/gui/gui.c
Normal file
|
@ -0,0 +1,312 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 "gui.h"
|
||||||
|
#include "widget.h"
|
||||||
|
#include "desktop.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
|
||||||
|
int16_t _guiMetric[METRIC_COUNT];
|
||||||
|
PixelT _guiColor[COLOR_COUNT];
|
||||||
|
|
||||||
|
|
||||||
|
static DesktopT *_guiDesktop = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void guiAttach(WidgetT *parent, WidgetT *child) {
|
||||||
|
// Add us to the child list.
|
||||||
|
child->parent = parent;
|
||||||
|
arrput(parent->children, child);
|
||||||
|
// New windows should be active.
|
||||||
|
if (child->magic == MAGIC_WINDOW) {
|
||||||
|
windowSetActive((WindowT *)child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiComposite() {
|
||||||
|
WidgetT *widget = (WidgetT *)_guiDesktop;
|
||||||
|
size_t len = arrlenu(widget->children);
|
||||||
|
size_t x;
|
||||||
|
|
||||||
|
// Repaint anyone who needs it.
|
||||||
|
guiPaint(widget);
|
||||||
|
|
||||||
|
vbeSurfaceSet(NULL);
|
||||||
|
|
||||||
|
// Render us?
|
||||||
|
if (widget->surface) {
|
||||||
|
vbeSurfaceBlit(widget->surface, widget->x, widget->y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now render all surface-containing children to the VBE buffer.
|
||||||
|
if (len > 0) {
|
||||||
|
for (x=0; x<len; x++) {
|
||||||
|
if (widget->children[x]->surface) {
|
||||||
|
vbeSurfaceBlit(widget->children[x]->surface, widget->children[x]->x, widget->children[x]->y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiDelete(WidgetT **widget) {
|
||||||
|
WidgetT *w = *widget;
|
||||||
|
size_t len = arrlenu(w->children);
|
||||||
|
size_t x = 0;
|
||||||
|
|
||||||
|
// Delete children.
|
||||||
|
if (len > 0) {
|
||||||
|
for (x=0; x<len; x++) {
|
||||||
|
guiDelete(&w->children[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arrfree(w->children);
|
||||||
|
|
||||||
|
// Delete us.
|
||||||
|
w->delMethod(&w);
|
||||||
|
|
||||||
|
// Make sure we're not drawing into oblivion.
|
||||||
|
vbeSurfaceSet(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiDrawHighlightFrame(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, PixelT upperLeft, PixelT lowerRight) {
|
||||||
|
guiDrawLine(x1, y1, x2, y1, upperLeft);
|
||||||
|
guiDrawLine(x1, y1, x1, y2, upperLeft);
|
||||||
|
guiDrawLine(x1, y2, x2, y2, lowerRight);
|
||||||
|
guiDrawLine(x2, y1, x2, y2, lowerRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiDrawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, PixelT color) {
|
||||||
|
int16_t x;
|
||||||
|
int16_t y;
|
||||||
|
int16_t dx;
|
||||||
|
int16_t dy;
|
||||||
|
int16_t incX;
|
||||||
|
int16_t incY;
|
||||||
|
int16_t balance;
|
||||||
|
|
||||||
|
if (x2 >= x1) {
|
||||||
|
dx = x2 - x1;
|
||||||
|
incX = 1;
|
||||||
|
} else {
|
||||||
|
dx = x1 - x2;
|
||||||
|
incX = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y2 >= y1) {
|
||||||
|
dy = y2 - y1;
|
||||||
|
incY = 1;
|
||||||
|
} else {
|
||||||
|
dy = y1 - y2;
|
||||||
|
incY = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = x1;
|
||||||
|
y = y1;
|
||||||
|
|
||||||
|
if (dx >= dy) {
|
||||||
|
dy <<= 1;
|
||||||
|
balance = dy - dx;
|
||||||
|
dx <<= 1;
|
||||||
|
while (x != x2) {
|
||||||
|
vbePutPixel(x, y, color);
|
||||||
|
if (balance >= 0) {
|
||||||
|
y += incY;
|
||||||
|
balance -= dx;
|
||||||
|
}
|
||||||
|
balance += dy;
|
||||||
|
x += incX;
|
||||||
|
}
|
||||||
|
vbePutPixel(x, y, color);
|
||||||
|
} else {
|
||||||
|
dx <<= 1;
|
||||||
|
balance = dx - dy;
|
||||||
|
dy <<= 1;
|
||||||
|
while (y != y2) {
|
||||||
|
vbePutPixel(x, y, color);
|
||||||
|
if (balance >= 0) {
|
||||||
|
x += incX;
|
||||||
|
balance -= dy;
|
||||||
|
}
|
||||||
|
balance += dx;
|
||||||
|
y += incY;
|
||||||
|
}
|
||||||
|
vbePutPixel(x, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiDrawFilledRectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, PixelT pixel) {
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
|
||||||
|
for (y=y1; y<=y2; y++) {
|
||||||
|
for (x=x1; x<=x2; x++) {
|
||||||
|
vbePutPixel(x, y, pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiProcessMouse(MouseT *mouse) {
|
||||||
|
size_t len;
|
||||||
|
int16_t x;
|
||||||
|
WidgetT *child;
|
||||||
|
WindowT *window;
|
||||||
|
WidgetT *parent = (WidgetT *)_guiDesktop;
|
||||||
|
static WidgetT *downOnWidget = NULL;
|
||||||
|
|
||||||
|
// Is the left button down?
|
||||||
|
if (mouse->buttonLeft) {
|
||||||
|
// Was it NOT down before?
|
||||||
|
if (!mouse->buttonLeftWasDown) {
|
||||||
|
// Initial click. Are we already dragging something?
|
||||||
|
if (!_guiDesktop->dragWidget) {
|
||||||
|
// Can we drag this?
|
||||||
|
len = arrlenu(parent->children);
|
||||||
|
for (x=len-1; x>=0; x--) {
|
||||||
|
child = parent->children[x];
|
||||||
|
// Are we clicking this widget?
|
||||||
|
if (mouse->x >= child->x && mouse->y >= child->y && mouse->x < child->x + child->w && mouse->y < child->y + child->h) {
|
||||||
|
// Remember this widget for when the mouse button is released. Buttons must come up on the same widget they went down on.
|
||||||
|
downOnWidget = child;
|
||||||
|
// Is this a Window?
|
||||||
|
if (child->magic == MAGIC_WINDOW) {
|
||||||
|
window = (WindowT *)child;
|
||||||
|
// Is it the active window?
|
||||||
|
if (GUI_GET_FLAG(window, WINDOW_FLAG_ACTIVE)) {
|
||||||
|
// Start dragging.
|
||||||
|
_guiDesktop->dragOffsetX = mouse->x - window->base.x;
|
||||||
|
_guiDesktop->dragOffsetY = mouse->y - window->base.y;
|
||||||
|
_guiDesktop->dragWidget = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // Was it NOT down before?
|
||||||
|
|
||||||
|
// Still holding left button, but not the initial click. Update dragged widget location.
|
||||||
|
if (_guiDesktop->dragWidget) {
|
||||||
|
_guiDesktop->dragWidget->x = mouse->x - _guiDesktop->dragOffsetX;
|
||||||
|
_guiDesktop->dragWidget->y = mouse->y - _guiDesktop->dragOffsetY;
|
||||||
|
// Keep it on the screen.
|
||||||
|
if (_guiDesktop->dragWidget->x < 0) _guiDesktop->dragWidget->x = 0;
|
||||||
|
if (_guiDesktop->dragWidget->x + _guiDesktop->dragWidget->w > vbeDisplayWidthGet()) _guiDesktop->dragWidget->x = vbeDisplayWidthGet() - _guiDesktop->dragWidget->w;
|
||||||
|
if (_guiDesktop->dragWidget->y < 0) _guiDesktop->dragWidget->y = 0;
|
||||||
|
if (_guiDesktop->dragWidget->y + _guiDesktop->dragWidget->h > vbeDisplayHeightGet()) _guiDesktop->dragWidget->y = vbeDisplayHeightGet() - _guiDesktop->dragWidget->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Was it NOT down before?
|
||||||
|
|
||||||
|
} else { // Left button down?
|
||||||
|
|
||||||
|
// No longer holding left button. Stop dragging.
|
||||||
|
_guiDesktop->dragWidget = NULL;
|
||||||
|
|
||||||
|
// Was the left button down last frame?
|
||||||
|
if (mouse->buttonLeftWasDown) {
|
||||||
|
//***TODO*** Right now, this only processes top-level windows attached directly to the desktop.
|
||||||
|
len = arrlenu(parent->children);
|
||||||
|
for (x=len-1; x>=0; x--) {
|
||||||
|
child = parent->children[x];
|
||||||
|
// Are we clicking this widget?
|
||||||
|
if (mouse->x >= child->x && mouse->y >= child->y && mouse->x < child->x + child->w && mouse->y < child->y + child->h) {
|
||||||
|
// Is this the widget we originally clicked? Buttons must come up on the same widget they went down on.
|
||||||
|
if (child == downOnWidget) {
|
||||||
|
// Is this a Window?
|
||||||
|
if (child->magic == MAGIC_WINDOW) {
|
||||||
|
window = (WindowT *)child;
|
||||||
|
// Bring window to top.
|
||||||
|
arrdel(parent->children, x);
|
||||||
|
arrput(parent->children, child);
|
||||||
|
windowSetActive(window);
|
||||||
|
} else {
|
||||||
|
//***TODO*** Dispatch to proper control if the containing window is active.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // Left button was down last frame.
|
||||||
|
|
||||||
|
} // Left button down.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiPaint(WidgetT *widget) {
|
||||||
|
size_t len = arrlenu(widget->children);
|
||||||
|
size_t x;
|
||||||
|
|
||||||
|
// Paint us, if needed.
|
||||||
|
if (widget->dirty && widget->paintMethod) {
|
||||||
|
widget->paintMethod(widget);
|
||||||
|
widget->dirty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paint all children, if needed.
|
||||||
|
if (len > 0) {
|
||||||
|
for (x=0; x<len; x++) {
|
||||||
|
if (widget->children[x]->dirty && widget->children[x]->paintMethod) {
|
||||||
|
widget->children[x]->paintMethod(widget->children[x]);
|
||||||
|
widget->children[x]->dirty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WidgetT *guiRootGet(void) {
|
||||||
|
return (WidgetT *)_guiDesktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DesktopT *guiStartup(void) {
|
||||||
|
|
||||||
|
_guiMetric[METRIC_WINDOW_BORDER_WIDTH] = 4; // Does not include highlight or shadow lines.
|
||||||
|
_guiMetric[METRIC_WINDOW_TITLE_HEIGHT] = 17; // Does not include highlight or shadow lines.
|
||||||
|
|
||||||
|
_guiColor[COLOR_DESKTOP] = vbeMakePixel( 51, 153, 255);
|
||||||
|
_guiColor[COLOR_WINDOW_BACKGROUND] = vbeMakePixel(168, 168, 168);
|
||||||
|
_guiColor[COLOR_WINDOW_HIGHLIGHT] = vbeMakePixel(248, 252, 248);
|
||||||
|
_guiColor[COLOR_WINDOW_SHADOW] = vbeMakePixel( 80, 84, 80);
|
||||||
|
_guiColor[COLOR_WINDOW_TITLE_ACTIVE] = vbeMakePixel( 80, 84, 80);
|
||||||
|
_guiColor[COLOR_WINDOW_TITLE_INACTIVE] = vbeMakePixel(168, 168, 168);
|
||||||
|
_guiColor[COLOR_WINDOW_TITLE_TEXT_ACTIVE] = vbeMakePixel(248, 252, 248);
|
||||||
|
_guiColor[COLOR_WINDOW_TITLE_TEXT_INACTIVE] = vbeMakePixel( 0, 0, 0);
|
||||||
|
|
||||||
|
// Create desktop and return it. Remember it for later.
|
||||||
|
_guiDesktop = desktopNew();
|
||||||
|
|
||||||
|
return _guiDesktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiShutdown(void) {
|
||||||
|
// Delete all widgets in GUI tree.
|
||||||
|
guiDelete((WidgetT **)&_guiDesktop);
|
||||||
|
}
|
90
client/src/gui/gui.h
Normal file
90
client/src/gui/gui.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 GUI_H
|
||||||
|
#define GUI_H
|
||||||
|
|
||||||
|
|
||||||
|
// Inspired by https://github.com/JMarlin/wsbe
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
#include "vesa.h"
|
||||||
|
#include "array.h"
|
||||||
|
#include "mouse.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define GUI_GET_FLAG(w,f) ((w)->flags & (1 << (f)))
|
||||||
|
#define GUI_SET_FLAG(w,f) ((w)->flags |= (1 << (f)))
|
||||||
|
#define GUI_CLEAR_FLAG(w,f) ((w)->flags &= (~(1 << (f))))
|
||||||
|
|
||||||
|
|
||||||
|
// Widget Magics
|
||||||
|
enum MagicE {
|
||||||
|
MAGIC_UNKNOWN = 0,
|
||||||
|
MAGIC_DESKTOP,
|
||||||
|
MAGIC_WINDOW,
|
||||||
|
MAGIC_BUTTON,
|
||||||
|
MAGIC_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
// Widget Metrics
|
||||||
|
enum MetricE {
|
||||||
|
METRIC_WINDOW_BORDER_WIDTH = 0,
|
||||||
|
METRIC_WINDOW_TITLE_HEIGHT,
|
||||||
|
METRIC_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
// Widget Colors
|
||||||
|
enum ColorE {
|
||||||
|
COLOR_DESKTOP = 0,
|
||||||
|
COLOR_WINDOW_BACKGROUND,
|
||||||
|
COLOR_WINDOW_HIGHLIGHT,
|
||||||
|
COLOR_WINDOW_SHADOW,
|
||||||
|
COLOR_WINDOW_TITLE_ACTIVE,
|
||||||
|
COLOR_WINDOW_TITLE_INACTIVE,
|
||||||
|
COLOR_WINDOW_TITLE_TEXT_ACTIVE,
|
||||||
|
COLOR_WINDOW_TITLE_TEXT_INACTIVE,
|
||||||
|
COLOR_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct WidgetS WidgetT;
|
||||||
|
typedef struct DesktopS DesktopT;
|
||||||
|
|
||||||
|
|
||||||
|
extern int16_t _guiMetric[METRIC_COUNT];
|
||||||
|
extern PixelT _guiColor[COLOR_COUNT];
|
||||||
|
|
||||||
|
|
||||||
|
void guiAttach(WidgetT *parent, WidgetT *child);
|
||||||
|
void guiComposite(void);
|
||||||
|
void guiDelete(WidgetT **widget);
|
||||||
|
void guiDrawHighlightFrame(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, PixelT upperLeft, PixelT lowerRight);
|
||||||
|
void guiDrawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, PixelT pixel);
|
||||||
|
void guiDrawFilledRectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, PixelT pixel);
|
||||||
|
void guiPaint(WidgetT *widget);
|
||||||
|
void guiProcessMouse(MouseT *mouse);
|
||||||
|
WidgetT *guiRootGet(void);
|
||||||
|
DesktopT *guiStartup(void);
|
||||||
|
void guiShutdown(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GUI_H
|
158
client/src/gui/image.c
Normal file
158
client/src/gui/image.c
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 STB_IMAGE_IMPLEMENTATION
|
||||||
|
#define STBI_ONLY_PNG
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
|
||||||
|
ImageT *imageAllocate(uint16_t w, uint16_t h) {
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
ImageT *image;
|
||||||
|
|
||||||
|
// Create new native image
|
||||||
|
image = (ImageT *)malloc(sizeof(ImageT));
|
||||||
|
if (!image) return NULL;
|
||||||
|
|
||||||
|
image->width = w;
|
||||||
|
image->height = h;
|
||||||
|
|
||||||
|
// Create space for converted pixel data - columns
|
||||||
|
image->pixels = (PixelT **)malloc(sizeof(PixelT *) * image->width);
|
||||||
|
if (!image->pixels) {
|
||||||
|
free(image);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Create space for converted pixel data - rows
|
||||||
|
for (x=0; x<image->width; x++) {
|
||||||
|
image->pixels[x] = (PixelT *)malloc(sizeof(PixelT) * image->height);
|
||||||
|
if (!image->pixels[x]) {
|
||||||
|
for (y=0; y<x; y++) {
|
||||||
|
free(image->pixels[y]);
|
||||||
|
}
|
||||||
|
free(image);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ImageT *imageCreate(uint16_t w, uint16_t h, PixelT color) {
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
ImageT *image = imageAllocate(w, h);
|
||||||
|
|
||||||
|
if (!image) return NULL;
|
||||||
|
|
||||||
|
for (y=0; y<image->height; y++) {
|
||||||
|
for (x=0; x<image->width; x++) {
|
||||||
|
image->pixels[x][y] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ImageT *imageLoad(char *filename) {
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
uint16_t n;
|
||||||
|
uint32_t b;
|
||||||
|
unsigned char *raw;
|
||||||
|
ImageT *image;
|
||||||
|
|
||||||
|
// Load image from disk
|
||||||
|
raw = stbi_load(filename, (int *)&x, (int *)&y, (int *)&n, 3);
|
||||||
|
if (!raw) return NULL;
|
||||||
|
|
||||||
|
// Create native image.
|
||||||
|
image = imageAllocate(x, y);
|
||||||
|
if (!image) {
|
||||||
|
stbi_image_free(raw);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert from RGB to our generic 32 bit pixel format
|
||||||
|
b = 0;
|
||||||
|
for (y=0; y<image->height; y++) {
|
||||||
|
for (x=0; x<image->width; x++) {
|
||||||
|
image->pixels[x][y] = vbeMakePixel(raw[b], raw[b + 1], raw[b + 2]);
|
||||||
|
b += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stbi_image_free(raw);
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PixelT imagePixelGet(ImageT *image, uint16_t x, uint16_t y) {
|
||||||
|
return image->pixels[x][y];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void imageRender(ImageT *image, uint16_t x, uint16_t y) {
|
||||||
|
uint16_t x1;
|
||||||
|
uint16_t y1;
|
||||||
|
|
||||||
|
for (y1=0; y1<image->height; y1++) {
|
||||||
|
for (x1=0; x1<image->width; x1++) {
|
||||||
|
vbePutPixel(x + x1, y + y1, image->pixels[x1][y1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void imageRenderWithAlpha(ImageT *image, uint16_t x, uint16_t y, PixelT alpha) {
|
||||||
|
uint16_t x1;
|
||||||
|
uint16_t y1;
|
||||||
|
uint16_t x2 = image->width;
|
||||||
|
uint16_t y2 = image->height;
|
||||||
|
|
||||||
|
// Clip on right and bottom
|
||||||
|
if (x + x2 > vbeDisplayWidthGet()) x2 -= x + x2 - vbeDisplayWidthGet();
|
||||||
|
if (y + y2 > vbeDisplayHeightGet()) y2 -= y + y2 - vbeDisplayHeightGet();
|
||||||
|
|
||||||
|
for (y1=0; y1<y2; y1++) {
|
||||||
|
for (x1=0; x1<x2; x1++) {
|
||||||
|
if (alpha != image->pixels[x1][y1]) {
|
||||||
|
vbePutPixel(x + x1, y + y1, image->pixels[x1][y1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void imageUnload(ImageT **image) {
|
||||||
|
uint16_t x;
|
||||||
|
ImageT *i = *image;
|
||||||
|
|
||||||
|
for (x=0; x<i->width; x++) {
|
||||||
|
free(i->pixels[x]);
|
||||||
|
}
|
||||||
|
free(i->pixels);
|
||||||
|
free(i);
|
||||||
|
i = NULL;
|
||||||
|
}
|
47
client/src/gui/image.h
Normal file
47
client/src/gui/image.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 IMAGE_H
|
||||||
|
#define IMAGE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
#include "vesa.h"
|
||||||
|
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ImageS {
|
||||||
|
uint16_t width;
|
||||||
|
uint16_t height;
|
||||||
|
PixelT **pixels;
|
||||||
|
} ImageT;
|
||||||
|
|
||||||
|
|
||||||
|
ImageT *imageAllocate(uint16_t w, uint16_t h);
|
||||||
|
ImageT *imageCreate(uint16_t w, uint16_t h, PixelT color);
|
||||||
|
ImageT *imageLoad(char *filename);
|
||||||
|
PixelT imagePixelGet(ImageT *image, uint16_t x, uint16_t y);
|
||||||
|
void imageRender(ImageT *image, uint16_t x, uint16_t y);
|
||||||
|
void imageRenderWithAlpha(ImageT *image, uint16_t x, uint16_t y, PixelT alpha);
|
||||||
|
void imageUnload(ImageT **image);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // IMAGE_H
|
50
client/src/gui/log.c
Normal file
50
client/src/gui/log.c
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 "log.h"
|
||||||
|
|
||||||
|
|
||||||
|
FILE *_log = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t logOpen(char *filename, uint8_t append) {
|
||||||
|
_log = fopen(filename, append ? "a" : "w");
|
||||||
|
if (_log) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void logClose(void) {
|
||||||
|
if (_log) {
|
||||||
|
fclose(_log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void logWrite(char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (_log) {
|
||||||
|
va_start(args, format);
|
||||||
|
vfprintf(_log, format, args);
|
||||||
|
va_end(args);
|
||||||
|
fflush(_log);
|
||||||
|
}
|
||||||
|
}
|
33
client/src/gui/log.h
Normal file
33
client/src/gui/log.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 LOG_H
|
||||||
|
#define LOG_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t logOpen(char *filename, uint8_t append);
|
||||||
|
void logClose(void);
|
||||||
|
void logWrite(char *format, ...);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // LOG_H
|
22
client/src/gui/memory.c
Normal file
22
client/src/gui/memory.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 STB_LEAKCHECK_IMPLEMENTATION
|
||||||
|
#include "stb_leakcheck.h"
|
31
client/src/gui/memory.h
Normal file
31
client/src/gui/memory.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 MEMORY_H
|
||||||
|
#define MEMORY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "stb_leakcheck.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define memoryLeaksShow stb_leakcheck_dumpmem
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MEMORY_H
|
49
client/src/gui/mouse.h
Normal file
49
client/src/gui/mouse.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 MOUSE_H
|
||||||
|
#define MOUSE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct MouseS {
|
||||||
|
uint8_t active;
|
||||||
|
uint8_t buttonCount;
|
||||||
|
uint8_t buttonLeft;
|
||||||
|
uint8_t buttonRight;
|
||||||
|
uint8_t buttonMiddle;
|
||||||
|
uint8_t buttonLeftWasDown;
|
||||||
|
uint8_t buttonRightWasDown;
|
||||||
|
uint8_t buttonMiddleWasDown;
|
||||||
|
uint16_t w;
|
||||||
|
uint16_t h;
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
} MouseT;
|
||||||
|
|
||||||
|
|
||||||
|
void mouseShutdown(void);
|
||||||
|
int16_t mouseStartup(void);
|
||||||
|
MouseT *mouseRead(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MOUSE_H
|
58
client/src/gui/os.h
Normal file
58
client/src/gui/os.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 OS_H
|
||||||
|
#define OS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <dos.h>
|
||||||
|
#include <dpmi.h>
|
||||||
|
#include <go32.h>
|
||||||
|
#include <conio.h>
|
||||||
|
#include <sys/nearptr.h>
|
||||||
|
#include <sys/farptr.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Has to be after system headers in this file.
|
||||||
|
//#include "memory.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))
|
||||||
|
|
||||||
|
|
||||||
|
#endif // OS_H
|
62
client/src/gui/vesa.h
Normal file
62
client/src/gui/vesa.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 VESA20_H
|
||||||
|
#define VESA20_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef uint32_t PixelT;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct SurfaceS {
|
||||||
|
uint16_t width;
|
||||||
|
uint16_t height;
|
||||||
|
size_t scanline;
|
||||||
|
size_t bytes;
|
||||||
|
union {
|
||||||
|
uint8_t *bits8;
|
||||||
|
uint16_t *bits16;
|
||||||
|
uint32_t *bits32;
|
||||||
|
} buffer;
|
||||||
|
} SurfaceT;
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp);
|
||||||
|
uint8_t vbeDisplayDepthGet(void);
|
||||||
|
uint16_t vbeDisplayHeightGet(void);
|
||||||
|
uint16_t vbeDisplayWidthGet(void);
|
||||||
|
PixelT vbeMakePixel(uint8_t red, uint8_t green, uint8_t blue);
|
||||||
|
void vbePresent(void);
|
||||||
|
int16_t vbeShowInfo(void);
|
||||||
|
int16_t vbeShutdown(void);
|
||||||
|
void vbeSurfaceBlit(SurfaceT *source, uint16_t x, uint16_t y);
|
||||||
|
void vbeSurfaceClear(PixelT color);
|
||||||
|
SurfaceT *vbeSurfaceCreate(uint16_t width, uint16_t height);
|
||||||
|
void vbeSurfaceDestroy(SurfaceT **surface);
|
||||||
|
void vbeSurfaceSet(SurfaceT *surface);
|
||||||
|
void vbeWaitVBlank(void);
|
||||||
|
|
||||||
|
extern void (*vbePutPixel)(uint16_t x, uint16_t y, PixelT pixel);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VESA20_H
|
50
client/src/gui/widget.c
Normal file
50
client/src/gui/widget.c
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 "widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
WidgetT *widgetInit(WidgetT *widget) {
|
||||||
|
widget->magic = MAGIC_UNKNOWN;
|
||||||
|
widget->x = 0;
|
||||||
|
widget->y = 0;
|
||||||
|
widget->w = 0;
|
||||||
|
widget->h = 0;
|
||||||
|
widget->dirty = 1; // Force a paint right away
|
||||||
|
widget->surface = NULL;
|
||||||
|
widget->children = NULL;
|
||||||
|
widget->parent = NULL;
|
||||||
|
widget->delMethod = NULL;
|
||||||
|
widget->paintMethod = NULL;
|
||||||
|
widget->mouseDownMethod = NULL;
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WidgetT *widgetNew(void) {
|
||||||
|
WidgetT *widget = (WidgetT *)malloc(sizeof(WidgetT));
|
||||||
|
|
||||||
|
if (!widget) return NULL;
|
||||||
|
|
||||||
|
widget = widgetInit(widget);
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
56
client/src/gui/widget.h
Normal file
56
client/src/gui/widget.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 WIDGET_H
|
||||||
|
#define WIDGET_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "gui.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct WidgetS;
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (*widgetDelMethod)(struct WidgetS **widget);
|
||||||
|
typedef void (*widgetPaintMethod)(struct WidgetS *widget);
|
||||||
|
typedef void (*widgetMouseDownMethod)(struct WidgetS *widget, uint16_t x, uint16_t y);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct WidgetS {
|
||||||
|
uint8_t magic; // Widget identifier constant
|
||||||
|
uint8_t dirty; // Does this widget need redrawn
|
||||||
|
SurfaceT *surface; // Pointer to compositable surface or NULL
|
||||||
|
int16_t x; // Position of widget on parent
|
||||||
|
int16_t y; // Position of widget on parent
|
||||||
|
uint16_t w; // Width of widget
|
||||||
|
uint16_t h; // Height of widget
|
||||||
|
struct WidgetS **children; // List of children
|
||||||
|
struct WidgetS *parent; // Parent of this widget
|
||||||
|
widgetDelMethod delMethod; // Delete method
|
||||||
|
widgetPaintMethod paintMethod; // Paint method
|
||||||
|
widgetMouseDownMethod mouseDownMethod; // Mouse button down handler
|
||||||
|
} WidgetT;
|
||||||
|
|
||||||
|
|
||||||
|
WidgetT *widgetInit(WidgetT *widget);
|
||||||
|
WidgetT *widgetNew(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // WIDGET_H
|
137
client/src/gui/window.c
Normal file
137
client/src/gui/window.c
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 "window.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void windowDeactivateAll(WidgetT *widget);
|
||||||
|
|
||||||
|
|
||||||
|
static void windowDeactivateAll(WidgetT *widget) {
|
||||||
|
size_t len = arrlenu(widget->children);
|
||||||
|
size_t x;
|
||||||
|
|
||||||
|
// Is this a Window?
|
||||||
|
if (widget->magic == MAGIC_WINDOW) {
|
||||||
|
// Deactivate it.
|
||||||
|
GUI_CLEAR_FLAG((WindowT *)widget, WINDOW_FLAG_ACTIVE);
|
||||||
|
widget->dirty = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process any children.
|
||||||
|
if (len > 0) {
|
||||||
|
for (x=0; x<len; x++) {
|
||||||
|
windowDeactivateAll(widget->children[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void windowDel(WidgetT **widget) {
|
||||||
|
WindowT *w = (WindowT *)*widget;
|
||||||
|
|
||||||
|
vbeSurfaceDestroy(&w->base.surface);
|
||||||
|
if (w->title) free(w->title);
|
||||||
|
free(w);
|
||||||
|
w = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WidgetT *windowInit(WidgetT *window, uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title) {
|
||||||
|
WindowT *win = (WindowT *)window;
|
||||||
|
|
||||||
|
win->base.magic = MAGIC_WINDOW;
|
||||||
|
win->base.x = x;
|
||||||
|
win->base.y = y;
|
||||||
|
win->base.w = w;
|
||||||
|
win->base.h = h;
|
||||||
|
win->base.delMethod = windowDel;
|
||||||
|
win->base.paintMethod = windowPaint;
|
||||||
|
win->title = NULL;
|
||||||
|
|
||||||
|
windowSetTitle(win, title);
|
||||||
|
|
||||||
|
win->base.surface = vbeSurfaceCreate(win->base.w, win->base.h);
|
||||||
|
if (!win->base.surface) {
|
||||||
|
free(win->title);
|
||||||
|
free(win);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WindowT *windowNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title) {
|
||||||
|
WindowT *window = (WindowT *)malloc(sizeof(WindowT));
|
||||||
|
WidgetT *widget = NULL;
|
||||||
|
|
||||||
|
if (!window) return NULL;
|
||||||
|
|
||||||
|
widget = widgetInit((WidgetT *)window);
|
||||||
|
if (!widget) {
|
||||||
|
free(window);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
window = (WindowT *)windowInit((WidgetT *)window, x, y, w, h, title);
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void windowPaint(WidgetT *window) {
|
||||||
|
WindowT *w = (WindowT *)window;
|
||||||
|
uint16_t x2 = w->base.w - 1;
|
||||||
|
uint16_t y2 = w->base.h - 1;
|
||||||
|
PixelT background = GUI_GET_FLAG(w, WINDOW_FLAG_ACTIVE) ? _guiColor[COLOR_WINDOW_TITLE_ACTIVE] : _guiColor[COLOR_WINDOW_TITLE_INACTIVE];
|
||||||
|
//PixelT text = GUI_GET_FLAG(w, WINDOW_FLAG_ACTIVE) ? _guiColor[COLOR_WINDOW_TITLE_TEXT_ACTIVE] : _guiColor[COLOR_WINDOW_TITLE_TEXT_INACTIVE];
|
||||||
|
|
||||||
|
if (w->base.dirty) {
|
||||||
|
vbeSurfaceSet(w->base.surface);
|
||||||
|
|
||||||
|
// Background.
|
||||||
|
vbeSurfaceClear(_guiColor[COLOR_WINDOW_BACKGROUND]);
|
||||||
|
|
||||||
|
// Outer edge.
|
||||||
|
guiDrawHighlightFrame(0, 0, x2, y2, _guiColor[COLOR_WINDOW_HIGHLIGHT], _guiColor[COLOR_WINDOW_SHADOW]);
|
||||||
|
|
||||||
|
// Inner edge - skip METRIC_WINDOW_BORDER_WIDTH pixels. Be sure shadow and highlight are not included in the width.
|
||||||
|
guiDrawHighlightFrame(_guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 2, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 2, x2 - _guiMetric[METRIC_WINDOW_BORDER_WIDTH] - 2, y2 - _guiMetric[METRIC_WINDOW_BORDER_WIDTH] - 2, _guiColor[COLOR_WINDOW_SHADOW], _guiColor[COLOR_WINDOW_HIGHLIGHT]);
|
||||||
|
|
||||||
|
// Title bar - METRIC_WINDOW_TITLE_HEIGHT pixels high. Be sure shadow and highlight are not included in the width.
|
||||||
|
guiDrawHighlightFrame(_guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 3, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 3, x2 - _guiMetric[METRIC_WINDOW_BORDER_WIDTH] - 3, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + _guiMetric[METRIC_WINDOW_TITLE_HEIGHT] + 4, _guiColor[COLOR_WINDOW_HIGHLIGHT], _guiColor[COLOR_WINDOW_SHADOW]);
|
||||||
|
guiDrawFilledRectangle(_guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 4, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 4, x2 - _guiMetric[METRIC_WINDOW_BORDER_WIDTH] - 4, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + _guiMetric[METRIC_WINDOW_TITLE_HEIGHT] + 2, background);
|
||||||
|
|
||||||
|
w->base.dirty = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void windowSetActive(WindowT *window) {
|
||||||
|
windowDeactivateAll(guiRootGet());
|
||||||
|
GUI_SET_FLAG(window, WINDOW_FLAG_ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void windowSetTitle(WindowT *window, char *title) {
|
||||||
|
if (window->title) free(window->title);
|
||||||
|
window->title = strdup(title);
|
||||||
|
}
|
51
client/src/gui/window.h
Normal file
51
client/src/gui/window.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 WINDOW_H
|
||||||
|
#define WINDOW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "gui.h"
|
||||||
|
#include "widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum WindowE {
|
||||||
|
WINDOW_FLAG_ACTIVE = 0,
|
||||||
|
WINDOW_FLAG_MODAL,
|
||||||
|
WINDOW_FLAG_RESIZABLE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct WindowS {
|
||||||
|
WidgetT base; // Must be first in every widget
|
||||||
|
uint8_t flags;
|
||||||
|
char *title;
|
||||||
|
} WindowT;
|
||||||
|
|
||||||
|
|
||||||
|
void windowDel(WidgetT **widget);
|
||||||
|
WidgetT *windowInit(WidgetT *window, uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title);
|
||||||
|
WindowT *windowNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title);
|
||||||
|
void windowPaint(WidgetT *window);
|
||||||
|
void windowSetActive(WindowT *window);
|
||||||
|
void windowSetTitle(WindowT *window, char *title);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // WINDOW_H
|
252
client/src/linux/linux.c
Normal file
252
client/src/linux/linux.c
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 <SDL2/SDL.h>
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
#include "mouse.h"
|
||||||
|
#include "vesa.h"
|
||||||
|
|
||||||
|
|
||||||
|
static SDL_Window *_window = NULL;
|
||||||
|
static SDL_Renderer *_renderer = NULL;
|
||||||
|
static SDL_Surface *_surface = NULL;
|
||||||
|
static SurfaceT *_offScreenBuffer = NULL;
|
||||||
|
static SurfaceT *_activeSurface = NULL;
|
||||||
|
static uint16_t _width = 0;
|
||||||
|
static uint16_t _height = 0;
|
||||||
|
static MouseT _mouse;
|
||||||
|
|
||||||
|
|
||||||
|
void (*vbePutPixel)(uint16_t x, uint16_t y, PixelT pixel);
|
||||||
|
|
||||||
|
|
||||||
|
static void vbePutPixel32(uint16_t x, uint16_t y, PixelT pixel);
|
||||||
|
|
||||||
|
|
||||||
|
void mouseShutdown(void) {
|
||||||
|
// Eh, don't care.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int16_t mouseStartup(void) {
|
||||||
|
_mouse.active = 1;
|
||||||
|
_mouse.buttonCount = 3;
|
||||||
|
_mouse.buttonLeft = 0;
|
||||||
|
_mouse.buttonRight = 0;
|
||||||
|
_mouse.buttonMiddle = 0;
|
||||||
|
_mouse.buttonLeftWasDown = 0;
|
||||||
|
_mouse.buttonRightWasDown = 0;
|
||||||
|
_mouse.buttonMiddleWasDown = 0;
|
||||||
|
_mouse.x = 0;
|
||||||
|
_mouse.y = 0;
|
||||||
|
_mouse.w = vbeDisplayWidthGet();
|
||||||
|
_mouse.h = vbeDisplayHeightGet();
|
||||||
|
|
||||||
|
return _mouse.active;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MouseT *mouseRead(void) {
|
||||||
|
int mouseX = 0;
|
||||||
|
int mouseY = 0;
|
||||||
|
int buttons = 0;
|
||||||
|
|
||||||
|
SDL_Delay(1);
|
||||||
|
SDL_PumpEvents();
|
||||||
|
|
||||||
|
buttons = SDL_GetMouseState((int *)&mouseX, (int *)&mouseY);
|
||||||
|
|
||||||
|
_mouse.buttonLeftWasDown = _mouse.buttonLeft;
|
||||||
|
_mouse.buttonRightWasDown = _mouse.buttonRight;
|
||||||
|
_mouse.buttonMiddleWasDown = _mouse.buttonMiddle;
|
||||||
|
|
||||||
|
_mouse.buttonLeft = ((buttons & SDL_BUTTON_LMASK) != 0);
|
||||||
|
_mouse.buttonRight = ((buttons & SDL_BUTTON_RMASK) != 0);
|
||||||
|
_mouse.buttonMiddle = ((buttons & SDL_BUTTON_MMASK) != 0);
|
||||||
|
|
||||||
|
_mouse.x = mouseX;
|
||||||
|
_mouse.y = mouseY;
|
||||||
|
|
||||||
|
return &_mouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t vbeDisplayDepthGet(void) {
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t vbeDisplayHeightGet(void) {
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t vbeDisplayWidthGet(void) {
|
||||||
|
return _width;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PixelT vbeMakePixel(uint8_t red, uint8_t green, uint8_t blue) {
|
||||||
|
return
|
||||||
|
(red << 24) |
|
||||||
|
(green << 16) |
|
||||||
|
(blue << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbePresent(void) {
|
||||||
|
SDL_SetRenderTarget(_renderer, NULL);
|
||||||
|
vbeSurfaceBlit(_offScreenBuffer, 0, 0);
|
||||||
|
SDL_RenderPresent(_renderer);
|
||||||
|
|
||||||
|
// Throttle this to some sane frame rate.
|
||||||
|
SDL_Delay(32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void vbePutPixel32(uint16_t x, uint16_t y, PixelT pixel) {
|
||||||
|
uint8_t red = (pixel & 0xff000000) >> 24;
|
||||||
|
uint8_t green = (pixel & 0x00ff0000) >> 16;
|
||||||
|
uint8_t blue = (pixel & 0x0000ff00) >> 8;
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(_renderer, red, green, blue, 0xff);
|
||||||
|
SDL_RenderDrawPoint(_renderer, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int16_t vbeShowInfo(void) {
|
||||||
|
// Eh, don't care.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int16_t vbeShutdown(void) {
|
||||||
|
vbeSurfaceDestroy(&_offScreenBuffer);
|
||||||
|
|
||||||
|
if (_renderer) {
|
||||||
|
SDL_DestroyRenderer(_renderer);
|
||||||
|
_renderer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_window) {
|
||||||
|
SDL_DestroyWindow(_window);
|
||||||
|
_window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
|
||||||
|
|
||||||
|
(void)bpp;
|
||||||
|
|
||||||
|
vbePutPixel = vbePutPixel32;
|
||||||
|
|
||||||
|
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);
|
||||||
|
SDL_RenderSetLogicalSize(_renderer, xRes, yRes);
|
||||||
|
|
||||||
|
_offScreenBuffer = vbeSurfaceCreate(xRes, yRes);
|
||||||
|
|
||||||
|
_width = xRes;
|
||||||
|
_height = yRes;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeSurfaceBlit(SurfaceT *source, uint16_t x, uint16_t y) {
|
||||||
|
SDL_Rect r;
|
||||||
|
|
||||||
|
r.x = x;
|
||||||
|
r.y = y;
|
||||||
|
r.w = source->width;
|
||||||
|
r.h = source->height;
|
||||||
|
|
||||||
|
SDL_RenderCopy(_renderer, (SDL_Texture *)source->buffer.bits8, NULL, &r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeSurfaceClear(PixelT color) {
|
||||||
|
uint8_t red = (color & 0xff000000) >> 24;
|
||||||
|
uint8_t green = (color & 0x00ff0000) >> 16;
|
||||||
|
uint8_t blue = (color & 0x0000ff00) >> 8;
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(_renderer, red, green, blue, 0xff);
|
||||||
|
SDL_RenderClear(_renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SurfaceT *vbeSurfaceCreate(uint16_t width, uint16_t height) {
|
||||||
|
SDL_Texture *texture = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
|
||||||
|
SDL_Texture *target = SDL_GetRenderTarget(_renderer);
|
||||||
|
SurfaceT *surface = (SurfaceT *)malloc(sizeof(SurfaceT));
|
||||||
|
|
||||||
|
surface->width = width;
|
||||||
|
surface->height = height;
|
||||||
|
surface->scanline = width * 4; // Always 32 bit.
|
||||||
|
surface->bytes = surface->scanline * height;
|
||||||
|
surface->buffer.bits8 = (uint8_t *)texture;
|
||||||
|
|
||||||
|
SDL_SetRenderTarget(_renderer, texture);
|
||||||
|
SDL_SetRenderDrawColor(_renderer, 0, 0, 0, 0xff);
|
||||||
|
SDL_RenderClear(_renderer);
|
||||||
|
|
||||||
|
SDL_SetRenderTarget(_renderer, target);
|
||||||
|
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeSurfaceDestroy(SurfaceT **surface) {
|
||||||
|
SurfaceT *s = *surface;
|
||||||
|
|
||||||
|
SDL_DestroyTexture((SDL_Texture *)s->buffer.bits8);
|
||||||
|
free(s);
|
||||||
|
s = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeSurfaceSet(SurfaceT *surface) {
|
||||||
|
SDL_Texture *texture = NULL;
|
||||||
|
|
||||||
|
if (surface) {
|
||||||
|
_activeSurface = surface;
|
||||||
|
} else {
|
||||||
|
_activeSurface = _offScreenBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture = (SDL_Texture *)_activeSurface->buffer.bits8;
|
||||||
|
SDL_SetRenderTarget(_renderer, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vbeWaitVBlank(void) {
|
||||||
|
// Eh, don't care.
|
||||||
|
}
|
||||||
|
|
90
client/src/main.c
Normal file
90
client/src/main.c
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 "vesa.h"
|
||||||
|
#include "mouse.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "font.h"
|
||||||
|
#include "gui.h"
|
||||||
|
#include "widget.h"
|
||||||
|
#include "desktop.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
|
||||||
|
void test(void) {
|
||||||
|
MouseT *mouse = NULL;
|
||||||
|
DesktopT *desktop = NULL;
|
||||||
|
WindowT *w1 = NULL;
|
||||||
|
WindowT *w2 = NULL;
|
||||||
|
WindowT *w3 = NULL;
|
||||||
|
ImageT *pointer = NULL;
|
||||||
|
PixelT alpha;
|
||||||
|
|
||||||
|
vbeStartup(800, 600, 8);
|
||||||
|
mouseStartup();
|
||||||
|
desktop = guiStartup();
|
||||||
|
|
||||||
|
pointer = imageLoad("mouse.png");
|
||||||
|
alpha = imagePixelGet(pointer, 5, 0);
|
||||||
|
|
||||||
|
w1 = windowNew(25, 25, 300, 200, "Window 1");
|
||||||
|
w2 = windowNew(150, 150, 300, 200, "Window 2");
|
||||||
|
w3 = windowNew(300, 300, 300, 200, "Window 3");
|
||||||
|
guiAttach((WidgetT *)desktop, (WidgetT *)w1);
|
||||||
|
guiAttach((WidgetT *)desktop, (WidgetT *)w2);
|
||||||
|
guiAttach((WidgetT *)desktop, (WidgetT *)w3);
|
||||||
|
|
||||||
|
do {
|
||||||
|
mouse = mouseRead();
|
||||||
|
guiProcessMouse(mouse);
|
||||||
|
guiComposite();
|
||||||
|
imageRenderWithAlpha(pointer, mouse->x, mouse->y, alpha);
|
||||||
|
vbeWaitVBlank();
|
||||||
|
vbePresent();
|
||||||
|
} while (!(!mouse->buttonRight && mouse->buttonRightWasDown)); // Exit on release of right-click.
|
||||||
|
|
||||||
|
imageUnload(&pointer);
|
||||||
|
|
||||||
|
guiShutdown();
|
||||||
|
mouseShutdown();
|
||||||
|
vbeShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
vbeShowInfo();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
logOpen("test.log", 1);
|
||||||
|
|
||||||
|
test();
|
||||||
|
|
||||||
|
logClose();
|
||||||
|
|
||||||
|
#ifdef memoryLeakShow
|
||||||
|
memoryLeaksShow();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
1895
client/src/thirdparty/stb_ds.h
vendored
Normal file
1895
client/src/thirdparty/stb_ds.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
7897
client/src/thirdparty/stb_image.h
vendored
Normal file
7897
client/src/thirdparty/stb_image.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
194
client/src/thirdparty/stb_leakcheck.h
vendored
Normal file
194
client/src/thirdparty/stb_leakcheck.h
vendored
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
// stb_leakcheck.h - v0.6 - quick & dirty malloc leak-checking - public domain
|
||||||
|
// LICENSE
|
||||||
|
//
|
||||||
|
// See end of file.
|
||||||
|
|
||||||
|
#ifdef STB_LEAKCHECK_IMPLEMENTATION
|
||||||
|
#undef STB_LEAKCHECK_IMPLEMENTATION // don't implement more than once
|
||||||
|
|
||||||
|
// if we've already included leakcheck before, undefine the macros
|
||||||
|
#ifdef malloc
|
||||||
|
#undef malloc
|
||||||
|
#undef free
|
||||||
|
#undef realloc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STB_LEAKCHECK_OUTPUT_PIPE
|
||||||
|
#define STB_LEAKCHECK_OUTPUT_PIPE stdout
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
typedef struct malloc_info stb_leakcheck_malloc_info;
|
||||||
|
|
||||||
|
struct malloc_info
|
||||||
|
{
|
||||||
|
const char *file;
|
||||||
|
int line;
|
||||||
|
size_t size;
|
||||||
|
stb_leakcheck_malloc_info *next,*prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static stb_leakcheck_malloc_info *mi_head;
|
||||||
|
|
||||||
|
void *stb_leakcheck_malloc(size_t sz, const char *file, int line)
|
||||||
|
{
|
||||||
|
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) malloc(sz + sizeof(*mi));
|
||||||
|
if (mi == NULL) return mi;
|
||||||
|
mi->file = file;
|
||||||
|
mi->line = line;
|
||||||
|
mi->next = mi_head;
|
||||||
|
if (mi_head)
|
||||||
|
mi->next->prev = mi;
|
||||||
|
mi->prev = NULL;
|
||||||
|
mi->size = (int) sz;
|
||||||
|
mi_head = mi;
|
||||||
|
return mi+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stb_leakcheck_free(void *ptr)
|
||||||
|
{
|
||||||
|
if (ptr != NULL) {
|
||||||
|
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1;
|
||||||
|
mi->size = ~mi->size;
|
||||||
|
#ifndef STB_LEAKCHECK_SHOWALL
|
||||||
|
if (mi->prev == NULL) {
|
||||||
|
assert(mi_head == mi);
|
||||||
|
mi_head = mi->next;
|
||||||
|
} else
|
||||||
|
mi->prev->next = mi->next;
|
||||||
|
if (mi->next)
|
||||||
|
mi->next->prev = mi->prev;
|
||||||
|
free(mi);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line)
|
||||||
|
{
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return stb_leakcheck_malloc(sz, file, line);
|
||||||
|
} else if (sz == 0) {
|
||||||
|
stb_leakcheck_free(ptr);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1;
|
||||||
|
if (sz <= mi->size)
|
||||||
|
return ptr;
|
||||||
|
else {
|
||||||
|
#ifdef STB_LEAKCHECK_REALLOC_PRESERVE_MALLOC_FILELINE
|
||||||
|
void *q = stb_leakcheck_malloc(sz, mi->file, mi->line);
|
||||||
|
#else
|
||||||
|
void *q = stb_leakcheck_malloc(sz, file, line);
|
||||||
|
#endif
|
||||||
|
if (q) {
|
||||||
|
memcpy(q, ptr, mi->size);
|
||||||
|
stb_leakcheck_free(ptr);
|
||||||
|
}
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stblkck_internal_print(const char *reason, stb_leakcheck_malloc_info *mi)
|
||||||
|
{
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900 // 1900=VS 2015
|
||||||
|
// Compilers that use the old MS C runtime library don't have %zd
|
||||||
|
// and the older ones don't even have %lld either... however, the old compilers
|
||||||
|
// without "long long" don't support 64-bit targets either, so here's the
|
||||||
|
// compromise:
|
||||||
|
#if _MSC_VER < 1400 // before VS 2005
|
||||||
|
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %8d bytes at %p\n", reason, mi->file, mi->line, (int)mi->size, (void*)(mi+1));
|
||||||
|
#else
|
||||||
|
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %16lld bytes at %p\n", reason, mi->file, mi->line, (long long)mi->size, (void*)(mi+1));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// Assume we have %zd on other targets.
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
__mingw_fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1));
|
||||||
|
#else
|
||||||
|
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void stb_leakcheck_dumpmem(void)
|
||||||
|
{
|
||||||
|
stb_leakcheck_malloc_info *mi = mi_head;
|
||||||
|
while (mi) {
|
||||||
|
if ((ptrdiff_t) mi->size >= 0)
|
||||||
|
stblkck_internal_print("LEAKED", mi);
|
||||||
|
mi = mi->next;
|
||||||
|
}
|
||||||
|
#ifdef STB_LEAKCHECK_SHOWALL
|
||||||
|
mi = mi_head;
|
||||||
|
while (mi) {
|
||||||
|
if ((ptrdiff_t) mi->size < 0)
|
||||||
|
stblkck_internal_print("FREED ", mi);
|
||||||
|
mi = mi->next;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif // STB_LEAKCHECK_IMPLEMENTATION
|
||||||
|
|
||||||
|
#if !defined(INCLUDE_STB_LEAKCHECK_H) || !defined(malloc)
|
||||||
|
#define INCLUDE_STB_LEAKCHECK_H
|
||||||
|
|
||||||
|
#include <stdlib.h> // we want to define the macros *after* stdlib to avoid a slew of errors
|
||||||
|
|
||||||
|
#define malloc(sz) stb_leakcheck_malloc(sz, __FILE__, __LINE__)
|
||||||
|
#define free(p) stb_leakcheck_free(p)
|
||||||
|
#define realloc(p,sz) stb_leakcheck_realloc(p,sz, __FILE__, __LINE__)
|
||||||
|
|
||||||
|
extern void * stb_leakcheck_malloc(size_t sz, const char *file, int line);
|
||||||
|
extern void * stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line);
|
||||||
|
extern void stb_leakcheck_free(void *ptr);
|
||||||
|
extern void stb_leakcheck_dumpmem(void);
|
||||||
|
|
||||||
|
#endif // INCLUDE_STB_LEAKCHECK_H
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
This software is available under 2 licenses -- choose whichever you prefer.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
ALTERNATIVE A - MIT License
|
||||||
|
Copyright (c) 2017 Sean Barrett
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||||
|
software, either in source code form or as a compiled binary, for any purpose,
|
||||||
|
commercial or non-commercial, and by any means.
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||||
|
software dedicate any and all copyright interest in the software to the public
|
||||||
|
domain. We make this dedication for the benefit of the public at large and to
|
||||||
|
the detriment of our heirs and successors. We intend this dedication to be an
|
||||||
|
overt act of relinquishment in perpetuity of all present and future rights to
|
||||||
|
this software under copyright law.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
*/
|
BIN
font/data/vga8x8.png
(Stored with Git LFS)
Normal file
BIN
font/data/vga8x8.png
(Stored with Git LFS)
Normal file
Binary file not shown.
31
font/font.pro
Normal file
31
font/font.pro
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#
|
||||||
|
# Kangaroo Punch Multi Player 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
TEMPLATE = app
|
||||||
|
CONFIG -= qt
|
||||||
|
|
||||||
|
DESTDIR = $$OUT_PWD/bin
|
||||||
|
|
||||||
|
HEADERS = \
|
||||||
|
src/stb_image.h \
|
||||||
|
src/stb_leakcheck.h \
|
||||||
|
src/stb.h
|
||||||
|
|
||||||
|
SOURCES = \
|
||||||
|
src/stb.c \
|
||||||
|
src/main.c
|
83
font/src/main.c
Normal file
83
font/src/main.c
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 <stdio.h>
|
||||||
|
|
||||||
|
#include "stb.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define BITMAP_FILE "/home/scott/code/kpmpgsmkii/font/data/vga8x8.png"
|
||||||
|
#define FONT_FILE "/home/scott/code/kpmpgsmkii/client/bin/vga8x8.dat"
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
unsigned char *font = NULL;
|
||||||
|
unsigned char data = 0;
|
||||||
|
FILE *out = NULL;
|
||||||
|
int bits = 0;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int n;
|
||||||
|
int w;
|
||||||
|
int h;
|
||||||
|
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
// Load 8x8 font from disk. Font is in a 16x16 grid.
|
||||||
|
font = stbi_load(BITMAP_FILE, (int *)&w, (int *)&h, (int *)&n, 3);
|
||||||
|
if (!font) return 1;
|
||||||
|
|
||||||
|
// Create data file for font.
|
||||||
|
out = fopen(FONT_FILE, "wb");
|
||||||
|
if (!out) {
|
||||||
|
stbi_image_free(font);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provide some metadata for enhancement later.
|
||||||
|
fputc(8, out); // Width of characters
|
||||||
|
fputc(8, out); // Height of characters
|
||||||
|
fputc(16, out); // Number of characters per row
|
||||||
|
fputc(255, out); // Number of characters - 1
|
||||||
|
|
||||||
|
// Convert bitmap to actual bits.
|
||||||
|
for (y=0; y<h; y++) {
|
||||||
|
for (x=0; x<w; x++) {
|
||||||
|
data <<= 1;
|
||||||
|
data |= (font[(y * w * 3) + (x * 3)] != 0);
|
||||||
|
bits++;
|
||||||
|
if (bits > 7) {
|
||||||
|
bits = 0;
|
||||||
|
fputc(data, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(out);
|
||||||
|
|
||||||
|
// Clean up.
|
||||||
|
stbi_image_free(font);
|
||||||
|
|
||||||
|
// Prove we cleaned up.
|
||||||
|
stb_leakcheck_dumpmem();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
26
font/src/stb.c
Normal file
26
font/src/stb.c
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 STB_IMAGE_IMPLEMENTATION
|
||||||
|
#define STBI_ONLY_PNG
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
#define STB_LEAKCHECK_IMPLEMENTATION
|
||||||
|
#include "stb_leakcheck.h"
|
29
font/src/stb.h
Normal file
29
font/src/stb.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 STB_H
|
||||||
|
#define STB_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "stb_image.h"
|
||||||
|
#include "stb_leakcheck.h"
|
||||||
|
|
||||||
|
|
||||||
|
#endif // STB_H
|
7897
font/src/stb_image.h
Normal file
7897
font/src/stb_image.h
Normal file
File diff suppressed because it is too large
Load diff
194
font/src/stb_leakcheck.h
Normal file
194
font/src/stb_leakcheck.h
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
// stb_leakcheck.h - v0.6 - quick & dirty malloc leak-checking - public domain
|
||||||
|
// LICENSE
|
||||||
|
//
|
||||||
|
// See end of file.
|
||||||
|
|
||||||
|
#ifdef STB_LEAKCHECK_IMPLEMENTATION
|
||||||
|
#undef STB_LEAKCHECK_IMPLEMENTATION // don't implement more than once
|
||||||
|
|
||||||
|
// if we've already included leakcheck before, undefine the macros
|
||||||
|
#ifdef malloc
|
||||||
|
#undef malloc
|
||||||
|
#undef free
|
||||||
|
#undef realloc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STB_LEAKCHECK_OUTPUT_PIPE
|
||||||
|
#define STB_LEAKCHECK_OUTPUT_PIPE stdout
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
typedef struct malloc_info stb_leakcheck_malloc_info;
|
||||||
|
|
||||||
|
struct malloc_info
|
||||||
|
{
|
||||||
|
const char *file;
|
||||||
|
int line;
|
||||||
|
size_t size;
|
||||||
|
stb_leakcheck_malloc_info *next,*prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static stb_leakcheck_malloc_info *mi_head;
|
||||||
|
|
||||||
|
void *stb_leakcheck_malloc(size_t sz, const char *file, int line)
|
||||||
|
{
|
||||||
|
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) malloc(sz + sizeof(*mi));
|
||||||
|
if (mi == NULL) return mi;
|
||||||
|
mi->file = file;
|
||||||
|
mi->line = line;
|
||||||
|
mi->next = mi_head;
|
||||||
|
if (mi_head)
|
||||||
|
mi->next->prev = mi;
|
||||||
|
mi->prev = NULL;
|
||||||
|
mi->size = (int) sz;
|
||||||
|
mi_head = mi;
|
||||||
|
return mi+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stb_leakcheck_free(void *ptr)
|
||||||
|
{
|
||||||
|
if (ptr != NULL) {
|
||||||
|
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1;
|
||||||
|
mi->size = ~mi->size;
|
||||||
|
#ifndef STB_LEAKCHECK_SHOWALL
|
||||||
|
if (mi->prev == NULL) {
|
||||||
|
assert(mi_head == mi);
|
||||||
|
mi_head = mi->next;
|
||||||
|
} else
|
||||||
|
mi->prev->next = mi->next;
|
||||||
|
if (mi->next)
|
||||||
|
mi->next->prev = mi->prev;
|
||||||
|
free(mi);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line)
|
||||||
|
{
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return stb_leakcheck_malloc(sz, file, line);
|
||||||
|
} else if (sz == 0) {
|
||||||
|
stb_leakcheck_free(ptr);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1;
|
||||||
|
if (sz <= mi->size)
|
||||||
|
return ptr;
|
||||||
|
else {
|
||||||
|
#ifdef STB_LEAKCHECK_REALLOC_PRESERVE_MALLOC_FILELINE
|
||||||
|
void *q = stb_leakcheck_malloc(sz, mi->file, mi->line);
|
||||||
|
#else
|
||||||
|
void *q = stb_leakcheck_malloc(sz, file, line);
|
||||||
|
#endif
|
||||||
|
if (q) {
|
||||||
|
memcpy(q, ptr, mi->size);
|
||||||
|
stb_leakcheck_free(ptr);
|
||||||
|
}
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stblkck_internal_print(const char *reason, stb_leakcheck_malloc_info *mi)
|
||||||
|
{
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900 // 1900=VS 2015
|
||||||
|
// Compilers that use the old MS C runtime library don't have %zd
|
||||||
|
// and the older ones don't even have %lld either... however, the old compilers
|
||||||
|
// without "long long" don't support 64-bit targets either, so here's the
|
||||||
|
// compromise:
|
||||||
|
#if _MSC_VER < 1400 // before VS 2005
|
||||||
|
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %8d bytes at %p\n", reason, mi->file, mi->line, (int)mi->size, (void*)(mi+1));
|
||||||
|
#else
|
||||||
|
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %16lld bytes at %p\n", reason, mi->file, mi->line, (long long)mi->size, (void*)(mi+1));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// Assume we have %zd on other targets.
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
__mingw_fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1));
|
||||||
|
#else
|
||||||
|
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void stb_leakcheck_dumpmem(void)
|
||||||
|
{
|
||||||
|
stb_leakcheck_malloc_info *mi = mi_head;
|
||||||
|
while (mi) {
|
||||||
|
if ((ptrdiff_t) mi->size >= 0)
|
||||||
|
stblkck_internal_print("LEAKED", mi);
|
||||||
|
mi = mi->next;
|
||||||
|
}
|
||||||
|
#ifdef STB_LEAKCHECK_SHOWALL
|
||||||
|
mi = mi_head;
|
||||||
|
while (mi) {
|
||||||
|
if ((ptrdiff_t) mi->size < 0)
|
||||||
|
stblkck_internal_print("FREED ", mi);
|
||||||
|
mi = mi->next;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif // STB_LEAKCHECK_IMPLEMENTATION
|
||||||
|
|
||||||
|
#if !defined(INCLUDE_STB_LEAKCHECK_H) || !defined(malloc)
|
||||||
|
#define INCLUDE_STB_LEAKCHECK_H
|
||||||
|
|
||||||
|
#include <stdlib.h> // we want to define the macros *after* stdlib to avoid a slew of errors
|
||||||
|
|
||||||
|
#define malloc(sz) stb_leakcheck_malloc(sz, __FILE__, __LINE__)
|
||||||
|
#define free(p) stb_leakcheck_free(p)
|
||||||
|
#define realloc(p,sz) stb_leakcheck_realloc(p,sz, __FILE__, __LINE__)
|
||||||
|
|
||||||
|
extern void * stb_leakcheck_malloc(size_t sz, const char *file, int line);
|
||||||
|
extern void * stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line);
|
||||||
|
extern void stb_leakcheck_free(void *ptr);
|
||||||
|
extern void stb_leakcheck_dumpmem(void);
|
||||||
|
|
||||||
|
#endif // INCLUDE_STB_LEAKCHECK_H
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
This software is available under 2 licenses -- choose whichever you prefer.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
ALTERNATIVE A - MIT License
|
||||||
|
Copyright (c) 2017 Sean Barrett
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||||
|
software, either in source code form or as a compiled binary, for any purpose,
|
||||||
|
commercial or non-commercial, and by any means.
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||||
|
software dedicate any and all copyright interest in the software to the public
|
||||||
|
domain. We make this dedication for the benefit of the public at large and to
|
||||||
|
the detriment of our heirs and successors. We intend this dedication to be an
|
||||||
|
overt act of relinquishment in perpetuity of all present and future rights to
|
||||||
|
this software under copyright law.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
*/
|
24
kpmpgsmkii.pro
Normal file
24
kpmpgsmkii.pro
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#
|
||||||
|
# Kangaroo Punch Multi Player 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
TEMPLATE = SUBDIRS
|
||||||
|
CONFIG *= ORDERED
|
||||||
|
|
||||||
|
SUBDIRS = \
|
||||||
|
font \
|
||||||
|
client
|
Loading…
Add table
Reference in a new issue