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:
maksw committed 2026-05-11 10:10:21 +02:00
1 parent cdf7ed4cea
commit 0c7f461c6d
24 files changed
+50236 -1310

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
[kernel]
debug = 1
[init]
commandline = init.exe
commandline = shell.exe
+48605
View File
File diff suppressed because it is too large. Load diff
+329
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+2 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+64 -63
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
// ---------------------------------------------------------------------------