aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSlendi <slendi@socopon.com>2023-04-01 12:03:36 +0300
committerSlendi <slendi@socopon.com>2023-04-01 12:03:36 +0300
commit143efd34c1acc354a4b5ca963bb4f4d4f16677ba (patch)
tree0549a6cbc98047f0aee4cee803cca11f89ff512d
Add masterHEADmaster
-rw-r--r--.gitignore3
-rw-r--r--LICENSE10
-rw-r--r--Lib/Base.HC41
-rw-r--r--Lib/DC.HC279
-rw-r--r--Lib/Debug.HC21
-rw-r--r--Lib/ELF64.HC281
-rw-r--r--Lib/Input.HC72
-rw-r--r--Lib/LibC.HC67
-rw-r--r--Lib/Misc.HC24
-rw-r--r--Lib/New.HC17
-rw-r--r--Lib/OS.HC36
-rw-r--r--Lib/Time.HC19
-rw-r--r--Load.HC22
-rw-r--r--README.md21
-rw-r--r--Run.HC1
-rw-r--r--dc.jakt227
-rw-r--r--include/dc.h23
-rw-r--r--include/input.h7
-rw-r--r--include/os.h4
-rw-r--r--include/time.h2
-rw-r--r--input.jakt67
-rw-r--r--libtemple/libtemple.cpp71
-rw-r--r--main.jakt9
-rw-r--r--os.jakt46
-rw-r--r--time.jakt20
25 files changed, 1390 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2922ac5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.vscode/
+build/
+libtemple/libtemple.o
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..cde4ac6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,10 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
+
+In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
diff --git a/Lib/Base.HC b/Lib/Base.HC
new file mode 100644
index 0000000..d96f831
--- /dev/null
+++ b/Lib/Base.HC
@@ -0,0 +1,41 @@
+#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 \
+ 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 MOV_ANS_RAX asm {MOV [&ans], RAX}
+#define MOV_P0_RDI asm {MOV [&p0], RDI}
+#define MOV_P1_RSI asm {MOV [&p1], RSI}
+#define MOV_P2_RDX asm {MOV [&p2], RDX}
+#define MOV_P3_RCX asm {MOV [&p3], RCX}
+#define MOV_P4_R8 asm {MOV [&p4], R8}
+#define MOV_P5_R9 asm {MOV [&p5], R9}
+#define GET_SYSV_ARGS \
+ MOV_P0_RDI MOV_P1_RSI MOV_P2_RDX MOV_P3_RCX MOV_P4_R8 MOV_P5_R9
+
+I64 p0, p1, p2, p3, p4, p5;
+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_P0_RDI
+ CallInd(_ELF_CALL, p0, elf_argc, elf_argv);
+ UserTaskCont;
+}
+
+U0 _exit() { UserTaskCont; } \ No newline at end of file
diff --git a/Lib/DC.HC b/Lib/DC.HC
new file mode 100644
index 0000000..1cecdac
--- /dev/null
+++ b/Lib/DC.HC
@@ -0,0 +1,279 @@
+U0 _Z8dc_aliasm() {
+ // dc_alias(unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_alias(0x%08x)\n", p0);
+ DCAlias(p0);
+ POP_SYSV_REGS
+}
+
+U0 _Z7dc_blotmmmm() {
+ // dc_blot(unsigned long, unsigned long, unsigned long, unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_blot(0x%08x, %d, %d, 0x%08x)\n", p0, p1, p2, p3);
+ GrBlot(p0, p1, p2, p3);
+ POP_SYSV_REGS
+}
+
+I64 @dc_color(CDC *dc) { return dc->color; }
+
+U0 _Z8dc_colorm() {
+ // dc_color(unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_color(0x%08x)\n", p0);
+ @dc_color(p0);
+ POP_SYSV_REGS
+}
+
+U0 @dc_copy(CDC *dest, I64 x, I64 y, CDC *src) {
+
+ // If position is off-screen, return
+ if (x > dest->width - 1 || y > dest->height - 1)
+ return;
+
+ // If device context dimensions match, MemCpy and return
+ if (dest->width_internal == src->width_internal &&
+ dest->height == src->height) {
+ MemCpy(dest->body, src->body, dest->width_internal * dest->height);
+ return;
+ }
+
+ CDC *dc1 = DCAlias(dest);
+ CDC *dc2 = DCAlias(src);
+
+ I64 src_line = 0;
+ I64 src_row = 0;
+ I64 clip_y = 0;
+
+ // Handle horizontal clipping left
+ while (x < 0) {
+ dc2->x0++;
+ x++;
+ }
+
+ // Handle vertical clipping top
+ while (y < 0) {
+ dc2->body += src->width_internal;
+ dc2->y0++;
+ y++;
+ }
+
+ // default, clip line to copy as width-left off screen
+ src_line = src->width - dc2->x0;
+
+ if (-dc2->x0 + x + src->width >= dest->width) {
+ src_line -= ((-dc2->x0 + x + src->width) - dest->width);
+ }
+
+ dc2->body += dc2->x0;
+ clip_y = y;
+
+ while (src_row < (src->height - dc2->y0) && clip_y < dest->height) {
+ MemCpy(dc1->body + (y * dest->width) + x, dc2->body, src_line);
+ dc2->body += src->width_internal;
+ dc1->body += dest->width_internal;
+ clip_y++;
+ src_row++;
+ }
+
+ Free(dc2);
+ Free(dc1);
+}
+
+U0 _Z7dc_copymmmm() {
+ // dc_copy(unsigned long, unsigned long, unsigned long, unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_copy(0x%08x, %d, %d, 0x%08x)\n", p0, p1, p2, p3);
+ @dc_copy(p0, p1, p2, p3);
+ POP_SYSV_REGS
+}
+
+U0 _Z10dc_destroym() {
+ // dc_destroy(unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_destroy(0x%08x)\n", p0);
+ DCDel(p0);
+ POP_SYSV_REGS
+}
+
+U0 _Z14dc_draw_circlemlll() {
+ // dc_draw_circle(unsigned long, long, long, long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_draw_circle(0x%08x, %d, %d, %d)\n", p0, p1, p2, p3);
+ GrCircle3(p0, p1, p2, 0, p3);
+ POP_SYSV_REGS
+}
+
+U0 _Z19dc_draw_filled_rectmllll() {
+ // dc_draw_filled_rect(unsigned long, long, long, long, long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_draw_filled_rect(0x%08x, %d, %d, %d, %d)\n", p0, p1,
+ p2, p3, p4);
+ GrRect(p0, p1, p2, p3, p4);
+ POP_SYSV_REGS
+}
+
+U0 _Z12dc_draw_linemllll() {
+ // dc_draw_line(unsigned long, long, long, long, long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_draw_line(0x%08x, %d, %d, %d, %d)\n", p0, p1, p2, p3,
+ p4);
+ GrLine3(p0, p1, p2, 0, p3, p4, 0);
+ POP_SYSV_REGS
+}
+
+U0 _Z13dc_draw_pixelmll() {
+ // dc_draw_pixel(unsigned long, long, long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_draw_pixel(0x%08x, %d, %d)\n", p0, p1, p2);
+ GrPlot(p0, p1, p2);
+ POP_SYSV_REGS
+}
+
+U0 _Z7dc_fillmm() {
+ // dc_fill(unsigned long, unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_fill(0x%08x, %d\n", p0, p1);
+ DCFill(p0, p1);
+ POP_SYSV_REGS
+}
+
+CDC *@dc_gr_dc() { return gr.dc; }
+
+U0 _Z8dc_gr_dcv() {
+ // dc_gr_dc()
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_gr_dc()\n");
+ @dc_gr_dc();
+ POP_SYSV_REGS
+}
+
+I64 @dc_height(CDC *dc) { return dc->height; }
+
+U0 _Z9dc_heightm() {
+ // dc_height(unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_height(0x%08x)\n", p0);
+ @dc_height(p0);
+ POP_SYSV_REGS
+}
+
+U0 _Z17dc_load_from_filePKc() {
+ // dc_load_from_file(char const*)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_load_from_file(%s, 0x%08x, 0x%08x)\n", p0);
+ GRRead(p0);
+ POP_SYSV_REGS
+}
+
+U0 _Z6dc_newmm() {
+ // dc_new(unsigned long, unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_new(%d, %d)\n", p0, p1);
+ DCNew(p0, p1);
+ POP_SYSV_REGS
+}
+
+U0 _Z11dc_pixel_atmll() {
+ // dc_pixel_at(unsigned long, long, long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_pixel_at(0x%08x, %d, %d)\n", p0, p1, p2);
+ GrPeek(p0, p1, p2);
+ POP_SYSV_REGS
+}
+
+U0 _Z16dc_replace_colormmm() {
+ // dc_replace_color(unsigned long, unsigned long, unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_replace_color(0x%08x, %d, %d)\n", p0, p1, p2);
+ DCColorChg(p0, p1, p2);
+ POP_SYSV_REGS
+}
+
+U0 _Z13dc_screenshotv() {
+ // dc_screenshot()
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_screenshot()\n");
+ DCScrnCapture(1);
+ POP_SYSV_REGS
+}
+
+U0 _Z15dc_save_to_filePKcm() {
+ // dc_save_to_file(char const*, unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_save_to_file(\"%s\", 0x%08x)\n", p0, p1);
+ GRWrite(p0, p1);
+ POP_SYSV_REGS
+}
+
+U0 @dc_set_color(CDC *dc, I64 color) { dc->color = color; }
+
+U0 _Z12dc_set_colorml() {
+ // dc_set_color(unsigned long, long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_set_color(0x%08x, %d)\n", p0, p1);
+ @dc_set_color(p0, p1);
+ POP_SYSV_REGS
+}
+
+U0 @dc_set_thickness(CDC *dc, I64 thickness) { dc->thick = thickness; }
+
+U0 _Z16dc_set_thicknessml() {
+ // dc_set_thickness(unsigned long, long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_set_thickness(0x%08x, %d)\n", p0, p1);
+ @dc_set_thickness(p0, p1);
+ POP_SYSV_REGS
+}
+
+I64 @dc_thickness(CDC *dc) { return dc->thick; }
+
+U0 _Z12dc_thicknessm() {
+ // dc_thickness(unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_thickness(0x%08x)\n", p0);
+ @dc_thickness(p0);
+ POP_SYSV_REGS
+}
+
+I64 @dc_width(CDC *dc) { return dc->width; }
+
+U0 _Z8dc_widthm() {
+ // dc_width(unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_width(0x%08x)\n", p0);
+ @dc_width(p0);
+ POP_SYSV_REGS
+}
+
+I64 @dc_width_internal(CDC *dc) { return dc->width_internal; }
+
+U0 _Z17dc_width_internalm() {
+ // dc_width_internal(unsigned long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: dc_width_internal(0x%08x)\n", p0);
+ @dc_width_internal(p0);
+ POP_SYSV_REGS
+} \ No newline at end of file
diff --git a/Lib/Debug.HC b/Lib/Debug.HC
new file mode 100644
index 0000000..0ce16c8
--- /dev/null
+++ b/Lib/Debug.HC
@@ -0,0 +1,21 @@
+class Debug {
+ Bool enabled;
+ I64 bookmark;
+ I64 counter;
+};
+
+Debug debug;
+debug.bookmark = 0;
+debug.counter = 0;
+debug.enabled = FALSE;
+
+U0 debug_print(U8 *fmt, ...) {
+ if (!debug.enabled || debug.counter < debug.bookmark) {
+ debug.counter++;
+ return;
+ }
+ U8 *buf = StrPrintJoin(NULL, fmt, argc, argv);
+ "[%05d] %s", debug.counter, buf;
+ Free(buf);
+ debug.counter++;
+}
diff --git a/Lib/ELF64.HC b/Lib/ELF64.HC
new file mode 100644
index 0000000..3315d5e
--- /dev/null
+++ b/Lib/ELF64.HC
@@ -0,0 +1,281 @@
+#define EI_NIDENT 16
+#define EM_X86_64 0x3E
+#define ET_EXEC 2
+#define ET_DYN 3
+
+class Elf64_Ehdr {
+ U8 e_ident[EI_NIDENT]; /* Magic number and other info */
+ U16 e_type; /* Object file type */
+ U16 e_machine; /* Architecture */
+ U32 e_version; /* Object file version */
+ U64 e_entry; /* Entry point virtual address */
+ U64 e_phoff; /* Program header table file offset */
+ U64 e_shoff; /* Section header table file offset */
+ U32 e_flags; /* Processor-specific flags */
+ U16 e_ehsize; /* ELF header size in bytes */
+ U16 e_phentsize; /* Program header table entry size */
+ U16 e_phnum; /* Program header table entry count */
+ U16 e_shentsize; /* Section header table entry size */
+ U16 e_shnum; /* Section header table entry count */
+ U16 e_shstrndx; /* Section header string table index */
+};
+
+class Elf64_Shdr {
+ U32 sh_name; /* Section name (string tbl index) */
+ U32 sh_type; /* Section type */
+ U64 sh_flags; /* Section flags */
+ U64 sh_addr; /* Section virtual addr at execution */
+ U64 sh_offset; /* Section file offset */
+ U64 sh_size; /* Section size in bytes */
+ U32 sh_link; /* Link to another section */
+ U32 sh_info; /* Additional section information */
+ U64 sh_addralign; /* Section alignment */
+ U64 sh_entsize; /* Entry size if section holds table */
+};
+
+class Elf64_Sym {
+ U32 st_name; /* Symbol name (string tbl index) */
+ U8 st_info; /* Symbol type and binding */
+ U8 st_other; /* Symbol visibility */
+ U16 st_shndx; /* Section index */
+ U64 st_value; /* Symbol value */
+ U64 st_size; /* Symbol size */
+};
+
+class PLT_entry {
+ U8 pad[0x10];
+};
+
+class RELA_entry {
+ U64 r_offset;
+ U64 r_info;
+ I64 r_addend;
+};
+
+class Elf {
+ union {
+ U8 *u8;
+ Elf64_Ehdr *ehdr;
+ } I64 size;
+ U8 *dynstr;
+ Elf64_Sym *dynsym;
+ PLT_entry *plt;
+ RELA_entry *rela_dyn;
+ RELA_entry *rela_plt;
+ Elf64_Sym *strtab;
+ Elf64_Sym *symtab;
+ I64 rela_dyn_size;
+ I64 rela_plt_size;
+ I64 strtab_size;
+ I64 symtab_size;
+};
+
+U0 (*_start)();
+
+U0 unimplemented_symbol() {
+ I32 s = 0xDEADF00D;
+ "Unimplemented symbol: %s\n", s;
+ while (1)
+ Sleep(1);
+}
+
+Bool is_valid_elf(Elf *elf) {
+ Bool res = TRUE;
+ if (MemCmp(elf->u8 + 1, "ELF", 3)) {
+ debug_print("Invalid signature (not ELF).\n");
+ res = FALSE;
+ }
+ if (elf->ehdr->e_type != ET_EXEC && elf->ehdr->e_type != ET_DYN) {
+ debug_print("Invalid object file type.\n");
+ res = FALSE;
+ }
+ if (elf->ehdr->e_machine != EM_X86_64) {
+ debug_print("Invalid architecture.\n");
+ res = FALSE;
+ }
+ return res;
+}
+
+U0 process_elf_section_header_table(Elf *elf) {
+ Elf64_Shdr *shdr = elf->u8 + elf->ehdr->e_shoff;
+ Elf64_Shdr *shdr_shstrtab = shdr + elf->ehdr->e_shstrndx;
+ U8 *shstrtab = elf->u8 + shdr_shstrtab->sh_offset;
+ I64 i = 0;
+ while (i < elf->ehdr->e_shnum) {
+ if (!StrCmp(shstrtab + shdr->sh_name, ".symtab")) {
+ debug_print("found symtab at 0x%08x, size = %d\n", shdr->sh_offset,
+ shdr->sh_size);
+ elf->symtab = elf->u8 + shdr->sh_offset;
+ elf->symtab_size = shdr->sh_size;
+ }
+ if (!StrCmp(shstrtab + shdr->sh_name, ".strtab")) {
+ debug_print("found strtab at 0x%08x, size = %d\n", shdr->sh_offset,
+ shdr->sh_size);
+ elf->strtab = elf->u8 + shdr->sh_offset;
+ elf->strtab_size = shdr->sh_size;
+ }
+ if (shdr->sh_addr) {
+ MemCpy(shdr->sh_addr, elf->u8 + shdr->sh_offset, shdr->sh_size);
+ if (!StrCmp(shstrtab + shdr->sh_name, ".dynstr"))
+ elf->dynstr = shdr->sh_addr;
+ if (!StrCmp(shstrtab + shdr->sh_name, ".dynsym"))
+ elf->dynsym = shdr->sh_addr;
+ if (!StrCmp(shstrtab + shdr->sh_name, ".plt"))
+ elf->plt = shdr->sh_addr;
+ if (!StrCmp(shstrtab + shdr->sh_name, ".rela.dyn")) {
+ elf->rela_dyn = shdr->sh_addr;
+ elf->rela_dyn_size = shdr->sh_size / shdr->sh_entsize;
+ }
+ if (!StrCmp(shstrtab + shdr->sh_name, ".rela.plt")) {
+ elf->rela_plt = shdr->sh_addr;
+ elf->rela_plt_size = shdr->sh_size / shdr->sh_entsize;
+ }
+ debug_print(
+ "MemCpy section '%s' to physical address 0x%06x, size = %d bytes\n",
+ shstrtab + shdr->sh_name, shdr->sh_addr, shdr->sh_size);
+ if (!StrCmp(shstrtab + shdr->sh_name, ".bss")) {
+ MemSet(shdr->sh_addr, NULL, shdr->sh_size);
+ debug_print("MemSet section '%s' at physical address 0x%06x to NULL, "
+ "size = %d bytes\n",
+ shstrtab + shdr->sh_name, shdr->sh_addr, shdr->sh_size);
+ }
+ if (!StrCmp(shstrtab + shdr->sh_name, ".data"))
+ i = elf->ehdr->e_shnum;
+ }
+ shdr++;
+ i++;
+ }
+}
+
+U0 process_elf_rela_dyn_entries(Elf *elf) {
+ I64 i;
+ U8 *entry_name;
+ RELA_entry *rela_dyn = elf->rela_dyn;
+ for (i = 0; i < elf->rela_dyn_size; i++) {
+ entry_name = elf->dynstr + elf->dynsym[(rela_dyn->r_info >> 32)].st_name;
+ debug_print("rela_dyn->r_offset = %08x\n", rela_dyn->r_offset);
+ debug_print("entry name = '%s'\n", entry_name);
+ if (!StrCmp(entry_name, "__libc_start_main")) {
+ *(rela_dyn->r_offset)(U64 *) = &_main;
+ 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;
+ debug_print("Set value for .rela.dyn entry '%s' to: %d\n", entry_name, 0);
+ }
+ if (!StrCmp(entry_name, "stdout")) {
+ *(rela_dyn->r_offset)(U64 *) = 1;
+ debug_print("Set value for .rela.dyn entry '%s' to: %d\n", entry_name, 1);
+ }
+ if (!StrCmp(entry_name, "stderr")) {
+ *(rela_dyn->r_offset)(U64 *) = 2;
+ debug_print("Set value for .rela.dyn entry '%s' to: %d\n", entry_name, 2);
+ }
+ rela_dyn++;
+ }
+}
+
+CHashClass *get_symbol_hash_entry(U8 *entry_name) {
+ I64 i;
+ CHashSrcSym *sym;
+ CHashTable *tbl = Fs->hash_table;
+ while (tbl) {
+ for (i = 0; i < tbl->mask; i++) {
+ sym = tbl->body[i];
+ while (sym) {
+ if (sym->type == HTT_CLASS)
+ if (!StrCmp(sym->str, entry_name))
+ return sym;
+ sym = sym->next;
+ }
+ }
+ tbl = tbl->next;
+ }
+ return NULL;
+}
+
+U64 get_symbol_address(U8 *entry_name) {
+ CHash *h = HashFind(entry_name, Fs->hash_table, Fs->hash_table->mask);
+ if (!h)
+ return NULL;
+ switch (h->type) {
+ case HTT_GLBL_VAR:
+ return h(CHashGlblVar *)->data_addr;
+ break;
+ case HTT_FUN:
+ return h(CHashFun *)->exe_addr;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ return NULL;
+}
+
+U0 process_elf_rela_plt_entries(Elf *elf) {
+ I64 i;
+ U32 handler;
+ U32 *patch;
+ U8 *entry_name;
+ Bool symbol_exists;
+ PLT_entry *plt = elf->plt;
+ RELA_entry *rela_plt = elf->rela_plt;
+ plt++;
+ for (i = 0; i < elf->rela_plt_size; i++) {
+ symbol_exists = FALSE;
+ entry_name = elf->dynstr + elf->dynsym[(rela_plt->r_info >> 32)].st_name;
+ handler = MAlloc(sizeof(unimplemented_symbol), Fs->code_heap);
+ MemCpy(handler, &unimplemented_symbol, sizeof(unimplemented_symbol));
+ patch = handler + 0x0A;
+ *patch = entry_name;
+ PatchJmpRel32(plt, handler);
+ PatchCallRel32(handler + 0x16, &PrintErr);
+ PatchCallRel32(handler + 0x21, &_exit);
+ if (!StrCmp(entry_name, "__libc_start_main")) {
+ symbol_exists = TRUE;
+ PatchJmpRel32(plt, &_main);
+ debug_print("Set value for .rela.plt entry '%s' to &_main\n", entry_name);
+ }
+ if (get_symbol_address(entry_name)) {
+ symbol_exists = TRUE;
+ PatchJmpRel32(plt, get_symbol_address(entry_name));
+ debug_print("Set value for .rela.plt entry '%s' to &%s\n", entry_name,
+ entry_name);
+ }
+ if (!symbol_exists)
+ debug_print(
+ "Set value for .rela.plt entry '%s' to &unimplemented_symbol\n",
+ entry_name);
+ rela_plt++;
+ plt++;
+ }
+}
+
+U0 load_elf(...) {
+ if (argc < 1) {
+ PrintErr("Not enough arguments.\n");
+ return;
+ }
+ if (!FileFind(argv[0])) {
+ PrintErr("File not found: %s\n", argv[0]);
+ return;
+ }
+
+ Elf elf;
+ elf.u8 = FileRead(argv[0], &elf.size);
+ debug_print("Load file '%s', size = %d bytes\n", argv[0], elf.size);
+
+ if (!is_valid_elf(&elf)) {
+ PrintErr("File is not a valid ELF x86-64 executable.\n");
+ return;
+ }
+
+ 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;
+} \ No newline at end of file
diff --git a/Lib/Input.HC b/Lib/Input.HC
new file mode 100644
index 0000000..c2524ff
--- /dev/null
+++ b/Lib/Input.HC
@@ -0,0 +1,72 @@
+U0 _Z16input_get_stringPKc() {
+ // input_get_string(char const*)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: input_get_string(%s)\n", p0);
+ GetStr(p0);
+ POP_SYSV_REGS
+}
+
+Bool @input_key_down(U8 scancode) { return Bt(kbd.down_bitmap, scancode); }
+
+U0 _Z14input_key_downh() {
+ // input_key_down(unsigned char)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: input_key_down(%c)\n", p0);
+ @input_key_down(p0);
+ POP_SYSV_REGS
+}
+
+Bool @input_mouse_left() { return ms.lb; }
+
+U0 _Z16input_mouse_leftv() {
+ // input_mouse_left()
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: input_mouse_left()\n");
+ @input_mouse_left();
+ POP_SYSV_REGS
+}
+
+Bool @input_mouse_right() { return ms.rb; }
+
+U0 _Z17input_mouse_rightv() {
+ // input_mouse_right()
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: input_mouse_right()\n");
+ @input_mouse_right();
+ POP_SYSV_REGS
+}
+
+I64 @input_mouse_x() { return ms.pos.x; }
+
+U0 _Z13input_mouse_xv() {
+ // input_mouse_x()
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: input_mouse_x()\n");
+ @input_mouse_x();
+ POP_SYSV_REGS
+}
+
+I64 @input_mouse_y() { return ms.pos.y; }
+
+U0 _Z13input_mouse_yv() {
+ // input_mouse_y()
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: input_mouse_y()\n");
+ @input_mouse_y();
+ POP_SYSV_REGS
+}
+
+U0 _Z17input_press_a_keyv() {
+ // input_press_a_key()
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called input_press_a_key()\n");
+ PressAKey;
+ POP_SYSV_REGS
+} \ No newline at end of file
diff --git a/Lib/LibC.HC b/Lib/LibC.HC
new file mode 100644
index 0000000..57e31c0
--- /dev/null
+++ b/Lib/LibC.HC
@@ -0,0 +1,67 @@
+#define stdin 0
+#define stdout 1
+#define stderr 2
+
+U0 free() {
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: free(0x%08x)\n", p0);
+ Free(p0);
+ POP_SYSV_REGS
+}
+
+I64 @fwrite(U8 *ptr, I64 size, I64 nmemb, U64 stream) {
+ U8 *tmp;
+ switch (stream) {
+ case stdout:
+ case stderr:
+ tmp = CAlloc((size * nmemb) + 1);
+ MemCpy(tmp, ptr, (size * nmemb));
+ PutS(tmp);
+ Free(tmp);
+ break;
+ default:
+ break;
+ }
+ return size * nmemb;
+}
+
+U0 fwrite() {
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: fwrite(0x%08x, %d, %d, 0x%08x)\n", p0, p1, p2, p3);
+ @fwrite(p0, p1, p2, p3);
+ POP_SYSV_REGS
+}
+
+U0 malloc() {
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: malloc(%d)\n", p0);
+ MAlloc(p0);
+ POP_SYSV_REGS
+}
+
+U0 memcpy() {
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: memcpy(0x%08x, 0x%08x, %d)\n", p0, p1, p2);
+ MemCpy(p0, p1, p2);
+ POP_SYSV_REGS
+}
+
+U0 memset() {
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: memset(0x%08x, %d, %d)\n", p0, p1, p2);
+ MemSet(p0, p1, p2);
+ POP_SYSV_REGS
+}
+
+U0 strlen() {
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: strlen(\"%s\")\n", p0);
+ StrLen(p0);
+ POP_SYSV_REGS
+} \ No newline at end of file
diff --git a/Lib/Misc.HC b/Lib/Misc.HC
new file mode 100644
index 0000000..67a3313
--- /dev/null
+++ b/Lib/Misc.HC
@@ -0,0 +1,24 @@
+U0 PatchCallRel32(U32 from, U32 to) {
+ *(from(U8 *)) = 0xE8;
+ *((from + 1)(I32 *)) = to - from - 5;
+}
+
+U0 PatchJmpRel32(U32 from, U32 to) {
+ *(from(U8 *)) = 0xE9;
+ *((from + 1)(I32 *)) = to - from - 5;
+}
+
+U0 EnableSSE() {
+ 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
+ }
+}
+
+EnableSSE;
diff --git a/Lib/New.HC b/Lib/New.HC
new file mode 100644
index 0000000..e69b09e
--- /dev/null
+++ b/Lib/New.HC
@@ -0,0 +1,17 @@
+U0 _ZdlPv() {
+ // operator delete(void*)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: operator delete(0x%08x)\n", p0);
+ Free(p0);
+ POP_SYSV_REGS
+}
+
+U0 _ZnwmRKSt9nothrow_t() {
+ // operator new(unsigned long, std::nothrow_t const&)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: operator new(%d)\n", p0);
+ MAlloc(p0);
+ POP_SYSV_REGS
+}
diff --git a/Lib/OS.HC b/Lib/OS.HC
new file mode 100644
index 0000000..8929091
--- /dev/null
+++ b/Lib/OS.HC
@@ -0,0 +1,36 @@
+U0 _Z8os_blinkPKc() {
+ // os_blink(char const*)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ F64 frequency = Str2F64(p0);
+ Print("called os_blink(%.1f)\n", frequency);
+ Blink(frequency);
+ POP_SYSV_REGS
+}
+
+U0 _Z7os_exitv() {
+ // os_exit()
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called os_exit()\n");
+ UserTaskCont;
+ POP_SYSV_REGS
+}
+
+U0 _Z19os_read_entire_filePKcPl() {
+ // os_read_entire_file(char const*, long*)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called os_read_entire_file(\"%s\", 0x%08x)\n", p0, p1);
+ FileRead(p0, p1);
+ POP_SYSV_REGS
+}
+
+U0 _Z20os_write_entire_filePKcPhl() {
+ // os_write_entire_file(char const*, unsigned char*, long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called os_write_entire_file(\"%s\", 0x%08x, %d)\n", p0, p1, p2);
+ FileWrite(p0, p1, p2);
+ POP_SYSV_REGS
+} \ No newline at end of file
diff --git a/Lib/Time.HC b/Lib/Time.HC
new file mode 100644
index 0000000..37b58a1
--- /dev/null
+++ b/Lib/Time.HC
@@ -0,0 +1,19 @@
+I64 @time_jiffies() { return cnts.jiffies; }
+
+U0 _Z12time_jiffiesv() {
+ // time_jiffies()
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: time_jiffies()\n");
+ @time_jiffies;
+ POP_SYSV_REGS
+}
+
+U0 _Z10time_sleepl() {
+ // time_sleep(long)
+ PUSH_SYSV_REGS
+ GET_SYSV_ARGS
+ debug_print("called: time_sleep(%d)\n", p0);
+ Sleep(p0);
+ POP_SYSV_REGS
+} \ No newline at end of file
diff --git a/Load.HC b/Load.HC
new file mode 100644
index 0000000..0347e31
--- /dev/null
+++ b/Load.HC
@@ -0,0 +1,22 @@
+/* clang-format off */
+
+#include "Lib/Debug";
+#include "Lib/Misc";
+
+#include "Lib/Base";
+#include "Lib/LibC";
+#include "Lib/New";
+
+#include "Lib/OS";
+#include "Lib/DC";
+#include "Lib/Input";
+#include "Lib/Time";
+
+#include "Lib/ELF64";
+
+/* clang-format on */
+
+IsRaw; // Quick and dirty method to return 0
+
+load_elf("build/program");
+_start();
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..46f35b7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,21 @@
+# unholy-jakt
+
+Jakt toolchain for TempleOS development
+
+# build
+
+```
+g++ -c -o libtemple/libtemple.o libtemple/libtemple.cpp; gcc -shared -o build/libtemple.so libtemple/libtemple.o
+
+jakt -S -o program -R <runtime_path> -B build main.jakt
+
+clang++-14 -I <runtime_path> -fcolor-diagnostics -std=c++20 -fno-exceptions -Wno-user-defined-literals -Wno-deprecated-declarations -Wno-parentheses-equality -Wno-unqualified-std-cast-call -Wno-unknown-warning-option -o build/program build/program.cpp build/libtemple.so
+```
+
+# usage
+
+Copy the contents of the repo to a RedSea ISO.C disk image,
+
+```
+Cd("T:"); #include "Run";
+```
diff --git a/Run.HC b/Run.HC
new file mode 100644
index 0000000..aed0702
--- /dev/null
+++ b/Run.HC
@@ -0,0 +1 @@
+XTalkWait(Fs, "#include \"Load\";\n"); \ No newline at end of file
diff --git a/dc.jakt b/dc.jakt
new file mode 100644
index 0000000..549cb20
--- /dev/null
+++ b/dc.jakt
@@ -0,0 +1,227 @@
+import extern c "/home/alec/repos/unholy-jakt/include/dc.h" {}
+
+class DC {
+ public function width(this) -> i64 {
+ mut width = 0
+ unsafe {
+ cpp {
+ "width = dc_width(this->context);"
+ }
+ }
+ return width
+ }
+ public function width_internal(this) -> i64 {
+ mut width_internal = 0
+ unsafe {
+ cpp {
+ "width_internal = dc_width_internal(this->context);"
+ }
+ }
+ return width_internal
+ }
+ public function height(this) -> i64 {
+ mut height = 0
+ unsafe {
+ cpp {
+ "height = dc_height(this->context);"
+ }
+ }
+ return height
+ }
+ public function color(this) -> i64 {
+ mut color = 0
+ unsafe {
+ cpp {
+ "color = dc_color(this->context);"
+ }
+ }
+ return color
+ }
+ public function thickness(this) -> i64 {
+ mut thickness = 0
+ unsafe {
+ cpp {
+ "thickness = dc_thickness(this->context);"
+ }
+ }
+ return thickness
+ }
+ context: usize
+ public function alias(this) throws -> DC {
+ mut dc = DC(context: 0);
+ unsafe {
+ cpp {
+ "dc->context = dc_alias(this->context);"
+ }
+ }
+ return dc
+ }
+ public function blot(this, dc: DC, x: i64, y: i64) {
+ unsafe {
+ cpp {
+ "dc_blot(dc->context, x, y, this->context);"
+ }
+ }
+ }
+ public function clear(this) {
+ .fill(color: 255)
+ }
+ public function copy(this, dc: DC, x: i64, y: i64) {
+ unsafe {
+ cpp {
+ "dc_copy(dc->context, x, y, this->context);"
+ }
+ }
+ }
+ public function create_rect(width: i64, height: i64) throws -> DC {
+ mut dc = DC(context: 0);
+ dc.init(width, height)
+ return dc
+ }
+ public function fill(this, color: i64) {
+ unsafe {
+ cpp {
+ "dc_fill(this->context, color);"
+ }
+ }
+ }
+ function destroy(this) {
+ unsafe {
+ cpp {
+ "dc_destroy(this->context);"
+ }
+ }
+ }
+ public function flip_horizontal(mut this) throws {
+ mut flipped_dc = DC::create_rect(width: .width(), height: .height())
+ for y in 0..this.height() {
+ for x in 0..this.width() {
+ flipped_dc.set_color(.pixel_at(x: .width() - 1 - x, y))
+ flipped_dc.draw_pixel(x, y)
+ }
+ }
+ .destroy()
+ .context = flipped_dc.context
+ }
+ public function flip_vertical(mut this) throws {
+ mut flipped_dc = DC::create_rect(width: .width(), height: .height())
+ for y in 0..this.height() {
+ for x in 0..this.width() {
+ flipped_dc.set_color(.pixel_at(x, y: .height() - 1 - y))
+ flipped_dc.draw_pixel(x, y)
+ }
+ }
+ .destroy()
+ .context = flipped_dc.context
+ }
+ public function draw_circle(this, x: i64, y: i64, radius: i64) {
+ unsafe {
+ cpp {
+ "dc_draw_circle(this->context, x, y, radius);"
+ }
+ }
+ }
+ public function draw_filled_rect(this, x: i64, y: i64, width: i64, height: i64) {
+ unsafe {
+ cpp {
+ "dc_draw_filled_rect(this->context, x, y, width, height);"
+ }
+ }
+ }
+ public function draw_line(this, x1: i64, y1: i64, x2: i64, y2: i64) {
+ unsafe {
+ cpp {
+ "dc_draw_line(this->context, x1, y1, x2, y2);"
+ }
+ }
+ }
+ public function draw_pixel(this, x: i64, y: i64) {
+ unsafe {
+ cpp {
+ "dc_draw_pixel(this->context, x, y);"
+ }
+ }
+ }
+ public function gr_dc() throws -> DC {
+ mut dc = DC(context: 0);
+ unsafe {
+ cpp {
+ "dc->context = dc_gr_dc();"
+ }
+ }
+ return dc
+ }
+ function init(mut this, width: i64, height: i64) {
+ unsafe {
+ cpp {
+ "this->context = dc_new(width, height);"
+ }
+ }
+ }
+ public function integer_scale(mut this, scale_factor: i64) throws {
+ mut scaled_dc = DC::create_rect(width: .width() * scale_factor, height: .height() * scale_factor)
+ for y in 0..this.height() {
+ for x in 0..this.width() {
+ scaled_dc.set_color(.pixel_at(x, y))
+ scaled_dc.draw_filled_rect(x: x * scale_factor, y: y * scale_factor, width: scale_factor, height: scale_factor)
+ }
+ }
+ .destroy()
+ .context = scaled_dc.context
+ }
+ public function load_from_file(anon filename: String) throws -> DC {
+ mut dc = DC(context: 0);
+ unsafe {
+ cpp {
+ "dc->context = dc_load_from_file(filename.c_string());"
+ }
+ }
+ return dc
+ }
+ public function pixel_at(this, x: i64, y: i64) -> i64 {
+ mut value = 0
+ unsafe {
+ cpp {
+ "value = dc_pixel_at(this->context, x, y);"
+ }
+ }
+ return value
+ }
+ public function replace_color(this, from: i64, to: i64) {
+ unsafe {
+ cpp {
+ "dc_replace_color(this->context, from, to);"
+ }
+ }
+ }
+ public function save_to_file(this, anon filename: String) {
+ unsafe {
+ cpp {
+ "dc_save_to_file(filename.c_string(), this->context);"
+ }
+ }
+ }
+ public function screenshot() throws -> DC {
+ mut dc = DC(context: 0);
+ unsafe {
+ cpp {
+ "dc->context = dc_screenshot();"
+ }
+ }
+ return dc
+ }
+ public function set_color(this, anon color: i64) {
+ unsafe {
+ cpp {
+ "dc_set_color(this->context, color);"
+ }
+ }
+ }
+ public function set_thickness(this, anon thickness: i64) {
+ unsafe {
+ cpp {
+ "dc_set_thickness(this->context, thickness);"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/include/dc.h b/include/dc.h
new file mode 100644
index 0000000..da49af5
--- /dev/null
+++ b/include/dc.h
@@ -0,0 +1,23 @@
+unsigned long dc_alias(unsigned long context);
+void dc_blot(unsigned long dest, unsigned long x, unsigned long y, unsigned long src);
+long dc_color(unsigned long context);
+void dc_copy(unsigned long dest, unsigned long x, unsigned long y, unsigned long src);
+void dc_destroy(unsigned long context);
+void dc_draw_circle(unsigned long context, long x, long y, long radius);
+void dc_draw_filled_rect(unsigned long context, long x, long y, long width, long height);
+void dc_draw_line(unsigned long context, long x1, long y1, long x2, long y2);
+void dc_draw_pixel(unsigned long context, long x, long y);
+void dc_fill(unsigned long context, unsigned long color);
+unsigned long dc_gr_dc();
+long dc_height(unsigned long context);
+unsigned long dc_load_from_file(const char * filename);
+unsigned long dc_new(unsigned long width, unsigned long height);
+long dc_pixel_at(unsigned long context, long x, long y);
+unsigned long dc_replace_color(unsigned long context, unsigned long from, unsigned long to);
+void dc_save_to_file(const char * filename, unsigned long context);
+unsigned long dc_screenshot();
+void dc_set_color(unsigned long context, long color);
+void dc_set_thickness(unsigned long context, long thickness);
+long dc_thickness(unsigned long context);
+long dc_width(unsigned long context);
+long dc_width_internal(unsigned long context); \ No newline at end of file
diff --git a/include/input.h b/include/input.h
new file mode 100644
index 0000000..a4b11a2
--- /dev/null
+++ b/include/input.h
@@ -0,0 +1,7 @@
+const char *input_get_string(const char *message);
+bool input_key_down(u8 scancode);
+bool input_mouse_left();
+bool input_mouse_right();
+i64 input_mouse_x();
+i64 input_mouse_y();
+void input_press_a_key(); \ No newline at end of file
diff --git a/include/os.h b/include/os.h
new file mode 100644
index 0000000..b4f14b3
--- /dev/null
+++ b/include/os.h
@@ -0,0 +1,4 @@
+bool os_blink(const char *frequency_as_string);
+void os_exit();
+u8 *os_read_entire_file(const char *filename, i64 *size);
+void os_write_entire_file(const char *filename, unsigned char *buffer, i64 size); \ No newline at end of file
diff --git a/include/time.h b/include/time.h
new file mode 100644
index 0000000..cd7d0c1
--- /dev/null
+++ b/include/time.h
@@ -0,0 +1,2 @@
+i64 time_jiffies();
+void time_sleep(i64 duration); \ No newline at end of file
diff --git a/input.jakt b/input.jakt
new file mode 100644
index 0000000..4629472
--- /dev/null
+++ b/input.jakt
@@ -0,0 +1,67 @@
+import extern c "/home/alec/repos/unholy-jakt/include/input.h" {}
+
+struct Input {
+ function get_string(message: String) throws -> String {
+ mut s = StringBuilder::create()
+ unsafe {
+ cpp {
+ "char const *chars = input_get_string(message.c_string());
+ TRY(s.append_c_string(chars));
+ delete(chars);"
+ }
+ }
+ return s.to_string()
+ }
+ function key_down(scancode: u8) -> bool {
+ mut key_is_down = false;
+ unsafe {
+ cpp {
+ "key_is_down = input_key_down(scancode);"
+ }
+ }
+ return key_is_down;
+ }
+ function mouse_left() -> bool {
+ mut left_button: bool = false
+ unsafe {
+ cpp {
+ "left_button = input_mouse_left();"
+ }
+ }
+ return left_button;
+ }
+ function mouse_right() -> bool {
+ mut right_button: bool = false
+ unsafe {
+ cpp {
+ "right_button = input_mouse_right();"
+ }
+ }
+ return right_button;
+ }
+ function mouse_x() -> i64 {
+ mut x = 0
+ unsafe {
+ cpp {
+ "x = input_mouse_x();"
+ }
+ }
+ return x;
+ }
+ function mouse_y() -> i64 {
+ mut y = 0
+ unsafe {
+ cpp {
+ "y = input_mouse_y();"
+ }
+ }
+ return y;
+ }
+ function press_a_key() {
+ unsafe {
+ cpp {
+ "input_press_a_key();"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/libtemple/libtemple.cpp b/libtemple/libtemple.cpp
new file mode 100644
index 0000000..ca3c7a1
--- /dev/null
+++ b/libtemple/libtemple.cpp
@@ -0,0 +1,71 @@
+unsigned long dc_alias(unsigned long context) { return 0; }
+
+void dc_blot(unsigned long dest, unsigned long x, unsigned long y, unsigned long src) {}
+
+void dc_copy(unsigned long dest, unsigned long x, unsigned long y, unsigned long src) {}
+
+long dc_color(unsigned long context) { return 0; }
+
+void dc_destroy(unsigned long context) {}
+
+void dc_draw_circle(unsigned long context, long x, long y, long radius) {}
+
+void dc_draw_filled_rect(unsigned long context, long x, long y, long width, long height) {}
+
+void dc_draw_line(unsigned long context, long x1, long y1, long x2, long y2) {}
+
+void dc_draw_pixel(unsigned long context, long x, long y) {}
+
+void dc_fill(unsigned long context, unsigned long color) {}
+
+unsigned long dc_gr_dc() { return 0; }
+
+long dc_height(unsigned long context) { return 0; }
+
+unsigned long dc_load_from_file(const char * filename) { return 0; }
+
+unsigned long dc_new(unsigned long width, unsigned long height) { return 0; }
+
+long dc_pixel_at(unsigned long context, long x, long y) { return 0; }
+
+void dc_replace_color(unsigned long context, unsigned long from, unsigned long to) {}
+
+void dc_save_to_file(const char * filename, unsigned long context) {}
+
+unsigned long dc_screenshot() { return 0; }
+
+void dc_set_color(unsigned long context, long color) {}
+
+void dc_set_thickness(unsigned long context, long thickness) {}
+
+long dc_thickness(unsigned long context) { return 0; }
+
+long dc_width(unsigned long context) { return 0; }
+
+long dc_width_internal(unsigned long context) { return 0; }
+
+const char *input_get_string(const char *message) { return 0; }
+
+bool input_key_down(unsigned char scancode) { return 0; }
+
+bool input_mouse_left() { return 0; }
+
+bool input_mouse_right() { return 0; }
+
+void input_press_a_key() {}
+
+unsigned long input_mouse_x() { return 0; }
+
+unsigned long input_mouse_y() { return 0; }
+
+bool os_blink(const char *frequency_as_string) { return 0; }
+
+void os_exit() {}
+
+unsigned long os_read_entire_file(const char *filename, long *size) { return 0; }
+
+void os_write_entire_file(const char *filename, unsigned char *buffer, long size) { }
+
+long time_jiffies() { return 0; }
+
+void time_sleep(long duration) { } \ No newline at end of file
diff --git a/main.jakt b/main.jakt
new file mode 100644
index 0000000..3f15158
--- /dev/null
+++ b/main.jakt
@@ -0,0 +1,9 @@
+import os { OS }
+import input { Input }
+
+function main() {
+ let my_string = Input::get_string(message: "Please enter some text: ")
+ println("You typed: {}", my_string)
+ Input::press_a_key()
+ OS::exit()
+} \ No newline at end of file
diff --git a/os.jakt b/os.jakt
new file mode 100644
index 0000000..5af2799
--- /dev/null
+++ b/os.jakt
@@ -0,0 +1,46 @@
+import extern c "/home/alec/repos/unholy-jakt/include/os.h" {}
+
+struct OS {
+ function blink(frequency: f64 = 2.5) throws -> bool {
+ let frequency_as_string = String::format("{}", frequency)
+ mut is_blink: bool = false
+ unsafe {
+ cpp {
+ "is_blink = os_blink(frequency_as_string.c_string());"
+ }
+ }
+ return is_blink
+ }
+ function exit() {
+ unsafe {
+ cpp {
+ "os_exit();"
+ }
+ }
+ }
+ function read_entire_file(anon filename: String) throws -> [u8] {
+ mut size = 0
+ mut buffer: [u8] = []
+ unsafe {
+ cpp {
+ "u8 *data = os_read_entire_file(filename.c_string(), &size);
+ for (int i = 0; i < size; i++)
+ TRY(buffer.push(data[i]));
+ free(data);"
+ }
+ }
+ return buffer
+ }
+ function write_entire_file(filename: String, buffer: [u8]) {
+ mut size = buffer.size()
+ unsafe {
+ cpp {
+ "unsigned char *data = (unsigned char *)malloc(size);
+ for (int i = 0; i < size; i++)
+ data[i] = buffer[i];
+ os_write_entire_file(filename.c_string(), data, size);
+ free(data);"
+ }
+ }
+ }
+}
diff --git a/time.jakt b/time.jakt
new file mode 100644
index 0000000..9ad60a8
--- /dev/null
+++ b/time.jakt
@@ -0,0 +1,20 @@
+import extern c "/home/alec/repos/unholy-jakt/include/time.h" {}
+
+struct Time {
+ function jiffies() throws -> i64 {
+ mut value: i64 = 0
+ unsafe {
+ cpp {
+ "value = time_jiffies();"
+ }
+ }
+ return value
+ }
+ function sleep(anon duration: i64) {
+ unsafe {
+ cpp {
+ "time_sleep(duration);";
+ }
+ }
+ }
+} \ No newline at end of file