Compare commits

...

8 Commits

Author SHA1 Message Date
Juhani Krekelä a496c5ce9d Fix typo 2023-03-29 16:46:17 +03:00
Juhani Krekelä 54a6755a5b Get README.md release-ready 2023-03-29 13:29:41 +03:00
Juhani Krekelä 5129f3f3b4 Lower mouse sensitivity 2023-03-29 13:28:36 +03:00
Juhani Krekelä 0b5fd0d84e Deallocate program memory only at end of event dispatch
Previously programs deallocated their memory before forwarding a
message. If the forwarded message made another program allocate, this
could cause the program code to be overwritten while it is still
running.
2023-03-29 13:24:28 +03:00
Juhani Krekelä 3f5d4ebd16 Fix typo that broke builds 2023-03-29 13:23:06 +03:00
Juhani Krekelä 8bea9d6120 Add stub WM_OPEN_FILE handler to hello.asm 2023-03-29 13:17:07 +03:00
Juhani Krekelä cb77e27fb2 Allow opening text files by clicking on them in the file window 2023-03-29 13:04:47 +03:00
Juhani Krekelä ceb7745b42 Exit with error from open_file if file is not found and asked to not create one 2023-03-29 12:21:13 +03:00
7 changed files with 293 additions and 90 deletions

View File

@ -68,16 +68,5 @@ You don't.
#### How do I install PonyDOS?
At the moment, PonyOS is only offered as a live floppy disk image with no
At the moment, PonyDOS is only offered as a live floppy disk image with no
installation option, for your safety.
## TODO
### Basic stuff
* be able to click on asm/text files in file listing to open
* delete the TODO from release README
### Nice to have
* ponysay

View File

@ -51,9 +51,14 @@ process_event:
push es
; On entry, ds and es will not be set correctly for us
mov bp, cs
mov ds, bp
mov es, bp
; WM_OPEN_FILE needs ds to be left-as is
cmp al, WM_OPEN_FILE
je .no_set_ds
push cs
pop ds
.no_set_ds:
push cs
pop es
cmp al, WM_PAINT
jne .not_paint
@ -79,7 +84,21 @@ process_event:
jmp .end
.not_unhook:
cmp al, WM_OPEN_FILE
jne .not_open_file
call event_open_file
jmp .end
.not_open_file:
.end:
cmp byte [exiting], 0
je .not_exiting
; Once we have deallocated our own memory, we may not call any
; external functions that might allocate. Safest place to do the
; deallocation is just before returning control to our caller
call deallocate_own_memory
.not_exiting:
pop es
pop ds
pop bp
@ -278,10 +297,7 @@ event_click:
jne .not_close
.close:
call unhook_self_from_window_chain
; Nothing can call into us again after we unhook
; the window, so deallocate the memory we have
; reserved
call deallocate_own_memory
mov byte [exiting], 1
; We don't need to call request_redraw here, since
; it will be called unconditionally above
jmp .title_bar_end
@ -316,7 +332,7 @@ event_click:
; out:
; clobbers everything
event_keyboard:
; Unlike other events, keyboard events are not forwarded
; Unlike most other events, keyboard events are not forwarded
; Since we do not care about the keyboard for this app, we just
; swallow the event
ret
@ -353,6 +369,24 @@ event_unhook:
mov ax, [window_next]
ret
; in:
; al = WM_OPEN_FILE
; ds:cx = filename
; ds ≠ cs
; out:
; ds = cs
; clobbers everything
event_open_file:
; File open events are sent specifically to a process, so we don't
; need to forward it
; Unlike other event handlers, event_open_file is called with ds
; still set to calling process's segment, so that it can read the
; passed-in filename. For simplicity of code running after the,
; event handlers, we set ds to point to our own segment on return
push cs
pop ds
ret
; ------------------------------------------------------------------
; Event handler subroutines
; ------------------------------------------------------------------
@ -643,6 +677,8 @@ request_redraw:
; Variables
; ------------------------------------------------------------------
exiting db 0
window_title db 'Hello'
.end:
WINDOW_TITLE_LEN equ window_title.end - window_title

View File

@ -72,7 +72,21 @@ process_event:
jmp .end
.not_unhook:
cmp al, WM_OPEN_FILE
jne .not_open_file
call event_open_file
jmp .end
.not_open_file:
.end:
cmp byte [exiting], 0
je .not_exiting
; Once we have deallocated our own memory, we may not call any
; external functions that might allocate. Safest place to do the
; deallocation is just before returning control to our caller
call deallocate_own_memory
.not_exiting:
pop es
pop ds
pop bp
@ -267,10 +281,7 @@ event_click:
jne .not_close
.close:
call unhook_self_from_window_chain
; Nothing can call into us again after we unhook
; the window, so deallocate the memory we have
; reserved
call deallocate_own_memory
mov byte [exiting], 1
; We don't need to call request_redraw here, since
; it will be called unconditionally above
jmp .title_bar_end
@ -297,7 +308,7 @@ event_click:
; out:
; clobbers everything
event_keyboard:
; Unlike other events, keyboard events are not forwarded
; Unlike most other events, keyboard events are not forwarded
; Since we do not care about the keyboard for this app, we just
; swallow the event
ret
@ -334,6 +345,24 @@ event_unhook:
mov ax, [window_next]
ret
; in:
; al = WM_OPEN_FILE
; ds:cx = filename
; ds ≠ cs
; out:
; ds = cs
; clobbers everything
event_open_file:
; File open events are sent specifically to a process, so we don't
; need to forward it
; Unlike other event handlers, event_open_file is called with ds
; still set to calling process's segment, so that it can read the
; passed-in filename. For simplicity of code running after the,
; event handlers, we set ds to point to our own segment on return
push cs
pop ds
ret
; ------------------------------------------------------------------
; Event handler subroutines
; ------------------------------------------------------------------
@ -530,6 +559,8 @@ request_redraw:
; Variables
; ------------------------------------------------------------------
exiting db 0
window_next dw 0xffff
window_x dw 65
window_y dw 3

View File

@ -8,8 +8,8 @@ bits 16
org 0x7c00
X_SENSITIVITY equ 1
Y_SENSITIVITY equ 2
X_SENSITIVITY equ 3
Y_SENSITIVITY equ 3
jmp 0:start
@ -328,7 +328,8 @@ shell_name db 'shell.bin', 0
; ds:si = file name
; dx = non-zero => do not create new file
; out:
; ax = LBA of first sector, 0 if no space left
; ax = LBA of first sector, 0 if no space left or if dx non-zero and the
; specified file was not found
; cx = length in sectors
; di = dirent address (in GLOBAL_DIRENTS)
; [Far calls only]
@ -386,7 +387,7 @@ open_file:
.create_file:
test dx, dx
jnz .return
jnz .error
; TODO: zero out the sector for this file?
inc word [es:di]

View File

@ -16,6 +16,7 @@ WM_PAINT equ 0
WM_MOUSE equ 1
WM_KEYBOARD equ 2
WM_UNHOOK equ 3
WM_OPEN_FILE equ 4
MOUSE_PRIMARY equ 0x01
MOUSE_SECONDARY equ 0x02

192
shell.asm
View File

@ -150,8 +150,11 @@ process_event:
cmp al, WM_UNHOOK
jne .not_remove
call unhook
jmp .end
.not_remove:
; We ignore WM_OPEN_FILE
.end:
cmp byte [open_windows], 0
jne .windows_open
@ -181,7 +184,7 @@ paint:
call get_window
mov bx, [si + window.next]
call forward_event
call send_event
cmp si, windows + WINDOW_ID_FILE_WINDOW*window.size
jne .not_file_window
@ -308,7 +311,7 @@ mouse:
mov cx, 0xffff
mov bx, [si + window.next]
mov al, WM_MOUSE
call forward_event
call send_event
ret
.outside:
@ -316,7 +319,7 @@ mouse:
pop cx
mov bx, [si + window.next]
mov al, WM_MOUSE
call forward_event
call send_event
ret
; in:
@ -442,10 +445,10 @@ unhook:
; Forward the event
mov bx, [si + window.next]
call forward_event
call send_event
; Update next ID
; If window.next was zero, forward_event will also return zero so
; If window.next was zero, send_event will also return zero so
; this is safe in all cases
mov [si + window.next], ax
@ -542,49 +545,129 @@ move:
pop dx
ret
; ------------------------------------------------------------------
; Launching
; ------------------------------------------------------------------
; out:
; clobbers everything
launch:
mov si, launch_filename
; Is it a .wall file?
; 4 letter file extension?
call strlen
cmp cx, 5
jb .not_wall
jb .less_than_5_chars
add si, cx
sub si, 5
; .text
mov di, text_extension
call strcmp
je .text_file
; .wall
mov di, wall_extension
call strcmp
jne .not_wall
je .wallpaper
.less_than_5_chars:
mov ax, cs
mov es, ax
mov si, launch_filename
mov di, wallpaper_name
mov cx, FS_DIRENT_NAME_SIZE
rep movsb
call set_wallpaper
call request_redraw
jmp .end
.not_wall:
; Is it a .bin file?
; 3 letter file extension?
cmp cx, 4
jb .not_launchable ; No, too short
mov si, launch_filename
add si, cx
sub si, 4
; .asm
mov di, asm_extension
call strcmp
je .text_file
; .txt
mov di, txt_extension
call strcmp
je .text_file
; .bin
mov di, bin_extension
call strcmp
jne .not_launchable ; No, wrong extension
jne .not_launchable ; No extension matched
mov si, launch_filename
call launch_binary
ret
.wallpaper:
mov ax, cs
mov es, ax
mov si, launch_filename
mov di, wallpaper_name
mov cx, FS_DIRENT_NAME_SIZE
rep movsb
call set_wallpaper
call request_redraw
ret
.not_launchable:
; Copy filename into the launch error dialog
mov si, launch_filename
call show_launch_error
ret
.text_file:
; Launch viewer.bin if it exists
mov si, viewer_file_name
call launch_binary
jc .viewer_not_found
; Send the WM_OPEN_FILE event to tell viewer the file we
; want it to open. launch_binary returned its segment in bx
; so we can just pass that to send_event, as window IDs are
; of the form segment | internal_id.
mov al, WM_OPEN_FILE
mov cx, launch_filename
call send_event
.viewer_not_found:
ret
; in:
; si = name of file not launchable
; out:
; clobbers everything
show_launch_error:
mov di, launch_error_dialog.filename
mov cx, FS_DIRENT_NAME_SIZE-1
mov ah, 0xf0
.copy:
lodsb
test al, al
je .copy_end
stosw
loop .copy
.copy_end:
; Zero out the rest
xor al, al
rep stosw
; Show dialog
mov ax, cs
add ax, WINDOW_ID_LAUNCH_ERROR
mov si, windows + WINDOW_ID_LAUNCH_ERROR*window.size
call show_window
ret
; in:
; si = name of the binary to launch
; out:
; cf = error occured when launching binary
; bx = segment of the launched binary
; clobbers everything else
launch_binary:
mov dx, 1 ; Don't create a new file if not found
call PONYDOS_SEG:SYS_OPEN_FILE
test ax, ax
jz .not_launchable
jz .file_not_found
push ax
push cx
@ -600,14 +683,7 @@ launch:
jz .found_free_segment
inc si
loop .find_free_segment
; Display an error dialog if we can't allocate a segment
mov ax, cs
add ax, WINDOW_ID_OOM_ERROR
mov si, windows + WINDOW_ID_OOM_ERROR*window.size
call show_window
pop cx
pop ax
jmp .end
jmp .out_of_memory
.found_free_segment:
mov byte [es:si], 1 ; Mark as used
@ -623,34 +699,37 @@ launch:
xor di, di ; Read
call PONYDOS_SEG:SYS_MODIFY_SECTORS
push es ; Save the segment for return value
; Transfer control to the newly loaded binary
push cs ; Return segment
mov ax, .end
mov ax, .success
push ax ; Return offset
push es ; Call segment
mov ax, PROC_INITIALIZE_ENTRYPOINT
push ax ; Call offset
retf
.end:
.success:
pop bx
clc
ret
.not_launchable:
; Copy filename into the launch error dialog
mov si, launch_filename
mov di, launch_error_dialog.filename
mov cx, FS_DIRENT_NAME_SIZE-1
.loop:
lodsb
stosb
inc di
loop .loop
.file_not_found:
call show_launch_error
jmp .error
; Show dialog
.out_of_memory:
; Display an error dialog if we can't allocate a segment
mov ax, cs
add ax, WINDOW_ID_LAUNCH_ERROR
mov si, windows + WINDOW_ID_LAUNCH_ERROR*window.size
add ax, WINDOW_ID_OOM_ERROR
mov si, windows + WINDOW_ID_OOM_ERROR*window.size
call show_window
pop cx
pop ax
.error:
stc
ret
; out:
@ -675,7 +754,7 @@ set_wallpaper:
; bx = window ID
; out:
; ax = return value of event handler; 0 if window ID is 0
forward_event:
send_event:
push bp
cmp bx, 0
@ -796,7 +875,7 @@ unhook_window:
mov bx, [es:GLOBAL_WINDOW_CHAIN_HEAD]
mov al, WM_UNHOOK
call forward_event
call send_event
mov [es:GLOBAL_WINDOW_CHAIN_HEAD], ax
@ -1130,14 +1209,20 @@ strcmp:
ret
; ------------------------------------------------------------------
; Variables
; Constants
; ------------------------------------------------------------------
asm_extension db '.asm', 0
bin_extension db '.bin', 0
txt_extension db '.txt', 0
text_extension db '.text', 0
wall_extension db '.wall', 0
wallpaper_name db 'ponydos.wall'
times FS_DIRENT_NAME_SIZE-12 db 0
viewer_file_name db 'viewer.bin', 0
; ------------------------------------------------------------------
; Variables
; ------------------------------------------------------------------
disk_icon:
db 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f
@ -1171,6 +1256,9 @@ windows:
open_windows db 0
wallpaper_name db 'ponydos.wall'
times FS_DIRENT_NAME_SIZE-12 db 0
launch_filename times FS_DIRENT_NAME_SIZE db 0
section .bss

View File

@ -51,9 +51,14 @@ process_event:
push es
; On entry, ds and es will not be set correctly for us
mov bp, cs
mov ds, bp
mov es, bp
; WM_OPEN_FILE needs ds to be left-as is
cmp al, WM_OPEN_FILE
je .no_set_ds
push cs
pop ds
.no_set_ds:
push cs
pop es
cmp al, WM_PAINT
jne .not_paint
@ -79,7 +84,18 @@ process_event:
jmp .end
.not_unhook:
cmp al, WM_OPEN_FILE
jne .not_open_file
call event_open_file
jmp .end
.not_open_file:
.end:
cmp byte [exiting], 0
je .not_exiting
call deallocate_own_memory
.not_exiting:
pop es
pop ds
pop bp
@ -579,7 +595,7 @@ event_click:
jne .not_cancel
.cancel:
call unhook_self_from_window_chain
call deallocate_own_memory
mov byte [exiting], 1
jmp .end
.not_cancel:
cmp byte [bx], OK_COLOR
@ -735,6 +751,39 @@ event_unhook:
mov ax, [window_next]
ret
; in:
; al = WM_OPEN_FILE
; ds:cx = filename
; ds ≠ cs
; out:
; ds = cs
; clobbers everything
event_open_file:
; Copy the file name over
mov si, cx
mov di, [es:cur_filename_address]
.copy_filename:
lodsb
test al, al
jz .copy_end
stosb
inc di
jmp .copy_filename
.copy_end:
mov [es:cur_filename_address], di
; Set ds to be as expected by most of the program
push cs
pop ds
; Mark that the filename came from WM_OPEN_FILE
mov byte [filename_from_wm_open_file], 1
call filename_ok
ret
; ------------------------------------------------------------------
; Event handler subroutines
; ------------------------------------------------------------------
@ -742,15 +791,20 @@ event_unhook:
; out:
; clobbers si, di, cx
close_window:
; If filename was from WM_OPEN_FILE event instead of user input,
; exit the app instead of going to name input dialog
cmp byte [filename_from_wm_open_file], 0
jne .exit_app
cmp word [window.data_address], oom_window_data
je .error_window
cmp word [window.data_address], ood_window_data
je .error_window
.not_error_window:
; Shut off app
.exit_app:
call unhook_self_from_window_chain
call deallocate_own_memory
mov byte [exiting], 1
ret
.error_window:
mov si, filename_window
mov di, window
@ -1116,10 +1170,13 @@ request_redraw:
; Variables
; ------------------------------------------------------------------
filename_from_wm_open_file db 0
exiting db 0
window_title times FS_DIRENT_NAME_SIZE db 0
cur_file_address: dw 0 ; Segment
dw 0
cur_file_address: dw 0
dw 0 ; Segment
beg_file_address dw 0
end_file_address dw 0