This commit is contained in:
de 2016-09-27 08:51:22 +02:00
parent b4b449ce04
commit 055567318d

593
code.asm
View file

@ -1,25 +1,40 @@
; %macro print_reg 1
; mov dx, %1
; mov cx, 16
; print_reg_loop:
; push cx
; test dx, 1000000000000000b
; jz print_reg_zero
; mov al, '1'
; jmp print_reg_do
; print_reg_zero:
; mov al, '0'
; print_reg_do:
; mov bx, 0x0006
; mov ah, 0x09 ; print brick
; mov cx, 1
; int 0x10
; call cursor_right
; pop cx
; shl dx, 1
; loop print_reg_loop
; jmp $
; %endmacro
; TODO Nachricht game over
; TODO intro
; TODO show next brick
; ==============================================================================
; DEBUGGING MACROS
; ==============================================================================
%macro print_reg 1
mov dx, %1
mov cx, 16
print_reg_loop:
push cx
mov al, '0'
test dh, 10000000b
jz print_reg_do
mov al, '1'
print_reg_do:
mov bx, 0x0006 ; page = 0 (BH), color = gray on black (BL)
mov ah, 0x09 ; write character stored in AL
mov cx, 1
int 0x10
mov ah, 3 ; move cursor one column forward
int 0x10
inc dx
mov ah, 2 ; set cursor
int 0x10
pop cx
shl dx, 1
loop print_reg_loop
jmp $
%endmacro
; ==============================================================================
; MACROS
; ==============================================================================
%macro sleep 1
pusha
@ -30,168 +45,7 @@
popa
%endmacro
section .text
; TODO print_brick optimieren ähnlich wie check_collision
; TODO volle zeilen löschen
; TODO Nachricht game over
; TODO intro
; ----------------------------------------------------------------------
xor ax, ax ; init ds for lodsb
mov ds, ax
start_tetris:
;call initial_animation
call init_screen
new_brick:
mov word [delay + 0x7c00], 500 ; time
call select_brick ; returns the selected brick in AL
mov dx, 0x0426 ; start at row 4 and col 38
loop:
call check_collision
jne game_over
mov bx, 9 ; show brick
call print_brick
; if you modify AL or DX here, you should know what you're doing
wait_or_keyboard:
mov cx, word [delay + 0x7c00]
wait_a:
sleep 100 ; wait 100 microseconds
push ax
mov ah, 1 ; check for keystroke; AX modified
int 0x16 ; http://www.ctyme.com/intr/rb-1755.htm
mov bx, ax
pop ax
jz no_key ; no keystroke
push bx
call clear_brick
pop bx
; 4b left, 48 up, 4d right, 50 down
cmp bh, 0x4b ; left arrow
je left_arrow ; http://stackoverflow.com/questions/16939449/how-to-detect-arrow-keys-in-assembly
cmp bh, 0x48 ; up arrow
je up_arrow
cmp bh, 0x4d
je right_arrow
mov word [delay + 0x7c00], 30 ; every other key is fast down
jmp clear_keys
left_arrow:
dec dl
call check_collision
je clear_keys ; no collision
inc dl
jmp clear_keys
right_arrow:
inc dl
call check_collision
je clear_keys ; no collision
dec dl
jmp clear_keys
up_arrow:
mov bl, al
ror al, 3
inc al
and al, 11100011b
rol al, 3
call check_collision
je clear_keys ; no collision
mov al, bl
clear_keys:
mov bx, 9
call print_brick
push ax
xor ah, ah ; remove key from buffer
int 0x16
pop ax
no_key:
loop wait_a
call clear_brick
inc dh ; increase row
call check_collision
je no_collision
dec dh
mov bx, 9
call print_brick
jmp new_brick
no_collision:
jmp loop
game_over:
xor bh, bh
xor dx, dx
mov ah, 2 ; set cursor position
int 0x10
mov ax, 0x0947 ; print brick
mov cx, 80
int 0x10
xor ax, ax ; wait for keyboard
int 16h
jmp start_tetris
; clear_brick:
; xor bx, bx
; print_brick:
; or bx, bx
; jz print_brick_no_color
; push ax
; and al, 7
; add bl, al
; shl bl, 4
; pop ax
; print_brick_no_color:
; ; BL = color of brick
; DX = position (DH = row), AL = brick
; return: flag
check_collision:
pusha
call brick_offset ; result in SI
lodsw
xchg ah, al
xor bx, bx
mov cx, 4
cc:
push cx
mov cl, 4
dd:
test ax, 1000000000000000b
jz is_zero
push ax
mov ah, 2 ; set cursor position, BH = 0
int 0x10
mov ah, 8 ; read character and attribute, BH = 0
int 0x10 ; result in AX
shr ah, 4 ; rotate to get background color in AH
jz is_zero_x ; jmp if background color is 0
inc bl
is_zero_x:
pop ax
is_zero:
shl ax, 1
inc dl ; move to next column
loop dd
sub dl, 4 ; reset column
inc dh ; move to next row
pop cx
loop cc
cmp bl, 0 ; bl != 0 -> collision
popa
ret
; ======================================================================
select_brick:
%macro select_brick 0
mov ah, 2 ; get time
int 0x1a
mov ax, word [seed_value + 0x7c00]
@ -203,11 +57,275 @@ select_brick:
xor dx, dx
mov bx, 7
div bx
xchg ax, dx
;mov byte [current_brick + 0x7c00], al
xchg ax, dx ; move result in AL
%endmacro
%macro init_screen 0
call clear_screen
mov dh, 3
mov cx, 18
ia:
push cx
inc dh ; increment row
mov dl, 33 ; set column
mov cx, 14 ; width of box
mov bx, 0x77 ; color
call write_data
cmp dh, 21 ; don't remove last line
je ib ; if last line jump
inc dx ; increase column
mov cx, 12 ; width of box
xor bx, bx ; color
call write_data
ib:
pop cx
loop ia
%endmacro
; ==============================================================================
section .text
xor ax, ax ; init ds for lodsb
mov ds, ax
start_tetris:
;call initial_animation
init_screen
new_brick:
mov word [delay + 0x7c00], 500
select_brick ; returns the selected brick in AL
mov dx, 0x0426 ; start at row 4 and col 38
loop:
call check_collision
jne game_over
call print_brick
; if you modify AL or DX here, you should know what you're doing
wait_or_keyboard:
mov cx, word [delay + 0x7c00]
wait_a:
push cx
sleep 100 ; wait 100 microseconds
push ax
mov ah, 1 ; check for keystroke; AX modified
int 0x16 ; http://www.ctyme.com/intr/rb-1755.htm
mov cx, ax
pop ax
jz no_key ; no keystroke
call clear_brick
; 4b left, 48 up, 4d right, 50 down
cmp ch, 0x4b ; left arrow
je left_arrow ; http://stackoverflow.com/questions/16939449/how-to-detect-arrow-keys-in-assembly
cmp ch, 0x48 ; up arrow
je up_arrow
cmp ch, 0x4d
je right_arrow
mov word [delay + 0x7c00], 30 ; every other key is fast down
jmp clear_keys
left_arrow:
dec dx
call check_collision
je clear_keys ; no collision
inc dx
jmp clear_keys
right_arrow:
inc dx
call check_collision
je clear_keys ; no collision
dec dx
jmp clear_keys
up_arrow:
mov bl, al
ror al, 3
inc ax ; inc al, but inc ax needs less memory
and al, 11100011b
rol al, 3
call check_collision
je clear_keys ; no collision
mov al, bl
clear_keys:
call print_brick
push ax
xor ah, ah ; remove key from buffer
int 0x16
pop ax
no_key:
pop cx
loop wait_a
call clear_brick
inc dh ; increase row
call check_collision
je no_collision
dec dh
call print_brick
call check_filled
jmp new_brick
no_collision:
jmp loop
write_data:
mov ah, 2 ; set cursor
int 0x10
mov ax, 0x0900 ; write boxes
int 0x10
ret
; TODO below mem optimized
set_and_read:
mov ah, 2 ; set cursor position
int 0x10
mov ah, 8 ; read character and attribute, BH = 0
int 0x10 ; result in AX
ret
check_filled:
pusha
mov dh, 21 ; row
next_row:
dec dh
jz cf_done
xor bx, bx
mov cx, 12
mov dl, 34 ; column
cf_loop:
call set_and_read
shr ah, 4 ; rotate to get background color in AH
jz cf_is_zero ; jmp if background color is 0
inc bx
inc dx
cf_is_zero:
loop cf_loop
cmp bl, 12
jne next_row
replace_next_row:
call replace_current_row
dec dh
jnz replace_next_row
popa
call check_filled
ret
cf_done:
popa
ret
replace_current_row: ; DH = current row
pusha
mov dl, 34 ; replace current row with row above
mov cx, 12
cf_aa:
push cx
dec dh
call set_and_read
inc dh
mov bl, ah ; color from AH to BL
mov ah, 2 ; set cursor position
int 0x10
mov ax, 0x920 ; write character
mov cx, 1
int 0x10
inc dx
pop cx
loop cf_aa
popa
ret
game_over:
jmp $
; xor bh, bh
; xor dx, dx
; mov ah, 2 ; set cursor position
; int 0x10
; mov ax, 0x0947 ; print brick
; mov cx, 80
; int 0x10
; xor ax, ax ; wait for keyboard
; int 16h
; jmp start_tetris
clear_brick:
xor bx, bx
jmp print_brick_no_color
print_brick:
mov bx, 9
push ax
and al, 7
add bl, al
shl bl, 4
pop ax
print_brick_no_color:
inc bx
mov di, bx
jmp check_collision_main
; BL = color of brick
; DX = position (DH = row), AL = brick
; return: flag
check_collision:
mov di, 0
check_collision_main: ; DI = 1 -> check, 0 -> print
pusha
call brick_offset ; result in SI
lodsw
xchg ah, al
xor bx, bx ; set BH = BL = 0
mov cx, 4
cc:
push cx
mov cl, 4
dd:
test ax, 1000000000000000b
jz is_zero
push ax
mov ah, 2 ; set cursor position, BH = 0
int 0x10
or di, di
jz ee ; jump if we want to check for collisions
; print space with color stored in DI at postion DX
pusha
mov bx, di
dec bx
mov ax, 0x0920 ; print brick
mov cx, 1
int 0x10
popa
jmp is_zero_a
ee:
mov ah, 8 ; read character and attribute, BH = 0
int 0x10 ; result in AX
shr ah, 4 ; rotate to get background color in AH
jz is_zero_a ; jmp if background color is 0
inc bx
is_zero_a:
pop ax
is_zero:
shl ax, 1
inc dx ; move to next column
loop dd
sub dl, 4 ; reset column
inc dh ; move to next row
pop cx
loop cc
cmp bl, 0 ; bl != 0 -> collision
popa
ret
; ======================================================================
@ -237,107 +355,6 @@ brick_offset:
add si, ax
ret
clear_brick:
xor bx, bx
; AL = brick data
; DL = column
; DH = row
; BX = 9 -> show brick; 0 -> delete brick (BL = start color for brick)
print_brick:
pusha
or bx, bx
jz print_brick_no_color
push ax
and al, 7
add bl, al
shl bl, 4
pop ax
print_brick_no_color:
call brick_offset ; result in si
; bl = color
; ds:si = address of brick
; dx = position of brick
mov cx, 2
ccc:
push cx
lodsb ; load next two rows of brick
call brick_line ; print first row
inc dh
call brick_line ; print second row
inc dh
pop cx
loop ccc
popa
ret
brick_line:
; bh = 0
; bl = color
; dx = position
; al = brick data
mov ah, 2 ; set cursor position
int 0x10
mov cx, 4
brick_line_a:
pusha
and al, 128
jz brick_line_d
mov ax, 0x0920 ; print brick
mov cx, 1
int 0x10
brick_line_d:
call cursor_right
popa
shl al, 1
loop brick_line_a
ret
; ----------------------------------------------------------------------
cursor_right:
pusha
mov ah, 3 ; get cursor position
xor bx, bx
int 0x10
inc dl ; increase column
mov ah, 2 ; set new cursor position
int 0x10
popa
ret
; ----------------------------------------------------------------------
; this should be highly memory optimized
init_screen:
call clear_screen
mov dh, 3
mov cx, 18
ia:
push cx
inc dh ; increment row
mov dl, 33 ; set column
mov cx, 14 ; width of box
mov bx, 0x77 ; color
call write_data
cmp dh, 21 ; don't remove last line
je ib ; if last line jump
inc dl ; increase column
mov cx, 12 ; width of box
xor bx, bx ; color
call write_data
ib:
pop cx
loop ia
ret
write_data:
mov ah, 2 ; set cursor
int 0x10
mov ax, 0x0900 ; write boxes
int 0x10
ret
; ----------------------------------------------------------------------
initial_animation: