Add app launcher and oskrnl
This commit is contained in:
@@ -218,6 +218,408 @@ duk_ret_t native_irq_register(duk_context *ctx)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Proxy getter for __oskrnl that forwards to root context's globalThis.__oskrnl
|
||||
duk_ret_t oskrnl_proxy_getter(duk_context *isolated_ctx)
|
||||
{
|
||||
// Get the property name being accessed
|
||||
const char *prop_name = duk_require_string(isolated_ctx, 1);
|
||||
|
||||
// Get the root context from the hidden symbol in the isolated context
|
||||
duk_push_global_stash(isolated_ctx);
|
||||
duk_get_prop_string(isolated_ctx, -1, "\xFF"
|
||||
"root_ctx_ptr");
|
||||
duk_context *root_ctx = (duk_context *)duk_get_pointer(isolated_ctx, -1);
|
||||
duk_pop_2(isolated_ctx);
|
||||
|
||||
if (root_ctx == NULL)
|
||||
{
|
||||
duk_push_undefined(isolated_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Access globalThis.__oskrnl[prop_name] in the root context
|
||||
duk_push_global_object(root_ctx);
|
||||
duk_get_prop_string(root_ctx, -1, "__oskrnl");
|
||||
|
||||
if (!duk_is_object(root_ctx, -1))
|
||||
{
|
||||
duk_pop_2(root_ctx);
|
||||
duk_push_undefined(isolated_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
duk_get_prop_string(root_ctx, -1, prop_name);
|
||||
|
||||
// If it's a function, we need to create a wrapper that calls it in root context
|
||||
if (duk_is_function(root_ctx, -1))
|
||||
{
|
||||
// Store the function reference in root context's stash
|
||||
char stash_key[128];
|
||||
snprintf(stash_key, sizeof(stash_key), "\xFF"
|
||||
"oskrnl_fn_%s",
|
||||
prop_name);
|
||||
|
||||
duk_push_global_stash(root_ctx);
|
||||
duk_dup(root_ctx, -2); // Duplicate the function
|
||||
duk_put_prop_string(root_ctx, -2, stash_key);
|
||||
duk_pop(root_ctx); // Pop stash
|
||||
|
||||
duk_pop_3(root_ctx); // Pop function, __oskrnl, globalThis
|
||||
|
||||
// Create a wrapper function in the isolated context
|
||||
// Use ES5 syntax compatible with Duktape
|
||||
const char *wrapper_code =
|
||||
"(function(propName) {"
|
||||
" return function() {"
|
||||
" var args = Array.prototype.slice.call(arguments);"
|
||||
" return __oskrnl_call_native(propName, args);"
|
||||
" };"
|
||||
"})";
|
||||
|
||||
duk_push_string(isolated_ctx, wrapper_code);
|
||||
if (duk_peval(isolated_ctx) != 0)
|
||||
{
|
||||
duk_pop(isolated_ctx);
|
||||
duk_push_undefined(isolated_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
duk_push_string(isolated_ctx, prop_name);
|
||||
if (duk_pcall(isolated_ctx, 1) != 0)
|
||||
{
|
||||
duk_pop(isolated_ctx);
|
||||
duk_push_undefined(isolated_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// For non-function properties, just get the value (primitives)
|
||||
if (duk_is_number(root_ctx, -1))
|
||||
{
|
||||
double val = duk_get_number(root_ctx, -1);
|
||||
duk_pop_3(root_ctx);
|
||||
duk_push_number(isolated_ctx, val);
|
||||
return 1;
|
||||
}
|
||||
else if (duk_is_string(root_ctx, -1))
|
||||
{
|
||||
const char *val = duk_get_string(root_ctx, -1);
|
||||
duk_pop_3(root_ctx);
|
||||
duk_push_string(isolated_ctx, val);
|
||||
return 1;
|
||||
}
|
||||
else if (duk_is_boolean(root_ctx, -1))
|
||||
{
|
||||
int val = duk_get_boolean(root_ctx, -1);
|
||||
duk_pop_3(root_ctx);
|
||||
duk_push_boolean(isolated_ctx, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
duk_pop_3(root_ctx);
|
||||
duk_push_undefined(isolated_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Callback bridge to call from root context back to isolated context
|
||||
duk_ret_t native_bridge_callback(duk_context *root_ctx)
|
||||
{
|
||||
// Get metadata from the current function (the bridge)
|
||||
duk_push_current_function(root_ctx);
|
||||
|
||||
duk_get_prop_string(root_ctx, -1, "\xFF"
|
||||
"isolated_ctx_ptr");
|
||||
duk_context *isolated_ctx = (duk_context *)duk_get_pointer(root_ctx, -1);
|
||||
duk_pop(root_ctx);
|
||||
|
||||
duk_get_prop_string(root_ctx, -1, "\xFF"
|
||||
"fn_id");
|
||||
const char *fn_id = duk_get_string(root_ctx, -1);
|
||||
duk_pop(root_ctx);
|
||||
|
||||
duk_pop(root_ctx); // Pop current function
|
||||
|
||||
if (isolated_ctx == NULL || fn_id == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the target function from isolated context stash
|
||||
duk_push_global_stash(isolated_ctx);
|
||||
duk_get_prop_string(isolated_ctx, -1, fn_id);
|
||||
duk_remove(isolated_ctx, -2); // Remove stash
|
||||
|
||||
if (!duk_is_function(isolated_ctx, -1))
|
||||
{
|
||||
duk_pop(isolated_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Marshal arguments from root to isolated
|
||||
duk_idx_t nargs = duk_get_top(root_ctx);
|
||||
for (duk_idx_t i = 0; i < nargs; i++)
|
||||
{
|
||||
if (duk_is_number(root_ctx, i))
|
||||
{
|
||||
duk_push_number(isolated_ctx, duk_get_number(root_ctx, i));
|
||||
}
|
||||
else if (duk_is_string(root_ctx, i))
|
||||
{
|
||||
duk_push_string(isolated_ctx, duk_get_string(root_ctx, i));
|
||||
}
|
||||
else if (duk_is_boolean(root_ctx, i))
|
||||
{
|
||||
duk_push_boolean(isolated_ctx, duk_get_boolean(root_ctx, i));
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_push_undefined(isolated_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// Call the isolated function
|
||||
if (duk_pcall(isolated_ctx, nargs) != 0)
|
||||
{
|
||||
// Error occurred
|
||||
const char *err = duk_safe_to_string(isolated_ctx, -1);
|
||||
// k_printf((char *)"[Bridge] Error: ", 24);
|
||||
// k_printf((char *)err, 25);
|
||||
duk_pop(isolated_ctx); // Pop error
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Marshal return value back to root
|
||||
if (duk_is_number(isolated_ctx, -1))
|
||||
{
|
||||
duk_push_number(root_ctx, duk_get_number(isolated_ctx, -1));
|
||||
}
|
||||
else if (duk_is_string(isolated_ctx, -1))
|
||||
{
|
||||
duk_push_string(root_ctx, duk_get_string(isolated_ctx, -1));
|
||||
}
|
||||
else if (duk_is_boolean(isolated_ctx, -1))
|
||||
{
|
||||
duk_push_boolean(root_ctx, duk_get_boolean(isolated_ctx, -1));
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_push_undefined(root_ctx);
|
||||
}
|
||||
|
||||
duk_pop(isolated_ctx); // Pop result
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Native helper to call root context oskrnl functions
|
||||
duk_ret_t oskrnl_call_native(duk_context *isolated_ctx)
|
||||
{
|
||||
// Get function name and arguments
|
||||
const char *fn_name = duk_require_string(isolated_ctx, 0);
|
||||
|
||||
if (!duk_is_array(isolated_ctx, 1))
|
||||
{
|
||||
duk_push_undefined(isolated_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the root context
|
||||
duk_push_global_stash(isolated_ctx);
|
||||
duk_get_prop_string(isolated_ctx, -1, "\xFF"
|
||||
"root_ctx_ptr");
|
||||
duk_context *root_ctx = (duk_context *)duk_get_pointer(isolated_ctx, -1);
|
||||
duk_pop_2(isolated_ctx);
|
||||
|
||||
if (root_ctx == NULL)
|
||||
{
|
||||
duk_push_undefined(isolated_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the function from root context stash
|
||||
char stash_key[128];
|
||||
snprintf(stash_key, sizeof(stash_key), "\xFF"
|
||||
"oskrnl_fn_%s",
|
||||
fn_name);
|
||||
|
||||
duk_push_global_stash(root_ctx);
|
||||
duk_get_prop_string(root_ctx, -1, stash_key);
|
||||
|
||||
if (!duk_is_function(root_ctx, -1))
|
||||
{
|
||||
duk_pop_2(root_ctx);
|
||||
duk_push_undefined(isolated_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Transfer arguments from isolated context to root context
|
||||
duk_size_t arg_count = duk_get_length(isolated_ctx, 1);
|
||||
|
||||
for (duk_size_t i = 0; i < arg_count; i++)
|
||||
{
|
||||
duk_get_prop_index(isolated_ctx, 1, i);
|
||||
|
||||
if (duk_is_number(isolated_ctx, -1))
|
||||
{
|
||||
duk_push_number(root_ctx, duk_get_number(isolated_ctx, -1));
|
||||
}
|
||||
else if (duk_is_string(isolated_ctx, -1))
|
||||
{
|
||||
duk_push_string(root_ctx, duk_get_string(isolated_ctx, -1));
|
||||
}
|
||||
else if (duk_is_boolean(isolated_ctx, -1))
|
||||
{
|
||||
duk_push_boolean(root_ctx, duk_get_boolean(isolated_ctx, -1));
|
||||
}
|
||||
else if (duk_is_function(isolated_ctx, -1))
|
||||
{
|
||||
// Create a bridge function in root context
|
||||
static int bridge_cnt = 0;
|
||||
char bridge_id[32];
|
||||
snprintf(bridge_id, sizeof(bridge_id), "b_%d", bridge_cnt++);
|
||||
|
||||
// Stash isolated function
|
||||
duk_push_global_stash(isolated_ctx);
|
||||
duk_dup(isolated_ctx, -2);
|
||||
duk_put_prop_string(isolated_ctx, -2, bridge_id);
|
||||
duk_pop(isolated_ctx);
|
||||
|
||||
// Create bridge in root
|
||||
duk_push_c_function(root_ctx, native_bridge_callback, DUK_VARARGS);
|
||||
|
||||
// Attach metadata
|
||||
duk_push_pointer(root_ctx, isolated_ctx);
|
||||
duk_put_prop_string(root_ctx, -2, "\xFF"
|
||||
"isolated_ctx_ptr");
|
||||
|
||||
duk_push_string(root_ctx, bridge_id);
|
||||
duk_put_prop_string(root_ctx, -2, "\xFF"
|
||||
"fn_id");
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_push_undefined(root_ctx);
|
||||
}
|
||||
|
||||
duk_pop(isolated_ctx);
|
||||
}
|
||||
|
||||
// Call the function in root context
|
||||
duk_int_t rc = duk_pcall(root_ctx, arg_count);
|
||||
|
||||
// Transfer return value back to isolated context
|
||||
if (rc == 0)
|
||||
{
|
||||
if (duk_is_number(root_ctx, -1))
|
||||
{
|
||||
duk_push_number(isolated_ctx, duk_get_number(root_ctx, -1));
|
||||
}
|
||||
else if (duk_is_string(root_ctx, -1))
|
||||
{
|
||||
duk_push_string(isolated_ctx, duk_get_string(root_ctx, -1));
|
||||
}
|
||||
else if (duk_is_boolean(root_ctx, -1))
|
||||
{
|
||||
duk_push_boolean(isolated_ctx, duk_get_boolean(root_ctx, -1));
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_push_undefined(isolated_ctx);
|
||||
}
|
||||
duk_pop(root_ctx); // Pop result
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_pop(root_ctx); // Pop error
|
||||
duk_push_undefined(isolated_ctx);
|
||||
}
|
||||
|
||||
duk_pop(root_ctx); // Pop stash
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Native function to execute JS code in isolated context with __oskrnl access
|
||||
duk_ret_t native_isolated_exec(duk_context *ctx)
|
||||
{
|
||||
// Get the JS code to execute
|
||||
const char *js_code = duk_require_string(ctx, 0);
|
||||
|
||||
// Create a new isolated Duktape heap
|
||||
duk_context *isolated_ctx = duk_create_heap_default();
|
||||
|
||||
if (isolated_ctx == NULL)
|
||||
{
|
||||
duk_push_boolean(ctx, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Store reference to root context in isolated context's stash
|
||||
duk_push_global_stash(isolated_ctx);
|
||||
duk_push_pointer(isolated_ctx, ctx);
|
||||
duk_put_prop_string(isolated_ctx, -2, "\xFF"
|
||||
"root_ctx_ptr");
|
||||
duk_pop(isolated_ctx);
|
||||
|
||||
// Register the native call helper in isolated context
|
||||
duk_push_c_function(isolated_ctx, oskrnl_call_native, 2);
|
||||
duk_put_global_string(isolated_ctx, "__oskrnl_call_native");
|
||||
|
||||
// Register the getter function
|
||||
duk_push_c_function(isolated_ctx, oskrnl_proxy_getter, 2);
|
||||
duk_put_global_string(isolated_ctx, "__oskrnl_get_prop");
|
||||
|
||||
// Create __oskrnl proxy object using ES6 Proxy
|
||||
const char *proxy_code =
|
||||
"(function() {"
|
||||
" var handler = {"
|
||||
" get: function(target, prop) {"
|
||||
" if (typeof prop === 'symbol') return undefined;"
|
||||
" return __oskrnl_get_prop(null, String(prop));"
|
||||
" }"
|
||||
" };"
|
||||
" return new Proxy({}, handler);"
|
||||
"})()";
|
||||
|
||||
duk_push_string(isolated_ctx, proxy_code);
|
||||
|
||||
if (duk_peval(isolated_ctx) != 0)
|
||||
{
|
||||
duk_pop(isolated_ctx);
|
||||
duk_destroy_heap(isolated_ctx);
|
||||
duk_push_boolean(ctx, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
duk_put_global_string(isolated_ctx, "__oskrnl");
|
||||
|
||||
// Execute the provided JS code
|
||||
duk_push_string(isolated_ctx, js_code);
|
||||
duk_int_t rc = duk_peval(isolated_ctx);
|
||||
|
||||
// Check for errors
|
||||
int success = (rc == 0);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
// Transfer error message back to root context for display
|
||||
const char *err = duk_safe_to_string(isolated_ctx, -1);
|
||||
k_printf((char *)"[Isolated] Execution error: ", 12);
|
||||
k_printf((char *)err, 13);
|
||||
}
|
||||
|
||||
duk_pop(isolated_ctx); // Pop result or error
|
||||
|
||||
// Clean up the isolated heap
|
||||
// duk_destroy_heap(isolated_ctx);
|
||||
|
||||
// Return success/failure
|
||||
duk_push_boolean(ctx, success);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void kmain()
|
||||
{
|
||||
// Initialize IDT and ISRs
|
||||
@@ -268,6 +670,10 @@ void kmain()
|
||||
duk_push_c_function(ctx, native_irq_register, 2);
|
||||
duk_put_global_string(ctx, "$irqregister");
|
||||
|
||||
// Register native isolated execution function
|
||||
duk_push_c_function(ctx, native_isolated_exec, 1);
|
||||
duk_put_global_string(ctx, "$isolatedExec");
|
||||
|
||||
// Enable interrupts before JavaScript execution
|
||||
__asm__ volatile("sti");
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Logger } from "../lib/libstd/logger/logger.kmod";
|
||||
import { charc } from "../lib/libts/byte";
|
||||
import { padStart } from "../lib/libts/string";
|
||||
import { uiarrtostr } from "../lib/libts/uint_arr";
|
||||
import { getDate } from "../lib/sys/date";
|
||||
import { kdriver_dev_ata_detectDisks } from "./drivers/dev/ata";
|
||||
import { kdriver_dev_pci_detectDevices } from "./drivers/dev/pci";
|
||||
@@ -11,6 +12,7 @@ import {
|
||||
import { devfs_driver, devfs_getDevice } from "./filesystem/devfs";
|
||||
import { fat32_driver } from "./filesystem/fat32";
|
||||
import { sysfs_driver, sysfs_readFile } from "./filesystem/sysfs";
|
||||
import { kmod_app_init, kmod_app_run } from "./modules/app/app.kmod";
|
||||
import { kmod_disks_detectDisks } from "./modules/disks/disks.kmod";
|
||||
import {
|
||||
kmod_drivers_init,
|
||||
@@ -56,42 +58,19 @@ export function kmain() {
|
||||
Logger.log("[Kernel] Initializing drives...");
|
||||
kmod_disks_detectDisks();
|
||||
|
||||
kmod_graphics_vga_pushLine("[Kernel] Kernel initialized successfully.");
|
||||
|
||||
const dev = devfs_getDevice("/hda1");
|
||||
if (!dev) throw new Error("Drive not found");
|
||||
|
||||
kmod_filesystem_mount("/home", function () {
|
||||
if (!dev) throw new Error("System drive not found");
|
||||
|
||||
kmod_filesystem_mount("/disk", function () {
|
||||
return fat32_driver(dev.driver, dev.data);
|
||||
});
|
||||
|
||||
let input = "";
|
||||
let running = false;
|
||||
Logger.log("[Kernel] Initializing app module...");
|
||||
kmod_app_init();
|
||||
|
||||
kmod_graphics_vga_setLastLine("> ");
|
||||
Logger.log("[Kernel] Kernel initialized successfully.");
|
||||
|
||||
kmod_terminal_input_onKeyboardInput(function (code) {
|
||||
if (running) return;
|
||||
const shell = uiarrtostr(kmod_filesystem_readFile("/disk/ushellc")!);
|
||||
|
||||
if (code == "Enter") {
|
||||
running = true;
|
||||
kmod_graphics_vga_pushLine("Starting " + input);
|
||||
const f = kmod_filesystem_readFile(input);
|
||||
if (!f) return;
|
||||
|
||||
let app = "";
|
||||
|
||||
for (let i = 0; i < f.length; i++) {
|
||||
app += String.fromCharCode(f[i]!);
|
||||
}
|
||||
|
||||
// EXTREMELY DANGEROUS -- REPLACE WITH SANDBOXING
|
||||
eval("const console = { log: Logger.log } ;" + app);
|
||||
Logger.log("DONE");
|
||||
running = false;
|
||||
} else {
|
||||
input += code.toLowerCase();
|
||||
kmod_graphics_vga_setLastLine("> " + input);
|
||||
}
|
||||
});
|
||||
kmod_app_run(shell);
|
||||
}
|
||||
|
||||
26
src/os/src/kernel/modules/app/app.kmod.ts
Normal file
26
src/os/src/kernel/modules/app/app.kmod.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Logger } from "../../../lib/libstd/logger/logger.kmod";
|
||||
import { Path } from "../../../lib/libstd/path";
|
||||
import { iexec } from "../../../lib/libts/exec";
|
||||
import { uiarrtostr } from "../../../lib/libts/uint_arr";
|
||||
import {
|
||||
kmod_filesystem_listDir,
|
||||
kmod_filesystem_readFile,
|
||||
} from "../filesystem/filesystem.kmod";
|
||||
import { oskrnl_register } from "../../../oskrnl";
|
||||
|
||||
export function kmod_app_init() {
|
||||
oskrnl_register();
|
||||
}
|
||||
|
||||
export function kmod_app_run(path: string) {
|
||||
const meta = JSON.parse(
|
||||
uiarrtostr(kmod_filesystem_readFile(Path.join(path, "meta.lam"))!)
|
||||
);
|
||||
|
||||
if (!meta) throw new Error("App metadata not found");
|
||||
|
||||
const entrypoint = Path.join(path, meta["app:entrypoint"]);
|
||||
const code = uiarrtostr(kmod_filesystem_readFile(entrypoint)!);
|
||||
|
||||
iexec(code);
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
import { charc } from "../../libts/byte";
|
||||
import { kdriver_etc_serial_transmit } from "../../../kernel/drivers/etc/serial";
|
||||
import { kmod_graphics_vga_pushLine } from "../../../kernel/modules/graphics/vga";
|
||||
import {
|
||||
kmod_graphics_vga_pushLine,
|
||||
kmod_graphics_vga_setLastLine,
|
||||
} from "../../../kernel/modules/graphics/vga";
|
||||
|
||||
export const Logger = {
|
||||
log(message: string) {
|
||||
@@ -12,4 +15,13 @@ export const Logger = {
|
||||
|
||||
kdriver_etc_serial_transmit(charc("\n"));
|
||||
},
|
||||
update(message: string) {
|
||||
kmod_graphics_vga_setLastLine(message);
|
||||
|
||||
kdriver_etc_serial_transmit(charc("\x1b[2K"));
|
||||
kdriver_etc_serial_transmit(charc("\r"));
|
||||
for (let i = 0; i < message.length; i++) {
|
||||
kdriver_etc_serial_transmit(charc(message[i]!));
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
3
src/os/src/lib/libts/exec.ts
Normal file
3
src/os/src/lib/libts/exec.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function iexec(code: string) {
|
||||
$isolatedExec(code);
|
||||
}
|
||||
9
src/os/src/lib/libts/uint_arr.ts
Normal file
9
src/os/src/lib/libts/uint_arr.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export function uiarrtostr(a: number[]) {
|
||||
let s = "";
|
||||
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
s += String.fromCharCode(a[i]!);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
9
src/os/src/oskrnl/console/console.ts
Normal file
9
src/os/src/oskrnl/console/console.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Logger } from "../../lib/libstd/logger/logger.kmod";
|
||||
|
||||
export function oskrnl_console_log(data: any) {
|
||||
Logger.log(String(data));
|
||||
}
|
||||
|
||||
export function oskrnl_console_update(data: any) {
|
||||
Logger.update(String(data));
|
||||
}
|
||||
10
src/os/src/oskrnl/index.ts
Normal file
10
src/os/src/oskrnl/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { oskrnl_console_log, oskrnl_console_update } from "./console/console";
|
||||
import { oskrnl_input_onKeyPress } from "./input/input";
|
||||
|
||||
export function oskrnl_register() {
|
||||
(globalThis as any).__oskrnl = {
|
||||
console_log: oskrnl_console_log,
|
||||
console_update: oskrnl_console_update,
|
||||
input_onKeyPress: oskrnl_input_onKeyPress,
|
||||
};
|
||||
}
|
||||
5
src/os/src/oskrnl/input/input.ts
Normal file
5
src/os/src/oskrnl/input/input.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { kmod_terminal_input_onKeyboardInput } from "../../kernel/modules/terminal/input";
|
||||
|
||||
export function oskrnl_input_onKeyPress(handler: (key: string) => void) {
|
||||
kmod_terminal_input_onKeyboardInput(handler);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
console.log("TS-DOS Program Started");
|
||||
2
src/os/src/types/c/bindings.d.ts
vendored
2
src/os/src/types/c/bindings.d.ts
vendored
@@ -11,3 +11,5 @@ declare const $irqregister: (
|
||||
irq: number,
|
||||
handler: (irqNum: number) => void
|
||||
) => boolean;
|
||||
declare function $isolatedExec(code: string): void;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user