taytyypa-menna-nopeasti/graphics.asm
2025-10-26 13:12:04 +02:00

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