wok-tiny annotate bootbricks/stuff/bricks.asm @ rev 186

Add bootlife
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Feb 04 18:02:38 2024 +0000 (3 months ago)
parents 61c76233911e
children
rev   line source
pascal@180 1 ;
pascal@180 2 ; Bricks game in one boot sector
pascal@180 3 ;
pascal@180 4 ; by Oscar Toledo G.
pascal@180 5 ;
pascal@180 6 ; Creation date: Nov/02/2019.
pascal@180 7 ;
pascal@180 8
pascal@180 9 cpu 8086
pascal@180 10
pascal@180 11 ;
pascal@180 12 ; Press Left Shift to start the game
pascal@180 13 ; Press Left Ctrl to move the paddle to the left
pascal@180 14 ; Press Left Alt to move the paddle to the right
pascal@180 15 ;
pascal@180 16
pascal@186 17 old_time: equ 16 ; word: Old time
pascal@180 18 ball_x: equ 14 ; X-coordinate of ball (8.8 fraction)
pascal@180 19 ball_y: equ 12 ; Y-coordinate of ball (8.8 fraction)
pascal@180 20 ball_xs: equ 10 ; X-speed of ball (8.8 fraction)
pascal@180 21 ball_ys: equ 8 ; Y-speed of ball (8.8 fraction)
pascal@186 22 beep: equ 6 ; byte: Frame count to turn off sound
pascal@186 23 bricks: equ 4 ; word: Remaining bricks
pascal@186 24 score: equ 2 ; word: Current score
pascal@186 25 balls: equ 0 ; byte: Remaining balls
pascal@186 26
pascal@186 27 %define MDA_SUPPORT
pascal@180 28
pascal@180 29 ;
pascal@180 30 ; Start of the game
pascal@180 31 ;
pascal@180 32 start:
pascal@186 33 cld
pascal@184 34 sti ; Allow interrupts
pascal@186 35 push cs
pascal@186 36 pop ss
pascal@186 37 mov sp,0xb800 ; Address of video screen
pascal@186 38 .set_segments:
pascal@186 39 mov ds,sp ; Setup DS
pascal@186 40 mov es,sp ; Setup ES
pascal@186 41 %ifdef MDA_SUPPORT
pascal@186 42 xor di,di
pascal@186 43 mov sp,0xb000 ; Address of video screen
pascal@186 44 inc word [di]
pascal@186 45 jz .set_segments
pascal@186 46 xchg ax,di
pascal@186 47 %else
pascal@186 48 xor ax,ax
pascal@186 49 %endif
pascal@180 50 push ax ; Reset score
pascal@180 51 mov al,4
pascal@180 52 push ax ; Balls remaining
pascal@180 53 mov bp,sp ; Setup stack frame for globals
pascal@182 54 mov al,0x02 ; Text mode 80x25x16 colors
pascal@182 55 int 0x10 ; Setup
pascal@186 56 %if 0
pascal@186 57 ; Disable VGA text mode cursor
pascal@186 58 ; https://wiki.osdev.org/Text_Mode_Cursor#Disabling_the_Cursor
pascal@186 59 mov ah, 0x01
pascal@186 60 mov ch, 0x3f
pascal@186 61 int 0x10
pascal@186 62 %endif
pascal@180 63 ;
pascal@180 64 ; Start another level
pascal@180 65 ;
pascal@180 66 another_level:
pascal@180 67 mov word [bp+bricks],273 ; 273 bricks on screen
pascal@180 68 xor di,di
pascal@180 69 mov ax,0x01b1 ; Draw top border
pascal@180 70 mov cx,80
pascal@180 71 rep stosw
pascal@180 72 mov cl,24 ; 24 rows
pascal@180 73 .1:
pascal@180 74 stosw ; Draw left border
pascal@180 75 mov ax,0x20 ; No bricks on this row
pascal@180 76 push cx
pascal@180 77 cmp cl,23
pascal@180 78 jnb .2
pascal@180 79 sub cl,15
pascal@180 80 jbe .2
pascal@180 81 mov al,0xdb ; Bricks on this row
pascal@180 82 mov ah,cl
pascal@180 83 .2:
pascal@180 84 mov cl,39 ; 39 bricks per row
pascal@180 85 .3:
pascal@186 86 test ah,0x07
pascal@186 87 jne .4
pascal@186 88 %ifdef MDA_SUPPORT
pascal@186 89 mov ah,0x02
pascal@186 90 %else
pascal@186 91 mov ah,0x01
pascal@186 92 %endif
pascal@186 93 .4:
pascal@180 94 stosw
pascal@180 95 stosw
pascal@180 96 inc ah ; Increase attribute color
pascal@180 97 loop .3
pascal@180 98 pop cx
pascal@180 99
pascal@180 100 mov ax,0x01b1 ; Draw right border
pascal@180 101 stosw
pascal@180 102 loop .1
pascal@180 103
pascal@180 104 ;
pascal@180 105 ; Start another ball
pascal@180 106 ;
pascal@180 107 mov di,0x0f4a ; Position of paddle
pascal@180 108 another_ball:
pascal@180 109 mov byte [bp+ball_x+1],0x28 ; Center X
pascal@180 110 mov byte [bp+ball_y+1],0x14 ; Center Y
pascal@186 111 and word [bp+ball_xs],0 ; Static on screen
pascal@186 112 and word [bp+ball_ys],0
pascal@180 113 mov byte [bp+beep],0x01
pascal@180 114
pascal@180 115 mov si,0x0ffe ; Don't erase ball yet
pascal@180 116 game_loop:
pascal@180 117 call wait_frame ; Wait 1/18.2 secs.
pascal@180 118
pascal@182 119 and word [si],0x0000 ; Erase ball
pascal@180 120
pascal@180 121 call update_score ; Update score
pascal@180 122
pascal@182 123 mov ah,0x01 ; Check for keys
pascal@182 124 int 0x16
pascal@182 125 jz .0
pascal@182 126 cbw ; Eat key
pascal@182 127 int 0x16
pascal@182 128 cmp al,27 ; ESC key ?
pascal@185 129 jnz .0
pascal@185 130 call wait_frame.2 ; Turn off sound
pascal@185 131 mov ax,0x0003 ; Text mode 80x25x16 colors
pascal@185 132 int 0x10 ; Setup
pascal@185 133 int 0x20 ; Exit to DOS / bootOS
pascal@185 134 int 0x19
pascal@182 135 .0:
pascal@180 136 mov ah,0x02 ; Read modifier keys
pascal@180 137 int 0x16
pascal@180 138 test al,0x04 ; Left ctrl
pascal@180 139 je .1
pascal@180 140 mov byte [di+6],0 ; Erase right side of paddle
pascal@180 141 mov byte [di+8],0
pascal@180 142 sub di,byte 4 ; Move paddle to left
pascal@180 143 cmp di,0x0f02 ; Limit
pascal@180 144 ja .1
pascal@180 145 mov di,0x0f02
pascal@180 146 .1:
pascal@180 147 test al,0x08 ; Left alt
pascal@180 148 je .2
pascal@180 149 xor ax,ax ; Erase left side of paddle
pascal@180 150 stosw
pascal@180 151 stosw ; DI increased automatically
pascal@180 152 cmp di,0x0f94 ; Limit
pascal@180 153 jb .2
pascal@180 154 mov di,0x0f94
pascal@180 155 .2:
pascal@180 156 test al,0x02 ; Left shift
pascal@180 157 je .15
pascal@180 158 mov ax,[bp+ball_xs] ; Ball moving?
pascal@180 159 add ax,[bp+ball_ys]
pascal@180 160 jne .15 ; Yes, jump
pascal@180 161 ; Setup movement of ball
pascal@180 162 mov word [bp+ball_xs],0xff40
pascal@180 163 mov word [bp+ball_ys],0xff80
pascal@180 164 .15:
pascal@180 165 mov ax,0x0adf ; Paddle graphic and color
pascal@180 166 push di
pascal@180 167 stosw ; Draw paddle
pascal@180 168 stosw
pascal@180 169 stosw
pascal@180 170 stosw
pascal@180 171 stosw
pascal@180 172 pop di
pascal@180 173
pascal@180 174 mov bx,[bp+ball_x] ; Draw ball
pascal@180 175 mov ax,[bp+ball_y]
pascal@180 176 call locate_ball ; Locate on screen
pascal@180 177 test byte [bp+ball_y],0x80 ; Y-coordinate half fraction?
pascal@180 178 mov ah,0x60 ; Interchange colors for smooth mov.
pascal@180 179 je .12
pascal@180 180 mov ah,0x06
pascal@180 181 .12: mov al,0xdc ; Graphic
pascal@180 182 mov [bx],ax ; Draw
pascal@180 183 push bx
pascal@180 184 pop si
pascal@180 185
pascal@180 186 .14:
pascal@180 187 mov bx,[bp+ball_x] ; Ball position
pascal@180 188 mov ax,[bp+ball_y]
pascal@180 189 add bx,[bp+ball_xs] ; Add movement speed
pascal@180 190 add ax,[bp+ball_ys]
pascal@180 191 push ax
pascal@180 192 push bx
pascal@180 193 call locate_ball ; Locate on screen
pascal@180 194 mov al,[bx]
pascal@180 195 cmp al,0xb1 ; Touching borders
pascal@180 196 jne .3
pascal@186 197 mov cl,5423/256 ; 1193180 / 220
pascal@180 198 call speaker ; Generate sound
pascal@180 199 pop bx
pascal@180 200 pop ax
pascal@180 201 cmp bh,0x4f
pascal@180 202 je .8
pascal@180 203 test bh,bh
pascal@180 204 jne .7
pascal@180 205 .8:
pascal@180 206 neg word [bp+ball_xs] ; Negate X-speed if it touches a side
pascal@180 207 .7:
pascal@180 208 test ah,ah
pascal@180 209 jnz .9
pascal@180 210 neg word [bp+ball_ys] ; Negate Y-speed if it touches a side
pascal@180 211 .9: jmp .14
pascal@180 212
pascal@180 213 .3:
pascal@180 214 cmp al,0xdf ; Touching paddle
pascal@180 215 jne .4
pascal@180 216 sub bx,di ; Subtract paddle position
pascal@180 217 sub bx,byte 4
pascal@180 218 mov cl,6 ; Multiply by 64
pascal@180 219 shl bx,cl
pascal@180 220 mov [bp+ball_xs],bx ; New X speed for ball
pascal@180 221 mov word [bp+ball_ys],0xff80 ; Update Y speed for ball
pascal@186 222 mov cl,2711/256 ; 1193180 / 440
pascal@180 223 call speaker ; Generate sound
pascal@186 224 .16: pop bx
pascal@180 225 pop ax
pascal@180 226 jmp .14
pascal@180 227
pascal@180 228 .4:
pascal@180 229 cmp al,0xdb ; Touching brick
pascal@180 230 jne .5
pascal@186 231 mov cl,1355/256 ; 1193180 / 880
pascal@180 232 call speaker ; Generate sound
pascal@180 233 test bl,2 ; Aligned with brick?
pascal@180 234 jne .10 ; Yes, jump
pascal@180 235 dec bx ; Align
pascal@180 236 dec bx
pascal@186 237 .10: and word [bx],0 ; Erase brick
pascal@186 238 and word [bx+2],0
pascal@180 239 inc word [bp+score] ; Increase score
pascal@180 240 neg word [bp+ball_ys] ; Negate Y speed (rebound)
pascal@186 241 dec word [bp+bricks] ; One brick less on screen
pascal@186 242 jne .16 ; Fully completed? No, jump.
pascal@180 243 pop bx
pascal@180 244 pop ax
pascal@180 245 jmp another_level ; Start another level
pascal@180 246
pascal@180 247 .5:
pascal@180 248 pop bx
pascal@180 249 pop ax
pascal@180 250 .6:
pascal@180 251 mov [bp+ball_x],bx ; Update ball position
pascal@180 252 mov [bp+ball_y],ax
pascal@180 253 cmp ah,0x19 ; Ball exited through bottom?
pascal@180 254 je ball_lost ; Yes, jump
pascal@180 255 jmp game_loop ; No, repeat game loop
pascal@180 256
pascal@180 257 ;
pascal@180 258 ; Ball lost
pascal@180 259 ;
pascal@180 260 ball_lost:
pascal@186 261 mov cl,10846/256 ; 1193180 / 110
pascal@180 262 call speaker ; Generate sound
pascal@180 263
pascal@182 264 and word [si],0 ; Erase ball
pascal@180 265 dec byte [bp+balls] ; One ball less
pascal@180 266 js .1 ; All finished? Yes, jump
pascal@180 267 jmp another_ball ; Start another ball
pascal@180 268
pascal@180 269 .1: call wait_frame.2 ; Turn off sound
pascal@180 270 jmp start
pascal@180 271
pascal@180 272 wait_frame:
pascal@180 273 .0:
pascal@182 274 hlt ; Wait for clock interrupt
pascal@180 275 mov ah,0x00 ; Read ticks
pascal@180 276 int 0x1a ; Call BIOS
pascal@180 277 cmp dx,[bp+old_time] ; Wait for change
pascal@180 278 je .0
pascal@180 279 mov [bp+old_time],dx
pascal@180 280
pascal@186 281 dec byte [bp+beep] ; Decrease time to turn off beep
pascal@186 282 jne speaker.2
pascal@180 283 .2:
pascal@180 284 in al,0x61
pascal@180 285 and al,0xfc ; Turn off
pascal@186 286 jmp speaker.1
pascal@180 287
pascal@180 288 ;
pascal@180 289 ; Generate sound on PC speaker
pascal@180 290 ;
pascal@180 291 speaker:
pascal@186 292 mov byte [bp+beep],3 ; Duration
pascal@180 293 mov al,0xb6 ; Setup timer 2
pascal@180 294 out 0x43,al
pascal@186 295 out 0x42,al ; Low byte of timer count
pascal@186 296 xchg ax,cx ; High byte of timer count
pascal@180 297 out 0x42,al
pascal@180 298 in al,0x61
pascal@180 299 or al,0x03 ; Connect PC speaker to timer 2
pascal@186 300 .1: out 0x61,al
pascal@186 301 .2: ret
pascal@180 302
pascal@180 303 ;
pascal@180 304 ; Locate ball on screen
pascal@180 305 ;
pascal@180 306 locate_ball:
pascal@180 307 mov al,0xa0
pascal@180 308 mul ah ; AH = Y coordinate (row)
pascal@180 309 mov bl,bh ; BH = X coordinate (column)
pascal@180 310 mov bh,0
pascal@186 311 add bx,bx
pascal@180 312 add bx,ax
pascal@180 313 ret
pascal@180 314
pascal@180 315 ;
pascal@180 316 ; Update score indicator (from bootRogue)
pascal@180 317 ;
pascal@180 318 update_score:
pascal@180 319 mov bx,0x0f98 ; Point to bottom right corner
pascal@180 320 mov ax,[bp+score]
pascal@180 321 call .1
pascal@180 322 mov al,[bp+balls]
pascal@180 323 .1:
pascal@180 324 xor cx,cx ; CX = Quotient
pascal@180 325 .2: inc cx
pascal@180 326 sub ax,10 ; Division by subtraction
pascal@180 327 jnc .2
pascal@180 328 add ax,0x0a3a ; Convert remainder to ASCII digit + color
pascal@180 329 call .3 ; Put on screen
pascal@180 330 xchg ax,cx
pascal@180 331 dec ax ; Quotient is zero?
pascal@180 332 jnz .1 ; No, jump to show more digits.
pascal@180 333
pascal@180 334 .3: mov [bx],ax
pascal@180 335 dec bx
pascal@180 336 dec bx
pascal@180 337 ret
pascal@180 338
pascal@180 339 times 510-($-$$) db 0x4f
pascal@180 340 db 0x55,0xaa ; Make it a bootable sector