Compare commits
8 commits
pre-releas
...
main
Author | SHA1 | Date | |
---|---|---|---|
cc4f8dfa51 | |||
e6cff10e60 | |||
d8108823b3 | |||
9ad75fff5c | |||
d97bb83dea | |||
f1fe3a6a97 | |||
a25b25984f | |||
b11a59d211 |
16 changed files with 299 additions and 225 deletions
9
Run.HC
9
Run.HC
|
@ -1,7 +1,8 @@
|
||||||
XTalkWait(Fs, "Cd(\"M:/System/\");\n");
|
Adam("Cd(\"M:/System/\");\n");
|
||||||
XTalkWait(Fs, "#include \"M:/System/MakeSystem\";\n");
|
Adam("#include \"M:/System/MakeSystem\";\n");
|
||||||
XTalkWait(Fs, "#include \"M:/MuJS\";\n");
|
|
||||||
|
WinMax;
|
||||||
|
AutoComplete(0);
|
||||||
|
|
||||||
XTalkWait(Fs, "Cd(\"M:/\");\n");
|
XTalkWait(Fs, "Cd(\"M:/\");\n");
|
||||||
XTalkWait(Fs, "mujs(\"examples/hello.js\");\n");
|
XTalkWait(Fs, "mujs(\"examples/hello.js\");\n");
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
|
|
@ -3,6 +3,36 @@
|
||||||
#define ET_EXEC 2
|
#define ET_EXEC 2
|
||||||
#define ET_DYN 3
|
#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, ...)
|
U0 @elf64_debug_print(U8 fmt, ...)
|
||||||
{
|
{
|
||||||
// FIXME: Remove unnecessary debug_print statements and PrintErr for errors.
|
// 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;
|
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("rela_dyn->r_offset = %08x\n", rela_dyn->r_offset);
|
||||||
@elf64_debug_print("entry name = '%s'\n", entry_name);
|
@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")) {
|
if (!StrCmp(entry_name, "stdin")) {
|
||||||
*(rela_dyn->r_offset)(U64*) = 0;
|
*(rela_dyn->r_offset)(U64*) = 0;
|
||||||
@elf64_debug_print("Set value for .rela.dyn entry '%s' to: %d\n", entry_name, 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 = entry_name;
|
||||||
@patch_jmp_rel32(plt, handler);
|
@patch_jmp_rel32(plt, handler);
|
||||||
@patch_call_rel32(handler + 0x16, &PrintErr);
|
@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)) {
|
if (get_symbol_address(entry_name)) {
|
||||||
symbol_exists = TRUE;
|
symbol_exists = TRUE;
|
||||||
@patch_jmp_rel32(plt, get_symbol_address(entry_name));
|
@patch_jmp_rel32(plt, get_symbol_address(entry_name));
|
||||||
|
@ -293,8 +312,4 @@ U0 load_elf(...)
|
||||||
process_elf_section_header_table(&elf);
|
process_elf_section_header_table(&elf);
|
||||||
process_elf_rela_dyn_entries(&elf);
|
process_elf_rela_dyn_entries(&elf);
|
||||||
process_elf_rela_plt_entries(&elf);
|
process_elf_rela_plt_entries(&elf);
|
||||||
|
|
||||||
_start = elf.ehdr->e_entry;
|
|
||||||
elf_argc = argc;
|
|
||||||
elf_argv = argv;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
asm {
|
||||||
_SETJMP::
|
_SETJMP::
|
||||||
MOV [RDI], RBX // Store caller saved registers
|
MOV [RDI], RBX // Store caller saved registers
|
||||||
|
@ -29,6 +51,30 @@ _LONGJMP::
|
||||||
_extern _SETJMP U64 _setjmp(U64 jmp_buf);
|
_extern _SETJMP U64 _setjmp(U64 jmp_buf);
|
||||||
_extern _LONGJMP U64 longjmp(U64 jmp_buf, U64 ret);
|
_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()
|
U0 free()
|
||||||
{
|
{
|
||||||
PUSH_SYSV_REGS
|
PUSH_SYSV_REGS
|
||||||
|
@ -60,6 +106,56 @@ U0 localtime()
|
||||||
POP_SYSV_REGS
|
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)
|
I64 @strncmp(U8* s1, U8* s2, I32 n)
|
||||||
{
|
{
|
||||||
U64 u1, u2;
|
U64 u1, u2;
|
||||||
|
@ -219,7 +315,6 @@ U0 strcmp()
|
||||||
{
|
{
|
||||||
PUSH_SYSV_REGS
|
PUSH_SYSV_REGS
|
||||||
GET_SYSV_ARGS
|
GET_SYSV_ARGS
|
||||||
//"strcmp: '%s', '%s'\n", p0, p1;
|
|
||||||
StrCmp(p0, p1);
|
StrCmp(p0, p1);
|
||||||
POP_SYSV_REGS
|
POP_SYSV_REGS
|
||||||
}
|
}
|
||||||
|
@ -269,14 +364,6 @@ U0 realloc()
|
||||||
POP_SYSV_REGS
|
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)
|
I64 @time(I64* ptr)
|
||||||
{
|
{
|
||||||
no_warn ptr;
|
no_warn ptr;
|
||||||
|
@ -363,11 +450,3 @@ U0 strstr()
|
||||||
POP_SYSV_REGS
|
POP_SYSV_REGS
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
U0 sprintf()
|
|
||||||
{
|
|
||||||
PUSH_SYSV_REGS
|
|
||||||
GET_SYSV_ARGS
|
|
||||||
StrPrint(p0, p1, p2, p3, p4, p5);
|
|
||||||
POP_SYSV_REGS
|
|
||||||
}
|
|
||||||
|
|
12
System/LibTemple/Input.HC
Normal file
12
System/LibTemple/Input.HC
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -1,44 +1,13 @@
|
||||||
/* clang-format off */
|
/* 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
|
// FFI support files
|
||||||
#include "FFI/Base";
|
|
||||||
#include "FFI/LibC";
|
#include "FFI/LibC";
|
||||||
#include "FFI/ELF64";
|
#include "FFI/ELF64";
|
||||||
|
|
||||||
// LibTemple support files
|
// LibTemple support files
|
||||||
|
#include "LibTemple/Input";
|
||||||
#include "LibTemple/OS";
|
#include "LibTemple/OS";
|
||||||
|
|
||||||
|
#include "MuJS";
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
print("Hello, TempleOS, from MuJS!")
|
print("Hello, TempleOS, from MuJS!")
|
||||||
print("Current date and time is: " + JSON.stringify(new Date()))
|
print("Current date and time is: " + new Date().toString());
|
||||||
print("Type mujs; with no arguments for a REPL, or mujs(\"path/to/file.js\"); to run a program.")
|
print("Type mujs; for a REPL, or mujs(\"path/to/file.js\"); to run a program.");
|
||||||
|
|
|
@ -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'
|
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():
|
def clang_format_src_files():
|
||||||
print("build-all: clang-format-src-files")
|
print("build-all: clang-format-src-files")
|
||||||
exclude_paths = ["mujs", "openlibm", ".iso.c"]
|
exclude_paths = ["mujs", "openlibm", ".iso.c"]
|
||||||
|
@ -115,7 +118,7 @@ def generate_iso_c_file():
|
||||||
|
|
||||||
# Fixup addresses for MuJS
|
# Fixup addresses for MuJS
|
||||||
mujs_bin_path = redsea_path + '/build/bin/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)
|
hc_fixup('MUJS_MAIN', 'main', mujs_bin_path, mujs_hc_path)
|
||||||
exit_fixup(mujs_bin_path, mujs_hc_path)
|
exit_fixup(mujs_bin_path, mujs_hc_path)
|
||||||
|
@ -140,6 +143,7 @@ def run():
|
||||||
raise ValueError("build-all: step 'run' failed, error code " + str(res))
|
raise ValueError("build-all: step 'run' failed, error code " + str(res))
|
||||||
|
|
||||||
def build_all():
|
def build_all():
|
||||||
|
kill_running_qemu_processes()
|
||||||
clang_format_src_files()
|
clang_format_src_files()
|
||||||
refresh_build_path()
|
refresh_build_path()
|
||||||
build_libtemple()
|
build_libtemple()
|
||||||
|
|
1
src/libtemple/input.h
Normal file
1
src/libtemple/input.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uint64_t input_key_down(uint64_t sc);
|
|
@ -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(char const* func) { return 0; }
|
||||||
|
|
||||||
unsigned long os_call_ext_str_1(char const* func, unsigned long arg1) { return 0; }
|
unsigned long os_call_ext_str_1(char const* func, unsigned long arg1) { return 0; }
|
||||||
|
|
|
@ -323,7 +323,7 @@ static char *fmtdate(char *buf, double t)
|
||||||
int d = DateFromTime(t);
|
int d = DateFromTime(t);
|
||||||
if (!isfinite(t))
|
if (!isfinite(t))
|
||||||
return "Invalid Date";
|
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;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,11 +338,11 @@ static char *fmttime(char *buf, double t, double tza)
|
||||||
if (!isfinite(t))
|
if (!isfinite(t))
|
||||||
return "Invalid Date";
|
return "Invalid Date";
|
||||||
if (tza == 0)
|
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)
|
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
|
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;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +353,7 @@ static char *fmtdatetime(char *buf, double t, double tza)
|
||||||
return "Invalid Date";
|
return "Invalid Date";
|
||||||
fmtdate(dbuf, t);
|
fmtdate(dbuf, t);
|
||||||
fmttime(tbuf, t, tza);
|
fmttime(tbuf, t, tza);
|
||||||
sprintf(buf, "%sT%s", dbuf, tbuf);
|
npf_snprintf(buf, 1024, "%sT%s", dbuf, tbuf);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "../libtemple/input.h"
|
||||||
#include "../libtemple/os.h"
|
#include "../libtemple/os.h"
|
||||||
|
|
||||||
#define value_or_number(v, x) js_isundefined(J, x) ? v : js_tonumber(J, x)
|
#define value_or_number(v, x) js_isundefined(J, x) ? v : js_tonumber(J, x)
|
||||||
|
@ -157,6 +158,84 @@ void jsLT_initgr(js_State *J)
|
||||||
js_defglobal(J, "Gr", JS_DONTENUM);
|
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_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");
|
||||||
|
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 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 **/
|
/** OS **/
|
||||||
|
|
||||||
// U0 Beep(I8 ona=62,Bool busy=FALSE)
|
// U0 Beep(I8 ona=62,Bool busy=FALSE)
|
||||||
|
@ -214,8 +293,9 @@ void OS_read_file_as_string(js_State *J)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const char* filename = js_tostring(J, 1);
|
const char* filename = js_tostring(J, 1);
|
||||||
long file_as_string = os_call_ext_str_3("FileRead", (uint64_t)filename, 0, 0);
|
char* file_as_string = (char*)os_call_ext_str_3("FileRead", (uint64_t)filename, 0, 0);
|
||||||
js_pushstring(J, file_as_string ? (char*)file_as_string : "");
|
js_pushstring(J, file_as_string ? file_as_string : "");
|
||||||
|
free(file_as_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
// U0 Reboot()
|
// U0 Reboot()
|
||||||
|
@ -276,5 +356,6 @@ void js_initlibtemple(js_State *J)
|
||||||
{
|
{
|
||||||
jsLT_initdc(J);
|
jsLT_initdc(J);
|
||||||
jsLT_initgr(J);
|
jsLT_initgr(J);
|
||||||
|
jsLT_initinput(J);
|
||||||
jsLT_initos(J);
|
jsLT_initos(J);
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,11 +116,11 @@ static void numtostr(js_State *J, const char *fmt, int w, double n)
|
||||||
{
|
{
|
||||||
/* buf needs to fit printf("%.20f", 1e20) */
|
/* buf needs to fit printf("%.20f", 1e20) */
|
||||||
char buf[50], *e;
|
char buf[50], *e;
|
||||||
sprintf(buf, fmt, w, n);
|
npf_snprintf(buf, 1024, fmt, w, n);
|
||||||
e = strchr(buf, 'e');
|
e = strchr(buf, 'e');
|
||||||
if (e) {
|
if (e) {
|
||||||
int exp = atoi(e+1);
|
int exp = atoi(e+1);
|
||||||
sprintf(e, "e%+d", exp);
|
npf_snprintf(e, 1024, "e%+d", exp);
|
||||||
}
|
}
|
||||||
js_pushstring(J, buf);
|
js_pushstring(J, buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -919,11 +919,11 @@ const char *js_ref(js_State *J)
|
||||||
s = v->u.boolean ? "_True" : "_False";
|
s = v->u.boolean ? "_True" : "_False";
|
||||||
break;
|
break;
|
||||||
case JS_TOBJECT:
|
case JS_TOBJECT:
|
||||||
sprintf(buf, "%p", (void*)v->u.object);
|
npf_snprintf(buf, 1024, "%p", (void*)v->u.object);
|
||||||
s = js_intern(J, buf);
|
s = js_intern(J, buf);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sprintf(buf, "%d", J->nextref++);
|
npf_snprintf(buf, 1024, "%d", J->nextref++);
|
||||||
s = js_intern(J, buf);
|
s = js_intern(J, buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
141
src/mujs/main.c
141
src/mujs/main.c
|
@ -94,6 +94,53 @@ char *readline(const char *prompt)
|
||||||
|
|
||||||
#define PS1 "> "
|
#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)
|
static void jsB_gc(js_State *J)
|
||||||
{
|
{
|
||||||
int report = js_toboolean(J, 1);
|
int report = js_toboolean(J, 1);
|
||||||
|
@ -103,14 +150,7 @@ static void jsB_gc(js_State *J)
|
||||||
|
|
||||||
static void jsB_load(js_State *J)
|
static void jsB_load(js_State *J)
|
||||||
{
|
{
|
||||||
int i, n = js_gettop(J);
|
eval_file(J, js_tostring(J, 1));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jsB_compile(js_State *J)
|
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)
|
static void jsB_read(js_State *J)
|
||||||
{
|
{
|
||||||
const char *filename = js_tostring(J, 1);
|
char *s = (char*)os_call_ext_str_3("FileRead", (uint64_t)js_tostring(J, 1), 0, 0);
|
||||||
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);
|
|
||||||
if (!s) {
|
if (!s) {
|
||||||
fclose(f);
|
js_pushundefined(J);
|
||||||
js_error(J, "out of memory");
|
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);
|
js_pushstring(J, s);
|
||||||
free(s);
|
free(s);
|
||||||
fclose(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jsB_readline(js_State *J)
|
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 };"
|
"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)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: mujs [options] [script [scriptArgs*]]\n");
|
fprintf(stderr, "Usage: mujs [options] [script [scriptArgs*]]\n");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue