add doom, disable warnings as errors, massive speedups in the fat32 driver, HAL_KEYBOARD Poll now returns the key and added IsKeyDown used by GetAsyncKeyState, slight upgrade in hal_main drain and pray, more accurate QueryTicks and by that GetTickCount, add GetTickCount64, boot.ini now dictates what executable should init launch, not the kernel, LaunchUserProcess in kmain.c now takes an argument, rearrange syscall numbers, add SysKbIsKeyDown syscall, use include windows.h over manual definitions, add fictional win32 api ClearConsoleScreenBuffer and real FlushConsoleInputBuffer and a clear command to the shell, print exit codes as signed int, StretchDIBits now can stretch, runa.bat now gives 256 MB.
This commit is contained in:
1 parent
cdf7ed4cea
commit
0c7f461c6d
24 files changed
+50236
-1310
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
[kernel]
|
||||
debug = 1
|
||||
[init]
|
||||
commandline = init.exe
|
||||
commandline = shell.exe
|
||||
+48605
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,329 @@
|
||||
// doom.c — NT-Lite port of PureDOOM
|
||||
// Win32 personality carrying all the weight, just like the real ntoskrnl does.
|
||||
// Drop doom1.wad (or doom.wad) next to this binary on your FAT32 volume.
|
||||
|
||||
#include <windows.h>
|
||||
#define DOOM_IMPLEMENTATION
|
||||
#include "PureDOOM.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
int _fltused;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Globals
|
||||
// ---------------------------------------------------------------------------
|
||||
static HANDLE g_stdout;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// doom_print_fn
|
||||
// ---------------------------------------------------------------------------
|
||||
static void doom_print_wrapper(const char* msg)
|
||||
{
|
||||
UINT len = (UINT)strlen(msg);
|
||||
WriteConsoleA(g_stdout, msg, len, 0, 0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// doom_malloc_fn / doom_free_fn
|
||||
// Heap handle 0, same convention as video.c.
|
||||
// ---------------------------------------------------------------------------
|
||||
static void* doom_malloc_wrapper(int size)
|
||||
{
|
||||
return HeapAlloc(0, HEAP_ZERO_MEMORY, size);
|
||||
}
|
||||
|
||||
static void doom_free_wrapper(void* ptr)
|
||||
{
|
||||
HeapFree(0, 0, ptr);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// File I/O wrappers
|
||||
// ---------------------------------------------------------------------------
|
||||
static void* doom_open_wrapper(const char* path, const char* mode)
|
||||
{
|
||||
DWORD access = GENERIC_READ;
|
||||
DWORD disp = OPEN_EXISTING;
|
||||
|
||||
if (mode[0] == 'w') {
|
||||
access = GENERIC_WRITE;
|
||||
disp = CREATE_ALWAYS;
|
||||
} else if (mode[0] == 'r' && mode[1] == '+') {
|
||||
access = GENERIC_READ | GENERIC_WRITE;
|
||||
}
|
||||
|
||||
HANDLE h = CreateFileA(path, access, FILE_SHARE_READ, 0, disp, 0, 0);
|
||||
return (h == INVALID_HANDLE_VALUE) ? 0 : h;
|
||||
}
|
||||
|
||||
static void doom_close_wrapper(void* handle)
|
||||
{
|
||||
CloseHandle((HANDLE)handle);
|
||||
}
|
||||
|
||||
static int doom_read_wrapper(void* handle, void* buf, int count)
|
||||
{
|
||||
DWORD read = 0;
|
||||
ReadFile((HANDLE)handle, buf, (DWORD)count, &read, 0);
|
||||
return (int)read;
|
||||
}
|
||||
|
||||
static int doom_write_wrapper(void* handle, const void* buf, int count)
|
||||
{
|
||||
DWORD written = 0;
|
||||
WriteFile((HANDLE)handle, buf, (DWORD)count, &written, 0);
|
||||
return (int)written;
|
||||
}
|
||||
|
||||
static int doom_seek_wrapper(void* handle, int offset, doom_seek_t origin)
|
||||
{
|
||||
DWORD method;
|
||||
switch (origin) {
|
||||
case DOOM_SEEK_SET: method = FILE_BEGIN; break;
|
||||
case DOOM_SEEK_CUR: method = FILE_CURRENT; break;
|
||||
case DOOM_SEEK_END: method = FILE_END; break;
|
||||
default: method = FILE_BEGIN; break;
|
||||
}
|
||||
SetFilePointer((HANDLE)handle, (LONG)offset, 0, method);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int doom_tell_wrapper(void* handle)
|
||||
{
|
||||
return (int)SetFilePointer((HANDLE)handle, 0, 0, FILE_CURRENT);
|
||||
}
|
||||
|
||||
static int doom_eof_wrapper(void* handle)
|
||||
{
|
||||
DWORD size = GetFileSize((HANDLE)handle, 0);
|
||||
DWORD pos = (DWORD)doom_tell_wrapper(handle);
|
||||
return (pos >= size) ? 1 : 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// doom_gettime_fn
|
||||
// ---------------------------------------------------------------------------
|
||||
static void doom_gettime_wrapper(int* sec, int* usec)
|
||||
{
|
||||
DWORD t = GetTickCount(); // milliseconds
|
||||
*sec = (int)(t / 1000);
|
||||
*usec = (int)((t % 1000) * 1000); // ms remainder → us
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// doom_exit_fn
|
||||
// ---------------------------------------------------------------------------
|
||||
static void doom_exit_wrapper(int code)
|
||||
{
|
||||
ExitProcess((UINT)code);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// doom_getenv_fn — we don't have environment variables
|
||||
// ---------------------------------------------------------------------------
|
||||
static char* doom_getenv_wrapper(const char* name)
|
||||
{
|
||||
if (strcmp(name, "HOME") == 0) {
|
||||
static char home[] = "fs0:\\";
|
||||
doom_print_wrapper("getenv: Returning HOME="); doom_print_wrapper(home); doom_print_wrapper("\n");
|
||||
return home;
|
||||
}
|
||||
doom_print_wrapper("getenv: Unknown variable "); doom_print_wrapper(name); doom_print_wrapper("\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Input — poll GetAsyncKeyState every frame
|
||||
// Generates key_down / key_up edge events, not held-key spam.
|
||||
// ---------------------------------------------------------------------------
|
||||
typedef struct { int vk; doom_key_t key; } KeyMap;
|
||||
|
||||
// NOTE: Win32 VK codes for letters are uppercase ASCII (e.g. 'W' = 0x57).
|
||||
// DOOM_KEY_* for letters are lowercase ASCII (e.g. DOOM_KEY_W = 'w' = 0x77).
|
||||
// These are different values — the VK column is what GetAsyncKeyState takes,
|
||||
// the doom_key column is what PureDOOM wants. Don't collapse them.
|
||||
static const KeyMap g_keymap[] = {
|
||||
// Letters — VK is uppercase, DOOM key is lowercase
|
||||
{ 'W', DOOM_KEY_W },
|
||||
{ 'A', DOOM_KEY_A },
|
||||
{ 'S', DOOM_KEY_S },
|
||||
{ 'D', DOOM_KEY_D },
|
||||
{ 'E', DOOM_KEY_E },
|
||||
{ 'Q', DOOM_KEY_Q },
|
||||
{ 'Y', DOOM_KEY_Y }, // yes/no menus
|
||||
{ 'N', DOOM_KEY_N },
|
||||
|
||||
// Arrow keys
|
||||
{ VK_UP, DOOM_KEY_UP_ARROW },
|
||||
{ VK_DOWN, DOOM_KEY_DOWN_ARROW },
|
||||
{ VK_LEFT, DOOM_KEY_LEFT_ARROW },
|
||||
{ VK_RIGHT, DOOM_KEY_RIGHT_ARROW },
|
||||
|
||||
// Action keys — Ctrl=fire, Shift=run, Alt=strafe
|
||||
{ VK_CONTROL, DOOM_KEY_CTRL },
|
||||
{ VK_SPACE, DOOM_KEY_SPACE },
|
||||
{ VK_SHIFT, DOOM_KEY_SHIFT },
|
||||
{ VK_MENU, DOOM_KEY_ALT },
|
||||
|
||||
// Navigation
|
||||
{ VK_ESCAPE, DOOM_KEY_ESCAPE },
|
||||
{ VK_RETURN, DOOM_KEY_ENTER },
|
||||
{ VK_TAB, DOOM_KEY_TAB },
|
||||
{ VK_BACK, DOOM_KEY_BACKSPACE },
|
||||
{ VK_PAUSE, DOOM_KEY_PAUSE },
|
||||
|
||||
// Weapon slots
|
||||
{ '1', DOOM_KEY_1 },
|
||||
{ '2', DOOM_KEY_2 },
|
||||
{ '3', DOOM_KEY_3 },
|
||||
{ '4', DOOM_KEY_4 },
|
||||
{ '5', DOOM_KEY_5 },
|
||||
{ '6', DOOM_KEY_6 },
|
||||
{ '7', DOOM_KEY_7 },
|
||||
|
||||
// Misc
|
||||
{ '-', DOOM_KEY_MINUS },
|
||||
{ '=', DOOM_KEY_EQUALS },
|
||||
{ ',', DOOM_KEY_COMMA }, // default strafe left
|
||||
{ '.', DOOM_KEY_PERIOD }, // default strafe right
|
||||
|
||||
// Function keys — save/load/volume/etc
|
||||
{ VK_F1, DOOM_KEY_F1 },
|
||||
{ VK_F2, DOOM_KEY_F2 },
|
||||
{ VK_F3, DOOM_KEY_F3 },
|
||||
{ VK_F4, DOOM_KEY_F4 },
|
||||
{ VK_F5, DOOM_KEY_F5 },
|
||||
{ VK_F6, DOOM_KEY_F6 },
|
||||
{ VK_F7, DOOM_KEY_F7 },
|
||||
{ VK_F8, DOOM_KEY_F8 },
|
||||
{ VK_F9, DOOM_KEY_F9 },
|
||||
{ VK_F10, DOOM_KEY_F10 },
|
||||
{ VK_F11, DOOM_KEY_F11 },
|
||||
{ VK_F12, DOOM_KEY_F12 },
|
||||
};
|
||||
|
||||
#define KEYMAP_COUNT (sizeof(g_keymap) / sizeof(g_keymap[0]))
|
||||
|
||||
static short g_prev_key[256];
|
||||
|
||||
static void poll_input(void)
|
||||
{
|
||||
for (int i = 0; i < (int)KEYMAP_COUNT; i++) {
|
||||
int vk = g_keymap[i].vk;
|
||||
short cur = GetAsyncKeyState(vk);
|
||||
int cur_down = (cur & 0x8000) != 0;
|
||||
int prev_down = (g_prev_key[vk] & 0x8000) != 0;
|
||||
|
||||
if (cur_down && !prev_down) doom_key_down(g_keymap[i].key);
|
||||
if (!cur_down && prev_down) doom_key_up (g_keymap[i].key);
|
||||
|
||||
g_prev_key[vk] = cur;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Render — StretchDIBits to screen, same pipeline as video.c.
|
||||
//
|
||||
// NOTE: PureDOOM's framebuffer is RGBA; Win32 StretchDIBits with BI_RGB/32bpp
|
||||
// expects BGRA. Channels will be swapped (red ↔ blue) until you either:
|
||||
// a) swap in the blit loop below, or
|
||||
// b) tell PureDOOM to give you BGRA if a future version supports it.
|
||||
// For a first boot, blue-tinted demons are still demons.
|
||||
// ---------------------------------------------------------------------------
|
||||
#define DOOM_W 320
|
||||
#define DOOM_H 200
|
||||
#define SCALE 3
|
||||
#define DISP_W (DOOM_W * SCALE)
|
||||
#define DISP_H (DOOM_H * SCALE)
|
||||
|
||||
static BITMAPINFO g_bmi;
|
||||
static uint32_t g_blit_buf[DOOM_W * DOOM_H]; // BGRA-swapped copy
|
||||
|
||||
static void render_frame(const uint8_t* rgba)
|
||||
{
|
||||
// Swap R <-> B so Win32 GDI sees correct colours
|
||||
const uint32_t* src = (const uint32_t*)rgba;
|
||||
for (int i = 0; i < DOOM_W * DOOM_H; i++) {
|
||||
uint32_t p = src[i];
|
||||
// RGBA -> BGRA: swap byte 0 (R) and byte 2 (B)
|
||||
g_blit_buf[i] = (p & 0xFF00FF00u)
|
||||
| ((p & 0x00FF0000u) >> 16)
|
||||
| ((p & 0x000000FFu) << 16);
|
||||
}
|
||||
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint((HWND)0, &ps);
|
||||
StretchDIBits(
|
||||
hdc,
|
||||
0, 0, DISP_W, DISP_H, // destination — scaled up
|
||||
0, 0, DOOM_W, DOOM_H, // source — native 320×200
|
||||
g_blit_buf,
|
||||
&g_bmi,
|
||||
DIB_RGB_COLORS,
|
||||
SRCCOPY
|
||||
);
|
||||
EndPaint((HWND)0, &ps);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// main
|
||||
// ---------------------------------------------------------------------------
|
||||
int main(const char* cmdline)
|
||||
{
|
||||
(void)cmdline;
|
||||
|
||||
g_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
WriteConsoleA(g_stdout, "doom: starting\n", 15, 0, 0);
|
||||
|
||||
// Prepare the BMI header once (top-down, like video.c)
|
||||
memset(&g_bmi, 0, sizeof(g_bmi));
|
||||
g_bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
g_bmi.bmiHeader.biWidth = DOOM_W;
|
||||
g_bmi.bmiHeader.biHeight = -DOOM_H; // negative = top-down
|
||||
g_bmi.bmiHeader.biPlanes = 1;
|
||||
g_bmi.bmiHeader.biBitCount = 32;
|
||||
g_bmi.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
// Wire up PureDOOM
|
||||
doom_set_print(doom_print_wrapper);
|
||||
doom_set_malloc(doom_malloc_wrapper, doom_free_wrapper);
|
||||
doom_set_file_io(
|
||||
doom_open_wrapper,
|
||||
doom_close_wrapper,
|
||||
doom_read_wrapper,
|
||||
doom_write_wrapper,
|
||||
doom_seek_wrapper,
|
||||
doom_tell_wrapper,
|
||||
doom_eof_wrapper
|
||||
);
|
||||
doom_set_gettime(doom_gettime_wrapper);
|
||||
doom_set_exit(doom_exit_wrapper);
|
||||
doom_set_getenv(doom_getenv_wrapper);
|
||||
|
||||
// Resolution + modern WASD bindings
|
||||
doom_set_resolution(DOOM_W, DOOM_H);
|
||||
doom_set_default_int("key_up", DOOM_KEY_W);
|
||||
doom_set_default_int("key_down", DOOM_KEY_S);
|
||||
doom_set_default_int("key_strafeleft", DOOM_KEY_A);
|
||||
doom_set_default_int("key_straferight", DOOM_KEY_D);
|
||||
doom_set_default_int("key_use", DOOM_KEY_E);
|
||||
doom_set_default_int("mouse_move", 0);
|
||||
|
||||
// No extra args — PureDOOM will scan for doom1.wad / doom.wad
|
||||
const char* args[] = { "doom" };
|
||||
doom_init(1, (char**)args, 0);
|
||||
|
||||
WriteConsoleA(g_stdout, "doom: entering game loop\n", 25, 0, 0);
|
||||
|
||||
// Game loop — identical shape to video.c's Bink loop
|
||||
while (1) {
|
||||
poll_input();
|
||||
doom_update();
|
||||
render_frame((const uint8_t*)doom_get_framebuffer(4 /* RGBA */));
|
||||
}
|
||||
|
||||
// Unreachable: doom_exit() -> ExitProcess() handles clean shutdown
|
||||
ExitProcess(0);
|
||||
}
|
||||
Binary file not shown.
+530
-573
File diff suppressed because it is too large.
Load diff
+2
-1
@@ -21,11 +21,12 @@ typedef struct HAL_SCREEN {
|
||||
} HAL_SCREEN;
|
||||
|
||||
typedef struct HAL_KEYBOARD {
|
||||
bool (*Poll)(void);
|
||||
uint8_t (*Poll)(void);
|
||||
uint8_t (*ReadScancode)(void);
|
||||
char (*ReadChar)(void);
|
||||
uint32_t (*GetModifiers)(void);
|
||||
void (*SetCallback)(void (*cb)(uint8_t scancode));
|
||||
bool (*IsKeyDown)(uint8_t scancode, bool extended);
|
||||
void (*Isr)(void);
|
||||
uint8_t IrqNumber;
|
||||
} HAL_KEYBOARD;
|
||||
|
||||
+71
-214
@@ -1,50 +1,31 @@
|
||||
// hal_keyboard.c - PS/2 keyboard, interrupt-driven, 256-entry ring buffer
|
||||
//
|
||||
// Scan-code set 1 (XT-compatible), as output by the 8042's built-in
|
||||
// translation layer. Supports make/break for all standard keys, Shift /
|
||||
// Ctrl / Alt / CapsLock / NumLock modifiers, and the E0-prefixed extended
|
||||
// key set (arrows, Home/End/PgUp/PgDn/Ins/Del, RCtrl, RAlt, numpad-Enter,
|
||||
// numpad-divide).
|
||||
//
|
||||
// Threading model
|
||||
// ---------------
|
||||
// Single-producer (ISR on IRQ 1) / single-consumer ring buffer. All
|
||||
// ISR-written state is declared volatile. On a uniprocessor, volatile
|
||||
// plus the natural atomicity of aligned int reads/writes is sufficient.
|
||||
// On SMP, add acquire/release memory barriers around gHead and gTail.
|
||||
//
|
||||
// Caller responsibilities
|
||||
// -----------------------
|
||||
// 1. Register KbdIsr with your interrupt dispatcher for IRQ 1.
|
||||
// 2. Send the APIC/PIC EOI *after* KbdIsr returns, in the surrounding
|
||||
// wrapper - not inside KbdIsr itself.
|
||||
// 3. Unmask IRQ 1 in the APIC or 8259 before expecting any interrupts.
|
||||
//
|
||||
// hal_keyboard.c - PS/2 keyboard, interrupt-driven, with live state tracking
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <intrin.h>
|
||||
#include <hal_api.h>
|
||||
#include <hal_apic.h>
|
||||
#include <hal_debug.h>
|
||||
|
||||
// -- Port addresses ------------------------------------------------------------
|
||||
#define PS2_DATA 0x60u
|
||||
#define PS2_STAT 0x64u
|
||||
#define PS2_CMD 0x64u
|
||||
|
||||
// -- Ring buffer ---------------------------------------------------------------
|
||||
// KBD_BUF_SIZE must be a power of two; KBD_BUF_MASK replaces % with &.
|
||||
// -- Ring buffer (for ASCII/typing) -------------------------------------------
|
||||
#define KBD_BUF_SIZE 256u
|
||||
#define KBD_BUF_MASK (KBD_BUF_SIZE - 1u)
|
||||
|
||||
static uint8_t gBuf[KBD_BUF_SIZE];
|
||||
static volatile int gHead = 0; // consumer read pointer (updated by reader)
|
||||
static volatile int gTail = 0; // producer write pointer (updated by ISR)
|
||||
static volatile int gHead = 0;
|
||||
static volatile int gTail = 0;
|
||||
|
||||
// -- Live Key State (for GetAsyncKeyState) ------------------------------------
|
||||
// These arrays track whether a key is currently held down.
|
||||
static volatile uint8_t gKeyState[128]; // Standard scan codes
|
||||
static volatile uint8_t gKeyStateExt[128]; // Extended (E0) scan codes
|
||||
|
||||
// -- Scan-code set 1 constants -------------------------------------------------
|
||||
#define SC1_BREAK_BIT 0x80u // OR'd into every break (key-up) scan code
|
||||
#define SC1_MAKE_MASK 0x7Fu // complement of SC1_BREAK_BIT; avoids ~uint cast
|
||||
#define SC1_EXT_PREFIX 0xE0u // one-byte prefix for extended keys
|
||||
#define SC1_BREAK_BIT 0x80u
|
||||
#define SC1_MAKE_MASK 0x7Fu
|
||||
#define SC1_EXT_PREFIX 0xE0u
|
||||
|
||||
// -- Modifier flags ------------------------------------------------------------
|
||||
#define MOD_LSHIFT (1u << 0)
|
||||
@@ -53,107 +34,38 @@ static volatile int gTail = 0; // producer write pointer (updated by ISR)
|
||||
#define MOD_RCTRL (1u << 3)
|
||||
#define MOD_LALT (1u << 4)
|
||||
#define MOD_RALT (1u << 5)
|
||||
#define MOD_CAPS (1u << 6) // toggle, not a held key
|
||||
#define MOD_NUMLOCK (1u << 7) // toggle, not a held key
|
||||
#define MOD_CAPS (1u << 6)
|
||||
#define MOD_NUMLOCK (1u << 7)
|
||||
|
||||
#define MOD_SHIFT (MOD_LSHIFT | MOD_RSHIFT)
|
||||
#define MOD_CTRL (MOD_LCTRL | MOD_RCTRL)
|
||||
#define MOD_ALT (MOD_LALT | MOD_RALT)
|
||||
|
||||
static volatile uint32_t gModifiers = 0;
|
||||
static volatile bool gNextExtended = false; // previous byte was 0xE0
|
||||
|
||||
// -- Raw-scancode callback (invoked from ISR context) --------------------------
|
||||
// The pointer must be volatile so the compiler re-reads it on every ISR entry
|
||||
// rather than caching the value seen at startup.
|
||||
static volatile bool gNextExtended = false;
|
||||
static void (* volatile gCallback)(uint8_t) = NULL;
|
||||
|
||||
// -- ASCII translation tables - scan-code set 1, non-extended keys only --------
|
||||
// Index = 7-bit make code (SC1_BREAK_BIT cleared). 0 = no printable glyph.
|
||||
// Numpad digits yield their digit characters; a NumLock-aware wrapper can
|
||||
// substitute cursor-movement codes (e.g. HAL_KEY_HOME) when NumLock is clear.
|
||||
//
|
||||
// Layout verified against the IBM PC/AT scan-code set 1 reference.
|
||||
|
||||
// -- ASCII Translation Tables --------------------------------------------------
|
||||
static const char gUnshifted[128] = {
|
||||
/*00*/ 0,
|
||||
/*01*/ 0, // ESC
|
||||
/*02*/ '1','2','3','4','5','6','7','8','9','0','-','=', // 02-0D
|
||||
/*0E*/ '\b',
|
||||
/*0F*/ '\t',
|
||||
/*10*/ 'q','w','e','r','t','y','u','i','o','p','[',']', // 10-1B
|
||||
/*1C*/ '\n',
|
||||
/*1D*/ 0, // Left Ctrl
|
||||
/*1E*/ 'a','s','d','f','g','h','j','k','l',';','\'','`', // 1E-29
|
||||
/*2A*/ 0, // Left Shift
|
||||
/*2B*/ '\\',
|
||||
/*2C*/ 'z','x','c','v','b','n','m',',','.','/', // 2C-35
|
||||
/*36*/ 0, // Right Shift
|
||||
/*37*/ '*', // Numpad * (also PrtSc on some keyboards)
|
||||
/*38*/ 0, // Left Alt
|
||||
/*39*/ ' ',
|
||||
/*3A*/ 0, // Caps Lock
|
||||
/*3B*/ 0,0,0,0,0,0,0,0,0,0, // F1-F10 (3B-44)
|
||||
/*45*/ 0, // Num Lock
|
||||
/*46*/ 0, // Scroll Lock
|
||||
/*47*/ '7','8','9', // Numpad 7-9
|
||||
/*4A*/ '-', // Numpad -
|
||||
/*4B*/ '4','5','6', // Numpad 4-6
|
||||
/*4E*/ '+', // Numpad +
|
||||
/*4F*/ '1','2','3', // Numpad 1-3
|
||||
/*52*/ '0', // Numpad 0
|
||||
/*53*/ '.', // Numpad .
|
||||
/*54*/ 0,0,0,
|
||||
/*57*/ 0, // F11
|
||||
/*58*/ 0, // F12
|
||||
/*59*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 59-68
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 69-78
|
||||
0,0,0,0,0,0,0, // 79-7F
|
||||
0, 0, '1','2','3','4','5','6','7','8','9','0','-','=','\b','\t',
|
||||
'q','w','e','r','t','y','u','i','o','p','[',']','\n', 0, 'a','s',
|
||||
'd','f','g','h','j','k','l',';','\'','`', 0, '\\','z','x','c','v',
|
||||
'b','n','m',',','.','/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, '7','8','9','-', '4','5','6','+', '1','2','3','0','.'
|
||||
};
|
||||
|
||||
static const char gShifted[128] = {
|
||||
/*00*/ 0,
|
||||
/*01*/ 0, // ESC
|
||||
/*02*/ '!','@','#','$','%','^','&','*','(',')','_','+', // 02-0D
|
||||
/*0E*/ '\b',
|
||||
/*0F*/ '\t',
|
||||
/*10*/ 'Q','W','E','R','T','Y','U','I','O','P','{','}', // 10-1B
|
||||
/*1C*/ '\n',
|
||||
/*1D*/ 0, // Left Ctrl
|
||||
/*1E*/ 'A','S','D','F','G','H','J','K','L',':','"','~', // 1E-29
|
||||
/*2A*/ 0, // Left Shift
|
||||
/*2B*/ '|',
|
||||
/*2C*/ 'Z','X','C','V','B','N','M','<','>','?', // 2C-35
|
||||
/*36*/ 0, // Right Shift
|
||||
/*37*/ '*',
|
||||
/*38*/ 0, // Left Alt
|
||||
/*39*/ ' ',
|
||||
/*3A*/ 0, // Caps Lock
|
||||
/*3B*/ 0,0,0,0,0,0,0,0,0,0, // F1-F10
|
||||
/*45*/ 0,
|
||||
/*46*/ 0,
|
||||
/*47*/ '7','8','9',
|
||||
/*4A*/ '-',
|
||||
/*4B*/ '4','5','6',
|
||||
/*4E*/ '+',
|
||||
/*4F*/ '1','2','3',
|
||||
/*52*/ '0',
|
||||
/*53*/ '.',
|
||||
/*54*/ 0,0,0,
|
||||
/*57*/ 0, // F11
|
||||
/*58*/ 0, // F12
|
||||
/*59*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,
|
||||
0, 0, '!','@','#','$','%','^','&','*','(',')','_','+','\b','\t',
|
||||
'Q','W','E','R','T','Y','U','I','O','P','{','}','\n', 0, 'A','S',
|
||||
'D','F','G','H','J','K','L',':','"','~', 0, '|','Z','X','C','V',
|
||||
'B','N','M','<','>','?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, '7','8','9','-', '4','5','6','+', '1','2','3','0','.'
|
||||
};
|
||||
|
||||
// -- Interrupt service routine --------------------------------------------------
|
||||
// Called with interrupts disabled (inside the hardware IRQ handler).
|
||||
// The caller's wrapper must send the APIC/PIC EOI after this returns.
|
||||
static void KbdIsr(void) {
|
||||
// -- ISR: The Engine -----------------------------------------------------------
|
||||
void KbdIsr(void) {
|
||||
uint8_t sc = __inbyte(PS2_DATA);
|
||||
|
||||
// E0 prefix: the following byte is an extended make/break code.
|
||||
if (sc == SC1_EXT_PREFIX) {
|
||||
gNextExtended = true;
|
||||
return;
|
||||
@@ -162,142 +74,87 @@ static void KbdIsr(void) {
|
||||
bool extended = gNextExtended;
|
||||
bool is_break = (sc & SC1_BREAK_BIT) != 0;
|
||||
uint8_t make = sc & SC1_MAKE_MASK;
|
||||
|
||||
gNextExtended = false;
|
||||
|
||||
// -- Update modifier state -------------------------------------------------
|
||||
// Update the live state arrays
|
||||
if (extended) {
|
||||
gKeyStateExt[make] = is_break ? 0 : 1;
|
||||
} else {
|
||||
gKeyState[make] = is_break ? 0 : 1;
|
||||
}
|
||||
|
||||
// Update modifiers
|
||||
if (!extended) {
|
||||
switch (make) {
|
||||
case 0x2A: // Left Shift
|
||||
gModifiers = is_break ? (gModifiers & ~MOD_LSHIFT)
|
||||
: (gModifiers | MOD_LSHIFT);
|
||||
return;
|
||||
case 0x36: // Right Shift
|
||||
gModifiers = is_break ? (gModifiers & ~MOD_RSHIFT)
|
||||
: (gModifiers | MOD_RSHIFT);
|
||||
return;
|
||||
case 0x1D: // Left Ctrl
|
||||
gModifiers = is_break ? (gModifiers & ~MOD_LCTRL)
|
||||
: (gModifiers | MOD_LCTRL);
|
||||
return;
|
||||
case 0x38: // Left Alt
|
||||
gModifiers = is_break ? (gModifiers & ~MOD_LALT)
|
||||
: (gModifiers | MOD_LALT);
|
||||
return;
|
||||
case 0x3A: // Caps Lock - toggle on make only
|
||||
if (!is_break) gModifiers ^= MOD_CAPS;
|
||||
return;
|
||||
case 0x45: // Num Lock - toggle on make only
|
||||
if (!is_break) gModifiers ^= MOD_NUMLOCK;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
case 0x2A: gModifiers = is_break ? (gModifiers & ~MOD_LSHIFT) : (gModifiers | MOD_LSHIFT); break;
|
||||
case 0x36: gModifiers = is_break ? (gModifiers & ~MOD_RSHIFT) : (gModifiers | MOD_RSHIFT); break;
|
||||
case 0x1D: gModifiers = is_break ? (gModifiers & ~MOD_LCTRL) : (gModifiers | MOD_LCTRL); break;
|
||||
case 0x38: gModifiers = is_break ? (gModifiers & ~MOD_LALT) : (gModifiers | MOD_LALT); break;
|
||||
case 0x3A: if (!is_break) gModifiers ^= MOD_CAPS; break;
|
||||
case 0x45: if (!is_break) gModifiers ^= MOD_NUMLOCK; break;
|
||||
}
|
||||
} else {
|
||||
// Extended make codes that map to modifier keys.
|
||||
switch (make) {
|
||||
case 0x1D: // Right Ctrl (E0 1D)
|
||||
gModifiers = is_break ? (gModifiers & ~MOD_RCTRL)
|
||||
: (gModifiers | MOD_RCTRL);
|
||||
return;
|
||||
case 0x38: // Right Alt / AltGr (E0 38)
|
||||
gModifiers = is_break ? (gModifiers & ~MOD_RALT)
|
||||
: (gModifiers | MOD_RALT);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
case 0x1D: gModifiers = is_break ? (gModifiers & ~MOD_RCTRL) : (gModifiers | MOD_RCTRL); break;
|
||||
case 0x38: gModifiers = is_break ? (gModifiers & ~MOD_RALT) : (gModifiers | MOD_RALT); break;
|
||||
}
|
||||
// All other extended keys (arrows, Home/End, etc.) fall through
|
||||
// and are enqueued as make codes for consumer-side interpretation.
|
||||
}
|
||||
|
||||
// -- Discard break codes for non-modifier keys -----------------------------
|
||||
if (is_break) return;
|
||||
|
||||
// -- Enqueue make code; silently drop if buffer is full --------------------
|
||||
int next = (gTail + 1) & (int)KBD_BUF_MASK;
|
||||
if (next != gHead) {
|
||||
gBuf[gTail] = make;
|
||||
gTail = next;
|
||||
// Buffer management (only for 'make' codes)
|
||||
if (!is_break) {
|
||||
int next = (gTail + 1) & (int)KBD_BUF_MASK;
|
||||
if (next != gHead) {
|
||||
gBuf[gTail] = make;
|
||||
gTail = next;
|
||||
}
|
||||
|
||||
void (*cb)(uint8_t) = (void (*)(uint8_t))gCallback;
|
||||
if (cb) cb(make);
|
||||
}
|
||||
|
||||
// -- Notify optional callback with the raw make code -----------------------
|
||||
// Take a local snapshot so the compiler cannot reorder the NULL check and
|
||||
// the call across a volatile barrier, and to avoid double-fetching.
|
||||
void (*cb)(uint8_t) = (void (*)(uint8_t))gCallback;
|
||||
if (cb) cb(make);
|
||||
}
|
||||
|
||||
// -- Consumer API --------------------------------------------------------------
|
||||
// -- Public API ----------------------------------------------------------------
|
||||
|
||||
static bool KbdPoll(void) {
|
||||
return gHead != gTail;
|
||||
// Use this inside your GetAsyncKeyState implementation!
|
||||
bool KbdIsKeyDown(uint8_t scancode, bool extended) {
|
||||
if (extended) return gKeyStateExt[scancode & 0x7F] != 0;
|
||||
return gKeyState[scancode & 0x7F] != 0;
|
||||
}
|
||||
|
||||
static uint8_t KbdPoll(void) {
|
||||
return (gHead == gTail) ? 0 : gBuf[gHead];
|
||||
}
|
||||
|
||||
// Blocking read. Spins with PAUSE until a make code is available.
|
||||
// On a preemptive kernel, replace the _mm_pause() loop with a
|
||||
// condition variable or sti/hlt to avoid wasting CPU cycles.
|
||||
static uint8_t KbdReadScancode(void) {
|
||||
while (gHead == gTail) {
|
||||
_mm_pause();
|
||||
}
|
||||
while (gHead == gTail) { _mm_pause(); }
|
||||
uint8_t sc = gBuf[gHead];
|
||||
gHead = (gHead + 1) & (int)KBD_BUF_MASK;
|
||||
return sc;
|
||||
}
|
||||
|
||||
// Returns the ASCII character for the next keypress, applying the current
|
||||
// Shift and CapsLock state. Returns 0 for keys with no ASCII mapping
|
||||
// (function keys, arrows, unmodified Ctrl/Alt keys, etc.).
|
||||
//
|
||||
// CapsLock inverts shift only for alphabetic keys (a-z); digit and symbol
|
||||
// keys are always governed solely by the physical Shift state.
|
||||
static char KbdReadChar(void) {
|
||||
uint8_t make = KbdReadScancode();
|
||||
if (make >= 128) return 0;
|
||||
|
||||
uint32_t mods = gModifiers; // snapshot; safe outside ISR
|
||||
bool shifted = (mods & MOD_SHIFT) != 0;
|
||||
uint32_t mods = gModifiers;
|
||||
bool shifted = (mods & MOD_SHIFT) != 0;
|
||||
|
||||
// CapsLock toggles the effective shift for alphabetic keys only.
|
||||
if (mods & MOD_CAPS) {
|
||||
char base = gUnshifted[make];
|
||||
if (base >= 'a' && base <= 'z') {
|
||||
shifted = !shifted;
|
||||
}
|
||||
if (base >= 'a' && base <= 'z') shifted = !shifted;
|
||||
}
|
||||
|
||||
return shifted ? gShifted[make] : gUnshifted[make];
|
||||
}
|
||||
|
||||
static void KbdSetCallback(void (*cb)(uint8_t)) {
|
||||
gCallback = cb;
|
||||
}
|
||||
|
||||
// Returns the current modifier bitmask (OR of MOD_* flags above).
|
||||
// Snapshot is taken outside ISR and may lag by at most one interrupt.
|
||||
static uint32_t KbdGetModifiers(void) {
|
||||
return gModifiers;
|
||||
}
|
||||
|
||||
// -- Initializer ---------------------------------------------------------------
|
||||
void HalKeyboardInitialize(HAL_KEYBOARD *out) {
|
||||
// Enable PS/2 auxiliary port so the mouse driver can claim IRQ 12.
|
||||
// The 8042 must have an empty input buffer before we can issue commands.
|
||||
while (__inbyte(PS2_STAT) & 2) { /* wait for input buffer empty */ }
|
||||
__outbyte(PS2_CMD, 0xA8); // enable aux port
|
||||
|
||||
// Drain any stale bytes sitting in the PS/2 output buffer before
|
||||
// enabling interrupts, so the first ISR call sees a clean state.
|
||||
while (__inbyte(PS2_STAT) & 1) {
|
||||
__inbyte(PS2_DATA);
|
||||
}
|
||||
while (__inbyte(PS2_STAT) & 2);
|
||||
__outbyte(PS2_CMD, 0xA8);
|
||||
while (__inbyte(PS2_STAT) & 1) { __inbyte(PS2_DATA); }
|
||||
|
||||
out->Poll = KbdPoll;
|
||||
out->ReadScancode = KbdReadScancode;
|
||||
out->ReadChar = KbdReadChar;
|
||||
out->SetCallback = KbdSetCallback;
|
||||
out->GetModifiers = KbdGetModifiers;
|
||||
out->IsKeyDown = KbdIsKeyDown;
|
||||
out->Isr = KbdIsr;
|
||||
out->IrqNumber = 1;
|
||||
}
|
||||
+2
-3
@@ -365,11 +365,10 @@ __declspec(dllexport) KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) {
|
||||
// and because the CPU missed the IRQ 12 edge transition (cli) later when we expect it to fire, it doesn't
|
||||
// leaving us with no mouse and no keyboard. The dreaded 8042 will hold the CLOCK line low forever.
|
||||
// To combat this we just go about our day executing the rest of the init and just before the end
|
||||
// of init we use a decaying poll to grab whatever the controller left for us ("Drain and Pray").
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
// of init we just iterate 256 times to grab whatever the controller left for us ("Drain and Pray").
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if (__inbyte(0x64) & 0x01) {
|
||||
__inbyte(0x60); // Consume
|
||||
i = 0; // Reset timeout if we are still getting data
|
||||
}
|
||||
gApi.Timer.Stall(1); // Micro-stalls
|
||||
}
|
||||
|
||||
+22
-2
@@ -21,6 +21,7 @@
|
||||
extern HAL_API gApi;
|
||||
static volatile uint32_t* gLapic = NULL;
|
||||
static uint32_t gApicTicksPerUs = 0;
|
||||
static uint32_t gApicTicksPerQuantum = 0;
|
||||
static uint64_t gHpetTicksPerUs = 0;
|
||||
static volatile uint64_t* gHpet = NULL;
|
||||
#define LAPIC_REG(off) (*(volatile uint32_t *)((uint8_t *)gLapic + (off)))
|
||||
@@ -37,7 +38,25 @@ static void TimerIsr(void) {
|
||||
// EOI is sent by KeIrqDispatch after this returns
|
||||
}
|
||||
|
||||
static uint64_t QueryTicks(void) { return gTicks; }
|
||||
static uint64_t QueryTicks(void) {
|
||||
uint64_t baseTicks = gTicks; // The 10ms "coarse" ticks
|
||||
|
||||
// The LAPIC timer counts DOWN.
|
||||
// Ticks elapsed = (Initial Value) - (Current Value)
|
||||
uint32_t current = LAPIC_REG(LAPIC_TIMER_CUR);
|
||||
uint32_t initial = gApicTicksPerQuantum;
|
||||
|
||||
uint32_t elapsedApicTicks = 0;
|
||||
if (current < initial) {
|
||||
elapsedApicTicks = initial - current;
|
||||
}
|
||||
|
||||
// Convert base 10ms ticks to microseconds + the remainder
|
||||
// gTicks * 10,000 (ms to us) + (elapsed / ticks_per_us)
|
||||
uint64_t totalUs = (baseTicks * QUANTUM_MS * 1000) + (elapsedApicTicks / gApicTicksPerUs);
|
||||
|
||||
return totalUs;
|
||||
}
|
||||
|
||||
static void Stall(uint32_t us) {
|
||||
// Priority 1: Use HPET (Highest Precision)
|
||||
@@ -157,6 +176,7 @@ KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *o
|
||||
}
|
||||
|
||||
gApicTicksPerUs = ticksPerMs / 1000;
|
||||
gApicTicksPerQuantum = ticksPerMs * QUANTUM_MS;
|
||||
|
||||
if (hpetPhys) {
|
||||
gHpet = (volatile uint64_t*)gApi.PhysToVirt(hpetPhys);
|
||||
@@ -169,7 +189,7 @@ KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *o
|
||||
// Configure LAPIC timer in periodic mode
|
||||
LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16;
|
||||
LAPIC_REG(LAPIC_TIMER_LVT) = TIMER_PERIODIC | TIMER_VECTOR;
|
||||
LAPIC_REG(LAPIC_TIMER_INIT) = ticksPerMs * QUANTUM_MS;
|
||||
LAPIC_REG(LAPIC_TIMER_INIT) = gApicTicksPerQuantum;
|
||||
|
||||
out->QueryTicks = QueryTicks;
|
||||
out->Stall = Stall;
|
||||
|
||||
+6
-6
@@ -16,19 +16,19 @@ extern void SysYield(void);
|
||||
|
||||
#define STATUS_SUCCESS 0u
|
||||
|
||||
void _start()
|
||||
void _start(const char* args)
|
||||
{
|
||||
uint32_t h = 0;
|
||||
uint32_t s = 0;
|
||||
|
||||
SysDebugPrint("[init] starting shell\n");
|
||||
s = SysCreateProcess("shell.exe", &h, NULL);
|
||||
|
||||
SysDebugPrint("[init] starting\n");
|
||||
s = SysCreateProcess(args, &h, NULL);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
SysDebugPrint("[init] FATAL: failed to start shell.exe\n");
|
||||
SysDebugPrint("[init] FATAL: failed to start!\n");
|
||||
SysExitProcess(1);
|
||||
}
|
||||
|
||||
SysDebugPrint("[init] waiting for shell\n");
|
||||
SysDebugPrint("[init] waiting\n");
|
||||
s = SysWaitForProcess(h);
|
||||
if (s != STATUS_SUCCESS)
|
||||
SysDebugPrint("[init] WARNING: SysWaitForProcess returned error\n");
|
||||
|
||||
+80
-66
@@ -102,14 +102,14 @@ static uint64_t SyscallExitProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_EXIT_THREAD (true) a0 = exitCode
|
||||
// SYS_EXIT_THREAD (1) a0 = exitCode
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallExitThread(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* t = KeGetCurrentThread();
|
||||
if (t) KeExitThread(t, (int)a0);
|
||||
while (true) ;
|
||||
while (true);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -485,7 +485,7 @@ static uint64_t SyscallReadFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_WRITE_FILE (43) a0=handle a1=buf a2=size a3=*bytesWrittenOut
|
||||
// SYS_WRITE_FILE (29) a0=handle a1=buf a2=size a3=*bytesWrittenOut
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallWriteFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -501,7 +501,7 @@ static uint64_t SyscallWriteFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_CREATE_FILE (44) a0=*path a1=*handleOut
|
||||
// SYS_CREATE_FILE (30) a0=*path a1=*handleOut
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallCreateFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -521,7 +521,7 @@ static uint64_t SyscallCreateFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_DELETE_FILE (45) a0=*path
|
||||
// SYS_DELETE_FILE (31) a0=*path
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallDeleteFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -531,7 +531,7 @@ static uint64_t SyscallDeleteFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_TRUNCATE_FILE (46) a0=handle a1=newSize
|
||||
// SYS_TRUNCATE_FILE (32) a0=handle a1=newSize
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallTruncateFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -544,7 +544,7 @@ static uint64_t SyscallTruncateFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_GET_FILE_POS (47) a0=handle -> current seek offset
|
||||
// SYS_GET_FILE_POS (33) a0=handle -> current seek offset
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallGetFilePos(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -557,7 +557,7 @@ static uint64_t SyscallGetFilePos(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_SEEK_FILE (29) a0=handle a1=offset
|
||||
// SYS_SEEK_FILE (34) a0=handle a1=offset
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallSeekFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -570,7 +570,7 @@ static uint64_t SyscallSeekFile(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_GET_FILE_SIZE (30) a0=handle -> uint64_t
|
||||
// SYS_GET_FILE_SIZE (35) a0=handle -> uint64_t
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallGetFileSize(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -583,7 +583,7 @@ static uint64_t SyscallGetFileSize(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_SCREEN_BLIT (31) a0=x a1=y a2=w a3=h a4=*pixels
|
||||
// SYS_SCREEN_BLIT (36) a0=x a1=y a2=w a3=h a4=*pixels
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallScreenBlit(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -595,7 +595,7 @@ static uint64_t SyscallScreenBlit(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_SCREEN_CLEAR (32) a0=color
|
||||
// SYS_SCREEN_CLEAR (37) a0=color
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallScreenClear(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -606,7 +606,7 @@ static uint64_t SyscallScreenClear(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_SCREEN_GET_SIZE (33) a0=*widthOut a1=*heightOut
|
||||
// SYS_SCREEN_GET_SIZE (38) a0=*widthOut a1=*heightOut
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallScreenGetSize(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -620,7 +620,7 @@ static uint64_t SyscallScreenGetSize(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_SCREEN_PUT_CHAR (34) a0=c a1=x a2=y a3=fg a4=bg
|
||||
// SYS_SCREEN_PUT_CHAR (39) a0=c a1=x a2=y a3=fg a4=bg
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallScreenPutChar(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -632,17 +632,30 @@ static uint64_t SyscallScreenPutChar(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_KB_POLL (35) -> 1 or 0
|
||||
// SYS_KB_POLL (40) -> 1 or 0
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallKbPoll(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
if (!gHal) return 0;
|
||||
return gHal->Keyboard.Poll() ? 1u : 0u;
|
||||
return gHal->Keyboard.Poll();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_KB_READ_CHAR (36) -> char (blocks, yields while waiting)
|
||||
// SYS_KB_IS_KEY_DOWN (41) a0=scancode a1=extended -> 1 or 0
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallKbIsKeyDown(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
|
||||
// Check gHal and ensure the HAL struct actually has the new function pointer
|
||||
if (!gHal || !gHal->Keyboard.IsKeyDown) return 0;
|
||||
|
||||
return gHal->Keyboard.IsKeyDown((uint8_t)a0, (bool)a1) ? 1u : 0u;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_KB_READ_CHAR (42) -> char (blocks, yields while waiting)
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallKbReadChar(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -653,7 +666,7 @@ static uint64_t SyscallKbReadChar(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_KB_READ_SCANCODE (37) -> uint8_t (blocks, yields while waiting)
|
||||
// SYS_KB_READ_SCANCODE (43) -> uint8_t (blocks, yields while waiting)
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallKbReadScancode(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -664,7 +677,7 @@ static uint64_t SyscallKbReadScancode(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_KB_GET_MODIFIERS (43) -> uint32_t
|
||||
// SYS_KB_GET_MODIFIERS (44) -> uint32_t
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallKbGetModifiers(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -674,7 +687,7 @@ static uint64_t SyscallKbGetModifiers(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_MOUSE_POLL (44) -> 1 or 0
|
||||
// SYS_MOUSE_POLL (45) -> 1 or 0
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallMousePoll(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -684,7 +697,7 @@ static uint64_t SyscallMousePoll(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_MOUSE_READ (45) a0=*dx a1=*dy a2=*buttons -> 1 or 0
|
||||
// SYS_MOUSE_READ (46) a0=*dx a1=*dy a2=*buttons -> 1 or 0
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallMouseRead(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -696,7 +709,7 @@ static uint64_t SyscallMouseRead(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_MOUSE_GET_POS (46) a0=*x a1=*y
|
||||
// SYS_MOUSE_GET_POS (47) a0=*x a1=*y
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallMouseGetPos(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -707,7 +720,7 @@ static uint64_t SyscallMouseGetPos(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_GET_TICK (47) -> uint64_t milliseconds
|
||||
// SYS_GET_TICK (48) -> uint64_t milliseconds
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallGetTick(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -716,7 +729,7 @@ static uint64_t SyscallGetTick(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_DEBUG_PRINT (39) a0=*str
|
||||
// SYS_DEBUG_PRINT (49) a0=*str
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallDebugPrint(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -726,7 +739,7 @@ static uint64_t SyscallDebugPrint(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_CREATE_PROCESS (40) a0=*path a1=*handleOut a2=*cmdline (optional)
|
||||
// SYS_CREATE_PROCESS (50) a0=*path a1=*handleOut a2=*cmdline (optional)
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -798,7 +811,7 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_WAIT_FOR_PROCESS (41) a0=handle
|
||||
// SYS_WAIT_FOR_PROCESS (51) a0=handle
|
||||
// Blocks until the target process signals its ExitEvent.
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallWaitForProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
@@ -814,7 +827,7 @@ static uint64_t SyscallWaitForProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_GET_PROCESS_EXIT_CODE (42) a0=handle a1=*exitCodeOut
|
||||
// SYS_GET_PROCESS_EXIT_CODE (52) a0=handle a1=*exitCodeOut
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallGetProcessExitCode(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -830,7 +843,7 @@ static uint64_t SyscallGetProcessExitCode(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_WRITE_CONSOLE (48) a0=*buf a1=len
|
||||
// SYS_WRITE_CONSOLE (53) a0=*buf a1=len
|
||||
// Writes user console text in white; distinct from green SYS_DEBUG_PRINT.
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallWriteConsole(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
@@ -843,7 +856,7 @@ static uint64_t SyscallWriteConsole(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_OPEN_DIR (49) a0=*dirPath a1=*handleOut
|
||||
// SYS_OPEN_DIR (54) a0=*dirPath a1=*handleOut
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallOpenDir(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -868,7 +881,7 @@ static uint64_t SyscallOpenDir(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_READ_DIR (50) a0=handle a1=*KDIR_ENTRY
|
||||
// SYS_READ_DIR (55) a0=handle a1=*KDIR_ENTRY
|
||||
// Returns STATUS_NO_MORE_FILES when the directory is exhausted.
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallReadDir(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
@@ -889,7 +902,7 @@ static uint64_t SyscallReadDir(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_SET_CWD (51) a0=*path
|
||||
// SYS_SET_CWD (56) a0=*path
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallSetCwd(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -900,7 +913,7 @@ static uint64_t SyscallSetCwd(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_GET_CWD (52) a0=*buf a1=size
|
||||
// SYS_GET_CWD (57) a0=*buf a1=size
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallGetCwd(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -912,7 +925,7 @@ static uint64_t SyscallGetCwd(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_WAIT_THREAD (53) a0=tid
|
||||
// SYS_WAIT_THREAD (58) a0=tid
|
||||
// Blocks the caller until the thread with the given TID exits.
|
||||
// Searches the current process's thread list; cross-process join is not
|
||||
// supported in v1 (POSIX pthread_join is always intra-process).
|
||||
@@ -956,7 +969,7 @@ static uint64_t SyscallWaitThread(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_GET_PROCESS_PID (54) a0=procHandle a1=*pidOut
|
||||
// SYS_GET_PROCESS_PID (59) a0=procHandle a1=*pidOut
|
||||
// Returns the numeric PID of a process identified by handle.
|
||||
// Used by posix_spawn to map the kernel handle back to a pid_t for waitpid.
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -999,7 +1012,7 @@ static NAMED_QUEUE_ENTRY gNamedQueues[NAMED_QUEUE_MAX];
|
||||
static SPINLOCK gNamedQueueLock;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_PUBLISH_QUEUE (55) a0=*name a1=queueHandle
|
||||
// SYS_PUBLISH_QUEUE (60) a0=*name a1=queueHandle
|
||||
//
|
||||
// Registers the queue identified by 'queueHandle' under 'name'.
|
||||
// Fails with STATUS_ALREADY_EXISTS if the name is already taken.
|
||||
@@ -1047,7 +1060,7 @@ static uint64_t SyscallPublishQueue(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_OPEN_NAMED_QUEUE (56) a0=*name a1=*handleOut
|
||||
// SYS_OPEN_NAMED_QUEUE (61) a0=*name a1=*handleOut
|
||||
//
|
||||
// Looks up 'name' in the registry and allocates a handle to the queue in the
|
||||
// calling process's handle table. Returns STATUS_NOT_FOUND if no match.
|
||||
@@ -1083,7 +1096,7 @@ static uint64_t SyscallOpenNamedQueue(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_QUEUE_DUPLICATE (61) a0=handle a1=targetPid a2=*handleOut
|
||||
// SYS_QUEUE_DUPLICATE (62) a0=handle a1=targetPid a2=*handleOut
|
||||
//
|
||||
// Looks up the QUEUE behind 'handle' in the CALLER's table, then allocates
|
||||
// a new handle for the same object in the TARGET process's table.
|
||||
@@ -1115,7 +1128,7 @@ static uint64_t SyscallQueueDuplicate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_NAMED_QUEUE_OWNER_PID (62) a0=*name a1=*pidOut
|
||||
// SYS_NAMED_QUEUE_OWNER_PID (63) a0=*name a1=*pidOut
|
||||
//
|
||||
// Returns the ProcessId of whoever published the named queue.
|
||||
// Lets a client get the publisher's PID so it can duplicate one of its
|
||||
@@ -1177,40 +1190,41 @@ static const SYSCALL_HANDLER gSyscallTable[SYS_MAX] = {
|
||||
/* 26 SYS_CLOSE_HANDLE */ SyscallCloseHandle,
|
||||
/* 27 SYS_OPEN_FILE */ SyscallOpenFile,
|
||||
/* 28 SYS_READ_FILE */ SyscallReadFile,
|
||||
/* 29 SYS_SEEK_FILE */ SyscallSeekFile,
|
||||
/* 30 SYS_GET_FILE_SIZE */ SyscallGetFileSize,
|
||||
/* 31 SYS_WRITE_FILE */ SyscallWriteFile,
|
||||
/* 32 SYS_CREATE_FILE */ SyscallCreateFile,
|
||||
/* 33 SYS_DELETE_FILE */ SyscallDeleteFile,
|
||||
/* 34 SYS_TRUNCATE_FILE */ SyscallTruncateFile,
|
||||
/* 35 SYS_GET_FILE_POS */ SyscallGetFilePos,
|
||||
/* 29 SYS_WRITE_FILE */ SyscallWriteFile,
|
||||
/* 30 SYS_CREATE_FILE */ SyscallCreateFile,
|
||||
/* 31 SYS_DELETE_FILE */ SyscallDeleteFile,
|
||||
/* 32 SYS_TRUNCATE_FILE */ SyscallTruncateFile,
|
||||
/* 33 SYS_GET_FILE_POS */ SyscallGetFilePos,
|
||||
/* 34 SYS_SEEK_FILE */ SyscallSeekFile,
|
||||
/* 35 SYS_GET_FILE_SIZE */ SyscallGetFileSize,
|
||||
/* 36 SYS_SCREEN_BLIT */ SyscallScreenBlit,
|
||||
/* 37 SYS_SCREEN_CLEAR */ SyscallScreenClear,
|
||||
/* 38 SYS_SCREEN_GET_SIZE */ SyscallScreenGetSize,
|
||||
/* 39 SYS_SCREEN_PUT_CHAR */ SyscallScreenPutChar,
|
||||
/* 40 SYS_KB_POLL */ SyscallKbPoll,
|
||||
/* 41 SYS_KB_READ_CHAR */ SyscallKbReadChar,
|
||||
/* 42 SYS_KB_READ_SCANCODE */ SyscallKbReadScancode,
|
||||
/* 43 SYS_KB_GET_MODIFIERS */ SyscallKbGetModifiers,
|
||||
/* 44 SYS_MOUSE_POLL */ SyscallMousePoll,
|
||||
/* 45 SYS_MOUSE_READ */ SyscallMouseRead,
|
||||
/* 46 SYS_MOUSE_GET_POS */ SyscallMouseGetPos,
|
||||
/* 47 SYS_GET_TICK */ SyscallGetTick,
|
||||
/* 48 SYS_DEBUG_PRINT */ SyscallDebugPrint,
|
||||
/* 49 SYS_CREATE_PROCESS */ SyscallCreateProcess,
|
||||
/* 50 SYS_WAIT_FOR_PROCESS */ SyscallWaitForProcess,
|
||||
/* 51 SYS_GET_PROCESS_EXIT_CODE */ SyscallGetProcessExitCode,
|
||||
/* 52 SYS_WRITE_CONSOLE */ SyscallWriteConsole,
|
||||
/* 53 SYS_OPEN_DIR */ SyscallOpenDir,
|
||||
/* 54 SYS_READ_DIR */ SyscallReadDir,
|
||||
/* 55 SYS_SET_CWD */ SyscallSetCwd,
|
||||
/* 56 SYS_GET_CWD */ SyscallGetCwd,
|
||||
/* 57 SYS_WAIT_THREAD */ SyscallWaitThread,
|
||||
/* 58 SYS_GET_PROCESS_PID */ SyscallGetProcessPid,
|
||||
/* 59 SYS_PUBLISH_QUEUE */ SyscallPublishQueue,
|
||||
/* 60 SYS_OPEN_NAMED_QUEUE */ SyscallOpenNamedQueue,
|
||||
/* 61 SYS_QUEUE_DUPLICATE */ SyscallQueueDuplicate,
|
||||
/* 62 SYS_NAMED_QUEUE_OWNER_PID */ SyscallNamedQueueOwnerPid,
|
||||
/* 41 SYS_KB_IS_KEY_DOWN */ SyscallKbIsKeyDown,
|
||||
/* 42 SYS_KB_READ_CHAR */ SyscallKbReadChar,
|
||||
/* 43 SYS_KB_READ_SCANCODE */ SyscallKbReadScancode,
|
||||
/* 44 SYS_KB_GET_MODIFIERS */ SyscallKbGetModifiers,
|
||||
/* 45 SYS_MOUSE_POLL */ SyscallMousePoll,
|
||||
/* 46 SYS_MOUSE_READ */ SyscallMouseRead,
|
||||
/* 47 SYS_MOUSE_GET_POS */ SyscallMouseGetPos,
|
||||
/* 48 SYS_GET_TICK */ SyscallGetTick,
|
||||
/* 49 SYS_DEBUG_PRINT */ SyscallDebugPrint,
|
||||
/* 50 SYS_CREATE_PROCESS */ SyscallCreateProcess,
|
||||
/* 51 SYS_WAIT_FOR_PROCESS */ SyscallWaitForProcess,
|
||||
/* 52 SYS_GET_PROCESS_EXIT_CODE */ SyscallGetProcessExitCode,
|
||||
/* 53 SYS_WRITE_CONSOLE */ SyscallWriteConsole,
|
||||
/* 54 SYS_OPEN_DIR */ SyscallOpenDir,
|
||||
/* 55 SYS_READ_DIR */ SyscallReadDir,
|
||||
/* 56 SYS_SET_CWD */ SyscallSetCwd,
|
||||
/* 57 SYS_GET_CWD */ SyscallGetCwd,
|
||||
/* 58 SYS_WAIT_THREAD */ SyscallWaitThread,
|
||||
/* 59 SYS_GET_PROCESS_PID */ SyscallGetProcessPid,
|
||||
/* 60 SYS_PUBLISH_QUEUE */ SyscallPublishQueue,
|
||||
/* 61 SYS_OPEN_NAMED_QUEUE */ SyscallOpenNamedQueue,
|
||||
/* 62 SYS_QUEUE_DUPLICATE */ SyscallQueueDuplicate,
|
||||
/* 63 SYS_NAMED_QUEUE_OWNER_PID */ SyscallNamedQueueOwnerPid,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
+5
-6
@@ -203,7 +203,7 @@ static void LoadAndRegisterDll(const char* filename) {
|
||||
// Returns the new PROCESS* with one reference owned by the caller.
|
||||
// Returns NULL on failure.
|
||||
// ---------------------------------------------------------------------------
|
||||
static PROCESS* LaunchUserProcess(const char* filePath) {
|
||||
static PROCESS* LaunchUserProcess(const char* filePath, const char* args) {
|
||||
KSTATUS s;
|
||||
FILE_OBJECT* f;
|
||||
|
||||
@@ -238,17 +238,16 @@ static PROCESS* LaunchUserProcess(const char* filePath) {
|
||||
}
|
||||
DbgPrint("Created process (PID %u) with command line: %s\n", proc->ProcessId, filePath);
|
||||
|
||||
strncpy(proc->Cmdline, filePath, sizeof(proc->Cmdline) - 1);
|
||||
strncpy(proc->Cmdline, args, sizeof(proc->Cmdline) - 1);
|
||||
|
||||
// proc->Cmdline is kernel pool (ffffc000...) - not readable at CPL=3.
|
||||
// Copy into user memory before handing the pointer to the initial thread.
|
||||
size_t cmdlineLen = strlen(proc->Cmdline) + 1;
|
||||
char* userCmdline = (char*)MmAllocateUserMemory(cmdlineLen);
|
||||
char* userCmdline = (char*)MmAllocateUserMemory(sizeof(proc->Cmdline));
|
||||
if (!userCmdline) {
|
||||
DbgPrint("LaunchUserProcess: Failed to allocate user cmdline buffer.\n");
|
||||
return (PROCESS*)0;
|
||||
}
|
||||
memcpy(userCmdline, proc->Cmdline, cmdlineLen);
|
||||
memcpy(userCmdline, proc->Cmdline, sizeof(proc->Cmdline));
|
||||
|
||||
// Parse the raw PE file and map it into executable memory
|
||||
uintptr_t imageBase = 0;
|
||||
@@ -331,7 +330,7 @@ void SystemInitThread(void* arg) {
|
||||
DbgPrint(" -> User Heap: %.2f MB\n", (float)MmGetUserHeapUsage() / (1024.0f * 1024.0f));
|
||||
|
||||
// Launch User-Mode Shell (this will trigger AHCI & FAT32 which CAN safely block now)
|
||||
PROCESS* shellProc = LaunchUserProcess(args->bootInfo->CommandLine);
|
||||
PROCESS* shellProc = LaunchUserProcess("init.exe", args->bootInfo->CommandLine);
|
||||
|
||||
if (shellProc) {
|
||||
KSTATUS ws = KeCreateKernelThread((uintptr_t)ProcessWatcherThread,
|
||||
|
||||
+46
-52
@@ -47,24 +47,24 @@
|
||||
#define SYS_SEM_CREATE 15 // (int32_t initial, int32_t max, uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_SEM_WAIT 16 // (uint32_t handle) -> KSTATUS
|
||||
#define SYS_SEM_TRY_WAIT 17 // (uint32_t handle) -> KSTATUS
|
||||
#define SYS_SEM_SIGNAL 18 // (uint32_t handle) -> void
|
||||
#define SYS_SEM_SIGNAL 18 // (uint32_t handle) -> KSTATUS
|
||||
|
||||
#define SYS_EVENT_CREATE 19 // (uint32_t type, uint32_t initialState, uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_EVENT_SIGNAL 20 // (uint32_t handle) -> void
|
||||
#define SYS_EVENT_CLEAR 21 // (uint32_t handle) -> void
|
||||
#define SYS_EVENT_CREATE 19 // (uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_EVENT_SIGNAL 20 // (uint32_t handle) -> KSTATUS
|
||||
#define SYS_EVENT_CLEAR 21 // (uint32_t handle) -> KSTATUS
|
||||
#define SYS_EVENT_WAIT 22 // (uint32_t handle) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Message Queues
|
||||
// Queue
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_QUEUE_CREATE 23 // (uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_QUEUE_SEND 24 // (uint32_t handle, const QUEUE_MESSAGE* msg, uint32_t blocking) -> KSTATUS
|
||||
#define SYS_QUEUE_RECV 25 // (uint32_t handle, QUEUE_MESSAGE* msg, uint32_t blocking) -> KSTATUS
|
||||
#define SYS_QUEUE_SEND 24 // (uint32_t handle, void* msg, int blocking) -> KSTATUS
|
||||
#define SYS_QUEUE_RECV 25 // (uint32_t handle, void* msg, int blocking) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Handle Management
|
||||
// Handle (unified close for all object types)
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_CLOSE_HANDLE 26 // (uint32_t handle) -> void
|
||||
#define SYS_CLOSE_HANDLE 26 // (uint32_t handle) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// File I/O
|
||||
@@ -72,13 +72,13 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_OPEN_FILE 27 // (const char* path, uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_READ_FILE 28 // (uint32_t handle, void* buf, size_t size, size_t* bytesReadOut) -> KSTATUS
|
||||
#define SYS_SEEK_FILE 29 // (uint32_t handle, uint64_t offset) -> KSTATUS
|
||||
#define SYS_GET_FILE_SIZE 30 // (uint32_t handle) -> uint64_t
|
||||
#define SYS_WRITE_FILE 31 // (uint32_t handle, const void* buf, size_t size, size_t* bytesWrittenOut) -> KSTATUS
|
||||
#define SYS_CREATE_FILE 32 // (const char* path, uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_DELETE_FILE 33 // (const char* path) -> KSTATUS
|
||||
#define SYS_TRUNCATE_FILE 34 // (uint32_t handle, uint64_t newSize) -> KSTATUS
|
||||
#define SYS_GET_FILE_POS 35 // (uint32_t handle) -> uint64_t
|
||||
#define SYS_WRITE_FILE 29 // (uint32_t handle, const void* buf, size_t size, size_t* bytesWrittenOut) -> KSTATUS
|
||||
#define SYS_CREATE_FILE 30 // (const char* path, uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_DELETE_FILE 31 // (const char* path) -> KSTATUS
|
||||
#define SYS_TRUNCATE_FILE 32 // (uint32_t handle, uint64_t newSize) -> KSTATUS
|
||||
#define SYS_GET_FILE_POS 33 // (uint32_t handle) -> uint64_t
|
||||
#define SYS_SEEK_FILE 34 // (uint32_t handle, uint64_t offset) -> KSTATUS
|
||||
#define SYS_GET_FILE_SIZE 35 // (uint32_t handle) -> uint64_t
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Screen / Graphics
|
||||
@@ -92,80 +92,74 @@
|
||||
// Keyboard
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_KB_POLL 40 // () -> uint32_t (1 if key available, 0 otherwise)
|
||||
#define SYS_KB_READ_CHAR 41 // () -> char (blocks, yields while waiting)
|
||||
#define SYS_KB_READ_SCANCODE 42 // () -> uint8_t (blocks, yields while waiting)
|
||||
#define SYS_KB_GET_MODIFIERS 43 // () -> uint32_t (current modifier bitmask)
|
||||
#define SYS_KB_IS_KEY_DOWN 41 // (int scancode) -> uint32_t (1 if down, 0 otherwise)
|
||||
#define SYS_KB_READ_CHAR 42 // () -> char (blocks, yields while waiting)
|
||||
#define SYS_KB_READ_SCANCODE 43 // () -> uint8_t (blocks, yields while waiting)
|
||||
#define SYS_KB_GET_MODIFIERS 44 // () -> uint32_t (current modifier bitmask)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Mouse
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_MOUSE_POLL 44 // () -> uint32_t (1 if packet waiting, 0 otherwise)
|
||||
#define SYS_MOUSE_READ 45 // (int* dx, int* dy, uint8_t* buttons) -> uint32_t (1=ok, 0=empty)
|
||||
#define SYS_MOUSE_GET_POS 46 // (int* x, int* y) -> void
|
||||
#define SYS_MOUSE_POLL 45 // () -> uint32_t (1 if packet waiting, 0 otherwise)
|
||||
#define SYS_MOUSE_READ 46 // (int* dx, int* dy, uint8_t* buttons) -> uint32_t (1=ok, 0=empty)
|
||||
#define SYS_MOUSE_GET_POS 47 // (int* x, int* y) -> void
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Timer
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_GET_TICK 47 // () -> uint64_t (milliseconds since boot)
|
||||
#define SYS_GET_TICK 48 // () -> uint64_t (milliseconds since boot)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Debug
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_DEBUG_PRINT 48 // (const char* str) -> void
|
||||
#define SYS_DEBUG_PRINT 49 // (const char* str) -> void
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Process launch & lifecycle
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_CREATE_PROCESS 49 // (const char* path, uint32_t* handleOut, const char* cmdline) -> KSTATUS
|
||||
#define SYS_WAIT_FOR_PROCESS 50 // (uint32_t handle) -> KSTATUS
|
||||
#define SYS_GET_PROCESS_EXIT_CODE 51 // (uint32_t handle, int* exitCodeOut) -> KSTATUS
|
||||
#define SYS_CREATE_PROCESS 50 // (const char* path, const char* args, uint32_t* pidOut) -> KSTATUS
|
||||
#define SYS_WAIT_FOR_PROCESS 51 // (uint32_t pid) -> KSTATUS
|
||||
#define SYS_GET_PROCESS_EXIT_CODE 52 // (uint32_t pid, int* exitCodeOut) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Console output (white text, distinct from green SYS_DEBUG_PRINT)
|
||||
// Console output (white text, for user programs)
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_WRITE_CONSOLE 52 // (const char* buf, size_t len) -> void
|
||||
#define SYS_WRITE_CONSOLE 53 // (const char* str, size_t len) -> void
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Directory enumeration
|
||||
// (Close the handle via SYS_CLOSE_HANDLE like any other object.)
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_OPEN_DIR 53 // (const char* dirPath, uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_READ_DIR 54 // (uint32_t handle, KDIR_ENTRY* entryOut) -> KSTATUS
|
||||
#define SYS_OPEN_DIR 54 // (const char* path, uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_READ_DIR 55 // (uint32_t handle, DirEntry* entryOut) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Current Working Directory
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_SET_CWD 55 // (const char* path) -> KSTATUS
|
||||
#define SYS_GET_CWD 56 // (char* buf, size_t size) -> KSTATUS
|
||||
#define SYS_SET_CWD 56 // (const char* path) -> KSTATUS
|
||||
#define SYS_GET_CWD 57 // (char* buf, size_t buflen) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Thread join
|
||||
// Thread join (used by pthread_join in posix.dll)
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_WAIT_THREAD 57 // (uint32_t tid) -> KSTATUS
|
||||
// Blocks until the thread with that TID exits.
|
||||
// Returns STATUS_NOT_FOUND if TID unknown.
|
||||
#define SYS_WAIT_THREAD 58 // (uint32_t tid) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Process PID query (needed by posix_spawn -> waitpid)
|
||||
// Process PID query (used by posix_spawn -> waitpid in posix.dll)
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_GET_PROCESS_PID 58 // (uint32_t procHandle, uint32_t* pidOut) -> KSTATUS
|
||||
#define SYS_GET_PROCESS_PID 59 // (uint32_t pid) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Named Queue Registry
|
||||
// SysPublishQueue - register a queue under a name (call once at startup)
|
||||
// SysOpenNamedQueue - resolve a name to a handle (retry until SUCCESS)
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_PUBLISH_QUEUE 59 // (const char* name, uint32_t queueHandle) -> KSTATUS
|
||||
#define SYS_OPEN_NAMED_QUEUE 60 // (const char* name, uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_PUBLISH_QUEUE 60 // (const char* name, uint32_t queueHandle) -> KSTATUS
|
||||
#define SYS_OPEN_NAMED_QUEUE 61 // (const char* name, uint32_t* handleOut) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Handle Duplication
|
||||
// Handle duplication
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_QUEUE_DUPLICATE 61 // (uint32_t handle, uint32_t targetPid, uint32_t* handleOut) -> KSTATUS
|
||||
// Duplicates a queue handle into another process's handle table.
|
||||
// Returns the new handle value (valid in targetPid's space) via *handleOut.
|
||||
#define SYS_NAMED_QUEUE_OWNER_PID 62 // (const char* name, uint32_t* pidOut) -> KSTATUS
|
||||
// Returns the ProcessId of whoever published the named queue.
|
||||
#define SYS_QUEUE_DUPLICATE 62 // (uint32_t handle, uint32_t targetPid, uint32_t* handleOut) -> KSTATUS
|
||||
#define SYS_NAMED_QUEUE_OWNER_PID 63 // (const char* name, uint32_t* pidOut) -> KSTATUS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sentinel
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SYS_MAX 63
|
||||
#define SYS_MAX 64
|
||||
+29
-95
@@ -1,102 +1,11 @@
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Win32 imports & definitions
|
||||
// ---------------------------------------------------------------------------
|
||||
_Noreturn void ExitProcess(unsigned int code);
|
||||
void OutputDebugStringA(const char* s);
|
||||
|
||||
typedef void* HANDLE;
|
||||
typedef unsigned long DWORD;
|
||||
typedef int BOOL;
|
||||
|
||||
#define INVALID_HANDLE_VALUE ((HANDLE)(intptr_t)-1)
|
||||
#define INFINITE 0xFFFFFFFFUL
|
||||
#define STD_INPUT_HANDLE ((DWORD)-10)
|
||||
#define STD_OUTPUT_HANDLE ((DWORD)-11)
|
||||
#define MAX_PATH 260
|
||||
|
||||
// File I/O constants
|
||||
#define GENERIC_READ 0x80000000L
|
||||
#define GENERIC_WRITE 0x40000000L
|
||||
#define OPEN_EXISTING 3
|
||||
#define CREATE_ALWAYS 2
|
||||
#define FILE_SHARE_READ 0x00000001
|
||||
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
|
||||
|
||||
HANDLE GetStdHandle(DWORD nStdHandle);
|
||||
DWORD GetLastError();
|
||||
|
||||
BOOL ReadConsoleA(HANDLE hConsoleInput, void* lpBuffer,
|
||||
DWORD nNumberOfCharsToRead, DWORD* lpNumberOfCharsRead,
|
||||
void* pInputControl);
|
||||
|
||||
BOOL WriteConsoleA(HANDLE hConsoleOutput, const void* lpBuffer,
|
||||
DWORD nNumberOfCharsToWrite, DWORD* lpNumberOfCharsWritten,
|
||||
void* lpReserved);
|
||||
|
||||
typedef struct {
|
||||
DWORD cb;
|
||||
char* lpReserved;
|
||||
char* lpDesktop;
|
||||
char* lpTitle;
|
||||
DWORD dwX, dwY, dwXSize, dwYSize;
|
||||
DWORD dwXCountChars, dwYCountChars;
|
||||
DWORD dwFillAttribute, dwFlags;
|
||||
unsigned short wShowWindow, cbReserved2;
|
||||
unsigned char* lpReserved2;
|
||||
HANDLE hStdInput, hStdOutput, hStdError;
|
||||
} STARTUPINFOA;
|
||||
|
||||
typedef struct {
|
||||
HANDLE hProcess;
|
||||
HANDLE hThread;
|
||||
DWORD dwProcessId;
|
||||
DWORD dwThreadId;
|
||||
} PROCESS_INFORMATION;
|
||||
|
||||
typedef struct _FILETIME {
|
||||
DWORD dwLowDateTime;
|
||||
DWORD dwHighDateTime;
|
||||
} FILETIME;
|
||||
|
||||
typedef struct _WIN32_FIND_DATAA {
|
||||
DWORD dwFileAttributes;
|
||||
FILETIME ftCreationTime;
|
||||
FILETIME ftLastAccessTime;
|
||||
FILETIME ftLastWriteTime;
|
||||
DWORD nFileSizeHigh;
|
||||
DWORD nFileSizeLow;
|
||||
DWORD dwReserved0;
|
||||
DWORD dwReserved1;
|
||||
char cFileName[MAX_PATH];
|
||||
char cAlternateFileName[14];
|
||||
} WIN32_FIND_DATAA;
|
||||
|
||||
BOOL CreateProcessA(const char* lpApp, char* lpCmdLine,
|
||||
void* lpPA, void* lpTA, BOOL bInherit,
|
||||
DWORD dwFlags, void* lpEnv, const char* lpDir,
|
||||
STARTUPINFOA* lpSI, PROCESS_INFORMATION* lpPI);
|
||||
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMs);
|
||||
BOOL GetExitCodeProcess(HANDLE hProcess, DWORD* lpExitCode);
|
||||
BOOL CloseHandle(HANDLE hObject);
|
||||
|
||||
// File operation imports
|
||||
HANDLE FindFirstFileA(const char* lpFileName, WIN32_FIND_DATAA* lpFindFileData);
|
||||
BOOL FindNextFileA(HANDLE hFindFile, WIN32_FIND_DATAA* lpFindFileData);
|
||||
BOOL FindClose(HANDLE hFindFile);
|
||||
BOOL SetCurrentDirectoryA(const char* lpPathName);
|
||||
BOOL DeleteFileA(const char* lpFileName);
|
||||
HANDLE CreateFileA(const char* lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
void* lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
BOOL ReadFile(HANDLE hFile, void* lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
DWORD* lpNumberOfBytesRead, void* lpOverlapped);
|
||||
BOOL WriteFile(HANDLE hFile, const void* lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
DWORD* lpNumberOfBytesWritten, void* lpOverlapped);
|
||||
// !Made-up! clear console api.
|
||||
BOOL ClearConsoleScreenBuffer(HANDLE hConsole);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Global handles
|
||||
@@ -129,6 +38,24 @@ static void printUInt(uint32_t n) {
|
||||
print(rev);
|
||||
}
|
||||
|
||||
static void printInt(int32_t n) {
|
||||
char buf[12];
|
||||
int i = 0;
|
||||
uint32_t val = (n < 0) ? (print("-"), (uint32_t)-(n + 1) + 1) : (uint32_t)n;
|
||||
|
||||
if (val == 0) { print("0"); return; }
|
||||
|
||||
while (val > 0) {
|
||||
buf[i++] = (char)('0' + (val % 10));
|
||||
val /= 10;
|
||||
}
|
||||
|
||||
while (i > 0) {
|
||||
char c[2] = { buf[--i], '\0' };
|
||||
print(c); // Assumes print() handles strings
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Line editor
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -280,6 +207,11 @@ static int runCommand(const char* cmd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "clear") == 0) {
|
||||
ClearConsoleScreenBuffer(hOut);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "dir") == 0) {
|
||||
cmd_dir();
|
||||
return 0;
|
||||
@@ -338,6 +270,8 @@ static int runCommand(const char* cmd) {
|
||||
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
|
||||
FlushConsoleInputBuffer(hOut);
|
||||
|
||||
DWORD exitCode = 0;
|
||||
GetExitCodeProcess(pi.hProcess, &exitCode);
|
||||
CloseHandle(pi.hProcess);
|
||||
@@ -347,7 +281,7 @@ static int runCommand(const char* cmd) {
|
||||
print("shell: '");
|
||||
print(cmd);
|
||||
print("' exited with code ");
|
||||
printUInt(exitCode);
|
||||
printInt(exitCode);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
|
||||
+66
-108
@@ -1,110 +1,68 @@
|
||||
; syscall_nr.inc - assembled from syscall_nr.h for use in .asm files
|
||||
; Keep in sync with syscall_nr.h and ke_syscall.c.
|
||||
; syscall_nr.inc - auto-synced with syscall_nr.h and ke_syscall.c
|
||||
|
||||
; Process & Thread
|
||||
SYS_EXIT_PROCESS EQU 0
|
||||
SYS_EXIT_THREAD EQU 1
|
||||
SYS_CREATE_THREAD EQU 2
|
||||
SYS_GET_CURRENT_TID EQU 3
|
||||
SYS_GET_CURRENT_PID EQU 4
|
||||
SYS_YIELD EQU 5
|
||||
SYS_SLEEP EQU 6
|
||||
SYS_SET_THREAD_PRIORITY EQU 7
|
||||
SYS_EXIT_PROCESS EQU 0
|
||||
SYS_EXIT_THREAD EQU 1
|
||||
SYS_CREATE_THREAD EQU 2
|
||||
SYS_GET_CURRENT_TID EQU 3
|
||||
SYS_GET_CURRENT_PID EQU 4
|
||||
SYS_YIELD EQU 5
|
||||
SYS_SLEEP EQU 6
|
||||
SYS_SET_THREAD_PRIORITY EQU 7
|
||||
SYS_ALLOC EQU 8
|
||||
SYS_FREE EQU 9
|
||||
SYS_REALLOC EQU 10
|
||||
SYS_MUTEX_CREATE EQU 11
|
||||
SYS_MUTEX_ACQUIRE EQU 12
|
||||
SYS_MUTEX_TRY_ACQUIRE EQU 13
|
||||
SYS_MUTEX_RELEASE EQU 14
|
||||
SYS_SEM_CREATE EQU 15
|
||||
SYS_SEM_WAIT EQU 16
|
||||
SYS_SEM_TRY_WAIT EQU 17
|
||||
SYS_SEM_SIGNAL EQU 18
|
||||
SYS_EVENT_CREATE EQU 19
|
||||
SYS_EVENT_SIGNAL EQU 20
|
||||
SYS_EVENT_CLEAR EQU 21
|
||||
SYS_EVENT_WAIT EQU 22
|
||||
SYS_QUEUE_CREATE EQU 23
|
||||
SYS_QUEUE_SEND EQU 24
|
||||
SYS_QUEUE_RECV EQU 25
|
||||
SYS_CLOSE_HANDLE EQU 26
|
||||
SYS_OPEN_FILE EQU 27
|
||||
SYS_READ_FILE EQU 28
|
||||
SYS_WRITE_FILE EQU 29
|
||||
SYS_CREATE_FILE EQU 30
|
||||
SYS_DELETE_FILE EQU 31
|
||||
SYS_TRUNCATE_FILE EQU 32
|
||||
SYS_GET_FILE_POS EQU 33
|
||||
SYS_SEEK_FILE EQU 34
|
||||
SYS_GET_FILE_SIZE EQU 35
|
||||
SYS_SCREEN_BLIT EQU 36
|
||||
SYS_SCREEN_CLEAR EQU 37
|
||||
SYS_SCREEN_GET_SIZE EQU 38
|
||||
SYS_SCREEN_PUT_CHAR EQU 39
|
||||
SYS_KB_POLL EQU 40
|
||||
SYS_KB_IS_KEY_DOWN EQU 41
|
||||
SYS_KB_READ_CHAR EQU 42
|
||||
SYS_KB_READ_SCANCODE EQU 43
|
||||
SYS_KB_GET_MODIFIERS EQU 44
|
||||
SYS_MOUSE_POLL EQU 45
|
||||
SYS_MOUSE_READ EQU 46
|
||||
SYS_MOUSE_GET_POS EQU 47
|
||||
SYS_GET_TICK EQU 48
|
||||
SYS_DEBUG_PRINT EQU 49
|
||||
SYS_CREATE_PROCESS EQU 50
|
||||
SYS_WAIT_FOR_PROCESS EQU 51
|
||||
SYS_GET_PROCESS_EXIT_CODE EQU 52
|
||||
SYS_WRITE_CONSOLE EQU 53
|
||||
SYS_OPEN_DIR EQU 54
|
||||
SYS_READ_DIR EQU 55
|
||||
SYS_SET_CWD EQU 56
|
||||
SYS_GET_CWD EQU 57
|
||||
SYS_WAIT_THREAD EQU 58
|
||||
SYS_GET_PROCESS_PID EQU 59
|
||||
SYS_PUBLISH_QUEUE EQU 60
|
||||
SYS_OPEN_NAMED_QUEUE EQU 61
|
||||
SYS_QUEUE_DUPLICATE EQU 62
|
||||
SYS_NAMED_QUEUE_OWNER_PID EQU 63
|
||||
|
||||
; Memory
|
||||
SYS_ALLOC EQU 8
|
||||
SYS_FREE EQU 9
|
||||
SYS_REALLOC EQU 10
|
||||
|
||||
; Mutex
|
||||
SYS_MUTEX_CREATE EQU 11
|
||||
SYS_MUTEX_ACQUIRE EQU 12
|
||||
SYS_MUTEX_TRY_ACQUIRE EQU 13
|
||||
SYS_MUTEX_RELEASE EQU 14
|
||||
|
||||
; Semaphore
|
||||
SYS_SEM_CREATE EQU 15
|
||||
SYS_SEM_WAIT EQU 16
|
||||
SYS_SEM_TRY_WAIT EQU 17
|
||||
SYS_SEM_SIGNAL EQU 18
|
||||
|
||||
; Event
|
||||
SYS_EVENT_CREATE EQU 19
|
||||
SYS_EVENT_SIGNAL EQU 20
|
||||
SYS_EVENT_CLEAR EQU 21
|
||||
SYS_EVENT_WAIT EQU 22
|
||||
|
||||
; Queue
|
||||
SYS_QUEUE_CREATE EQU 23
|
||||
SYS_QUEUE_SEND EQU 24
|
||||
SYS_QUEUE_RECV EQU 25
|
||||
|
||||
; Handle (unified - one close for every object type)
|
||||
SYS_CLOSE_HANDLE EQU 26
|
||||
|
||||
; File I/O
|
||||
SYS_OPEN_FILE EQU 27
|
||||
SYS_READ_FILE EQU 28
|
||||
SYS_SEEK_FILE EQU 29
|
||||
SYS_GET_FILE_SIZE EQU 30
|
||||
SYS_WRITE_FILE EQU 31 ; handle, buf, size, *bytesWritten
|
||||
SYS_CREATE_FILE EQU 32 ; *path, *handleOut
|
||||
SYS_DELETE_FILE EQU 33 ; *path
|
||||
SYS_TRUNCATE_FILE EQU 34 ; handle, newSize
|
||||
SYS_GET_FILE_POS EQU 35 ; handle -> current offset
|
||||
|
||||
; Screen
|
||||
SYS_SCREEN_BLIT EQU 36
|
||||
SYS_SCREEN_CLEAR EQU 37
|
||||
SYS_SCREEN_GET_SIZE EQU 38
|
||||
SYS_SCREEN_PUT_CHAR EQU 39
|
||||
|
||||
; Keyboard
|
||||
SYS_KB_POLL EQU 40
|
||||
SYS_KB_READ_CHAR EQU 41
|
||||
SYS_KB_READ_SCANCODE EQU 42
|
||||
SYS_KB_GET_MODIFIERS EQU 43
|
||||
|
||||
; Mouse
|
||||
SYS_MOUSE_POLL EQU 44
|
||||
SYS_MOUSE_READ EQU 45
|
||||
SYS_MOUSE_GET_POS EQU 46
|
||||
|
||||
; Timer
|
||||
SYS_GET_TICK EQU 47
|
||||
|
||||
; Debug
|
||||
SYS_DEBUG_PRINT EQU 48
|
||||
|
||||
; Process launch & lifecycle
|
||||
SYS_CREATE_PROCESS EQU 49
|
||||
SYS_WAIT_FOR_PROCESS EQU 50
|
||||
SYS_GET_PROCESS_EXIT_CODE EQU 51
|
||||
|
||||
; Console output
|
||||
SYS_WRITE_CONSOLE EQU 52
|
||||
|
||||
; Directory enumeration
|
||||
SYS_OPEN_DIR EQU 53
|
||||
SYS_READ_DIR EQU 54
|
||||
|
||||
; Current Working Directory
|
||||
SYS_SET_CWD EQU 55
|
||||
SYS_GET_CWD EQU 56
|
||||
|
||||
; Thread join
|
||||
SYS_WAIT_THREAD EQU 57 ; a0=tid -> KSTATUS
|
||||
|
||||
; Process PID query
|
||||
SYS_GET_PROCESS_PID EQU 58 ; a0=procHandle a1=*pidOut -> KSTATUS
|
||||
|
||||
; Named Queue Registry
|
||||
SYS_PUBLISH_QUEUE EQU 59 ; a0=*name a1=queueHandle -> KSTATUS
|
||||
SYS_OPEN_NAMED_QUEUE EQU 60 ; a0=*name a1=*handleOut -> KSTATUS
|
||||
|
||||
; Handle duplication
|
||||
SYS_QUEUE_DUPLICATE EQU 61 ; a0=handle a1=targetPid a2=*handleOut -> KSTATUS
|
||||
SYS_NAMED_QUEUE_OWNER_PID EQU 62 ; a0=*name a1=*pidOut -> KSTATUS
|
||||
|
||||
; Sentinel
|
||||
SYS_MAX EQU 63
|
||||
SYS_MAX EQU 64
|
||||
@@ -49,153 +49,154 @@ ENDM
|
||||
; ---------------------------------------------------------------------------
|
||||
; Process & Thread
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 ExitProcess, SYS_EXIT_PROCESS
|
||||
SYSCALL_STUB2 ExitThread, SYS_EXIT_THREAD
|
||||
SYSCALL_STUB2 CreateThread, SYS_CREATE_THREAD
|
||||
SYSCALL_STUB2 GetCurrentTid, SYS_GET_CURRENT_TID
|
||||
SYSCALL_STUB2 GetCurrentPid, SYS_GET_CURRENT_PID
|
||||
SYSCALL_STUB2 Yield, SYS_YIELD
|
||||
SYSCALL_STUB2 Sleep, SYS_SLEEP
|
||||
SYSCALL_STUB2 SetThreadPriority, SYS_SET_THREAD_PRIORITY
|
||||
SYSCALL_STUB2 ExitProcess, SYS_EXIT_PROCESS ; (int exitCode) -> void
|
||||
SYSCALL_STUB2 ExitThread, SYS_EXIT_THREAD ; (int exitCode) -> void
|
||||
SYSCALL_STUB2 CreateThread, SYS_CREATE_THREAD ; (uint64_t entry, uint64_t arg, uint32_t priority, uint32_t* tidOut) -> KSTATUS
|
||||
SYSCALL_STUB2 GetCurrentTid, SYS_GET_CURRENT_TID ; () -> uint32_t
|
||||
SYSCALL_STUB2 GetCurrentPid, SYS_GET_CURRENT_PID ; () -> uint32_t
|
||||
SYSCALL_STUB2 Yield, SYS_YIELD ; () -> void
|
||||
SYSCALL_STUB2 Sleep, SYS_SLEEP ; (uint32_t ms) -> void
|
||||
SYSCALL_STUB2 SetThreadPriority, SYS_SET_THREAD_PRIORITY ; (uint32_t priority) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Memory
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 Alloc, SYS_ALLOC
|
||||
SYSCALL_STUB2 Free, SYS_FREE
|
||||
SYSCALL_STUB2 Realloc, SYS_REALLOC
|
||||
SYSCALL_STUB2 Alloc, SYS_ALLOC ; (size_t size) -> void* (NULL on failure)
|
||||
SYSCALL_STUB2 Free, SYS_FREE ; (void* ptr, size_t size) -> void
|
||||
SYSCALL_STUB2 Realloc, SYS_REALLOC ; (void* ptr, size_t newSize) -> void*
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Mutex
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 MutexCreate, SYS_MUTEX_CREATE
|
||||
SYSCALL_STUB2 MutexAcquire, SYS_MUTEX_ACQUIRE
|
||||
SYSCALL_STUB2 MutexTryAcquire, SYS_MUTEX_TRY_ACQUIRE
|
||||
SYSCALL_STUB2 MutexRelease, SYS_MUTEX_RELEASE
|
||||
SYSCALL_STUB2 MutexCreate, SYS_MUTEX_CREATE ; (uint32_t* handleOut) -> KSTATUS
|
||||
SYSCALL_STUB2 MutexAcquire, SYS_MUTEX_ACQUIRE ; (uint32_t handle) -> KSTATUS
|
||||
SYSCALL_STUB2 MutexTryAcquire, SYS_MUTEX_TRY_ACQUIRE ; (uint32_t handle) -> KSTATUS
|
||||
SYSCALL_STUB2 MutexRelease, SYS_MUTEX_RELEASE ; (uint32_t handle) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Semaphore
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 SemCreate, SYS_SEM_CREATE
|
||||
SYSCALL_STUB2 SemWait, SYS_SEM_WAIT
|
||||
SYSCALL_STUB2 SemTryWait, SYS_SEM_TRY_WAIT
|
||||
SYSCALL_STUB2 SemSignal, SYS_SEM_SIGNAL
|
||||
SYSCALL_STUB2 SemCreate, SYS_SEM_CREATE ; (int32_t initial, int32_t max, uint32_t* handleOut) -> KSTATUS
|
||||
SYSCALL_STUB2 SemWait, SYS_SEM_WAIT ; (uint32_t handle) -> KSTATUS
|
||||
SYSCALL_STUB2 SemTryWait, SYS_SEM_TRY_WAIT ; (uint32_t handle) -> KSTATUS
|
||||
SYSCALL_STUB2 SemSignal, SYS_SEM_SIGNAL ; (uint32_t handle) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Event
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 EventCreate, SYS_EVENT_CREATE
|
||||
SYSCALL_STUB2 EventSignal, SYS_EVENT_SIGNAL
|
||||
SYSCALL_STUB2 EventClear, SYS_EVENT_CLEAR
|
||||
SYSCALL_STUB2 EventWait, SYS_EVENT_WAIT
|
||||
SYSCALL_STUB2 EventCreate, SYS_EVENT_CREATE ; (uint32_t* handleOut) -> KSTATUS
|
||||
SYSCALL_STUB2 EventSignal, SYS_EVENT_SIGNAL ; (uint32_t handle) -> KSTATUS
|
||||
SYSCALL_STUB2 EventClear, SYS_EVENT_CLEAR ; (uint32_t handle) -> KSTATUS
|
||||
SYSCALL_STUB2 EventWait, SYS_EVENT_WAIT ; (uint32_t handle) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Queue
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 QueueCreate, SYS_QUEUE_CREATE
|
||||
SYSCALL_STUB2 QueueSend, SYS_QUEUE_SEND
|
||||
SYSCALL_STUB2 QueueRecv, SYS_QUEUE_RECV
|
||||
SYSCALL_STUB2 QueueCreate, SYS_QUEUE_CREATE ; (uint32_t* handleOut) -> KSTATUS
|
||||
SYSCALL_STUB2 QueueSend, SYS_QUEUE_SEND ; (uint32_t handle, void* msg, int blocking) -> KSTATUS
|
||||
SYSCALL_STUB2 QueueRecv, SYS_QUEUE_RECV ; (uint32_t handle, void* msg, int blocking) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Handle (unified - use for files, mutexes, semaphores, events, queues)
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 CloseHandle, SYS_CLOSE_HANDLE
|
||||
SYSCALL_STUB2 CloseHandle, SYS_CLOSE_HANDLE ; (uint32_t handle) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; File I/O
|
||||
; (To close: SysCloseHandle(handle) - no dedicated SysCloseFile)
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 OpenFile, SYS_OPEN_FILE
|
||||
SYSCALL_STUB2 ReadFile, SYS_READ_FILE
|
||||
SYSCALL_STUB2 SeekFile, SYS_SEEK_FILE
|
||||
SYSCALL_STUB2 GetFileSize, SYS_GET_FILE_SIZE
|
||||
SYSCALL_STUB2 WriteFile, SYS_WRITE_FILE
|
||||
SYSCALL_STUB2 CreateFile, SYS_CREATE_FILE
|
||||
SYSCALL_STUB2 DeleteFile, SYS_DELETE_FILE
|
||||
SYSCALL_STUB2 TruncateFile, SYS_TRUNCATE_FILE
|
||||
SYSCALL_STUB2 GetFilePos, SYS_GET_FILE_POS
|
||||
SYSCALL_STUB2 OpenFile, SYS_OPEN_FILE ; (const char* path, uint32_t* handleOut) -> KSTATUS
|
||||
SYSCALL_STUB2 ReadFile, SYS_READ_FILE ; (uint32_t handle, void* buf, size_t size, size_t* bytesReadOut) -> KSTATUS
|
||||
SYSCALL_STUB2 WriteFile, SYS_WRITE_FILE ; (uint32_t handle, const void* buf, size_t size, size_t* bytesWrittenOut) -> KSTATUS
|
||||
SYSCALL_STUB2 CreateFile, SYS_CREATE_FILE ; (const char* path, uint32_t* handleOut) -> KSTATUS
|
||||
SYSCALL_STUB2 DeleteFile, SYS_DELETE_FILE ; (const char* path) -> KSTATUS
|
||||
SYSCALL_STUB2 TruncateFile, SYS_TRUNCATE_FILE ; (uint32_t handle, uint64_t newSize) -> KSTATUS
|
||||
SYSCALL_STUB2 GetFilePos, SYS_GET_FILE_POS ; (uint32_t handle) -> uint64_t
|
||||
SYSCALL_STUB2 SeekFile, SYS_SEEK_FILE ; (uint32_t handle, uint64_t offset) -> KSTATUS
|
||||
SYSCALL_STUB2 GetFileSize, SYS_GET_FILE_SIZE ; (uint32_t handle) -> uint64_t
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Screen
|
||||
; SysScreenBlit has 5 args (x, y, w, h, pixels) - needs SYSCALL_STUB6.
|
||||
; SysScreenPutChar has 5 args (c, x, y, fg, bg) - needs SYSCALL_STUB6.
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB6 ScreenBlit, SYS_SCREEN_BLIT
|
||||
SYSCALL_STUB2 ScreenClear, SYS_SCREEN_CLEAR
|
||||
SYSCALL_STUB2 ScreenGetSize, SYS_SCREEN_GET_SIZE
|
||||
SYSCALL_STUB6 ScreenPutChar, SYS_SCREEN_PUT_CHAR
|
||||
SYSCALL_STUB6 ScreenBlit, SYS_SCREEN_BLIT ; (int x, int y, int w, int h, const uint32_t* pixels) -> void
|
||||
SYSCALL_STUB2 ScreenClear, SYS_SCREEN_CLEAR ; (uint32_t color) -> void
|
||||
SYSCALL_STUB2 ScreenGetSize, SYS_SCREEN_GET_SIZE ; (int* widthOut, int* heightOut) -> void
|
||||
SYSCALL_STUB6 ScreenPutChar, SYS_SCREEN_PUT_CHAR ; (char c, int x, int y, uint32_t fg, uint32_t bg) -> void
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Keyboard
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 KbPoll, SYS_KB_POLL
|
||||
SYSCALL_STUB2 KbReadChar, SYS_KB_READ_CHAR
|
||||
SYSCALL_STUB2 KbReadScancode, SYS_KB_READ_SCANCODE
|
||||
SYSCALL_STUB2 KbGetModifiers, SYS_KB_GET_MODIFIERS
|
||||
SYSCALL_STUB2 KbPoll, SYS_KB_POLL ; () -> uint32_t (1 if key available, 0 otherwise)
|
||||
SYSCALL_STUB2 KbIsKeyDown, SYS_KB_IS_KEY_DOWN ; (int scancode) -> uint32_t (1 if down, 0 otherwise)
|
||||
SYSCALL_STUB2 KbReadChar, SYS_KB_READ_CHAR ; () -> char (blocks, yields while waiting)
|
||||
SYSCALL_STUB2 KbReadScancode, SYS_KB_READ_SCANCODE ; () -> uint8_t (blocks, yields while waiting)
|
||||
SYSCALL_STUB2 KbGetModifiers, SYS_KB_GET_MODIFIERS ; () -> uint32_t (current modifier bitmask)
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Mouse
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 MousePoll, SYS_MOUSE_POLL
|
||||
SYSCALL_STUB2 MouseRead, SYS_MOUSE_READ
|
||||
SYSCALL_STUB2 MouseGetPos, SYS_MOUSE_GET_POS
|
||||
SYSCALL_STUB2 MousePoll, SYS_MOUSE_POLL ; () -> uint32_t (1 if packet waiting, 0 otherwise)
|
||||
SYSCALL_STUB2 MouseRead, SYS_MOUSE_READ ; (int* dx, int* dy, uint8_t* buttons) -> uint32_t (1=ok, 0=empty)
|
||||
SYSCALL_STUB2 MouseGetPos, SYS_MOUSE_GET_POS ; (int* x, int* y) -> void
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Timer
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 GetTick, SYS_GET_TICK
|
||||
SYSCALL_STUB2 GetTick, SYS_GET_TICK ; () -> uint64_t (milliseconds since boot)
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Debug
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 DebugPrint, SYS_DEBUG_PRINT
|
||||
SYSCALL_STUB2 DebugPrint, SYS_DEBUG_PRINT ; (const char* str) -> void
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Process launch & lifecycle
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 CreateProcess, SYS_CREATE_PROCESS
|
||||
SYSCALL_STUB2 WaitForProcess, SYS_WAIT_FOR_PROCESS
|
||||
SYSCALL_STUB2 GetProcessExitCode, SYS_GET_PROCESS_EXIT_CODE
|
||||
SYSCALL_STUB2 CreateProcess, SYS_CREATE_PROCESS ; (const char* path, const char* args, uint32_t* pidOut) -> KSTATUS
|
||||
SYSCALL_STUB2 WaitForProcess, SYS_WAIT_FOR_PROCESS ; (uint32_t pid) -> KSTATUS
|
||||
SYSCALL_STUB2 GetProcessExitCode, SYS_GET_PROCESS_EXIT_CODE ; (uint32_t pid, int* exitCodeOut) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Console output (white text, for user programs)
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 WriteConsole, SYS_WRITE_CONSOLE
|
||||
SYSCALL_STUB2 WriteConsole, SYS_WRITE_CONSOLE ; (const char* str, size_t len) -> void
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Directory enumeration
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 OpenDir, SYS_OPEN_DIR
|
||||
SYSCALL_STUB2 ReadDir, SYS_READ_DIR
|
||||
SYSCALL_STUB2 OpenDir, SYS_OPEN_DIR ; (const char* path, uint32_t* handleOut) -> KSTATUS
|
||||
SYSCALL_STUB2 ReadDir, SYS_READ_DIR ; (uint32_t handle, DirEntry* entryOut) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Current Working Directory
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 SetCwd, SYS_SET_CWD
|
||||
SYSCALL_STUB2 GetCwd, SYS_GET_CWD
|
||||
SYSCALL_STUB2 SetCwd, SYS_SET_CWD ; (const char* path) -> KSTATUS
|
||||
SYSCALL_STUB2 GetCwd, SYS_GET_CWD ; (char* buf, size_t buflen) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Thread join (used by pthread_join in posix.dll)
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 WaitThread, SYS_WAIT_THREAD
|
||||
SYSCALL_STUB2 WaitThread, SYS_WAIT_THREAD ; (uint32_t tid) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Process PID query (used by posix_spawn -> waitpid in posix.dll)
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 GetProcessPid, SYS_GET_PROCESS_PID
|
||||
SYSCALL_STUB2 GetProcessPid, SYS_GET_PROCESS_PID ; (uint32_t pid) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Named Queue Registry
|
||||
; SysPublishQueue - register a queue under a name (call once at startup)
|
||||
; SysOpenNamedQueue - resolve a name to a handle (retry until SUCCESS)
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 PublishQueue, SYS_PUBLISH_QUEUE
|
||||
SYSCALL_STUB2 OpenNamedQueue, SYS_OPEN_NAMED_QUEUE
|
||||
SYSCALL_STUB2 PublishQueue, SYS_PUBLISH_QUEUE ; (const char* name, uint32_t queueHandle) -> KSTATUS
|
||||
SYSCALL_STUB2 OpenNamedQueue, SYS_OPEN_NAMED_QUEUE ; (const char* name, uint32_t* handleOut) -> KSTATUS
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Handle duplication
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 QueueDuplicate, SYS_QUEUE_DUPLICATE
|
||||
SYSCALL_STUB2 NamedQueueOwnerPid, SYS_NAMED_QUEUE_OWNER_PID
|
||||
SYSCALL_STUB2 QueueDuplicate, SYS_QUEUE_DUPLICATE ; (uint32_t handle, uint32_t targetPid, uint32_t* handleOut) -> KSTATUS
|
||||
SYSCALL_STUB2 NamedQueueOwnerPid, SYS_NAMED_QUEUE_OWNER_PID ; (const char* name, uint32_t* pidOut) -> KSTATUS
|
||||
|
||||
END
|
||||
Binary file not shown.
+1
-72
@@ -1,81 +1,10 @@
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
#include "bink.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Win32 Boilerplate & API declarations
|
||||
// ---------------------------------------------------------------------------
|
||||
typedef void* HWND;
|
||||
typedef void* HDC;
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned int UINT;
|
||||
typedef long LONG;
|
||||
typedef int BOOL;
|
||||
|
||||
#define BI_RGB 0L
|
||||
#define DIB_RGB_COLORS 0
|
||||
#define SRCCOPY 0x00CC0020
|
||||
|
||||
#define STD_OUTPUT_HANDLE ((DWORD)-11)
|
||||
|
||||
typedef struct _RECT {
|
||||
LONG left, top, right, bottom;
|
||||
} RECT;
|
||||
|
||||
typedef struct tagPAINTSTRUCT {
|
||||
HDC hdc;
|
||||
BOOL fErase;
|
||||
RECT rcPaint;
|
||||
BOOL fRestore;
|
||||
BOOL fIncUpdate;
|
||||
char rgbReserved[32];
|
||||
} PAINTSTRUCT;
|
||||
|
||||
typedef struct tagBITMAPINFOHEADER {
|
||||
DWORD biSize;
|
||||
LONG biWidth;
|
||||
LONG biHeight;
|
||||
WORD biPlanes;
|
||||
WORD biBitCount;
|
||||
DWORD biCompression;
|
||||
DWORD biSizeImage;
|
||||
LONG biXPelsPerMeter;
|
||||
LONG biYPelsPerMeter;
|
||||
DWORD biClrUsed;
|
||||
DWORD biClrImportant;
|
||||
} BITMAPINFOHEADER;
|
||||
|
||||
typedef struct tagRGBQUAD {
|
||||
unsigned char rgbBlue, rgbGreen, rgbRed, rgbReserved;
|
||||
} RGBQUAD;
|
||||
|
||||
typedef struct tagBITMAPINFO {
|
||||
BITMAPINFOHEADER bmiHeader;
|
||||
RGBQUAD bmiColors[1];
|
||||
} BITMAPINFO;
|
||||
|
||||
// Kernel/Win32 Exports
|
||||
void* GetStdHandle(DWORD nStdHandle);
|
||||
int WriteConsoleA(void* hConsoleOutput, const void* lpBuffer, unsigned int nNumberOfCharsToWrite, unsigned int* lpNumberOfCharsWritten, void* lpReserved);
|
||||
_Noreturn void ExitProcess(unsigned int code);
|
||||
void* HeapAlloc(void* heap, unsigned long flags, size_t size);
|
||||
void* CreateFileA(const char* name, unsigned long access, unsigned long share, void* sa, unsigned long disp, unsigned long flags, void* templ);
|
||||
unsigned long GetFileSize(void* handle, unsigned long* high);
|
||||
int ReadFile(void* handle, void* buf, unsigned long toRead, unsigned long* read, void* overlapped);
|
||||
BOOL CloseHandle(void* hObject);
|
||||
|
||||
// New GDI/User32 Exports
|
||||
HDC BeginPaint(HWND hwnd, PAINTSTRUCT* lpPaint);
|
||||
BOOL EndPaint(HWND hwnd, const PAINTSTRUCT* lpPaint);
|
||||
int StretchDIBits(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight,
|
||||
int xSrc, int ySrc, int SrcWidth, int SrcHeight,
|
||||
const void *lpBits, const BITMAPINFO *lpbmi,
|
||||
UINT iUsage, DWORD rop);
|
||||
|
||||
|
||||
int main(const char* cmdline) {
|
||||
void* h = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
WriteConsoleA(h, "video: starting\n", 16, 0, 0);
|
||||
|
||||
+105
-14
@@ -1,11 +1,20 @@
|
||||
// gdi32.c - Win32 Graphics Device Interface stubs
|
||||
// gdi32.c
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__SSE2__) || defined(_M_X64) || defined(_M_IX86)
|
||||
#include <emmintrin.h>
|
||||
#elif defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(_M_ARM64)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Syscall stubs (from syscall.dll)
|
||||
// ---------------------------------------------------------------------------
|
||||
extern void SysScreenBlit(int x, int y, int w, int h, const uint32_t* pixels);
|
||||
extern void* SysAlloc(size_t size);
|
||||
extern void SysFree(void* ptr, size_t size);
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Win32 Base Types
|
||||
@@ -54,9 +63,17 @@ typedef struct tagBITMAPINFO {
|
||||
RGBQUAD bmiColors[1];
|
||||
} BITMAPINFO;
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// GDI Exports
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Static buffers to persist between function calls
|
||||
static uint32_t* destBuffer = NULL;
|
||||
static int* srcX_map = NULL;
|
||||
static int currentDestCapacity = 0;
|
||||
static int currentXMapCapacity = 0;
|
||||
|
||||
__declspec(dllexport) int StretchDIBits(
|
||||
HDC hdc,
|
||||
int xDest, int yDest, int DestWidth, int DestHeight,
|
||||
@@ -64,20 +81,94 @@ __declspec(dllexport) int StretchDIBits(
|
||||
const void *lpBits, const BITMAPINFO *lpbmi,
|
||||
UINT iUsage, DWORD rop)
|
||||
{
|
||||
(void)hdc; (void)xSrc; (void)ySrc; (void)SrcWidth; (void)SrcHeight;
|
||||
(void)lpbmi; (void)iUsage; (void)rop;
|
||||
(void)hdc; (void)lpbmi; (void)iUsage; (void)rop;
|
||||
|
||||
// Direct mapping to kernel screen blit
|
||||
SysScreenBlit(xDest, yDest, DestWidth, DestHeight, (const uint32_t*)lpBits);
|
||||
// Safety check to prevent division by zero
|
||||
if (DestWidth <= 0 || DestHeight <= 0 || SrcWidth <= 0 || SrcHeight <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle trivial case (1:1 copy) to bypass allocation and scaling overhead
|
||||
if (DestWidth == SrcWidth && DestHeight == SrcHeight && xSrc == 0 && ySrc == 0) {
|
||||
SysScreenBlit(xDest, yDest, DestWidth, DestHeight, (const uint32_t*)lpBits);
|
||||
return DestHeight;
|
||||
}
|
||||
|
||||
const uint32_t* srcPixels = (const uint32_t*)lpBits;
|
||||
|
||||
// Only reallocate if the new size is LARGER than what we already have
|
||||
int requiredPixels = DestWidth * DestHeight;
|
||||
if (requiredPixels > currentDestCapacity) {
|
||||
SysFree(destBuffer, 0);
|
||||
destBuffer = (uint32_t*)SysAlloc(requiredPixels * sizeof(uint32_t));
|
||||
currentDestCapacity = requiredPixels;
|
||||
}
|
||||
|
||||
if (DestWidth > currentXMapCapacity) {
|
||||
SysFree(srcX_map, 0);
|
||||
srcX_map = (int*)SysAlloc(DestWidth * sizeof(int));
|
||||
currentXMapCapacity = DestWidth;
|
||||
}
|
||||
|
||||
for (int dx = 0; dx < DestWidth; ++dx) {
|
||||
// Nearest neighbor coordinate mapping
|
||||
srcX_map[dx] = xSrc + (dx * SrcWidth) / DestWidth;
|
||||
|
||||
// Clamp to safe bounds
|
||||
if (srcX_map[dx] < 0) srcX_map[dx] = 0;
|
||||
if (srcX_map[dx] >= SrcWidth) srcX_map[dx] = SrcWidth - 1;
|
||||
}
|
||||
|
||||
// Process the image row by row
|
||||
for (int dy = 0; dy < DestHeight; ++dy) {
|
||||
// Map destination Y to source Y
|
||||
int sy = ySrc + (dy * SrcHeight) / DestHeight;
|
||||
if (sy < 0) sy = 0;
|
||||
if (sy >= SrcHeight) sy = SrcHeight - 1;
|
||||
|
||||
// Assumes stride == SrcWidth (tightly packed 32bpp)
|
||||
const uint32_t* srcRow = srcPixels + (sy * SrcWidth);
|
||||
uint32_t* dstRow = destBuffer + (dy * DestWidth);
|
||||
|
||||
int dx = 0;
|
||||
|
||||
#if defined(__SSE2__) || defined(_M_X64)
|
||||
// Process 4 pixels (16 bytes) per loop iteration using SSE2
|
||||
for (; dx <= DestWidth - 4; dx += 4) {
|
||||
// Gather 4 source pixels using our precomputed X map.
|
||||
// Note: _mm_set_epi32 takes arguments in reverse order (3, 2, 1, 0)
|
||||
__m128i pixels = _mm_set_epi32(
|
||||
srcRow[srcX_map[dx + 3]],
|
||||
srcRow[srcX_map[dx + 2]],
|
||||
srcRow[srcX_map[dx + 1]],
|
||||
srcRow[srcX_map[dx + 0]]
|
||||
);
|
||||
// Issue a single 128-bit unaligned store
|
||||
_mm_storeu_si128((__m128i*)&dstRow[dx], pixels);
|
||||
}
|
||||
#elif defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(_M_ARM64)
|
||||
// Process 4 pixels per loop iteration using ARM NEON
|
||||
for (; dx <= DestWidth - 4; dx += 4) {
|
||||
// Initialize a vector and populate lanes (avoids stack-memory hop)
|
||||
uint32x4_t pixels = vdupq_n_u32(0);
|
||||
pixels = vsetq_lane_u32(srcRow[srcX_map[dx + 0]], pixels, 0);
|
||||
pixels = vsetq_lane_u32(srcRow[srcX_map[dx + 1]], pixels, 1);
|
||||
pixels = vsetq_lane_u32(srcRow[srcX_map[dx + 2]], pixels, 2);
|
||||
pixels = vsetq_lane_u32(srcRow[srcX_map[dx + 3]], pixels, 3);
|
||||
|
||||
// Issue a single 128-bit store
|
||||
vst1q_u32(&dstRow[dx], pixels);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Epilogue: Handle remaining pixels if DestWidth isn't a multiple of 4
|
||||
for (; dx < DestWidth; ++dx) {
|
||||
dstRow[dx] = srcRow[srcX_map[dx]];
|
||||
}
|
||||
}
|
||||
|
||||
// Direct mapping to kernel screen blit using the stretched buffer
|
||||
SysScreenBlit(xDest, yDest, DestWidth, DestHeight, destBuffer);
|
||||
|
||||
// Return the number of scanlines copied
|
||||
return DestHeight;
|
||||
}
|
||||
|
||||
__declspec(dllexport) BOOL BitBlt(HDC hdcDest, int xDest, int yDest, int w, int h,
|
||||
HDC hdcSrc, int xSrc, int ySrc, DWORD rop) {
|
||||
(void)hdcDest; (void)xDest; (void)yDest; (void)w; (void)h;
|
||||
(void)hdcSrc; (void)xSrc; (void)ySrc; (void)rop;
|
||||
// Stubbed. Applications manipulating pixels directly will use StretchDIBits.
|
||||
return TRUE;
|
||||
}
|
||||
+128
-27
@@ -28,45 +28,59 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
// Syscall stubs (from syscall.dll, assembled from syscall_stubs.asm)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Memory
|
||||
extern void* SysAlloc(size_t size);
|
||||
extern void SysFree(void* ptr, size_t size);
|
||||
extern void* SysRealloc(void* ptr, size_t newSize);
|
||||
|
||||
extern uint32_t SysOpenFile(const char* path, uint32_t* handleOut);
|
||||
extern uint32_t SysReadFile(uint32_t handle, void* buf, size_t size, size_t* bytesReadOut);
|
||||
extern uint32_t SysWriteFile(uint32_t handle, const void* buf,
|
||||
size_t size, size_t* bytesWrittenOut);
|
||||
extern uint32_t SysCreateFile(const char* path, uint32_t* handleOut);
|
||||
extern uint32_t SysDeleteFile(const char* path);
|
||||
extern uint32_t SysTruncateFile(uint32_t handle, uint64_t newSize);
|
||||
extern uint64_t SysGetFilePos(uint32_t handle);
|
||||
extern uint32_t SysSeekFile(uint32_t handle, uint64_t offset);
|
||||
extern uint64_t SysGetFileSize(uint32_t handle);
|
||||
extern void SysCloseHandle(uint32_t handle);
|
||||
|
||||
// Process & Thread
|
||||
extern void SysExitProcess(int exitCode);
|
||||
extern void SysExitThread(int exitCode);
|
||||
extern uint32_t SysCreateThread(uint64_t entry, uint64_t arg,
|
||||
uint32_t priority, uint32_t* tidOut);
|
||||
extern uint32_t SysGetCurrentTid(void);
|
||||
extern uint32_t SysGetCurrentPid(void);
|
||||
extern uint32_t SysCreateProcess(const char* path, uint32_t* handleOut, const char* cmdline);
|
||||
extern uint32_t SysWaitForProcess(uint32_t handle);
|
||||
extern uint32_t SysCreateThread(uint64_t entry, uint64_t arg, uint32_t priority, uint32_t* tidOut);
|
||||
extern uint32_t SysGetCurrentPid(void);
|
||||
extern uint32_t SysGetCurrentTid(void);
|
||||
extern uint32_t SysGetProcessExitCode(uint32_t handle, int* exitCodeOut);
|
||||
extern char SysKbReadChar(void);
|
||||
extern uint32_t SysKbPoll(void);
|
||||
extern void SysYield(void);
|
||||
extern void SysSleep(uint32_t ms);
|
||||
extern uint32_t SysWaitForProcess(uint32_t handle);
|
||||
|
||||
extern uint64_t SysGetTick(void);
|
||||
extern void SysDebugPrint(const char* str);
|
||||
// File I/O
|
||||
extern void SysCloseHandle(uint32_t handle);
|
||||
extern uint32_t SysCreateFile(const char* path, uint32_t* handleOut);
|
||||
extern uint32_t SysDeleteFile(const char* path);
|
||||
extern uint64_t SysGetFilePos(uint32_t handle);
|
||||
extern uint64_t SysGetFileSize(uint32_t handle);
|
||||
extern uint32_t SysOpenFile(const char* path, uint32_t* handleOut);
|
||||
extern uint32_t SysReadFile(uint32_t handle, void* buf, size_t size, size_t* bytesReadOut);
|
||||
extern uint32_t SysSeekFile(uint32_t handle, uint64_t offset);
|
||||
extern uint32_t SysTruncateFile(uint32_t handle, uint64_t newSize);
|
||||
extern uint32_t SysWriteFile(uint32_t handle, const void* buf, size_t size, size_t* bytesWrittenOut);
|
||||
|
||||
// Console & directory & CWD stubs (syscall.dll)
|
||||
extern void SysWriteConsole(const char* buf, size_t len);
|
||||
// Console & directory & CWD stubs
|
||||
extern uint32_t SysGetCwd(char* buf, size_t size);
|
||||
extern uint32_t SysOpenDir(const char* dirPath, uint32_t* handleOut);
|
||||
extern uint32_t SysReadDir(uint32_t handle, void* entryOut);
|
||||
extern void SysScreenClear(uint32_t color);
|
||||
extern uint32_t SysSetCwd(const char* path);
|
||||
extern uint32_t SysGetCwd(char* buf, size_t size);
|
||||
extern void SysWriteConsole(const char* buf, size_t len);
|
||||
|
||||
// Keyboard syscalls
|
||||
extern uint32_t SysKbGetModifiers(void);
|
||||
extern uint64_t SysKbIsKeyDown(uint8_t scancode, bool extended);
|
||||
extern uint32_t SysKbPoll(void);
|
||||
extern char SysKbReadChar(void);
|
||||
extern unsigned char SysKbReadScancode(void);
|
||||
|
||||
// Mouse syscalls
|
||||
extern void SysMouseGetPos(int* x, int* y);
|
||||
extern uint32_t SysMousePoll(void);
|
||||
extern uint32_t SysMouseRead(int* dx, int* dy, unsigned char* buttons);
|
||||
|
||||
// Misc
|
||||
extern void SysDebugPrint(const char* str);
|
||||
extern void SysYield(void);
|
||||
extern void SysSleep(uint32_t ms);
|
||||
extern uint64_t SysGetTick(void);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Types
|
||||
@@ -74,6 +88,10 @@ extern uint32_t SysGetCwd(char* buf, size_t size);
|
||||
typedef void* HANDLE;
|
||||
typedef unsigned long DWORD;
|
||||
typedef int BOOL;
|
||||
typedef unsigned char BYTE;
|
||||
typedef short SHORT;
|
||||
typedef long LONG;
|
||||
typedef struct { LONG x; LONG y; } POINT;
|
||||
|
||||
#define MAX_PATH 260
|
||||
#define TRUE 1
|
||||
@@ -156,7 +174,11 @@ __declspec(dllexport) void OutputDebugStringA(const char* str) {
|
||||
// Timer
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) DWORD GetTickCount(void) {
|
||||
return (DWORD)SysGetTick() * 10;
|
||||
return (DWORD)(SysGetTick() / 1000);
|
||||
}
|
||||
|
||||
__declspec(dllexport) uint64_t GetTickCount64(void) {
|
||||
return SysGetTick() / 1000;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -194,6 +216,85 @@ __declspec(dllexport) void* GetProcessHeap(void) {
|
||||
return (void*)1;
|
||||
}
|
||||
|
||||
// --- Win32 API ---
|
||||
|
||||
// Updated GetAsyncKeyState implementation
|
||||
__declspec(dllexport) SHORT GetAsyncKeyState(int vKey) {
|
||||
static const struct { int vk; uint8_t sc; bool ext; } vk_to_sc[] = {
|
||||
// Letters
|
||||
{ 0x41, 0x1E, false }, { 0x42, 0x30, false }, { 0x43, 0x2E, false },
|
||||
{ 0x44, 0x20, false }, { 0x45, 0x12, false }, { 0x46, 0x21, false },
|
||||
{ 0x47, 0x22, false }, { 0x48, 0x23, false }, { 0x49, 0x17, false },
|
||||
{ 0x4A, 0x24, false }, { 0x4B, 0x25, false }, { 0x4C, 0x26, false },
|
||||
{ 0x4D, 0x32, false }, { 0x4E, 0x31, false }, { 0x4F, 0x18, false },
|
||||
{ 0x50, 0x19, false }, { 0x51, 0x10, false }, { 0x52, 0x13, false },
|
||||
{ 0x53, 0x1F, false }, { 0x54, 0x14, false }, { 0x55, 0x16, false },
|
||||
{ 0x56, 0x2F, false }, { 0x57, 0x11, false }, { 0x58, 0x2D, false },
|
||||
{ 0x59, 0x15, false }, { 0x5A, 0x2C, false },
|
||||
|
||||
// Numbers
|
||||
{ 0x31, 0x02, false }, { 0x32, 0x03, false }, { 0x33, 0x04, false },
|
||||
{ 0x34, 0x05, false }, { 0x35, 0x06, false }, { 0x36, 0x07, false },
|
||||
{ 0x37, 0x08, false }, { 0x38, 0x09, false }, { 0x39, 0x0A, false },
|
||||
{ 0x30, 0x0B, false },
|
||||
|
||||
// Arrows (Extended)
|
||||
{ 0x26, 0x48, true }, // VK_UP
|
||||
{ 0x28, 0x50, true }, // VK_DOWN
|
||||
{ 0x25, 0x4B, true }, // VK_LEFT
|
||||
{ 0x27, 0x4D, true }, // VK_RIGHT
|
||||
|
||||
// Controls
|
||||
{ 0x1B, 0x01, false }, // ESC
|
||||
{ 0x0D, 0x1C, false }, // ENTER
|
||||
{ 0x20, 0x39, false }, // SPACE
|
||||
{ 0x11, 0x1D, false }, // CTRL (Generic)
|
||||
{ 0x10, 0x2A, false }, // SHIFT (Generic)
|
||||
{ 0x12, 0x38, false }, // ALT (Generic)
|
||||
{ 0x08, 0x0E, false }, // BACKSPACE
|
||||
{ 0x09, 0x0F, false }, // TAB
|
||||
|
||||
// Function Keys
|
||||
{ 0x70, 0x3B, false }, { 0x71, 0x3C, false }, { 0x72, 0x3D, false },
|
||||
{ 0x73, 0x3E, false }, { 0x74, 0x3F, false }, { 0x75, 0x40, false },
|
||||
{ 0x76, 0x41, false }, { 0x77, 0x42, false }, { 0x78, 0x43, false },
|
||||
{ 0x79, 0x44, false }, { 0x7A, 0x57, false }, { 0x7B, 0x58, false },
|
||||
|
||||
// Symbols
|
||||
{ 0xBD, 0x0C, false }, // MINUS '-'
|
||||
{ 0xBB, 0x0D, false }, // EQUALS '='
|
||||
{ 0xBC, 0x33, false }, // COMMA ','
|
||||
{ 0xBE, 0x34, false }, // PERIOD '.'
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(vk_to_sc)/sizeof(vk_to_sc[0]); ++i) {
|
||||
if (vk_to_sc[i].vk == vKey) {
|
||||
// Check the hardware state array via our HAL helper
|
||||
if (SysKbIsKeyDown(vk_to_sc[i].sc, vk_to_sc[i].ext)) {
|
||||
return (SHORT)0x8000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FlushConsoleInputBuffer: clear the keyboard input buffer
|
||||
__declspec(dllexport) BOOL FlushConsoleInputBuffer(HANDLE hConsoleInput) {
|
||||
(void)hConsoleInput;
|
||||
// Drain the keyboard buffer by reading until empty
|
||||
while (SysKbPoll()) {
|
||||
(void)SysKbReadChar();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// !Made-up! clear console api.
|
||||
__declspec(dllexport) BOOL ClearConsoleScreenBuffer(HANDLE hConsole) {
|
||||
SysScreenClear(0x00000000);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Locale / code-page stubs
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user