mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-12 09:06:55 -04:00
Sort of get terminal backend to work on windows
This commit is contained in:
parent
8630a87cc7
commit
079e83dae6
18
.github/workflows/build_windows.yml
vendored
18
.github/workflows/build_windows.yml
vendored
@ -25,19 +25,19 @@ jobs:
|
||||
id: compile
|
||||
env:
|
||||
COMMON_FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn"
|
||||
WIN32_FLAGS: "-mwindows -nostartfiles -Wl,-e_main_real -DCC_NOMAIN"
|
||||
WIN32_FLAGS: "-mwindows -nostartfiles -Wl,-e_main_real -DCC_NOMAIN CCicon_32.res"
|
||||
run: |
|
||||
sudo apt-get -y install gcc-mingw-w64-i686
|
||||
LATEST_FLAG=-DCC_COMMIT_SHA=\"$(git rev-parse --short "$GITHUB_SHA")\"
|
||||
|
||||
cp misc/windows/CCicon_32.res src/CCicon_32.res
|
||||
cd src
|
||||
i686-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -o cc-w32-d3d9.exe CCicon_32.res $LATEST_FLAG -lwinmm -limagehlp
|
||||
i686-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -o cc-w32-ogl.exe CCicon_32.res $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL -lwinmm -limagehlp -lopengl32
|
||||
i686-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -o cc-w32-d3d11.exe CCicon_32.res $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_D3D11 -lwinmm -limagehlp
|
||||
i686-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -o cc-w32-d3d9.exe $LATEST_FLAG -lwinmm -limagehlp
|
||||
i686-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -o cc-w32-ogl.exe $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL -lwinmm -limagehlp -lopengl32
|
||||
i686-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -o cc-w32-d3d11.exe $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_D3D11 -lwinmm -limagehlp
|
||||
|
||||
# mingw defaults to i686, but some really old CPUs only support i586
|
||||
i686-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -march=i586 -o cc-w9x-ogl.exe CCicon_32.res $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL -lwinmm -limagehlp -lopengl32
|
||||
i686-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -march=i586 -o cc-w9x-ogl.exe $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL -lwinmm -limagehlp -lopengl32
|
||||
|
||||
|
||||
- uses: ./.github/actions/notify_failure
|
||||
@ -91,16 +91,16 @@ jobs:
|
||||
id: compile
|
||||
env:
|
||||
COMMON_FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn"
|
||||
WIN64_FLAGS: "-mwindows -nostartfiles -Wl,-emain_real -DCC_NOMAIN"
|
||||
WIN64_FLAGS: "-mwindows -nostartfiles -Wl,-emain_real -DCC_NOMAIN CCicon_64.res"
|
||||
run: |
|
||||
sudo apt-get -y install gcc-mingw-w64-x86-64
|
||||
LATEST_FLAG=-DCC_COMMIT_SHA=\"$(git rev-parse --short "$GITHUB_SHA")\"
|
||||
|
||||
cp misc/windows/CCicon_64.res src/CCicon_64.res
|
||||
cd src
|
||||
x86_64-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN64_FLAGS }} -o cc-w64-d3d9.exe CCicon_64.res $LATEST_FLAG -lwinmm -limagehlp
|
||||
x86_64-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN64_FLAGS }} -o cc-w64-ogl.exe CCicon_64.res $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_D3D11 -lwinmm -limagehlp -lopengl32
|
||||
x86_64-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN64_FLAGS }} -o cc-w64-d3d11.exe CCicon_64.res $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL -lwinmm -limagehlp
|
||||
x86_64-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN64_FLAGS }} -o cc-w64-d3d9.exe $LATEST_FLAG -lwinmm -limagehlp
|
||||
x86_64-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN64_FLAGS }} -o cc-w64-ogl.exe $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL -lwinmm -limagehlp -lopengl32
|
||||
x86_64-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN64_FLAGS }} -o cc-w64-d3d11.exe $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_D3D11 -lwinmm -limagehlp
|
||||
|
||||
|
||||
- uses: ./.github/actions/notify_failure
|
||||
|
@ -12,26 +12,81 @@
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef CC_BUILD_WIN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <termios.h>
|
||||
#include <poll.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef CC_BUILD_LINUX
|
||||
#include <sys/kd.h>
|
||||
#include <linux/keyboard.h>
|
||||
#endif
|
||||
|
||||
static cc_bool pendingResize, pendingClose;
|
||||
#define CSI "\x1B["
|
||||
|
||||
#define ERASE_CMD(cmd) CSI cmd "J"
|
||||
#define DEC_PM_SET(cmd) CSI "?" cmd "h"
|
||||
#define DEC_PM_RESET(cmd) CSI "?" cmd "1"
|
||||
|
||||
#ifdef CC_BUILD_WIN
|
||||
static HANDLE hStdin, hStdout;
|
||||
static DWORD fdwSaveOldMode;
|
||||
|
||||
static void UpdateDimensions(void) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi = { 0 };
|
||||
int cols, rows;
|
||||
|
||||
GetConsoleScreenBufferInfo(hStdout, &csbi);
|
||||
cols = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||
rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
||||
|
||||
DisplayInfo.Width = cols;
|
||||
DisplayInfo.Height = rows * 2;
|
||||
Window_Main.Width = DisplayInfo.Width;
|
||||
Window_Main.Height = DisplayInfo.Height;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||
#endif
|
||||
|
||||
static void HookTerminal(void) {
|
||||
hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
GetConsoleMode(hStdin, &fdwSaveOldMode);
|
||||
|
||||
DWORD mode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT;
|
||||
SetConsoleMode(hStdin, mode);
|
||||
}
|
||||
|
||||
static void UnhookTerminal(void) {
|
||||
SetConsoleMode(hStdin, fdwSaveOldMode);
|
||||
}
|
||||
|
||||
static BOOL WINAPI consoleHandler(DWORD signal) {
|
||||
if (signal == CTRL_C_EVENT) pendingClose = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void sigterm_handler(int sig) { pendingClose = true; UnhookTerminal(); }
|
||||
|
||||
static void HookSignals(void) {
|
||||
SetConsoleCtrlHandler(consoleHandler, TRUE);
|
||||
|
||||
signal(SIGTERM, sigterm_handler);
|
||||
signal(SIGINT, sigterm_handler);
|
||||
}
|
||||
#else
|
||||
// Inspired from https://github.com/Cubified/tuibox/blob/main/tuibox.h#L606
|
||||
// Uses '▄' to double the vertical resolution
|
||||
// (this trick was inspired from https://github.com/ichinaski/pxl/blob/master/main.go#L30)
|
||||
static struct termios tio;
|
||||
static struct winsize ws;
|
||||
|
||||
#define CSI "\x1B["
|
||||
|
||||
#define ERASE_CMD(cmd) CSI cmd "J"
|
||||
#define DEC_PM_SET(cmd) CSI "?" cmd "h"
|
||||
#define DEC_PM_RESET(cmd) CSI "?" cmd "1"
|
||||
|
||||
#ifdef CC_BUILD_LINUX
|
||||
static int orig_KB = K_XLATE;
|
||||
#endif
|
||||
@ -41,10 +96,6 @@ static void UpdateDimensions(void) {
|
||||
|
||||
DisplayInfo.Width = ws.ws_col;
|
||||
DisplayInfo.Height = ws.ws_row * 2;
|
||||
DisplayInfo.Depth = 4;
|
||||
DisplayInfo.ScaleX = 0.5f;
|
||||
DisplayInfo.ScaleY = 0.5f;
|
||||
|
||||
Window_Main.Width = DisplayInfo.Width;
|
||||
Window_Main.Height = DisplayInfo.Height;
|
||||
}
|
||||
@ -80,23 +131,28 @@ static void UnhookTerminal(void) {
|
||||
printf(DEC_PM_SET("25"));
|
||||
}
|
||||
|
||||
static cc_bool pendingResize, pendingClose;
|
||||
static void sigwinch_handler(int sig) { pendingResize = true; }
|
||||
static void sigterm_handler(int sig) { pendingClose = true; UnhookTerminal(); }
|
||||
|
||||
void Window_Init(void) {
|
||||
Input.Sources = INPUT_SOURCE_NORMAL;
|
||||
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
|
||||
//ioctl(STDIN_FILENO , KDGKBMODE, &orig_KB);
|
||||
//ioctl(STDIN_FILENO, KDSKBMODE, K_MEDIUMRAW);
|
||||
HookTerminal();
|
||||
|
||||
UpdateDimensions();
|
||||
static void HookSignals(void) {
|
||||
signal(SIGWINCH, sigwinch_handler);
|
||||
signal(SIGTERM, sigterm_handler);
|
||||
signal(SIGINT, sigterm_handler);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Window_Init(void) {
|
||||
Input.Sources = INPUT_SOURCE_NORMAL;
|
||||
DisplayInfo.Depth = 4;
|
||||
DisplayInfo.ScaleX = 0.5f;
|
||||
DisplayInfo.ScaleY = 0.5f;
|
||||
|
||||
//ioctl(STDIN_FILENO , KDGKBMODE, &orig_KB);
|
||||
//ioctl(STDIN_FILENO, KDSKBMODE, K_MEDIUMRAW);
|
||||
HookTerminal();
|
||||
UpdateDimensions();
|
||||
HookSignals();
|
||||
}
|
||||
|
||||
void Window_Free(void) {
|
||||
UnhookTerminal();
|
||||
@ -145,6 +201,75 @@ void Window_RequestClose(void) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#ifdef CC_BUILD_WIN
|
||||
static void KeyEventProc(KEY_EVENT_RECORD ker)
|
||||
{
|
||||
printf("Key event: ");
|
||||
|
||||
if(ker.bKeyDown)
|
||||
printf("key pressed\n");
|
||||
else
|
||||
printf("key released\n");
|
||||
}
|
||||
|
||||
static VOID MouseEventProc(MOUSE_EVENT_RECORD mer) {
|
||||
switch(mer.dwEventFlags)
|
||||
{
|
||||
case 0:
|
||||
if(mer.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
|
||||
{
|
||||
printf("left button press \n");
|
||||
}
|
||||
else if(mer.dwButtonState == RIGHTMOST_BUTTON_PRESSED)
|
||||
{
|
||||
printf("right button press \n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("button press\n");
|
||||
}
|
||||
break;
|
||||
case DOUBLE_CLICK:
|
||||
printf("double click\n");
|
||||
break;
|
||||
case MOUSE_MOVED:
|
||||
printf("mouse moved\n");
|
||||
break;
|
||||
case MOUSE_WHEELED:
|
||||
printf("vertical mouse wheel\n");
|
||||
break;
|
||||
default:
|
||||
printf("unknown\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessConsoleEvents(float delta) {
|
||||
DWORD events = 0;
|
||||
GetNumberOfConsoleInputEvents(hStdin, &events);
|
||||
if (!events) return;
|
||||
|
||||
INPUT_RECORD buffer[128];
|
||||
if (!ReadConsoleInput(hStdin, buffer, 128, &events)) return;
|
||||
|
||||
for (int i = 0; i < events; i++)
|
||||
{
|
||||
switch (buffer[i].EventType)
|
||||
{
|
||||
case KEY_EVENT:
|
||||
KeyEventProc(buffer[i].Event.KeyEvent);
|
||||
break;
|
||||
case MOUSE_EVENT:
|
||||
MouseEventProc(buffer[i].Event.MouseEvent);
|
||||
break;
|
||||
case WINDOW_BUFFER_SIZE_EVENT:
|
||||
pendingResize = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static int MapNativeMouse(int button) {
|
||||
if (button == 1) return CCMOUSE_L;
|
||||
if (button == 2) return CCMOUSE_M;
|
||||
@ -164,14 +289,14 @@ static int MapNativeMouse(int button) {
|
||||
}
|
||||
|
||||
static int stdin_available(void) {
|
||||
struct pollfd pfd;
|
||||
pfd.fd = STDIN_FILENO;
|
||||
pfd.events = POLLIN;
|
||||
struct pollfd pfd;
|
||||
pfd.fd = STDIN_FILENO;
|
||||
pfd.events = POLLIN;
|
||||
|
||||
if (poll(&pfd, 1, 0)) {
|
||||
if (poll(&pfd, 1, 0)) {
|
||||
if (pfd.revents & POLLIN) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ExtractXY() \
|
||||
@ -181,13 +306,13 @@ static int stdin_available(void) {
|
||||
y = atoi(tok) * 2;
|
||||
|
||||
static void ProcessMouse(char* buf, int n) {
|
||||
char cpy[256+2];
|
||||
char cpy[256 + 2];
|
||||
strncpy(cpy, buf, n);
|
||||
char* tok = strtok(cpy + 3, ";");
|
||||
int x, y, mouse;
|
||||
if (!tok) return;
|
||||
|
||||
switch (tok[0]){
|
||||
switch (tok[0]){
|
||||
case '0':
|
||||
mouse = strchr(buf, 'm') == NULL;
|
||||
ExtractXY();
|
||||
@ -199,25 +324,61 @@ static void ProcessMouse(char* buf, int n) {
|
||||
ExtractXY();
|
||||
Pointer_SetPosition(0, x, y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessKey(int key) {
|
||||
if (key >= 'a' && key <= 'z') key -= 32;
|
||||
|
||||
if (key >= 'A' && key <= 'Z') {
|
||||
Input_SetPressed(key);
|
||||
// Input_SetReleased(key);
|
||||
} else if (key == ' ') {
|
||||
Input_SetPressed(CCKEY_SPACE);
|
||||
Input_SetReleased(CCKEY_SPACE);
|
||||
}
|
||||
}
|
||||
|
||||
void Window_ProcessEvents(float delta) {
|
||||
static int MapKey(int key) {
|
||||
if (key == ' ') return CCKEY_SPACE;
|
||||
|
||||
if (key >= 'a' && key <= 'z') key -= 32;
|
||||
if (key >= 'A' && key <= 'Z') return key;
|
||||
|
||||
Platform_Log1("Unknown key: %i", &key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static float event_time;
|
||||
static float press_start[256];
|
||||
static void ProcessKey(int raw) {
|
||||
int key = MapKey(raw);
|
||||
if (key) {
|
||||
Input_SetPressed(key);
|
||||
press_start[raw] = event_time;
|
||||
}
|
||||
|
||||
if (raw >= 32 && raw < 127) {
|
||||
Event_RaiseInt(&InputEvents.Press, raw);
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessConsoleEvents(float delta) {
|
||||
char buf[256];
|
||||
int n;
|
||||
|
||||
if (!stdin_available()) return;
|
||||
n = read(STDIN_FILENO, buf, sizeof(buf));
|
||||
int A = buf[0];
|
||||
//Platform_Log2("IN: %i, %i", &n, &A);
|
||||
|
||||
if (n >= 4 && buf[0] == '\x1b' && buf[1] == '[' && buf[2] == '<') {
|
||||
ProcessMouse(buf, n);
|
||||
} else if (buf[0] >= 32 && buf[0] < 127) {
|
||||
ProcessKey(buf[0]);
|
||||
}
|
||||
|
||||
event_time += delta;
|
||||
// Auto release keys after a while
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
if (press_start[i] && (event_time - press_start[i]) > 1.0f) {
|
||||
Input_SetReleased(MapKey(i));
|
||||
press_start[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Window_ProcessEvents(float delta) {
|
||||
if (pendingResize) {
|
||||
pendingResize = false;
|
||||
UpdateDimensions();
|
||||
@ -231,17 +392,7 @@ void Window_ProcessEvents(float delta) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!stdin_available()) return;
|
||||
n = read(STDIN_FILENO, buf, sizeof(buf));
|
||||
int A = buf[0];
|
||||
//Platform_Log2("IN: %i, %i", &n, &A);
|
||||
|
||||
if (n >= 4 && buf[0] == '\x1b' && buf[1] == '[' && buf[2] == '<') {
|
||||
ProcessMouse(buf, n);
|
||||
} else if (buf[0] >= 32 && buf[0] < 127) {
|
||||
ProcessKey(buf[0]);
|
||||
}
|
||||
// TODO
|
||||
ProcessConsoleEvents(delta);
|
||||
}
|
||||
|
||||
void Window_ProcessGamepads(float delta) { }
|
||||
@ -281,16 +432,22 @@ void Window_AllocFramebuffer(struct Bitmap* bmp) {
|
||||
|
||||
void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) {
|
||||
for (int y = r.y & ~0x01; y < r.y + r.height; y += 2)
|
||||
for (int x = r.x; x < r.x + r.width; x++)
|
||||
{
|
||||
BitmapCol top = Bitmap_GetPixel(bmp, x, y + 0);
|
||||
BitmapCol bot = Bitmap_GetPixel(bmp, x, y + 1);
|
||||
printf(CSI "%i;%iH", y / 2, r.x); // move cursor to start
|
||||
for (int x = r.x; x < r.x + r.width; x++)
|
||||
{
|
||||
BitmapCol top = Bitmap_GetPixel(bmp, x, y + 0);
|
||||
BitmapCol bot = Bitmap_GetPixel(bmp, x, y + 1);
|
||||
|
||||
// Use '▄' so each cell can use a background and foreground colour
|
||||
// This essentially doubles the vertical resolution of the displayed image
|
||||
printf(CSI "48;2;%i;%i;%im", BitmapCol_R(top), BitmapCol_G(top), BitmapCol_B(top));
|
||||
printf(CSI "38;2;%i;%i;%im", BitmapCol_R(bot), BitmapCol_G(bot), BitmapCol_B(bot));
|
||||
printf(CSI "%i;%iH\xE2\x96\x84", y / 2, x);
|
||||
// Use '▄' so each cell can use a background and foreground colour
|
||||
// This essentially doubles the vertical resolution of the displayed image
|
||||
//printf(CSI "48;2;%i;%i;%im", BitmapCol_R(top), BitmapCol_G(top), BitmapCol_B(top));
|
||||
//printf(CSI "38;2;%i;%i;%im", BitmapCol_R(bot), BitmapCol_G(bot), BitmapCol_B(bot));
|
||||
//printf("\xE2\x96\x84");
|
||||
printf(CSI "48;2;%i;%i;%im" CSI "38;2;%i;%i;%im" "\xE2\x96\x84",
|
||||
BitmapCol_R(top), BitmapCol_G(top), BitmapCol_B(top),
|
||||
BitmapCol_R(bot), BitmapCol_G(bot), BitmapCol_B(bot));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user