208 lines
No EOL
2.8 KiB
NASM
208 lines
No EOL
2.8 KiB
NASM
PIXELS_PER_BYTE equ 8
|
|
|
|
section constants
|
|
screen_width_bytes dw SCREEN_WIDTH / PIXELS_PER_BYTE
|
|
section data
|
|
active_page db 0
|
|
section code
|
|
|
|
video_init:
|
|
pusha
|
|
mov ah, 0xf
|
|
int 0x10
|
|
mov [.saved_video_mode], al
|
|
mov [.saved_page], bh
|
|
|
|
mov ah, 0
|
|
mov al, 0xd ; 320x200 16-colour
|
|
int 0x10
|
|
popa
|
|
ret
|
|
|
|
section data
|
|
.saved_video_mode resb 1
|
|
.saved_page resb 1
|
|
section code
|
|
|
|
video_deinit:
|
|
pusha
|
|
mov al, [video_init.saved_video_mode]
|
|
mov ah, 0
|
|
int 0x10
|
|
|
|
mov al, [video_init.saved_page]
|
|
mov ah, 5
|
|
int 0x10
|
|
popa
|
|
ret
|
|
|
|
flip_pages:
|
|
ret
|
|
|
|
; backbuffer -> es:0
|
|
get_backbuffer:
|
|
cmp [cs:active_page], 0
|
|
;jne .active_1
|
|
push 0xa000
|
|
pop es
|
|
ret
|
|
|
|
; requires: es:0 = backbuffer
|
|
clear_screen:
|
|
pusha
|
|
mov cx, SCREEN_WIDTH * SCREEN_HEIGHT / PIXELS_PER_BYTE / 2
|
|
xor ax, ax
|
|
xor di, di
|
|
rep stosw
|
|
popa
|
|
ret
|
|
|
|
; ah = plane mask
|
|
set_ink:
|
|
pusha
|
|
mov bh, ah ; save mask
|
|
|
|
mov ax, 5h
|
|
mov dx, 0x3ce
|
|
out dx, ax
|
|
mov ah, 0xf
|
|
and ah, bh
|
|
mov al, 2
|
|
mov dx, 0x3c4
|
|
out dx, ax
|
|
popa
|
|
ret
|
|
|
|
; ax = X
|
|
; bx = Y
|
|
; dl = set/erase pixel
|
|
; requires: es:0 = backbuffer
|
|
plot:
|
|
pusha
|
|
cmp ax, 0
|
|
jl .outside
|
|
cmp ax, SCREEN_WIDTH
|
|
jge .outside
|
|
cmp bx, 0
|
|
jl .outside
|
|
cmp bx, SCREEN_HEIGHT
|
|
jge .outside
|
|
|
|
mov ch, dl
|
|
mov cl, al
|
|
xchg ax, bx
|
|
mul word [screen_width_bytes]
|
|
shr bx, 3
|
|
add bx, ax
|
|
; bx = Y * screen_width_bytes + byte_offset(X)
|
|
and cl, 0x7
|
|
mov al, 0x80
|
|
shr al, cl
|
|
; al = bitmask of the sub-byte offset
|
|
test ch, ch
|
|
jz .erase
|
|
or [es:bx], al
|
|
jmp .end
|
|
.erase:
|
|
not al
|
|
and [es:bx], al
|
|
.end:
|
|
|
|
.outside:
|
|
popa
|
|
ret
|
|
|
|
; ax = X0
|
|
; bx = Y0
|
|
; dl = colour
|
|
; si = X1
|
|
; di = Y1
|
|
draw_line:
|
|
pusha
|
|
|
|
call plot
|
|
xchg ax, si
|
|
xchg bx, di
|
|
call plot
|
|
|
|
sub si, ax
|
|
sub di, bx
|
|
; si = delta_x, di = delta_y
|
|
|
|
cmp si, 0
|
|
jl .delta_x_negative
|
|
cmp di, 0
|
|
jl .dy_neg
|
|
jmp .neither_neg
|
|
.delta_x_negative:
|
|
cmp di, 0
|
|
jl .both_neg
|
|
jmp .dx_neg
|
|
|
|
.both_neg:
|
|
neg si
|
|
neg di
|
|
sub ax, si
|
|
sub bx, di
|
|
|
|
.neither_neg:
|
|
cmp si, di
|
|
jg brasenham_shallow
|
|
jmp brasenham_steep
|
|
|
|
.dx_neg:
|
|
neg si
|
|
cmp si, di
|
|
jl brasenham_steep_neg
|
|
sub ax, si
|
|
add bx, di
|
|
jmp brasenham_shallow_neg
|
|
|
|
.dy_neg:
|
|
neg di
|
|
cmp si, di
|
|
jg brasenham_shallow_neg
|
|
add ax, si
|
|
sub bx, di
|
|
jmp brasenham_steep_neg
|
|
|
|
popa
|
|
ret
|
|
|
|
; brasenham origin_i, origin_j, delta_i, delta_j, delta_j_sign
|
|
; requires: 0 <= delta_i <= delta_j
|
|
%macro brasenham 5
|
|
mov bp, %4
|
|
add bp, %4
|
|
sub bp, %3
|
|
; bp = 2*delta_i - delta_j
|
|
; bp is the error term
|
|
|
|
mov cx, %3
|
|
.loop:
|
|
jcxz .end
|
|
call plot
|
|
cmp bp, 0
|
|
jl .no_y_change
|
|
add %2, %5
|
|
sub bp, %3
|
|
sub bp, %3
|
|
.no_y_change:
|
|
inc %1
|
|
add bp, %4
|
|
add bp, %4
|
|
dec cx
|
|
jmp .loop
|
|
.end:
|
|
popa
|
|
ret
|
|
%endmacro
|
|
|
|
brasenham_shallow:
|
|
brasenham ax, bx, si, di, 1
|
|
brasenham_shallow_neg:
|
|
brasenham ax, bx, si, di, -1
|
|
brasenham_steep:
|
|
brasenham bx, ax, di, si, 1
|
|
brasenham_steep_neg:
|
|
brasenham bx, ax, di, si, -1 |