413ab08496af0e15b1f4431774706018e4166247
[nemesis.git] / nemesis.z80
1 ;----------------------------------------------------------------------------
2 ;---------------------- NEMESIS ---------------------------------------------
3 ;----------------------------------------------- cool arcade-shoot-em-up-game
4
5 ;by SHIAR | shiar0@hotmail.com | icq#43840958 | www.shiar.org
6
7 ;This source should only be used for learning practises, do not
8 ;alter it, and certainly never distribute an altered version!!
9
10 ;&&& marks uncertainties or things to optimize
11
12 ;TO DO:
13 ; up-double | torpedoes | levels 7-12 | jp m | better weapons
14
15 ;---------------------- nemesis.z80 start -----------------------------------
16
17 #include        "asm86.h"
18 #include        "ti86asm.inc"   ;standard ti86 romcalls
19 #include        "ti86abs.inc"   ;used to save hiscores and so
20
21         .org _asm_exec_ram
22
23 #define           cal   call    ;just to make it harder for you to understand
24 #define           psh   push    ; ^:D
25 #define           dnz   djnz    ;Dec&Jump while NonZero becomes Do w.Non-Zero
26
27 dispbuffer      = $81FA ;= $C9FA                ;virtual screen
28 ;VIDEO_MEM      = $FC00         ;tha big scareen
29 TEXT_MEM        = _textShadow   ;text buffer; C0F9-C1A0 (167/$A7 bytes)
30
31 _clrWindow      = $4a86         ;_clrLCD and _clrScrn
32 _ex_ahl_bde     = $45f3         ;exchange values between AHL and BDE
33 _shracc         = $4383         ;like _shlacc but just the opposite :P
34 _dispahl        = $4a33         ;display value in ahl <100000 (cheap TI)
35 _asapvar        = $d6fc         ;our own variable name (likely "nemesis")
36
37 storepos        = _asm_exec_ram+7000            ;120 OF 165
38 storepos2       = _asm_exec_ram+7200            ;141 OF 167 9000 BYTES
39
40 ;---------------------- in-game vars ----------------------------------------
41
42 just_fired      = storepos              ; +0    ;counts how long a blast lasts
43 hiscorepos      = storepos              ; +0    ;entering hiscore name
44                                         ;       ;--------YOU
45 x               = storepos+1            ; +1    ;your ship's position
46 y               = x+1                   ; +2    ;your y-pos
47 firex           = y+1                   ; +3    ;(1 byte)
48 firey           = firex+1               ; +4    ;(1 byte)
49                                         ;       ;--------LEVEL
50 eventleft       = storepos+5            ; +5    ;nr. of enemies still to come
51 level_enemy     = eventleft+1           ; +7    ;enemy type
52 level_info      = level_enemy+1         ; +8    ;info (see below)
53 level_move      = level_info+1          ; +9    ;=
54 spacespace      = level_move+1          ;+10
55 groundinfo      = spacespace+1          ;+20
56 groundpos       = groundinfo+1          ;+21    $10
57 ceilingpos      = groundpos+16          ;+37    $10
58                                         ;       ;--------STARS
59 stars1          = ceilingpos+16         ;+53
60 stars2          = stars1+1              ;+54
61 nrstars1        = 7
62 starx1          = storepos+55           ;+55
63 nrstars2        = 7
64 starx2          = starx1+(nrstars1*2)   ;+69
65                                         ;       ;--------MULTIPLES
66 your_prevpos    = starx2+(nrstars2*2)   ;+87    ;save previous positions (32d)
67 mm              = 4                             ;max. number of multiples
68
69 ;^-----------------------------------<1 ;-120=$78
70
71 enemies         = storepos2             ;  +0   ;info about each enemy
72 enemysize       = 10                            ;infobytes per enemy
73 nrenemies       = 16                            ;max. nr of enemies
74
75 ybullets        = enemies+(nrenemies*enemysize) ;60 bytes = 20(state,damg,x,y)
76 nrybuls         = 128                   ; +80\
77 ebullets        = ybullets+(nrybuls*4)  ;+110   ;30 bytes = 10(state,x,y)
78 nrebuls         = 48
79 lvlenemies      = ebullets+(nrebuls*3)
80
81 ;^-----------------------------------<2 ;-141=$8D
82 ;level_info:
83 ;       [0000:damage 0:diagfire 0:ground 0:ceiling 0:-]
84 ;enemies:
85 ;       [HP64] [000000:HP left 00:(00=no enemy 01=exploding 10=normal 11=moving)]
86 ;       [ship type or explosion frame] [x] [y] [movetype] [movecounter]
87 ;       [firecounter] [firefreq] [firetype]
88
89 ;---------------------- introduction ----------------------------------------
90
91          nop                    ;hello yas/ase/rascall/whathever
92          jp init                ;here's the program, but first: a description
93         .dw $0001               ;description type 2 (description + YASicon)
94         .dw Title               ;pointer to description (all shells)
95         .dw Icon                ;pointer to YAS icon
96
97 Title:  .db "Nemesis v0.99.812 by SHIAR",0
98
99 Icon:   .db 8,1                 ;icon for YAS: width = 1byte; height = 9bytes
100         .db %11100000           ; ███
101         .db %01111000           ;  ████
102         .db %00111110           ;   █████
103         .db %01111001           ;  ████  █
104         .db %00111110           ;   █████
105         .db %01111000           ;  ████
106         .db %11100000           ; ███             ;recommend 80x50 screen mode
107         .db 0                   ;YAS 0.92 compatibility
108
109 ;---------------------- init ------------------------------------------------
110
111 int_handler:                    ;new interrupt proc
112         ex  af,af'              ;just af only (no need for exx)
113         in  a,($03)             ;read bit 3 port 3
114         bit 3,a                 ;is ON key pressed?
115         jp  z,$0039             ;no: np, return
116         res 0,a                 ;yes: then we have a problem (freeze), so...
117         out ($03),a             ;...mask the ON key interrupts!
118         jp  $0039               ;all done, return
119 int_end:
120
121 init:   cal BUSY_OFF            ;turns the run-indicator off, obviously
122         cal _clrScrn            ;clean the screen
123         xor a                   ;ld a,0
124         res 2,(iy+13)           ;don't scroll the screen
125         cal _flushallmenus      ;remove TI menus
126
127 FixKeys:                        ;fixes some key problems like left+down bug
128         im  1
129         ld  a,$D4
130         ld  bc,$0100
131         ld  h,a
132         ld  l,c                 ;ld hl,$D400 (user silent link routine space)
133         ld  d,a
134         ld  e,b                 ;ld de,$D401
135         dec a                   ;ld a,$D3
136         ld  (hl),a
137         ldir                    ;fill $D400-D500 with $D3s (slink/user on)
138         ld  hl,int_handler      ;new interrupt handler
139         ld  d,a
140         ld  e,a                 ;ld de,$D3D3
141         ld  bc,int_end-int_handler
142         ldir                    ;load new handler at ($D3D3)
143         inc a                   ;ld a,$D4
144         ld  i,a
145         im  2
146
147 ;---------------------- main menu -------------------------------------------
148
149 LogoPut:
150         xor a                   ;white bitmask (a=0)
151         ld  hl,logo_nemesis     ;from...
152         ld  de,VIDEO_MEM+16     ;...to one line from top
153         ld  b,e                 ;ld b,16: one line
154 AboveLogo:
155         ld  (de),a              ;clear/n byte
156         inc de                  ;next
157         dnz AboveLogo           ;repeat for the first line
158         ld  bc,16*19            ;logo size
159         ldir                    ;display one line of logo
160
161         ld  hl,16*$33+VIDEO_MEM ;$33 rows down
162         ld  b,16*7              ;draw black 7 lines
163         ld  a,%11111111         ;horizontal line mask
164 underline:
165         ld  (hl),a              ;draw one piece of the divider-line
166         inc hl                  ;move right (8 pixels = 1 byte)
167         dnz underline           ;repeat
168
169         ld  hl,_txt_email       ;at the very bottom of tha screen
170         ld  (_penCol),hl
171         ld  hl,txt_email        ;hey, my e-mail address so SEND ME SOMETHING!!
172         cal _vputs              ;VERY important, so display in small font ?:}
173
174         set 3,(iy+5)            ;set white on black
175         ld  de,_txt_about       ;near the bottom of the screen
176         ld  (_penCol),de        ;hl=txt_email++=txt_about
177         cal _vputs              ;display version + me
178         res 3,(iy+5)            ;return to default black on white
179
180 dispmenu:
181         ld  de,$0304
182         ld  (_curRow),de
183         ld  hl,txt_menu1
184         cal _puts
185         ld  de,$0305
186         ld  (_curRow),de
187         ld  hl,txt_menu2
188         cal _puts
189
190 menuloop:
191         ld  a,0                 ;current menu item (0 or 1); 0 by default
192 menuitem =$-1
193         ld  h,$01
194         add a,4
195         ld  l,a
196
197         ld  a,5
198         ld  (_curRow),hl
199         cal _putc
200
201         ld  a,(menuitem)
202         ld  h,$01
203         sub 5
204         neg
205         ld  l,a
206
207         ld  a,32
208         ld  (_curRow),hl
209         cal _putc
210
211         cal getsomekeys         ;read keys (z if enter/2nd pressed)
212         jr  z,start_tha_freakin_game
213         cp  K_EXIT
214         jr  z,menuexit
215         cp  K_UP
216         jr  z,menuchange
217         cp  K_DOWN
218         jr  nz,menuloop
219 menuchange:
220         ld  hl,menuitem
221         ld  a,(hl)
222         xor 1                   ;0=1; 1=0
223         ld  (hl),a              ;set new menu item
224         jr  menuloop
225
226 start_tha_freakin_game:
227         ld  a,(menuitem)
228         dec a
229         cal nz,New_game         ;NEW GAME
230         jp  samelevel           ;CONTINUE: game_main_loop
231
232 menuexit:
233         ld  hl,0                ;reset score
234         ld  (your_score),hl     ;(prevents hiscore while never played)
235         jp  game_over           ;and go to game over screen
236
237 do_invert:                      ;invert screen (b<>w)
238         psh hl
239         psh af                  ;can't destroy b
240         ld  hl,_invert
241         ld  a,$98
242         xor (hl)                ;$2F (cpl) <-> $B7 (or a)
243         ld  (hl),a
244         pop af
245         pop hl
246         ret
247
248 getsomekeys:
249         halt
250         halt
251         cal GET_KEY
252         cp  K_SECOND
253         ret z
254         cp  K_ENTER
255         ret
256
257 ;----------------------------------------------------------------------------
258 ;---------------------- game loop -------------------------------------------
259 ;----------------------------------------------------------------------------
260
261 game_main_loop:                 ;REPEATS FROM HERE EVERY FRAME
262         ld  hl,timer            ;update time
263         inc (hl)                ;increase by 1
264         ld  a,(hl)
265         and %11111
266         ld  hl,1                ;once every 32 frames, increase score by 1
267         cal z,scoreInc          ;do it
268
269 Clear_screen:
270         ld  hl,dispbuffer       ;move from (hl) = top left
271         ld  (hl),$00            ;first pixel will be copied all over the screen
272         ld  de,dispbuffer+1     ;(de) = next pixel, thus clearing whole screen
273         ld  bc,896              ;loop 896 times = (128/8) * (64-8 for scorebar)
274         ldir                    ;all clear!
275
276         ld  a,0                 ;current frame/turn 0-255
277 timer =$-1
278         and %11                 ;a=0 once every 4 turns
279         jr  z,movestarsdone     ;don't move stars once every 4 frames
280         cal movestars1          ;move the stars on the FRONT layer
281         cal movestars2          ;move the distant stars
282 movestarsdone:
283         ld  a,(stars1)          ;star positions (the missing byte...)
284         ld  b,nrstars1          ;how many stars? now we know.
285         ld  hl,starx1           ;points to the position of the stars
286         cal DisplayStars        ;display front layer stars
287         ld  a,(stars2)          ;weren't you paying attention five lines ago?
288         ld  b,nrstars2          ;that many?! whow!
289         ld  hl,starx2           ;and there they are
290         cal DisplayStars        ;use the same procedure to display back layer
291
292         ld  a,(level_info)      ;level info
293         and %00000110           ;isolate ground&ceiling
294         jr  z,game_stuff        ;both non-present
295         and %00000010           ;bit representing the presence of any ceiling
296         cal nz,Handle_ceiling   ;scroll the ceiling (if any) +check4collision
297         cal Handle_ground       ;scroll the ground and check if we're dead
298
299 game_stuff:
300         cal Handle_Ship         ;move you
301         ld  a,(your_occ)        ;are you 100% OK?
302         or  a                   ;a=0??
303         jr  nz,_gamestuff1      ;then don't check for movements/fires/...
304
305 check_keys:
306         ld  a,%10111111         ;function keys (MORE,EXIT,2ND,F1,F2,F3,F4,F5)
307         out (1),a               ;ask for them
308         nop \ nop               ;delay 8 clocks
309         in  a,(1)               ;gettem!
310
311 check_exitkey:
312         bit 6,a                 ;test bit 6 = exit-key = EXIT
313         jp  z,game_over         ;<exit> pressed, so be it
314 check_morekey:                  ;another unused label... poor compiler
315         bit 7,a                 ;test bit 7 = more-key = PAUSE
316         psh af
317         cal z,Pause             ;yes, go to pause
318         pop af
319
320 check_firekey:
321         bit 5,a                 ;test bit 5 = 2nd-key = FIRE
322         ld  hl,check_selkey     ;where to continue after executing Fire_bullet
323         psh hl                  ;push hl on stack (instead of cal Fire_bullet)
324         jp  z,Fire_bullet       ;fire smtn (bulletstaillasermultiples+stuff..)
325         pop hl                  ;no cal to Fire_bullet made, so pop stack
326         ld  hl,just_fired       ;no:
327         ld  (hl),5              ;able to fire (five turns = laser duration)
328 laserdur =$-1                   ;SMC laser duration
329
330 check_selkey:
331         ld  a,%01011111         ;look at first column of keys (ALPHA to STO)
332         out (1),a
333         in  a,(1)               ;our precious keys
334
335         bit 6,a                 ;'bout the GRAPH key...
336         cal z,Teacher           ;you didn't _press_ it, did you?!?
337
338         rla                     ;test bit7 so we know f ALPHA has been pressed
339         cal nc,select           ;yeppy, select the currently selected upgrade
340
341         cal Enemies_hit         ;check for collision with enemies
342         cal inc_weapdamage
343
344 _gamestuff1:
345         cal Handle_enemies      ;move enemies
346
347         cal Handle_bullets      ;move your bullets + check for hits
348         cal Enemy_bullets       ;move enemy bullets
349
350         cal Level_event         ;insert enemies
351         cal Display_Screen      ;display all
352
353 delay:
354         halt                    ;delay and preserve batteries :)
355         jp  game_main_loop      ;LOOP ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
356
357 ;------- weapon -------
358
359 inc_weapdamage:
360         ld  a,0
361 weapincs =$-1
362         inc a
363         cp  97                  ;max. 96 times (=96/16=6 increases)
364         ret nc                  ;return if already maxed
365         ld  (weapincs),a        ;save new incs
366
367         and %11110000           ;clear last 4 bits so no cf when rotating
368                                 ;btw: AND resets cf
369         rra                     ;rotate acting as shift (srl a) but just 1B
370         rra
371         rra
372         rra                     ;increase once just every 16 turns
373         ld  b,a                 ;times to increase
374 incthedamage:
375         add  a,1                ;increase damage for one increase
376 weapdaminc =$-1
377         dnz incthedamage        ;a=total increase damage
378         ld  b,1                 ;minimal damage
379 weapdamage =$-1
380         add a,b                 ;a=total damage
381         ld  (curweapdamage),a   ;safe the current damage
382
383
384 disp_charge:                    ;display charge bar
385         ld  hl,(59*16)+VIDEO_MEM+3
386         ld  b,3
387 chargebarclr:
388         dec hl
389         ld  (hl),0
390         dnz chargebarclr
391
392         ld  a,(weapincs)        ;load bar size (0-80)
393         srl a                   ;half the size (0-40)
394         srl a                   ;again half that size (0-20 pixels)
395         ld  c,a                 ;psh a
396         srl a                   ;/2
397         srl a                   ;/4
398         srl a                   ;/8: don't display last 3 bits of a (later)
399         jr  z,nochargebar       ;if a=0 then it would loop 256x so skip it
400         ld  b,a                 ;loop b=a times
401 chargebar:                      ;starting at ($39*16)+VIDEO_MEM
402         ld  (hl),%11111111      ;draw a piece of the bar
403         inc hl                  ;next position
404         dnz chargebar           ;loop it b times
405 nochargebar:
406         ld  a,c                 ;pop a
407         and %111                ;display last bits of chargebar
408         ret z                   ;if armor=0 then bit = %00000000 (don't disp)
409         ld  b,a                 ;into B
410         xor a                   ;bit = %00000000
411 chargebarbit:
412         scf                     ;set carry flag
413         rra                     ;rotates A right and sets bit 7 (c-flag)
414         dnz chargebarbit        ;repeat B times (so if B=6 then a=%11111100)
415 chargebarready:                 ;               (an if B=3 then a=%11100000)
416         ld  (hl),a              ;draw this last byte
417         ret
418
419 ;--------------------------- ground -----------------------------------------
420
421 Handle_ground:
422         ld  a,(timer)
423         and %111                ;once every 8 frames
424         jr  nz,Display_ground   ;otherwise skip the scroll
425         ld  bc,15               ;scroll all 16 bytes minus one (teh new byte)
426         ld  hl,groundpos+1      ;from..
427         ld  de,groundpos        ;to (one byte to the left)
428         ldir                    ;LoaDIncreaseRepeat = scroll!
429
430         ld  a,(groundinfo)      ;what kind of ground
431         dec a                   ;type 1:
432         jr  z,ground_tunnel     ;tunnel effect
433 ground_boring:
434         ld  a,(groundpos)       ;type 0
435         jr  newground+1
436
437 ground_tunnel:
438         ld  a,(groundpos+14)
439         ld  d,a
440         ld  hl,spacespace
441         ld  bc,$500             ;range=0..4
442         cal Random              ;a=0..4
443         dec a                   ;a=-1..3
444         dec a                   ;a=-2..2
445         ld  b,a
446         add a,(hl)              ;add to spacesize (so +2..-2)
447         cp  10
448         jr  c,newground         ;>=0 then don't change
449         ld  c,a
450         ld  a,d
451         add a,b                 ;new position
452         or  a
453         jr  z,newground         ;may not be 0 (=256)
454         cp  -10
455         jr  nc,newground        ;and not be <0 (>246)
456 diffground:
457         ld  d,a
458         ld  (hl),c
459 newground:
460         ld  a,d
461         ld  (groundpos+15),a    ;save new byte on the right
462
463 Display_ground:
464         ld  b,16                ;screen width
465         ld  de,groundpos-1      ;height of current byte (previous actually)
466         psh de                  ;use later
467         ld  hl,dispbuffer+(56*16)-1 ;screen position
468         psh hl
469
470 groundloopright:
471         ld  c,b                 ;push b for groundloopup
472         pop hl \ inc hl         ;get screen position and go one right
473         pop de \ inc de         ;get height info and set to the next byte
474         psh de \ psh hl         ;save these for the next time
475         ld  a,(de)              ;height of current byte
476         ld  b,a                 ;save in b
477
478         ld  de,16               ;to substract to go one line up
479         ld  a,%11111111         ;bitmask black
480         or  a
481 groundloopup:
482         ld  (hl),a              ;display black byte
483         sbc hl,de               ;go up (sbc must be used for 16-bit sub)
484         dnz groundloopup        ;and loop >groundpos< times
485
486         ld  b,c                 ;pop b used by groundloopup
487         dnz groundloopright     ;loop right for entire screen (16x)
488         pop hl \ pop hl         ;restore stack
489
490 CheckGround:                    ;check for collision with the ground
491         ld  a,(x)
492         srl a
493         srl a
494         srl a
495         inc a
496         ld  l,a
497         ld  h,0
498         ld  de,groundpos
499         add hl,de
500         ld  a,(y)
501         sub 57-7
502         neg
503         cp  (hl)
504         ret nc
505         ld  b,auch_ground
506         jp  damage_you
507
508 ;--------------------------- ceiling ----------------------------------------
509
510 Handle_ceiling:
511         ld  a,(timer)
512         and %111                ;once every 8 frames
513         jr  nz,Display_ceiling  ;otherwise skip the scroll
514         ld  bc,15               ;scroll all 15 bytes (16th is new position)
515         ld  hl,ceilingpos+1     ;from..
516         ld  de,ceilingpos       ;to (one byte to the left)
517         ldir                    ;LoaDIncreaseRepeat = scroll!
518
519         ld  a,(groundinfo)      ;what kind of ceiling
520         dec a                   ;type 1:
521         jr  z,ceiling_tunnel    ;tunnel effect
522 ceiling_boring:
523
524 ceiling_tunnel:
525         ld  a,(ceilingpos+14)
526         ld  d,a                 ;d=new ceiling
527         ld  hl,spacespace
528
529         ld  bc,$201             ;range=1..3
530         cal Random              ;a=1-3
531         dec a
532         jr  z,newceiling        ;1:same
533         dec a
534         jr  z,ctunnelup         ;2:up
535 ctunneldown:                    ;3:down
536         ld  a,(hl)
537         or  a                   ;(spacespace)=0:
538         jr  z,newceiling+2      ;keep same ceiling
539         inc (hl)
540         inc d
541         jr  newceiling
542 ctunnelup:
543         ld  a,1
544         cp  d                   ;if size=1 then don't
545         jr  z,newceiling
546         dec d
547         dec (hl)
548 newceiling:
549         ld  a,d
550         ld  (ceilingpos+15),a   ;save the new byte
551
552 Display_ceiling:
553         ld  b,16                ;screen width
554         ld  de,ceilingpos-1     ;height of current byte
555         psh de                  ;use later
556         ld  hl,dispbuffer-17    ;screen position
557         psh hl
558
559 ceilingloopright:
560         ld  c,b                 ;push b for groundloopup
561         pop hl \ inc hl         ;get screen position and go one right
562         pop de \ inc de         ;get height info and set to the next byte
563         psh de \ psh hl         ;save these for the next time
564         ld  a,(de)              ;height of current byte
565         ld  b,a                 ;save in b
566
567         ld  de,16               ;to substract to go one line up
568         ld  a,%11111111         ;bitmask black
569         or  a
570 ceilingloopdown:
571         ld  (hl),a              ;display black byte
572         add hl,de               ;go down
573         dnz ceilingloopdown     ;and loop >groundpos< times
574
575         ld  b,c                 ;pop b used by groundloopup
576         dnz ceilingloopright    ;loop right for entire screen (16x)
577         pop hl \ pop hl         ;restore stack
578
579 CheckCeiling:                   ;check for collision with the ground
580         ld  a,(x)               ;your x
581         srl a                   ;x/2
582         srl a                   ;x/4
583         srl a                   ;x/8 (current ceiling-byte)
584         inc a                   ;correction
585
586         ld  l,a                 ;hl = a
587         ld  h,0                 ;"
588         ld  de,ceilingpos       ;first ceiling-byte
589         add hl,de               ;current ceiling-byte
590         ld  a,(y)               ;your y-pos
591         inc a
592         cp  (hl)                ;compare with ceiling
593         ret nc                  ;carry if ceiling is above you
594         ld  b,auch_ground
595         jp  damage_you          ;otherwise you don't wanna be in that ship
596
597 ;--------------------------- move stars -------------------------------------
598
599 DisplayStars:                   ;inputs: hl=starx# a=stars# b=nrstars#
600         ld  e,(hl)
601         inc hl
602         ld  d,(hl)
603         ld  (de),a
604         inc hl
605         dnz DisplayStars
606         ret                     ;let's comment this: returns
607
608 movestars2:
609         ld  ix,starx2
610         ld  a,(stars2)
611         rlca                    ;move bits (star) left
612         ld  (stars2),a
613         ret nc                  ;if star didn't went from left to right bit
614         ld  b,nrstars2          ;otherwise move all stars one byte left
615         jr  movestars_loop
616
617 movestars1:
618         ld  ix,starx1
619         ld  a,(timer)
620         rra
621         ld  a,(stars1)
622         ret c
623         rlca
624         ld  (stars1),a
625         ret nc
626         ld  b,nrstars1
627
628 movestars_loop:
629         ld  h,(ix+1)
630         ld  l,(ix)
631         dec hl
632
633         ld  a,l
634         and %00001111
635         cp  (dispbuffer&15)-1   ;$C9FAand15-- = 9
636         jr  nz,newstarok
637         cal RandomY
638
639 newstarok:
640         ld  (ix),l
641         ld  (ix+1),h
642         inc ix \ inc ix
643         dnz movestars_loop
644         ret                     ;for stupid people, here's another comment...
645
646 ;--------------------------- pause ------------------------------------------
647
648 Pause:
649         ld  hl,_txt_pause
650         ld  (_penCol),hl
651         ld  hl,txt_pause
652         cal _vputs              ;display small font
653         ld  hl,_txt_pressenter  ;top centered
654         ld  (_curRow),hl
655         ld  hl,txt_pressenter   ;"Enter to continue"
656         cal _puts               ;display message
657 pause:
658         cal getsomekeys         ;GET_KEY w/ halts and checks for enter
659         ret z                   ;enter/second pressed: continue game
660         cp  K_F1                ;F1 pressed?
661         cal z,do_invert         ;if so then change invert screen (AF saved)
662         ld  hl,CONTRAST         ;contrast setting (0-31)
663         ld  b,(hl)              ;load contrast into b
664         cp  K_UP                ;+ key changes contrast up
665         jr  nz,contr_not_up
666         inc b                   ;increase contrast
667         jr  setcontrast         ;set
668 contr_not_up:
669         cp  K_DOWN              ;- key
670         jr  nz,pause            ;nope: loop
671         dec b                   ;decrease contrast
672 setcontrast:
673         ld  a,b
674         ld  (hl),a
675         out (2),a               ;and set it
676         cal releasekeys
677         jr  pause               ;and loop
678
679 ;--------------------------- teacher ----------------------------------------
680
681 Teacher:
682         ld  (iy+12),5           ;enable flashing cursor
683         cal _clrWindow          ;top left
684         ld  hl,txt_teacher
685         cal _puts               ;display message
686         cal releasekeys
687
688 teacherloop:
689         cal _getkey             ;enter low-power mode and wait for key
690         cp  kEnter              ;enter pressed?
691         jr  z,teacherans
692         cp  kGrMenu             ;keypressed = graph?
693         jr  nz,teacherloop      ;no, wait some more
694
695         ld  (iy+12),0           ;disable cursor
696         cal releasekeys
697         jp  disp_icons          ;+ret
698
699 teacherans:
700         ld  a,' '
701         cal _putc
702
703         ld  hl,$0701
704         ld  (_curRow),hl
705         ld  hl,txt_teacherans
706         cal _puts
707         jr  teacherloop
708
709
710 ;--------------------------- exit -------------------------------------------
711
712 quit:   im  1                   ;release keyfix procedure
713         set 2,(iy+13)           ;set back screen scrolling
714         xor a
715         ld (_asapvar+1),a       ;next Asm( run will reload the program
716         ld  hl,dispbuffer       ;graph-screen location
717         ld  de,dispbuffer+1
718         ld  (hl),a
719         ld  bc,1024-1           ;do it 1024 times = entire screen
720         ldir
721         jp  _clrWindow          ;as _clrLCD but also clears TEXT_MEM (like the
722                                 ;_clrScrn) AND also executes _homeup and ret
723
724 ;--------------------------- display ----------------------------------------
725
726 Display_Screen:
727         ld  hl,dispbuffer       ;from buffer (top left)
728         ld  de,VIDEO_MEM        ;to real screen (top left)
729         ld  c,56                ;display height = 64 bytes (minus 8 for bar)
730 displayloop:
731         ld  b,16                ;display width = 16 bytes (16*8bits=256pixels)
732 displaytloop:
733         ld  a,(hl)              ;copy byte from (hl)
734 _invert:                        ;SMC: cpl <-> or a
735         cpl                     ;xor $ff: invert byte (white<=>black)
736         ld  (de),a              ;to (de)
737         inc hl \ inc de         ;next byte
738         dnz displaytloop        ;16x hl >> de
739         dec c                   ;next line
740         jr  nz,displayloop      ;loop 56x
741
742         ld  hl,time2invert
743         ld  a,(hl)
744         or  a                   ;(time2invert)=0:
745         jr  z,noinvert          ; do nothing
746         dec a                   ;otherwise decrease
747         cal z,do_invert         ;if it became 0 then invert
748         ld  (hl),a              ;save new value
749 noinvert:
750
751         ld  hl,$396b            ;Display Score
752         ld  (_penCol),hl        ;bottom right of screen
753         ld  hl,(your_score)
754
755 _D_HL_DECI:                     ;------- display 5-digit value -------
756         ld  de,savestr+4        ;savenr saves number string
757         ld  b,5                 ;five digits
758 ldhld:  cal UNPACK_HL           ;one digit of hl
759         add a,'0'               ;make number
760         ld  (de),a              ;save into savenr
761         dec de                  ;point to next digit
762         dnz ldhld               ;repeat for all digits
763
764         ld  hl,savestr          ;we (the program) saved the value righthere
765         jp  _vputs              ;the only thing left to do is to display it
766
767 savestr:                        ;@here the score will be stored
768         .db "00000",0           ;don't worry, it's just temporary
769
770 ;------------------------- handle ship --------------------------------------
771
772 Handle_Ship:
773         ld  a,(your_occ)        ;are
774         or  a                   ;you
775         jr  z,ok                ;ok?
776
777         inc a                   ;no! next (explosion)frame
778         ld  (your_occ),a        ;save
779
780         cp  64+1                ;last explosion frame? (1-16=1st;49-64=4th)
781         jp  c,exploding_you     ;not yet: display explosion
782         cp  64+16               ;delay finished?
783         jp  z,You_die           ;yes = game over
784         ret                     ;don't display anything
785
786 ;----move----
787 ok:                             ;we are
788         ld  a,%01111110         ;get arrow keys
789         out (1),a               ;it's cold outside
790         ld  hl,y                ;instead of nop\nop do something usefull
791         in  a,(1)               ;come back in
792
793         ld  b,a                 ;psh a (keys)
794         xor -1                  ;inverted a: 0 if arrow-key has been pressed
795         ld  a,(your_multiples)          ;(btw: CPL doesn't set any flags)
796         res 7,a                 ;reset move bit (no flags changed)
797         jr  z,adv_ok            ;if so, leave the multiples where they are
798         set 7,a                 ;set move bit
799 adv_ok: ld  (your_multiples),a
800
801         ld  a,(timer)           ;framecounter
802         and %1                  ;switches 0<>1 each frame
803         inc a                   ;a = 1 or 2 (1.5 avg)
804         ld  c,a                 ;c = your_speed
805
806         ld  a,b                 ;pop a (keys)
807         rra                     ;rotate right (put last bit in c)
808         ld  b,a                 ;we need a later
809
810         jr  c,no_down
811         ld  a,(hl)
812         add a,c
813         cp  50                  ;56-6 = bottom of screen
814         jr  nc,no_down
815         ld  (hl),a
816 no_down:
817         dec hl
818         rr  b                   ;because we now use b, it's rr instead of rra
819         jr  c,no_left
820         ld  a,(hl)
821         sub c                   ;<dec a> doesn't affect c-flag
822         jr  c,no_left           ;-1 = left side
823         ld  (hl),a
824 no_left:
825         rr  b
826         jr  c,no_right
827         ld  a,(hl)
828         add a,c
829         cp  122                 ;128-6 = right side
830         jr  nc,no_right
831         ld  (hl),a
832 no_right:
833         ld  d,(hl)              ;d=x
834         inc hl
835         rr  b
836         jr  c,no_up
837         ld  a,(hl)
838         sub c                   ;<dec a> doesn't affect carry-flag
839         jr  c,no_up             ;-1 = top of screen
840         ld  (hl),a              ;save new y
841
842 no_up:  ld  e,(hl)              ;e=y
843         ld  ix,spr_ship01       ;normal ship sprite
844 your_shipspr =$-2
845         ld  hl,your_inv         ;invulnerable?
846         ld  a,(hl)              ;load time in a
847         or  a                   ;is it 0?
848         jr  z,disp_ship         ;yes so ship = normal (display \ continue)
849
850         ld  a,(timer)           ;load frame nr.
851         and %00000111           ;a=0 once every four frames
852         jr  nz,not_time         ;a<>0 = not time to update counter
853         dec (hl)                ;decrease inv-time left
854 not_time:
855         and %00000100           ;a switches 0<->1 every 2 frames
856         jr  z,disp_ship         ;show normal ship
857 inv_flicker:
858         ld  bc,spr_ship01i-spr_ship01
859         add ix,bc               ;display invulnerable ship
860 disp_ship:
861         cal safeputsprite       ;display your ship; save de
862
863 ;----multiples----
864
865 handle_multiples:
866         ld  a,(your_multiples)  ;do you have multiples
867         ld  b,a                 ;save a for 2nd check
868         and %1111               ;no? (last four bits = nr of multiples)
869         ret z                   ;then don't handle them either
870         bit 7,b                 ;move the multiples??? (=move bit set?)
871         jr  z,mult_adv          ;nope, just let them (saves (y)in y, (x)in x)
872
873         psh de                  ;current position = needed later
874         ld  hl,mm*14+1+your_prevpos     ;previous positions
875         ld  de,mm*14+3+your_prevpos     ;move all positions one back
876         ld  bc,mm*14+2
877         lddr                    ;change 0-57 -> 2-59 (if mm=4 that is)
878         inc hl                  ;your_prevpos+0
879         pop de
880         ld  (hl),d              ;x-pos
881         inc hl                  ;=current position
882         ld  (hl),e              ;y-pos
883
884 mult_adv:
885         ld  ix,spr_multiple     ;normal sprite
886         ld  hl,timer
887         bit 3,(hl)              ;change sprites every 8 turns
888         jr  z,disp_multiples
889         ld  ix,spr_multiple2    ;second sprite
890 disp_multiples:
891         ld  hl,your_prevpos+16  ;first pos.
892 dispmultiplesloop:
893         psh af
894         psh hl
895         ld  d,(hl)              ;load coords
896         inc hl
897         ld  e,(hl)
898         psh ix
899         cal putsprite           ;display
900         pop ix                  ;same sprite next time ;)
901         pop hl
902         ld  de,14
903         add hl,de               ;next multiple
904         pop af                  ;counter
905         dec a
906         ret z                   ;return if all done
907         jr  dispmultiplesloop   ;loop
908
909 ;----explode----
910
911 exploding_you:
912         srl a                   ;half the framerate
913         srl a                   ;half that framerate
914         srl a                   ;and half again that framerate
915         ld  hl,x-1
916         ld  ix,spr_yexplosion   ;base sprite
917
918 explosion_stuff:                ;in:a=frame*2+(0 to 1); (hl)=xpos-- ix=sprite
919         and %11111110
920         add a,a
921         add a,a                 ;frame*8
922         ld  c,a
923         ld  b,0                 ;bc=a
924         add ix,bc               ;go to correct sprite (each spr. is 8 bytes)
925         inc hl
926         ld  d,(hl)              ;load xpos
927         inc hl
928         ld  e,(hl)              ;and y
929         jp  putsprite           ;and display it too
930
931 ;----hit----
932
933 damage_you:                     ;damages you B points
934         ld  a,(your_inv)        ;shield left?
935         or  a
936         jr  z,dothadamage       ;no shield
937         srl b                   ;shield: half the damage
938 dothadamage:
939         ld  hl,time2invert
940         xor a                   ;a=0
941         cp  (hl)                ;not already inverted?
942         cal z,do_invert         ;then invert screen
943         ld  (hl),2              ;change back 2 frames from now
944
945         ld  hl,your_armor       ;armor left
946         ld  a,(hl)              ;load hp in A
947         sub b                   ;decrease hp by B
948         jr  nc,newarmor         ;>=0hp left so don't explode
949         ld  a,%01               ;occ %xxxxxx01 = explode
950         ld  (your_occ),a        ;too bad, you're dead meat
951 newarmor:
952         ld  (hl),a              ;save decreased hp
953         jp  disp_armor          ;and display new value
954
955 ;------------------------- place multiples ----------------------------------
956
957 Place_multiples:
958         ld  hl,your_prevpos     ;place all previous positions
959         ld  b,mm*7+2            ;all saved positions of them (14 per multiple)
960 place_multiples:
961         ld  (hl),e              ;set prev-x to d
962         inc hl                  ;next
963         ld  (hl),d              ;set prev-y to e
964         inc hl                  ;next
965         dnz place_multiples     ;repeat
966         ret
967
968 ;------------------------- select upgrade -----------------------------------
969
970 inc_armor:
971         ld  a,(your_armor)      ;load current armor
972         cp  25-6                ;may not become >=25
973         jr  c,doincarmor        ;ok then just add 6
974         ld  a,24-6              ;set to maximum (6 will be added below)
975 doincarmor:
976         add a,6                 ;add 6 to armor
977         ld  (your_armor),a      ;change armor
978         ret
979
980 select:
981         ld  hl,your_pickup      ;select pickups
982         ld  a,(hl)              ;load pickups taken so far
983         dec a                   ;is it 1?
984         ret m                   ;return if it's 0 (no pickups)
985         jr  nz,select2          ;no, carry on
986 select1:
987         ld  (hl),a              ;reset pickups
988         cal inc_armor
989         jr  disp_icons          ;display and return
990 select2:
991         dec a                   ;is it 2?
992         jr  nz,select3          ;no, carry on
993         ld  (hl),a              ;reset pickups
994         inc a                   ;a=1
995         ld  (your_tail),a       ;ready tail beam
996         jr  disp_icons          ;display 'n return
997 select3:
998         dec a                   ;is it 3?
999         jr  nz,select4          ;no, carry on
1000         ld  (hl),a              ;reset pickups
1001         ld  hl,your_weapon
1002         ld  a,(hl)
1003         inc a
1004         cp  maxweapon
1005         jr  nc,disp_icons       ;weapon maxed out
1006         ld  (hl),a              ;set new weapon
1007         cal loadweapon          ;load it (damage and stuff)
1008         jr  disp_icons          ;display n return
1009 select4:
1010         dec a                   ;is it 4?
1011         jr  nz,select5          ;no, carry on again
1012         ld  (hl),a              ;reset pickups
1013         ld  hl,your_weapon
1014         ld  a,(hl)
1015         cp  maxweapon           ;upgrade from bullet
1016         jr  nc,upgradelaser     ;nope, just upgrade
1017         ld  a,maxweapon-1       ;yes, set laser #1
1018 upgradelaser:
1019         inc a                   ;next laser
1020         cp  maxlaser
1021         jr  nc,disp_icons       ;laser maxed out
1022         ld  (hl),a
1023         cal loadweapon
1024         jr  disp_icons          ;display + return
1025 select5:
1026         dec a                   ;is it 5?
1027         jr  nz,select6          ;no, carry on once more
1028         ld  (hl),a              ;reset pickups
1029         ld  hl,your_multiples
1030         ld  a,(hl)              ;multiples you already got
1031         and %1111               ;reset movebit so (your_multiples)=real value
1032         inc a                   ;one more
1033         cp  mm+1
1034         jr  nc,enoughmultiples  ;maxed out
1035         ld  (hl),a
1036 enoughmultiples:
1037         ld  de,(x)
1038         dec a                   ;if this is your first multiple then...
1039         cal z,Place_multiples   ;reset multiples positions
1040         jr  disp_icons          ;display, return
1041 select6:
1042         ld  (hl),0              ;reset pickups
1043 ;       jr  disp_icons
1044
1045 ;--------------------------- show icon --------------------------------------
1046
1047 disp_icons:
1048  psh bc \ psh de \ psh hl \ psh ix ;&&&
1049
1050         ld  hl,VIDEO_MEM+(16*56);56 rows down = eight rows from bottom
1051         ld  (PutWhere),hl       ;place icons at bottom of normal screen
1052         ld  b,16                ;draw 16x (screen width)
1053         ld  a,%11111111         ;horizontal line mask
1054         cal drawline            ;draw divider-line
1055
1056         ld  b,16*7              ;draw 16x (screen width) 7x (height)
1057         xor a                   ;blank line mask
1058         cal drawline            ;clear scorebar
1059
1060 disp_lives:
1061         ld  de,5                ;(0,5)
1062         ld  a,(your_lives)      ;nr of lives
1063         or  a
1064         jr  z,displivesdone     ;no lives
1065         ld  b,a
1066 displivesloop:
1067         psh bc
1068         ld  ix,spr_lship
1069         cal safeputsprite       ;put li'l ship
1070         ld  a,lshipsize+1
1071         add a,d
1072         ld  d,a                 ;x=x+5
1073         pop bc
1074         dnz displivesloop       ;one ship per life
1075 displivesdone:
1076         cal disp_armor          ;display bar
1077
1078         ld  ix,spr_icon01       ;torpedoIcon
1079         ld  de,$1901            ;icon #1
1080         cal putwidesprite       ;display icon
1081
1082         ld  ix,spr_icon00
1083         ld  a,(your_weapon)     ;ur weapon
1084         cp  maxweapon           ;laser?
1085         psh af                  ;(your_weapon)
1086         jr  nc,no_tail          ;if laser (nc) then tail ain't fired
1087         ld  a,(your_tail)
1088         or  a
1089         jr  z,no_tail
1090         ld  ix,spr_icon02       ;tailbeamIcon
1091 no_tail:
1092         ld  de,$2901            ;icon #2
1093         cal putwidesprite       ;display
1094
1095         ld  ix,spr_icon00
1096         pop af                  ;a=(your_weapon); cf=bullets
1097         psh af
1098         jr  nc,no_bullets       ;=laser
1099         ld  hl,$3945            ;position to display bullet-type digit
1100         pop af                  ;digit=(your_weapon)
1101         psh af
1102         inc a                   ;1 = weapon #1 (=0)
1103         ld  (_penCol),hl        ;set location
1104         add a,'0'               ;make digit
1105         cal _vputmap            ;display char
1106         ld  ix,spr_icon03       ;bulletIcon
1107 no_bullets:
1108         ld  de,$3901            ;icon #3
1109         cal putwidesprite       ;display icon
1110
1111         ld  ix,spr_icon00       ;emptyIcon
1112         pop af                  ;ld a,(your_weapon)
1113         ld  b,a
1114         jr  c,no_laser          ;popped carry
1115         ld  hl,$3955            ;position to display bullet-type digit
1116         ld  (_penCol),hl        ;set location
1117         ld  a,b                 ;(your_weapon)  ;load = faster than push
1118         sub maxweapon-1         ;1 = laser #1 (=maxweapon)
1119         add a,'0'               ;make digit
1120         cal _vputmap            ;display char
1121         ld  ix,spr_icon04       ;laserIcon
1122 no_laser:
1123         ld  de,$4901            ;icon #4
1124         cal putwidesprite
1125
1126         ld  ix,spr_icon00       ;emptyIcon
1127         ld  a,(your_multiples)
1128         and %111
1129         jr  z,no_multiples
1130         ld  ix,spr_icon05
1131 no_multiples:
1132         ld  de,$5901            ;icon #5
1133         cal putwidesprite
1134
1135         ld  ix,spr_dividerline
1136         ld  de,$6901
1137         cal putwidesprite
1138
1139         ld  a,(your_pickup)     ;pickups taken
1140         add a,a                 ;picks*2 (sets z-flag)
1141         jr  z,iconsdone         ;return if no pickups
1142         add a,a                 ;picks*4
1143         add a,a                 ;picks*8
1144         add a,a                 ;picks*$10
1145         add a,$09               ;add 0ah
1146         ld  d,a                 ;y-pos = picks * $10 + $0a (19,29,39,49,59)
1147         ld  e,$01               ;x-pos = bottom (1a01,2a01,3a01,4a01,5a01)
1148
1149         ld  ix,spr_icon
1150         cal putwidesprite
1151 iconsdone:
1152         ld  hl,dispbuffer       ;normal game-screen
1153         ld  (PutWhere),hl       ;set sprite-position to normal screen
1154
1155  pop ix \ pop hl \ pop de \ pop bc
1156         ret
1157
1158 disp_armor:
1159         ld  de,16               ;line size
1160         ld  hl,(57*16)+VIDEO_MEM+3
1161         ld  b,3
1162 armorbarclr:
1163         dec hl
1164         ld  (hl),0
1165         add hl,de
1166         ld  (hl),0
1167         sbc hl,de
1168         dnz armorbarclr
1169
1170         ld  a,(your_armor)      ;load your armor (<25)
1171         ld  c,a                 ;psh a
1172         srl a                   ;/2
1173         srl a                   ;/4
1174         srl a                   ;/8: don't display last 3 bits of a (later)
1175         jr  z,noarmorbar        ;if a=0 then it would loop 256x so skip it
1176         ld  b,a                 ;loop b=a times
1177 armorbar:                       ;starting at ($39*16)+VIDEO_MEM
1178         ld  (hl),%11111111      ;draw a piece of the bar
1179         add hl,de               ;one down (resets carry)
1180         ld  (hl),%11111111      ;same piece
1181         sbc hl,de               ;up again
1182         inc hl                  ;next position
1183         dnz armorbar            ;loop it b times
1184
1185 noarmorbar:
1186         ld  a,c                 ;pop a
1187         and %111                ;display last bits of armor
1188         ret z                   ;if armor=0 then bit = %00000000 (don't disp)
1189         ld  b,a                 ;into B
1190         xor a                   ;bit = %00000000
1191 armorbarbit:
1192         scf                     ;set carry flag
1193         rra                     ;rotates A right and sets bit 7 (c-flag)
1194         dnz armorbarbit         ;repeat B times (so if B=6 then a=%11111100)
1195 armorbarready:                  ;               (an if B=3 then a=%11100000)
1196         ld  (hl),a              ;draw this last byte
1197         add hl,de
1198         ld  (hl),a              ;and just below
1199         ret
1200
1201 drawline:
1202         ld  (hl),a              ;draw one piece of the divider-line
1203         inc hl                  ;move right (8 pixels = 1 byte)
1204         dnz drawline            ;repeat (16bytes * 8pixels =128= screen width)
1205         ret
1206
1207 ;------------------------- fire bullet --------------------------------------
1208
1209 fire_multiple:
1210         psh af
1211         psh ix                  ;save ix for next fire
1212         cal fireany             ;fire from multiple position
1213         pop ix                  ;saving ix is much faster than recalculating
1214         pop af                  ;number of multiples
1215         dec a                   ;one just displayed
1216         pop hl                  ;ret
1217         ret z                   ;ret2 if none left
1218         jp  (hl)                ;real ret
1219
1220 fire_multiples:
1221         ld  hl,(your_prevpos+16);then, fire from multiple position
1222         cal fire_multiple
1223         ld  hl,(your_prevpos+30)
1224         cal fire_multiple
1225         ld  hl,(your_prevpos+44)
1226         cal fire_multiple
1227         ld  hl,(your_prevpos+58)
1228         cal fire_multiple       ;no JP: that messes up the stack
1229         ret
1230
1231 Fire_bullet:
1232         ld  hl,just_fired       ;=for how long you may hold fire (2nd)
1233         ld  a,(hl)              ;a = time left
1234         dec a                   ;decrease timer
1235         ret z                   ;may not fire when (just_fired) became 0
1236         ld  (hl),a              ;save new decreased value
1237
1238         ld  a,(your_weapon)     ;if you have bullets.....
1239         cp  maxweapon
1240         jr  nc,fireOK           ;>weapons = laser
1241         ld  (hl),1              ;bullet may last one turn (just fire 1 bullet)
1242 fireOK:
1243         ld  a,(your_weapon)     ;weapon nr.
1244         ld  ix,weapondata+2
1245         add a,a                 ;weap*2
1246         add a,a                 ;    *4
1247         add a,a                 ;    *8
1248         ld  c,a
1249         ld  b,0                 ;go to current weapon (bc=a)
1250         add ix,bc               ;ix=weapon ptr
1251
1252         ld  a,(your_multiples)  ;any multiples?
1253         and %1111               ;nr. of multiples
1254         cal nz,fire_multiples   ;if >0 then fire them too
1255         ld  hl,(x)              ;fire from ship position (x)
1256 fireany:                        ;HL=(x,y)
1257         ld  (firex),hl          ;set position to fire from
1258         ld  b,3  ;or use the proc at fireOK with ld ix,weapondata+2-(256*3)
1259 fire_weapon:
1260         psh bc                  ;save counter
1261         ld  a,(ix)              ;load this weapon
1262         ld  c,a                 ;save bulletType in c
1263         and %11100000           ;%111?????=laser
1264         cp  %11100000           ;is it?
1265         cal z,fire_laser        ;fire laser (will set c=0 when done)
1266         xor a                   ;<>0=bullet
1267         cp  c                   ;c<>0?
1268         cal nz,fire_ybullet     ;then fire bullet
1269         inc ix                  ;otherwise fire next weapon
1270         inc ix
1271         pop bc                  ;weapon counter (do 3 weapons)
1272         dnz fire_weapon
1273
1274 fire_tail:
1275         ld  hl,your_tail
1276         ld  a,(hl)
1277         dec a
1278         ret nz
1279         ld  a,(ix-2)            ;last weapon fired
1280         cp  %11100000           ;issit laser
1281         ret z                   ;then return
1282         xor %11111              ;smart way of going left instead of right :P
1283                                 ;fire tail bullet
1284 ;-----fire BULLETs-----
1285
1286 fire_ybullet:           ;fire bullet type=C dam=(curweapdamage) at (firex/y)
1287         ld  hl,ybullets         ;check for unused bullet
1288         ld  de,4
1289         ld  b,nrybuls
1290 find_ybullet:
1291         ld  a,(hl)
1292         or  a
1293         jr  z,found_ybullet     ;0 = no bullet here
1294         add hl,de
1295         dnz find_ybullet        ;look next bullet
1296         ret                     ;none found, return don't fire
1297
1298 found_ybullet:
1299         ld  (hl),c              ;use the bullet and set correct bullet-type
1300         inc hl                  ;@damage
1301         ld  (hl),1              ;set bullet damage
1302 curweapdamage =$-1
1303         ld  a,(firex)           ;your x-pos
1304         add a,5                 ;place bullet in front of you
1305         inc hl                  ;go to bullet-x
1306         ld  (hl),a              ;set x
1307
1308         ld  a,(firey)           ;your y-pos
1309         add a,(ix+1)            ;place bullet at the middle of your ship
1310         inc hl                  ;go to bullet-y
1311         ld  (hl),a              ;set y
1312
1313         xor a
1314         ld  (weapincs),a        ;reset damage
1315         ret
1316
1317 ;-----fire LASER-----
1318
1319 fire_laser:
1320         ld  b,0                 ;overflow counter
1321         ld  hl,firex
1322         ld  d,(hl)              ;d = your x-pos
1323         inc hl
1324
1325         ld  a,(hl)              ;base y-coord (firey)
1326         add a,(ix+1)            ;at specified offset (most likely the middle)
1327         ld  e,a                 ;save laser-y in e
1328         psh de                  ;save unmodified (x,y)
1329         add a,a                 ;y*2
1330         add a,a                 ;y*4
1331         add a,a                 ;y*8
1332         rl  b                   ;b (=0) =b*2+overflow (if y>32 then bc=bc+256)
1333         add a,a                 ;y*16 (width of screen)
1334         rl  b                   ;b=b*2+overflow (if y>64 then bc=bc+512)
1335         inc a                   ;8 pixels to right (a=even so no overflow)
1336
1337         srl d                   ;X/2
1338         srl d                   ;X/4
1339         srl d                   ;X/8
1340         add a,d                 ;a = (Y*16+X/8) mod 256 (c set on overflow)
1341
1342         jr  nc,_nolc            ;jump if no carry = no overflow = a<=255
1343         inc b                   ;a>255 so increase bc by 256
1344 _nolc:  ld  c,a                 ;c = (Y*16+X/8) mod 256
1345         ld  hl,dispbuffer       ;save-location
1346         add hl,bc               ;bc = Y*16+X/8: hl=screen address
1347         ld  a,15                ;128/8=16=screen width ** minus one (inc a ^^)
1348         sub d                   ;minus x-start (d=X/8)
1349         ld  b,a
1350 drawlaser:
1351         ld  (hl),%11111111
1352         inc hl                  ;Go to next byte
1353         dnz drawlaser
1354 handle_laser:
1355         pop de                  ;de=(firex): x-pos unmodified
1356
1357 check_laserhits:                ;de = (x,y)
1358         psh ix
1359         ld  b,nrenemies         ;check all enemies
1360         ld  hl,enemies+1        ;enemy#1+occ/hp00
1361 laserhits:                      ;hits with normal enemies
1362         psh hl
1363         ld  a,(hl)              ;occ+hp00
1364         and %00000010           ;normal/moving occ.=%1x
1365         jr  z,nolashit          ;no hit when enemy_occ <> 2/3
1366         inc hl                  ;enemy type
1367         ld  a,(hl)
1368         or  a                   ;enemy #0 = pickup
1369         jr  z,nolashit          ;yes: don't destroy
1370
1371         cal find_sprite         ;ix=sprite to enemy (hl)
1372         inc hl
1373         ld  a,(hl)              ;check x
1374         sub d
1375         jr  c,nolashit          ;no hit when enemy is left of you
1376         inc hl
1377         ld  a,(hl)              ;check y
1378         sub e
1379         jr  z,enemy_lashit      ;a-e=0 = laser on top line of enemy = hit
1380         jr  nc,nolashit         ;a-e>0 = enemy above laser = no hit
1381         dec a                   ;minus one
1382         add a,(ix+1)            ;add enemy height (according to sprite @ix)
1383         jp  m,nolashit          ;a-e>0 = hit
1384 enemy_lashit:
1385         ld  a,(curweapdamage)   ;damage
1386         cal enemy_hit           ;hl=enemy+y
1387 nolashit:
1388         pop hl                  ;enemy+1
1389         ld  a,b                 ;psh bc
1390         ld  bc,enemysize
1391         add hl,bc               ;go to next enemy
1392         ld  b,a                 ;pop bc
1393         dnz laserhits           ;check all enemies
1394         xor a
1395         ld  (weapincs),a        ;reset damage
1396         pop ix
1397         ld  c,a                 ;c=0
1398         ret
1399
1400 ;------------------------ handle bullets ------------------------------------
1401
1402 move_bullet:
1403         ld  c,a                 ;c=type
1404         and %11111              ;pixels to move
1405         add a,(hl)              ;a = X + (hl) to the right
1406         sub 16                  ;and 16 to the left (so -16..+15)
1407         jr  c,remove_bullet     ;remove if x<0
1408         cp  128
1409         jr  nc,remove_bullet    ;or x>=128
1410         ld  (hl),a              ;save new pos.
1411         ld  d,a                 ;d = X
1412
1413         inc hl                  ;@y-pos
1414         ld  a,c
1415         cal _shracc             ;%11110000->1111
1416 ;Note: a _shracc procedure inside Nemesis itself would be 27 cycles faster
1417         srl a                   ;%1110->111
1418         dec a
1419         jr  z,bullet_noymove    ;1=straight forward
1420         dec a
1421         jr  z,bullet_up         ;2=up
1422         dec a
1423         jr  z,bullet_halfup     ;3=1/2up
1424         dec a
1425         jr  z,bullet_down       ;4=down
1426
1427 bullet_halfdown:                ;5=1/2down
1428         ld  a,(timer)
1429         rra                     ;carry once every other turn
1430         jr  c,bullet_noymove
1431 bullet_down:
1432         ld  a,(hl)
1433         inc a
1434         cp  55
1435         jr  z,bullet_noymove
1436         ld  (hl),a
1437 bullet_halfup:
1438         ld  a,(timer)
1439         rra                     ;CF every other turn
1440         jr  c,bullet_noymove
1441 bullet_up:
1442         ld  a,(hl)
1443         dec a
1444         jr  z,bullet_noymove
1445         ld  (hl),a
1446 bullet_noymove:
1447         ld  e,(hl)              ;e = Y
1448         ret
1449
1450 remove_bullet:
1451         pop hl                  ;cal move_bullet
1452         pop hl                  ;enemy+type
1453         ld  (hl),0              ;dump this bullet!
1454         jr  next_ybullet+1      ;+1:skip pop hl at next_ybullet
1455
1456 Handle_bullets:
1457         ld  hl,ybullets
1458         ld  b,nrybuls
1459 scan_bullets:
1460         ld  a,(hl)              ;@bulletType
1461         or  a                   ;bulletType=0 >> no bullet
1462         jp  z,next_ybullet+2    ;skip pops (+2); jP for speed
1463
1464         psh bc                  ;bullet counter
1465         psh hl                  ;save enemy+type
1466         ld  (temp1),hl          ;needed for check_bullethits
1467         inc hl                  ;@damage
1468         inc hl                  ;@x
1469         cal move_bullet         ;move bullet
1470
1471 display_bullet:
1472         dec hl                  ;@x
1473         dec hl                  ;@damage
1474         ld  a,(hl)              ;bullet damage=size
1475         ld  hl,bullettable      ;pointer to first bullet
1476         srl a
1477         srl a                   ;per 4
1478         ld  b,0
1479         ld  c,a                 ;->16bit (de=a)
1480         add hl,bc               ;point to correct bullet offset
1481         ld  a,(hl)              ;load bullet offset
1482         ld  c,a                 ;convert to 16bit (d=0)
1483         ld  ix,spr_bullet01     ;first sprite
1484         add ix,bc               ;add offset (go to correct sprite)
1485
1486         ld  a,(ix)              ;bullet x-size
1487         ld  (bulletxsize),a     ;used at check_bullethits
1488         ld  a,(ix+1)            ;bullet y-size...
1489         ld  (bulletysize),a     ;...too
1490
1491         cal safeputsprite       ;display bullet; DE used for check_bullethits
1492
1493         cal check_bullethits
1494
1495 next_ybullet:
1496         pop hl                  ;restore enemy+type
1497         pop bc                  ;b=counter
1498         inc hl  ;&&&add hl = faster
1499         inc hl
1500         inc hl
1501         inc hl                  ;skip type,dam,x,y: next enemy+type
1502         dnz scan_bullets        ;next bullet (loop)
1503         ret
1504
1505 ;--------------------------- check bullethits -------------------------------
1506
1507 check_bullethits:               ;INPUT: de=X,Y; (temp1)=bullet
1508         ld  b,nrenemies
1509         ld  hl,enemies+1
1510
1511 hit_enemies:                    ;Hits with normal enemies
1512         psh bc                  ;enemy counter
1513         psh hl
1514
1515         ld  a,(hl)
1516         and %00000010
1517         jr  z,nohit             ;no hit when enemy_occ <> 2/3
1518
1519         inc hl                  ;enemy type
1520         ld  a,(hl)
1521         or  a                   ;enemy #0 = pickup
1522         jr  z,nohit             ;yes: don't destroy
1523
1524         cal find_sprite         ;set ix to the sprite of this enemy
1525
1526         inc hl                  ;@x
1527         ld  a,(hl)              ;check x
1528         sub d                   ;minus bullet x-position
1529         ld  b,a                 ;psh a
1530         sub 5                   ;minus bullet x-size
1531 bulletxsize =$-1
1532         jp  p,nohit             ;miss
1533         ld  a,b                 ;pop a
1534         add a,(ix)              ;add enemy width
1535         jp  m,nohit             ;miss
1536
1537         inc hl                  ;@y
1538         ld  a,(hl)              ;check y
1539         sub e                   ;minus bullet y-position
1540         ld  b,a                 ;psh a
1541         sub 3                   ;substract bullet height
1542 bulletysize =$-1
1543         jp  p,nohit             ;nope, missed it
1544         ld  a,b                 ;pop a
1545         add a,(ix+1)            ;add enemy height
1546         dec a                   ;minus one
1547         jp  m,nohit             ;missed after all
1548
1549                                 ;---bullet hits enemy (auch-time!)---
1550         psh hl
1551         ld  hl,0                ;@bulletType
1552 temp1 =$-2
1553         ld  (hl),0              ;remove bullet
1554         inc hl                  ;@damage
1555         ld  a,(hl)              ;set damage
1556         pop hl                  ;enemy+y
1557         cal enemy_hit
1558 nohit:
1559         pop hl
1560         ld  bc,enemysize
1561         add hl,bc
1562         pop bc
1563         dnz hit_enemies         ;check next enemy
1564         ret
1565
1566 enemy_hit:                      ;*in:a=damage;hl=enemy+y
1567         add a,a                 ;a=damage to inflict
1568         add a,a                 ;first 2 bits used for occ.
1569         ld  b,a
1570
1571         dec hl                  ;@x
1572         dec hl                  ;@type
1573         dec hl                  ;@hp00 (occ)
1574         ld  a,(hl)              ;load hp00
1575         sub b                   ;decrease HP (if <0xx then c is set)
1576         ld  (hl),a              ;save (no flag-changes)
1577         dec hl                  ;@hp64; no change in c
1578         ld  a,(hl)              ;load; no c-change
1579         sbc a,0                 ;if cf then decrease a
1580         ld  (hl),a              ;save back the new value
1581         ret nc                  ;if a>=0 then return, otherwise explode
1582
1583         inc hl                  ;goto occ again
1584         ld  (hl),%01            ;set to explode
1585
1586         ld  a,(pickuptimer)     ;counts enemies destroyed
1587         dec a                   ;enough destroyed for a pickup?
1588         psh af                  ;save flags and a=0
1589         jr  nz,pickupdone       ;otherwise just explode
1590         ld  a,18                ;reset enemies counter (18 hits = next)
1591 pickupdone:
1592         ld  (pickuptimer),a     ;save new enemiescounter value
1593         inc hl                  ;@type
1594         ld  (hl),0              ;explosionFrame 0 or enemy #0=pickup
1595         pop af
1596         cal z,place_enemy       ;place pickup (enemy#=0=a cuz ZF)
1597
1598         ld  hl,1                ;increase score by one
1599         jp  scoreInc            ;+ret
1600
1601 ;--------------------------- level events -----------------------------------
1602
1603 Level_event:
1604         ld  a,0                 ;time to next event
1605 nextevent =$-1
1606         dec a                   ;decrease counter
1607         ld  (nextevent),a       ;store new value
1608         ret nz                  ;hasn't reached zero yet: get outta here!
1609
1610         ld  bc,0                ;enemy frequency (lvl)
1611 eventtime =$-2
1612         cal Random
1613         ld  (nextevent),a       ;set time to next event
1614         ld  hl,eventleft
1615         dec (hl)                ;update enemy-counter
1616
1617         ld  a,(hl)              ;look at counter
1618         or  a                   ;has it reached 0?
1619         jp  z,Next_level        ;yes: level finished
1620         dec a                   ;has it reached 1?
1621         jr  z,standby_event     ;yes: wait until no enemies present/left
1622         dec a                   ;has it reached 2?
1623         jr  z,place_boss        ;yep: place the BigBossTM!
1624         dec a                   ;has it reached 3?
1625         jr  nz,place_ranenemy   ;nope: >3 = place an enemy
1626         inc hl                  ;nextevent located behind eventleft
1627         ld  (hl),123            ;set delay
1628         ret                     ;don't place any more enemies
1629
1630 standby_event:
1631         ld  b,nrenemies
1632         ld  hl,enemies+1-enemysize
1633         ld  de,enemysize
1634         xor a
1635 chk_enemyleft:
1636         add hl,de
1637         cp  (hl)                ;0 = no enemy present
1638         jr  nz,enemyleft
1639         dnz chk_enemyleft
1640         ret
1641 enemyleft:
1642         ld  hl,eventleft
1643         inc (hl)
1644         ret
1645
1646
1647 place_ranenemy:
1648         ld  bc,0                ;0..nrlvlenemies
1649 nrlvlenemies =$-1               ;=nr of enemies minus 1
1650         cal Random              ;random enemy b..b+c = 0..nrenemies-1
1651         ld  b,0
1652         ld  c,a                 ;bc=a
1653         ld  hl,lvlenemies
1654         add hl,bc               ;go to a random enemy
1655         ld  a,(hl)              ;load enemy nr of this mysterious random enemy
1656         jr  place_enemy
1657
1658 place_boss:
1659         ld  hl,(levelp)         ;the leveldata (including the boss)
1660         dec hl                  ;points to leveldata\boss\enemynr
1661         ld  a,(hl)              ;load enemy# of boss
1662
1663 place_enemy:                    ;places enemy #=a
1664         psh af
1665         ld  hl,enemies+1-enemysize
1666         ld  bc,enemysize
1667         xor a                   ;a=0
1668 chk_noenemy:                    ;find an unused (no) enemy
1669         add hl,bc               ;check next enemy
1670         cp  (hl)                ;(hl) = 0 ??
1671         jr  nz,chk_noenemy      ;jump if enemy present (non-0)
1672         ex  de,hl               ;de=hl=usable enemy +1
1673         pop af                  ;enemy# to place
1674         cal findenemyspecs      ;hl = enemy #a specs
1675
1676         dec de                  ;goto hp64 (before occ)
1677         ldi                     ;set hp64
1678         ldi                     ;set hitpoints+occ of enemy class
1679         ld  a,(hl)              ;save sprite-offset/2 (ldi decs bc so in a)
1680         ldi                     ;set sprite
1681         ldi                     ;set x-position
1682
1683         ld  c,a                 ;c=sprite
1684         ld  a,(hl)              ;load placeInfo
1685         inc hl
1686         dec a                   ;is it 1?
1687         jr  z,random_enemy      ;yes: create random value <51 in a
1688         dec a                   ;is it 2?
1689         jr  z,lure_enemy        ;yes: create a 100% luring enemy
1690                                 ;otherwise?
1691 halflure_enemy:                 ;yes (of course it is): pick one (50% lure)
1692         ld  a,(timer)           ;look at frame-number
1693         rra                     ;make random if odd frame nr.
1694         jr  nc,random_enemy     ;1st possibility: random enemy
1695 lure_enemy:                     ;2nd possibility: luring enemy
1696         ld  a,(y)               ;place at same y-pos as YOUR ship
1697         jr  ypos_OK
1698 random_enemy:
1699         ld  b,0                 ;bc = enemy sprite offset / 2
1700         ld  ix,spr_enemy00      ;first enemy sprite
1701         add ix,bc               ;add offset for current enemy
1702         add ix,bc               ;twice (offset stored as offset/2)
1703         ld  a,64-8              ;=57=screen height (8 is scorebar)
1704         sub (ix+1)              ;minus sprite height=bottom
1705         ld  c,b                 ;range=0 to...
1706         ld  b,a                 ;...57-y
1707         cal Random              ;random value on screen
1708 ypos_OK:                        ;random value successfully created
1709         ld  (de),a              ;save y-position
1710         inc de                  ;@movecounter
1711         ldi                     ;set move-type
1712         ld  a,1                 ;movecounter = 1
1713         ld  (de),a              ;set
1714         inc de                  ;@firecounter
1715         ldi                     ;set time-to-1st-fire
1716         ldi                     ;set firefreq
1717         ldi                     ; "  firetype
1718         ret                     ;return
1719
1720 ;--------------------------- enemy fires ------------------------------------
1721
1722 Enemy_fires:                    ;de = x,y; c = type
1723         ld  hl,ebullets         ;first bullet to check
1724         ld  b,nrebuls
1725         dec d
1726         dec d                   ;d = x-2
1727         inc e                   ;e = y+1
1728 enemy_fires_again:              ;same but hl = first bullet possibly free
1729         xor a
1730 find_ebullet:
1731         cp  (hl)
1732         jr  z,found_ebullet     ;0 = not used
1733         inc hl \ inc hl \ inc hl
1734         dnz find_ebullet        ;look next bullet
1735         ret
1736
1737 found_ebullet:
1738         ld  a,c
1739         sub 6
1740         jr  c,bulletok          ;type #0-5 = done (normal/diag)
1741         or  a
1742         jr  z,bulletaiming      ;type #6 = aiming = type#2..5
1743         dec a
1744         jr  z,bullettriple      ;type #7 = triple
1745
1746 bulletdouble:
1747         dec e                   ;one up
1748         ld  c,1                 ;type #1
1749         cal enemy_fires_again   ;fire bullet
1750         inc hl                  ;next bullet position
1751         inc e
1752         inc e                   ;one down
1753         jr  bulletok            ;fire another bullet
1754
1755 bullettriple:
1756         ld  c,1                 ;type #1 = normal
1757         cal enemy_fires_again   ;fire
1758         inc hl                  ;next bullet
1759         ld  c,4                 ;type #4 = down 50%
1760         cal enemy_fires_again
1761         inc hl
1762         ld  c,5                 ;type #5 = up 50%
1763         jr  bulletok
1764
1765 bulletaiming:
1766         ld  a,(y)
1767         sub e
1768         add a,10
1769         jp  p,bulletnotup
1770         ld  c,5                 ;yourY-bulY = negative (=bullet below you)
1771         add a,10
1772         jp  p,bulletnotup
1773         ld  c,3                 ;yourY-bulY = even more negative (going up)
1774 bulletnotup:
1775         sub 20
1776         jr  c,bulletok
1777         ld  c,4                 ;bullet going down (=jp m)
1778         sub 10
1779         jr  c,bulletok          ;even more going down
1780         ld  c,2
1781
1782 bulletok:
1783         ld  (hl),c              ;set bullet direction
1784         inc hl
1785         ld  (hl),d              ;set x-pos
1786         inc hl
1787         ld  (hl),e              ;set y-pos
1788         ret
1789
1790 ;----------------------------- enemy bullets --------------------------------
1791
1792 Enemy_bullets:
1793         ld  hl,ebullets         ;hl=bullet pointer
1794         ld  b,nrebuls           ;number of bullets (or _possible_ bullets)
1795 handle_bullet:
1796         psh bc
1797         psh hl
1798         ld  a,(hl)              ;load bulletType in a
1799         or  a                   ;bullet present?
1800         cal nz,enemy_bullet     ;non-0: handle bullet
1801         pop hl                  ;enemy_bullet could've added one or two to hl
1802         pop bc                  ;bullet counter
1803         inc hl \ inc hl \ inc hl ;next bullet (3 bytes per bullet)
1804         dnz handle_bullet       ;loop for each and every bullet
1805         ret
1806
1807 enemy_bullet:
1808         inc hl                  ;@x
1809         ld  d,(hl)              ;check if it has reached the left side of scrn
1810         bit 7,d                 ;x<0?
1811         jr  nz,remove_ebullet   ;yes, remove bullet
1812         dec d                   ;move one pixel left
1813         dec d                   ;and another one (that makes 2)
1814         ld  (hl),d              ;save new x-coordinate in (HL) and D
1815         inc hl                  ;@y   (BTW: x >= -2)
1816         ld  e,(hl)              ;e=y
1817
1818         dec a
1819         jr  z,ebullet_common    ;type 1: normal bullet
1820         dec a
1821         jr  z,ebullet_down      ;type 2: moving down
1822         dec a
1823         jr  z,ebullet_up        ;type 3: moving up
1824
1825         ld  b,a                 ;save bulletType
1826         ld  a,(timer)           ;load timer
1827         rra                     ;half speed (CF set every other turn)
1828         jr  c,ebullet_common    ;if bit then normal bullet
1829
1830         dec b
1831         jr  z,ebullet_down      ;type 4: moving down 50%
1832                                 ;type 5: moving up 50%
1833 ebullet_up:
1834         dec e                   ;move up
1835         jp  m,ebullet_common    ;y<top; don't save new value (so y=0)
1836         ld  (hl),e
1837         jr  ebullet_common
1838 ebullet_down:
1839         inc e                   ;move down
1840         ld  a,e                 ;a=y too
1841         cp  58-3                ;y>bottom?
1842         jr  z,ebullet_common    ;then keep it there
1843         ld  (hl),e              ;otherwise save new y
1844
1845 ebullet_common:
1846         ld  ix,spr_bullete1     ;display enemy bullet
1847         psh hl
1848         cal putsprite
1849         pop hl                  ;we'll need it again
1850
1851 ebullet_hits:
1852         ld  a,(your_occ)
1853         or  a
1854         ret nz                  ;0 = you're normal
1855
1856         ld  a,(y)               ;check y collision
1857         sub (hl)
1858         add a,6
1859         ret m
1860         cp  9
1861         ret nc
1862
1863         dec hl                  ;check x
1864         ld  a,(x)
1865         sub (hl)
1866         add a,6
1867         ret m
1868         cp  9
1869         ret nc
1870
1871         ld  b,auch_bullet       ;set damage-amount
1872         psh hl
1873         cal damage_you          ;HIT!!
1874         pop hl                  ;save hl to remove the bullet
1875 remove_ebullet:
1876         dec hl                  ;points to bullettype again
1877         ld  (hl),0              ;bullet > unused
1878         ret
1879
1880 ;--------------------------- handle enemies ---------------------------------
1881
1882 Handle_enemies:
1883         ld  hl,enemies+1
1884         ld  b,nrenemies         ;handle all enemies
1885
1886 handle_enemy:
1887         psh bc
1888         psh hl
1889
1890         ld  a,(hl)
1891         and %00000011
1892         jr  z,next_enemy        ;occ "no enemy" 0
1893         dec a
1894         jr  z,exploding_enemy   ;occ "exploding" 1
1895
1896 normal_enemy:
1897         inc hl
1898         ld  c,(hl)              ;c = enemy type = de
1899         cal find_sprite
1900
1901         inc hl
1902         ld  d,(hl)              ;x
1903         inc hl
1904         ld  e,(hl)              ;y
1905
1906         inc hl                  ;@movetype
1907         cal moving_enemy
1908         dec hl
1909
1910         ld  a,e                 ;new y value
1911         cp  57
1912         jr  c,enemyonscreenY    ;=on screen
1913         cp  -20                 ;moved off at top
1914         ld  e,0                 ;reset to top
1915         jr  nc,enemyonscreenY
1916         ld  e,57                ;otherwise reset to bottom
1917 enemyonscreenY:
1918         ld  (hl),e              ;store new y
1919         dec hl                  ;@x
1920
1921         ld  a,d                 ;new x value
1922         cp  129                 ;x<=128
1923         jr  c,enemyonscreenX    ;=on screen
1924         cp  -7                  ;x<=-8
1925         jr  c,remove_enemy      ;=off screen
1926 enemyonscreenX:
1927         ld  (hl),d              ;store new x
1928         ld  a,c                 ;a = enemy type
1929         or  a                   ;type 0? (pickup)
1930         jr  nz,check_enemyfire  ;no, a normal enemy; let em fire
1931         jr  firing_done         ;continue
1932
1933 check_enemyfire:
1934         ld  bc,4                ;4x inc hl
1935         add hl,bc               ;@firecount
1936         dec (hl)                ;decrease counter till next blast
1937         ld  a,(hl)              ;&&&doesn't seem efficient to me
1938         or  a                   ;has it reached zero?
1939         jr  nz,firing_done      ;finished if not
1940
1941         inc hl                  ;@firefreq
1942         ld  a,(hl)
1943         inc hl                  ;@firetype
1944         ld  c,(hl)              ;in c
1945         dec hl
1946         dec hl                  ;@firecount again
1947         ld  (hl),a              ;reset counter for next blast
1948         psh de                  ;save registers for firing-use
1949         cal Enemy_fires         ;fires bullet
1950         pop de                  ;restore (destroyed by Enemy_fires)
1951 firing_done:
1952         cal putwidesprite       ;display sprite @ix
1953
1954 next_enemy:
1955         pop hl
1956         ld  bc,enemysize
1957         add hl,bc
1958         pop bc
1959         dnz handle_enemy
1960         ret
1961
1962 exploding_enemy:
1963         inc hl
1964         ld  a,(hl)
1965         cp  16
1966         jr  nz,keep_enemy       ;remove when at last frame
1967 remove_enemy:
1968         pop hl
1969         ld  (hl),$0000          ;bye bye enemy
1970         jr  next_enemy+1        ;continue AFTER pop hl (already done)
1971 keep_enemy:
1972         inc a
1973         ld  (hl),a              ;next frame
1974         dec a                   ;1-16 -> 0-15
1975         ld  ix,spr_explosion    ;base sprite
1976         cal explosion_stuff     ;display explosion
1977         jr  next_enemy
1978
1979 ;--------------------------- moving enemies ---------------------------------
1980
1981 moving_enemy:
1982         dec d                   ;move left once
1983         ld  a,(hl)              ;how does this enemy move?
1984         and a
1985         ret z                   ;0 = (1<)
1986         ld  b,a
1987         ld  a,(timer)
1988         dec b
1989         jr  z,movetype_updown   ;1 = (1<) up / down
1990         dec b
1991         jr  z,movetype_vslow    ;2 = (.25<)
1992         dec b
1993         jr  z,movetype_slow     ;3 = (.5<)
1994         dec b
1995         jr  z,movetype_fast     ;4 = (1.5<)
1996         dec b
1997         jr  z,movetype_vfast    ;5 = (2<)
1998
1999         inc d                   ;speed 0
2000         dec b
2001         jr  z,movetype_smart    ;6 = &&& smart
2002         dec b
2003         jr  z,movetype_lure     ;7 = (0) move y towards you
2004         dec b
2005         jr  z,movetype_slowlure ;8 = (0) lure 1/2 speed
2006         dec b
2007         dec b
2008         jr  z,movetype_fulllure ;10 = x+y towards you 1/2 speed
2009         dec b
2010         jr  z,movetype_right    ;11 = (.5>)
2011         dec b
2012         jr  z,movetype_fright   ;12 = (1>)
2013
2014 movetype_right:
2015         rra
2016         ret c                   ;speed 0 50%
2017 movetype_fright:
2018         inc d                   ;move right one px
2019         ret
2020
2021 movetype_fulllure:
2022         rra
2023         ret c                   ;50% speed
2024         cal movetype_lure
2025         ld  a,(x)
2026         cp  d
2027         jr  c,movetype_vfast    ;moves left (again)
2028 lure_right:
2029         inc d                   ;move right
2030         ret
2031
2032 movetype_slowlure:
2033         rra                     ;half the time
2034         ret c
2035 movetype_lure:
2036         ld  a,110
2037         cp  d
2038         jr  nc,dothelurethingy
2039         dec d                   ;x>109: move left
2040 dothelurethingy:
2041         ld  a,(y)
2042         cp  e
2043         ret z                   ;don't move vertically if equal
2044         jr  c,lure_up           ;below you then move up
2045 lure_down:                      ;above then move down
2046         inc e
2047         ret
2048 lure_up:dec e
2049         ret
2050
2051 movetype_smart:
2052         inc hl                  ;@movecount
2053         ld  a,(hl)
2054         inc a
2055         and %1111
2056         ld  (hl),a
2057
2058         or  a                   ;reset carry flag
2059         dec hl                  ;reset hl to <y>
2060         and %11111100
2061         jr  z,movetype_fast
2062
2063 movetype_slow:
2064         rra
2065         ret c
2066         inc d                   ;don't move
2067         ret
2068
2069 movetype_vslow:
2070         and %11
2071         ret z
2072         inc d                   ;don't move
2073         ret
2074
2075 movetype_fast:
2076         rra
2077         ret c                   ;once every other turn
2078 movetype_vfast:
2079         dec d                   ;move left twice
2080         ret
2081
2082 movetype_updown:
2083         inc hl                  ;@movecount
2084         ld  a,(hl)
2085         dec a
2086         and 127                 ;range 0..127
2087         ld  (hl),a              ;store new movecounter
2088         dec hl                  ;reset hl to @movetype
2089         and %00100000           ;ZF changes once every 64 turns
2090         ld  a,e                 ;load current y-position
2091         jr  z,movedown
2092 moveup: dec a                   ;decrease y-pos (=move up)
2093         ret m                   ;don't move off the screen (y<0)
2094         dec e                   ;save new y-pos
2095         ret                     ;finish
2096 movedown:
2097         inc a                   ;increase y-pos
2098         cp  55                  ;compare with bottom
2099         ret nc                  ;return if it has passed that line (>40)
2100         inc e                   ;otherwise save new position
2101         ret                     ;and return
2102
2103 ;--------------------------- check collision --------------------------------
2104
2105 Enemies_hit:
2106         ld  hl,(x)              ;e = X, d = Y
2107         ld  de,$0707            ;add 7 to both d and e
2108         add hl,de
2109         ex  de,hl               ;e = X+7, d = Y+7
2110
2111         ld  hl,enemies+1
2112         ld  b,nrenemies         ;check all 20 enemies
2113 check_collision:
2114         psh bc                  ;counter
2115         psh hl                  ;pointer
2116         ld  a,(hl)
2117         and %00000010           ;enemy status
2118         jr  z,check_next        ;2 or 3 = ok, otherwise: next enemy
2119         inc hl                  ;enemy#
2120
2121 collide_enemy:                  ;&&& include in Handle_enemy proc
2122         cal find_sprite
2123
2124         inc hl                  ;@x
2125         ld  a,(hl)              ;check x match
2126         sub e                   ;enemy position minus yours minus 7
2127         jp  p,check_next
2128         add a,6
2129         add a,(ix)              ;enemy width
2130         jp  m,check_next
2131
2132         inc hl
2133         ld  a,(hl)              ;check y match
2134         sub d                   ;same as with x-check
2135         jr  nc,check_next       ;(=jp p)
2136         add a,6
2137         add a,(ix+1)            ;enemy height
2138         jp  m,check_next
2139         dec hl
2140         dec hl
2141
2142 take_pickup:
2143         psh hl                  ;we need hl
2144         ld  hl,2                ;increase score by 2
2145         cal scoreInc
2146         pop hl                  ;we're done
2147
2148         ld  a,(hl)              ;load enemy type
2149         or  a
2150         jr  nz,collide          ;enemy when <>0
2151
2152         psh hl
2153         ld  hl,your_pickup      ;your pickups
2154         ld  a,(hl)              ;current
2155         inc a                   ;go to next
2156         cp  6                   ;pickups >=6
2157         jr  c,not_maxpickup
2158         ld  a,1                 ;yes: reset to pickup 1
2159 not_maxpickup:
2160         ld  (hl),a              ;save new
2161         cal disp_icons          ;display altered pickupicons
2162         pop hl
2163
2164         dec hl                  ;to enemy occ
2165         xor a                   ;set to 0 = gone
2166         ld  (hl),a              ;remove
2167         jr  check_next          ;all done, next..
2168
2169 collide:
2170         dec hl
2171         ld  a,(hl)
2172         sub auch_ecollide
2173         ld  (hl),a
2174         jr  nc,enemydamaged     ;enemy still ok (HP>=0)
2175         ld  (hl),%01            ;set to explode
2176         inc hl
2177         ld  (hl),0              ;explosionFrame 0
2178 enemydamaged:                   ;damage to enemy delivered
2179         ld  b,auch_collide      ;your damage
2180         cal damage_you
2181
2182 check_next:
2183         pop hl
2184         ld  bc,enemysize
2185         add hl,bc
2186         pop bc
2187         dnz check_collision
2188         ret
2189
2190 ;--------------------------- story ------------------------------------------
2191
2192 storyPage:
2193         psh hl                  ;hl will be destroyed by _clrLCD
2194         cal _clrLCD             ;clear screen
2195         pop hl
2196         ld  a,(hl)
2197         ld  (curline),a         ;begin line for special effect
2198 storyLine:
2199         ld  d,(hl)              ;vertical position of text
2200         inc hl
2201         ld  e,(hl)              ;horizontal text-position
2202         ld  (_penCol),de        ;set position
2203         inc hl
2204         cal _vputs              ;display text
2205
2206         ld  a,(hl)              ;load next byte
2207         inc hl
2208         or  a                   ;0 means more text
2209         jr  z,storyLine         ;loop if there is
2210
2211         psh af
2212         psh hl
2213         ld  hl,VIDEO_MEM        ;copy text
2214         ld  de,dispbuffer       ;to GRAPH_MEM
2215         ld  bc,1024             ;entire screen
2216         ldir
2217         cal _clrLCD             ;clear VIDEO_MEM
2218         pop hl
2219         pop bc                  ;last byte (<>0) is lines to SFX
2220         psh hl
2221         cal DoSFX               ;do special effects
2222         cal _getkey             ;wait for a key
2223         pop hl
2224         ret
2225
2226 dostory:
2227         cal storyPage                   ;do some story
2228         ld  a,(hl)                      ;load next byte in a
2229         inc a                           ;set z-flag if a = $ff
2230         jr  nz,dostory                  ;otherwise loop
2231         inc hl
2232         inc hl                          ;set hl to beginning of the level
2233         ld  (levelp),hl                 ;set the level-pointer
2234         ret                             ;and return
2235
2236 ;--------------------------- SFX --------------------------------------------
2237
2238 DoSFX:                          ;in:(curline)=beginLine;b=nrOfLines
2239 SFXloop:
2240         psh bc
2241
2242         ld  a,0                 ;get line number
2243 curline =$-1
2244         inc a                   ;go to the next line
2245         ld  (curline),a         ;update
2246         ld  l,a
2247         ld  h,0                 ;hl=a
2248         add hl,hl
2249         add hl,hl
2250         add hl,hl
2251         add hl,hl               ;*16 (a pixels down=a*16)
2252         sub 64                  ;a=a-64
2253         neg                     ;a=64-a (lines from bottom)
2254
2255         ld  b,h                 ;save hl for later
2256         ld  c,l
2257         ld  de,VIDEO_MEM        ;where to put sfx
2258         add hl,de               ;go to ymin
2259         ex  de,hl               ;put into de again
2260         ld  hl,dispbuffer       ;source of original
2261         add hl,bc               ;hl->source
2262
2263 SFXdisp:                        ;display this frame on screen
2264         ld  bc,16               ;one line (=16 bytes, you'd know by now)
2265         ldir                    ;display (copy actually)
2266         ld  bc,-16              ;go up one line (not on screen)
2267         add hl,bc               ;so the same line will be displayed
2268         dec a                   ;counter
2269         jr  nz,SFXdisp          ;repeat until whole screen is displayed
2270
2271         ld  b,8
2272 SFXdelay:
2273         halt                    ;delay
2274         dnz SFXdelay            ;8x
2275
2276         pop bc                  ;counter
2277         dnz SFXloop
2278         ret
2279
2280 ;--------------------------- proc -------------------------------------------
2281
2282 Random:                         ;a=c<random<b+c; destr:none
2283         psh hl
2284         ld  hl,rancount         ;amount to increase with (0-255)
2285 randomloop:
2286         inc (hl)                ;change for next time
2287         ld  a,r                 ;value $0-7F (can be _anything_ so watch out!)
2288         add a,0                 ;add to last random value
2289 ranseed =$-1                    ;SMC :P
2290         add a,(hl)              ;add the changing increase value
2291                         ;(this is because R can be anything;
2292                         ; ie always be even so freeze when a must be 1<=a<=1)
2293         ld  (ranseed),a         ;save for next time
2294         cp  b                   ;a>=b
2295         jr  nc,randomloop       ;then add again
2296         add a,c                 ;a<b; a=a+c
2297         pop hl
2298         ret
2299 rancount: .db 0
2300
2301 RandomY:                        ;HL = random Y 0..50 right side ((1..51)*16-1)
2302         psh bc
2303         ld  bc,50*256+1         ;range=1..51
2304         cal Random              ;a = 1..51
2305         ld  h,0
2306         ld  l,a                 ;hl = 1..51
2307         add hl,hl
2308         add hl,hl
2309         add hl,hl
2310         add hl,hl               ;hl = 1..51 * 16 (left side at random y)
2311         dec hl                  ;hl = 0..50 * 16 (" at right side of screen)
2312         ld  de,dispbuffer
2313         add hl,de               ;position on screen
2314         pop bc
2315         ret
2316
2317 scoreInc:
2318         psh bc
2319         ld  bc,(your_score)
2320         add hl,bc
2321         ld  (your_score),hl
2322         pop bc
2323         ret
2324
2325 find_sprite:                    ;in:hl=enemy+type | out:ix=sprite to enemy
2326         psh de
2327         psh hl
2328         ld  e,(hl)              ;e = enemy offset/2
2329         ld  d,0                 ;de = e
2330         ld  ix,spr_enemy00      ;first enemy sprite
2331         add ix,de               ;add offset for current enemy
2332         add ix,de               ;twice (offset stored as offset/2)
2333         pop hl
2334         pop de
2335         ret
2336
2337 BLACKLCD:
2338         ld  hl,VIDEO_MEM        ;screen location (top left)
2339         ld  de,VIDEO_MEM+1
2340         ld  (hl),%11111111
2341         ld  bc,1024-1           ;do it 1024 times = entire screen
2342         ldir
2343         set 3,(iy+5)            ;set white on black
2344         ret
2345
2346 releasekeys:
2347         halt
2348         ld  a,%10000000         ;all key-masks
2349         out (1),a
2350         in  a,(1)
2351         inc a                   ;cp %11111111 (no keys pressed)
2352         jr  nz,releasekeys      ;keep waitin
2353         jp  GET_KEY             ;clear buffer
2354
2355 findenemyspecs:                 ;enemy #a specs in (hl); in:b=0; out:ac=?
2356         ld  hl,enemyspecs       ;enemy "0" specs
2357         ld  c,a
2358         add a,a                 ;a=type*2
2359         add a,a                 ;a=type*4
2360         add a,a                 ;a=type*8
2361         add a,c                 ;a=type*9
2362         ld  c,a                 ;b=0; c=bc=type*8
2363         add hl,bc               ;hl = enemy specs
2364         ret
2365
2366 ;--------------------------- game over / new game / death -------------------
2367 chartable:
2368         .db 0,".<>!",0,0,0,0  ;down,L,R,up
2369         .db 0,"xtoje0",0      ;enter..clear
2370         .db " wsnid9",0       ;(-)..custom
2371         .db "zvrmhc8",0       ;dot..del
2372         .db "yuqlgb7#"        ;0..xvar
2373         .db $D9,"-pkfa6'"     ;on..alpha
2374         .db "54321*",0,$D0    ;F5..more
2375
2376 save_hi:
2377         ld  hl,_asapvar         ;find own variable
2378         rst 20h                 ;cal _ABS_MOV10TOOP1
2379         rst 10h                 ;cal _FINDSYM
2380
2381         xor a
2382         ld  hl,4+storehi_start-_asm_exec_ram
2383         add hl,de               ;hl=pointer to data in original prog
2384         adc a,b
2385         cal _SET_ABS_DEST_ADDR
2386         xor a
2387         ld  hl,storehi_start
2388         cal _SET_ABS_SRC_ADDR
2389         ld  hl,storehi_end-storehi_start
2390         cal _SET_MM_NUM_BYTES
2391         cal _mm_ldir            ;save done (cal \ ret)
2392         jp  _RAM_PAGE_1
2393
2394 save_lvl:
2395         ld  hl,_asapvar         ;find own variable
2396         rst 20h                 ;cal _ABS_MOV10TOOP1
2397         rst 10h                 ;cal _FINDSYM
2398
2399         xor a
2400         ld  hl,4+storesave_start-_asm_exec_ram
2401         add hl,de               ;hl=pointer to data in original prog
2402         adc a,b
2403         cal _SET_ABS_DEST_ADDR
2404         xor a
2405         ld  hl,storesave_start
2406         cal _SET_ABS_SRC_ADDR
2407         ld  hl,storesave_end-storesave_start
2408         cal _SET_MM_NUM_BYTES
2409         cal _mm_ldir            ;save done (cal \ ret)
2410         jp  _RAM_PAGE_1
2411
2412 game_over:                      ;stack=+0
2413         cal BLACKLCD            ;clear screen
2414         ld  hl,$0603
2415         ld  (_curRow),hl        ;center
2416         ld  hl,txt_gameover
2417         cal _puts               ;display "GAME OVER"
2418         cal releasekeys         ;wait for all keys to be released
2419
2420         ld  hl,$0007
2421         ld  (_curRow),hl
2422
2423         ld  de,(your_score)
2424         ld  hl,(hiscore)
2425         cal CP_HL_DE
2426         jr  nc,no_hiscore
2427         ld  (hiscore),de
2428
2429 ask_hiname:
2430         ld  ix,hiname
2431         ld  a,9
2432         ld  (hiscorepos),a
2433 enter_name_loop:
2434         ld  a,'_'
2435         cal _putc
2436         ld  hl,_curCol
2437         dec (hl)
2438 nokeypressed:
2439         cal getsomekeys
2440         jr  z,nomore
2441         or  a
2442         jr  z,nokeypressed
2443
2444         cp  K_DEL
2445         jr  z,backup
2446         cp  K_EXIT
2447         jr  z,nomore
2448
2449         ld  hl,hiscorepos
2450         ld  b,(hl)
2451         dec b
2452         jr  z,nokeypressed
2453         ld  (hl),b
2454
2455         ld  hl,chartable
2456         ld  e,a
2457         ld  d,0
2458         add hl,de
2459         ld  a,(hl)
2460         or  a
2461         jr  z,nokeypressed
2462
2463         ld  (ix),a
2464         cal _putc
2465         inc ix
2466         cal releasekeys
2467         jr  enter_name_loop
2468
2469 backup:
2470         ld  hl,hiscorepos
2471         ld  a,(hl)
2472         cp  9
2473         jr  nc,nokeypressed
2474         inc (hl)
2475
2476         dec ix
2477         ld  (ix),' '
2478         ld  a,32
2479         cal _putc
2480         ld  hl,_curCol
2481         dec (hl)
2482         dec (hl)
2483         jr  enter_name_loop
2484
2485 nomore:
2486         ld  a,' '
2487         cal _putc
2488         ld  (ix),0
2489         cal save_hi
2490         jr  hiscoredone
2491
2492 no_hiscore:
2493         ld  hl,hiname
2494         cal _puts
2495
2496 hiscoredone:
2497         xor a                   ;clear a (Ahl will be displayed)
2498         ld  hl,$1006            ;bottom-1 right
2499         ld  (_curRow),hl        ;set
2500         ld  hl,(your_score)     ;your score
2501         cal _dispahl            ;display it (a=0)
2502
2503         ld  hl,$314b            ;bottom-1 right before score ^^
2504         ld  (_penCol),hl        ;set
2505         ld  hl,txt_score        ;"Score"
2506         cal _vputs              ;display (small)
2507
2508         ld  hl,$1007            ;bottom right
2509         ld  (_curRow),hl        ;set
2510         ld  hl,(hiscore)        ;hi-score
2511         cal _dispahl            ;display
2512         ld  hl,$3946            ;bottom right before hiscore ^^
2513         ld  (_penCol),hl        ;set
2514         ld  hl,txt_hiscore      ;"Hiscore"
2515         cal _vputs              ;display (small)
2516         res 3,(iy+5)
2517
2518         ld  b,16
2519         ld  de,16
2520         ld  hl,VIDEO_MEM+(49*16)-1
2521 restore_line:
2522         set 1,(hl)
2523         add hl,de
2524         dnz restore_line
2525
2526         cal _getkey             ;wait for keypress
2527         jp  quit                ;restore some things and return to TI-OS/shell
2528
2529 invship:                        ;procedure used in New_game
2530         psh af
2531         inc b
2532         ld  de,$C0
2533         ld  hl,VIDEO_MEM+$30-$C0;begin pos
2534 invshipinit:
2535         add hl,de
2536         dnz invshipinit
2537         ld  b,$B0               ;12 lines down
2538 invshiploop:
2539         ld  a,(hl)
2540         cpl                     ;invert byte
2541         ld  (hl),a
2542         inc hl
2543         dnz invshiploop         ;loop
2544         pop af
2545         ret
2546
2547 New_game:                       ;stack must be +1 (so change the jp in cal :)
2548         cal _clrLCD
2549         ld  hl,VIDEO_MEM
2550         ld  (PutWhere),hl       ;will be reset after displaying iconbar
2551         ld  ix,spr_ship01       ;first ship: sprite
2552         ld  de,$0105            ;position
2553         ld  b,4                 ;number of ships to display
2554 dispshipsloop:
2555         psh bc                  ;counter
2556         psh de                  ;position
2557         cal putwidesprite       ;display
2558         pop de
2559         ld  bc,spr_ship01i-spr_ship01+2
2560         add ix,bc               ;go to next ship
2561         ld  a,12                ;below the previous one
2562         add a,e
2563         ld  e,a
2564         pop bc
2565         dnz dispshipsloop       ;loop
2566
2567         ld  b,0                 ;menu pos.
2568 selectship:
2569         psh bc
2570         cal invship
2571 selectshiploop:
2572         halt
2573         cal GET_KEY
2574         or  a
2575         jr  z,selectshiploop
2576         pop bc
2577         psh bc
2578         cal invship
2579         pop bc
2580         cp  K_SECOND
2581         jr  z,startthenewgame
2582         cp  K_ENTER
2583         jr  z,startthenewgame
2584         cp  K_DOWN
2585         jr  nz,selnotdown
2586         inc b
2587 selnotdown:
2588         cp  K_UP
2589         jr  nz,selnotup
2590         dec b
2591 selnotup:
2592         ld  a,b
2593         and %11
2594         ld  b,a
2595         jr  selectship
2596
2597 startthenewgame:
2598         ld  hl,spr_ship01-(spr_ship02-spr_ship01)
2599         ld  de,spr_ship02-spr_ship01
2600         inc b                   ;your ship #0-3++
2601 searchyourship:
2602         add hl,de               ;next ship
2603         dnz searchyourship
2604         ld  (your_ship),hl
2605         xor a                   ;ld a,0
2606         ld  (your_score),a      ;reset score
2607         ld  (your_score+1),a    ;reset score (0)
2608         ld  (your_tail),a       ;no tail beam
2609         ld  (your_weapon),a     ;no laser
2610         ld  (your_pickup),a     ;reset pickups
2611         ld  (your_multiples),a  ;no multiples
2612         inc a                   ;ld a,1
2613         ld  (level),a           ;reset level nr (#1)
2614         ld  hl,level00          ;set level pointer to level#1
2615         ld  (levelp),hl         ;reset level pointer
2616         ld  a,4
2617         ld  (your_lives),a      ;3 lives (4 will be decreased @ You_die)
2618         ld  (pickuptimer),a     ;next pickup after 4 enemies destroyed
2619
2620 You_die:                        ;stack must be +1
2621         pop hl                  ;restore stack
2622         ld  a,12
2623         ld  (your_armor),a      ;12 HPs/shields
2624         ld  a,(your_lives)      ;load lives left
2625         dec a                   ;decrease lives
2626         ld  (your_lives),a      ;if lives=0ffh GO
2627         inc a                   ;if -1 then zf set now
2628         jp  z,game_over         ;and game's over
2629         jr  samelevel
2630
2631 gamedone:
2632         cal dostory             ;display end (hl=(levelp))
2633         ld  hl,250
2634         cal scoreInc            ;game complete bonus: 250
2635         jp  game_over           ;game over (+hiscore)
2636
2637 ;--------------------------- next level -------------------------------------
2638
2639 Next_level:                     ;stack must be +1
2640         pop hl
2641
2642         cal inc_armor           ;increase armor
2643
2644         ld  hl,(levelp)         ;level pointer
2645         ld  b,0                 ;advance one level
2646         ld  c,(hl)
2647         add hl,bc               ;passed the enemies
2648         ld  c,1+7+3
2649         add hl,bc               ;update to point to next level
2650         ld  (levelp),hl         ;save
2651
2652         ld  a,(level)           ;level number
2653         inc a                   ;next level #
2654         cp  endlevel+1          ;last level done?
2655         jr  nc,gamedone         ;yes: display end story and quit
2656         ld  (level),a
2657
2658         add a,a
2659         add a,a
2660         ld  h,0                 ;increase score....
2661         ld  l,a                 ;by level number * 4
2662         ld  bc,20
2663         add hl,bc               ;plus 20
2664         cal scoreInc            ;update score
2665
2666 samelevel:
2667         ld  hl,(your_ship)
2668         ld  (your_shipspr),hl
2669
2670         ld  a,80
2671         ld  (nextevent),a       ;time to first enemy appearance
2672
2673         ld  hl,(levelp)         ;level pointer
2674         dec hl                  ;byte before level (boss byte)
2675         xor a                   ;if it's zero it means here's a story
2676         cp  (hl)
2677         inc hl                  ;begin of level
2678         cal z,dostory           ;do the story and set (levelp) to real level
2679
2680         ld  a,(hl)              ;number of (different) enemies in this level
2681         inc hl
2682         ld  c,a
2683         ld  (nrlvlenemies),a    ;set nr of enemies-1
2684         ld  b,0                 ;bc=c so we can use ldir
2685         ld  de,lvlenemies       ;table of enemies
2686         ldir                    ;load enemies to table
2687         ld  a,(hl)              ;load new appearance-time
2688         ld  (eventtime),a
2689         inc hl
2690         ld  a,(hl)
2691         ld  (eventtime+1),a     ;set
2692         inc hl
2693         ld  a,(hl)              ;load nr of enemies in this level
2694         ld  (eventleft),a       ;set nr of events left
2695         inc hl
2696         ld  de,level_info
2697         ld  c,4                 ;bc=4
2698         ldir                    ;4xLDI
2699                 ;loads (level_info); (level_move); (spacespace); (groundinfo)
2700         ld  a,1
2701         ld  b,32                ;fill (groundpos) and (ceilingpos)
2702 fillground:
2703         ld  (de),a
2704         inc de
2705         dnz fillground
2706
2707         ld  ix,starx1
2708         ld  b,nrstars1
2709         cal placestars
2710         ld  ix,starx2
2711         ld  b,nrstars2
2712         cal placestars
2713
2714         xor a
2715         ld  (timer),a           ;reset time
2716         ld  hl,your_occ         ;hl = your_occ
2717         ld  (hl),a              ;reset your ship (not exploding)
2718         inc hl                  ;hl = your_inv
2719         ld  (hl),25             ;set 25*4=100 frames invulnerable
2720         ld  de,$1820
2721         ld  (x),de              ;begin position (x,y)
2722         cal Place_multiples     ;place all multiple-positions at that (0,24)
2723
2724         cal loadweapon          ;load (your_weapon)
2725
2726         ld  hl,enemies          ;remove all enemies and bullets
2727         ld  (hl),0              ;clear first byte
2728         ld  de,enemies+1        ;copy this to the next byte
2729         ld  bc,(nrenemies*enemysize)+(nrybuls*4)+(nrebuls*3)-1
2730         ldir                    ;clear enemies + bullets (y/e)
2731
2732 ;--------------------------- setup game -------------------------------------
2733
2734 game_setup:
2735         cal BLACKLCD            ;white on black
2736         ld  hl,txt_level
2737         ld  de,$0703
2738         ld  (_curRow),de        ;center
2739         cal _puts               ;display "LEVEL "
2740
2741         ld  a,(level)           ;current level
2742         ld  l,a
2743         ld  h,0                 ;in hl
2744         cal UNPACK_HL           ;create first digit
2745         add a,'0'               ;0-9
2746         ld  b,a                 ;into b
2747         cal UNPACK_HL           ;second digit
2748         add a,'0'               ;0-9
2749         cal _putc               ;display second digit
2750         ld  a,b
2751         cal _putmap             ;display first digit
2752
2753         ld  hl,txt_lives        ;bar text: "Lx0"...
2754         ld  de,$0904
2755         ld  (_curRow),de        ;display lives left below level nr
2756         cal _puts
2757         ld  a,(your_lives)      ;lives left
2758         add a,'0'               ;make value 0='0'
2759         cal _putc
2760
2761         cal releasekeys         ;wait for user to release all keys
2762         ld  hl,txt_savekey      ;"Press [F1] to save"
2763         ld  de,$3A46            ;bottom-right
2764         ld  (_penCol),de
2765         cal _vputs
2766
2767         res 3,(iy+5)            ;set white on black
2768         cal _getkey             ;wait for keypress
2769         cp  kF1
2770         cal z,save_lvl
2771
2772         cal _clrLCD             ;clear screen
2773         cal disp_icons          ;display bottom icons +ret
2774         jp  game_main_loop
2775
2776 placestars:
2777         cal RandomY             ;a = random y-pos 1..bottom
2778         ld  a,b                 ;a =  b = star nr. = 1..7
2779         add a,a                 ;a = 2b = 2..14
2780         ld  d,0
2781         ld  e,a                 ;de = a = 2-14
2782         or  a
2783         sbc hl,de               ;substract from random y => random pos anywhere
2784
2785         ld  (ix),l              ;save x-pos (l)
2786         ld  (ix+1),h            ;save y-pos (h)
2787         inc ix \ inc ix         ;next star
2788         dnz placestars          ;repeat for all stars
2789         ret
2790
2791 loadweapon:
2792         ld  a,(your_weapon)
2793         add a,a                 ;weap*2
2794         add a,a                 ;    *4
2795         add a,a                 ;    *8
2796         ld  c,a
2797         ld  b,0
2798         ld  hl,weapondata
2799         add hl,bc
2800         ld  a,(hl)
2801         ld  (weapdamage),a      ;damage of bullets
2802         inc hl
2803         ld  a,(hl)
2804         ld  (weapdaminc),a      ;damage increase
2805         inc hl
2806         ld  a,(hl)
2807         and %00011111           ;laser duration
2808         ld  (laserdur),a
2809         ret
2810
2811 ;----------------------------------------------------------------------------
2812 ;--------------------------- putsprite --------------------------------------
2813 ;----------------------------------------------------------------------------
2814 ;in:  de=(x,y); ix=sprite
2815 ;out: ix=behind sprite; hl:a=right below sprite; b=0; d=width; ce=?
2816
2817 putsprite:
2818         ld  c,(ix)              ;save width
2819 _putsprite:                     ;putsprite with custom width
2820         ld  a,d                 ;a=X
2821         bit 7,d                 ;check sign bit of X
2822         jr  z,CSpositive        ;X>=0
2823
2824         neg                     ;a=|X|
2825         cp  (ix)                ;off screen?
2826         ret nc                  ;X<=-width: don't draw at all
2827         ld  b,a                 ;b=|X|mod 8=1..7=bits to draw
2828         ld  a,%11111111         ;all bits set (draw everything)
2829 CSclipleft:
2830         srl a                   ;remove first bit in a for each b
2831         dnz CSclipleft          ;b=1: a=%01111111
2832                                 ;b=2: a=%00111111
2833                                 ;b=3: a=%00011111
2834                                 ;b=4: a=%00001111
2835                                 ;b=5: a=%00000111
2836                                 ;b=6: a=%00000011
2837                                 ;b=7: a=%00000001
2838         res 7,d                 ;X+128 (right side of screen)
2839         dec e                   ;Y--
2840         jr  CSdisplay           ;done clipping
2841
2842 CSpositive:
2843         sub 129-8               ;minus (screen width - byte width)
2844         ld  b,a
2845         ld  a,%11111111         ;clipmask
2846         jr  c,CSdisplay         ;x+width<128 then entire sprite is on screen
2847         inc b                   ;b = number of pixels off screen
2848 CSclipright:
2849         add a,a                 ;remove last bit in a for each b
2850         dnz CSclipright         ;b=1: a=%11111110
2851                                 ;b=2: a=%11111100
2852                                 ;b=3: a=%11111000
2853                                 ;b=4: a=%11110000
2854                                 ;b=5: a=%11100000
2855                                 ;b=6: a=%11000000
2856                                 ;b=7: a=%10000000
2857                                 ;b>7: a=%00000000 = off screen
2858
2859 CSdisplay:                      ;display the sprite ix at (d,e) masked
2860         ld  (CSclipmask),a      ;set mask
2861         cal findpixel           ;convert de to screen location hl:a
2862         ld  (CSbitmask),a
2863
2864         ld  d,c                 ;width
2865         ld  b,(ix+1)            ;height
2866 CSyloop:
2867         psh bc                  ;save rows to go
2868         psh hl                  ;screen
2869         ld  b,d                 ;width
2870         ld  a,(ix+2)            ;load image line
2871         and 255                 ;mask
2872 CSclipmask =$-1
2873         ld  c,a                 ;c=image
2874         inc ix                  ;next
2875 CSbitmask =$+1
2876         ld  a,1                 ;saved bitmask
2877 CSxloop:
2878         sla c                   ;test leftmost pixel
2879         jr  nc,CSnodraw         ;don't draw if it's 0
2880         ld  e,a                 ;psh af: save bitmask
2881         or  (hl)
2882         ld  (hl),a              ;OR pixel with screen
2883         ld  a,e                 ;pop af
2884 CSnodraw:
2885         rrca                    ;next bit
2886         jr  nc,CSbitdrawn       ;carry set if bit "jumped"
2887         inc hl                  ;next byte
2888 CSbitdrawn:
2889         dnz CSxloop
2890         pop hl                  ;screen at x-offset=0
2891         ld  bc,16
2892         add hl,bc               ;next line
2893         pop bc                  ;rows counter
2894         dnz CSyloop
2895 CSdone: ret
2896
2897 ;--------------------------- putbigsprite -----------------------------------
2898
2899 putwidesprite:
2900 ;destr: abcdehl+ix (ix=behind sprite; hl:a=right below sprite; b=0; d=width)
2901         ld  a,(ix)              ;width
2902         cp  9
2903         jr  c,putsprite         ;width<=8: just draw the sprite
2904
2905         ld  a,(ix)
2906         sub 8                   ;width>8
2907         psh af
2908         ld  c,8
2909         psh de
2910         cal _putsprite          ;otherwise draw one column (8 pixels wide)
2911         pop de
2912         inc ix                  ;no x-size to load
2913         ld  a,8                 ;next
2914         add a,d                 ;8 pixels right
2915         ld  d,a
2916         pop bc                  ;then draw the remaining pixels (c=width-8)
2917         ld  c,b
2918         jr  _putsprite
2919
2920 safeputsprite:                  ;cal putsprite with de intact
2921         psh de
2922         cal putsprite
2923         pop de
2924         ret
2925
2926 ;------------------------------- findpixel ----------------------------------
2927 ;based upon CLEM's fp | 131 cycles | 28 bytes | in:(d,e); out:hla; destr:de
2928
2929 findpixel:
2930         ld  a,e                 ;a=e=Y
2931         add a,a
2932         add a,a                 ;add a,a is 7 cycles faster than add hl,hl
2933         ld  h,0                 ;switch to hl now (Y<64)
2934         ld  l,a                 ;hl=4*Y
2935         ld  a,d                 ;a=d=X
2936         rra                     ;RRA: carry flag must be reset!
2937         add hl,hl               ;that's what the adds are for :P
2938         rra
2939         add hl,hl               ;hl=16*Y
2940         rra                     ;a=X/8
2941         or  l
2942         ld  l,a                 ;hl=hl+a
2943         ld  a,d
2944         and 7                   ;a=X\8
2945         cpl
2946         rlca
2947         rlca
2948         rlca
2949         ld (FPbit),a
2950         xor a
2951 FPbit =$+1
2952         set 0,a
2953         ld  de,dispbuffer       ;screen base position (where x+y=0)
2954 PutWhere =$-2
2955         add hl,de
2956         ret
2957
2958 ;----------------------------------------------------------------------------
2959 ;------------------------------- sprites ------------------------------------
2960 ;----------------------------------------------------------------------------
2961
2962 spr_ship01:
2963         .db 7,7         ;ship alpha class
2964         .db %11000000   ;██
2965         .db %11110000   ;████
2966         .db %01111110   ; ██████
2967         .db %11101000   ;███ █
2968         .db %01111110   ; ██████
2969         .db %11110000   ;████
2970         .db %11000000   ;██
2971 spr_ship01i:
2972         .db 8,7
2973         .db %11000010   ;██    █
2974         .db %11110001   ;████   █
2975         .db %01111111   ; ███████
2976         .db %11101001   ;███ █  █
2977         .db %01111111   ; ███████
2978         .db %11110001   ;████   █
2979         .db %11000010   ;██    █
2980
2981 spr_ship02:
2982         .db 7,7         ;ship beta class
2983         .db %11100000   ;███
2984         .db %11111000   ;█████
2985         .db %01111100   ; █████
2986         .db %01110010   ; ███  █
2987         .db %01111100   ; █████
2988         .db %11111000   ;█████
2989         .db %11100000   ;███
2990 spr_ship02i:
2991         .db 8,7
2992         .db %11100010   ;███   █
2993         .db %11111001   ;█████  █
2994         .db %01111101   ; █████ █
2995         .db %01110011   ; ███  ██
2996         .db %01111101   ; █████ █
2997         .db %11111001   ;█████  █
2998         .db %11100010   ;███   █
2999
3000 spr_ship03:
3001         .db 7,7         ;ship gamma class
3002         .db %11111000   ;█████
3003         .db %01100000   ; ██
3004         .db %11111100   ;██████
3005         .db %11100110   ;███  ██
3006         .db %11111100   ;██████
3007         .db %01100000   ; ██
3008         .db %11111000   ;█████
3009 spr_ship03i:
3010         .db 8,7
3011         .db %11111010   ;█████ █
3012         .db %01100001   ; ██    █
3013         .db %11111101   ;██████ █
3014         .db %11100111   ;███  ███
3015         .db %11111101   ;██████ █
3016         .db %01100001   ; ██    █
3017         .db %11111010   ;█████ █
3018
3019 spr_ship04:
3020         .db 7,7         ;ship delta class
3021         .db %11000000   ; ██
3022         .db %11110000   ; ████
3023         .db %11111100   ; ██████
3024         .db %01100010   ;  ██   █
3025         .db %11111100   ; ██████
3026         .db %11110000   ; ████
3027         .db %11000000   ; ██
3028 spr_ship04i:
3029         .db 8,7
3030         .db %11000010   ; ██    █
3031         .db %11110001   ; ████   █
3032         .db %11111101   ; ██████ █
3033         .db %01100011   ;  ██   ██
3034         .db %11111101   ; ██████ █
3035         .db %11110001   ; ████   █
3036         .db %11000010   ; ██    █
3037
3038 spr_ship05:
3039         .db 8,8         ;XC1701II ship
3040         .db %11110000   ;████
3041         .db %10001100   ;█   ██
3042         .db %11110010   ;████  █
3043         .db %01011101   ; █ ███ █
3044         .db %01011101   ; █ ███ █
3045         .db %11110010   ;████  █
3046         .db %10001100   ;█   ██
3047         .db %11110000   ;████
3048
3049 auch_bullet  = 1        ;damage to you when hit by an enemy bullet
3050 auch_ground  = 5        ;the same when you hit the ground/ceiling
3051 auch_collide = 3        ;when you hit an enemy
3052 auch_ecollide = 2*4     ;damage to both the enemy that hit you (skip bit 0/1)
3053
3054 spr_multiple:
3055         .db 6,6         ;multiples
3056         .db %00000000   ;
3057         .db %00111000   ;  ███
3058         .db %01111100   ; █████
3059         .db %01111100   ; █████
3060         .db %01111100   ; █████
3061         .db %00111000   ;  ███
3062 spr_multiple2:
3063         .db 7,7         ;multiples
3064         .db %00111000   ;  ███
3065         .db %01111100   ; █████
3066         .db %11111110   ;███████
3067         .db %11111110   ;███████
3068         .db %11111110   ;███████
3069         .db %01111100   ; █████
3070         .db %00111000   ;  ███
3071
3072 ;-------------------------------- explosions --------------------------------
3073
3074 spr_explosion:
3075         .db 8,6         ;1
3076         .db %00000000
3077         .db %00011100   ;    ███
3078         .db %00111110   ;   █████
3079         .db %01010110   ;  █ █ ██
3080         .db %00111000   ;   ███
3081         .db %00000000
3082
3083         .db 8,6         ;2
3084         .db %00110000   ;   ██
3085         .db %01001110   ;  █ ▒███
3086         .db %10111110   ; █ █████
3087         .db %01001111   ;  █ ▒████
3088         .db %00111000   ;   ███
3089         .db %00011010   ;    ██ █
3090
3091         .db 8,6         ;3
3092         .db %10110000   ; █ ██
3093         .db %01001110   ;  █  ███
3094         .db %10110101   ; █ ██▒█▒█
3095         .db %01000101   ;  █  ▒█▒█
3096         .db %00111110   ;   █████
3097         .db %01011010   ;  █ ██ █
3098
3099         .db 8,6         ;4
3100         .db %00101010   ; ▒ █▒█ █
3101         .db %01000110   ;  █  ▒██
3102         .db %10110101   ; █ ██ █ █
3103         .db %01100110   ;  ██  ██▒
3104         .db %00111100   ;   ████▒
3105         .db %01011001   ;  █ ██ ▒█
3106
3107         .db 8,6         ;5
3108         .db %01000000   ;  █▒ ▒ ▒
3109         .db %00100101   ;  ▒█  █▒█
3110         .db %00010100   ; ▒ ▒█ █ ▒
3111         .db %01000100   ;  █▒  █
3112         .db %00010010   ;   ▒█▒▒█
3113         .db %10011010   ; █▒ ██ █▒
3114
3115         .db 8,6         ;6
3116         .db %01000100   ;  █   █
3117         .db %00100000   ;   ▒█ ▒ ▒
3118         .db %00000001   ;    ▒ ▒ █
3119         .db %01000100   ;  █   █
3120         .db %00100010   ;   █▒  █
3121         .db %01001000   ; ▒█ ▒█ ▒
3122
3123         .db 8,6         ;7
3124         .db %00001000   ;  ▒  █▒
3125         .db %11000010   ; ██ ▒  █
3126         .db %00000000   ;        ▒
3127         .db %00100000   ;  ▒█  ▒
3128         .db %00000001   ;   ▒   ▒█
3129         .db %00110000   ;  ▒██▒
3130
3131         .db 8,6         ;8
3132         .db %00000100   ;     ▒█
3133         .db %00000000   ; ▒▒    ▒
3134         .db %01000000   ;  █
3135         .db %00000000   ;   ▒
3136         .db %00000010   ;       █▒
3137         .db %00100100   ;   █▒ █
3138
3139 spr_yexplosion:
3140         .db 8,5         ;1
3141         .db %00000000
3142         .db %00101100   ;  █ ██
3143         .db %00011110   ;   ████
3144         .db %00110100   ;  ██ █
3145         .db %00011000   ;   ██
3146         .db %00000000
3147
3148         .db 8,5         ;2
3149         .db %00111000   ;  ███
3150         .db %01011100   ; █ ███
3151         .db %10010111   ;█  █ ███
3152         .db %01000110   ; █   ██
3153         .db %00111000   ;  ███
3154         .db %00000000
3155
3156         .db 8,6         ;3
3157         .db %00111100   ;   ████
3158         .db %01001111   ; █  ████
3159         .db %10100011   ;█ █   ██
3160         .db %11000110   ;██   ██
3161         .db %01110101   ; ███ █ █
3162         .db %00111000   ;  ███
3163
3164         .db 8,6         ;4
3165         .db %00110110   ;  ██ ██
3166         .db %00000101   ;     █ █
3167         .db %11000001   ;██     █
3168         .db %01100001   ; ██    █
3169         .db %11000010   ;██    █
3170         .db %01010001   ; █ █   █
3171
3172 ;--------------------------------- bullets ----------------------------------
3173
3174 bullettable:
3175         .db (spr_bullet01-spr_bullet01) ;0
3176         .db (spr_bullet02-spr_bullet01) ;4
3177         .db (spr_bullet03-spr_bullet01) ;8
3178         .db (spr_bullet04-spr_bullet01) ;12
3179         .db (spr_bullet05-spr_bullet01) ;16
3180         .db (spr_bullet06-spr_bullet01) ;20
3181         .db (spr_bullet07-spr_bullet01) ;24
3182         .db (spr_bullet08-spr_bullet01) ;28
3183         .db (spr_bullet09-spr_bullet01) ;32
3184         .db (spr_bullet10-spr_bullet01) ;36
3185         .db (spr_bullet11-spr_bullet01) ;40
3186         .db (spr_bullet12-spr_bullet01) ;44
3187         .db (spr_bullet13-spr_bullet01) ;48
3188         .db (spr_bullet13-spr_bullet01) ;52
3189         .db (spr_bullet13-spr_bullet01) ;56
3190         .db (spr_bullet13-spr_bullet01) ;60
3191
3192 spr_bullet01:
3193         .db 2,1
3194         .db %11000000   ;▒██
3195 spr_bullet02:
3196         .db 4,1
3197         .db %11110000   ;▒████
3198 spr_bullet03:
3199         .db 2,2
3200         .db %11000000   ;▒██
3201         .db %11000000   ;▒██
3202 spr_bullet04:
3203         .db 4,2
3204         .db %10110000   ;▒█▒██
3205         .db %10110000   ;▒█▒██
3206 spr_bullet05:
3207         .db 4,3
3208         .db %01100000   ; ▒██
3209         .db %11110000   ;▒████
3210         .db %01100000   ; ▒██
3211 spr_bullet06:
3212         .db 5,3
3213         .db %00110000   ;  ▒██
3214         .db %11111000   ;▒█████
3215         .db %00110000   ;  ▒██
3216 spr_bullet07:
3217         .db 5,3
3218         .db %01110000   ; ▒███
3219         .db %11111000   ;▒█████
3220         .db %01110000   ; ▒███
3221 spr_bullet08:
3222         .db 5,3
3223         .db %11110000   ;▒████
3224         .db %11111000   ;▒█████
3225         .db %11110000   ;▒████
3226 spr_bullet09:
3227         .db 5,4
3228         .db %00010000   ;   ▒█
3229         .db %10111000   ;▒█▒███
3230         .db %01111000   ; ▒████
3231         .db %00010000   ;   ▒█
3232 spr_bullet10:
3233         .db 6,4
3234         .db %00111000   ;  ▒███
3235         .db %01111100   ; ▒█████
3236         .db %11111100   ;▒██████
3237         .db %00110000   ;  ▒██
3238 spr_bullet11:
3239         .db 7,5
3240         .db %00011000   ;   ▒██
3241         .db %11111100   ;▒██████
3242         .db %00111110   ;  ▒█████
3243         .db %01111100   ; ▒█████
3244         .db %00011000   ;   ▒██
3245 spr_bullet12:
3246         .db 7,6
3247         .db %00110000   ;  ▒██
3248         .db %11111100   ;▒██████
3249         .db %00111110   ;  ▒█████
3250         .db %01111110   ; ▒██████
3251         .db %11111100   ;▒██████
3252         .db %00111000   ;  ▒███
3253 spr_bullet13:
3254         .db 8,8
3255         .db %00111100   ;  ▒████
3256         .db %11111110   ;▒███████
3257         .db %01111111   ; ▒███████
3258         .db %00011111   ;   ▒█████
3259         .db %01111111   ; ▒███████
3260         .db %11111110   ;▒███████
3261         .db %00111100   ;  ▒████
3262
3263 spr_bullett1:
3264         .db 4,3         ;▒▒▒
3265         .db %11100000   ;▒███
3266         .db %11110000   ; ████
3267         .db %01110000   ;  ███
3268
3269 spr_bullete1:
3270         .db 4,3         ;enemy bullets
3271         .db %01100000   ; ██▒
3272         .db %11110000   ;████▒
3273         .db %01100000   ; ██▒
3274
3275 ;format:[min.damage] [dam.inc] [000:direction 00000:speed] [offset]
3276 ;damage = min.damage + dam.inc*incs (0<=incs<=6)
3277 ;speed in pixels/frame (>=%10010=forward; <=%01110=backwards)
3278 ;direction: 0=straight forward; 1=up; 2=1/2up; 3=down; 4=1/2down
3279
3280 maxnrweapons = 8+1
3281 weapondata:
3282         .db 1,1,%00000000,0,%00000000,0,%00010010,3     ;1 single fire
3283         .db 4,1,%00000000,0,%00000000,0,%00010011,3     ;2 fast single
3284         .db 1,1,%00000000,0,%00010010,0,%00010010,6     ;3 double
3285         .db 1,1,%01110010,2,%10010010,2,%00110010,2     ;4 triple
3286         .db 3,2,%01110011,2,%10010011,2,%00110011,2     ;5
3287         .db 5,3,%01110011,2,%10010100,2,%00110011,2     ;6
3288         .db 7,4,%01110100,2,%10010100,2,%00110100,2     ;7
3289         .db 12,5,%01110110,2,%10010110,2,%00110110,2    ;8
3290 maxweapon = 8
3291         .db 1,1,%11100100,3,%00000000,0,%00000000,0     ;1 single laser
3292         .db 1,1,%11111111,0,%11100000,6,%00000000,0     ;2 double laser
3293         .db 10,1,%11100001,0,%11100000,6,%11100000,3    ;3 triple laser
3294 maxlaser = 11
3295
3296 ;------------------------------------ bar -----------------------------------
3297
3298 spr_lship:
3299         .db 5,3                 ;li'l ship indicating lives left
3300         .db %11100000           ;███
3301         .db %01111000           ; ████
3302         .db %11100000           ;███
3303 lshipsize = 5                   ;space between two ship icons
3304
3305 spr_icon:
3306         .db 16,7        ;selected.......:.......:
3307         .db %11111111           ;████████████████
3308         .db %11000000           ;██             █
3309         .db %11000000           ;██             █
3310         .db %11000000           ;██             █
3311         .db %11000000           ;██             █
3312         .db %11000000           ;██             █
3313         .db %11111111           ;████████████████
3314         .db 7
3315         .db %11111111
3316         .db %00000001
3317         .db %00000001
3318         .db %00000001
3319         .db %00000001
3320         .db %00000001
3321         .db %11111111
3322 spr_icon00:
3323         .db 16,7        ;unused  .......:.......:
3324         .db %10101010           ;█ █ █ █ █ █ █ █
3325         .db %11010101           ;██ █ █ █ █ █ █ █
3326         .db %10101010           ;█ █ █ █ █ █ █ █
3327         .db %11010101           ;██ █ █ █ █ █ █ █
3328         .db %10101010           ;█ █ █ █ █ █ █ █
3329         .db %11010101           ;██ █ █ █ █ █ █ █
3330         .db %10101010           ;█ █ █ █ █ █ █ █
3331         .db 7
3332         .db %10101010
3333         .db %01010101
3334         .db %10101010
3335         .db %01010101
3336         .db %10101010
3337         .db %01010101
3338         .db %10101010
3339 spr_icon01:
3340         .db 16,7        ;torpedo .......:.......:
3341         .db %10000001           ;█      ███  ██ █▒
3342         .db %10000000           ;█       ███  ██ ▒
3343         .db %11000000           ;██      ███   ██▒
3344         .db %10110001           ;█ ██   ███   █ █▒
3345         .db %11001100           ;██  ██      ██  ▒
3346         .db %10110011           ;█ ██  ██   ████ ▒
3347         .db %11001100           ;██  ██  ██   ██ ▒
3348         .db 7
3349         .db %11001101
3350         .db %11100110
3351         .db %11100011
3352         .db %11000101
3353         .db %00001100
3354         .db %00011110
3355         .db %11000110
3356 spr_icon02:
3357         .db 16,7        ;tailbeam.......:.......:
3358         .db %10000000           ;█               ▒
3359         .db %10000011           ;█     ██        ▒
3360         .db %10000001           ;█      ███      ▒
3361         .db %10111011           ;█ ███ ██████  ██▒
3362         .db %10000001           ;█      ███      ▒
3363         .db %10000011           ;█     ██        ▒
3364         .db %10000000           ;█               ▒
3365         .db 5
3366         .db %00000000
3367         .db %00000000
3368         .db %11000000
3369         .db %11110011
3370         .db %11000000
3371 spr_icon03:
3372         .db 11,7        ;bullets .......:.......:
3373         .db %10000000           ;█       ██      ▒
3374         .db %10000011           ;█     █████ ▒▒▒ ▒
3375         .db %10011000           ;█  ██   ██  ▒▒▒ ▒
3376         .db %11111100           ;██████      ▒▒▒ ▒
3377         .db %10011000           ;█  ██   ██  ▒▒▒ ▒
3378         .db %10000011           ;█     █████ ▒▒▒ ▒
3379         .db %10000000           ;█       ██      ▒
3380         .db 7
3381         .db %11000000
3382         .db %11100000
3383         .db %11000000
3384         .db %00000000
3385         .db %11000000
3386         .db %11100000
3387         .db %11000000
3388 spr_icon04:
3389         .db 16,7        ;laser   .......:.......:
3390         .db %10000000           ;█               ▒
3391         .db %10001010           ;█   █ █     ▒▒▒ ▒
3392         .db %11101100           ;███ ██      ▒▒▒ ▒
3393         .db %11110111           ;████ ███████▒▒▒█▒
3394         .db %11101100           ;███ ██      ▒▒▒ ▒
3395         .db %10001010           ;█   █ █     ▒▒▒ ▒
3396         .db %10000000           ;█               ▒
3397         .db 4
3398         .db %00000000
3399         .db %00000000
3400         .db %00000000
3401         .db %11111111
3402 spr_icon05:
3403         .db 16,7        ;multiple.......:.......:
3404         .db %10000011           ;█     ███       ▒
3405         .db %10000001           ;█      ████  ██ ▒
3406         .db %10000001           ;█      ████     ▒
3407         .db %10000011           ;█     ███       ▒
3408         .db %10011000           ;█  ██           ▒
3409         .db %10111100           ;█ ████  ██    ██▒
3410         .db %10011000           ;█  ██           ▒
3411         .db 6
3412         .db %10000000
3413         .db %11100110
3414         .db %11100000
3415         .db %10000000
3416         .db %00000000
3417         .db %11000011
3418 spr_dividerline:
3419         .db 8,7
3420         .db 128,128,128,128,128,128,128 ;128 = %10000000
3421
3422 ;---------------------------- texts -----------------------------------------
3423
3424 txt_email:      .db "www.shiar.org ",127 ;title screen
3425                 .db " shiar0@hotmail.com",0
3426 _txt_email        = $3A01 ;$3A1E=just email
3427 txt_about:      .db "v0.99.812 ",127," by Shiar",0 ;right behind txt_email
3428 _txt_about        = $3321
3429 txt_menu1:      .db "NEW GAME",0
3430 txt_menu2:      .db "CONTINUE",0
3431
3432 txt_level:      .db "LEVEL ",0 ;new level screen
3433 txt_lives:      .db   "Lx0",0
3434 txt_savekey:    .db "Press [F1] to save",0
3435
3436 txt_gameover:   .db "GAME OVER!",0 ;game over screen
3437 txt_score:      .db "Score",0
3438 txt_hiscore:    .db "Hiscore",0
3439
3440 txt_pause:      .db " ",6,"/",7," ",$1C,"contrast; "
3441                 .db "F1",$1C,"B",$CF,5,"W Mode",0
3442 _txt_pause        = $020B
3443 txt_pressenter: .db "Enter to continue",0 ;pause
3444 _txt_pressenter   = $0201
3445 txt_teacher:    .db "(2",Lpi,"*.98)/sin 13",0 ;teacher
3446 txt_teacherans: .db Lneg,"14.6549373495",0
3447
3448 ;---------------------------- save data -------------------------------------
3449
3450 storehi_start:
3451 hiscore         .dw 0                   ;default hiscore
3452 hiname          .db "shiar.99",0        ;   "       "    name
3453 storehi_end:
3454
3455 storesave_start:                        ;--SAVED GAME--                 defs:
3456 level           .db  1                  ;level number                   1
3457 levelp          .dw level01             ;pointer to level data          l01
3458 pickuptimer     .db  4                  ;counts when to place a pickup  4
3459 your_ship       .dw spr_ship01          ;your sprite                    sprs1
3460 your_score      .dw  0                  ;current score                  0
3461 your_pickup     .db  4                  ;pickups already picked up      0
3462 your_occ        .db  0                  ;0=normal 1..16=exploding       0
3463 your_inv        .db  0                  ;invincibility left             0
3464 your_armor      .db 22                  ;HP left                        12
3465 your_lives      .db  3                  ;lives left                     3
3466 your_weapon     .db  8                  ;current weapon upgrade         0
3467 your_multiples  .db  0                  ;multiples present              0
3468 your_tail       .db  0                  ;tail beam present              0
3469 storesave_end:
3470
3471 time2invert:    .db 0                   ;time until b<>w switch (0 at startup)
3472
3473 ;------------------------------ levels data ---------------------------------
3474
3475 ;format:boss: [moveType] [enemyType]
3476 ;       @level: [nr.dif.enemies]x [enemy nr]
3477 ;       [min. enemy frequency] [enemy frequency max.inc] [next lvl]
3478 ;       [level_info: 0000:damage 0:diagfire 0:ground 0:ceiling 0:?]
3479 ;       [level_move] [tunnel size] [groundtype] [stars1] [stars2]
3480 ;efrequency must be odd if halfluring!
3481
3482         .db 0   ;storyline ID
3483 level00:        ;[y-pos] [x-pos] [text,0] [SFX lines; 0=more text] [-1=end]
3484         .db 25,33,"Imperial ships have",0,0
3485         .db 31,9,"been sent to intercept you",0,31-25+6,-1
3486
3487         .db 20 ;boss for level01
3488 level01:                        ;intro-like, just a few enemies to begin with
3489         .db 2,6,8
3490         .db 26,70,20,%00010000,0,0,0
3491         .db 1,1
3492
3493         .db 21
3494 level02:                        ;first wave of enemies; easeey
3495         .db 3,6,7,8
3496         .db 20,60,60,%00100000,0,0,0
3497         .db 1,1
3498
3499         .db 22
3500 level03:                        ;some more enemies
3501         .db 4,7,8,9,10
3502         .db 17,40,75,%00110000,0,0,0
3503         .db 1,1
3504
3505         .db 0
3506         .db 1,1,"Long-Range scanners are ",
3507         .db     "showing",0,0
3508         .db 8,1,"lots of enemy vessels ",
3509         .db     "advancing fast.",0,8-1+6
3510         .db 24,1,"I'm changing course to a",
3511         .db     " nearby ",0,0
3512         .db 31,1,"asteroid belt and try to",0,0
3513         .db 38,1,"lose them inthere.",0,38-24+6,-1
3514
3515         .db 23
3516 level04:                        ;approaching asteroid belt
3517         .db 7,11,11,12,12,13,1,2
3518         .db 12,24,80,%00111000
3519         .db 2,0,0,1,1
3520
3521         .db 24
3522 level05:                        ;light asteroid belt
3523         .db 5,11,12,1,2,4
3524         .db 12,24,80,%00111000
3525         .db 2,0,0,1,1
3526
3527         .db 25
3528 level06:                        ;inside asteroid belt
3529         .db 6,13,1,2,3,4,5
3530         .db 7,18,180,%01011000
3531         .db 2,0,0,1,1
3532
3533         .db 0,1,1,"That's it for now...",0,5,-1
3534
3535 endlevel = 6
3536
3537         .db 0
3538         .db 1,1,"And the storyline conti",
3539                 .db "nues.....",0,5
3540         .db 9,1,"You decide to fly close",
3541                 .db " to the",0,0
3542         .db 15,1,"surface of a nearby pl",
3543                 .db "anet =)",0,15-9+6,-1
3544
3545         .db 26
3546 level03b:
3547         .db 1,2
3548         .db $13,40,$4b,%00100100,0,-5,1
3549         .db 1,1
3550
3551         .db 0
3552
3553         .db 0
3554         .db $01,01,"Blablabla...",0,1
3555         .db $01,34,"this storyline sux",0,0,1,39
3556         .db $FF
3557
3558         .db 27
3559 level03a:
3560         .db 1,$03
3561         .db $2d,$3f,%00110110,0,-9,1
3562         .db -1,-1 ;=%11111111=line
3563
3564         .db $07,$08
3565 level04b:
3566         .db 1,$04
3567         .db $11,$41,%00100001,0,0,0
3568         .db 1,1
3569         .db $07,$09
3570 level05a:
3571         .db 1,$05
3572         .db $11,$45,%00100101,%10,-7,1
3573         .db 1,1
3574         .db $07,$08
3575 level06c:
3576         .db 1,$06
3577         .db $19,$3a,%00100111,0,-4,1
3578         .db 1,1
3579
3580         .db $07,$09
3581 level07:
3582         .db 1,$07
3583         .db $09,$ff,%00100001,0,0,0
3584         .db 1,1
3585
3586 ;------------------------------ enemies -------------------------------------
3587
3588 ;format:        [HP64] [000000:HP 00:occ] [sprite] [xpos] [appearance(ypos)]
3589 ;               [movetype] [time2fire] [firefreq] [firetype]
3590 ;appearances:   1=random; 2=lure; 3=halflure
3591 ;movetypes:     1=updown; 2=1/4x; 3=1/2x; 4=1.5x; 5=2x; 6=smart; 7=y-lure;
3592 ;               8=y-lure 1/2x; 9=x; 10=x+y-lure 1/2x
3593 ;firetypes:     1=normal; 6=aiming; 7=triple; 8=double
3594
3595 enemyspecs:
3596         .db 0,%00000110,(spr_enemy00-spr_enemy00)/2,128,2,03, 0, 0,1 ;pickup
3597 ;1-5=asteroids         ,                           ,   , ,  ,  ,
3598         .db 0,%00100110,(spr_enemyA1-spr_enemy00)/2,128,1,00, 0, 0,1
3599         .db 0,%00111110,(spr_enemyA2-spr_enemy00)/2,128,1,00, 0, 0,1
3600         .db 0,%01011010,(spr_enemyA3-spr_enemy00)/2,128,1,04, 0, 0,1
3601         .db 1,%00001010,(spr_enemyA4-spr_enemy00)/2,128,1,03, 0, 0,1 ;slow+hard
3602         .db 0,%00111110,(spr_enemyA4-spr_enemy00)/2,128,1,05, 0, 0,1
3603 ;6-10=basic enemies    ,                           ,   , ,  ,  ,
3604         .db 0,%00010010,(spr_enemyE1-spr_enemy00)/2,128,1,00,10, 0,1 ;weak
3605         .db 0,%00110010,(spr_enemyE4-spr_enemy00)/2,128,1,03, 6,50,1 ;slow
3606         .db 0,%00100110,(spr_enemyE2-spr_enemy00)/2,128,1,00, 1, 0,1
3607         .db 0,%00101110,(spr_enemyE3-spr_enemy00)/2,128,3,00,19,39,8 ;heavy
3608         .db 0,%00101010,(spr_enemyE5-spr_enemy00)/2,128,3,04, 1, 0,1 ;fast
3609 ;11-13=backwards enemies                           ,   , ,  ,  ,
3610         .db 0,%00011110,(spr_enemyB1-spr_enemy00)/2,000,3,11,19,92,1
3611         .db 0,%00101110,(spr_enemyB2-spr_enemy00)/2,000,1,12,11,45,1
3612         .db 0,%00110110,(spr_enemyB3-spr_enemy00)/2,000,1,11,10,41,8 ;small
3613 ;14=improved enemies   ,                           ,   , ,  ,  ,
3614         .db 0,%01001010,(spr_enemyG1-spr_enemy00)/2,128,3,00, 1,35,1
3615
3616         .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,128,0,00, 0, 0,1 ;15
3617         .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,128,0,00, 0, 0,1 ;16
3618         .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,128,0,00, 0, 0,1 ;17
3619         .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,128,0,00, 0, 0,1 ;18
3620         .db 0,%00000011,(spr_enemy00-spr_enemy00)/2,128,0,00, 0, 0,1 ;19
3621 ;20-23=first bosses    ,                           ,   , ,  ,  ,
3622         .db 1,%00101011,(spr_boss2  -spr_enemy00)/2,127,1,08,20,12,1 ;small
3623         .db 1,%00110011,(spr_boss1  -spr_enemy00)/2,127,1,08,15,11,8 ;normal
3624         .db 1,%01001011,(spr_boss1  -spr_enemy00)/2,127,3,10,10,11,1 ;moving
3625         .db 0,%11111111,(spr_boss3  -spr_enemy00)/2,127,2,10, 1, 4,1 ;weak+rapidfire
3626 ;24-25=asteroid bosses ,                           ,   , ,  ,  ,
3627         .db 2,%00001011,(spr_bossA1 -spr_enemy00)/2,127,1,10,36,14,6
3628         .db 2,%00110011,(spr_bossA1 -spr_enemy00)/2,127,2,10,28,12,6
3629 ;26-27=big bosses      ,                           ,   , ,  ,  ,
3630         .db 2,%00000111,(spr_bossB1 -spr_enemy00)/2,127,3,07,18, 7,7
3631         .db 2,%01001011,(spr_bossB2 -spr_enemy00)/2,127,3,07,18, 7,7
3632
3633 spr_enemy00:
3634         .db 16,8                        ;pickup
3635         .db %11111111                   ; ████████████
3636         .db %10000110                   ; █    ██    █
3637         .db %10000110                   ; █    ██    █
3638         .db %10111111                   ; █ ████████ █
3639         .db %10111111                   ; █ ████████ █
3640         .db %10000110                   ; █    ██    █
3641         .db %10000110                   ; █    ██    █
3642         .db %11111111                   ; ████████████
3643         .db 8
3644         .db %11110000
3645         .db %00010000
3646         .db %00010000
3647         .db %11010000
3648         .db %11010000
3649         .db %00010000
3650         .db %00010000
3651         .db %11110000
3652         .db 0
3653
3654 spr_enemyA1:
3655         .db 7,6                         ;asteroid one
3656         .db %00011000                   ;   ██
3657         .db %01101100                   ; ██ ██
3658         .db %10011110                   ;█  ████
3659         .db %11111010                   ;█████ █
3660         .db %10111100                   ;█ ████
3661         .db %01110000                   ; ███
3662 spr_enemyA2:
3663         .db 8,7                         ;asteroid two
3664         .db %00111100                   ;  ████
3665         .db %01011010                   ; █ ██ █
3666         .db %01101101                   ; ██ ██ █
3667         .db %11111101                   ;██████ █
3668         .db %11111111                   ;████████
3669         .db %10110110                   ;█ ██ ██
3670         .db %01100000                   ; ██
3671         .db 0
3672 spr_enemyA3:
3673         .db 8,8                         ;asteroid three
3674         .db %00011110                   ;   ████
3675         .db %01110011                   ; ███  ██
3676         .db %01111101                   ; █████ █
3677         .db %10110111                   ;█ ██ ███
3678         .db %11111110                   ;███████
3679         .db %11111101                   ;██████ █
3680         .db %01010111                   ; █ █ ███
3681         .db %00001110                   ;    ███
3682 spr_enemyA4:
3683         .db 7,6                         ;asteroid four
3684         .db %01111000                   ; ████
3685         .db %10110110                   ;█ ██ ██
3686         .db %11111101                   ;██████ █
3687         .db %01111011                   ; ████ ██
3688         .db %01001110                   ; █  ███
3689         .db %00110000                   ;  ██
3690
3691 spr_enemyE1:
3692         .db 6,7                         ;weak
3693         .db %00111100                   ;  ████
3694         .db %01000100                   ; █   █
3695         .db %10111000                   ;█ ███
3696         .db %11100000                   ;███
3697         .db %10111000                   ;█ ███
3698         .db %01000100                   ; █   █
3699         .db %00111100                   ;  ████
3700         .db 0
3701 spr_enemyE2:
3702         .db 6,6                         ;weak
3703         .db %00111100                   ;  ████
3704         .db %01010000                   ; █ █
3705         .db %10100000                   ;█ █
3706         .db %10100000                   ;█ █
3707         .db %01010000                   ; █ █
3708         .db %00111100                   ;  ████
3709 spr_enemyE3:
3710         .db 6,6                         ;normal solid (Galaxian enemy)
3711         .db %00111100                   ;  ████
3712         .db %01110000                   ; ███
3713         .db %11110000                   ;████
3714         .db %11110000                   ;████
3715         .db %01110000                   ; ███
3716         .db %00111100                   ;  ████
3717 spr_enemyE4:
3718         .db 6,7
3719         .db %00011100                   ;   ███
3720         .db %01101000                   ; ██ █
3721         .db %10011000                   ;█  ██
3722         .db %01110000                   ; ███
3723         .db %10011000                   ;█  ██
3724         .db %01101000                   ; ██ █
3725         .db %00011100                   ;   ███
3726         .db 0
3727 spr_enemyE5:
3728         .db 6,6                         ;speedy
3729         .db %00011100                   ;   ███
3730         .db %01111000                   ; ████
3731         .db %11100000                   ;███
3732         .db %11100000                   ;███
3733         .db %01111000                   ; ████
3734         .db %00011100                   ;   ███
3735
3736 spr_enemyB1:
3737         .db 6,6                         ;solid backwards
3738         .db %11110000                   ;████
3739         .db %00101000                   ;  █ █
3740         .db %01010100                   ; █ █ █
3741         .db %01010100                   ; █ █ █
3742         .db %00101000                   ;  █ █
3743         .db %11110000                   ;████
3744 spr_enemyB2:
3745         .db 6,7
3746         .db %11110000                   ;████
3747         .db %01001000                   ; █  █
3748         .db %01110100                   ; ███ █
3749         .db %00100100                   ;  █  █
3750         .db %01110100                   ; ███ █
3751         .db %01001000                   ; █  █
3752         .db %11110000                   ;████
3753         .db 0
3754 spr_enemyB3:
3755         .db 5,7
3756         .db %11100000                   ;███
3757         .db %01010000                   ; █ █
3758         .db %01111000                   ; ████
3759         .db %01000000                   ; █
3760         .db %01111000                   ; ████
3761         .db %01010000                   ; █ █
3762         .db %11100000                   ;███
3763         .db 0
3764
3765 spr_enemyG1:
3766         .db 8,6                         ;G-Type
3767         .db %00111111                   ;   █████
3768         .db %01001000                   ; █  █
3769         .db %10110100                   ;█ ██ █
3770         .db %10110100                   ;█ ██ █
3771         .db %01001000                   ; █  █
3772         .db %00111111                   ;   █████
3773 spr_enemyG2:
3774         .db 8,6                         ;smaller nacelles
3775         .db %00000111                   ;     ███
3776         .db %01101100                   ; ██ ██
3777         .db %10110100                   ;█ ██ █
3778         .db %10110100                   ;█ ██ █
3779         .db %01101100                   ; ██ ██
3780         .db %00000111                   ;     ███
3781 spr_enemyG3:
3782         .db 8,6                         ;shuttle
3783         .db %00001111                   ;    ████
3784         .db %01111100                   ; █████
3785         .db %10011100                   ;█  ███
3786         .db %10011100                   ;█  ███
3787         .db %01111100                   ; █████
3788         .db %00001111                   ;    ████
3789 spr_enemyG4:
3790         .db 8,6                         ;G-Type solid
3791         .db %00111111                   ;   █████
3792         .db %01111000                   ; ████
3793         .db %11111100                   ;██████
3794         .db %11111100                   ;██████
3795         .db %01111000                   ; ████
3796         .db %00111111                   ;   █████
3797 spr_enemyG5:
3798         .db 6,6
3799         .db %01111100                   ; █████
3800         .db %10110000                   ;█ ██
3801         .db %10111000                   ;█ ███
3802         .db %10111000                   ;█ ███
3803         .db %10110000                   ;█ ██
3804         .db %01111100                   ; █████
3805 spr_enemyG6:
3806         .db 7,6                         ;small G-type solid
3807         .db %00011110                   ;   ████
3808         .db %01111000                   ; ████
3809         .db %11110000                   ;████
3810         .db %11110000                   ;████
3811         .db %01111000                   ; ████
3812         .db %00011110                   ;   ████
3813
3814 spr_enemyS1:
3815         .db 6,6                         ;solid
3816         .db %00111000                   ;   ███
3817         .db %01111100                   ;  █████
3818         .db %11111000                   ; █████
3819         .db %11111000                   ; █████
3820         .db %01111100                   ;  █████
3821         .db %00111000                   ;   ███
3822 spr_enemyS2:
3823         .db 7,6                         ;some attack vessel
3824         .db %00011100                   ;    ███
3825         .db %01110010                   ;  ███  █
3826         .db %10101100                   ; █ █ ██
3827         .db %10101100                   ; █ █ ██
3828         .db %01110010                   ;  ███  █
3829         .db %00011100                   ;    ███
3830 spr_enemyS3:
3831         .db 7,6                         ;interceptor
3832         .db %00011110                   ;    ████
3833         .db %01111110                   ;  ██████
3834         .db %11111100                   ; ██████
3835         .db %11111100                   ; ██████
3836         .db %01111110                   ;  ██████
3837         .db %00011110                   ;    ████
3838 spr_enemyS4:
3839         .db 8,6                         ;cheap intercept
3840         .db %00011011                   ;    ██ ██
3841         .db %01110110                   ;  ███ ██
3842         .db %10111100                   ; █ ████
3843         .db %10111100                   ; █ ████
3844         .db %01110110                   ;  ███ ██
3845         .db %00011011                   ;    ██ ██
3846
3847 spr_enemyN1:
3848         .db 8,7                         ;some cool Nemesis-MSX enemy
3849         .db %00111110                   ;  █████
3850         .db %11110001                   ;████   █
3851         .db %00001110                   ;    ███
3852         .db %00010101                   ;   █ █ █
3853         .db %00001110                   ;    ███
3854         .db %11110001                   ;████   █
3855         .db %00111110                   ;  █████
3856         .db 0
3857 spr_enemyN2:
3858         .db 8,7                         ;
3859         .db %00111110                   ;  █████
3860         .db %00011101                   ;   ███ █
3861         .db %11111111                   ;████ ███
3862         .db %01110110                   ; ██ ███
3863         .db %11111111                   ;████ ███
3864         .db %00011101                   ;   ███ █
3865         .db %00111110                   ;  █████
3866         .db 0
3867 spr_enemyN3:
3868         .db 8,7                         ;Nem3MSX jumper lvl#3
3869         .db %10111110                   ;█ █████
3870         .db %01011101                   ; █ ███ █
3871         .db %01111110                   ; ██████
3872         .db %00010100                   ;   █ █
3873         .db %01111110                   ; ██████
3874         .db %01011101                   ; █ ███ █
3875         .db %10111110                   ;█ █████
3876         .db 0
3877 spr_enemyN4:
3878         .db 8,8                         ;Stolen from XC1701II
3879         .db %01111110                   ; ██████
3880         .db %11110101                   ;████ █ █
3881         .db %00011111                   ;   █████
3882         .db %00111101                   ;  ████ █
3883         .db %00111001                   ;  ███  █
3884         .db %00011111                   ;   █████
3885         .db %11110101                   ;████ █ █
3886         .db %01111110                   ; ██████
3887 spr_enemyN5:
3888         .db 7,8                         ;Stolen from XC1701II
3889         .db %00111100                   ;  ████
3890         .db %01010010                   ; █ █  █
3891         .db %11111110                   ;███████
3892         .db %01001010                   ; █  █ █
3893         .db %01011010                   ; █ ██ █
3894         .db %11111110                   ;███████
3895         .db %01010010                   ; █ █  █
3896         .db %01111100                   ;  ████
3897
3898 spr_boss1:
3899         .db 16,10                       ;.......:.......:
3900         .db %00000001                   ;       ██████ ██
3901         .db %00001110                   ;    ███   █ ███
3902         .db %00110010                   ;  ██  █ ████
3903         .db %01001101                   ; █  ██ ██
3904         .db %11101011                   ;███ █ ██ █
3905         .db %11101011                   ;███ █ ██ █
3906         .db %01001101                   ; █  ██ ██
3907         .db %00110010                   ;  ██  █ ████
3908         .db %00001110                   ;    ███   █ ███
3909         .db %00000001                   ;       ██████ ██
3910         .db 10
3911         .db %11111011
3912         .db %00101110
3913         .db %11110000
3914         .db %10000000
3915         .db %01000000
3916         .db %01000000
3917         .db %10000000
3918         .db %11110000
3919         .db %00101110
3920         .db %11111011
3921         .db 0
3922 spr_boss2:
3923         .db 12,12                       ;.......:....5..:
3924         .db %00011110                   ;   ████
3925         .db %01100001                   ; ██    ██
3926         .db %10110010                   ;█ ██  █  ██
3927         .db %00000101                   ;     █ ██ █
3928         .db %00001010                   ;    █ █  ██
3929         .db %00011010                   ;   ██ █ █  █
3930         .db %00011010                   ;   ██ █ █  █
3931         .db %00001010                   ;    █ █  ██
3932         .db %00000101                   ;     █ ██ █
3933         .db %10110010                   ;█ ██  █  ██
3934         .db %01100001                   ; ██    ██
3935         .db %00011110                   ;   ████
3936         .db 11
3937         .db %00000000
3938         .db %10000000
3939         .db %01100000
3940         .db %10100000
3941         .db %01100000
3942         .db %10010000
3943         .db %10010000
3944         .db %01100000
3945         .db %10100000
3946         .db %01100000
3947         .db %10000000
3948 spr_boss3:
3949         .db 16,10                       ;.......:.......:
3950         .db %11111110                   ;███████
3951         .db %00000011                   ;      ███   ████
3952         .db %00110101                   ;  ██ █ ████    █
3953         .db %01111010                   ; ████ █ █  █ ██
3954         .db %10001101                   ;█   ██ █ ██ ██ █
3955         .db %10001101                   ;█   ██ █ ██ ██ █
3956         .db %01111010                   ; ████ █ █  █ ██
3957         .db %00110101                   ;  ██ █ ████    █
3958         .db %00000011                   ;      ███   ████
3959         .db %11111110                   ;███████
3960         .db 9
3961         .db %00000000
3962         .db %10001111
3963         .db %11100001
3964         .db %10010110
3965         .db %01101101
3966         .db %01101101
3967         .db %10010110
3968         .db %11100001
3969         .db %10001111
3970 spr_bossA1:
3971         .db 16,11                       ;AsteroidBoss one
3972         .db %00011110                   ;   ████
3973         .db %01110011                   ; ███  ███
3974         .db %01111111                   ; ███████ █
3975         .db %01111111                   ; █████████
3976         .db %11111110                   ;███████ ███
3977         .db %11111111                   ;███████████
3978         .db %11111111                   ;████████████
3979         .db %10111110                   ;█ █████ ████
3980         .db %01011111                   ; █ ███████
3981         .db %00110111                   ;  ██ ███
3982         .db %00001110                   ;    ███
3983         .db 9
3984         .db %00000000
3985         .db %10000000
3986         .db %01000000
3987         .db %11000000
3988         .db %11100000
3989         .db %11100000
3990         .db %11110000
3991         .db %11110000
3992         .db %11000000
3993         .db 0
3994 spr_bossB1:
3995         .db 16,18                       ;BigBoss one    :
3996         .db %00000000                   ;         █ █
3997         .db %00000111                   ;     ███ ███
3998         .db %00000011                   ;      ████ █
3999         .db %00000001                   ;       ██ ██
4000         .db %00000011                   ;      ███ ██
4001         .db %00000000                   ;        █████
4002         .db %00010111                   ;   █ ██████████
4003         .db %00111111                   ;  ██████ ██ ██
4004         .db %11111000                   ;█████   ██ █ ███
4005         .db %00001111                   ;    █████ ██ █ █
4006         .db %11111000                   ;█████   ██ █ ███
4007         .db %00111111                   ;  ██████ ██ ██
4008         .db %00010111                   ;   █ ██████████
4009         .db %00000000                   ;        █████
4010         .db %00000011                   ;      ███ ██
4011         .db %00000001                   ;       ██ ██
4012         .db %00000011                   ;      ████ █
4013         .db %00000111                   ;     ███ ███
4014         .db 19                          ;         █ █
4015         .db %01010000                   ;modelled after a Nemesis][MSX boss
4016         .db %01110000
4017         .db %11010000
4018         .db %10110000
4019         .db %10110000
4020         .db %11111000
4021         .db %11111110
4022         .db %01101100
4023         .db %11010111
4024         .db %10110101
4025         .db %11010111
4026         .db %01101100
4027         .db %11111110
4028         .db %11111000
4029         .db %10110000
4030         .db %10110000
4031         .db %11010000
4032         .db %01110000
4033         .db %01010000
4034 spr_bossB2:
4035         .db 16,15                       ;BigBoss two    :
4036         .db %00001111                   ;    █████
4037         .db %00111110                   ;  █████ █████
4038         .db %01111101                   ; █████ █ ███████
4039         .db %00000011                   ;      ██
4040         .db %00000100                   ;     █  █
4041         .db %00000011                   ;      █████
4042         .db %00011110                   ;   ████ ██ ████
4043         .db %11110011                   ;████  ██ █ █
4044         .db %00011110                   ;   ████ ██ ████
4045         .db %00000011                   ;      █████
4046         .db %00000100                   ;     █  █
4047         .db %00000011                   ;      ██
4048         .db %01111101                   ; █████ █ ███████
4049         .db %00111110                   ;  █████ █████
4050         .db %00001111                   ;    █████
4051         .db 15                          ;modelled after a Nemesis][MSX boss
4052         .db %10000000
4053         .db %11111000
4054         .db %01111111
4055         .db %00000000
4056         .db %10000000
4057         .db %11100000
4058         .db %11011110
4059         .db %01010000
4060         .db %11011110
4061         .db %11100000
4062         .db %10000000
4063         .db %00000000
4064         .db %01111111
4065         .db %11111000
4066         .db %10000000
4067         .db 0
4068
4069 ;----------------------------------------------------------------------------
4070 ;----------------------------- logo ------------------------------------------
4071 ;----------------------------------------------------------------------------
4072
4073 logo_nemesis:
4074 .db %11111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00001011,%11111111,%11111111,%11111111,%11111110
4075 .db %01111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00011011,%11111111,%11111111,%11111111,%11111100
4076 .db %00111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00111011,%11111111,%11111111,%11111111,%11111000
4077 .db %00011111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%01111011,%11111111,%11111111,%11111111,%11110000
4078 .db %00000000,%00000000,%00000001,%00011110,%00010000,%00000000,%10000001,%00011110,%00010000,%000000001,%00000000,%00001000,%01000000,%00000000,%00000000,%00000000
4079 .db %00000000,%00000000,%00000011,%00011110,%00110000,%00000001,%10000011,%00011110,%00110000,%000000011,%00000000,%00011000,%11000000,%00000000,%00000000,%00000000
4080 .db %00000000,%00000000,%00000111,%00011110,%01110000,%00000011,%10000111,%00011110,%01110000,%000000111,%00000000,%00111001,%11000000,%00000000,%00000000,%00000000
4081 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
4082 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
4083 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
4084 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
4085 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
4086 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
4087 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
4088 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
4089 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000111,%11010001
4090 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00011011
4091 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010101
4092 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010001
4093
4094 ;----------------------------- end ------------------------------------------
4095
4096         .end
4097 .end
4098
4099
4100 ;----------------------------------------------------------------------------
4101 ;----------------------------------------------------------------------------
4102 ;----------------------------------------------------------------------------
4103
4104 ; 0.98.77 -- 7.VII.00 -- size 6707
4105 ;
4106 ;       # bullets do damage in all levels
4107 ;       * more armor at armor-upgrade and extra armor at end of a level
4108 ;       - internal levels again (no need 4 external, safer/smaller)
4109 ;       # some registers not correctly pushed/popped
4110 ;       * several optimizations (init.procs some bytes smaller)
4111 ;       # enemies hit with hitpoints left disappeared (one pop too much...)
4112 ;       + bullets "charge up" (more damage) when not firing
4113 ;       - removed contrast changes
4114 ;       + more powerful bullets have different sprites (larger=more damage)
4115 ;       # multiples appear at your position (begin level/just selected)
4116 ;       # when invulnerable multiples acted weird
4117 ;       # no more error at activation after APD off after running Nemesis
4118 ;       # saves correctly if own name ain't "nemesis" + some bytes smaller
4119 ;       # screen wasn't always entirely cleared after quit
4120 ;       * waits until all keys have been released after death
4121 ;       + different bullets sizes will miss if they're too small
4122 ;       + at level start "press F1 to save"-text will be displayed
4123 ;       * w3.shiar.org displayed at title screen, black bar behind version nr
4124 ;       # score to 0 when exit pressed at main menu
4125 ;       # no residual story-text in first frame of game
4126 ;       # game doesn't continue again after death (stack messed up)
4127 ;       # game over when lives<0 (didn't work in v0.96+)
4128 ;       * using some self-modifiing code (so it's smaller)
4129 ;       # new random procedure: stars don't appear on one line anymore
4130 ;       * weapons appear centered at multiples
4131 ;       * laser properties can be changed (damage, charge)
4132 ;       + weapon can be combination of bullets/lasers (max. of 3 per weapon)
4133 ;       * bullet-icon is removed when laser is selected
4134 ;       * enemy sprite table integrated in enemy specs (-1 byte/enemy)
4135 ;       + random enemy is chosen from any number of enemies per level
4136 ;       * time to first enemy fire defined per enemy, not per level
4137 ;       + CLIPPED sprites!! no more in/out popping enemies! wow...
4138 ;       * bullets/enemies removed when _entirely_ off screen
4139 ;       # enemies would sometimes be hit by bullets going right below them
4140 ;       # size of the second bullet was too big (invisible hit)
4141 ;       * the frequency an enemy fires bullets is defined per enemy
4142 ;       + wide clipped sprites implemented (width 1-16 pixels)
4143 ;       # bosses first move left until x=100, otherwise they'd be off-screen
4144 ;       * at status bar left below ships are displayed for lives left
4145 ;       * armor bar is two pixels high (better visible)
4146 ;       # bullet overflow fixed again (>63 bullets fired)
4147 ;       # correct weapon loaded when continuing a saved game
4148 ;       # game freezed when generating a random value <=1
4149 ;       * you explode in a different way than the enemies
4150 ;       + screen inverts for a brief time when you are hit!
4151 ;       # stats-bar was messed up when ya got 0 lives left
4152 ;       * two new (big) bosses modeled after a common MSX Nemesis2-boss
4153 ;       * score increased once every 32 frames (instead of every 256)
4154 ;       # ground fixed for new random routine (smaller routine; incs -2 to 2)
4155 ;       + laser will upgrade as well when you reselect it
4156 ;       * 2nd can be used in main menu (wow!)
4157 ;       # altered variable storage space because of Nemesis grew beyond 6kb
4158 ;       # fixed armor bar display when at maximum
4159 ;       + a few new enemies (asteroids) and remade 1st 4 levels; new pickup
4160 ;       - torpedo since it was kinda useless
4161 ;       + second icon now selects TAIL BEAM: bullet going backwards
4162 ;       # armor increase at the end of a level doesn't overflow armorbar
4163 ;       + you can choose your own ship out of four vessel after NEW GAME!
4164 ;       + enemies can appear at any x-position and move both left and right
4165 ;       + move patterns given per enemy, not per level
4166 ;       * new (faster) enemy-move system; 10 basic moves (x2 left+right)
4167 ;       # enemies can _never_ move above or below visible screen
4168 ;       * "randomY"-enemies are placed entirely on screen (height calced)
4169 ;       # the major TI-OS crash bug WAS afterall caused by sprites drawn
4170 ;          (partially) outside screen memory. temporarily fixed by setting
4171 ;          virtual screen buffer to $8200 (enough mem there)
4172 ;       + upto 29 cool enemy sprites and redone first five levels
4173 ;       * improved enemy-move routine; smooth luring, five speeds+backwards
4174 ;       # after pause weapon will not be fired
4175 ;       # teacher key fixed (waits for GRAPH to be release before&after)
4176 ;
4177 ; 0.99.815 -- 15.VIII.00 -- size 6399
4178 ;
4179 ;       + you can have upto FOUR multiples! (~20 pixels apart)
4180 ;       * some optimizations: keycall, menu handling, port nops removed,
4181 ;          more SMC, fire handling, fast bullet handling, enemy movement
4182 ;       * better "backwards" enemies handling (and implemented in game)
4183 ;       # when enemy changed into a pickup, movement is set to vslow
4184 ;       * instead of turning into a pickup, enemies explode and a pickup
4185 ;          appears at the right side of the screen (moves left slowly)
4186 ;       # bullets do damage again (screenflash made damage become 0)
4187 ;       + when destroyed by bullets, the armor bar will show 0HP left
4188 ;       * all enemy bullets do the same damage in all levels
4189 ;       * you now appear at (*32*,30) because enemies can come from left
4190 ;       * improved bullet handling (faster, smaller, etc.)
4191 ;       + multiples are animated like real Nemesis (grow-shrink-grow-shrink>)
4192 ;       # fixed a bug that didn't select multiples when you were moving
4193 ;       # enemy collision screwed up invert and some other weird stuff
4194 ;       + in pause screen change contrast with up/down and B/W mode with F1
4195 ;       + lasers can have different durations (beams last longer)
4196 ;       * some sign-flag checkings replaced by carry-flag (thus reducing size)
4197 ;       # slow enemies (including pickups) didn't always appear (just 25-50%)
4198 ;       + enemies can fire different kinds of bullets: aiming, double, triple
4199 ;       * maximum number of bullets increased (48 for enemies, 128 for you)
4200 ;
4201 ;        + added        - removed       * changed       # bug fixed
4202
4203 ;bullet handling: (255/enemy)+419+putsprite cycles per bullet