From 7d0db9acc9a0631d981f1633935a8bc7f60ed2a1 Mon Sep 17 00:00:00 2001 From: bungao Date: Sun, 1 Jul 2012 22:00:21 +1000 Subject: [PATCH 01/13] New Process handler - uses stack instead of buffering to a table. - affected the operation of the keyboard driver which is now completely interrupt driven. - the read_line routine now doesn't need to poll the keyboard - mem_clear and mem_copy are now secure against a zero length --- apps/AtlasShell.dasm16 | 10 +- include/kernel.inc | 67 ++++-------- kernel/core.dasm16 | 75 +++---------- kernel/drivers.dasm16 | 13 +-- kernel/interrupts.dasm16 | 15 +-- kernel/library.dasm16 | 11 +- kernel/memory.dasm16 | 5 + kernel/process.dasm16 | 220 +++++++++++++++++++-------------------- 8 files changed, 169 insertions(+), 247 deletions(-) diff --git a/apps/AtlasShell.dasm16 b/apps/AtlasShell.dasm16 index fa9da1b..641fbff 100644 --- a/apps/AtlasShell.dasm16 +++ b/apps/AtlasShell.dasm16 @@ -43,7 +43,7 @@ SET A, input_text_buffer JSR [0x1019] IFE B, 0 - SET PC, AtlasShell_loop_wait + SET PC, AtlasShell_newline ; Parse out the primary command SET A, input_text_buffer @@ -121,18 +121,18 @@ IFN [ack_command], 1 JSR command_unknownf :AtlasShell_loop_wait - ; Pause then loop back to start of process - ;JSR [0x1002] - ;INT [clock_address] ; FIX THIS ASAP! SET PC, AtlasShell_loop :AtlasShell_loop_end +:AtlasShell_newline + JSR [0x101f] + SET PC, AtlasShell_loop_wait ; ==BEGIN COMMAND FUNCTIONS== ; Command function when we got an unknown command :command_unknownf - JSR [0x101F] SET a, text_unrecognized JSR [0x101E] + JSR [0x101F] SET pc, pop ; Command function to display version info diff --git a/include/kernel.inc b/include/kernel.inc index c2ba866..3047c5a 100644 --- a/include/kernel.inc +++ b/include/kernel.inc @@ -70,54 +70,28 @@ dat " \\____//____/", 0xA0, 0x00 dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 :message_queue_table_end +:int_msg dat 0x0 +:processes dat 1 :proc_current dat 0x0001 -:proc_buffer dat 0x0000 -:proc_buffer_a dat 0x0000 -:proc_buffer_b dat 0x0000 -:proc_buffer_c dat 0x0000 -:proc_buffer_x dat 0x0000 -:proc_buffer_y dat 0x0000 -:proc_buffer_z dat 0x0000 -:proc_buffer_i dat 0x0000 -:proc_buffer_j dat 0x0000 -:proc_buffer_sp dat 0x0000 -:proc_buffer_mem dat 0x0000 -:proc_buffer_flags dat 0x0000 +:proc_suspend_int dat 0x0 + :proc_table - dat 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 -:proc_table10 - dat 0xFFFF, 0x0000, 0xFFFD ; OS-Proc - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 ; 1st proc - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 ; 2nd proc - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 ; 3rd proc - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 ; 4th proc - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 ; 5th proc - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 ; [...] - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0001, 0xFFFF, 0x0000, 0xFFFD +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000 :proc_table_end ; Keyboard driver variables @@ -130,7 +104,6 @@ dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 :keyboard_buffers_flags_end :keyboard_buffers_exclusive dat 0x0000 ; Contains buffer mem loc that has exclusive access -:keyboard_oldvalue dat 0x0000 ; Kernel watchdog variables :kernel_watchdog_proc_list_buffer diff --git a/kernel/core.dasm16 b/kernel/core.dasm16 index 829af35..15b7735 100644 --- a/kernel/core.dasm16 +++ b/kernel/core.dasm16 @@ -17,8 +17,6 @@ SET PC, kernel_boot :kernel_boot JSR bios_boot -; Set the interrupt handler first -IAS kernel_interrupt_handler ; clear screen (for emulator) JSR clear @@ -31,35 +29,23 @@ JSR text_out SET A, text_start JSR text_out -; Reserve kernel-memory +; Reserve all operating system code including api space SET X, 0 -:kernel_mem -IFG X, kernel_end - SET PC, kernel_mem_end -SET A, X -JSR page_reserve -ADD X, 1024 -SET PC, kernel_mem -:kernel_mem_end - -; Reserve misc-memory -SET X, os_content -:os_content_mem +:code_mem IFG X, os_content_end - SET PC, os_content_mem_end + SET PC, code_mem_end SET A, X JSR page_reserve ADD X, 1024 -SET PC, os_content_mem -:os_content_mem_end +SET PC, code_mem +:code_mem_end + ; Reserve stack-memory SET A, 0xFFFF JSR page_reserve -; Reserve the API space -SET A, 0x1000 -JSR page_reserve + SET X, 0 @@ -72,63 +58,34 @@ JSR mem_copy ; Clear out a few things SET [keyboard_buffers_exclusive], 0 -SET [keyboard_oldvalue], 0 JSR keyboard_unregister_all ; OS ready message SET A, text_start_ok JSR text_out +; Set the interrupt handler last since booting has finished +IAS kernel_interrupt_handler ; Main kernel loop :kernel_loop - ; Call the keyboard driver - JSR driver_keyboard - ; Check if the kernel is the only running process, if so start the shell JSR kernel_watchdog_checkalone ; Release back to other running processes - INT 0xFEDC - ;JSR proc_suspend - + INT [proc_suspend_int] + SET PC, kernel_loop ; Watchdog to ensure the shell is always running even if in the background :kernel_watchdog_checkalone - SET PUSH, C - SET PUSH, B - SET PUSH, A - - SET C, kernel_watchdog_proc_list_buffer - SET A, kernel_watchdog_helper - JSR proc_callback_list - SET C, kernel_watchdog_proc_list_buffer - ADD C, 1 - IFE [C], 0 - JSR kernel_watchdog_loadshell - - ; Clear the proc buffer - SET C, kernel_watchdog_proc_list_buffer - SET [C], 0 - ADD C, 1 - SET [C], 0 - - SET A, POP - SET B, POP - SET C, POP - SET PC, POP -:kernel_watchdog_helper - IFE C, kernel_watchdog_proc_list_buffer_end - SET PC, POP - SET [C], A - ADD C, 1 + SET A, proc_table + ADD A, 4 + IFN [A], 2 + SET PC, kernel_watchdog_loadshell + SET PC, POP :kernel_watchdog_loadshell - ; This is a workaround so the shell doesn't freak out - ; when there is no data in the keyboard buffer - SET [keyboard_oldvalue], 0xFFFF - ; Now start the shell SET A, AtlasShell SET B, AtlasShell_end SUB B, AtlasShell diff --git a/kernel/drivers.dasm16 b/kernel/drivers.dasm16 index 1da930e..0b9bc0c 100644 --- a/kernel/drivers.dasm16 +++ b/kernel/drivers.dasm16 @@ -96,7 +96,7 @@ SET B, [clock_address] ; Our magic word to tell the handler we have a clock tick ADD B, 1 ; Always use HW+1 so we never pass a 0 to B as that would disable interrupts HWI [clock_address] - + SET [proc_suspend_int], B SET PC, POP :bios_floppy_init @@ -192,9 +192,9 @@ dat 0x0000 ; Bit 1 - Is active, Bit 2 - ??, Bit 3 - ??, Bit 4 - ?? SET A, 1 HWI [keyboard_address] - ; Skip the driver if the key value hasn't changed - IFE C, [keyboard_oldvalue] - SET PC, driver_keyboard_end + ; Skip the driver if the key value is 0 + IFE C, 0 + SET PC, driver_keyboard_end SET A, keyboard_buffers @@ -210,7 +210,6 @@ dat 0x0000 ; Bit 1 - Is active, Bit 2 - ??, Bit 3 - ??, Bit 4 - ?? IFN A, keyboard_buffers_end SET PC, driver_keyboard_loop :driver_keyboard_end - SET [keyboard_oldvalue], C SET A, 0 HWI [keyboard_address] SET C, POP @@ -299,9 +298,7 @@ dat 0x0000 ; Bit 1 - Is active, Bit 2 - ??, Bit 3 - ??, Bit 4 - ?? SET PC, POP :keyboard_unregister_exclusive - ; Trigger a keyboard buffer update on any other register buffers - SET [keyboard_oldvalue], 0xFFFF - ; And clear the exclusive data +; clear the exclusive data SET [keyboard_buffers_exclusive], 0 SET PC, POP diff --git a/kernel/interrupts.dasm16 b/kernel/interrupts.dasm16 index 761f90c..3a77057 100644 --- a/kernel/interrupts.dasm16 +++ b/kernel/interrupts.dasm16 @@ -16,8 +16,7 @@ RFI 0 :kernel_interrupt_handler_manual - IFN [proc_suspend_param], 0 - SET PC, kernel_interrupt_handler_manual_skip_suspend + SET PUSH, C SET PUSH, B @@ -32,13 +31,13 @@ SET B, POP SET C, POP - SET [proc_suspend_param], 1 + JSR proc_suspend_interrupt -:kernel_interrupt_handler_manual_skip_suspend + SET PC, POP ; This line should never be called :kernel_interrupt_handler_keyboard - ; TODO +jsr driver_keyboard SET PC, POP :kernel_interrupt_handler_clock @@ -55,11 +54,7 @@ SET B, POP SET C, POP - IFN [proc_suspend_param], 0 - SET PC, kernel_interrupt_handler_clock_skip_suspend - - ;SET [proc_suspend_param], 1 - ;JSR proc_suspend_interrupt + JSR proc_suspend_interrupt :kernel_interrupt_handler_clock_skip_suspend SET PC, POP diff --git a/kernel/library.dasm16 b/kernel/library.dasm16 index 42d0d02..2e9f7d3 100644 --- a/kernel/library.dasm16 +++ b/kernel/library.dasm16 @@ -385,6 +385,8 @@ SET PC, POP SET B, 0 :strlen_loop + IFE [A], 0 + SET PC, strlen_end ADD A, 1 IFN [A], 0 SET PC, strlen_loop @@ -409,9 +411,7 @@ SET PC, POP ADD B, A :read_line_loop - INT 0xFEDC - ;JSR proc_suspend - + IFE [C], 0x11 ; 13 -> 17 per keyboard HW (enter) SET PC, read_line_end IFE [C], 0x10 ; 8 -> 16 per keyboard HW (backspace) @@ -442,7 +442,7 @@ SET PC, POP JSR scroll SET B, POP SET A, POP - + SET [C], 0 ADD A, 1 :read_line_skip @@ -487,6 +487,7 @@ SET PC, POP SET B, POP SET A, POP SUB A, 1 + SET [C], 0 SET PC, read_line_skip :read_line_end @@ -502,7 +503,7 @@ SET PC, POP SET C, POP SET B, POP SET A, POP - + SET [C], 0 ; Add the null terminator SET [A], 0 ; Pop everything back out diff --git a/kernel/memory.dasm16 b/kernel/memory.dasm16 index 6c0d83d..7da874b 100644 --- a/kernel/memory.dasm16 +++ b/kernel/memory.dasm16 @@ -2,6 +2,9 @@ ; A: From Addr ; B: Length :mem_clear + IFE B, 0 + SET PC, POP + SET PUSH, A SET PUSH, B @@ -24,6 +27,8 @@ ; B -> dest ; C -> length :mem_copy + IFE C, 0 + SET PC, POP SET PUSH, A SET PUSH, B SET PUSH, C diff --git a/kernel/process.dasm16 b/kernel/process.dasm16 index 67d0ab2..ec2eee5 100644 --- a/kernel/process.dasm16 +++ b/kernel/process.dasm16 @@ -56,8 +56,9 @@ JSR proc_id :proc_get_info_of - MUL A, 12 - ADD A, proc_buffer + MUL A, 4 + ADD A, proc_table + SUB A, 4 SET PC, POP ; Sets the flags of the current process @@ -145,107 +146,77 @@ SET A, [B] IFN A, 0 JSR PEEK - ADD B, 12 + ADD B, 4 IFN B, proc_table_end SET PC, proc_callback_list_loop SET A, POP SET B, POP SET PC, POP - -; Trigger a manual process suspend interrupt -; THIS IS WEIRDLY BROKEN! WHY!? -; Tried added dummy ops, still broken + :proc_suspend - SET A, 42 ; dummy op - INT 0xFEDC - SET A, 42 ; dummy op - SET PC, POP - -; proc_suspend_interrupt -; Takes 164 - 264 cycles to complete which is 1.6ms to 2.6ms -:proc_suspend_interrupt - IFE [preemptive_enabled], 0 - SET PC, proc_suspend_interrupt_skipstart - IFE [proc_suspend_param], 0 - SET PC, proc_suspend_interrupt_skipstart - - SET A, POP ; Pop off the return address - SET A, POP ; Pop off another return address - SET EX, POP ; Get EX back - SET A, POP ; Get A back - SET [proc_suspend_param], 0 ; Reset the param -:proc_suspend_interrupt_skipstart - - SET [proc_buffer], [proc_current] ; Buffer the registers of the current process - SET [proc_buffer_a], A - SET [proc_buffer_b], B - SET [proc_buffer_c], C - SET [proc_buffer_x], X - SET [proc_buffer_y], Y - SET [proc_buffer_z], Z - SET [proc_buffer_i], I - SET [proc_buffer_j], J - SET [proc_buffer_sp], SP - - ; Restore the Stackpointer so we can call subroutines - SET SP, [proc_table10] - - ; Copy the buffered state to the table - JSR proc_get_info - SET B, A - SET A, proc_buffer - SET C, 12 - JSR mem_copy +INT [proc_suspend_int] +SET PC, POP + - ; Process saved, now restore the next proc - SET A, B +:proc_suspend_interrupt +ADD SP, 3 +ifl [processes], 2 +rfi a +SET PUSH, B +SET PUSH, C +SET PUSH, X +SET PUSH, Y +SET PUSH, Z +SET PUSH, I +SET PUSH, J +SET PUSH, EX + +SET [int_msg], A + + +SET A, [proc_current] +MUL A, 4 +SUB A, 4 +ADD A, proc_table +ADD A, 1 +SET [A], SP + + +add a, 3 :proc_kill_me_hook - ADD A, 12 + :proc_suspend_loop IFE A, proc_table_end SET A, proc_table SET X, [A] IFN X, 0x0000 SET PC, proc_suspend_invoke - ADD A, 12 + ADD A, 4 SET PC, proc_suspend_loop :proc_suspend_invoke - ; Copy the process information to the registers - SET B, proc_buffer - JSR mem_copy - - ; DEBUG OUTPUT - SET A, 1 - SET B, 0 - SET C, 0x4000 - JSR kernel_interrupt_debug_clock_ticker - ; END DEBUG OUTPUT - - SET [proc_current], [proc_buffer] - SET A, [proc_buffer_a] - SET B, [proc_buffer_b] - SET C, [proc_buffer_c] - SET X, [proc_buffer_x] - SET Y, [proc_buffer_y] - SET Z, [proc_buffer_z] - SET I, [proc_buffer_i] - SET J, [proc_buffer_j] - SET SP, [proc_buffer_sp] - - IFN [preemptive_enabled], 0 - IAQ 0 - - SET PC, POP ; Jump into the Program - -:proc_suspend_param dat 0x0000 + + SET [proc_current], [A] + ADD A, 1 + SET SP, [A] + set EX, POP + set J, POP + set I, POP + set Z, POP + set Y, POP + set X, POP + set C, POP + set B, POP + + RFI A ; Jump into the Program + ; Loads a new process into memory ; A: Begin of the BLOB ; B: Length of the BLOB :proc_load - + IAQ 1 SET PUSH, B SET PUSH, C SET PUSH, X @@ -277,7 +248,7 @@ IFE [X], 0x0000 SET PC, proc_load_to - ADD X, 12 + ADD X, 4 IFN X, proc_table_end SET PC, proc_load_loop @@ -292,7 +263,7 @@ ; Calculate the ProcID by finding the proc_table record number (OS is 1). SET [X], X SUB [X], proc_table - DIV [X], 12 + DIV [X], 4 ADD [X], 1 ; X = ProcInfo Addr @@ -303,15 +274,15 @@ ; Finally load the Process - A is the source mem addr, B is length. SET C, B SET PUSH, A - - ; If we're loading from a built-in app, no need to allocate extra memory + + ; If we're loading from a built-in app, we only need to allocate a page for the stack IFN Z, 0x4714 SET B, A IFN Z, 0x4714 - SET PC, proc_load_skip_alloc + SET PC, proc_load_stack_alloc ; Pretend the routine has been called by this not-yet-loaded process, so we can allocate memory. - SET PUSH, [proc_current] + SET PUSH, [proc_current] SET [proc_current], [X] SET B, C @@ -332,7 +303,7 @@ IFE Z, 0x4714 SET C, J ; If we are an ABI exe set the size to just the code length JSR mem_copy -:proc_load_skip_alloc + SET A, POP ; Get the flags back. @@ -347,25 +318,11 @@ SUB Y, 1 ; Move back 1 ADD Y, B ; Offset by the memory start +:proc_load_stack_alloc_end + SET A, [X] ; A return the ProcID ; Fill the proc_table entry for this process. - ADD X, 1 ; A - SET [X], 0 - ADD X, 1 ; B - SET [X], 0 - ADD X, 1 ; C - SET [X], 0 - ADD X, 1 ; X - SET [X], 0 - ADD X, 1 ; Y - SET [X], 0 - ADD X, 1 ; Z - SET [X], 0 - ADD X, 1 ; I - SET [X], 0 - ADD X, 1 ; J - SET [X], 0 - + ; Set the SP to the last byte of the allocated memory page(s) ADD X, 1 ; SP SET [X], Y @@ -373,15 +330,26 @@ ; Store the memory address of the process. ADD X, 1 SET [X], B + + ; Store flags ADD X, 1 ; Flags BOR C, 0x0001 ; OR in the active flag. This will overwrite the ART flag but we don't care SET [X], C SET [Y], B ; "Push" the "return" address on the process stack - this is the beginning of the process program. + SUB X, 2 ; back to SP + SUB [X], 9 + SET PUSH, A ; clear new proccess stack area so we start with each register being 0 + SET A, Y + SUB A, 10 + SET B, 9 + JSR mem_clear + SET A, POP + :proc_load_end - ; Enable preemptive threading via interrupts now that we have a new process - SET [preemptive_enabled], 1 + ; add to number of processes + ADD [processes], 1 SET J, POP SET I, POP @@ -390,8 +358,33 @@ SET X, POP SET C, POP SET B, POP + IAQ 0 + INT [proc_suspend_int] SET PC, POP - + +:proc_load_stack_alloc + + ; Pretend the routine has been called by this not-yet-loaded process, so we can allocate memory. + SET PUSH, [proc_current] + SET [proc_current], [X] + JSR page_alloc + SET [proc_current], POP + + SET Y, A ; Save the address of the new page + SET A, PEEK ; Get back our original source address + ADD Y, 1024 + SUB Y, 1 + + SET A, POP + + ; Get the flags back. + SET C, POP + + ; Check if we have any flags to deal with + IFN C, 0 + JSR proc_handle_flags + + SET PC, proc_load_stack_alloc_end :proc_handle_flags SET PUSH, A @@ -451,7 +444,7 @@ SET X, A JSR proc_get_info_of ; Save process info address SET Y, A - ADD A, 10 ; Save memory page + ADD A, 2 ; Save memory page SET Z, [A] ADD A, 1 ; Move to the flags word @@ -461,14 +454,13 @@ JSR manage_charset SET A, Y ; Delete the process info entry - SET B, 12 + SET B, 4 JSR mem_clear SET A, X JSR page_free_of - + SUB [processes], 1 SET A, Y ; Restore the pointer to the info entry - SET C, 12 SET PC, proc_kill_me_hook :proc_kill @@ -479,16 +471,18 @@ JSR proc_get_info_of ; Save process info address SET Y, A - ADD A, 10 ; Save memory page + ADD A, 2 ; Save memory page SET Z, [A] SET A, Y ; Delete the process info entry - SET B, 12 + SET B, 4 JSR mem_clear SET A, POP ; Free the process memory page JSR page_free_of ; ! It will not be cleared ! + SUB [processes], 1 + SET Z, POP SET Y, POP SET B, POP From 2481785ffe2e6facb0ea8ec342de6ee01dd99531 Mon Sep 17 00:00:00 2001 From: bungao Date: Sun, 1 Jul 2012 22:28:29 +1000 Subject: [PATCH 02/13] Newline fix and text_out_length routine - Changed Newline Character to 0x000A as per ascii standard - text_out_length will output a string given by A but only up to B character in length --- apps/AtlasShell.dasm16 | 20 ++++++------- include/kernel.inc | 20 ++++++------- kernel/library.dasm16 | 68 ++++++++++++++++++++++++++++++++++++++++-- misc/vfs.dasm16 | 8 ++--- 4 files changed, 89 insertions(+), 27 deletions(-) diff --git a/apps/AtlasShell.dasm16 b/apps/AtlasShell.dasm16 index 641fbff..c9b0315 100644 --- a/apps/AtlasShell.dasm16 +++ b/apps/AtlasShell.dasm16 @@ -934,28 +934,28 @@ SET PC, POP ; Misc data -:text_versionoutput dat "Atlas-Shell v0.4.2", 0xA0, 0x00 +:text_versionoutput dat "Atlas-Shell v0.4.2", 0xA, 0x00 :text_prompt dat " $> ", 0x00 -:text_unrecognized dat "Unrecognized command", 0xA0, 0x00 +:text_unrecognized dat "Unrecognized command", 0xA, 0x00 :input_text_buffer dat " ", 0x00 :input_buffer dat 0x0000 :ack_command dat 0x00 :command_version_os dat "os", 0 :command_version_separator dat ".", 0 -:command_load_help dat "Syntax: load [appID]", 0xA0, 0x00 -:command_load_unknown dat "Failed to load application", 0xA0, 0x00 -:command_kill_forbidden dat "Cannot kill process: Forbidden", 0xA0, 0x00 -:command_kill_help dat "Syntax: kill [last|procID]", 0xA0, 0x00 +:command_load_help dat "Syntax: load [appID]", 0xA, 0x00 +:command_load_unknown dat "Failed to load application", 0xA, 0x00 +:command_kill_forbidden dat "Cannot kill process: Forbidden", 0xA, 0x00 +:command_kill_help dat "Syntax: kill [last|procID]", 0xA, 0x00 :command_kill_last dat "last", 0 -:command_list_info dat "Process list:", 0xA0, 0x00 +:command_list_info dat "Process list:", 0xA, 0x00 :command_parameter_buffer dat " ", 0x00 :command_number_buffer dat " ", 0x00 :command_ls_row dat " ", 0x00 :command_cd_back dat "..", 0 :command_cd_root dat "/", 0 -:command_cd_help dat "Syntax : cd [directory|..|/]", 0xA0, 0x00 -:command_cd_unknown dat " doesnt exist", 0xA0, 0 -:command_runfile_notexe_text dat "File is not executable", 0xA0, 0x00 +:command_cd_help dat "Syntax : cd [directory|..|/]", 0xA, 0x00 +:command_cd_unknown dat " doesnt exist", 0xA, 0 +:command_runfile_notexe_text dat "File is not executable", 0xA, 0x00 ; Command list :command_clear dat "clear", 0 diff --git a/include/kernel.inc b/include/kernel.inc index 3047c5a..5af9858 100644 --- a/include/kernel.inc +++ b/include/kernel.inc @@ -20,17 +20,17 @@ SET PC, data_end :preemptive_enabled dat 0x0000 :text_start dat "AtlasOS v0.6.2 starting... ", 0x00 -:text_start_ok dat "OK", 0xA0, 0x00 +:text_start_ok dat "OK", 0xA, 0x00 :text_logo -dat " ___ __ __", 0xA0 -dat " / | / /_ / /____ ______", 0xA0 -dat " / /| |/ __// // __ `/ ___/", 0xA0 -dat " / ___ / / / // /_/ (__ )", 0xA0 -dat " /_/ |_\\_/_/_/ \\__,_/____/", 0xA0 -dat " / __ \\/ ___/", 0xA0 -dat " / / / /\\__ \\", 0xA0 -dat " / /_/ /___/ /", 0xA0 -dat " \\____//____/", 0xA0, 0x00 +dat " ___ __ __", 0xA +dat " / | / /_ / /____ ______", 0xA +dat " / /| |/ __// // __ `/ ___/", 0xA +dat " / ___ / / / // /_/ (__ )", 0xA +dat " /_/ |_\\_/_/_/ \\__,_/____/", 0xA +dat " / __ \\/ ___/", 0xA +dat " / / / /\\__ \\", 0xA +dat " / /_/ /___/ /", 0xA +dat " \\____//____/", 0xA, 0x00 :text_logo_end ; Bitmap of the OS-managed memory, occupied pages are marked by 1's. ; Total of 64kB of memory supported here - each word covers 16kB. diff --git a/kernel/library.dasm16 b/kernel/library.dasm16 index 2e9f7d3..115296f 100644 --- a/kernel/library.dasm16 +++ b/kernel/library.dasm16 @@ -18,7 +18,7 @@ SET C, [A] IFE C, 0x0000 SET PC, text_out_end - IFE C, 0x00A0 + IFE C, 0xA SET PC, text_out_nl AND C, 0x00FF BOR C, B @@ -51,6 +51,69 @@ SET A, POP SET PC, POP +; prints a text to stdout with a length limitation +; A: start address of the text +; B: number of a characters +:text_out_length + SET PUSH, A + SET PUSH, B + SET PUSH, C + SET PUSH, X + SET PUSH, Y + SET PUSH, I + + SET Y, B + + SET B, [video_col] + SET I, [video_cur] + + SET X, [video_width] + MUL X, [video_height] + ADD X, [video_mem] + + +:text_out_length_loop + IFE Y, 1 + SET PC, text_out_length_end + SET C, [A] + IFE C, 0x0000 + SET PC, text_out_length_end + IFE C, 0xA + SET PC, text_out_length_nl + AND C, 0x00FF + BOR C, B + SET [I], C + ADD A, 1 + SUB Y, 1 + ADD I, 1 + IFE I, X + SET PC, text_out_length_scroll + SET PC, text_out_length_loop + +:text_out_length_scroll + SET [video_cur], I + JSR scroll + SET I, [video_cur] + SET PC, text_out_length_loop + +:text_out_length_nl + SET [video_cur], I + JSR newline + SET I, [video_cur] + ADD A, 1 + SUB Y, 1 + SET PC, text_out_length_loop + +:text_out_length_end + SET [video_cur], I + SET I, POP + SET Y, POP + SET X, POP + SET C, POP + SET B, POP + SET A, POP + SET PC, POP + ; Linefeed :newline SET PUSH, A @@ -388,8 +451,7 @@ SET PC, POP IFE [A], 0 SET PC, strlen_end ADD A, 1 - IFN [A], 0 - SET PC, strlen_loop + set PC, strlen_loop :strlen_end SET B, A SUB B, PEEK diff --git a/misc/vfs.dasm16 b/misc/vfs.dasm16 index 11e6843..017a32d 100644 --- a/misc/vfs.dasm16 +++ b/misc/vfs.dasm16 @@ -31,8 +31,8 @@ :file01_end :file06 - dat "Now some tests for output", 0xA0 - dat "to see how we handle things", 0xA0 + dat "Now some tests for output", 0xA + dat "to see how we handle things", 0xA dat "I hope it works", 0x00 :file06_end @@ -49,7 +49,7 @@ ; Code dat 0x7C01, 0x0008, 0x7820, 0x101E, 0x7820, 0x1002, 0x7820, 0x1005 ; Data - dat 0x0048, 0x0065, 0x006c, 0x006c, 0x006f, 0x0020, 0x0057, 0x006f, 0x0072, 0x006c, 0x0064, 0x00a0, 0x0000 + dat 0x0048, 0x0065, 0x006c, 0x006c, 0x006f, 0x0020, 0x0057, 0x006f, 0x0072, 0x006c, 0x0064, 0xA, 0x0000 :file02_end ; Free @@ -70,7 +70,7 @@ dat 0x0017, 0x7C01, 0x0027, 0x7820, 0x101E, 0x7820, 0x1005 ; Data (29 words) dat 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0077, 0x006f, 0x0072, 0x0064, 0x0073, 0x0020, 0x0066, 0x0072, 0x0065, 0x0065, 0x0020, 0x0028 - dat 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x004b, 0x0042, 0x0029, 0x00a0, 0x0000 + dat 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x004b, 0x0042, 0x0029, 0x00A, 0x0000 :file03_end :file04 From 869c1d3a13d30769205d10a422a817de0e898a86 Mon Sep 17 00:00:00 2001 From: bungao Date: Sun, 1 Jul 2012 22:29:49 +1000 Subject: [PATCH 03/13] AtlasText Enhancements - 1024 characters of wonderful editing space. --- apps/AtlasText.dasm16 | 203 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 3 deletions(-) diff --git a/apps/AtlasText.dasm16 b/apps/AtlasText.dasm16 index 51c406c..0d2a6d3 100644 --- a/apps/AtlasText.dasm16 +++ b/apps/AtlasText.dasm16 @@ -1,5 +1,6 @@ ; AtlasText - A simple, dummy text editor :AtlasText + IAQ 1 JSR [0x1021] ; clear SET I, AtlasText_loop_end ; Calculate the length of the back-jump @@ -10,23 +11,219 @@ ; And ask for exclusive keyboard access SET B, 1 JSR [0x1026] ; keyboard_register + + JSR [0x100f] ; page allocate for large string bufer + SET [AtlasText_page], A + + SET [AtlasText_input_buffer], 0 + + SET C, AtlasText_input_buffer + SET A, [AtlasText_page] + SET B, 1024 + SET PUSH, C + SET PUSH, B + SET PUSH, A + + JSR mem_clear ; Clear the buffer + + ADD B, A + + SET PUSH, A + SET A, AtlasText_intro + JSR text_out + SET A, POP + + IAQ 0 :AtlasText_loop + IFE [AtlasText_input_buffer], 0 + SET PC, AtlasText_skip + ; If we hit ESC kill the editor IFE [AtlasText_input_buffer], 0x001B SET PC, AtlasText_die - ; Just print the text to the screen - SET A, AtlasText_input_buffer - JSR [0x101E] ; text_out + IFE [C], 0x11 ; 13 -> 17 per keyboard HW (enter) + SET PC, AtlasText_return + IFE [C], 0x10 ; 8 -> 16 per keyboard HW (backspace) + SET PC, AtlasText_backspace + IFG 0x20, [C] + SET PC, AtlasText_skip + IFG [C], 0x7F + SET PC, AtlasText_skip + IFE A, B + SET PC, AtlasText_skip + + SET [A], [C] + + ; Put the character on-screen so the user can see what is being typed + ; Maybe have this toggleable? + SET PUSH, A + SET PUSH, B + SET B, [A] + BOR B, 0x7000 + SET A, B + SET B, [video_cur] + SET [B], A + ADD [video_cur], 1 + SET A, [video_width] + MUL A, [video_height] + ADD A, [video_mem] + IFE [video_cur], A + JSR scroll + SET B, POP + SET A, POP + SET [C], 0 + ADD A, 1 + +:AtlasText_skip + ; Display the blinking cursor + SET PUSH, A + SET PUSH, B + SET PUSH, C + SET A, [video_cur] + SUB A, [video_mem] + SET B, 0 + SET C, 0x709F + JSR char_put + SET C, POP + SET B, POP + SET A, POP + + + SET PC, AtlasText_loop + +:AtlasText_backspace + ; Remove the blinking cursor + SET PUSH, A + SET PUSH, B + SET PUSH, C + SET A, [video_cur] + SUB A, [video_mem] + SET B, 0 + SET C, [video_clear] + JSR char_put + SET C, POP + SET B, POP + SET A, POP + + ; Ensure we don't backspace past the beginning + IFE A, PEEK + SET PC, AtlasText_skip + SET PUSH, A + + SET A, [video_mem] + IFE [video_cur], A + JSR AtlasText_scrollback + + SET A, POP + SUB A, 1 + IFE [A], 0xA ; if last character was a new line move cursor back to last printed character + JSR AtlasText_backspace_newline + ADD A, 1 + + SET PUSH, A + SET PUSH, B + SUB [video_cur], 1 + SET B, [video_cur] + SET [B], 0 + SET B, POP + SET A, POP + SUB A, 1 + SET [A], 0 + SET [C], 0 + SET PC, AtlasText_skip + +:AtlasText_backspace_newline + SET PUSH, A + SET PUSH, B + SET B, 32 +:AtlasText_backspace_newline_loop + IFE B, 0 + SET PC, AtlasText_backspace_newline_loop_end + SET A, [video_cur] + SUB A, 1 + SET A, [A] + AND A, 0x7f + IFN A, 0x20 + SET PC, AtlasText_backspace_newline_loop_end + SUB [video_cur], 1 + SUB B, 1 + SET PC, AtlasText_backspace_newline_loop + +:AtlasText_backspace_newline_loop_end +ADD [video_cur], 1 +SET B, POP +SET A, POP + +SET PC, POP + +:AtlasText_scrollback +SET PUSH, PICK 1 ;get in text string and find either position of last newline or 32 characters back, what evers comes first +SET A, PEEK +SET PUSH, B +SET B, 32 +:AtlasText_scrollback_loop +IFE B, 0 + SET PC, AtlasText_scrollback_loop_end +IFE [A], 0xA +IFE [AtlasText_newlinefound], 1 +SET PC, AtlasText_scrollback_loop_end +IFE [A], 0xA +SET [AtlasText_newlinefound], 1 +SUB B, 1 +SUB A, 1 +IFE A, [AtlasText_page] +SET PC, AtlasText_scrollback_loop_end +SET PC, AtlasText_scrollback_loop + + +:AtlasText_scrollback_loop_end +SET [video_cur], [video_mem] +IFN [A+1], 0 +ADD A, 1 +JSR text_out +SET [AtlasText_newlinefound], 0 +SET B, POP +SET A, POP +SET [C], 0 +SET PC, POP + + +:AtlasText_return + ; Remove the blinking cursor + SET PUSH, A + SET PUSH, B + SET PUSH, C + SET A, [video_cur] + SUB A, [video_mem] + SET B, 0 + SET C, [video_clear] + JSR char_put + SET C, POP + SET B, POP + SET A, POP + SET [C], 0 + ; Add the newline symbol + SET [A], 0xA + ADD A, 1 + JSR [0x101f] ; newline + SET PC, AtlasText_skip + +:AtlasText_loop_skip JSR [0x1002] ; proc_suspend SUB PC, I :AtlasText_loop_end :AtlasText_die SET A, AtlasText_input_buffer + IAQ 1 JSR [0x1027] ; keyboard_unregister JSR [0x1021] ; clear + IAQ 0 JSR [0x1005] ; proc_kill_me :AtlasText_data :AtlasText_input_buffer dat 0x0000, 0x0000 + :AtlasText_page dat 0x0000 + :AtlasText_intro dat " AtlasText Version 0.1", 0xA, 0x0 + :AtlasText_newlinefound dat 0 :AtlasText_end From 28b18a74497881c54b4b4983bd33412f6fbebc3b Mon Sep 17 00:00:00 2001 From: bungao Date: Sun, 1 Jul 2012 23:57:24 +1000 Subject: [PATCH 04/13] Basic 32bit math library --- kernel/core.dasm16 | 1 + kernel/math.dasm16 | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 kernel/math.dasm16 diff --git a/kernel/core.dasm16 b/kernel/core.dasm16 index 15b7735..4f8d653 100644 --- a/kernel/core.dasm16 +++ b/kernel/core.dasm16 @@ -13,6 +13,7 @@ SET PC, kernel_boot #include "memory.dasm16" #include "messages.dasm16" #include "process.dasm16" +#include "math.dasm16" :kernel_boot JSR bios_boot diff --git a/kernel/math.dasm16 b/kernel/math.dasm16 new file mode 100644 index 0000000..750be29 --- /dev/null +++ b/kernel/math.dasm16 @@ -0,0 +1,50 @@ +:math_ABdivC +SET PUSH, Y +DIV A, C +SET Y, EX +DIV B, C +ADD B, Y +SET Y, POP +SET PC, POP + +:math_ABaddXY +ADD B, Y +ADD A, EX +ADD A, X +SET PC, POP + +:math_ABsubXY +SUB B, Y +SUB A, EX +SUB A, X +SET PC, POP + +:math_ABgXY ; sets c to 1 if (AB) is greater than (XY), otherwise C = 0 +IFL A, X +SET pc, math_false + +IFG A, X +set PC, math_true + +IFE B, Y +SET PC, math_false + +IFL B, Y +SET PC, math_false +SET PC, math_true + +:math_true +SET C, 1 +SET PC, POP + +:math_false +SET C, 0 +SET PC, POP + +:math_ABeXY +IFE A, X +IFE B, Y +SET PC, math_true +SET PC, math_false + + From 7ef3c274bce0b59749a8f9030d78817fc392b307 Mon Sep 17 00:00:00 2001 From: bungao Date: Mon, 2 Jul 2012 16:38:29 +1000 Subject: [PATCH 05/13] New build organisation - uses a make file that contains no code - allows for the use of an included 0x10c devkit solution - updated Organic --- Organic.exe | Bin 57344 -> 63488 bytes atlas.10cproj | 31 +++++++++++++++++++++++++++++++ atlas.10csln | 11 +++++++++++ atlas.10csuo | 4 ++++ build.bat | 2 +- build.sh | 2 +- build_disassemble.bat | 2 +- build_disassemble.sh | 2 +- build_output_listing.bat | 2 +- build_output_listing.sh | 2 +- build_upload.bat | 2 +- build_upload.sh | 2 +- include/kernel.inc | 1 + kernel/core.dasm16 | 29 +---------------------------- make.dasm16 | 22 ++++++++++++++++++++++ misc/vfs.dasm16 | 2 ++ 16 files changed, 80 insertions(+), 36 deletions(-) create mode 100644 atlas.10cproj create mode 100644 atlas.10csln create mode 100644 atlas.10csuo create mode 100644 make.dasm16 diff --git a/Organic.exe b/Organic.exe index 582a48c4e7ad35020d0a1b5b235dd21c6081888b..c8c154990c24104a3e371a31be0f37e5a1260b14 100644 GIT binary patch literal 63488 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 literal 57344 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 + + atlas + + true + atlas.bin + false + atlas.hex + false + + + + + DevKit 10c Assembly File + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/atlas.10csln b/atlas.10csln new file mode 100644 index 0000000..936cd12 --- /dev/null +++ b/atlas.10csln @@ -0,0 +1,11 @@ + + + atlas + + atlas + project + + + + + \ No newline at end of file diff --git a/atlas.10csuo b/atlas.10csuo new file mode 100644 index 0000000..e30300d --- /dev/null +++ b/atlas.10csuo @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/build.bat b/build.bat index 66036d0..56250d7 100644 --- a/build.bat +++ b/build.bat @@ -1,2 +1,2 @@ -@organic --working-directory kernel/ --input-file kernel/core.dasm16 --output-file AtlasOS.bin +@organic --input-file make.dasm16 --output-file AtlasOS.bin @pause \ No newline at end of file diff --git a/build.sh b/build.sh index 890bdee..2046f8b 100644 --- a/build.sh +++ b/build.sh @@ -1,2 +1,2 @@ #!/bin/sh -mono organic.exe --working-directory kernel/ --input-file kernel/core.dasm16 --output-file AtlasOS.bin \ No newline at end of file +mono organic.exe --input-file make.dasm16 --output-file AtlasOS.bin \ No newline at end of file diff --git a/build_disassemble.bat b/build_disassemble.bat index 1584c42..70be168 100644 --- a/build_disassemble.bat +++ b/build_disassemble.bat @@ -1,3 +1,3 @@ -@organic --working-directory kernel/ --input-file kernel/core.dasm16 --output-file AtlasOS.bin +@organic --input-file make.dasm16 --output-file AtlasOS.bin @java -jar utilities\bin2asmbin\bin2asmbin.jar AtlasOS.bin AtlasOS_D.dasm16 -l @pause \ No newline at end of file diff --git a/build_disassemble.sh b/build_disassemble.sh index e607399..b8f90f9 100644 --- a/build_disassemble.sh +++ b/build_disassemble.sh @@ -1,4 +1,4 @@ #!/bin/sh -mono organic.exe --working-directory kernel/ --input-file kernel/core.dasm16 --output-file AtlasOS.bin +mono organic.exe --input-file make.dasm16 --output-file AtlasOS.bin java -jar utilities/bin2asmbin/bin2asmbin.jar AtlasOS.bin AtlasOS_D.dasm16 -l \ No newline at end of file diff --git a/build_output_listing.bat b/build_output_listing.bat index 982b54d..ae04e71 100644 --- a/build_output_listing.bat +++ b/build_output_listing.bat @@ -1,2 +1,2 @@ -@organic --working-directory kernel/ --input-file kernel/core.dasm16 --output-file AtlasOS.bin --listing Atlas_listing.txt +@organic --input-file make.dasm16 --output-file AtlasOS.bin --listing Atlas_listing.txt @pause \ No newline at end of file diff --git a/build_output_listing.sh b/build_output_listing.sh index a24515f..abcac0a 100644 --- a/build_output_listing.sh +++ b/build_output_listing.sh @@ -1,3 +1,3 @@ #!/bin/sh -mono organic.exe --working-directory kernel/ --input-file kernel/core.dasm16 --output-file AtlasOS.bin --listing Atlas_listing.txt \ No newline at end of file +mono organic.exe --input-file make.dasm16 --output-file AtlasOS.bin --listing Atlas_listing.txt \ No newline at end of file diff --git a/build_upload.bat b/build_upload.bat index bc31238..904a926 100644 --- a/build_upload.bat +++ b/build_upload.bat @@ -1,2 +1,2 @@ -@organic --working-directory kernel/ --input-file kernel/core.dasm16 --output-file AtlasOS.bin --0x10co.de +@organic --input-file make.dasm16 --output-file AtlasOS.bin --0x10co.de @pause \ No newline at end of file diff --git a/build_upload.sh b/build_upload.sh index e042569..0dcbf6c 100644 --- a/build_upload.sh +++ b/build_upload.sh @@ -1,3 +1,3 @@ #!/bin/sh -mono Organic.exe --working-directory kernel/ --input-file kernel/core.dasm16 --output-file AtlasOS.bin --0x10co.de +mono Organic.exe --input-file make.dasm16 --output-file AtlasOS.bin --0x10co.de diff --git a/include/kernel.inc b/include/kernel.inc index 5af9858..dce0aa6 100644 --- a/include/kernel.inc +++ b/include/kernel.inc @@ -1,3 +1,4 @@ +SET PC, kernel_boot :data SET PC, data_end diff --git a/kernel/core.dasm16 b/kernel/core.dasm16 index 4f8d653..85282f1 100644 --- a/kernel/core.dasm16 +++ b/kernel/core.dasm16 @@ -1,24 +1,8 @@ -#include "AtlasOS 0.6.2" - -#include "../include/kernel.inc" - -SET PC, kernel_boot - ; Kernel -#include "drivers.dasm16" -#include "filesystem.dasm16" -#include "graphics.dasm16" -#include "interrupts.dasm16" -#include "library.dasm16" -#include "memory.dasm16" -#include "messages.dasm16" -#include "process.dasm16" -#include "math.dasm16" :kernel_boot JSR bios_boot - ; clear screen (for emulator) JSR clear @@ -112,15 +96,4 @@ dat " dat " " dat " " dat " " -:api_padding_end - -; Apps -:os_content -#include "../apps/AtlasShell.dasm16" -#include "../apps/AtlasText.dasm16" -#include "../apps/apps.dasm16" - -; Virtual Filesystem -#include "../misc/vfs.dasm16" -:os_content_end - \ No newline at end of file +:api_padding_end \ No newline at end of file diff --git a/make.dasm16 b/make.dasm16 new file mode 100644 index 0000000..ec91991 --- /dev/null +++ b/make.dasm16 @@ -0,0 +1,22 @@ +; Kernel +.longform +.include "include/kernel.inc" +.include "kernel/drivers.dasm16" +.include "kernel/filesystem.dasm16" +.include "kernel/graphics.dasm16" +.include "kernel/interrupts.dasm16" +.include "kernel/library.dasm16" +.include "kernel/memory.dasm16" +.include "kernel/messages.dasm16" +.include "kernel/process.dasm16" +.include "kernel/core.dasm16" +.include "kernel/math.dasm16" + + +; Apps +.include "apps/AtlasShell.dasm16" +.include "apps/AtlasText.dasm16" +.include "apps/apps.dasm16" + +; Virtual Filesystem +.include "misc/vfs.dasm16" diff --git a/misc/vfs.dasm16 b/misc/vfs.dasm16 index 017a32d..7032eff 100644 --- a/misc/vfs.dasm16 +++ b/misc/vfs.dasm16 @@ -99,3 +99,5 @@ :file05_end :files_end + +:os_content_end \ No newline at end of file From 464b5231821a6959c252a4b6c1f6cc170d26b02f Mon Sep 17 00:00:00 2001 From: bungao Date: Mon, 2 Jul 2012 16:38:56 +1000 Subject: [PATCH 06/13] Help command - displays a list of available shell commands --- apps/AtlasShell.dasm16 | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/apps/AtlasShell.dasm16 b/apps/AtlasShell.dasm16 index c9b0315..ae195b2 100644 --- a/apps/AtlasShell.dasm16 +++ b/apps/AtlasShell.dasm16 @@ -112,6 +112,13 @@ JSR [0x101A] IFE C, 0 JSR command_echof + + ; Check for the 'help' command + SET A, command_help + SET B, command_parameter_buffer + JSR [0x101A] + IFE C, 0 + JSR command_helpf ; Check if we're trying to run a file IFN [ack_command], 1 @@ -812,6 +819,16 @@ SET B, POP SET A, POP SET PC, POP + +:command_helpf + SET [ack_command], 1 + SET PUSH, A + SET A, command_help_list + JSR [0x101E] + + SET A, POP + SET PC, POP + :AtlasShell_die SET A, input_buffer @@ -936,7 +953,7 @@ ; Misc data :text_versionoutput dat "Atlas-Shell v0.4.2", 0xA, 0x00 :text_prompt dat " $> ", 0x00 -:text_unrecognized dat "Unrecognized command", 0xA, 0x00 +:text_unrecognized dat "Unrecognized command", 0x00 :input_text_buffer dat " ", 0x00 :input_buffer dat 0x0000 :ack_command dat 0x00 @@ -956,6 +973,7 @@ :command_cd_help dat "Syntax : cd [directory|..|/]", 0xA, 0x00 :command_cd_unknown dat " doesnt exist", 0xA, 0 :command_runfile_notexe_text dat "File is not executable", 0xA, 0x00 +:command_help_list dat "Available commands:", 0xA, "For command syntax and usage:", 0xA, "[command] help", 0xA, "clear", 0xa, "version", 0xA, "load", 0xa, "kill", 0xA, "list", 0xA, "ls", 0xA, "cd", 0xA, "cat", 0xA, "echo", 0xA, 0x0 ; Command list :command_clear dat "clear", 0 @@ -972,6 +990,8 @@ :command_ln dat "ln", 0 ; UNFINISHED :command_mv dat "mv", 0 ; UNFINISHED :command_echo dat "echo", 0 +:command_help dat "help", 0 + ; Process list buffer. Used for the 'kill' command :proc_list_buffer From 99f2e1f60e63528ed79c106cace6a99ed42f745e Mon Sep 17 00:00:00 2001 From: bungao Date: Tue, 3 Jul 2012 13:28:54 +1000 Subject: [PATCH 07/13] gui box drawing routine --- kernel/library.dasm16 | 100 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/kernel/library.dasm16 b/kernel/library.dasm16 index 115296f..ec0c4bc 100644 --- a/kernel/library.dasm16 +++ b/kernel/library.dasm16 @@ -600,4 +600,102 @@ SET PC, POP XOR A, 1273 SET [entropy], A SET PC, POP - \ No newline at end of file + +; draws a box limited to 32x12 resolution using default box charaters +; A, B -> coordinates of first corner +; X, Y -> coordinates of second corner ie on a diagonal +; Z-> colour +:gui_box +IFG A, 0x1f +SET PC, POP +IFG B, 0xB +SET PC, POP +IFG X, 0x1f +SET PC, POP +IFG Y, 0xB +SET PC, POP +IFE A, X +SET PC, POP +IFE B, Y +SET PC, POP + +jsr pusha + +IFG A, X +SET PC, gui_box_l1 +SET [gui_box_corners], A +SET [gui_box_corners+2], X +SET PC, gui_box_l2 + +:gui_box_l1 +SET [gui_box_corners], X +SET [gui_box_corners+2], A +:gui_box_l2 +IFG B, Y +SET PC, gui_box_l3 +SET [gui_box_corners+1], B +SET [gui_box_corners+3], Y +SET PC, gui_box_l4 +:gui_box_l3 +SET [gui_box_corners+1], Y +SET [gui_box_corners+3], B +:gui_box_l4 + +SET A, [gui_box_corners] +SET B, [gui_box_corners+1] +SET C, 0x9 +BOR C, Z +jsr char_put + +ADD A, 1 +SET C, 0x7 +BOR C, Z +:gui_box_l5 +jsr char_put +ADD A, 1 +IFN A, [gui_box_corners+2] +SET PC, gui_box_l5 + +SET C, 0xA +BOR C, Z +jsr char_put + +ADD B, 1 +SET C, 0x8 +BOR C, Z +:gui_box_l6 +jsr char_put +ADD B, 1 +IFN B, [gui_box_corners+3] +SET PC, gui_box_l6 + +SET C, 0xB +BOR C, Z +jsr char_put + +SUB A, 1 +SET C, 0x7 +BOR C, Z +:gui_box_l7 +jsr char_put +SUB A, 1 +IFN A, [gui_box_corners] +SET PC, gui_box_l7 + +SET C, 0xC +BOR C, Z +JSR char_put +SUB B, 1 +SET C, 0x8 +BOR C, Z +:gui_box_l8 +jsr char_put +SUB B, 1 +IFN B, [gui_box_corners+1] +SET PC, gui_box_l8 + +jsr popa +SET PC, POP + +:gui_box_corners +dat 0,0 , 0,0 \ No newline at end of file From bcfe51c68ecd0bc8bfe5eca9c084f1b3e3455bf4 Mon Sep 17 00:00:00 2001 From: bungao Date: Tue, 3 Jul 2012 14:05:49 +1000 Subject: [PATCH 08/13] Introducing my long awaited HAT filesystem driver. You can test it out using AtlasText which can save to a file. Included is a binary of my BIEF (Binary Image Exchange Format) disk converter. This allows a user to convert a 0x10c devkit disk file into 1.44mb binary image capable of being viewed in a suitable hex viewer. *Note needs the HMD 2043 media device to function* --- apps/AtlasText.dasm16 | 54 +- atlas.10cproj | 1 + biefconverter.exe | Bin 0 -> 11264 bytes disk.bat | 1 + kernel/HAT_driver.dasm16 | 1468 ++++++++++++++++++++++++++++++++++++++ kernel/core.dasm16 | 4 + kernel/drivers.dasm16 | 6 +- kernel/filesystem.dasm16 | 102 ++- kernel/library.dasm16 | 83 ++- 9 files changed, 1711 insertions(+), 8 deletions(-) create mode 100644 biefconverter.exe create mode 100644 disk.bat create mode 100644 kernel/HAT_driver.dasm16 diff --git a/apps/AtlasText.dasm16 b/apps/AtlasText.dasm16 index 0d2a6d3..5f6ee96 100644 --- a/apps/AtlasText.dasm16 +++ b/apps/AtlasText.dasm16 @@ -1,7 +1,6 @@ ; AtlasText - A simple, dummy text editor :AtlasText IAQ 1 - JSR [0x1021] ; clear SET I, AtlasText_loop_end ; Calculate the length of the back-jump SUB I, AtlasText_loop @@ -27,13 +26,38 @@ JSR mem_clear ; Clear the buffer ADD B, A - + IAQ 0 SET PUSH, A + SET PUSH, B + SET PUSH, C + +:AtlasText_getfilename + JSR [0x1021] ; clear + SET A, AtlasText_intro JSR text_out + + SET A, AtlasText_filename_buffer + SET B, 16 + JSR mem_clear + + SET A, AtlasText_filename + JSR text_out + + SET A, AtlasText_filename_buffer + SET B, 15 + SET C, AtlasText_input_buffer + JSR [0x1023] ; readline + + SET A, AtlasText_filename_buffer + JSR [0x1019] ; strlen + IFE B, 0 + SET PC, AtlasText_getfilename ; loopback on blank filename + JSR [0x1021] ; clear + SET C, POP + SET B, POP SET A, POP - IAQ 0 :AtlasText_loop IFE [AtlasText_input_buffer], 0 SET PC, AtlasText_skip @@ -46,6 +70,8 @@ SET PC, AtlasText_return IFE [C], 0x10 ; 8 -> 16 per keyboard HW (backspace) SET PC, AtlasText_backspace + IFE [C], 0x13 ; delete key for save, since control doesn't work in devkit at the moment. + SET PC, AtlasText_save IFG 0x20, [C] SET PC, AtlasText_skip IFG [C], 0x7F @@ -214,6 +240,24 @@ SET PC, POP JSR [0x1002] ; proc_suspend SUB PC, I :AtlasText_loop_end + +:AtlasText_save + SET C, A + SET A, 0 + SET B, [AtlasText_page] + SET X, AtlasText_filename_buffer + JSR HAT_inode_directory_add_file + JSR [0x1021] ; clear + SET A, AtlasText_saved + jsr text_out + SET A, AtlasText_filename_buffer + JSR text_out + + SET A, AtlasText_exit + SET B, AtlasText_die + SET C, AtlasText_input_buffer + JSR pakto + :AtlasText_die SET A, AtlasText_input_buffer IAQ 1 @@ -226,4 +270,8 @@ SET PC, POP :AtlasText_page dat 0x0000 :AtlasText_intro dat " AtlasText Version 0.1", 0xA, 0x0 :AtlasText_newlinefound dat 0 + :AtlasText_filename_buffer dat "123456789abcedf", 0 + :AtlasText_filename dat "Filename:", 0 + :AtlasText_saved dat "File saved to: ", 0 + :AtlasText_exit dat "exit.", 0 :AtlasText_end diff --git a/atlas.10cproj b/atlas.10cproj index 7fdafa8..0f9ab00 100644 --- a/atlas.10cproj +++ b/atlas.10cproj @@ -23,6 +23,7 @@ + diff --git a/biefconverter.exe b/biefconverter.exe new file mode 100644 index 0000000000000000000000000000000000000000..28e19ef8a7e2d19344d6fd62d46464cbe5f88785 GIT binary patch literal 11264 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 A-v9sr literal 0 HcmV?d00001 diff --git a/disk.bat b/disk.bat new file mode 100644 index 0000000..2cea37d --- /dev/null +++ b/disk.bat @@ -0,0 +1 @@ +biefconverter test.10cdisk test.txt \ No newline at end of file diff --git a/kernel/HAT_driver.dasm16 b/kernel/HAT_driver.dasm16 new file mode 100644 index 0000000..35caaa7 --- /dev/null +++ b/kernel/HAT_driver.dasm16 @@ -0,0 +1,1468 @@ +;MIT Open License +; +;Copyright (c) 2012 Russell Oliver + +;Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +;The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +;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 OR COPYRIGHT HOLDERS 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. +; +; + +:HAT_driver_start +; reads first 6 sectors of floppy disk, and updates current media info +:HAT_read_header +SET PUSH, A +SET PUSH, B +SET PUSH, I +SET PUSH, J + +SET [HAT_header_in_paging], 1 + +SET A, 0 +SET B, 6 +JSR filesystem_read_disk_sectors +SET I, [floppy_paging_address] +SET J, HAT_header +STI [J], [I] +STI [J], [I] +STI [J], [I] +STI [J], [I] +STI [J], [I] +STI [J], [I] +STI [J], [I] +STI [J], [I] +STI [J], [I] +STI [J], [I] +SET J, POP +SET I, POP +SET B, POP +SET A, POP +SET PC, POP + +;Writes first 6 sectors of floppy disk +:HAT_write_header +SET PUSH, A +SET PUSH, B + + + +SET A, 0 +SET B, 6 +JSR filesystem_write_disk_sectors +SET [HAT_header_in_paging], 0 +SET B, POP +SET A, POP +SET PC, POP + +;copies a disk header to floppy and sets floppy up as empty +;with a 256 sector size +:HAT_format_disk_256 + +JSR filesystem_clear_floppy_paging + +SET PUSH, A +SET PUSH, B +SET PUSH, C + +SET A, HAT_header_256 +SET B, [floppy_paging_address] +SET C, 10 +JSR mem_copy + +SET A, [floppy_paging_address] +ADD A, [HAT_header_256 + 10] +SET [A], [HAT_header_256 + 11] + +JSR HAT_write_header +SET A, HAT_header_256 +SET B, HAT_header +SET C, 10 +JSR mem_copy + +SET C, POP +SET B, POP +SET A, POP +SET PC, POP + +;copies a disk header to floppy and sets floppy up as empty +;with a 1024 sector size +:HAT_format_disk_1024 + +JSR filesystem_clear_floppy_paging + +SET PUSH, A +SET PUSH, B +SET PUSH, C + +SET A, HAT_header_1024 +SET B, [floppy_paging_address] +SET C, 10 +JSR mem_copy + +SET A, [floppy_paging_address] +ADD A, [HAT_header_1024+10] +SET [A], [HAT_header_1024+11] + +JSR HAT_write_header +SET A, HAT_header_1024 +SET B, HAT_header +SET C, 10 +JSR mem_copy + +SET C, POP +SET B, POP +SET A, POP +SET PC, POP + +; Finds a free sector and returns ID to A, or 0xFFFF to A if none +:HAT_find_free_sector +SET PUSH, B +SET PUSH, I + +IFE [HAT_header_in_paging], 0 +JSR HAT_read_header + +SET A, [floppy_paging_address] +ADD A, 9 +SET [HAT_sectors_used], [A] + +IFE [HAT_num_sectors], [HAT_sectors_used] + SET PC, HAT_find_free_sector_none + +IFN [HAT_sector_map_start], 0 + SET PC, HAT_error + +SET A, [floppy_paging_address] +ADD A, [HAT_sector_map_start+1] +SET B, 0 +SET I, [HAT_num_sectors] + +:HAT_find_free_sector_loop +IFN [A], 0xFFFF + SET PC, HAT_find_free_sector_found +ADD A, 1 +ADD B, 1 +SUB I, 1 +IFE I, 0 + SET PC, HAT_find_free_sector_none +SET PC, HAT_find_free_sector_loop + +:HAT_find_free_sector_found +SET PUSH, [A] +MUL B, 16 +SET A, B + +:HAT_find_free_sector_found_loop + SHL PEEK, 1 + IFN EX, 0x0000 + SET PC, HAT_find_free_sector_skip + + ADD SP, 1 + SET PC, HAT_find_free_sector_end + +:HAT_find_free_sector_skip + ADD A, 1 + SET PC, HAT_find_free_sector_found_loop + +:HAT_find_free_sector_none + SET A, 0xFFFF + SET I, POP + SET B, POP + SET PC, POP + +:HAT_find_free_sector_end + SET I, POP + SET B, POP + SET PC, POP + +;Allocates a sector given by A +:HAT_allocate_sector +SET PUSH, C +SET PUSH, B +SET PUSH, A +SET B, A + + +IFE [HAT_num_sectors], [HAT_sectors_used] + SET PC, HAT_error + +IFN [HAT_sector_map_start], 0 + SET PC, HAT_error + +IFE [HAT_header_in_paging], 0 +JSR HAT_read_header +ADD [HAT_header_in_paging], 1 + +SET A, [HAT_sector_map_start+1] +ADD A, [floppy_paging_address] +DIV B, 16 +ADD A, B +SET B, PEEK +MOD B, 16 ; position of bit in word +SET C, 0x8000 +SHR C, B + +BOR [A], C +ADD [HAT_sectors_used], 1 + +SUB [HAT_header_in_paging], 1 +IFE [HAT_header_in_paging], 1 +JSR HAT_write_header + +SET A, POP +SET B, POP +SET C, POP +SET PC, POP + +;Deallocates a sector given by A +:HAT_deallocate_sector +SET PUSH, C +SET PUSH, B +SET PUSH, A +SET B, A + + +IFE [HAT_num_sectors], [HAT_sectors_used] + SET PC, HAT_error + +IFN [HAT_sector_map_start], 0 + SET PC, HAT_error + +IFE [HAT_header_in_paging], 0 +JSR HAT_read_header +ADD [HAT_header_in_paging], 1 + +SET A, [HAT_sector_map_start+1] +ADD A, [floppy_paging_address] +DIV B, 16 +ADD A, B +SET B, PEEK +MOD B, 16 ; position of bit in word +SET C, 0x8000 +SHR C, B +XOR C, 0xffff + +AND [A], C +SUB [HAT_sectors_used], 1 + +SUB [HAT_header_in_paging], 1 +IFE [HAT_header_in_paging], 1 +JSR HAT_write_header + +SET A, POP +SET B, POP +SET C, POP +SET PC, POP + +; A -> Current sector +; A <- next sector +:HAT_find_next_sector + +IFE [HAT_header_in_paging], 0 +JSR HAT_read_header + +IFN [HAT_sector_joins_start], 0 + SET PC, HAT_error + +ADD A, [HAT_sector_joins_start+1] +ADD A, [floppy_paging_address] +SET A, [A] +SET PC, POP + +;joins 2 sectors +; A -> first sector joins to second sector +; B - > second sector +:HAT_join_sectors +SET PUSH, B +SET PUSH, A + + + +IFN [HAT_sector_joins_start], 0 + SET PC, HAT_error + +IFE [HAT_header_in_paging], 0 +JSR HAT_read_header +ADD [HAT_header_in_paging], 1 + +SET A, [HAT_sector_joins_start+1] +ADD A, [floppy_paging_address] +ADD A, PEEK +SET [A], B + +SUB [HAT_header_in_paging], 1 +IFE [HAT_header_in_paging], 1 +JSR HAT_write_header + +SET A, POP +SET B, POP +SET PC, POP + +; clears the floppy paging space +;currently located in Atlas before the +:filesystem_clear_floppy_paging +SET PUSH, A +SET PUSH, B + +SET A, [floppy_paging_address] +SET B, 0xD00 +JSR mem_clear + +SET B, POP +SET A, POP +SET PC, POP + + +:HAT_error +;todo +SUB PC, 1 + +; Removes joins in a strip of sectors +; A -> starting sector +:HAT_delete_strip +SET PUSH, B +SET B, A + + +IFN [HAT_sector_joins_start], 0 + SET PC, HAT_error + +IFE [HAT_header_in_paging], 0 +JSR HAT_read_header +ADD [HAT_header_in_paging], 1 + + +:HAT_delete_strip_loop +SET A, B +JSR HAT_deallocate_sector +ADD A, [HAT_sector_joins_start+1] +ADD A, [floppy_paging_address] + +IFE [A], 0x0000 + SET PC, HAT_delete_strip_end + +SET B, [A] +SET [A], 0x0000 +SET PC, HAT_delete_strip_loop + +:HAT_delete_strip_end + +SUB [HAT_header_in_paging], 1 +IFE [HAT_header_in_paging], 1 +JSR HAT_write_header + +SET B, POP +SET PC, POP + +; finds the end of a strip +; A -> starting sector or any sector in the strip +; A <- end sector +:HAT_find_strip_end +SET PUSH, B +SET PUSH, A + + + +IFN [HAT_sector_joins_start], 0 + SET PC, HAT_error + +IFE [HAT_header_in_paging], 0 +JSR HAT_read_header + +SET B, POP +:HAT_find_strip_end_loop +SET A, B +ADD A, [HAT_sector_joins_start+1] +ADD A, [floppy_paging_address] + +IFE [A], 0x0000 + SET PC, HAT_find_strip_end_end + +SET B, [A] +SET PC, HAT_find_strip_end_loop + +:HAT_find_strip_end_end +SET A, B +SET B, POP +SET PC, POP + +;adds a number of sectors to a strip defined by a sector of that strip +; A -> sector of strip +; B -> number of sectors to add +:HAT_strip_add_sectors +IFE B, 0 +SET PC, POP +SET PUSH, I +SET PUSH, A +SET PUSH, B + +JSR HAT_find_strip_end +SET PUSH, A ; store end sector + +SET I, B + +IFE [HAT_header_in_paging], 0 +JSR HAT_read_header +ADD [HAT_header_in_paging], 1 + +:HAT_strip_add_sectors_loop +JSR HAT_find_free_sector +IFE A, 0xFFFF +SET PC, HAT_error +JSR HAT_allocate_sector +SET B, A ; set B to free sector +SET A, POP ; set A to end sector +JSR HAT_join_sectors ; join sector A to B +SET PUSH, B ; store new end sector + +SUB I, 1 +IFE I, 0 + SET PC, HAT_strip_add_sectors_end +SET PC, HAT_strip_add_sectors_loop + +:HAT_strip_add_sectors_end +SUB [HAT_header_in_paging], 1 +IFE [HAT_header_in_paging], 1 +JSR HAT_write_header + +ADD SP, 1 +SET B, POP +SET A, POP +SET I, POP +SET PC, POP + +;reads a HAT sector (as opposed to a disk sector) +; A -> sector to be read +; B -> start of memory location to read to, if 0 it will be left in the paging space +; C -> length of data +; X -> offset in sector to start reading from +:HAT_read_sector +SET PUSH, Y +SET PUSH, X +SET PUSH, C +SET PUSH, A +SET PUSH, B + +JSR HAT_sector_position + + +SET B, [HAT_sector_size] +DIV B, [floppy_words_per_sector] +IFE B, 0 + ADD B, 1 ; number of sectors to read, atleast 1 +JSR filesystem_read_disk_sectors + +JSR HAT_sector_offset + +ADD A, [floppy_paging_address] +SET B, POP +IFE B, 0 +SET PC, HAT_read_sector_skip +SET Y, C +ADD Y, X +IFG Y, [HAT_sector_size] +SET PC, HAT_read_sector_l1 +:HAT_read_sector_l2 +IFG C, [HAT_sector_size] + SET C, [HAT_sector_size] +SET C, [HAT_sector_size] +JSR mem_copy + +:HAT_read_sector_skip +SET [HAT_header_in_paging], 0 +SET A, POP +SET C, POP +SET X, POP +SET Y, POP +SET PC, POP + +:HAT_read_sector_l1 +MOD Y, [HAT_sector_size] +SUB C, Y +SET PC, HAT_read_sector_l2 + +;writes a HAT sector direct from memory +;use for small writes +; if the data length is less than than the HAT sector size it will first read sector, then copies data into the paging space at the offset determined by X, then writes it back out, leaving the rest of the disk sector untouched. +; if it is equal it will just write to the sector. +; In specifying the offset in the sector to write to, this subroutine will limit the length of the data copied to the size of the sector, ie won't go past the end. + + +; A -> sector to be writen +; B -> start of location in memory to write from, if 0 it will assume data for whole HAT sector is already in the floppy paging space and properly alligned, also ignores C, X +; C -> length of data +; X -> offset in sector to start writing + +:HAT_write_sector +IFG C, [HAT_sector_size] + SET PC, HAT_write_sectors +SET PUSH, A +SET PUSH, B +SET PUSH, C +SET PUSH, Y +SET PUSH, X + +JSR HAT_sector_position +SET X, A + +IFG [HAT_sector_size], [floppy_words_per_sector] +IFE B, 0 +SET PC, HAT_write_sector_read_skip +IFE B, 0 +SET PC, HAT_write_sector_read_skip + + +SET B, [HAT_sector_size] +DIV B, [floppy_words_per_sector] +IFE B, 0 + ADD B, 1 ; number of sectors to read, atleast 1 +JSR filesystem_read_disk_sectors + +:HAT_write_sector_read_skip +SET [HAT_header_in_paging], 0 + +SET A, PICK 4 ; hat sector that has been read +JSR HAT_sector_offset + +ADD A, [floppy_paging_address] ; +SET B, A ; destination +ADD B, PEEK +SET A, PICK 3 ; source +IFE A, 0 + SET PC, HAT_write_sector_copy_skip +SET C, PICK 2 ; C back to original C ie length +SET Y, C +ADD Y, PEEK +IFG Y, [HAT_sector_size] +SET PC, HAT_write_sector_l1 +:HAT_write_sector_l2 +IFG C, [HAT_sector_size] + SET C, [HAT_sector_size] +JSR mem_copy + +:HAT_write_sector_copy_skip +SET A, X +SET B, [HAT_sector_size] +DIV B, [floppy_words_per_sector] +IFE B, 0 + ADD B, 1 ; number of sectors to read, atleast 1 +JSR filesystem_write_disk_sectors + + +SET X, POP +SET Y, POP +SET C, POP +SET B, POP +SET A, POP +SET PC, POP + +:HAT_write_sector_l1 +MOD Y, [HAT_sector_size] +SUB C, Y +SET PC, HAT_write_sector_l2 + +; for writing large blocks or data +; A -> start sector +; B -> start of location in memory to write from +; C -> length of data in words +; X -> offset in first sector +; will handle the allocation and joining of needed extra sectors, assuming starting sector is already allocated +:HAT_write_sectors +IFE C, [HAT_sector_size] + SET PC, HAT_write_sector +IFL C, [HAT_sector_size] + SET PC, HAT_write_sector + +SET PUSH, X +SET PUSH, A +SET PUSH, B +SET PUSH, C +SET PUSH, Y + + +SET B, C +ADD B, X +DIV B, [HAT_sector_size] +MOD C, [HAT_sector_size] +IFE C, 0 +SUB B, 1 + +JSR HAT_strip_add_sectors + +SET A, PICK 3 +SET B, PICK 2 +SET Y, PICK 1 + +:HAT_write_sectors_loop +IFE Y, [HAT_sector_size] + SET PC, HAT_write_sectors_last +IFL Y, [HAT_sector_size] + SET PC, HAT_write_sectors_last + +SET C, [HAT_sector_size] +JSR HAT_write_sector +JSR HAT_find_next_sector +ADD B, [HAT_sector_size] +SUB Y, [HAT_sector_size] +SET X, 0 + +IFE Y, 0 + SET PC, HAT_write_sectors_end +SET PC, HAT_write_sectors_loop + +:HAT_write_sectors_last +SET C, Y +JSR HAT_write_sector +:HAT_write_sectors_end +SET Y, POP +SET C, POP +SET B, POP +SET A, POP +SET X, POP +SET PC, POP + + +; for reading large blocks of data +; A -> start sector +; B -> start location in memory to read to +; C -> length of data in words +; X -> offset in first sector + +:HAT_read_sectors +IFE C, [HAT_sector_size] + SET PC, HAT_read_sector +IFL C, [HAT_sector_size] + SET PC, HAT_read_sector + +SET PUSH, X +SET PUSH, A +SET PUSH, B +SET PUSH, C +SET PUSH, Y + +SET B, C +DIV B, [HAT_sector_size] +MOD C, [HAT_sector_size] +IFN C, 0 +ADD B, 1 + +SET A, PICK 3 ; start sector +SET B, PICK 2 ; location in memory +SET Y, PICK 1 ; num words + +:HAT_read_sectors_loop +IFE Y, [HAT_sector_size] + SET PC, HAT_read_sectors_last +IFL Y, [HAT_sector_size] + SET PC, HAT_read_sectors_last + +SET C, [HAT_sector_size] +SUB C, X +JSR HAT_read_sector +JSR HAT_find_next_sector +ADD B, C +SUB Y, C +SET X, 0 + +IFE Y, 0 + SET PC, HAT_read_sectors_end +SET PC, HAT_read_sectors_loop + +:HAT_read_sectors_last +JSR HAT_read_sector +:HAT_read_sectors_end +SET Y, POP +SET C, POP +SET B, POP +SET A, POP +SET X, POP +SET PC, POP + +:HAT_testwrite +SET PUSH, A +SET PUSH, B +SET PUSH, C +SET PUSH, X + +SET A, 0x002 ; query device flags +HWI [floppy_address] +SET Y, B ; store flags + +AND A, 0xFFFE ; set device to blocking mode +SET B, A +SET A, 0x0003 +HWI [floppy_address] + +SET A, 0x0011 ; write sector interrupt +SET B, 0 ; start at a sector given by a +SET C, 128 ; write a number of 512 word sectors +SET X, 0 +HWI [floppy_address] + +SET B, 0 +IFG A, 0 + SET PC, HAT_error + +SET B, Y ;retrieve flags +SET A, 0x3 ; reset flags +HWI [floppy_address] + +SET X, POP +SET C, POP +SET B, POP +SET A, POP +SET PC, POP + +; A-> hat sector id +; A <- the floppy sector that the hat sector lies in +:HAT_sector_position +SET PUSH, B +SET PUSH, C + +MUL A, [HAT_sector_size] ; multiply by sector size to get number of words +SET B, EX + +ADD A, [HAT_sectors_start+1] ; add lower and lower +ADD B, EX ; carry +ADD B, [HAT_sectors_start] + +DIV B, [floppy_words_per_sector] ; divide position of hat sector in words by number of words in a floppy sector to get the floppy sector the hat sector lies in +SET C, EX +DIV A, [floppy_words_per_sector] +ADD A, C +SUB A, 1 ; returns to A the floppy sector that the hat sector lies in +SET C, POP +SET B, POP +SET PC, POP + +; A-> HAT sector id +; A<- the offset in words of the HAT sector given by A within the floppy sector +:HAT_sector_offset +SET PUSH, B +SET PUSH, A +JSR HAT_sector_position +ADD A, 1 +SET B, A +SET A, POP +MUL A, [HAT_sector_size] +ADD A, [HAT_sectors_start+1] ; add lower and lower + +MUL B, [floppy_words_per_sector] +SUB A, B +SET B, POP +SET PC, POP + +;for writing a sector using data in the stack +; +; A -> start sector +; B -> number of words +; C -> offset in sector +:HAT_write_sector_stack +SET [HAT_write_sector_stack_pc], PEEK +SET [HAT_write_sector_stack_A], A +SET [HAT_write_sector_stack_B], B +SET [HAT_write_sector_stack_C], C +ADD SP, 1 +SET PUSH, B +IFG [HAT_sector_size], [floppy_words_per_sector] +SET PC, HAT_write_sector_stack_read_skip + +JSR HAT_sector_position + +SET PUSH, B +SET B, [HAT_sector_size] +DIV B, [floppy_words_per_sector] +IFE B, 0 + ADD B, 1 ; number of sectors to read, atleast 1 +JSR filesystem_read_disk_sectors + +SET B, POP + +:HAT_write_sector_stack_read_skip +SET [HAT_header_in_paging], 0 +SET A, [HAT_write_sector_stack_A] +JSR HAT_sector_offset +; A is now the offset of the sector in the floppy paging space. data now needs to be written to that space plus the offset +; then write back same number of sectors + +ADD A, [floppy_paging_address] +IFG C, [HAT_sector_size] +SET C, [HAT_sector_size] +ADD A, C +SET B, POP +ADD B, C +IFG B, [HAT_sector_size] +SET B, [HAT_sector_size] +SUB B, C +JSR stackpull + +SET A, [HAT_write_sector_stack_A] +JSR HAT_sector_position +SET PUSH, B +SET B, [HAT_sector_size] +DIV B, [floppy_words_per_sector] +IFE B, 0 + ADD B, 1 ; number of sectors to read, atleast 1 +JSR filesystem_write_disk_sectors + +SET B, POP +SET A, [HAT_write_sector_stack_A] +SET B, [HAT_write_sector_stack_B] +SET C, [HAT_write_sector_stack_C] +SET PC, [HAT_write_sector_stack_pc] + +:HAT_write_sector_stack_pc dat 0 +:HAT_write_sector_stack_A dat 0 +:HAT_write_sector_stack_B dat 0 +:HAT_write_sector_stack_C dat 0 + + +;for reading values from a sector to the stack +; A -> start sector +; B -> number of words +; C-> word offset in sector ie 0 is start of sector +:HAT_read_sector_stack +SET [HAT_read_sector_stack_pc], PEEK +SET [HAT_read_sector_stack_A], A +SET [HAT_read_sector_stack_B], B +SET [HAT_read_sector_stack_C], C +ADD SP, 1 + +JSR HAT_sector_position + +SET PUSH, B +SET B, [HAT_sector_size] +DIV B, [floppy_words_per_sector] +IFE B, 0 + ADD B, 1 ; number of sectors to read, atleast 1 +JSR filesystem_read_disk_sectors + +SET [HAT_header_in_paging], 0 +SET A, [HAT_read_sector_stack_A] +JSR HAT_sector_offset +; A is now the offset of the sector in the floppy paging space. data now needs to be read from that space plus the offset + +ADD A, [floppy_paging_address] +IFG C, [HAT_sector_size] +SET C, [HAT_sector_size] +ADD A, C +SET B, POP +ADD B, C +IFG B, [HAT_sector_size] +SET B, [HAT_sector_size] +SUB B, C +JSR stackpush + +SET A, [HAT_read_sector_stack_A] +SET B, [HAT_read_sector_stack_B] +SET C, [HAT_read_sector_stack_C] +SET PC, [HAT_read_sector_stack_pc] +:HAT_read_sector_stack_pc dat 0 +:HAT_read_sector_stack_A dat 0 +:HAT_read_sector_stack_B dat 0 +:HAT_read_sector_stack_C dat 0 + +;creates an inode in a free sector +; A -> type +; B -> number of links +; A <- sector + +:HAT_inode_create +SET PUSH, A ; store type +SET PUSH, B +SET PUSH, C + +JSR HAT_find_free_sector +SET PUSH, A ;store free sector +JSR HAT_allocate_sector + +SET PUSH, PICK 3 +SET PUSH, PICK 3 +SET PUSH, 0 +SET PUSH, 0 +SET B, 4 +SET C, 0 +JSR HAT_write_sector_stack +SET A, POP +SET C, POP +SET B, POP +ADD SP, 1 +SET PC, POP + +; Deletes an inode +; A -> inode to delete +:HAT_inode_delete +SET PUSH, A +SET PUSH, B +SET PUSH, C +SET PUSH, 0 +SET PUSH, 0 +SET PUSH, 0 +SET PUSH, 0 +SET B, 4 +SET C, 0 +JSR HAT_write_sector_stack +JSR HAT_delete_strip +SET C, POP +SET B, POP +SET A, POP +SET PC, POP + + +;for creating a directory inode +; A <- hat sector of new inode +:HAT_inode_directory_create +SET PUSH, B +SET A, 1 +SET B, 1 +JSR HAT_inode_create +SET B, POP +SET PC, POP + +;for adding a link to a directory inode +; A-> hat sector of inode +; B-> hat sector for link +; C-> address of name string (15 characters) +; A <- nothing or error codes +; 0xffff = inode is not a directory +; todo: handle entries going beyond a single hat sector +:HAT_inode_directory_add_link +SET PUSH, Y +SET PUSH, X +SET PUSH, Z +SET PUSH, I +SET PUSH, J +SET PUSH, A +SET PUSH, B +SET PUSH, C + +SET B, 4 +SET C, 0 +JSR HAT_read_sector_stack + +;check to see if inode is a directory +IFN PICK 3, 1 + SET PC, HAT_inode_directory_add_link_error1 + +SET A, PICK 1 +SET B, PEEK +SET X, 0 +SET Y, 4 +JSR math_ABaddXY +SET C, [HAT_sector_size] +JSR math_ABdivC +SET Z, B +SET A, PICK 1 +SET B, PEEK +SET X, 0 +SET Y, 20 +JSR math_ABaddXY +SET C, [HAT_sector_size] +JSR math_ABdivC + +IFG B, Z ; if b is greater than z, entry extends over 2 hat sectors ie need to add sector to strip + SET PC, HAT_inode_directory_add_link_bridge + +IFG Z, 0 ; if Z is greater than 0 entry is not in first sector in directory strip + SET PC, HAT_inode_directory_add_link_getendsector + +SET B, PEEK +ADD B, 4 +SET Z, B + +ADD SP, 4 +SET I, PICK 2; A-> hat sector of inode +SET X, PICK 1 ; B-> hat sector for link +SET Y, PEEK ; C-> address of name string (15 characters) + +SET A, I ; add entry length to content length of inode +SET B, 4 +SET C, 0 +JSR HAT_read_sector_stack +ADD PEEK, 16 +ADD PICK 1, EX +JSR HAT_write_sector_stack + +SET PUSH, X ; +SET A, Y +SET B, 15 +JSR stackpush +SET A, I +SET B, 16 +SET C, Z +JSR HAT_write_sector_stack + +:HAT_inode_directory_add_link_end +SET C, POP +SET B, POP +SET A, POP +SET J, POP +SET I, POP +SET Z, POP +SET X, POP +SET Y, POP +SET PC, POP + +:HAT_inode_directory_add_link_getendsector +ADD SP, 4 +SET I, PICK 2; A-> hat sector of inode +SET X, PICK 1 ; B-> hat sector for link +SET Y, PEEK ; C-> address of name string (15 characters) + +SET A, I ; add entry length to content length of inode +SET B, 4 +SET C, 0 +JSR HAT_read_sector_stack +ADD PEEK, 16 +ADD PICK 1, EX +SET X, PICK 1 +SET Y, PEEK +JSR HAT_write_sector_stack +SET A, X +SET B, Y +SET X, 0 +SET Y, 16 +JSR math_ABsubXY +SET A, I +JSR HAT_find_strip_end +ADD B, 4 +MOD B, [HAT_sector_size] +SET C, B ; C is now offset in sector +SET I, A ; last sector in strip +SET X, PICK 1 ; B-> hat sector for link +SET Y, PEEK ; C-> address of name string (15 characters) + +SET PUSH, X +SET A, Y +SET B, 15 +JSR stackpush +SET A, I +SET B, 16 +; C is offset in sector +JSR HAT_write_sector_stack + +SET PC, HAT_inode_directory_add_link_end + +:HAT_inode_directory_add_link_bridge +SET X, PICK 1 +SET Y, PEEK +SET A, 0 +SET B, 4 +JSR math_ABaddXY +SET X, A +SET Y, B +ADD PEEK, 16 +ADD PICK 1, EX +SET A, PICK 6 +SET B, 4 +SET C, 0 +JSR HAT_write_sector_stack +SET A, PICK 2 +IFG Z, 0 +JSR HAT_find_strip_end +SET B, Y +MOD B, [HAT_sector_size] +SET C, B +SET I, A + +SET Y, PEEK +SET PUSH, PICK 1 ; push link inode +SET A, Y ; address of name string +SET B, [HAT_sector_size] +SUB B, C +SUB B, 1 +ADD Y, B +JSR stackpush +ADD B, 1 +SET A, I +JSR HAT_write_sector_stack +SET PUSH, B +JSR HAT_find_free_sector +JSR HAT_allocate_sector +SET B, A +SET A, I +JSR HAT_join_sectors +SET I, B +SET B, POP +SET C, 16 +SUB C, B +SET B, C +SET A, Y +JSR stackpush +SET A, I +SET C, 0 +JSR HAT_write_sector_stack +SET PC, HAT_inode_directory_add_link_end + +:HAT_inode_directory_add_link_error1 +ADD SP, 4 +SET C, POP +SET B, POP +ADD SP, 1 +SET A, 0xFFFF +SET J, POP +SET I, POP +SET Z, POP +SET X, POP +SET Y, POP +SET PC, POP + +;creates an file inode and copies data into the file +; A-> start of file data +; B-> end of file of data +; A <- start sector of file +:HAT_inode_file_create +SET PUSH, X +SET PUSH, Y +SET PUSH, C +SET PUSH, B +SET PUSH, A + +SET Y, B +SUB Y, A + +SET A, 2 +SET B, 1 +JSR HAT_inode_create +SET PUSH, 0 +SET PUSH, Y +SET B, 2 +SET C, 2 +JSR HAT_write_sector_stack +SET B, POP +SET C, Y +SET X, 4 +JSR HAT_write_sectors +SET B, POP +SET C, POP +SET Y, POP +SET X, POP +SET PC, POP + + + +; lists directory links on screen +; A -> inode of directory to be listed in screen ie precurser to ls +:HAT_directory_list +SET PUSH, J +SET PUSH, I +SET PUSH, Y +SET PUSH, C +SET PUSH, B +SET PUSH, A +SET B, 4 +SET C, 0 +JSR HAT_read_sector_stack +IFN PICK 3, 1 + SET PC, HAT_directory_list_error1 ; not a directory + +SET A, PICK 1 +SET B, PEEK +SET C, 16 +JSR math_ABdivC +SET Y, B +ADD SP, 4 +SET A, PEEK +SET PUSH, A +SET B, 0 +JSR HAT_read_sector +JSR HAT_sector_offset +ADD A, [floppy_paging_address] +ADD A, 5 +SET J, 4 +SET I, 0 +:HAT_directory_list_loop +SUB Y, 1 +SET B, 15 +JSR text_out_length +JSR newline +ADD A, 16 +ADD J, 16 +ADD I, EX +SET B, J +MOD B, [HAT_sector_size] +SET C, [HAT_sector_size] +SUB C, B +IFL C, 16 +JSR HAT_directory_list_bridge + +IFN Y, 0 +SET PC, HAT_directory_list_loop + +;HAT_directory_list_end +SET A, POP +SET A, POP +SET B, POP +SET C, POP +SET Y, POP +SET I, POP +SET J, POP +SET PC, POP + +:HAT_directory_list_bridge +SET B, C +JSR text_out_length +SET B, 16 +SUB B, C +SET A, PICK 1 +JSR HAT_find_next_sector +SET PICK 1, A +JSR HAT_read_sector +JSR HAT_sector_offset +ADD A, [floppy_paging_address] +JSR text_out_length +ADD A, B +ADD A, 1 +JSR newline +SET PC, POP + + +:HAT_directory_list_error1 +ADD SP, 4 +SET A, POP +SET B, POP +SET C, POP +SET Y, POP +SET PC, POP + + +; A-> directory inode +; B-> file start +; C-> file end +; X-> file name (15 characters) +:HAT_inode_directory_add_file +SET PUSH, B +SET PUSH, C +SET PUSH, A +SET A, B +SET B, C +JSR HAT_inode_file_create +SET B, A +SET A, PEEK +SET C, X +JSR HAT_inode_directory_add_link +SET A, POP +SET C, POP +SET B, POP +SET PC, POP + +;initiates a stream to a file +; subsequent calls to HAT_file_stream_to will add data to the file as defined by the initialised paramaters. +; this will allow loops to add data from a buffer to a file by simply calling HAT_file_stream_to +; calling HAT_file_stream_stop will pretect accidental calls to HAT_file_stream_to from occuring. +; A -> inode of file to stream to +; B -> memory location of buffer to read from +; C -> length of buffer. +:HAT_file_stream_to_init +IFN [HAT_file_stream_to_active], 0 ; stream already initialised, must call HAT_file_stream_stop first +SET PC, POP + +SET [HAT_file_stream_to_active], 1 +SET [HAT_file_stream_to_inode], A +SET [HAT_file_stream_to_buffer], B +SET [HAT_file_stream_to_buffer_length], C + +JSR pusha ; push all registers. + +SET A, [HAT_file_stream_to_inode] +SET B, 4 +SET C, 0 +JSR HAT_read_sector_stack + +;check to see if inode is a file +IFN PICK 3, 2 + SET PC, HAT_file_stream_to_init_error1 + +SET X, PICK 1 +SET Y, PEEK +SET A, X +SET B, Y +ADD B, 4 +ADD A, EX +SET [HAT_file_stream_to_position], A +SET [HAT_file_stream_to_position+1], B +SUB [HAT_file_stream_to_position+1], 1 +SUB [HAT_file_stream_to_position], EX +SET A, [HAT_file_stream_to_inode] +JSR HAT_find_strip_end +SET [HAT_file_stream_to_strip_end], A +ADD SP, 4 +jsr popa +SET PC, POP + +:HAT_file_stream_to_init_error1 +JSR popa ; push all registers. +SET [HAT_file_stream_to_active], 0 +SET A, [HAT_file_stream_to_inode] +SET B, [HAT_file_stream_to_buffer] +SET C, [HAT_file_stream_to_buffer_length] +SET PC, POP + +:HAT_file_stream_to_active dat 0 +:HAT_file_stream_to_inode dat 0 +:HAT_file_stream_to_buffer dat 0 +:HAT_file_stream_to_buffer_length dat 0 +:HAT_file_stream_to_strip_end dat 0 +:HAT_file_stream_to_position dat 0, 0 +:HAT_file_stream_to_buffer_pos dat 0 + +; streams data from the buffer to a file determined by HAT_file_stream_to_init +; returns silent if it hasn't been intialised. +:HAT_file_stream_to +IFN [HAT_file_stream_to_active], 1 +SET PC, POP +SET PUSH, A +SET PUSH, B +SET PUSH, C +SET PUSH, X + +SET A, [HAT_file_stream_to_inode] +SET B, 2 +SET C, 2 +JSR HAT_read_sector_stack + +ADD PEEK, [HAT_file_stream_to_buffer_length] +ADD PICK 1, EX +SET A, [HAT_file_stream_to_inode] +SET B, 2 +SET C, 2 +JSR HAT_write_sector_stack + +SET A, [HAT_file_stream_to_position] +SET B, [HAT_file_stream_to_position+1] +MOD B, [HAT_sector_size] +SET X, B +SET C, [HAT_file_stream_to_buffer_length] +SET B, [HAT_file_stream_to_buffer] +SET A, [HAT_file_stream_to_strip_end] +JSR HAT_write_sectors +JSR HAT_find_strip_end +SET [HAT_file_stream_to_strip_end], A + +SET X, POP +SET C, POP +SET B, POP +SET A, POP +SET PC, POP + + + +;initiates a stream from a file +; subsequent calls to HAT_file_stream_to will incrementally read data from a file to the buffer location +; this will allow loops to retreive data from a file to a buffer by simply calling HAT_file_stream_from without any paramaters +; calling HAT_file_stream_from_stop will pretect accidental calls to HAT_file_stream_from from occuring. +; A -> inode of file to stream from +; B -> memory location of buffer to read to +; C -> length of buffer. +:HAT_file_stream_from_init +IFN [HAT_file_stream_from_active], 0 ; stream already initialised, must call HAT_file_stream_from_stop first +SET PC, POP + +SET [HAT_file_stream_from_active], 1 +SET [HAT_file_stream_from_inode], A +SET [HAT_file_stream_from_current_sector], A +SET [HAT_file_stream_from_buffer], B +SET [HAT_file_stream_from_buffer_length], C +SET [HAT_file_stream_from_position], 0 +SET [HAT_file_stream_from_position+1], 4 + +SET PUSH, A +SET PUSH, B +SET PUSH, C + +SET A, [HAT_file_stream_from_inode] +SET B, 4 +SET C, 0 +JSR HAT_read_sector_stack + +;check to see if inode is a file +IFN PICK 3, 2 + SET PC, HAT_file_stream_from_init_error1 + +SET [HAT_file_stream_from_size], PICK 1 +SET [HAT_file_stream_from_size+1], PEEK +ADD [HAT_file_stream_from_size+1], 4 +ADD [HAT_file_stream_from_size], EX +ADD SP, 4 +SET C, POP +SET B, POP +SET A, POP +SET PC, POP + +:HAT_file_stream_from_init_error1 +ADD SP, 7 +SET [HAT_file_stream_from_active], 0 +SET A, [HAT_file_stream_from_inode] +SET B, [HAT_file_stream_from_buffer] +SET C, [HAT_file_stream_from_buffer_length] +SET PC, POP + + +; streams data from the buffer to a file determined by HAT_file_stream_to_init +; returns silent if it hasn't been intialised. +:HAT_file_stream_from +IFN [HAT_file_stream_from_active], 1 +SET PC, POP + +JSR pusha ; push all registers. + +SET A, [HAT_file_stream_from_size] +SET B, [HAT_file_stream_from_size+1] +SET X, [HAT_file_stream_from_position] +SET Y, [HAT_file_stream_from_position+1] +JSR math_ABsubXY +SET X, A +SET Y, B ; XY number of words left to read from file + +SET C, [HAT_file_stream_from_buffer_length] +IFG [HAT_file_stream_from_buffer_length], B +SET C, B + +SET A, [HAT_file_stream_from_current_sector] +SET X, Y +MOD X, [HAT_sector_size] +JSR HAT_read_sectors + +:HAT_file_stream_from_end +JSR popa +SET PC, POP + +:HAT_file_stream_from_active dat 0 +:HAT_file_stream_from_inode dat 0 +:HAT_file_stream_from_buffer dat 0 +:HAT_file_stream_from_buffer_length dat 0 +:HAT_file_stream_from_size dat 0, 0 +:HAT_file_stream_from_position dat 0, 0 +:HAT_file_stream_from_current_sector dat 0 + + + + +:HAT_header_in_paging +dat 0x0 + +:HAT_header +:HAT_system_version +dat 0x0 +:HAT_num_sectors +dat 0 +:HAT_sector_map_start +dat 0, 0 +:HAT_sector_joins_start +dat 0, 0 +:HAT_sectors_start +dat 0, 0 +:HAT_sector_size +dat 0 +:HAT_sectors_used +dat 0 + +:HAT_header_256 +dat 0x4001, 0x0B34, 0x0000, 0x000A, 0x0000, 0x00BE, 0x0000, 0x0C00, 0x0100, 0x0000, 0x00BD, 0x0004 + +:HAT_header_1024 +dat 0x4001, 0x02CF, 0x0000, 0x000A, 0x0000, 0x0037, 0x0000, 0x0C00, 0x0400, 0x0000, 0x0036, 0x000F + +:HAT_driver_end \ No newline at end of file diff --git a/kernel/core.dasm16 b/kernel/core.dasm16 index 85282f1..097ced9 100644 --- a/kernel/core.dasm16 +++ b/kernel/core.dasm16 @@ -45,6 +45,10 @@ JSR mem_copy SET [keyboard_buffers_exclusive], 0 JSR keyboard_unregister_all +;Format Disk and Create root directory +JSR HAT_format_disk_256 +JSR HAT_inode_directory_create + ; OS ready message SET A, text_start_ok JSR text_out diff --git a/kernel/drivers.dasm16 b/kernel/drivers.dasm16 index 0b9bc0c..12caac3 100644 --- a/kernel/drivers.dasm16 +++ b/kernel/drivers.dasm16 @@ -21,9 +21,9 @@ IFE B, 0x12D0 ; Generic Clock (upper 16 bits) JSR bios_clock_init - ;IFE A, 0x4CAE ; HMD2043 floppy disc drive (lower 16 bits) - ; IFE B, 0x74FA ; HMD2043 floppy disc drive (upper 16 bits) - ; JSR bios_floppy_init + IFE A, 0x4CAE ; HMD2043 floppy disc drive (lower 16 bits) + IFE B, 0x74FA ; HMD2043 floppy disc drive (upper 16 bits) + JSR bios_floppy_init IFN Z, 0 SET PC, bios_discover_hardware_loop diff --git a/kernel/filesystem.dasm16 b/kernel/filesystem.dasm16 index d5fa8c8..789c9c4 100644 --- a/kernel/filesystem.dasm16 +++ b/kernel/filesystem.dasm16 @@ -82,12 +82,19 @@ ; *** Hardware Functions *** ; Returns the sector size in words :filesystem_getsectorsize +SET A, [floppy_words_per_sector] +SET PC, POP ; Returns the total number of sectors :filesystem_getsectorcount +SET A, [floppy_sectors] +SET PC, POP ; Returns the total disk size in words :filesystem_getdisksize +SET A, [floppy_sectors] +MUL A, [floppy_words_per_sector] +SET PC, POP ; *** Software Functions *** ; Returns the total FAT size in sectors @@ -96,4 +103,97 @@ ; Returns the total number of free sectors on the disk :filesystem_getfreespace -; ##########END PHYSICAL FILESYSTEM########### \ No newline at end of file + +; reads a number of floppy sectors from the floppy from a starting sector in the floppy to the floppy paging space +; A --> start sector +; B --> number of sectors +:filesystem_read_disk_sectors +IFG A, 1439 + SET PC, filesystem_error +IFG B, 6 + SET PC, filesystem_error + +SET PUSH, C ; push c, x, y for code safety +SET PUSH, X +SET PUSH, Y + +SET PUSH, B ; store A and B +SET PUSH, A + +SET A, 0x002 ; query device flags +HWI [floppy_address] +SET Y, B ; store flags + +AND A, 0xFFFE ; set device to blocking mode +SET B, A +SET A, 0x0003 +HWI [floppy_address] + +SET A, 0x0010 ; read sector interrupt +SET B, PEEK ; start at sector given by A +SET C, PICK 1 ; read a number of sectors given by B +SET X, [floppy_paging_address] +HWI [floppy_address] + +IFG A, 0 + SET PC, filesystem_error + +SET B, Y ;retrieve flags +SET A, 0x3 ; reset flags +HWI [floppy_address] + +SET A, POP +SET B, POP +SET Y, POP +SET X, POP +SET C, POP +SET PC, POP + +; Writes a number of floppy sectors from the floppy paging space to a starting sector on the floppy. +; A --> start sector +; B --> number of sectors +:filesystem_write_disk_sectors +IFG A, 1439 + SET PC, filesystem_error +IFG B, 6 + SET PC, filesystem_error + +SET PUSH, C ; push c, x, y for code safety +SET PUSH, X +SET PUSH, Y + +SET PUSH, B ; store A and B +SET PUSH, A + +SET A, 0x002 ; query device flags +HWI [floppy_address] +SET Y, B ; store flags + +AND A, 0xFFFE ; set device to blocking mode +SET B, A +SET A, 0x0003 +HWI [floppy_address] + +SET A, 0x0011 ; write sector interrupt +SET B, POP ; start at a sector given by a +SET C, POP ; write a number of 512 word sectors +SET X, [floppy_paging_address] +HWI [floppy_address] + +SET B, 0 +IFG A, 0 + SET PC, filesystem_error + +SET B, Y ;retrieve flags +SET A, 0x3 ; reset flags +HWI [floppy_address] + +SET Y, POP +SET X, POP +SET C, POP +SET PC, POP + +:filesystem_error +SUB PC, 1 +; ##########END PHYSICAL FILESYSTEM########### + diff --git a/kernel/library.dasm16 b/kernel/library.dasm16 index ec0c4bc..9276d38 100644 --- a/kernel/library.dasm16 +++ b/kernel/library.dasm16 @@ -698,4 +698,85 @@ jsr popa SET PC, POP :gui_box_corners -dat 0,0 , 0,0 \ No newline at end of file +dat 0,0 , 0,0 + +;copies data from a memory location to the stack ie in reverse +;A -> memory location +;B -> number of words +:stackpush +SET [stackpush_pc], PEEK +SUB SP, B +ADD SP, 1 +SET PUSH, A +SET PUSH, B +ADD SP, B +ADD SP, 2 +:stackpush_loop +IFE B, 0 + SET PC, stackpush_end +SET PUSH, [A] +ADD A, 1 +SUB B, 1 +SET PC, stackpush_loop + +:stackpush_end +SUB SP, 2 +SET B, POP +SET A, POP +SET PC, [stackpush_pc] + +:stackpush_pc +dat 0 + +;copies data from the stack to a memory location +;A -> memory location +;B -> number of words +:stackpull +SET [stackpull_pc], peek +SET [stackpull_A], A +SET [stackpull_B], B +ADD A, B +SUB A, 1 +ADD SP, 1 +:stackpull_loop +IFE B, 0 +SET PC, stackpull_end +SET [A], POP +SUB A, 1 +SUB B, 1 +SET PC, stackpull_loop + +:stackpull_end +SET B, [stackpull_A] +SET A, [stackpull_B] +SET PC, [stackpull_pc] + +:stackpull_pc +dat 0 +:stackpull_A +dat 0 +:stackpull_B +dat 0 + +; press any key to +; A -> string to finish the sentence +; B -> memory address to continue program +; C -> keyboard input buffer +:pakto +ADD SP, 1 +SET PUSH, A +SET [C], 0 + +jsr newline +SET A, pakto_text1 +JSR text_out + +SET A, POP +jsr text_out + +:pakto_loop +IFE [C], 0 +SET PC, pakto_loop +SET PC, B + +:pakto_text1 dat "Press any key to ", 0 \ No newline at end of file From 22358627f966856b0b7e0b482201bf552e15a194 Mon Sep 17 00:00:00 2001 From: bungao Date: Sun, 14 Oct 2012 16:03:15 +1100 Subject: [PATCH 09/13] GUI text in box subroutine --- kernel/library.dasm16 | 70 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/kernel/library.dasm16 b/kernel/library.dasm16 index 9276d38..c1ad6ca 100644 --- a/kernel/library.dasm16 +++ b/kernel/library.dasm16 @@ -73,7 +73,7 @@ :text_out_length_loop - IFE Y, 1 + IFE Y, 0 SET PC, text_out_length_end SET C, [A] IFE C, 0x0000 @@ -298,6 +298,7 @@ ; Takes a text buffer containing an integer and converts it to an integer ; A: Address of text buffer +; C <- value :atoi SET PUSH, A SET PUSH, B @@ -700,6 +701,73 @@ SET PC, POP :gui_box_corners dat 0,0 , 0,0 +:gui_box_text ; creates a box using the given coordinates and prints a string inside the box. +; A, B -> coordinates of first corner +; X, Y -> coordinates of second corner ie on a diagonal +; I -> text string. +; Z-> colour of box +IFG A, 0x1f +SET PC, POP +IFG B, 0xB +SET PC, POP +IFG X, 0x1f +SET PC, POP +IFG Y, 0xB +SET PC, POP +IFE A, X +SET PC, POP +IFE B, Y +SET PC, POP + +jsr gui_box +jsr pusha + +SET A, [gui_box_corners] +SET B, [gui_box_corners+1] +SET X, [gui_box_corners+2] +SET Y, [gui_box_corners+3] + +SUB X, A +IFE X, 1 + SET PC, gui_box_text_end +SUB Y, B +IFE Y, 1 + SET PC, gui_box_text_end +SUB X, 1 +SUB Y, 1 +SET Z, X +MUL Z, B ; maximum number of characters that can be places in box. +SET PUSH, X ; width +SET PUSH, Y ; rows +SET A, [gui_box_corners] +ADD A, 1 +SET B, [gui_box_corners+1] +ADD B, 1 +MUL B, [video_width] +ADD A, B +ADD A, [video_mem] +SET [video_cur], A +SET J, A ; start of first row +:gui_box_text_loop1 +IFE PEEK, 0 + SET PC, gui_box_text_end +SET [video_cur], J +SET A, I +SET B, PICK 1 +JSR text_out_length +SUB PEEK, 1 +ADD J, [video_width] +ADD I, PICK 1 +SET PC, gui_box_text_loop1 + + + +:gui_box_text_end +ADD SP, 2 +jsr popa +set pc, pop + + ;copies data from a memory location to the stack ie in reverse ;A -> memory location ;B -> number of words From 7a39ab7d1365a9cb78e537fdfeaa9174cd722778 Mon Sep 17 00:00:00 2001 From: bungao Date: Sun, 14 Oct 2012 16:09:56 +1100 Subject: [PATCH 10/13] Addition of an inbuilt assembler, very experimental Credit to Nils Ole Timm --- apps/apps.dasm16 | 1 + apps/asm.dasm16 | 1174 ++++++++++++++++++++++++++++++++++++++ atlas.10cproj | 1 + kernel/HAT_driver.dasm16 | 2 - kernel/core.dasm16 | 7 +- kernel/interrupts.dasm16 | 16 +- make.dasm16 | 1 + 7 files changed, 1183 insertions(+), 19 deletions(-) create mode 100644 apps/asm.dasm16 diff --git a/apps/apps.dasm16 b/apps/apps.dasm16 index 361d42f..f5e9a82 100644 --- a/apps/apps.dasm16 +++ b/apps/apps.dasm16 @@ -5,4 +5,5 @@ :application_table :app1 dat "AtlasText", 0, AtlasText, AtlasText_end :app2 dat "AtlasShell", 0, AtlasShell, AtlasShell_end +:app3 dat "asm", 0, asm, asm_end :application_table_end diff --git a/apps/asm.dasm16 b/apps/asm.dasm16 new file mode 100644 index 0000000..6579319 --- /dev/null +++ b/apps/asm.dasm16 @@ -0,0 +1,1174 @@ +;-------------------------------------------- +; Title: compiler +; Author: Nils Ole Timm +; Date: 11.07.2012 +; Version: 1.0 +; -------------------------------------------- +:asm + + ; Register our buffer with the driver + SET A, asm_input_buffer + ; And ask for exclusive keyboard access + SET B, 1 + JSR [0x1026] ; keyboard_register + + SET [AtlasText_input_buffer], 0 + +:asm_inputfile ; display prompt for file position + + JSR [0x1021] ; clear + + SET A, asm_intro + JSR text_out + jsr newline + SET A, text_prompt + jsr text_out + + SET A, asm_file_buffer + SET B, 5 + JSR mem_clear + + SET A, asm_file_buffer + SET B, 5 + SET C, asm_input_buffer + JSR [0x1023] ; readline + + SET A, asm_file_buffer + jsr atoi + SET Z, C + IFE C, 0 + SET PC, asm_die + JSR page_alloc + SET Y, A + SET [asm_output_location], A + + JSR page_alloc + SET [asm_label_storage], A + + + +:asm_parse_start + set [asm_program_counter], Y ; start of memory space to assemble to + set [asm_char_counter], Z ; start of txt file of code to assemble. + set [asm_labels_to_fill_count], 0 + +; -------------------------------------------- +; Title: compiler +; Author: Nils Ole Timm +; Date: 11.07.2012 +; Version: 1.0 +; -------------------------------------------- +;This compiler uses an asm_atoi and print routine +;from my AlmOSt, so you'll need to replace +;those with your own + +;note that asm_atoi returns the length +;of the read number in X + +;This compiler does currently not use the +;0x20-0x3f semantics for small values +;and is therefore a bit slower + +:asm_parse_op + set A, [asm_program_counter] + ifg 0x2fff, A + set PC, asm_err_addr + set B, [asm_char_counter] + jsr asm_skip_whites; + set C, [B] + ife C, 0; Done + set X, 0 + ife C, 0 + jsr asm_fill_labels + ife C, 0; Done + set Y, [asm_program_counter] + ife C, 0; Done + set PC, asm_die + ife C, 0x3A; : add label + set PC, asm_add_label + ife C, 0x41 ;A + set PC, asm_parse_op_A + ife C, 0x42 ;B + set PC, asm_parse_op_B + ife C, 0x44 ;D + set PC, asm_parse_op_D + ife C, 0x48 ;H + set PC, asm_parse_op_H + ife C, 0x49 ;I + set PC, asm_parse_op_I + ife C, 0x4a ;J + set PC, asm_parse_op_J + ife C, 0x4d ;M + set PC, asm_parse_op_M + ife C, 0x52 ;R + set PC, asm_parse_op_R + ife C, 0x53;S + set PC, asm_parse_op_S + ife C, 0x58;X + set PC, asm_parse_op_X + set PC, asm_error +:asm_parse_op_A + add B, 1 + set C, [B] + ife C, 0x53 ;S + set PC, asm_parse_op_AS + ife C, 0x44 ;D + set PC, asm_parse_op_AD + ife C, 0x4e ;N + set PC, asm_parse_op_AN + set PC, asm_error +:asm_parse_op_AS + add B, 1 + set C, [B] + ife C, 0x52;R + set [asm_rop], [asm_oASR] + ife C, 0x52 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_AD + add B, 1 + set C, [B] + ife C, 0x44;D + set [asm_rop], [asm_oADD] + ife C, 0x44 + set PC, asm_parse_val + ife C, 0x58;X + set [asm_rop], [asm_oADX] + ife C, 0x58 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_AN + add B, 1 + set C, [B] + ife C, 0x44;D + set [asm_rop], [asm_oAND] + ife C, 0x44 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_B + add B, 1 + set C, [B] + ife C, 0x4F + set PC, asm_parse_op_BO + set PC, asm_error +:asm_parse_op_BO + add B, 1 + set C, [B] + ife C, 0x52;R + set [asm_rop], [asm_oBOR] + ife C, 0x52 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_D + add B, 1 + set C, [B] + ife C, 0x40;A + set PC, asm_parse_op_DA + ife C, 0x49;I + set PC, asm_parse_op_DI + ife C, 0x56;V + set PC, asm_parse_op_DV +:asm_parse_op_DA + add B, 1 + set C, [B] + ife C, 0x54;T + set PC, asm_parse_dat + set PC, asm_error +:asm_parse_op_DI + add B, 1 + set C, [B] + ife C, 0x56;V + set [asm_rop], [asm_oDIV] + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_DV + add B, 1 + set C, [B] + ife C, 0x49;I + set [asm_rop], [asm_oDVI] + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_H + add B, 1 + set C, [B] + ife C, 0x57;W + set PC, asm_parse_op_HW + set PC, asm_error +:asm_parse_op_HW + add B, 1 + set C, [B] + ife C, 0x49;I + set [asm_rop], [asm_sHWI] + ife C, 0x49 + set PC, asm_parse_val_s + ife C, 0x4e;N + set [asm_rop], [asm_sHWN] + ife C, 0x4e + set PC, asm_parse_val_s + ife C, 0x51;Q + set [asm_rop], [asm_sHWQ] + ife C, 0x51 + set PC, asm_parse_val_s + set PC, asm_error +:asm_parse_op_I + add B, 1 + set C, [B] + ife C, 0x41;A + set PC, asm_parse_op_IA + ife C, 0x46;F + set PC, asm_parse_op_IF + ife C, 0x4e;N + set PC, asm_parse_op_IN +:asm_parse_op_IA + add B, 1 + set C, [B] + ife C, 0x47;G + set [asm_rop], [asm_sIAG] + ife C, 0x47 + set PC, asm_parse_val_s + ife C, 0x51;Q + set [asm_rop], [asm_sIAQ] + ife C, 0x51 + set PC, asm_parse_val_s + ife C, 0x53;G + set [asm_rop], [asm_sIAS] + ife C, 0x53 + set PC, asm_parse_val_s +:asm_parse_op_IF + add B, 1 + set C, [B] + ife C, 0x41;A + set [asm_rop], [asm_oIFA] + ife C, 0x41 + set PC, asm_parse_val + ife C, 0x42;B + set [asm_rop], [asm_oIFB] + ife C, 0x42 + set PC, asm_parse_val + ife C, 0x43;C + set [asm_rop], [asm_oIFC] + ife C, 0x43 + set PC, asm_parse_val + ife C, 0x45;E + set [asm_rop], [asm_oIFE] + ife C, 0x45 + set PC, asm_parse_val + ife C, 0x47;G + set [asm_rop], [asm_oIFG] + ife C, 0x47 + set PC, asm_parse_val + ife C, 0x4c;L + set [asm_rop], [asm_oIFL] + ife C, 0x4c + set PC, asm_parse_val + ife C, 0x4e;N + set [asm_rop], [asm_oIFN] + ife C, 0x4e + set PC, asm_parse_val + ife C, 0x55;U + set [asm_rop], [asm_oIFU] + ife C, 0x55 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_IN + add B, 1 + set C, [B] + ife C, 0x54;T + set [asm_rop], [asm_sINT] + ife C, 0x54 + set PC, asm_parse_val_s + set PC, asm_error +:asm_parse_op_J + add B, 1 + set C, [B] + ife C, 0x53;S + set PC, asm_parse_op_JS + set PC, asm_error +:asm_parse_op_JS + add B, 1 + set C, [B] + ife C, 0x52;R + set [asm_rop], [asm_sJSR] + ife C, 0x52 + set PC, asm_parse_val_s + set PC, asm_error +:asm_parse_op_M + add B, 1 + set C, [B] + ife C, 0x44;D + set PC, asm_parse_op_MD + ife C, 0x4c;L + set PC, asm_parse_op_ML + ife C, 0x4f;O + set PC, asm_parse_op_MO + ife C, 0x55;U + set PC, asm_parse_op_MU + set PC, asm_error +:asm_parse_op_MD + add B, 1 + set C, [B] + ife C, 0x49;I + set [asm_rop], [asm_oMDI] + ife C, 0x49 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_ML + add B, 1 + set C, [B] + ife C, 0x49;I + set [asm_rop], [asm_oMLI] + ife C, 0x49 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_MO + add B, 1 + set C, [B] + ife C, 0x44;I + set [asm_rop], [asm_oMOD] + ife C, 0x44 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_MU + add B, 1 + set C, [B] + ife C, 0x4c;I + set [asm_rop], [asm_oMUL] + ife C, 0x4c + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_R + add B, 1 + set C, [B] + ife C, 0x46;F + set PC, asm_parse_op_RF + set PC, asm_error +:asm_parse_op_RF + add B, 1 + set C, [B] + ife C, 0x4c;I + set [asm_rop], [asm_sRFI] + ife C, 0x4c + set PC, asm_parse_val_s + set PC, asm_error +:asm_parse_op_S + add B, 1 + set C, [B] + ife C, 0x42;B + set PC, asm_parse_op_SB + ife C, 0x45;E + set PC, asm_parse_op_SE + ife C, 0x48;H + set PC, asm_parse_op_SH + ife C, 0x54;T + set PC, asm_parse_op_ST + ife C, 0x55;U + set PC, asm_parse_op_SU + set PC, asm_error +:asm_parse_op_SB + add B, 1 + set C, [B] + ife C, 0x58;X + set [asm_rop], [asm_oSBX] + ife C, 0x58 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_SE + add B, 1 + set C, [B] + ife C, 0x54; + set [asm_rop], [asm_oSET] + ife C, 0x54 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_SH + add B, 1 + set C, [B] + ife C, 0x4c;L + set [asm_rop], [asm_oSHL] + ife C, 0x4c + set PC, asm_parse_val + ife C, 0x52;R + set [asm_rop], [asm_oSHR] + ife C, 0x52 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_ST + add B, 1 + set C, [B] + ife C, 0x44;D + set [asm_rop], [asm_oSTD] + ife C, 0x44 + set PC, asm_parse_val + ife C, 0x49;I + set [asm_rop], [asm_oSTI] + ife C, 0x49 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_SU + add B, 1 + set C, [B] + ife C, 0x42;B + set [asm_rop], [asm_oSUB] + ife C, 0x42 + set PC, asm_parse_val + set PC, asm_error +:asm_parse_op_X + add B, 1 + set C, [B] + ife C, 0x51 + set PC, asm_parse_op_XO + set PC, asm_error +:asm_parse_op_XO + add B, 1 + set C, [B] + ife C, 0x52 + set [asm_rop], [asm_oXOR] + ife C, 0x52 + set PC, asm_parse_val + set PC, asm_error + +:asm_parse_val;normal instructions + add B, 1 + jsr asm_skip_whites + set X, 0 + jsr asm_read_val + add B, 1 + jsr asm_skip_whites + set X, 1 + jsr asm_read_val + set Z, [asm_program_counter] + set [Z], [asm_rop] + and [Z], [asm_opCodeMask] + set Y, [asm_rB] + shl Y, 5 + and Y, [asm_BValueMask] + bor [Z], Y + set Y, [asm_rA] + shl Y, 10 + and Y, [asm_AValueMask] + bor [Z], Y + ife [asm_param_counter], 2 + jsr asm_swap_params + add [asm_program_counter] ,1 + add [asm_program_counter] ,[asm_param_counter] + set [asm_param_counter], 0 + add B, 1 + set [asm_char_counter], B + set PC, asm_parse_op +:asm_parse_val_s;special instructions + add B, 1 + jsr asm_skip_whites + set X, 1 + jsr asm_read_val + set Z, [asm_program_counter] + set [Z], 0 + and [Z], [asm_opCodeMask] + set Y, [asm_rop] + shl Y, 5 + and Y, [asm_BValueMask] + bor [Z], Y + set Y, [asm_rA] + shl Y, 10 + and Y, [asm_AValueMask] + bor [Z], Y + add [asm_program_counter] ,1 + add [asm_program_counter] ,[asm_param_counter] + set [asm_param_counter], 0 + add B, 1 + set [asm_char_counter], B + set PC, asm_parse_op + +:asm_swap_params + set J,[asm_program_counter] + set Z,[J+1] + set [J+1], [J+2] + set [J+2], Z + set PC, POP +:asm_read_val + set C, [B] + ife C, 0x5B;[ + set PC, asm_read_val_ob + ife C, 0x68;h + set PC, asm_read_val_n + ifg C, 0x2f; '0'-'9' + ifg 0x3a, C + set PC, asm_read_val_n + ife C, 0x4c; 'l' used to identify labels + set PC, asm_read_val_n + ife C, 0x41; 'A' + set PC, asm_read_val_A + ife C, 0x42; 'B' + set PC, asm_read_val_B + ife C, 0x43; 'C' + set PC, asm_read_val_C + ife C, 0x58; 'X' + set PC, asm_read_val_X + ife C, 0x59; 'Y' + set PC, asm_read_val_Y + ife C, 0x5a; 'Z' + set PC, asm_read_val_Z + ife C, 0x49; 'I' + set PC, asm_read_val_I + ife C, 0x4a; 'J' + set PC, asm_read_val_J + ife C, 0x50; 'P' + set PC, asm_read_val_P + ife C, 0x53; 'S' + set PC, asm_read_val_S + ife C, 0x45; 'E' + set PC, asm_read_val_E +:asm_read_val_ob + add B, 1 + set C, [B] + ife C, 0x68;h + set PC, asm_read_val_obn + ifg C, 0x2f; '0'-'9' + ifg 0x3a, C + set PC, asm_read_val_obn + ifg C, 0x4c; 'l' used to identify labels + set PC, asm_read_val_obn + ife C, 0x41; 'A' + set PC, asm_read_val_obA + ife C, 0x42; 'B' + set PC, asm_read_val_obB + ife C, 0x43; 'C' + set PC, asm_read_val_obC + ife C, 0x58; 'X' + set PC, asm_read_val_obX + ife C, 0x59; 'Y' + set PC, asm_read_val_obY + ife C, 0x5a; 'Z' + set PC, asm_read_val_obZ + ife C, 0x49; 'I' + set PC, asm_read_val_obI + ife C, 0x4a; 'J' + set PC, asm_read_val_obJ + ife C, 0x53; 'S' + set PC, asm_read_val_obS +:asm_read_val_obn + set I, 0 + ife C, 0x4C + set I, 1 + ife C, 0x4c + add B, 1 + set PUSH, X + set PUSH, B + set PUSH, B + jsr asm_atoi + set B, POP + add B, X + set X, POP + set PUSH, C + jsr asm_skip_whites; + set C, [B] + ifn C, 0x5D;']' + set PC, asm_error + set C, POP + add [asm_param_counter], 1 + set Z, [asm_param_counter] + add Z, [asm_program_counter] + ife I, 1 + jsr asm_add_f_label + set [Z], C + set Y, [asm_vbn] + set PC, asm_write_val +:asm_read_val_obA + add B, 1 + jsr asm_skip_whites + set C, [B] + ife C, 0x2B;+ + set Y, [asm_vbApn] + ife C, 0x2B;+ + set PC, asm_read_val_obApn + ifn C, 0x5D;] + set PC, asm_error + ;If we get here we are done + set Y, [asm_vbA] + set PC, asm_write_val +:asm_read_val_obB + add B, 1 + jsr asm_skip_whites + set C, [B] + ife C, 0x2B;+ + set Y, [asm_vbBpn] + ife C, 0x2B;+ + set PC, asm_read_val_obBpn + ifn C, 0x5D;] + set PC, asm_error + ;If we get here we are done + set Y, [asm_vbB] + set PC, asm_write_val +:asm_read_val_obC + add B, 1 + jsr asm_skip_whites + set C, [B] + ife C, 0x2B;+ + set Y, [asm_vbCpn] + ife C, 0x2B;+ + set PC, asm_read_val_obCpn + ifn C, 0x5D;] + set PC, asm_error + ;If we get here we are done + set Y, [asm_vbC] + set PC, asm_write_val +:asm_read_val_obX + add B, 1 + jsr asm_skip_whites + set C, [B] + ife C, 0x2B;+ + set Y, [asm_vbXpn] + ife C, 0x2B;+ + set PC, asm_read_val_obApn + ifn C, 0x5D;] + set PC, asm_error + ;If we get here we are done + set Y, [asm_vbX] + set PC, asm_write_val +:asm_read_val_obY + add B, 1 + jsr asm_skip_whites + set C, [B] + ife C, 0x2B;+ + set Y, [asm_vbYpn] + ife C, 0x2B;+ + set PC, asm_read_val_obYpn + ifn C, 0x5D;] + set PC, asm_error + ;If we get here we are done + set Y, [asm_vbY] + set PC, asm_write_val +:asm_read_val_obZ + add B, 1 + jsr asm_skip_whites + set C, [B] + ife C, 0x2B;+ + set Y, [asm_vbZpn] + ife C, 0x2B;+ + set PC, asm_read_val_obZpn + ifn C, 0x5D;] + set PC, asm_error + ;If we get here we are done + set Y, [asm_vbZ] + set PC, asm_write_val +:asm_read_val_obI + add B, 1 + jsr asm_skip_whites + set C, [B] + ife C, 0x2B;+ + set Y, [asm_vbIpn] + ife C, 0x2B;+ + set PC, asm_read_val_obIpn + ifn C, 0x5D;] + set PC, asm_error + ;If we get here we are done + set Y, [asm_vbI] + set PC, asm_write_val +:asm_read_val_obJ + add B, 1 + jsr asm_skip_whites + set C, [B] + ife C, 0x2B;+ + set Y, [asm_vbJpn] + ife C, 0x2B;+ + set PC, asm_read_val_obJpn + ifn C, 0x5D;] + set PC, asm_error + ;If we get here we are done + set Y, [asm_vbJ] + set PC, asm_write_val +:asm_read_val_obS + add B, 1 + set C, [B] + ifn C, 0x50;P + set PC, asm_error + add B, 1 + jsr asm_skip_whites + ife C, 0x2B;+ + set Y, [asm_vbSPpn] + ife C, 0x2B;+ + set PC, asm_read_val_obSPpn + ifn C, 0x5D;] + set PC, asm_error + ;If we get here we are done + set Y, [asm_vbSP] + set PC, asm_write_val +:asm_read_val_obApn +:asm_read_val_obBpn +:asm_read_val_obCpn +:asm_read_val_obXpn +:asm_read_val_obYpn +:asm_read_val_obZpn +:asm_read_val_obIpn +:asm_read_val_obJpn +:asm_read_val_obSPpn +;parse numerical value here + add B, 1 + set C, [B] + set I, 0 + ife C, 0x4c + set I, 1 + ife C, 0x4c + add B, 1 + set PUSH, Y + set PUSH, X + set PUSH, B + + set PUSH, B + jsr asm_atoi + + set B, POP + add B, X + sub B, 1 + set X, POP + set Y, POP + + add [asm_param_counter], 1 + set Z, [asm_param_counter] + add Z, [asm_program_counter] + ife I, 1 + jsr asm_add_f_label + + set [Z], C + set PC, asm_write_val +:asm_read_val_A + add B, 1 + set C, [B] + ifn C, 0x20;space + set PC, asm_error + sub B, 1 + set Y, [asm_vA] + set PC, asm_write_val +:asm_read_val_B + add B, 1 + set C, [B] + ifn C, 0x20;space + set PC, asm_error + sub B, 1 + set Y, [asm_vB] + set PC, asm_write_val +:asm_read_val_C + add B, 1 + set C, [B] + ifn C, 0x20;space + set PC, asm_error + sub B, 1 + set Y, [asm_vC] + set PC, asm_write_val +:asm_read_val_X + add B, 1 + set C, [B] + ifn C, 0x20;space + set PC, asm_error + sub B, 1 + set Y, [asm_vX] + set PC, asm_write_val +:asm_read_val_Y + add B, 1 + set C, [B] + ifn C, 0x20;space + set PC, asm_error + sub B, 1 + set Y, [asm_vY] + set PC, asm_write_val +:asm_read_val_Z + add B, 1 + set C, [B] + ifn C, 0x20;space + set PC, asm_error + sub B, 1 + set Y, [asm_vZ] + set PC, asm_write_val +:asm_read_val_I + add B, 1 + set C, [B] + ifn C, 0x20;space + set PC, asm_error + sub B, 1 + set Y, [asm_vI] + set PC, asm_write_val +:asm_read_val_J + add B, 1 + set C, [B] + ifn C, 0x20;space + set PC, asm_error + sub B, 1 + set Y, [asm_vJ] + set PC, asm_write_val +:asm_read_val_P + add B, 1 + set C, [B] + ife C, 0x4F;O + set PC, asm_read_val_PO + ife C, 0x43;C + set Y, [asm_vPC] + ife C, 0x43;C + set PC, asm_write_val + ife C, 0x55;U + set PC, asm_read_val_PU + set PC, asm_error +:asm_read_val_PO + add B, 1 + set C, [B] + ife C, 0x50;P + set Y, [asm_vPOP] + ife C, 0x50 + set PC, asm_write_val + set PC, asm_error +:asm_read_val_PU + add B, 1 + set C, [B] + ifn C, 0x53;S + set PC, asm_error + add B, 1 + set C, [B] + ifn C, 0x48;H + set PC, asm_error + set Y, [asm_vPUSH] + set PC, asm_write_val + +:asm_read_val_S + add B, 1 + set C, [B] + ife C, 0x50;P + set Y, [asm_vSP] + ife C, 0x50 + set PC, asm_write_val + set PC, asm_error +:asm_read_val_E + add B, 1 + set C, [B] + ife C, 0x58;X + set Y, [asm_vEX] + ife C, 0x58 + set PC, asm_write_val + set PC, asm_error +:asm_read_val_n + set I, 0 + ife C, 0x4c + set I, 1 + ife C, 0x4c + add B, 1 + set PUSH, X + set PUSH, B + set PUSH, B + jsr asm_atoi + set B, POP + add B, X + sub B, 2 + set X, POP + add [asm_param_counter], 1 + set Z, [asm_param_counter] + add Z, [asm_program_counter] + ife I, 1 + jsr asm_add_f_label + set [Z], C + set Y, [asm_vn] + set PC, asm_write_val + +:asm_write_val + ife X, 0 + set [asm_rb], Y + ife X, 1 + set [asm_ra], Y + add B, 1 + set PC, POP +:asm_skip_whites + set C, [B] + ife C, 0x20 + set PC, asm_skip_whites_loop + ife C, 10 + set PC, asm_skip_whites_loop + set PC, POP +:asm_skip_whites_loop + add B, 1 + set C, [B] + ife C, 0x20; Space + set PC, asm_skip_whites_loop + ife C, 10; New Line + set PC, asm_skip_whites_loop + set PC, POP +:asm_error + set a, asm_err_comp + jsr text_out + set X, 1 + set PC, POP +:asm_err_addr + set a, asm_err_saddr + jsr text_out + set PC, POP +:asm_add_label + add B, 1 + set PUSH, B + set PUSH, B + jsr asm_atoi + set B, POP + add B, X + ifg C, [asm_label_storage_size] + set PC, asm_parse_op + set X, [asm_label_storage] + add C, X + set X, [asm_program_counter] + set [C], X + set [asm_char_counter], B + set PC, asm_parse_op +:asm_add_f_label + set PUSH, A + set PUSH, B + set PUSH, C + set PUSH, Z + set PUSH, Z + set PUSH, C + jsr asm_add_label_to_fill + set Z, POP + set C, POP + set B, POP + set A, POP + set PC, POP +:asm_add_label_to_fill + set A, [asm_labels_to_fill_count] + shl A, 1 + add A, [asm_labels_to_fill] + set Z, POP + set B, POP + set C, POP + set PUSH, Z + set [A], C ;addr + set [A+1], B ;lbl + add [asm_labels_to_fill_count], 1 + set PC, POP +:asm_fill_labels + set I, 0xffff + sub [asm_labels_to_fill_count], 1 + set PUSH, C +:asm_fill_labels_loop + add I, 1 + set A, I + shl A, 1 + add A, [asm_labels_to_fill] + set X, [asm_label_storage] + set B, [A] + set C, [A+1] + add X, C + set [B], [X] + ifg [asm_labels_to_fill_count], I + set PC, asm_fill_labels_loop + set C, POP + set PC, POP +:asm_parse_dat + add B, 1 + jsr asm_skip_whites + set I, 0 + ife [B], 0x4C + set I, 1 + ife [B], 0x4C + add B, 1 + set PUSH, B + set PUSH, I + set PUSH, B + jsr asm_atoi + set I, POP + set B, POP + add B, X + ife I, 1 + set Z, [asm_label_storage] + ife I, 1 + add Z, C + ife I, 1 + set C, [Z] + set X, [asm_program_counter] + set [X], C + add [asm_program_counter], 1 + set [asm_char_counter], B + set PC, asm_parse_op +;SHL 10 +:asm_AValueMask +dat 0xfc00 +;SHL 5 +:asm_BValueMask +dat 0x03e0 +:asm_OpCodeMask +dat 0x001f +;Values +:asm_vA dat 0x0000 +:asm_vB dat 0x0001 +:asm_vC dat 0x0002 +:asm_vX dat 0x0003 +:asm_vY dat 0x0004 +:asm_vZ dat 0x0005 +:asm_vI dat 0x0006 +:asm_vJ dat 0x0007 +:asm_vbA dat 0x0008 +:asm_vbB dat 0x0009 +:asm_vbC dat 0x000a +:asm_vbX dat 0x000b +:asm_vbY dat 0x000c +:asm_vbZ dat 0x000d +:asm_vbI dat 0x000e +:asm_vbJ dat 0x000f +:asm_vbApn dat 0x0010 +:asm_vbBpn dat 0x0011 +:asm_vbCpn dat 0x0012 +:asm_vbXpn dat 0x0013 +:asm_vbYpn dat 0x0014 +:asm_vbZpn dat 0x0015 +:asm_vbIpn dat 0x0016 +:asm_vbJpn dat 0x0017 +:asm_vPOP dat 0x0018 +:asm_vPUSH dat 0x0018 +:asm_vbSP dat 0x0019 +:asm_vPEEK dat 0x0019 +:asm_vbSPpn dat 0x001a +:asm_vPICK dat 0x001a +:asm_vSP dat 0x001b +:asm_vPC dat 0x001c +:asm_vEX dat 0x001d +:asm_vbn dat 0x001e +:asm_vn dat 0x001f + +:asm_oSET dat 0x01 +:asm_oADD dat 0x02 +:asm_oSUB dat 0x03 +:asm_oMUL dat 0x04 +:asm_oMLI dat 0x05 +:asm_oDIV dat 0x06 +:asm_oDVI dat 0x07 +:asm_oMOD dat 0x08 +:asm_oMDI dat 0x09 +:asm_oAND dat 0x0a +:asm_oBOR dat 0x0b +:asm_oXOR dat 0x0c +:asm_oSHR dat 0x0d +:asm_oASR dat 0x0e +:asm_oSHL dat 0x0f +:asm_oIFB dat 0x10 +:asm_oIFC dat 0x11 +:asm_oIFE dat 0x12 +:asm_oIFN dat 0x13 +:asm_oIFG dat 0x14 +:asm_oIFA dat 0x15 +:asm_oIFL dat 0x16 +:asm_oIFU dat 0x17 +:asm_oADX dat 0x1a +:asm_oSBX dat 0x1b +:asm_oSTI dat 0x1e +:asm_oSTD dat 0x1f + +;special Instructions +:asm_sJSR dat 0x01 +:asm_sINT dat 0x08 +:asm_sIAG dat 0x09 +:asm_sIAS dat 0x0a +:asm_sRFI dat 0x0b +:asm_sIAQ dat 0x0c +:asm_sHWN dat 0x10 +:asm_sHWQ dat 0x11 +:asm_sHWI dat 0x12 + +;label token +:asm_rop +dat 0x0000 +:asm_rA +dat 0x0000 +:asm_rB +dat 0x0000 + +:asm_intro +dat "Welcome to the inbuilt assembler of AtlasOS", 0xA, "This assembler is a port of that found in AlmOSt by Nils Ole Timm", 0xA, "To start input the decimal location of the file to assemble", 0 +:asm_done +dat "Done", 0xa, 0 +:asm_output_location +dat 0 +:asm_input_buffer +dat 0 +:asm_file_buffer +dat 0, 0, 0, 0, 0, 0 +:asm_label_storage_size +dat 0x0500 +:asm_label_storage +dat 0x9100 +:asm_labels_to_fill +dat 0x9600 +:asm_labels_to_fill_count +dat 0x0000 +:asm_program_counter +dat 0x0000 +:asm_char_counter +dat 0x0000 +:asm_param_counter +dat 0x0000 +:asm_err_comp +dat "Could not compile",10,0 +:asm_err_saddr +dat "Can not write to that address",10,0 +:asm_test +dat "SET A h0000 " +dat ":0 " +dat "SET [A+h8000] h4570 " +dat "ADD A 1 " +dat "IFG h0200 A " +dat "SET PC L0 " +dat "SET PC POP ", 0 + +;included A +;returns result in C +;returns length in X +;(ret, val*) +:asm_atoi + set Z, POP + set A, POP + set PUSH, Z + set C, 0 + set X, 0 +:asm_atoi10_loop + set J, [A] + and J, 0x00ff + ife J, 104 + set PC, asm_atoi16_loopstart + ifg J, 0x3a + set PC, POP + ifg 0x30, J + set PC, POP + mul C, 10 + set B, [A] + and B, 0x00ff + sub B, 48 + add C, B + add A, 1 + add X, 1 + set PC, asm_atoi10_loop +:asm_atoi16_loopstart + add A, 1 + add X, 1 +:asm_atoi16_loop + set J, [A] + and J, 0x00ff + set B, [A] + and B, 0x00ff + sub B, 48 + ifg 10, B + set PC, asm_atoi16_skip + ifg B, 9;If it's not between 0 and 9 assume capital letter -17+10='A'-'0'+10 + sub B, 7 + ifg B, 15; maybe small letter + sub B, 32 + ifg 10, B + set PC, POP + ifg B, 15 + set PC, POP +:asm_atoi16_skip + shl C, 4 + add C, B + add A, 1 + add X, 1 + set PC, asm_atoi16_loop + +:asm_die + SET A, asm_input_buffer + IAQ 1 + JSR [0x1027] ; keyboard_unregister + IAQ 0 + jsr newline + set a, asm_done + jsr text_out + JSR [0x1005] ; proc_kill_me +:asm_end \ No newline at end of file diff --git a/atlas.10cproj b/atlas.10cproj index 0f9ab00..cf489cc 100644 --- a/atlas.10cproj +++ b/atlas.10cproj @@ -26,6 +26,7 @@ + diff --git a/kernel/HAT_driver.dasm16 b/kernel/HAT_driver.dasm16 index 35caaa7..f5bb865 100644 --- a/kernel/HAT_driver.dasm16 +++ b/kernel/HAT_driver.dasm16 @@ -732,7 +732,6 @@ DIV B, [floppy_words_per_sector] ; divide position of hat sector in words by num SET C, EX DIV A, [floppy_words_per_sector] ADD A, C -SUB A, 1 ; returns to A the floppy sector that the hat sector lies in SET C, POP SET B, POP SET PC, POP @@ -743,7 +742,6 @@ SET PC, POP SET PUSH, B SET PUSH, A JSR HAT_sector_position -ADD A, 1 SET B, A SET A, POP MUL A, [HAT_sector_size] diff --git a/kernel/core.dasm16 b/kernel/core.dasm16 index 097ced9..85e33be 100644 --- a/kernel/core.dasm16 +++ b/kernel/core.dasm16 @@ -46,13 +46,14 @@ SET [keyboard_buffers_exclusive], 0 JSR keyboard_unregister_all ;Format Disk and Create root directory -JSR HAT_format_disk_256 -JSR HAT_inode_directory_create +;JSR HAT_format_disk_256 +;JSR HAT_inode_directory_create ; OS ready message SET A, text_start_ok JSR text_out + ; Set the interrupt handler last since booting has finished IAS kernel_interrupt_handler ; Main kernel loop @@ -100,4 +101,4 @@ dat " dat " " dat " " dat " " -:api_padding_end \ No newline at end of file +:api_padding_end \ No newline at end of file diff --git a/kernel/interrupts.dasm16 b/kernel/interrupts.dasm16 index 3a77057..858dff3 100644 --- a/kernel/interrupts.dasm16 +++ b/kernel/interrupts.dasm16 @@ -40,21 +40,9 @@ jsr driver_keyboard SET PC, POP -:kernel_interrupt_handler_clock - SET PUSH, C - SET PUSH, B - SET PUSH, A - - SET A, 0 - SET B, 0 - SET C, 0x5000 - JSR kernel_interrupt_debug_clock_ticker - - SET A, POP - SET B, POP - SET C, POP - +:kernel_interrupt_handler_clock JSR proc_suspend_interrupt + :kernel_interrupt_handler_clock_skip_suspend SET PC, POP diff --git a/make.dasm16 b/make.dasm16 index ec91991..4c45170 100644 --- a/make.dasm16 +++ b/make.dasm16 @@ -16,6 +16,7 @@ ; Apps .include "apps/AtlasShell.dasm16" .include "apps/AtlasText.dasm16" +.include "apps/asm.dasm16 .include "apps/apps.dasm16" ; Virtual Filesystem From 6ea0f6b6a4e291139aab67847889508de0735bf3 Mon Sep 17 00:00:00 2001 From: bungao Date: Wed, 31 Oct 2012 18:51:29 +1100 Subject: [PATCH 11/13] added a virtual machine program - hello word is the example at the moment --- apps/apps.dasm16 | 1 + apps/dcpu-vm.dasm16 | 397 ++++++++++++++++++++++++++++++++++++++ atlas.10cproj | 2 + misc/dcpu-vm.dasm16 | 408 ++++++++++++++++++++++++++++++++++++++++ misc/hello_world.dasm16 | 15 ++ 5 files changed, 823 insertions(+) create mode 100644 apps/dcpu-vm.dasm16 create mode 100644 misc/dcpu-vm.dasm16 create mode 100644 misc/hello_world.dasm16 diff --git a/apps/apps.dasm16 b/apps/apps.dasm16 index 361d42f..ea7a578 100644 --- a/apps/apps.dasm16 +++ b/apps/apps.dasm16 @@ -5,4 +5,5 @@ :application_table :app1 dat "AtlasText", 0, AtlasText, AtlasText_end :app2 dat "AtlasShell", 0, AtlasShell, AtlasShell_end +:app3 dat "dcpu_vm", 0, dcpu_vm, dcpu_vm_end :application_table_end diff --git a/apps/dcpu-vm.dasm16 b/apps/dcpu-vm.dasm16 new file mode 100644 index 0000000..ddd9c62 --- /dev/null +++ b/apps/dcpu-vm.dasm16 @@ -0,0 +1,397 @@ +; -------------------------------------------- +; Title: virtual +; Author: bungao +; Date: 28/10/2012 +; Version: +; -------------------------------------------- + +;dcpu virtual machine + +;memory based registers +;no hardware interupts +set [reg_pc], code +set pc, virtual_machine_start +:regs_AJ dat 0, 0, 0, 0, 0, 0, 0, 0 +:reg_SP dat 0 +:reg_PC dat 0 +:reg_EX dat 0 + +:val_nw dat 0 +:val_A dat 0 +:val_B dat 0 +:val_op dat 0 +:val_word dat 0 +:addr_source dat 0 +:addr_dest dat 0 +:mem_start dat 0 +:mem_end dat 0 +:cyclecounter dat 0 +:skipflag dat 0 + +:virtual_machine_start +add [cyclecounter], 1 +set a, [reg_PC] +set [val_word], [a] +set a , [val_word] +and a, 0x1f +set [val_op], a +set a, [val_word] +and a, 0x3e0 +set [val_B], a +set a, [val_word] +and a, 0xfc00 +set [val_A], a + +:decode_val_A + set a, [val_A] + shr a, 10 + ifl a, 8 + set pc, decode_val_A_1 + ifl a, 0x10 + set pc, decode_val_A_2 + ifl a, 0x18 + set pc, decode_val_A_3 + ife a, 0x1f + set pc, decode_val_A_nw + ife a, 0x1e + set pc, decode_val_A_nwr + ifg a, 0x1a + ifl a, 0x1e + set pc, decode_val_A_SPPCEX + ife a, 0x1a + set pc, decode_val_A_pick + ife a, 0x19 + set pc, decode_val_A_peek + ife a, 0x18 + set pc, decode_val_A_pop + ifg a, 0x1f + set pc, decode_val_A_lit + +:decode_val_A_1 + set b, regs_AJ + add b, a + set [addr_source], b + set pc, decode_val_B + +:decode_val_A_2 + set b, regs_AJ + sub a, 0x8 + add b, a + set [addr_source], [b] + set pc, decode_val_b + +:decode_val_A_3 + set b, [reg_PC] + set b, [b+1] ; next word value + sub a, 0x10 + set c, [a + regs_AJ] ; c = register value + add b, c + set [addr_source], b + add [reg_PC], 1 + set pc, decode_val_B + +:decode_val_A_SPPCEX + set b, reg_SP + sub a, 0x1b + add b, a + set [addr_source], b + set pc, decode_val_B + +:decode_val_A_nw + set b, [reg_PC] + add b, 1 + set [addr_source], b + add [reg_PC], 1 + set pc, decode_val_B + +:decode_val_A_nwr + set b, [reg_PC] + set [addr_source], [b + 1] + add [reg_PC], 1 + set pc, decode_val_B + +:decode_val_A_pop + set b, [reg_sp] + set [addr_source], b + add [reg_sp], 1 + set pc, decode_val_B + +:decode_val_A_peek + set [addr_source], [reg_sp] + set pc, decode_val_B + +:decode_val_A_pick + set c, [reg_PC] + set c, [c+1] + set b, [reg_sp] + add b, c + set [addr_source], b + set pc, decode_val_B + +:decode_val_A_lit + sub a, 0x20 + add a, lit_table + set [addr_source], a + set pc, decode_val_B + + + + + + + + +:decode_val_B + set a, [val_B] + shr a, 5 + + ifl a, 8 + set pc, decode_val_B_1 + ifl a, 0x10 + set pc, decode_val_B_2 + ifl a, 0x18 + set pc, decode_val_B_3 + ife a, 0x1f + set pc, op_end + ife a, 0x1e + set pc, decode_val_B_nwr + ifg a, 0x1a + ifl a, 0x1e + set pc, decode_val_B_SPPCEX + ife a, 0x1a + set pc, decode_val_B_pick + ife a, 0x19 + set pc, decode_val_B_peek + ife a, 0x18 + set pc, decode_val_B_push + ifg a, 0x1f + set pc, op_end + +:decode_val_B_1 + set b, regs_AJ + add b, a + set [addr_dest], b + set pc, decode_val_op + +:decode_val_B_2 + set b, regs_AJ + sub a, 0x8 + add b, a + set [addr_dest], [b] + set pc, decode_val_op + +:decode_val_B_3 + set b, [reg_PC] + set b, [b+1] ; next word value + sub a, 0x10 + set c, [a + regs_AJ] ; c = register value + add b, c + set [addr_dest], b + add [reg_PC], 1 + set pc, decode_val_op + +:decode_val_B_nwr + set b, [reg_PC] + set [addr_dest], [b+1] + add [reg_PC], 1 + set pc, decode_val_B + +:decode_val_B_SPPCEX + set b, reg_SP + sub a, 0x1b + add b, a + set [addr_dest], b + set pc, decode_val_op + +:decode_val_B_push + sub [reg_sp], 1 + set [addr_dest], [reg_sp] + set pc, decode_val_B + +:decode_val_B_peek + set [addr_dest], [reg_sp] + set pc, decode_val_B + +:decode_val_B_pick + set c, [reg_PC] + set c, [c+1] + set b, [reg_sp] + add b, c + set [addr_dest], b + set pc, decode_val_B + + +:decode_val_op + ife [skipflag], 1 + set pc, op_end_skipped + + set b, [addr_dest] + set c, [addr_source] + set a, [val_op] + + ife a, 0 + set pc, decode_val_op_special + + ifg a, 0xf + ifl a, 0x18 + set pc, decode_val_op_if + ife a, 0x1a + set pc, decode_val_op_adx + ife a, 0x1b + set pc, decode_val_op_sbx + ife a, 0x1e + set pc, decode_val_op_sti + ife a, 0x1e + set pc, decode_val_op_std + +sub a, 1 +mul a, 2 +add a, decode_val_op_table +set ex, [reg_EX] +set pc, a + +:decode_val_op_adx + set ex, [reg_EX] + adx [b], [c] + set pc, op_end + +:decode_val_op_sbx + set ex, [reg_EX] + adx [b], [c] + set pc, op_end + +:decode_val_op_sti + sti [b], [c] + add [regs_AJ + 7], 1 + add [regs_AJ + 8], 1 + set pc, op_end + +:decode_val_op_std + sti [b], [c] + sub [regs_AJ + 7], 1 + sub [regs_AJ + 8], 1 + set pc, op_end + +:decode_val_op_special + ifn [val_b], 0x20 + set pc, op_end + sub [reg_sp], 1 + set a, [reg_sp] + set c, [reg_PC] + add c, 1 + set [a], c + set b, [addr_source] + set b, [b] + sub b, 1 + set [reg_pc], b + set pc, op_end + + +:decode_val_op_if +sub a, 0x10 +mul a, 5 +add a, decode_val_op_table_if +set ex, [reg_EX] +set pc, a + +:decode_val_op_if_false + set [skipflag], 1 + set pc, op_end + +:decode_val_op_if_true +:op_end_skipped +set [skipflag], 0 + +:op_end + +set [reg_EX], EX +ife [skipflag], 0 +ifn [addr_dest], reg_PC +add [reg_PC], 1 + +ife [skipflag], 1 +add [reg_pc], 1 +set pc, virtual_machine_start + +:decode_val_op_table + SET [b], [c] + set pc, op_end + ADD [b], [c] + set pc, op_end + SUB [b], [c] + set pc, op_end + MUL [b], [c] + set pc, op_end + MLI [b], [c] + set pc, op_end + DIV [b], [c] + set pc, op_end + DVI [b], [c] + set pc, op_end + MOD [b], [c] + set pc, op_end + MDI [b], [c] + set pc, op_end + AND [b], [c] + set pc, op_end + BOR [b], [c] + set pc, op_end + XOR [b], [c] + set pc, op_end + SHR [b], [c] + set pc, op_end + ASR [b], [c] + set pc, op_end + SHL [b], [c] + set pc, op_end + +:decode_val_op_table_if + IFB [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFC [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFE [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFN [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFG [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFA [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFL [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFU [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + +:lit_table +dat 0xffff, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E + + +:code +set a, 1 +jsr code3 +set a, 2 + +:code2 +dat code +:code3 +set a, 5 +set pc, pop + + + + + + + + + + diff --git a/atlas.10cproj b/atlas.10cproj index 7fdafa8..2ccc46a 100644 --- a/atlas.10cproj +++ b/atlas.10cproj @@ -25,6 +25,8 @@ + + diff --git a/misc/dcpu-vm.dasm16 b/misc/dcpu-vm.dasm16 new file mode 100644 index 0000000..719defd --- /dev/null +++ b/misc/dcpu-vm.dasm16 @@ -0,0 +1,408 @@ +; -------------------------------------------- +; Title: virtual +; Author: bungao +; Date: 28/10/2012 +; Version: +; -------------------------------------------- + +;dcpu virtual machine + +;memory based registers +;no hardware interupts +:dcpu_vm +set [reg_pc], [code_start] +JSR [0x100f] ; page allocate for stack +add a, 1024 +set [reg_sp], a + +; Register our buffer with the driver, to remove kernel screen access +IAQ 1 + SET A, dcpu_vm_input + ; And ask for exclusive keyboard access + SET B, 1 + JSR [0x1026] ; keyboard_register +IAQ 0 + +:virtual_machine_start +add [cyclecounter], 1 +ife [reg_pc], [code_end] + set pc, virtual_machine_end +set a, [reg_PC] +set [val_word], [a] +set a , [val_word] +and a, 0x1f +set [val_op], a +set a, [val_word] +and a, 0x3e0 +set [val_B], a +set a, [val_word] +and a, 0xfc00 +set [val_A], a + +:decode_val_A + set a, [val_A] + shr a, 10 + ifl a, 8 + set pc, decode_val_A_1 + ifl a, 0x10 + set pc, decode_val_A_2 + ifl a, 0x18 + set pc, decode_val_A_3 + ife a, 0x1f + set pc, decode_val_A_nw + ife a, 0x1e + set pc, decode_val_A_nwr + ifg a, 0x1a + ifl a, 0x1e + set pc, decode_val_A_SPPCEX + ife a, 0x1a + set pc, decode_val_A_pick + ife a, 0x19 + set pc, decode_val_A_peek + ife a, 0x18 + set pc, decode_val_A_pop + ifg a, 0x1f + set pc, decode_val_A_lit + +:decode_val_A_1 + set b, regs_AJ + add b, a + set [addr_source], b + set pc, decode_val_B + +:decode_val_A_2 + set b, regs_AJ + sub a, 0x8 + add b, a + set [addr_source], [b] + set pc, decode_val_b + +:decode_val_A_3 + set b, [reg_PC] + set b, [b+1] ; next word value + sub a, 0x10 + set c, [a + regs_AJ] ; c = register value + add b, c + set [addr_source], b + add [reg_PC], 1 + set pc, decode_val_B + +:decode_val_A_SPPCEX + set b, reg_SP + sub a, 0x1b + add b, a + set [addr_source], b + set pc, decode_val_B + +:decode_val_A_nw + set b, [reg_PC] + add b, 1 + set [addr_source], b + add [reg_PC], 1 + set pc, decode_val_B + +:decode_val_A_nwr + set b, [reg_PC] + set [addr_source], [b + 1] + add [reg_PC], 1 + set pc, decode_val_B + +:decode_val_A_pop + set b, [reg_sp] + set [addr_source], b + add [reg_sp], 1 + set pc, decode_val_B + +:decode_val_A_peek + set [addr_source], [reg_sp] + set pc, decode_val_B + +:decode_val_A_pick + set c, [reg_PC] + set c, [c+1] + set b, [reg_sp] + add b, c + set [addr_source], b + set pc, decode_val_B + +:decode_val_A_lit + sub a, 0x20 + add a, lit_table + set [addr_source], a + set pc, decode_val_B + + + + + + + + +:decode_val_B + set a, [val_B] + shr a, 5 + + ifl a, 8 + set pc, decode_val_B_1 + ifl a, 0x10 + set pc, decode_val_B_2 + ifl a, 0x18 + set pc, decode_val_B_3 + ife a, 0x1f + set pc, op_end + ife a, 0x1e + set pc, decode_val_B_nwr + ifg a, 0x1a + ifl a, 0x1e + set pc, decode_val_B_SPPCEX + ife a, 0x1a + set pc, decode_val_B_pick + ife a, 0x19 + set pc, decode_val_B_peek + ife a, 0x18 + set pc, decode_val_B_push + ifg a, 0x1f + set pc, op_end + +:decode_val_B_1 + set b, regs_AJ + add b, a + set [addr_dest], b + set pc, decode_val_op + +:decode_val_B_2 + set b, regs_AJ + sub a, 0x8 + add b, a + set [addr_dest], [b] + set pc, decode_val_op + +:decode_val_B_3 + set b, [reg_PC] + set b, [b+1] ; next word value + sub a, 0x10 + set c, [a + regs_AJ] ; c = register value + add b, c + set [addr_dest], b + add [reg_PC], 1 + set pc, decode_val_op + +:decode_val_B_nwr + set b, [reg_PC] + set [addr_dest], [b+1] + add [reg_PC], 1 + set pc, decode_val_op + +:decode_val_B_SPPCEX + set b, reg_SP + sub a, 0x1b + add b, a + set [addr_dest], b + set pc, decode_val_op + +:decode_val_B_push + sub [reg_sp], 1 + set [addr_dest], [reg_sp] + set pc, decode_val_op + +:decode_val_B_peek + set [addr_dest], [reg_sp] + set pc, decode_val_op + +:decode_val_B_pick + set c, [reg_PC] + set c, [c+1] + set b, [reg_sp] + add b, c + set [addr_dest], b + set pc, decode_val_op + + +:decode_val_op + ife [skipflag], 1 + set pc, op_end_skipped + + set b, [addr_dest] + set c, [addr_source] + set a, [val_op] + + ife a, 0 + set pc, decode_val_op_special + + ifg a, 0xf + ifl a, 0x18 + set pc, decode_val_op_if + ife a, 0x1a + set pc, decode_val_op_adx + ife a, 0x1b + set pc, decode_val_op_sbx + ife a, 0x1e + set pc, decode_val_op_sti + ife a, 0x1e + set pc, decode_val_op_std + +sub a, 1 +mul a, 3 +add a, decode_val_op_table +set ex, [reg_EX] +set pc, a + +:decode_val_op_adx + set ex, [reg_EX] + adx [b], [c] + set pc, op_end + +:decode_val_op_sbx + set ex, [reg_EX] + adx [b], [c] + set pc, op_end + +:decode_val_op_sti + sti [b], [c] + add [regs_AJ + 7], 1 + add [regs_AJ + 8], 1 + set pc, op_end + +:decode_val_op_std + sti [b], [c] + sub [regs_AJ + 7], 1 + sub [regs_AJ + 8], 1 + set pc, op_end + +:decode_val_op_special + ifn [val_b], 0x20 + set pc, op_end + sub [reg_sp], 1 + set a, [reg_sp] + set c, [reg_PC] + add c, 1 + set [a], c + set b, [addr_source] + set b, [b] + sub b, 1 + set [reg_pc], b + set pc, op_end + + +:decode_val_op_if +sub a, 0x10 +mul a, 5 +add a, decode_val_op_table_if +set ex, [reg_EX] +set pc, a + +:decode_val_op_if_false + set [skipflag], 1 + set pc, op_end + +:decode_val_op_if_true + +:op_end + +set [reg_EX], EX +ife [skipflag], 0 +ifn [addr_dest], reg_PC +add [reg_PC], 1 + +ife [skipflag], 1 +add [reg_pc], 1 + +set pc, virtual_machine_start + +:op_end_skipped +set [reg_EX], EX + +add [reg_pc], 1 +set [skipflag], 0 +set pc, virtual_machine_start + +:decode_val_op_table + SET [b], [c] + set pc, op_end + ADD [b], [c] + set pc, op_end + SUB [b], [c] + set pc, op_end + MUL [b], [c] + set pc, op_end + MLI [b], [c] + set pc, op_end + DIV [b], [c] + set pc, op_end + DVI [b], [c] + set pc, op_end + MOD [b], [c] + set pc, op_end + MDI [b], [c] + set pc, op_end + AND [b], [c] + set pc, op_end + BOR [b], [c] + set pc, op_end + XOR [b], [c] + set pc, op_end + SHR [b], [c] + set pc, op_end + ASR [b], [c] + set pc, op_end + SHL [b], [c] + set pc, op_end + +:decode_val_op_table_if + IFB [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFC [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFE [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFN [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFG [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFA [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFL [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + IFU [b], [c] + set pc, decode_val_op_if_true + set pc, decode_val_op_if_false + +:lit_table +dat 0xffff, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E + + +:regs_AJ dat 0, 0, 0, 0, 0, 0, 0, 0 +:reg_SP dat 0 +:reg_PC dat 0 +:reg_EX dat 0 + +:val_nw dat 0 +:val_A dat 0 +:val_B dat 0 +:val_op dat 0 +:val_word dat 0 +:addr_source dat 0 +:addr_dest dat 0 +:code_start dat hello +:code_end dat hello_world +:cyclecounter dat 0 +:skipflag dat 0 +:dcpu_vm_input dat 0, 0 + +:virtual_machine_end +IAQ 1 +set a, dcpu_vm_input +JSR [0x1027] ; keyboard_unregister +IAQ 0 +JSR [0x1005] ; proc_kill_me + + +:dcpu_vm_end + diff --git a/misc/hello_world.dasm16 b/misc/hello_world.dasm16 new file mode 100644 index 0000000..81ba5d4 --- /dev/null +++ b/misc/hello_world.dasm16 @@ -0,0 +1,15 @@ +; -------------------------------------------- +; Title: hello_world +; Author: russell +; Date: 30/10/2012 +; Version: +; -------------------------------------------- + +:hello +set a, hello_world +set b, [video_mem] + +JSR text_out ; +:hello_world +dat "Hello World", 0xA, 0 +:hello_end \ No newline at end of file From be9ff25e6cb40321d67aa07c94b8ad63fb3a76e2 Mon Sep 17 00:00:00 2001 From: bungao Date: Thu, 1 Nov 2012 22:54:15 +1100 Subject: [PATCH 12/13] updated bios to new m35fd spec --- kernel/HAT_driver.dasm16 | 32 +++---- kernel/core.dasm16 | 4 +- kernel/drivers.dasm16 | 47 +++++----- kernel/filesystem.dasm16 | 118 ------------------------ kernel/floppy.dasm16 | 187 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 220 insertions(+), 168 deletions(-) create mode 100644 kernel/floppy.dasm16 diff --git a/kernel/HAT_driver.dasm16 b/kernel/HAT_driver.dasm16 index f5bb865..4dc1b78 100644 --- a/kernel/HAT_driver.dasm16 +++ b/kernel/HAT_driver.dasm16 @@ -22,7 +22,7 @@ SET [HAT_header_in_paging], 1 SET A, 0 SET B, 6 -JSR filesystem_read_disk_sectors +JSR pfloppy_read_sectors SET I, [floppy_paging_address] SET J, HAT_header STI [J], [I] @@ -50,7 +50,7 @@ SET PUSH, B SET A, 0 SET B, 6 -JSR filesystem_write_disk_sectors +JSR pfloppy_write_sectors SET [HAT_header_in_paging], 0 SET B, POP SET A, POP @@ -60,7 +60,7 @@ SET PC, POP ;with a 256 sector size :HAT_format_disk_256 -JSR filesystem_clear_floppy_paging +JSR pfloppy_clear_paging SET PUSH, A SET PUSH, B @@ -90,7 +90,7 @@ SET PC, POP ;with a 1024 sector size :HAT_format_disk_1024 -JSR filesystem_clear_floppy_paging +JSR pfloppy_clear_paging SET PUSH, A SET PUSH, B @@ -300,19 +300,7 @@ SET A, POP SET B, POP SET PC, POP -; clears the floppy paging space -;currently located in Atlas before the -:filesystem_clear_floppy_paging -SET PUSH, A -SET PUSH, B - -SET A, [floppy_paging_address] -SET B, 0xD00 -JSR mem_clear -SET B, POP -SET A, POP -SET PC, POP :HAT_error @@ -452,7 +440,7 @@ SET B, [HAT_sector_size] DIV B, [floppy_words_per_sector] IFE B, 0 ADD B, 1 ; number of sectors to read, atleast 1 -JSR filesystem_read_disk_sectors +JSR pfloppy_read_sectors JSR HAT_sector_offset @@ -518,7 +506,7 @@ SET B, [HAT_sector_size] DIV B, [floppy_words_per_sector] IFE B, 0 ADD B, 1 ; number of sectors to read, atleast 1 -JSR filesystem_read_disk_sectors +JSR pfloppy_read_sectors :HAT_write_sector_read_skip SET [HAT_header_in_paging], 0 @@ -548,7 +536,7 @@ SET B, [HAT_sector_size] DIV B, [floppy_words_per_sector] IFE B, 0 ADD B, 1 ; number of sectors to read, atleast 1 -JSR filesystem_write_disk_sectors +JSR pfloppy_write_sectors SET X, POP @@ -774,7 +762,7 @@ SET B, [HAT_sector_size] DIV B, [floppy_words_per_sector] IFE B, 0 ADD B, 1 ; number of sectors to read, atleast 1 -JSR filesystem_read_disk_sectors +JSR pfloppy_read_sectors SET B, POP @@ -803,7 +791,7 @@ SET B, [HAT_sector_size] DIV B, [floppy_words_per_sector] IFE B, 0 ADD B, 1 ; number of sectors to read, atleast 1 -JSR filesystem_write_disk_sectors +JSR pfloppy_write_sectors SET B, POP SET A, [HAT_write_sector_stack_A] @@ -835,7 +823,7 @@ SET B, [HAT_sector_size] DIV B, [floppy_words_per_sector] IFE B, 0 ADD B, 1 ; number of sectors to read, atleast 1 -JSR filesystem_read_disk_sectors +JSR pfloppy_read_sectors SET [HAT_header_in_paging], 0 SET A, [HAT_read_sector_stack_A] diff --git a/kernel/core.dasm16 b/kernel/core.dasm16 index 85e33be..3080e07 100644 --- a/kernel/core.dasm16 +++ b/kernel/core.dasm16 @@ -46,8 +46,8 @@ SET [keyboard_buffers_exclusive], 0 JSR keyboard_unregister_all ;Format Disk and Create root directory -;JSR HAT_format_disk_256 -;JSR HAT_inode_directory_create +JSR HAT_format_disk_256 +JSR HAT_inode_directory_create ; OS ready message SET A, text_start_ok diff --git a/kernel/drivers.dasm16 b/kernel/drivers.dasm16 index 12caac3..18b5ec5 100644 --- a/kernel/drivers.dasm16 +++ b/kernel/drivers.dasm16 @@ -21,8 +21,8 @@ IFE B, 0x12D0 ; Generic Clock (upper 16 bits) JSR bios_clock_init - IFE A, 0x4CAE ; HMD2043 floppy disc drive (lower 16 bits) - IFE B, 0x74FA ; HMD2043 floppy disc drive (upper 16 bits) + IFE A, 0x4fd5 ; M35FD floppy disc drive (lower 16 bits) + IFE B, 0x24c5 ; M35FD floppy disc drive (upper 16 bits) JSR bios_floppy_init IFN Z, 0 @@ -103,35 +103,30 @@ SET [floppy_address], Z ;Set interrupts for floppy - SET A, 5 - SET B, [floppy_address] ; Our magic word to tell the handler we have a floppy event - ADD B, 1 + SET A, 1 + SET X, [floppy_address] ; Our magic word to tell the handler we have a floppy event + ADD X, 1 HWI [floppy_address] SET A, 0 ; check if media is present HWI [floppy_address] + IFE B, 0 + SET [floppy_inserted], 1 IFE B, 0 SET PC, bios_floppy_end - - SET A, 0x0001 ;check media parameters - HWI [floppy_address] - SET [floppy_words_per_sector], B - SET [floppy_sectors], C - SET [floppy_write_locked], X - - ;check media quality - SET A, 0xFFFF - HWI [floppy_address] - SET [floppy_quality], B + + SET + IFE B, 2 + SET [floppy_write_locked], 1 ; Reserve disk paging space - SET X, [floppy_paging_address] - SET Y, X - ADD Y, [floppy_paging_size] + SET A, [floppy_paging_address] + SET B, A + ADD B, [floppy_paging_size] :bios_floppy_page_reserve JSR page_reserve - ADD X, 512 - IFN X, Y + ADD A, 1024 + IFN B, A SET PC, bios_floppy_page_reserve :bios_floppy_end SET PC, POP @@ -163,18 +158,18 @@ dat 0x0000 :floppy_address dat 0x0000 +:floppy_media_inserted +dat 0 :floppy_words_per_sector -dat 0x0000 +dat 512 :floppy_sectors -dat 0x0000 +dat 1440 :floppy_write_locked dat 0x0000 -:floppy_quality -dat 0x0000 :floppy_paging_address dat 0xEB00 :floppy_paging_size -dat 0x1000 ; 8 sectors @ 512 words/sector +dat 0x0008 ; 8 sectors :floppy_page_inuseflags dat 0x0000 ; Bit map of RAM pages in use along with flags (4 flag bits per sector) dat 0x0000 ; Bit 1 - Is active, Bit 2 - ??, Bit 3 - ??, Bit 4 - ?? diff --git a/kernel/filesystem.dasm16 b/kernel/filesystem.dasm16 index 789c9c4..4abde23 100644 --- a/kernel/filesystem.dasm16 +++ b/kernel/filesystem.dasm16 @@ -77,123 +77,5 @@ ; ######END VIRTUAL FILESYSTEM FUNCTIONS###### -; ############PHYSICAL FILESYSTEM############# -; *** Hardware Functions *** -; Returns the sector size in words -:filesystem_getsectorsize -SET A, [floppy_words_per_sector] -SET PC, POP - -; Returns the total number of sectors -:filesystem_getsectorcount -SET A, [floppy_sectors] -SET PC, POP - -; Returns the total disk size in words -:filesystem_getdisksize -SET A, [floppy_sectors] -MUL A, [floppy_words_per_sector] -SET PC, POP - -; *** Software Functions *** -; Returns the total FAT size in sectors -:filesystem_getFATsize - -; Returns the total number of free sectors on the disk -:filesystem_getfreespace - - -; reads a number of floppy sectors from the floppy from a starting sector in the floppy to the floppy paging space -; A --> start sector -; B --> number of sectors -:filesystem_read_disk_sectors -IFG A, 1439 - SET PC, filesystem_error -IFG B, 6 - SET PC, filesystem_error - -SET PUSH, C ; push c, x, y for code safety -SET PUSH, X -SET PUSH, Y - -SET PUSH, B ; store A and B -SET PUSH, A - -SET A, 0x002 ; query device flags -HWI [floppy_address] -SET Y, B ; store flags - -AND A, 0xFFFE ; set device to blocking mode -SET B, A -SET A, 0x0003 -HWI [floppy_address] - -SET A, 0x0010 ; read sector interrupt -SET B, PEEK ; start at sector given by A -SET C, PICK 1 ; read a number of sectors given by B -SET X, [floppy_paging_address] -HWI [floppy_address] - -IFG A, 0 - SET PC, filesystem_error - -SET B, Y ;retrieve flags -SET A, 0x3 ; reset flags -HWI [floppy_address] - -SET A, POP -SET B, POP -SET Y, POP -SET X, POP -SET C, POP -SET PC, POP - -; Writes a number of floppy sectors from the floppy paging space to a starting sector on the floppy. -; A --> start sector -; B --> number of sectors -:filesystem_write_disk_sectors -IFG A, 1439 - SET PC, filesystem_error -IFG B, 6 - SET PC, filesystem_error - -SET PUSH, C ; push c, x, y for code safety -SET PUSH, X -SET PUSH, Y - -SET PUSH, B ; store A and B -SET PUSH, A - -SET A, 0x002 ; query device flags -HWI [floppy_address] -SET Y, B ; store flags - -AND A, 0xFFFE ; set device to blocking mode -SET B, A -SET A, 0x0003 -HWI [floppy_address] - -SET A, 0x0011 ; write sector interrupt -SET B, POP ; start at a sector given by a -SET C, POP ; write a number of 512 word sectors -SET X, [floppy_paging_address] -HWI [floppy_address] - -SET B, 0 -IFG A, 0 - SET PC, filesystem_error - -SET B, Y ;retrieve flags -SET A, 0x3 ; reset flags -HWI [floppy_address] - -SET Y, POP -SET X, POP -SET C, POP -SET PC, POP - -:filesystem_error -SUB PC, 1 -; ##########END PHYSICAL FILESYSTEM########### diff --git a/kernel/floppy.dasm16 b/kernel/floppy.dasm16 new file mode 100644 index 0000000..a1f85e9 --- /dev/null +++ b/kernel/floppy.dasm16 @@ -0,0 +1,187 @@ +;Floppy routines +;some code is reused between routines to conserve on space. + +; Writes a floppy sector from memory +; A --> sector +; B --> memory address +:floppy_write_sector +IFG A, 1439 + SET PC, filesystem_error + + SET PUSH, X + SET PUSH, Y + SET PUSH, C + SET PUSH, B + SET PUSH, A + +:floppy_write_sector_poll + SET A, 0 + HWI [floppy_address] + IFE B, 0 + SET PC, floppy_wr_error + IFE B, 2 + SET PC, floppy_wr_error + + IFE B, 3 + SET PC, floppy_write_sector_poll + + SET X, PEEK + SET Y, PICK 1 + SET A, 3 + HWI [floppy_address] + SET PC, floppy_wr_end + +:floppy_wr_error + SET PEEK, 0xffff + +:floppy_wr_end + SET A, POP + SET B, POP + SET C, POP + SET Y, POP + SET X, POP + SET PC, POP + +; Reads a floppy sector from the disk to memory +; A --> sector +; B --> memory address +:floppy_read_sector +IFG A, 1439 + SET PC, filesystem_error + + SET PUSH, X + SET PUSH, Y + SET PUSH, C + SET PUSH, B + SET PUSH, A + +:floppy_read_sector_poll + SET A, 0 + HWI [floppy_address] + IFE B, 0 + SET PC, floppy_wr_error + IFN B, 2 + IFN B, 1 + SET PC, floppy_read_sector_poll + + SET X, PEEK + SET Y, PICK 1 + SET A, 2 + HWI [floppy_address] + SET PC, floppy_wr_end + +; Writes a number of floppy sectors from memory +; A --> start sector +; B --> start memory address +: C --> number of sectors +:floppy_write_sectors + SET PUSH, C + SET PUSH, B + SET PUSH, A + +:floppy_write_sectors_loop + IFE C, 0 + SET PC, floppy_write_sectors_end + JSR floppy_write_sector + IFE A, 0xffff + SET PC, floppy_write_sectors_error + ADD A, 1 + ADD B, 512 + SUB C, 1 + SET PC, floppy_write_sectors_loop + +:floppy_wr_sectors_error + SET PEEK, 0xffff +:floppy_wr_sectors_end + SET A, POP + SET B, POP + SET C, POP + SET PC, POP + +; Reads a number of floppy sectors to memory +; A --> start sector +; B --> start memory address +: C --> number of sectors +:floppy_read_sectors + SET PUSH, C + SET PUSH, B + SET PUSH, A + +:floppy_read_sectors_loop + IFE C, 0 + SET PC, floppy_wr_sectors_end + JSR floppy_read_sector + IFE A, 0xffff + SET PC, floppy_wr_sectors_error + ADD A, 1 + ADD B, 512 + SUB C, 1 + SET PC, floppy_read_sectors_loop + + + +;Writes a number of sectors from the floppy paging space. +; A --> start sector on disk +; B --> number of sectors from paging space to write to disk +; set a to 0xffff in case of disk error +: Sets a to 0xffe in case of number of sectors being larger than the paging space +:pfloppy_write_sectors + SET PUSH, C + SET PUSH, B + SET PUSH, A + + IFG B, [floppy_paging_size] + SET PC, pfloppy_wr_sectors_error + + SET C, B + SET B, [floppy_paging_address] + JSR floppy_write_sectors + IFE A, 0xffff + SET PEEK, 0xffff + +:pfloppy_wr_sectors_end + SET A, POP + SET B, POP + SET C, POP + SET PC, POP + +:pfloppy_wr_sectors_error + SET PEEK, 0xfffe + SET PC, pfloppy_write_sectors_end + +:pfloppy_read_sectors + +;Reads a number of sectors from the floppy paging space. +; A --> start sector on disk +; B --> number of sectors from paging space to read from disk +; set a to 0xffff in case of disk error +: Sets a to 0xffe in case of number of sectors being larger than the paging space +:pfloppy_read_sectors + SET PUSH, C + SET PUSH, B + SET PUSH, A + + IFG B, [floppy_paging_size] + SET PC, pfloppy_wr_sectors_error + + SET C, B + SET B, [floppy_paging_address] + JSR floppy_read_sectors + IFE A, 0xffff + SET PEEK, 0xffff + SET PC, pfloppy_wr_sectors_end + + +:pfloppy_clear_paging +; clears the floppy paging space +SET PUSH, A +SET PUSH, B + +SET A, [floppy_paging_address] +SET B, [floppy_paging_size] +MUL B, 512 +JSR mem_clear + +SET B, POP +SET A, POP +SET PC, POP \ No newline at end of file From 5b537758443b80d6cb5487ae97a97a7a29597475 Mon Sep 17 00:00:00 2001 From: bungao Date: Tue, 29 Jan 2013 22:07:38 +1100 Subject: [PATCH 13/13] im pretty sure i did something useful and it didn't break changed paging changed kernel calls from jumps to interrupts other stuff --- Organic.exe | Bin 63488 -> 65536 bytes apps/AtlasShell.dasm16 | 213 ++++---- apps/AtlasText.dasm16 | 116 ++--- apps/asm.dasm16 | 6 +- apps/dcpu-vm.dasm16 | 155 +++--- {misc => apps}/hello_world.dasm16 | 4 +- atlas.10cproj | 18 +- build.bat | 2 +- kernel/HAT_driver.dasm16 | 85 ++-- kernel/core.dasm16 | 59 +-- kernel/drivers.dasm16 | 32 +- kernel/floppy.dasm16 | 28 +- kernel/interrupts.dasm16 | 43 +- include/kernel.inc => kernel/kernel.dasm16 | 100 ++-- kernel/library.dasm16 | 402 +++++++-------- kernel/libs.dasm16 | 4 +- kernel/memory.dasm16 | 540 ++++++++------------- kernel/process.dasm16 | 118 ++++- make.dasm16 | 11 +- misc/vfs.dasm16 | 2 +- 20 files changed, 913 insertions(+), 1025 deletions(-) rename {misc => apps}/hello_world.dasm16 (91%) rename include/kernel.inc => kernel/kernel.dasm16 (73%) diff --git a/Organic.exe b/Organic.exe index c8c154990c24104a3e371a31be0f37e5a1260b14..14f189bf956bfee4b91ff33415c448336b2ec07f 100644 GIT binary patch literal 65536 zcmeFa37lL-wLf0>_TD|)ou28Q$u^z6Nv9{1jdX?xnam8yK=uVDY)Q{dCuuU7JKUZL ziD592{jtaw`U;%eZT+z z_xb!L>FPSCPMxYcb?Vfqx>dJVop!bG2qC=qy!);Y58|8tmU8&s!G0uHG<>5%JP`W9 z$UAd ztkgW>`p;j#)-LU3p=%K>D8&B)24D2oSfdG%KqP^0svX63S#QL+{`4)jA{}`8^N6Jv z2~oxWi{A>AB;u!0O>Cez_}=JKNcY!LO_Tv%3%Utz{E^}br|L`@1iZqPr*R;+X8`bm zw-6wW+p6jfi2o93O`}z?x&d+BP)Feh@K;WDf~62hqm}D5K}dBKs58sputUO;r9vz# z#XuG$SNu`kbm0>Zd|8N_w~*|F7>Ck+{5c_BQGGykNBWC4X(9q5a5eOO33N<2CH%9d z=$;`0X4&azD$*yr(+L=sKE<6*fRm2;A^%i&Iss0)F#s_knR;< zLFJ(ehHfF!KLn9__1I7)eKo|cL^ZUqKW3o@{kQw$R)D|jEVLSMy#+dakF%ouJ>IJ4 z?+I1|e^0bf4ALiADgJH$GHVDI zQ4F~75UPdfM2bShC<%Ikl4_I4$=_gx?V|WW;YmZ^9y0miYr%i$L(8i5?7> zhmxQUr>jEN-Nbt)fY@OzrNyFt!=LtL9tLs9%`#!LjCu`k?4b2OkS&>%**H%^-$&9n zymbc+Z~S1wgKkM40|FC`3X4=PXZyk^*{G++%(jrTVOW=zHc8({y*gGl5sY`11p`;* z4|}O{&7ODPeOJoXBhZloH8q6pu^uA6=x;v{b0Nkz1%!@1MwO86?#yCu@1x%Jniv3K zq3O)2iCaG?>j5%f|obPWthm&`f9p;Pcb zI@_3?o~=rgWtvS$jd!Y&rzeraAMcbE5GkT%9z<0hif=9t#SZH>r*fGXl9`1+crc0a z=ud7$K;6r_VH5i@&tfQ`OQn8s#m~6KNF_HAHPr2@e7wkdK=`l96RtD9nQcwf?~fV& zSTH#kH4#uw!ylw{34<6tRm@)R2dF4IDRFarv&!iY2jiQ|WX*|ztbAq>S5D_nG3TKS zC7$^lWz(>ahB%s2xP)pPFakPDYp4fkeIJIVw?>J0rzo@&P0$D$UUMm;!U)F9Winy} z%r=V2Jh~Ay7jT<`ChVKvmRF4kAf*);6BaQnG9QOgQ5X~+G*3WM)C-9=G$+?1K0By$ z4O3d2`nkCr`h_w`hsP-dMjG$7fBsdtMhGwQRn-wRjt2-Z8Uu8Bz)^k*k z<3MW{Rn1IfQ8ts1^@4j4lSZe}Oqf5fF8eGATj|&LQJ7C>gGUSw*#EgVKu- z4RPDjvyD*9#5@yD9*-bB&ITJA8!Mdn7P4${GHz6A9AbH*9GPB5Y)C%&KN2tCS{;#&~D6(P%W%q(WhsAS(8A`aYUi zj1Xx{m~<+fj_dnqhEcfWCbSz7Edbsz~Pgd(JZ zx)G9Y0GC$y2q|F1h`2_I`C;IM5wUBxM}dKTG)TNEv33TA?UV|KHeZH@m`yXdYAJ zC_PPBeqSvg+M@r*TOL&X^@y=fHN@O3yH%J<$36`bK( zo6OMFqGYqZDk9To5}7n^B2z1i{@7Rw_`A_P;WiX%cqh6%*mxmNPDq_mCpS3EZRBql zaqAXht>!=;GjRj|*e!!^Lhh~fVu7@7BU+ai+k8GxK2DN*GOjo3h>^@g36fV27h7-L zWfxnV+RBGdZ4;S$y;1M3P1J^qtF`7ovx3#T*I%=p33*&RIv$FY!MYkk8E3@g`aU|r znBek@xf&r6i;mBHf(a)`Pj~KUo-X;g(qraqe#(}rE83_Mul7-6JX7hZ7Ko(Igst+& z<=i^gm>V-D+-}TG!qrJ7(U&RNFHmhb$fVliY}IaFiUqo2<;!%3sgfcUCMlazsCCkT z+d&eJMJHkfG>O*uvOU9Auu={oP zT}qyTzD6pyd7M!<-Q11}SieoOh#==PQIrT+FHpg8c2VDJ30$}sY~@l4#c-WR6vF-;yLOAD zYu6Ak8jg~wv*IawcMktZrQMlqOfIoI-Y9H?+d9}je7!NbG~xZ5jptFSFl;lSjM!*q z<6cSV?q@O^a@%GcO+NdE84T-p&?bBRFhN4fcG_#II%7iIn7|gRZnK$%1e0)4{4h6= z!3Q4v0~j6DuTx632HV1cVNB6mcYFoTe{B|oeGm+OdWG~ zY$`87kbZ>SG2%cg68G+y;~@?+hVkeWwP}W2YRAv5{>=vuzx(beBVdYc=E5*$SW)~C zleN$d?3e{G^l10pADtG9PB*4uonzD1N(zipn<5^aE=ovf`=x%E`LoCon4TVQOxuUS z>YZJQND>jr8H;OM|3=HakSYexXxdOOWr@zHiO$3h&z1AxkF)P=Os8Sq{81XPMj$44 z&}2#W60KHOMaykv*}56UTCkm9BC3{~Xr?h^UkW&5CV$PJuHc4AjpGy!QECuT#oaoY z4$?*xbjQxz&@ev=!efB3eoteOyb-(UAg+_d0b|C{*_10_%pBUuk$nX3n~gyAMDs&D z{Gk;4X!#(eLC+jgwD*}}x#&pbd}&Z5v9aWjV*4*iR@HBIk#(G(I<7|2bW}WArY@I^Y=IPPFGwdt36K z(&v|t(&xqfUbV1|s}-#=!96(El-`XfFEp!~a_9e)6^8}E$^u>4zKt8sNR4-&$Y9N1Jqk z9WFsGrtmb(p=mN4_B5Qqk%+%`ekf3D+okeQI>^JkEY;u-942!DRM-<>Po*ps_V`sy z1R)>djjGf61;b+wL3DB}_pl}(s2wSNe3MUfMNl8)uZdRIM57`Wjz#!+X&D}p0`C`@ zIiL{na3J0p2_&j8L&yh4wMK2aL0Er=rA%VM7Z%n%x*hdIYcgSEb3dkaKdXzCXPyFc zI2@?Dmmj97#j7Vo(|LFwte#g*mp1AgLZLgt@Eg`w$C6ld(jKy2?MY*u8Hkqs6m40>$e_-_&5*h?HK<82rpvBNPKWydDkS;=_R&9Ae; zEWn~+rr84dn?HuO*=6rzl4o4o)m%hUad0z|#+n~2@uFggvbqV1B{7d#x;xPwH$J|=zvDadWlB_MrYIWF&P(d<1B$aZZ$N3~f#s_U4ndeM9PkI!F1v{~n zp*$MFTcslzUS{VRjo~eJqKn~lXdG?#(V7=e3Pb8K|8#!9f#;EkWn!-;>bFrC1_~9hQBZM(3RZ^>*TQg(uMW%aSTqugmX#3BmgR9_b!Z44 z(yQ^ve9}l(!%VgwhKp(GyaJ78*j2AlovzXk`xinC1=K$rt%fzPrd_C%X%bwQ+6iaB zpQ7b3JU*AlQ=e+8u9qH9g;Bw3YLuJjl0-=>d99&@k*2j|S*jfL?8=aWK7nCdKirk6 zGhsO7u)Y+}1?p&uBH|z_u?8u4EZmsv@~iT8epXV_;k1X=ESur)bN<&zm1AK=W>Zt% zcoM_S<&?YAuo^Ui@J`fNXO>l|b~kKP z7H9ohl`wrDreJS;^D{&AjRQ-a>{3hjWYDN&DIc-UnZcg$$TDXo+m zf0TufrBm4XI|f6=t~0E+S~7EQR?sN2(_FJptT-HL0NeI8YLhyn+M#pp4!DU_&gRQe zj#CilcFjv^b8Pzx6XBTg;lAG{RgzucuntkyW#n)z)`W7vCXDa04FYO8Qs--{MCNJe>M(xO9e&NXlkh>`8TFMCMg2h>60?!!QnWX|*~yoVK+uFkJ7!`n zH#P~-O)0c<77&D$ZYrM#)?QXK7YiA>qZ`cHG% zsNJRaUw>FEH6{I$1v^EG@pHo-NK)Zo+>dM`Aq1y~vz4frH5hEBkT2Or?^ zSbHCj?=l*HF`P6t4}fcVs;t_R{3v1(f1opr_ytrJjufR|!;IxQ9Gm1S$X}M?b-ac% z9y&(y#H3_D9%qn0RW1bn8=}y~V>)i0PLrUY7w6^{irb@J-v_2_cX7T3YjRIvKaz34 zjL>?(ybx6o0ji(BN)w*aN3F=xd>`6@8tj9S@tPM=g`+96I-0x~(K6ww){~bYCRdI0 zoR$}-_Qn()>PasZ9>sSBDAfa(@=(ZJN}zn!TkZ#=O96-Ie4(G7MWa1YFzXevHq& z378`P7h#$`);q&18uHZfv-2v=V|l#FKU4K=z8+OTzb-`?^}PMVwKvcZ)%_5_g~T^5 ziQJEYzz{R2-Qv~}lL;@$Hx8%3vAODM0( zkI8inXyMMg*v76aHgPUeJyu{?Z=}}>S6}^-9x%Zy_wxfLK44#iJ)|p9%~3k(7a@ql zkLRJbmS=tdjK?Y;UdHZX88{JNT1XPhbr>z2jIF7zVYe_{R$Y6zb}|NrQ43R3le`MW z7d}RHsI9I|UTs$fcTA+hq$>RIC}|~9tVt`^1Y2jt0&$Y;AcXV~BL>}TCFF>Tu!k+4JJO&$l0lbsTa+J-kLFiPTgyhK)iDQ};=Cxiq3W2CzDa zhEo&p1@8h=jLd6(92u}EB9bo}VdX6lROups{}RTYhVVq=G3=78!Ncl0c@UZoem10v zBL+{}c~w9h{08hTRTW-IEy&VEGD-qZ96A66&WEV8H>x7H8t52)Vnu99rJD#~XrYPJ zaIQSuAilsblJqYyo9GA@QMf1~m{FI?{TM_ZIf2we?@Ia`CC7`(`I#c+)KMs7MauKo zUKh7SZ7sv)6j*k75`hPlJukGPN>!RX2retb=fLfJ$(o8(&>o9^-sw{8Zv=a27Hq3sAZ8C~NvccGOh^;o6+WJ? z>cBdR-LWyvVh`wyir7Iuwmmy)RKySRy)s+q%3!Cb;%RY3-9g^a3#<7t=b9fUFrP7t zc?V+@3{Vcux6#TXvuKrUDb8V@g(RF2rY}B+WFDkuBY`I8*&!rRBt4ZY*+Q1!3=pVF zci1p`$gXs$n(jp%C@Y=7SbQ3Q!_o71L!!-7G2$Cy1x(T5>3rEPmb{tc(ChxVibMAO zbt;azslQ&u@kphAoQl^YK3>J=B0fRI7a~4U#TO$!NyV{5>c{N}S=c%P!U{N*fQSOl zB%n+InCbc($`#N}K!pO%A)rzLI|-;#0LiMsPyh+4p;`gc35Y5HPE3D8jRH~x)G}~5 zx}W5v#AVcDYvmTmXK@T3t}(7X278I#7nAWpiv$d;z#JmTJ^3;|Kf>pAd;$2A|}FvUX4#bKG))t`4R%``tV~HC_pEm)0Em}?iiVNx}A2($TaMC zplWzVwR2<|wvA-knvrP@4O_bGWccyJtApfjJJ}eSj6lF1aG77hY`#v zA^15Hz&NnY=iLdiHARSxk=(Sh8+P{*^N?*Q$&=b`*CIAItaK?}(w5XlhoY%`bc%Tn z#bMp1IIL$&3o3Vvc+^N?C23$V8OAK^=}dqb6z7Wl|7kA`2fZ^siA@takKW`L^@z}s zZISsC+9ztmwYX>)D^HzHJ6srB;fAD~u;C-8YvogMc}|7A=CmHd(ozu~QzWe8Q$ax( zMw-2d&?iEX6fCjYky;AQnCB_w27hg1@fkCA>wt^PWhLJxm5w5gbox{Mx(C-71Nf-p zWo+7=XR4GF>l_d+R}Z4G=%Mi&4ORz}pF)uyJSFDU4WBqEU2Rgq&40&nCoH;{uOHiD zeu$8tW5XPg01Z58j$xlA>WxKxsgrTiU2Z#-iD1KA*;=|H8wmKfJ`+hb1RI))NZ5Zo z+6c&}TSlP#&lsWpyi;QM<%|DnWg9Kl%zDfFXE0Jh36u4a%J_s)@$OnYv)dgJ8E_=c$tB4Fd{OSLTCnhD~jt~9u#Yr z)-Yv0u27;NpPj{r8>m{jlRi_{!%4>BPf{eWL$GgHMLqGT&q*8_o`^=HN~j0ASS~Xm zWZGbP8{G{@k{nbcY=rnkF5w>p-p^7-sX(L`ih6l&88@k79=~jQe6!p+xZNm=2N2Ye zcCvZ_hz3)>8U$DZN*(eDdiHAYf7NG!STvX+V}XyZJIVrk*dv=4WN7Q46R|N3rE8rJB(_j zVT8FV5Iiz8FQ!K?2KLVQHm$shP53`U@K6-8UjA9*q4Q_LSH__m+;zVd>KRVLW5APh zXC;k;rRg$}Ob|9RAG9@*nzEYmnkbI?`S^NN)E|$MoMX|DTa9cEcJ)q0+;;WOMBH}ub|P-OdgmZ+yLuNOZo7J)M%;Gw zzK*!#>V1;{+tqu90Nd632?4gN_c{T#tLO6puwA|B1lX=#I{~(1lEdl#z!H-+<`1+|G^)?l_@>XN z@%aKiU&H4~^?4fK^m$Qzd{7RWis>^&eP-c%AwDPLlf{R&>NA%jkXruIsu1g8ymNXq zau-9Ugjo!A!Mcb)4Ux+1tS@Ejv|>0-369s2HhZ@nUIf7)61D$5p^JEEr2*|-HH-o zUnavu#o=geLgk#+@FdLxFjL8d$?-JKUpg6eb%>(=%zr?dFnO7O$9M7$RCPw?7l^VL zq+IA0C^A-aBb}_~4931KHxq0bk~aw2SBGI|GWN%WEi0@AK#N?RuGiu&Q3VY08jgkc zp^m&UOX4;lQi5TzE6h7th!wOkDLZ4Lur{N;xQ+WUd~s`4Z{(?%3KIwO=q`4Jxe^hY z0EwsXrIV2g3wdbL3}L-KIs-a40HRhAPzz+vX_Q4$bAqLqvecN>$h<;Z7>)&p)rIv2 zqvp5%>)m$)X*|c4tY})`)(Wd3fQD?NhGya>U94e8D$eWBAfl z0l5c2E;JfybA-A+3Gx8nnQ{pzvjWWR;<@Y=+;<_P?A*bj3QZJ&!e_v-cq6zH9yD|z z4B3<=??yyk6s{C0I3v+YIb&2C>V|De3Ap2LR0d3p5OS}p2(sQnFz&lO(PlI4sk>S1bcH62@7LGGV-8$b%mV$^U_JWN#s5 z`&dOC`vHq0hO{l~FD;51crP`OG^rAP0G_5yI~+r=I8RexKx%5DwZV}+8Vc6Q+upb| z?nn*ID3w|cB||m2geysfNtA?)&WJ^4ruvK-#?0%YF+BCgA>wF_5lh}j6^i5hzZzsg zoQwH9aAK4?7)C8l(iw4Fn1Fr9J?wb$i}>cp6WGGMA93?blpu_maByZCxCLMjo%DrV zRj2*!qqd(tk7!*e9l%>EXf(uF$3upZgl^GQMnW?V$HbEG3Bw|!8VnO3Dm(xTZ8~9t zmTQ80gkO<0a^&(;%x=P3fxcB5V5o-=q)yRs)^4O2x4Qwu(CG#C-nerXUXAz1BqmztD){7{`?F`e(Lt^EdGp0~iO#<^tZoU{dkisYh zl1{j7#4T78jIoKny+zKI7q1d<)+%;T!W0 z{}KLbcxk`KH@yzbjsFDTv&oE?74hSn@DLWXSc~9EEen$-VFXa>!NzJN`@cdLRLae89q+um#c!Tm843@}gkKrv7pkzZw zi0`88$S^DK@SNxH42I65sVn(SYS~f*oed%89Vp=)DdA05G{@qd`3pKyvBzqlfGuKr zFO{FQm-qXM>f5{u9aECj2C=ecH_scMw9-k64^P_YB)yGZEn(Q@B>i%DlI0{lH9YB~ zP7+OZB@C~1lCB<}bgP||-cyq0UI)Lm1m9s_@Jz2L!GG1EZz{n%uZBq1mEh@EJPQps z_58L6ql_(7q4{~p%jpPu<(Jf>kCWOPzM%CTln12a!m#_ohUfysRoRq6B5@_*5~L5Nh@>@8!iDp z>hw>n?W|$7H3FT_994~_Pe9uk^cpVg*Rex`jiXTKb&|nzY&a9TJnA%Nm)Yj-|Ep0Z zm6Uuy(zte#EBPGcNbuu&!eTes2hCDR^h!(rm}3;nwkWABy$0~Thb|j^d-iGm``_4w z7&b}xaTEgUwOK7If7wHORQ z7QNPRs?3^z-jlm7IRCX2BX!(iFXrXf{CvDHk`e*Dqtzn@kRN;c_WUb!`Ly9AdfIRu zrarC6l{1zp)aq2%zvO-}jVcsS*a@x8+HL4&UJS~sCW zxaxzp`3vY*zxg=G;q4JW^bZbu3ggG{!}R30kf57SAe1)~soh?22_`CdUQ{NE=9LqS zCDu3RAVDvn`@=(&pclSPQF79F1HrnBB=Hn+^Gn42Hlp~plQ8@cer6K{Gk#_h!S2<+ zB2!tA_eE%aqv8U=1Cje)DNW&YuBnI$CqspCRG=0I2cLT`Czsb`rUZCSfULlu8{@z$9dZK7)AL$?4k4y-We{7>Wx`>jVHck@}q zBYL2az;_a3Av^>kZ@|O~7S%jdg$Ub zUL+zs{*h-|J@&~MlyQn|T4Zc$>rP^`9GS}ke(Uoic?L~15!YeAN=e%&dT0(+;~YfG zL(MyB#f$fvpjmX?7YS>K=0#!s%*g-=$uYWI-25wkWiF2wKjbrE4EbQV`!c_E$;Uce zWOoEnm1RDLjKL!dil3gPr~9o*QCr@_M9CEBE;vD`QS+!` zkie>FrxP3lL0eo&6p5)8mIzYCeOh1pX!2rGXG!@1bd1V@Y%JceYd0%-S zc_(qX7-8;m;dWEGghjcq$)lG$JTI4flzAJtT(sIi!2 zh*@;Nm?k`r`74IuuLQ+8=-?@+7p}aqvlg~r1cqx|u?D<9hwgvOzz2M}KX0L#S{mc~lFjhN-2fF*Lwy z{s!QT_s%I_QHe_M3%Av4$3*6O3>;O{M^RJWKXB^)w2g7qeHjLvUF@*BH@$ZaO6s0@ z3v2`qAh_B-SG+faiLSQeydW{qz4ptqI4L%l z@Ib8I4F8_uA61B{S?^u#@$PElnet?KFG}RkyOe`9gY5Vi(tTf=vHA$29IYW^3k8*? zSKupo9Sdbs!foCJwB4AO?Z!Cz^9LJK)E^v$7nw=Or6i!&r~zYl*CKkG1k8)~y@l$2 zd0ys+bq>F(QTWN9lXxHe&M)$#XC$SAVjN0fOtDeT@6ezqRpvSGU7lN)GY?XBzg#ey zDTl%-=?8`TI24??cb!zH7){6oqpxPzIQ2~ zMjv%odyLR~`5C23(TA0jQi{wlrAW`fv;eQ$>o#BNG^X^c@TRC@_NBwJH~;+~)u{*G zhfXQmY3mf-raq$4{3?xL)w}7{@-gW z-oOTnQiI)41A8BfXZJ;86+PV9yM%bKvzNKK$nVmB2EUa>em4(SQ#xQgY;o}Z+$Olh z(uZ^$!6W5&dx9eKNis|14LaV5+&ljOzR`MkI?_SmU$uB2i)Fgb;rfX$4<1HvSDOlRUB`Ep|$zm+FOsgNG7c$dCPE=W;Ny z!aZ%;fKfjym%?wj5g7ZxdkG?=haFjb@&8I$sK(o}uzzvyeW;497@7YSbY$`9a9RAr z`$zYYV(H%cF*lBSMs6Jav%C9!&A%c;XXDj4dD50gdZxlW?O^P!$Di34mk;%A#~9hh zr1@S#y@!q;VJD-`wd%~!B~xju_y!^kk=4U^$K|bt_iwaCh8BS(E8^xSsT0+2B;rtm zQC9j>dUX6@B#wT$iI%x^`3#nj&EUFWwNzH_1K0I^_3V*|OAH$9!B* zB$DPgNR*}ZI6_ajRWoxpW%s*(1E|a%Yr{6>H;uX9C^zf5AIBE4lAxrucjAsTirh+r zL39(wgpxzJwz#Fsa@ae8yWq?hnUDO5uqbc!6djWzZSj}6 zOl>NUv*4UxifJ=lsHjo;|3TE&wPr8Z6>Is^W!T~RKc$>r2;Ohu4cnzIK3?u9TS+gH z!2uBY^U`CrQj)s1uuAuK$MKu~@k3bHSi{9(`Sxc$PS0@t(2E14!xkop(kir!sj(x9 z({;KA=4avQF~v7E`v?psxH=bSVH)|3Zu{xD*Q`nMceQbp0M8`lZ=p|x$FzmO;=eW}eaMGu7emog3<|lxP`W-eM9XeUgTsIv7PC8~H)MK7Iod74@%jww6 zES5vSu=EA)bOM}o3{vpNN}-safLSNWdSXa=Xdf0GC(oB%0U1q49vqy&=nMV|6V2V&7frR^3*z;Y|8v1jgKw?hV7J@^F4k$w~sGi%hxmL zymN=ceZ=-^Sw5fbqjPWjP_G%I)C<4gChO%Xt(G@lo?2;__z%|QX1rH|US>eQVNR#s zW>P)mOin*K4^02<^0EQn*v>qSy3);fzTRF=FK={TLO&g6t>i1Pmf><;gt9{N%7h6y+l3e9B9aXs@KfmR({cO=0<_1`aj(n` z61}ZyA`-Kk+o@(t@L7cqFxwhCGX+V~*LW5X*5-ChG@=8a<-k)P)AvsG{TRM8bY8=6 zEv4xUb}}5!EM!Dm5iyMsD~gCHBb+Bo;f&6RJLsN+FkjOZ*PE(an|Z;PAPtG2jlAY$pD#O<&4C*it=bx_L=urXYC z83-d-C4ygAJygeW*;tTY)|kYo!0Xrp=I`+xyT;Yu;*fuas3|`*6PJ{0%2NsSZUhyg z-#c+e9O~2jO}t#z4-3ohiy=M4`wH}h%{m>+#Jhgvd<~}?^VqTOd5i#Oo|E(BB6m6g zPP&|jGwyT(ob=huf3Z8A04H7Y$3$10M+tCT3%j1Ooa5Yd1UP);d=I58@*%)Um-#>B zPA6cDayGc>2pB;p<+jmHN5HW1Ho4OYaMCe^Aoo+;=>!Z*Kh>R1z_4_jL@2hG0H>a_ zY(Iqk54Udy%U8@pfWs4G7IoU{PA8zmr@2u1G#=RQlS!rUC%r&?d-xY%bnj3Xvgy8| zZu*K3?Vzs;FTZvlF7hq{c_l1YpoKp`!-x8S6|>ILJzighmtN%y*GaGNapuwR+n9cv zq_6NNFL83n6v@fwaPso6n2A~EbB^J7y~3|b`qX=->lFe1Sv4{1VpXy)`7f$uSpspA zHMq*As0h#y=k^Szc`q*8xrLA~`Dst!JB|JkdL$6v++I#%$0v+WH9q6;nSu|dGyy+X zU<`?6_?(2#dVEg92c05PJFGKc$ik^T)`k4tZ{5k?JFF-9d#m;D{M~6)$B1sNwVuCM zSQqm5QtR{lov|w7l-^`D@^{kedSDQOWqY(c$l|SHWE`0-P}??Z|*Tod73Y z+Q&h6Isw$r;t&>{e|+ehQxhArUA?))Hq+Xb9cV5OPfZN$?aw84XL|>8iJiH_DR1w5(jA-|XutBnC|2oJ`1@;4FpyTz5X(+q+j4GLY*b z#$47GBC&Gk4CXCh&)tz90JCg&j!JE$G_!voZ}w$-how!=QX-W$B|AmdkFrefa?o8a z^t3)gXA`|(Z-JL=57(c#n2D}j!WSFGIu3DoU_bEN@uC5I&s|GmH?Htw>e=_!_ks%vnMwj)yVesB)S;apS7~P zawxITm`JEf_L+U@u52OSt#UB;j=n@!zAtO-olSKs{_KjPncQwv#oStROyhKY|TM1@FaceE=5Q0OF8JTW66Lm}Q9#%Ul@B&}wHOpv?vlZ%=I4SR&=Q zki|xqlpST6npnMN^|F=?9j!&RncA0VYO=W@J~wd^NfzouDf8?U0_MAc1#V!W8#vYt zEK00sJ(1agK_=0$8u|&|02U`YS|C;lv;f#(1IrTYPeg;L3fW!^pT6usE>YOqH;~=K zIXRtUt;n`cQi7u+6sl~yyA~(fKwkoCvEo#8FqaFBSaGUkfRuRvRJnlMt)1&`?ObpuvY1)A%-v+!N2nqRg=^k|ilg>QPF(Y4 zr6{U-YblCq-dT#Gnr|*eQO!>)MN!Q=N>NnvlN{7k*^#ioa$3Qr_&qOmLOapbv?k6CbuNkcC?u9T0| z*)6gY6O?soqG`{(rgYPu`6tqp-e(TbgxovW1MeZs9QWS5_ z6@oSd?#2hcE!_teSQGKv{)i6iP_8Go>cl#Hu({3o;m7ee{5?^L54pOsRd`{Wme>4v zuOEe%ad;iVu=ug|6<}(03eVthnU`qleF0yEIMcVv=NDh~5$2X4g`eZ_s&b0ISxI42 zRRA>0Iqc!^0uFEH@GBhtn8VjOoQfmxezAzdc7yVs#o<-PKBFLR$8MQlJY(Dsnm-|| z#*Z^nyph9>YAVsJ&Q<%x)g0c!;Wrrn7Y-|<|Ao}W(Y#hIwnR7JQoz|!YTYlQlxtiS zg@5MwVGhe`h-acESKS~!TtlVb!YQ6$)HMK-Jxt6#stDS>ij+FERwL5B2 zA5MLU!&Nb&+{)oO9Nxp>D;)loLrRy2!N-dy}{^2ozNI+*Ot^>mUCZL&EzR}j!0ze^X)^SX^ zLYyJW0iD25FGF+1iQ)jZb}nKr$3o+X=hX`8Wau`AjuYL2_WJGyWZ;*8&SvO-hE@Z* z4P`w7oEkhklSr9j%Bq4rLOOn_vZV~JD-v|l&#b>lnBK)cLDTJ?R zcOm=(hq_LfDf+z#8#!FY;VS(BV7m2(5f0$=l3!e;KY{Q{{d)+n=kQw3-w?maqoIH9 z@`MoH>mkaJcLN%>*}D^A-doV3;z!MO zhvx_TbicSTNOisn7)?~*72BGa7Wy8-4}}hb^K*=OGgLsi5+4auYBEgawneDK(<6jA zH$r)@i#&|*3yhgqMwt0!l$SXB{Ts>_=%?&Iz3guYyE*LV@O%!h;P4g>zrf*R96rzC zYaIR;hkiezA$#CB9HWVGi6pVpb4*L{~`j`Y|FfFBJx!54W*wWq4X8)t~wzDyGFm zFe4oyaMQp z3Yz744SN~?s-VT5*8%-lK`W5YCtg#~8OY}oZ!&aou;240+8UTF@ON?WfafhhRT8Ru z&|_!;@$3{zJ0KoqsA(Egitl)8k+#->8nmF8Mw>dIe8w{iBla-`9rDc4BH}#WEWAMc z(Q`arb@ujZN%?orNm_;ITqAi-@}7Yo8cdui(;5L)i4|u_XqC51GsM#hI@fzHZ2lEn zW!eSaA&k(+vIN~AuJ(QuuYoTKQpu zE)W;_9zj~~J_%h1Xq>qEJPF+fXuL=aN$B%{CWy80VyGW}>ieEHQCy**KLVO0zN4UV z{ui|d;r)oDoC7E!mMZ8J{~xr;;yeZA0ZkDPD(GsQPnas+QqWz1rirHglFM`Wt+VN( zS3!RQG(+4YAyE~0M4KtTrl5&|33^g|hoJ*vPGE|DjM#sIz~2G!P)!>iUf!ypX93L? z-%&CfM(`~_ zH!J9`!H?+~@nr>hLe~R&SVCO0#o|eomJeO7FBU&n(7B;Uw8i4r3c4tCx85xNuAu8e z_X6^MimG~XkV-#Jj8_nqew>)5pxZ)k;=$T+3c5e^7N9l-JsvuQA2&H&LEjI(0;oqq zsM#ah@nR1{H;7#LYx)VI>eE!-4Z;dPtS=QeD(EBOZ|Td#y|>D=%Rt#CuD(q|p9+6Z zZx_MaCG@%QbNX^|p@O~)$_`O>7o}Ysd^r3Xww9+V=&A7QfMzS`$Kf~eWS~_+zX-nt zXr+Sw5WZYrDY_N(PWTc0#AvUA$|5i8tHcEg8Xx&BpeqzKEApmTE$&dzqR3l-?v)Vt z${O*2O8Z;na(#{XzJm0!N3=EKSp`MP?$+0e*A-M#b}yi}6h!*6PDDN<+eiAcPSi+< zOCbNB{+=qQ5{l6IHHaU!+{>ry2M{4 z6eKO^7L~Mwf-aF3bc;F#{S`A(kC>w%PiQY7d47+0?)BuvN|^@ede1g-hXdX0Ia@sB zKzDge@jo5t3!VY-dk6Z4=flEx50?%uPkKHgraRD&JQs;o4)mhu3PCSuMm<6KThF!P zItTiT=O*zWLpO+UWxe;);?mC&9jw z;u3Q-^&E@lE6nY8cvhwfsxyA4m@)rWLl_y#ybs3-^BB|oE7KHt>f(pMcsNxPKN*&K zbdo$FTq+-39CG;R;x|rQa?^zu+Y}??M^{#{=9-YwmKb;Ig5a-zxdqH+hfI?y0_9H?%KR-wL1mo7JBI=G)bV zW@z7M{Ew^e1O8C;5HP>1{*rgGHX-_;cY&A^eazb?W<+21_Hwv{!wXfpspui>8!n9g z-rJ#_5d9BOwjtij;RJC*@LlhP;PA2+z8CO@))Dpl)@gg95%~58q7xBb28;pBkk-Rx z8QRs+DZaVd!RSnccOW#hFQXJgdo)TO&!@t(fq5!A&$p2|Z^U~m4`Ki02hqihKLO!^ zXgk91SD%FNd2r5ZzmA@O-Mu%W_hHvBP_x!YwLQ&uK&z`k4YXM`IbT*gzUDsfW!lL# zd0#zB>_fPv#`0akExm%vx<5NQY~xn1LrpG5i+XDAKv}&tU-F*8lxK*GYVP-4 zFRrWkz4v6$lD|BmPrzVjG=GvjYo_%GB<^xdZY8RcHct+*33>-_hECg*=ZJRIJO zu&nm?-g}w;Nz~^YeVsPG_DcWLpnSmpEOYy=Mx{KA)R(>MwAHmw`5zV=Y6z)jk%wVw|>EItd$GHB+@2&taG)1Ih(oKycb zuuglr_J@HQ=GMbCuVJ1mA)h}4&SMFmC-y{VL!Qsq{v|L0d|nX~G}6@xS|(N*yh&?| zU9SI$N7LW5eC(c}rVquw2K^zL+qAF6J|8UOx@EO*0#9QEqgeZS?15m7(p!?%G>v+Y z^zB>0X)NJ-{gT@61Ut09#C{m8*WQUe7rafYh`$tkL5szI6`ZWU6C*zF#PYslbmBQ# zr%^`rnT3({RP=YjziG$D{}i07x5wWJ5=INn)~Lr9psbvK3Ac0smu2YGit|_k16=bC z{XgU14|V9Fx@SXe+`8EuUZ#z!`&B5bO|8p8&*#_W5uOnJ_fUsuu6q-d)anj#LfwCc zR)YQl`@G||^(TBs==5tSihV0d$$XqQ}Pu75>L0S|pJCExb5`?M1oLDY`;%)Jc zPOg~l2@0utpn?uue-LoS;odn9yb+oTkk|nA8>^oUJWJ*rXkg zaDmo}aEV5omon!z=DdPA?_hi{6%&_$%fq zG^#^_!=)T<<#0cTPw14o)bn?*?$NvypUhzkhgl8}aCjSskIT?Ul)vOq^K&i^TR6;e zc!0xOIlPU-$2feP!(CpcWn;Z_cN@SAwL zXFtaut_d=kQhzALH<44u8p^DC4{wCOF*6;eHNp9`}qFl=1Ru1<| zOf})Ra`-ZbBFa2DT*~2A4)=37*SpyJA#aQKQtx-XKk+{6`;h;a{!M`k0(HUepcT9* zcw;aa+8O#t=*G~eLZ1yi5NZr>3LgyL7d{kzCp;l?T;#OK?#LG-4@ABmc|7vn$gd-R zh`b#!$|jc0E}MrdkXSt7If5Ty$d82ro+H4S#dCyegpc@R@YFTKc zL>b<|T#jRZl^A=5NQi1N8Q3X!kMUIG@&p&@cwQMi0pTnT7YADrZ{zsJ;Bv$_g+7Jw zv=GI+LboG4AxxN#F#Y1K#BT^w>XtC^`EGMtLP? ziTP|f;jbz`)q|hc<@lKu#7Cy)DvC9fb(5UCLYIU7yIhJ4txC#8wW`8>0UdHkA|%Op z@X--g;Y>a5k%(CcHGF)G^#PxTacZD#M?Mrj^5DmgpR@$=r0W?;wd~C zPmOi#m{GVA{iop|{dmMz<4vL(-ZnlF@lMfz_-2H3M`AMKrz6zyY;7vyXClHZLfLy!d4fgFAm^3bsx+ycynkcW=>g2HP> zJ22NF)Ws*na>Q@s@F1k3i<>z7BxIxE`TEJ?WPQE9S>LK}*W0}-z3aW5-Ywp3-d)}S z?}xn~^}g!;u)j%-#jo`Y_ z=1^DY=b^))if}wUGrTwa(eU&#?|xcOx&IOXpkU6QCblv`DK5`A5A?_WL*Fq_imRld z%YT$%Dh>&Fz}<^a1+?cJJi-5p__Xh9_ zbNIZ4Pc-s`HV>b5bSeRd99Eev}JB3cl7PIXt;7Dw5zDsP_TNudg5^K87&UK?zXj;BITNr4|_2#xC8}i#? zYsZ0F(a$oYLN{5xqI(d>Y9ZC09umCb)!1tG_JSG2UuayO>&sdBZuC>Od*@a>%g^`b zR^vQUL9ER8DxY>jv-{LIoLN)5T}~fP6)IOM{c_zvpll2<(Vtamu{UW z*6=}9J{Bxin|;gZEUFvF4VKC4bG_Mt{O%l!n@TPWpepNg+j6LVcdmy?3u3L6H?8G3 zCzI`!9n-Omt1bFW$|6oQt?t}Pvv2!Kc|f-yw&w=6fVtTXN%bfxpq_=%(L~J^>gX%v zERs(L+PsI!N5eCB(;O&DN^&km5!ISryL6^-fvy^&yyccT*zc~MgCn|*f@%xI&O{{$ zB_x)Nit`vKhz@zQX>E33hiIg}5-ZJYj}*NWGua`GQzI*xO5I#?jMEzKjnht1)Sh!~&JPqX?mF25?Rs zqp?s-Se4E9vEtZ9qt(ix(@8H#TBH>#(3Ne2yZT!!E4vrETIlc1?%jZ(utUgPD{{U4 zb^^yqP91%GGPJkY99Ki-=xl_lsu5+Iz`ZPED4n#3G&+b`uE(w)L3Uhm>D<-Z2wgfy zbhg=N&m;wFcbj=`U$2viQP9%?oQRi1VnZ%#b?>lwuFvhlX+o6*v32xqgE=H)Ax*9Y zxo@=gO2DzLBHPomWfU~ds)O5TDYlB(mXA4%K&t#B@I~`agNXAEL#dp@uo5hGi7TfI zS(4X|8-C8EKV{-??SWG8kc~ z>xubXZ;x0qip?2GL_@J?fJUYlZOzCu+ngxFGm^kzm^GHDuDxmSq2V4wpU_BzMu@fP&YDQ>2{ktbE2aKhq$|yBf#-i z43jPhS1ikcgCcA1!{Fu&+hJYVGoYD)BZQGk*2AXOjuU)^Tt=5ro)H3CqB4z4 zkQ_$fxn#Q}RSFeY9G+CaB1CEMnE05goYjgDrEM56``23LcH9o(+PYy%FHUbVw!~pQ zqH0SV&LfjtY)2+C=MiY9AmQ+Z3sS7Dtj|U(zYBJSPT|4_$!>$|fwTGK5)uH@ogaV= z%fo}~hI@0WbL|Hno1{BAx0j|XIl4FXjGLoA_)S?3L0gf|Ob` z7M$t=Db;aSZ0|z(E~P#Q=d{O-Si(h*kj;_}PQfG7ip7phE7oDOH0cG6NRiDi7U`PM ziym0P9;;G#qhtyC6NjhMqrr*XWvaDe#;g(o7@dFn6th49_i|} z4WhTnjbnP1B;84yu&7fV@Nc(gT{E^#;#goH3WM9W<-7CHEzU@{r^H6nT$SzHTSRQ? z>xM_xOHMn==HuY(A)5my!VB&Zo8TaB!_3v=$X>Mc=C}84G}ppOw~J*ztc?iCsZ`De zFHOiZ&Ox|6V3zG0D3*emlG)f6PEO=%5yKkX25q+Te6LNMg31$T>Iyq9-3{R;qhx1F zBHed@C3b8?|JVu4Te;BO_ja6^7AGK1a)C<}*$BQ%ibNyQY}Q2*!OI8ochp@vXG!74 z6}z`MwMaMDUe>USnClU&^)2#inOdq~_JR^~x2%F0$ZmHQjW)Q}EDYd|Vy>q+3JYXk zPQ>a5%h*=<;*u{$rX8w%Wm zEQlS=YN^i7~_+w|HZIpcieo zS=bJtOG`&4!kTZ(Zy&_c96CN)@~(ai+K~yE`g(Bla%4iQ*}oUA#EwytHd=7fcV(@e zqvS%b3|g+r+s;3h!}(pgMqVhG{Tp)D?mXrZOhUU($rtkQh>EHv6}$w2a+iCAm)!{4DnNg62D=5jkR+jSK%8n8xHj4_hV z!AONuXHkcWj$#~3Hruno)Pk*vHQUfETA9g0&@!y{3oCO27_&}fjnxLXS(=-bxxVda z)JAiqc`iu64Rb1I?x0;J$Vs-EjSG4Ww}q)gv5GG6z*f>Gy(G1Q<;?Yo4q8i_1+J}( z=CF#E+d}MrwaRU%BCexA1<=X>ws=EsU<3hm8)_+qg)Zpm!{u(-2}&HajRAFVK`duk zl2`?qtcDhdO&FDPkHtn_0V`lBu_g8z&epTzyS8kZiyi1u6XubS3MM*&%{JLN0k@JT zkhR&og`F-cm^{rB2m87Kp1K3uR!+B}p6E7bd^kIAZUW3aShWxv>}fD(w0%=Qb|dYK zq|xXd7=O|fqHNjF+R;H0Af-gFWAh7(B$&M2c^(25c`;B!P%uYmL2g@?c1F>j-Pqou zBBXHId)c$Wj0BxspY6lMw*-4_yD?BZXgibK9#-?V9K7$|!twh~Ts*gBaZA(O^s=_h zvh;#^^V`yk7tT92-M(y5`{I^)Ez2@3Ck}~e)8zEhwCC6+{LNjM<}C-iMyLSPi8X&? z%f=lRy1ZyH+EDmLSXFN8YP^K0y>EBkGW*yC0|ys)O4iD=?hP+5i}FgfJQl{QO9a=i5<}DzJdAk#IpQ=k{3E-eGYYqoK(&@xB*drQc< za^SXjm0 zfW5W6NGO|6Y~-qx8c5KIcxQpabQCa*;Hpv&5ZV?kJ4PFGyZUW8W0Insaoz^A`4mJ8 zBmqUkV3r$pfC@hHP_YJOO8658#WD{N@rQ}WJg3NFAT_3KxN_A1A~sE z)gn4hQ5QsKQNxNcduNSm%C+Q;bv0zAVv?4!ys?Vf37f^!poJ|?xJWc!8oPO4wL>mK z(bs5!{a~c6b?v4B5>Mj*1~L8Nf#EDXj+ui`3ZJyld`obiL->xztvG?RIk=wTn;~W( zJPS|Qga@#PzJc*f$9tAOgeP7f!uMqP?PJJCkN_v}@X$wclsJT`H3FK7=W~7djnZyB zb8N#iv9)3o^dT#{VE@nz#P{GMJUFoG!Bbq1iBBI&%Hr8&7k)yxfTweV;L{E26Tyda z2@fu~dJ_2HDh^I=2+tNgMs7sPIiM90I|hnC56S|6V=D6YflDtadWeV7I07>j_&%g= zv&*Tpb9FJTsI>Da*x?G_7rb}6xVkaJxRy7HT}*GGZNh_#GM*$p$Ka(mRCB6D--y3cSS<%Km`iG7g)GdSuCef zcn@%M@i2HcKJ+gkifKe|LO2NsbO&e?j-X~EPTfqoiDLn|;LU@M@^nLZ)PaK#eipF= zK3G!VL*LXXSlmMu#Qw`$5TR=9V*S_)(sQ{ldJ%&)14M;W#$DVa)VDcQwpct?2;3y9 z>L614IV@I{Dnv3P-d)I>P<*<%f)-MUBPxTw=mig~aZy#1OBCpf5x819GX%E{6az)d z+Nq;q!IPRyJi1j$#B&6$-qwSWDYiC@NP+%S9kyd6OtoX4^Pvw-=oaC@Gjham6$v56 z6+-A88*O!nx(IjUSFlJIbTgQyPs<*;lRlS;nNfH_5_i4L0=vAhIIFn^ZOr+CC>;_PFFLHBHJztEBv7U-HNYey9WP z1#|2FcYEg(8^?9u@i#NOd_#&Hac8Ais=3UB5hE!OMN*;+%cWv5TB}mQ#D+!72hm6< zQIdsFBuko-l|!(+6ewB)H4qAU`@P@)dHZH|lR7E9>fnK+tKZwGUN-2J+@7BT5z8_ ziG9P>X|IB)l7wYKlIk-D`)LW`2`yVlal^?=u%DDOmuI`{piiOY8^D38E zgoHu81kcw<{xZ>flC_(gsFeOkM_-{{9&5`v6qE2Ox=a0aH|hJtVR!^)?>b~rkAdoW zDOY6f453rPBpa2+E|^>F29eIc>uSZ3pi#11^(vSZs}1xHHXE!`I`N1;>p+Mu_EYo~ zTI5kQi-*9_+#Ui+6sL>eW&;Vt}8`TbOJG3vnD(f0@y`W391gJzE-YI(8{| zd*+#`SHTcmYN(ZhdZ#Qis~oL4{ij^{#6ia|1Klfq)yJ`a(1&P+FWggd4%e%Z{qf5@ zr@A*$mDh1ga!r5csf0sih@XDd2{)u0a_=(MHOG;AP|0QmuDmLOtUwj}^}TYmc>WOHDq-;{$C^uH z6mfCcBq%aa8OoM3Q8Usnr#r-FIrO*SjA`D1C$HkJZ(>YKY?hK__wcZJ0RNI1WBy_< z=R%@3MK16Hkov>2=qbv-Yw&dw_q65a^0w1}wxe62x()5OnT;a9bmIaP&vK0Z@)t50 zZ_Q$FKLM2|kP^#gdws~Zo7^1`29>T9O4GjM3?Zm#Z`%-fDg~}uWF9`b*@R5*OXMe| zax(OSvJw_e!ACV^9Q`!+W-9Vj@=}M<7>ru3W2iKd>);SSwo&UL{GXzeqK%Jug7pn* zo|SX=URII&EoTM`C=A~lf>Y{W^o^Ufi^0!{HVRR*_Dz$%&X!yL|;UhVa=mS*<5FHhw`yzRwya1JEt-YRuP8GvLNG(Lnv4_{ah zhN0}*=N%Qk!*VL&yH0O^cjsrM?8MKi%D##+tB}5{SCGVtvk7Geo74u)moEG4N!lXl zK1fTCz4h+RGY{wZg0rUonJ)I?+^>xxNQ(y9p7bi*{RDmNt@VCoe@|Jtv|gc1Ih=xi z|ION`*+iAs?)S#Mo=x{)l@|;;p@85sLr=p&nVHx0{>=5$arN_Uh4~z;>%ry~;x+#b z`sohNWBl!zwK%^&-}bz}h80M!eAe0T@lS&*XjsVHivu8$l|C1|{ALrMrqD3WpTgl&IxCyf zntrmUSc2&#Vw#>(CvR@kjH+6z+pF`qw#T$YFTVlIuzV9taTVOcr5jtXdc9C8!EswX z(%WJNgX`DwO*wh1k6*cUFt9!v_Vl|+zx@UPp5|@vY=Oxq7*c+7)Eh*oGe^QLDGFhI z*^KDcT5dt9h#AyXRZ_hfkqSv0WB{h=$Mw~Xh%>=_%wV^~@|f~8b42r3CI>Vy$oaE8 zU`y2;k$(70mt3~zN||icM&5g*x-yM@OC`+%7D}ufG>aCP!UJULOkqUj^>9^pvxOUS zQf9>Wkt8(p-XzJ`GIJj6X46MC1M#TLprKE5cUgBsZGB5I&sCi3t52+n5+0aHhPglC z+3JKH>B%zxSy??TdH3G*Dvi^^lEPTfZfRi~>ZSWy3JpnJZ~I<2l7?iW`7(ZTZ~Okl zm|jrhtwYPMqCie$li7<4LCfg(@_uOQqn=ut^1UUQeuw6hFvibnysYQ}f0~gNMHF}s zy6JaoduNw`tOQElW}TGt(4JqDhtbSEzxYQ`rQ%NiiX}a7E-+*HP5D}#)zc>@=N@nu&c5z2$}i~-*mGa-y>^8q4xnE_1!Q2;GazT{ckScJ~{W}zlsO4&fokY#i)3|4h$U6 zk4Kq5rIxFcaaQ+dF1c=n);Q+pMGB)Dn-)>z3VgYc*0@M1SQRXVScSL*W_4~w`Fwdk zMTcmxaKrP(Y^aD`^J11UD$BCa;%ko-aXy@Rsz92G+BEfK=A-o@%8QKp|iNOJ&xwa!&!~WGKue1Nm7XpKkcm zF@I|N(^5Q8uLExE1e9AiljO5merXIuHlKy_Fxljb4(}opTm&pXs6Z9^wIT3%^5ub`^im|nJu&Cv;)-p}{Tur@- z=8K-q615nwbLuIhqNp*u6g959b39lU8fS)z0aw*H6DnKQmX(y^;liq2#m2cKzB3n% zGgSjadm7H6jTTl9iwcZu%%80kGHaZ1$8(ZdDxHlQJJvcr+Qed27K5^pBrm(HOZ{Va z%zRZjwRu0oQ?4?#u1AW57=)E*_F2tJw8rF<16WPxy^NF2pvLOBXdz;xE_*@h8B(uj zjn3a&NNbuVW?=Kq`>ia^)Gs%#)aT=U<@gW8SVPJVJwBF*j@# z6(6!Z3g4=yshhX0qu5Pz0@Nku{u5MW&=s}D(OO5@APUsz{2R!vJLjjwqBNx^+*V8W zww-I0ZX|X5$nwSfSeE4TFeihla7t_{DM+*Y6qhl7S)8B3n(|@X8h=Fz1%{$i3;?V! zEWYHD@yXa`M;v`Wgi*~%6#lSV_ersw$W44l$VFUp^nG zsLry=xST^v*oDi%E%^XRnjs;{!NvrNI8D+q3-`*JG*(UOuGJH}l>mPV^%B=lqjcD! z4I+**q&k54sHax;fl+jR0gqetY*;@=gVyJr|Ky#=B3~MaC*_TZaW-nD!d*>C2Zx9} zOgXilJR&Aa3*sT?3{fYP$cYUA&KlFSh>_B0Gx~G;d|u>jHy$D~n=fU#<72+)g_gz% zno{V`^N4O;u6pWIDC5r#GQYI!YI6%ciR+oAj6@E(9ZAtWI3+Ekwv`>V!>%HsoT7bj zq0#v-9e3-FBOho^sN!NBN7WkR*dj5&$S^oej4MnG*6lW&Vb(2vS|46p(AYf*EdF7R zBQoc)v9TNW3>B`2@aE_>1fRfK-uK=a8^Xi9XOTj_dmJB&CG8#u6vUO3w8mP@&AYXk zAV^pE1V=a1)T|K)Mb79#J`RUg3Z&}FbYxQ>DCPRbI$ z7YZo*E`y^nog5S9#_g~`!G~5opQN5CARliTU$} z{3R{}s!L(?B|>z*yFin|4M=RAvA|*4&hmCIWj3Lzdx2|0<2-&0 zCS^j$ZLKW$OLvSz^NrAa!*wc;-R5JV`Iu`ikKN{WXl}da^4M)&3e8Kdxje=S7-M6X z?HGEV7v4=fK_TW0)hb9j<)jPw8~Ic0#^QhBG8)|?-EpxJWwdqdB_qSoIgXE6`S3WA zRmy@0GT8}*h9nt8i)36`JYs9OS+8UB{;D*i`B*Ww-b#*GsbLl;Nh>L1eHqNh>K5m7 z#vRWMN5+;Lm5gac=ETA}KSfYJ#qEAvM%$OB*g{FTB|kEskIZ;?|8()M9~JGb`%jBD zo4?sxSX`Kyy}&IS?;XB4yYj;2yB97_UAXjMW@>JAW^U^8y%+9Jt;}7xcX@X8;_Ag& z-l8h>v%F28KcnB@v!svN@n_!LTG`}DiS7nCHf3!*-FAKH_3eNB_G{{` z+>eDSv(}8v+An!u{;l?{55NB7pFR1odG(|AXHF*HdH>&)@?Cpr`3)ZM-Co|>VWw+q z%k8a=&AS`#F5h~GXF`_QE4zGmXZ_*I#`1=Lwtcze&@#K`m*0Kyg=M$5I@F%uT)oSS z{{uBpt#SdP13sfY{d_ZfgSXiF>>glsPkrCNe|~jM^DySulcu=pN`E~3U*v$^x9?P? zbAt1WY`N;6rPQC_k2s|M?E~sHzN16m$Lr?bQulWS?)YyRt$_4&B=AOFq$ETu5mpV@)rKHLIyTgoaHj8vyDptpeI z7k#wQqUBkAP8p3_qE*W$+t{*}PReCe*W;gSs~C9%P1-5-h+Yp5fOOUM@f+rJoMQoS zhVhHM?IdC;UJLVKIYvLwvEUY4{L)MKw#R>|?iY^r9jo6d>A!#%DKFxoqAu<>OFsuJ zS<|n7vEM*P@3{UYXu+Ljac8FcUwDSWBQE*nA1zU?AqW3$@m~1hn|fouPWX(Nu@<5= zLbLAQ7=Rz#S67&ijApB)uut1CV9ZrVmu9EMDoH|Ef>d=S4j)dR=fi7^*OKZE3ykmd z%xdpA{SJlr*57|G_xAHnV;0GSR(n=nQ==c*&|!W$NQetb`}g=6jj$a2fZXgKKmYGI@Ehs}gopqD literal 63488 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 diff --git a/apps/AtlasShell.dasm16 b/apps/AtlasShell.dasm16 index ae195b2..9559437 100644 --- a/apps/AtlasShell.dasm16 +++ b/apps/AtlasShell.dasm16 @@ -1,34 +1,34 @@ ; BASH-like Process :AtlasShell SET A, text_versionoutput - JSR [0x101E] + INT 0x101E :AtlasShell_start ; Register our buffer with the driver SET A, input_buffer - JSR [0x1026] + INT 0x1026 :AtlasShell_loop ; First check if anything is taking exclusive keyboard access - JSR [0x1028] + INT 0x1028 IFN A, 0 SET PC, AtlasShell_loop_wait ; Load the pwd name JSR command_clear_present_working_directory_name SET A, [present_working_directory] - JSR [0x102B] + INT 0x102B IFE C, 0 SET PC, AtlasShell_skip_display_path ADD C, 2 SET A, C SET B, present_working_directory_name - JSR [0x1017] + INT 0x1017 ; Display the current path SET A, present_working_directory_name - JSR [0x101E] + INT 0x101E :AtlasShell_skip_display_path ; Display the prompt SET A, text_prompt - JSR [0x101E] + INT 0x101E ; Reset the basics SET [ack_command], 0 ; reset command recognized @@ -37,11 +37,11 @@ SET A, input_text_buffer SET B, 32 SET C, input_buffer - JSR [0x1023] + INT 0x1023 ; Skip everything if we got an empty line SET A, input_text_buffer - JSR [0x1019] + INT 0x1019 IFE B, 0 SET PC, AtlasShell_newline @@ -53,70 +53,70 @@ ; Check for the 'clear' command SET A, command_clear SET B, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE C, 0 JSR command_clearf ; Check for the 'version' command SET a, command_version SET b, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE c, 0 JSR command_versionf ; Check for the 'load' command SET a, command_load SET b, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE c, 0 JSR command_loadf ; Check for the 'kill' command SET a, command_kill SET b, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE c, 0 JSR command_killf ; Check for the 'list' command SET a, command_list SET b, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE c, 0 JSR command_listf ; Check for the 'ls' command SET A, command_ls SET B, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE C, 0 JSR command_lsf ; Check for the 'cd' command SET A, command_cd SET B, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE C, 0 JSR command_cdf ; Check for the 'cat' command SET A, command_cat SET B, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE C, 0 JSR command_catf ; Check for the 'echo' command SET A, command_echo SET B, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE C, 0 JSR command_echof ; Check for the 'help' command SET A, command_help SET B, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE C, 0 JSR command_helpf @@ -128,18 +128,19 @@ IFN [ack_command], 1 JSR command_unknownf :AtlasShell_loop_wait + ;INT 0x1002 SET PC, AtlasShell_loop :AtlasShell_loop_end :AtlasShell_newline - JSR [0x101f] + INT 0x101f SET PC, AtlasShell_loop_wait ; ==BEGIN COMMAND FUNCTIONS== ; Command function when we got an unknown command :command_unknownf SET a, text_unrecognized - JSR [0x101E] - JSR [0x101F] + INT 0x101E + INT 0x101F SET pc, pop ; Command function to display version info @@ -152,7 +153,7 @@ ; Clear the param buffer SET A, command_parameter_buffer SET B, 16 - JSR [0x1014] + INT 0x1014 ; Capture the param SET A, input_text_buffer SET B, 1 @@ -160,26 +161,26 @@ ; Check if our param was blank SET A, command_parameter_buffer - JSR [0x1019] + INT 0x1019 IFE B, 0 SET PC, command_versionf_shell ; Check if our param was 'os' to give OS version SET A, command_version_os SET B, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE C, 0 SET PC, command_versionf_os :command_versionf_shell - JSR [0x101F] + INT 0x101F SET A, text_versionoutput - JSR [0x101E] + INT 0x101E SET C, POP SET B, POP SET A, POP SET PC, POP :command_versionf_os - JSR [0x101F] + INT 0x101F JSR command_os_version_display SET C, POP SET B, POP @@ -189,7 +190,7 @@ ; Command function to clear the screen :command_clearf SET [ack_command], 1 ; acknowledge recognized command - JSR [0x1021] + INT 0x1021 SET pc, pop ; Command function to load a new process @@ -208,14 +209,14 @@ ; check if blank > load help SET A, command_parameter_buffer - JSR [0x1019] + INT 0x1019 IFE B, 0 SET PC, command_loadf_help ;check if list > list applications in table SET A, command_parameter_buffer SET B, command_list - JSR [0x101A] + INT 0x101A IfE C, 0 SET PC, command_loadf_list @@ -227,12 +228,12 @@ IFG A, application_table_end ; if index is at the end of the table, we have an unknown app SET PC, command_loadf_unknown SET B, command_parameter_buffer - JSR [0x101A] ; compare table string to parameter + INT 0x101A ; compare table string to parameter IFE C, 0 SET PC, command_loadf_loop_end ; if equal move to end ; Get the length of the app name and move our pointer forward past that - JSR [0x1019] + INT 0x1019 ADD A, B ; Skip past the null terminator, the start address, and the end address ADD A, 3 @@ -240,9 +241,9 @@ :command_loadf_loop_end SET PUSH, A - JSR [0x101F] + INT 0x101F SET A, command_parameter_buffer - JSR [0x1019] + INT 0x1019 SET A, POP ADD A, B ADD A, 1 @@ -254,7 +255,7 @@ SET B, [B] SUB B, A - JSR [0x1007] + INT 0x1007 IFE A, 0 SET PC, command_loadf_unknown @@ -263,39 +264,39 @@ SET PC, command_loadf_end :command_loadf_help - JSR [0x101F] + INT 0x101F SET A, command_load_help - JSR [0x101E] + INT 0x101E SET PC, command_loadf_end :command_loadf_list JSR command_clear_parameter_buffer ;clear parameter buffer so list command doesn't run afterwards - JSR [0x101F] + INT 0x101F SET A, application_table :command_loadf_list_loop IFE A, application_table_end ; if index is at the end of the table, finish listing apps SET PC, command_loadf_end IFG A, application_table_end ; if index is past end of the table, finish listing apps SET PC, command_loadf_end - JSR [0x101E] ;print out app name - JSR [0x101F] + INT 0x101E ;print out app name + INT 0x101F ; Get the length of the app name and move our pointer forward past that - JSR [0x1019] + INT 0x1019 ADD A, B ; Skip past the null terminator, the start address, and the end address ADD A, 3 SET PC, command_loadf_list_loop ; loopback :command_loadf_unknown - JSR [0x101F] + INT 0x101F SET A, command_load_unknown - JSR [0x101E] + INT 0x101E :command_loadf_end SET C, POP SET B, POP SET A, POP - ;JSR [0x1002] + ;INT 0x1002 SET PC, POP ; Command function to kill a running process @@ -314,20 +315,20 @@ ; Check if our param was blank SET A, command_parameter_buffer - JSR [0x1019] + INT 0x1019 IFE B, 0 SET PC, command_killf_help ; Check if our param was 'last' to kill the last process SET A, command_kill_last SET B, command_parameter_buffer - JSR [0x101A] + INT 0x101A IFE C, 0 SET PC, command_killf_last ; Convert the param to an integer SET A, command_parameter_buffer - JSR [0x101D] ; A is source, C is result + INT 0x101D ; A is source, C is result ; Handle overflow IFG C, 32 @@ -335,7 +336,7 @@ ; Selfkill? SET PUSH, A - JSR [0x1001] + INT 0x1001 IFE A, C ; Wants to kill me? SET PC, AtlasShell_die SET A, POP @@ -345,29 +346,29 @@ SET PC, command_killf_forbidden ; Kill the corresponding process - JSR [0x101F] + INT 0x101F SET A, C - JSR [0x1006] + INT 0x1006 SET PC, command_killf_end :command_killf_forbidden - JSR [0x101F] + INT 0x101F SET A, command_kill_forbidden - JSR [0x101E] + INT 0x101E SET PC, command_killf_end :command_killf_last - JSR [0x101F] + INT 0x101F SET A, [last_proc] - JSR [0x1006] + INT 0x1006 SET PC, command_killf_end :command_killf_help - JSR [0x101F] + INT 0x101F SET A, command_kill_help - JSR [0x101E] + INT 0x101E :command_killf_end SET C, POP SET B, POP SET A, POP - ;JSR [0x1002] + ;INT 0x1002 SET PC, POP ; Command function to list process IDs @@ -390,11 +391,11 @@ ; Get the process ID list SET C, proc_list_buffer SET A, command_listf_helper - JSR [0x1009] + INT 0x1009 - JSR [0x101F] + INT 0x101F SET A, command_list_info - JSR [0x101E] + INT 0x101E SET A, 0 ; OS process JSR command_listf_display_procID SET A, 1 ; Shell process @@ -429,10 +430,10 @@ ; Convert to text and display SET B, command_number_buffer SET C, 10 ; radix - JSR [0x101B] ; itoa + INT 0x101B ; itoa SET A, command_number_buffer - JSR [0x101E] - JSR [0x101F] + INT 0x101E + INT 0x101F SET PC, POP @@ -444,8 +445,8 @@ SET PUSH, C SET PUSH, X SET PUSH, Y - JSR [0x101F] - JSR [0x102A] + INT 0x101F + INT 0x102A SET X, [A] SET Y, 0 ADD A, 1 @@ -514,7 +515,7 @@ ADD A, 1 ; Store the file name - JSR [0x1017] + INT 0x1017 ADD B, 16 ADD A, 16 @@ -536,7 +537,7 @@ SUB A, C SET B, command_number_buffer SET C, 10 ; radix - JSR [0x101B] ; itoa + INT 0x101B ; itoa SET A, 5 :command_lsf_filesize_sanitize IFE [B], 0 @@ -548,7 +549,7 @@ SET A, command_number_buffer SET B, PEEK SET C, 5 - JSR [0x1018] ; strncpy + INT 0x1018 ; strncpy SET B, POP SET A, POP @@ -559,7 +560,7 @@ ; Output the file info SET PUSH, A SET A, command_ls_row - JSR [0x101E] ; text_out + INT 0x101E ; text_out SET A, POP SET PC, command_lsf_skip_file_end :command_lsf_skip_file @@ -571,7 +572,7 @@ ADD A, 1 SET PC, command_lsf_loop :command_lsf_end - ;JSR [0x1002] + ;INT 0x1002 SET Y, POP SET X, POP SET C, POP @@ -584,10 +585,10 @@ SET PUSH, B SET PUSH, C - JSR [0x101F] + INT 0x101F SET A, command_parameter_buffer - JSR [0x1029] + INT 0x1029 IFE C, 0 SET PC, command_runfile_end @@ -608,13 +609,13 @@ ADD C, 1 SET B, [C] SUB B, A - JSR [0x1007] + INT 0x1007 IFN A, 0 SET [ack_command], 1 SET PC, command_runfile_end :command_runfile_notexe SET A, command_runfile_notexe_text - JSR [0x101E] + INT 0x101E SET [ack_command], 1 :command_runfile_end SET C, POP @@ -633,43 +634,43 @@ SET B, 1 JSR shell_getparameter - JSR [0x101F] + INT 0x101F ;check if 'cd' SET A, command_parameter_buffer SET B, command_cd - JSR [0x101A] + INT 0x101A IFE C, 0 SET PC, command_cdf_help ; check if blank > load help SET A, command_parameter_buffer - JSR [0x1019] + INT 0x1019 IFE B, 0 SET PC, command_cdf_help ;check if '..' SET A, command_parameter_buffer SET B, command_cd_back - JSR [0x101A] + INT 0x101A IFE C, 0 SET PC, command_cdf_back ;check if '/' SET A, command_parameter_buffer SET B, command_cd_root - JSR [0x101A] + INT 0x101A IFE C, 0 SET PC, command_cdf_root - JSR [0x1029] + INT 0x1029 IFN C, 0 SET PC, command_cdf_cd SET PC, command_cdf_unknown :command_cdf_help SET A, command_cd_help - JSR [0x101E] + INT 0x101E SET PC, command_cdf_end :command_cdf_back @@ -701,9 +702,9 @@ :command_cdf_unknown SET A, command_parameter_buffer - JSR [0x101E] + INT 0x101E SET A, command_cd_unknown - JSR [0x101E] + INT 0x101E SET PC, command_cdf_end :command_cdf_cd @@ -748,10 +749,10 @@ SET A, input_text_buffer SET B, 1 JSR shell_getparameter - JSR [0x101F] ; newline + INT 0x101F ; newline ; Get the file from the filename SET A, command_parameter_buffer - JSR [0x1029] ; filesystem_getfile + INT 0x1029 ; filesystem_getfile IFE C, 0 SET PC, command_catf_end @@ -773,13 +774,13 @@ SET PUSH, B SET PUSH, A - JSR [0x100F] ; page_alloc + INT 0x100F ; page_alloc SET C, A SET A, POP SET B, C SET C, POP AND C, 0x03FF ; For now we are limiting cat to just 1024 words of output - JSR [0x1013] ; mem_copy + INT 0x1013 ; mem_copy SET A, B :command_catf_sanitize IFE [B], 0 @@ -790,11 +791,11 @@ SET PC, command_catf_sanitize SET [B], 0 - JSR [0x101E] ; text_out + INT 0x101E ; text_out :command_catf_end SET [ack_command], 1 - JSR [0x101F] ; newline + INT 0x101F ; newline SET C, POP SET B, POP @@ -809,12 +810,12 @@ SET A, input_text_buffer ADD A, 5 SET B, command_parameter_buffer - JSR [0x1017] + INT 0x1017 SET A, command_parameter_buffer - JSR [0x101F] ; Newline (hack!) - JSR [0x101E] - JSR [0x101F] ; Newline + INT 0x101F ; Newline (hack!) + INT 0x101E + INT 0x101F ; Newline SET B, POP SET A, POP @@ -824,7 +825,7 @@ SET [ack_command], 1 SET PUSH, A SET A, command_help_list - JSR [0x101E] + INT 0x101E SET A, POP SET PC, POP @@ -832,9 +833,9 @@ :AtlasShell_die SET A, input_buffer - JSR [0x1027] ; unregister_keyboard - JSR [0x101F] ; newline - JSR [0x1005] ; proc_kill_me + INT 0x1027 ; unregister_keyboard + INT 0x101F ; newline + INT 0x1005 ; proc_kill_me ; ==BEGIN HELPER FUNCTIONS== ; Displays OS version using API call to get version numbers @@ -845,13 +846,13 @@ SET B, 0 SET C, 0 ; A - main version, B - sub version, C - fix version - JSR [0x1000] + INT 0x1000 SET PUSH, C SET PUSH, B MUL A, 10000 SET B, command_number_buffer SET C, 10 ; radix - JSR [0x101B] ; itoa + INT 0x101B ; itoa IFE A, 0 SET [B], 0x0030 SET A, command_number_buffer @@ -860,21 +861,21 @@ MUL A, 100 SET B, command_number_buffer SET C, 10 ; radix - JSR [0x101B] ; itoa + INT 0x101B ; itoa SET A, command_number_buffer SET C, POP SET A, C SET B, command_number_buffer SET C, 10 ; radix - JSR [0x101B] ; itoa + INT 0x101B ; itoa SET A, command_number_buffer ADD A, 1 SET [A], [command_version_separator] ADD A, 2 SET [A], [command_version_separator] SET A, command_number_buffer - JSR [0x101E] - JSR [0x101F] + INT 0x101E + INT 0x101F SET PC, POP ; Clears the parameter buffer :command_clear_parameter_buffer @@ -882,7 +883,7 @@ SET PUSH, B SET A, command_parameter_buffer SET B, 32 - JSR [0x1014] + INT 0x1014 SET B, POP SET A, POP SET PC, POP @@ -907,7 +908,7 @@ SET PUSH, B SET A, present_working_directory_name SET B, 16 - JSR [0x1014] + INT 0x1014 SET B, POP SET A, POP SET PC, POP diff --git a/apps/AtlasText.dasm16 b/apps/AtlasText.dasm16 index 5f6ee96..05c9d59 100644 --- a/apps/AtlasText.dasm16 +++ b/apps/AtlasText.dasm16 @@ -1,17 +1,16 @@ ; AtlasText - A simple, dummy text editor :AtlasText - IAQ 1 - SET I, AtlasText_loop_end ; Calculate the length of the back-jump - SUB I, AtlasText_loop + ; Register our buffer with the driver SET A, AtlasText_input_buffer ; And ask for exclusive keyboard access SET B, 1 - JSR [0x1026] ; keyboard_register + INT 0x1026 + INT 0x102D - JSR [0x100f] ; page allocate for large string bufer + INT 0x100f ; page allocate for large string bufer SET [AtlasText_page], A SET [AtlasText_input_buffer], 0 @@ -26,13 +25,13 @@ JSR mem_clear ; Clear the buffer ADD B, A - IAQ 0 + SET PUSH, A SET PUSH, B SET PUSH, C :AtlasText_getfilename - JSR [0x1021] ; clear + JSR clear ; clear SET A, AtlasText_intro JSR text_out @@ -47,16 +46,17 @@ SET A, AtlasText_filename_buffer SET B, 15 SET C, AtlasText_input_buffer - JSR [0x1023] ; readline + INT 0x1023 ; readline SET A, AtlasText_filename_buffer - JSR [0x1019] ; strlen + INT 0x1019 ; strlen IFE B, 0 SET PC, AtlasText_getfilename ; loopback on blank filename - JSR [0x1021] ; clear + INT 0x1021 ; clear SET C, POP SET B, POP SET A, POP + SET PC, AtlasText_blink :AtlasText_loop IFE [AtlasText_input_buffer], 0 @@ -101,63 +101,44 @@ SET [C], 0 ADD A, 1 -:AtlasText_skip +:AtlasText_blink ; Display the blinking cursor SET PUSH, A - SET PUSH, B - SET PUSH, C SET A, [video_cur] - SUB A, [video_mem] - SET B, 0 - SET C, 0x709F - JSR char_put - SET C, POP - SET B, POP + SET [A], 0x709F SET A, POP - +:AtlasText_skip SET PC, AtlasText_loop :AtlasText_backspace ; Remove the blinking cursor SET PUSH, A - SET PUSH, B - SET PUSH, C SET A, [video_cur] - SUB A, [video_mem] - SET B, 0 - SET C, [video_clear] - JSR char_put - SET C, POP - SET B, POP + SET [A], [video_clear] SET A, POP ; Ensure we don't backspace past the beginning IFE A, PEEK - SET PC, AtlasText_skip + SET PC, AtlasText_blink SET PUSH, A - SET A, [video_mem] - IFE [video_cur], A - JSR AtlasText_scrollback + IFE [video_cur], [video_mem] + SET PC, AtlasText_scrollback SET A, POP SUB A, 1 IFE [A], 0xA ; if last character was a new line move cursor back to last printed character JSR AtlasText_backspace_newline - ADD A, 1 - SET PUSH, A SET PUSH, B SUB [video_cur], 1 SET B, [video_cur] SET [B], 0 SET B, POP - SET A, POP - SUB A, 1 SET [A], 0 SET [C], 0 - SET PC, AtlasText_skip + SET PC, AtlasText_blink :AtlasText_backspace_newline SET PUSH, A @@ -165,80 +146,81 @@ SET B, 32 :AtlasText_backspace_newline_loop IFE B, 0 - SET PC, AtlasText_backspace_newline_loop_end + SET PC, AtlasText_backspace_newline_loop1_end SET A, [video_cur] SUB A, 1 SET A, [A] AND A, 0x7f IFN A, 0x20 - SET PC, AtlasText_backspace_newline_loop_end + SET PC, AtlasText_backspace_newline_loop1_end SUB [video_cur], 1 SUB B, 1 SET PC, AtlasText_backspace_newline_loop -:AtlasText_backspace_newline_loop_end +:AtlasText_backspace_newline_loop1_end ADD [video_cur], 1 SET B, POP +SET A, PEEK +:AtlasText_backspace_newline_loop2 +SUB A, 1 +IFN [A], 0x20 + SET PC, AtlasText_backspace_newline_loop2_end +IFE A, PICK 1 + SET PC, AtlasText_backspace_newline_loop2_end +SET PC, AtlasText_backspace_newline_loop2 + +:AtlasText_backspace_newline_loop2_end +ADD A, 1 +JSR text_out_line SET A, POP SET PC, POP :AtlasText_scrollback -SET PUSH, PICK 1 ;get in text string and find either position of last newline or 32 characters back, what evers comes first -SET A, PEEK +; find either position of last newline or 32 characters back, what evers comes first SET PUSH, B SET B, 32 :AtlasText_scrollback_loop +IFE A, [AtlasText_page] +SET PC, AtlasText_scrollback_loop_end IFE B, 0 SET PC, AtlasText_scrollback_loop_end IFE [A], 0xA -IFE [AtlasText_newlinefound], 1 SET PC, AtlasText_scrollback_loop_end -IFE [A], 0xA -SET [AtlasText_newlinefound], 1 + SUB B, 1 SUB A, 1 -IFE A, [AtlasText_page] -SET PC, AtlasText_scrollback_loop_end SET PC, AtlasText_scrollback_loop :AtlasText_scrollback_loop_end SET [video_cur], [video_mem] -IFN [A+1], 0 -ADD A, 1 +;IFN [A+1], 0 JSR text_out -SET [AtlasText_newlinefound], 0 +;SET [AtlasText_newlinefound], 0 SET B, POP SET A, POP SET [C], 0 -SET PC, POP +SET PC, AtlasText_blink :AtlasText_return ; Remove the blinking cursor SET PUSH, A - SET PUSH, B - SET PUSH, C SET A, [video_cur] - SUB A, [video_mem] - SET B, 0 - SET C, [video_clear] - JSR char_put - SET C, POP - SET B, POP + SET [A], [video_clear] SET A, POP SET [C], 0 ; Add the newline symbol SET [A], 0xA ADD A, 1 - JSR [0x101f] ; newline - SET PC, AtlasText_skip + INT 0x101f ; newline + SET PC, AtlasText_blink :AtlasText_loop_skip - JSR [0x1002] ; proc_suspend - SUB PC, I + INT 0x1002 + SET PC, AtlasText_loop :AtlasText_loop_end :AtlasText_save @@ -247,7 +229,7 @@ SET PC, POP SET B, [AtlasText_page] SET X, AtlasText_filename_buffer JSR HAT_inode_directory_add_file - JSR [0x1021] ; clear + JSR clear ; clear SET A, AtlasText_saved jsr text_out SET A, AtlasText_filename_buffer @@ -261,10 +243,10 @@ SET PC, POP :AtlasText_die SET A, AtlasText_input_buffer IAQ 1 - JSR [0x1027] ; keyboard_unregister - JSR [0x1021] ; clear + JSR keyboard_unregister ; + JSR clear ; clear IAQ 0 - JSR [0x1005] ; proc_kill_me + JSR proc_kill_me ; proc_kill_me :AtlasText_data :AtlasText_input_buffer dat 0x0000, 0x0000 :AtlasText_page dat 0x0000 diff --git a/apps/asm.dasm16 b/apps/asm.dasm16 index 6579319..f599e4d 100644 --- a/apps/asm.dasm16 +++ b/apps/asm.dasm16 @@ -867,9 +867,9 @@ :asm_write_val ife X, 0 - set [asm_rb], Y + set [asm_rB], Y ife X, 1 - set [asm_ra], Y + set [asm_rA], Y add B, 1 set PC, POP :asm_skip_whites @@ -986,7 +986,7 @@ dat 0xfc00 ;SHL 5 :asm_BValueMask dat 0x03e0 -:asm_OpCodeMask +:asm_opCodeMask dat 0x001f ;Values :asm_vA dat 0x0000 diff --git a/apps/dcpu-vm.dasm16 b/apps/dcpu-vm.dasm16 index ddd9c62..4d59a03 100644 --- a/apps/dcpu-vm.dasm16 +++ b/apps/dcpu-vm.dasm16 @@ -9,27 +9,24 @@ ;memory based registers ;no hardware interupts -set [reg_pc], code -set pc, virtual_machine_start -:regs_AJ dat 0, 0, 0, 0, 0, 0, 0, 0 -:reg_SP dat 0 -:reg_PC dat 0 -:reg_EX dat 0 - -:val_nw dat 0 -:val_A dat 0 -:val_B dat 0 -:val_op dat 0 -:val_word dat 0 -:addr_source dat 0 -:addr_dest dat 0 -:mem_start dat 0 -:mem_end dat 0 -:cyclecounter dat 0 -:skipflag dat 0 +:dcpu_vm +set [reg_PC], [code_start] +JSR [0x100f] ; page allocate for stack +add a, 1024 +set [reg_sp], a + +; Register our buffer with the driver, to remove kernel screen access +IAQ 1 + SET A, dcpu_vm_input + ; And ask for exclusive keyboard access + SET B, 1 + JSR [0x1026] ; keyboard_register +IAQ 0 :virtual_machine_start add [cyclecounter], 1 +ife [reg_PC], [code_end] + set pc, virtual_machine_end set a, [reg_PC] set [val_word], [a] set a , [val_word] @@ -37,7 +34,7 @@ and a, 0x1f set [val_op], a set a, [val_word] and a, 0x3e0 -set [val_B], a +set [val_b], a set a, [val_word] and a, 0xfc00 set [val_A], a @@ -71,7 +68,7 @@ set [val_A], a set b, regs_AJ add b, a set [addr_source], b - set pc, decode_val_B + set pc, decode_val_b :decode_val_A_2 set b, regs_AJ @@ -88,37 +85,37 @@ set [val_A], a add b, c set [addr_source], b add [reg_PC], 1 - set pc, decode_val_B + set pc, decode_val_b :decode_val_A_SPPCEX - set b, reg_SP + set b, reg_sp sub a, 0x1b add b, a set [addr_source], b - set pc, decode_val_B + set pc, decode_val_b :decode_val_A_nw set b, [reg_PC] add b, 1 set [addr_source], b add [reg_PC], 1 - set pc, decode_val_B + set pc, decode_val_b :decode_val_A_nwr set b, [reg_PC] set [addr_source], [b + 1] add [reg_PC], 1 - set pc, decode_val_B + set pc, decode_val_b :decode_val_A_pop set b, [reg_sp] set [addr_source], b add [reg_sp], 1 - set pc, decode_val_B + set pc, decode_val_b :decode_val_A_peek set [addr_source], [reg_sp] - set pc, decode_val_B + set pc, decode_val_b :decode_val_A_pick set c, [reg_PC] @@ -126,13 +123,13 @@ set [val_A], a set b, [reg_sp] add b, c set [addr_source], b - set pc, decode_val_B + set pc, decode_val_b :decode_val_A_lit sub a, 0x20 add a, lit_table set [addr_source], a - set pc, decode_val_B + set pc, decode_val_b @@ -141,46 +138,46 @@ set [val_A], a -:decode_val_B - set a, [val_B] +:decode_val_b + set a, [val_b] shr a, 5 ifl a, 8 - set pc, decode_val_B_1 + set pc, decode_val_b_1 ifl a, 0x10 - set pc, decode_val_B_2 + set pc, decode_val_b_2 ifl a, 0x18 - set pc, decode_val_B_3 + set pc, decode_val_b_3 ife a, 0x1f set pc, op_end ife a, 0x1e - set pc, decode_val_B_nwr + set pc, decode_val_b_nwr ifg a, 0x1a ifl a, 0x1e - set pc, decode_val_B_SPPCEX + set pc, decode_val_b_SPPCEX ife a, 0x1a - set pc, decode_val_B_pick + set pc, decode_val_b_pick ife a, 0x19 - set pc, decode_val_B_peek + set pc, decode_val_b_peek ife a, 0x18 - set pc, decode_val_B_push + set pc, decode_val_b_push ifg a, 0x1f set pc, op_end -:decode_val_B_1 +:decode_val_b_1 set b, regs_AJ add b, a set [addr_dest], b set pc, decode_val_op -:decode_val_B_2 +:decode_val_b_2 set b, regs_AJ sub a, 0x8 add b, a set [addr_dest], [b] set pc, decode_val_op -:decode_val_B_3 +:decode_val_b_3 set b, [reg_PC] set b, [b+1] ; next word value sub a, 0x10 @@ -190,35 +187,35 @@ set [val_A], a add [reg_PC], 1 set pc, decode_val_op -:decode_val_B_nwr +:decode_val_b_nwr set b, [reg_PC] set [addr_dest], [b+1] add [reg_PC], 1 - set pc, decode_val_B + set pc, decode_val_op -:decode_val_B_SPPCEX - set b, reg_SP +:decode_val_b_SPPCEX + set b, reg_sp sub a, 0x1b add b, a set [addr_dest], b set pc, decode_val_op -:decode_val_B_push +:decode_val_b_push sub [reg_sp], 1 set [addr_dest], [reg_sp] - set pc, decode_val_B + set pc, decode_val_op -:decode_val_B_peek +:decode_val_b_peek set [addr_dest], [reg_sp] - set pc, decode_val_B + set pc, decode_val_op -:decode_val_B_pick +:decode_val_b_pick set c, [reg_PC] set c, [c+1] set b, [reg_sp] add b, c set [addr_dest], b - set pc, decode_val_B + set pc, decode_val_op :decode_val_op @@ -245,7 +242,7 @@ set [val_A], a set pc, decode_val_op_std sub a, 1 -mul a, 2 +mul a, 3 add a, decode_val_op_table set ex, [reg_EX] set pc, a @@ -283,7 +280,7 @@ set pc, a set b, [addr_source] set b, [b] sub b, 1 - set [reg_pc], b + set [reg_PC], b set pc, op_end @@ -299,8 +296,6 @@ set pc, a set pc, op_end :decode_val_op_if_true -:op_end_skipped -set [skipflag], 0 :op_end @@ -310,7 +305,15 @@ ifn [addr_dest], reg_PC add [reg_PC], 1 ife [skipflag], 1 -add [reg_pc], 1 +add [reg_PC], 1 + +set pc, virtual_machine_start + +:op_end_skipped +set [reg_EX], EX + +add [reg_PC], 1 +set [skipflag], 0 set pc, virtual_machine_start :decode_val_op_table @@ -375,23 +378,31 @@ set pc, virtual_machine_start dat 0xffff, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E -:code -set a, 1 -jsr code3 -set a, 2 - -:code2 -dat code -:code3 -set a, 5 -set pc, pop - - - - - +:regs_AJ dat 0, 0, 0, 0, 0, 0, 0, 0 +:reg_sp dat 0 +:reg_PC dat 0 +:reg_EX dat 0 +:val_nw dat 0 +:val_A dat 0 +:val_b dat 0 +:val_op dat 0 +:val_word dat 0 +:addr_source dat 0 +:addr_dest dat 0 +:code_start dat hello +:code_end dat hello_world +:cyclecounter dat 0 +:skipflag dat 0 +:dcpu_vm_input dat 0, 0 +:virtual_machine_end +IAQ 1 +set a, dcpu_vm_input +JSR [0x1027] ; keyboard_unregister +IAQ 0 +JSR [0x1005] ; proc_kill_me +:dcpu_vm_end diff --git a/misc/hello_world.dasm16 b/apps/hello_world.dasm16 similarity index 91% rename from misc/hello_world.dasm16 rename to apps/hello_world.dasm16 index 81ba5d4..9c22c63 100644 --- a/misc/hello_world.dasm16 +++ b/apps/hello_world.dasm16 @@ -12,4 +12,6 @@ set b, [video_mem] JSR text_out ; :hello_world dat "Hello World", 0xA, 0 -:hello_end \ No newline at end of file +:hello_end + +;hello my baby \ No newline at end of file diff --git a/atlas.10cproj b/atlas.10cproj index f6df7fe..ccdcafd 100644 --- a/atlas.10cproj +++ b/atlas.10cproj @@ -10,24 +10,26 @@ - - DevKit 10c Assembly File - + + + - + + - - - - + + + + + diff --git a/build.bat b/build.bat index 56250d7..45918f4 100644 --- a/build.bat +++ b/build.bat @@ -1,2 +1,2 @@ -@organic --input-file make.dasm16 --output-file AtlasOS.bin +@organic --input-file make.dasm16 --output-file AtlasOS.bin --listing Atlas_listing.lst --long-literals @pause \ No newline at end of file diff --git a/kernel/HAT_driver.dasm16 b/kernel/HAT_driver.dasm16 index 4dc1b78..0aec2d4 100644 --- a/kernel/HAT_driver.dasm16 +++ b/kernel/HAT_driver.dasm16 @@ -141,7 +141,7 @@ SET I, [HAT_num_sectors] :HAT_find_free_sector_loop IFN [A], 0xFFFF - SET PC, HAT_find_free_sector_found + SET PC, HAT_find_free_sector_found ADD A, 1 ADD B, 1 SUB I, 1 @@ -155,16 +155,16 @@ MUL B, 16 SET A, B :HAT_find_free_sector_found_loop - SHL PEEK, 1 - IFN EX, 0x0000 - SET PC, HAT_find_free_sector_skip + SHL PEEK, 1 + IFN EX, 0x0000 + SET PC, HAT_find_free_sector_skip - ADD SP, 1 - SET PC, HAT_find_free_sector_end + ADD SP, 1 + SET PC, HAT_find_free_sector_end :HAT_find_free_sector_skip - ADD A, 1 - SET PC, HAT_find_free_sector_found_loop + ADD A, 1 + SET PC, HAT_find_free_sector_found_loop :HAT_find_free_sector_none SET A, 0xFFFF @@ -668,40 +668,7 @@ SET A, POP SET X, POP SET PC, POP -:HAT_testwrite -SET PUSH, A -SET PUSH, B -SET PUSH, C -SET PUSH, X - -SET A, 0x002 ; query device flags -HWI [floppy_address] -SET Y, B ; store flags - -AND A, 0xFFFE ; set device to blocking mode -SET B, A -SET A, 0x0003 -HWI [floppy_address] - -SET A, 0x0011 ; write sector interrupt -SET B, 0 ; start at a sector given by a -SET C, 128 ; write a number of 512 word sectors -SET X, 0 -HWI [floppy_address] - -SET B, 0 -IFG A, 0 - SET PC, HAT_error -SET B, Y ;retrieve flags -SET A, 0x3 ; reset flags -HWI [floppy_address] - -SET X, POP -SET C, POP -SET B, POP -SET A, POP -SET PC, POP ; A-> hat sector id ; A <- the floppy sector that the hat sector lies in @@ -856,22 +823,22 @@ SET PC, [HAT_read_sector_stack_pc] ; A <- sector :HAT_inode_create -SET PUSH, A ; store type -SET PUSH, B -SET PUSH, C +SET PUSH, A ; store type +SET PUSH, B ; +SET PUSH, C ; JSR HAT_find_free_sector -SET PUSH, A ;store free sector +SET PUSH, A ;store free sector JSR HAT_allocate_sector -SET PUSH, PICK 3 -SET PUSH, PICK 3 -SET PUSH, 0 -SET PUSH, 0 -SET B, 4 -SET C, 0 +SET PUSH, PICK 3 +SET PUSH, PICK 3 +SET PUSH, 0 +SET PUSH, 0 +SET B, 4 +SET C, 0 JSR HAT_write_sector_stack -SET A, POP +SET A, POP SET C, POP SET B, POP ADD SP, 1 @@ -900,12 +867,14 @@ SET PC, POP ;for creating a directory inode ; A <- hat sector of new inode :HAT_inode_directory_create -SET PUSH, B -SET A, 1 -SET B, 1 -JSR HAT_inode_create -SET B, POP -SET PC, POP + SET PUSH, B + + SET A, 1 + SET B, 1 + JSR HAT_inode_create + + SET B, POP + SET PC, POP ;for adding a link to a directory inode ; A-> hat sector of inode diff --git a/kernel/core.dasm16 b/kernel/core.dasm16 index 3080e07..8454f23 100644 --- a/kernel/core.dasm16 +++ b/kernel/core.dasm16 @@ -6,24 +6,19 @@ JSR bios_boot ; clear screen (for emulator) JSR clear -; Display the logo -SET A, text_logo -JSR text_out + ; Bootmessage SET A, text_start JSR text_out ; Reserve all operating system code including api space -SET X, 0 -:code_mem -IFG X, os_content_end - SET PC, code_mem_end -SET A, X +SET A, 0 JSR page_reserve -ADD X, 1024 -SET PC, code_mem -:code_mem_end +SET A, os_content_end +DIV A, 512 +ADD A, 1 +JSR page_alloc_big ; Reserve stack-memory @@ -31,23 +26,20 @@ SET A, 0xFFFF JSR page_reserve - -SET X, 0 - ; Copy the API. -SET B, 0x1000 -SET A, api_start -SET C, api_end -SUB C, A -JSR mem_copy +;SET B, 0x1000 +;SET A, api_start +;SET C, api_end +;SUB C, A +;JSR mem_copy ; Clear out a few things SET [keyboard_buffers_exclusive], 0 JSR keyboard_unregister_all ;Format Disk and Create root directory -JSR HAT_format_disk_256 -JSR HAT_inode_directory_create +;JSR HAT_format_disk_256 +;JSR HAT_inode_directory_create ; OS ready message SET A, text_start_ok @@ -61,10 +53,7 @@ IAS kernel_interrupt_handler ; Check if the kernel is the only running process, if so start the shell JSR kernel_watchdog_checkalone - - ; Release back to other running processes - INT [proc_suspend_int] - + JSR proc_suspend SET PC, kernel_loop ; Watchdog to ensure the shell is always running even if in the background @@ -83,22 +72,4 @@ IAS kernel_interrupt_handler SET PC, POP :kernel_end - SET PC, kernel_end - -:api_padding -dat " " -dat " " -dat " " -dat " " -dat " " -dat " " -dat " " -dat " " -dat " " -dat " " -dat " " -dat " " -dat " " -dat " " -dat " " -:api_padding_end \ No newline at end of file + SET PC, kernel_end \ No newline at end of file diff --git a/kernel/drivers.dasm16 b/kernel/drivers.dasm16 index 18b5ec5..3ce57ec 100644 --- a/kernel/drivers.dasm16 +++ b/kernel/drivers.dasm16 @@ -21,9 +21,9 @@ IFE B, 0x12D0 ; Generic Clock (upper 16 bits) JSR bios_clock_init - IFE A, 0x4fd5 ; M35FD floppy disc drive (lower 16 bits) - IFE B, 0x24c5 ; M35FD floppy disc drive (upper 16 bits) - JSR bios_floppy_init +; IFE A, 0x24c5 ; M35FD floppy disc drive (lower 16 bits) +; IFE B, 0x4fd5 ; M35FD floppy disc drive (upper 16 bits) +; JSR bios_floppy_init IFN Z, 0 SET PC, bios_discover_hardware_loop @@ -88,7 +88,7 @@ ; Set clock tick rate (60/B = 5/sec) SET A, 0 - SET B, 12 ; 5/sec + SET B, 60 ; 5/sec HWI [clock_address] ; Setup interrupts for clock @@ -96,7 +96,6 @@ SET B, [clock_address] ; Our magic word to tell the handler we have a clock tick ADD B, 1 ; Always use HW+1 so we never pass a 0 to B as that would disable interrupts HWI [clock_address] - SET [proc_suspend_int], B SET PC, POP :bios_floppy_init @@ -115,7 +114,6 @@ IFE B, 0 SET PC, bios_floppy_end - SET IFE B, 2 SET [floppy_write_locked], 1 @@ -126,7 +124,7 @@ :bios_floppy_page_reserve JSR page_reserve ADD A, 1024 - IFN B, A + IFG B, A SET PC, bios_floppy_page_reserve :bios_floppy_end SET PC, POP @@ -158,7 +156,7 @@ dat 0x0000 :floppy_address dat 0x0000 -:floppy_media_inserted +:floppy_inserted dat 0 :floppy_words_per_sector dat 512 @@ -169,7 +167,7 @@ dat 0x0000 :floppy_paging_address dat 0xEB00 :floppy_paging_size -dat 0x0008 ; 8 sectors +dat 0x1000 ; 8 sectors @ 512 words :floppy_page_inuseflags dat 0x0000 ; Bit map of RAM pages in use along with flags (4 flag bits per sector) dat 0x0000 ; Bit 1 - Is active, Bit 2 - ??, Bit 3 - ??, Bit 4 - ?? @@ -199,14 +197,14 @@ dat 0x0000 ; Bit 1 - Is active, Bit 2 - ??, Bit 3 - ??, Bit 4 - ?? :driver_keyboard_loop ; Check to see if we have a buffer registered at this spot IFN [A], 0 - JSR driver_keyboard_save_to_buffer + JSR driver_keyboard_save_to_buffer ; Increment to the next buffer as long as we aren't at the end ADD A, 1 IFN A, keyboard_buffers_end - SET PC, driver_keyboard_loop + SET PC, driver_keyboard_loop :driver_keyboard_end - SET A, 0 - HWI [keyboard_address] + ;SET A, 0 + ;HWI [keyboard_address] SET C, POP SET B, POP SET A, POP @@ -247,10 +245,10 @@ dat 0x0000 ; Bit 1 - Is active, Bit 2 - ??, Bit 3 - ??, Bit 4 - ?? :keyboard_register_loop IFE [C], 0 - SET PC, keyboard_register_set + SET PC, keyboard_register_set ADD C, 1 IFN C, keyboard_buffers_end - SET PC, keyboard_register_loop + SET PC, keyboard_register_loop :keyboard_register_set SET [C], A @@ -275,10 +273,10 @@ dat 0x0000 ; Bit 1 - Is active, Bit 2 - ??, Bit 3 - ??, Bit 4 - ?? :keyboard_unregister_loop IFE [B], A - SET PC, keyboard_unregister_unset + SET PC, keyboard_unregister_unset ADD B, 1 IFN B, keyboard_buffers_end - SET PC, keyboard_unregister_loop + SET PC, keyboard_unregister_loop SET PC, keyboard_unregister_end :keyboard_unregister_unset SET [B], 0x0000 diff --git a/kernel/floppy.dasm16 b/kernel/floppy.dasm16 index a1f85e9..67d2ffe 100644 --- a/kernel/floppy.dasm16 +++ b/kernel/floppy.dasm16 @@ -5,14 +5,16 @@ ; A --> sector ; B --> memory address :floppy_write_sector -IFG A, 1439 - SET PC, filesystem_error + SET PUSH, X SET PUSH, Y SET PUSH, C SET PUSH, B SET PUSH, A + + IFG A, 1439 + SET PC, floppy_wr_error :floppy_write_sector_poll SET A, 0 @@ -46,15 +48,14 @@ IFG A, 1439 ; A --> sector ; B --> memory address :floppy_read_sector -IFG A, 1439 - SET PC, filesystem_error - SET PUSH, X SET PUSH, Y SET PUSH, C SET PUSH, B SET PUSH, A - + + IFG A, 1439 + SET PC, floppy_wr_error :floppy_read_sector_poll SET A, 0 HWI [floppy_address] @@ -73,7 +74,7 @@ IFG A, 1439 ; Writes a number of floppy sectors from memory ; A --> start sector ; B --> start memory address -: C --> number of sectors +; C --> number of sectors :floppy_write_sectors SET PUSH, C SET PUSH, B @@ -81,10 +82,10 @@ IFG A, 1439 :floppy_write_sectors_loop IFE C, 0 - SET PC, floppy_write_sectors_end + SET PC, floppy_wr_sectors_end JSR floppy_write_sector IFE A, 0xffff - SET PC, floppy_write_sectors_error + SET PC, floppy_wr_sectors_error ADD A, 1 ADD B, 512 SUB C, 1 @@ -101,7 +102,7 @@ IFG A, 1439 ; Reads a number of floppy sectors to memory ; A --> start sector ; B --> start memory address -: C --> number of sectors +; C --> number of sectors :floppy_read_sectors SET PUSH, C SET PUSH, B @@ -124,7 +125,7 @@ IFG A, 1439 ; A --> start sector on disk ; B --> number of sectors from paging space to write to disk ; set a to 0xffff in case of disk error -: Sets a to 0xffe in case of number of sectors being larger than the paging space +; Sets a to 0xffe in case of number of sectors being larger than the paging space :pfloppy_write_sectors SET PUSH, C SET PUSH, B @@ -147,15 +148,14 @@ IFG A, 1439 :pfloppy_wr_sectors_error SET PEEK, 0xfffe - SET PC, pfloppy_write_sectors_end + SET PC, pfloppy_wr_sectors_end -:pfloppy_read_sectors ;Reads a number of sectors from the floppy paging space. ; A --> start sector on disk ; B --> number of sectors from paging space to read from disk ; set a to 0xffff in case of disk error -: Sets a to 0xffe in case of number of sectors being larger than the paging space +; Sets a to 0xffe in case of number of sectors being larger than the paging space :pfloppy_read_sectors SET PUSH, C SET PUSH, B diff --git a/kernel/interrupts.dasm16 b/kernel/interrupts.dasm16 index 858dff3..e658115 100644 --- a/kernel/interrupts.dasm16 +++ b/kernel/interrupts.dasm16 @@ -5,36 +5,21 @@ IFE A, [keyboard_address] JSR kernel_interrupt_handler_keyboard + IFE A, [clock_address] - JSR kernel_interrupt_handler_clock + JSR kernel_interrupt_handler_clock + IFE A, [floppy_address] JSR kernel_interrupt_handler_floppy - IFE A, 0xFEDB - JSR kernel_interrupt_handler_manual + + IFE A, 0x1001 + JSR proc_suspend_interrupt + IFG A, 0x1000 + JSR kernel_interrupt_handler_kernel_call + SET EX, POP RFI 0 - -:kernel_interrupt_handler_manual - - - SET PUSH, C - SET PUSH, B - SET PUSH, A - - SET A, 2 - SET B, 0 - SET C, 0x6000 - JSR kernel_interrupt_debug_clock_ticker - - SET A, POP - SET B, POP - SET C, POP - - - JSR proc_suspend_interrupt - - SET PC, POP ; This line should never be called :kernel_interrupt_handler_keyboard jsr driver_keyboard @@ -50,6 +35,16 @@ jsr driver_keyboard JSR driver_floppy_handle_interrupt SET PC, POP +:kernel_interrupt_handler_kernel_call +SUB A, 0xFFF +ADD A, api_start +SET [kernel_call], [A] +SET A, PICK 2 +JSR [kernel_call] +SET PICK 2, A +SET PC, POP + +:kernel_call dat 0 ; ################################################## ; A -> X coordinate diff --git a/include/kernel.inc b/kernel/kernel.dasm16 similarity index 73% rename from include/kernel.inc rename to kernel/kernel.dasm16 index dce0aa6..929dd19 100644 --- a/include/kernel.inc +++ b/kernel/kernel.dasm16 @@ -18,21 +18,11 @@ SET PC, data_end :os_version_sub dat 0x0006 :os_version_fix dat 0x0002 -:preemptive_enabled dat 0x0000 +:proc_realtime_id dat 0x0000 :text_start dat "AtlasOS v0.6.2 starting... ", 0x00 :text_start_ok dat "OK", 0xA, 0x00 -:text_logo -dat " ___ __ __", 0xA -dat " / | / /_ / /____ ______", 0xA -dat " / /| |/ __// // __ `/ ___/", 0xA -dat " / ___ / / / // /_/ (__ )", 0xA -dat " /_/ |_\\_/_/_/ \\__,_/____/", 0xA -dat " / __ \\/ ___/", 0xA -dat " / / / /\\__ \\", 0xA -dat " / /_/ /___/ /", 0xA -dat " \\____//____/", 0xA, 0x00 -:text_logo_end + ; Bitmap of the OS-managed memory, occupied pages are marked by 1's. ; Total of 64kB of memory supported here - each word covers 16kB. :page_map @@ -40,59 +30,63 @@ dat " \\____//____/", 0xA, 0x00 :page_map1 dat 0x0000 :page_map2 dat 0x0000 :page_map3 dat 0x0000 +:page_map4 dat 0x0000 +:page_map5 dat 0x0000 +:page_map6 dat 0x0000 +:page_map7 dat 0x0000 ; Table mapping memory pages to processes. ; Each word holds a page descriptor. Low byte encodes proc id, high byte encodes ; the memory offset of the associated 1kB page. For example 0x0702 marks the memory area ; from 0x1C00 to 0x1FFF (7th page) as belonging to process 2. -:page_table ; 128 words - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +:page_table ; 128 words + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 :page_table_end - + :message_queue_table ; 32 words - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 :message_queue_table_end :int_msg dat 0x0 :processes dat 1 :proc_current dat 0x0001 -:proc_suspend_int dat 0x0 +:proc_suspend_int dat 0x1002 :proc_table -dat 0x0001, 0xFFFF, 0x0000, 0xFFFD -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 -dat 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0001, 0xFFFF, 0x0000, 0xFFFD, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 :proc_table_end ; Keyboard driver variables @@ -181,7 +175,7 @@ dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 dat scroll ; 0x1020 Scrolls the screen one line dat clear ; 0x1021 Clears the screen dat char_put ; 0x1022 Puts a char on the screen - dat read_line ; 0x1023 Reads a line from the keyboard to a buffer + dat read_line_intcall ; 0x1023 Reads a line from the keyboard to a buffer dat rand ; 0x1024 Gets a random number dat srand ; 0x1025 Initializes the random number generator @@ -195,6 +189,8 @@ dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 dat virtual_filesystem_getfile_bystart ; 0x102B Returns the start of the matched filesystem entry in C, 0 otherwise dat char_get ; 0x102C Returns the value at the A, B location on the screen + dat proc_realtime ; 0x102D toggles realtime status of current process + dat text_out_line ; 0x102C :api_end diff --git a/kernel/library.dasm16 b/kernel/library.dasm16 index c1ad6ca..ce430d0 100644 --- a/kernel/library.dasm16 +++ b/kernel/library.dasm16 @@ -1,181 +1,218 @@ ; prints a text to stdout ; A: start address of the text :text_out - SET PUSH, A - SET PUSH, B - SET PUSH, C - SET PUSH, X - SET PUSH, I + SET PUSH, A + SET PUSH, B + SET PUSH, C + SET PUSH, X + SET PUSH, I - SET B, [video_col] - SET I, [video_cur] + SET B, [video_col] + SET I, [video_cur] - SET X, [video_width] - MUL X, [video_height] - ADD X, [video_mem] + SET X, [video_width] + MUL X, [video_height] + ADD X, [video_mem] :text_out_loop - SET C, [A] - IFE C, 0x0000 - SET PC, text_out_end - IFE C, 0xA - SET PC, text_out_nl - AND C, 0x00FF - BOR C, B - SET [I], C - ADD A, 1 - ADD I, 1 - IFE I, X - SET PC, text_out_scroll - SET PC, text_out_loop + SET C, [A] + IFE C, 0x0000 + SET PC, text_out_end + IFE C, 0xA + SET PC, text_out_nl + AND C, 0x00FF + BOR C, B + SET [I], C + ADD A, 1 + ADD I, 1 + IFE I, X + SET PC, text_out_scroll + SET PC, text_out_loop :text_out_scroll - SET [video_cur], I - JSR scroll - SET I, [video_cur] - SET PC, text_out_loop + SET [video_cur], I + JSR scroll + SET I, [video_cur] + SET PC, text_out_loop :text_out_nl - SET [video_cur], I - JSR newline - SET I, [video_cur] - ADD A, 1 - SET PC, text_out_loop + SET [video_cur], I + JSR newline + SET I, [video_cur] + ADD A, 1 + SET PC, text_out_loop :text_out_end - SET [video_cur], I - SET I, POP - SET X, POP - SET C, POP - SET B, POP - SET A, POP - SET PC, POP + SET [video_cur], I + SET I, POP + SET X, POP + SET C, POP + SET B, POP + SET A, POP + SET PC, POP ; prints a text to stdout with a length limitation ; A: start address of the text ; B: number of a characters :text_out_length - SET PUSH, A - SET PUSH, B - SET PUSH, C - SET PUSH, X - SET PUSH, Y - SET PUSH, I + SET PUSH, A + SET PUSH, B + SET PUSH, C + SET PUSH, X + SET PUSH, Y + SET PUSH, I - SET Y, B + SET Y, B - SET B, [video_col] - SET I, [video_cur] + SET B, [video_col] + SET I, [video_cur] - SET X, [video_width] - MUL X, [video_height] - ADD X, [video_mem] + SET X, [video_width] + MUL X, [video_height] + ADD X, [video_mem] :text_out_length_loop - IFE Y, 0 + IFE Y, 0 SET PC, text_out_length_end - SET C, [A] - IFE C, 0x0000 - SET PC, text_out_length_end - IFE C, 0xA - SET PC, text_out_length_nl - AND C, 0x00FF - BOR C, B - SET [I], C - ADD A, 1 - SUB Y, 1 - ADD I, 1 - IFE I, X - SET PC, text_out_length_scroll - SET PC, text_out_length_loop + SET C, [A] + IFE C, 0x0000 + SET PC, text_out_length_end + IFE C, 0xA + SET PC, text_out_length_nl + AND C, 0x00FF + BOR C, B + SET [I], C + ADD A, 1 + SUB Y, 1 + ADD I, 1 + IFE I, X + SET PC, text_out_length_scroll + SET PC, text_out_length_loop :text_out_length_scroll - SET [video_cur], I - JSR scroll - SET I, [video_cur] - SET PC, text_out_length_loop + SET [video_cur], I + JSR scroll + SET I, [video_cur] + SET PC, text_out_length_loop :text_out_length_nl - SET [video_cur], I - JSR newline - SET I, [video_cur] - ADD A, 1 - SUB Y, 1 - SET PC, text_out_length_loop + SET [video_cur], I + JSR newline + SET I, [video_cur] + ADD A, 1 + SUB Y, 1 + SET PC, text_out_length_loop :text_out_length_end - SET [video_cur], I - SET I, POP - SET Y, POP - SET X, POP - SET C, POP - SET B, POP - SET A, POP - SET PC, POP + SET [video_cur], I + SET I, POP + SET Y, POP + SET X, POP + SET C, POP + SET B, POP + SET A, POP + SET PC, POP + +; prints a text to stdout stops at null or newline character +; A: start address of the text +:text_out_line + SET PUSH, A + SET PUSH, B + SET PUSH, C + SET PUSH, X + SET PUSH, I + + SET B, [video_col] + SET I, [video_cur] + + SET X, [video_width] + MUL X, [video_height] + ADD X, [video_mem] + +:text_out_line_loop + SET C, [A] + IFE C, 0x0000 + SET PC, text_out_end + IFE C, 0xA + SET PC, text_out_end + AND C, 0x00FF + BOR C, B + SET [I], C + ADD A, 1 + ADD I, 1 + IFE I, X + SET PC, text_out_line_scroll + SET PC, text_out_line_loop + +:text_out_line_scroll + SET [video_cur], I + JSR scroll + SET I, [video_cur] + SET PC, text_out_line_loop ; Linefeed :newline - SET PUSH, A - SET PUSH, B - SET PUSH, X - - SET X, [video_width] - MUL X, [video_height] - ADD X, [video_mem] - - SET A, 0x0020 - SET B, [video_cur] - MOD B, A - SUB A, B - ADD [video_cur], A - IFE [video_cur], X - JSR scroll - - SET X, POP - SET B, POP - SET A, POP - SET PC, POP + SET PUSH, A + SET PUSH, B + SET PUSH, X + + SET X, [video_width] + MUL X, [video_height] + ADD X, [video_mem] + + SET A, 0x0020 + SET B, [video_cur] + MOD B, A + SUB A, B + ADD [video_cur], A + IFE [video_cur], X + JSR scroll + + SET X, POP + SET B, POP + SET A, POP + SET PC, POP ; Scrolls the screen one line :scroll - SET PUSH, A - SET PUSH, X - SET PUSH, Y - - SET X, [video_mem] ; Set X to the video memory - SET Y, [video_mem] - ADD Y, 0x0020 ; Set Y to the second line in the video memory - - SET A, [video_width] - MUL A, [video_height] - ADD A, [video_mem] + SET PUSH, A + SET PUSH, X + SET PUSH, Y + + SET X, [video_mem] ; Set X to the video memory + SET Y, [video_mem] + ADD Y, 0x0020 ; Set Y to the second line in the video memory + + SET A, [video_width] + MUL A, [video_height] + ADD A, [video_mem] :scroll_loop1 - SET [X], [Y] - SET [1+X], [1+Y] - SET [2+X], [2+Y] - SET [3+X], [3+Y] + SET [X], [Y] + SET [1+X], [1+Y] + SET [2+X], [2+Y] + SET [3+X], [3+Y] - ADD X, 4 - ADD Y, 4 + ADD X, 4 + ADD Y, 4 - IFN Y, A + IFN Y, A SET PC, scroll_loop1 :scroll_loop2 - SET [X], [video_clear] - ADD X, 1 - IFE X, A - SET PC, scroll_end - SET PC, scroll_loop2 + SET [X], [video_clear] + ADD X, 1 + IFE X, A + SET PC, scroll_end + SET PC, scroll_loop2 :scroll_end - SUB [video_cur], 0x20 - SET Y, POP - SET X, POP - SET A, POP - SET PC, POP + SUB [video_cur], 0x20 + SET Y, POP + SET X, POP + SET A, POP + SET PC, POP ; Clears the screen and sets the cursor to the first line (working) :clear @@ -185,26 +222,25 @@ SET A, [video_mem] SET B, [video_clear] - SET C, [video_width] - MUL C, [video_height] + SET C, 384 ADD C, [video_mem] :clear_loop - SET [A], B - SET [1+A], B - SET [2+A], B - SET [3+A], B - ADD A, 4 + SET [A], B + SET [1+A], B + SET [2+A], B + SET [3+A], B + ADD A, 4 - IFN A, C - SET PC, clear_loop + IFN A, C + SET PC, clear_loop :clear_end - SET [video_cur], [video_mem] - SET C, POP - SET B, POP - SET A, POP - SET PC, POP + SET [video_cur], [video_mem] + SET C, POP + SET B, POP + SET A, POP + SET PC, POP ; Clamps the value to within the screen memory map ; A -> Value input @@ -218,6 +254,8 @@ IFG A, B SET A, B + IFG [video_mem], A + SET A, [video_mem] SET B, POP SET PC, POP @@ -234,6 +272,8 @@ ADD A, B ADD A, [video_mem] JSR clamp_to_screen + IFl A, [video_mem] + ADD A, 1 SET [A], C :char_put_end SET B, POP @@ -326,7 +366,7 @@ SET B, POP SET A, POP SET PC, POP - + ; PUSHes all registers to the stack :pusha SET [pushpop_buffer], POP ; Save jump-back-address @@ -339,7 +379,7 @@ SET PUSH, Z SET PUSH, I SET PUSH, J - SET PUSH, EX + SET PUSH, EX SET PC, [pushpop_buffer] ; jump back @@ -347,7 +387,7 @@ :popa SET [pushpop_buffer], POP ; Save jump-back-address - SET EX, POP + SET EX, POP SET J, POP SET I, POP SET Z, POP @@ -391,19 +431,19 @@ ADD C, B :strncpy_loop1 IFE [A], 0 - SET PC, strncpy_loop2 + SET PC, strncpy_loop2 SET [B], [A] ADD A, 1 ADD B, 1 IFE B, C - SET PC, strncpy_end + SET PC, strncpy_end SET PC, strncpy_loop1 :strncpy_loop2 SET [B], 0 ADD B, 1 IFN B, C - SET PC, strncpy_loop2 + SET PC, strncpy_loop2 :strncpy_end SET C, POP @@ -427,9 +467,9 @@ SET PC, POP SET C, 0 :strcmp_loop IFE [A], 0 - SET PC, strcmp_end + SET PC, strcmp_end IFN [A], [B] - SET PC, strcmp_end + SET PC, strcmp_end ADD A, 1 ADD B, 1 SET PC, strcmp_loop @@ -464,6 +504,9 @@ SET PC, POP ; A: String buffer address ; B: Length ; C: Keybuffer +:read_line_intcall +ADD SP, 4 +IAQ 0 :read_line SET PUSH, C SET PUSH, B @@ -472,7 +515,7 @@ SET PC, POP JSR mem_clear ; Clear the buffer ADD B, A - + SET PC, read_line_blink :read_line_loop IFE [C], 0x11 ; 13 -> 17 per keyboard HW (enter) @@ -502,69 +545,50 @@ SET PC, POP MUL A, [video_height] ADD A, [video_mem] IFE [video_cur], A - JSR scroll + INT 0x1020 ; scroll SET B, POP SET A, POP SET [C], 0 ADD A, 1 -:read_line_skip - ; Display the blinking cursor +:read_line_blink + ; Display the blinking cursor SET PUSH, A - SET PUSH, B - SET PUSH, C SET A, [video_cur] - SUB A, [video_mem] - SET B, 0 - SET C, 0x709F - JSR char_put - SET C, POP - SET B, POP + SET [A], 0x709F SET A, POP +:read_line_skip SET PC, read_line_loop :read_line_backspace ; Remove the blinking cursor SET PUSH, A - SET PUSH, B - SET PUSH, C SET A, [video_cur] - SUB A, [video_mem] - SET B, 0 - SET C, [video_clear] - JSR char_put - SET C, POP - SET B, POP + SET [A], [video_clear] SET A, POP ; Ensure we don't backspace past the beginning IFE A, PEEK - SET PC, read_line_skip - - SET PUSH, A - SET PUSH, B + SET PC, read_line_blink + SUB [video_cur], 1 - SET B, [video_cur] - SET [B], 0 - SET B, POP + + SET PUSH, A + SET A, [video_cur] + SET [A], [video_clear] SET A, POP + SUB A, 1 + SET [A], 0 SET [C], 0 SET PC, read_line_skip :read_line_end ; Remove the blinking cursor SET PUSH, A - SET PUSH, B - SET PUSH, C SET A, [video_cur] - SUB A, [video_mem] - SET B, 0 - SET C, [video_clear] - JSR char_put - SET C, POP - SET B, POP + SET [A], [video_clear] SET A, POP SET [C], 0 ; Add the null terminator diff --git a/kernel/libs.dasm16 b/kernel/libs.dasm16 index 6b141b9..5d01e68 100644 --- a/kernel/libs.dasm16 +++ b/kernel/libs.dasm16 @@ -203,8 +203,8 @@ JSR lib_get_function IFN A, 0 JSR A - - SET A, [PEEK] + SET A, PEEK + SET A, [A] JSR page_free :lib_unload_end diff --git a/kernel/memory.dasm16 b/kernel/memory.dasm16 index 7da874b..12cbe76 100644 --- a/kernel/memory.dasm16 +++ b/kernel/memory.dasm16 @@ -2,23 +2,20 @@ ; A: From Addr ; B: Length :mem_clear - IFE B, 0 - SET PC, POP - - SET PUSH, A - SET PUSH, B + SET PUSH, A + SET PUSH, B - ADD B, A + ADD B, A :mem_clear_loop - SET [A], 0 - ADD A, 1 - IFN A, B - SET PC, mem_clear_loop + SET [A], 0 + ADD A, 1 + IFN A, B + SET PC, mem_clear_loop - SET B, POP - SET A, POP - SET PC, POP + SET B, POP + SET A, POP + SET PC, POP ; mem_copy ; Copies data from one location to another @@ -27,8 +24,6 @@ ; B -> dest ; C -> length :mem_copy - IFE C, 0 - SET PC, POP SET PUSH, A SET PUSH, B SET PUSH, C @@ -53,195 +48,135 @@ SET B, POP SET A, POP SET PC, POP - -; A: Mem addr of the page + +; Reserve memory for the current process +; A: Mem address of the page :page_reserve - SET PUSH, B - - SET B, A - MOD B, 1024 - SUB A, B - DIV A, 1024 ; Set the pagenum - - JSR page_remove ; Remove all occurences of this page - SET B, 0x0001 ; By the OS - JSR page_combine ; Combine A (the page num) and B (the proc id) to the page entry - BOR A, 0x8000 ; Set the "reserved" flag - JSR page_add - - SET B, POP - SET PC, POP + SET PUSH, B + SET PUSH, A + + + JSR proc_id + SET B, A + SET A, POP + JSR page_reserve_for + + SET B, POP + SET PC, POP + +; Reserve memory for the process given by B +; A: Mem address of the page +; B: Process ID number +:page_reserve_for + SET PUSH, B + SET PUSH, A + DIV A, 512 + SET [A+page_table], B + JSR page_set_map + + SET A, POP + SET B, POP + SET PC, POP -; A: Removes all entries with the given page num +; Free page number given by A :page_remove - SET PUSH, A - SET PUSH, B - - AND A, 0x003F - SHL A, 8 - SET PUSH, A - - SET B, page_table - -:page_remove_loop - SET A, [B] - AND A, 0x3F00 - IFE A, PEEK - SET [B], 0x0000 ; Remove entry - ADD B, 1 - IFN B, page_table_end - SET PC, page_remove_loop - - SET A, POP ; Remove a from stack - SET B, POP ; Restore registers - SET A, POP - SET PC, POP - -; A -> page num -; B -> proc id -; A <- combined page entry -:page_combine - SET PUSH, B - - AND A, 0x003F - SHL A, 8 - AND B, 0x00FF - BOR A, B - - SET B, POP - SET PC, POP - -; A -> combined page entry -; A <- page num -; B <- proc id -:page_decombine - SET B, A - - SHR A, 8 - AND A, 0x003F - AND B, 0x00FF - - SET PC, POP - -; Find an empty entry in the page_table and store the page descriptor. -; A -> combined page entry -; A <- 1 of succeeded, 0 if failed -:page_add - SET PUSH, B - SET B, page_table - -:page_add_loop - IFE [B], 0 - SET PC, page_add_set - - ADD B, 1 - IFN B, page_table_end - SET PC, page_add_loop - - SET A, 0 - -:page_add_end - SET B, POP - SET PC, POP - -:page_add_set - SET [B], A - - JSR page_decombine - JSR page_set_map + SET [A+page_table], 0 + JSR page_unset_map + SET PC, POP - SET A, 1 - SET PC, page_add_end +; Reserve memory for the current process +; A: Mem address of the page +; B: number of pages +:page_reserve_big + SET PUSH, B + SET PUSH, A + +:page_reserve_big_loop + JSR page_reserve + IFE B, 0 + SET PC, page_reserve_big_end + ADD A, 512 + SUB B, 1 + SET PC, page_reserve_big_loop +:page_reserve_big_end + SET A, POP + SET B, POP ; Finds the first free page of memory by inspecting the bits of the page_map. ; A <- first free page number. :page_find_free + SET PUSH, I + SET PUSH, J + SET PUSH, B + + SET I, page_map + SET J, 0 +:page_find_free_loop + ; 0xFFFF means given 16kB is fully occupied. + + IFN [I], 0xFFFF + SET PC, page_find_free_found + STI A, A + IFE J, 8 + SET PC, page_find_free_none + IFN J, 8 + SET PC, page_find_free_loop + +:page_find_free_none + ; Nothing found, exiting! (later: Swap) + SET A, 0 - ;SET PC, page_find_free - - SET PUSH, B - - ; 0xFFFF means given 16kB is fully occupied. - SET A, page_map - SET B, 0 - IFN [A], 0xFFFF - SET PC, page_find_free_found - ADD A, 1 - ADD B, 1 - IFN [A], 0xFFFF - SET PC, page_find_free_found - ADD A, 1 - ADD B, 1 - IFN [A], 0xFFFF - SET PC, page_find_free_found - ADD A, 1 - ADD B, 1 - IFN [A], 0xFFFF - SET PC, page_find_free_found - - ; Nothing found, exiting! (later: Swap) - SET A, 0 - -:page_find_free_end - SET B, POP - SET PC, POP +:page_find_free_end + SET B, POP + SET J, POP + SET I, POP + SET PC, POP ; Find free page within this 16kB block by looking for a bit set to 0. :page_find_free_found - SET PUSH, [A] - ; B is the id of the page_map word - each word covers 16 pages. - MUL B, 16 - ; A will hold the final number. - SET A, B + SET PUSH, [I] + ; J is the id of the page_map word - each word covers 16 pages. + MUL J, 16 + ; A will hold the final number. + SET A, J :page_find_free_found_loop - SHR PEEK, 1 - IFN EX, 0x0000 - SET PC, page_find_free_skip + SHR PEEK, 1 + IFN EX, 0x0000 + SET PC, page_find_free_skip - ADD SP, 1 - SET PC, page_find_free_end + ADD SP, 1 + SET PC, page_find_free_end :page_find_free_skip - ADD A, 1 - SET PC, page_find_free_found_loop + ADD A, 1 + SET PC, page_find_free_found_loop ; Allocates a page for the current application ; A <- Address of the allocated memory page. :page_alloc - SET PUSH, B - - JSR page_find_free - IFE A, 0 - SET PC, page_alloc_error - - SET PUSH, A - - JSR proc_id - SET B, A ; proc_id - SET A, PEEK ; free page number + SET PUSH, B - JSR page_combine - JSR page_add - IFE A, 0 - SET PC, page_alloc_error2 + JSR page_find_free + IFE A, 0 + SET PC, page_alloc_error - SET A, POP + ; Calculate the real mem address of the allocated page. + MUL A, 512 + + JSR page_reserve - ; Calculate the real mem address of the allocated page. - MUL A, 1024 :page_alloc_end - SET B, POP - SET PC, POP - -:page_alloc_error2 - SET A, POP + SET B, POP + SET PC, POP :page_alloc_error - SET A, 0 - SET PC, page_alloc_end + SET A, 0 + SET PC, page_alloc_end + + ; Allocates multiple pages for the application to be used if the application exceeds one page length ; A -> number of pages to allocate @@ -249,7 +184,7 @@ :page_alloc_big SET PUSH, C SET PUSH, B - + SET B, A ; Store the number of pages SUB B, 1 @@ -280,214 +215,121 @@ ; Frees the given page for the current application ; A: memory :page_free - - SET PC, page_free - - SET PUSH, A - SET PUSH, B - SET PUSH, C - - SET B, A - MOD B, 1024 - SUB A, B - SET C, A - - JSR proc_id - SET B, A - SET A, C - - JSR page_combine - SET PUSH, A - SET A, page_table - -:page_free_loop - SET B, [A] - AND B, 0x3FFF - IFE B, PEEK - SET PC, page_free_found - ADD A, 1 - IFN A, page_table_end - SET PC, page_free_loop - -:page_free_end - SET A, POP - SET C, POP - SET B, POP - SET A, POP - SET PC, POP - -:page_free_found - SET [A], 0x0000 - - ADD SP, 3 - SET A, PEEK - SUB SP, 3 - - JSR page_unset_map - - SET PC, page_free_end + SET PUSH, A + DIV A, 512 + JSR page_remove + SET A, POP + SET PC, POP ; Deallocate all pages belonging to the process ; A -> proc_id (or proc info structure) :page_free_of - SET PUSH, A - SET PUSH, B - - SET PUSH, C - AND A, 0x00FF - SET PUSH, A - SET C, page_table - + SET PUSH, A + SET PUSH, B + SET PUSH, C + SET B, A + SET A, 0 + SET C, page_table_end + SUB C, page_table + :page_free_of_loop - SET A, [C] - - - JSR page_decombine - - ; check the proc id - IFN B, PEEK - SET PC, page_free_of_loop_skip - - ; found page associated with the process - free it in page_table - SET [C], 0x0000 - ; unset the page bit in page_map (page number is in A after decombine) - JSR page_unset_map - -:page_free_of_loop_skip - ADD C, 1 - IFN C, page_table_end - SET PC, page_free_of_loop - - ADD SP, 1 + IFE [A+page_table], B + JSR page_remove + IFE A, C + SET PC, page_free_of_end + ADD A, 1 + SET PC, page_free_of_loop + - SET C, POP - SET B, POP - SET A, POP - SET PC, POP +:page_free_of_end + SET C, POP + SET B, POP + SET A, POP + SET PC, POP ; A: page num :page_set_map - SET PUSH, A - SET PUSH, B - - SET B, 0x0001 + SET PUSH, A + SET PUSH, B + SET PUSH, C + SET C, A + SET B, 0x0001 - IFG 16, A - SET PC, page_set_map_0 - IFG 32, A - SET PC, page_set_map_1 - IFG 48, A - SET PC, page_set_map_2 + DIV A, 16 + MOD C, 16 - SUB A, 48 - SHL B, A - BOR [page_map3], B + SHL B, C + BOR [page_map+A], B :page_set_map_end - SET B, POP - SET A, POP - SET PC, POP - -:page_set_map_0 - SHL B, A - BOR [page_map0], B - SET PC, page_set_map_end - -:page_set_map_1 - SUB A, 16 - SHL B, A - BOR [page_map1], B - SET PC, page_set_map_end + SET C, POP + SET B, POP + SET A, POP + SET PC, POP -:page_set_map_2 - SUB A, 32 - SHL B, A - BOR [page_map2], B - SET PC, page_set_map_end ; A: page num :page_unset_map - SET PUSH, A - SET PUSH, B + SET PUSH, A + SET PUSH, B + SET PUSH, C + SET C, A - SET B, 0x0001 + SET B, 0x0001 - IFG 16, A - SET PC, page_unset_map_0 - IFG 32, A - SET PC, page_unset_map_1 - IFG 48, A - SET PC, page_unset_map_2 + DIV A, 16 + MOD C, 16 - SUB A, 48 - SHL B, A - XOR B, 0xFFFF - AND [page_map3], B + + SHL B, C + XOR B, 0xFFFF + AND [page_map+A], B :page_unset_map_end - SET B, POP - SET A, POP - SET PC, POP - -:page_unset_map_0 - SHL B, A - XOR B, 0xFFFF - AND [page_map0], B - SET PC, page_unset_map_end - -:page_unset_map_1 - SUB A, 16 - SHL B, A - XOR B, 0xFFFF - AND [page_map1], B - SET PC, page_unset_map_end - -:page_unset_map_2 - SUB A, 32 - SHL B, A - XOR B, 0xFFFF - AND [page_map2], B - SET PC, page_unset_map_end + SET C, POP + SET B, POP + SET A, POP + SET PC, POP + ; Returns the amount of reserved memory :page_check - SET PUSH, B + SET PUSH, B - SET B, page_table - SET A, 0 + SET B, page_table + SET A, 0 :page_check_loop - IFN [B], 0 - ADD A, 1024 - ADD B, 1 - IFN B, page_table_end - SET PC, page_check_loop + IFN [B], 0 + ADD A, 512 + ADD B, 1 + IFN B, page_table_end + SET PC, page_check_loop - SET B, POP - SET PC, POP + SET B, POP + SET PC, POP :page_check_of - SET PUSH, B - SET PUSH, C - SET PUSH, A + SET PUSH, B + SET PUSH, C + SET PUSH, A - SET B, page_table - SET A, 0 + SET B, page_table + SET A, 0 :page_check_of_loop - SET C, [B] - AND C, 0x00FF - IFE C, PEEK - ADD A, 1024 - ADD B, 1 - IFN B, page_table_end - SET PC, page_check_of_loop - - ADD SP, 1 - SET C, POP - SET B, POP - SET PC, POP \ No newline at end of file + SET C, [B] + IFE C, PEEK + ADD A, 512 + ADD B, 1 + IFN B, page_table_end + SET PC, page_check_of_loop + + ADD SP, 1 + SET C, POP + SET B, POP + SET PC, POP \ No newline at end of file diff --git a/kernel/process.dasm16 b/kernel/process.dasm16 index ec2eee5..459e2b9 100644 --- a/kernel/process.dasm16 +++ b/kernel/process.dasm16 @@ -44,7 +44,7 @@ :proc_get_flags_of JSR proc_get_info_of - ADD A, 11 + ADD A, 3 SET A, [A] SET PC, POP @@ -56,9 +56,9 @@ JSR proc_id :proc_get_info_of - MUL A, 4 + MUL A, 5 ADD A, proc_table - SUB A, 4 + SUB A, 5 SET PC, POP ; Sets the flags of the current process @@ -146,7 +146,7 @@ SET A, [B] IFN A, 0 JSR PEEK - ADD B, 4 + ADD B, 5 IFN B, proc_table_end SET PC, proc_callback_list_loop @@ -155,7 +155,7 @@ SET PC, POP :proc_suspend -INT [proc_suspend_int] +INT 0x1002 SET PC, POP @@ -163,6 +163,8 @@ SET PC, POP ADD SP, 3 ifl [processes], 2 rfi a +ife [proc_realtime_id], [proc_current] +rfi a SET PUSH, B SET PUSH, C SET PUSH, X @@ -176,14 +178,14 @@ SET [int_msg], A SET A, [proc_current] -MUL A, 4 -SUB A, 4 +MUL A, 5 +SUB A, 5 ADD A, proc_table ADD A, 1 SET [A], SP -add a, 3 +add a, 4 :proc_kill_me_hook :proc_suspend_loop @@ -192,7 +194,7 @@ add a, 3 SET X, [A] IFN X, 0x0000 SET PC, proc_suspend_invoke - ADD A, 4 + ADD A, 5 SET PC, proc_suspend_loop :proc_suspend_invoke @@ -248,7 +250,7 @@ add a, 3 IFE [X], 0x0000 SET PC, proc_load_to - ADD X, 4 + ADD X, 5 IFN X, proc_table_end SET PC, proc_load_loop @@ -263,7 +265,7 @@ add a, 3 ; Calculate the ProcID by finding the proc_table record number (OS is 1). SET [X], X SUB [X], proc_table - DIV [X], 4 + DIV [X], 5 ADD [X], 1 ; X = ProcInfo Addr @@ -359,7 +361,7 @@ add a, 3 SET C, POP SET B, POP IAQ 0 - INT [proc_suspend_int] + INT 0x1002 SET PC, POP :proc_load_stack_alloc @@ -372,7 +374,7 @@ add a, 3 SET Y, A ; Save the address of the new page SET A, PEEK ; Get back our original source address - ADD Y, 1024 + ADD Y, 512 SUB Y, 1 SET A, POP @@ -442,6 +444,8 @@ add a, 3 :proc_kill_me JSR proc_id ; Save process ID SET X, A + IFE [proc_realtime_id], A + JSR proc_realtime JSR proc_get_info_of ; Save process info address SET Y, A ADD A, 2 ; Save memory page @@ -489,4 +493,90 @@ add a, 3 SET PC, POP -; ############################################################## \ No newline at end of file +:proc_realtime + SET PUSH, A + IFN [proc_realtime_id], 0 + SET PC, proc_realtime_off + JSR proc_id + SET [proc_realtime_id], A + SET A, POP + SET PC, POP + +:proc_realtime_off + SET [proc_realtime_id], 0 + SET A, POP + SET PC, POP + +; ############################################################## + +; Threading +; using the underlying process architecture, threads are created much in the same way as processes, except that when a process is killed any accociated threads are killed as well. +; threads are also designed to run through once before returning to the owning process. In theory a thread could own other threads. +; Designed to allow effecient code reuse, ie a thread is created to manage a device by copying generic code. The owning process can then copy data into the thread memeory area to initilise it. Threads will have to prefaced with a relocation tabel to facilitate this. +; Atlas is limited to 16 threads/proccesses including the kernel. + +; A -> thread code location +; B -> thread code length +; C -> boolean if 1 thread code is copied into new memory location. +; A <- proc_id of thread +; B <- memory location of thread. +:create_thread + IAQ 1 + SET PUSH, B + SET PUSH, C + SET PUSH, X + SET PUSH, Y + SET PUSH, Z + SET PUSH, I + SET PUSH, J + + + SET X, proc_table + +:create_thread_loop1 + IFE [X], 0x0000 + SET PC, create_thread_start + + ADD X, 5 + IFN X, proc_table_end + SET PC, create_thread_loop1 + +:create_thread_error + SET A, 0 + SET PC, create_thread_end + +:create_thread_start + SET [X], X + SUB [X], proc_table + DIV [X], 5 + ADD [X], 1 + + ; X = ProcInfo Addr + + IFN C, 1 + create_thread_stack_alloc + + SET C, B + SET PUSH, A + + ADD B, 128 + DIV B, 1024 + ADD B, 1 + SET Y, B + SET A, B, + + + +; Must be called inside a process +; A -> proc_id of thread. +; removes a thread from the process list. +:kill_thread + +; Must be called inside a process +; A -> proc_id of thread. +; sets up the process manager to switch to the thread. +:call_thread + +; Must be called inside a thread +; Sets up the process manager to switch to the owning process. +:return_thread diff --git a/make.dasm16 b/make.dasm16 index 4c45170..bf9d88f 100644 --- a/make.dasm16 +++ b/make.dasm16 @@ -1,23 +1,28 @@ ; Kernel -.longform -.include "include/kernel.inc" + +.include "kernel/kernel.dasm16" .include "kernel/drivers.dasm16" .include "kernel/filesystem.dasm16" .include "kernel/graphics.dasm16" .include "kernel/interrupts.dasm16" .include "kernel/library.dasm16" .include "kernel/memory.dasm16" +.include "kernel/floppy.dasm16" .include "kernel/messages.dasm16" .include "kernel/process.dasm16" .include "kernel/core.dasm16" .include "kernel/math.dasm16" +.include "kernel/HAT_driver.dasm16" ; Apps .include "apps/AtlasShell.dasm16" .include "apps/AtlasText.dasm16" -.include "apps/asm.dasm16 +.include "apps/dcpu-vm.dasm16" +.include "apps/hello_world.dasm16" +.include "apps/asm.dasm16" .include "apps/apps.dasm16" ; Virtual Filesystem + .include "misc/vfs.dasm16" diff --git a/misc/vfs.dasm16 b/misc/vfs.dasm16 index 7032eff..0bf3a61 100644 --- a/misc/vfs.dasm16 +++ b/misc/vfs.dasm16 @@ -2,7 +2,7 @@ ; Primary file table ; Flags: Bit 1 - read, Bit 2 - write, Bit 3 - hidden, Bit 4 - executable, Bit 5 - directory -; Bit 6 - encrypted, Bit 7 - compressed +; Bit 6 - encrypted, Bit 7 - compressed ; Each entry must be 20 words long ; directory ID, flags, name, null terminator, padding, start, end ; For directory entries, the 'start' contains the ID and the 'end' is unused