Sort of get terminal backend to work on windows

This commit is contained in:
UnknownShadow200 2024-05-22 21:39:43 +10:00
parent 8630a87cc7
commit 079e83dae6
2 changed files with 228 additions and 71 deletions

View File

@ -25,19 +25,19 @@ jobs:
id: compile id: compile
env: env:
COMMON_FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn" 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: | run: |
sudo apt-get -y install gcc-mingw-w64-i686 sudo apt-get -y install gcc-mingw-w64-i686
LATEST_FLAG=-DCC_COMMIT_SHA=\"$(git rev-parse --short "$GITHUB_SHA")\" LATEST_FLAG=-DCC_COMMIT_SHA=\"$(git rev-parse --short "$GITHUB_SHA")\"
cp misc/windows/CCicon_32.res src/CCicon_32.res cp misc/windows/CCicon_32.res src/CCicon_32.res
cd src 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-d3d9.exe $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-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 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-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 # 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 - uses: ./.github/actions/notify_failure
@ -91,16 +91,16 @@ jobs:
id: compile id: compile
env: env:
COMMON_FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn" 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: | run: |
sudo apt-get -y install gcc-mingw-w64-x86-64 sudo apt-get -y install gcc-mingw-w64-x86-64
LATEST_FLAG=-DCC_COMMIT_SHA=\"$(git rev-parse --short "$GITHUB_SHA")\" LATEST_FLAG=-DCC_COMMIT_SHA=\"$(git rev-parse --short "$GITHUB_SHA")\"
cp misc/windows/CCicon_64.res src/CCicon_64.res cp misc/windows/CCicon_64.res src/CCicon_64.res
cd src 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-d3d9.exe $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-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 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-d3d11.exe $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_D3D11 -lwinmm -limagehlp
- uses: ./.github/actions/notify_failure - uses: ./.github/actions/notify_failure

View File

@ -12,26 +12,81 @@
#include <signal.h> #include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef CC_BUILD_WIN
#include <windows.h>
#else
#include <termios.h> #include <termios.h>
#include <poll.h> #include <poll.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#endif
#ifdef CC_BUILD_LINUX #ifdef CC_BUILD_LINUX
#include <sys/kd.h> #include <sys/kd.h>
#include <linux/keyboard.h> #include <linux/keyboard.h>
#endif #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 // Inspired from https://github.com/Cubified/tuibox/blob/main/tuibox.h#L606
// Uses '▄' to double the vertical resolution // Uses '▄' to double the vertical resolution
// (this trick was inspired from https://github.com/ichinaski/pxl/blob/master/main.go#L30) // (this trick was inspired from https://github.com/ichinaski/pxl/blob/master/main.go#L30)
static struct termios tio; static struct termios tio;
static struct winsize ws; 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 #ifdef CC_BUILD_LINUX
static int orig_KB = K_XLATE; static int orig_KB = K_XLATE;
#endif #endif
@ -41,10 +96,6 @@ static void UpdateDimensions(void) {
DisplayInfo.Width = ws.ws_col; DisplayInfo.Width = ws.ws_col;
DisplayInfo.Height = ws.ws_row * 2; DisplayInfo.Height = ws.ws_row * 2;
DisplayInfo.Depth = 4;
DisplayInfo.ScaleX = 0.5f;
DisplayInfo.ScaleY = 0.5f;
Window_Main.Width = DisplayInfo.Width; Window_Main.Width = DisplayInfo.Width;
Window_Main.Height = DisplayInfo.Height; Window_Main.Height = DisplayInfo.Height;
} }
@ -80,23 +131,28 @@ static void UnhookTerminal(void) {
printf(DEC_PM_SET("25")); printf(DEC_PM_SET("25"));
} }
static cc_bool pendingResize, pendingClose;
static void sigwinch_handler(int sig) { pendingResize = true; } static void sigwinch_handler(int sig) { pendingResize = true; }
static void sigterm_handler(int sig) { pendingClose = true; UnhookTerminal(); } static void sigterm_handler(int sig) { pendingClose = true; UnhookTerminal(); }
void Window_Init(void) { static void HookSignals(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();
signal(SIGWINCH, sigwinch_handler); signal(SIGWINCH, sigwinch_handler);
signal(SIGTERM, sigterm_handler); signal(SIGTERM, sigterm_handler);
signal(SIGINT, 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) { void Window_Free(void) {
UnhookTerminal(); UnhookTerminal();
@ -145,6 +201,75 @@ void Window_RequestClose(void) {
// TODO // 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) { static int MapNativeMouse(int button) {
if (button == 1) return CCMOUSE_L; if (button == 1) return CCMOUSE_L;
if (button == 2) return CCMOUSE_M; if (button == 2) return CCMOUSE_M;
@ -164,14 +289,14 @@ static int MapNativeMouse(int button) {
} }
static int stdin_available(void) { static int stdin_available(void) {
struct pollfd pfd; struct pollfd pfd;
pfd.fd = STDIN_FILENO; pfd.fd = STDIN_FILENO;
pfd.events = POLLIN; pfd.events = POLLIN;
if (poll(&pfd, 1, 0)) { if (poll(&pfd, 1, 0)) {
if (pfd.revents & POLLIN) return 1; if (pfd.revents & POLLIN) return 1;
} }
return 0; return 0;
} }
#define ExtractXY() \ #define ExtractXY() \
@ -181,13 +306,13 @@ static int stdin_available(void) {
y = atoi(tok) * 2; y = atoi(tok) * 2;
static void ProcessMouse(char* buf, int n) { static void ProcessMouse(char* buf, int n) {
char cpy[256+2]; char cpy[256 + 2];
strncpy(cpy, buf, n); strncpy(cpy, buf, n);
char* tok = strtok(cpy + 3, ";"); char* tok = strtok(cpy + 3, ";");
int x, y, mouse; int x, y, mouse;
if (!tok) return; if (!tok) return;
switch (tok[0]){ switch (tok[0]){
case '0': case '0':
mouse = strchr(buf, 'm') == NULL; mouse = strchr(buf, 'm') == NULL;
ExtractXY(); ExtractXY();
@ -199,25 +324,61 @@ static void ProcessMouse(char* buf, int n) {
ExtractXY(); ExtractXY();
Pointer_SetPosition(0, x, y); Pointer_SetPosition(0, x, y);
break; 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]; char buf[256];
int n; 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) { if (pendingResize) {
pendingResize = false; pendingResize = false;
UpdateDimensions(); UpdateDimensions();
@ -231,17 +392,7 @@ void Window_ProcessEvents(float delta) {
return; return;
} }
if (!stdin_available()) return; ProcessConsoleEvents(delta);
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
} }
void Window_ProcessGamepads(float delta) { } void Window_ProcessGamepads(float delta) { }
@ -281,16 +432,22 @@ void Window_AllocFramebuffer(struct Bitmap* bmp) {
void Window_DrawFramebuffer(Rect2D r, 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 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); printf(CSI "%i;%iH", y / 2, r.x); // move cursor to start
BitmapCol bot = Bitmap_GetPixel(bmp, x, y + 1); for (int x = r.x; x < r.x + r.width; x++)
{
// Use '▄' so each cell can use a background and foreground colour BitmapCol top = Bitmap_GetPixel(bmp, x, y + 0);
// This essentially doubles the vertical resolution of the displayed image BitmapCol bot = Bitmap_GetPixel(bmp, x, y + 1);
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)); // Use '▄' so each cell can use a background and foreground colour
printf(CSI "%i;%iH\xE2\x96\x84", y / 2, x); // 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));
}
} }
} }