major restructuring, prepare for smp

This commit is contained in:
maksw committed 2026-05-28 18:53:37 +02:00
1 parent b3569a2b90
commit 6bff37746d
229 files changed
+1617 -1489

No files matched your search

File diff suppressed because it is too large. Load diff
+388
View File
@@ -0,0 +1,388 @@
// doom.c — PureDOOM port
// Native personality carrying all the weight.
// Drop doom1.wad (or doom.wad) next to this binary on your FAT32 volume.
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <intrin.h>
#include <ntlite/syscall.h>
#define DOOM_IMPLEMENTATION
#include "PureDOOM.h"
int _fltused;
// ---------------------------------------------------------------------------
// doom_print_fn
// ---------------------------------------------------------------------------
static void doom_print_wrapper(const char* msg)
{
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(msg) };
SysWriteConsole(&req);
}
// ---------------------------------------------------------------------------
// doom_malloc_fn / doom_free_fn
// ---------------------------------------------------------------------------
static void* doom_malloc_wrapper(int size)
{
void* p = SysAlloc(size);
if (!p) SysExitProcess(1);
return p;
}
static void doom_free_wrapper(void* ptr)
{
if (!ptr) return;
SysFree(ptr);
}
// ---------------------------------------------------------------------------
// File I/O wrappers
// ---------------------------------------------------------------------------
typedef struct DOOM_FILE_HANDLE {
uint32_t Handle;
uint64_t Pos;
uint64_t Size;
} DOOM_FILE_HANDLE;
static void* doom_open_wrapper(const char* path, const char* mode)
{
uint32_t handle = 0;
uint32_t result;
SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), &handle };
if (mode[0] == 'w') {
result = SysCreateFile(&req);
} else {
result = SysOpenFile(&req);
}
if (result != 0) return 0;
DOOM_FILE_HANDLE* f = (DOOM_FILE_HANDLE*)SysAlloc(sizeof(DOOM_FILE_HANDLE));
if (!f) {
SysCloseHandle(handle);
return 0;
}
f->Handle = handle;
f->Pos = 0;
f->Size = SysGetFileSize(handle);
return f;
}
static void doom_close_wrapper(void* handle)
{
if (!handle) return;
DOOM_FILE_HANDLE* f = (DOOM_FILE_HANDLE*)handle;
SysCloseHandle(f->Handle);
SysFree(f);
}
static int doom_read_wrapper(void* handle, void* buf, int count)
{
if (!handle || count <= 0) return 0;
DOOM_FILE_HANDLE* f = (DOOM_FILE_HANDLE*)handle;
size_t read = 0;
SysReadFile(f->Handle, buf, (size_t)count, &read);
f->Pos += read;
if (f->Pos > f->Size) f->Size = f->Pos;
return (int)read;
}
static int doom_write_wrapper(void* handle, const void* buf, int count)
{
if (!handle || count <= 0) return 0;
DOOM_FILE_HANDLE* f = (DOOM_FILE_HANDLE*)handle;
size_t written = 0;
SysWriteFile(f->Handle, buf, (size_t)count, &written);
f->Pos += written;
if (f->Pos > f->Size) f->Size = f->Pos;
return (int)written;
}
static int doom_seek_wrapper(void* handle, int offset, doom_seek_t origin)
{
if (!handle) return -1;
DOOM_FILE_HANDLE* f = (DOOM_FILE_HANDLE*)handle;
int64_t base = 0;
switch (origin) {
case DOOM_SEEK_SET:
base = 0;
break;
case DOOM_SEEK_CUR:
base = (int64_t)f->Pos;
break;
case DOOM_SEEK_END:
base = (int64_t)f->Size;
break;
default:
base = 0;
break;
}
int64_t target = base + (int64_t)offset;
if (target < 0) target = 0;
uint32_t s = SysSeekFile(f->Handle, (uint64_t)target);
if (s != 0) return -1;
f->Pos = (uint64_t)target;
return 0;
}
static int doom_tell_wrapper(void* handle)
{
if (!handle) return -1;
return (int)((DOOM_FILE_HANDLE*)handle)->Pos;
}
static int doom_eof_wrapper(void* handle)
{
if (!handle) return 1;
DOOM_FILE_HANDLE* f = (DOOM_FILE_HANDLE*)handle;
return (f->Pos >= f->Size) ? 1 : 0;
}
// ---------------------------------------------------------------------------
// doom_gettime_fn
// ---------------------------------------------------------------------------
static void doom_gettime_wrapper(int* sec, int* usec)
{
uint64_t t = SysGetTick();
*sec = (int)(t / 1000000); // 1,000,000 us = 1 second
*usec = (int)(t % 1000000); // Remainder in microseconds
}
// ---------------------------------------------------------------------------
// doom_exit_fn
// ---------------------------------------------------------------------------
static void doom_exit_wrapper(int code)
{
SysExitProcess(code);
}
// ---------------------------------------------------------------------------
// doom_getenv_fn
// ---------------------------------------------------------------------------
static char* doom_getenv_wrapper(const char* name)
{
if (strcmp(name, "HOME") == 0) {
static char home[] = ".";
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 — Maps Scancode Set 1 values to PureDOOM
// ---------------------------------------------------------------------------
typedef struct { uint8_t scancode; bool extended; doom_key_t key; } KeyMap;
static const KeyMap g_keymap[] = {
// Letters
{ 0x11, false, DOOM_KEY_W },
{ 0x1E, false, DOOM_KEY_A },
{ 0x1F, false, DOOM_KEY_S },
{ 0x20, false, DOOM_KEY_D },
{ 0x12, false, DOOM_KEY_E },
{ 0x10, false, DOOM_KEY_Q },
{ 0x15, false, DOOM_KEY_Y },
{ 0x31, false, DOOM_KEY_N },
// Arrow keys
{ 0x48, true, DOOM_KEY_UP_ARROW },
{ 0x50, true, DOOM_KEY_DOWN_ARROW },
{ 0x4B, true, DOOM_KEY_LEFT_ARROW },
{ 0x4D, true, DOOM_KEY_RIGHT_ARROW },
// Action keys
{ 0x1D, false, DOOM_KEY_CTRL },
{ 0x39, false, DOOM_KEY_SPACE },
{ 0x2A, false, DOOM_KEY_SHIFT },
{ 0x38, false, DOOM_KEY_ALT },
// Navigation
{ 0x01, false, DOOM_KEY_ESCAPE },
{ 0x1C, false, DOOM_KEY_ENTER },
{ 0x0F, false, DOOM_KEY_TAB },
{ 0x0E, false, DOOM_KEY_BACKSPACE },
// Weapon slots
{ 0x02, false, DOOM_KEY_1 },
{ 0x03, false, DOOM_KEY_2 },
{ 0x04, false, DOOM_KEY_3 },
{ 0x05, false, DOOM_KEY_4 },
{ 0x06, false, DOOM_KEY_5 },
{ 0x07, false, DOOM_KEY_6 },
{ 0x08, false, DOOM_KEY_7 },
// Misc
{ 0x0C, false, DOOM_KEY_MINUS },
{ 0x0D, false, DOOM_KEY_EQUALS },
{ 0x33, false, DOOM_KEY_COMMA },
{ 0x34, false, DOOM_KEY_PERIOD },
// Function keys
{ 0x3B, false, DOOM_KEY_F1 },
{ 0x3C, false, DOOM_KEY_F2 },
{ 0x3D, false, DOOM_KEY_F3 },
{ 0x3E, false, DOOM_KEY_F4 },
{ 0x3F, false, DOOM_KEY_F5 },
{ 0x40, false, DOOM_KEY_F6 },
{ 0x41, false, DOOM_KEY_F7 },
{ 0x42, false, DOOM_KEY_F8 },
{ 0x43, false, DOOM_KEY_F9 },
{ 0x44, false, DOOM_KEY_F10 },
{ 0x57, false, DOOM_KEY_F11 },
{ 0x58, false, DOOM_KEY_F12 },
};
#define KEYMAP_COUNT (sizeof(g_keymap) / sizeof(g_keymap[0]))
static bool g_prev_key[KEYMAP_COUNT];
static void poll_input(void)
{
for (int i = 0; i < (int)KEYMAP_COUNT; i++) {
bool cur_down = (SysKbIsKeyDown(g_keymap[i].scancode, g_keymap[i].extended) != 0);
bool prev_down = g_prev_key[i];
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[i] = cur_down;
}
}
// ---------------------------------------------------------------------------
// Render — Performs lightweight software upscale and blits to the screen
// ---------------------------------------------------------------------------
#define DOOM_W 320
#define DOOM_H 200
#define SCALE 3
#define DISP_W (DOOM_W * SCALE)
#define DISP_H (DOOM_H * SCALE)
static uint32_t g_blit_buf[DISP_W * DISP_H];
static void render_frame(const uint8_t* rgba)
{
const uint32_t* src = (const uint32_t*)rgba;
// Software upscale loop mapping 320x200 buffer directly to scaled window buffer
for (int y = 0; y < DOOM_H; y++) {
for (int x = 0; x < DOOM_W; x++) {
uint32_t p = src[y * DOOM_W + x];
// RGBA -> BGRA conversion (standard for linear x86/64 framebuffers)
uint32_t bgra = (p & 0xFF00FF00u)
| ((p & 0x00FF0000u) >> 16)
| ((p & 0x000000FFu) << 16);
// Populate SCALE * SCALE pixel block
for (int sy = 0; sy < SCALE; sy++) {
for (int sx = 0; sx < SCALE; sx++) {
g_blit_buf[(y * SCALE + sy) * DISP_W + (x * SCALE + sx)] = bgra;
}
}
}
}
SysScreenBlit(0, 0, DISP_W, DISP_H, g_blit_buf);
}
static int build_argv_from_command_line(const char* cmdline, char* storage, size_t storageSize,
const char** argv, int maxArgv) {
if (!storage || storageSize == 0 || !argv || maxArgv <= 1) return 0;
if (!cmdline || cmdline[0] == '\0') cmdline = "doom";
size_t len = strlen(cmdline);
if (len >= storageSize) len = storageSize - 1;
memcpy(storage, cmdline, len);
storage[len] = '\0';
int argc = 0;
char* p = storage;
while (*p && argc < maxArgv - 1) {
while (*p == ' ' || *p == '\t') p++;
if (!*p) break;
if (*p == '"') {
p++;
argv[argc++] = p;
while (*p && *p != '"') p++;
if (*p) *p++ = '\0';
} else {
argv[argc++] = p;
while (*p && *p != ' ' && *p != '\t') p++;
if (*p) *p++ = '\0';
}
}
argv[argc] = 0;
if (argc == 0) {
argv[0] = "doom";
argv[1] = 0;
argc = 1;
}
return argc;
}
// ---------------------------------------------------------------------------
// main
// ---------------------------------------------------------------------------
int main(void)
{
const char* cmdline = SysGetPeb()->CommandLine.Data;
do { SYS_WRITE_CONSOLE_REQUEST req = { SYS_SV_LITERAL("doom: starting\n") }; SysWriteConsole(&req); } while (0);
// Wire up PureDOOM core mechanics
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);
char argvStorage[512];
const char* argv[32];
int argc = build_argv_from_command_line(cmdline, argvStorage, sizeof(argvStorage), argv, 32);
doom_init(argc, argv, 0);
do { SYS_WRITE_CONSOLE_REQUEST req = { SYS_SV_LITERAL("doom: entering game loop\n") }; SysWriteConsole(&req); } while (0);
// Core execution loop
while (1) {
poll_input();
doom_update();
render_frame((const uint8_t*)doom_get_framebuffer(4 /* RGBA */));
}
SysExitProcess(0);
return 0;
}
Binary file not shown.
+494
View File
@@ -0,0 +1,494 @@
// edit.c - tiny native text editor for nt-lite
// Controls:
// arrows/home/end/pageup/pagedown move
// enter/backspace/delete/tab edit
// ctrl+s save
// ctrl+q quit (press twice if dirty)
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <ntlite/syscall.h>
#define GLYPH_W 8
#define GLYPH_H 16
#define MAX_LINES 512
#define MAX_LINE 256
#define PATH_MAX2 260
#define MSG_MAX 160
#define COL_BG 0x000000u
#define COL_FG 0xC8C8C8u
#define COL_DIM 0x808080u
#define COL_STATUS 0x303030u
#define COL_STATUSF 0xFFFFFFu
#define COL_CURSOR 0xE0E0E0u
#define COL_CURSORF 0x000000u
#define MOD_LSHIFT (1u << 0)
#define MOD_RSHIFT (1u << 1)
#define MOD_LCTRL (1u << 2)
#define MOD_RCTRL (1u << 3)
#define MOD_CAPS (1u << 6)
#define MOD_SHIFT (MOD_LSHIFT | MOD_RSHIFT)
#define MOD_CTRL (MOD_LCTRL | MOD_RCTRL)
#define SC_ESC 0x01u
#define SC_BACKSPACE 0x0Eu
#define SC_TAB 0x0Fu
#define SC_Q 0x10u
#define SC_S 0x1Fu
#define SC_ENTER 0x1Cu
#define SC_HOME 0x47u
#define SC_UP 0x48u
#define SC_PGUP 0x49u
#define SC_LEFT 0x4Bu
#define SC_RIGHT 0x4Du
#define SC_END 0x4Fu
#define SC_DOWN 0x50u
#define SC_PGDN 0x51u
#define SC_DEL 0x53u
typedef struct LINE {
int len;
char text[MAX_LINE];
} LINE;
static LINE gLines[MAX_LINES];
static int gLineCount = 1;
static int gCx = 0;
static int gCy = 0;
static int gTop = 0;
static int gLeft = 0;
static int gCols = 80;
static int gRows = 25;
static bool gDirty = false;
static bool gQuitArmed = false;
static char gFilename[PATH_MAX2] = "untitled.txt";
static char gMessage[MSG_MAX] = "ready";
static const char gUnshifted[128] = {
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] = {
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','.'
};
static void put_cell(int col, int row, char c, uint32_t fg, uint32_t bg) {
SysScreenPutChar(c ? c : ' ', col * GLYPH_W, row * GLYPH_H, fg, bg);
}
static void clear_row(int row, uint32_t bg) {
for (int x = 0; x < gCols; x++) put_cell(x, row, ' ', COL_FG, bg);
}
static void draw_text(int col, int row, const char* s, uint32_t fg, uint32_t bg) {
while (*s && col < gCols) put_cell(col++, row, *s++, fg, bg);
}
static void msg_set(const char* s) {
size_t n = strlen(s);
if (n >= sizeof(gMessage)) n = sizeof(gMessage) - 1;
memcpy(gMessage, s, n);
gMessage[n] = 0;
}
static void append_char(char* b, size_t cap, size_t* p, char c) {
if (*p + 1 < cap) b[(*p)++] = c;
b[*p < cap ? *p : cap - 1] = 0;
}
static void append_str(char* b, size_t cap, size_t* p, const char* s) {
while (*s) append_char(b, cap, p, *s++);
}
static void append_u32(char* b, size_t cap, size_t* p, uint32_t v) {
char tmp[12];
int n = 0;
if (v == 0) { append_char(b, cap, p, '0'); return; }
while (v && n < (int)sizeof(tmp)) {
tmp[n++] = (char)('0' + (v % 10u));
v /= 10u;
}
while (n > 0) append_char(b, cap, p, tmp[--n]);
}
static char key_to_char(uint8_t sc, uint32_t mods) {
if (sc >= 128) return 0;
bool shifted = (mods & MOD_SHIFT) != 0;
if (mods & MOD_CAPS) {
char base = gUnshifted[sc];
if (base >= 'a' && base <= 'z') shifted = !shifted;
}
return shifted ? gShifted[sc] : gUnshifted[sc];
}
static void clamp_cursor(void) {
if (gLineCount < 1) gLineCount = 1;
if (gCy < 0) gCy = 0;
if (gCy >= gLineCount) gCy = gLineCount - 1;
if (gCx < 0) gCx = 0;
if (gCx > gLines[gCy].len) gCx = gLines[gCy].len;
}
static void ensure_visible(void) {
int textRows = gRows - 2;
if (textRows < 1) textRows = 1;
if (gCy < gTop) gTop = gCy;
if (gCy >= gTop + textRows) gTop = gCy - textRows + 1;
if (gTop < 0) gTop = 0;
if (gCx < gLeft) gLeft = gCx;
if (gCx >= gLeft + gCols) gLeft = gCx - gCols + 1;
if (gLeft < 0) gLeft = 0;
}
static void render(void) {
int pxW = 0, pxH = 0;
if (SysScreenGetSize(&pxW, &pxH) == 0 && pxW > 0 && pxH > 0) {
gCols = pxW / GLYPH_W;
gRows = pxH / GLYPH_H;
if (gCols < 20) gCols = 20;
if (gRows < 5) gRows = 5;
}
clamp_cursor();
ensure_visible();
char status[256];
size_t p = 0;
append_str(status, sizeof(status), &p, " edit ");
append_str(status, sizeof(status), &p, gFilename);
append_str(status, sizeof(status), &p, gDirty ? " * " : " ");
append_str(status, sizeof(status), &p, "Ctrl+S save Ctrl+Q quit Ln ");
append_u32(status, sizeof(status), &p, (uint32_t)(gCy + 1));
append_str(status, sizeof(status), &p, ", Col ");
append_u32(status, sizeof(status), &p, (uint32_t)(gCx + 1));
clear_row(0, COL_STATUS);
draw_text(0, 0, status, COL_STATUSF, COL_STATUS);
int textRows = gRows - 2;
for (int sy = 0; sy < textRows; sy++) {
int row = sy + 1;
int li = gTop + sy;
clear_row(row, COL_BG);
if (li >= gLineCount) continue;
LINE* ln = &gLines[li];
for (int sx = 0; sx < gCols; sx++) {
int ci = gLeft + sx;
char c = (ci < ln->len) ? ln->text[ci] : ' ';
bool atCursor = (li == gCy && ci == gCx);
put_cell(sx, row, c, atCursor ? COL_CURSORF : COL_FG,
atCursor ? COL_CURSOR : COL_BG);
}
}
clear_row(gRows - 1, COL_STATUS);
draw_text(0, gRows - 1, gMessage, COL_STATUSF, COL_STATUS);
}
static void insert_char_at_cursor(char c) {
LINE* ln = &gLines[gCy];
if (ln->len >= MAX_LINE - 1) { msg_set("line too long"); return; }
memmove(&ln->text[gCx + 1], &ln->text[gCx], (size_t)(ln->len - gCx + 1));
ln->text[gCx] = c;
ln->len++;
gCx++;
gDirty = true;
}
static void newline_at_cursor(void) {
if (gLineCount >= MAX_LINES) { msg_set("too many lines"); return; }
for (int i = gLineCount; i > gCy + 1; i--) gLines[i] = gLines[i - 1];
LINE* cur = &gLines[gCy];
LINE* next = &gLines[gCy + 1];
int tail = cur->len - gCx;
if (tail > 0) memcpy(next->text, &cur->text[gCx], (size_t)tail);
next->len = tail;
next->text[next->len] = 0;
cur->len = gCx;
cur->text[cur->len] = 0;
gLineCount++;
gCy++;
gCx = 0;
gDirty = true;
}
static void backspace_at_cursor(void) {
if (gCx > 0) {
LINE* ln = &gLines[gCy];
memmove(&ln->text[gCx - 1], &ln->text[gCx], (size_t)(ln->len - gCx + 1));
ln->len--;
gCx--;
gDirty = true;
return;
}
if (gCy <= 0) return;
LINE* prev = &gLines[gCy - 1];
LINE* cur = &gLines[gCy];
if (prev->len + cur->len >= MAX_LINE) { msg_set("join would make line too long"); return; }
int oldLen = prev->len;
memcpy(&prev->text[prev->len], cur->text, (size_t)cur->len + 1);
prev->len += cur->len;
for (int i = gCy; i < gLineCount - 1; i++) gLines[i] = gLines[i + 1];
gLineCount--;
gCy--;
gCx = oldLen;
gDirty = true;
}
static void delete_at_cursor(void) {
LINE* ln = &gLines[gCy];
if (gCx < ln->len) {
memmove(&ln->text[gCx], &ln->text[gCx + 1], (size_t)(ln->len - gCx));
ln->len--;
gDirty = true;
return;
}
if (gCy + 1 >= gLineCount) return;
LINE* next = &gLines[gCy + 1];
if (ln->len + next->len >= MAX_LINE) { msg_set("join would make line too long"); return; }
memcpy(&ln->text[ln->len], next->text, (size_t)next->len + 1);
ln->len += next->len;
for (int i = gCy + 1; i < gLineCount - 1; i++) gLines[i] = gLines[i + 1];
gLineCount--;
gDirty = true;
}
static void move_left(void) {
if (gCx > 0) gCx--;
else if (gCy > 0) { gCy--; gCx = gLines[gCy].len; }
}
static void move_right(void) {
if (gCx < gLines[gCy].len) gCx++;
else if (gCy + 1 < gLineCount) { gCy++; gCx = 0; }
}
static void move_up(void) {
if (gCy > 0) gCy--;
if (gCx > gLines[gCy].len) gCx = gLines[gCy].len;
}
static void move_down(void) {
if (gCy + 1 < gLineCount) gCy++;
if (gCx > gLines[gCy].len) gCx = gLines[gCy].len;
}
static void save_file(void) {
uint32_t h = 0;
SYS_PATH_HANDLE_REQUEST pathReq = { SysSvFromCstr(gFilename), &h };
uint32_t st = SysCreateFile(&pathReq);
if (st != 0) st = SysOpenFile(&pathReq);
if (st != 0) { msg_set("save failed: cannot open file"); return; }
SysTruncateFile(h, 0);
SysSeekFile(h, 0);
for (int i = 0; i < gLineCount; i++) {
size_t written = 0;
if (gLines[i].len) {
st = SysWriteFile(h, gLines[i].text, (size_t)gLines[i].len, &written);
if (st != 0) { SysCloseHandle(h); msg_set("save failed: write error"); return; }
}
if (i + 1 < gLineCount) {
const char nl = '\n';
st = SysWriteFile(h, &nl, 1, &written);
if (st != 0) { SysCloseHandle(h); msg_set("save failed: write error"); return; }
}
}
SysCloseHandle(h);
gDirty = false;
msg_set("saved");
}
static void reset_buffer(void) {
gLineCount = 1;
gLines[0].len = 0;
gLines[0].text[0] = 0;
gCx = gCy = gTop = gLeft = 0;
gDirty = false;
}
static void load_file(void) {
reset_buffer();
uint32_t h = 0;
SYS_PATH_HANDLE_REQUEST pathReq = { SysSvFromCstr(gFilename), &h };
if (SysOpenFile(&pathReq) != 0) {
msg_set("new file");
return;
}
char buf[512];
size_t got = 0;
bool truncated = false;
while (SysReadFile(h, buf, sizeof(buf), &got) == 0 && got > 0) {
for (size_t i = 0; i < got; i++) {
char c = buf[i];
if (c == '\r') continue;
if (c == '\n') {
if (gLineCount < MAX_LINES) {
gLineCount++;
gLines[gLineCount - 1].len = 0;
gLines[gLineCount - 1].text[0] = 0;
} else truncated = true;
continue;
}
if (c < 0x20 && c != '\t') continue;
LINE* ln = &gLines[gLineCount - 1];
if (ln->len + 1 < MAX_LINE) {
ln->text[ln->len++] = (c == '\t') ? ' ' : c;
ln->text[ln->len] = 0;
} else truncated = true;
}
}
SysCloseHandle(h);
msg_set(truncated ? "loaded, truncated long file" : "loaded");
}
static const char* skip_spaces(const char* s) {
while (s && (*s == ' ' || *s == '\t')) s++;
return s;
}
static const char* skip_token(const char* s) {
s = skip_spaces(s);
if (!s || !*s) return s;
if (*s == '"') {
s++;
while (*s && *s != '"') s++;
if (*s == '"') s++;
return s;
}
while (*s && *s != ' ' && *s != '\t') s++;
return s;
}
static bool read_token(const char* s, char* out, size_t cap) {
s = skip_spaces(s);
if (!s || !*s || cap == 0) return false;
size_t n = 0;
if (*s == '"') {
s++;
while (*s && *s != '"') {
if (n + 1 < cap) out[n++] = *s;
s++;
}
} else {
while (*s && *s != ' ' && *s != '\t') {
if (n + 1 < cap) out[n++] = *s;
s++;
}
}
out[n] = 0;
return n != 0;
}
static void parse_filename_from_cmdline(void) {
SYS_PEB* peb = SysGetPeb();
const char* cmd = (peb && peb->CommandLine.Data) ? peb->CommandLine.Data : NULL;
const char* arg = skip_token(cmd);
if (read_token(arg, gFilename, sizeof(gFilename))) return;
strcpy(gFilename, "untitled.txt");
}
static void editor_loop(void) {
while (true) {
render();
uint8_t sc = SysKbReadScancode();
uint32_t mods = SysKbGetModifiers();
bool ctrl = (mods & MOD_CTRL) != 0;
if (ctrl && sc == SC_Q) {
if (gDirty && !gQuitArmed) {
gQuitArmed = true;
msg_set("unsaved changes: press Ctrl+Q again to quit");
continue;
}
break;
}
gQuitArmed = false;
if (ctrl && sc == SC_S) { save_file(); continue; }
if (sc == SC_ESC) { msg_set("Ctrl+Q quits, Ctrl+S saves"); continue; }
switch (sc) {
case SC_LEFT: move_left(); break;
case SC_RIGHT: move_right(); break;
case SC_UP: move_up(); break;
case SC_DOWN: move_down(); break;
case SC_HOME: gCx = 0; break;
case SC_END: gCx = gLines[gCy].len; break;
case SC_PGUP: {
int n = gRows - 2;
if (n < 1) n = 1;
gCy -= n;
clamp_cursor();
break;
}
case SC_PGDN: {
int n = gRows - 2;
if (n < 1) n = 1;
gCy += n;
clamp_cursor();
break;
}
case SC_BACKSPACE: backspace_at_cursor(); break;
case SC_DEL: delete_at_cursor(); break;
case SC_ENTER: newline_at_cursor(); break;
case SC_TAB:
for (int i = 0; i < 4; i++) insert_char_at_cursor(' ');
break;
default: {
char c = key_to_char(sc, mods);
if (!ctrl && c >= 0x20 && c <= 0x7E) insert_char_at_cursor(c);
break;
}
}
}
}
static void print(const char* s) {
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) };
SysWriteConsole(&req);
}
int main(void) {
parse_filename_from_cmdline();
load_file();
SysScreenClear(COL_BG);
editor_loop();
SysScreenClear(COL_BG);
print("edit: goodbye\n");
SysExitProcess(0);
return 0;
}
+258
View File
@@ -0,0 +1,258 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <ntlite/syscall.h>
static void print(const char* s) {
if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); }
}
static void print_char(char c) {
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
SysWriteConsole(&req);
}
static void print_u64(uint64_t v) {
char buf[32];
int n = 0;
if (v == 0) { print("0"); return; }
while (v && n < (int)sizeof(buf)) {
buf[n++] = (char)('0' + (v % 10));
v /= 10;
}
while (n > 0) print_char(buf[--n]);
}
static void append_char(char* dst, size_t cap, size_t* off, char c) {
if (!dst || !off || cap == 0 || *off + 1 >= cap) return;
dst[*off] = c;
*off += 1;
dst[*off] = 0;
}
static void append_str(char* dst, size_t cap, size_t* off, const char* s) {
if (!s) return;
while (*s) append_char(dst, cap, off, *s++);
}
static void append_u8(char* dst, size_t cap, size_t* off, uint8_t v) {
if (v >= 100) {
append_char(dst, cap, off, (char)('0' + v / 100));
v %= 100;
append_char(dst, cap, off, (char)('0' + v / 10));
append_char(dst, cap, off, (char)('0' + v % 10));
} else if (v >= 10) {
append_char(dst, cap, off, (char)('0' + v / 10));
append_char(dst, cap, off, (char)('0' + v % 10));
} else {
append_char(dst, cap, off, (char)('0' + v));
}
}
static void format_ipv4(char* dst, size_t cap, const uint8_t ip[4]) {
size_t off = 0;
if (!dst || cap == 0) return;
dst[0] = 0;
append_u8(dst, cap, &off, ip[0]); append_char(dst, cap, &off, '.');
append_u8(dst, cap, &off, ip[1]); append_char(dst, cap, &off, '.');
append_u8(dst, cap, &off, ip[2]); append_char(dst, cap, &off, '.');
append_u8(dst, cap, &off, ip[3]);
}
static bool parse_u8(const char** p, uint8_t* out) {
const char* s = *p;
uint32_t v = 0;
int digits = 0;
while (*s >= '0' && *s <= '9') {
v = v * 10u + (uint32_t)(*s - '0');
if (v > 255u) return false;
s++;
digits++;
}
if (digits == 0) return false;
*out = (uint8_t)v;
*p = s;
return true;
}
static bool parse_ipv4(const char* s, uint8_t ip[4]) {
if (!s || !ip) return false;
for (int i = 0; i < 4; i++) {
if (!parse_u8(&s, &ip[i])) return false;
if (i != 3) {
if (*s != '.') return false;
s++;
}
}
return *s == 0;
}
static const char* next_token(const char* s, char* out, size_t outSize) {
if (!s || !out || outSize == 0) return NULL;
while (*s == ' ' || *s == '\t') s++;
if (*s == 0) { out[0] = 0; return NULL; }
size_t n = 0;
while (*s && *s != ' ' && *s != '\t') {
if (n + 1 < outSize) out[n++] = *s;
s++;
}
out[n] = 0;
return s;
}
static void usage(void) {
print("usage: httpget.exe [host-or-ipv4] [path]\n");
print("default: httpget.exe 10.0.2.2 /\n");
}
static uint32_t resolve_host(const char* host, uint8_t ip[4]) {
if (parse_ipv4(host, ip))
return SYS_STATUS_SUCCESS;
SYS_SOCKET_ADDRESS_IPV4 resolved;
size_t resolvedSize = sizeof(resolved);
SYS_RESOLVE_HOST_REQUEST req;
memset(&resolved, 0, sizeof(resolved));
memset(&req, 0, sizeof(req));
req.Name = SysSvFromCstr(host);
req.Family = SYS_AF_INET;
req.AddressOut = &resolved;
req.AddressSizeInOut = &resolvedSize;
uint32_t st = SysResolveHost(&req);
if (st != SYS_STATUS_SUCCESS)
return st;
if (resolved.Family != SYS_AF_INET)
return SYS_STATUS_NOT_FOUND;
ip[0] = resolved.Address[0];
ip[1] = resolved.Address[1];
ip[2] = resolved.Address[2];
ip[3] = resolved.Address[3];
return SYS_STATUS_SUCCESS;
}
int main(void) {
uint8_t ip[4] = {10, 0, 2, 2};
char host[256];
char path[128];
strcpy(host, "10.0.2.2");
path[0] = '/';
path[1] = 0;
const char* cmd = SysGetPeb()->CommandLine.Data;
char tok[256];
cmd = next_token(cmd, tok, sizeof(tok)); // program path
if (cmd) {
const char* rest = next_token(cmd, tok, sizeof(tok));
if (tok[0]) {
if (strlen(tok) >= sizeof(host)) {
print("httpget: host too long\n");
SysExitProcess(1);
}
strcpy(host, tok);
cmd = rest;
}
if (cmd) {
(void)next_token(cmd, tok, sizeof(tok));
if (tok[0]) {
size_t len = strlen(tok);
if (len + 2 > sizeof(path)) {
print("httpget: path too long\n");
SysExitProcess(1);
}
if (tok[0] != '/') {
path[0] = '/';
memcpy(path + 1, tok, len + 1);
} else {
memcpy(path, tok, len + 1);
}
}
}
}
uint32_t st = resolve_host(host, ip);
if (st != SYS_STATUS_SUCCESS) {
print("httpget: resolve failed "); print_u64(st); print(" for "); print(host); print("\n");
usage();
SysExitProcess(1);
}
char ipText[16];
format_ipv4(ipText, sizeof(ipText), ip);
print("httpget: GET http://");
print(host);
print(path);
print(" (");
print(ipText);
print(")\n");
uint32_t sock = 0;
st = SysSocket(SYS_AF_INET, SYS_SOCK_STREAM, SYS_IPPROTO_TCP, &sock);
if (st != SYS_STATUS_SUCCESS) {
print("httpget: SysSocket failed "); print_u64(st); print("\n");
SysExitProcess(1);
}
SYS_SOCKET_ADDRESS_IPV4 addr;
memset(&addr, 0, sizeof(addr));
addr.Family = SYS_AF_INET;
addr.Port = 80;
addr.Address[0] = ip[0];
addr.Address[1] = ip[1];
addr.Address[2] = ip[2];
addr.Address[3] = ip[3];
st = SysConnect(sock, &addr, sizeof(addr));
if (st != SYS_STATUS_SUCCESS) {
print("httpget: SysConnect failed "); print_u64(st); print("\n");
SysCloseHandle(sock);
SysExitProcess(1);
}
char request[512];
size_t off = 0;
request[0] = 0;
append_str(request, sizeof(request), &off, "GET ");
append_str(request, sizeof(request), &off, path);
append_str(request, sizeof(request), &off, " HTTP/1.0\r\nHost: ");
append_str(request, sizeof(request), &off, host);
append_str(request, sizeof(request), &off, "\r\nUser-Agent: nt-lite-sys-socket\r\nConnection: close\r\n\r\n");
size_t totalSent = 0;
while (totalSent < off) {
size_t sent = 0;
st = SysSend(sock, request + totalSent, off - totalSent, 0, &sent);
if (st != SYS_STATUS_SUCCESS || sent == 0) {
print("httpget: SysSend failed "); print_u64(st); print(" sent="); print_u64(sent); print("\n");
SysCloseHandle(sock);
SysExitProcess(1);
}
totalSent += sent;
}
char buf[513];
size_t total = 0;
for (;;) {
size_t got = 0;
st = SysRecv(sock, buf, sizeof(buf) - 1, 0, &got);
if (st != SYS_STATUS_SUCCESS) {
print("\nhttpget: SysRecv failed "); print_u64(st); print(" after "); print_u64(total); print(" bytes\n");
SysCloseHandle(sock);
SysExitProcess(1);
}
if (got == 0) break;
buf[got] = 0;
print(buf);
total += got;
}
print("\nhttpget: done, "); print_u64(total); print(" bytes\n");
SysShutdown(sock, SYS_SHUTDOWN_BOTH);
SysCloseHandle(sock);
SysExitProcess(0);
return 0;
}
+376
View File
@@ -0,0 +1,376 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <ntlite/syscall.h>
#define PING_DEFAULT_TARGET "10.0.2.2"
#define PING_DEFAULT_COUNT 4u
#define PING_TIMEOUT_MS 1000u
#define US_PER_MS 1000ull
#define PING_PAYLOAD_BYTES 32u
#define PING_PACKET_BYTES (8u + PING_PAYLOAD_BYTES)
static void print(const char* s) {
if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); }
}
static void print_char(char c) {
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
SysWriteConsole(&req);
}
static void print_u64(uint64_t v) {
char buf[32];
int n = 0;
if (v == 0) { print("0"); return; }
while (v && n < (int)sizeof(buf)) {
buf[n++] = (char)('0' + (v % 10));
v /= 10;
}
while (n > 0) print_char(buf[--n]);
}
static void print_ipv4(const uint8_t ip[4]) {
print_u64(ip[0]); print("."); print_u64(ip[1]); print(".");
print_u64(ip[2]); print("."); print_u64(ip[3]);
}
static void print_rtt_us(uint64_t us) {
uint64_t whole = us / US_PER_MS;
uint64_t frac = us % US_PER_MS;
print_u64(whole);
print(".");
if (frac < 100) print("0");
if (frac < 10) print("0");
print_u64(frac);
}
static void format_ipv4(char* out, size_t outSize, const uint8_t ip[4]) {
if (!out || outSize == 0) return;
size_t off = 0;
for (int i = 0; i < 4; i++) {
char tmp[4];
uint32_t v = ip[i];
int n = 0;
if (v >= 100) tmp[n++] = (char)('0' + (v / 100));
if (v >= 10) tmp[n++] = (char)('0' + ((v / 10) % 10));
tmp[n++] = (char)('0' + (v % 10));
for (int j = 0; j < n && off + 1 < outSize; j++) out[off++] = tmp[j];
if (i != 3 && off + 1 < outSize) out[off++] = '.';
}
out[off < outSize ? off : outSize - 1] = 0;
}
static const char* next_token(const char* s, char* out, size_t outSize) {
if (!s || !out || outSize == 0) return NULL;
while (*s == ' ' || *s == '\t') s++;
if (*s == 0) { out[0] = 0; return NULL; }
size_t n = 0;
while (*s && *s != ' ' && *s != '\t') {
if (n + 1 < outSize) out[n++] = *s;
s++;
}
out[n] = 0;
return s;
}
static bool parse_u8(const char** p, uint8_t* out) {
const char* s = *p;
uint32_t v = 0;
int digits = 0;
while (*s >= '0' && *s <= '9') {
v = v * 10u + (uint32_t)(*s - '0');
if (v > 255u) return false;
s++;
digits++;
}
if (digits == 0) return false;
*out = (uint8_t)v;
*p = s;
return true;
}
static bool parse_ipv4(const char* s, uint8_t ip[4]) {
if (!s || !ip) return false;
for (int i = 0; i < 4; i++) {
if (!parse_u8(&s, &ip[i])) return false;
if (i != 3) {
if (*s != '.') return false;
s++;
}
}
return *s == 0;
}
static bool parse_u32(const char* s, uint32_t* out) {
if (!s || !*s || !out) return false;
uint32_t v = 0;
while (*s >= '0' && *s <= '9') {
uint32_t d = (uint32_t)(*s - '0');
if (v > (0xFFFFFFFFu - d) / 10u) return false;
v = v * 10u + d;
s++;
}
if (*s != 0) return false;
*out = v;
return true;
}
static uint32_t resolve_host(const char* host, uint8_t ip[4]) {
if (parse_ipv4(host, ip))
return SYS_STATUS_SUCCESS;
SYS_SOCKET_ADDRESS_IPV4 resolved;
size_t resolvedSize = sizeof(resolved);
SYS_RESOLVE_HOST_REQUEST req;
memset(&resolved, 0, sizeof(resolved));
memset(&req, 0, sizeof(req));
req.Name = SysSvFromCstr(host);
req.Family = SYS_AF_INET;
req.AddressOut = &resolved;
req.AddressSizeInOut = &resolvedSize;
uint32_t st = SysResolveHost(&req);
if (st != SYS_STATUS_SUCCESS)
return st;
if (resolved.Family != SYS_AF_INET)
return SYS_STATUS_NOT_FOUND;
ip[0] = resolved.Address[0];
ip[1] = resolved.Address[1];
ip[2] = resolved.Address[2];
ip[3] = resolved.Address[3];
return SYS_STATUS_SUCCESS;
}
static uint16_t icmp_checksum(const uint8_t* data, size_t length) {
uint32_t sum = 0;
while (length >= 2) {
sum += ((uint32_t)data[0] << 8) | data[1];
data += 2;
length -= 2;
}
if (length)
sum += ((uint32_t)data[0] << 8);
while (sum >> 16)
sum = (sum & 0xFFFFu) + (sum >> 16);
return (uint16_t)(~sum & 0xFFFFu);
}
static void make_echo_request(uint8_t packet[PING_PACKET_BYTES], uint16_t ident, uint16_t seq) {
memset(packet, 0, PING_PACKET_BYTES);
packet[0] = 8; // echo request
packet[1] = 0;
packet[4] = (uint8_t)(ident >> 8);
packet[5] = (uint8_t)(ident & 0xFFu);
packet[6] = (uint8_t)(seq >> 8);
packet[7] = (uint8_t)(seq & 0xFFu);
for (uint32_t i = 0; i < PING_PAYLOAD_BYTES; i++)
packet[8 + i] = (uint8_t)('a' + (i % 26u));
uint16_t sum = icmp_checksum(packet, PING_PACKET_BYTES);
packet[2] = (uint8_t)(sum >> 8);
packet[3] = (uint8_t)(sum & 0xFFu);
}
static bool parse_echo_reply(const uint8_t* buf, size_t len, uint16_t ident, uint16_t seq,
size_t* payloadLenOut, uint8_t* typeOut, uint8_t* codeOut) {
size_t off = 0;
if (len >= 20 && (buf[0] >> 4) == 4) {
size_t ihl = (size_t)(buf[0] & 0x0Fu) * 4u;
if (ihl >= 20 && ihl <= len && buf[9] == SYS_IPPROTO_ICMP)
off = ihl;
}
if (len < off + 8)
return false;
uint8_t type = buf[off + 0];
uint8_t code = buf[off + 1];
if (typeOut) *typeOut = type;
if (codeOut) *codeOut = code;
uint16_t rid = ((uint16_t)buf[off + 4] << 8) | buf[off + 5];
uint16_t rseq = ((uint16_t)buf[off + 6] << 8) | buf[off + 7];
if (type == 0 && code == 0 && rid == ident && rseq == seq) {
if (payloadLenOut)
*payloadLenOut = len - off;
return true;
}
return false;
}
static void usage(void) {
print("usage: apps/ping.exe [host-or-ipv4] [count]\n");
print("default: apps/ping.exe 10.0.2.2 4\n");
}
int main(void) {
char host[256];
char tok[256];
uint32_t count = PING_DEFAULT_COUNT;
strcpy(host, PING_DEFAULT_TARGET);
const char* cmd = SysGetPeb()->CommandLine.Data;
cmd = next_token(cmd, tok, sizeof(tok)); // program path
if (cmd) {
const char* rest = next_token(cmd, tok, sizeof(tok));
if (tok[0]) {
if (strlen(tok) >= sizeof(host)) {
print("ping: host too long\n");
SysExitProcess(1);
}
strcpy(host, tok);
cmd = rest;
}
if (cmd) {
(void)next_token(cmd, tok, sizeof(tok));
if (tok[0] && (!parse_u32(tok, &count) || count == 0 || count > 1000)) {
usage();
SysExitProcess(1);
}
}
}
uint8_t ip[4];
uint32_t st = resolve_host(host, ip);
if (st != SYS_STATUS_SUCCESS) {
print("ping: resolve failed "); print_u64(st); print(" for "); print(host); print("\n");
SysExitProcess(1);
}
char ipText[16];
format_ipv4(ipText, sizeof(ipText), ip);
uint32_t sock = 0;
st = SysSocket(SYS_AF_INET, SYS_SOCK_RAW, SYS_IPPROTO_ICMP, &sock);
if (st != SYS_STATUS_SUCCESS) {
print("ping: SysSocket(raw icmp) failed "); print_u64(st); print("\n");
SysExitProcess(1);
}
uint32_t timeout = PING_TIMEOUT_MS;
SYS_SOCKET_OPTION_REQUEST opt;
memset(&opt, 0, sizeof(opt));
opt.Option = SYS_SOCKET_OPT_RECV_TIMEOUT_MS;
opt.Value = &timeout;
opt.ValueSize = sizeof(timeout);
(void)SysSetSocketOption(sock, &opt);
SYS_SOCKET_ADDRESS_IPV4 remote;
memset(&remote, 0, sizeof(remote));
remote.Family = SYS_AF_INET;
remote.Port = 0;
remote.Address[0] = ip[0];
remote.Address[1] = ip[1];
remote.Address[2] = ip[2];
remote.Address[3] = ip[3];
print("PING "); print(host); print(" ("); print(ipText); print(") ");
print_u64(PING_PAYLOAD_BYTES); print(" data bytes\n");
uint16_t ident = (uint16_t)(SysGetCurrentPid() & 0xFFFFu);
uint32_t sentPackets = 0;
uint32_t receivedPackets = 0;
uint64_t minUs = 0, maxUs = 0, sumUs = 0;
for (uint32_t i = 0; i < count; i++) {
uint16_t seq = (uint16_t)(i + 1u);
uint8_t packet[PING_PACKET_BYTES];
make_echo_request(packet, ident, seq);
size_t sent = 0;
SYS_SOCKET_SEND_TO_REQUEST sendReq;
memset(&sendReq, 0, sizeof(sendReq));
sendReq.Buffer = packet;
sendReq.Length = sizeof(packet);
sendReq.RemoteAddress = &remote;
sendReq.RemoteAddressSize = sizeof(remote);
sendReq.SentOut = &sent;
uint64_t start = SysGetTick();
st = SysSendTo(sock, &sendReq);
if (st != SYS_STATUS_SUCCESS) {
print("ping: send failed seq="); print_u64(seq); print(" status="); print_u64(st); print("\n");
if (i + 1 < count) SysSleep(1000);
continue;
}
sentPackets++;
bool matched = false;
uint8_t lastType = 0, lastCode = 0;
for (;;) {
uint8_t recvBuf[512];
SYS_SOCKET_ADDRESS_IPV4 from;
size_t fromSize = sizeof(from);
size_t got = 0;
SYS_SOCKET_RECV_FROM_REQUEST recvReq;
memset(&recvReq, 0, sizeof(recvReq));
recvReq.Buffer = recvBuf;
recvReq.Length = sizeof(recvBuf);
recvReq.RemoteAddressOut = &from;
recvReq.RemoteAddressSizeInOut = &fromSize;
recvReq.ReceivedOut = &got;
st = SysRecvFrom(sock, &recvReq);
if (st == SYS_STATUS_TIMEOUT)
break;
if (st != SYS_STATUS_SUCCESS) {
print("ping: recv failed status="); print_u64(st); print("\n");
break;
}
size_t icmpLen = 0;
if (parse_echo_reply(recvBuf, got, ident, seq, &icmpLen, &lastType, &lastCode)) {
uint64_t end = SysGetTick();
uint64_t deltaUs = end >= start ? end - start : 0;
receivedPackets++;
sumUs += deltaUs;
if (receivedPackets == 1 || deltaUs < minUs) minUs = deltaUs;
if (deltaUs > maxUs) maxUs = deltaUs;
print_u64(icmpLen); print(" bytes from "); print_ipv4(from.Address);
print(": icmp_seq="); print_u64(seq);
print(" time="); print_rtt_us(deltaUs); print(" ms\n");
matched = true;
break;
}
uint64_t now = SysGetTick();
if (now - start >= ((uint64_t)PING_TIMEOUT_MS * US_PER_MS))
break;
}
if (!matched) {
print("Request timeout for icmp_seq "); print_u64(seq);
if (lastType || lastCode) {
print(" last_type="); print_u64(lastType); print(" code="); print_u64(lastCode);
}
print("\n");
}
if (i + 1 < count)
SysSleep(1000);
}
print("--- "); print(host); print(" ping statistics ---\n");
print_u64(sentPackets); print(" packets transmitted, ");
print_u64(receivedPackets); print(" packets received, ");
uint32_t loss = sentPackets ? (uint32_t)(((uint64_t)(sentPackets - receivedPackets) * 100u) / sentPackets) : 100u;
print_u64(loss); print("% packet loss\n");
if (receivedPackets) {
print("round-trip min/avg/max = ");
print_rtt_us(minUs); print("/"); print_rtt_us(sumUs / receivedPackets); print("/"); print_rtt_us(maxUs); print(" ms\n");
}
SysCloseHandle(sock);
SysExitProcess(receivedPackets ? 0 : 1);
return receivedPackets ? 0 : 1;
}
+81
View File
@@ -0,0 +1,81 @@
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <ntlite/syscall.h>
static void print(const char* s) {
if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); }
}
static void print_char(char c) {
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
SysWriteConsole(&req);
}
static void print_u64(uint64_t v) {
char buf[32];
int n = 0;
if (v == 0) { print("0"); return; }
while (v && n < (int)sizeof(buf)) {
buf[n++] = (char)('0' + (v % 10));
v /= 10;
}
while (n > 0) print_char(buf[--n]);
}
static const char* next_token(const char* s, char* out, size_t outSize) {
if (!s || !out || outSize == 0) return NULL;
while (*s == ' ' || *s == '\t') s++;
if (*s == 0) { out[0] = 0; return NULL; }
size_t n = 0;
while (*s && *s != ' ' && *s != '\t') {
if (n + 1 < outSize) out[n++] = *s;
s++;
}
out[n] = 0;
return s;
}
static void print_ipv4(const uint8_t ip[4]) {
print_u64(ip[0]); print("."); print_u64(ip[1]); print(".");
print_u64(ip[2]); print("."); print_u64(ip[3]);
}
int main(void) {
char name[256];
const char* cmd = SysGetPeb()->CommandLine.Data;
cmd = next_token(cmd, name, sizeof(name)); // program path
(void)cmd;
name[0] = 0;
if (cmd)
(void)next_token(cmd, name, sizeof(name));
if (!name[0]) {
print("usage: resolve.exe hostname\n");
SysExitProcess(1);
}
SYS_SOCKET_ADDRESS_IPV4 addr;
size_t addrSize = sizeof(addr);
SYS_RESOLVE_HOST_REQUEST req;
memset(&addr, 0, sizeof(addr));
memset(&req, 0, sizeof(req));
req.Name = SysSvFromCstr(name);
req.Family = SYS_AF_INET;
req.AddressOut = &addr;
req.AddressSizeInOut = &addrSize;
uint32_t st = SysResolveHost(&req);
if (st != SYS_STATUS_SUCCESS) {
print("resolve: SysResolveHost failed "); print_u64(st); print("\n");
SysExitProcess(1);
}
print(name);
print(" -> ");
print_ipv4(addr.Address);
print("\n");
SysExitProcess(0);
return 0;
}
+285
View File
@@ -0,0 +1,285 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <ntlite/syscall.h>
#define MAX_CMD 256
// ---------------------------------------------------------------------------
// Output helpers
// ---------------------------------------------------------------------------
static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); }
static uint32_t open_file(const char* path, uint32_t* handleOut) {
SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut };
return SysOpenFile(&req);
}
static uint32_t create_file(const char* path, uint32_t* handleOut) {
SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut };
return SysCreateFile(&req);
}
static uint32_t open_dir(const char* path, uint32_t* handleOut) {
SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut };
return SysOpenDir(&req);
}
static uint32_t set_cwd(const char* path) {
SYS_PATH_REQUEST req = { SysSvFromCstr(path) };
return SysSetCwd(&req);
}
static uint32_t delete_file(const char* path) {
SYS_PATH_REQUEST req = { SysSvFromCstr(path) };
return SysDeleteFile(&req);
}
static uint32_t create_process(const char* path, uint32_t* handleOut, const char* cmdline) {
SYS_CREATE_PROCESS_REQUEST req = { SysSvFromCstr(path), SysSvFromCstr(cmdline), handleOut };
return SysCreateProcess(&req);
}
static void printUInt(uint32_t n) {
char buf[12]; int i = 0;
if (n == 0) { print("0"); return; }
while (n > 0) { buf[i++] = (char)('0' + n % 10); n /= 10; }
while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); }
}
static void printInt(int32_t n) {
if (n < 0) { print("-"); printUInt((uint32_t)-(n + 1) + 1); }
else { printUInt((uint32_t)n); }
}
static void printUInt64(uint64_t n) {
if (n == 0) { print("0"); return; }
char buf[20]; int i = 0;
while (n > 0) { buf[i++] = (char)('0' + (int)(n % 10)); n /= 10; }
while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); }
}
// ---------------------------------------------------------------------------
// Line editor
// ---------------------------------------------------------------------------
static void readLine(char* buf, int len) {
int pos = 0;
while (true) {
char c = SysKbReadChar();
if (!c) { SysYield(); continue; }
if (c == '\r' || c == '\n') { print("\n"); break; }
if ((c == '\b' || c == 127) && pos > 0) { pos--; print("\b \b"); continue; }
if (c < 0x20 || c == 127) continue;
if (pos < len - 1) { buf[pos++] = c; char echo[2] = {c, '\0'}; print(echo); }
}
buf[pos] = '\0';
}
static char* trim(char* s) {
while (*s == ' ') s++;
int len = (int)strlen(s);
while (len > 0 && s[len - 1] == ' ') len--;
s[len] = '\0';
return s;
}
// ---------------------------------------------------------------------------
// Built-in commands
// ---------------------------------------------------------------------------
static void cmd_help() {
print("Available commands:\n"
" help - Show this list\n"
" mem - Show memory usage\n"
" dir [path] - List directory contents\n"
" cd <path> - Change directory\n"
" type <file> - Display file contents\n"
" del <file> - Delete a file\n"
" write <file> <tx> - Create a file with text\n"
" clear - Clear the screen\n"
" exit - Close the shell\n");
}
static void printSizeKiB(uint64_t bytes) {
printUInt64(bytes / 1024u);
print(" KiB");
}
static void cmd_mem(void) {
SYS_MEMORY_STATUS st;
if (SysGetMemoryStatus(&st) != 0) {
print("mem: failed\n");
return;
}
print("Memory Status:\n");
print(" Free physical: ");
printSizeKiB(st.FreePhysicalBytes);
print("\n Kernel pool: ");
printSizeKiB(st.KernelPoolBytes);
print("\n User heap: ");
printSizeKiB(st.UserHeapBytes);
print("\n");
}
static void cmd_write(const char* args) {
char filename[MAX_CMD]; int i = 0;
while (args[i] != ' ' && args[i] != '\0' && i < MAX_CMD - 1) {
filename[i] = args[i]; i++;
}
filename[i] = '\0';
if (args[i] == '\0' || args[i+1] == '\0') { print("write: usage: write <filename> <text>\n"); return; }
uint32_t hFile;
if (create_file(filename, &hFile) != 0) { print("write: could not create file\n"); return; }
size_t written;
SysWriteFile(hFile, args + i + 1, strlen(args + i + 1), &written);
SysCloseHandle(hFile);
print("File written successfully.\n");
}
static void cmd_dir(const char* path) {
uint32_t hDir;
const char* target = (path && *path != '\0') ? path : ".";
if (open_dir(target, &hDir) != 0) {
print("dir: failed to open directory\n");
return;
}
SYS_DIR_ENTRY ke;
while (SysReadDir(hDir, &ke) == 0) {
// Corrected Attribute Check: 0x10 is the Directory bit in FAT
if (ke.Attr & 0x10) {
print("<DIR> ");
} else {
print(" ");
}
print(ke.Name);
// Optional: print file size for non-directories
if (!(ke.Attr & 0x10)) {
print(" (");
printUInt(ke.FileSize);
print(" bytes)");
}
print("\n");
}
SysCloseHandle(hDir);
}
static void cmd_type(const char* filename) {
uint32_t hFile;
if (open_file(filename, &hFile) != 0) { print("type: cannot open file\n"); return; }
char buffer[512]; size_t bytesRead;
while (SysReadFile(hFile, buffer, sizeof(buffer) - 1, &bytesRead) == 0 && bytesRead > 0) {
buffer[bytesRead] = '\0'; print(buffer);
}
SysCloseHandle(hFile); print("\n");
}
static bool extractProgramPath(const char* cmdline, char* out, size_t outSize) {
if (!cmdline || !out || outSize == 0) return false;
while (*cmdline == ' ' || *cmdline == '\t') cmdline++;
if (*cmdline == '\0') return false;
size_t pos = 0;
if (*cmdline == '"') {
cmdline++;
while (*cmdline && *cmdline != '"' && pos + 1 < outSize)
out[pos++] = *cmdline++;
} else {
while (*cmdline && *cmdline != ' ' && *cmdline != '\t' && pos + 1 < outSize)
out[pos++] = *cmdline++;
}
out[pos] = '\0';
return pos != 0;
}
// ---------------------------------------------------------------------------
// Run one command
// ---------------------------------------------------------------------------
static int runCommand(const char* cmd) {
if (!cmd || *cmd == '\0') return 0;
if (strcmp(cmd, "exit") == 0) return 1;
if (strcmp(cmd, "help") == 0) { cmd_help(); return 0; }
if (strcmp(cmd, "clear") == 0) { SysScreenClear(0); return 0; }
if (strncmp(cmd, "crash", 5) == 0) {
// Check the sub-option trailing "crash " (offset 6)
if (strcmp(cmd + 6, "void") == 0) {
// Jumping into the void
void (*invalid_func)(void) = NULL;
invalid_func();
return 0;
}
else if (strcmp(cmd + 6, "noncanonical") == 0) {
// Non-canonical pointer dereference
volatile int *ptr = (volatile int*)0x4242424242424242ULL;
*ptr = 1337;
return 0;
}
else if (strcmp(cmd + 6, "ud2") == 0) {
__ud2();
return 0;
}
else if (strcmp(cmd + 6, "nx") == 0) {
// NX / DEP Violation
unsigned char code[] = { 0xC3 };
void (*execute_stack)(void) = (void (*)(void))code;
execute_stack();
return 0;
}
else if (strcmp(cmd + 6, "divzero") == 0) {
// Division by zero
volatile int zero = 0;
volatile int result = 1 / zero;
(void)result;
return 0;
}
else {
// Default fallback if just "crash" or an unknown sub-option is passed
*(volatile int*)0 = 42;
return 0;
}
}
if (strcmp(cmd, "mem") == 0) { cmd_mem(); return 0; }
if (strcmp(cmd, "dir") == 0) { cmd_dir("."); return 0; }
if (strncmp(cmd, "dir ", 4) == 0) { cmd_dir(cmd + 4); return 0; }
if (strncmp(cmd, "cd ", 3) == 0) { if (set_cwd(cmd + 3) != 0) print("cd: failed\n"); return 0; }
if (strncmp(cmd, "del ", 4) == 0) { delete_file(cmd + 4); return 0; }
if (strncmp(cmd, "type ", 5) == 0) { cmd_type(cmd + 5); return 0; }
if (strncmp(cmd, "write ", 6) == 0) { cmd_write(cmd + 6); return 0; }
char program[MAX_CMD];
if (!extractProgramPath(cmd, program, sizeof(program))) return 0;
uint32_t hProc;
if (create_process(program, &hProc, cmd) == 0) {
SysWaitForProcess(hProc);
SysCloseHandle(hProc);
while (SysKbPoll()) (void)SysKbReadChar();
} else { print("shell: launch failed\n"); }
return 0;
}
int main(void) {
const char* cmdline = SysGetPeb()->CommandLine.Data;
char lineBuf[MAX_CMD];
print("shell: command line: ");
print(cmdline);
print("\n");
print("shell: ready\n");
while (true) {
print("> ");
readLine(lineBuf, MAX_CMD);
if (runCommand(trim(lineBuf))) break;
}
print("shell: goodbye\n");
SysExitProcess(0);
return 0;
}
+182
View File
@@ -0,0 +1,182 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <ntlite/syscall.h>
#define MAX_CMD 256
#define NAME_MAX 259
typedef struct dirent { char d_name[NAME_MAX + 1]; unsigned char d_type; } dirent;
typedef struct DIR { uint32_t KHandle; dirent Current; bool Valid; } DIR;
extern int read(int fd, void *buf, size_t count);
extern int write(int fd, const void *buf, size_t count);
extern int open(const char *pathname, int flags, ...);
extern int close(int fd);
extern int chdir(const char *path);
extern DIR* opendir(const char* path);
extern dirent* readdir(DIR* d);
extern int closedir(DIR* d);
extern int unlink(const char *pathname);
extern int posix_spawn(int *pid, const char *path, const void *act, const void *attr, char *const argv[], char *const envp[]);
extern int waitpid(int pid, int *status, int options);
extern void exit(int status);
extern void clearscreen(void);
extern void clearkeyboard(void);
extern void PosixFdInit(void);
static int hIn = 0; static int hOut = 1;
static void print(const char* s) { write(hOut, s, strlen(s)); }
static void printUInt(uint32_t n) {
char buf[12]; int i = 0;
if (n == 0) { print("0"); return; }
while (n > 0) { buf[i++] = (char)('0' + n % 10); n /= 10; }
while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); }
}
static void printInt(int32_t n) {
if (n < 0) { print("-"); n = -n; }
printUInt((uint32_t)n);
}
static void readLine(char* buf, int len) {
int pos = 0;
while (true) {
char c; if (read(hIn, &c, 1) <= 0) break;
if (c == '\r' || c == '\n') { print("\n"); break; }
if ((c == '\b' || c == 127) && pos > 0) { pos--; print("\b \b"); continue; }
if (c < 0x20 || c == 127) continue;
if (pos < len - 1) { buf[pos++] = c; char echo[2] = {c, '\0'}; print(echo); }
}
buf[pos] = '\0';
}
static int splitCommandLine(char* line, char** argv, int maxArgv) {
int argc = 0;
char* p = line;
while (*p && argc < maxArgv - 1) {
while (*p == ' ' || *p == '\t') p++;
if (!*p) break;
if (*p == '"') {
p++;
argv[argc++] = p;
while (*p && *p != '"') p++;
if (*p) *p++ = '\0';
} else {
argv[argc++] = p;
while (*p && *p != ' ' && *p != '\t') p++;
if (*p) *p++ = '\0';
}
}
argv[argc] = NULL;
return argc;
}
static char* trim(char* s) {
while (*s == ' ') s++;
int len = (int)strlen(s);
while (len > 0 && s[len - 1] == ' ') len--;
s[len] = '\0';
return s;
}
static void cmd_help() {
print("Available commands:\n"
" help - Show this list\n"
" dir [path] - List directory contents\n"
" cd <path> - Change directory\n"
" type <file> - Display file contents\n"
" del <file> - Delete a file\n"
" write <file> <txt> - Create a file with text\n"
" clear - Clear the screen\n"
" exit - Close the shell\n");
}
static void cmd_write(const char* args) {
char filename[MAX_CMD]; int i = 0;
while (args[i] != ' ' && args[i] != '\0' && i < MAX_CMD - 1) {
filename[i] = args[i]; i++;
}
filename[i] = '\0';
if (args[i] == '\0' || args[i+1] == '\0') { print("write: usage: write <filename> <text>\n"); return; }
int fd = open(filename, 0x0241, 0644); // O_WRONLY | O_CREAT | O_TRUNC
if (fd < 0) { print("write: could not create file\n"); return; }
write(fd, args + i + 1, strlen(args + i + 1));
close(fd);
print("File written successfully.\n");
}
static void cmd_dir(const char* path) {
const char* target = (path && *path != '\0') ? path : ".";
DIR* d = opendir(target);
if (!d) { print("dir: cannot access directory\n"); return; }
dirent* entry;
while ((entry = readdir(d)) != NULL) {
print(entry->d_type == 1 ? "<DIR> " : " ");
print(entry->d_name); print("\n");
}
closedir(d);
}
static void cmd_type(const char* filename) {
int fd = open(filename, 0); // O_RDONLY
if (fd < 0) { print("type: cannot open file\n"); return; }
char buffer[512]; int n;
while ((n = read(fd, buffer, 511)) > 0) { buffer[n] = '\0'; print(buffer); }
close(fd); print("\n");
}
static int runCommand(const char* cmd) {
if (!cmd || *cmd == '\0') return 0;
if (strcmp(cmd, "exit") == 0) return 1;
if (strcmp(cmd, "help") == 0) { cmd_help(); return 0; }
if (strcmp(cmd, "clear") == 0) { clearscreen(); return 0; }
if (strcmp(cmd, "crash") == 0) { *(int*)0 = 42; return 0; }
if (strcmp(cmd, "dir") == 0) { cmd_dir("."); return 0; }
if (strncmp(cmd, "dir ", 4) == 0) { cmd_dir(cmd + 4); return 0; }
if (strncmp(cmd, "cd ", 3) == 0) { if (chdir(cmd + 3) != 0) print("cd: failed\n"); return 0; }
if (strncmp(cmd, "del ", 4) == 0) { unlink(cmd + 4); return 0; }
if (strncmp(cmd, "type ", 5) == 0) { cmd_type(cmd + 5); return 0; }
if (strncmp(cmd, "write ", 6) == 0) { cmd_write(cmd + 6); return 0; }
char cmdBuf[MAX_CMD];
strncpy(cmdBuf, cmd, MAX_CMD - 1);
cmdBuf[MAX_CMD - 1] = '\0';
char* argv[32];
int argc = splitCommandLine(cmdBuf, argv, 32);
if (argc == 0) return 0;
int pid;
if (posix_spawn(&pid, argv[0], NULL, NULL, argv, NULL) == 0) {
int status; waitpid(pid, &status, 0);
clearkeyboard();
} else { print("shell: launch failed\n"); }
return 0;
}
int main(void) {
PosixFdInit();
const char* cmdline = SysGetPeb()->CommandLine.Data;
char lineBuf[MAX_CMD];
print("shell: command line: ");
print(cmdline);
print("\n");
print("shell: ready\n");
while (true) {
print("> ");
readLine(lineBuf, MAX_CMD);
if (runCommand(trim(lineBuf))) break;
}
print("shell: goodbye\n");
exit(0);
}
+166
View File
@@ -0,0 +1,166 @@
#include <windows.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#define MAX_CMD 256
static HANDLE hIn = INVALID_HANDLE_VALUE;
static HANDLE hOut = INVALID_HANDLE_VALUE;
// External/Custom API
BOOL ClearConsoleScreenBuffer(HANDLE hConsole);
// --- Output Helpers ---
static void print(const char* s) {
DWORD written;
if (hOut != INVALID_HANDLE_VALUE) WriteConsoleA(hOut, s, (DWORD)strlen(s), &written, 0);
else OutputDebugStringA(s);
}
static void printUInt(uint32_t n) {
char buf[12]; int i = 0;
if (n == 0) { print("0"); return; }
while (n > 0) { buf[i++] = (char)('0' + n % 10); n /= 10; }
while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); }
}
static void printInt(int32_t n) {
if (n < 0) { print("-"); n = -n; }
printUInt((uint32_t)n);
}
// --- Line Editor ---
static void readLine(char* buf, int len) {
int pos = 0;
while (true) {
char c; DWORD nRead;
ReadConsoleA(hIn, &c, 1, &nRead, 0);
if (!nRead) continue;
if (c == '\r' || c == '\n') { print("\n"); break; }
if ((c == '\b' || c == 127) && pos > 0) { pos--; print("\b \b"); continue; }
if (c < 0x20 || c == 127) continue;
if (pos < len - 1) {
buf[pos++] = c;
char echo[2] = { c, '\0' };
print(echo);
}
}
buf[pos] = '\0';
}
static char* trim(char* s) {
while (*s == ' ') s++;
int len = (int)strlen(s);
while (len > 0 && s[len - 1] == ' ') len--;
s[len] = '\0';
return s;
}
// --- Built-in Commands ---
static void cmd_help() {
print("Available commands:\n"
" help - Show this list\n"
" dir [path] - List directory contents\n"
" cd <path> - Change directory\n"
" type <file> - Display file contents\n"
" del <file> - Delete a file\n"
" write <file> <tx> - Create a file with text\n"
" clear - Clear the screen\n"
" exit - Close the shell\n");
}
static void cmd_write(const char* args) {
char filename[MAX_PATH]; int i = 0;
while (args[i] != ' ' && args[i] != '\0' && i < MAX_PATH - 1) {
filename[i] = args[i]; i++;
}
filename[i] = '\0';
if (args[i] == '\0' || args[i+1] == '\0') {
print("write: usage: write <filename> <text>\n");
return;
}
HANDLE hFile = CreateFileA(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (hFile == INVALID_HANDLE_VALUE) { print("write: could not create file\n"); return; }
DWORD written;
WriteFile(hFile, args + i + 1, (DWORD)strlen(args + i + 1), &written, 0);
CloseHandle(hFile);
print("File written successfully.\n");
}
static void cmd_dir(const char* path) {
WIN32_FIND_DATAA fd;
char search_path[MAX_PATH];
const char* target = (path && *path != '\0') ? path : ".";
size_t len = strlen(target);
if (len + 3 > MAX_PATH) { print("dir: path too long\n"); return; }
strcpy(search_path, target);
strcat(search_path, "\\*");
HANDLE hFind = FindFirstFileA(search_path, &fd);
if (hFind == INVALID_HANDLE_VALUE) { print("dir: failed to read directory\n"); return; }
do {
print(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? "<DIR> " : " ");
print(fd.cFileName); print("\n");
} while (FindNextFileA(hFind, &fd));
FindClose(hFind);
}
static void cmd_type(const char* filename) {
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile == INVALID_HANDLE_VALUE) { print("type: cannot open file\n"); return; }
char buffer[512]; DWORD bytesRead;
while (ReadFile(hFile, buffer, sizeof(buffer) - 1, &bytesRead, 0) && bytesRead > 0) {
buffer[bytesRead] = '\0'; print(buffer);
}
CloseHandle(hFile); print("\n");
}
static int runCommand(const char* cmd) {
if (!cmd || *cmd == '\0') return 0;
if (strcmp(cmd, "exit") == 0) return 1;
if (strcmp(cmd, "help") == 0) { cmd_help(); return 0; }
if (strcmp(cmd, "clear") == 0) { ClearConsoleScreenBuffer(hOut); return 0; }
if (strcmp(cmd, "crash") == 0) { *(int*)0 = 42; return 0; }
if (strcmp(cmd, "dir") == 0) { cmd_dir("."); return 0; }
if (strncmp(cmd, "dir ", 4) == 0) { cmd_dir(cmd + 4); return 0; }
if (strncmp(cmd, "cd ", 3) == 0) { if (!SetCurrentDirectoryA(cmd + 3)) print("cd: failed\n"); return 0; }
if (strncmp(cmd, "del ", 4) == 0) { DeleteFileA(cmd + 4); return 0; }
if (strncmp(cmd, "type ", 5) == 0) { cmd_type(cmd + 5); return 0; }
if (strncmp(cmd, "write ", 6) == 0) { cmd_write(cmd + 6); return 0; }
PROCESS_INFORMATION pi;
char cmdBuf[MAX_CMD];
strncpy(cmdBuf, cmd, MAX_CMD - 1);
cmdBuf[MAX_CMD - 1] = '\0';
if (CreateProcessA(NULL, cmdBuf, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE);
if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
CloseHandle(pi.hThread);
FlushConsoleInputBuffer(hIn);
} else {
print("shell: launch failed\n");
}
return 0;
}
int main(void) {
hIn = GetStdHandle(STD_INPUT_HANDLE);
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
const char* cmdline = GetCommandLineA();
char lineBuf[MAX_CMD];
print("shell: command line: ");
print(cmdline);
print("\n");
print("shell: ready\n");
while (true) {
print("> ");
readLine(lineBuf, MAX_CMD);
if (runCommand(trim(lineBuf))) break;
}
print("shell: goodbye\n");
ExitProcess(0);
}
+183
View File
@@ -0,0 +1,183 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <ntlite/syscall.h>
static void print(const char* s) {
if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); }
}
static void print_char(char c) {
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
SysWriteConsole(&req);
}
static void print_u64(uint64_t v) {
char buf[32];
int n = 0;
if (v == 0) { print("0"); return; }
while (v && n < (int)sizeof(buf)) {
buf[n++] = (char)('0' + (v % 10));
v /= 10;
}
while (n > 0) print_char(buf[--n]);
}
static void print_ipv4(const uint8_t ip[4]) {
print_u64(ip[0]); print("."); print_u64(ip[1]); print(".");
print_u64(ip[2]); print("."); print_u64(ip[3]);
}
static const char* next_token(const char* s, char* out, size_t outSize) {
if (!s || !out || outSize == 0) return NULL;
while (*s == ' ' || *s == '\t') s++;
if (*s == 0) { out[0] = 0; return NULL; }
size_t n = 0;
while (*s && *s != ' ' && *s != '\t') {
if (n + 1 < outSize) out[n++] = *s;
s++;
}
out[n] = 0;
return s;
}
static bool parse_port(const char* s, uint16_t* out) {
if (!s || !*s || !out) return false;
uint32_t v = 0;
while (*s >= '0' && *s <= '9') {
v = v * 10u + (uint32_t)(*s - '0');
if (v > 65535u) return false;
s++;
}
if (*s != 0 || v == 0) return false;
*out = (uint16_t)v;
return true;
}
static void usage(void) {
print("usage: tcpserve.exe [port]\n");
print("default: tcpserve.exe 8080\n");
}
int main(void) {
uint16_t port = 8080;
const char* cmd = SysGetPeb()->CommandLine.Data;
char tok[64];
cmd = next_token(cmd, tok, sizeof(tok)); // program path
if (cmd) {
(void)next_token(cmd, tok, sizeof(tok));
if (tok[0] && !parse_port(tok, &port)) {
usage();
SysExitProcess(1);
}
}
uint32_t listener = 0;
uint32_t st = SysSocket(SYS_AF_INET, SYS_SOCK_STREAM, SYS_IPPROTO_TCP, &listener);
if (st != SYS_STATUS_SUCCESS) {
print("tcpserve: SysSocket failed "); print_u64(st); print("\n");
SysExitProcess(1);
}
SYS_SOCKET_ADDRESS_IPV4 bindAddr;
memset(&bindAddr, 0, sizeof(bindAddr));
bindAddr.Family = SYS_AF_INET;
bindAddr.Port = port;
bindAddr.Address[0] = 0;
bindAddr.Address[1] = 0;
bindAddr.Address[2] = 0;
bindAddr.Address[3] = 0;
st = SysBind(listener, &bindAddr, sizeof(bindAddr));
if (st != SYS_STATUS_SUCCESS) {
print("tcpserve: SysBind failed "); print_u64(st); print("\n");
SysCloseHandle(listener);
SysExitProcess(1);
}
st = SysListen(listener, 4);
if (st != SYS_STATUS_SUCCESS) {
print("tcpserve: SysListen failed "); print_u64(st); print("\n");
SysCloseHandle(listener);
SysExitProcess(1);
}
print("tcpserve: listening on 0.0.0.0:"); print_u64(port); print("\n");
print("tcpserve: accepting one connection...\n");
SYS_SOCKET_ADDRESS_IPV4 remote;
size_t remoteSize = sizeof(remote);
uint32_t client = 0;
st = SysAccept(listener, &remote, &remoteSize, &client);
if (st != SYS_STATUS_SUCCESS) {
print("tcpserve: SysAccept failed "); print_u64(st); print("\n");
SysCloseHandle(listener);
SysExitProcess(1);
}
print("tcpserve: accepted from ");
if (remote.Family == SYS_AF_INET) {
print_ipv4(remote.Address);
print(":"); print_u64(remote.Port);
} else {
print("unknown");
}
print("\n");
char request[1025];
size_t got = 0;
st = SysRecv(client, request, sizeof(request) - 1, 0, &got);
if (st != SYS_STATUS_SUCCESS) {
print("tcpserve: SysRecv failed "); print_u64(st); print("\n");
SysCloseHandle(client);
SysCloseHandle(listener);
SysExitProcess(1);
}
request[got] = 0;
print("tcpserve: received "); print_u64(got); print(" bytes\n");
if (got) {
print("--- request begins ---\n");
print(request);
print("\n--- request ends ---\n");
}
const char body[] = "hello from nt-lite tcpserve\n";
char response[256];
size_t off = 0;
#define APPEND_LITERAL(x) do { const char* _s = (x); while (*_s && off + 1 < sizeof(response)) response[off++] = *_s++; response[off] = 0; } while (0)
APPEND_LITERAL("HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\nContent-Length: ");
char lenbuf[24];
uint64_t len = sizeof(body) - 1;
int n = 0;
if (len == 0) lenbuf[n++] = '0';
else {
char rev[24];
while (len && n < (int)sizeof(rev)) { rev[n++] = (char)('0' + (len % 10)); len /= 10; }
for (int i = n - 1; i >= 0 && off + 1 < sizeof(response); --i) response[off++] = rev[i];
response[off] = 0;
n = 0;
}
if (n) {
for (int i = 0; i < n && off + 1 < sizeof(response); ++i) response[off++] = lenbuf[i];
response[off] = 0;
}
APPEND_LITERAL("\r\n\r\n");
#undef APPEND_LITERAL
size_t sent = 0;
st = SysSend(client, response, off, 0, &sent);
if (st == SYS_STATUS_SUCCESS)
st = SysSend(client, body, sizeof(body) - 1, 0, &sent);
if (st != SYS_STATUS_SUCCESS)
print("tcpserve: SysSend failed "), print_u64(st), print("\n");
SysShutdown(client, SYS_SHUTDOWN_BOTH);
SysCloseHandle(client);
SysCloseHandle(listener);
print("tcpserve: done\n");
SysExitProcess(0);
return 0;
}
+233
View File
@@ -0,0 +1,233 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <ntlite/syscall.h>
static void print(const char* s) {
if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); }
}
static void print_char(char c) {
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
SysWriteConsole(&req);
}
static void print_u64(uint64_t v) {
char buf[32];
int n = 0;
if (v == 0) { print("0"); return; }
while (v && n < (int)sizeof(buf)) {
buf[n++] = (char)('0' + (v % 10));
v /= 10;
}
while (n > 0) print_char(buf[--n]);
}
static void print_ipv4(const uint8_t ip[4]) {
print_u64(ip[0]); print("."); print_u64(ip[1]); print(".");
print_u64(ip[2]); print("."); print_u64(ip[3]);
}
static const char* next_token(const char* s, char* out, size_t outSize) {
if (!s || !out || outSize == 0) return NULL;
while (*s == ' ' || *s == '\t') s++;
if (*s == 0) { out[0] = 0; return NULL; }
size_t n = 0;
while (*s && *s != ' ' && *s != '\t') {
if (n + 1 < outSize) out[n++] = *s;
s++;
}
out[n] = 0;
return s;
}
static bool parse_u8(const char** p, uint8_t* out) {
const char* s = *p;
uint32_t v = 0;
int digits = 0;
while (*s >= '0' && *s <= '9') {
v = v * 10u + (uint32_t)(*s - '0');
if (v > 255u) return false;
s++;
digits++;
}
if (digits == 0) return false;
*out = (uint8_t)v;
*p = s;
return true;
}
static bool parse_ipv4(const char* s, uint8_t ip[4]) {
if (!s || !ip) return false;
for (int i = 0; i < 4; i++) {
if (!parse_u8(&s, &ip[i])) return false;
if (i != 3) {
if (*s != '.') return false;
s++;
}
}
return *s == 0;
}
static bool parse_port(const char* s, uint16_t* out) {
if (!s || !*s || !out) return false;
uint32_t v = 0;
while (*s >= '0' && *s <= '9') {
v = v * 10u + (uint32_t)(*s - '0');
if (v > 65535u) return false;
s++;
}
if (*s != 0 || v == 0) return false;
*out = (uint16_t)v;
return true;
}
static void usage(void) {
print("usage:\n");
print(" udp.exe send <ipv4> <port> [message]\n");
print(" udp.exe listen <port>\n");
print("examples:\n");
print(" udp.exe send 10.0.2.2 9999 hello\n");
print(" udp.exe listen 9999\n");
}
static int run_send(const char* cmd) {
char tok[256];
uint8_t ip[4];
uint16_t port = 0;
cmd = next_token(cmd, tok, sizeof(tok));
if (!tok[0] || !parse_ipv4(tok, ip)) { usage(); return 1; }
cmd = next_token(cmd, tok, sizeof(tok));
if (!tok[0] || !parse_port(tok, &port)) { usage(); return 1; }
// Skip leading whitespace, then take the entire remaining command line
if (cmd) {
while (*cmd == ' ' || *cmd == '\t') {
cmd++;
}
}
const char* msg = "hello from nt-lite udp\n";
if (cmd && *cmd != '\0') {
msg = cmd;
}
uint32_t sock = 0;
uint32_t st = SysSocket(SYS_AF_INET, SYS_SOCK_DGRAM, SYS_IPPROTO_UDP, &sock);
if (st != SYS_STATUS_SUCCESS) {
print("udp: SysSocket failed "); print_u64(st); print("\n");
return 1;
}
SYS_SOCKET_ADDRESS_IPV4 remote;
memset(&remote, 0, sizeof(remote));
remote.Family = SYS_AF_INET;
remote.Port = port;
remote.Address[0] = ip[0];
remote.Address[1] = ip[1];
remote.Address[2] = ip[2];
remote.Address[3] = ip[3];
size_t sent = 0;
SYS_SOCKET_SEND_TO_REQUEST req;
memset(&req, 0, sizeof(req));
req.Buffer = msg;
req.Length = strlen(msg);
req.RemoteAddress = &remote;
req.RemoteAddressSize = sizeof(remote);
req.SentOut = &sent;
st = SysSendTo(sock, &req);
SysCloseHandle(sock);
if (st != SYS_STATUS_SUCCESS) {
print("udp: SysSendTo failed "); print_u64(st); print("\n");
return 1;
}
print("udp: sent "); print_u64(sent); print(" bytes to "); print_ipv4(ip); print(":"); print_u64(port); print("\n");
return 0;
}
static int run_listen(const char* cmd) {
char tok[64];
uint16_t port = 0;
(void)next_token(cmd, tok, sizeof(tok));
if (!tok[0] || !parse_port(tok, &port)) { usage(); return 1; }
uint32_t sock = 0;
uint32_t st = SysSocket(SYS_AF_INET, SYS_SOCK_DGRAM, SYS_IPPROTO_UDP, &sock);
if (st != SYS_STATUS_SUCCESS) {
print("udp: SysSocket failed "); print_u64(st); print("\n");
return 1;
}
SYS_SOCKET_ADDRESS_IPV4 bindAddr;
memset(&bindAddr, 0, sizeof(bindAddr));
bindAddr.Family = SYS_AF_INET;
bindAddr.Port = port;
st = SysBind(sock, &bindAddr, sizeof(bindAddr));
if (st != SYS_STATUS_SUCCESS) {
print("udp: SysBind failed "); print_u64(st); print("\n");
SysCloseHandle(sock);
return 1;
}
print("udp: listening on 0.0.0.0:"); print_u64(port); print(" for one datagram\n");
char buf[1025];
SYS_SOCKET_ADDRESS_IPV4 remote;
size_t remoteSize = sizeof(remote);
size_t got = 0;
SYS_SOCKET_RECV_FROM_REQUEST req;
memset(&req, 0, sizeof(req));
req.Buffer = buf;
req.Length = sizeof(buf) - 1;
req.RemoteAddressOut = &remote;
req.RemoteAddressSizeInOut = &remoteSize;
req.ReceivedOut = &got;
st = SysRecvFrom(sock, &req);
SysCloseHandle(sock);
if (st != SYS_STATUS_SUCCESS) {
print("udp: SysRecvFrom failed "); print_u64(st); print("\n");
return 1;
}
buf[got] = 0;
print("udp: received "); print_u64(got); print(" bytes from ");
if (remote.Family == SYS_AF_INET) {
print_ipv4(remote.Address); print(":"); print_u64(remote.Port);
} else {
print("unknown");
}
print("\n");
print(buf);
if (got && buf[got - 1] != '\n') print("\n");
return 0;
}
int main(void) {
const char* cmd = SysGetPeb()->CommandLine.Data;
char tok[64];
cmd = next_token(cmd, tok, sizeof(tok)); // program path
cmd = next_token(cmd, tok, sizeof(tok)); // verb
if (!tok[0]) { usage(); SysExitProcess(1); }
int rc;
if (strcmp(tok, "send") == 0) {
rc = run_send(cmd);
} else if (strcmp(tok, "listen") == 0) {
rc = run_listen(cmd);
} else {
usage();
rc = 1;
}
SysExitProcess(rc);
return rc;
}
File diff suppressed because it is too large. Load diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
+148
View File
@@ -0,0 +1,148 @@
#include <windows.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <intrin.h>
#include "bink.h"
static const char* commandLineSecondToken(const char* cmdline, char* out, size_t outSize) {
if (!out || outSize == 0) return "video.bk2";
strcpy(out, "video.bk2");
if (!cmdline) return out;
while (*cmdline == ' ' || *cmdline == '\t') cmdline++;
if (*cmdline == '\0') return out;
if (*cmdline == '"') {
cmdline++;
while (*cmdline && *cmdline != '"') cmdline++;
if (*cmdline == '"') cmdline++;
} else {
while (*cmdline && *cmdline != ' ' && *cmdline != '\t') cmdline++;
}
while (*cmdline == ' ' || *cmdline == '\t') cmdline++;
if (*cmdline == '\0') return out;
size_t pos = 0;
if (*cmdline == '"') {
cmdline++;
while (*cmdline && *cmdline != '"' && pos + 1 < outSize)
out[pos++] = *cmdline++;
} else {
while (*cmdline && *cmdline != ' ' && *cmdline != '\t' && pos + 1 < outSize)
out[pos++] = *cmdline++;
}
out[pos] = '\0';
return out;
}
int main(void) {
const char* cmdline = GetCommandLineA();
char videoPath[260];
const char* path = commandLineSecondToken(cmdline, videoPath, sizeof(videoPath));
void* h = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsoleA(h, "video: starting\n", 16, 0, 0);
WriteConsoleA(h, cmdline, (unsigned int)strlen(cmdline), 0, 0);
WriteConsoleA(h, "\n", 1, 0, 0);
void* f = CreateFileA(path, 0, 0, 0, 3, 0, 0);
if (!f || f == (void*)(unsigned long long)0xFFFFFFFF) { // fuckass
WriteConsoleA(h, "video: failed to open input file\n", 33, 0, 0);
ExitProcess(1);
}
unsigned long s = GetFileSize(f, 0);
if (!s || s == 0xFFFFFFFF) {
WriteConsoleA(h, "video: GetFileSize failed!\n", 27, 0, 0);
ExitProcess(1);
}
void* buf = HeapAlloc(0, 0, s);
if (!buf) {
WriteConsoleA(h, "video: HeapAlloc failed\n", 24, 0, 0);
ExitProcess(1);
}
int r = ReadFile(f, buf, s, 0, 0);
if (!r) {
WriteConsoleA(h, "video: ReadFile failed\n", 23, 0, 0);
ExitProcess(1);
}
WriteConsoleA(h, "video: input file loaded\n", 25, 0, 0);
CloseHandle(h);
HBINK b = BinkOpen(buf, BINKFROMMEMORY);
if (!b) {
WriteConsoleA(h, "video: BinkOpen failed: ", 24, 0, 0);
const char* err = BinkGetError();
WriteConsoleA(h, err, (unsigned int)strlen(err), 0, 0);
WriteConsoleA(h, "\n", 1, 0, 0);
ExitProcess(1);
}
uint32_t width = b->Width;
uint32_t height = b->Height;
uint32_t* fb = HeapAlloc(0, 0, width * height * sizeof(uint32_t));
if (!fb) {
WriteConsoleA(h, "video: framebuffer alloc failed\n", 32, 0, 0);
ExitProcess(1);
}
// Prepare the Win32 BITMAPINFO structure
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -(LONG)height; // Negative means top-down drawing!
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
while (1) {
if (BinkWait(b)) {
_mm_pause();
continue;
}
BinkDoFrame(b);
if (BinkShouldSkip(b)) {
BinkNextFrame(b);
BinkDoFrame(b);
continue;
}
BinkCopyToBuffer(b, fb, width * 4, height, 0, 0,
BINKSURFACE32);
// Welcome to the GDI pipeline!
PAINTSTRUCT ps;
// Using NULL/0 as the HWND since we don't have a real window handle yet
HDC hdc = BeginPaint((HWND)0, &ps);
StretchDIBits(
hdc,
0, 0, width, height, // Destination rect
0, 0, width, height, // Source rect
fb,
&bmi,
DIB_RGB_COLORS,
SRCCOPY
);
EndPaint((HWND)0, &ps);
if (b->FrameNum == b->Frames)
break;
BinkNextFrame(b);
}
WriteConsoleA(h, "video: goodbye\n", 15, 0, 0);
ExitProcess(0);
}