wok-tiny annotate bootfbird/stuff/fbird.asm @ rev 183

linux: fix bundle.S
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Sep 26 17:09:38 2023 +0000 (8 months ago)
parents bbb34fe4904d
children 34a0a4406539
rev   line source
pascal@180 1 ;
pascal@180 2 ; F-bird text game in a bootsector
pascal@180 3 ;
pascal@180 4 ; by Oscar Toledo G.
pascal@180 5 ; http://nanochess.org/
pascal@180 6 ;
pascal@180 7 ; Creation date: Jun/04/2017. A messy unoptimized thing.
pascal@180 8 ; Revision date: Jun/05/2017. Better usage of graphic charset.
pascal@180 9 ; Removed a non-8088 long jump. Added
pascal@180 10 ; sound. Solved bug when overwriting
pascal@180 11 ; previous score.
pascal@180 12 ;
pascal@180 13
pascal@180 14 use16
pascal@180 15 cpu 8086
pascal@180 16
pascal@180 17 restart:
pascal@180 18 mov ax,0x0002 ; Set 80x25 text mode
pascal@180 19 int 0x10 ; Call BIOS
pascal@180 20 ;
pascal@180 21 ; Game restart
pascal@180 22 ;
pascal@180 23 fb21: cld ; Reset direction flag (so stosw increments registers)
pascal@183 24 sti ; Allow interrupts
pascal@180 25 mov ax,0xb800 ; Point to video segment
pascal@180 26 mov ds,ax ; Both the source (common access)
pascal@180 27 mov es,ax ; and target segments
pascal@180 28 mov di,pipe ; Init variables in video segment (saves big bytes)
pascal@180 29 cbw
pascal@180 30 stosw ; pipe
pascal@180 31 stosw ; score
pascal@180 32 stosw ; grav
pascal@180 33 mov al,0xa0
pascal@180 34 stosw ; next
pascal@180 35 mov al,0x60
pascal@180 36 stosw ; bird
pascal@180 37
pascal@180 38 mov di,0x004a ; Game title
pascal@180 39 mov ax,0x0f46 ; 'F' in white, good old ASCII
pascal@180 40 stosw
pascal@180 41 mov al,0x2d ; '-'
pascal@180 42 stosw
pascal@180 43 mov al,0x42 ; 'B'
pascal@180 44 stosw
pascal@180 45 mov al,0x49 ; 'I'
pascal@180 46 stosw
pascal@180 47 mov al,0x52 ; 'R'
pascal@180 48 stosw
pascal@180 49 mov al,0x44 ; 'D'
pascal@180 50 stosw
pascal@182 51 mov bp,80 ; Introduce 80 columns of scenery
pascal@182 52 fb1: call scroll_scenery
pascal@182 53 dec bp
pascal@182 54 jnz fb1
pascal@180 55
pascal@180 56 fb23: mov ah,0x01 ; Check if key pressed
pascal@180 57 int 0x16
pascal@180 58 pushf
pascal@180 59 xor ax,ax ; Wait for a key
pascal@180 60 int 0x16
pascal@180 61 popf
pascal@180 62 jnz fb23 ; Jump if key was accumulated, if not already waited for key ;)
pascal@180 63
pascal@180 64 ;
pascal@180 65 ; Main loop
pascal@180 66 ;
pascal@180 67 fb12: mov si,bird
pascal@180 68 lodsw ; Bird falls...
pascal@180 69 add al,[grav] ; ...because of gravity...
pascal@180 70 mov [bird],al ; ...into new position.
pascal@180 71 and al,0xf8 ; Row is a 5.3 fraction, nullify fraction
pascal@180 72 mov ah,0x14 ; Given integer is x8, multiply by 20 to get 160 per line
pascal@180 73 mul ah ; Row into screen
pascal@180 74 add ax,$0020 ; Fixed column
pascal@180 75 xchg ax,di ; Pass to DI (AX cannot be used as pointer)
pascal@180 76 lodsb ; mov al,[frame]
pascal@180 77 and al,4 ; Wing movement each 4 frames
pascal@180 78 jz fb15
pascal@180 79 mov al,[di-160] ; Get character below
pascal@180 80 mov word [di-160],$0d1e ; Draw upper wing
pascal@180 81 add al,[di] ; Add another character below
pascal@180 82 shr al,1 ; Normalize
pascal@180 83 mov word [di],$0d14 ; Draw body
pascal@180 84 jmp short fb16
pascal@180 85
pascal@180 86 fb15: mov al,[di] ; Get character below
pascal@180 87 mov word [di],$0d1f ; Draw body
pascal@180 88 fb16: add al,[di+2] ; Get character below head
pascal@180 89 mov word [di+2],$0d10 ; Draw head
pascal@180 90 cmp al,0x40 ; Collision with scenery?
pascal@180 91 jz fb19
pascal@180 92 ;
pascal@180 93 ; Stars and game over
pascal@180 94 ;
pascal@180 95 mov byte [di],$2a ; '*' Asterisks to indicate crashing
pascal@180 96 mov byte [di+2],$2a
pascal@180 97 mov di,0x07CA
pascal@180 98 mov ax,0x0f42 ; 'B' in white, good old ASCII
pascal@180 99 stosw
pascal@180 100 mov al,0x4F ; 'O'
pascal@180 101 stosw
pascal@180 102 mov al,0x4E ; 'N'
pascal@180 103 stosw
pascal@180 104 mov al,0x4B ; 'K'
pascal@180 105 stosw
pascal@180 106 mov al,0x21 ; '!'
pascal@180 107 stosw
pascal@182 108 mov bp,100 ; Wait 100 frames
pascal@182 109 fb20: call wait_frame
pascal@182 110 dec bp
pascal@182 111 jnz fb20
pascal@180 112 jmp fb21 ; Restart
pascal@180 113
pascal@180 114 fb19: call wait_frame ; Wait for frame
pascal@180 115 mov al,[frame]
pascal@180 116 and al,7 ; 8 frames have passed?
pascal@180 117 jnz fb17 ; No, jump
pascal@180 118 inc word [grav] ; Increase gravity
pascal@180 119 fb17:
pascal@180 120 mov al,$20
pascal@180 121 mov [di-160],al ; Delete bird from screen
pascal@180 122 mov [di+2],al
pascal@180 123 stosb
pascal@180 124 call scroll_scenery ; Scroll scenery
pascal@180 125 call scroll_scenery ; Scroll scenery
pascal@180 126 cmp byte [0x00a0],0xb0 ; Passed a column?
pascal@180 127 jz fb27
pascal@180 128 cmp byte [0x00a2],0xb0 ; Passed a column?
pascal@180 129 fb27: jnz fb24
pascal@180 130 inc word [score] ; Increase score
pascal@180 131 mov ax,[score]
pascal@180 132 mov di,0x008e ; Show current score
pascal@180 133 fb25: xor dx,dx ; Extend AX to 32 bits
pascal@180 134 mov bx,10 ; Divisor is 10
pascal@180 135 div bx ; Divide
pascal@180 136 add dx,0x0c30 ; Convert remaining 0-9 to ASCII, also put color
pascal@180 137 xchg ax,dx
pascal@180 138 std
pascal@180 139 stosw
pascal@180 140 mov byte [di],0x20 ; Clean at least one character of prev. score
pascal@180 141 cld
pascal@180 142 xchg ax,dx
pascal@180 143 or ax,ax ; Score digits still remain?
pascal@180 144 jnz fb25 ; Yes, jump
pascal@180 145 fb24: mov ah,0x01 ; Any key pressed?
pascal@180 146 int 0x16
pascal@180 147 jz fb26 ; No, go to main loop
pascal@180 148 mov ah,0x00
pascal@180 149 int 0x16 ; Get key
pascal@180 150 dec ah ; Escape key?
pascal@180 151 jne fb4 ; No, jump
pascal@180 152 mov al,3
pascal@180 153 int 0x10
pascal@180 154 int 0x20 ; Exit to DOS or to oblivion (boot sector)
pascal@182 155 int 0x19
pascal@180 156 fb4: mov ax,[bird]
pascal@180 157 sub ax,0x10 ; Move bird two rows upward
pascal@180 158 cmp ax,0x08 ; Make sure the bird doesn't fly free outside screen
pascal@180 159 jb fb18
pascal@180 160 mov [bird],ax
pascal@180 161 fb18: mov byte [grav],0 ; Reset gravity
pascal@180 162 mov al,0xb6 ; Flap sound
pascal@180 163 out (0x43),al
pascal@180 164 mov al,0x90
pascal@180 165 out (0x42),al
pascal@180 166 mov al,0x4a
pascal@180 167 out (0x42),al
pascal@180 168 in al,(0x61)
pascal@180 169 or al,0x03 ; Turn on sound
pascal@180 170 out (0x61),al
pascal@180 171 fb26: jmp fb12
pascal@180 172
pascal@180 173 ;
pascal@180 174 ; Scroll scenery one column at a time
pascal@180 175 ;
pascal@180 176 scroll_scenery:
pascal@180 177 ;
pascal@180 178 ; Move whole screen
pascal@180 179 ;
pascal@180 180 mov si,0x00a2 ; Point to row 1, column 1 in SI
pascal@180 181 mov di,0x00a0 ; Point to row 1, column 0 in DI
pascal@180 182 fb2: mov cx,79 ; 79 columns
pascal@180 183 repz ; Scroll!!!
pascal@180 184 movsw
pascal@180 185 mov ax,0x0e20 ; Clean last character
pascal@180 186 stosw
pascal@180 187 lodsw ; Advance source to keep pair source/target
pascal@180 188 cmp si,0x0fa2 ; All scrolled?
pascal@180 189 jnz fb2 ; No, jump
pascal@180 190 ;
pascal@180 191 ; Insert houses
pascal@180 192 ;
pascal@180 193 mov word [0x0f9e],0x02df ; Terrain
pascal@180 194 in al,(0x40) ; Get "random" number
pascal@180 195 and al,0x70
pascal@180 196 jz fb5
pascal@180 197 mov bx,0x0408 ; House of one floor
pascal@180 198 mov [0x0efe],bx
pascal@180 199 mov di,0x0e5e
pascal@180 200 and al,0x20 ; Check "random" number
pascal@180 201 jz fb3
pascal@180 202 mov [di],bx ; House of two floors
pascal@180 203 sub di,0x00a0
pascal@180 204 fb3: mov word [di],0x091e ; Add roof
pascal@180 205 ;
pascal@180 206 ; Check if it's time to insert a column
pascal@180 207 ;
pascal@180 208 fb5: dec word [next] ; Decrease time (column really) for next pipe
pascal@180 209 mov bx,[next]
pascal@180 210 cmp bx,0x03 ; bx = 3,2,1,0 for the four columns making the pipe
pascal@180 211 ja fb6
pascal@180 212 jne fb8
pascal@180 213 in al,(0x40) ; Get "random" number
pascal@180 214 and ax,0x0007 ; Between 0 and 7
pascal@180 215 add al,0x04 ; Between 4 and 11
pascal@180 216 mov [tall],ax ; This will tell how tall the pipe is
pascal@180 217 fb8: mov cx,[tall]
pascal@180 218 or bx,bx ; Rightmost?
pascal@180 219 mov dl,0xb0
pascal@180 220 jz fb7 ; Yes, jump
pascal@180 221 mov dl,0xdb
pascal@180 222 cmp bx,0x03 ; Leftmost?
pascal@180 223 jb fb7 ; No, jump
pascal@180 224 mov dl,0xb1
pascal@180 225 fb7: mov di,0x013e ; Start from top of screen
pascal@180 226 mov ah,0x0a
pascal@180 227 mov al,dl
pascal@180 228 mov dx,0x009e
pascal@180 229 fb9: stosw
pascal@180 230 add di,dx
pascal@180 231 loop fb9
pascal@180 232 mov al,0xc4
pascal@180 233 stosw
pascal@180 234 add di,0x009e*6+10
pascal@180 235 mov al,0xdf
pascal@180 236 stosw
pascal@180 237 add di,dx
pascal@180 238 fb10: mov al,dl
pascal@180 239 stosw
pascal@180 240 add di,dx
pascal@180 241 cmp di,0x0f00
pascal@180 242 jb fb10
pascal@180 243 or bx,bx
pascal@180 244 jnz fb6
pascal@180 245 mov ax,[pipe]
pascal@180 246 inc ax ; Increase total pipes shown
pascal@180 247 mov [pipe],ax
pascal@180 248 mov cl,3
pascal@180 249 shr ax,cl
pascal@180 250 mov ah,0x50 ; Decrease distance between pipes
pascal@180 251 sub ah,al
pascal@180 252 cmp ah,0x10
pascal@180 253 ja fb11
pascal@180 254 mov ah,0x10
pascal@180 255 fb11: mov [next],ah ; Time for next pipe
pascal@180 256 fb6: ret
pascal@180 257
pascal@180 258 ;
pascal@180 259 ; Wait for a frame
pascal@180 260 ;
pascal@180 261 wait_frame:
pascal@180 262
pascal@180 263 mov bx, tick
pascal@182 264 fb14: hlt ; Wait for clock interrupt
pascal@182 265 mov ah,0x00 ; Use base clock tick
pascal@180 266 int 0x1a
pascal@180 267 cmp dx,[bx]
pascal@180 268 jz fb14
pascal@180 269 mov [bx],dx
pascal@180 270 inc word [bx+frame-tick] ; Increase frame count
pascal@180 271 in al,(0x61)
pascal@180 272 and al,0xfc ; Turn off sound
pascal@180 273 out (0x61),al
pascal@180 274 ret
pascal@180 275
pascal@180 276 times 507 - ($-$$) db 0 ; pad remaining 507 bytes with zeroes
pascal@180 277
pascal@180 278 db "OTG" ; 3 unused bytes
pascal@180 279
pascal@180 280 db 0x55,0xaa ; Bootable signature
pascal@180 281
pascal@180 282 pipe: equ 0x0fa0
pascal@180 283 score: equ 0x0fa2
pascal@180 284 grav: equ 0x0fa4
pascal@180 285 next: equ 0x0fa6
pascal@180 286 bird: equ 0x0fa8
pascal@180 287 frame: equ 0x0faa
pascal@180 288 tall: equ 0x0fac
pascal@180 289 tick: equ 0x0fae