ponydos/shell.asm
Juhani Krekelä d4c15687c8 Add option for 8-colour mode
Some BIOSs initialize the VGA card by default into a mode where the high
bit of background nybble signals that the cell should blink. The simple
way to avoid this is by restricting the background colours to the range
0…7. However, since our mouse cursor is implemented by swapping the
foreground and the background colours, we also need to restrict the
foreground colours to the range 0…7.
2023-05-11 22:02:18 +03:00

1281 lines
23 KiB
NASM

%include "ponydos.inc"
cpu 8086
bits 16
%ifdef BLINKY
TITLEBAR_ATTRIBUTE equ 0x07
WINDOW_ATTRIBUTE equ 0x70
DISK_ATTRIBUTE equ 0x07
%else
TITLEBAR_ATTRIBUTE equ 0x0f
WINDOW_ATTRIBUTE equ 0xf0
DISK_ATTRIBUTE equ 0x0f
%endif
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, WINDOW_ATTRIBUTE
.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, TITLEBAR_ATTRIBUTE<<8
rep stosw
mov cx, (ROWS-1)*COLUMNS
mov ax, WINDOW_ATTRIBUTE<<8
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, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE
db 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x09, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE
db 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, '|', DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE
oom_error_dialog:
db 'E', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'o', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE
times 13-5-1 db 0x00, TITLEBAR_ATTRIBUTE
db 'x', TITLEBAR_ATTRIBUTE
db 'O', WINDOW_ATTRIBUTE, 'u', WINDOW_ATTRIBUTE, 't', WINDOW_ATTRIBUTE, ' ', WINDOW_ATTRIBUTE, 'o', WINDOW_ATTRIBUTE, 'f', WINDOW_ATTRIBUTE
db ' ', WINDOW_ATTRIBUTE, 'm', WINDOW_ATTRIBUTE, 'e', WINDOW_ATTRIBUTE, 'm', WINDOW_ATTRIBUTE, 'o', WINDOW_ATTRIBUTE, 'r', WINDOW_ATTRIBUTE
db 'y', WINDOW_ATTRIBUTE
launch_error_dialog:
db 'E', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'o', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE
times FS_DIRENT_NAME_SIZE-1-5-1 db 0x00, TITLEBAR_ATTRIBUTE
db 'x', TITLEBAR_ATTRIBUTE
db 'C', WINDOW_ATTRIBUTE, 'a', WINDOW_ATTRIBUTE, 'n', WINDOW_ATTRIBUTE, 'n', WINDOW_ATTRIBUTE, 'o', WINDOW_ATTRIBUTE, 't', WINDOW_ATTRIBUTE
db ' ', WINDOW_ATTRIBUTE, 'l', WINDOW_ATTRIBUTE, 'a', WINDOW_ATTRIBUTE, 'u', WINDOW_ATTRIBUTE, 'n', WINDOW_ATTRIBUTE, 'c', WINDOW_ATTRIBUTE
db 'h', WINDOW_ATTRIBUTE, ' ', WINDOW_ATTRIBUTE, 'f', WINDOW_ATTRIBUTE, 'i', WINDOW_ATTRIBUTE, 'l', WINDOW_ATTRIBUTE, 'e', WINDOW_ATTRIBUTE
db ':', WINDOW_ATTRIBUTE
times FS_DIRENT_NAME_SIZE-1-19 db 0x00, WINDOW_ATTRIBUTE
.filename times FS_DIRENT_NAME_SIZE-1 db 0x00, WINDOW_ATTRIBUTE
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