└── bootris.s /bootris.s: -------------------------------------------------------------------------------- 1 | %define HEIGHT 22 2 | KEYBOARD_INTERRUPT EQU 9 3 | TIMER_INTERRUPT EQU 8 4 | 5 | TIMER_MOD EQU 0 6 | 7 | STACK_SEGMENT EQU 09000h ; Top of conventional memory 8 | STACK_SIZE EQU 0ffffh ; 64K - 1 bytes of stack 9 | 10 | ORG 0x7C00 11 | 12 | block_L: db 0x17,0 13 | db 0x22,0x30 14 | db 0x71,0 15 | db 0x30,0x22 16 | 17 | ; initialize the stack 18 | cli 19 | push word 0 20 | pop ds 21 | mov [4 * KEYBOARD_INTERRUPT], word keyboard_interrupt 22 | mov [4 * KEYBOARD_INTERRUPT + 2], cs 23 | mov [4 * TIMER_INTERRUPT], word timer_interrupt 24 | mov [4 * TIMER_INTERRUPT + 2], cs 25 | mov sp, STACK_SEGMENT 26 | mov ss, sp 27 | mov sp, STACK_SIZE 28 | push cs 29 | pop ds 30 | ; and jump to the main code 31 | jmp 0x0000:start 32 | 33 | title: dw 'TETRIS' 34 | world1: times 32 db 205 35 | 36 | start: 37 | mov word [counter], 0 38 | mov byte [timer_mod], 100 39 | call BiosClearScreen 40 | mov ax, title 41 | mov dh,0 42 | mov dl,37 43 | mov cx,6 44 | call puts 45 | call draw_boarder 46 | mov word [next_obj],block_L 47 | 48 | ;start game 49 | sti 50 | hlt 51 | 52 | do_new_object: 53 | mov word ax, [next_obj] 54 | mov word [current_obj], ax 55 | mov byte [obj_height],0 56 | mov byte [offset],0 57 | mov byte [rotation],0 58 | ret 59 | 60 | draw_boarder: 61 | mov dh, 1 62 | mov dl,24 63 | mov cx, 32 64 | mov ax, world1 65 | call puts 66 | add dh, HEIGHT 67 | call puts 68 | 69 | dec dh 70 | .loop: 71 | mov dl, 23 72 | mov ax, 0x0200 73 | xor bx, bx 74 | int 0x10 75 | mov cx, 1 76 | mov ah, 0x0A 77 | mov al, 186 78 | int 0x10 79 | mov dl, 56 80 | mov ax, 0x0200 81 | xor bx, bx 82 | int 0x10 83 | mov cx, 1 84 | mov ah, 0x0A 85 | mov al, 186 86 | int 0x10 87 | dec dh 88 | 89 | cmp dh, 1 90 | jnz .loop 91 | ret 92 | 93 | puts: 94 | pusha 95 | mov bp, ax 96 | mov ax, 0x1300 97 | mov bx, 7 98 | int 0x10 99 | popa 100 | ret 101 | 102 | do_game_tick: 103 | call draw_boarder 104 | ret 105 | 106 | keyboard_interrupt: 107 | ; save our registers! 108 | pusha 109 | in al, 60h 110 | ; Ignore codes with high bit set 111 | test al, 80h 112 | jnz EOI 113 | ; Read the ASCII code from the table 114 | mov cx, 1 115 | mov ah, 0x0A 116 | int 0x10 117 | jmp EOI 118 | 119 | timer_interrupt: 120 | pusha 121 | mov ax, [counter] 122 | or ax, ax 123 | jnz .end 124 | ; we hit zero! Do the game tick... 125 | call do_game_tick 126 | mov word [counter], 10 127 | mov cx, 1 128 | mov ah, 0x0A 129 | int 0x10 130 | .end: 131 | dec word [counter] 132 | ; fall through 133 | EOI: 134 | mov al, 20h 135 | out 20h, al 136 | popa 137 | iret 138 | 139 | BiosClearScreen: 140 | pusha 141 | mov ax,0x0600 ; clear the "window" 142 | xor cx, cx 143 | mov dx,0x184f ; to (24,79) 144 | mov bh,0x07 ; keep light grey display 145 | int 0x10 146 | popa 147 | ret 148 | 149 | ; last two bytes must be 55 AA 150 | times 510-($-$$) db 0 151 | db 0x55 152 | db 0xAA 153 | 154 | absolute 0x7e00 155 | counter: resw 1 156 | timer_mod: resb 1 157 | arena: times HEIGHT resw 1 158 | current_obj: resw 1 159 | next_obj: resw 1 160 | obj_height: resb 1 161 | offset: resb 1 162 | rotation: resb 1 163 | --------------------------------------------------------------------------------