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

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