Add basic viewer
This commit is contained in:
parent
bd9a62c1ce
commit
cdf0f77379
2
Makefile
2
Makefile
|
@ -6,7 +6,7 @@ PYTHON = python3
|
|||
|
||||
all: ponydos.img
|
||||
|
||||
FS_FILES = ponydos.wall passion.wall shell.bin hello.bin
|
||||
FS_FILES = shell.bin ponydos.wall passion.wall viewer.bin hello.bin ponydos.asm
|
||||
|
||||
ponydos.img: ponydos.bin $(FS_FILES)
|
||||
$(PYTHON) assemble_floppy.py $@ ponydos.bin $(FS_FILES)
|
||||
|
|
|
@ -662,4 +662,4 @@ window_status db WINDOW_STATUS_NORMAL
|
|||
window_move_x_offset dw 0
|
||||
|
||||
section .bss
|
||||
window_data resw 25*80
|
||||
window_data resw ROWS*COLUMNS
|
||||
|
|
|
@ -0,0 +1,906 @@
|
|||
%include "ponydos.inc"
|
||||
cpu 8086
|
||||
bits 16
|
||||
|
||||
WINDOW_STATUS_NORMAL equ 0
|
||||
WINDOW_STATUS_MOVE equ 1
|
||||
WINDOW_STATUS_RESIZE equ 2
|
||||
|
||||
; Resize button, title, space, close button
|
||||
WINDOW_MIN_WIDTH equ 1 + 8 + 1 + 1
|
||||
WINDOW_MIN_HEIGHT equ 2
|
||||
|
||||
; 0x0000
|
||||
jmp near process_event
|
||||
|
||||
; 0x0003 PROC_INITIALIZE_ENTRYPOINT
|
||||
; initialize needs to preserve ds
|
||||
; in:
|
||||
; ds:si = text filename
|
||||
; ax:bx = file address
|
||||
; cx = text file size in sectors
|
||||
initialize:
|
||||
push ds
|
||||
|
||||
; Setup the input parameters for now
|
||||
mov bp, cs
|
||||
mov ds, bp
|
||||
mov si, tmp_window_title
|
||||
mov dx, 1
|
||||
call PONYDOS_SEG:SYS_OPEN_FILE ; TODO: error
|
||||
|
||||
mov dx, 0xF000
|
||||
mov es, dx
|
||||
xor bx, bx
|
||||
xor di, di ; read
|
||||
call PONYDOS_SEG:SYS_MODIFY_SECTORS
|
||||
mov ax, es
|
||||
; End of temporary set-up
|
||||
|
||||
; On entry, ds and es will not be set correctly for us
|
||||
mov bp, cs
|
||||
mov es, bp
|
||||
|
||||
push cx
|
||||
call strlen
|
||||
mov di, window_title
|
||||
rep movsb
|
||||
pop cx
|
||||
|
||||
mov ds, bp
|
||||
|
||||
mov [cur_file_address + 2], ax
|
||||
mov [cur_file_address], bx
|
||||
mov [beg_file_address], bx
|
||||
shl cx, 1 ; 2
|
||||
shl cx, 1 ; 4
|
||||
shl cx, 1 ; 8
|
||||
shl cx, 1 ; 16
|
||||
shl cx, 1 ; 32
|
||||
shl cx, 1 ; 64
|
||||
shl cx, 1 ; 128
|
||||
shl cx, 1 ; 256
|
||||
shl cx, 1 ; 512
|
||||
add bx, cx
|
||||
mov [end_file_address], bx
|
||||
|
||||
call hook_self_onto_window_chain
|
||||
|
||||
call render_window
|
||||
|
||||
; We must explicitly request redraw from the compositor
|
||||
call request_redraw
|
||||
|
||||
pop ds
|
||||
retf
|
||||
|
||||
; process_event needs to preserve all registers other than ax
|
||||
; 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
|
||||
|
||||
; On entry, ds and es will not be set correctly for us
|
||||
mov bp, cs
|
||||
mov ds, bp
|
||||
mov es, bp
|
||||
|
||||
cmp al, WM_PAINT
|
||||
jne .not_paint
|
||||
call event_paint
|
||||
jmp .end
|
||||
.not_paint:
|
||||
|
||||
cmp al, WM_MOUSE
|
||||
jne .not_mouse
|
||||
call event_mouse
|
||||
jmp .end
|
||||
.not_mouse:
|
||||
|
||||
cmp al, WM_KEYBOARD
|
||||
jne .not_keyboard
|
||||
call event_keyboard
|
||||
jmp .end
|
||||
.not_keyboard:
|
||||
|
||||
cmp al, WM_UNHOOK
|
||||
jne .not_unhook
|
||||
call event_unhook
|
||||
jmp .end
|
||||
.not_unhook:
|
||||
|
||||
.end:
|
||||
pop es
|
||||
pop ds
|
||||
pop bp
|
||||
pop di
|
||||
pop si
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
retf
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; File handlers
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
; in:
|
||||
; es:di = where to start printing on screen
|
||||
print_file:
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push si
|
||||
push di
|
||||
push ds
|
||||
|
||||
lds si, [cur_file_address]
|
||||
|
||||
mov cx, [cs:window_height]
|
||||
dec cx
|
||||
mov dx, [cs:window_width]
|
||||
mov bl, 1 ; Haven't read anything yet
|
||||
.window_loop:
|
||||
push di
|
||||
.line_loop:
|
||||
cmp si, [cs:end_file_address]
|
||||
jne .not_end_file
|
||||
test bl, bl
|
||||
jz .end_window_loop ; Need to have read something to hit end-of-file
|
||||
|
||||
.not_end_file:
|
||||
lodsb
|
||||
xor bl, bl ; Have read something
|
||||
|
||||
; Special byte handling
|
||||
cmp al, 0x0A ; \n
|
||||
je .next_line
|
||||
|
||||
cmp al, 0x09 ; \t
|
||||
jne .null_check
|
||||
add di, 8
|
||||
sub dx, 4
|
||||
jc .next_line
|
||||
jz .next_line
|
||||
jmp .line_loop
|
||||
|
||||
.null_check:
|
||||
test al, al
|
||||
jz .end_window_loop
|
||||
|
||||
stosb
|
||||
inc di
|
||||
dec dx
|
||||
jnz .line_loop
|
||||
.next_line:
|
||||
mov dx, [cs:window_width]
|
||||
|
||||
pop di
|
||||
add di, [cs:window_width]
|
||||
add di, [cs:window_width]
|
||||
loop .window_loop
|
||||
|
||||
.ret:
|
||||
pop ds
|
||||
pop di
|
||||
pop si
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
.end_window_loop:
|
||||
pop di
|
||||
jmp .ret
|
||||
|
||||
; out:
|
||||
; dx = non-zero if cur_file_address is updated
|
||||
file_next_line:
|
||||
push ax
|
||||
push si
|
||||
push ds
|
||||
|
||||
xor dx, dx
|
||||
|
||||
lds si, [cur_file_address]
|
||||
|
||||
.loop:
|
||||
lodsb
|
||||
|
||||
cmp al, 0x0A ; \n
|
||||
je .found_next_line
|
||||
|
||||
test al, al
|
||||
jz .ret
|
||||
|
||||
cmp si, [cs:end_file_address]
|
||||
je .ret
|
||||
|
||||
jmp .loop
|
||||
|
||||
.found_next_line:
|
||||
cmp si, [cs:end_file_address]
|
||||
je .ret
|
||||
|
||||
cmp byte [ds:si], 0
|
||||
je .ret
|
||||
|
||||
not dx
|
||||
mov [cs:cur_file_address], si
|
||||
|
||||
.ret:
|
||||
pop ds
|
||||
pop si
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; out:
|
||||
; dx = non-zero if cur_file_address is updated
|
||||
file_prev_line:
|
||||
push ax
|
||||
push si
|
||||
push ds
|
||||
|
||||
std
|
||||
|
||||
xor dx, dx
|
||||
|
||||
lds si, [cur_file_address]
|
||||
cmp si, [cs:beg_file_address] ; Already at the beginning?
|
||||
je .ret
|
||||
|
||||
dec si
|
||||
cmp si, [cs:beg_file_address] ; Last line was empty?
|
||||
je .ret
|
||||
|
||||
dec si
|
||||
.loop:
|
||||
cmp si, [cs:beg_file_address]
|
||||
je .found_prev_line
|
||||
lodsb
|
||||
|
||||
cmp al, 0x0A ; \n
|
||||
jne .loop
|
||||
|
||||
inc si
|
||||
inc si
|
||||
|
||||
.found_prev_line:
|
||||
not dx
|
||||
mov [cs:cur_file_address], si
|
||||
|
||||
.ret:
|
||||
cld
|
||||
|
||||
pop ds
|
||||
pop si
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Event handlers
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
; in:
|
||||
; al = WM_PAINT
|
||||
; bx = window ID
|
||||
; out:
|
||||
; clobbers everything
|
||||
event_paint:
|
||||
; Forward the paint event to the next window in the chain
|
||||
; We must do this before we paint ourselves, because painting must
|
||||
; happen from the back to the front
|
||||
; Because we only have one window, we don't need to save our own ID
|
||||
mov bx, [window_next]
|
||||
call send_event
|
||||
|
||||
mov bx, [window_width] ; Buffer width, usually same as window width
|
||||
mov cx, [window_width]
|
||||
mov dx, [window_height]
|
||||
mov si, window_data
|
||||
mov di, [window_x]
|
||||
mov bp, [window_y]
|
||||
|
||||
cmp di, 0
|
||||
jge .not_clip_left
|
||||
.clip_left:
|
||||
; Adjust the start of buffer to point to the first cell
|
||||
; that is on screen
|
||||
sub si, di
|
||||
sub si, di
|
||||
; Adjust window width to account for non-rendered area
|
||||
; that is off screen
|
||||
add cx, di
|
||||
; Set X to 0
|
||||
xor di, di
|
||||
.not_clip_left:
|
||||
|
||||
mov ax, di
|
||||
add ax, cx
|
||||
cmp ax, COLUMNS
|
||||
jle .not_clip_right
|
||||
.clip_right:
|
||||
; Adjust the width to only go as far as the right edge
|
||||
sub ax, COLUMNS
|
||||
sub cx, ax
|
||||
.not_clip_right:
|
||||
|
||||
mov ax, bp
|
||||
add ax, dx
|
||||
cmp ax, ROWS
|
||||
jle .not_clip_bottom
|
||||
.clip_bottom:
|
||||
; Adjust the height to only go as far as the bottom edge
|
||||
sub ax, ROWS
|
||||
sub dx, ax
|
||||
.not_clip_bottom:
|
||||
|
||||
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
|
||||
event_mouse:
|
||||
test dl, MOUSE_PRIMARY | MOUSE_SECONDARY
|
||||
jnz .not_end_window_change
|
||||
; If we were moving or resizing the window, releasing the
|
||||
; button signals the end of the action
|
||||
mov byte [window_status], WINDOW_STATUS_NORMAL
|
||||
.not_end_window_change:
|
||||
|
||||
; Expand X and Y to 16 bits for easier calculations
|
||||
; Because we only have one window, we don't need to save our own ID
|
||||
xor bx, bx
|
||||
mov bl, ch
|
||||
xor ch, ch
|
||||
|
||||
; Are we moving the window at the moment?
|
||||
cmp byte [window_status], WINDOW_STATUS_MOVE
|
||||
jne .not_moving
|
||||
call move_window
|
||||
.not_moving:
|
||||
|
||||
; Are we resizing the window at the moment?
|
||||
cmp byte [window_status], WINDOW_STATUS_RESIZE
|
||||
jne .not_resizing
|
||||
call resize_window
|
||||
.not_resizing:
|
||||
|
||||
; Check if the mouse is outside our window
|
||||
cmp cx, [window_x]
|
||||
jl .outside ; x < window_x
|
||||
cmp bx, [window_y]
|
||||
jl .outside ; y < window_y
|
||||
mov ax, [window_x]
|
||||
add ax, [window_width]
|
||||
cmp ax, cx
|
||||
jle .outside ; window_x + window_width <= x
|
||||
mov ax, [window_y]
|
||||
add ax, [window_height]
|
||||
cmp ax, bx
|
||||
jle .outside ; window_y + window_height <= y
|
||||
|
||||
.inside:
|
||||
cmp byte [window_mouse_released_inside], 0
|
||||
je .not_click
|
||||
test dl, MOUSE_PRIMARY | MOUSE_SECONDARY
|
||||
jz .not_click
|
||||
.click:
|
||||
call event_click
|
||||
.not_click:
|
||||
|
||||
; We need to keep track of if the mouse has been inside our
|
||||
; window without the buttons held, in order to avoid
|
||||
; generating click events in cases where the cursor is
|
||||
; dragged into our window while buttons are held
|
||||
test dl, MOUSE_PRIMARY | MOUSE_SECONDARY
|
||||
jz .buttons_not_held
|
||||
.buttons_held:
|
||||
mov byte [window_mouse_released_inside], 0
|
||||
jmp .buttons_end
|
||||
.buttons_not_held:
|
||||
mov byte [window_mouse_released_inside], 1
|
||||
.buttons_end:
|
||||
|
||||
; We must forward the event even if it was inside our
|
||||
; window, to make sure other windows know when the mouse
|
||||
; leaves them
|
||||
; Set x and y to 255 so that windows below ours don't think
|
||||
; the cursor is inside them
|
||||
; Also clear the mouse buttons – not absolutely necessary
|
||||
; but it's cleaner if other windows don't get any
|
||||
; information about the mouse
|
||||
mov al, WM_MOUSE
|
||||
mov bx, [window_next]
|
||||
mov cx, 0xffff
|
||||
xor dl, dl
|
||||
call send_event
|
||||
ret
|
||||
|
||||
.outside:
|
||||
mov byte [window_mouse_released_inside], 0
|
||||
|
||||
; Not our window, forward the event
|
||||
mov al, WM_MOUSE
|
||||
mov ch, bl ; Pack the X and Y back into cx
|
||||
mov bx, [window_next]
|
||||
call send_event
|
||||
ret
|
||||
ret
|
||||
|
||||
; in:
|
||||
; bx = Y
|
||||
; cx = X
|
||||
; dl = mouse buttons
|
||||
; out:
|
||||
; clobbers ax
|
||||
event_click:
|
||||
; This is not a true event passed into our event handler, but
|
||||
; rather one we've synthetized from the mouse event
|
||||
; The reason we synthetize this event is because most interface
|
||||
; elements react to clicks specifically, so having this event
|
||||
; making implementing them easier
|
||||
|
||||
; Raising a window is done by first unhooking, then rehooking it to
|
||||
; the window chain
|
||||
call unhook_self_from_window_chain
|
||||
call hook_self_onto_window_chain
|
||||
call request_redraw
|
||||
|
||||
; Did the user click the title bar?
|
||||
cmp [window_y], bx
|
||||
jne .not_title_bar
|
||||
.title_bar:
|
||||
; Did the user click the window close button?
|
||||
mov ax, [window_x]
|
||||
add ax, [window_width]
|
||||
dec ax
|
||||
cmp ax, cx
|
||||
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
|
||||
; We don't need to call request_redraw here, since
|
||||
; it will be called unconditionally above
|
||||
jmp .title_bar_end
|
||||
.not_close:
|
||||
|
||||
; Did the user click on the resize button?
|
||||
cmp [window_x], cx
|
||||
jne .not_resize
|
||||
.resize:
|
||||
mov byte [window_status], WINDOW_STATUS_RESIZE
|
||||
jmp .title_bar_end
|
||||
.not_resize:
|
||||
|
||||
; Clicking on the title bar signals beginning of a window
|
||||
; move
|
||||
mov byte [window_status], WINDOW_STATUS_MOVE
|
||||
mov ax, [window_x]
|
||||
sub ax, cx
|
||||
mov [window_move_x_offset], ax
|
||||
.title_bar_end:
|
||||
.not_title_bar:
|
||||
|
||||
.end:
|
||||
ret
|
||||
|
||||
; in:
|
||||
; al = WM_KEYBOARD
|
||||
; bx = window ID
|
||||
; cl = typed character
|
||||
; ch = pressed key
|
||||
; out:
|
||||
; clobbers everything
|
||||
event_keyboard:
|
||||
cmp ch, 0x50 ; down key
|
||||
jne .up_key_check
|
||||
call file_next_line
|
||||
test dx, dx
|
||||
jz .ret
|
||||
|
||||
call render_window
|
||||
call request_redraw
|
||||
|
||||
.up_key_check:
|
||||
cmp ch, 0x48 ; up key
|
||||
jne .ret
|
||||
call file_prev_line
|
||||
test dx, dx
|
||||
jz .ret
|
||||
|
||||
call render_window
|
||||
call request_redraw
|
||||
|
||||
.ret:
|
||||
ret
|
||||
|
||||
; in:
|
||||
; al = WM_UNHOOK
|
||||
; bx = window ID
|
||||
; cx = window ID of the window to unhook from the window chain
|
||||
; out:
|
||||
; ax = own window ID if we did not unhook
|
||||
; next window ID if we did
|
||||
; clobbers everything else
|
||||
event_unhook:
|
||||
cmp bx, cx
|
||||
je .unhook_self
|
||||
|
||||
; Save our own ID
|
||||
push bx
|
||||
|
||||
; Propagate the event
|
||||
mov bx, [window_next]
|
||||
call send_event
|
||||
|
||||
; Update window_next in case the next one unhooked
|
||||
mov [window_next], ax
|
||||
|
||||
; Return our own ID
|
||||
pop ax
|
||||
ret
|
||||
|
||||
.unhook_self:
|
||||
; Return window_next to the caller, unhooking us from the
|
||||
; chain
|
||||
mov ax, [window_next]
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Event handler subroutines
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
; in:
|
||||
; bx = Y
|
||||
; cx = X
|
||||
move_window:
|
||||
push ax
|
||||
|
||||
; Offset the X coördinate so that the apparent drag position
|
||||
; remains the same
|
||||
mov ax, cx
|
||||
add ax, [window_move_x_offset]
|
||||
|
||||
; Only do an update if something has changed. Reduces flicker
|
||||
cmp [window_x], ax
|
||||
jne .update_location
|
||||
cmp [window_y], bx
|
||||
jne .update_location
|
||||
jmp .end
|
||||
|
||||
.update_location:
|
||||
mov [window_x], ax
|
||||
mov [window_y], bx
|
||||
call request_redraw
|
||||
|
||||
.end:
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; in:
|
||||
; bx = Y
|
||||
; cx = X
|
||||
resize_window:
|
||||
push ax
|
||||
push bx
|
||||
push bp
|
||||
|
||||
; Calculate new width
|
||||
mov ax, [window_width]
|
||||
add ax, [window_x]
|
||||
sub ax, cx
|
||||
|
||||
cmp ax, WINDOW_MIN_WIDTH
|
||||
jge .width_large_enough
|
||||
mov ax, WINDOW_MIN_WIDTH
|
||||
.width_large_enough:
|
||||
|
||||
cmp ax, COLUMNS
|
||||
jle .width_small_enough
|
||||
mov ax, COLUMNS
|
||||
.width_small_enough:
|
||||
|
||||
; Calculate new height
|
||||
mov bp, [window_height]
|
||||
add bp, [window_y]
|
||||
sub bp, bx
|
||||
|
||||
cmp bp, WINDOW_MIN_HEIGHT
|
||||
jge .height_large_enough
|
||||
mov bp, WINDOW_MIN_HEIGHT
|
||||
.height_large_enough:
|
||||
|
||||
cmp bp, ROWS
|
||||
jle .height_small_engough
|
||||
mov bp, ROWS
|
||||
.height_small_engough:
|
||||
|
||||
; Only do an update if something has changed. Reduces flicker
|
||||
cmp [window_width], ax
|
||||
jne .update_size
|
||||
cmp [window_height], bp
|
||||
jne .update_size
|
||||
jmp .end
|
||||
|
||||
.update_size:
|
||||
mov bx, [window_x]
|
||||
add bx, [window_width]
|
||||
sub bx, ax
|
||||
mov [window_x], bx
|
||||
mov [window_width], ax
|
||||
|
||||
mov bx, [window_y]
|
||||
add bx, [window_height]
|
||||
sub bx, bp
|
||||
mov [window_y], bx
|
||||
mov [window_height], bp
|
||||
|
||||
call render_window
|
||||
|
||||
call request_redraw
|
||||
|
||||
.end:
|
||||
pop bp
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
render_window:
|
||||
push ax
|
||||
push cx
|
||||
push dx
|
||||
push si
|
||||
push di
|
||||
|
||||
; Clear window to be black-on-white
|
||||
mov di, window_data
|
||||
mov ax, [window_width]
|
||||
mov cx, [window_height]
|
||||
mul cx
|
||||
mov cx, ax
|
||||
mov ax, 0xf000 ; Attribute is in the high byte
|
||||
rep stosw
|
||||
|
||||
; Set title bar to be white-on-black
|
||||
mov di, window_data
|
||||
mov ax, 0x0f00
|
||||
mov cx, [window_width]
|
||||
rep stosw
|
||||
|
||||
; Add title bar buttons
|
||||
mov di, window_data
|
||||
mov byte [di], 0x17 ; Resize arrow
|
||||
add di, [window_width]
|
||||
add di, [window_width]
|
||||
sub di, 2
|
||||
mov byte [di], 'x' ; Close button
|
||||
|
||||
; Add window title
|
||||
mov di, window_data
|
||||
add di, 2
|
||||
mov si, window_title
|
||||
mov cx, [window_width]
|
||||
dec cx
|
||||
dec cx
|
||||
cmp cx, FS_DIRENT_NAME_SIZE
|
||||
jle .copy_title
|
||||
mov cx, FS_DIRENT_NAME_SIZE
|
||||
.copy_title:
|
||||
lodsb
|
||||
stosb
|
||||
inc di
|
||||
loop .copy_title
|
||||
|
||||
; Print text
|
||||
mov di, window_data
|
||||
add di, [window_width]
|
||||
add di, [window_width]
|
||||
call print_file
|
||||
|
||||
pop di
|
||||
pop si
|
||||
pop dx
|
||||
pop cx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Window chain
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
; in:
|
||||
; al = event
|
||||
; bx = window to send the event to
|
||||
; cx, dx = event-specific
|
||||
; out:
|
||||
; ax = event-specific, 0 if bx=0
|
||||
send_event:
|
||||
test bx, bx
|
||||
jnz .non_zero_id
|
||||
|
||||
; Returning 0 if the window ID is 0 makes window unhooking simpler
|
||||
xor ax, ax
|
||||
ret
|
||||
|
||||
.non_zero_id:
|
||||
push bp
|
||||
|
||||
; Push the return address
|
||||
push cs
|
||||
mov bp, .end
|
||||
push bp
|
||||
|
||||
; Push the address we're doing a far-call to
|
||||
mov bp, bx
|
||||
and bp, 0xf000 ; Highest nybble of window ID marks the segment
|
||||
push bp
|
||||
xor bp, bp ; Event handler is always at address 0
|
||||
push bp
|
||||
|
||||
retf
|
||||
|
||||
.end:
|
||||
pop bp
|
||||
ret
|
||||
|
||||
hook_self_onto_window_chain:
|
||||
push ax
|
||||
push es
|
||||
|
||||
mov ax, PONYDOS_SEG
|
||||
mov es, ax
|
||||
|
||||
; Window ID is made of the segment (top nybble) and an arbitrary
|
||||
; process-specific part (lower three nybbles). Since we only have
|
||||
; one window, we can leave the process-specific part as zero
|
||||
mov ax, cs
|
||||
|
||||
xchg [es:GLOBAL_WINDOW_CHAIN_HEAD], ax
|
||||
|
||||
; Save the old head of the chain, so that we can propagate events
|
||||
; down to it
|
||||
mov [window_next], ax
|
||||
|
||||
pop es
|
||||
pop ax
|
||||
ret
|
||||
|
||||
unhook_self_from_window_chain:
|
||||
push bx
|
||||
push cx
|
||||
push es
|
||||
|
||||
mov ax, PONYDOS_SEG
|
||||
mov es, ax
|
||||
|
||||
mov al, WM_UNHOOK
|
||||
mov bx, [es:GLOBAL_WINDOW_CHAIN_HEAD]
|
||||
; Our window ID is just our segment, see the comment in
|
||||
; hook_self_onto_window_chain
|
||||
mov cx, cs
|
||||
call send_event
|
||||
|
||||
; Update the head of the chain, in case we were at the head
|
||||
mov [es:GLOBAL_WINDOW_CHAIN_HEAD], ax
|
||||
|
||||
pop es
|
||||
pop cx
|
||||
pop bx
|
||||
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
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Painting
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
request_redraw:
|
||||
push ax
|
||||
push es
|
||||
|
||||
mov ax, PONYDOS_SEG
|
||||
mov es, ax
|
||||
|
||||
mov byte [es:GLOBAL_REDRAW], 1
|
||||
|
||||
pop es
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; String functions
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
; in:
|
||||
; ds:si = string
|
||||
; out:
|
||||
; cx = stlen
|
||||
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
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Variables
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
tmp_window_title db "ponydos.asm", 0, 0
|
||||
window_title times FS_DIRENT_NAME_SIZE + 1 db 0
|
||||
|
||||
cur_file_address: dw 0 ; Segment
|
||||
dw 0
|
||||
beg_file_address: dw 0
|
||||
end_file_address: dw 0
|
||||
|
||||
window_next dw 0xffff
|
||||
window_x dw 4
|
||||
window_y dw 12
|
||||
window_width dw 32
|
||||
window_height dw 8
|
||||
|
||||
window_mouse_released_inside db 0
|
||||
window_status db WINDOW_STATUS_NORMAL
|
||||
window_move_x_offset dw 0
|
||||
|
||||
section .bss
|
||||
window_data resw ROWS*COLUMNS
|
Loading…
Reference in New Issue