From b11a59d211751f68a58903fa4661c872fd6b91d4 Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Tue, 10 Jun 2025 07:13:13 -0400 Subject: [PATCH 1/8] Update scripts/build-all --- scripts/build-all | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/build-all b/scripts/build-all index d3a1c68..d6cef26 100755 --- a/scripts/build-all +++ b/scripts/build-all @@ -26,6 +26,9 @@ templeos_iso_file = home_path + 'iso/TempleOS.ISO' qemu_run_cmd = qemu_bin_path + ' ' + qemu_display + ' -enable-kvm -m 1024 -cdrom ' + qemu_slipstream_iso_file + ' -audiodev pa,id=snd0 -machine pcspk-audiodev=snd0 -debugcon stdio -boot d' +def kill_running_qemu_processes(): + os.system('killall -e "' + qemu_bin_path + '"') + def clang_format_src_files(): print("build-all: clang-format-src-files") exclude_paths = ["mujs", "openlibm", ".iso.c"] @@ -140,6 +143,7 @@ def run(): raise ValueError("build-all: step 'run' failed, error code " + str(res)) def build_all(): + kill_running_qemu_processes() clang_format_src_files() refresh_build_path() build_libtemple() From a25b25984f5e54f675ea2859445a42ae97b544b0 Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Tue, 10 Jun 2025 07:42:11 -0400 Subject: [PATCH 2/8] Initialize interpreter in Adam task --- Run.HC | 9 ++++--- System/FFI/Base.HC | 51 --------------------------------------- System/FFI/ELF64.HC | 45 ++++++++++++++++++++++------------ System/FFI/LibC.HC | 22 +++++++++++++++++ System/MakeSystem.HC | 36 ++------------------------- MuJS.HC => System/MuJS.HC | 0 scripts/build-all | 2 +- 7 files changed, 60 insertions(+), 105 deletions(-) delete mode 100644 System/FFI/Base.HC rename MuJS.HC => System/MuJS.HC (100%) diff --git a/Run.HC b/Run.HC index c9808e0..5216383 100644 --- a/Run.HC +++ b/Run.HC @@ -1,7 +1,8 @@ -XTalkWait(Fs, "Cd(\"M:/System/\");\n"); -XTalkWait(Fs, "#include \"M:/System/MakeSystem\";\n"); -XTalkWait(Fs, "#include \"M:/MuJS\";\n"); +Adam("Cd(\"M:/System/\");\n"); +Adam("#include \"M:/System/MakeSystem\";\n"); + +WinMax; +AutoComplete(0); XTalkWait(Fs, "Cd(\"M:/\");\n"); XTalkWait(Fs, "mujs(\"examples/hello.js\");\n"); - diff --git a/System/FFI/Base.HC b/System/FFI/Base.HC deleted file mode 100644 index 0211c44..0000000 --- a/System/FFI/Base.HC +++ /dev/null @@ -1,51 +0,0 @@ -#define PUSH_SYSV_REGS \ - asm {PUSH RCX PUSH RDX PUSH RBX PUSH RBP PUSH RSI PUSH RDI PUSH R8 PUSH R9 PUSH \ - R10 PUSH R11 PUSH R12 PUSH R13 PUSH R14 PUSH R15} -#define POP_SYSV_REGS \ - p0 = p0; \ - p1 = p1; \ - p2 = p2; \ - p3 = p3; \ - p4 = p4; \ - p5 = p5; \ - asm {POP R15 POP R14 POP R13 POP R12 POP R11 POP R10 POP R9 POP R8 POP RDI POP \ - RSI POP RBP POP RBX POP RDX POP RCX} -#define GET_SYSV_ARGS \ - asm {PUSH R9 PUSH R8 PUSH RCX PUSH RDX PUSH RSI PUSH RDI} \ - I64 reg RDI p0; \ - I64 reg RSI p1; \ - I64 reg RDX p2; \ - I64 reg RCX p3; \ - I64 reg R8 p4; \ - I64 reg R9 p5; \ - asm {POP RDI POP RSI POP RDX POP RCX POP R8 POP R9} - -#define MOV_ANS_RAX asm { MOV[&ans], RAX } -#define MOV_PARAM0_RDI asm {MOV [¶m0], RDI} - -I64 param0; -I64 elf_argc; -U8** elf_argv; - -asm { -_ELF_CALL:: - PUSH RBP - MOV RBP,RSP - MOV RAX,U64 SF_ARG1[RBP] - MOV RDI,U64 SF_ARG2[RBP] - MOV RSI,U64 SF_ARG3[RBP] - TEST RAX,RAX - JZ @@05 - CALL RAX -@@05: POP RBP - RET1 8 -} - -U0 _main() -{ - MOV_PARAM0_RDI - CallInd(_ELF_CALL, param0, elf_argc, elf_argv); - UserTaskCont; -} - -//U0 _exit() { UserTaskCont; } diff --git a/System/FFI/ELF64.HC b/System/FFI/ELF64.HC index 87af9fd..324ca1f 100644 --- a/System/FFI/ELF64.HC +++ b/System/FFI/ELF64.HC @@ -3,6 +3,36 @@ #define ET_EXEC 2 #define ET_DYN 3 +U0 @patch_call_rel32(U32 from, U32 to) +{ + *(from(U8*)) = 0xE8; + *((from + 1)(I32*)) = to - from - 5; +} + +U0 @patch_jmp_rel32(U32 from, U32 to) +{ + *(from(U8*)) = 0xE9; + *((from + 1)(I32*)) = to - from - 5; +} + +U0 @sse_enable() +{ + /* clang-format off */ + asm + { + MOV_EAX_CR0 + AND AX, 0xFFFB // clear coprocessor emulation CR0.EM + OR AX, 0x2 // set coprocessor monitoring CR0.MP + MOV_CR0_EAX + MOV_EAX_CR4 + OR AX, 3 << 9 // set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time + MOV_CR4_EAX + } + /* clang-format on */ +} + +@sse_enable; + U0 @elf64_debug_print(U8 fmt, ...) { // FIXME: Remove unnecessary debug_print statements and PrintErr for errors. @@ -170,11 +200,6 @@ U0 process_elf_rela_dyn_entries(Elf* elf) entry_name = elf->dynstr + elf->dynsym[(rela_dyn->r_info >> 32)].st_name; @elf64_debug_print("rela_dyn->r_offset = %08x\n", rela_dyn->r_offset); @elf64_debug_print("entry name = '%s'\n", entry_name); - if (!StrCmp(entry_name, "__libc_start_main")) { - *(rela_dyn->r_offset)(U64*) = &_main; - @elf64_debug_print("Set value for .rela.dyn entry '%s' to: &_main\n", - entry_name); - } if (!StrCmp(entry_name, "stdin")) { *(rela_dyn->r_offset)(U64*) = 0; @elf64_debug_print("Set value for .rela.dyn entry '%s' to: %d\n", entry_name, 0); @@ -249,12 +274,6 @@ U0 process_elf_rela_plt_entries(Elf* elf) *patch = entry_name; @patch_jmp_rel32(plt, handler); @patch_call_rel32(handler + 0x16, &PrintErr); - //@patch_call_rel32(handler + 0x21, &_exit); - if (!StrCmp(entry_name, "__libc_start_main")) { - symbol_exists = TRUE; - @patch_jmp_rel32(plt, &_main); - @elf64_debug_print("Set value for .rela.plt entry '%s' to &_main\n", entry_name); - } if (get_symbol_address(entry_name)) { symbol_exists = TRUE; @patch_jmp_rel32(plt, get_symbol_address(entry_name)); @@ -293,8 +312,4 @@ U0 load_elf(...) process_elf_section_header_table(&elf); process_elf_rela_dyn_entries(&elf); process_elf_rela_plt_entries(&elf); - - _start = elf.ehdr->e_entry; - elf_argc = argc; - elf_argv = argv; } diff --git a/System/FFI/LibC.HC b/System/FFI/LibC.HC index 230fef1..d089d7a 100644 --- a/System/FFI/LibC.HC +++ b/System/FFI/LibC.HC @@ -1,3 +1,25 @@ +#define PUSH_SYSV_REGS \ +asm {PUSH RCX PUSH RDX PUSH RBX PUSH RBP PUSH RSI PUSH RDI PUSH R8 PUSH R9 PUSH \ + R10 PUSH R11 PUSH R12 PUSH R13 PUSH R14 PUSH R15} + #define POP_SYSV_REGS \ + p0 = p0; \ + p1 = p1; \ + p2 = p2; \ + p3 = p3; \ + p4 = p4; \ + p5 = p5; \ + asm {POP R15 POP R14 POP R13 POP R12 POP R11 POP R10 POP R9 POP R8 POP RDI POP \ + RSI POP RBP POP RBX POP RDX POP RCX} + #define GET_SYSV_ARGS \ + asm {PUSH R9 PUSH R8 PUSH RCX PUSH RDX PUSH RSI PUSH RDI} \ + I64 reg RDI p0; \ + I64 reg RSI p1; \ + I64 reg RDX p2; \ + I64 reg RCX p3; \ + I64 reg R8 p4; \ + I64 reg R9 p5; \ + asm {POP RDI POP RSI POP RDX POP RCX POP R8 POP R9} + asm { _SETJMP:: MOV [RDI], RBX // Store caller saved registers diff --git a/System/MakeSystem.HC b/System/MakeSystem.HC index 54ed209..fbb1cbd 100644 --- a/System/MakeSystem.HC +++ b/System/MakeSystem.HC @@ -1,44 +1,12 @@ /* clang-format off */ -WinMax; -AutoComplete(0); - -U0 @patch_call_rel32(U32 from, U32 to) -{ - *(from(U8*)) = 0xE8; - *((from + 1)(I32*)) = to - from - 5; -} - -U0 @patch_jmp_rel32(U32 from, U32 to) -{ - *(from(U8*)) = 0xE9; - *((from + 1)(I32*)) = to - from - 5; -} - -U0 @sse_enable() -{ - /* clang-format off */ - asm - { - MOV_EAX_CR0 - AND AX, 0xFFFB // clear coprocessor emulation CR0.EM - OR AX, 0x2 // set coprocessor monitoring CR0.MP - MOV_CR0_EAX - MOV_EAX_CR4 - OR AX, 3 << 9 // set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time - MOV_CR4_EAX - } - /* clang-format on */ -} - -@sse_enable; - // FFI support files -#include "FFI/Base"; #include "FFI/LibC"; #include "FFI/ELF64"; // LibTemple support files #include "LibTemple/OS"; +#include "MuJS"; + /* clang-format on */ diff --git a/MuJS.HC b/System/MuJS.HC similarity index 100% rename from MuJS.HC rename to System/MuJS.HC diff --git a/scripts/build-all b/scripts/build-all index d6cef26..9a90620 100755 --- a/scripts/build-all +++ b/scripts/build-all @@ -118,7 +118,7 @@ def generate_iso_c_file(): # Fixup addresses for MuJS mujs_bin_path = redsea_path + '/build/bin/mujs' - mujs_hc_path = redsea_path + '/MuJS.HC' + mujs_hc_path = redsea_path + '/System/MuJS.HC' hc_fixup('MUJS_MAIN', 'main', mujs_bin_path, mujs_hc_path) exit_fixup(mujs_bin_path, mujs_hc_path) From f1fe3a6a9735cd26520ca68b7c6c991dda0ab2b9 Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Tue, 10 Jun 2025 09:25:26 -0400 Subject: [PATCH 3/8] Add kludge for sprintf -> npf_snprintf in mujs --- System/FFI/LibC.HC | 9 --------- src/mujs/jsdate.c | 10 +++++----- src/mujs/jsnumber.c | 4 ++-- src/mujs/jsrun.c | 4 ++-- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/System/FFI/LibC.HC b/System/FFI/LibC.HC index d089d7a..2f1fe23 100644 --- a/System/FFI/LibC.HC +++ b/System/FFI/LibC.HC @@ -241,7 +241,6 @@ U0 strcmp() { PUSH_SYSV_REGS GET_SYSV_ARGS - //"strcmp: '%s', '%s'\n", p0, p1; StrCmp(p0, p1); POP_SYSV_REGS } @@ -385,11 +384,3 @@ U0 strstr() POP_SYSV_REGS } - -U0 sprintf() -{ - PUSH_SYSV_REGS - GET_SYSV_ARGS - StrPrint(p0, p1, p2, p3, p4, p5); - POP_SYSV_REGS -} diff --git a/src/mujs/jsdate.c b/src/mujs/jsdate.c index bf1d406..fd5ab46 100644 --- a/src/mujs/jsdate.c +++ b/src/mujs/jsdate.c @@ -323,7 +323,7 @@ static char *fmtdate(char *buf, double t) int d = DateFromTime(t); if (!isfinite(t)) return "Invalid Date"; - sprintf(buf, "%04d-%02d-%02d", y, m+1, d); + npf_snprintf(buf, 1024, "%04d-%02d-%02d", y, m+1, d); return buf; } @@ -338,11 +338,11 @@ static char *fmttime(char *buf, double t, double tza) if (!isfinite(t)) return "Invalid Date"; if (tza == 0) - sprintf(buf, "%02d:%02d:%02d.%03dZ", H, M, S, ms); + npf_snprintf(buf, 1024, "%02d:%02d:%02d.%03dZ", H, M, S, ms); else if (tza < 0) - sprintf(buf, "%02d:%02d:%02d.%03d-%02d:%02d", H, M, S, ms, tzh, tzm); + npf_snprintf(buf, 1024, "%02d:%02d:%02d.%03d-%02d:%02d", H, M, S, ms, tzh, tzm); else - sprintf(buf, "%02d:%02d:%02d.%03d+%02d:%02d", H, M, S, ms, tzh, tzm); + npf_snprintf(buf, 1024, "%02d:%02d:%02d.%03d+%02d:%02d", H, M, S, ms, tzh, tzm); return buf; } @@ -353,7 +353,7 @@ static char *fmtdatetime(char *buf, double t, double tza) return "Invalid Date"; fmtdate(dbuf, t); fmttime(tbuf, t, tza); - sprintf(buf, "%sT%s", dbuf, tbuf); + npf_snprintf(buf, 1024, "%sT%s", dbuf, tbuf); return buf; } diff --git a/src/mujs/jsnumber.c b/src/mujs/jsnumber.c index 8e79d34..86259da 100644 --- a/src/mujs/jsnumber.c +++ b/src/mujs/jsnumber.c @@ -116,11 +116,11 @@ static void numtostr(js_State *J, const char *fmt, int w, double n) { /* buf needs to fit printf("%.20f", 1e20) */ char buf[50], *e; - sprintf(buf, fmt, w, n); + npf_snprintf(buf, 1024, fmt, w, n); e = strchr(buf, 'e'); if (e) { int exp = atoi(e+1); - sprintf(e, "e%+d", exp); + npf_snprintf(e, 1024, "e%+d", exp); } js_pushstring(J, buf); } diff --git a/src/mujs/jsrun.c b/src/mujs/jsrun.c index b956208..e06b212 100644 --- a/src/mujs/jsrun.c +++ b/src/mujs/jsrun.c @@ -919,11 +919,11 @@ const char *js_ref(js_State *J) s = v->u.boolean ? "_True" : "_False"; break; case JS_TOBJECT: - sprintf(buf, "%p", (void*)v->u.object); + npf_snprintf(buf, 1024, "%p", (void*)v->u.object); s = js_intern(J, buf); break; default: - sprintf(buf, "%d", J->nextref++); + npf_snprintf(buf, 1024, "%d", J->nextref++); s = js_intern(J, buf); break; } From d97bb83dea0384124d5c0da0e39e58761622f689 Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Tue, 10 Jun 2025 09:26:01 -0400 Subject: [PATCH 4/8] Add gmtime, mktime to LibC --- System/FFI/LibC.HC | 82 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 8 deletions(-) diff --git a/System/FFI/LibC.HC b/System/FFI/LibC.HC index 2f1fe23..f26949f 100644 --- a/System/FFI/LibC.HC +++ b/System/FFI/LibC.HC @@ -51,6 +51,30 @@ _LONGJMP:: _extern _SETJMP U64 _setjmp(U64 jmp_buf); _extern _LONGJMP U64 longjmp(U64 jmp_buf, U64 ret); +class libc_tm { + I32 tm_sec; /* seconds, range 0 to 59 */ + I32 tm_min; /* minutes, range 0 to 59 */ + I32 tm_hour; /* hours, range 0 to 23 */ + I32 tm_mday; /* day of the month, range 1 to 31 */ + I32 tm_mon; /* month, range 0 to 11 */ + I32 tm_year; /* The number of years since 1900 */ + I32 tm_wday; /* day of the week, range 0 to 6 */ + I32 tm_yday; /* day in the year, range 0 to 365 */ + I32 tm_isdst; /* daylight saving time */ +}; + +#define NIST_TIME_OFFSET -9488 + +I64 CDate2Unix(CDate dt) +{ // TempleOS datetime to Unix timestamp. + return ToI64((dt - Str2Date("1/1/1970")) / CDATE_FREQ + NIST_TIME_OFFSET); +} + +public CDate Unix2CDate(I64 timestamp) +{//Unix timestamp to TempleOS datetime. + return (timestamp-NIST_TIME_OFFSET)*CDATE_FREQ+Str2Date("1/1/1970"); +} + U0 free() { PUSH_SYSV_REGS @@ -82,6 +106,56 @@ U0 localtime() POP_SYSV_REGS } +U64 @gmtime(U64* timep) +{ + CDateStruct ds; + Date2Struct(&ds, Unix2CDate(*timep)); + libc_tm* tm = CAlloc(sizeof(libc_tm)); + + tm->tm_sec = ds.sec; + tm->tm_min = ds.min; + tm->tm_hour = ds.hour; + tm->tm_mday = ds.day_of_mon; + tm->tm_mon = ds.mon; + tm->tm_year = ds.year; + tm->tm_wday = ds.day_of_week; + return tm; +} + +U0 gmtime() +{ + PUSH_SYSV_REGS + GET_SYSV_ARGS + @gmtime(p0); + POP_SYSV_REGS +} + +U64 @mktime(libc_tm* tm) +{ + CDateStruct ds; + MemSet(&ds, 0, sizeof(CDateStruct)); + if (tm) { + ds.sec = tm->tm_sec; + ds.min = tm->tm_min; + ds.hour = tm->tm_hour; + ds.day_of_mon = tm->tm_mday; + ds.mon = tm->tm_mon; + ds.year = tm->tm_year; + ds.day_of_week = tm->tm_wday; + } else { + Date2Struct(&ds, Now); + } + return CDate2Unix(Struct2Date(&ds)); +} + +U0 mktime() +{ + PUSH_SYSV_REGS + GET_SYSV_ARGS + @mktime(p0); + POP_SYSV_REGS +} + I64 @strncmp(U8* s1, U8* s2, I32 n) { U64 u1, u2; @@ -290,14 +364,6 @@ U0 realloc() POP_SYSV_REGS } -#define MY_TIME_OFFSET 9488 - -public -I64 CDate2Unix(CDate dt) -{ // TempleOS datetime to Unix timestamp. - return ToI64((dt - Str2Date("1/1/1970")) / CDATE_FREQ) - MY_TIME_OFFSET; -} - I64 @time(I64* ptr) { no_warn ptr; From 9ad75fff5cbe45bdbe39ddeb2fc8e3671ec2e2a0 Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Tue, 10 Jun 2025 09:30:04 -0400 Subject: [PATCH 5/8] Update examples/hello.js --- examples/hello.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/hello.js b/examples/hello.js index 90d3b5e..6bc550f 100644 --- a/examples/hello.js +++ b/examples/hello.js @@ -1,3 +1,3 @@ print("Hello, TempleOS, from MuJS!") -print("Current date and time is: " + JSON.stringify(new Date())) -print("Type mujs; with no arguments for a REPL, or mujs(\"path/to/file.js\"); to run a program.") +print("Current date and time is: " + new Date().toString()); +print("Type mujs; for a REPL, or mujs(\"path/to/file.js\"); to run a program."); From d8108823b3c93fdaa2aa327b4cd349dcf8c8523c Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Tue, 10 Jun 2025 10:39:34 -0400 Subject: [PATCH 6/8] Wire up jsB_load, jsB_read to FileRead in mujs --- src/mujs/main.c | 141 ++++++++++++++++++------------------------------ 1 file changed, 51 insertions(+), 90 deletions(-) diff --git a/src/mujs/main.c b/src/mujs/main.c index a86e9c2..2eabef2 100644 --- a/src/mujs/main.c +++ b/src/mujs/main.c @@ -94,6 +94,53 @@ char *readline(const char *prompt) #define PS1 "> " +static int eval_file(js_State *J, const char* filename) +{ + char* source = (char*)os_call_ext_str_3("FileRead", (uint64_t)filename, 0, 0); + if (!source) { + js_pushundefined(J); + return 1; + } + int res = js_ploadstring(J, filename, source); + free(source); + if (res) { + fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); + js_pop(J, 1); + return 1; + } + js_pushundefined(J); + if (js_pcall(J, 0)) { + fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); + js_pop(J, 1); + return 1; + } + if (js_isdefined(J, -1)) { + printf("%s\n", js_tryrepr(J, -1, "can't convert to string")); + } + js_pop(J, 1); + return 0; +} + +static int eval_print(js_State *J, const char *source) +{ + if (js_ploadstring(J, "[stdin]", source)) { + fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); + js_pop(J, 1); + return 1; + } + js_pushundefined(J); + if (js_pcall(J, 0)) { + fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); + js_pop(J, 1); + return 1; + } + if (js_isdefined(J, -1)) { + printf("%s\n", js_tryrepr(J, -1, "can't convert to string")); + } + js_pop(J, 1); + return 0; +} + static void jsB_gc(js_State *J) { int report = js_toboolean(J, 1); @@ -103,14 +150,7 @@ static void jsB_gc(js_State *J) static void jsB_load(js_State *J) { - int i, n = js_gettop(J); - for (i = 1; i < n; ++i) { - js_loadfile(J, js_tostring(J, i)); - js_pushundefined(J); - js_call(J, 0); - js_pop(J, 1); - } - js_pushundefined(J); + eval_file(J, js_tostring(J, 1)); } static void jsB_compile(js_State *J) @@ -164,49 +204,13 @@ static void jsB_write(js_State *J) static void jsB_read(js_State *J) { - const char *filename = js_tostring(J, 1); - FILE *f; - char *s; - int n, t; - - f = fopen(filename, "rb"); - if (!f) { - js_error(J, "cannot open file '%s': %s", filename, strerror(errno)); - } - - if (fseek(f, 0, SEEK_END) < 0) { - fclose(f); - js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno)); - } - - n = ftell(f); - if (n < 0) { - fclose(f); - js_error(J, "cannot tell in file '%s': %s", filename, strerror(errno)); - } - - if (fseek(f, 0, SEEK_SET) < 0) { - fclose(f); - js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno)); - } - - s = malloc(n + 1); + char *s = (char*)os_call_ext_str_3("FileRead", (uint64_t)js_tostring(J, 1), 0, 0); if (!s) { - fclose(f); - js_error(J, "out of memory"); + js_pushundefined(J); + return; } - - t = fread(s, 1, n, f); - if (t != n) { - free(s); - fclose(f); - js_error(J, "cannot read data from file '%s': %s", filename, strerror(errno)); - } - s[n] = 0; - js_pushstring(J, s); free(s); - fclose(f); } static void jsB_readline(js_State *J) @@ -258,49 +262,6 @@ static const char *console_js = "var console = { log: print, debug: print, warn: print, error: print };" ; -static int eval_file(js_State *J, const char* filename) -{ - char* source = (char*)os_call_ext_str_3("FileRead", (uint64_t)filename, 0, 0); - int res = js_ploadstring(J, filename, source); - free(source); - if (res) { - fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); - js_pop(J, 1); - return 1; - } - js_pushundefined(J); - if (js_pcall(J, 0)) { - fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); - js_pop(J, 1); - return 1; - } - if (js_isdefined(J, -1)) { - printf("%s\n", js_tryrepr(J, -1, "can't convert to string")); - } - js_pop(J, 1); - return 0; -} - -static int eval_print(js_State *J, const char *source) -{ - if (js_ploadstring(J, "[stdin]", source)) { - fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); - js_pop(J, 1); - return 1; - } - js_pushundefined(J); - if (js_pcall(J, 0)) { - fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); - js_pop(J, 1); - return 1; - } - if (js_isdefined(J, -1)) { - printf("%s\n", js_tryrepr(J, -1, "can't convert to string")); - } - js_pop(J, 1); - return 0; -} - static void usage(void) { fprintf(stderr, "Usage: mujs [options] [script [scriptArgs*]]\n"); From e6cff10e600edfe656c1581438152fdcdee1a610 Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Tue, 10 Jun 2025 11:28:31 -0400 Subject: [PATCH 7/8] Add Input.mouse_x(), Input.mouse_y(), Input.mouse_lb(), Input.mouse_rb() to jslibtemple.c --- src/mujs/jslibtemple.c | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/mujs/jslibtemple.c b/src/mujs/jslibtemple.c index 6448e96..6036612 100644 --- a/src/mujs/jslibtemple.c +++ b/src/mujs/jslibtemple.c @@ -157,6 +157,53 @@ void jsLT_initgr(js_State *J) js_defglobal(J, "Gr", JS_DONTENUM); } +/** Input **/ + +uint64_t get_glbl_var_addr(char* name) +{ + // 0x100300 + 0x3d0: adam_task + offset(CTask.hash_table) + // 0x8: HTT_GLBL_VAR + // 0x78: offset(CHashGlblVar.data_addr) + uint64_t addr = os_call_ext_str_4("HashFind", (uint64_t)name, *(uint64_t*)(0x100300 + 0x3d0), 8, 1); + return addr ? *(uint64_t*)(addr + 0x78) : 0; +} + +void Input_mouse_x(js_State *J) +{ + uint64_t* res = (uint64_t*)get_glbl_var_addr("ms"); + js_pushnumber(J, res[0]); // offset(CMsStateGlbls.pos.x) +} + +void Input_mouse_y(js_State *J) +{ + uint64_t* res = (uint64_t*)get_glbl_var_addr("ms"); + js_pushnumber(J, res[1]); // offset(CMsStateGlbls.pos.y) +} + +void Input_mouse_lb(js_State *J) +{ + uint8_t* res = (uint8_t*)get_glbl_var_addr("ms"); + js_pushboolean(J, res[0xa0]); // offset(CMsStateGlbls.lb) +} + +void Input_mouse_rb(js_State *J) +{ + uint8_t* res = (uint8_t*)get_glbl_var_addr("ms"); + js_pushboolean(J, res[0xa1]); // offset(CMsStateGlbls.rb) +} + +void jsLT_initinput(js_State *J) +{ + js_pushobject(J, jsV_newobject(J, -1, J->Object_prototype)); + { + jsB_propf(J, "Input.mouse_x", Input_mouse_x, 0); + jsB_propf(J, "Input.mouse_y", Input_mouse_y, 0); + jsB_propf(J, "Input.mouse_lb", Input_mouse_lb, 0); + jsB_propf(J, "Input.mouse_rb", Input_mouse_rb, 0); + } + js_defglobal(J, "Input", JS_DONTENUM); +} + /** OS **/ // U0 Beep(I8 ona=62,Bool busy=FALSE) @@ -276,5 +323,6 @@ void js_initlibtemple(js_State *J) { jsLT_initdc(J); jsLT_initgr(J); + jsLT_initinput(J); jsLT_initos(J); } From cc4f8dfa516ca65dd610fbcfd6edc1dab201224f Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Tue, 10 Jun 2025 13:34:00 -0400 Subject: [PATCH 8/8] Add LibTemple/Input functions --- System/LibTemple/Input.HC | 12 ++++++++++++ System/MakeSystem.HC | 1 + src/libtemple/input.h | 1 + src/libtemple/libtemple.c | 2 ++ src/mujs/jslibtemple.c | 37 +++++++++++++++++++++++++++++++++++-- 5 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 System/LibTemple/Input.HC create mode 100644 src/libtemple/input.h diff --git a/System/LibTemple/Input.HC b/System/LibTemple/Input.HC new file mode 100644 index 0000000..43f1083 --- /dev/null +++ b/System/LibTemple/Input.HC @@ -0,0 +1,12 @@ +Bool @input_key_down(I64 sc) +{ + return Bt(kbd.down_bitmap, sc); +} + +U0 input_key_down() +{ + PUSH_SYSV_REGS + GET_SYSV_ARGS + @input_key_down(p0); + POP_SYSV_REGS +} diff --git a/System/MakeSystem.HC b/System/MakeSystem.HC index fbb1cbd..63860be 100644 --- a/System/MakeSystem.HC +++ b/System/MakeSystem.HC @@ -5,6 +5,7 @@ #include "FFI/ELF64"; // LibTemple support files +#include "LibTemple/Input"; #include "LibTemple/OS"; #include "MuJS"; diff --git a/src/libtemple/input.h b/src/libtemple/input.h new file mode 100644 index 0000000..eea94ec --- /dev/null +++ b/src/libtemple/input.h @@ -0,0 +1 @@ +uint64_t input_key_down(uint64_t sc); diff --git a/src/libtemple/libtemple.c b/src/libtemple/libtemple.c index 5dad194..5b51dd1 100644 --- a/src/libtemple/libtemple.c +++ b/src/libtemple/libtemple.c @@ -1,3 +1,5 @@ +unsigned long input_key_down(unsigned long sc) { return 0; } + unsigned long os_call_ext_str(char const* func) { return 0; } unsigned long os_call_ext_str_1(char const* func, unsigned long arg1) { return 0; } diff --git a/src/mujs/jslibtemple.c b/src/mujs/jslibtemple.c index 6036612..aa5251c 100644 --- a/src/mujs/jslibtemple.c +++ b/src/mujs/jslibtemple.c @@ -1,6 +1,7 @@ #include #include +#include "../libtemple/input.h" #include "../libtemple/os.h" #define value_or_number(v, x) js_isundefined(J, x) ? v : js_tonumber(J, x) @@ -168,6 +169,22 @@ uint64_t get_glbl_var_addr(char* name) return addr ? *(uint64_t*)(addr + 0x78) : 0; } +void Input_get_char(js_State *J) +{ + js_pushnumber(J, os_call_ext_str_3("GetChar", 0, 0, 0)); +} + +void Input_get_string(js_State *J) +{ + char* res = (char*)os_call_ext_str_3("GetStr", js_isundefined(J, 1) ? 0 : (uint64_t)js_tostring(J, 1), 0, 0); + if (!res) { + js_pushundefined(J); + return; + } + js_pushstring(J, res); + free(res); +} + void Input_mouse_x(js_State *J) { uint64_t* res = (uint64_t*)get_glbl_var_addr("ms"); @@ -192,16 +209,31 @@ void Input_mouse_rb(js_State *J) js_pushboolean(J, res[0xa1]); // offset(CMsStateGlbls.rb) } +void Input_key_down(js_State *J) +{ + js_pushboolean(J, input_key_down(js_tonumber(J, 1))); +} + +void Input_press_a_key(js_State *J) +{ + js_pushnumber(J, os_call_ext_str("PressAKey")); +} + void jsLT_initinput(js_State *J) { js_pushobject(J, jsV_newobject(J, -1, J->Object_prototype)); { + jsB_propf(J, "Input.get_char", Input_get_char, 0); + jsB_propf(J, "Input.get_string", Input_get_string, 1); jsB_propf(J, "Input.mouse_x", Input_mouse_x, 0); jsB_propf(J, "Input.mouse_y", Input_mouse_y, 0); jsB_propf(J, "Input.mouse_lb", Input_mouse_lb, 0); jsB_propf(J, "Input.mouse_rb", Input_mouse_rb, 0); + jsB_propf(J, "Input.press_a_key", Input_press_a_key, 0); + jsB_propf(J, "Input.key_down", Input_key_down, 1); } js_defglobal(J, "Input", JS_DONTENUM); + js_dostring(J, "Input.key_up = function(sc) { return !Input.key_down(sc) }"); } /** OS **/ @@ -261,8 +293,9 @@ void OS_read_file_as_string(js_State *J) return; } const char* filename = js_tostring(J, 1); - long file_as_string = os_call_ext_str_3("FileRead", (uint64_t)filename, 0, 0); - js_pushstring(J, file_as_string ? (char*)file_as_string : ""); + char* file_as_string = (char*)os_call_ext_str_3("FileRead", (uint64_t)filename, 0, 0); + js_pushstring(J, file_as_string ? file_as_string : ""); + free(file_as_string); } // U0 Reboot()