├── LICENSE ├── README.txt ├── build-windows.c ├── build.sh ├── clib ├── bcd_to_int.asm ├── check_for_key.asm ├── clear_screen.asm ├── create_file.asm ├── crt0.asm ├── dialog_box.asm ├── draw_background.asm ├── draw_block.asm ├── dump_registers.asm ├── dump_string.asm ├── fatal_error.asm ├── file_exists.asm ├── file_selector.asm ├── find_char_in_string.asm ├── get_api_version.asm ├── get_cursor_pos.asm ├── get_date_string.asm ├── get_file_list.asm ├── get_file_size.asm ├── get_random.asm ├── get_time_string.asm ├── get_via_serial.asm ├── hide_cursor.asm ├── input_string.asm ├── int_to_string.asm ├── ioerr.asm ├── list_dialog.asm ├── load_file.asm ├── long_int_negate.asm ├── long_int_to_string.asm ├── mlib.asm ├── move_cursor.asm ├── pause.asm ├── port_byte_in.asm ├── port_byte_out.asm ├── print_1hex.asm ├── print_2hex.asm ├── print_4hex.asm ├── print_digit.asm ├── print_horiz_line.asm ├── print_newline.asm ├── print_space.asm ├── print_string.asm ├── readme.txt ├── remove_file.asm ├── rename_file.asm ├── run_basic.asm ├── send_via_serial.asm ├── serial_port_enable.asm ├── set_date_fmt.asm ├── set_time_fmt.asm ├── show_cursor.asm ├── sint_to_string.asm ├── speaker_off.asm ├── speaker_tone.asm ├── string_charchange.asm ├── string_chomp.asm ├── string_compare.asm ├── string_copy.asm ├── string_join.asm ├── string_length.asm ├── string_lowercase.asm ├── string_parse.asm ├── string_reverse.asm ├── string_strincmp.asm ├── string_strip.asm ├── string_to_int.asm ├── string_truncate.asm ├── string_uppercase.asm ├── wait_for_key.asm └── write_file.asm ├── image ├── PathOS.flp └── PathOS.iso ├── include ├── clib.h ├── crt0.asm └── mikedev.inc ├── programs ├── 2048.bin ├── 2048.c ├── archive.bas ├── calc.bas ├── cf.bas ├── clib.h ├── cosmicflight.bas ├── gorilla.bas ├── image-viewer.asm ├── image-viewer.bin ├── kd.asm ├── keyboard.asm ├── keyboard.bin ├── mbpp.bas ├── memedit.bas ├── mikedev.inc ├── monitor.asm ├── monitor.bin ├── mouse.lib ├── pos-vim.asm ├── pos-vim.bin ├── serial.asm ├── serial.bin ├── snake.bas └── test.c └── src ├── boot ├── boot.bin ├── bootload.asm └── bootload.bin ├── features ├── basic.asm ├── cli.asm ├── disk.asm ├── keyboard.asm ├── libmouse-1.1.1 │ ├── Old Versions │ │ ├── mouse.lib.100 │ │ ├── mouse.lib.110 │ │ └── mouse.lib.111 │ ├── api.txt │ ├── changes.txt │ ├── licence.txt │ ├── mikedev.inc │ ├── mouse.asm │ ├── mouse.lib │ ├── mouse2.asm │ ├── mouse3.asm │ └── readme.txt ├── math.asm ├── misc.asm ├── ports.asm ├── screen.asm ├── sound.asm └── string.asm ├── kernel.asm └── kernel.bin /README.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | PathOS 0.0.5! Big changes coming in version 0.1.0! 3 | 4 | --Version 0.0.5-- 5 | -Improved C library 6 | -Bug fixes 7 | -Added the game 2048 8 | 9 | How to install: 10 | Put image/PathOS.iso in a VM and give it no more than 256MB of memory. I would recommend gnome-boxes or VirtualBox. 11 | You can also write image/PathOS.flp on a floppy. 12 | 13 | How to build disk image: 14 | sudo su 15 | chmod +x build.sh 16 | ./build.sh 17 | 18 | How to buld disk image on Windows: 19 | Compile build-windows.c then run the exe, you may have to run it as administrator 20 | 21 | THANK YOU 22 | http://mikeos.sourceforge.net/ 23 | https://github.com/I8087 24 | https://github.com/ZeroKelvinKeyboard/ 25 | https://github.com/Camroku 26 | -------------------------------------------------------------------------------- /build-windows.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | printf("You need need NASM, if you don't have it (go to nasm.us)\n"); 6 | printf("PathOS Build Script For Windows\n"); 7 | printf("Assembling bootloader\n"); 8 | system("cd src/boot/ & nasm -00 -f bin -o bootload.bin bootload.bin"); 9 | printf("Assembling PathOS kernel\n"); 10 | system("cd src & nasm -00 -f -o kernel.bin kernel.asm"); 11 | printf("Compiling libraries\n"); 12 | system("cd clib & nasm -f elf -o ../mlib.a mlib.asm"); 13 | system("start https://www.nasm.us/"); 14 | return 0; 15 | } 16 | 17 | main(); 18 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script assembles the PathOS bootloader, kernel and programs 4 | # (If you need to blank the floppy image: 'mkdosfs image/PathOS.flp') 5 | # GNU GENERAL PUBLIC LICENSE 6 | 7 | 8 | if test "`whoami`" != "root" ; then 9 | echo "You must be logged in as root to build (for loopback mounting)" 10 | echo "Enter 'su' or 'sudo bash' to switch to root" 11 | exit 12 | fi 13 | 14 | 15 | if [ ! -e image/PathOS.flp ] 16 | then 17 | echo ">>> Creating new PathOS floppy image..." 18 | mkdosfs -C image/PathOS.flp 1440 || exit 19 | fi 20 | 21 | 22 | echo ">>> Assembling bootloader..." 23 | 24 | nasm -O0 -w+orphan-labels -f bin -o src/boot/boot.bin src/boot/bootload.asm || exit 25 | 26 | 27 | echo ">>> Assembling PathOS kernel..." 28 | 29 | cd src 30 | nasm -O0 -w+orphan-labels -f bin -o kernel.bin kernel.asm || exit 31 | cd .. 32 | 33 | cd clib 34 | nasm -f elf -o ../mlib.a mlib.asm || exit 35 | cp ../mlib.a ../src/mlib.a 36 | cd .. 37 | 38 | echo ">>> Assembling programs..." 39 | 40 | cd programs 41 | 42 | for i in *.asm 43 | do 44 | nasm -O0 -w+orphan-labels -f bin $i -o `basename $i .asm`.bin || exit 45 | done 46 | 47 | cd .. 48 | 49 | 50 | echo ">>> Adding bootloader to floppy image..." 51 | 52 | dd status=noxfer conv=notrunc if=src/boot/boot.bin of=image/PathOS.flp || exit 53 | 54 | 55 | echo ">>> Copying PathOS kernel and programs..." 56 | 57 | rm -rf tmp-loop 58 | 59 | mkdir tmp-loop && mount -o loop -t vfat image/PathOS.flp tmp-loop && cp src/kernel.bin tmp-loop/ 60 | 61 | cp programs/*.bin programs/*.bas programs/sample.pcx tmp-loop 62 | 63 | sleep 0.2 64 | 65 | echo ">>> Unmounting loopback floppy..." 66 | 67 | umount tmp-loop || exit 68 | 69 | rm -rf tmp-loop 70 | 71 | 72 | echo ">>> Creating CD-ROM ISO image..." 73 | 74 | rm -f image/PathOS.iso 75 | genisoimage -quiet -V 'PathOS' -input-charset iso8859-1 -o image/PathOS.iso -b PathOS.flp image/ || exit 76 | mkisofs -quiet -V 'PathOS' -input-charset iso8859-1 -o image/PathOS.iso -b PathOS.flp image/ || exit 77 | 78 | echo '>>> Done!' 79 | 80 | -------------------------------------------------------------------------------- /clib/bcd_to_int.asm: -------------------------------------------------------------------------------- 1 | global _bcd_to_int 2 | 3 | _bcd_to_int: 4 | push bp 5 | mov bp, sp 6 | 7 | mov al, byte [bp+4] 8 | 9 | call os_bcd_to_int 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/check_for_key.asm: -------------------------------------------------------------------------------- 1 | global _check_for_key 2 | 3 | _check_for_key: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_check_for_key 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/clear_screen.asm: -------------------------------------------------------------------------------- 1 | global _clear_screen 2 | 3 | _clear_screen: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_clear_screen 8 | 9 | pop bp 10 | ret 11 | -------------------------------------------------------------------------------- /clib/create_file.asm: -------------------------------------------------------------------------------- 1 | global _create_file 2 | 3 | _create_file: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_create_file 10 | 11 | jc .error 12 | 13 | mov word [_ioerr], 0 14 | jmp .skip 15 | 16 | .error: 17 | mov word [_ioerr], 1 18 | 19 | .skip: 20 | pop bp 21 | ret 22 | -------------------------------------------------------------------------------- /clib/crt0.asm: -------------------------------------------------------------------------------- 1 | extern _main 2 | global __start 3 | 4 | __start: 5 | push bp 6 | mov bp, sp 7 | 8 | ; Make sure the Mike OS API version is 17 or higher. 9 | ; This will insure that the library doesn't call any 10 | ; functions that don't exist on older versions. 11 | call _get_api_version 12 | mov ah, 17 13 | cmp al, ah 14 | jl .api_error 15 | 16 | ; argv 17 | mov bx, .buffer 18 | 19 | ; argv[0] is always the file's name! 20 | mov word [bx], 0 21 | add bx, 2 22 | 23 | ; argc 24 | mov cx, 1 25 | 26 | ; If si is 0, then there are no args. 27 | cmp si, 0 28 | je .done 29 | 30 | ; Decrease because of the upcoming loop. 31 | dec si 32 | 33 | .loop: 34 | inc si 35 | 36 | ; Skip multiple blank spaces! 37 | cmp byte [si], ' ' 38 | je .loop 39 | 40 | ; Found an arg. 41 | mov [bx], si 42 | inc cx 43 | add bx, 2 44 | 45 | ; Make sure argv doesn't overflow! 46 | cmp cx, 12 47 | je .arg_error 48 | 49 | .find: 50 | ; That's all the args. 51 | cmp byte [si], 0 52 | je .done 53 | 54 | ; Go to the next arg! 55 | cmp byte [si], ' ' 56 | je .next 57 | 58 | inc si 59 | 60 | jmp .find 61 | 62 | .next: 63 | mov byte [si], 0 64 | 65 | jmp .loop 66 | 67 | .done: 68 | ; Push argv and argc respectively. 69 | push word .buffer 70 | push cx 71 | 72 | ; Call the main function and clean up after it. 73 | call _main 74 | add sp, 4 75 | 76 | .exit: 77 | mov sp, bp 78 | pop bp 79 | ret 80 | 81 | .arg_error: 82 | push .arg_str 83 | call _print_string 84 | call _wait_for_key 85 | jmp .exit 86 | 87 | .api_error: 88 | push .api_str 89 | call _print_string 90 | call _wait_for_key 91 | jmp .exit 92 | 93 | .arg_str: db "Too many arguments were passed!", 13, 10, 0 94 | .api_str: db "This program will only run on MikeOS 4.6 and up!", 13, 10, 0 95 | .buffer: times 11 dw 0 96 | -------------------------------------------------------------------------------- /clib/dialog_box.asm: -------------------------------------------------------------------------------- 1 | global _dialog_box 2 | 3 | _dialog_box: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | mov bx, word [bp+6] 9 | mov cx, word [bp+8] 10 | movzx dx, byte [bp+10] 11 | 12 | call os_dialog_box 13 | 14 | pop bp 15 | ret -------------------------------------------------------------------------------- /clib/draw_background.asm: -------------------------------------------------------------------------------- 1 | global _draw_background 2 | 3 | _draw_background: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov [bp-2], bx 9 | 10 | mov ax, word [bp+4] 11 | mov bx, word [bp+6] 12 | mov cx, word [bp+8] 13 | 14 | call os_draw_background 15 | 16 | mov bx, word [bp-2] 17 | 18 | mov sp, bp 19 | pop bp 20 | ret 21 | -------------------------------------------------------------------------------- /clib/draw_block.asm: -------------------------------------------------------------------------------- 1 | global _draw_block 2 | 3 | _draw_block: 4 | push bp 5 | mov bp, sp 6 | sub sp, 6 7 | 8 | mov [bp-2], bx 9 | mov [bp-4], si 10 | mov [bp-6], di 11 | 12 | mov bl, byte [bp+4] 13 | mov dl, byte [bp+6] 14 | mov dh, byte [bp+8] 15 | movzx si, byte [bp+10] 16 | movzx di, byte [bp+12] 17 | 18 | call os_draw_block 19 | 20 | mov bx, word [bp-2] 21 | mov si, word [bp-4] 22 | mov di, word [bp-6] 23 | 24 | mov sp, bp 25 | pop bp 26 | ret 27 | -------------------------------------------------------------------------------- /clib/dump_registers.asm: -------------------------------------------------------------------------------- 1 | global _dump_registers 2 | 3 | _dump_registers: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_dump_registers 8 | 9 | pop bp 10 | ret 11 | -------------------------------------------------------------------------------- /clib/dump_string.asm: -------------------------------------------------------------------------------- 1 | global _dump_string 2 | 3 | _dump_string: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, word [bp+4] 8 | 9 | call os_dump_string 10 | 11 | pop bp 12 | ret -------------------------------------------------------------------------------- /clib/fatal_error.asm: -------------------------------------------------------------------------------- 1 | global _fatal_error 2 | 3 | _fatal_error: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_fatal_error 10 | 11 | pop bp 12 | ret -------------------------------------------------------------------------------- /clib/file_exists.asm: -------------------------------------------------------------------------------- 1 | global _file_exists 2 | 3 | _file_exists: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_file_exists 10 | 11 | jc .failed 12 | 13 | xor ax, ax 14 | jmp .skip 15 | 16 | .failed: 17 | mov ax, 1 18 | 19 | .skip: 20 | mov [_ioerr], ax 21 | 22 | pop bp 23 | ret 24 | -------------------------------------------------------------------------------- /clib/file_selector.asm: -------------------------------------------------------------------------------- 1 | global _file_selector 2 | 3 | _file_selector: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_file_selector 8 | 9 | jnc .skip 10 | 11 | xor ax, ax 12 | 13 | .skip: 14 | pop bp 15 | ret 16 | -------------------------------------------------------------------------------- /clib/find_char_in_string.asm: -------------------------------------------------------------------------------- 1 | global _find_char_in_string 2 | 3 | _find_char_in_string: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, [bp+4] 8 | mov al, byte [bp+6] 9 | 10 | call os_find_char_in_string 11 | 12 | pop bp 13 | ret 14 | -------------------------------------------------------------------------------- /clib/get_api_version.asm: -------------------------------------------------------------------------------- 1 | global _get_api_version 2 | 3 | _get_api_version: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_get_api_version 8 | 9 | pop bp 10 | ret -------------------------------------------------------------------------------- /clib/get_cursor_pos.asm: -------------------------------------------------------------------------------- 1 | global _get_cursor_pos 2 | 3 | _get_cursor_pos: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_get_cursor_pos 8 | 9 | mov ax, dx 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/get_date_string.asm: -------------------------------------------------------------------------------- 1 | global _get_date_string 2 | 3 | _get_date_string: 4 | push bp 5 | mov bp, sp 6 | 7 | mov bx, [bp+4] 8 | 9 | call os_get_date_string 10 | 11 | mov ax, bx 12 | 13 | pop bp 14 | ret 15 | -------------------------------------------------------------------------------- /clib/get_file_list.asm: -------------------------------------------------------------------------------- 1 | global _get_file_list 2 | 3 | _get_file_list: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov [bp-2], bx 9 | 10 | mov ax, word [bp+4] 11 | 12 | call os_get_file_list 13 | 14 | mov bx, ax 15 | cmp byte [bx], 0 16 | je .error 17 | 18 | mov word [_ioerr], 0 19 | jmp .skip 20 | 21 | .error: 22 | mov word [_ioerr], 1 23 | 24 | .skip: 25 | mov bx, word [bp-2] 26 | 27 | mov sp, bp 28 | pop bp 29 | ret 30 | -------------------------------------------------------------------------------- /clib/get_file_size.asm: -------------------------------------------------------------------------------- 1 | global _get_file_size 2 | 3 | _get_file_size: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov [bp-2], bx 9 | 10 | mov ax, word [bp+4] 11 | 12 | call os_get_file_size 13 | 14 | jc .error 15 | 16 | mov word [_ioerr], 0 17 | jmp .skip 18 | 19 | .error: 20 | xor bx, bx 21 | mov word [_ioerr], 1 22 | 23 | .skip: 24 | mov ax, bx 25 | mov bx, word [bp-2] 26 | 27 | mov sp, bp 28 | pop bp 29 | ret 30 | -------------------------------------------------------------------------------- /clib/get_random.asm: -------------------------------------------------------------------------------- 1 | global _get_random 2 | 3 | _get_random: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov [bp-2], bx 9 | 10 | mov ax, [bp+4] 11 | mov bx, [bp+6] 12 | 13 | call os_get_random 14 | 15 | mov ax, cx 16 | 17 | mov bx, word [bp-2] 18 | 19 | mov sp, bp 20 | pop bp 21 | ret 22 | -------------------------------------------------------------------------------- /clib/get_time_string.asm: -------------------------------------------------------------------------------- 1 | global _get_time_string 2 | 3 | _get_time_string: 4 | push bp 5 | mov bp, sp 6 | 7 | mov bx, [bp+4] 8 | 9 | call os_get_time_string 10 | 11 | mov ax, bx 12 | 13 | pop bp 14 | ret 15 | -------------------------------------------------------------------------------- /clib/get_via_serial.asm: -------------------------------------------------------------------------------- 1 | global _get_via_serial 2 | 3 | _get_via_serial: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_get_via_serial 8 | 9 | and ah, 64 10 | jnz .error 11 | 12 | mov word [_ioerr], 0 13 | jmp .skip 14 | 15 | .error: 16 | mov word [_ioerr], 1 17 | 18 | .skip: 19 | pop bp 20 | ret 21 | -------------------------------------------------------------------------------- /clib/hide_cursor.asm: -------------------------------------------------------------------------------- 1 | global _hide_cursor 2 | 3 | _hide_cursor: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_hide_cursor 8 | 9 | pop bp 10 | ret 11 | -------------------------------------------------------------------------------- /clib/input_string.asm: -------------------------------------------------------------------------------- 1 | global _input_string 2 | 3 | _input_string: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov [bp-2], bx 9 | 10 | mov ax, [bp+4] 11 | mov bx, [bp+6] 12 | 13 | call os_input_string 14 | 15 | mov bx, [bp-2] 16 | 17 | mov sp, bp 18 | pop bp 19 | ret -------------------------------------------------------------------------------- /clib/int_to_string.asm: -------------------------------------------------------------------------------- 1 | global _int_to_string 2 | 3 | _int_to_string: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, [bp+4] 8 | 9 | call os_int_to_string 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/ioerr.asm: -------------------------------------------------------------------------------- 1 | global _ioerr 2 | 3 | _ioerr: 4 | dw 0 -------------------------------------------------------------------------------- /clib/list_dialog.asm: -------------------------------------------------------------------------------- 1 | global _list_dialog 2 | 3 | _list_dialog: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov [bp-2], bx 9 | 10 | mov ax, word [bp+4] 11 | mov bx, word [bp+6] 12 | mov cx, word [bp+8] 13 | 14 | call os_list_dialog 15 | 16 | jnc .skip 17 | 18 | xor ax, ax 19 | 20 | .skip: 21 | mov bx, word [bp-2] 22 | 23 | mov sp, bp 24 | pop bp 25 | ret 26 | -------------------------------------------------------------------------------- /clib/load_file.asm: -------------------------------------------------------------------------------- 1 | global _load_file 2 | 3 | _load_file: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov [bp-2], bx 9 | 10 | mov ax, word [bp+4] 11 | mov cx, word [bp+6] 12 | 13 | call os_load_file 14 | 15 | mov ax, bx 16 | 17 | jc .error 18 | 19 | mov word [_ioerr], 0 20 | jmp .skip 21 | 22 | .error: 23 | mov word [_ioerr], 1 24 | 25 | .skip: 26 | mov bx, word [bp-2] 27 | 28 | mov sp, bp 29 | pop bp 30 | ret 31 | -------------------------------------------------------------------------------- /clib/long_int_negate.asm: -------------------------------------------------------------------------------- 1 | global _long_int_negate 2 | 3 | _long_int_negate: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov word [bp-2], bx 9 | 10 | mov bx, [bp+4] 11 | mov dx, [bx] 12 | mov ax, [bx+2] 13 | 14 | call os_long_int_negate 15 | 16 | mov bx, [bp+4] 17 | mov [bx], dx 18 | mov [bx+2], ax 19 | 20 | mov sp, bp 21 | pop bp 22 | ret 23 | -------------------------------------------------------------------------------- /clib/long_int_to_string.asm: -------------------------------------------------------------------------------- 1 | global _long_int_to_string 2 | 3 | _long_int_to_string: 4 | push bp 5 | mov bp, sp 6 | sub sp, 4 7 | 8 | mov word [bp-2], bx 9 | mov word [bp-4], di 10 | 11 | mov bx, [bp+4] 12 | mov dx, [bx] 13 | mov ax, [bx+2] 14 | 15 | mov bx, [bp+6] 16 | mov di, [bp+8] 17 | 18 | call os_long_int_to_string 19 | 20 | mov ax, di 21 | 22 | mov bx, [bp-2] 23 | mov di, [bp-4] 24 | 25 | mov sp, bp 26 | pop bp 27 | ret 28 | -------------------------------------------------------------------------------- /clib/mlib.asm: -------------------------------------------------------------------------------- 1 | bits 16 2 | 3 | section .text 4 | 5 | ; Include PathOS API vectors. 6 | %include "../include/mikedev.inc" 7 | %include "../src/kernel.asm" 8 | 9 | ; Include the C runtime function. 10 | %include "../include/crt0.asm" 11 | 12 | ; Include the disk functions. 13 | %include "get_file_list.asm" 14 | %include "load_file.asm" 15 | %include "write_file.asm" 16 | %include "file_exists.asm" 17 | %include "create_file.asm" 18 | %include "remove_file.asm" 19 | %include "rename_file.asm" 20 | %include "get_file_size.asm" 21 | 22 | ; Include the keyboard functions. 23 | %include "wait_for_key.asm" 24 | %include "check_for_key.asm" 25 | 26 | ; Include the math functions. 27 | %include "bcd_to_int.asm" 28 | %include "long_int_negate.asm" 29 | %include "get_random.asm" 30 | 31 | ; Inclue the misc functions. 32 | %include "get_api_version.asm" 33 | %include "pause.asm" 34 | %include "fatal_error.asm" 35 | 36 | ; Include the port functions. 37 | %include "port_byte_out.asm" 38 | %include "port_byte_in.asm" 39 | %include "serial_port_enable.asm" 40 | %include "send_via_serial.asm" 41 | %include "get_via_serial.asm" 42 | 43 | ; Include the screen functions. 44 | %include "print_string.asm" 45 | %include "clear_screen.asm" 46 | %include "move_cursor.asm" 47 | %include "get_cursor_pos.asm" 48 | %include "print_horiz_line.asm" 49 | %include "show_cursor.asm" 50 | %include "hide_cursor.asm" 51 | %include "draw_block.asm" 52 | %include "file_selector.asm" 53 | %include "list_dialog.asm" 54 | %include "draw_background.asm" 55 | %include "print_newline.asm" 56 | %include "dump_registers.asm" 57 | %include "dialog_box.asm" 58 | %include "print_space.asm" 59 | %include "dump_string.asm" 60 | %include "print_digit.asm" 61 | %include "print_1hex.asm" 62 | %include "print_2hex.asm" 63 | %include "print_4hex.asm" 64 | %include "input_string.asm" 65 | 66 | ; Include the string functions. 67 | %include "string_length.asm" 68 | %include "find_char_in_string.asm" 69 | %include "string_reverse.asm" 70 | %include "string_charchange.asm" 71 | %include "string_uppercase.asm" 72 | %include "string_lowercase.asm" 73 | %include "string_copy.asm" 74 | %include "string_truncate.asm" 75 | %include "string_join.asm" 76 | %include "string_chomp.asm" 77 | %include "string_strip.asm" 78 | %include "string_compare.asm" 79 | %include "string_strincmp.asm" 80 | %include "string_parse.asm" 81 | %include "string_to_int.asm" 82 | %include "int_to_string.asm" 83 | %include "sint_to_string.asm" 84 | %include "long_int_to_string.asm" 85 | %include "set_time_fmt.asm" 86 | %include "get_time_string.asm" 87 | %include "set_date_fmt.asm" 88 | %include "get_date_string.asm" 89 | 90 | ; Include the sound functions. 91 | %include "speaker_tone.asm" 92 | %include "speaker_off.asm" 93 | 94 | ; Include the BASIC interpreter function. 95 | %include "run_basic.asm" 96 | 97 | section .data 98 | 99 | ; Include the I/O error variable. 100 | %include "ioerr.asm" 101 | -------------------------------------------------------------------------------- /clib/move_cursor.asm: -------------------------------------------------------------------------------- 1 | global _move_cursor 2 | 3 | _move_cursor: 4 | push bp 5 | mov bp, sp 6 | 7 | mov dx, word [bp+4] 8 | 9 | call os_move_cursor 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/pause.asm: -------------------------------------------------------------------------------- 1 | global _pause 2 | 3 | _pause: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_pause 10 | 11 | pop bp 12 | ret -------------------------------------------------------------------------------- /clib/port_byte_in.asm: -------------------------------------------------------------------------------- 1 | global _port_byte_in 2 | 3 | _port_byte_in: 4 | push bp 5 | mov bp, sp 6 | 7 | mov dx, [bp+4] 8 | 9 | call os_port_byte_in 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/port_byte_out.asm: -------------------------------------------------------------------------------- 1 | global _port_byte_out 2 | 3 | _port_byte_out: 4 | push bp 5 | mov bp, sp 6 | 7 | mov dx, [bp+4] 8 | mov al, byte [bp+6] 9 | 10 | call os_port_byte_out 11 | 12 | pop bp 13 | ret 14 | -------------------------------------------------------------------------------- /clib/print_1hex.asm: -------------------------------------------------------------------------------- 1 | global _print_1hex 2 | 3 | _print_1hex: 4 | push bp 5 | mov bp, sp 6 | 7 | mov al, byte [bp+4] 8 | 9 | call os_print_1hex 10 | 11 | pop bp 12 | ret -------------------------------------------------------------------------------- /clib/print_2hex.asm: -------------------------------------------------------------------------------- 1 | global _print_2hex 2 | 3 | _print_2hex: 4 | push bp 5 | mov bp, sp 6 | 7 | mov al, byte [bp+4] 8 | 9 | call os_print_2hex 10 | 11 | pop bp 12 | ret -------------------------------------------------------------------------------- /clib/print_4hex.asm: -------------------------------------------------------------------------------- 1 | global _print_4hex 2 | 3 | _print_4hex: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_print_4hex 10 | 11 | pop bp 12 | ret -------------------------------------------------------------------------------- /clib/print_digit.asm: -------------------------------------------------------------------------------- 1 | global _print_digit 2 | 3 | _print_digit: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_print_digit 10 | 11 | pop bp 12 | ret -------------------------------------------------------------------------------- /clib/print_horiz_line.asm: -------------------------------------------------------------------------------- 1 | global _print_horiz_line 2 | 3 | _print_horiz_line: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_print_horiz_line 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/print_newline.asm: -------------------------------------------------------------------------------- 1 | global _print_newline 2 | 3 | _print_newline: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_print_newline 8 | 9 | pop bp 10 | ret 11 | -------------------------------------------------------------------------------- /clib/print_space.asm: -------------------------------------------------------------------------------- 1 | global _print_space 2 | 3 | _print_space: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_print_space 8 | 9 | pop bp 10 | ret -------------------------------------------------------------------------------- /clib/print_string.asm: -------------------------------------------------------------------------------- 1 | global _print_string 2 | 3 | _print_string: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, word [bp+4] 8 | 9 | call os_print_string 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/readme.txt: -------------------------------------------------------------------------------- 1 | The C library is in a very early experimental stage 2 | -------------------------------------------------------------------------------- /clib/remove_file.asm: -------------------------------------------------------------------------------- 1 | global _remove_file 2 | 3 | _remove_file: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_remove_file 10 | 11 | jc .error 12 | 13 | mov word [_ioerr], 0 14 | jmp .skip 15 | 16 | .error: 17 | mov word [_ioerr], 1 18 | 19 | .skip: 20 | 21 | pop bp 22 | ret 23 | -------------------------------------------------------------------------------- /clib/rename_file.asm: -------------------------------------------------------------------------------- 1 | global _rename_file 2 | 3 | _rename_file: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov [bp-2], bx 9 | 10 | mov ax, word [bp+4] 11 | mov bx, word [bp+6] 12 | 13 | call os_rename_file 14 | 15 | jc .error 16 | 17 | mov word [_ioerr], 0 18 | jmp .skip 19 | 20 | .error: 21 | mov word [_ioerr], 1 22 | 23 | .skip: 24 | mov bx, word [bp-2] 25 | 26 | mov sp, bp 27 | pop bp 28 | ret 29 | -------------------------------------------------------------------------------- /clib/run_basic.asm: -------------------------------------------------------------------------------- 1 | global _run_basic 2 | 3 | _run_basic: 4 | push bp 5 | mov bp, sp 6 | sub sp, 4 7 | 8 | mov [bp-2], bx 9 | mov [bp-4], si 10 | 11 | mov ax, word [bp+4] 12 | mov bx, word [bp+6] 13 | mov si, word [bp+8] 14 | 15 | call os_run_basic 16 | 17 | mov si, word [bp-4] 18 | mov bx, word [bp-2] 19 | 20 | mov sp, bp 21 | pop bp 22 | ret 23 | -------------------------------------------------------------------------------- /clib/send_via_serial.asm: -------------------------------------------------------------------------------- 1 | global _send_via_serial 2 | 3 | _send_via_serial: 4 | push bp 5 | mov bp, sp 6 | 7 | mov al, byte [bp+4] 8 | 9 | call os_send_via_serial 10 | 11 | and ah, 64 12 | jnz .error 13 | 14 | mov word [_ioerr], 0 15 | jmp .skip 16 | 17 | .error: 18 | mov word [_ioerr], 1 19 | 20 | .skip: 21 | pop bp 22 | ret 23 | -------------------------------------------------------------------------------- /clib/serial_port_enable.asm: -------------------------------------------------------------------------------- 1 | global _serial_port_enable 2 | 3 | _serial_port_enable: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, [bp+4] 8 | 9 | call os_serial_port_enable 10 | 11 | and ah, 64 12 | jnz .error 13 | 14 | mov word [_ioerr], 0 15 | jmp .skip 16 | 17 | .error: 18 | mov word [_ioerr], 1 19 | 20 | .skip: 21 | pop bp 22 | ret 23 | -------------------------------------------------------------------------------- /clib/set_date_fmt.asm: -------------------------------------------------------------------------------- 1 | global _set_date_fmt 2 | 3 | _set_date_fmt: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, [bp+4] 8 | 9 | call os_set_date_fmt 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/set_time_fmt.asm: -------------------------------------------------------------------------------- 1 | global _set_time_fmt 2 | 3 | _set_time_fmt: 4 | push bp 5 | mov bp, sp 6 | 7 | mov al, byte [bp+4] 8 | 9 | call os_set_time_fmt 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/show_cursor.asm: -------------------------------------------------------------------------------- 1 | global _show_cursor 2 | 3 | _show_cursor: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_show_cursor 8 | 9 | pop bp 10 | ret 11 | -------------------------------------------------------------------------------- /clib/sint_to_string.asm: -------------------------------------------------------------------------------- 1 | global _sint_to_string 2 | 3 | _sint_to_string: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, [bp+4] 8 | 9 | call os_sint_to_string 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/speaker_off.asm: -------------------------------------------------------------------------------- 1 | global _speaker_off 2 | 3 | _speaker_off: 4 | push bp 5 | mov bp, sp 6 | 7 | call os_speaker_off 8 | 9 | pop bp 10 | ret 11 | -------------------------------------------------------------------------------- /clib/speaker_tone.asm: -------------------------------------------------------------------------------- 1 | global _speaker_tone 2 | 3 | _speaker_tone: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_speaker_tone 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/string_charchange.asm: -------------------------------------------------------------------------------- 1 | global _string_charchange 2 | 3 | _string_charchange: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, [bp+4] 8 | mov al, byte [bp+6] 9 | mov bl, byte [bp+8] 10 | 11 | call os_string_charchange 12 | 13 | pop bp 14 | ret 15 | -------------------------------------------------------------------------------- /clib/string_chomp.asm: -------------------------------------------------------------------------------- 1 | global _string_chomp 2 | 3 | _string_chomp: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, [bp+4] 8 | 9 | call os_string_chomp 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/string_compare.asm: -------------------------------------------------------------------------------- 1 | global _string_compare 2 | 3 | _string_compare: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, [bp+4] 8 | mov di, [bp+6] 9 | 10 | call os_string_compare 11 | 12 | jc .same 13 | 14 | xor ax, ax 15 | jmp .skip 16 | 17 | .same: 18 | mov ax, 1 19 | 20 | .skip: 21 | 22 | pop bp 23 | ret 24 | -------------------------------------------------------------------------------- /clib/string_copy.asm: -------------------------------------------------------------------------------- 1 | global _string_copy 2 | 3 | _string_copy: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, [bp+4] 8 | mov di, [bp+6] 9 | 10 | call os_string_copy 11 | 12 | mov ax, di 13 | 14 | pop bp 15 | ret 16 | -------------------------------------------------------------------------------- /clib/string_join.asm: -------------------------------------------------------------------------------- 1 | global _string_join 2 | 3 | _string_join: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, [bp+4] 8 | mov bx, [bp+6] 9 | mov cx, [bp+8] 10 | 11 | call os_string_join 12 | 13 | mov ax, cx 14 | 15 | pop bp 16 | ret 17 | -------------------------------------------------------------------------------- /clib/string_length.asm: -------------------------------------------------------------------------------- 1 | global _string_length 2 | 3 | _string_length: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, [bp+4] 8 | 9 | call os_string_length 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/string_lowercase.asm: -------------------------------------------------------------------------------- 1 | global _string_lowercase 2 | 3 | _string_lowercase: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, [bp+4] 8 | 9 | call os_string_lowercase 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/string_parse.asm: -------------------------------------------------------------------------------- 1 | global _string_parse 2 | 3 | _string_parse: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov word [bp-2], si 9 | 10 | mov si, [bp+6] 11 | 12 | call os_string_parse 13 | 14 | push bx 15 | 16 | mov bx, [bp+4] 17 | mov [bx], ax 18 | 19 | pop ax 20 | 21 | mov [bx+2], ax 22 | mov [bx+4], cx 23 | mov [bx+6], dx 24 | 25 | mov si, [bp-2] 26 | 27 | mov sp, bp 28 | pop bp 29 | ret 30 | -------------------------------------------------------------------------------- /clib/string_reverse.asm: -------------------------------------------------------------------------------- 1 | global _string_reverse 2 | 3 | _string_reverse: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, [bp+4] 8 | 9 | call os_string_reverse 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/string_strincmp.asm: -------------------------------------------------------------------------------- 1 | global _string_strincmp 2 | 3 | _string_strincmp: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, [bp+4] 8 | mov di, [bp+6] 9 | mov cl, byte [bp+8] 10 | 11 | call os_string_strincmp 12 | 13 | jc .same 14 | 15 | xor ax, ax 16 | jmp .skip 17 | 18 | .same: 19 | mov ax, 1 20 | 21 | .skip: 22 | 23 | pop bp 24 | ret 25 | -------------------------------------------------------------------------------- /clib/string_strip.asm: -------------------------------------------------------------------------------- 1 | global _string_strip 2 | 3 | _string_strip: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, [bp+4] 8 | mov al, byte [bp+6] 9 | 10 | call os_string_strip 11 | 12 | pop bp 13 | ret 14 | -------------------------------------------------------------------------------- /clib/string_to_int.asm: -------------------------------------------------------------------------------- 1 | global _string_to_int 2 | 3 | _string_to_int: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, [bp+4] 8 | 9 | call os_string_to_int 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/string_truncate.asm: -------------------------------------------------------------------------------- 1 | global _string_truncate 2 | 3 | _string_truncate: 4 | push bp 5 | mov bp, sp 6 | 7 | mov si, [bp+4] 8 | mov ax, [bp+6] 9 | 10 | call os_string_truncate 11 | 12 | mov ax, si 13 | 14 | pop bp 15 | ret 16 | -------------------------------------------------------------------------------- /clib/string_uppercase.asm: -------------------------------------------------------------------------------- 1 | global _string_uppercase 2 | 3 | _string_uppercase: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, [bp+4] 8 | 9 | call os_string_uppercase 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/wait_for_key.asm: -------------------------------------------------------------------------------- 1 | global _wait_for_key 2 | 3 | _wait_for_key: 4 | push bp 5 | mov bp, sp 6 | 7 | mov ax, word [bp+4] 8 | 9 | call os_wait_for_key 10 | 11 | pop bp 12 | ret 13 | -------------------------------------------------------------------------------- /clib/write_file.asm: -------------------------------------------------------------------------------- 1 | global _write_file 2 | 3 | _write_file: 4 | push bp 5 | mov bp, sp 6 | sub sp, 2 7 | 8 | mov [bp-2], bx 9 | 10 | mov ax, word [bp+4] 11 | mov bx, word [bp+6] 12 | mov cx, word [bp+8] 13 | 14 | call os_write_file 15 | 16 | jc .error 17 | 18 | mov word [_ioerr], 0 19 | jmp .skip 20 | 21 | .error: 22 | mov word [_ioerr], 1 23 | 24 | .skip: 25 | mov bx, word [bp-2] 26 | 27 | mov sp, bp 28 | pop bp 29 | ret 30 | -------------------------------------------------------------------------------- /image/PathOS.flp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/image/PathOS.flp -------------------------------------------------------------------------------- /image/PathOS.iso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/image/PathOS.iso -------------------------------------------------------------------------------- /include/clib.h: -------------------------------------------------------------------------------- 1 | #ifndef MLIB_H 2 | #define MLIB_H 3 | 4 | /* Define some helpful keywords. */ 5 | #ifndef NULL 6 | #define NULL ((void*) 0x0) 7 | #endif 8 | 9 | #ifndef bool 10 | typedef int bool; 11 | #endif 12 | 13 | #ifndef true 14 | #define true 0x1 15 | #endif 16 | 17 | #ifndef false 18 | #define false 0x0 19 | #endif 20 | 21 | /* Define PathOS definitions. */ 22 | #ifndef BLACK_ON_WHITE 23 | #define BLACK_ON_WHITE 0xF0 24 | #endif 25 | 26 | #ifndef WHITE_ON_BLACK 27 | #define WHITE_ON_BLACK 0x0F 28 | #endif 29 | 30 | #ifndef WHITE_ON_LIGHT_RED 31 | #define WHITE_ON_LIGHT_RED 0xCF 32 | #endif 33 | 34 | #ifndef WHITE_ON_GREEN 35 | #define WHITE_ON_GREEN 0x2F 36 | #endif 37 | 38 | #ifndef RED_ON_LIGHT_GREEN 39 | #define WHITE_ON_LIGHT_GREEN 0xA4 40 | #endif 41 | 42 | #ifndef KEY_UP 43 | #define KEY_UP 0x48 44 | #endif 45 | 46 | #ifndef KEY_DOWN 47 | #define KEY_DOWN 0x50 48 | #endif 49 | 50 | #ifndef KEY_LEFT 51 | #define KEY_LEFT 0x4B 52 | #endif 53 | 54 | #ifndef KEY_RIGHT 55 | #define KEY_RIGHT 0x4D 56 | #endif 57 | 58 | #ifndef KEY_ESC 59 | #define KEY_ESC 0x1B 60 | #endif 61 | 62 | #ifndef KEY_ENTER 63 | #define KEY_ENTER 0xD 64 | #endif 65 | 66 | /* A global variable for I/O error reporting. */ 67 | #ifndef ioerr 68 | extern bool ioerr; 69 | #endif 70 | 71 | /* A structure for string_parse(). */ 72 | #ifndef str_p 73 | typedef struct str_p { 74 | char *str1; 75 | char *str2; 76 | char *str3; 77 | char *str4; 78 | } str_p; 79 | #endif 80 | 81 | /* Create a long structure for long_int_to_string() and long_int_negate(). */ 82 | #ifndef long_int 83 | typedef struct long_int { 84 | int upper; 85 | int lower; 86 | } long_int; 87 | #endif 88 | 89 | /* Define the disk functions. */ 90 | char* get_file_list(char* buffer); 91 | int load_file(char* string, unsigned int location); 92 | void write_file(char* filename, char* buffer, unsigned int bytestowrite); 93 | bool file_exists(char* filename); 94 | void create_file(char* filename); 95 | void remove_file(char* filename); 96 | void rename_file(char* old_filename, char* new_oldname); 97 | int get_file_size(char* filename); 98 | 99 | /* Define the keyboard functions. */ 100 | int wait_for_key(void); 101 | int check_for_key(void); 102 | 103 | /* Define the math functions. */ 104 | int bcd_to_int(char number); 105 | void long_int_negate(long_int *number); 106 | int get_random(int low, int high); 107 | 108 | /* Define the misc functions. */ 109 | char get_api_version(void); 110 | void pause(unsigned int decisecond); 111 | void fatal_error(char* message); 112 | 113 | /* Define the port functions. */ 114 | void port_byte_out(int port, char data); 115 | char port_byte_in(int port); 116 | void serial_port_enable(bool mode); 117 | void send_via_serial(char data); 118 | char get_via_serial(); 119 | 120 | /* Define the screen functions. */ 121 | void print_string(char* string); 122 | void clear_screen(void); 123 | void move_cursor(unsigned int cursor); 124 | int get_cursor_pos(void); 125 | void print_horiz_line(bool double_line); 126 | void show_cursor(void); 127 | void hide_cursor(void); 128 | void draw_block(unsigned char color, unsigned char start_x, unsigned char start_y, unsigned char end_x, unsigned char end_y); 129 | char* file_selector(void); 130 | char list_dialog(char* list, char* string1, char* string2); 131 | void draw_background(char* top, char* bottom, unsigned int color); 132 | void print_newline(void); 133 | void dump_registers(void); 134 | bool dialog_box(char* string1, char* string2, char* string3, bool mode); 135 | void print_space(void); 136 | void dump_string(char* string); 137 | void print_digit(unsigned int digit); 138 | void print_1hex(unsigned char digit); 139 | void print_2hex(unsigned char digit); 140 | void print_4hex(unsigned int digit); 141 | char* input_string(char* buffer, int limit); 142 | 143 | /* Define the string functions. */ 144 | int string_length(char* string); 145 | int find_char_in_string(char* string, char chartofind); 146 | void string_reverse(char* string); 147 | void string_charchange(char* string, char chartofind, char chartoreplacewith); 148 | char* string_uppercase(char* string); 149 | char* string_lowercase(char* string); 150 | char* string_copy(char* oldstring, char* newstring); 151 | char* string_truncate(char* string, int size); 152 | char* string_join(char* string1, char* string2, char* outstring); 153 | void string_chomp(char* string); 154 | void string_strip(char* string, char chartoremove); 155 | bool string_compare(char* string1, char* string2); 156 | bool string_strincmp(char* string1, char* string2, char chartocheck); 157 | void string_parse(str_p *strings, char* string); 158 | int string_to_int(char* string); 159 | char* int_to_string(int number); 160 | char* sint_to_string(int number); 161 | void long_int_to_string(long_int *number, int base, char *output_string); 162 | void set_time_fmt(bool format); 163 | void get_time_string(char *string); 164 | void set_date_fmt(int format); 165 | void get_date_string(char* string); 166 | 167 | /* Define the sound functions. */ 168 | void speaker_tone(unsigned int frequency); 169 | void speaker_off(void); 170 | 171 | /* Define the BASIC interpreter function. */ 172 | void run_basic(char* code, unsigned int size, char* parameter_string); 173 | 174 | #endif 175 | -------------------------------------------------------------------------------- /include/crt0.asm: -------------------------------------------------------------------------------- 1 | extern _main 2 | global __start 3 | 4 | __start: 5 | push bp 6 | mov bp, sp 7 | 8 | ; Make sure the Mike OS API version is 17 or higher. 9 | ; This will insure that the library doesn't call any 10 | ; functions that don't exist on older versions. 11 | call _get_api_version 12 | mov ah, 17 13 | cmp al, ah 14 | jl .api_error 15 | 16 | ; argv 17 | mov bx, .buffer 18 | 19 | ; argv[0] is always the file's name! 20 | mov word [bx], 0 21 | add bx, 2 22 | 23 | ; argc 24 | mov cx, 1 25 | 26 | ; If si is 0, then there are no args. 27 | cmp si, 0 28 | je .done 29 | 30 | ; Decrease because of the upcoming loop. 31 | dec si 32 | 33 | .loop: 34 | inc si 35 | 36 | ; Skip multiple blank spaces! 37 | cmp byte [si], ' ' 38 | je .loop 39 | 40 | ; Found an arg. 41 | mov [bx], si 42 | inc cx 43 | add bx, 2 44 | 45 | ; Make sure argv doesn't overflow! 46 | cmp cx, 12 47 | je .arg_error 48 | 49 | .find: 50 | ; That's all the args. 51 | cmp byte [si], 0 52 | je .done 53 | 54 | ; Go to the next arg! 55 | cmp byte [si], ' ' 56 | je .next 57 | 58 | inc si 59 | 60 | jmp .find 61 | 62 | .next: 63 | mov byte [si], 0 64 | 65 | jmp .loop 66 | 67 | .done: 68 | ; Push argv and argc respectively. 69 | push word .buffer 70 | push cx 71 | 72 | ; Call the main function and clean up after it. 73 | call _main 74 | add sp, 4 75 | 76 | .exit: 77 | mov sp, bp 78 | pop bp 79 | ret 80 | 81 | .arg_error: 82 | push .arg_str 83 | call _print_string 84 | call _wait_for_key 85 | jmp .exit 86 | 87 | .api_error: 88 | push .api_str 89 | call _print_string 90 | call _wait_for_key 91 | jmp .exit 92 | 93 | .arg_str: db "Too many arguments were passed!", 13, 10, 0 94 | .api_str: db "This program will only run on MikeOS 4.6 and up!", 13, 10, 0 95 | .buffer: times 11 dw 0 96 | -------------------------------------------------------------------------------- /include/mikedev.inc: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Include file for PathOS program development (MikeOS API version 17) 3 | ; ------------------------------------------------------------------ 4 | 5 | ; ------------------------------------------------------------------ 6 | ; IMPORTANT LOCATIONS 7 | 8 | os_main equ 0000h ; Where the OS code starts 9 | 10 | 11 | ; ------------------------------------------------------------------ 12 | ; COLOURS (eg for os_draw_background and os_draw_block) 13 | 14 | %DEFINE BLACK_ON_WHITE 11110000b 15 | %DEFINE WHITE_ON_BLACK 00001111b 16 | %DEFINE WHITE_ON_LIGHT_RED 11001111b 17 | %DEFINE WHITE_ON_GREEN 00101111b 18 | %DEFINE RED_ON_LIGHT_GREEN 10100100b 19 | 20 | 21 | ; ------------------------------------------------------------------ 22 | ; KEYS 23 | 24 | %DEFINE KEY_UP 72 25 | %DEFINE KEY_DOWN 80 26 | %DEFINE KEY_LEFT 75 27 | %DEFINE KEY_RIGHT 77 28 | 29 | %DEFINE KEY_ESC 27 30 | %DEFINE KEY_ENTER 13 31 | 32 | 33 | ; ------------------------------------------------------------------ 34 | ; SYSTEM CALLS 35 | 36 | ; Screen control 37 | 38 | os_clear_screen equ 0009h ; (Nothing used) 39 | os_print_string equ 0003h ; SI = zero-terminated string location 40 | os_move_cursor equ 0006h ; DH, DL = row, column 41 | os_print_horiz_line equ 000Ch ; AX = 1 for double line, else single 42 | os_print_newline equ 000Fh ; (Nothing used) 43 | os_draw_background equ 002Ah ; AX, BX = strings, CX = colour 44 | os_draw_block equ 00B4h ; BL = colour, DH/DL/SI/DI = pos 45 | os_input_dialog equ 00A8h ; AX = input string, BX = msg string 46 | os_dialog_box equ 003Ch ; AX, BX, CX = strings, DX = type 47 | ; OUT: AX = 0 for OK, 1 for cancel 48 | ; (only multi choice for DX = 1) 49 | os_list_dialog equ 00ABh ; IN: AX = comma-separated list of 50 | ; option strings, BX, CX = help to 51 | ; display at top of list 52 | ; OUT: AX = number (starting from 1) 53 | ; of option selected, or carry if Esc 54 | os_file_selector equ 005Ah ; Returns filename in AX 55 | os_get_cursor_pos equ 0069h ; OUT: DH = row, DL = column 56 | os_print_space equ 006Ch ; (Nothing used) 57 | os_dump_string equ 006Fh ; SI = string location 58 | os_print_digit equ 0072h ; AX = digit to print 59 | os_print_1hex equ 0075h ; Display low nibble of AL in hex 60 | os_print_2hex equ 0078h ; Display AL in hex 61 | os_print_4hex equ 007Bh ; Display AX in hex 62 | os_show_cursor equ 008Ah ; (Nothing used) 63 | os_hide_cursor equ 008Dh ; (Nothing used) 64 | os_dump_registers equ 0090h ; Shows contents of AX, BX, CX, DX 65 | 66 | 67 | ; Keyboard handling 68 | 69 | os_wait_for_key equ 0012h ; Returns AL = key pressed 70 | os_check_for_key equ 0015h ; Returns AL = key pressed 71 | 72 | 73 | ; File handling 74 | 75 | os_get_file_list equ 0042h ; AX = string to store filenames 76 | os_load_file equ 0021h ; IN: AX = filename string location, 77 | ; CX = location to load file 78 | ; OUT: BX = file size in bytes, 79 | ; carry clear if OK, set if missing 80 | os_write_file equ 0096h ; AX = filename, BX = data location, 81 | ; CX = number of bytes to save 82 | os_file_exists equ 0099h ; AX = filename, carry clear if exists 83 | os_create_file equ 009Ch ; AX = filename 84 | os_remove_file equ 009Fh ; AX = filename 85 | os_rename_file equ 00A2h ; AX = filename, BX = new filename 86 | os_get_file_size equ 00A5h ; AX = filename, OUT: BX = bytes 87 | ; (64K max) 88 | 89 | 90 | ; Sound 91 | 92 | os_speaker_tone equ 001Bh ; AX = note frequency 93 | os_speaker_off equ 001Eh ; (Nothing used) 94 | 95 | 96 | ; String handling 97 | 98 | os_int_to_string equ 0018h ; AX = unsigned integer, out AX = string 99 | os_sint_to_string equ 00C0h ; AX = signed integer, out AX = string 100 | os_string_reverse equ 00AEh ; SI = string location 101 | os_string_length equ 002Dh ; AX = string loc, returns AX = length 102 | os_string_uppercase equ 0030h ; AX = zero-terminated string 103 | os_string_lowercase equ 0033h ; AX = zero-terminated string 104 | os_input_string equ 0036h ; AX = string location, BX = maximum characters 105 | os_string_copy equ 0039h ; SI = source, DI = dest strings 106 | os_string_join equ 003Fh ; AX, BX = source strings, CX = dest 107 | os_string_compare equ 0045h ; SI, DI = strings, carry set if same 108 | os_string_strincmp equ 0093h ; As above, but with CL = chars to check 109 | os_string_chomp equ 0048h ; AX = string location 110 | os_string_strip equ 004Bh ; SI = string, AX = char to remove 111 | os_string_truncate equ 004Eh ; SI = string, AX = number of chars 112 | os_set_time_fmt equ 0084h ; AL = format 113 | os_set_date_fmt equ 0087h ; AX = format 114 | os_get_time_string equ 0054h ; BX = string location for eg '20:41' 115 | os_get_date_string equ 005Dh ; BX = string loc for eg '12/31/2007' 116 | os_find_char_in_string equ 0066h ; IN: SI = string, AL = char to find 117 | os_long_int_to_string equ 007Eh ; DX:AX = num, BX = base, DI = string 118 | os_string_to_int equ 00B1h ; SI = string (up to 65535), AX = int 119 | os_string_charchange equ 00BAh ; SI = string, AL = old char, BL = new 120 | os_string_parse equ 00C3h ; SI = string; output: AX/BX/CX/DX = 121 | ; substrings (or 0 if not present) 122 | os_string_tokenize equ 00CFh ; SI = string, AL = sep char; returns 123 | ; DI = next token 124 | 125 | 126 | ; Math routines 127 | 128 | os_get_random equ 00B7h ; IN: AX, BX = low, high; OUT: CX = num 129 | os_bcd_to_int equ 0051h ; AL = BCD number, returns AX = integer 130 | os_long_int_negate equ 0081h ; DX:AX = number 131 | 132 | 133 | ; Ports 134 | 135 | os_port_byte_out equ 00C9h ; IN: DX = port, AL = byte 136 | os_port_byte_in equ 00CCh ; IN: DX = port; OUT: AL = byte 137 | os_serial_port_enable equ 00BDh ; AX = 0 for 9600 baud, 1 for 1200 138 | os_send_via_serial equ 0060h ; AL = byte to send 139 | os_get_via_serial equ 0063h ; Returns AL = byte received 140 | ; OUT: AX = location, or 0 if not found 141 | 142 | 143 | ; Misc OS functions 144 | 145 | os_run_basic equ 00C6h ; AX = code location in RAM, BX = size, 146 | ; SI = parameter string (or 0 if none) 147 | os_get_api_version equ 0057h ; Returns API version in AL 148 | os_pause equ 0024h ; AX = 10ths of second to wait 149 | os_fatal_error equ 0027h ; AX = error string location 150 | 151 | 152 | ; ------------------------------------------------------------------ 153 | 154 | -------------------------------------------------------------------------------- /programs/2048.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/programs/2048.bin -------------------------------------------------------------------------------- /programs/2048.c: -------------------------------------------------------------------------------- 1 | /* https://github.com/ZeroKelvinKeyboard/MikeOS-Apps/tree/master/2048 */ 2 | #include "clib.h" 3 | #include "textio.h" 4 | 5 | int brd_w = 4; 6 | int brd_h = 4; 7 | 8 | typedef int board[4][4]; 9 | 10 | void init_display(); 11 | void reset_game(); 12 | void play_game(); 13 | 14 | void display_board(board *b); 15 | void reset_board(board *b); 16 | void add_tile(board *b); 17 | board *dup_board(board *b); 18 | int cmp_board(board *a, board *b); 19 | 20 | int can_move_up(board *b); 21 | void merge_up(board *b); 22 | void shift_up(board *b); 23 | 24 | int can_move_down(board *b); 25 | void merge_down(board *b); 26 | void shift_down(board *b); 27 | 28 | int can_move_left(board *b); 29 | void merge_left(board *b); 30 | void shift_left(board *b); 31 | 32 | int can_move_right(board *b); 33 | void merge_right(board *b); 34 | void shift_right(board *b); 35 | 36 | int game_is_lost(); 37 | void end_program(); 38 | 39 | void add_big_int(struct longint *value, struct longint *to_add); 40 | void set_big_int(struct longint *value, int new_val); 41 | 42 | 43 | 44 | board grid; 45 | int alt_video_page = 0; 46 | 47 | struct longint score; 48 | struct longint merge_score; 49 | 50 | char conv_buffer[10]; 51 | 52 | 53 | char *seperator = "+-----+-----+-----+-----+"; 54 | 55 | int main() 56 | { 57 | int key; 58 | 59 | init_display(); 60 | 61 | play_again: 62 | reset_game(); 63 | display_board(&grid); 64 | play_game(); 65 | 66 | movecur(15, 9 + brd_h * 2); 67 | textcolour(12); 68 | strout("Game Over! Press ESCAPE to exit or ENTER to play again."); 69 | 70 | do { 71 | key = os_wait_for_key(); 72 | } while (key != ESC_KEY && key != ENTER_KEY); 73 | 74 | if (key == ENTER_KEY) goto play_again; 75 | end_program(); 76 | } 77 | 78 | void reset_game() 79 | { 80 | int x, y; 81 | board *b = grid; 82 | 83 | set_big_int(&score, 0); 84 | 85 | reset_board(b); 86 | 87 | /* Add two tiles with the value two. */ 88 | /* Do not use add_tile() as this can generate fours as well. */ 89 | (*b)[os_get_random(0, 1)][os_get_random(0, 3)] = 2; 90 | (*b)[os_get_random(2, 3)][os_get_random(0, 3)] = 2; 91 | } 92 | 93 | void reset_board(board *b) 94 | { 95 | int x, y; 96 | 97 | for (y = 0; y < brd_h; y++) { 98 | for (x = 0; x < brd_w; x++) { 99 | (*b)[y][x] = 0; 100 | } 101 | } 102 | } 103 | 104 | void init_display() 105 | { 106 | os_hide_cursor(); 107 | textio_init(); 108 | viewpage(2); 109 | outpage(2); 110 | clearscr(); 111 | } 112 | 113 | void play_game() 114 | { 115 | board *b = &grid; 116 | 117 | do { 118 | 119 | switch (os_wait_for_key()) { 120 | case ESC_KEY: 121 | return; 122 | 123 | case UP_KEY: 124 | if (can_move_up(b)) { 125 | shift_up(b); 126 | merge_up(b); 127 | shift_up(b); 128 | add_big_int(&score, &merge_score); 129 | break; 130 | } else { 131 | continue; 132 | } 133 | 134 | case DOWN_KEY: 135 | if (can_move_down(b)) { 136 | shift_down(b); 137 | merge_down(b); 138 | shift_down(b); 139 | add_big_int(&score, &merge_score); 140 | break; 141 | } else { 142 | continue; 143 | } 144 | 145 | case LEFT_KEY: 146 | if (can_move_left(b)) { 147 | shift_left(b); 148 | merge_left(b); 149 | shift_left(b); 150 | add_big_int(&score, &merge_score); 151 | break; 152 | } else { 153 | continue; 154 | } 155 | 156 | case RIGHT_KEY: 157 | if (can_move_right(b)) { 158 | shift_right(b); 159 | merge_right(b); 160 | shift_right(b); 161 | add_big_int(&score, &merge_score); 162 | break; 163 | } else { 164 | continue; 165 | } 166 | 167 | default: 168 | continue; 169 | } 170 | 171 | add_tile(b); 172 | display_board(b); 173 | 174 | } while (!game_is_lost()); 175 | } 176 | 177 | 178 | void display_board(board *b) 179 | { 180 | int x, y; 181 | 182 | if (alt_video_page) { 183 | outpage(2); 184 | } else { 185 | outpage(4); 186 | } 187 | 188 | textcolour(7); 189 | clearscr(); 190 | 191 | movecur(30, 7); 192 | os_long_int_to_string(&score, 10, conv_buffer); 193 | strout("Score: "); 194 | strout(conv_buffer); 195 | 196 | for (y = 0; y < brd_h; y++) { 197 | movecur(30, y * 2 + 8); 198 | strout(seperator); 199 | movecur(30, y * 2 + 9); 200 | 201 | for (x = 0; x < brd_w; x++) { 202 | charout('|'); 203 | 204 | if ((*b)[y][x] < 10000) charout(' '); 205 | if ((*b)[y][x] < 1000) charout(' '); 206 | if ((*b)[y][x] < 100) charout(' '); 207 | if ((*b)[y][x] < 10) charout(' '); 208 | 209 | if ((*b)[y][x] == 0) { 210 | charout(' '); 211 | } else { 212 | strout(os_int_to_string((*b)[y][x])); 213 | } 214 | } 215 | 216 | charout('|'); 217 | } 218 | 219 | movecur(30, 16); 220 | strout(seperator); 221 | 222 | if (alt_video_page) { 223 | viewpage(2); 224 | alt_video_page = 0; 225 | } else { 226 | viewpage(4); 227 | alt_video_page = 1; 228 | } 229 | } 230 | 231 | void add_tile(board *b) 232 | { 233 | int x, y, fill_pos; 234 | int empty = 0; 235 | 236 | for (y = 0; y < brd_h; y++) { 237 | for (x = 0; x < brd_w; x++) { 238 | if ((*b)[y][x] == 0) empty++; 239 | } 240 | } 241 | 242 | if (empty == 0) return; 243 | 244 | fill_pos = os_get_random(1, empty); 245 | 246 | for (y = 0; y < brd_h; y++) { 247 | for (x = 0; x < brd_w; x++) { 248 | if ((*b)[y][x] == 0) fill_pos--; 249 | if (fill_pos == 0) { 250 | if (os_get_random(0, 9) == 0) { 251 | (*b)[y][x] = 4; 252 | } else { 253 | (*b)[y][x] = 2; 254 | } 255 | 256 | return; 257 | } 258 | } 259 | } 260 | } 261 | 262 | int can_move_up(board *b) 263 | { 264 | board *tmp; 265 | 266 | /* Create a copy of the board and simulate up action. */ 267 | tmp = dup_board(b); 268 | 269 | shift_up(tmp); 270 | merge_up(tmp); 271 | shift_up(tmp); 272 | 273 | /* If the board is the same, the action is not possible. */ 274 | if (cmp_board(b, tmp)) { 275 | free(tmp); 276 | return 0; 277 | } else { 278 | free(tmp); 279 | return 1; 280 | } 281 | } 282 | 283 | 284 | void merge_up(board *b) 285 | { 286 | int x, y; 287 | struct longint tmp; 288 | 289 | set_big_int(&merge_score, 0); 290 | 291 | for (x = 0; x < brd_w; x++) { 292 | for (y = 0; y < brd_h - 1; y++) { 293 | if ((*b)[y][x] > 0 && (*b)[y][x] == (*b)[y + 1][x]) { 294 | (*b)[y][x] <<= 1; 295 | (*b)[y + 1][x] = 0; 296 | set_big_int(&tmp, (*b)[y][x]); 297 | add_big_int(&merge_score, &tmp); 298 | } 299 | } 300 | } 301 | } 302 | 303 | 304 | void shift_up(board *b) 305 | { 306 | int x, y, lastpos; 307 | 308 | for (x = 0; x < brd_w; x++) { 309 | lastpos = 0; 310 | for (y = 0; y < brd_h; y++) { 311 | if ((*b)[y][x] != 0) { 312 | (*b)[lastpos][x] = (*b)[y][x]; 313 | if (lastpos++ != y) { 314 | (*b)[y][x] = 0; 315 | } 316 | } 317 | } 318 | } 319 | } 320 | 321 | int can_move_down(board *b) 322 | { 323 | board *tmp; 324 | 325 | tmp = dup_board(b); 326 | 327 | shift_down(tmp); 328 | merge_down(tmp); 329 | shift_down(tmp); 330 | 331 | if (cmp_board(b, tmp)) { 332 | free(tmp); 333 | return 0; 334 | } else { 335 | free(tmp); 336 | return 1; 337 | } 338 | } 339 | 340 | 341 | void merge_down(board *b) 342 | { 343 | int x, y; 344 | struct longint tmp; 345 | 346 | set_big_int(&merge_score, 0); 347 | 348 | for (x = 0; x < brd_w; x++) { 349 | for (y = 3; y > 0; y--) { 350 | if ((*b)[y][x] > 0 && (*b)[y][x] == (*b)[y - 1][x]) { 351 | (*b)[y][x] <<= 1; 352 | (*b)[y - 1][x] = 0; 353 | set_big_int(&tmp, (*b)[x][y]); 354 | add_big_int(&merge_score, &tmp); 355 | 356 | } 357 | } 358 | } 359 | } 360 | 361 | 362 | void shift_down(board *b) 363 | { 364 | int x, y, lastpos; 365 | 366 | for (x = 0; x < brd_w; x++) { 367 | lastpos = 3; 368 | for (y = 3; y >= 0; y--) { 369 | if ((*b)[y][x] != 0) { 370 | (*b)[lastpos][x] = (*b)[y][x]; 371 | if (lastpos-- != y) { 372 | (*b)[y][x] = 0; 373 | } 374 | } 375 | } 376 | } 377 | } 378 | 379 | 380 | int can_move_left(board *b) 381 | { 382 | board *tmp; 383 | 384 | tmp = dup_board(b); 385 | 386 | shift_left(tmp); 387 | merge_left(tmp); 388 | shift_left(tmp); 389 | 390 | if (cmp_board(b, tmp)) { 391 | free(tmp); 392 | return 0; 393 | } else { 394 | free(tmp); 395 | return 1; 396 | } 397 | } 398 | 399 | 400 | void merge_left(board *b) 401 | { 402 | int x, y; 403 | struct longint tmp; 404 | 405 | set_big_int(&merge_score, 0); 406 | 407 | for (y = 0; y < brd_h; y++) { 408 | for (x = 0; x < brd_w - 1; x++) { 409 | if ((*b)[y][x] > 0 && (*b)[y][x] == (*b)[y][x + 1]) { 410 | (*b)[y][x] <<= 1; 411 | (*b)[y][x + 1] = 0; 412 | set_big_int(&tmp, (*b)[y][x]); 413 | add_big_int(&merge_score, &tmp); 414 | } 415 | } 416 | } 417 | } 418 | 419 | 420 | void shift_left(board *b) 421 | { 422 | int x, y, lastpos; 423 | 424 | for (y = 0; y < brd_h; y++) { 425 | lastpos = 0; 426 | for (x = 0; x < brd_w; x++) { 427 | if ((*b)[y][x] != 0) { 428 | (*b)[y][lastpos] = (*b)[y][x]; 429 | if (lastpos++ != x) { 430 | (*b)[y][x] = 0; 431 | } 432 | } 433 | } 434 | } 435 | } 436 | 437 | 438 | int can_move_right(board *b) 439 | { 440 | board *tmp; 441 | 442 | tmp = dup_board(b); 443 | 444 | shift_right(tmp); 445 | merge_right(tmp); 446 | shift_right(tmp); 447 | 448 | if (cmp_board(b, tmp)) { 449 | free(tmp); 450 | return 0; 451 | } else { 452 | free(tmp); 453 | return 1; 454 | } 455 | } 456 | 457 | 458 | void merge_right(board *b) 459 | { 460 | int x, y; 461 | struct longint tmp; 462 | 463 | set_big_int(&merge_score, 0); 464 | 465 | for (y = 0; y < brd_h; y++) { 466 | for (x = 3; x > 0; x--) { 467 | if ((*b)[y][x] > 0 && (*b)[y][x] == (*b)[y][x - 1]) { 468 | (*b)[y][x] <<= 1; 469 | (*b)[y][x - 1] = 0; 470 | set_big_int(&tmp, (*b)[y][x]); 471 | add_big_int(&merge_score, &tmp); 472 | } 473 | } 474 | } 475 | } 476 | 477 | 478 | void shift_right(board *b) 479 | { 480 | int x, y, lastpos; 481 | 482 | for (y = 0; y < brd_h; y++) { 483 | lastpos = 3; 484 | for (x = 3; x >= 0; x--) { 485 | if ((*b)[y][x] != 0) { 486 | (*b)[y][lastpos] = (*b)[y][x]; 487 | if (lastpos-- != x) { 488 | (*b)[y][x] = 0; 489 | } 490 | } 491 | } 492 | } 493 | } 494 | 495 | 496 | int game_is_lost() 497 | { 498 | if (can_move_left(&grid) || can_move_right(&grid) || 499 | can_move_up(&grid) || can_move_down(&grid)) { 500 | return 0; 501 | } else { 502 | return 1; 503 | } 504 | } 505 | 506 | 507 | void end_program() 508 | { 509 | viewpage(0); 510 | os_show_cursor(); 511 | exit(0); 512 | } 513 | 514 | board *dup_board(board *src, board *dest) 515 | { 516 | int x, y; 517 | 518 | board *dest; 519 | 520 | dest = malloc(sizeof(*dest)); 521 | 522 | if (!dest) { 523 | end_program(); 524 | } 525 | 526 | for (y = 0; y < brd_h; y++) { 527 | for (x = 0; x < brd_w; x++) { 528 | (*dest)[y][x] = (*src)[y][x]; 529 | } 530 | } 531 | 532 | return dest; 533 | } 534 | 535 | int cmp_board(board *a, board *b) 536 | { 537 | int x, y; 538 | 539 | for (y = 0; y < brd_h; y++) { 540 | for (x = 0; x < brd_w; x++) { 541 | if ((*a)[y][x] != (*b)[y][x]) return 0; 542 | } 543 | } 544 | } 545 | 546 | 547 | void add_big_int(struct longint *value, struct longint *to_add) 548 | { 549 | int old_val; 550 | 551 | old_val = value->lower; 552 | 553 | value->lower += to_add->lower; 554 | 555 | if (value->lower < to_add->lower) value->upper++; 556 | 557 | value->upper += to_add->upper; 558 | } 559 | 560 | void set_big_int(struct longint *value, int new_val) 561 | { 562 | value->upper = 0; 563 | value->lower = new_val; 564 | } 565 | 566 | -------------------------------------------------------------------------------- /programs/archive.bas: -------------------------------------------------------------------------------- 1 | if $1 = "" then goto help 2 | d = ramstart 3 | 4 | main: 5 | rem >>> Collect command, help if invalid <<< 6 | gosub collect_parameter 7 | if $2 = "HELP" then goto help 8 | if $2 = "CREATE" then goto create_archive 9 | if $2 = "ADD" then goto add_file 10 | if $2 = "REMOVE" then goto remove_file 11 | if $2 = "EXTRACT" then goto extract_file 12 | if $2 = "EXTRACTALL" then goto extract_all 13 | if $2 = "LIST" then goto archive_list 14 | goto help 15 | 16 | collect_parameter: 17 | rem >>> Collects a parameter separated by a space to $2 <<< 18 | rem >>> Offset(P) updated each time <<< 19 | x = & $1 20 | x = x + p 21 | do 22 | x = x + 1 23 | peek v x 24 | if v = 0 then v = 32 25 | loop until v = 32 26 | poke 0 x 27 | x = & $1 28 | x = x + p 29 | string load $2 x 30 | len $2 v 31 | p = p + v + 1 32 | case upper $2 33 | return 34 | 35 | collect_list_item: 36 | rem >>> Collect an item from a comma separated list $2 to $3 <<< 37 | rem >>> offset in Q, returns null if list finished <<< 38 | if q = 255 then $3 = "" 39 | if q = 255 then return 40 | x = & $2 41 | x = x + q 42 | do 43 | x = x + 1 44 | peek v x 45 | if v = 0 then v = 44 46 | if v = 32 then v = 44 47 | loop until v = 44 48 | peek v x 49 | poke 0 x 50 | x = & $2 51 | x = x + q 52 | string load $3 x 53 | if v < 33 then q = 255 54 | len $3 v 55 | if q < 255 then q = q + v + 1 56 | case upper $3 57 | return 58 | 59 | find_free_block: 60 | rem >>> Find a free block big enough for filesize S <<< 61 | rem >>> Returns N = block number, M = number of blocks <<< 62 | 63 | if s = 0 then return 64 | 65 | x = d + 14 66 | peek y x 67 | 68 | rem turn raw size into a number of 512 byte blocks 69 | m = s / 512 70 | v = s % 512 71 | if v > 0 then m = m + 1 72 | w = 0 73 | z = 0 74 | 75 | x = d + 5 76 | peekint v x 77 | x = d + v 78 | 79 | rem search the allocation map for free space 80 | do 81 | peek v x 82 | x = x + 1 83 | if v = 0 then w = w + 1 84 | if v > 0 then w = 0 85 | z = z + 1 86 | rem if we exceed the allocation map there is no space 87 | if z > y then print "There is no area large enough for this file." 88 | if z > y then end 89 | loop until w = m 90 | 91 | n = z - m 92 | return 93 | 94 | allocate_file_entry: 95 | rem >>> Create a file entry with filename $3, size S and the used block <<< 96 | rem >>> Must run find_free_block first to get file area <<< 97 | 98 | rem check the maximum files is not reached 99 | x = d + 11 100 | peek v x 101 | x = d + 12 102 | peek w x 103 | if v = w then print "No free file entries." 104 | if v = w then end 105 | rem increase files in archive 106 | v = v + 1 107 | x = d + 11 108 | poke v x 109 | 110 | x = d + 7 111 | peekint v x 112 | x = v + d 113 | z = 0 114 | rem search the file list for blank entries 115 | do 116 | peek v x 117 | x = x + 17 118 | z = z + 1 119 | if z > w then print "No free file entries." 120 | if z > w then end 121 | loop until v = 0 122 | x = x - 17 123 | 124 | w = d + 9 125 | peekint z w 126 | 127 | rem store information in entry 128 | string store $3 x 129 | x = x + 13 130 | o = n * 512 + z 131 | pokeint o x 132 | x = x + 2 133 | pokeint s x 134 | return 135 | 136 | allocate_free_block: 137 | rem >>> Allocate free block found with find_free_block <<< 138 | 139 | x = d + 5 140 | peekint v x 141 | x = d + v + n 142 | 143 | rem store area as allocated 144 | w = m 145 | do 146 | poke 1 x 147 | x = x + 1 148 | w = w - 1 149 | loop until w = 0 150 | 151 | rem if the last block allocate is more than highest block, update 152 | w = n + m - 1 153 | x = d + 13 154 | peek v x 155 | if w > v then v = w 156 | poke v x 157 | return 158 | 159 | collect_file_data: 160 | rem >>> find filename $3 in the file list and get offset(O) and size(S) <<< 161 | x = d + 12 162 | peek z x 163 | 164 | x = d + 7 165 | peekint v x 166 | x = d + v 167 | 168 | rem search file entries until we find a match 169 | w = 0 170 | y = 0 171 | do 172 | string load $4 x 173 | if $4 = $3 then w = 1 174 | x = x + 17 175 | y = y + 1 176 | if y = z then print "File does not exist." 177 | if y = z then end 178 | loop until w = 1 179 | 180 | rem collect information 181 | x = x - 17 182 | x = x + 13 183 | peekint o x 184 | x = x + 2 185 | peekint s x 186 | return 187 | 188 | deallocate_block: 189 | rem >>> Deallocate block used by a file <<< 190 | rem >>> Run collect_file_info first <<< 191 | 192 | x = d + 9 193 | peekint v x 194 | 195 | rem figure out block number and amount from offset and size 196 | n = o - v / 512 197 | m = s / 512 198 | v = s % 512 199 | if v > 0 then m = m + 1 200 | if m = 0 then return 201 | 202 | x = d + 5 203 | peekint v x 204 | x = v + n + d 205 | y = m 206 | rem store blocks as unused 207 | do 208 | poke 0 x 209 | x = x + 1 210 | y = y - 1 211 | loop until y = 0 212 | 213 | x = d + 14 214 | peek z x 215 | x = d + 5 216 | peekint v x 217 | x = d + v + z - 1 218 | 219 | rem find the new highest block and update 220 | z = z + 1 221 | do 222 | peek v x 223 | x = x - 1 224 | z = z - 1 225 | if z = 0 then v = 1 226 | loop until v = 1 227 | 228 | x = d + 13 229 | poke z x 230 | return 231 | 232 | deallocate_file_entry: 233 | rem >>> Remove file entry with name $3 <<< 234 | rem >>> Must run collect_file_data first <<< 235 | 236 | rem reduce files in archive 237 | x = d + 11 238 | peek v x 239 | v = v - 1 240 | poke v x 241 | 242 | x = d + 7 243 | peekint v x 244 | x = d + v 245 | 246 | rem find file entry 247 | w = 0 248 | do 249 | string load $4 x 250 | x = x + 17 251 | if $4 = $3 then w = 1 252 | loop until w = 1 253 | 254 | rem blank file entry 255 | x = x - 17 256 | for y = 1 to 17 257 | poke 0 x 258 | x = x + 1 259 | next y 260 | return 261 | 262 | load_archive: 263 | rem >>> load and verify archive <<< 264 | 265 | print "Opening Archive..." 266 | rem get name off the commandline parameters 267 | gosub collect_parameter 268 | load $2 d 269 | rem preserve opened name 270 | $8 = $2 271 | 272 | rem make sure file is valid 273 | if s = 0 then print "Archive file is blank." 274 | if s = 0 then end 275 | 276 | if r = 1 then print "Archive file does not exist." 277 | if r = 1 then end 278 | 279 | rem check for archive header 280 | string load $4 d 281 | if $4 = "MFA" then rem 282 | else print "Not an archive file." 283 | else end 284 | 285 | rem check version is current 286 | x = d + 4 287 | peek v x 288 | if v > 1 then print "Archive version not supported." 289 | if v > 1 then end 290 | return 291 | 292 | save_archive: 293 | rem >>> calculate size and store archive <<< 294 | 295 | print "Saving Archive..." 296 | rem header size 297 | z = 14 298 | 299 | rem allocate block size 300 | x = d + 14 301 | peek v x 302 | z = z + v 303 | 304 | rem file list size 305 | x = d + 12 306 | peek v x 307 | v = v * 17 308 | z = z + v 309 | 310 | rem save only up to the last allocated block of data 311 | x = d + 13 312 | peek v x 313 | v = v + 1 314 | v = v * 512 315 | z = z + v 316 | 317 | rem save per existing name, overwrite 318 | delete $8 319 | save $8 d z 320 | return 321 | 322 | help: 323 | rem present is no arguments, help argument or invalid argument 324 | print "============================" 325 | print "ARCHIVE: File archiving tool" 326 | print "============================" 327 | print "Version 1.0.0" 328 | print "Copyright (C) Joshua Beck" 329 | print "Email: mikeosdeveloper@gmail.com" 330 | print "Licenced under the GNU General Public Licence v3" 331 | print "" 332 | print "Syntax: ARCHIVE (command) (archive filename) [comma separated list]" 333 | print "" 334 | print "Commands:" 335 | print " Create - Create an empty archive" 336 | print " Add - Added listed files to archive" 337 | print " Remove - Remove listed files from archive" 338 | print " Extract - Extract listed files from archive" 339 | print " ExtractAll - Extract all files from archive" 340 | print " List - List files in an archive" 341 | print " Help - Display this help screen" 342 | print "" 343 | end 344 | 345 | create_archive: 346 | rem >>> create new archive <<< 347 | 348 | rem file identifier 349 | d = ramstart 350 | $4 = "MFA" 351 | string store $4 d 352 | 353 | rem file version 354 | x = d + 4 355 | poke 1 x 356 | 357 | rem allocation map offset 358 | x = d + 5 359 | pokeint 15 x 360 | 361 | rem file list offset 362 | x = d + 7 363 | pokeint 45 x 364 | 365 | rem data offset 366 | x = d + 9 367 | pokeint 385 x 368 | 369 | rem files in archive 370 | x = d + 11 371 | poke 0 x 372 | 373 | rem file list entries 374 | x = d + 12 375 | poke 20 x 376 | 377 | rem highest allocated block 378 | x = d + 13 379 | poke 0 x 380 | 381 | rem blocks (512 bytes) in allocation map 382 | x = d + 14 383 | poke 40 x 384 | 385 | rem create blank allocation map 386 | x = d + 15 387 | for y = 1 to 40 388 | poke 0 x 389 | x = x + 1 390 | next y 391 | 392 | rem create blank file list 393 | x = d + 45 394 | for y = 1 to 340 395 | poke 0 x 396 | x = x + 1 397 | next y 398 | 399 | rem collect filename off parameter list 400 | gosub collect_parameter 401 | $8 = $2 402 | gosub save_archive 403 | print "File created." 404 | end 405 | 406 | add_file: 407 | gosub load_archive 408 | 409 | gosub collect_parameter 410 | gosub collect_list_item 411 | 412 | t = 0 413 | do 414 | $4 = "Adding file: " + $3 415 | print $4 416 | 417 | size $3 418 | gosub find_free_block 419 | gosub allocate_file_entry 420 | gosub allocate_free_block 421 | 422 | v = d + o 423 | load $3 v 424 | if r = 1 then print "File does not exist." 425 | if r = 1 then end 426 | 427 | gosub collect_list_item 428 | if $3 = "" then t = 1 429 | loop until t = 1 430 | 431 | gosub save_archive 432 | print "All files added successfully." 433 | end 434 | 435 | remove_file: 436 | gosub load_archive 437 | 438 | gosub collect_parameter 439 | gosub collect_list_item 440 | 441 | t = 0 442 | do 443 | $4 = "Removing file: " + $3 444 | print $4 445 | 446 | gosub collect_file_data 447 | gosub deallocate_block 448 | gosub deallocate_file_entry 449 | 450 | gosub collect_list_item 451 | if $3 = "" then t = 1 452 | loop until t = 1 453 | 454 | gosub save_archive 455 | print "All files successfully removed." 456 | end 457 | 458 | extract_file: 459 | gosub load_archive 460 | 461 | gosub collect_parameter 462 | gosub collect_list_item 463 | 464 | t = 0 465 | do 466 | $4 = "Extracting file: " + $3 467 | print $4 468 | 469 | gosub collect_file_data 470 | v = o + d 471 | delete $3 472 | save $3 v s 473 | if r > 0 then print "Invalid filename or read-only disk." 474 | if r > 0 then end 475 | 476 | gosub collect_list_item 477 | if $3 = "" then t = 1 478 | loop until t = 1 479 | 480 | print "All files extracted successfully." 481 | end 482 | 483 | extract_all: 484 | gosub load_archive 485 | 486 | x = d + 12 487 | peek w x 488 | w = w * 17 489 | x = d + 7 490 | peekint t x 491 | t = t + d 492 | u = t + w 493 | 494 | do 495 | string load $3 t 496 | t = t + 17 497 | 498 | $4 = "Extracting file: " + $3 499 | if $3 = "" then rem 500 | else print $4 501 | 502 | gosub collect_file_data 503 | v = o + d 504 | if $3 = "" then rem 505 | else delete $3 506 | else save $3 v s 507 | 508 | if r = 1 then print "Invalid filename or read-only disk." 509 | if r = 1 then end 510 | loop until t = u 511 | 512 | print "All files extracted successfully." 513 | end 514 | 515 | archive_list: 516 | gosub load_archive 517 | 518 | x = d + 11 519 | peek a x 520 | $4 = "File in archive: " + a 521 | x = d + 12 522 | peek b x 523 | 524 | $4 = "Files in archive: " + a 525 | $5 = "Maximum files: " + b 526 | $6 = "Archive size: " + s 527 | 528 | print "Mega File Archive - Version 1" 529 | print $4 530 | print $5 531 | print $6 532 | print "File list:" 533 | if v = 0 then end 534 | 535 | x = d + 12 536 | peek w x 537 | x = d + 7 538 | peekint v x 539 | x = d + v 540 | 541 | do 542 | string load $4 x 543 | if $4 = "" then rem 544 | else print $4 545 | x = x + 17 546 | w = w - 1 547 | loop until w = 0 548 | end 549 | 550 | 551 | -------------------------------------------------------------------------------- /programs/calc.bas: -------------------------------------------------------------------------------- 1 | rem Calculator Application (CALC.BAS) 2 | rem A simple calculator application. 3 | rem Version 2.1.0 4 | rem Made by Joshua Beck 5 | rem Released under the GNU General Public Licence version 3 6 | rem Send any bugs, ideas or comments to zerokelvinkeyboard@gmail.com 7 | 8 | rem Uses the MB++ Library version 4.0 9 | rem Avaliable at code.google.com/p/mikebasic-applications 10 | INCLUDE "MBPP.BAS" 11 | 12 | START: 13 | CLS 14 | REM MB++ initialise function 15 | GOSUB STARTPRG 16 | REM set the text colour and highlight (for the menu) 17 | C = 3 18 | H = 11 19 | REM set the box colour 20 | T = 2 21 | MOVE 30 13 22 | PRINT "Calculating..." 23 | GOTO MAIN 24 | 25 | MAIN: 26 | REM main menu 27 | $5 = "Calculator" 28 | $6 = "Simple Calculations|Advanced Maths|Change Colour Scheme|About|Exit" 29 | GOSUB MENUBOX 30 | IF V = 1 THEN GOSUB BASEMATH 31 | IF V = 2 THEN GOSUB ADVMATH 32 | IF V = 3 THEN GOSUB COLCHANGE 33 | IF V = 4 THEN GOSUB ABOUT 34 | IF V = 5 THEN GOSUB ENDPROG 35 | GOTO MAIN 36 | 37 | COLCHANGE: 38 | $5 = "Change Colour Scheme" 39 | $6 = "Input a new colour for outline, 1-255" 40 | $7 = "Input a new text colour, 1-15" 41 | V = 0 42 | GOSUB DINBOX 43 | $8 = "Invalid colour" 44 | IF A < 1 THEN GOTO ERRBOX 45 | IF A > 255 THEN GOTO ERRBOX 46 | IF B < 1 THEN GOTO ERRBOX 47 | IF B > 15 THEN GOTO ERRBOX 48 | T = A 49 | C = B 50 | $6 = "Input a new highlight colour, 1-15" 51 | V = 0 52 | GOSUB INPBOX 53 | $8 = "Invalid colour" 54 | IF V < 1 THEN GOTO ERRBOX 55 | IF V > 15 THEN GOTO ERRBOX 56 | H = V 57 | RETURN 58 | 59 | BASEMATH: 60 | REM start the menu loop 61 | DO 62 | REM set the menu title 63 | $5 = "Simple Calculations" 64 | REM set items in the menu 65 | $6 = "Addition|Subtraction|Multiplication|Division|Back" 66 | REM call a menu 67 | GOSUB MENUBOX 68 | REM find out what they selected and gosub there 69 | IF V = 1 THEN GOSUB ADD 70 | IF V = 2 THEN GOSUB SUB 71 | IF V = 3 THEN GOSUB MUL 72 | IF V = 4 THEN GOSUB DIV 73 | REM present the menu again unless 'back' was selected 74 | LOOP UNTIL V = 5 75 | V = 0 76 | RETURN 77 | 78 | ADD: 79 | REM INPBOX and DINBOX use V to choose between text and numerical input 80 | REM we want numerical 81 | V = 0 82 | REM set the title 83 | $5 = "Addition" 84 | REM first input prompt 85 | $6 = "Input first number..." 86 | REM second input prompt 87 | $7 = "Input second number..." 88 | REM DINBOX is similar to INPBOX (Print text and asks for input) but 89 | REM it asks for two inputs rather than just one. 90 | GOSUB DINBOX 91 | REM do the actual calculation 92 | REM the first input is A and the second is B 93 | a = a + b 94 | REM prompt above first number 95 | $6 = "Answer is:" 96 | REM prompt about second 97 | REM this is set to a blank string so it won't print it (we only need one) 98 | $7 = "" 99 | REM call a number box to print our answer 100 | GOSUB NUMBOX 101 | REM back to main menu 102 | RETURN 103 | 104 | SUB: 105 | V = 0 106 | $5 = "Subtraction" 107 | $6 = "Input number to subtract from..." 108 | $7 = "Input number to subtract..." 109 | GOSUB DINBOX 110 | A = A - B 111 | $6 = "Answer is:" 112 | $7 = "" 113 | GOSUB NUMBOX 114 | RETURN 115 | 116 | MUL: 117 | V = 0 118 | $5 = "Multiplication" 119 | $6 = "Input first number..." 120 | $7 = "Input second number..." 121 | GOSUB DINBOX 122 | A = A * B 123 | $6 = "Answer is:" 124 | $7 = "" 125 | GOSUB NUMBOX 126 | RETURN 127 | 128 | DIV: 129 | V = 0 130 | $5 = "Division" 131 | $6 = "Input number to be divided..." 132 | $7 = "Input number to divide by..." 133 | GOSUB DINBOX 134 | REM define error message 135 | REM if the divisor is zero then present this error 136 | $8 = "Attempted to divide by zero!" 137 | IF B = 0 THEN GOTO ERRBOX 138 | D = A / B 139 | E = A % B 140 | A = D 141 | B = E 142 | $6 = "Answer is:" 143 | $7 = "Reminder is:" 144 | GOSUB NUMBOX 145 | RETURN 146 | 147 | ADVMATH: 148 | DO 149 | $5 = "Advanced Maths" 150 | $6 = "Square/Cube Number|Power|Mass Addition|Mass Subtraction|Back" 151 | GOSUB MENUBOX 152 | IF V = 1 THEN GOSUB SQUARE 153 | IF V = 2 THEN GOSUB POWER 154 | IF V = 3 THEN GOSUB MASSADD 155 | IF V = 4 THEN GOSUB MASSTAKE 156 | LOOP UNTIL V = 5 157 | V = 0 158 | RETURN 159 | 160 | SQUARE: 161 | $5 = "Square/Cube Number" 162 | $6 = "|Input a number to square and cube" 163 | V = 0 164 | GOSUB INPBOX 165 | A = V 166 | D = A 167 | A = A * D 168 | B = A * D 169 | $5 = "Square/Cube Number" 170 | $6 = "Number Squared is:" 171 | $7 = "Number Cubed is:" 172 | GOSUB NUMBOX 173 | RETURN 174 | 175 | POWER: 176 | $5 = "Power" 177 | $6 = "Input a number" 178 | $7 = "Input power to raise to" 179 | V = 0 180 | GOSUB DINBOX 181 | D = A 182 | IF B = 0 THEN A = 1 183 | IF B = 0 THEN GOTO POWERSKIP 184 | IF B = 1 THEN GOTO POWERSKIP 185 | DO 186 | A = A * D 187 | B = B - 1 188 | LOOP UNTIL B = 1 189 | POWERSKIP: 190 | $5 = "Power" 191 | $6 = "Answer is:" 192 | $7 = "" 193 | GOSUB NUMBOX 194 | RETURN 195 | 196 | MASSADD: 197 | $5 = "Mass Add" 198 | $6 = "Enter the base number" 199 | $7 = "Enter the first number to add" 200 | V = 0 201 | GOSUB DINBOX 202 | N = A 203 | N = N + B 204 | ADDMORE: 205 | $5 = "Mass Add" 206 | $6 = "Enter another number to add|or zero to finish the sum" 207 | V = 0 208 | GOSUB INPBOX 209 | N = N + V 210 | IF V > 0 THEN GOTO ADDMORE 211 | $6 = "The base number was: " 212 | $7 = "The total was: " 213 | B = N 214 | GOSUB NUMBOX 215 | RETURN 216 | 217 | MASSTAKE: 218 | $5 = "Mass Subtract" 219 | $6 = "Enter the base number" 220 | $7 = "Enter the first number to take" 221 | V = 0 222 | GOSUB DINBOX 223 | N = A 224 | N = N - B 225 | TAKEMORE: 226 | $5 = "Mass Subtract" 227 | $6 = "Enter another number to take|or zero to finish the sum" 228 | V = 0 229 | GOSUB INPBOX 230 | N = N - V 231 | IF V > 0 THEN GOTO TAKEMORE 232 | $6 = "The base number was: " 233 | $7 = "The total was: " 234 | B = N 235 | GOSUB NUMBOX 236 | RETURN 237 | 238 | ABOUT: 239 | REM About message (strings have an 128 character limit) 240 | MOVE 0 0 241 | $5 = "About" 242 | $6 = "Calculator, version 2.1.0|" 243 | $6 = $6 + "An advanced calculator application|" 244 | $6 = $6 + "Released under the GNU GPL v3|\7" 245 | $7 = "Written in MikeOS BASIC|" 246 | $7 = $7 + "Uses the MB++ Library, version 4.0" 247 | GOSUB MESBOX 248 | RETURN 249 | -------------------------------------------------------------------------------- /programs/clib.h: -------------------------------------------------------------------------------- 1 | #ifndef MLIB_H 2 | #define MLIB_H 3 | 4 | /* Define some helpful keywords. */ 5 | #ifndef NULL 6 | #define NULL ((void*) 0x0) 7 | #endif 8 | 9 | #ifndef bool 10 | typedef int bool; 11 | #endif 12 | 13 | #ifndef true 14 | #define true 0x1 15 | #endif 16 | 17 | #ifndef false 18 | #define false 0x0 19 | #endif 20 | 21 | /* Define PathOS definitions. */ 22 | #ifndef BLACK_ON_WHITE 23 | #define BLACK_ON_WHITE 0xF0 24 | #endif 25 | 26 | #ifndef WHITE_ON_BLACK 27 | #define WHITE_ON_BLACK 0x0F 28 | #endif 29 | 30 | #ifndef WHITE_ON_LIGHT_RED 31 | #define WHITE_ON_LIGHT_RED 0xCF 32 | #endif 33 | 34 | #ifndef WHITE_ON_GREEN 35 | #define WHITE_ON_GREEN 0x2F 36 | #endif 37 | 38 | #ifndef RED_ON_LIGHT_GREEN 39 | #define WHITE_ON_LIGHT_GREEN 0xA4 40 | #endif 41 | 42 | #ifndef KEY_UP 43 | #define KEY_UP 0x48 44 | #endif 45 | 46 | #ifndef KEY_DOWN 47 | #define KEY_DOWN 0x50 48 | #endif 49 | 50 | #ifndef KEY_LEFT 51 | #define KEY_LEFT 0x4B 52 | #endif 53 | 54 | #ifndef KEY_RIGHT 55 | #define KEY_RIGHT 0x4D 56 | #endif 57 | 58 | #ifndef KEY_ESC 59 | #define KEY_ESC 0x1B 60 | #endif 61 | 62 | #ifndef KEY_ENTER 63 | #define KEY_ENTER 0xD 64 | #endif 65 | 66 | /* A global variable for I/O error reporting. */ 67 | #ifndef ioerr 68 | extern bool ioerr; 69 | #endif 70 | 71 | /* A structure for string_parse(). */ 72 | #ifndef str_p 73 | typedef struct str_p { 74 | char *str1; 75 | char *str2; 76 | char *str3; 77 | char *str4; 78 | } str_p; 79 | #endif 80 | 81 | /* Create a long structure for long_int_to_string() and long_int_negate(). */ 82 | #ifndef long_int 83 | typedef struct long_int { 84 | int upper; 85 | int lower; 86 | } long_int; 87 | #endif 88 | 89 | /* Define the disk functions. */ 90 | char* get_file_list(char* buffer); 91 | int load_file(char* string, unsigned int location); 92 | void write_file(char* filename, char* buffer, unsigned int bytestowrite); 93 | bool file_exists(char* filename); 94 | void create_file(char* filename); 95 | void remove_file(char* filename); 96 | void rename_file(char* old_filename, char* new_oldname); 97 | int get_file_size(char* filename); 98 | 99 | /* Define the keyboard functions. */ 100 | int wait_for_key(void); 101 | int check_for_key(void); 102 | 103 | /* Define the math functions. */ 104 | int bcd_to_int(char number); 105 | void long_int_negate(long_int *number); 106 | int get_random(int low, int high); 107 | 108 | /* Define the misc functions. */ 109 | char get_api_version(void); 110 | void pause(unsigned int decisecond); 111 | void fatal_error(char* message); 112 | 113 | /* Define the port functions. */ 114 | void port_byte_out(int port, char data); 115 | char port_byte_in(int port); 116 | void serial_port_enable(bool mode); 117 | void send_via_serial(char data); 118 | char get_via_serial(); 119 | 120 | /* Define the screen functions. */ 121 | void print_string(char* string); 122 | void clear_screen(void); 123 | void move_cursor(unsigned int cursor); 124 | int get_cursor_pos(void); 125 | void print_horiz_line(bool double_line); 126 | void show_cursor(void); 127 | void hide_cursor(void); 128 | void draw_block(unsigned char color, unsigned char start_x, unsigned char start_y, unsigned char end_x, unsigned char end_y); 129 | char* file_selector(void); 130 | char list_dialog(char* list, char* string1, char* string2); 131 | void draw_background(char* top, char* bottom, unsigned int color); 132 | void print_newline(void); 133 | void dump_registers(void); 134 | bool dialog_box(char* string1, char* string2, char* string3, bool mode); 135 | void print_space(void); 136 | void dump_string(char* string); 137 | void print_digit(unsigned int digit); 138 | void print_1hex(unsigned char digit); 139 | void print_2hex(unsigned char digit); 140 | void print_4hex(unsigned int digit); 141 | char* input_string(char* buffer, int limit); 142 | 143 | /* Define the string functions. */ 144 | int string_length(char* string); 145 | int find_char_in_string(char* string, char chartofind); 146 | void string_reverse(char* string); 147 | void string_charchange(char* string, char chartofind, char chartoreplacewith); 148 | char* string_uppercase(char* string); 149 | char* string_lowercase(char* string); 150 | char* string_copy(char* oldstring, char* newstring); 151 | char* string_truncate(char* string, int size); 152 | char* string_join(char* string1, char* string2, char* outstring); 153 | void string_chomp(char* string); 154 | void string_strip(char* string, char chartoremove); 155 | bool string_compare(char* string1, char* string2); 156 | bool string_strincmp(char* string1, char* string2, char chartocheck); 157 | void string_parse(str_p *strings, char* string); 158 | int string_to_int(char* string); 159 | char* int_to_string(int number); 160 | char* sint_to_string(int number); 161 | void long_int_to_string(long_int *number, int base, char *output_string); 162 | void set_time_fmt(bool format); 163 | void get_time_string(char *string); 164 | void set_date_fmt(int format); 165 | void get_date_string(char* string); 166 | 167 | /* Define the sound functions. */ 168 | void speaker_tone(unsigned int frequency); 169 | void speaker_off(void); 170 | 171 | /* Define the BASIC interpreter function. */ 172 | void run_basic(char* code, unsigned int size, char* parameter_string); 173 | 174 | #endif 175 | -------------------------------------------------------------------------------- /programs/image-viewer.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Program to display text files and PCX images (320x200, 8-bit only) 3 | ; ------------------------------------------------------------------ 4 | 5 | 6 | BITS 16 7 | %INCLUDE "mikedev.inc" 8 | ORG 32768 9 | 10 | 11 | main_start: 12 | call draw_background 13 | 14 | call os_file_selector ; Get filename 15 | 16 | jc near close ; Quit if Esc pressed in dialog box 17 | 18 | mov bx, ax ; Save filename for now 19 | 20 | mov di, ax 21 | 22 | call os_string_length 23 | add di, ax ; DI now points to last char in filename 24 | 25 | dec di 26 | dec di 27 | dec di ; ...and now to first char of extension! 28 | 29 | mov si, txt_extension 30 | mov cx, 3 31 | rep cmpsb ; Does the extension contain 'TXT'? 32 | je near valid_txt_extension ; Skip ahead if so 33 | 34 | dec di 35 | 36 | mov si, bas_extension 37 | mov cx, 3 38 | rep cmpsb ; Does the extension contain 'BAS'? 39 | je near valid_txt_extension ; Skip ahead if so 40 | 41 | dec di 42 | 43 | mov si, pcx_extension 44 | mov cx, 3 45 | rep cmpsb ; Does the extension contain 'PCX'? 46 | je valid_pcx_extension ; Skip ahead if so 47 | 48 | ; Otherwise show error dialog 49 | mov dx, 0 ; One button for dialog box 50 | mov ax, err_string 51 | mov bx, 0 52 | mov cx, 0 53 | call os_dialog_box 54 | 55 | jmp main_start ; And retry 56 | 57 | 58 | valid_pcx_extension: 59 | mov ax, bx 60 | mov cx, 36864 ; Load PCX at 36864 (4K after program start) 61 | call os_load_file 62 | 63 | 64 | mov ah, 0 ; Switch to graphics mode 65 | mov al, 13h 66 | int 10h 67 | 68 | 69 | mov ax, 0A000h ; ES = video memory 70 | mov es, ax 71 | 72 | 73 | mov si, 36864+80h ; Move source to start of image data 74 | ; (First 80h bytes is header) 75 | 76 | mov di, 0 ; Start our loop at top of video RAM 77 | 78 | decode: 79 | mov cx, 1 80 | lodsb 81 | cmp al, 192 ; Single pixel or string? 82 | jb single 83 | and al, 63 ; String, so 'mod 64' it 84 | mov cl, al ; Result in CL for following 'rep' 85 | lodsb ; Get byte to put on screen 86 | single: 87 | rep stosb ; And show it (or all of them) 88 | cmp di, 64001 89 | jb decode 90 | 91 | 92 | mov dx, 3c8h ; Palette index register 93 | mov al, 0 ; Start at colour 0 94 | out dx, al ; Tell VGA controller that... 95 | inc dx ; ...3c9h = palette data register 96 | 97 | mov cx, 768 ; 256 colours, 3 bytes each 98 | setpal: 99 | lodsb ; Grab the next byte. 100 | shr al, 2 ; Palettes divided by 4, so undo 101 | out dx, al ; Send to VGA controller 102 | loop setpal 103 | 104 | 105 | call os_wait_for_key 106 | 107 | mov ax, 3 ; Back to text mode 108 | mov bx, 0 109 | int 10h 110 | mov ax, 1003h ; No blinking text! 111 | int 10h 112 | 113 | mov ax, 2000h ; Reset ES back to original value 114 | mov es, ax 115 | call os_clear_screen 116 | jmp main_start 117 | 118 | 119 | draw_background: 120 | mov ax, title_msg ; Set up screen 121 | mov bx, footer_msg 122 | mov cx, BLACK_ON_WHITE 123 | call os_draw_background 124 | ret 125 | 126 | 127 | 128 | ; Meanwhile, if it's a text file... 129 | 130 | valid_txt_extension: 131 | mov ax, bx 132 | mov cx, 36864 ; Load file 4K after program start 133 | call os_load_file 134 | 135 | 136 | ; Now BX contains the number of bytes in the file, so let's add 137 | ; the load offset to get the last byte of the file in RAM 138 | 139 | add bx, 36864 140 | 141 | 142 | mov cx, 0 ; Lines to skip when rendering 143 | mov word [skiplines], 0 144 | 145 | 146 | pusha 147 | mov ax, txt_title_msg ; Set up screen 148 | mov bx, txt_footer_msg 149 | mov cx, 11110000b ; Black text on white background 150 | call os_draw_background 151 | popa 152 | 153 | 154 | 155 | txt_start: 156 | pusha 157 | 158 | mov bl, 11110000b ; Black text on white background 159 | mov dh, 2 160 | mov dl, 0 161 | mov si, 80 162 | mov di, 23 163 | call os_draw_block ; Overwrite old text for scrolling 164 | 165 | mov dh, 2 ; Move cursor to near top 166 | mov dl, 0 167 | call os_move_cursor 168 | 169 | popa 170 | 171 | 172 | mov si, 36864 ; Start of text data 173 | mov ah, 0Eh ; BIOS char printing routine 174 | 175 | 176 | redraw: 177 | cmp cx, 0 ; How many lines to skip? 178 | je loopy 179 | dec cx 180 | 181 | skip_loop: 182 | lodsb ; Read bytes until newline, to skip a line 183 | cmp al, 10 184 | jne skip_loop 185 | jmp redraw 186 | 187 | 188 | loopy: 189 | lodsb ; Get character from file data 190 | 191 | cmp al, 10 ; Return to start of line if carriage return character 192 | jne skip_return 193 | call os_get_cursor_pos 194 | mov dl, 0 195 | call os_move_cursor 196 | 197 | skip_return: 198 | int 10h ; Print the character 199 | 200 | cmp si, bx ; Have we printed all in the file? 201 | je finished 202 | 203 | call os_get_cursor_pos ; Are we at the bottom of the display area? 204 | cmp dh, 23 205 | je get_input 206 | 207 | jmp loopy 208 | 209 | 210 | get_input: ; Get cursor keys and Q 211 | call os_wait_for_key 212 | cmp ah, KEY_UP 213 | je go_up 214 | cmp ah, KEY_DOWN 215 | je go_down 216 | cmp al, 'q' 217 | je main_start 218 | cmp al, 'Q' 219 | je main_start 220 | jmp get_input 221 | 222 | 223 | go_up: 224 | cmp word [skiplines], 0 ; Don't scroll up if we're at the top 225 | jle txt_start 226 | dec word [skiplines] ; Otherwise decrement the lines we need to skip 227 | mov word cx, [skiplines] 228 | jmp txt_start 229 | 230 | go_down: 231 | inc word [skiplines] ; Increment the lines we need to skip 232 | mov word cx, [skiplines] 233 | jmp txt_start 234 | 235 | 236 | finished: ; We get here when we've printed the final character 237 | call os_wait_for_key 238 | cmp ah, 48h 239 | je go_up ; Can only scroll up at this point 240 | cmp al, 'q' 241 | je main_start 242 | cmp al, 'Q' 243 | je main_start 244 | jmp finished 245 | 246 | 247 | close: 248 | call os_clear_screen 249 | ret 250 | 251 | 252 | txt_extension db 'TXT', 0 253 | bas_extension db 'BAS', 0 254 | pcx_extension db 'PCX', 0 255 | 256 | err_string db 'Please select a TXT, BAS or PCX file!', 0 257 | 258 | title_msg db 'PathOS File Viewer', 0 259 | footer_msg db 'Select a PCX file to view, or press Esc to exit', 0 260 | 261 | txt_title_msg db 'PathOS Text File Viewer', 0 262 | txt_footer_msg db 'Use arrow keys to scroll and Q to quit', 0 263 | 264 | skiplines dw 0 265 | 266 | 267 | ; ------------------------------------------------------------------ 268 | 269 | -------------------------------------------------------------------------------- /programs/image-viewer.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/programs/image-viewer.bin -------------------------------------------------------------------------------- /programs/kd.asm: -------------------------------------------------------------------------------- 1 | bits 16 2 | org 32768 3 | %include "mikedev.inc" 4 | 5 | mov ah, 09h 6 | mov al, ' ' 7 | mov bx, 0004h 8 | mov cx, 42 9 | int 10h 10 | mov si, i_tr ; 42 11 | call os_print_string 12 | mov dh, 24 13 | mov dl, 0 14 | call os_move_cursor 15 | mov ah, 09h 16 | mov al, ' ' 17 | mov bx, 0004h 18 | mov cx, 79 19 | int 10h 20 | mov si, footer ; 79 21 | call os_print_string 22 | mov dh, 1 23 | mov dl, 0 24 | call os_move_cursor 25 | mov ah, 09h 26 | mov al, ' ' 27 | mov bx, 0002h 28 | mov cx, 80 29 | int 10h 30 | mov ax, input 31 | mov bx, 80 32 | call os_input_string 33 | call os_print_newline 34 | mov ah, 09h 35 | mov al, ' ' 36 | mov bx, 0004h 37 | mov cx, 6 38 | int 10h 39 | mov si, sonuc 40 | call os_print_string 41 | mov ah, 09h 42 | mov al, ' ' 43 | mov bx, 0002h 44 | mov cx, 80 45 | int 10h 46 | mov si, input 47 | jmp lp 48 | lp: 49 | pusha 50 | mov ah, 0Eh 51 | 52 | .tekrar: 53 | lodsb 54 | cmp al, 0 55 | je .done 56 | 57 | cmp al, 'a' 58 | je .sesli 59 | cmp al, 'e' 60 | je .sesli 61 | cmp al, 'i' 62 | je .sesli 63 | cmp al, 'u' 64 | je .sesli 65 | cmp al, 'o' 66 | je .sesli 67 | cmp al, 'A' 68 | je .sesli_b 69 | cmp al, 'E' 70 | je .sesli_b 71 | cmp al, 'I' 72 | je .sesli_b 73 | cmp al, 'U' 74 | je .sesli_b 75 | cmp al, 'O' 76 | je .sesli_b 77 | int 10h 78 | jmp .tekrar 79 | 80 | .sesli: 81 | int 10h 82 | pusha 83 | mov al, 'g' 84 | int 10h 85 | popa 86 | int 10h 87 | jmp .tekrar 88 | 89 | .sesli_b: 90 | int 10h 91 | pusha 92 | mov al, 'G' 93 | int 10h 94 | popa 95 | int 10h 96 | jmp .tekrar 97 | 98 | .done: 99 | call os_print_newline 100 | call os_wait_for_key 101 | ret 102 | 103 | input times 80 db 0 104 | i_tr db 'Turkce metin girin (en fazla 80 karakter):', 0 105 | footer db 'GH: Comrade-Otaku/kd-mikeos Made by Camroku', 0 106 | sonuc db 'Sonuc:', 13, 10, 0 107 | -------------------------------------------------------------------------------- /programs/keyboard.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Music keyboard -- Use the keyboard to play notes via the PC speaker 3 | ; Use Z key rightwards for an octave 4 | ; ------------------------------------------------------------------ 5 | 6 | 7 | BITS 16 8 | %INCLUDE "mikedev.inc" 9 | ORG 32768 10 | 11 | 12 | start: 13 | call os_hide_cursor 14 | 15 | call os_clear_screen 16 | 17 | mov ax, mus_kbd_title_msg ; Set up screen 18 | mov bx, mus_kbd_footer_msg 19 | mov cx, WHITE_ON_LIGHT_RED 20 | call os_draw_background 21 | 22 | mov bl, BLACK_ON_WHITE ; White block to draw keyboard on 23 | mov dh, 4 24 | mov dl, 5 25 | mov si, 69 26 | mov di, 21 27 | call os_draw_block 28 | 29 | 30 | 31 | ; Now lots of loops to draw the keyboard 32 | 33 | mov dl, 24 ; Top line of box 34 | mov dh, 6 35 | call os_move_cursor 36 | 37 | mov ah, 0Eh 38 | mov al, 196 39 | 40 | mov cx, 31 41 | .loop1: 42 | int 10h 43 | loop .loop1 44 | 45 | 46 | mov dl, 24 ; Bottom line of box 47 | mov dh, 18 48 | call os_move_cursor 49 | 50 | mov ah, 0Eh 51 | mov al, 196 52 | 53 | mov cx, 31 54 | .loop2: 55 | int 10h 56 | loop .loop2 57 | 58 | 59 | 60 | mov dl, 23 ; Top-left corner 61 | mov dh, 6 62 | call os_move_cursor 63 | 64 | mov al, 218 65 | int 10h 66 | 67 | 68 | mov dl, 55 ; Top-right corner 69 | mov dh, 6 70 | call os_move_cursor 71 | 72 | mov al, 191 73 | int 10h 74 | 75 | 76 | mov dl, 23 ; Bottom-left corner 77 | mov dh, 18 78 | call os_move_cursor 79 | 80 | mov al, 192 81 | int 10h 82 | 83 | 84 | mov dl, 55 ; Bottom-right corner 85 | mov dh, 18 86 | call os_move_cursor 87 | 88 | mov al, 217 89 | int 10h 90 | 91 | 92 | mov dl, 23 ; Left-hand box line 93 | mov dh, 7 94 | mov al, 179 95 | .loop3: 96 | call os_move_cursor 97 | int 10h 98 | inc dh 99 | cmp dh, 18 100 | jne .loop3 101 | 102 | 103 | mov dl, 55 ; Right-hand box line 104 | mov dh, 7 105 | mov al, 179 106 | .loop4: 107 | call os_move_cursor 108 | int 10h 109 | inc dh 110 | cmp dh, 18 111 | jne .loop4 112 | 113 | 114 | mov dl, 23 ; Key-separating lines 115 | .biggerloop: 116 | add dl, 4 117 | mov dh, 7 118 | mov al, 179 119 | .loop5: 120 | call os_move_cursor 121 | int 10h 122 | inc dh 123 | cmp dh, 18 124 | jne .loop5 125 | cmp dl, 51 126 | jne .biggerloop 127 | 128 | 129 | mov al, 194 ; Top of box line joiners 130 | mov dh, 6 131 | mov dl, 27 132 | .loop6: 133 | call os_move_cursor 134 | int 10h 135 | add dl, 4 136 | cmp dl, 55 137 | jne .loop6 138 | 139 | 140 | mov al, 193 ; Bottom of box line joiners 141 | mov dh, 18 142 | mov dl, 27 143 | .loop7: 144 | call os_move_cursor 145 | int 10h 146 | add dl, 4 147 | cmp dl, 55 148 | jne .loop7 149 | 150 | 151 | ; And now for the black keys... 152 | 153 | mov bl, WHITE_ON_BLACK 154 | 155 | mov dh, 6 156 | mov dl, 26 157 | mov si, 3 158 | mov di, 13 159 | call os_draw_block 160 | 161 | mov dh, 6 162 | mov dl, 30 163 | mov si, 3 164 | mov di, 13 165 | call os_draw_block 166 | 167 | mov dh, 6 168 | mov dl, 38 169 | mov si, 3 170 | mov di, 13 171 | call os_draw_block 172 | 173 | mov dh, 6 174 | mov dl, 42 175 | mov si, 3 176 | mov di, 13 177 | call os_draw_block 178 | 179 | mov dh, 6 180 | mov dl, 46 181 | mov si, 3 182 | mov di, 13 183 | call os_draw_block 184 | 185 | 186 | 187 | ; And lastly, draw the labels on the keys indicating which 188 | ; (computer!) keys to press to get notes 189 | 190 | mov ah, 0Eh 191 | 192 | mov dh, 17 193 | mov dl, 25 194 | call os_move_cursor 195 | 196 | mov al, 'Z' 197 | int 10h 198 | 199 | add dl, 4 200 | call os_move_cursor 201 | mov al, 'X' 202 | int 10h 203 | 204 | add dl, 4 205 | call os_move_cursor 206 | mov al, 'C' 207 | int 10h 208 | 209 | add dl, 4 210 | call os_move_cursor 211 | mov al, 'V' 212 | int 10h 213 | 214 | add dl, 4 215 | call os_move_cursor 216 | mov al, 'B' 217 | int 10h 218 | 219 | add dl, 4 220 | call os_move_cursor 221 | mov al, 'N' 222 | int 10h 223 | 224 | add dl, 4 225 | call os_move_cursor 226 | mov al, 'M' 227 | int 10h 228 | 229 | add dl, 4 230 | call os_move_cursor 231 | mov al, ',' 232 | int 10h 233 | 234 | ; Now the accidentals... 235 | 236 | mov dh, 11 237 | mov dl, 27 238 | call os_move_cursor 239 | mov al, 'S' 240 | int 10h 241 | 242 | add dl, 4 243 | call os_move_cursor 244 | mov al, 'D' 245 | int 10h 246 | 247 | add dl, 8 248 | call os_move_cursor 249 | mov al, 'G' 250 | int 10h 251 | 252 | add dl, 4 253 | call os_move_cursor 254 | mov al, 'H' 255 | int 10h 256 | 257 | add dl, 4 258 | call os_move_cursor 259 | mov al, 'J' 260 | int 10h 261 | 262 | ; Phew! We've drawn all the keys now 263 | 264 | .retry: 265 | call os_wait_for_key 266 | 267 | .nokey: ; Matching keys with notes 268 | cmp al, 'z' 269 | jne .s 270 | mov ax, 4000 271 | mov bx, 0 272 | call os_speaker_tone 273 | jmp .retry 274 | .s: 275 | cmp al, 's' 276 | jne .x 277 | mov ax, 3800 278 | mov bx, 0 279 | call os_speaker_tone 280 | jmp .retry 281 | .x: 282 | cmp al, 'x' 283 | jne .d 284 | mov ax, 3600 285 | mov bx, 0 286 | call os_speaker_tone 287 | jmp .retry 288 | .d: 289 | cmp al, 'd' 290 | jne .c 291 | mov ax, 3400 292 | mov bx, 0 293 | call os_speaker_tone 294 | jmp .retry 295 | .c: 296 | cmp al, 'c' 297 | jne .v 298 | mov ax, 3200 299 | mov bx, 0 300 | call os_speaker_tone 301 | jmp .retry 302 | 303 | 304 | .v: 305 | cmp al, 'v' 306 | jne .g 307 | mov ax, 3000 308 | mov bx, 0 309 | call os_speaker_tone 310 | jmp .retry 311 | .g: 312 | cmp al, 'g' 313 | jne .b 314 | mov ax, 2850 315 | mov bx, 0 316 | call os_speaker_tone 317 | jmp .retry 318 | .b: 319 | cmp al, 'b' 320 | jne .h 321 | mov ax, 2700 322 | mov bx, 0 323 | call os_speaker_tone 324 | jmp .retry 325 | .h: 326 | cmp al, 'h' 327 | jne .n 328 | mov ax, 2550 329 | mov bx, 0 330 | call os_speaker_tone 331 | jmp .retry 332 | .n: 333 | cmp al, 'n' 334 | jne .j 335 | mov ax, 2400 336 | mov bx, 0 337 | call os_speaker_tone 338 | jmp .retry 339 | .j: 340 | cmp al, 'j' 341 | jne .m 342 | mov ax, 2250 343 | mov bx, 0 344 | call os_speaker_tone 345 | jmp .retry 346 | .m: 347 | cmp al, 'm' 348 | jne .comma 349 | mov ax, 2100 350 | mov bx, 0 351 | call os_speaker_tone 352 | jmp .retry 353 | 354 | .comma: 355 | cmp al, ',' 356 | jne .space 357 | mov ax, 2000 358 | mov bx, 0 359 | call os_speaker_tone 360 | jmp .retry 361 | 362 | .space: 363 | cmp al, ' ' 364 | jne .esc 365 | call os_speaker_off 366 | jmp .retry 367 | 368 | .esc: 369 | cmp al, 27 370 | je .end 371 | jmp .nowt 372 | 373 | .nowt: 374 | jmp .retry 375 | 376 | .end: 377 | call os_speaker_off 378 | 379 | call os_clear_screen 380 | 381 | call os_show_cursor 382 | 383 | ret ; Back to OS 384 | 385 | 386 | mus_kbd_title_msg db 'MikeOS Music Keyboard (PC speaker sound)', 0 387 | mus_kbd_footer_msg db 'Hit keys to play notes, space to silence a note, and Esc to quit', 0 388 | 389 | 390 | ; ------------------------------------------------------------------ 391 | 392 | -------------------------------------------------------------------------------- /programs/keyboard.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/programs/keyboard.bin -------------------------------------------------------------------------------- /programs/mbpp.bas: -------------------------------------------------------------------------------- 1 | REM >>>MIKEBASIC-PLUS-PLUS-LIBRARY<<< 2 | REM Library Version 4.1.0 3 | REM Copyright (C) Joshua Beck. 4 | REM Email: zerokelvinkeyboard@gmail.com 5 | REM Licenced under the GNU General Public Licence revision 3. 6 | REM Requires MikeOS version 4.5 or later. 7 | 8 | REM Wiki: https://github.com/ZeroKelvinKeyboard/MikeOS-Apps/wiki/mbppdoc 9 | 10 | PRINT "MB++ Library version 4.1.0" 11 | END 12 | 13 | ANCITEXT: 14 | GOSUB SAVEVAR 15 | GOSUB SAVELOC 16 | ink c 17 | W = X 18 | POKE Y 65430 19 | CURSPOS X Y 20 | POKE X 65431 21 | DO 22 | IF X > W THEN X = 79 23 | if x > 78 then y = y + 1 24 | if x > 78 then peek x 65431 25 | PEEK J 65430 26 | IF Y > J THEN J = 0 27 | IF Y > 23 THEN J = 0 28 | move x y 29 | IF J > 0 THEN PEEK J V 30 | IF J = 0 THEN W = J + 1 31 | IF J < 20 THEN GOSUB ANCITXTS 32 | IF J > 0 THEN PRINT CHR J 33 | x = x + 1 34 | v = v + 1 35 | LOOP UNTIL W > J 36 | GOSUB LOADLOC 37 | GOSUB LOADVAR 38 | RETURN 39 | 40 | ANCITXTS: 41 | IF J = 0 THEN RETURN 42 | IF J = 1 THEN V = V + 1 43 | IF J = 1 THEN J = 255 44 | IF J = 7 THEN J = 255 45 | IF J = 10 THEN Y = Y + 1 46 | IF J = 10 THEN PEEK X 65431 47 | IF J = 10 THEN V = V + 1 48 | IF J = 10 THEN GOTO ANCITEX2 49 | RETURN 50 | 51 | ARRAYGET: 52 | POKEINT J 65418 53 | IF X > 99 THEN $8 = "ARRAYGET: Array over maximum" 54 | IF X > 99 THEN GOTO ERRBOX 55 | IF X < 0 THEN $8 = "ARRAYGET: Number below zero" 56 | IF X < 0 THEN GOTO ERRBOX 57 | J = X 58 | J = J * 2 59 | J = J + 65000 60 | PEEKINT V J 61 | PEEKINT J 65418 62 | RETURN 63 | 64 | ARRAYPUT: 65 | POKEINT J 65418 66 | IF X > 99 THEN $8 = "ARRAYGET: Array over maximum" 67 | IF X > 99 THEN GOTO ERRBOX 68 | IF X < 0 THEN $8 = "ARRAYGET: Number below zero" 69 | IF X < 0 THEN GOTO ERRBOX 70 | J = X 71 | J = J * 2 72 | J = J + 65000 73 | POKEINT V J 74 | PEEKINT J 65418 75 | RETURN 76 | 77 | ASKBOX: 78 | GOSUB OPENBOX 79 | MOVE 22 11 80 | GOSUB BOXPRINT 81 | move 27 16 82 | print "--Yes-- --No--" 83 | poke 1 65420 84 | V = 1 85 | gosub askdraw 86 | askloop: 87 | waitkey j 88 | if j = 3 then gosub swleft 89 | if j = 4 then gosub swright 90 | if j = 13 then goto askend 91 | goto askloop 92 | askend: 93 | peek v 65420 94 | j = v 95 | if j = 0 then v = 1 96 | if j = 1 then v = 0 97 | GOSUB CLOSEBOX 98 | return 99 | swleft: 100 | peek v 65420 101 | if v = 0 then return 102 | if v = 1 then v = 0 103 | poke v 65420 104 | gosub askdraw 105 | return 106 | swright: 107 | peek v 65420 108 | if v = 1 then return 109 | if v = 0 then v = 1 110 | poke v 65420 111 | gosub askdraw 112 | return 113 | askdraw: 114 | move 27 16 115 | if v = 0 then ink h 116 | if v = 1 then ink c 117 | print "--Yes--" 118 | move 42 16 119 | if v = 0 then ink c 120 | if v = 1 then ink h 121 | print "--No--" 122 | return 123 | 124 | BOXPRINT: 125 | GOSUB SAVEVAR 126 | X = 64146 127 | Y = 64151 128 | FOR W = 1 TO 5 129 | POKE 0 X 130 | POKE 22 Y 131 | X = X + 1 132 | Y = Y + 1 133 | NEXT W 134 | X = & $6 135 | W = 36 136 | Y = 0 137 | DO 138 | PEEK V X 139 | X = X + 1 140 | IF V = '|' THEN GOTO BOXNEWLN 141 | IF V = '\' THEN GOTO BOXOPT 142 | PRINT CHR V ; 143 | W = W - 1 144 | IF W < 1 THEN GOTO BOXNEWLN 145 | IF Y = 0 AND Y > 32 THEN GOSUB BOXPOFFS 146 | IF Y = 0 AND Y < 32 THEN GOSUB BOXPOFFS 147 | BOXPRNT2: 148 | LOOP UNTIL V = 0 149 | IF V > 15 THEN GOTO BOXPRNT3 150 | CURSPOS J V 151 | J = J - 22 152 | W = V - 11 + 64151 153 | POKE J W 154 | BOXPRNT3: 155 | GOSUB LOADVAR 156 | RETURN 157 | 158 | BOXPOFFS: 159 | CURSPOS J V 160 | V = V - 11 + 64146 161 | POKE J V 162 | Y = 1 163 | RETURN 164 | 165 | BOXOPT: 166 | PEEK V X 167 | X = X + 1 168 | IF V = '1' THEN X = & $1 169 | IF V = '2' THEN X = & $2 170 | IF V = '3' THEN X = & $3 171 | IF V = '4' THEN X = & $4 172 | IF V = '5' THEN X = & $5 173 | IF V = '7' THEN X = & $7 174 | IF V = 't' THEN GOTO BOXTAB 175 | GOTO BOXPRNT2 176 | 177 | BOXTAB: 178 | CURSPOS J V 179 | J = J / 8 + 1 * 8 180 | MOVE J V 181 | W = 58 - J 182 | V = 1 183 | GOTO BOXPRNT2 184 | 185 | BOXNEWLN: 186 | CURSPOS J V 187 | J = J - 22 188 | W = V - 11 + 64151 189 | POKE J W 190 | J = 22 191 | V = V + 1 192 | MOVE J V 193 | W = 36 194 | IF V > 15 THEN GOTO BOXLIMIT 195 | Y = 0 196 | GOTO BOXPRNT2 197 | 198 | BOXLIMIT: 199 | V = 0 200 | GOTO BOXPRNT2 201 | 202 | BORDER: 203 | GOSUB SAVEVAR 204 | GOSUB SAVELOC 205 | INK Z 206 | FOR Y = 0 TO 24 207 | IF Y = 0 THEN PEEK V 64160 208 | ELSE IF Y = 2 THEN PEEK V 64162 209 | ELSE IF Y = 24 THEN PEEK V 64164 210 | ELSE PEEK V 64166 211 | MOVE 0 Y 212 | PRINT CHR V ; 213 | IF Y = 0 THEN PEEK V 64161 214 | ELSE IF Y = 2 THEN PEEK V 64163 215 | ELSE IF Y = 24 THEN PEEK V 64165 216 | ELSE PEEK V 64166 217 | MOVE 79 Y 218 | PRINT CHR V ; 219 | NEXT Y 220 | PEEK V 64167 221 | FOR X = 1 TO 78 222 | MOVE X 0 223 | PRINT CHR V ; 224 | MOVE X 2 225 | PRINT CHR V ; 226 | MOVE X 24 227 | PRINT CHR V ; 228 | NEXT X 229 | GOSUB LOADLOC 230 | GOSUB LOADVAR 231 | RETURN 232 | 233 | BORDERDATA: 234 | 218 191 195 180 192 217 179 196 235 | 236 | BOX: 237 | INK T 238 | FOR Y = 8 TO 17 239 | IF Y = 8 THEN PEEK V 65400 240 | ELSE IF Y = 10 THEN PEEK V 65402 241 | ELSE IF Y = 17 THEN PEEK V 65404 242 | ELSE PEEK V 65406 243 | MOVE 20 Y 244 | PRINT CHR V ; 245 | IF Y = 8 THEN PEEK V 65401 246 | ELSE IF Y = 10 THEN PEEK V 65403 247 | ELSE IF Y = 17 THEN PEEK V 65405 248 | ELSE PEEK V 65406 249 | MOVE 59 Y 250 | PRINT CHR V ; 251 | NEXT Y 252 | PEEK V 65407 253 | FOR X = 21 TO 58 254 | MOVE X 8 255 | PRINT CHR V ; 256 | MOVE X 10 257 | PRINT CHR V ; 258 | MOVE X 17 259 | PRINT CHR V ; 260 | NEXT X 261 | INK C 262 | move 21 9 263 | print " " 264 | for x = 11 to 16 265 | move 21 x 266 | print " " 267 | next x 268 | RETURN 269 | 270 | BOXDATA: 271 | 201 187 204 185 200 188 186 205 272 | 273 | BOXSAVE: 274 | INK 0 275 | V = 64200 276 | j = 64600 277 | for y = 8 to 17 278 | move 20 y 279 | for x = 20 to 59 280 | curschar w 281 | poke w j 282 | CURSCOL W 283 | POKE W V 284 | print " "; 285 | j = j + 1 286 | V = V + 1 287 | next x 288 | next y 289 | return 290 | 291 | BOXREST: 292 | V = 64200 293 | j = 64600 294 | for y = 8 to 17 295 | MOVE 20 Y 296 | for x = 20 to 59 297 | PEEK W V 298 | INK W 299 | peek w j 300 | print chr w ; 301 | j = j + 1 302 | V = V + 1 303 | next x 304 | next y 305 | return 306 | 307 | CLOSEBOX: 308 | POKE V 65418 309 | CURSOR OFF 310 | INK 7 311 | H = H / 16 312 | GOSUB BOXREST 313 | GOSUB LOADLOC 314 | GOSUB LOADVAR 315 | PEEK V 65418 316 | RETURN 317 | 318 | CONTENT: 319 | RETURN 320 | 321 | cserial: 322 | gosub savevar 323 | v = 0 324 | serial rec x 325 | if x = 4 then v = 1 326 | if x = 5 then v = 2 327 | if v > 0 then goto cserialc 328 | serial send 5 329 | serial rec x 330 | if x > 31 then x = 5 331 | if x = 6 then x = 3 332 | if x = 0 then v = 6 333 | if v > 0 then goto cserialc 334 | v = 4 335 | cserialc: 336 | poke v 65418 337 | gosub loadvar 338 | peek v 65418 339 | return 340 | 341 | DINBOX: 342 | $8 = "INPBOX: Invalid input type." 343 | IF V > 1 THEN GOTO ERRBOX 344 | IF V < 0 THEN GOTO ERRBOX 345 | GOSUB OPENBOX 346 | if $6 = "" then goto dinboxnf 347 | move 22 11 348 | print $6 349 | move 22 12 350 | print ">" 351 | move 23 12 352 | cursor on 353 | if v = 0 then input a 354 | if v = 1 then input $6 355 | if v = 2 then input a 356 | if v = 3 then input $6 357 | dinboxnf: 358 | if $7 = "" then goto dinboxns 359 | move 22 13 360 | print $7 361 | move 22 14 362 | print ">" 363 | move 23 14 364 | if v = 0 then input b 365 | if v = 1 then input $7 366 | if v = 2 then input $7 367 | if v = 3 then input b 368 | dinboxns: 369 | GOSUB CLOSEBOX 370 | return 371 | 372 | ENDPROG: 373 | cls 374 | cursor on 375 | FOR X = 64000 TO 65535 376 | POKE 0 X 377 | NEXT X 378 | end 379 | 380 | ERRBOX: 381 | $5 = "Error" 382 | gosub openbox 383 | pokeint v 65418 384 | len $8 v 385 | if v > 38 then $8 = "Error text too long!" 386 | if v > 38 then goto fatalerr 387 | peekint v 65418 388 | move 22 12 389 | print $8 390 | move 22 14 391 | print "Press escape to end program." 392 | move 22 15 393 | print "Press any other key to continue." 394 | cursor on 395 | move 53 15 396 | waitkey j 397 | if j = 27 then gosub endprog 398 | gosub closebox 399 | return 400 | 401 | FATALERR: 402 | MOVE 2 1 403 | INK 12 404 | PRINT "Fatal: " ; 405 | PRINT $8 ; 406 | WAITKEY K 407 | GOSUB ENDPROG 408 | 409 | INPBOX: 410 | GOSUB OPENBOX 411 | $8 = "INPBOX: Invalid input type." 412 | MOVE 21 11 413 | GOSUB BOXPRINT 414 | MOVE 21 15 415 | PRINT "> " ; 416 | cursor on 417 | IF V = 0 THEN INPUT V 418 | ELSE IF V = 1 THEN INPUT $6 419 | ELSE GOTO ERRBOX 420 | GOSUB CLOSEBOX 421 | return 422 | 423 | LOADLOC: 424 | POKEINT X 64156 425 | POKEINT Y 64158 426 | PEEK X 65428 427 | PEEK Y 65429 428 | MOVE X Y 429 | PEEK X 65438 430 | INK X 431 | PEEKINT X 64156 432 | PEEKINT Y 64158 433 | RETURN 434 | 435 | LOADVAR: 436 | POKEINT J 65426 437 | PEEK J 65421 438 | IF J = 0 THEN $8 = "Can't load variables, none stored!" 439 | IF J = 0 THEN GOSUB FATALERR 440 | J = J + 65198 441 | PEEKINT Y J 442 | J = J - 2 443 | PEEKINT X J 444 | J = J - 2 445 | PEEKINT V J 446 | J = J - 2 447 | PEEKINT W J 448 | J = J - 65202 449 | POKE J 65421 450 | J = J + 65200 451 | PEEKINT J J 452 | RETURN 453 | 454 | MENUBOX: 455 | GOSUB OPENBOX 456 | V = 11 457 | GOSUB MENUDRAW 458 | MOVE 22 16 459 | INK C 460 | PRINT "Press enter to select an option." 461 | 462 | DO 463 | WAITKEY W 464 | IF W = 1 AND V > 11 THEN GOSUB MENUBUP 465 | IF W = 2 AND V < 15 THEN GOSUB MENUBDWN 466 | IF W = 27 THEN V = 16 467 | IF W = 13 THEN W = 27 468 | LOOP UNTIL W = 27 469 | GOTO MENUEND 470 | 471 | MENUBUP: 472 | V = V - 1 473 | GOSUB MENUDRAW 474 | RETURN 475 | 476 | MENUBDWN: 477 | V = V + 1 478 | GOSUB MENUDRAW 479 | RETURN 480 | 481 | MENUDRAW: 482 | INK C 483 | MOVE 22 11 484 | GOSUB BOXPRINT 485 | INK H 486 | X = V - 11 + 64146 487 | PEEK J X 488 | X = V - 11 + 64151 489 | PEEK Y X 490 | Y = Y + J - 1 491 | MOVE 22 V 492 | FOR X = J TO Y 493 | CURSCHAR J 494 | PRINT CHR J ; 495 | NEXT X 496 | RETURN 497 | 498 | MENUEND: 499 | W = V 500 | V = V - 10 501 | GOSUB CLOSEBOX 502 | RETURN 503 | 504 | MESBOX: 505 | GOSUB OPENBOX 506 | move 22 11 507 | gosub boxprint 508 | move 22 16 509 | print "Press any key to continue..." 510 | waitkey j 511 | GOSUB CLOSEBOX 512 | return 513 | 514 | NUMBOX: 515 | GOSUB OPENBOX 516 | if $6 = "" then goto numboxa 517 | move 22 11 518 | print $6 519 | move 22 12 520 | print a 521 | numboxa: 522 | if $7 = "" then goto numboxb 523 | move 22 13 524 | print $7 525 | move 22 14 526 | print b 527 | numboxb: 528 | move 22 16 529 | print "Press any key to continue..." 530 | waitkey j 531 | GOSUB CLOSEBOX 532 | return 533 | 534 | OPENBOX: 535 | GOSUB SAVEVAR 536 | GOSUB SAVELOC 537 | POKEINT V 65418 538 | GOSUB BOXSAVE 539 | IF C < 0 THEN C = 7 540 | IF C > 15 THEN C = 7 541 | H = H * 16 542 | H = H + C 543 | CURSOR OFF 544 | INK C 545 | MOVE 22 9 546 | PRINT $5 547 | GOSUB BOX 548 | MOVE 22 9 549 | PRINT $5 550 | PEEKINT V 65418 551 | RETURN 552 | 553 | pictotxt: 554 | GOSUB SAVEVAR 555 | for x = 0 to 19 556 | for y = 0 to 76 557 | peek w v 558 | if w = 0 then w = 32 559 | poke w v 560 | v = v + 1 561 | next y 562 | poke 10 v 563 | v = v + 1 564 | poke 1 v 565 | v = v + 1 566 | poke 1 v 567 | v = v + 1 568 | next x 569 | GOSUB LOADVAR 570 | return 571 | 572 | REFRESH: 573 | GOSUB SAVEVAR 574 | cls 575 | gosub border 576 | gosub title 577 | GOSUB LOADVAR 578 | gosub content 579 | return 580 | 581 | rserial: 582 | gosub savevar 583 | do 584 | serial rec w 585 | if w = 5 then serial send 6 586 | loop until w = 4 587 | serial send 6 588 | do 589 | serial rec w 590 | if w > 32 then w = 0 591 | loop until w > 0 592 | if w = 20 then goto rserialc 593 | gosub loadvar 594 | $8 = "Serial: Invalid protocol!" 595 | goto errbox 596 | rserialc: 597 | serial rec w 598 | poke w 65418 599 | v = w + x 600 | v = v - 1 601 | for w = x to v 602 | serial rec j 603 | poke j w 604 | next w 605 | gosub loadvar 606 | peek v 65418 607 | return 608 | 609 | SAVELOC: 610 | POKEINT X 64156 611 | POKEINT Y 64158 612 | CURSPOS X Y 613 | POKE X 65428 614 | POKE Y 65429 615 | X = INK 616 | POKE X 65438 617 | PEEKINT X 64156 618 | PEEKINT Y 64158 619 | RETURN 620 | 621 | SAVEVAR: 622 | POKEINT Y 65426 623 | PEEK Y 65421 624 | IF Y > 198 THEN $8 = "Variable storage area full!" 625 | IF Y > 198 THEN GOSUB FATALERR 626 | Y = Y + 65200 627 | POKEINT J Y 628 | Y = Y + 2 629 | POKEINT W Y 630 | Y = Y + 2 631 | POKEINT V Y 632 | Y = Y + 2 633 | POKEINT X Y 634 | Y = Y + 2 635 | Y = Y - 65200 636 | POKE Y 65421 637 | PEEKINT Y 65426 638 | POKEINT X 65426 639 | PEEK X 65421 640 | X = X + 65200 641 | POKEINT Y X 642 | X = X + 2 643 | X = X - 65200 644 | POKE X 65421 645 | PEEKINT X 65426 646 | RETURN 647 | 648 | SETTITLE: 649 | GOSUB SAVEVAR 650 | GOSUB SAVELOC 651 | LEN $5 J 652 | IF J = 0 THEN RETURN 653 | IF J > 78 THEN RETURN 654 | POKE Z 65439 655 | INK Z 656 | MOVE 1 1 657 | PRINT " " ; 658 | PRINT $5 ; 659 | FOR X = J TO 76 660 | PRINT " " ; 661 | NEXT X 662 | Y = & $5 663 | J = J + 65441 664 | FOR X = 65440 TO J 665 | PEEK W Y 666 | POKE W X 667 | Y = Y + 1 668 | NEXT X 669 | FOR X = X TO 65514 670 | POKE 0 X 671 | NEXT X 672 | GOSUB LOADLOC 673 | GOSUB LOADVAR 674 | RETURN 675 | 676 | sserial: 677 | if v > 255 then $8 = "Serial: Packet size too big!" 678 | if v > 255 then goto errbox 679 | gosub savevar 680 | do 681 | serial send 4 682 | serial rec w 683 | if w > 32 then w = 0 684 | loop until w = 6 685 | serial send 20 686 | serial send v 687 | v = v + x 688 | v = v - 1 689 | for w = x to v 690 | peek j w 691 | serial send j 692 | next w 693 | gosub loadvar 694 | return 695 | 696 | STARTPRG: 697 | FOR X = 64000 TO 65535 698 | POKE 0 X 699 | NEXT X 700 | GOSUB SAVEVAR 701 | Y = 64168 702 | J = 64160 703 | V = 65400 704 | FOR X = 1 TO 32 705 | READ XMEMASM X W 706 | POKE W Y 707 | Y = Y + 1 708 | NEXT X 709 | FOR X = 1 TO 8 710 | READ BORDERDATA X W 711 | POKE W J 712 | J = J + 1 713 | READ BOXDATA X W 714 | POKE W V 715 | V = V + 1 716 | NEXT X 717 | V = 12288 718 | GOSUB XMEM 719 | POKE 7 65439 720 | X = 65400 721 | C = 7 722 | H = 14 723 | T = 7 724 | Z = 7 725 | INK 7 726 | GOSUB LOADVAR 727 | RETURN 728 | 729 | TITLE: 730 | GOSUB SAVEVAR 731 | GOSUB SAVELOC 732 | PEEK J 65439 733 | INK J 734 | MOVE 2 1 735 | X = 65440 736 | DO 737 | PEEK J X 738 | IF J < 32 AND J > 0 THEN J = 32 739 | PRINT CHR J ; 740 | X = X + 1 741 | LOOP UNTIL J = 0 742 | CURSPOS X Y 743 | FOR X = X TO 78 744 | PRINT " " ; 745 | NEXT X 746 | GOSUB LOADLOC 747 | GOSUB LOADVAR 748 | RETURN 749 | 750 | XMEM: 751 | GOSUB SAVEVAR 752 | POKEINT V 65436 753 | GOSUB LOADVAR 754 | RETURN 755 | 756 | XMEMASM: 757 | 6 161 156 255 142 192 160 142 255 139 62 144 255 170 7 195 758 | 30 139 54 144 255 161 156 255 142 216 172 31 162 142 255 195 759 | 760 | XGET: 761 | POKEINT X 65424 762 | CALL 65184 763 | PEEK V 65422 764 | RETURN 765 | 766 | XPUT: 767 | POKEINT X 65424 768 | POKE V 65422 769 | CALL 65168 770 | RETURN 771 | -------------------------------------------------------------------------------- /programs/memedit.bas: -------------------------------------------------------------------------------- 1 | rem PathOS Memory Manipulator 2 | 3 | rem Requires the MB++ library, version 4.0.0 minimum 4 | include "mbpp.bas" 5 | 6 | parameters: 7 | if $1 = "" then goto init 8 | size $1 9 | if r = 1 then print "File does not exist." 10 | if r = 1 then end 11 | x = ramstart 12 | x = x / 16 13 | x = x + 1 14 | x = x * 16 15 | y = 65535 - x 16 | if s > y then print "File too big." 17 | if s > y then end 18 | load $1 x 19 | d = x 20 | f = x 21 | 22 | init: 23 | gosub startprg 24 | z = 9 25 | $5 = "Memory Manipulator" 26 | gosub settitle 27 | cls 28 | cursor off 29 | c = 7 30 | h = 9 31 | t = 1 32 | z = 1 33 | gosub refresh 34 | 35 | a = 5 36 | b = 4 37 | gosub update_screen 38 | gosub highlight_on 39 | 40 | x = ramstart 41 | y = progstart 42 | v = 0 - x 43 | x = x - y 44 | 45 | $5 = " About" 46 | $6 = "Memory Manipulator, version 3.2.0|" 47 | $6 = $6 + "Copyright (C) Joshua Beck 2015|" 48 | $6 = $6 + "Licenced under the GNU GPLv3|\7" 49 | $7 = "Program Memory: " + x + " bytes|" 50 | $7 = $7 + "Avaliable Memory: " + v + " bytes" 51 | gosub mesbox 52 | goto main 53 | 54 | main: 55 | do 56 | waitkey k 57 | if k = 1 then gosub go_up 58 | if k = 2 then gosub go_down 59 | if k = 3 then gosub go_left 60 | if k = 4 then gosub go_right 61 | if k = 13 then gosub new_value 62 | if k = 27 then gosub endprog 63 | if k > 96 and k < 123 then k = k - 32 64 | if k = 'G' then gosub go_location 65 | if k = 'L' then gosub load_file 66 | if k = 'O' then gosub save_file 67 | if k = 'Q' then gosub page_up 68 | if k = 'Z' then gosub page_down 69 | loop endless 70 | 71 | go_up: 72 | if b = 4 then goto scroll_up 73 | gosub highlight_off 74 | b = b - 1 75 | d = d - 16 76 | gosub highlight_on 77 | return 78 | 79 | go_down: 80 | if b = 19 then goto scroll_down 81 | gosub highlight_off 82 | b = b + 1 83 | d = d + 16 84 | gosub highlight_on 85 | return 86 | 87 | go_left: 88 | if a = 5 then goto back_line 89 | gosub highlight_off 90 | a = a - 3 91 | d = d - 1 92 | gosub highlight_on 93 | return 94 | 95 | go_right: 96 | if a = 50 then goto forward_line 97 | gosub highlight_off 98 | a = a + 3 99 | d = d + 1 100 | gosub highlight_on 101 | return 102 | 103 | scroll_up: 104 | gosub highlight_off 105 | f = f - 16 106 | d = d - 16 107 | gosub update_screen 108 | gosub highlight_on 109 | return 110 | 111 | scroll_down: 112 | gosub highlight_off 113 | f = f + 16 114 | d = d + 16 115 | gosub update_screen 116 | gosub highlight_on 117 | return 118 | 119 | back_line: 120 | if b = 4 then goto sback_line 121 | gosub highlight_off 122 | b = b - 1 123 | a = 50 124 | d = d - 1 125 | gosub highlight_on 126 | return 127 | 128 | forward_line: 129 | if b = 19 then goto sforward_line 130 | gosub highlight_off 131 | b = b + 1 132 | a = 5 133 | d = d + 1 134 | gosub highlight_on 135 | return 136 | 137 | sback_line: 138 | gosub highlight_off 139 | a = 50 140 | f = f - 16 141 | d = d - 1 142 | gosub update_screen 143 | gosub highlight_on 144 | return 145 | 146 | sforward_line: 147 | gosub highlight_off 148 | a = 5 149 | f = f + 16 150 | d = d + 1 151 | gosub update_screen 152 | gosub highlight_on 153 | return 154 | 155 | page_up: 156 | gosub highlight_off 157 | f = f - 256 158 | d = d - 256 159 | gosub update_screen 160 | gosub highlight_on 161 | return 162 | 163 | page_down: 164 | gosub highlight_off 165 | f = f + 256 166 | d = d + 256 167 | gosub update_screen 168 | gosub highlight_on 169 | return 170 | 171 | go_location: 172 | t = 2 173 | $5 = "Goto - Location" 174 | $6 = "Enter a hexdecimal memory address to|go to between 0000 and FFFF." 175 | v = 1 176 | gosub inpbox 177 | $4 = $6 178 | 179 | if $4 = "" then return 180 | gosub highlight_off 181 | gosub hexstr_to_num 182 | w = d - f 183 | d = v 184 | v = v - w 185 | f = v 186 | gosub update_screen 187 | gosub highlight_on 188 | return 189 | 190 | new_value: 191 | gosub highlight_off 192 | move a b 193 | print " " 194 | move a b 195 | w = a - 5 / 3 + 59 196 | move w b 197 | print " " 198 | move a b 199 | v = 0 200 | cursor on 201 | 202 | do 203 | waitkey k 204 | if k = 27 then goto bad_number 205 | v = 16 206 | if k > 47 and k < 58 then v = k - 48 207 | if k > 64 and k < 71 then v = k - 55 208 | if k > 96 and k < 103 then v = k - 87 209 | loop until v < 16 210 | print chr k ; 211 | v = v * 16 212 | 213 | do 214 | waitkey k 215 | if k = 27 then goto bad_number 216 | j = 16 217 | if k > 47 and k < 58 then j = k - 48 218 | if k > 64 and k < 71 then j = k - 55 219 | if k > 96 and k < 103 then j = k - 87 220 | if j < 16 then print chr k ; 221 | loop until j < 16 222 | v = v + j 223 | 224 | poke v d 225 | cursor off 226 | gosub update_screen 227 | gosub highlight_on 228 | return 229 | 230 | bad_number: 231 | loop until k = 27 232 | getkey k 233 | cursor off 234 | gosub update_screen 235 | gosub highlight_on 236 | return 237 | 238 | load_file: 239 | t = 14 240 | $5 = "Load" 241 | $6 = "Enter a filename to load at the|selected location (blank to cancel)" 242 | v = 1 243 | gosub inpbox 244 | $4 = $6 245 | if $4 = "" then return 246 | 247 | load $4 d 248 | if r = 1 then $8 = "File does not exist!" 249 | if r = 1 then goto errbox 250 | 251 | gosub highlight_off 252 | gosub update_screen 253 | gosub highlight_on 254 | return 255 | 256 | save_file: 257 | t = 13 258 | $5 = "Save" 259 | $6 = "What filename do you want to use?" 260 | $7 = "How many bytes to save (hex)?" 261 | v = 1 262 | gosub dinbox 263 | 264 | if $7 = "" then return 265 | $4 = $7 266 | gosub hexstr_to_num 267 | delete $6 268 | save $6 d v 269 | 270 | if r = 1 then $8 = "Read-only disk!" 271 | if r = 1 then goto errbox 272 | return 273 | 274 | update_screen: 275 | ink 7 276 | w = f 277 | for y = 4 to 19 278 | move 5 y 279 | for x = 1 to 16 280 | peek v w 281 | w = w + 1 282 | print hex v ; 283 | print " " ; 284 | next x 285 | next y 286 | 287 | w = f 288 | for y = 4 to 19 289 | move 59 y 290 | for x = 1 to 16 291 | peek v w 292 | print chr v ; 293 | w = w + 1 294 | next x 295 | next y 296 | return 297 | 298 | highlight_on: 299 | move a b 300 | ink 232 301 | curschar v 302 | print chr v ; 303 | curschar v 304 | print chr v ; 305 | w = a - 5 / 3 + 59 306 | move w b 307 | curschar v 308 | print chr v 309 | 310 | ink 9 311 | move 74 1 312 | v = d / 256 313 | print hex v ; 314 | v = d % 256 315 | print hex v ; 316 | move 74 1 317 | for x = 1 to 4 318 | curschar v 319 | print chr v ; 320 | next x 321 | return 322 | 323 | highlight_off: 324 | move a b 325 | ink 7 326 | curschar v 327 | print chr v ; 328 | curschar v 329 | print chr v ; 330 | w = a - 5 / 3 + 59 331 | move w b 332 | curschar v 333 | print chr v 334 | return 335 | 336 | hexstr_to_num: 337 | w = & $4 338 | v = 0 339 | do 340 | peek j w 341 | gosub digit_convert 342 | if j < 16 then v = v * 16 343 | if j < 16 then v = v + j 344 | w = w + 1 345 | loop until j = 16 346 | return 347 | 348 | digit_convert: 349 | if j < 16 then j = 16 350 | if j > 47 and j < 58 then j = j - 48 351 | if j > 64 and j < 71 then j = j - 55 352 | if j > 96 and j < 103 then j = j - 87 353 | if j > 15 then j = 16 354 | return 355 | 356 | content: 357 | gosub savevar 358 | move 59 1 359 | ink 9 360 | print "Selected Byte: 0000" 361 | ink 3 362 | move 5 3 363 | print "0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF" 364 | move 5 20 365 | print "0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF" 366 | for y = 0 to 15 367 | v = y * 16 368 | w = y + 4 369 | move 2 w 370 | print hex v 371 | move 76 w 372 | print hex v 373 | move 2 w 374 | curschar v 375 | print chr v ; 376 | curschar v 377 | print chr v ; 378 | move 76 w 379 | curschar v 380 | print chr v ; 381 | curschar v 382 | print chr v ; 383 | next y 384 | ink 1 385 | move 0 21 386 | print chr 195 ; 387 | for x = 1 to 78 388 | print chr 196 ; 389 | next x 390 | print chr 180 ; 391 | ink 3 392 | move 2 22 393 | print "Use the arrow keys to move around, G for GOTO, Enter to change a value," 394 | move 2 23 395 | print "Q for page up, Z for page down, O to Save and L to load files into memory." 396 | return 397 | 398 | 399 | -------------------------------------------------------------------------------- /programs/mikedev.inc: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Include file for PathOS program development (MikeOS API version 17) 3 | ; ------------------------------------------------------------------ 4 | 5 | ; ------------------------------------------------------------------ 6 | ; IMPORTANT LOCATIONS 7 | 8 | os_main equ 0000h ; Where the OS code starts 9 | 10 | 11 | ; ------------------------------------------------------------------ 12 | ; COLOURS (eg for os_draw_background and os_draw_block) 13 | 14 | %DEFINE BLACK_ON_WHITE 11110000b 15 | %DEFINE WHITE_ON_BLACK 00001111b 16 | %DEFINE WHITE_ON_LIGHT_RED 11001111b 17 | %DEFINE WHITE_ON_GREEN 00101111b 18 | %DEFINE RED_ON_LIGHT_GREEN 10100100b 19 | 20 | 21 | ; ------------------------------------------------------------------ 22 | ; KEYS 23 | 24 | %DEFINE KEY_UP 72 25 | %DEFINE KEY_DOWN 80 26 | %DEFINE KEY_LEFT 75 27 | %DEFINE KEY_RIGHT 77 28 | 29 | %DEFINE KEY_ESC 27 30 | %DEFINE KEY_ENTER 13 31 | 32 | 33 | ; ------------------------------------------------------------------ 34 | ; SYSTEM CALLS 35 | 36 | ; Screen control 37 | 38 | os_clear_screen equ 0009h ; (Nothing used) 39 | os_print_string equ 0003h ; SI = zero-terminated string location 40 | os_move_cursor equ 0006h ; DH, DL = row, column 41 | os_print_horiz_line equ 000Ch ; AX = 1 for double line, else single 42 | os_print_newline equ 000Fh ; (Nothing used) 43 | os_draw_background equ 002Ah ; AX, BX = strings, CX = colour 44 | os_draw_block equ 00B4h ; BL = colour, DH/DL/SI/DI = pos 45 | os_input_dialog equ 00A8h ; AX = input string, BX = msg string 46 | os_dialog_box equ 003Ch ; AX, BX, CX = strings, DX = type 47 | ; OUT: AX = 0 for OK, 1 for cancel 48 | ; (only multi choice for DX = 1) 49 | os_list_dialog equ 00ABh ; IN: AX = comma-separated list of 50 | ; option strings, BX, CX = help to 51 | ; display at top of list 52 | ; OUT: AX = number (starting from 1) 53 | ; of option selected, or carry if Esc 54 | os_file_selector equ 005Ah ; Returns filename in AX 55 | os_get_cursor_pos equ 0069h ; OUT: DH = row, DL = column 56 | os_print_space equ 006Ch ; (Nothing used) 57 | os_dump_string equ 006Fh ; SI = string location 58 | os_print_digit equ 0072h ; AX = digit to print 59 | os_print_1hex equ 0075h ; Display low nibble of AL in hex 60 | os_print_2hex equ 0078h ; Display AL in hex 61 | os_print_4hex equ 007Bh ; Display AX in hex 62 | os_show_cursor equ 008Ah ; (Nothing used) 63 | os_hide_cursor equ 008Dh ; (Nothing used) 64 | os_dump_registers equ 0090h ; Shows contents of AX, BX, CX, DX 65 | 66 | 67 | ; Keyboard handling 68 | 69 | os_wait_for_key equ 0012h ; Returns AL = key pressed 70 | os_check_for_key equ 0015h ; Returns AL = key pressed 71 | 72 | 73 | ; File handling 74 | 75 | os_get_file_list equ 0042h ; AX = string to store filenames 76 | os_load_file equ 0021h ; IN: AX = filename string location, 77 | ; CX = location to load file 78 | ; OUT: BX = file size in bytes, 79 | ; carry clear if OK, set if missing 80 | os_write_file equ 0096h ; AX = filename, BX = data location, 81 | ; CX = number of bytes to save 82 | os_file_exists equ 0099h ; AX = filename, carry clear if exists 83 | os_create_file equ 009Ch ; AX = filename 84 | os_remove_file equ 009Fh ; AX = filename 85 | os_rename_file equ 00A2h ; AX = filename, BX = new filename 86 | os_get_file_size equ 00A5h ; AX = filename, OUT: BX = bytes 87 | ; (64K max) 88 | 89 | 90 | ; Sound 91 | 92 | os_speaker_tone equ 001Bh ; AX = note frequency 93 | os_speaker_off equ 001Eh ; (Nothing used) 94 | 95 | 96 | ; String handling 97 | 98 | os_int_to_string equ 0018h ; AX = unsigned integer, out AX = string 99 | os_sint_to_string equ 00C0h ; AX = signed integer, out AX = string 100 | os_string_reverse equ 00AEh ; SI = string location 101 | os_string_length equ 002Dh ; AX = string loc, returns AX = length 102 | os_string_uppercase equ 0030h ; AX = zero-terminated string 103 | os_string_lowercase equ 0033h ; AX = zero-terminated string 104 | os_input_string equ 0036h ; AX = string location, BX = maximum characters 105 | os_string_copy equ 0039h ; SI = source, DI = dest strings 106 | os_string_join equ 003Fh ; AX, BX = source strings, CX = dest 107 | os_string_compare equ 0045h ; SI, DI = strings, carry set if same 108 | os_string_strincmp equ 0093h ; As above, but with CL = chars to check 109 | os_string_chomp equ 0048h ; AX = string location 110 | os_string_strip equ 004Bh ; SI = string, AX = char to remove 111 | os_string_truncate equ 004Eh ; SI = string, AX = number of chars 112 | os_set_time_fmt equ 0084h ; AL = format 113 | os_set_date_fmt equ 0087h ; AX = format 114 | os_get_time_string equ 0054h ; BX = string location for eg '20:41' 115 | os_get_date_string equ 005Dh ; BX = string loc for eg '12/31/2007' 116 | os_find_char_in_string equ 0066h ; IN: SI = string, AL = char to find 117 | os_long_int_to_string equ 007Eh ; DX:AX = num, BX = base, DI = string 118 | os_string_to_int equ 00B1h ; SI = string (up to 65535), AX = int 119 | os_string_charchange equ 00BAh ; SI = string, AL = old char, BL = new 120 | os_string_parse equ 00C3h ; SI = string; output: AX/BX/CX/DX = 121 | ; substrings (or 0 if not present) 122 | os_string_tokenize equ 00CFh ; SI = string, AL = sep char; returns 123 | ; DI = next token 124 | 125 | 126 | ; Math routines 127 | 128 | os_get_random equ 00B7h ; IN: AX, BX = low, high; OUT: CX = num 129 | os_bcd_to_int equ 0051h ; AL = BCD number, returns AX = integer 130 | os_long_int_negate equ 0081h ; DX:AX = number 131 | 132 | 133 | ; Ports 134 | 135 | os_port_byte_out equ 00C9h ; IN: DX = port, AL = byte 136 | os_port_byte_in equ 00CCh ; IN: DX = port; OUT: AL = byte 137 | os_serial_port_enable equ 00BDh ; AX = 0 for 9600 baud, 1 for 1200 138 | os_send_via_serial equ 0060h ; AL = byte to send 139 | os_get_via_serial equ 0063h ; Returns AL = byte received 140 | ; OUT: AX = location, or 0 if not found 141 | 142 | 143 | ; Misc OS functions 144 | 145 | os_run_basic equ 00C6h ; AX = code location in RAM, BX = size, 146 | ; SI = parameter string (or 0 if none) 147 | os_get_api_version equ 0057h ; Returns API version in AL 148 | os_pause equ 0024h ; AX = 10ths of second to wait 149 | os_fatal_error equ 0027h ; AX = error string location 150 | 151 | 152 | ; ------------------------------------------------------------------ 153 | 154 | -------------------------------------------------------------------------------- /programs/monitor.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Machine code monitor -- by Yutaka Saito and Mike Saunders 3 | ; 4 | ; Accepts code in hex format, ORGed to 36864 (4K after where 5 | ; this program is loaded) 6 | ; ------------------------------------------------------------------ 7 | 8 | 9 | BITS 16 10 | %INCLUDE "mikedev.inc" 11 | ORG 32768 12 | 13 | 14 | ; This line determines where the machine code will 15 | ; be generated -- if you change it, you will need to 16 | ; ORG the code you enter at the new address 17 | 18 | CODELOC equ 36864 19 | 20 | 21 | mov si, helpmsg1 ; Print help text 22 | call os_print_string 23 | 24 | mov si, helpmsg2 25 | call os_print_string 26 | 27 | mov si, helpmsg3 28 | call os_print_string 29 | 30 | main_loop: 31 | mov si, helpmsg4 32 | call os_print_string 33 | 34 | .noinput: 35 | call os_print_newline 36 | 37 | mov si, prompt ; Print prompt 38 | call os_print_string 39 | 40 | mov ax, input ; Get hex string 41 | mov bx, 255 42 | call os_input_string 43 | 44 | mov ax, input 45 | call os_string_length 46 | cmp ax, 0 47 | je .noinput 48 | 49 | mov si, input ; Convert to machine code... 50 | mov di, run 51 | 52 | 53 | .more: 54 | cmp byte [si], '$' ; If char in string is '$', end of code 55 | je .done 56 | cmp byte [si], ' ' ; If space, move on to next char 57 | je .space 58 | cmp byte [si], 'r' ; If 'r' entered, re-run existing code 59 | je .runprog 60 | cmp byte [si], 'x' ; Or if 'x' entered, return to OS 61 | jne .noexit 62 | call os_print_newline 63 | ret 64 | .noexit: 65 | mov al, [si] 66 | and al, 0F0h 67 | cmp al, 40h 68 | je .H_A_to_F 69 | .H_1_to_9: 70 | mov al, [si] 71 | sub al, 30h 72 | mov ah, al 73 | sal ah, 4 74 | jmp .H_end 75 | .H_A_to_F: 76 | mov al, [si] 77 | sub al, 37h 78 | mov ah, al 79 | sal ah, 4 80 | .H_end: 81 | inc si 82 | mov al, [si] 83 | and al, 0F0h 84 | cmp al, 40h 85 | je .L_A_to_F 86 | .L_1_to_9: 87 | mov al, [si] 88 | sub al, 30h 89 | jmp .L_end 90 | .L_A_to_F: 91 | mov al, [si] 92 | sub al, 37h 93 | .L_end: 94 | or al, ah 95 | mov [di], al 96 | inc di 97 | .space: 98 | inc si 99 | jmp .more 100 | .done: 101 | mov byte [di], 0 ; Write terminating zero 102 | 103 | mov si, run ; Copy machine code to location for execution 104 | mov di, CODELOC 105 | mov cx, 255 106 | cld 107 | rep movsb 108 | 109 | 110 | .runprog: 111 | call os_print_newline 112 | 113 | call CODELOC ; Run program 114 | 115 | call os_print_newline 116 | 117 | jmp main_loop 118 | 119 | 120 | input times 255 db 0 ; Code entered by user (in ASCII) 121 | run times 255 db 0 ; Translated machine code to execute 122 | 123 | helpmsg1 db 'MIKEOS MACHINE CODE MONITOR', 10, 13, 0 124 | helpmsg2 db '(See the User Handbook for a quick guide)', 13, 10, 13, 10, 0 125 | helpmsg3 db 'Enter instructions in hex, terminated by $ character', 10, 13, 0 126 | helpmsg4 db 'Commands: r = re-run previous code, x = exit', 10, 13, 0 127 | 128 | prompt db '= ', 0 129 | 130 | 131 | ; ------------------------------------------------------------------ 132 | 133 | -------------------------------------------------------------------------------- /programs/monitor.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/programs/monitor.bin -------------------------------------------------------------------------------- /programs/pos-vim.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Program to edit text and C files 3 | ; ------------------------------------------------------------------ 4 | 5 | 6 | BITS 16 7 | %INCLUDE "mikedev.inc" 8 | %INCLUDE "clib.h" 9 | ORG 32768 10 | 11 | 12 | main_start: 13 | call draw_background 14 | 15 | call os_file_selector ; Get filename 16 | 17 | jc near close ; Quit if Esc pressed in dialog box 18 | 19 | mov bx, ax ; Save filename for now 20 | 21 | mov di, ax 22 | 23 | call os_string_length 24 | add di, ax ; DI now points to last char in filename 25 | 26 | dec di 27 | dec di 28 | dec di ; ...and now to first char of extension! 29 | 30 | mov si, txt_extension 31 | mov cx, 3 32 | rep cmpsb ; Does the extension contain 'TXT'? 33 | je near valid_txt_extension ; Skip ahead if so 34 | 35 | dec di 36 | 37 | mov si, c_extension 38 | mov cx, 1 39 | rep cmpsb ; Does the extension contain 'C' 40 | je valid_c_extension ; Skip ahead if so 41 | 42 | ; Otherwise show error dialog 43 | mov dx, 0 ; One button for dialog box 44 | mov ax, err_string 45 | mov bx, 0 46 | mov cx, 0 47 | call os_dialog_box 48 | 49 | jmp main_start ; And retry 50 | 51 | 52 | ecode: 53 | mov cx, 1 54 | lodsb 55 | cmp al, 192 ; Single pixel or string? 56 | jb single 57 | and al, 63 ; String, so 'mod 64' it 58 | mov cl, al ; Result in CL for following 'rep' 59 | lodsb ; Get byte to put on screen 60 | single: 61 | rep stosb ; And show it (or all of them) 62 | cmp di, 64001 63 | jb decode 64 | 65 | 66 | mov dx, 3c8h ; Palette index register 67 | mov al, 0 ; Start at colour 0 68 | out dx, al ; Tell VGA controller that... 69 | inc dx ; ...3c9h = palette data register 70 | 71 | mov cx, 768 ; 256 colours, 3 bytes each 72 | setpal: 73 | lodsb ; Grab the next byte. 74 | shr al, 2 ; Palettes divided by 4, so undo 75 | out dx, al ; Send to VGA controller 76 | loop setpal 77 | 78 | 79 | call os_wait_for_key 80 | 81 | mov ax, 3 ; Back to text mode 82 | mov bx, 0 83 | int 10h 84 | mov ax, 1003h ; No blinking text! 85 | int 10h 86 | 87 | mov ax, 2000h ; Reset ES back to original value 88 | mov es, ax 89 | call os_clear_screen 90 | jmp main_start 91 | 92 | 93 | draw_background: 94 | mov ax, title_msg ; Set up screen 95 | mov bx, footer_msg 96 | mov cx, BLACK_ON_WHITE 97 | call os_draw_background 98 | ret 99 | 100 | ; Meanwhile, if it's a text or C file... 101 | 102 | valid_c_extension: 103 | mov ax, bx 104 | mov cx, 36864 ; Load file 4K after program start 105 | call os_load_file 106 | 107 | 108 | ; Now BX contains the number of bytes in the file, so let's add 109 | ; the load offset to get the last byte of the file in RAM 110 | 111 | add bx, 36864 112 | 113 | 114 | mov cx, 0 ; Lines to skip when rendering 115 | mov word [skiplines], 0 116 | 117 | 118 | pusha 119 | mov ax, c_title_msg ; Set up screen 120 | mov bx, c_footer_msg 121 | mov cx, 00100000b ; Green text on white background 122 | call os_draw_background 123 | popa 124 | 125 | c_start: 126 | pusha 127 | 128 | mov bl, 00100000b ; Green text on white background 129 | mov dh, 2 130 | mov dl, 0 131 | mov si, 80 132 | mov di, 23 133 | call os_draw_block ; Overwrite old text for scrolling 134 | 135 | mov dh, 2 ; Move cursor to near top 136 | mov dl, 0 137 | call os_move_cursor 138 | 139 | popa 140 | 141 | mov si, 36864 ; Start of C data 142 | mov ah, 0Eh 143 | 144 | valid_txt_extension: 145 | mov ax, bx 146 | mov cx, 36864 ; Load file 4K after program start 147 | call os_load_file 148 | 149 | 150 | ; Now BX contains the number of bytes in the file, so let's add 151 | ; the load offset to get the last byte of the file in RAM 152 | 153 | add bx, 36864 154 | 155 | 156 | mov cx, 0 ; Lines to skip when rendering 157 | mov word [skiplines], 0 158 | 159 | 160 | pusha 161 | mov ax, txt_title_msg ; Set up screen 162 | mov bx, txt_footer_msg 163 | mov cx, 11110000b ; Black text on white background 164 | call os_draw_background 165 | popa 166 | 167 | 168 | 169 | txt_start: 170 | pusha 171 | 172 | mov bl, 11110000b ; Black text on white background 173 | mov dh, 2 174 | mov dl, 0 175 | mov si, 80 176 | mov di, 23 177 | call os_draw_block ; Overwrite old text for scrolling 178 | 179 | mov dh, 2 ; Move cursor to near top 180 | mov dl, 0 181 | call os_move_cursor 182 | 183 | popa 184 | 185 | 186 | mov si, 36864 ; Start of text data 187 | mov ah, 0Eh ; BIOS char printing routine 188 | 189 | 190 | redraw: 191 | cmp cx, 0 ; How many lines to skip? 192 | je loopy 193 | dec cx 194 | 195 | skip_loop: 196 | lodsb ; Read bytes until newline, to skip a line 197 | cmp al, 10 198 | jne skip_loop 199 | jmp redraw 200 | 201 | 202 | loopy: 203 | lodsb ; Get character from file data 204 | 205 | cmp al, 10 ; Return to start of line if carriage return character 206 | jne skip_return 207 | call os_get_cursor_pos 208 | mov dl, 0 209 | call os_move_cursor 210 | 211 | skip_return: 212 | int 10h ; Print the character 213 | 214 | cmp si, bx ; Have we printed all in the file? 215 | je finished 216 | 217 | call os_get_cursor_pos ; Are we at the bottom of the display area? 218 | cmp dh, 23 219 | je get_input 220 | 221 | jmp loopy 222 | 223 | 224 | get_input: ; Get arrow keys and Q 225 | call os_wait_for_key 226 | cmp ah, KEY_UP 227 | je go_up 228 | cmp ah, KEY_DOWN 229 | je go_down 230 | cmp al, 'q' 231 | je main_start 232 | cmp al, 'Q' 233 | je main_start 234 | jmp get_input 235 | 236 | 237 | go_up: 238 | cmp word [skiplines], 0 ; Don't scroll up if we're at the top 239 | jle txt_start 240 | dec word [skiplines] ; Otherwise decrement the lines we need to skip 241 | mov word cx, [skiplines] 242 | jmp txt_start 243 | 244 | go_down: 245 | inc word [skiplines] ; Increment the lines we need to skip 246 | mov word cx, [skiplines] 247 | jmp txt_start 248 | 249 | 250 | finished: ; We get here when we've printed the final character 251 | call os_wait_for_key 252 | cmp ah, 48h 253 | je go_up ; Can only scroll up at this point 254 | cmp al, 'q' 255 | je main_start 256 | cmp al, 'Q' 257 | je main_start 258 | jmp finished 259 | 260 | 261 | close: 262 | call os_clear_screen 263 | ret 264 | 265 | 266 | txt_extension db 'TXT', 0 267 | c_extension db 'C', 0 268 | 269 | err_string db 'SELECT TXT OR C', 0 270 | 271 | title_msg db 'PathOS File Viewer', 0 272 | footer_msg db 'Select a TXT or C file. Press Esc to exit', 0 273 | 274 | txt_title_msg db 'PathOS Text File Viewer', 0 275 | txt_footer_msg db 'Use arrow keys to scroll and Q to quit', 0 276 | 277 | c_title_msg db 'PathOS C Editor', 0 278 | c_footer_msg db 'Use arrow keys to scrill and Q to quit', 0 279 | 280 | skiplines dw 0 281 | 282 | 283 | ; ------------------------------------------------------------------ 284 | 285 | -------------------------------------------------------------------------------- /programs/pos-vim.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/programs/pos-vim.bin -------------------------------------------------------------------------------- /programs/serial.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Minicom-like program for MikeOS 3 | ; ------------------------------------------------------------------ 4 | 5 | 6 | ; With this program and an appropriate serial (null modem) cable, you 7 | ; can log in to Linux machines. You will need your Linux box to establish 8 | ; a serial terminal in /etc/inittab, with something like this: 9 | ; 10 | ; T0:2345:respawn:/sbin/getty/ -L ttyS0 9600 vt100 11 | ; 12 | ; Connect the serial cable to your MikeOS machine and Linux machine. 13 | ; Start MikeOS and run SERIAL.BIN, then start your Linux box with the 14 | ; above serial terminal entry. On the MikeOS machine, you will see a 15 | ; familiar Linux login prompt -- you're ready to go! Note that very few 16 | ; VT100 terminal features are implemented at present, so complicated 17 | ; programs (eg Emacs) will not display correctly. 18 | ; 19 | ; Press the F8 key to exit. 20 | 21 | 22 | BITS 16 23 | 24 | %INCLUDE "mikedev.inc" 25 | ORG 32768 26 | 27 | 28 | start: 29 | mov ax, warnmsg_1 30 | mov bx, warnmsg_2 31 | mov cx, 0 32 | mov dx, 1 33 | call os_dialog_box 34 | cmp ax, 0 35 | je .proceed 36 | 37 | call os_clear_screen 38 | ret 39 | 40 | 41 | .proceed: 42 | call os_clear_screen 43 | 44 | mov ax, 0 ; 9600 baud mode 45 | call os_serial_port_enable 46 | 47 | mov si, start_msg 48 | call os_print_string 49 | 50 | 51 | main_loop: 52 | mov dx, 0 ; Set port to COM1 53 | mov ax, 0 54 | mov ah, 03h ; Check COM1 status 55 | int 14h 56 | 57 | bt ax, 8 ; Data received? 58 | jc received_byte 59 | 60 | mov ax, 0 ; If not, have we something to send? 61 | call os_check_for_key 62 | 63 | cmp ax, 4200h ; F8 key pressed? 64 | je finish ; Quit if so 65 | 66 | cmp al, 0 ; If no other key pressed, go back 67 | je main_loop 68 | 69 | call os_send_via_serial ; Otherwise send it 70 | jmp main_loop 71 | 72 | received_byte: ; Print data received 73 | call os_get_via_serial 74 | 75 | cmp al, 1Bh ; 'Esc' character received? 76 | je esc_received 77 | 78 | mov ah, 0Eh ; Otherwise print char 79 | int 10h 80 | jmp main_loop 81 | 82 | finish: 83 | mov si, finish_msg 84 | call os_print_string 85 | 86 | call os_wait_for_key 87 | 88 | ret 89 | 90 | 91 | 92 | esc_received: 93 | call os_get_via_serial ; Get next character... 94 | cmp al, '[' ; Is it a screen control code? 95 | jne main_loop 96 | 97 | mov bl, al ; Store for now 98 | 99 | call os_get_via_serial ; If control code, parse it 100 | 101 | cmp al, 'H' 102 | je near move_to_home 103 | 104 | cmp al, 'J' 105 | je near erase_to_bottom 106 | 107 | cmp al, 'K' 108 | je near erase_to_end_of_line 109 | 110 | 111 | ; If it wasn't a control char that 112 | ; we can parse yet, print the whole 113 | ; thing for debugging purposes 114 | 115 | mov cl, al ; Store second char 116 | mov al, bl ; Get first 117 | 118 | mov ah, 0Eh ; Print them 119 | int 10h 120 | mov al, cl 121 | int 10h 122 | 123 | jmp main_loop 124 | 125 | 126 | 127 | move_to_home: 128 | mov dx, 0 129 | call os_move_cursor 130 | jmp main_loop 131 | 132 | 133 | erase_to_bottom: 134 | call os_get_cursor_pos 135 | 136 | push dx ; Store where we are 137 | 138 | call erase_sub 139 | 140 | inc dh ; Move to start of next line 141 | mov dl, 0 142 | call os_move_cursor 143 | 144 | mov ah, 0Ah ; Get ready to print 80 spaces 145 | mov al, ' ' 146 | mov bx, 0 147 | mov cx, 80 148 | .more: 149 | int 10h 150 | inc dh ; Next line... 151 | call os_move_cursor 152 | cmp dh, 25 ; Reached bottom of screen? 153 | jne .more 154 | 155 | pop dx ; Put cursor back to where we started 156 | call os_move_cursor 157 | 158 | jmp main_loop 159 | 160 | 161 | 162 | erase_to_end_of_line: 163 | call erase_sub 164 | jmp main_loop 165 | 166 | 167 | erase_sub: 168 | call os_get_cursor_pos 169 | 170 | push dx ; Store where we are 171 | 172 | mov ah, 80 ; Calculate how many spaces 173 | sub ah, dl ; we need to print... 174 | 175 | mov cx, 0 ; And drop into CL 176 | mov cl, ah 177 | 178 | mov ah, 0Ah ; Print spaces CL number of times 179 | mov al, ' ' 180 | mov bx, 0 181 | int 10h 182 | 183 | pop dx 184 | call os_move_cursor 185 | 186 | ret 187 | 188 | 189 | warnmsg_1 db 'Serial terminal program -- may lock up', 0 190 | warnmsg_2 db 'if you have no serial ports! Proceed?', 0 191 | 192 | start_msg db 'MikeOS minicom -- Press F8 to quit', 13, 10, 'Connecting via serial at 9600 baud...', 13, 10, 13, 10, 0 193 | finish_msg db 13, 10, 13, 10, 'Exiting MikeOS minicom; press a key to return to MikeOS', 13, 10, 0 194 | 195 | 196 | ; ------------------------------------------------------------------ 197 | 198 | -------------------------------------------------------------------------------- /programs/serial.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/programs/serial.bin -------------------------------------------------------------------------------- /programs/snake.bas: -------------------------------------------------------------------------------- 1 | rem ** Muncher for MikeOS ** 2 | rem Created by Justin Tokarchuk 3 | rem ------------------------------ 4 | 5 | rem VARS 6 | rem j = score multiplier 7 | rem x, y = coords 8 | rem e = body 9 | rem s = score 10 | rem i = multipliers 11 | rem n = wallpiece counter, gets reloaded by bonus engine 12 | 13 | goto logo 14 | %include 'mouse.lib' 15 | 16 | waitforenter: 17 | waitkey x 18 | if x = 13 then goto pregame 19 | if x = 27 then cursor on 20 | if x = 27 then END 21 | goto waitforenter 22 | 23 | logo: 24 | cls 25 | cursor off 26 | move 0 7 27 | print " ## ## ## ## ## ## ###### ## ## ######## ######## ###" 28 | print " ### ### ## ## ### ## ## ## ## ## ## ## ## ###" 29 | print " #### #### ## ## #### ## ## ## ## ## ## ## ###" 30 | print " ## ### ## ## ## ## ## ## ## ######### ###### ######## # " 31 | print " ## ## ## ## ## #### ## ## ## ## ## ## " 32 | print " ## ## ## ## ## ### ## ## ## ## ## ## ## ###" 33 | print " ## ## ####### ## ## ###### ## ## ######## ## ## ###" 34 | print "" 35 | print " ======================================================================" 36 | print "" 37 | print " Press ENTER to play, ESC to quit. " 38 | gosub changelook 39 | 40 | goto waitforenter 41 | 42 | changelook: 43 | for b = 0 to 24 44 | for a = 0 to 78 45 | move a b 46 | curschar c 47 | if c = '#' then c = 219 48 | if c = '=' then c = 220 49 | print chr c ; 50 | next a 51 | next b 52 | return 53 | 54 | pregame: 55 | cls 56 | n = 0 57 | 58 | cls 59 | cursor off 60 | gosub setwalls 61 | 62 | 63 | rem ** Place user in middle of screen. ** 64 | x = 40 65 | y = 12 66 | move x y 67 | 68 | rem ** dirs = up (1), down (2), left (3), right (4) 69 | rem ** start moving left 70 | 71 | d = 3 72 | 73 | rem ** score 74 | s = 0 75 | 76 | rem ** Body character. 77 | e = 35 78 | 79 | 80 | gosub addapple 81 | 82 | game: 83 | print chr e ; 84 | gosub printscore 85 | pause 1 86 | if d = 1 then pause 1 87 | if d = 2 then pause 1 88 | 89 | getkey k 90 | 91 | rem ** controls 92 | if k = 'w' then d = 1 93 | if k = 'W' then d = 1 94 | if k = 'a' then d = 3 95 | if k = 'A' then d = 3 96 | if k = 's' then d = 2 97 | if k = 'S' then d = 2 98 | if k = 'd' then d = 4 99 | if k = 'D' then d = 4 100 | 101 | 102 | rem if they press ESC exit game 103 | if k = 27 then goto finish 104 | 105 | if d = 1 then gosub moveupdown 106 | if d = 2 then gosub moveupdown 107 | if d = 3 then gosub moveleft 108 | if d = 4 then gosub moveright 109 | 110 | move x y 111 | 112 | curschar c 113 | rem ***did we collide with wall*** 114 | if x = 79 then goto finish 115 | if c = 'x' then goto finish 116 | if c = 178 then goto finish 117 | if c = e then goto finish 118 | if c = '@' then gosub getbonus 119 | goto game 120 | 121 | moveupdown: 122 | move x y 123 | print " " 124 | if d = 1 then y = y - 1 125 | if d = 2 then y = y + 1 126 | return 127 | 128 | 129 | moveleft: 130 | print " " ; 131 | move x y 132 | print " " 133 | x = x - 1 134 | return 135 | 136 | moveright: 137 | if x = q AND y = r then gosub getbonus 138 | move x y 139 | print " " 140 | x = x + 1 141 | return 142 | 143 | setwalls: 144 | a = 178 145 | 146 | move 0 0 147 | for x = 0 to 78 148 | print chr a ; 149 | next x 150 | 151 | move 0 23 152 | for x = 0 to 78 153 | print chr a ; 154 | next x 155 | 156 | for y = 0 to 23 157 | move 0 y 158 | print chr a ; 159 | next y 160 | 161 | for y = 0 to 23 162 | move 78 y 163 | print chr a ; 164 | next y 165 | 166 | return 167 | 168 | printscore: 169 | move 0 24 170 | print "Score: " ; 171 | print s ; 172 | move x y 173 | return 174 | 175 | addapple: 176 | rand q 1 77 177 | rand r 1 22 178 | g = 64 179 | if q = x then goto addapple 180 | if r = y then goto addapple 181 | move q r 182 | print chr g 183 | 184 | rem generate random number of wallpieces 185 | if s < 500 then rand g 1 2 186 | if s > 499 then rand g 2 5 187 | if s > 999 then rand g 5 10 188 | if s > 1999 then rand g 10 20 189 | morewallz: 190 | if s > 0 then gosub wallpiece 191 | g = g - 1 192 | if g > 0 then goto morewallz 193 | move x y 194 | return 195 | 196 | wallpiece: 197 | rem ** now add a wall piece ** 198 | rand l 1 77 199 | rand m 1 22 200 | rem Don't put it on a character or the apple please! 201 | if l = q then goto wallpiece 202 | if l = x then goto wallpiece 203 | if m = r then goto wallpiece 204 | if m = y then goto wallpiece 205 | 206 | rem is the wall piece too close to the character? 207 | if l > x then a = l - x 208 | if l < x then a = x - l 209 | if m > y then b = m - y 210 | if m < y then b = y - m 211 | if a < 7 then goto wallpiece 212 | if b < 4 then goto wallpiece 213 | move l m 214 | if c = 'x' then gosub wallpiece 215 | print "x" ; 216 | 217 | return 218 | 219 | getbonus: 220 | move x y 221 | g = 1 222 | print chr g 223 | pause 1 224 | move x y 225 | g = 2 226 | print chr g 227 | pause 1 228 | move x y 229 | g = 1 230 | print chr g 231 | pause 1 232 | move x y 233 | print " " 234 | rem *i = intermediate number for score bonus 235 | if s > 250 then j = 2 236 | if s > 1000 then j = 3 237 | if s > 3000 then j = 5 238 | if s > 5000 then j = 10 239 | gosub addapple 240 | j = 1 241 | i = 150 * j 242 | s = s + i 243 | return 244 | 245 | finish: 246 | 247 | cls 248 | cursor off 249 | move 0 2 250 | print " ###### ### ## ## ####### " 251 | print " ## ## ## ## ### ### ## " 252 | print " ## ## ## #### #### ## " 253 | print " ## #### ## ## ## ### ## ###### " 254 | print " ## ## ######### ## ## ## " 255 | print " ## ## ## ## ## ## ## " 256 | print " ###### ## ## ## ## ####### " 257 | print "" 258 | print " ####### ## ## ######## ######## " 259 | print " ## ## ## ## ## ## ## " 260 | print " ## ## ## ## ## ## ## " 261 | print " ## ## ## ## ###### ######## " 262 | print " ## ## ## ## ## ## ## " 263 | print " ## ## ## ## ## ## ## " 264 | print " ####### ### ######## ## ## " 265 | print "" 266 | print " Your Score Was: " ; 267 | print s 268 | print "" 269 | print " Play Again? (Y/N)" 270 | gosub changelook 271 | 272 | goto escloop 273 | 274 | escloop: 275 | waitkey x 276 | cursor on 277 | if x = 'n' then end 278 | if x = 'N' then end 279 | if x = 27 then end 280 | if x = 'y' then goto logo 281 | if x = 'Y' then goto logo 282 | goto escloop 283 | 284 | -------------------------------------------------------------------------------- /programs/test.c: -------------------------------------------------------------------------------- 1 | #include "clib.h" 2 | #include 3 | 4 | int main() { 5 | printf("Hello, PathOS\n"); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /src/boot/boot.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/src/boot/boot.bin -------------------------------------------------------------------------------- /src/boot/bootload.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; Based on a free boot loader by E Dehling. It scans the FAT12 3 | ; floppy for KERNEL.BIN (the MikeOS kernel), loads it and executes it. 4 | ; This must grow no larger than 512 bytes (one sector), with the final 5 | ; two bytes being the boot signature (AA55h). Note that in FAT12, 6 | ; a cluster is the same as a sector: 512 bytes. 7 | ; ================================================================== 8 | 9 | 10 | BITS 16 11 | 12 | jmp short bootloader_start ; Jump past disk description section 13 | nop ; Pad out before disk description 14 | 15 | 16 | ; ------------------------------------------------------------------ 17 | ; Disk description table, to make it a valid floppy 18 | ; Note: some of these values are hard-coded in the source! 19 | ; Values are those used by IBM for 1.44 MB, 3.5" diskette 20 | 21 | OEMLabel db "POSBOOT" ; Disk label 22 | BytesPerSector dw 512 ; Bytes per sector 23 | SectorsPerCluster db 1 ; Sectors per cluster 24 | ReservedForBoot dw 1 ; Reserved sectors for boot record 25 | NumberOfFats db 2 ; Number of copies of the FAT 26 | RootDirEntries dw 224 ; Number of entries in root dir 27 | ; (224 * 32 = 7168 = 14 sectors to read) 28 | LogicalSectors dw 2880 ; Number of logical sectors 29 | MediumByte db 0F0h ; Medium descriptor byte 30 | SectorsPerFat dw 9 ; Sectors per FAT 31 | SectorsPerTrack dw 18 ; Sectors per track (36/cylinder) 32 | Sides dw 2 ; Number of sides/heads 33 | HiddenSectors dd 0 ; Number of hidden sectors 34 | LargeSectors dd 0 ; Number of LBA sectors 35 | DriveNo dw 0 ; Drive No: 0 36 | Signature db 41 ; Drive signature: 41 for floppy 37 | VolumeID dd 00000000h ; Volume ID: any number 38 | VolumeLabel db "PATHOS "; Volume Label: any 11 chars 39 | FileSystem db "FAT12 " ; File system type: don't change! 40 | 41 | 42 | ; ------------------------------------------------------------------ 43 | ; Main bootloader code 44 | 45 | bootloader_start: 46 | mov ax, 07C0h ; Set up 4K of stack space above buffer 47 | add ax, 544 ; 8k buffer = 512 paragraphs + 32 paragraphs (loader) 48 | cli ; Disable interrupts while changing stack 49 | mov ss, ax 50 | mov sp, 4096 51 | sti ; Restore interrupts 52 | 53 | mov ax, 07C0h ; Set data segment to where we're loaded 54 | mov ds, ax 55 | 56 | ; NOTE: A few early BIOSes are reported to improperly set DL 57 | 58 | cmp dl, 0 59 | je no_change 60 | mov [bootdev], dl ; Save boot device number 61 | mov ah, 8 ; Get drive parameters 62 | int 13h 63 | jc fatal_disk_error 64 | and cx, 3Fh ; Maximum sector number 65 | mov [SectorsPerTrack], cx ; Sector numbers start at 1 66 | movzx dx, dh ; Maximum head number 67 | add dx, 1 ; Head numbers start at 0 - add 1 for total 68 | mov [Sides], dx 69 | 70 | no_change: 71 | mov eax, 0 ; Needed for some older BIOSes 72 | 73 | 74 | ; First, we need to load the root directory from the disk. Technical details: 75 | ; Start of root = ReservedForBoot + NumberOfFats * SectorsPerFat = logical 19 76 | ; Number of root = RootDirEntries * 32 bytes/entry / 512 bytes/sector = 14 77 | ; Start of user data = (start of root) + (number of root) = logical 33 78 | 79 | floppy_ok: ; Ready to read first block of data 80 | mov ax, 19 ; Root dir starts at logical sector 19 81 | call l2hts 82 | 83 | mov si, buffer ; Set ES:BX to point to our buffer (see end of code) 84 | mov bx, ds 85 | mov es, bx 86 | mov bx, si 87 | 88 | mov ah, 2 ; Params for int 13h: read floppy sectors 89 | mov al, 14 ; And read 14 of them 90 | 91 | pusha ; Prepare to enter loop 92 | 93 | 94 | read_root_dir: 95 | popa ; In case registers are altered by int 13h 96 | pusha 97 | 98 | stc ; A few BIOSes do not set properly on error 99 | int 13h ; Read sectors using BIOS 100 | 101 | jnc search_dir ; If read went OK, skip ahead 102 | call reset_floppy ; Otherwise, reset floppy controller and try again 103 | jnc read_root_dir ; Floppy reset OK? 104 | 105 | jmp reboot ; If not, fatal double error 106 | 107 | 108 | search_dir: 109 | popa 110 | 111 | mov ax, ds ; Root dir is now in [buffer] 112 | mov es, ax ; Set DI to this info 113 | mov di, buffer 114 | 115 | mov cx, word [RootDirEntries] ; Search all (224) entries 116 | mov ax, 0 ; Searching at offset 0 117 | 118 | 119 | next_root_entry: 120 | xchg cx, dx ; We use CX in the inner loop... 121 | 122 | mov si, kern_filename ; Start searching for kernel filename 123 | mov cx, 11 124 | rep cmpsb 125 | je found_file_to_load ; Pointer DI will be at offset 11 126 | 127 | add ax, 32 ; Bump searched entries by 1 (32 bytes per entry) 128 | 129 | mov di, buffer ; Point to next entry 130 | add di, ax 131 | 132 | xchg dx, cx ; Get the original CX back 133 | loop next_root_entry 134 | 135 | mov si, file_not_found ; If kernel is not found, bail out 136 | call print_string 137 | jmp reboot 138 | 139 | 140 | found_file_to_load: ; Fetch cluster and load FAT into RAM 141 | mov ax, word [es:di+0Fh] ; Offset 11 + 15 = 26, contains 1st cluster 142 | mov word [cluster], ax 143 | 144 | mov ax, 1 ; Sector 1 = first sector of first FAT 145 | call l2hts 146 | 147 | mov di, buffer ; ES:BX points to our buffer 148 | mov bx, di 149 | 150 | mov ah, 2 ; int 13h params: read (FAT) sectors 151 | mov al, 9 ; All 9 sectors of 1st FAT 152 | 153 | pusha ; Prepare to enter loop 154 | 155 | 156 | read_fat: 157 | popa ; In case registers are altered by int 13h 158 | pusha 159 | 160 | stc 161 | int 13h ; Read sectors using the BIOS 162 | 163 | jnc read_fat_ok ; If read went OK, skip ahead 164 | call reset_floppy ; Otherwise, reset floppy controller and try again 165 | jnc read_fat ; Floppy reset OK? 166 | 167 | ; ****************************************************************** 168 | fatal_disk_error: 169 | ; ****************************************************************** 170 | mov si, disk_error ; If not, print error message and reboot 171 | call print_string 172 | jmp reboot ; Fatal double error 173 | 174 | 175 | read_fat_ok: 176 | popa 177 | 178 | mov ax, 2000h ; Segment where we'll load the kernel 179 | mov es, ax 180 | mov bx, 0 181 | 182 | mov ah, 2 ; int 13h floppy read params 183 | mov al, 1 184 | 185 | push ax ; Save in case we (or int calls) lose it 186 | 187 | 188 | ; Now we must load the FAT from the disk. Here's how we find out where it starts: 189 | ; FAT cluster 0 = media descriptor = 0F0h 190 | ; FAT cluster 1 = filler cluster = 0FFh 191 | ; Cluster start = ((cluster number) - 2) * SectorsPerCluster + (start of user) 192 | ; = (cluster number) + 31 193 | 194 | load_file_sector: 195 | mov ax, word [cluster] ; Convert sector to logical 196 | add ax, 31 197 | 198 | call l2hts ; Make appropriate params for int 13h 199 | 200 | mov ax, 2000h ; Set buffer past what we've already read 201 | mov es, ax 202 | mov bx, word [pointer] 203 | 204 | pop ax ; Save in case we (or int calls) lose it 205 | push ax 206 | 207 | stc 208 | int 13h 209 | 210 | jnc calculate_next_cluster ; If there's no error... 211 | 212 | call reset_floppy ; Otherwise, reset floppy and retry 213 | jmp load_file_sector 214 | 215 | 216 | ; In the FAT, cluster values are stored in 12 bits, so we have to 217 | ; do a bit of maths to work out whether we're dealing with a byte 218 | ; and 4 bits of the next byte -- or the last 4 bits of one byte 219 | ; and then the subsequent byte! 220 | 221 | calculate_next_cluster: 222 | mov ax, [cluster] 223 | mov dx, 0 224 | mov bx, 3 225 | mul bx 226 | mov bx, 2 227 | div bx ; DX = [cluster] mod 2 228 | mov si, buffer 229 | add si, ax ; AX = word in FAT for the 12 bit entry 230 | mov ax, word [ds:si] 231 | 232 | or dx, dx ; If DX = 0 [cluster] is even; if DX = 1 then it's odd 233 | 234 | jz even ; If [cluster] is even, drop last 4 bits of word 235 | ; with next cluster; if odd, drop first 4 bits 236 | 237 | odd: 238 | shr ax, 4 ; Shift out first 4 bits (they belong to another entry) 239 | jmp short next_cluster_cont 240 | 241 | 242 | even: 243 | and ax, 0FFFh ; Mask out final 4 bits 244 | 245 | 246 | next_cluster_cont: 247 | mov word [cluster], ax ; Store cluster 248 | 249 | cmp ax, 0FF8h ; FF8h = end of file marker in FAT12 250 | jae end 251 | 252 | add word [pointer], 512 ; Increase buffer pointer 1 sector length 253 | jmp load_file_sector 254 | 255 | 256 | end: ; We've got the file to load! 257 | pop ax ; Clean up the stack (AX was pushed earlier) 258 | mov dl, byte [bootdev] ; Provide kernel with boot device info 259 | 260 | jmp 2000h:0000h ; Jump to entry point of loaded kernel! 261 | 262 | 263 | ; ------------------------------------------------------------------ 264 | ; BOOTLOADER SUBROUTINES 265 | 266 | reboot: 267 | mov ax, 0 268 | int 16h ; Wait for keystroke 269 | mov ax, 0 270 | int 19h ; Reboot the system 271 | 272 | 273 | print_string: ; Output string in SI to screen 274 | pusha 275 | 276 | mov ah, 0Eh ; int 10h teletype function 277 | 278 | .repeat: 279 | lodsb ; Get char from string 280 | cmp al, 0 281 | je .done ; If char is zero, end of string 282 | int 10h ; Otherwise, print it 283 | jmp short .repeat 284 | 285 | .done: 286 | popa 287 | ret 288 | 289 | 290 | reset_floppy: ; IN: [bootdev] = boot device; OUT: carry set on error 291 | push ax 292 | push dx 293 | mov ax, 0 294 | mov dl, byte [bootdev] 295 | stc 296 | int 13h 297 | pop dx 298 | pop ax 299 | ret 300 | 301 | 302 | l2hts: ; Calculate head, track and sector settings for int 13h 303 | ; IN: logical sector in AX, OUT: correct registers for int 13h 304 | push bx 305 | push ax 306 | 307 | mov bx, ax ; Save logical sector 308 | 309 | mov dx, 0 ; First the sector 310 | div word [SectorsPerTrack] 311 | add dl, 01h ; Physical sectors start at 1 312 | mov cl, dl ; Sectors belong in CL for int 13h 313 | mov ax, bx 314 | 315 | mov dx, 0 ; Now calculate the head 316 | div word [SectorsPerTrack] 317 | mov dx, 0 318 | div word [Sides] 319 | mov dh, dl ; Head/side 320 | mov ch, al ; Track 321 | 322 | pop ax 323 | pop bx 324 | 325 | mov dl, byte [bootdev] ; Set correct device 326 | 327 | ret 328 | 329 | 330 | ; ------------------------------------------------------------------ 331 | ; STRINGS AND VARIABLES 332 | 333 | kern_filename db "KERNEL BIN" 334 | 335 | disk_error db "Floppy error! Press any key...", 0 336 | file_not_found db "KERNEL.BIN not found!", 0 337 | 338 | bootdev db 0 ; Boot device number 339 | cluster dw 0 ; Cluster of the file we want to load 340 | pointer dw 0 ; Pointer into Buffer, for loading kernel 341 | 342 | 343 | ; ------------------------------------------------------------------ 344 | ; END OF BOOT SECTOR AND BUFFER START 345 | 346 | times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros 347 | dw 0AA55h ; Boot signature (DO NOT CHANGE!) 348 | 349 | 350 | buffer: ; Disk buffer begins (8k after this, stack starts) 351 | 352 | 353 | ; ================================================================== 354 | 355 | -------------------------------------------------------------------------------- /src/boot/bootload.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/src/boot/bootload.bin -------------------------------------------------------------------------------- /src/features/keyboard.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; MikeOS -- The Mike Operating System kernel 3 | ; Copyright (C) 2006 - 2019 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; KEYBOARD HANDLING ROUTINES 6 | ; ================================================================== 7 | 8 | ; ------------------------------------------------------------------ 9 | ; os_wait_for_key -- Waits for keypress and returns key 10 | ; IN: Nothing; OUT: AX = key pressed, other regs preserved 11 | 12 | os_wait_for_key: 13 | mov ah, 0x11 14 | int 0x16 15 | 16 | jnz .key_pressed 17 | 18 | hlt 19 | jmp os_wait_for_key 20 | 21 | .key_pressed: 22 | mov ah, 0x10 23 | int 0x16 24 | ret 25 | 26 | 27 | ; ------------------------------------------------------------------ 28 | ; os_check_for_key -- Scans keyboard for input, but doesn't wait 29 | ; IN: Nothing; OUT: AX = 0 if no key pressed, otherwise scan code 30 | 31 | os_check_for_key: 32 | pusha 33 | 34 | mov ax, 0 35 | mov ah, 1 ; BIOS call to check for key 36 | int 16h 37 | 38 | jz .nokey ; If no key, skip to end 39 | 40 | mov ax, 0 ; Otherwise get it from buffer 41 | int 16h 42 | 43 | mov [.tmp_buf], ax ; Store resulting keypress 44 | 45 | popa ; But restore all other regs 46 | mov ax, [.tmp_buf] 47 | ret 48 | 49 | .nokey: 50 | popa 51 | mov ax, 0 ; Zero result if no key pressed 52 | ret 53 | 54 | 55 | .tmp_buf dw 0 56 | 57 | 58 | ; ================================================================== 59 | 60 | -------------------------------------------------------------------------------- /src/features/libmouse-1.1.1/api.txt: -------------------------------------------------------------------------------- 1 | MikeOS Mouse Library 2 | Version 1.1.0 3 | API Document 4 | 5 | Function: mouselib_install_driver 6 | Input: Nothing 7 | Output: Nothing 8 | Description: Initialises the mouse device and installs the mouse driver that handles 9 | the core library fuctionality. The driver will then continue to run in the background. 10 | This must be run before calling any other mouse functions. 11 | 12 | Function: mouselib_locate 13 | Input: Nothing 14 | Output: CX = mouse X; DX = mouse Y 15 | Description: Returns coordinates to the current mouse position. 16 | 17 | Function: mouselib_move 18 | Input: CX = mouse X, DX = mouse Y 19 | Output: Nothing 20 | Description: Assigns the coordinates for a new mouse position. 21 | 22 | Function: mouselib_show 23 | Input: Nothing 24 | Output: Nothing 25 | Description: In text mode this inverts the colour of the text character corrosponding 26 | to the mouse position. This should not be used in graphical modes. 27 | 28 | Function: mouselib_hide 29 | Input: Nothing 30 | Output: Nothing 31 | Description: Resets a text character after a previous call to mouselib_show. 32 | 33 | Function: mouselib_range 34 | Input: AX = minimum X; BX = minimum Y 35 | CX = maximum X; DX = maximum Y 36 | Output: Nothing 37 | Description: Sets the minimum and maximum movement range for the mouse cursor. 38 | In the default 80x25 text mode the values (0, 0, 79, 24) will allow all the screen. 39 | Note that changes will not affect the current position. This must be set initially. 40 | 41 | Function: mouselib_wait 42 | Input: Nothing 43 | Output: Nothing 44 | Description: Stops the program until a mouse event is registered by the driver. 45 | This can be mouse movement or a mouse click. Power is conserved by halting the CPU 46 | whilst waiting. 47 | 48 | Function: mouselib_anyclick 49 | Input: Nothing 50 | Output: CF = set if any mouse button currently pressed, otherwise cleared 51 | Description: Uses the carry flags to return the status of all mouse buttons. 52 | The carry flag will be set if the left, middle or right mouse button is 53 | currently pressed or any combination of the previous. 54 | 55 | Function: mouselib_leftclick 56 | Input: Nothing 57 | Output: CF = set if left mouse button pressed, otherwise clear 58 | 59 | Function: mouselib_rightclick 60 | Input: Nothing 61 | Output: CF = set if left mouse button pressed, otherwise clear 62 | 63 | Function: mouselib_middleclick 64 | Input: Nothing 65 | Output: CF = set if left mouse button pressed, otherwise clear 66 | Note that some mice might not have middle buttons. 67 | 68 | Function: mouselib_input_wait 69 | Input: Nothing 70 | Output: CF = source, set if keyboard, clear if mouse 71 | Description: Stops the program until either a mouse action or keyboard input 72 | to occurs. If a mouse event occured the carry flags is clear, if keyboard input 73 | occurred the carry flags is set. The actual input will be collected in neither 74 | instance, so the program will need to check inputs as per normal.Power is 75 | conserved by halting the CPU whilst waiting. 76 | 77 | Function: mouselib_scale 78 | Input: DL = mouse X scale, DH = mouse Y scale 79 | Output: Nothing 80 | Description: Sets an movement speed of the mouse cursor. This takes the form 81 | 1:2^X, so higher values mean slower. 82 | speeds. 83 | The maximum rate is (0,0) = 1:1 84 | The recommended text mode value is (2,3) 85 | The recommended graphics mode value is (1,1) 86 | This must be set initially. 87 | 88 | Function: mouselib_remove_driver 89 | Input: Nothing 90 | Output: Nothing 91 | Description: Removes the mouse driver. This must be down before exiting the 92 | program or the operating system may lockup. 93 | 94 | Function: mouselib_freemove 95 | Input: Nothing 96 | Output: AX = keyboard value 97 | CX = mouse X; DX = mouse Y 98 | CF = set if mouse clicked, clear if keyboard input 99 | Description: Pauses the program and displays a mouse cursor on the screen that 100 | can be moved around by the user. The program is resumed when any mouse click or 101 | keyboard input occurs and the output are set accordingly. This can be useful 102 | for event driven programs. 103 | On a mouse click: AX = 0, CF = clear, CX = mouse X, DX = mouse Y 104 | On keyboard input: AX = key value, CF = set, CX = mouse X, DX = mouse Y 105 | 106 | Function: mouselib_setup 107 | Input: Nothing 108 | Output: Nothing 109 | Description: Install the mouse driver and sets default settings for text mode. 110 | 111 | Function: mouselib_eventmode_start 112 | Input: Nothing 113 | Output: Nothing 114 | Description: Enters event mode, an event-driven system that detects mouse and 115 | keyboard events and calls event handlers to deal with them if they exist. 116 | Remember to assign event handlers before entering event mode. 117 | 118 | Function: mouselib_eventmode_stop 119 | Input: Nothing 120 | Output: Nothing 121 | Description: Stops event mode when all current events have been processed. 122 | 123 | Function: mouselib_eventmode_assignhandler 124 | Input: CL = Event ID, AX = address of handler 125 | Output: Nothing 126 | Description: Assigns a handler to be called when the specified event is 127 | generated in event mode. 128 | 129 | Function: mouselib_eventmode_releasehandler 130 | Input: CL = Event ID 131 | Output: Nothing 132 | Description: Removes the handler for a specific event. The event will be 133 | ignored if it occurs. 134 | 135 | Possible Events Identifiers: 136 | MOUSELIB_EVENT_MOVE --- The mouse has been moved. 137 | MOUSELIB_EVENT_LEFTCLICK --- The left mouse button has been pressed. 138 | MOUSELIB_EVENT_MIDDLECLICK --- The middle mouse button has been pressed. 139 | MOUSELIB_EVENT_RIGHTCLICK --- The right mouse button has been pressed. 140 | MOUSELIB_EVENT_LEFTRELEASE --- The left mouse button has been released. 141 | MOUSELIB_EVENT_MIDDLERELEASE --- The middle mouse button has been released. 142 | MOUSELIB_EVENT_RIGHTRELEASE --- The right mouse button has been released. 143 | MOUSELIB_EVENT_KEYBOARD --- A keyboard key has been pressed. (AX = Key Value) 144 | 145 | If multiple, simultaneous events occur they will be processed in the order 146 | respective to that of the list, i.e. "MOVE" events will be processed before 147 | "LEFTCLICK" events. 148 | 149 | Constants: 150 | HAS_MOUSE_DRIVER --- Defined when the library is included 151 | MOUSE_DRIVER_VERSION --- Version number of the mouse driver (currently 110) 152 | 153 | -------------------------------------------------------------------------------- /src/features/libmouse-1.1.1/changes.txt: -------------------------------------------------------------------------------- 1 | Version 1.1.1 2 | * Fixed a bug that caused stack corruption if 'mouselib_show' was 3 | called multiple times without 'mouselib_hide'. 4 | * 'mouselib_show' and 'mouselib_hide' no longer alter the cursor 5 | position. 6 | 7 | 8 | Version 1.1.0 9 | * Fixed a bug causing mouse movement to glitch in QEMU. 10 | * Added library documentation. 11 | * Added Event Mode, a method of creating event driven programs. 12 | * Added a new demonstration program to show event mode. 13 | * Cleaned up demonstration programs. 14 | * Added new library calls: 15 | * mouselib_setup 16 | * mouselib_eventmode_start 17 | * mouselib_eventmode_stop 18 | * mouselib_eventmode_assignhandler 19 | * mouselib_eventmode_releasehandler 20 | * Added new events: 21 | * MOUSELIB_EVENT_MOVE 22 | * MOUSELIB_EVENT_LEFTCLICK 23 | * MOUSELIB_EVENT_MIDDLECLICK 24 | * MOUSELIB_EVENT_RIGHTCLICK 25 | * MOUSELIB_EVENT_LEFTRELEASE 26 | * MOUSELIB_EVENT_MIDDLERELEASE 27 | * MOUSELIB_EVENT_RIGHTRELEASE 28 | * MOUSELIB_EVENT_KEYBOARD 29 | * Added library version constant. 30 | * Library can now be included anywhere in the program. 31 | * Library will prevent itself from being included multiple times. 32 | 33 | 34 | Version 1.0.0 35 | * Initial Release 36 | * Has the following library calls: 37 | * mouselib_install_driver 38 | * mouselib_locate 39 | * mouselib_move 40 | * mouselib_show 41 | * mouselib_hide 42 | * mouselib_range 43 | * mouselib_wait 44 | * mouselib_anyclick 45 | * mouselib_leftclick 46 | * mouselib_rightclick 47 | * mouselib_middleclick 48 | * mouselib_input_wait 49 | * mouselib_scale 50 | * mouselib_remove_driver 51 | * mouselib_freemove 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/features/libmouse-1.1.1/mikedev.inc: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Include file for PathOS program development (MikeOS API version 17) 3 | ; ------------------------------------------------------------------ 4 | 5 | ; ------------------------------------------------------------------ 6 | ; IMPORTANT LOCATIONS 7 | 8 | os_main equ 0000h ; Where the OS code starts 9 | 10 | 11 | ; ------------------------------------------------------------------ 12 | ; COLOURS (eg for os_draw_background and os_draw_block) 13 | 14 | %DEFINE BLACK_ON_WHITE 11110000b 15 | %DEFINE WHITE_ON_BLACK 00001111b 16 | %DEFINE WHITE_ON_LIGHT_RED 11001111b 17 | %DEFINE WHITE_ON_GREEN 00101111b 18 | %DEFINE RED_ON_LIGHT_GREEN 10100100b 19 | 20 | 21 | ; ------------------------------------------------------------------ 22 | ; KEYS 23 | 24 | %DEFINE KEY_UP 72 25 | %DEFINE KEY_DOWN 80 26 | %DEFINE KEY_LEFT 75 27 | %DEFINE KEY_RIGHT 77 28 | 29 | %DEFINE KEY_ESC 27 30 | %DEFINE KEY_ENTER 13 31 | 32 | 33 | ; ------------------------------------------------------------------ 34 | ; SYSTEM CALLS 35 | 36 | ; Screen control 37 | 38 | os_clear_screen equ 0009h ; (Nothing used) 39 | os_print_string equ 0003h ; SI = zero-terminated string location 40 | os_move_cursor equ 0006h ; DH, DL = row, column 41 | os_print_horiz_line equ 000Ch ; AX = 1 for double line, else single 42 | os_print_newline equ 000Fh ; (Nothing used) 43 | os_draw_background equ 002Ah ; AX, BX = strings, CX = colour 44 | os_draw_block equ 00B4h ; BL = colour, DH/DL/SI/DI = pos 45 | os_input_dialog equ 00A8h ; AX = input string, BX = msg string 46 | os_dialog_box equ 003Ch ; AX, BX, CX = strings, DX = type 47 | ; OUT: AX = 0 for OK, 1 for cancel 48 | ; (only multi choice for DX = 1) 49 | os_list_dialog equ 00ABh ; IN: AX = comma-separated list of 50 | ; option strings, BX, CX = help to 51 | ; display at top of list 52 | ; OUT: AX = number (starting from 1) 53 | ; of option selected, or carry if Esc 54 | os_file_selector equ 005Ah ; Returns filename in AX 55 | os_get_cursor_pos equ 0069h ; OUT: DH = row, DL = column 56 | os_print_space equ 006Ch ; (Nothing used) 57 | os_dump_string equ 006Fh ; SI = string location 58 | os_print_digit equ 0072h ; AX = digit to print 59 | os_print_1hex equ 0075h ; Display low nibble of AL in hex 60 | os_print_2hex equ 0078h ; Display AL in hex 61 | os_print_4hex equ 007Bh ; Display AX in hex 62 | os_show_cursor equ 008Ah ; (Nothing used) 63 | os_hide_cursor equ 008Dh ; (Nothing used) 64 | os_dump_registers equ 0090h ; Shows contents of AX, BX, CX, DX 65 | 66 | 67 | ; Keyboard handling 68 | 69 | os_wait_for_key equ 0012h ; Returns AL = key pressed 70 | os_check_for_key equ 0015h ; Returns AL = key pressed 71 | 72 | 73 | ; File handling 74 | 75 | os_get_file_list equ 0042h ; AX = string to store filenames 76 | os_load_file equ 0021h ; IN: AX = filename string location, 77 | ; CX = location to load file 78 | ; OUT: BX = file size in bytes, 79 | ; carry clear if OK, set if missing 80 | os_write_file equ 0096h ; AX = filename, BX = data location, 81 | ; CX = number of bytes to save 82 | os_file_exists equ 0099h ; AX = filename, carry clear if exists 83 | os_create_file equ 009Ch ; AX = filename 84 | os_remove_file equ 009Fh ; AX = filename 85 | os_rename_file equ 00A2h ; AX = filename, BX = new filename 86 | os_get_file_size equ 00A5h ; AX = filename, OUT: BX = bytes 87 | ; (64K max) 88 | 89 | 90 | ; Sound 91 | 92 | os_speaker_tone equ 001Bh ; AX = note frequency 93 | os_speaker_off equ 001Eh ; (Nothing used) 94 | 95 | 96 | ; String handling 97 | 98 | os_int_to_string equ 0018h ; AX = unsigned integer, out AX = string 99 | os_sint_to_string equ 00C0h ; AX = signed integer, out AX = string 100 | os_string_reverse equ 00AEh ; SI = string location 101 | os_string_length equ 002Dh ; AX = string loc, returns AX = length 102 | os_string_uppercase equ 0030h ; AX = zero-terminated string 103 | os_string_lowercase equ 0033h ; AX = zero-terminated string 104 | os_input_string equ 0036h ; AX = string location, BX = maximum characters 105 | os_string_copy equ 0039h ; SI = source, DI = dest strings 106 | os_string_join equ 003Fh ; AX, BX = source strings, CX = dest 107 | os_string_compare equ 0045h ; SI, DI = strings, carry set if same 108 | os_string_strincmp equ 0093h ; As above, but with CL = chars to check 109 | os_string_chomp equ 0048h ; AX = string location 110 | os_string_strip equ 004Bh ; SI = string, AX = char to remove 111 | os_string_truncate equ 004Eh ; SI = string, AX = number of chars 112 | os_set_time_fmt equ 0084h ; AL = format 113 | os_set_date_fmt equ 0087h ; AX = format 114 | os_get_time_string equ 0054h ; BX = string location for eg '20:41' 115 | os_get_date_string equ 005Dh ; BX = string loc for eg '12/31/2007' 116 | os_find_char_in_string equ 0066h ; IN: SI = string, AL = char to find 117 | os_long_int_to_string equ 007Eh ; DX:AX = num, BX = base, DI = string 118 | os_string_to_int equ 00B1h ; SI = string (up to 65535), AX = int 119 | os_string_charchange equ 00BAh ; SI = string, AL = old char, BL = new 120 | os_string_parse equ 00C3h ; SI = string; output: AX/BX/CX/DX = 121 | ; substrings (or 0 if not present) 122 | os_string_tokenize equ 00CFh ; SI = string, AL = sep char; returns 123 | ; DI = next token 124 | 125 | 126 | ; Math routines 127 | 128 | os_get_random equ 00B7h ; IN: AX, BX = low, high; OUT: CX = num 129 | os_bcd_to_int equ 0051h ; AL = BCD number, returns AX = integer 130 | os_long_int_negate equ 0081h ; DX:AX = number 131 | 132 | 133 | ; Ports 134 | 135 | os_port_byte_out equ 00C9h ; IN: DX = port, AL = byte 136 | os_port_byte_in equ 00CCh ; IN: DX = port; OUT: AL = byte 137 | os_serial_port_enable equ 00BDh ; AX = 0 for 9600 baud, 1 for 1200 138 | os_send_via_serial equ 0060h ; AL = byte to send 139 | os_get_via_serial equ 0063h ; Returns AL = byte received 140 | ; OUT: AX = location, or 0 if not found 141 | 142 | 143 | ; Misc OS functions 144 | 145 | os_run_basic equ 00C6h ; AX = code location in RAM, BX = size, 146 | ; SI = parameter string (or 0 if none) 147 | os_get_api_version equ 0057h ; Returns API version in AL 148 | os_pause equ 0024h ; AX = 10ths of second to wait 149 | os_fatal_error equ 0027h ; AX = error string location 150 | 151 | 152 | ; ------------------------------------------------------------------ 153 | 154 | -------------------------------------------------------------------------------- /src/features/libmouse-1.1.1/mouse.asm: -------------------------------------------------------------------------------- 1 | %INCLUDE 'mikedev.inc' 2 | org 32768 3 | bits 16 4 | 5 | call mouselib_setup 6 | 7 | call os_hide_cursor 8 | 9 | ; reset the mouse position 10 | mov cx, 0 11 | mov dx, 0 12 | call mouselib_move 13 | 14 | mouse_loop: 15 | call os_clear_screen 16 | call mouselib_locate 17 | 18 | ; Print Mouse X 19 | mov ax, cx 20 | mov si, mouse_x_string 21 | call os_print_string 22 | call os_int_to_string 23 | mov si, ax 24 | call os_print_string 25 | call os_print_newline 26 | 27 | ; Print Mouse Y 28 | mov ax, dx 29 | mov si, mouse_y_string 30 | call os_print_string 31 | call os_int_to_string 32 | mov si, ax 33 | call os_print_string 34 | call os_print_newline 35 | 36 | mov si, exit_msg 37 | call os_print_string 38 | 39 | ; Show the cursor 40 | call mouselib_show 41 | 42 | ; Wait for input 43 | call mouselib_input_wait 44 | 45 | ; If the input was keyboard input, check the key 46 | jc key_pressed 47 | 48 | ; If it was a mouse click then finish program 49 | call mouselib_anyclick 50 | jc exit 51 | 52 | ; Otherwise hide the cursor and loop 53 | call mouselib_hide 54 | jmp mouse_loop 55 | 56 | key_pressed: 57 | call os_check_for_key 58 | 59 | ; Was the escape key pressed? 60 | cmp al, 27 61 | je exit 62 | 63 | ; If not hide the cursor and loop 64 | call mouselib_hide 65 | 66 | jmp mouse_loop 67 | 68 | exit: 69 | call mouselib_hide 70 | call os_clear_screen 71 | call os_show_cursor 72 | call mouselib_remove_driver 73 | ret 74 | 75 | mouse_x_string db 'Mouse X: ', 0 76 | mouse_y_string db 'Mouse Y: ', 0 77 | exit_msg db 'Press the escape key or click any mouse button to exit.', 0 78 | 79 | %INCLUDE 'mouse.lib' -------------------------------------------------------------------------------- /src/features/libmouse-1.1.1/mouse2.asm: -------------------------------------------------------------------------------- 1 | BITS 16 2 | ORG 32768 3 | %include 'mikedev.inc' 4 | %include 'mouse.lib' 5 | 6 | call mouselib_setup 7 | 8 | main: 9 | call mouselib_freemove 10 | jc keypress 11 | 12 | push dx 13 | mov dx, 0 14 | call os_move_cursor 15 | mov si, filler 16 | call os_print_string 17 | call os_move_cursor 18 | pop dx 19 | 20 | 21 | mov si, message 22 | call os_print_string 23 | mov ax, cx 24 | call os_int_to_string 25 | mov si, ax 26 | call os_print_string 27 | mov si, seperator 28 | call os_print_string 29 | mov ax, dx 30 | call os_int_to_string 31 | mov si, ax 32 | call os_print_string 33 | 34 | jmp main 35 | 36 | keypress: 37 | cmp al, 27 38 | je exit 39 | 40 | jmp main 41 | 42 | exit: 43 | call mouselib_remove_driver 44 | ret 45 | 46 | filler db ' ', 0 47 | message db 'Mouse click at X: ', 0 48 | seperator db ' Y: ', 0 49 | -------------------------------------------------------------------------------- /src/features/libmouse-1.1.1/mouse3.asm: -------------------------------------------------------------------------------- 1 | ; Mouse Demo 3 2 | ; An example of event mode 3 | 4 | bits 16 5 | org 32768 6 | %include 'mikedev.inc' 7 | %include 'mouse.lib' 8 | 9 | %ifndef MOUSE_DRIVER_VERSION 10 | %error 'Invalid mouse driver version' 11 | %else 12 | %if MOUSE_DRIVER_VERSION < 110 13 | %error 'Invalid mouse driver version' 14 | %endif 15 | %endif 16 | 17 | call os_hide_cursor 18 | call os_clear_screen 19 | call mouselib_setup 20 | 21 | ; Install event handlers before entering event mode 22 | mov ax, keyboard_handler 23 | mov cl, MOUSELIB_EVENT_KEYBOARD 24 | call mouselib_eventmode_assignhandler 25 | 26 | mov ax, move_handler 27 | mov cl, MOUSELIB_EVENT_MOVE 28 | call mouselib_eventmode_assignhandler 29 | 30 | mov ax, leftclick_handler 31 | mov cl, MOUSELIB_EVENT_LEFTCLICK 32 | call mouselib_eventmode_assignhandler 33 | 34 | mov ax, rightrelease_handler 35 | mov cl, MOUSELIB_EVENT_RIGHTRELEASE 36 | call mouselib_eventmode_assignhandler 37 | 38 | ; Enter interactive code, this will not return until interactive mode is exited 39 | call mouselib_eventmode_start 40 | call os_clear_screen 41 | call os_show_cursor 42 | ret 43 | 44 | keyboard_handler: 45 | ; Draw the character pressed at the cursor position 46 | call os_move_cursor 47 | 48 | mov ah, 0Ah 49 | mov bh, 0 50 | mov cx, 1 51 | int 10h 52 | 53 | ret 54 | 55 | move_handler: 56 | ; Draw red area wherever the cursor moves 57 | call os_move_cursor 58 | 59 | mov ah, 09h 60 | mov al, 32 61 | mov bh, 0 62 | mov bl, 64 63 | mov cx, 1 64 | int 10h 65 | 66 | ret 67 | 68 | leftclick_handler: 69 | call os_move_cursor 70 | 71 | mov ah, 09h 72 | mov al, 1 73 | mov bh, 0 74 | mov bl, 64 75 | mov cx, 1 76 | int 10h 77 | 78 | ret 79 | 80 | 81 | rightrelease_handler: 82 | ; Exit interactive mode when the right mouse button is released 83 | call mouselib_eventmode_stop 84 | ret 85 | -------------------------------------------------------------------------------- /src/features/libmouse-1.1.1/readme.txt: -------------------------------------------------------------------------------- 1 | ======================== 2 | The MikeOS Mouse Library 3 | ======================== 4 | Copyright (C) Joshua Beck 2013 5 | Email: mikeosdeveloper@gmail.com 6 | This program is licence under the GNU General Public Licence, version 3 7 | See 'licence.txt' for details 8 | 9 | The MikeOS Mouse Library is a fully functional mouse library for MikeOS that can be included in any assembly program. 10 | 11 | How to use the MikeOS mouse library in your MikeOS program: 12 | 13 | 1) Copy the file 'mouse.lib' from the archive to the 'programs' directory inside your MikeOS folder. 14 | 15 | 2) Include the library with your program. This can be archieved by adding the following line anywhere in the program. 16 | %include 'mouse.lib' 17 | 18 | 3) Install the mouse driver in the program before any mouse functionality is needed. This can be done with the following line. 19 | call mouselib_setup 20 | 21 | 4) Before the program exits remember to run uninstall the mouse driver or MikeOS may lockup. Use the following line. 22 | call mouselib_remove_driver 23 | 24 | 5) That's it, you can now use calls to the mouse library in your program. See the 'API' document for details. 25 | 26 | Information on library calls can be found within the API document. 27 | 28 | Files: 29 | readme.txt --- This document. 30 | mouse.lib --- The mouse library. This is included with programs so place it in your MikeOS folder. 31 | mouse.asm --- Demonstration Program. An example of basic library functions. 32 | mouse2.asm --- Demonstration Program. An example of interactive move. 33 | mouse3.asm --- Demonstration Program. An example of event mode. 34 | api.txt --- API Documentation. Reference for the functions provided by the library. 35 | licence.txt --- The GNU General Public Licence version 3, under which all code in this archive is released. 36 | changes.txt --- Log of previous changes to the library. 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/features/math.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; MikeOS -- The Mike Operating System kernel 3 | ; Copyright (C) 2006 - 2019 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; MATH ROUTINES 6 | ; ================================================================== 7 | 8 | ; ------------------------------------------------------------------ 9 | ; os_seed_random -- Seed the random number generator based on clock 10 | ; IN: Nothing; OUT: Nothing (registers preserved) 11 | 12 | os_seed_random: 13 | push bx 14 | push ax 15 | 16 | mov bx, 0 17 | mov al, 0x02 ; Minute 18 | out 0x70, al 19 | in al, 0x71 20 | 21 | mov bl, al 22 | shl bx, 8 23 | mov al, 0 ; Second 24 | out 0x70, al 25 | in al, 0x71 26 | mov bl, al 27 | 28 | mov word [os_random_seed], bx ; Seed will be something like 0x4435 (if it 29 | ; were 44 minutes and 35 seconds after the hour) 30 | pop ax 31 | pop bx 32 | ret 33 | 34 | 35 | os_random_seed dw 0 36 | 37 | 38 | ; ------------------------------------------------------------------ 39 | ; os_get_random -- Return a random integer between low and high (inclusive) 40 | ; IN: AX = low integer, BX = high integer 41 | ; OUT: CX = random integer 42 | 43 | os_get_random: 44 | push dx 45 | push bx 46 | push ax 47 | 48 | sub bx, ax ; We want a number between 0 and (high-low) 49 | call .generate_random 50 | mov dx, bx 51 | add dx, 1 52 | mul dx 53 | mov cx, dx 54 | 55 | pop ax 56 | pop bx 57 | pop dx 58 | add cx, ax ; Add the low offset back 59 | ret 60 | 61 | 62 | .generate_random: 63 | push dx 64 | push bx 65 | 66 | mov ax, [os_random_seed] 67 | mov dx, 0x7383 ; The magic number (random.org) 68 | mul dx ; DX:AX = AX * DX 69 | mov [os_random_seed], ax 70 | 71 | pop bx 72 | pop dx 73 | ret 74 | 75 | 76 | ; ------------------------------------------------------------------ 77 | ; os_bcd_to_int -- Converts binary coded decimal number to an integer 78 | ; IN: AL = BCD number; OUT: AX = integer value 79 | 80 | os_bcd_to_int: 81 | pusha 82 | 83 | mov bl, al ; Store entire number for now 84 | 85 | and ax, 0Fh ; Zero-out high bits 86 | mov cx, ax ; CH/CL = lower BCD number, zero extended 87 | 88 | shr bl, 4 ; Move higher BCD number into lower bits, zero fill msb 89 | mov al, 10 90 | mul bl ; AX = 10 * BL 91 | 92 | add ax, cx ; Add lower BCD to 10*higher 93 | mov [.tmp], ax 94 | 95 | popa 96 | mov ax, [.tmp] ; And return it in AX! 97 | ret 98 | 99 | 100 | .tmp dw 0 101 | 102 | 103 | ; ------------------------------------------------------------------ 104 | ; os_long_int_negate -- Multiply value in DX:AX by -1 105 | ; IN: DX:AX = long integer; OUT: DX:AX = -(initial DX:AX) 106 | 107 | os_long_int_negate: 108 | neg ax 109 | adc dx, 0 110 | neg dx 111 | ret 112 | 113 | 114 | ; ================================================================== 115 | 116 | -------------------------------------------------------------------------------- /src/features/misc.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; PathOS -- The Path Operating System kernel 3 | ; Copyright (C) PathOS has no copyright 4 | ; 5 | ; MISCELLANEOUS BULLSHIT ROUTINES 6 | ; ================================================================== 7 | 8 | ; ------------------------------------------------------------------ 9 | ; os_get_api_version -- Return current version of PathOS API 10 | ; IN: Nothing; OUT: AL = API version number 11 | 12 | os_get_api_version: 13 | mov al, MIKEOS_API_VER 14 | ret 15 | 16 | 17 | ; ------------------------------------------------------------------ 18 | ; os_pause -- Delay execution for specified 110ms chunks 19 | ; IN: AX = 100 millisecond chunks to wait (max delay is 32767, 20 | ; which multiplied by 55ms = 1802 seconds = 30 minutes) 21 | 22 | os_pause: 23 | pusha 24 | cmp ax, 0 25 | je .time_up ; If delay = 0 then bail out 26 | 27 | mov cx, 0 28 | mov [.counter_var], cx ; Zero the counter variable 29 | 30 | mov bx, ax 31 | mov ax, 0 32 | mov al, 2 ; 2 * 55ms = 110mS 33 | mul bx ; Multiply by number of 110ms chunks required 34 | mov [.orig_req_delay], ax ; Save it 35 | 36 | mov ah, 0 37 | int 1Ah ; Get tick count 38 | 39 | mov [.prev_tick_count], dx ; Save it for later comparison 40 | 41 | .checkloop: 42 | mov ah,0 43 | int 1Ah ; Get tick count again 44 | 45 | cmp [.prev_tick_count], dx ; Compare with previous tick count 46 | 47 | jne .up_date ; If it's changed check it 48 | jmp .checkloop ; Otherwise wait some more 49 | 50 | .time_up: 51 | popa 52 | ret 53 | 54 | .up_date: 55 | mov ax, [.counter_var] ; Inc counter_var 56 | inc ax 57 | mov [.counter_var], ax 58 | 59 | cmp ax, [.orig_req_delay] ; Is counter_var = required delay? 60 | jge .time_up ; Yes, so bail out 61 | 62 | mov [.prev_tick_count], dx ; No, so update .prev_tick_count 63 | 64 | jmp .checkloop ; And go wait some more 65 | 66 | 67 | .orig_req_delay dw 0 68 | .counter_var dw 0 69 | .prev_tick_count dw 0 70 | 71 | 72 | ; ------------------------------------------------------------------ 73 | ; os_fatal_error -- Display error message and halt execution 74 | ; IN: AX = error message string location 75 | 76 | os_fatal_error: 77 | mov bx, ax ; Store string location for now 78 | 79 | mov dh, 0 80 | mov dl, 0 81 | call os_move_cursor 82 | 83 | pusha 84 | mov ah, 09h ; Draw red bar at top 85 | mov bh, 0 86 | mov cx, 240 87 | mov bl, 01001111b 88 | mov al, ' ' 89 | int 10h 90 | popa 91 | 92 | mov dh, 0 93 | mov dl, 0 94 | call os_move_cursor 95 | 96 | mov si, .msg_inform ; Inform of fatal error 97 | call os_print_string 98 | 99 | mov si, bx ; Program-supplied error message 100 | call os_print_string 101 | 102 | jmp $ ; Halt execution 103 | 104 | 105 | .msg_inform db '>>> FATAL OPERATING SYSTEM ERROR', 13, 10, 0 106 | 107 | 108 | ; ================================================================== 109 | 110 | -------------------------------------------------------------------------------- /src/features/ports.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; MikeOS -- The Mike Operating System kernel 3 | ; Copyright (C) 2006 - 2019 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; PORT INPUT AND OUTPUT ROUTINES 6 | ; ================================================================== 7 | 8 | ; ------------------------------------------------------------------ 9 | ; os_port_byte_out -- Send byte to a port 10 | ; IN: DX = port address, AL = byte to send 11 | 12 | os_port_byte_out: 13 | pusha 14 | 15 | out dx, al 16 | 17 | popa 18 | ret 19 | 20 | 21 | ; ------------------------------------------------------------------ 22 | ; os_port_byte_in -- Receive byte from a port 23 | ; IN: DX = port address 24 | ; OUT: AL = byte from port 25 | 26 | os_port_byte_in: 27 | pusha 28 | 29 | in al, dx 30 | mov word [.tmp], ax 31 | 32 | popa 33 | mov ax, [.tmp] 34 | ret 35 | 36 | 37 | .tmp dw 0 38 | 39 | 40 | ; ------------------------------------------------------------------ 41 | ; os_serial_port_enable -- Set up the serial port for transmitting data 42 | ; IN: AX = 0 for normal mode (9600 baud), or 1 for slow mode (1200 baud) 43 | 44 | os_serial_port_enable: 45 | pusha 46 | 47 | mov dx, 0 ; Configure serial port 1 48 | cmp ax, 1 49 | je .slow_mode 50 | 51 | mov ah, 0 52 | mov al, 11100011b ; 9600 baud, no parity, 8 data bits, 1 stop bit 53 | jmp .finish 54 | 55 | .slow_mode: 56 | mov ah, 0 57 | mov al, 10000011b ; 1200 baud, no parity, 8 data bits, 1 stop bit 58 | 59 | .finish: 60 | int 14h 61 | 62 | popa 63 | ret 64 | 65 | 66 | ; ------------------------------------------------------------------ 67 | ; os_send_via_serial -- Send a byte via the serial port 68 | ; IN: AL = byte to send via serial; OUT: AH = Bit 7 clear on success 69 | 70 | os_send_via_serial: 71 | pusha 72 | 73 | mov ah, 01h 74 | mov dx, 0 ; COM1 75 | 76 | int 14h 77 | 78 | mov [.tmp], ax 79 | 80 | popa 81 | 82 | mov ax, [.tmp] 83 | 84 | ret 85 | 86 | 87 | .tmp dw 0 88 | 89 | 90 | ; ------------------------------------------------------------------ 91 | ; os_get_via_serial -- Get a byte from the serial port 92 | ; OUT: AL = byte that was received; OUT: AH = Bit 7 clear on success 93 | 94 | os_get_via_serial: 95 | pusha 96 | 97 | mov ah, 02h 98 | mov dx, 0 ; COM1 99 | 100 | int 14h 101 | 102 | mov [.tmp], ax 103 | 104 | popa 105 | 106 | mov ax, [.tmp] 107 | 108 | ret 109 | 110 | 111 | .tmp dw 0 112 | 113 | 114 | ; ================================================================== 115 | 116 | -------------------------------------------------------------------------------- /src/features/sound.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; PathOS Sound 3 | ; PC SPEAKER SOUND ROUTINES 4 | ; ================================================================== 5 | 6 | ; ------------------------------------------------------------------ 7 | ; os_speaker_tone -- Generate PC speaker tone (call os_speaker_off to turn off) 8 | ; IN: AX = note frequency; OUT: Nothing (registers preserved) 9 | 10 | os_speaker_tone: 11 | pusha 12 | 13 | mov cx, ax ; Store note value for now 14 | 15 | mov al, 182 16 | out 43h, al 17 | mov ax, cx ; Set up frequency 18 | out 42h, al 19 | mov al, ah 20 | out 42h, al 21 | 22 | in al, 61h ; Switch PC speaker on 23 | or al, 03h 24 | out 61h, al 25 | 26 | popa 27 | ret 28 | 29 | 30 | ; ------------------------------------------------------------------ 31 | ; os_speaker_off -- Turn off PC speaker 32 | ; IN/OUT: Nothing (registers preserved) 33 | 34 | os_speaker_off: 35 | pusha 36 | 37 | in al, 61h 38 | and al, 0FCh 39 | out 61h, al 40 | 41 | popa 42 | ret 43 | 44 | 45 | ; ================================================================== 46 | 47 | -------------------------------------------------------------------------------- /src/kernel.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; PathOS -- The Path Operating System kernel 3 | ; Copyright (C) GNU GENERAL PUBLIC LICENSE 4 | ; 5 | ; This is loaded from the drive by BOOTLOAD.BIN, as KERNEL.BIN. 6 | ; First we have the system call vectors, which start at a static point 7 | ; for programs to use. Following that is the main kernel code and 8 | ; then additional system call code is included. 9 | ; ================================================================== 10 | 11 | 12 | BITS 16 13 | 14 | %DEFINE PATHOS_VER '0.0.5' ; OS version number 15 | %DEFINE MIKEOS_VER '4.6.1' ; MikeOS version number 16 | %DEFINE MIKEOS_API_VER 17 ; API version for programs to check 17 | 18 | 19 | ; This is the location in RAM for kernel disk operations, 24K 20 | ; after the point where the kernel has loaded; it's 8K in size, 21 | ; because external programs load after it at the 32K point: 22 | 23 | disk_buffer equ 24576 24 | 25 | 26 | ; ------------------------------------------------------------------ 27 | ; OS CALL VECTORS -- Static locations for system call vectors 28 | ; Note: these cannot be moved, or it'll break the calls! 29 | 30 | ; The comments show exact locations of instructions in this section, 31 | ; and are used in programs/mikedev.inc so that an external program can 32 | ; use a PathOS system call without having to know its exact position 33 | ; in the kernel source code... 34 | 35 | os_call_vectors: 36 | jmp os_main ; 0000h -- Called from bootloader 37 | jmp os_print_string ; 0003h 38 | jmp os_move_cursor ; 0006h 39 | jmp os_clear_screen ; 0009h 40 | jmp os_print_horiz_line ; 000Ch 41 | jmp os_print_newline ; 000Fh 42 | jmp os_wait_for_key ; 0012h 43 | jmp os_check_for_key ; 0015h 44 | jmp os_int_to_string ; 0018h 45 | jmp os_speaker_tone ; 001Bh 46 | jmp os_speaker_off ; 001Eh 47 | jmp os_load_file ; 0021h 48 | jmp os_pause ; 0024h 49 | jmp os_fatal_error ; 0027h 50 | jmp os_draw_background ; 002Ah 51 | jmp os_string_length ; 002Dh 52 | jmp os_string_uppercase ; 0030h 53 | jmp os_string_lowercase ; 0033h 54 | jmp os_input_string ; 0036h 55 | jmp os_string_copy ; 0039h 56 | jmp os_dialog_box ; 003Ch 57 | jmp os_string_join ; 003Fh 58 | jmp os_get_file_list ; 0042h 59 | jmp os_string_compare ; 0045h 60 | jmp os_string_chomp ; 0048h 61 | jmp os_string_strip ; 004Bh 62 | jmp os_string_truncate ; 004Eh 63 | jmp os_bcd_to_int ; 0051h 64 | jmp os_get_time_string ; 0054h 65 | jmp os_get_api_version ; 0057h 66 | jmp os_file_selector ; 005Ah 67 | jmp os_get_date_string ; 005Dh 68 | jmp os_send_via_serial ; 0060h 69 | jmp os_get_via_serial ; 0063h 70 | jmp os_find_char_in_string ; 0066h 71 | jmp os_get_cursor_pos ; 0069h 72 | jmp os_print_space ; 006Ch 73 | jmp os_dump_string ; 006Fh 74 | jmp os_print_digit ; 0072h 75 | jmp os_print_1hex ; 0075h 76 | jmp os_print_2hex ; 0078h 77 | jmp os_print_4hex ; 007Bh 78 | jmp os_long_int_to_string ; 007Eh 79 | jmp os_long_int_negate ; 0081h 80 | jmp os_set_time_fmt ; 0084h 81 | jmp os_set_date_fmt ; 0087h 82 | jmp os_show_cursor ; 008Ah 83 | jmp os_hide_cursor ; 008Dh 84 | jmp os_dump_registers ; 0090h 85 | jmp os_string_strincmp ; 0093h 86 | jmp os_write_file ; 0096h 87 | jmp os_file_exists ; 0099h 88 | jmp os_create_file ; 009Ch 89 | jmp os_remove_file ; 009Fh 90 | jmp os_rename_file ; 00A2h 91 | jmp os_get_file_size ; 00A5h 92 | jmp os_input_dialog ; 00A8h 93 | jmp os_list_dialog ; 00ABh 94 | jmp os_string_reverse ; 00AEh 95 | jmp os_string_to_int ; 00B1h 96 | jmp os_draw_block ; 00B4h 97 | jmp os_get_random ; 00B7h 98 | jmp os_string_charchange ; 00BAh 99 | jmp os_serial_port_enable ; 00BDh 100 | jmp os_sint_to_string ; 00C0h 101 | jmp os_string_parse ; 00C3h 102 | jmp os_run_basic ; 00C6h 103 | jmp os_port_byte_out ; 00C9h 104 | jmp os_port_byte_in ; 00CCh 105 | jmp os_string_tokenize ; 00CFh 106 | 107 | 108 | ; ------------------------------------------------------------------ 109 | ; START OF MAIN KERNEL CODE 110 | 111 | os_main: 112 | cli ; Clear interrupts 113 | mov ax, 0 114 | mov ss, ax ; Set stack segment and pointer 115 | mov sp, 0FFFFh 116 | sti ; Restore interrupts 117 | 118 | cld ; The default direction for string operations 119 | ; will be 'up' - incrementing address in RAM 120 | 121 | mov ax, 2000h ; Set all segments to match where kernel is loaded 122 | mov ds, ax ; After this, we don't need to bother with 123 | mov es, ax ; segments ever again, as PathOS and its programs 124 | mov fs, ax ; live entirely in 64K 125 | mov gs, ax 126 | 127 | cmp dl, 0 128 | je no_change 129 | mov [bootdev], dl ; Save boot device number 130 | push es 131 | mov ah, 8 ; Get drive parameters 132 | int 13h 133 | pop es 134 | and cx, 3Fh ; Maximum sector number 135 | mov [SecsPerTrack], cx ; Sector numbers start at 1 136 | movzx dx, dh ; Maximum head number 137 | add dx, 1 ; Head numbers start at 0 - add 1 for total 138 | mov [Sides], dx 139 | 140 | no_change: 141 | mov ax, 1003h ; Set text output with certain attributes 142 | mov bx, 0 ; to be bright, and not blinking 143 | int 10h 144 | 145 | call os_seed_random ; Seed random number generator 146 | 147 | 148 | ; Let's see if there's a file called AUTORUN.BIN and execute 149 | ; it if so, before going to the program launcher menu 150 | 151 | mov ax, autorun_bin_file_name 152 | call os_file_exists 153 | jc no_autorun_bin ; Skip next three lines if AUTORUN.BIN doesn't exist 154 | 155 | mov cx, 32768 ; Otherwise load the program into RAM... 156 | call os_load_file 157 | jmp execute_bin_program ; ...and move on to the executing part 158 | 159 | 160 | ; Or perhaps there's an AUTORUN.BAS file? 161 | 162 | no_autorun_bin: 163 | mov ax, autorun_bas_file_name 164 | call os_file_exists 165 | jc option_screen ; Skip next section if AUTORUN.BAS doesn't exist 166 | 167 | mov cx, 32768 ; Otherwise load the program into RAM 168 | call os_load_file 169 | call os_clear_screen 170 | mov ax, 32768 171 | call os_run_basic ; Run the kernel's BASIC interpreter 172 | 173 | jmp app_selector ; And go to the app selector menu when BASIC ends 174 | 175 | 176 | ; Now we display a dialog box offering the user a choice of 177 | ; a menu-driven program selector, or a command-line interface 178 | 179 | option_screen: 180 | mov ax, os_init_msg ; Set up the welcome screen 181 | mov bx, os_version_msg 182 | mov cx, 00000100b ; Color: red text on black 183 | call os_draw_background 184 | 185 | mov ax, dialog_string_1 ; Ask if user wants app selector or command-line 186 | mov bx, dialog_string_2 187 | mov cx, dialog_string_3 188 | mov dx, 1 ; We want a two-option dialog box (OK or Cancel) 189 | call os_dialog_box 190 | 191 | cmp ax, 1 ; If OK (option 0) chosen, start app selector 192 | jne near app_selector 193 | 194 | call os_clear_screen ; Otherwise clean screen and start the CLI 195 | call os_command_line 196 | 197 | jmp option_screen ; Offer menu/CLI choice after CLI has exited 198 | 199 | 200 | ; Data for the above code... 201 | 202 | os_init_msg db 'Welcome to PathOS', 0 203 | os_version_msg db 'Version ', PATHOS_VER, 0 204 | 205 | dialog_string_1 db 'Thanks for trying out PathOS!', 0 206 | dialog_string_2 db 'Please select an interface: OK for the', 0 207 | dialog_string_3 db 'program menu, CLI for command line.', 0 208 | 209 | 210 | 211 | app_selector: 212 | mov ax, os_init_msg ; Draw main screen layout 213 | mov bx, os_version_msg 214 | mov cx, 00000100b ; Color: red text on black 215 | call os_draw_background 216 | 217 | call os_file_selector ; Get user to select a file, and store 218 | ; the resulting string location in AX 219 | ; (other registers are undetermined) 220 | 221 | jc option_screen ; Return to the CLI/menu choice screen if Esc pressed 222 | 223 | mov si, ax ; Did the user try to run 'KERNEL.BIN'? 224 | mov di, kern_file_name 225 | call os_string_compare 226 | jc no_kernel_execute ; Show an error message if so 227 | 228 | 229 | ; Next, we need to check that the program we're attempting to run is 230 | ; valid -- in other words, that it has a .BIN extension 231 | 232 | push si ; Save filename temporarily 233 | 234 | mov bx, si 235 | mov ax, si 236 | call os_string_length 237 | 238 | mov si, bx 239 | add si, ax ; SI now points to end of filename... 240 | 241 | dec si 242 | dec si 243 | dec si ; ...and now to start of extension! 244 | 245 | mov di, bin_ext 246 | mov cx, 3 247 | rep cmpsb ; Are final 3 chars 'BIN'? 248 | jne not_bin_extension ; If not, it might be a '.BAS' 249 | 250 | pop si ; Restore filename 251 | 252 | 253 | mov ax, si 254 | mov cx, 32768 ; Where to load the program file 255 | call os_load_file ; Load filename pointed to by AX 256 | 257 | 258 | execute_bin_program: 259 | call os_clear_screen ; Clear screen before running 260 | 261 | mov ax, 0 ; Clear all registers 262 | mov bx, 0 263 | mov cx, 0 264 | mov dx, 0 265 | mov si, 0 266 | mov di, 0 267 | 268 | call 32768 ; Call the external program code, 269 | ; loaded at second 32K of segment 270 | ; (program must end with 'ret') 271 | 272 | mov si, program_finished_msg ; Give the program a chance to display 273 | call os_print_string ; any output before clearing the screen 274 | call os_wait_for_key 275 | 276 | call os_clear_screen ; When finished, clear screen 277 | jmp app_selector ; and go back to the program list 278 | 279 | 280 | no_kernel_execute: ; Warn about trying to executing kernel! 281 | mov ax, kerndlg_string_1 282 | mov bx, kerndlg_string_2 283 | mov cx, kerndlg_string_3 284 | mov dx, 0 ; One button for dialog box 285 | call os_dialog_box 286 | 287 | jmp app_selector ; Start over again... 288 | 289 | 290 | not_bin_extension: 291 | pop si ; We pushed during the .BIN extension check 292 | 293 | push si ; Save it again in case of error... 294 | 295 | mov bx, si 296 | mov ax, si 297 | call os_string_length 298 | 299 | mov si, bx 300 | add si, ax ; SI now points to end of filename... 301 | 302 | dec si 303 | dec si 304 | dec si ; ...and now to start of extension! 305 | 306 | mov di, bas_ext 307 | mov cx, 3 308 | rep cmpsb ; Are final 3 chars 'BAS'? 309 | jne not_bas_extension ; If not, error out 310 | 311 | 312 | pop si 313 | 314 | mov ax, si 315 | mov cx, 32768 ; Where to load the program file 316 | call os_load_file ; Load filename pointed to by AX 317 | 318 | call os_clear_screen ; Clear screen before running 319 | 320 | mov ax, 32768 321 | mov si, 0 ; No params to pass 322 | call os_run_basic ; And run our BASIC interpreter on the code! 323 | 324 | mov si, program_finished_msg 325 | call os_print_string 326 | call os_wait_for_key 327 | 328 | call os_clear_screen 329 | jmp app_selector ; and go back to the program list 330 | 331 | 332 | not_bas_extension: 333 | pop si 334 | 335 | mov ax, ext_string_1 336 | mov bx, ext_string_2 337 | mov cx, 0 338 | mov dx, 0 ; One button for dialog box 339 | call os_dialog_box 340 | 341 | jmp app_selector ; Start over again... 342 | 343 | 344 | ; And now data for the above code... 345 | 346 | kern_file_name db 'KERNEL.BIN', 0 347 | 348 | autorun_bin_file_name db 'AUTORUN.BIN', 0 349 | autorun_bas_file_name db 'AUTORUN.BAS', 0 350 | 351 | bin_ext db 'BIN' 352 | bas_ext db 'BAS' 353 | 354 | kerndlg_string_1 db 'ERROR', 0 355 | kerndlg_string_2 db '5TUP1D', 0 356 | kerndlg_string_3 db 'DO NOT TRY TO RUN THE KERNEL', 0 357 | 358 | ext_string_1 db 'ERROR', 0 359 | ext_string_2 db '1D10T', 0 360 | 361 | program_finished_msg db 'Program Complete, Press Any Key To Continue', 0 362 | 363 | 364 | ; ------------------------------------------------------------------ 365 | ; SYSTEM VARIABLES -- Settings for programs and system calls 366 | 367 | 368 | ; Time and date formatting 369 | 370 | fmt_12_24 db 0 ; Non-zero = 24-hr format 371 | 372 | fmt_date db 0, '/' ; 0, 1, 2 = M/D/Y, D/M/Y or Y/M/D 373 | ; Bit 7 = use name for months 374 | ; If bit 7 = 0, second byte = separator character 375 | 376 | 377 | ; ------------------------------------------------------------------ 378 | ; FEATURES -- Code to pull into the kernel 379 | 380 | 381 | %INCLUDE "features/cli.asm" 382 | %INCLUDE "features/disk.asm" 383 | %INCLUDE "features/keyboard.asm" 384 | %INCLUDE "features/math.asm" 385 | %INCLUDE "features/misc.asm" 386 | %INCLUDE "features/ports.asm" 387 | %INCLUDE "features/screen.asm" 388 | %INCLUDE "features/sound.asm" 389 | %INCLUDE "features/string.asm" 390 | %INCLUDE "features/basic.asm" 391 | ;%INCLUDE "../clib/mlib.asm" 392 | ;%INCLUDE "../include/clib.h" 393 | ;%INCLUDE "features/libmouse-1.1.1/mouse.asm" 394 | 395 | 396 | ; ================================================================== 397 | ; END OF KERNEL 398 | ; ================================================================== 399 | 400 | -------------------------------------------------------------------------------- /src/kernel.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calebrwalk5/PathOS/d12c6c8faa36ba8b0b6093e0013096e1c76b6839/src/kernel.bin --------------------------------------------------------------------------------