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