Allow launching programs from the shell

This commit is contained in:
Juhani Krekelä 2023-03-23 00:41:12 +02:00
parent ebf106dcc4
commit 6ebb889fcf
5 changed files with 208 additions and 13 deletions

View File

@ -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 $@ $<

39
hello.asm Normal file
View File

@ -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

View File

@ -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

View File

@ -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

171
shell.asm
View File

@ -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