diff --git a/Makefile b/Makefile index 6575615..7d5de89 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ PYTHON = python3 all: ponydos.img -FS_FILES = ponydos.wall passion.wall shell.bin +FS_FILES = ponydos.wall passion.wall shell.bin hello.bin ponydos.img: ponydos.bin $(FS_FILES) $(PYTHON) assemble_floppy.py $@ ponydos.bin $(FS_FILES) @@ -18,6 +18,8 @@ ponydos.bin: ponydos_static.inc shell.bin: ponydos.inc +hello.bin: ponydos.inc + .asm.bin: $(NASM) -fbin -o $@ $< diff --git a/hello.asm b/hello.asm new file mode 100644 index 0000000..46753a3 --- /dev/null +++ b/hello.asm @@ -0,0 +1,39 @@ +%include "ponydos.inc" +cpu 8086 +bits 16 + +; 0x0000 +jmp near process_event + +; 0x0003 PROC_INITIALIZE_ENTRYPOINT +; This needs to preserve ds +initialize: + push ds + + call deallocate_own_memory + + pop ds + retf + +process_event: + retf + +deallocate_own_memory: + push bx + push cx + push es + + mov bx, PONYDOS_SEG + mov es, bx + + ; Segment 0xn000 corresponds to slot n in the allocation table + mov bx, cs + mov cl, 12 + shr bx, cl + + mov byte [es:GLOBAL_MEMORY_ALLOCATION_MAP + bx], 0 + + pop es + pop cx + pop bx + ret diff --git a/ponydos.asm b/ponydos.asm index d58a2d4..2ffb8f3 100644 --- a/ponydos.asm +++ b/ponydos.asm @@ -72,7 +72,7 @@ load_shell: call 0:modify_sectors ; TODO: error management? Surely this works... - call 0x1000:3 + call 0x1000:PROC_INITIALIZE_ENTRYPOINT initialize_screen: ; Disable text cursor diff --git a/ponydos_static.inc b/ponydos_static.inc index acefa99..bf1be74 100644 --- a/ponydos_static.inc +++ b/ponydos_static.inc @@ -4,6 +4,7 @@ GLOBAL_WALLPAPER equ 0x500 GLOBAL_DIRENTS equ 0x2000 FS_DIRENT_SIZE equ 32 +FS_DIRENT_NAME_SIZE equ 30 FS_FILE_MAX_SIZE equ 128 WM_PAINT equ 0 @@ -13,3 +14,7 @@ WM_UNHOOK equ 3 MOUSE_PRIMARY equ 0x01 MOUSE_SECONDARY equ 0x02 + +MEM_ALLOCATION_MAP_SIZE equ 10 + +PROC_INITIALIZE_ENTRYPOINT equ 3 diff --git a/shell.asm b/shell.asm index 19b229a..517c1c6 100644 --- a/shell.asm +++ b/shell.asm @@ -27,13 +27,26 @@ initialize: push cs pop ds + ; Has shell been started already? + mov bp, PONYDOS_SEG + mov es, bp + cmp word [es:GLOBAL_WINDOW_CHAIN_HEAD], 0 + je .not_relaunch + .relaunch: + ; TODO: Display an alert if trying to re-run shell + ; Clean up memory when exiting + mov bx, cs + mov cl, 12 + shr bx, cl + mov byte [es:GLOBAL_MEMORY_ALLOCATION_MAP + bx], 0 + jmp .end + .not_relaunch: + ; Set wallpaper mov si, wallpaper_name xor dx, dx call PONYDOS_SEG:SYS_OPEN_FILE - mov bp, PONYDOS_SEG - mov es, bp mov bx, GLOBAL_WALLPAPER xor di, di ; read call PONYDOS_SEG:SYS_MODIFY_SECTORS @@ -62,6 +75,7 @@ initialize: call request_redraw + .end: pop ds retf @@ -117,7 +131,7 @@ process_event: ; al = WM_PAINT ; bx = window ID ; out: -; trashes everything +; clobbers everything paint: call get_window @@ -142,7 +156,7 @@ paint: ; ch = Y ; dl = mouse buttons held down ; out: -; trashes everything +; clobbers everything mouse: call get_window @@ -180,11 +194,11 @@ mouse: .not_clicking: test dl, MOUSE_PRIMARY | MOUSE_SECONDARY - jz .not_primary_held - .primary_held: + jz .not_buttons_held + .buttons_held: mov byte [si + window.mouse_released_inside], 0 jmp .inside - .not_primary_held: + .not_buttons_held: mov byte [si + window.mouse_released_inside], 1 .inside: @@ -212,8 +226,13 @@ mouse: ; dl = which buttons are held down ; si = pointer to window structure ; out: -; trashes everything +; dl = which buttons are held down +; si = pointer to window structure +; clobbers everything else click: + push dx + push si + cmp byte [si + window.icon], 0 je .file_window .icon: @@ -233,9 +252,43 @@ click: jne .not_close .close: call hide_file_window + jmp .end .not_close: + ; If clicked within the content area + mov ax, bx + sub ax, [si + window.y] + jz .end + + ; Find the start of the line user clicked on + mov bx, [si + window.width] + shl bx, 1 + mul bx + + mov si, [si + window.data] + add si, ax + + ; Zero out launch_filename + mov di, launch_filename + mov cx, FS_DIRENT_NAME_SIZE + xor al, al + rep stosb + + ; Copy file name to launch_filename + mov di, launch_filename + .copy_filename_loop: + lodsw + test al, al + jz .copy_filename_loop_end + stosb + jmp .copy_filename_loop + .copy_filename_loop_end: + + call launch + .end: + pop si + pop dx ret show_file_window: @@ -282,13 +335,80 @@ hide_file_window: call request_redraw ret +; out: +; clobbers everything +launch: + mov si, launch_filename + + ; Is it a .bin file? + call strlen + cmp cx, 4 + jb .end ; No, too short + add si, cx + sub si, 4 + mov di, bin_extension + call strcmp + jne .end ; No, wrong extension + + mov si, launch_filename + mov dx, 1 ; Don't create a new file if not found + call PONYDOS_SEG:SYS_OPEN_FILE + test ax, ax + ; TODO: Display an alert on file not being found + jz .end + + push ax + push cx + + ; Allocate a segment + mov ax, PONYDOS_SEG + mov es, ax + mov si, GLOBAL_MEMORY_ALLOCATION_MAP + mov cx, MEM_ALLOCATION_MAP_SIZE + .find_free_segment: + mov al, [es:si] + test al, al + jz .found_free_segment + inc si + loop .find_free_segment + ; TODO: Display an alert on OOM error + pop cx + pop ax + jmp .end + .found_free_segment: + mov byte [es:si], 1 ; Mark as used + + ; Set up es to point to the allocated segment + sub si, GLOBAL_MEMORY_ALLOCATION_MAP + mov cl, 12 + shl si, cl + mov es, si + + pop cx + pop ax + xor bx, bx ; Load at the start of the segment + xor di, di ; Read + call PONYDOS_SEG:SYS_MODIFY_SECTORS + + ; Transfer control to the newly loaded binary + push cs ; Return segment + mov ax, .end + push ax ; Return offset + push es ; Call segment + mov ax, PROC_INITIALIZE_ENTRYPOINT + push ax ; Call offset + retf + + .end: + ret + ; in: ; al = WM_KEYBOARD ; bx = window ID ; cl = typed character ; cl = typed key ; out: -; trashes everything +; clobbers everything keyboard: call get_window mov si, [si + window.data] @@ -304,7 +424,7 @@ keyboard: ; out: ; ax = own ID if not the window to unhook ; next ID if the window to unhook -; trashes everything else +; clobbers everything else unhook: call get_window @@ -573,6 +693,31 @@ strlen: pop ax ret +; in: +; ds:si = string1 +; ds:di = string2 +; out: +; zf(ef) = strings are equal +strcmp: + push si + push di + + .loop: + lodsb + cmp [di], al + jne .end + + test al, al + jz .end + + inc di + jmp .loop + + .end: + pop di + pop si + ret + ; in: ; bx = window ID ; out: @@ -605,6 +750,8 @@ forward_event: wallpaper_name db 'ponydos.wall', 0 +bin_extension db '.bin', 0 + %include "debug.inc" file_window_visible db 0 @@ -618,8 +765,10 @@ file_window: db 'A', 0x0f, ':', 0x0f times 37 db ' ', 0x0f db 'x', 0x0f - times 15*40 db ' ', 0xf0 + times 15*40 db 0, 0xf0 windows: times window.size db 0 times window.size db 0 + +launch_filename times FS_DIRENT_NAME_SIZE db 0