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