diff --git a/code.asm b/code.asm index db5af33..faa824b 100644 --- a/code.asm +++ b/code.asm @@ -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: