DJGPP backend working.
This commit is contained in:
parent
ef63b14c2f
commit
4d0b209adc
16 changed files with 1451 additions and 840 deletions
|
@ -23,6 +23,8 @@ HEADERS += \
|
||||||
$$SHARED/stddclmr.h \
|
$$SHARED/stddclmr.h \
|
||||||
$$SHARED/thirdparty/memwatch/memwatch.h \
|
$$SHARED/thirdparty/memwatch/memwatch.h \
|
||||||
$$SHARED/thirdparty/stb_ds.h \
|
$$SHARED/thirdparty/stb_ds.h \
|
||||||
|
$$SHARED/log.h \
|
||||||
|
$$SHARED/util.h \
|
||||||
src/gui/font.h \
|
src/gui/font.h \
|
||||||
src/gui/gui.h \
|
src/gui/gui.h \
|
||||||
src/gui/image.h \
|
src/gui/image.h \
|
||||||
|
@ -38,6 +40,8 @@ SOURCES += \
|
||||||
$$SHARED/array.c \
|
$$SHARED/array.c \
|
||||||
$$SHARED/memory.c \
|
$$SHARED/memory.c \
|
||||||
$$SHARED/thirdparty/memwatch/memwatch.c \
|
$$SHARED/thirdparty/memwatch/memwatch.c \
|
||||||
|
$$SHARED/log.c \
|
||||||
|
$$SHARED/util.c \
|
||||||
src/gui/font.c \
|
src/gui/font.c \
|
||||||
src/gui/gui.c \
|
src/gui/gui.c \
|
||||||
src/gui/image.c \
|
src/gui/image.c \
|
||||||
|
|
|
@ -25,7 +25,7 @@ static ColorT _mouseTransparency;
|
||||||
|
|
||||||
|
|
||||||
void guiRun(void) {
|
void guiRun(void) {
|
||||||
EventT event;
|
EventT event = { 0 };
|
||||||
|
|
||||||
while (_guiRunning) {
|
while (_guiRunning) {
|
||||||
// Read mouse & keyboard.
|
// Read mouse & keyboard.
|
||||||
|
@ -75,12 +75,13 @@ void guiShutdown(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void guiStartup(int16_t width, int16_t height, int16_t depth) {
|
uint8_t guiStartup(int16_t width, int16_t height, int16_t depth) {
|
||||||
|
|
||||||
platformStartup(width, height, depth);
|
if (platformStartup(width, height, depth) == FAIL) return FAIL;
|
||||||
|
|
||||||
__guiScreenBuffer = videoSurfaceScreenGet();
|
__guiScreenBuffer = videoSurfaceScreenGet();
|
||||||
__guiBackBuffer = videoSurfaceCreate(videoDisplayWidthGet(), videoDisplayHeightGet());
|
__guiBackBuffer = videoSurfaceCreate(videoDisplayWidthGet(), videoDisplayHeightGet());
|
||||||
|
videoSurfaceSet(__guiBackBuffer);
|
||||||
|
|
||||||
_mousePointer = imageLoad("mouse.png");
|
_mousePointer = imageLoad("mouse.png");
|
||||||
_mouseTransparency = videoSurfacePixelGet(_mousePointer, videoSurfaceWidthGet(_mousePointer) - 2, 0); // Find our transparency color.
|
_mouseTransparency = videoSurfacePixelGet(_mousePointer, videoSurfaceWidthGet(_mousePointer) - 2, 0); // Find our transparency color.
|
||||||
|
@ -90,6 +91,8 @@ void guiStartup(int16_t width, int16_t height, int16_t depth) {
|
||||||
wmStartup();
|
wmStartup();
|
||||||
|
|
||||||
guiRegister(windowRegister);
|
guiRegister(windowRegister);
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ void guiModesShow(void);
|
||||||
void guiRegister(WidgetRegisterT widgetRegister);
|
void guiRegister(WidgetRegisterT widgetRegister);
|
||||||
void guiRun(void);
|
void guiRun(void);
|
||||||
void guiShutdown(void);
|
void guiShutdown(void);
|
||||||
void guiStartup(int16_t width, int16_t height, int16_t depth);
|
uint8_t guiStartup(int16_t width, int16_t height, int16_t depth);
|
||||||
void guiStop(void);
|
void guiStop(void);
|
||||||
void guiWidgetBaseSet(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
void guiWidgetBaseSet(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||||
|
|
||||||
|
|
|
@ -7,19 +7,22 @@ int main(int argc, char *argv[]) {
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
|
||||||
|
|
||||||
guiStartup(800, 600, 24);
|
memoryStartup(argv[0]);
|
||||||
|
logOpenByHandle(memoryLogHandleGet());
|
||||||
|
|
||||||
|
if (guiStartup(800, 600, 32) == SUCCESS) {
|
||||||
i = 1;
|
i = 1;
|
||||||
//for (i=1; i<4; i++) {
|
//for (i=1; i<4; i++) {
|
||||||
sprintf(title, "Testing %d", i);
|
sprintf(title, "Testing %d", i);
|
||||||
windowCreate(i * 50, i * 50, 300, 200, title, WIN_CLOSE | WIN_MAXIMIZE | WIN_MINIMIZE | WIN_RESIZE);
|
windowCreate(i * 50, i * 50, 300, 200, title, WIN_CLOSE | WIN_MAXIMIZE | WIN_MINIMIZE | WIN_RESIZE);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
guiRun();
|
guiRun();
|
||||||
|
|
||||||
guiShutdown();
|
guiShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
logClose();
|
||||||
|
memoryShutdown();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,14 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "stddclmr.h"
|
#include "stddclmr.h"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifdef BACKEND_DJGPP
|
#ifdef BACKEND_DJGPP
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
#include <dos.h>
|
#include <dos.h>
|
||||||
#include <dpmi.h>
|
#include <dpmi.h>
|
||||||
#include <go32.h>
|
#include <go32.h>
|
||||||
|
@ -8,19 +10,52 @@
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#include <sys/farptr.h>
|
#include <sys/farptr.h>
|
||||||
#include <sys/nearptr.h>
|
#include <sys/nearptr.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "djgpp.h"
|
#include "djgpp.h"
|
||||||
|
|
||||||
|
|
||||||
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))
|
|
||||||
|
|
||||||
|
|
||||||
// These are all we support
|
// These are all we support
|
||||||
#define VBE_MM_PACKED 4
|
#define VBE_MM_PACKED 4
|
||||||
#define VBE_MM_DCOLOR 6
|
#define VBE_MM_DCOLOR 6
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
|
||||||
|
#define KEYBOARD_READ_EXTENDED 0x10
|
||||||
|
#define KEYBOARD_CHECK_EXTENDED 0x11
|
||||||
|
#define KEYBOARD_META_EXTENDED 0x12
|
||||||
|
|
||||||
|
|
||||||
|
enum MetaBitsE {
|
||||||
|
KEY_META_SHIFT_RIGHT = 0,
|
||||||
|
KEY_META_SHIFT_LEFT,
|
||||||
|
KEY_META_CONTROL,
|
||||||
|
KEY_META_ALT,
|
||||||
|
KEY_META_SCROLL_LOCKED,
|
||||||
|
KEY_META_NUM_LOCKED,
|
||||||
|
KEY_META_CAPS_LOCKED,
|
||||||
|
KEY_META_INSERT_LOCKED,
|
||||||
|
KEY_META_CONTROL_LEFT,
|
||||||
|
KEY_META_ALT_LEFT,
|
||||||
|
KEY_META_CONTROL_RIGHT,
|
||||||
|
KEY_META_ALT_RIGHT,
|
||||||
|
KEY_META_SCROLL_LOCK,
|
||||||
|
KEY_META_NUM_LOCK,
|
||||||
|
KEY_META_CAPS_LOCK,
|
||||||
|
KEY_META_SYSREQ
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct VBEInfoS {
|
typedef struct VBEInfoS {
|
||||||
char vbeSignature[4]; // 'VESA' 4 byte signature
|
char vbeSignature[4]; // 'VESA' 4 byte signature
|
||||||
int16_t vbeVersion; // VBE version number
|
int16_t vbeVersion; // VBE version number
|
||||||
|
@ -121,6 +156,9 @@ typedef struct VBESurfaceS {
|
||||||
} VBESurfaceT;
|
} VBESurfaceT;
|
||||||
|
|
||||||
|
|
||||||
|
extern ColorT *__guiBaseColors;
|
||||||
|
|
||||||
|
|
||||||
static VBESurfaceT _vbeSurface;
|
static VBESurfaceT _vbeSurface;
|
||||||
static VBEInfoT _vbeInfo;
|
static VBEInfoT _vbeInfo;
|
||||||
static VBEModeInfoT _vbeModeInfo;
|
static VBEModeInfoT _vbeModeInfo;
|
||||||
|
@ -148,7 +186,98 @@ void (*videoSurfacePixelSet)(uint16_t x, uint16_t y, ColorT color);
|
||||||
|
|
||||||
|
|
||||||
void platformEventGet(EventT *event) {
|
void platformEventGet(EventT *event) {
|
||||||
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
int16_t dx;
|
||||||
|
int16_t dy;
|
||||||
|
int16_t h = videoDisplayHeightGet();
|
||||||
|
int16_t w = videoDisplayWidthGet();
|
||||||
|
int16_t ext = bioskey(KEYBOARD_CHECK_EXTENDED);
|
||||||
|
int16_t meta = bioskey(KEYBOARD_META_EXTENDED);
|
||||||
|
int16_t key = 0;
|
||||||
|
union REGS regs;
|
||||||
|
|
||||||
|
// Read mouse motion.
|
||||||
|
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 = event->x + dx;
|
||||||
|
y = event->y + dy;
|
||||||
|
if (x < 0) x = 0;
|
||||||
|
if (x > w - 1) x = w - 1;
|
||||||
|
if (y < 0) y = 0;
|
||||||
|
if (y > h - 1) y = h - 1;
|
||||||
|
event->x = x;
|
||||||
|
event->y = y;
|
||||||
|
|
||||||
|
// Read mouse buttons.
|
||||||
|
regs.x.ax = MOUSE_STATUS;
|
||||||
|
int86(MOUSE_INT, ®s, ®s);
|
||||||
|
|
||||||
|
// Was the left button down?
|
||||||
|
if (event->buttons & BUTTON_LEFT) {
|
||||||
|
// Yes. Is it still down?
|
||||||
|
if ((regs.x.bx & MOUSE_LEFT_BUTTON) > 0) {
|
||||||
|
// Yes. Do nothing.
|
||||||
|
} else {
|
||||||
|
// No! Clear it and set UP event.
|
||||||
|
event->buttons &= ~BUTTON_LEFT;
|
||||||
|
event->flags |= EVENT_FLAG_LEFT_UP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No. Is it down now?
|
||||||
|
if ((regs.x.bx & MOUSE_LEFT_BUTTON) > 0) {
|
||||||
|
// Yes! Set bit and DOWN event.
|
||||||
|
event->buttons |= BUTTON_LEFT;
|
||||||
|
event->flags |= EVENT_FLAG_LEFT_DOWN;
|
||||||
|
} else {
|
||||||
|
// No. Do nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Was the right button down?
|
||||||
|
if (event->buttons & BUTTON_RIGHT) {
|
||||||
|
// Yes. Is it still down?
|
||||||
|
if ((regs.x.bx & MOUSE_RIGHT_BUTTON) > 0) {
|
||||||
|
// Yes. Do nothing.
|
||||||
|
} else {
|
||||||
|
// No! Clear it and set UP event.
|
||||||
|
event->buttons &= ~BUTTON_RIGHT;
|
||||||
|
event->flags |= EVENT_FLAG_RIGHT_UP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No. Is it down now?
|
||||||
|
if ((regs.x.bx & MOUSE_RIGHT_BUTTON) > 0) {
|
||||||
|
// Yes! Set bit and DOWN event.
|
||||||
|
event->buttons |= BUTTON_RIGHT;
|
||||||
|
event->flags |= EVENT_FLAG_RIGHT_DOWN;
|
||||||
|
} else {
|
||||||
|
// No. Do nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read keyboard.
|
||||||
|
event->key = 0;
|
||||||
|
event->kbstat = 0;
|
||||||
|
if (ext > 0) {
|
||||||
|
key = bioskey(KEYBOARD_READ_EXTENDED);
|
||||||
|
// The value returned is a combination of the key's scan code in the high 8 bits
|
||||||
|
// and its ASCII code in the low 8 bits. For non-alphanumeric keys, such as the
|
||||||
|
// arrow keys, the low 8 bits are zeroed.
|
||||||
|
// Extended keys have the E0h prefix in the low 8 bits.
|
||||||
|
event->flags |= EVENT_FLAG_KEYPRESS;
|
||||||
|
if (LOW_BYTE(key) == 0xE0) {
|
||||||
|
//_extended = 1;
|
||||||
|
event->key = HIGH_BYTE(key);
|
||||||
|
} else {
|
||||||
|
//_extended = 0;
|
||||||
|
event->key = LOW_BYTE(key);
|
||||||
|
}
|
||||||
|
if ((meta & (1 << KEY_META_ALT)) + (meta & (1 << KEY_META_ALT_LEFT)) + (meta & (1 << KEY_META_ALT_RIGHT))) event->kbstat |= META_ALT;
|
||||||
|
if ((meta & (1 << KEY_META_CONTROL)) + (meta & (1 << KEY_META_CONTROL_LEFT)) + (meta & (1 << KEY_META_CONTROL_RIGHT))) event->kbstat |= META_CTRL;
|
||||||
|
if ((meta & (1 << KEY_META_SHIFT_LEFT)) + (meta & (1 << KEY_META_SHIFT_RIGHT))) event->kbstat |= META_SHIFT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,6 +285,8 @@ void platformShutdown(void) {
|
||||||
__dpmi_regs r;
|
__dpmi_regs r;
|
||||||
__dpmi_meminfo m;
|
__dpmi_meminfo m;
|
||||||
|
|
||||||
|
free(__guiBaseColors);
|
||||||
|
|
||||||
if (_vbeSurface.vbeInitBoolean == 0) {
|
if (_vbeSurface.vbeInitBoolean == 0) {
|
||||||
r.x.ax = 0x03; // make sure we're in 3h
|
r.x.ax = 0x03; // make sure we're in 3h
|
||||||
__dpmi_int(0x10, &r); // for buggy vesa implementations
|
__dpmi_int(0x10, &r); // for buggy vesa implementations
|
||||||
|
@ -192,32 +323,51 @@ void platformShutdown(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void platformStartup(int16_t width, int16_t height, int16_t depth) {
|
uint8_t platformStartup(int16_t width, int16_t height, int16_t depth) {
|
||||||
uint16_t vbeModeNumber;
|
uint16_t vbeModeNumber;
|
||||||
|
uint8_t i;
|
||||||
|
uint8_t EGA[16][3] = {
|
||||||
|
{ 0, 0, 0 }, /* black */
|
||||||
|
{ 0, 0, 170 }, /* blue */
|
||||||
|
{ 0, 170, 0 }, /* green */
|
||||||
|
{ 0, 170, 170 }, /* cyan */
|
||||||
|
{ 170, 0, 0 }, /* red */
|
||||||
|
{ 170, 0, 170 }, /* magenta */
|
||||||
|
{ 170, 85, 0 }, /* brown */
|
||||||
|
{ 170, 170, 170 }, /* light gray */
|
||||||
|
{ 85, 85, 85 }, /* dark gray */
|
||||||
|
{ 85, 85, 255 }, /* light blue */
|
||||||
|
{ 85, 255, 85 }, /* light green */
|
||||||
|
{ 85, 255, 255 }, /* light cyan */
|
||||||
|
{ 255, 85, 85 }, /* light red */
|
||||||
|
{ 255, 85, 255 }, /* light magenta */
|
||||||
|
{ 255, 255, 85 }, /* yellow */
|
||||||
|
{ 255, 255, 255 } /* white */
|
||||||
|
};
|
||||||
|
|
||||||
if (vbeGetInfo() == NULL) {
|
if (vbeGetInfo() == NULL) {
|
||||||
//logWrite("No VESA BIOS Extensions found.\n");
|
logWrite("No VESA BIOS Extensions found.\n");
|
||||||
//vbeShutdown();
|
platformShutdown();
|
||||||
return;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_vbeInfo.vbeVersion < 0x0200) {
|
if (_vbeInfo.vbeVersion < 0x0200) {
|
||||||
//logWrite("VBE Version 2.0 or better required.\n");
|
logWrite("VBE Version 2.0 or better required.\n");
|
||||||
//vbeShutdown();
|
platformShutdown();
|
||||||
return;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
vbeGetPmodeInterface();
|
vbeGetPmodeInterface();
|
||||||
|
|
||||||
if ((vbeModeNumber = vbeSelectModeNumber(width, height, depth)) == 0) {
|
if ((vbeModeNumber = vbeSelectModeNumber(width, height, depth)) == 0) {
|
||||||
//logWrite("No appropriate video mode available.\n");
|
logWrite("No appropriate video mode available.\n");
|
||||||
//vbeShutdown();
|
platformShutdown();
|
||||||
return;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vbeSetMode(vbeModeNumber) == NULL) {
|
if (vbeSetMode(vbeModeNumber) == NULL) {
|
||||||
//vbeShutdown();
|
platformShutdown();
|
||||||
return;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_vbeSurface.bitsPerPixel == 8) videoSurfacePixelSet = videoSurfacePixelSet8;
|
if (_vbeSurface.bitsPerPixel == 8) videoSurfacePixelSet = videoSurfacePixelSet8;
|
||||||
|
@ -225,6 +375,12 @@ void platformStartup(int16_t width, int16_t height, int16_t depth) {
|
||||||
if (_vbeSurface.bitsPerPixel == 15) videoSurfacePixelSet = videoSurfacePixelSet16;
|
if (_vbeSurface.bitsPerPixel == 15) videoSurfacePixelSet = videoSurfacePixelSet16;
|
||||||
if (_vbeSurface.bitsPerPixel == 32) videoSurfacePixelSet = videoSurfacePixelSet32;
|
if (_vbeSurface.bitsPerPixel == 32) videoSurfacePixelSet = videoSurfacePixelSet32;
|
||||||
|
|
||||||
|
__guiBaseColors = (ColorT *)malloc(sizeof(ColorT) * 16);
|
||||||
|
for (i=0; i<16; i++) {
|
||||||
|
__guiBaseColors[i] = videoColorMake(EGA[i][0], EGA[i][1], EGA[i][2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -414,6 +570,8 @@ static uint8_t vbeIsDesiredMode(void) {
|
||||||
if (((_vbeModeInfo.modeAttributes) & (1<<7)) >> 7) {
|
if (((_vbeModeInfo.modeAttributes) & (1<<7)) >> 7) {
|
||||||
// Packed or Direct Color mode.
|
// Packed or Direct Color mode.
|
||||||
if (_vbeModeInfo.memoryModel == VBE_MM_PACKED || _vbeModeInfo.memoryModel == VBE_MM_DCOLOR) {
|
if (_vbeModeInfo.memoryModel == VBE_MM_PACKED || _vbeModeInfo.memoryModel == VBE_MM_DCOLOR) {
|
||||||
|
// We only handle these bit depths.
|
||||||
|
if ((_vbeModeInfo.bitsPerPixel == 8) || (_vbeModeInfo.bitsPerPixel == 15) || (_vbeModeInfo.bitsPerPixel == 16) || (_vbeModeInfo.bitsPerPixel == 32)) {
|
||||||
// Resolution minimum of 640x480.
|
// Resolution minimum of 640x480.
|
||||||
if (_vbeModeInfo.xResolution >= 640 && _vbeModeInfo.yResolution >= 480) {
|
if (_vbeModeInfo.xResolution >= 640 && _vbeModeInfo.yResolution >= 480) {
|
||||||
// Multiple of 8
|
// Multiple of 8
|
||||||
|
@ -424,6 +582,7 @@ static uint8_t vbeIsDesiredMode(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Rejected!
|
// Rejected!
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -568,7 +727,61 @@ uint16_t videoDisplayWidthGet(void) {
|
||||||
|
|
||||||
|
|
||||||
void videoModesShow(void) {
|
void videoModesShow(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) {
|
||||||
|
logWrite("No VESA BIOS Extensions found.\n");
|
||||||
|
platformShutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logWrite(
|
||||||
|
"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) {
|
||||||
|
logWrite(
|
||||||
|
"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 {
|
||||||
|
logWrite("VESA BIOS Extension 2.0 or better required!\n");
|
||||||
|
platformShutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (counter=0; ; counter++) {
|
||||||
|
if (_vbeInfo.videoModePtr[counter] == 0xFFFF) break;
|
||||||
|
vbeGetModeInfo(_vbeInfo.videoModePtr[counter]);
|
||||||
|
if (vbeIsDesiredMode()) {
|
||||||
|
logWrite("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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
platformShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
|
|
||||||
void platformShutdown(void);
|
void platformShutdown(void);
|
||||||
void platformStartup(int16_t width, int16_t height, int16_t depth);
|
uint8_t platformStartup(int16_t width, int16_t height, int16_t depth);
|
||||||
|
|
||||||
void videoModesShow(void);
|
void videoModesShow(void);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
#include "thirdparty/stb_ds.h"
|
#include "thirdparty/stb_ds.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
93
shared/log.c
Normal file
93
shared/log.c
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
// ***TODO*** On DOS, open and close the log on every write so the file gets updated and we still have data on a crash.
|
||||||
|
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
|
||||||
|
static FILE *_log = NULL;
|
||||||
|
static uint8_t _ourHandle = 0;
|
||||||
|
static char *_logBuffer = NULL;
|
||||||
|
static uint16_t _logBufferSize = 0;
|
||||||
|
static logCallback _logCallback = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void logCallbackSet(logCallback callback) {
|
||||||
|
_logCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void logClose(void) {
|
||||||
|
if (_log && _ourHandle) {
|
||||||
|
fclose(_log);
|
||||||
|
_ourHandle = 0;
|
||||||
|
}
|
||||||
|
DEL(_logBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t logOpen(char *filename, uint8_t append) {
|
||||||
|
_log = fopen(filename, append ? "a" : "w");
|
||||||
|
if (_log) {
|
||||||
|
_ourHandle = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void logOpenByHandle(FILE *handle) {
|
||||||
|
_log = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void logWrite(char *format, ...) {
|
||||||
|
va_list args = { 0 };
|
||||||
|
va_list args2 = { 0 };
|
||||||
|
uint16_t length = 0;
|
||||||
|
|
||||||
|
if (_log) {
|
||||||
|
va_start(args, format);
|
||||||
|
va_copy(args2, args);
|
||||||
|
|
||||||
|
// Attempt to write into current log buffer.
|
||||||
|
length = vsnprintf(_logBuffer, _logBufferSize, format, args);
|
||||||
|
|
||||||
|
// Did it fit?
|
||||||
|
if (length >= _logBufferSize) {
|
||||||
|
// Nope. Resize buffer to fit plus a bit more.
|
||||||
|
if (_logBuffer) free(_logBuffer);
|
||||||
|
_logBufferSize = length + 32;
|
||||||
|
_logBuffer = (char *)malloc(_logBufferSize);
|
||||||
|
// Do it again.
|
||||||
|
vsnprintf(_logBuffer, _logBufferSize, format, args2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//#ifdef __linux__
|
||||||
|
// Also output to stdout on Linux.
|
||||||
|
fprintf(stdout, "%s", _logBuffer);
|
||||||
|
fflush(stdout);
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
if (_logCallback) _logCallback(_logBuffer);
|
||||||
|
|
||||||
|
fprintf(_log, "%s", _logBuffer);
|
||||||
|
fflush(_log);
|
||||||
|
|
||||||
|
va_end(args2);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void logWriteToFileOnly(char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
if (_log) {
|
||||||
|
vfprintf(_log, format, args);
|
||||||
|
fflush(_log);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
19
shared/log.h
Normal file
19
shared/log.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef LOG_H
|
||||||
|
#define LOG_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (*logCallback)(char *message);
|
||||||
|
|
||||||
|
|
||||||
|
void logCallbackSet(logCallback callback);
|
||||||
|
void logClose(void);
|
||||||
|
uint8_t logOpen(char *filename, uint8_t append);
|
||||||
|
void logOpenByHandle(FILE *handle);
|
||||||
|
void logWrite(char *format, ...);
|
||||||
|
void logWriteToFileOnly(char *format, ...);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // LOG_H
|
|
@ -12,6 +12,13 @@
|
||||||
#define DEL(v) {if(v) {free(v); v=NULL;}}
|
#define DEL(v) {if(v) {free(v); v=NULL;}}
|
||||||
|
|
||||||
|
|
||||||
|
// Some helper defines.
|
||||||
|
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))
|
||||||
|
#define HIGH_BYTE(b) ((uint8_t)(((b) & 0xFF00) >> 8))
|
||||||
|
#define LOW_BYTE(b) ((uint8_t)((b) & 0x00FF))
|
||||||
|
|
||||||
|
|
||||||
|
// Return codes.
|
||||||
#define SUCCESS 0
|
#define SUCCESS 0
|
||||||
#define FAIL 1
|
#define FAIL 1
|
||||||
|
|
||||||
|
|
|
@ -1 +1,51 @@
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
|
||||||
|
FILE *_memoryLog = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MEMORY_CHECK_ENABLED
|
||||||
|
void mwLogW(FILE *p);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
FILE *memoryLogHandleGet(void) {
|
||||||
|
return _memoryLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MEMORY_CHECK_ENABLED
|
||||||
|
void memoryOutput(int c) {
|
||||||
|
fputc(c, _memoryLog);
|
||||||
|
fflush(_memoryLog);
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
// Also output to stdout on Linux.
|
||||||
|
fputc(c, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void memoryShutdown(void) {
|
||||||
|
#ifdef MEMORY_CHECK_ENABLED
|
||||||
|
unlink("memwatch.log"); // It just insists on creating this!
|
||||||
|
mwTerm();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void memoryStartup(char *appName) {
|
||||||
|
char *logName = utilAppNameWithNewExtensionGet(appName, "log");
|
||||||
|
|
||||||
|
_memoryLog = fopen(logName, "w");
|
||||||
|
|
||||||
|
#ifdef MEMORY_CHECK_ENABLED
|
||||||
|
mwLogW(_memoryLog);
|
||||||
|
mwSetOutFunc(memoryOutput);
|
||||||
|
mwInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free(logName);
|
||||||
|
}
|
||||||
|
|
|
@ -4,10 +4,16 @@
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef MEMORY_CHECK_ENABLED
|
#ifdef MEMORY_CHECK_ENABLED
|
||||||
#define MEMWATCH
|
#define MEMWATCH
|
||||||
#include "thirdparty/memwatch/memwatch.h"
|
#include "thirdparty/memwatch/memwatch.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
FILE *memoryLogHandleGet(void);
|
||||||
|
void memoryShutdown(void);
|
||||||
|
void memoryStartup(char *appName);
|
||||||
|
|
||||||
|
|
||||||
#endif // MEMORY_H
|
#endif // MEMORY_H
|
||||||
|
|
181
shared/util.c
Normal file
181
shared/util.c
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
char __scratch[SCRATCH_SIZE];
|
||||||
|
|
||||||
|
|
||||||
|
char *utilAppNameWithNewExtensionGet(char *appName, char *extension) {
|
||||||
|
char *c = NULL;
|
||||||
|
char *newName = NULL;
|
||||||
|
int16_t x = strlen(appName);
|
||||||
|
uint16_t len = 2 + strlen(extension); // 2 = dot in extension and 0 terminator.
|
||||||
|
|
||||||
|
// Find last portion of filename.
|
||||||
|
while (x > 0) {
|
||||||
|
if (appName[x] == '/' || appName[x] == '\\') break;
|
||||||
|
x--;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use this + length of new extension for new string length.
|
||||||
|
newName = (char *)malloc(len);
|
||||||
|
if (newName) {
|
||||||
|
if (strlen(appName) - x < len) {
|
||||||
|
// Replace extension
|
||||||
|
strncpy(newName, &appName[x + 1], len - 1);
|
||||||
|
c = strstr(newName, ".");
|
||||||
|
if (c) *c = 0;
|
||||||
|
strncat(newName, ".", len - 1);
|
||||||
|
strncat(newName, extension, len - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void utilBitsPrint(uint8_t byte) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (i = 7; 0 <= i; i--) {
|
||||||
|
printf("%c", (byte & (1 << i)) ? '1' : '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *utilCreateString(char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
char *string;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
string = utilCreateStringVArgs(format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__((__format__(__printf__, 1, 0)))
|
||||||
|
char *utilCreateStringVArgs(char *format, va_list args) {
|
||||||
|
va_list argsCopy;
|
||||||
|
int32_t size = 0;
|
||||||
|
char *buffer = NULL;
|
||||||
|
|
||||||
|
va_copy(argsCopy, args);
|
||||||
|
size = vsnprintf(NULL, 0, format, argsCopy) + 1;
|
||||||
|
va_end(argsCopy);
|
||||||
|
buffer = calloc(1, (size_t)size);
|
||||||
|
if (buffer) {
|
||||||
|
vsnprintf(buffer, (size_t)size, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void utilDie(const char *why, ...) {
|
||||||
|
va_list args;
|
||||||
|
char msg[2048];
|
||||||
|
|
||||||
|
va_start(args, why);
|
||||||
|
vsprintf(msg, why, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
logWrite("DIE: %s", msg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t utilFileExists(char *filename) {
|
||||||
|
FILE *f = fopen(filename, "rb");
|
||||||
|
|
||||||
|
if (f) {
|
||||||
|
fclose(f);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t utilFromFileReadByte(FILE *f, uint8_t *result) {
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
|
// Get next byte.
|
||||||
|
c = fgetc(f);
|
||||||
|
// End of file?
|
||||||
|
if (feof(f)) return FAIL;
|
||||||
|
// Add to result.
|
||||||
|
*result = c;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t utilFromFileReadString(FILE *f, char **result) {
|
||||||
|
unsigned char c;
|
||||||
|
uint16_t x = 0;
|
||||||
|
|
||||||
|
// Something already in 'result'?
|
||||||
|
DEL(*result);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// Get next byte.
|
||||||
|
c = fgetc(f);
|
||||||
|
// End of file?
|
||||||
|
if (feof(f)) return FAIL;
|
||||||
|
// Add to result.
|
||||||
|
__scratch[x++] = c;
|
||||||
|
__scratch[x] = 0;
|
||||||
|
// End of string?
|
||||||
|
if (c == 0) {
|
||||||
|
*result = strdup(__scratch);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void utilStringToLower(char *string) {
|
||||||
|
uint16_t i;
|
||||||
|
|
||||||
|
for (i=0; i<strlen(string); i++) string[i] = tolower(string[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char **utilWrapText(char *text, uint16_t width) {
|
||||||
|
char **lines = NULL;
|
||||||
|
char *head = text;
|
||||||
|
char *buffer = NULL;
|
||||||
|
int32_t bufferPos;
|
||||||
|
int32_t pos;
|
||||||
|
int32_t lastSpace;
|
||||||
|
int32_t isLf;
|
||||||
|
|
||||||
|
buffer = (char *)malloc(width + 2);
|
||||||
|
if (buffer) {
|
||||||
|
pos = lastSpace = bufferPos = 0;
|
||||||
|
while (head[pos] != 0) {
|
||||||
|
isLf = (head[pos] == '\n');
|
||||||
|
if (isLf || pos == width) {
|
||||||
|
if (isLf || lastSpace == 0) lastSpace = pos; // just cut it
|
||||||
|
while (*head!=0 && lastSpace-- > 0) {
|
||||||
|
buffer[bufferPos++] = *head++;
|
||||||
|
buffer[bufferPos] = 0;
|
||||||
|
}
|
||||||
|
arrput(lines, strdup(buffer));
|
||||||
|
if (isLf) head++; // jump the line feed
|
||||||
|
while (*head!=0 && *head==' ') head++; // clear the leading space
|
||||||
|
lastSpace = pos = bufferPos = 0;
|
||||||
|
} else {
|
||||||
|
if (head[pos] == ' ') lastSpace = pos;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arrput(lines, strdup(head));
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
26
shared/util.h
Normal file
26
shared/util.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef UTIL_H
|
||||||
|
#define UTIL_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define SCRATCH_SIZE 4096
|
||||||
|
|
||||||
|
|
||||||
|
extern char __scratch[SCRATCH_SIZE];
|
||||||
|
|
||||||
|
|
||||||
|
char *utilAppNameWithNewExtensionGet(char *appName, char *extension);
|
||||||
|
void utilBitsPrint(uint8_t byte);
|
||||||
|
char *utilCreateString(char *format, ...);
|
||||||
|
char *utilCreateStringVArgs(char *format, va_list args);
|
||||||
|
void utilDie(const char *why, ...);
|
||||||
|
uint8_t utilFileExists(char *filename);
|
||||||
|
uint8_t utilFromFileReadByte(FILE *f, uint8_t *result);
|
||||||
|
uint8_t utilFromFileReadString(FILE *f, char **result);
|
||||||
|
void utilStringToLower(char *string);
|
||||||
|
char **utilWrapText(char *text, uint16_t width);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // UTIL_H
|
Loading…
Add table
Reference in a new issue