ponydos/ponydos.asm

457 lines
6.7 KiB
NASM
Raw Normal View History

cpu 286
2022-02-11 16:16:49 +00:00
bits 16
org 0x7c00
2023-02-06 15:45:26 +00:00
COLUMNS equ 80
ROWS equ 25
2023-03-11 15:49:55 +00:00
WALLPAPER equ 0x500
2023-03-16 10:10:03 +00:00
DIRENTS equ 0x2000
DIRENT_SIZE equ 32
FILE_MAX_SIZE equ 128
2022-02-11 16:16:49 +00:00
jmp 0:start
start:
cld
; Set up segments and stack
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, $$
2023-02-06 15:15:47 +00:00
; Clear BSS
2023-03-16 10:10:03 +00:00
;xor al, al
2023-02-06 15:15:47 +00:00
mov di, _bss_start
mov cx, _bss_end - _bss_start
rep stosb
2023-03-11 15:49:55 +00:00
mov [boot_disk], dl
2023-01-30 16:56:16 +00:00
initialize_mouse:
; Initialize mouse
; https://www.ctyme.com/intr/rb-1601.htm
mov ax, 0xc205
mov bh, 3 ; TODO: This is the usual PS/2 mouse packet size, but is it correct here?
int 0x15
jc .error
; Set handler address
; https://www.ctyme.com/intr/rb-1603.htm
mov ax, 0xc207
; es is already set correctly
mov bx, mouse_handler
int 0x15
jc .error
; Enable mouse
; https://www.ctyme.com/intr/rb-1596.htm
mov ax, 0xc200
mov bh, 1
int 0x15
jc .error
2023-02-06 15:45:26 +00:00
jmp .done
2023-01-30 16:56:16 +00:00
.error:
; https://www.ctyme.com/intr/rb-1601.htm
mov ax, 0xc201
int 0x15
jmp initialize_mouse
2022-02-11 16:16:49 +00:00
2023-02-06 15:45:26 +00:00
.done:
2023-03-11 15:49:55 +00:00
load_wallpaper:
2023-03-16 10:10:03 +00:00
mov si, wallpaper_name
call open_file
mov bx, WALLPAPER
2023-03-11 15:49:55 +00:00
call read_sectors
2023-03-16 10:10:03 +00:00
; TODO: error management? Surely this works...
2023-03-11 15:49:55 +00:00
2023-03-17 23:05:32 +00:00
load_shell:
mov ax, 0x1000
mov es, ax
mov si, shell_name
call open_file
xor bx, bx
call read_sectors
call 0x1000:0
2023-03-11 15:49:55 +00:00
initialize_screen:
2023-02-06 15:45:26 +00:00
; Disable text cursor
2023-02-06 16:02:21 +00:00
mov ah, 0x01
mov ch, 0x20
int 0x10
2023-03-11 15:49:55 +00:00
call draw_wallpaper
2023-02-06 15:45:26 +00:00
call flip_mouse_cursor
2022-02-11 16:16:49 +00:00
mainloop:
2023-02-06 15:45:26 +00:00
mov bx, [mouse_x]
2023-02-06 16:02:21 +00:00
shr bx, 1
2023-02-06 15:45:26 +00:00
mov cx, [mouse_y]
2023-02-06 16:02:21 +00:00
shr cx, 1
shr cx, 1
cmp [mouse_column], bl
2023-02-06 15:45:26 +00:00
jne .update_cursor
2023-02-06 16:02:21 +00:00
cmp [mouse_row], cl
2023-02-06 15:45:26 +00:00
jne .update_cursor
2022-02-11 16:16:49 +00:00
hlt
2023-02-06 15:45:26 +00:00
jmp mainloop
.update_cursor:
call flip_mouse_cursor
2023-02-06 16:02:21 +00:00
mov [mouse_column], bl
mov [mouse_row], cl
2023-02-06 15:45:26 +00:00
call flip_mouse_cursor
jmp mainloop
2023-03-11 15:49:55 +00:00
; ------------------------------------------------------------------
; Drawing subroutines
; ------------------------------------------------------------------
draw_wallpaper:
pusha
2023-03-11 15:49:55 +00:00
push es
mov bx, 0xb800
mov es, bx
mov si, WALLPAPER
xor di, di
mov cx, 80*25
rep movsw
pop es
popa
2023-03-11 15:49:55 +00:00
ret
2023-02-06 15:45:26 +00:00
flip_mouse_cursor:
pusha
2023-02-06 15:45:26 +00:00
push es
mov bx, 0xb800
mov es, bx
; Column
xor bh, bh
2023-02-06 16:02:21 +00:00
mov bl, [mouse_column]
2023-02-06 15:45:26 +00:00
shl bx, 1
; Row
2023-02-06 16:02:21 +00:00
mov al, [mouse_row]
2023-02-06 15:45:26 +00:00
mov cl, COLUMNS*2
mul cl
add bx, ax
; Swap foreground and background colours
inc bx
mov al, [es:bx]
mov cl, 4
ror al, cl
mov [es:bx], al
pop es
popa
2023-02-06 15:45:26 +00:00
ret
2022-02-11 16:16:49 +00:00
2023-03-11 15:49:55 +00:00
; ------------------------------------------------------------------
; Disk subroutines
; ------------------------------------------------------------------
; in:
; ax = LBA of first sector
2023-03-16 10:10:03 +00:00
;; bl = drive number
2023-03-11 15:49:55 +00:00
; cx = number of sectors to read (must be at least 1)
2023-03-16 10:10:03 +00:00
; es:bx = output buffer
2023-03-11 15:49:55 +00:00
read_sectors:
pusha
2023-03-11 15:49:55 +00:00
2023-03-16 10:42:22 +00:00
xor di, di
2023-03-11 15:49:55 +00:00
.loop:
2023-03-16 10:42:22 +00:00
call modify_sector
2023-03-11 15:49:55 +00:00
inc ax
2023-03-16 10:10:03 +00:00
add bx, 512
2023-03-11 15:49:55 +00:00
loop .loop
popa
2023-03-11 15:49:55 +00:00
ret
; in:
2023-03-16 10:42:22 +00:00
; ax = LBA of first sector
;; bl = drive number, use [boot_disk] for now
; es:bx = output buffer
; di = 0x0100 for write, 0x0000 for read
modify_sector:
pusha
2023-03-16 15:52:41 +00:00
push ds
2023-03-16 10:42:22 +00:00
2023-03-16 15:52:41 +00:00
xor cx, cx
mov ds, cx
;mov cx, 18
mov cl, 18
2023-03-11 15:49:55 +00:00
div cx
; cl = sector (1…18)
mov cl, dl
inc cl
; dh = head (0…1)
mov dh, 1
and dh, al
; ch = cylinder
shr ax, 1
mov ch, al
; dl = drive number
2023-03-16 15:52:41 +00:00
mov dl, [ds:boot_disk]
2023-03-11 15:49:55 +00:00
2023-03-13 12:40:28 +00:00
.retry:
2023-03-16 10:42:22 +00:00
mov ax, 0x0201 ; read/write one sector
add ax, di
2023-03-11 15:49:55 +00:00
int 0x13
2023-03-13 12:40:28 +00:00
jc .error
2023-03-11 15:49:55 +00:00
2023-03-16 15:52:41 +00:00
pop ds
popa
2023-03-11 15:49:55 +00:00
ret
2023-03-13 12:40:28 +00:00
.error:
; Reset the disk system unconditinoally, as we have no
; kernel panic handler to go to after 3 tries and proper
; error handling would take too much code
xor ah, ah
int 0x10
jmp .retry
2023-03-16 10:10:03 +00:00
; ------------------------------------------------------------------
; Filesystem
; ------------------------------------------------------------------
wallpaper_name: db 'wallpaper.bin', 0
2023-03-17 23:05:32 +00:00
shell_name: db 'shell.bin', 0
2023-03-16 10:10:03 +00:00
; in:
2023-03-16 15:52:41 +00:00
; ds:si = file name
2023-03-16 10:10:03 +00:00
; out:
; ax = LBA of first sector, 0 if no space left
; cx = length in sectors
open_file:
push si
push di
push bx
2023-03-16 15:52:41 +00:00
push es
2023-03-16 10:10:03 +00:00
; Stolen from https://stackoverflow.com/a/72746473, get strlen in cx
2023-03-16 15:52:41 +00:00
mov cx, ds
mov es, cx
2023-03-16 10:10:03 +00:00
mov di, si
mov cx, -1
xor ax, ax
repne scasb
not cx
dec cx
2023-03-16 15:52:41 +00:00
mov es, ax
2023-03-16 10:10:03 +00:00
;mov ax, 1
mov al, 1
mov bx, DIRENTS
2023-03-16 10:42:22 +00:00
xor di, di
call modify_sector
2023-03-16 10:10:03 +00:00
mov ax, 2
mov di, bx
.loop:
2023-03-16 15:52:41 +00:00
cmp word [es:di], 0
2023-03-16 10:10:03 +00:00
je .create_file
inc di
inc di
pusha
2023-03-16 10:10:03 +00:00
repe cmpsb
popa
2023-03-16 10:10:03 +00:00
je .success
add ax, FILE_MAX_SIZE
add di, DIRENT_SIZE - 2
cmp di, DIRENTS + 0x200
jl .loop
.error:
xor ax, ax
; Return with mangled cx
.success:
2023-03-16 15:52:41 +00:00
mov cx, [es:di - 2]
2023-03-16 10:10:03 +00:00
.return:
2023-03-16 15:52:41 +00:00
pop es
2023-03-16 10:10:03 +00:00
pop bx
pop di
pop si
ret
.create_file:
; TODO: zero out the sector for this file?
2023-03-16 15:52:41 +00:00
inc word [es:di]
2023-03-16 10:10:03 +00:00
inc di
inc di
rep movsb
push ax
mov ax, 1
;mov bx, DIRENTS
2023-03-16 10:42:22 +00:00
mov di, 0x0100 ; write
call modify_sector
2023-03-16 10:10:03 +00:00
pop ax
;mov cx, 1
mov cl, 1
jmp .return
2023-03-11 15:49:55 +00:00
; ------------------------------------------------------------------
; Mouse callback
; ------------------------------------------------------------------
2023-02-06 15:15:47 +00:00
Y_OVERFLOW equ 0x80
X_OVERFLOW equ 0x40
Y_NEGATIVE equ 0x20
X_NEGATIVE equ 0x10
BUTTONS equ 0x03
2023-02-06 16:02:21 +00:00
X_MAX_VALUE equ 2*COLUMNS-1
Y_MAX_VALUE equ 4*ROWS-1
2023-02-06 15:15:47 +00:00
2023-01-30 16:56:16 +00:00
mouse_handler:
pusha
2023-02-06 15:15:47 +00:00
push ds
2023-01-30 16:56:16 +00:00
2023-02-06 15:15:47 +00:00
mov ax, cs
mov ds, ax
2023-01-30 16:56:16 +00:00
2023-02-06 15:15:47 +00:00
mov bp, sp
2023-01-30 16:56:16 +00:00
mov bx, [bp+2*9+10] ; status
2023-02-06 15:15:47 +00:00
test bl, X_OVERFLOW
jnz .x_end
.x:
mov ax, [bp+2*9+8] ; X
2023-02-06 15:15:47 +00:00
test bl, X_NEGATIVE
jnz .x_negative
.x_nonnegative:
add [mouse_x], ax
cmp word [mouse_x], X_MAX_VALUE
jb .x_end
mov word [mouse_x], X_MAX_VALUE
jmp .x_end
.x_negative:
neg al
sub [mouse_x], ax
jnc .x_end
mov word [mouse_x], 0
.x_end:
test bl, Y_OVERFLOW
jnz .y_end
.y:
mov ax, [bp+2*9+6] ; Y
2023-02-06 15:15:47 +00:00
test bl, Y_NEGATIVE
jnz .y_negative
.y_nonnegative:
; Y-axis is inverted
sub [mouse_y], ax
jnc .y_end
mov word [mouse_y], 0
jmp .y_end
.y_negative:
neg al
add [mouse_y], ax
cmp word [mouse_y], Y_MAX_VALUE
jb .y_end
mov word [mouse_y], Y_MAX_VALUE
2023-03-11 15:17:40 +00:00
.y_end:
2023-02-06 15:15:47 +00:00
and bl, BUTTONS
mov [mouse_buttons], bl
pop ds
popa
2023-01-30 16:56:16 +00:00
retf
2023-03-11 15:49:55 +00:00
; ------------------------------------------------------------------
; Debug routines
; ------------------------------------------------------------------
2023-03-16 10:10:03 +00:00
%if 0
2023-01-30 16:56:16 +00:00
hexprint16:
xchg ah, al
call hexprint8
xchg ah, al
2022-02-11 16:16:49 +00:00
hexprint8:
push ax
push cx
mov cl, 4
shr al, cl
call hexprint4
pop cx
pop ax
hexprint4:
push ax
and al, 0xf
cmp al, 10
jb .digit09
add al, 'a' - '0' - 10
.digit09:
add al, '0'
mov ah, 0x0e
int 0x10
pop ax
ret
2023-03-11 15:49:55 +00:00
hang:
hlt
jmp hang
2023-03-16 10:10:03 +00:00
%endif
2023-03-11 15:49:55 +00:00
; ------------------------------------------------------------------
; Padding and boot sector signature
; ------------------------------------------------------------------
2022-02-11 16:16:49 +00:00
times 510-($-$$) db 0
2023-03-16 10:10:03 +00:00
2022-02-11 16:16:49 +00:00
db 0x55
db 0xaa
2023-02-06 15:15:47 +00:00
2023-03-11 15:49:55 +00:00
; ------------------------------------------------------------------
; Zero-initialized variables
; ------------------------------------------------------------------
2023-02-06 15:15:47 +00:00
section .bss
_bss_start:
mouse_x resw 1
mouse_y resw 1
mouse_buttons resb 1
2023-02-06 16:02:21 +00:00
mouse_column resb 1
mouse_row resw 1
2023-02-06 15:45:26 +00:00
2023-03-11 15:49:55 +00:00
boot_disk resb 1
_bss_end: