ponydos/shell.asm
2023-03-29 13:17:07 +03:00

1269 lines
22 KiB
NASM

%include "ponydos.inc"
struc window
.next resw 1
.width resw 1
.height resw 1
.x resw 1
.y resw 1
.data resw 1
.icon resb 1
.visible resb 1
.resizable resb 1
.mouse_released_inside resb 1
.status resb 1
.res_x resw 1
.res_y resw 1
.size:
endstruc
WINDOW_ID_ICON equ 0
WINDOW_ID_FILE_WINDOW equ 1
WINDOW_ID_OOM_ERROR equ 2
WINDOW_ID_LAUNCH_ERROR equ 3
WINDOW_MOVE equ 1
WINDOW_RESIZE equ 2
WINDOW_MIN_WIDTH equ 5
WINDOW_MIN_HEIGHT equ 2
cpu 8086
bits 16
org 0
; 0x0000
jmp near process_event
; 0x0003
; out:
; clobbers everything but ds
initialize:
push ds
push cs
pop ds
; Has shell been started already?
mov bp, PONYDOS_SEG
mov es, bp
xor bp, bp
cmp word [es:GLOBAL_WINDOW_CHAIN_HEAD], 0
je .not_relaunch
mov bp, 1
jmp .skip_desktop
.not_relaunch:
; Set wallpaper
call set_wallpaper
; Create icon for the disk on the desktop
mov word [windows + WINDOW_ID_ICON*window.size + window.width], 5
mov word [windows + WINDOW_ID_ICON*window.size + window.height], 3
mov word [windows + WINDOW_ID_ICON*window.size + window.x], 1
mov word [windows + WINDOW_ID_ICON*window.size + window.y], 1
mov word [windows + WINDOW_ID_ICON*window.size + window.data], disk_icon
mov byte [windows + WINDOW_ID_ICON*window.size + window.icon], 1
mov ax, cs
add ax, WINDOW_ID_ICON
mov si, windows + WINDOW_ID_ICON*window.size
call show_window
.skip_desktop:
; Initialize file window but don't show it
mov word [windows + WINDOW_ID_FILE_WINDOW*window.size + window.width], 40
mov word [windows + WINDOW_ID_FILE_WINDOW*window.size + window.height], 17
mov word [windows + WINDOW_ID_FILE_WINDOW*window.size + window.x], 10
mov word [windows + WINDOW_ID_FILE_WINDOW*window.size + window.y], 4
mov word [windows + WINDOW_ID_FILE_WINDOW*window.size + window.data], file_window
mov byte [windows + WINDOW_ID_FILE_WINDOW*window.size + window.resizable], 1
test bp, bp
jz .no_file_window_on_start
.file_window_on_start:
; Offset the window so that it's clearly another window
mov word [windows + WINDOW_ID_FILE_WINDOW*window.size + window.x], 7
mov word [windows + WINDOW_ID_FILE_WINDOW*window.size + window.y], 3
mov ax, cs
add ax, WINDOW_ID_FILE_WINDOW
mov si, windows + WINDOW_ID_FILE_WINDOW*window.size
call show_window
.no_file_window_on_start:
; Initialize error dialogs
mov word [windows + WINDOW_ID_OOM_ERROR*window.size + window.width], 13
mov word [windows + WINDOW_ID_OOM_ERROR*window.size + window.height], 2
mov word [windows + WINDOW_ID_OOM_ERROR*window.size + window.x], 30
mov word [windows + WINDOW_ID_OOM_ERROR*window.size + window.y], 10
mov word [windows + WINDOW_ID_OOM_ERROR*window.size + window.data], oom_error_dialog
mov word [windows + WINDOW_ID_LAUNCH_ERROR*window.size + window.width], FS_DIRENT_NAME_SIZE-1 ; Size includes null terminator
mov word [windows + WINDOW_ID_LAUNCH_ERROR*window.size + window.height], 3
mov word [windows + WINDOW_ID_LAUNCH_ERROR*window.size + window.x], 24
mov word [windows + WINDOW_ID_LAUNCH_ERROR*window.size + window.y], 11
mov word [windows + WINDOW_ID_LAUNCH_ERROR*window.size + window.data], launch_error_dialog
call request_redraw
.end:
pop ds
retf
; in:
; al = event
; bx = window ID
; cx, dx = event specific
; out:
; ax = event specific
process_event:
push bx
push cx
push dx
push si
push di
push bp
push ds
push es
mov bp, cs
mov ds, bp
mov es, bp
cmp al, WM_PAINT
jne .not_paint
call paint
jmp .end
.not_paint:
cmp al, WM_MOUSE
jne .not_mouse
call mouse
jmp .end
.not_mouse:
cmp al, WM_KEYBOARD
jne .not_keyboard
call keyboard
jmp .end
.not_keyboard:
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
call deallocate_own_memory
.windows_open:
pop es
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
retf
; ------------------------------------------------------------------
; Event handlers
; ------------------------------------------------------------------
; in:
; al = WM_PAINT
; bx = window ID
; out:
; clobbers everything
paint:
call get_window
mov bx, [si + window.next]
call send_event
cmp si, windows + WINDOW_ID_FILE_WINDOW*window.size
jne .not_file_window
.file_window:
; See if the dirents have changed since we rendered the
; window contents. If yes, rerender.
push si
mov bp, PONYDOS_SEG
mov es, bp
mov si, dirents
mov di, GLOBAL_DIRENTS
mov cx, FS_DIRENT_SIZE*FS_DIRECTORY_DIRENTS
repe cmpsb
pop si
je .no_rerender
call render_file_window
.no_rerender:
.not_file_window:
; Draw a rectangle on-screen
mov bx, [si + window.width]
mov dx, [si + window.height]
mov di, [si + window.x]
mov bp, [si + window.y]
mov si, [si + window.data]
add dx, bp
cmp dx, ROWS
jle .no_clipping_height
mov dx, ROWS
.no_clipping_height:
sub dx, bp
mov cx, bx
add cx, di
cmp cx, COLUMNS
jle .no_clipping_width_right
mov cx, COLUMNS
.no_clipping_width_right:
sub cx, di
cmp di, 0
jge .no_clipping_width_left
sub si, di
sub si, di
add cx, di
xor di, di
.no_clipping_width_left:
call PONYDOS_SEG:SYS_DRAW_RECT
ret
; in:
; al = WM_MOUSE
; bx = window ID
; cl = X
; ch = Y
; dl = mouse buttons held down
; out:
; clobbers everything
mouse:
call get_window
test dl, MOUSE_PRIMARY | MOUSE_SECONDARY
jnz .any_buttons_held
mov byte [si + window.status], 0
.any_buttons_held:
mov ax, bx
push cx
; Y
xor bx, bx
mov bl, ch
; X
xor ch, ch
cmp byte [si + window.status], WINDOW_MOVE
jne .not_move
call move
.not_move:
cmp byte [si + window.status], WINDOW_RESIZE
jne .not_resize
call resize
.not_resize:
cmp cx, [si + window.x]
jl .outside ; x < window_x
cmp bx, [si + window.y]
jl .outside ; y < window_y
mov bp, [si + window.x]
add bp, [si + window.width]
cmp bp, cx
jle .outside ; window_x + window_width <= x
mov bp, [si + window.y]
add bp, [si + window.height]
cmp bp, bx
jle .outside ; window_y + window_height <= y
cmp byte [si + window.mouse_released_inside], 0
je .not_clicking
test dl, MOUSE_PRIMARY | MOUSE_SECONDARY
jz .not_clicking
.clicking:
call click
.not_clicking:
test dl, MOUSE_PRIMARY | MOUSE_SECONDARY
jz .not_buttons_held
.buttons_held:
mov byte [si + window.mouse_released_inside], 0
jmp .inside
.not_buttons_held:
mov byte [si + window.mouse_released_inside], 1
.inside:
pop cx
xor dx, dx
; Use coördinates (255,255) to make sure other windows in
; the chain don't think the cursor is inside them
mov cx, 0xffff
mov bx, [si + window.next]
mov al, WM_MOUSE
call send_event
ret
.outside:
mov byte [si + window.mouse_released_inside], 0
pop cx
mov bx, [si + window.next]
mov al, WM_MOUSE
call send_event
ret
; in:
; ax = window ID
; bx = Y coördinate
; cx = X coördinate
; dl = which buttons are held down
; si = pointer to window structure
; out:
; 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:
mov ax, cs
add ax, WINDOW_ID_FILE_WINDOW
mov si, windows + WINDOW_ID_FILE_WINDOW*window.size
call show_window
call render_file_window
jmp .end
.file_window:
call raise_window
; Save window ID
mov bp, ax
cmp bx, [si + window.y]
jne .not_title_bar
; Resize button
mov ax, [si + window.x]
cmp byte [si + window.resizable], 0
je .not_resizable
cmp ax, cx
je .resize
.not_resizable:
; Window close button
add ax, [si + window.width]
dec ax
cmp ax, cx
je .close
.move:
mov byte [si + window.status], WINDOW_MOVE
sub cx, [si + window.x]
mov [si + window.res_x], cx ; In-window x-coordinate of press
jmp .end
.resize:
mov byte [si + window.status], WINDOW_RESIZE
add cx, [si + window.width]
mov [si + window.res_x], cx ; Lower right corner + 1
add bx, [si + window.height]
mov [si + window.res_y], bx ; Lower right corner + 1
jmp .end
.close:
call hide_window
jmp .end
.not_title_bar:
; If clicked within the content area
mov ax, bx
sub ax, [si + window.y]
jz .end
dec ax
cmp ax, FS_DIRECTORY_DIRENTS
jae .end
mov bp, FS_DIRENT_SIZE
mul bp
mov si, dirents
add si, ax
cmp word [si], 0
je .end
; Copy file name to launch_filename
add si, FS_DIRENT_NAME_OFFSET
mov di, launch_filename
mov cx, FS_DIRENT_NAME_SIZE
rep movsb
call launch
.end:
pop si
pop dx
ret
; in:
; al = WM_KEYBOARD
; bx = window ID
; cl = typed character
; cl = typed key
; out:
; clobbers everything
keyboard:
ret
; in:
; al = WM_UNHOOK
; bx = window ID
; cx = window to unhook
; out:
; ax = own ID if not the window to unhook
; next ID if the window to unhook
; clobbers everything else
unhook:
call get_window
cmp bx, cx
je .match
push bx
; Forward the event
mov bx, [si + window.next]
call send_event
; Update next ID
; If window.next was zero, send_event will also return zero so
; this is safe in all cases
mov [si + window.next], ax
; Return own ID to keep self in the chain
pop ax
ret
.match:
; Return next ID in the chain to unhook
mov ax, [si + window.next]
ret
; ------------------------------------------------------------------
; Event handler subroutines
; ------------------------------------------------------------------
; in:
; ax = window ID
; bx = Y coördinate
; cx = X coördinate
; si = pointer to window structure
resize:
push dx
push bp
xor bp, bp ; Change?
mov dx, [si + window.res_y]
sub dx, bx
jc .end_y
cmp dx, WINDOW_MIN_HEIGHT
jl .end_y
cmp dx, ROWS
jg .end_y
cmp [si + window.y], bx
je .end_y
inc bp
mov [si + window.y], bx
mov [si + window.height], dx
.end_y:
mov dx, [si + window.res_x]
sub dx, cx
jc .end_x
cmp dx, WINDOW_MIN_WIDTH
jl .end_x
cmp dx, COLUMNS
jg .end_x
cmp [si + window.x], cx
je .end_x
inc bp
mov [si + window.x], cx
mov [si + window.width], dx
.end_x:
test bp, bp
jz .end
call render_file_window
call request_redraw
.end:
pop bp
pop dx
ret
; in:
; ax = window ID
; bx = Y coördinate
; cx = X coördinate
; si = pointer to window structure
move:
push dx
mov dx, cx
sub dx, [si + window.res_x]
cmp [si + window.y], bx
jne .change
cmp [si + window.x], dx
jne .change
jmp .end
.change:
mov [si + window.y], bx
mov [si + window.x], dx
call request_redraw
.end:
pop dx
ret
; ------------------------------------------------------------------
; Launching
; ------------------------------------------------------------------
; out:
; clobbers everything
launch:
mov si, launch_filename
; 4 letter file extension?
call strlen
cmp cx, 5
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
je .wallpaper
.less_than_5_chars:
; 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 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 .file_not_found
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
jmp .out_of_memory
.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
push es ; Save the segment for return value
; Transfer control to the newly loaded binary
push cs ; Return segment
mov ax, .success
push ax ; Return offset
push es ; Call segment
mov ax, PROC_INITIALIZE_ENTRYPOINT
push ax ; Call offset
retf
.success:
pop bx
clc
ret
.file_not_found:
call show_launch_error
jmp .error
.out_of_memory:
; 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
.error:
stc
ret
; out:
; clobbers everything
set_wallpaper:
mov ax, PONYDOS_SEG
mov es, ax
mov si, wallpaper_name
xor dx, dx
call PONYDOS_SEG:SYS_OPEN_FILE
mov bx, GLOBAL_WALLPAPER
xor di, di ; read
call PONYDOS_SEG:SYS_MODIFY_SECTORS
ret
; ------------------------------------------------------------------
; Windows
; ------------------------------------------------------------------
; in:
; bx = window ID
; out:
; ax = return value of event handler; 0 if window ID is 0
send_event:
push bp
cmp bx, 0
je .id_is_zero
push cs ; Return segment
mov bp, .end
push bp ; Return offset
mov bp, 0xf000
and bp, bx
push bp ; Call segment
xor bp, bp
push bp ; Call offset
retf
.id_is_zero:
; This gets skipped over in normal execution, because it
; explicitly returns to .end
xor ax, ax
.end:
pop bp
ret
; in:
; bx = valid window id for this process
; out:
; si = pointer to window structure
get_window:
push bx
mov si, cs
sub bx, si
mov si, windows
push ax
push dx
mov ax, window.size
mul bx
add si, ax
pop dx
pop ax
pop bx
ret
; in:
; ax = window ID
; si = pointer to window structure
show_window:
push ax
cmp byte [si + window.visible], 0
je .not_yet_visible
call raise_window
jmp .end
.not_yet_visible:
call hook_window
mov [si + window.next], ax
mov byte [si + window.visible], 1
call request_redraw
inc byte [open_windows]
.end:
pop ax
ret
; in:
; bp = window ID
; si = pointer to window structure
hide_window:
push cx
mov cx, bp
call unhook_window
mov byte [si + window.visible], 0
call request_redraw
dec byte [open_windows]
pop cx
ret
; in:
; ax = window ID to hook
; out:
; ax = next window ID
hook_window:
push bp
push es
mov bp, PONYDOS_SEG
mov es, bp
xchg [es:GLOBAL_WINDOW_CHAIN_HEAD], ax
pop es
pop bp
ret
; in:
; cx = window ID to unhook
unhook_window:
push ax
push bx
push es
mov bx, PONYDOS_SEG
mov es, bx
mov bx, [es:GLOBAL_WINDOW_CHAIN_HEAD]
mov al, WM_UNHOOK
call send_event
mov [es:GLOBAL_WINDOW_CHAIN_HEAD], ax
pop es
pop bx
pop ax
ret
; in:
; ax = window ID to raise
raise_window:
push ax
push bx
push cx
push si
push es
mov cx, PONYDOS_SEG
mov es, cx
cmp [es:GLOBAL_WINDOW_CHAIN_HEAD], ax
je .already_top
mov bx, ax
call get_window
mov cx, ax
call unhook_window
call hook_window
mov [si + window.next], ax
call request_redraw
.already_top:
pop es
pop si
pop cx
pop bx
pop ax
ret
; ------------------------------------------------------------------
; Painting
; ------------------------------------------------------------------
; in
; si = pointer to window structure
render_file_window:
call copy_dirents
push ax
push cx
push dx
push di
push es
mov ax, cs
mov es, ax
mov di, [si + window.data]
mov cx, [si + window.width]
mov ax, 0x0f00
rep stosw
mov cx, (ROWS-1)*COLUMNS
mov ax, 0xf000
rep stosw
mov di, [si + window.data]
mov byte [di], 0x17
mov byte [di + 2], 'A'
mov byte [di + 4], ':'
add di, [si + window.width]
add di, [si + window.width]
mov byte [di - 2], 'x'
mov cx, [si + window.height]
dec cx
mov dx, [si + window.width]
call print_ls
pop es
pop di
pop dx
pop cx
pop ax
ret
request_redraw:
push es
push ax
mov ax, PONYDOS_SEG
mov es, ax
mov byte [es:GLOBAL_REDRAW], 1
pop ax
pop es
ret
; ------------------------------------------------------------------
; File access
; ------------------------------------------------------------------
; in
; cx = height of window (>= 1)
; dx = width of window in characters
; es:di = start of output
print_ls:
push ax
push bx
push cx
push si
push di
push bp
push cx
push di
mov si, dirents + FS_DIRENT_NAME_OFFSET
xor ax, ax ; Maximum filename size
.name_loop:
cmp word [si - FS_DIRENT_NAME_OFFSET], 0
je .done_names
push cx
call strlen
mov bx, cx
pop cx
cmp bx, dx
jle .not_long_filename
mov bx, dx
.not_long_filename:
cmp ax, bx
jge .not_new_max
mov ax, bx
.not_new_max:
push si
push di
.copy:
movsb
inc di ; Formatting
dec bx
jnz .copy
pop di
pop si
; Move to next line
add di, dx
add di, dx
add si, FS_DIRENT_SIZE
cmp si, dirents + FS_DIRECTORY_DIRENTS*FS_DIRENT_SIZE
jge .done_names
dec cx
jnz .name_loop
.done_names:
pop di
pop cx
; Don't print sizes for too short a window
cmp dx, 10
jle .done
add ax, 5 ; 1 whitespace, 4 length
cmp ax, dx
jle .not_truncate
mov ax, dx
.not_truncate:
sub ax, 5 ; Go to start of where to put the file length
add di, ax
add di, ax
mov si, dirents
.size_loop:
mov ax, word [si]
test ax, ax
jz .done
mov byte [di + 8], 'K'
shr ax, 1
aam ; mango
add ax, 0x3030
cmp ah, 0x30
je .one_digit
mov byte [di + 2], ' '
mov [di + 4], ah
jmp .one_digit_print
.one_digit:
test word [si], 1
jnz .one_and_half_digit
mov byte [di + 4], ' '
.one_digit_print:
mov [di + 6], al
jmp .next_iter_size_loop
.one_and_half_digit:
mov byte [di], ' '
mov byte [di + 2], al
mov byte [di + 4], '.'
mov byte [di + 6], '5'
.next_iter_size_loop:
; Move to next line
add di, dx
add di, dx
add si, FS_DIRENT_SIZE
cmp si, dirents + FS_DIRECTORY_DIRENTS*FS_DIRENT_SIZE
jge .done
dec cx
jnz .size_loop
.done:
pop bp
pop di
pop si
pop cx
pop bx
pop ax
ret
copy_dirents:
push cx
push si
push di
push ds
push es
mov bp, PONYDOS_SEG
mov ds, bp
mov bp, cs
mov es, bp
mov si, GLOBAL_DIRENTS
mov di, dirents
mov cx, FS_DIRENT_SIZE*FS_DIRECTORY_DIRENTS
rep movsb
pop es
pop ds
pop di
pop si
pop cx
ret
; ------------------------------------------------------------------
; Memory management
; ------------------------------------------------------------------
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
; ------------------------------------------------------------------
; String routines
; ------------------------------------------------------------------
; in:
; ds:si = string
; out:
; cx = strlen
strlen:
push ax
push di
push es
mov cx, ds
mov es, cx
mov di, si
mov cx, -1
xor ax, ax
repne scasb
not cx
dec cx
pop es
pop di
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
; ------------------------------------------------------------------
; 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
viewer_file_name db 'viewer.bin', 0
; ------------------------------------------------------------------
; Variables
; ------------------------------------------------------------------
disk_icon:
db 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f
db 0x00, 0x0f, 0x00, 0x0f, 0x09, 0x0f, 0x00, 0x0f, 0x00, 0x0f
db 0x00, 0x0f, 0x00, 0x0f, '|', 0x0f, 0x00, 0x0f, 0x00, 0x0f
oom_error_dialog:
db 'E', 0x0f, 'r', 0x0f, 'r', 0x0f, 'o', 0x0f, 'r', 0x0f
times 13-5-1 db 0x00, 0x0f
db 'x', 0x0f
db 'O', 0xf0, 'u', 0xf0, 't', 0xf0, ' ', 0xf0, 'o', 0xf0, 'f', 0xf0
db ' ', 0xf0, 'm', 0xf0, 'e', 0xf0, 'm', 0xf0, 'o', 0xf0, 'r', 0xf0
db 'y', 0xf0
launch_error_dialog:
db 'E', 0x0f, 'r', 0x0f, 'r', 0x0f, 'o', 0x0f, 'r', 0x0f
times FS_DIRENT_NAME_SIZE-1-5-1 db 0x00, 0x0f
db 'x', 0x0f
db 'C', 0xf0, 'a', 0xf0, 'n', 0xf0, 'n', 0xf0, 'o', 0xf0, 't', 0xf0
db ' ', 0xf0, 'l', 0xf0, 'a', 0xf0, 'u', 0xf0, 'n', 0xf0, 'c', 0xf0
db 'h', 0xf0, ' ', 0xf0, 'f', 0xf0, 'i', 0xf0, 'l', 0xf0, 'e', 0xf0
db ':', 0xf0
times FS_DIRENT_NAME_SIZE-1-19 db 0x00, 0xf0
.filename times FS_DIRENT_NAME_SIZE-1 db 0x00, 0xf0
windows:
times window.size db 0
times window.size db 0
times window.size db 0
times window.size db 0
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
dirents:
resb FS_DIRENT_SIZE*FS_DIRECTORY_DIRENTS
file_window:
resw ROWS*COLUMNS