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