build.bat can create the image if missing, split the shell into native, posix and win32, clean up the build by moving executables into directories, the bootloader is no longer responsible to resolve drivers, fix ResolvePath, every process gets a copy of a module (dll), the child always inherits the cwd, fix function exports in posix, add unlink and exit to posix, add path translator to win32, first bugcheck.

This commit is contained in:
maksw committed 2026-05-13 09:24:16 +02:00
1 parent 0c7f461c6d
commit f80e66ecde
38 files changed
+1620 -462

No files matched your search

+1 -8
View File
@@ -1,6 +1,7 @@
// gdi32.c
#include <stdint.h>
#include <stddef.h>
#include <syscall.h>
#if defined(__SSE2__) || defined(_M_X64) || defined(_M_IX86)
#include <emmintrin.h>
@@ -8,14 +9,6 @@
#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
// ---------------------------------------------------------------------------
+70 -77
View File
@@ -24,63 +24,7 @@
#include <stdbool.h>
#include <string.h>
#include <intrin.h>
// ---------------------------------------------------------------------------
// 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);
// Process & Thread
extern void SysExitProcess(int exitCode);
extern void SysExitThread(int exitCode);
extern uint32_t SysCreateProcess(const char* path, uint32_t* handleOut, const char* cmdline);
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 uint32_t SysWaitForProcess(uint32_t handle);
// 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
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 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);
#include <syscall.h>
// ---------------------------------------------------------------------------
// Types
@@ -143,6 +87,36 @@ typedef struct _WIN32_FIND_DATAA {
static inline HANDLE KH_TO_HANDLE(uint32_t kh) { return (HANDLE)(uintptr_t)kh; }
static inline uint32_t HANDLE_TO_KH(HANDLE h) { return (uint32_t)(uintptr_t)h; }
// Path translator
static void TranslatePath(const char* input, char* output) {
if (input && input[0] != '\0' && input[1] == ':' && (input[2] == '\\' || input[2] == '/')) {
// Translate "C:\" -> "0:/" (assuming 'C' maps to '0', etc.)
// Map drive letter to index: 'C' or 'c' -> '0'
char drive = input[0];
if (drive >= 'a') drive -= ('a' - 'A'); // To uppercase
output[0] = (char)('0' + (drive - 'C'));
output[1] = ':';
output[2] = '/';
// Copy the rest, swapping backslashes to forward slashes
const char* src = input + 3;
char* dst = output + 3;
while (*src) {
*dst = (*src == '\\') ? '/' : *src;
src++; dst++;
}
*dst = '\0';
} else {
// Fallback for relative paths: just swap slashes
while (*input) {
*output = (*input == '\\') ? '/' : *input;
input++; output++;
}
*output = '\0';
}
}
// ---------------------------------------------------------------------------
// GetLastError / SetLastError (single-threaded stub)
// ---------------------------------------------------------------------------
@@ -342,24 +316,28 @@ __declspec(dllexport) DWORD GetOEMCP(void) { return 437; } // DOS Latin US
// CreateFileA - opens or creates a file.
// Supported modes:
// OPEN_EXISTING + GENERIC_READ -> open existing, read-only
// OPEN_EXISTING + GENERIC_WRITE -> open existing, read-write
// OPEN_EXISTING + GENERIC_READ -> open existing, read-only
// OPEN_EXISTING + GENERIC_WRITE -> open existing, read-write
// OPEN_EXISTING + GENERIC_READ|GENERIC_WRITE -> open existing, read-write
// CREATE_ALWAYS + GENERIC_WRITE -> create/truncate, write
// OPEN_ALWAYS + GENERIC_WRITE -> create if absent, write
// TRUNCATE_EXISTING + GENERIC_WRITE -> open & truncate to zero
__declspec(dllexport) HANDLE CreateFileA(const char* name,
DWORD access, DWORD share,
void* sa, DWORD disposition,
DWORD flags, void* templ) {
DWORD access, DWORD share,
void* sa, DWORD disposition,
DWORD flags, void* templ) {
(void)share; (void)sa; (void)flags; (void)templ;
// Translate the path from Windows format to custom 0:/ format
char translatedName[260];
TranslatePath(name, translatedName);
int wantWrite = (access & GENERIC_WRITE) != 0;
if (disposition == OPEN_EXISTING || disposition == TRUNCATE_EXISTING) {
// Open the file via the read path (it must already exist).
uint32_t kh = 0;
uint32_t s = SysOpenFile(name, &kh);
uint32_t s = SysOpenFile(translatedName, &kh);
if (s != 0) { gLastError = 2; return INVALID_HANDLE_VALUE; }
if (disposition == TRUNCATE_EXISTING && wantWrite) {
@@ -378,10 +356,10 @@ __declspec(dllexport) HANDLE CreateFileA(const char* name,
// Create-or-replace: try to create; if the file already exists,
// open it and truncate it to zero instead.
uint32_t kh = 0;
uint32_t s = SysCreateFile(name, &kh);
uint32_t s = SysCreateFile(translatedName, &kh);
if (s != 0) {
// File may already exist - open and truncate.
s = SysOpenFile(name, &kh);
s = SysOpenFile(translatedName, &kh);
if (s != 0) { gLastError = 5; return INVALID_HANDLE_VALUE; }
SysTruncateFile(kh, 0);
}
@@ -391,8 +369,8 @@ __declspec(dllexport) HANDLE CreateFileA(const char* name,
if (disposition == OPEN_ALWAYS && wantWrite) {
// Open if exists, create if not.
uint32_t kh = 0;
if (SysOpenFile(name, &kh) != 0) {
if (SysCreateFile(name, &kh) != 0) {
if (SysOpenFile(translatedName, &kh) != 0) {
if (SysCreateFile(translatedName, &kh) != 0) {
gLastError = 5;
return INVALID_HANDLE_VALUE;
}
@@ -404,7 +382,7 @@ __declspec(dllexport) HANDLE CreateFileA(const char* name,
// Fail if the file already exists (we can't check atomically,
// but SysCreateFile returns NAME_COLLISION for existing files).
uint32_t kh = 0;
uint32_t s = SysCreateFile(name, &kh);
uint32_t s = SysCreateFile(translatedName, &kh);
if (s != 0) { gLastError = 80; return INVALID_HANDLE_VALUE; } // ERROR_FILE_EXISTS
return KH_TO_HANDLE(kh);
}
@@ -417,7 +395,7 @@ __declspec(dllexport) HANDLE CreateFileA(const char* name,
// GetFileSize - fills optional high-DWORD pointer, returns low DWORD.
// Returns 0xFFFFFFFF on error, matching Win32 behaviour.
__declspec(dllexport) DWORD GetFileSize(HANDLE hFile, DWORD* fileSizeHigh) {
if (!hFile) { gLastError = 6; return 0xFFFFFFFFUL; }
if (!hFile || hFile == INVALID_HANDLE_VALUE) { gLastError = 6; return 0xFFFFFFFFUL; }
uint64_t sz = SysGetFileSize(HANDLE_TO_KH(hFile));
if (fileSizeHigh) *fileSizeHigh = (DWORD)(sz >> 32);
return (DWORD)(sz & 0xFFFFFFFFULL);
@@ -427,7 +405,7 @@ __declspec(dllexport) DWORD GetFileSize(HANDLE hFile, DWORD* fileSizeHigh) {
__declspec(dllexport) BOOL ReadFile(HANDLE hFile, void* buf, DWORD toRead,
DWORD* bytesRead, void* overlapped) {
(void)overlapped;
if (!hFile || !buf) { gLastError = 6; return FALSE; }
if (!hFile || hFile == INVALID_HANDLE_VALUE || !buf) { gLastError = 6; return FALSE; }
size_t got = 0;
uint32_t s = SysReadFile(HANDLE_TO_KH(hFile), buf, (size_t)toRead, &got);
if (bytesRead) *bytesRead = (DWORD)got;
@@ -452,7 +430,7 @@ __declspec(dllexport) BOOL WriteFile(HANDLE hFile, const void* buf, DWORD toWrit
// Returns new position low DWORD, or 0xFFFFFFFF on error.
__declspec(dllexport) DWORD SetFilePointer(HANDLE hFile, long dist,
long* distHigh, DWORD method) {
if (!hFile) { gLastError = 6; return 0xFFFFFFFFUL; }
if (!hFile || hFile == INVALID_HANDLE_VALUE) { gLastError = 6; return 0xFFFFFFFFUL; }
uint32_t kh = HANDLE_TO_KH(hFile);
uint64_t offset = 0;
@@ -481,7 +459,7 @@ __declspec(dllexport) DWORD SetFilePointer(HANDLE hFile, long dist,
// SetEndOfFile - truncate or extend the file to the current seek position.
__declspec(dllexport) BOOL SetEndOfFile(HANDLE hFile) {
if (!hFile) { gLastError = 6; return FALSE; }
if (!hFile || hFile == INVALID_HANDLE_VALUE) { gLastError = 6; return FALSE; }
uint32_t kh = HANDLE_TO_KH(hFile);
uint64_t pos = SysGetFilePos(kh);
if (pos == (uint64_t)-1) { gLastError = 6; return FALSE; }
@@ -493,8 +471,12 @@ __declspec(dllexport) BOOL SetEndOfFile(HANDLE hFile) {
// DeleteFileA - delete a file by name; no open handle required.
__declspec(dllexport) BOOL DeleteFileA(const char* lpFileName) {
if (!lpFileName) { gLastError = 87; return FALSE; }
uint32_t s = SysDeleteFile(lpFileName);
if (s != 0) { gLastError = 2; return FALSE; } // ERROR_FILE_NOT_FOUND
char translatedPath[MAX_PATH];
TranslatePath(lpFileName, translatedPath);
uint32_t s = SysDeleteFile(translatedPath);
if (s != 0) { gLastError = 2; return FALSE; }
return TRUE;
}
@@ -712,9 +694,12 @@ __declspec(dllexport) BOOL CreateProcessA(
// Build the cmdline: prefer lpCommandLine if given, otherwise fall back to path
const char* cmdline = lpCommandLine ? lpCommandLine : targetPath;
char translatedPath[MAX_PATH];
TranslatePath(targetPath, translatedPath);
uint32_t kh = 0;
// Call the syscall.dll stub
uint32_t s = SysCreateProcess(targetPath, &kh, cmdline);
uint32_t s = SysCreateProcess(translatedPath, &kh, cmdline);
if (s != 0 || kh == 0) {
gLastError = 2; // ERROR_FILE_NOT_FOUND
return FALSE;
@@ -956,10 +941,14 @@ __declspec(dllexport) HANDLE FindFirstFileA(const char* lpFileName,
return INVALID_HANDLE_VALUE;
}
// Translate the path
char translatedInput[MAX_PATH];
TranslatePath(lpFileName, translatedInput);
// Split path into directory and wildcard pattern
char dir[MAX_PATH];
char pat[MAX_PATH];
SplitFindPath(lpFileName, dir, sizeof(dir), pat, sizeof(pat));
SplitFindPath(translatedInput, dir, sizeof(dir), pat, sizeof(pat));
// Open the kernel directory iterator
uint32_t kh = 0;
@@ -1040,7 +1029,11 @@ __declspec(dllexport) BOOL FindClose(HANDLE hFindFile) {
__declspec(dllexport) BOOL SetCurrentDirectoryA(const char* lpPathName) {
if (!lpPathName) { gLastError = 87; return FALSE; }
uint32_t s = SysSetCwd(lpPathName);
char translatedPath[MAX_PATH];
TranslatePath(lpPathName, translatedPath);
uint32_t s = SysSetCwd(translatedPath);
if (s != 0) { gLastError = 2; return FALSE; }
return TRUE;
}
+1 -2
View File
@@ -2,6 +2,7 @@
// No COM infrastructure at this stage; all functions fail gracefully.
#include <stdint.h>
#include <stddef.h>
#include <syscall.h>
// ---------------------------------------------------------------------------
// Types
@@ -37,8 +38,6 @@ typedef struct {
};
} PROPVARIANT;
extern void SysFree(void* ptr, size_t size);
// ---------------------------------------------------------------------------
// COM initialisation
// ---------------------------------------------------------------------------
+1 -3
View File
@@ -1,9 +1,7 @@
// user32.c - Win32 User Interface
#include <stdint.h>
#include <stddef.h>
extern void SysYield(void);
extern void SysDebugPrint(const char* str);
#include <syscall.h>
typedef void* HWND;
typedef void* HDC;
+1 -4
View File
@@ -2,6 +2,7 @@
// Stubs only; no audio hardware access at this stage.
#include <stdint.h>
#include <stddef.h>
#include <syscall.h>
// ---------------------------------------------------------------------------
// Types
@@ -51,10 +52,6 @@ typedef struct {
// Timer
// ---------------------------------------------------------------------------
// timeGetTime is the lightweight alternative to GetTickCount; both return
// milliseconds since system start. We forward to the kernel tick counter.
extern uint64_t SysGetTick(void);
__declspec(dllexport) unsigned long timeGetTime(void) {
return (unsigned long)SysGetTick();
}