wok-tiny view bootinvaders/stuff/invaders.asm @ rev 180

Add boot-man, bootbricks, bootfbird, bootinvaders, bootmine, bootpillman, bootris, bootsokoban
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Sep 20 13:08:44 2023 +0000 (7 months ago)
parents
children bbb34fe4904d
line source
1 ;
2 ; Invaders in 512 bytes
3 ;
4 ; by Oscar Toledo G.
5 ;
6 ; (c) Copyright 2015-2019 Oscar Toledo G.
7 ;
8 ; Creation: Oct/27/2015.
9 ; Revision: Nov/06/2015. Adjusted bullet collision. Invaders
10 ; accelerate.
11 ; Revision: Apr/03/2019. Invaders now can shoot. Spaceship does
12 ; explosion.
13 ; Revision: May/28/2019. Invaders goes down at 11px instead 12px.
14 ; Now starts another invaders wave more
15 ; difficult.
16 ; Revision: Jun/01/2019. Redesigned for 320x200x256 mode.
17 ; Revision: Jun/02/2019. Now in color. Color carries information
18 ; about thing being hit.
19 ; Revision: Jun/03/2019. Optimized, 601 bytes as COM!!!
20 ; Revision: Jun/04/2019. At last 512 bytes!
21 ; Revision: Jun/05/2019. By popular demand added pure8088 option. Now
22 ; the 8088 version also is bootable! so now
23 ; 8088 is the default.
24 ; Revision: Jun/06/2019. jtsiomb made the point that the COM file
25 ; doesn't need to be 512 bytes, so Esc for
26 ; exiting and also returns to text mode.
27 ; Revision: Jun/29/2019. Now spaceship moves to left pressing Ctrl,
28 ; to right pressing Alt, and shoots pressing
29 ; Shift. Spaceship stops when you depress the
30 ; direction key. To exit you press Scroll
31 ; Lock. Used the extra bytes to implement
32 ; barriers that stop the invaders' bullets.
33 ; (suggested in Reddit by nils-m-holm).
34 ; Revision: Sep/13/2023. Fix bootsector end of game. Position
35 ; independant code.
36 ;
38 cpu 8086
40 base: equ 0xfc80 ; Memory base (same segment as video)
42 shots: equ base+0x00 ; Space to contain 4 shots (2 bytes each one)
43 ; Plus space for a ignored shot (full table)
44 ; Notice (sprites + SPRITE_SIZE) - (shots + 2)
45 ; must be divisible by SPRITE_SIZE.
46 old_time: equ base+0x0c ; Old time
47 level: equ base+0x10 ; Current level number
48 lives: equ base+0x11 ; Current lives
49 sprites: equ base+0x12 ; Space to contain sprite table
51 SHIP_ROW: equ 0x5c*OFFSET_X ; Row of spaceship
52 X_WIDTH: equ 0x0140 ; X-width of video
53 OFFSET_X: equ X_WIDTH*2 ; X-offset between screen rows (2 pixels)
54 SPRITE_SIZE: equ 4 ; Size of each sprite in bytes
56 ;
57 ; All colors different (important to distinguish things)
58 ;
59 SPACESHIP_COLOR: equ 0x1c ; Must be below 0x20
60 BARRIER_COLOR: equ 0x0b
61 SHIP_EXPLOSION_COLOR: equ 0x0a
62 INVADER_EXPLOSION_COLOR: equ 0x0e
63 BULLET_COLOR: equ 0x0c
64 START_COLOR: equ ((sprites+SPRITE_SIZE-(shots+2))/SPRITE_SIZE+0x20)
66 restart_game:
67 mov ax,0x0013 ; Set mode 0x13 (320x200x256 VGA)
68 int 0x10 ; Call BIOS
69 cld
70 mov ax,0xa000 ; Point to screen memory
71 mov ds,ax ; Both DS...
72 mov es,ax ; ...and ES
73 mov ah,0x04
74 mov [level],ax ; Level = 0, Lives = 4
75 mov cx,level/2 ; Clear screen and variables (except level/lives)
76 xor di,di
77 mul di ; Clear ax and dx
78 rep
79 stosw ; ch is zero from here
81 ;
82 ; Setup descend state
83 ;
84 mov ax,[di] ; al now contains level, ah contains lives
85 inc ax ; Increase by 2 (so invaders descend correctly)
86 inc ax
87 stosw ; Advance level
88 mov ah,al
89 xchg ax,dx ; Shouldn't damage DX starting here
91 ;
92 ; Setup the spaceship
93 ;
94 mov ah,SPACESHIP_COLOR
95 stosw
96 mov ax,SHIP_ROW+0x4c*2
97 stosw
98 ;
99 ; Setup the invaders
100 ;
101 mov ax,0x08*OFFSET_X+0x28
102 mov bx,START_COLOR*0x0100+0x10
103 in1: mov cl,0x0b ; Eleven invaders per row
104 in5: stosw ; Set invader position
105 add ax,0x0b*2 ; Go to next column
106 xchg ax,bx
107 stosw ; Set invader color and shape
108 inc ah ; Go to next color
109 xchg ax,bx
110 loop in5 ; Loop and also make sure ch is zero
111 add ax,0x09*OFFSET_X-0x000b*0x000b*2 ; Go to next row
112 cmp bh,START_COLOR+55 ; Whole board finished?
113 jne in1 ; No, jump
115 ;
116 ; Draw the barriers
117 ;
118 mov di,0x55*0x280+0x10*2
119 mov cl,5
120 in48:
121 mov ax,BARRIER_COLOR*0x0100+0x04
122 call draw_sprite
123 add di,0x1e*2
124 loop in48
126 ; CH is zero
128 in14:
129 mov si,sprites+SPRITE_SIZE
131 ;
132 ; Game loop
133 ;
134 ; Globals:
135 ; SI = Next invader to animate
136 ; DL = state (0=left, 1=right, >=2 down)
137 ; DH = nstate (next state)
138 ; CH = dead invaders
139 ; BP = frame counter
140 ;
141 in46:
142 cmp byte [si+2],0x20 ; Current invader is cosmic debris?
143 jc in2 ; No, jump
144 inc ch ; Count another dead invader
145 cmp ch,55 ; All invaders defeated?
146 je restart_game ; Yes, jump.
147 ;
148 ; Yes, invaders speed up
149 ;
150 in6:
151 lodsw ; Load position in AX
152 xchg ax,di ; Move to DI
153 lodsw ; Get type of sprite
154 cmp al,0x20 ; Explosion?
155 ja in27 ; Destroyed? jump
156 jne in29 ; No explosion, jump
157 mov byte [si-2],0x28 ; Don't draw again
158 in29: call draw_sprite ; Draw invader on screen
159 in27: cmp si,sprites+56*SPRITE_SIZE ; Whole board revised?
160 jne in46 ; No, jump
161 mov al,dh
162 sub al,2 ; Going down?
163 jc in14 ; No, preserve left/right direction
164 xor al,1 ; Switch direction
165 mov dl,al
166 mov dh,al
167 jmp in14
169 in2:
170 xor byte [si+2],8 ; Invader animation (before possible explosion)
171 ;
172 ; Synchronize game to 18.20648 hz. of BIOS
173 ;
174 inc bp
175 and bp,7 ; Each 8 invaders
176 push dx
177 push si
178 push bp
179 mov si,shots ; Point to shots list
180 jne in12
181 in22:
182 mov ah,0x00
183 int 0x1a ; BIOS clock read
184 cmp dx,[si+old_time-shots] ; Wait for change
185 je in22
186 mov [si+old_time-shots],dx ; Save new current time
187 in12:
188 %if 1
189 ;
190 ; Handle player bullet
191 ;
192 mov cx,4 ; 4 shots at most
193 lodsw ; Read position (player)
194 cmp ax,X_WIDTH ; Is it at top of screen?
195 xchg ax,di
196 jc in31 ; Erase bullet
197 ; Doesn't mind doing it all time
198 call zero ; Remove bullet
199 sub di,X_WIDTH+2
200 mov al,[di] ; Read pixel
201 sub al,0x20 ; Hits invader?
202 jc in30 ; No, jump
203 push si
204 push di
205 mov ah,SPRITE_SIZE ; The pixel indicates the...
206 mul ah ; ...invader hit.
207 add si,ax
208 lodsw
209 xchg ax,di
210 mov byte [si],0x20 ; Erase next time
211 mov ax,INVADER_EXPLOSION_COLOR*0x0100+0x08 ; But explosion now
212 call draw_sprite ; Draw sprite
213 pop di
214 pop si
215 jmp in31
217 ;
218 ; Handle invader bullets
219 ;
220 in24:
221 lodsw ; Read current coordinate
222 or ax,ax ; Is it falling?
223 je in23 ; No, jump
224 cmp ax,0x60*OFFSET_X ; Pixel lower than spaceship?
225 xchg ax,di
226 jnc in31 ; Yes, remove bullet
227 call zero ; Remove bullet
228 add di,X_WIDTH-2 ; Bullet falls down
230 ; Draw bullet
231 in30:
232 mov al,BULLET_COLOR
233 mov [si-2],di ; Update position of bullet
234 cmp byte [di+X_WIDTH],BARRIER_COLOR ; Barrier in path?
235 jne in7 ; Yes, erase bullet and barrier pixel
237 ; Remove bullet
238 in31: xor ax,ax ; AX contains zero (DI unaffected)
239 mov [si-2],ax ; Delete bullet from table
241 in7: cmp byte [di],SPACESHIP_COLOR ; Check collision with player
242 jne in41 ; No, jump
243 mov word [sprites],SHIP_EXPLOSION_COLOR*0x0100+0x38 ; Player explosion
244 in41:
245 call big_pixel ; Draw/erase bullet
246 in23: loop in24
247 %endif
249 ;
250 ; Spaceship handling
251 ;
252 mov si,sprites ; Point to spaceship
253 lodsw ; Load sprite frame / color
254 or al,al ; Explosion?
255 je in42 ; No, jump
256 add al,0x08 ; Keep explosion
257 jne in42 ; Finished? No, jump
258 mov ah,SPACESHIP_COLOR ; Restore color (sprite already)
259 dec byte [si-2-sprites+lives] ; Remove one life
260 js in10 ; Exit if all used
261 in42: mov [si-2],ax ; Save new frame / color
262 mov di,[si] ; Load position
263 call draw_sprite ; Draw sprite (spaceship)
264 jne in43 ; Jump if still explosion
266 mov ah,0x02 ; BIOS Get Keyboard Flags
267 int 0x16
268 test al,0x10 ; Test for Scroll Lock and exit
269 jnz in10
271 mov bx,12 ; Ctrl/Alt key?
272 and bl,al
273 jp in17 ; test Ctrl xor Alt
274 lea di,[bx+di-6] ; Move 2 pixels to left/right
275 in17:
276 test al,0x03 ; Shift keys?
277 jz in35 ; No, jump
278 cmp word [shots],bx ; Bullet available?
279 ja in35 ; No, jump
280 lea ax,[di+(0x04*2)] ; Offset from spaceship
281 mov [shots],ax ; Start bullet
282 in35:
283 xchg ax,di
284 cmp ax,SHIP_ROW-2 ; Update if not touching border
285 je in43
286 cmp ax,SHIP_ROW+0x0132
287 je in43
288 in19: mov [si],ax ; Update position
289 in43:
290 pop bp
291 pop si
292 pop dx
294 mov cx,4 ; ch = 0 - invader alive
295 mov ax,[si] ; Get position of current invader
296 cmp dl,1 ; Going down (state 2)?
297 jbe in9 ; No, jump
298 add ax,0x0280 ; Go down by 2 pixels
299 cmp ax,0x55*0x280 ; Reaches Earth?
300 jc in8 ; No, jump
301 in10:
302 mov ax,0x0003 ; Restore text mode
303 int 0x10
304 int 0x20 ; Exit to DOS
305 jmp restart_game
307 in9: dec ax ; Moving to left
308 dec ax
309 jc in20
310 add ax,cx ; Moving to right
311 in20: push ax
312 shr ax,1 ; Divide position by 2...
313 mov bl,0xa0 ; ...means we can get column dividing by 0xa0
314 div bl ; ...instead of 0x0140 (longer code)
315 dec ah ; Convert 0x00 to 0xff
316 cmp ah,0x94 ; Border touched? (>= 0x94)
317 pop ax
318 jb in8 ; No, jump
319 or dh,22 ; Goes down by 11 pixels (11 * 2) must be odd
320 in8: mov [si],ax
321 add ax,0x06*0x280+0x03*2 ; Offset for bullet
322 xchg ax,bx
324 in al,(0x40) ; Read timer
325 cmp al,0xfc ; Random event happening?
326 jc in4 ; No, jump
328 mov di,shots
329 in45: scasw ; Advance DI
330 cmp [di],ch ; Search for free slot
331 loopne in45 ; Until 3 slots searched
332 mov [di],bx ; Start invader shot (or put in ignored slot)
333 in4:
334 jmp in6
336 ;
337 ; Draw pixel per Carry (use AX if Carry=1 or zero if Carry=0)
338 ;
339 bit: jc big_pixel
340 zero: xor ax,ax
341 ; Draw a big pixel (2x2 pixels)
342 big_pixel:
343 mov ah, al
344 mov [di+X_WIDTH],ax
345 stosw
346 ret
348 ; ah = sprite color
349 ; al = sprite (x8)
350 ; di = Target address
351 draw_sprite:
352 push cx
353 push di
354 pushf
355 in3: push ax
356 call get_bitmaps
357 ;
358 ; Bitmaps for sprites
359 ;
360 bitmaps:
361 db 0x18,0x18,0x3c,0x24,0x3c,0x7e,0xFf,0x24 ; Spaceship
362 db 0x00,0x80,0x42,0x18,0x10,0x48,0x82,0x01 ; Explosion
363 db 0x00,0xbd,0xdb,0x7e,0x24,0x3c,0x66,0xc3 ; Alien (frame 1)
364 db 0x00,0x3c,0x5a,0xff,0xa5,0x3c,0x66,0x66 ; Alien (frame 2)
365 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; Erase
367 get_bitmaps:
368 pop bx
369 cs xlat ; Extract one byte from bitmap
370 xchg ax,bx ; bl contains byte, bh contains color
371 mov cx,10 ; Two extra zero pixels at left and right
372 clc ; Left pixel as zero (clean)
373 in0: mov al,bh ; Duplicate color in AX
374 call bit ; Draw pixel
375 shl bl,1
376 loop in0
377 add di,OFFSET_X-20 ; Go to next video line
378 pop ax
379 inc ax ; Next bitmap byte
380 test al,7 ; Sprite complete?
381 jne in3 ; No, jump
382 popf
383 pop di
384 pop cx
385 ret
387 times 510-($-$$) db 0x4f
388 db 0x55,0xaa ; Make it a bootable sector