cefd4d00cb14c4ef106b40a141b55a6002b91fea
[nemesis.git] / nemesis.z80
1         .include "asm86.h"
2         .include "ti86asm.inc"
3
4         .org _asm_exec_ram
5
6 TEXT_MEM = _textShadow
7
8         nop
9         jp  init
10         .dw $0001               ;description type 2 (= +YASicon)
11         .dw Title               ;pointer to description
12         .dw spr_ship            ;pointer to YAS icon
13
14 Title:  .db "Nemesis v0.9.94 by Shiar",0
15
16 just_fired      = TEXT_MEM      ;byte
17 temp1           = TEXT_MEM+1    ;word
18 RanPos          = TEXT_MEM+3    ;byte
19
20 ;---------------------- init --------------------------------------------------
21
22 init:
23         call _runindicoff       ;turn the run-indicator off, obviously
24         call _clrLCD            ;clean the screen
25
26         ld  a,(CONTRAST)        ;load current contrast level
27         cp  $1f                 ;if already at maximum...
28         jr  z,skipdarken        ;...then skip level increase
29         inc a                   ;otherwise increase contrast level
30 skipdarken:
31         out (2),a               ;set it
32
33 ;---------------------- main menu ---------------------------------------------
34
35 LogoPut:
36         ld hl,logo_nemesis      ;from...
37         ld de,VIDEO_MEM+16      ;...to one line from top
38         ld a,19                 ;19 rows
39 LogoLoop:
40         ld bc,16                ;set screen width
41         ldir                    ;display one line
42         dec a                   ;decrease line-counter
43         jr nz,LogoLoop          ;repeat when counter is not yet zero
44
45 menutext:
46         ld  hl,$1608            ;just below logo
47         ld  (_penCol),hl
48         ld  hl,txt_about        ;display "by Shiar (ICQ#43840958)"
49         call _vputs
50
51         ld  hl,$0705            ;located one row above bottom
52         ld  (_curRow),hl        ;go there
53         ld  hl,txt_1player      ;display "ONE PLAYER"
54         call _puts
55         ld  hl,$0706            ;below oneplayer text
56         ld  (_curRow),hl
57         ld  hl,txt_2players     ;display "TWO PLAYERS"
58         call _puts
59
60         call _getkey            ;wait for keypress
61         call New_game           ;prepare level
62
63 ;------------------------------------------------------------------------------
64 ;---------------------- game loop ---------------------------------------------
65 ;------------------------------------------------------------------------------
66
67 game_main_loop:
68         ld  hl,timer            ;update time
69         inc (hl)                ;increase by 1
70         ld  b,(hl)              ;new time
71
72         ld  hl,RanPos           ;random counter
73         ld  a,(hl)              ;random value
74         add a,b                 ;even more random by adding timer
75         ld  (hl),a              ;save even more random value back
76
77 Clear_screen:
78         xor a                   ;empty bitmask
79         ld  hl,GRAPH_MEM        ;screen location (top left)
80         ld  b,$E0               ;loop 0E0h = 224 times = 256-32 for score-bar)
81 clearloop:
82         ld  (hl),a              ;clear four times (total = 224*4 = 896 bytes)
83         inc hl
84         ld  (hl),a
85         inc hl
86         ld  (hl),a
87         inc hl
88         ld  (hl),a
89         inc hl
90         djnz clearloop          ;repeat 224x
91
92 check_exitkey:
93         ld  a,%00111111         ;<exit> pressed?
94         out (1),a
95         nop \ nop
96         in  a,(1)
97         bit 6,a                 ;test bit 6 = <EXIT>
98         jr  z,quit              ;yes: quit game
99
100 game_stuff:
101         call Level_event        ;insert enemies
102         call Handle_Ship        ;move you
103         call Fire_bullet        ;check for fire
104         call Handle_enemies     ;move enemies
105         call Handle_bullets     ;move your bullets
106         call Handle_torp        ;move your torpedo
107         call Enemy_bullets      ;move enemy bullets
108         call Enemies_hit        ;check for collision with enemies
109
110         call Display_Screen     ;display all
111         halt ;\ halt            ;delay
112         jr   game_main_loop     ;loop
113
114 ;--------------------------- exit ---------------------------------------------
115
116 quit:
117         ld  a,(CONTRAST)        ;load original contrast level
118         out (2),a               ;and set it back
119         ret                     ;quit Nemesis :(
120
121 ;--------------------------- display ------------------------------------------
122
123 Display_Screen:
124         ld  hl,GRAPH_MEM        ;from storage (top left)
125         ld  de,VIDEO_MEM        ;to screen (top left)
126         ld  a,56                ;display height = 64 bytes (minus 8 for bar)
127 displayloop:
128         ld  bc,16               ;display width = 16 bytes (16*8bits=256pixels)
129         ldir                    ;16x de >> hl
130         dec a                   ;next line
131         jr  nz,displayloop      ;loop 64x
132
133         ld  hl,$396b            ;Display Score
134         ld  (_penCol),hl        ;bottom right of screen
135         ld  hl,(timer)
136         ld  h,0
137
138 _D_HL_DECI:             ;------- display 5-digit value -------
139         ld   de,savestr+4       ;savenr saves number string
140         ld   b,5                ;five digits
141 ldhld:  call UNPACK_HL          ;one digit of hl
142         add  a,'0'              ;make number
143         ld   (de),a             ;save into savenr
144         dec  de                 ;point to next digit
145         djnz ldhld              ;repeat for all digits
146
147         ld   hl,savestr
148         call _vputs             ;display string
149         ret
150
151 savestr:
152         .db "SHIAR",0
153
154 ;------------------------- handle ship ----------------------------------------
155
156 Handle_Ship:
157         ld  a,(your_occ)
158         or  a
159         jr  z,ok                ;0 = normal stat
160
161         inc a                   ;next (explosion)frame
162         ld  (your_occ),a        ;save
163
164         cp  34                  ;last explosion frame?
165         jr  c,exploding_you     ;not yet: display explosion
166         cp  40                  ;delay finished?
167         jp  z,You_die           ;yes = game over
168         ret                     ;don't display anything
169
170 ok:
171         ld  a,%01111110
172         out (1),a
173         ld  hl,y
174         in  a,(1)
175         rra                     ;rotate right (put last bit in c)
176         ld  b,a                 ;we need a
177
178         jr  c,no_down
179         ld  a,(hl)
180         cp  49                  ;55-6 = bottom of screen
181         jr  z,no_down
182         inc a
183         ld  (hl),a
184 no_down:
185         dec hl
186         rr  b                   ;because we now use b, it's rr instead of rra
187         jr  c,no_left
188         ld  a,(hl)
189         sub 1                   ;<dec a> doesn't affect c-flag
190         jr  c,no_left           ;-1 = left side
191         ld  (hl),a
192 no_left:
193         rr  b   
194         jr  c,no_right
195         ld  a,(hl)
196         cp  121                 ;127-6 = right side
197         jr  z,no_right
198         inc a
199         ld  (hl),a
200 no_right:
201         ld  d,(hl)
202         inc hl
203         rr  b
204         jr  c,no_up
205         ld  a,(hl)
206         sub 1                   ;<dec a> doesn't affect carry-flag
207         jr  c,no_up             ;-1 = top of screen
208         ld  (hl),a              ;save new y
209
210 no_up:  ld  e,(hl)
211         ld  ix,spr_ship01       ;ship sprite
212         ld  hl,your_inv         ;invulnerable?
213         ld  a,(hl)              ;load time in a
214         or  a                   ;is it 0?
215         jp  z,putsprite         ;yes so ship = normal (display \ ret)
216
217         ld  b,a                 ;save inv-time
218         ld  a,(timer)           ;load frame nr.
219         and %00000011           ;a=0 once every four frames
220         jr  nz,not_time         ;a<>0 = not time to update counter
221         dec (hl)                ;decrease inv-time left
222 not_time:
223         and %00000010           ;a switches 0<->1 every 2 frames
224         jr  z,no_flicker        ;don't show normal sprite anyway
225         ld  a,b                 ;pop inv-time
226         and %11110000           ;inv-time <16 ticks left?
227         jp  z,putsprite         ;yes: display normal sprite
228
229 no_flicker:
230         ld  ix,spr_ship01i      ;display inv-ship (ld ix is faster than add ix)
231         jp  putsprite           ;ret
232
233 exploding_you:
234         srl a                   ;half the framerate
235         dec a                   ;first frame is 1>inc>srl>dec = 0
236         ld  hl,x-1
237
238 explosion_stuff:
239         rra
240         add a,a
241         add a,a
242         add a,a
243         ld  c,a
244         ld  b,0
245         ld  ix,spr_explosion
246         add ix,bc
247         inc hl
248         ld  d,(hl)
249         inc hl
250         ld  e,(hl)
251         jp  putsprite
252
253 damage_you:
254         ld  a,(your_inv)        ;invulnerability left?
255         or  a
256         ret nz                  ;return if inv>0
257         ld  hl,your_armor       ;armor left
258         ld  a,(hl)              ;check
259         dec a                   ;is it 0?
260         jp  m,no_armor          ;yes, 0hp left so explode
261         ld  (hl),a              ;no, so save decreased hp
262         call disp_armor         ;and display new value
263         ret                     ;and return
264 no_armor:
265         ld  a,%01               ;occ %xxxxxx01 = explode
266         ld  (your_occ),a        ;set to explode
267         ret
268
269 ;------------------------- fire bullet ----------------------------------------
270
271 Fire_bullet:
272         ld  a,(your_occ)        ;are you 100% OK?
273         or  a                   ;a=0??
274         ret nz                  ;return if not normal stat
275
276         ld  a,%00111111         ;function keys (F1-F5)
277         out (1),a               ;ask for them
278         nop \ nop               ;delay 8 clocks
279         in  a,(1)               ;get zem!
280         bit 4,a                 ;test bit 4 = F1-key
281         jr  z,fire              ;fire pressed?
282         ld  hl,just_fired
283         ld  (hl),0              ;no: reset just_fired
284         bit 3,a                 ;test bit 3 = F2-key &&&
285         ret nz                  ;return if not
286
287 select:
288         ld  hl,your_pickup      ;select pickups
289         ld  a,(hl)              ;load pickups taken so far
290         dec a                   ;is it 1?
291         jr  nz,select2          ;no, carry on
292         ld  (hl),a              ;reset pickups
293         ld  hl,your_armor       ;change armor
294         inc (hl)                ;increase HPs by one
295         jp  disp_icons          ;display and return
296 select2:
297         dec a                   ;is it 2?
298         jr  nz,select3          ;no, carry on
299         ld  (hl),a              ;reset pickups
300         inc a                   ;a=1
301         ld  (torp_occ),a        ;ready torpedoes
302         jp  disp_icons          ;display 'n return
303 select3:
304         ld  (hl),0              ;reset pickups
305         jp  disp_icons          ;display n return
306
307 fire:   ld  hl,RanPos           ;random
308         inc (hl)                ;update random counter
309         ld  hl,just_fired
310         ld  a,(hl)              ;just_fired
311         or  a                   ;zero when key just pressed (not already in)
312         ret nz                  ;return when already pressed
313         inc (hl)                ;set just_fired to 1
314
315         ld  hl,ybullets
316         ld  de,3
317         ld  b,10
318 find_ybullet:
319         ld  a,(hl)
320         or  a
321         jr  z,found_ybullet     ;0 = no bullet here
322         add hl,de
323         djnz find_ybullet       ;look next bullet
324         ret
325
326 found_ybullet:
327         ld  (hl),1              ;use bullet
328         ld  a,(x)               ;your x-pos
329         add a,5                 ;place bullet in front of you
330         inc hl                  ;go to bullet-x
331         ld  (hl),a              ;set x
332         ld  e,a                 ;save torp-x in e
333
334         ld  a,(y)               ;your y-pos
335         add a,2                 ;place bullet at the middle of your ship
336         inc hl                  ;go to bullet-y
337         ld  (hl),a              ;set y
338         add a,3                 ;place torpedo at bottom of ship
339         ld  d,a                 ;save torp-y in d
340
341         ld  hl,torp_occ         ;torpedo...
342         ld  a,(hl)              ;load torpInfo
343         dec a                   ;do you have (unused) torpedoes?
344         ret nz                  ;nope (a must be 1)
345         ld  (hl),2              ;yes; use torpedo
346         ld  (torp_pos),de       ;save torpedo position (in de)
347
348         ret
349
350 ;------------------------ handle bullets --------------------------------------
351
352 remove_bullet:
353         dec hl
354         ld  (hl),0              ;dump this bullet!
355         ret
356
357 Handle_bullets:
358         ld  hl,ybullets
359         ld  b,10
360 scan_bullets:
361         push bc
362         push hl
363         ld  (temp1),hl
364         ld  a,(hl)
365         inc hl
366         dec a                   ;type 1?
367         call z,bullet_2left     ;yes: 2left
368         pop hl
369         pop bc
370         ld  de,3
371         add hl,de               ;3 x <inc hl>
372         djnz scan_bullets       ;next bullet (loop)
373         ret
374
375 bullet_2left:
376         ld  a,(hl)              ;d = X
377         cp  122                 ;off screen? (x>128-5)
378         jr  nc,remove_bullet
379         add a,2                 ;move 2 2 the right
380         ld  (hl),a              ;save new pos.
381         ld  d,a
382
383         inc hl                  ;to y-pos
384         ld  e,(hl)              ;e = Y
385
386         ld  ix,spr_bullet01
387         push de
388         call putsprite          ;display bullet
389         pop de
390
391 check_bullethits:               ;INPUT: de=X,Y
392         ld  b,nrenemies
393         ld  hl,enemies
394
395 hit_enemies:                    ;Hits with normal enemies
396         push hl
397
398         ld  a,(hl)
399         and %00000010
400         jr  z,nohit             ;no hit when enemy_occ <> 2/3
401
402         inc hl                  ;enemy type
403         ld  a,(hl)
404         or  a                   ;enemy #0 = pickup
405         jr  z,nohit             ;yes: don't destroy
406
407         inc hl
408         ld  a,(hl)              ;check x
409         sub d
410         add a,5
411         jp  m,nohit
412         cp  8
413         jr  nc,nohit
414
415         inc hl
416         ld  a,(hl)              ;check y
417         sub e
418         add a,5
419         jp  m,nohit
420         cp  10
421         jr  nc,nohit
422
423         push hl
424         ld  hl,(temp1)
425         ld  (hl),$00            ;remove bullet
426         pop hl
427
428         dec hl
429         dec hl
430         dec hl
431         ld  a,(hl)              ;occ
432         ld  b,a                 ;push occ
433         and %11111100           ;occ/4 = HP left        ;<srl a\srl a
434         jr  nz,hpleft           ;not zero -> jump
435         ld  (hl),%01            ;set to explode
436
437         ld  a,(RanPos)          ;use random var
438         and %01011011           ;matches 0 100/2/2/2/2/2=3% of the time
439         jr  nz,pickupdone       ;otherwise just explode
440         ld  (hl),%00000110      ;change it into a pickup (with 2 HP)
441 pickupdone:
442         inc hl
443         ld  b,(hl)              ;save enemy type
444         ld  (hl),$00            ;explosionFrame 0
445
446         pop hl
447         ret
448
449 hpleft:
450         ld  a,b                 ;pop occ
451         sub %00000100           ;decrease HP by one
452         ld  (hl),a              ;save
453         pop hl
454         ret
455
456 nohit:
457         pop hl
458         inc hl
459         inc hl
460         inc hl
461         inc hl
462         djnz hit_enemies        ;check next enemy
463         ret
464
465 ;--------------------------- handle torpedo -----------------------------------
466
467 Handle_torp:
468         ld  a,(torp_occ)
469         sub 2
470         ret m                   ;return if occ=0/1
471
472         ld  hl,torp_pos         ;x-position
473         ld  a,(hl)              ;load in a
474         inc a                   ;move right
475         cp  125                 ;right edge reached
476         jr  nc,remove_torp      ;remove if x>125
477         ld  (hl),a              ;save new x
478         ld  d,a
479
480         inc hl                  ;y-position
481         ld  a,(hl)
482         inc a                   ;move down
483         cp  56                  ;bottom reached
484         jr  nc,remove_torp      ;remove if y>40
485         ld  (hl),a              ;save new y
486         ld  e,a
487
488         ld  ix,spr_bullett1
489         push de
490         call putsprite          ;display torpedo
491         pop de
492         jr check_bullethits     ;check for hits with enemies
493
494 remove_torp:
495         ld  a,1
496         ld  (torp_occ),a
497         ret
498
499 ;--------------------------- level events -------------------------------------
500
501 Level_event:
502         ld  hl,nextevent        ;time to next event     <ld  a,(nextevent)
503         dec (hl)                ;decrease counter       <dec a
504         ld  a,(hl)              ;look at counter        <ld  (nextevent),a
505         or  a                   ;has it reached zero?
506         ret nz                  ;nope: get outta here!
507
508         ld  a,(eventtime)       ;enemy frequency (lvl)
509         ld  (nextevent),a       ;set time to next event
510         ld  hl,eventleft
511         dec (hl)                ;update enemy-counter
512
513         ld  a,(hl)              ;look at counter
514         or  a                   ;has it reached 0?
515         jp  z,Next_level        ;yes: level finished
516         dec a                   ;has it reached 1?
517         jr  nz,do_event         ;nope: wait for enemies to leave
518         inc hl                  ;nextevent located behind eventleft
519         ld  (hl),119            ;set delay
520         ret                     ;don't place any more enemies
521
522 do_event:
523         ld  de,enemies-4
524 chk_noenemy:
525         inc de
526         inc de
527         inc de
528         inc de
529         ld  a,(de)
530         or  a                   ;0 = no enemy present
531         jr  nz,chk_noenemy
532
533 place_enemy:
534         ld  a,(eventenemy)      ;enemy type to place (lvl)
535         ld  hl,enemy00          ;enemy 1 specs
536         add a,a                 ;a=type*2
537         add a,a                 ;a=type*4
538         ld  c,a                 ;c=type
539         ld  b,0                 ;bc = enemy nr.
540         add hl,bc               ;hl = enemy specs
541         ld  a,(hl)              ;load hitpoints+occ of this enemy class
542         ld  (de),a              ;occ
543
544         inc hl                  ;next enemyInfo byte
545         inc de                  ;next byte of current enemy
546         ld  a,(hl)              ;load movement+type of this enemy class
547         ld  (de),a              ;enemy type
548
549         inc de                  ;set x-pos
550         ld  a,122               ;appear at right edge of screen (128-6)
551         ld  (de),a              ;= x-position
552
553         inc de                  ;set y-pos
554         inc hl                  ;where to place??
555         ld  a,(hl)              ;load placeInfo
556         dec a                   ;is it 1?
557         jr  z,random_enemy      ;yes: create random value <51 in a
558         dec a                   ;is it 2?
559         jr  z,lure_enemy        ;yes: create a 100% luring enemy
560                                 ;otherwise?
561 halflure_enemy:                 ;yes (of course it is): pick one (50% lure)
562         ld  a,(timer)           ;look at frame-number
563         and %00000001           ;make random if odd frame nr.
564         jr  nz,random_enemy     ;1st possibility: random enemy
565 lure_enemy:                     ;2nd possibility: luring enemy
566         ld  a,(y)               ;place at same y-pos as YOUR ship
567         jr  ypos_OK
568
569 random_enemy:
570         call Random             ;make a (in a) random value 0-255
571         cp  51                  ;y may not be more than 51
572         jr  c,ypos_OK           ;OK if a<51
573         and %00111111           ;a = 0..63
574         sub 13                  ;a = -13..50
575         jr  c,random_enemy      ;not OK if a<0
576
577 ypos_OK:                        ;random value successfully created
578         ld  (de),a              ;save y-position
579
580         ld  hl,add2enemy-3      ;offset to xtra enemy info
581         add hl,de               ;hl points to <xtra info: move>
582         ld  (hl),1              ;set move-counter to 1
583         inc hl                  ;hl to <xtra info: fire>
584         ld  (hl),1              ;set time-to-fire to 1 frame (fires directly)
585         ret                     ;return
586
587 Random:
588         ld  a,(RanPos)          ;a handy random-var.
589         ld  hl,x                ;add your x-coord for randomness
590         adc a,(hl)
591         ld  hl,y                ;add your y-coord for randomness
592         adc a,(hl)
593         ld  (RanPos),a          ;save altered random-var
594         ret                     ;RanPos also in #a
595
596 ;--------------------------- enemy fires --------------------------------------
597
598 Enemy_fires:                    ;de = x,y
599         push de
600         dec d
601         dec d                   ;d = x-2
602         inc e                   ;e = y+1
603
604         ld  b,10
605         ld  hl,ebullets
606 find_ebullet:
607         ld  a,(hl)
608         or  a
609         jr  z,found_ebullet     ;0 = not used
610         inc hl \ inc hl \ inc hl
611         djnz find_ebullet       ;look next bullet
612         ret
613
614 found_ebullet:
615         ld  (hl),1              ;use bullet &&&
616         inc hl
617         ld  (hl),d              ;set x-pos
618         inc hl
619         ld  (hl),e              ;set y-pos
620         pop de
621         ret         
622
623 ;----------------------------- enemy bullets ----------------------------------
624
625 Enemy_bullets:
626         ld  hl,ebullets
627         ld  b,10
628 handle_bullet:
629         push bc
630         push hl
631         ld  a,(hl)              ;load bulletType in a
632         or  a                   ;is it 0?
633         jr  nz,enemy_bullet     ;no: handle bullet
634 next_bullet:
635         pop hl                  ;do not move the <pop hl>
636         pop bc
637         inc hl \ inc hl \ inc hl
638         djnz handle_bullet
639         ret
640
641 enemy_bullet:
642         ld  b,a                 ;save type
643         inc hl                  ;bullet x
644         ld  a,(hl)              ;check if it has reached the left side of scrn
645         and %11111110           ;it is <2 (0 or 1)?
646         jr  z,remove_ebullet    ;yes, remove bullet
647         dec (hl)                ;move one left
648         dec (hl)                ;and another one
649         ld  d,(hl)              ;d=x
650         inc hl                  ;@y
651
652         ld  a,b                 ;restore type
653         dec a                   ;type 1?
654         jr  z,ebullet_common    ;normal bullet
655
656 ebullet_down:
657         ld  a,(timer)
658         rra
659         jr  c,ebullet_common
660         inc (hl)
661
662 ebullet_common:
663         ld  e,(hl)              ;e=y
664         ld  ix,spr_bullete1     ;display enemy bullet
665         call putsprite
666
667 ebullet_hits:
668         ld  a,(your_occ)
669         or  a
670         jr  nz,next_bullet      ;0 = you're normal
671
672         pop hl
673         push hl
674         inc hl                  ;check x
675         ld  a,(x)
676         sub (hl)
677         add a,6
678         jp  m,next_bullet
679         cp  9
680         jr  nc,next_bullet
681
682         inc hl                  ;check y
683         ld  a,(y)
684         sub (hl)
685         add a,6
686         jp  m,next_bullet
687         cp  9
688         jr  nc,next_bullet
689
690         call damage_you         ;HIT!!
691 remove_ebullet:
692         pop hl                  ;hl could be destroyed by damage_you
693         ld  (hl),0              ;bullet > unused
694         jr  next_bullet+1       ;next bullet (SKIP THE <POP HL> = one byte)
695
696 ;--------------------------- handle enemies -----------------------------------
697
698 Handle_enemies:
699         ld  hl,enemies
700         ld  b,nrenemies         ;handle all enemies
701
702 handle_enemy:
703         push bc
704         push hl
705
706         ld  a,(hl)
707         and %00000011
708         jr  z,next_enemy        ;occ "no enemy" 0
709         dec a
710         jr  z,exploding_enemy   ;occ "exploding" 1
711         ld  b,a                 ;b=2 if moving, otherwise b=1
712
713 normal_enemy:                   ;occ "normal" 2 or "moving" 3
714         inc hl
715         push hl
716
717         ld  e,(hl)              ;e = enemy type
718         ld  c,e                 ;c = e
719         ld  d,0                 ;de = e
720         ld  hl,sprites          ;hl = @sprites offset-table
721         add hl,de               ;points to offset of current enemy offset
722         ld  e,(hl)              ;de = @enemy offset
723
724         ld  ix,spr_enemy00      ;first enemy sprite
725         add ix,de               ;add offset for current enemy
726         pop hl
727
728         inc hl
729         ld  a,(hl)              ;x
730         dec a                   ;move left
731         jr  c,remove_enemy      ;off screen
732         jr  z,remove_enemy      ;"
733         ld  d,a
734
735         inc hl
736         ld  e,(hl)              ;y
737         ld  a,b                 ;moving state was stored in b earlier
738         dec a                   ;is it 1?
739         call nz,moving_enemy    ;2 = moving enemy
740
741         dec hl                  ;@x
742         ld  (hl),d              ;store new x
743
744 check_enemyfire:
745         ld  a,c                 ;a = enemy type
746         or  a                   ;type 0? (pickup)
747         jr  z,firing_done       ;pickups don't fire
748
749         ld  bc,add2enemy+1-2    ;offset of <xtra enemy info: fire>
750         add hl,bc               ;go there (@hl)
751         dec (hl)                ;decrease counter till next blast
752         ld  a,(hl)              ;load new counter
753         or  a                   ;has it reached zero?
754         jr  nz,firing_done      ;finished if not
755
756         add a,64                ;re-set counter for next blast
757         ld  (hl),a              ;save
758         call Enemy_fires        ;fires bullet
759
760 firing_done:
761         push de                 ;save registers for firing-use
762         call putsprite          ;display sprite @ix
763         pop  de                 ;restore (destroyed by putsprite)
764
765 next_enemy:
766         pop hl
767         ld  bc,$0004
768         add hl,bc
769         pop bc
770         djnz handle_enemy
771         ret
772
773 remove_enemy:
774         pop hl
775         ld  (hl),$0000          ;bye bye enemy
776         push hl
777         jr  next_enemy
778
779 exploding_enemy:
780         inc  hl
781         push hl
782         ld   a,(hl)
783         call explosion_stuff    ;display explosion
784         pop  hl
785
786         ld  a,(hl)
787         cp  15
788         jr  z,remove_enemy      ;remove when at last frame
789         inc a
790         ld  (hl),a              ;next frame
791         jr  next_enemy
792
793 ;--------------------------- moving enemies -----------------------------------
794
795 moving_enemy:
796 movetype_updown:
797         ld  bc,add2enemy
798         add hl,bc
799
800         ld  a,(hl)
801         dec a
802         jr  nz,move_updated
803         add a,128
804 move_updated:
805         ld  (hl),a
806
807         or  a                   ;reset carry flag
808         sbc hl,bc
809         and %00100000
810         jr  z,movedown
811
812 moveup:
813         ld  a,(hl)              ;load y-position
814         dec a                   ;decrease y-pos (=move up)
815         ret m                   ;don't move off the screen (y<0)
816         ld  (hl),a              ;save new y-pos
817         ret                     ;finish
818 movedown:
819         ld  a,(hl)              ;load current y
820         inc a                   ;increase y-pos
821         cp  55                  ;compare with bottom
822         ret nc                  ;return if it has passed that line (>40)
823         ld  (hl),a              ;otherwise save new position
824         ret                     ;and return
825
826 ;--------------------------- check collision ----------------------------------
827
828 Enemies_hit:
829         ld  a,(your_occ)
830         or  a                   ;0 = you're normal
831         ret nz
832
833         ld  de,(x)              ;e = X, d = Y
834         ld  hl,enemies
835         ld  b,nrenemies         ;check all 20 enemies
836 check_collision:
837         push hl
838         ld  a,(hl)
839         and %00000010
840         jr  z,check_next        ;2 or 3 = ok
841         inc hl
842
843 collide_enemy:
844 ;       push hl
845 ;       push bc
846 ;       ld  hl,enemy00          ;enemy 1 specs
847 ;       add a,a                 ;a=type*2
848 ;       add a,a                 ;a=type*4
849 ;       ld  c,a                 ;c=type
850 ;       ld  b,0                 ;bc = 4 * enemy nr.
851 ;       add hl,bc               ;hl = enemy specs
852 ;       ld  a,(hl)              ;load size byte
853 ;       pop bc
854 ;       pop hl
855 ;       ld  c,a                 ;save size in c
856
857         inc hl
858         ld  a,(hl)              ;check x match
859         sub e                   ;enemy position minus yours
860         add a,6
861         jp  m,check_next
862         cp  12
863         jr  nc,check_next
864
865         inc hl
866         ld  a,(hl)              ;check y match
867         sub d                   ;same as with x-check
868         add a,6
869         jp  m,check_next
870         cp  12
871         jr  nc,check_next
872         dec hl
873         dec hl
874
875 take_pickup:
876         ld  a,(hl)              ;load enemy type
877         or  a
878         jr  nz,collide          ;enemy when <>0
879
880         push hl
881         ld  hl,your_pickup      ;your pickups
882         ld  a,(hl)              ;current
883         inc a                   ;go to next
884         cp  3                   ;pickups >3
885         jr  c,not_maxpickup
886         ld  a,1                 ;yes: reset to pickup 1
887 not_maxpickup:
888         ld  (hl),a              ;save new
889         call disp_icons         ;display altered pickupicons
890         pop hl
891
892         dec hl                  ;to enemy occ
893         xor a                   ;set to 0 = gone
894         ld  (hl),a              ;remove
895         jr  check_next          ;all done, next..
896
897 collide:
898         xor a
899         ld  (hl),a              ;explosionFrame 0
900         dec hl
901         inc a
902         ld  (hl),a              ;set to explode
903         call damage_you         ;auch!
904
905 check_next:
906         pop hl
907         inc hl
908         inc hl
909         inc hl
910         inc hl
911         djnz check_collision
912         ret
913
914 ;--------------------------- show icon ----------------------------------------
915
916 disp_icons:
917         ld  hl,VIDEO_MEM+(16*57);57 rows down = seven rows from bottom
918         ld  b,16*7              ;draw 16x (screen width) 7x (height)
919 cleanline:
920         ld  a,%00000000         ;blank line mask
921         ld  (hl),a              ;draw one piece of the divider-line
922         inc hl                  ;move right (8 pixels = 1 byte)
923         djnz cleanline          ;repeat (16bytes * 7rows * 8pixels)
924
925         ld  hl,VIDEO_MEM+(56*16)
926         ld  (PutWhere),hl
927
928         call disp_lives
929
930         ld  ix,spr_icon01       ;armorIcon
931         ld  de,$1a01            ;icon #1
932         call putwidesprite      ;display icon
933         call disp_armor         ;display value
934
935         ld  ix,spr_icon00
936         ld  a,(torp_occ)
937         or  a
938         jr  z,no_torp
939         ld  ix,spr_icon02       ;torpedoIcon
940 no_torp:
941         ld  de,$2a01            ;icon #2
942         call putwidesprite      ;display
943
944         ld  ix,spr_icon00       ;
945         ld  de,$3a01            ;icon #3
946         call putwidesprite
947         ld  ix,spr_icon00       ;emptyIcon
948         ld  de,$4a01            ;icon #4
949         call putwidesprite
950         ld  ix,spr_icon00       ;emptyIcon
951         ld  de,$5a01            ;icon #5
952         call putwidesprite
953
954         ld  a,(your_pickup)     ;pickups taken
955         add a,a                 ;picks*2
956         ret z                   ;return if no pickups
957         add a,a                 ;picks*4
958         add a,a                 ;picks*8
959         add a,a                 ;picks*$10
960         add a,$0a               ;add 0ah
961         ld  d,a                 ;y-pos = picks * $10 + $0a (1a,2a,3a,4a,5a)
962         ld  e,$01               ;x-pos = bottom (1a01,2a01,3a01,4a01,5a01)
963
964         ld  ix,spr_icon
965         call putwidesprite
966         ret
967
968 disp_armor:
969         ld  hl,$3926            ;Display Armor left
970         ld  (_penCol),hl        ;place @ armorIcon
971         ld  a,(your_armor)      ;load armor left
972         add a,'0'               ;make digit
973         call _vputmap           ;display char
974         ret
975
976 disp_lives:
977         ld  hl,$3900            ;display Lives
978         ld  (_penCol),hl        ;bottom left
979         ld  hl,savestr+2
980         ld  (hl),'L'
981         inc hl
982         ld  (hl),'x'
983         inc hl
984
985         ld  a,(lives)           ;nr of lives in a
986         add a,'0'               ;make digit
987         ld  (hl),a
988         dec hl \ dec hl
989         call _vputs             ;display on screen
990         ret
991
992 ;--------------------------- game over / new game / death ---------------------
993
994 game_over:
995         call _clrLCD            ;clear screen
996         ld  hl,$0603
997         ld  (_curRow),hl        ;center
998         ld  hl,txt_gameover
999         call _puts              ;display "GAME OVER"
1000
1001         ld  b,$20
1002 wait2:  halt \ halt
1003         djnz wait2              ;delay
1004         call _getkey            ;wait for keypress
1005
1006         pop hl                  ;=ret (game_over was called from a procedure)
1007         ret                     ;quit to TI-OS or shell
1008
1009 New_game:
1010         xor a                   ;score 0
1011         ld  (score),a           ;reset score
1012         inc a                   ;level #1
1013         ld  (level),a           ;reset level nr
1014         ld  hl,level01          ;set level pointer to level#1
1015         ld  (levelp),hl         ;reset level pointer
1016         ld  hl,lives            ;starting lives
1017         ld  (hl),4              ;3 lives (will be decreased @ You_die)
1018
1019 You_die:
1020         ld  hl,lives
1021         dec (hl)                ;decrease lives
1022         ld  a,(hl)              ;load lives left
1023         inc a                   ;if lives=0ffh then a=0
1024         jr  z,game_over         ;if so, game's over
1025
1026         xor a                   ;a=0
1027         ld  (your_armor),a      ;no armor
1028         ld  (torp_occ),a        ;no torpedoes
1029         ld  (your_pickup),a     ;reset pickups
1030         jr  nonext_level
1031
1032 ;--------------------------- next level ---------------------------------------
1033
1034 Next_level:
1035         ld  hl,level            ;level number
1036         inc (hl)                ;increase it
1037         ld  hl,(levelp)         ;level pointer
1038         inc hl
1039         inc hl
1040         inc hl                  ;update to point to next level
1041         ld  (levelp),hl         ;save
1042
1043 nonext_level:
1044         ld  a,80
1045         ld  (nextevent),a       ;time to first enemy appearance
1046
1047         ld  hl,(levelp)         ;level pointer
1048         ld  a,(hl)              ;load new level-enemy type
1049         ld  (eventenemy),a      ;set level-enemy
1050         inc hl
1051         ld  a,(hl)              ;load new appearance-time
1052         ld  (eventtime),a       ;set
1053         inc hl
1054         ld  a,(hl)              ;load nr of enemies in this level
1055         ld  (eventleft),a       ;set nr of events left
1056
1057         xor a
1058         ld  (timer),a           ;reset time
1059         ld  hl,your_occ         ;hl = your_occ
1060         ld  (hl),a              ;reset your ship (not exploding)
1061         inc hl                  ;hl = your_inv
1062         ld  (hl),50             ;set 50 frames invulnerable
1063         ld  hl,x                ;begin position x=...
1064         ld  (hl),a              ;...=a=0=left
1065         inc hl                  ;y=...
1066         ld  (hl),24             ;...=24=middle
1067
1068 ;--------------------------- setup game ---------------------------------------
1069
1070 game_setup:
1071         call _clrLCD            ;clear screen
1072         ld a,%10111011
1073         ld  hl,VIDEO_MEM        ;screen location (top left)
1074         ld  b,0                 ;b = 0 (loop 0-1 = 0FFh = 256 times)
1075 clearloop2:
1076         inc a
1077         ld  (hl),a              ;clear four times (total = 256*4 = 1024 bytes)
1078         inc hl
1079         ld  (hl),a
1080         inc hl
1081         xor $ff
1082         ld  (hl),a
1083         inc hl
1084         ld  (hl),a
1085         inc hl
1086         xor $ff
1087         djnz clearloop2         ;repeat 256x
1088
1089         ld  hl,$0703
1090         ld  (_curRow),hl        ;center
1091         ld  hl,txt_level
1092         call _puts              ;display "LEVEL "
1093
1094         ld  a,(level)
1095         ld  l,a
1096         ld  h,$00
1097
1098         call UNPACK_HL
1099         add a,'0'
1100         ld  b,a
1101         call UNPACK_HL
1102         add a,'0'
1103         call _putc              ;display second digit
1104         ld  a,b
1105         call _putmap            ;display first digit
1106
1107         ld  hl,$0904
1108         ld  (_curRow),hl        ;display lives left below level nr
1109         ld  hl,txt_lives        ;bar text: "Lx0"...
1110         ld  a,(lives)           ;lives left
1111         add a,'0'               ;make value
1112         ld  (txt_lives+3),a     ;add to text
1113         call _puts              ;display the string
1114
1115         ld  b,$20
1116 wait:   halt \ halt
1117         djnz wait               ;delay
1118         call _getkey            ;wait for keypress
1119
1120         call _clrLCD            ;clear screen
1121         call disp_icons         ;display bottom icons
1122
1123         ld  hl,VIDEO_MEM+(16*56);56 rows down = eight rows from bottom
1124         ld  b,16                ;draw 16x (screen width)
1125 drawline:
1126         ld  a,%11111111         ;horizontal line mask
1127         ld  (hl),a              ;draw one piece of the divider-line
1128         inc hl                  ;move right (8 pixels = 1 byte)
1129         djnz drawline           ;repeat (16bytes * 8pixels =128= screen width)
1130         ret
1131
1132 ;--------------------------- putsprite ----------------------------------------
1133 ;--------------------------- de =(X,Y) ----------------------------------------
1134
1135 offsets_table:
1136         .db 128,64,32,%10000,%01000,%00100,%00010,%00001
1137 putsprite:
1138         ld  a,d                 ;a = X
1139         and %00000111           ;a = X mod 8 = bit nr. to mask
1140         ld  hl,offsets_table    ;pixel mask table
1141         ld  c,a                 ;bit nr.
1142         ld  b,0                 ;word
1143         add hl,bc               ;add to table
1144         ld  a,(hl)              ;a = pixel mask
1145         ld  (_smc1+1),a         ;alter pixel mask
1146
1147         ld  hl,GRAPH_MEM        ;save-location
1148         ld  a,e                 ;y-coord
1149         add a,a                 ;y*2
1150         add a,a                 ;y*4
1151         add a,a                 ;y*8
1152         rl  b                   ;b (=0) =b*2+overflow (if y>32 then bc=bc+256)
1153         add a,a                 ;y*16 (width of screen)
1154         rl  b                   ;b=b*2+overflow (if y>64 then bc=bc+512)
1155         srl d                   ;d/2
1156         srl d                   ;d/4
1157         srl d                   ;d/8 (8 bits in byte) ** c is set when overflow
1158         add a,d                 ;a = (Y*16+X/8) mod 256
1159         jr  nc,_n1              ;jump if no carry = no overflow = a<=255
1160         inc b                   ;a>255 so increase bc by 256
1161 _n1:    ld  c,a                 ;c = (Y*16+X/8) mod 256
1162         add hl,bc               ;bc = Y*16+X/8
1163           
1164         ld  d,(ix)
1165         ld  b,(ix+1)
1166 _oloop: push bc                 ;Save # of rows
1167         push hl                 ;Save screen address
1168         ld  b,d                 ;Load width
1169         ld  c,(ix+2)            ;Load one line of image
1170         inc ix
1171 _smc1:  ld  a,1                 ;Load pixel mask
1172 _iloop: sla c                   ;Test leftmost pixel
1173         jr  nc,_noplot          ;See if a plot is needed
1174         ld  e,a                 ;OR pixel with screen
1175         or  (hl)
1176         ld  (hl),a
1177         ld  a,e
1178 _noplot:rrca
1179         jr  nc,_notedge         ;Test if edge of byte reached
1180         inc hl                  ;Go to next byte
1181 _notedge:
1182         djnz _iloop
1183         pop hl                  ;Restore address
1184         ld  bc,16               ;Go to next line
1185         add hl,bc
1186         pop bc                  ;Restore data
1187         djnz _oloop
1188         ret
1189
1190 ;--------------------------- putbigsprite -------------------------------------
1191
1192 putwidesprite:
1193         ld       a,d
1194         and      7
1195         ld       hl,offsets_table
1196         ld       c,a
1197         ld       b,0
1198         add      hl,bc
1199         ld       a,(hl)
1200         ld       (wsmc1+1),a
1201         ld       (wsmc2+1),a
1202         ld       hl,(PutWhere)
1203
1204         ld       a,e
1205         add      a,a
1206         add      a,a
1207         add      a,a
1208
1209         rl       b
1210         add      a,a
1211         rl       b
1212         srl      d
1213         srl      d
1214         srl      d
1215         add      a,d
1216         jr       nc,n1
1217         inc      b
1218 n1:     ld       c,a
1219         add      hl,bc                                    
1220           
1221         ld       d,(ix)       
1222         ld       b,(ix+1)        
1223 woloop: push     bc                         ;Save # of rows
1224         push     hl                         ;Save screen address
1225         ld       b,d                        ;Load width
1226         ld       c,(ix+2)                   ;Load one line of image
1227         inc      ix
1228 wsmc1:  ld       a,1                        ;Load pixel mask
1229 wiloop: sla      c                          ;Test leftmost pixel
1230         jr       nc,wnoplot                 ;See if a plot is needed
1231         ld       e,a                        ;OR pixel with screen
1232         or       (hl)
1233         ld       (hl),a
1234         ld       a,e
1235 wnoplot:
1236         rrca
1237         jr       nc,wnotedge                ;Test if edge of byte reached
1238         inc      hl                         ;Go to next byte
1239 wnotedge:
1240 wsmc2:  cp       1
1241         jr       z,wover_1
1242
1243         djnz     wiloop
1244         pop      hl                         ;Restore address
1245         ld       bc,16                      ;Go to next line
1246         add      hl,bc
1247         pop      bc                         ;Restore data
1248         djnz     woloop
1249         ret
1250 wover_1:
1251         ld       c,(ix+2)
1252         inc      ix
1253         djnz     wiloop
1254         dec      ix
1255         pop      hl
1256         ld       bc,16
1257         add      hl,bc
1258         pop      bc
1259         djnz     woloop
1260         ret
1261
1262 ;------------------------------------------------------------------------------
1263 ;------------------------------- sprites --------------------------------------
1264 ;------------------------------------------------------------------------------
1265
1266 spr_ship:
1267         .db 9,1         ;ship icon
1268         .db %11100000   ; ███
1269         .db %01111000   ;  ████
1270         .db %00111110   ;   █████
1271         .db %01111001   ;  ████  █
1272         .db %01111001   ;  ████  █
1273         .db %01111001   ;  ████  █
1274         .db %00111110   ;   █████
1275         .db %01111000   ;  ████
1276         .db %11100000   ; ███
1277
1278 spr_ship01:
1279         .db 7,7         ;ship alpha class
1280         .db %01111000   ;  ████
1281         .db %11100000   ; ███
1282         .db %11111100   ; ██████
1283         .db %11110010   ; ████  █
1284         .db %11111100   ; ██████
1285         .db %11100000   ; ███
1286         .db %01111000   ;  ████
1287 spr_ship01i:
1288         .db 7,7         ;ship alpha class
1289         .db %01010000   ;  █ █
1290         .db %10100000   ; █ █
1291         .db %01010100   ;  █ █ █
1292         .db %10100010   ; █ █   █
1293         .db %01010100   ;  █ █ █
1294         .db %10100000   ; █ █
1295         .db %01010000   ;  █ █
1296
1297 spr_ship02:
1298         .db 7,7         ;ship beta class
1299         .db %11100000   ; ███
1300         .db %11110000   ; ████
1301         .db %01111100   ;  █████
1302         .db %01110010   ;  ███  █
1303         .db %01111100   ;  █████
1304         .db %11110000   ; ████
1305         .db %11100000   ; ███
1306 spr_ship02i:
1307         .db 7,7         ;ship beta class
1308         .db %01000000   ;  █
1309         .db %10100000   ; █ █
1310         .db %01010100   ;  █ █ █
1311         .db %00100010   ;   █   █
1312         .db %01010100   ;  █ █ █
1313         .db %10100000   ; █ █
1314         .db %01000000   ;  █
1315
1316 spr_bullet01:
1317         .db 5,3         ;your bullets
1318         .db %00110000   ;   ░▒▓█▒
1319         .db %11111000   ; ░▒▓████▒
1320         .db %00110000   ;   ░▒▓█▒
1321 spr_bullet02:
1322         .db 5,3
1323         .db %11110000   ; ░▒▓███▒
1324         .db %11111000   ; ░▒▓████▒
1325         .db %11110000   ; ░▒▓███▒
1326 spr_bullett1:
1327         .db 4,3         ;▒▒▒
1328         .db %11100000   ;▒███
1329         .db %11110000   ; ████
1330         .db %01110000   ;  ███
1331
1332 spr_bullete1:
1333         .db 4,3         ;enemy bullets
1334         .db %01100000   ;  ▒█▓▒░
1335         .db %11110000   ; ▒███▓▒░
1336         .db %01100000   ;  ▒█▓▒░
1337
1338 ;---------------------------------------- explosion -------------------------------------------
1339
1340 spr_explosion:                               
1341         .db 8,6         ;1
1342         .db %00000000
1343         .db %00011100   ;    ███
1344         .db %00111110   ;   █████
1345         .db %01010110   ;  █ █ ██
1346         .db %00111000   ;   ███
1347         .db %00000000
1348
1349         .db 8,6         ;2
1350         .db %00110000   ;   ██
1351         .db %01001110   ;  █ ▒███
1352         .db %10111110   ; █ █████
1353         .db %01001111   ;  █ ▒████
1354         .db %00111000   ;   ███
1355         .db %00011010   ;    ██ █
1356
1357         .db 8,6         ;3
1358         .db %10110000   ; █ ██
1359         .db %01001110   ;  █  ███
1360         .db %10110101   ; █ ██▒█▒█
1361         .db %01000101   ;  █  ▒█▒█
1362         .db %00111110   ;   █████
1363         .db %01011010   ;  █ ██ █
1364
1365         .db 8,6         ;4
1366         .db %00101010   ; ▒ █▒█ █
1367         .db %01000110   ;  █  ▒██
1368         .db %10110101   ; █ ██ █ █
1369         .db %01100110   ;  ██  ██▒
1370         .db %00111100   ;   ████▒
1371         .db %01011001   ;  █ ██ ▒█
1372
1373         .db 8,6         ;5
1374         .db %01000000   ;  █▒ ▒ ▒
1375         .db %00100101   ;  ▒█  █▒█
1376         .db %00010100   ; ▒ ▒█ █ ▒
1377         .db %01000100   ;  █▒  █
1378         .db %00010010   ;   ▒█▒▒█
1379         .db %10011010   ; █▒ ██ █▒
1380
1381         .db 8,6         ;6
1382         .db %01000100   ;  █   █
1383         .db %00100000   ;   ▒█ ▒ ▒
1384         .db %00000001   ;    ▒ ▒ █
1385         .db %01000100   ;  █   █
1386         .db %00100010   ;   █▒  █
1387         .db %01001000   ; ▒█ ▒█ ▒
1388
1389         .db 8,6         ;7
1390         .db %00001000   ;  ▒  █▒
1391         .db %11000010   ; ██ ▒  █
1392         .db %00000000   ;        ▒
1393         .db %00100000   ;  ▒█  ▒
1394         .db %00000001   ;   ▒   ▒█
1395         .db %00110000   ;  ▒██▒
1396
1397         .db 8,6         ;8
1398         .db %00000100   ;     ▒█
1399         .db %00000000   ; ▒▒    ▒
1400         .db %01000000   ;  █
1401         .db %00000000   ;   ▒
1402         .db %00000010   ;       █▒
1403         .db %00100100   ;   █▒ █
1404
1405 ;--------------------------------------- bar -----------------------------------
1406
1407 spr_icon:
1408         .db 16,7        ;unused   .......:.......:
1409         .db %11111111,%11111111 ; ████████████████
1410         .db %11000000,%00000001 ; ██             █
1411         .db %11000000,%00000001 ; ██             █
1412         .db %11000000,%00000001 ; ██             █
1413         .db %11000000,%00000001 ; ██             █
1414         .db %11000000,%00000001 ; ██             █
1415         .db %11111111,%11111111 ; ████████████████
1416 spr_icon00:
1417         .db 16,7        ;unused   .......:.......:
1418         .db %10101010,%10101010 ; █ █ █ █ █ █ █ █
1419         .db %11010101,%01010101 ; ██ █ █ █ █ █ █ █
1420         .db %10101010,%10101010 ; █ █ █ █ █ █ █ █
1421         .db %11010101,%01010101 ; ██ █ █ █ █ █ █ █
1422         .db %10101010,%10101010 ; █ █ █ █ █ █ █ █
1423         .db %11010101,%01010101 ; ██ █ █ █ █ █ █ █
1424         .db %10101010,%10101010 ; █ █ █ █ █ █ █ █
1425 spr_icon01:
1426         .db 16,7        ;armor  ; .......:.......:
1427         .db %10001111,%10000000 ; █   █████
1428         .db %10010000,%01000000 ; █  █     █  ▒▒▒
1429         .db %10101110,%00100000 ; █ █ ███   █ ▒▒▒
1430         .db %10100111,%10100000 ; █ █  ████ █ ▒▒▒
1431         .db %10101110,%00100000 ; █ █ ███   █ ▒▒▒
1432         .db %10010000,%01000000 ; █  █     █  ▒▒▒
1433         .db %10001111,%10000000 ; █   █████
1434 spr_icon02:
1435         .db 16,7        ;torpedo  .......:.......:
1436         .db %10111000,%00010101 ; █ ███      █ █ █
1437         .db %10011100,%00010101 ; █  ███     █ █ █
1438         .db %10111000,%01001010 ; █ ███    █  █ █
1439         .db %10000000,%11101010 ; █       ███ █ █
1440         .db %11100001,%11100101 ; ███    ████  █ █
1441         .db %10011000,%11110101 ; █  ██   ████ █ █
1442         .db %11100110,%00110010 ; ███  ██   ██  █
1443 spr_icon03:
1444         .db 16,7        ;laser    ........:.......:
1445         .db %10000000,%00000000 ; █
1446         .db %10110001,%01000000 ; █ ██   █ █
1447         .db %10111011,%10000000 ; █ ███ ███
1448         .db %10011101,%11111111 ; █  ███ ██████████
1449         .db %10111011,%10000000 ; █ ███ ███
1450         .db %10110001,%01000000 ; █ ██   █ █
1451         .db %10000000,%00000000 ; █
1452 spr_icon04:
1453         .db 16,7        ;invulnerable....:.......:
1454         .db %10000000,%01010100 ; █        O O O
1455         .db %10011110,%00101010 ; █  OOOO   O O O
1456         .db %10111000,%00010101 ; █ OOO      O O O
1457         .db %10111111,%10101010 ; █ OOOOOOO O O O
1458         .db %10111111,%00010101 ; █ OOOOOOO  O O O
1459         .db %10111000,%00101010 ; █ OOO     O O O
1460         .db %10011110,%01010100 ; █  OOOO  O O O
1461
1462 ;---------------------------- texts -------------------------------------------
1463
1464 txt_about:      .db "v0.9.94 ","by Shiar  "
1465                 .db "(ICQ#43840958)",0
1466 txt_1player:    .db "1 PLAYER",0
1467 txt_2players:   .db "2 PLAYERS",0
1468 txt_level:      .db "LEVEL ",0
1469 txt_gameover:   .db "GAME OVER!",0
1470 txt_lives:      .db "Lx0?",0
1471
1472 ;---------------------------- save data ---------------------------------------
1473
1474 stored_data_start:
1475
1476 PutWhere        .dw GRAPH_MEM           ;where to put the wide sprites
1477
1478 timer           .db $00                 ;frame counter
1479 level           .db $00                 ;level number
1480 levelp          .dw level01             ;pointer to level data
1481
1482 eventenemy      .db $02                 ;enemy type
1483 eventtime       .db $15                 ;enemy frequency
1484 eventleft       .db $00                 ;nr. of enemies still to come
1485 nextevent       .db $50                 ;time to next event
1486
1487 score           .dw $0000
1488
1489 your_pickup     .db $00
1490 your_occ        .db $00                 ;0=normal 1..16=exploding
1491 your_inv        .db $50                 ;invincibility left
1492 your_armor      .db $13                 ;HP left
1493 lives           .db $04                 ;
1494 x               .db $16                 ;x-pos
1495 y               .db $46                 ;think about it..
1496 hp              .db $00                 ;hitpoints left
1497
1498 torp_occ        .db $00                 ;torp.state: 0=unavail 1=avail 2=presnt
1499 torp_pos        .dw $0000               ;torpedo position (x,y)
1500
1501 ybullets        .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0       ;10 x (state,x,y)
1502 ebullets        .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0       ;10 x (state,x,y)
1503
1504 nrenemies       = 10
1505 enemies         .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1506                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1507                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1508                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1509
1510 enemiesxtra     .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1511                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1512                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1513                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1514 add2enemy       = 40
1515
1516 ; %111111 (HP left) 11 (00=no enemy 01=exploding 10=normal 11=moving)
1517 ; %11111111 (ship type or explosion frame)  %11111111 (x) %11111111 (y)
1518
1519 ;---------------------------- enemy data --------------------------------------
1520
1521 sprites:
1522         .db $00
1523         .db spr_enemy01-spr_enemy00
1524         .db spr_enemy02-spr_enemy00
1525         .db spr_enemy03-spr_enemy00
1526         .db spr_enemy04-spr_enemy00
1527         .db spr_enemy05-spr_enemy00
1528         .db spr_enemy06-spr_enemy00
1529         .db spr_enemy07-spr_enemy00
1530
1531 spr_enemy00:
1532         .db 7,5         ;pickup
1533         .db %11111110   ; ███████
1534         .db %10011010   ; █  ██ █
1535         .db %11111110   ; ███████
1536         .db %10011010   ; █  ██ █
1537         .db %11111110   ; ███████
1538 spr_enemy01:
1539         .db 6,6         ;enemy type one
1540         .db %00111100   ;   ████
1541         .db %01110000   ;  ███
1542         .db %11110000   ; ████
1543         .db %11110000   ; ████
1544         .db %01110000   ;  ███
1545         .db %00111100   ;   ████
1546 spr_enemy02:
1547         .db 8,6         ;enemy type two
1548         .db %00111111   ;    █████
1549         .db %01111000   ;  ████
1550         .db %11111100   ; ██████
1551         .db %11111100   ; ██████
1552         .db %01111000   ;  ████
1553         .db %00111111   ;    █████
1554 spr_enemy03:
1555         .db 6,6         ;enemy type three
1556         .db %01111100   ;  █████
1557         .db %11110000   ; ████
1558         .db %11111000   ; █████
1559         .db %11111000   ; █████
1560         .db %11110000   ; ████
1561         .db %01111100   ;  █████
1562 spr_enemy04:
1563         .db 6,6         ;enemy type four
1564         .db %00111000   ;   ███
1565         .db %01111100   ;  █████
1566         .db %11111000   ; █████
1567         .db %11111000   ; █████
1568         .db %01111100   ;  █████
1569         .db %00111000   ;   ███
1570 spr_enemy05:
1571         .db 7,6         ;enemy type four
1572         .db %00011110   ;    ████
1573         .db %01111110   ;  ██████
1574         .db %11111100   ; ██████
1575         .db %11111100   ; ██████
1576         .db %01111110   ;  ██████
1577         .db %00011110   ;    ████
1578 spr_enemy06:
1579         .db 7,6         ;enemy type four
1580         .db %00011100   ;    ███
1581         .db %01111110   ;  ██████
1582         .db %10111000   ; █ ███
1583         .db %10111000   ; █ ███
1584         .db %01111110   ;  ██████
1585         .db %00011100   ;    ███
1586 spr_enemy07:
1587         .db 8,6         ;enemy type four
1588         .db %00011110   ;    ████
1589         .db %01111111   ;  ███████
1590 enemy00:.db %10011100   ; █  ███
1591         .db %10011100   ; █  ███
1592         .db %01111111   ;  ███████
1593         .db %00011110   ;    ████
1594
1595         ;enemyInfo:     %000000:HP %10:occ $00:type $00:app $00:unused
1596 enemy01:                        ;#1     HP:1    app:random
1597         .db %00000010,1,1,0
1598 enemy02:                        ;#2     HP:1    app:halflure
1599         .db %00000010,2,3,0
1600 enemy03:                        ;#3     HP:1    app:random      moving
1601         .db %00000011,3,1,0
1602 enemy04:                        ;#4     HP:2    app:lure
1603         .db %00000110,4,2,0
1604 enemy05:                        ;#5     HP:2    app:random      moving
1605         .db %00000111,5,1,0
1606 enemy06:                        ;#6     HP:2    app:lure        moving
1607         .db %00000111,6,2,0
1608 enemy07:                        ;#7     HP:4    app:halflure    moving
1609         .db %00001111,7,3,0
1610
1611 ;----------------------------- level info -------------------------------------
1612
1613 level01:
1614         .db $01,$1b,$2f                 ;enemy nr ; enemy frequency ; next lvl
1615 level02:                                ;frequency must be odd if halfluring!
1616         .db $02,$11,$4b
1617 level03:
1618         .db $03,$1d,$3f
1619 level04:
1620         .db $04,$0d,$4f
1621 level05:
1622         .db $05,$25,$3d
1623 level06:
1624         .db $06,$23,$39
1625 level07:
1626         .db $07,$1f,$f9
1627
1628 ;----------------------------- logo -------------------------------------------
1629
1630 logo_nemesis:
1631 .db %11111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00001011,%11111111,%11111111,%11111111,%11111000
1632 .db %01111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00011011,%11111111,%11111111,%11111111,%11110000
1633 .db %00111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00111011,%11111111,%11111111,%11111111,%11100000
1634 .db %00011111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%01111011,%11111111,%11111111,%11111111,%11000000
1635 .db %00000000,%00000000,%00000001,%00011110,%00010000,%00000000,%10000001,%00011110,%00010000,%000000001,%00000000,%00001000,%01000000,%00000000,%00000000,%00000000
1636 .db %00000000,%00000000,%00000011,%00011110,%00110000,%00000001,%10000011,%00011110,%00110000,%000000011,%00000000,%00011000,%11000000,%00000000,%00000000,%00000000
1637 .db %00000000,%00000000,%00000111,%00011110,%01110000,%00000011,%10000111,%00011110,%01110000,%000000111,%00000000,%00111001,%11000000,%00000000,%00000000,%00000000
1638 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1639 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1640 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1641 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1642 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1643 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1644 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1645 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1646 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000111,%11010001
1647 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00011011
1648 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010101
1649 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010001
1650
1651 ;----------------------------- end --------------------------------------------
1652
1653         .end
1654 .end
1655
1656 ;----------------------------- NEMESIS'86 by Shiar ----------------------------
1657
1658 ;Game · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · NEMESIS
1659 ;Version  · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·  0.9.94
1660 ;Latest modification  · · · · · · · · · · · · · · · · · · · · · · · · · 4.IX.99
1661 ;Calc · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·  TI-86 only
1662 ;Size · · · · · · · · · · · · · · · · · · · · · · · · · · ·  2694 bytes on calc
1663
1664 ;Author · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · SHIAR
1665 ;ICQ · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·  #43840958
1666 ;E-mail · · · · · · · · · · · · · · · · · · · · · · · · · ·  shiar0@hotmail.com
1667 ;Homepage · · · · · · · · · · · · · · · · · · coming soon (www.wish.net/~shiar)
1668
1669 ;Notes:
1670 ;  <*> This game is not yet finished (BETA) and there may still be some bugs.
1671 ;  <*> Source will be released when the game has been finished.
1672 ;  <*> Have fun, and have even more fun with the completed version of NEMESIS!
1673
1674 ;----------------------------- version history --------------------------------
1675
1676 ;0.01.717 -- 17.VII.99 -- size 909
1677 ;
1678 ;       + used "Galaxian"-game engine (drawings, movement, enemy-routines)
1679 ;       + movement of ship over 3/4 screen (96 pixels; 32 pixels for score)
1680 ;       + enemies moving from right to left, appearing right at specified times
1681 ;
1682 ; 0.1.718 -- 18.VII.99 -- size 832
1683 ;
1684 ;       # no crash when level restarts for the third time
1685 ;       * exit-procedure updated, unnecessary stuff/keychecks removed
1686 ;       - alot of unused code removed
1687 ;       + different types of enemies (just look different)
1688 ;       + collision detection!! enemy ships disappear when you hit them
1689 ;
1690 ; 0.2.718 -- 18.VII.99 -- size 1078
1691 ;
1692 ;       + ability to fire bullets (F1). Enemies disappear on impact
1693 ;       * enemies explode instead of disappearing
1694 ;
1695 ; 0.3.719 -- 19.VII.99 -- size 1326
1696 ;
1697 ;       * bullets appear correctly (not INSIDE your ship)
1698 ;       + some enemies can take multiple hits (differs per class)
1699 ;       + all enemies fire bullets at random
1700 ;       + if you're hit by bullet/enemy, you'll lose one hitpoint
1701 ;
1702 ; 0.4.720 -- 20.VII.99 -- size 1406
1703 ;
1704 ;       # collision detection fixed and optimized (much faster now!)
1705 ;       + shell-icon added (YAS type)
1706 ;       * code optimizations, some data "compression"
1707 ;       * explosion looks better, and some vars removed/smaller
1708 ;       # enemies are removed when at left side (instead of becoming invisible)
1709 ;       + displays level number before each level begins
1710 ;
1711 ; 0.5.725 -- 25.VII.99 -- size 1703
1712 ;
1713 ;       * waits a sec at level display (in case of accidental keypress)
1714 ;       * moving enemies (move up+down)
1715 ;       # bullets removed correctly so they can be used again later
1716 ;       * first level made
1717 ;       # enemy weaponfire is fired from correct positions
1718 ;       + your ship explodes on impact with ships/bullets
1719 ;       * game over screen will be displayed just *after* your ship's gone
1720 ;       + frame counter onscreen
1721 ;
1722 ; 0.6.820 -- 20.IIX.99 -- size 2077
1723 ;
1724 ;       * play field increased to full screen instead of 3/4
1725 ;       + bottom eight lines used for score (etc) display
1726 ;       - no more solid levels, enemies are placed at random
1727 ;       + enemies appear every x turns (depends on level)
1728 ;       # fixed bullets so they don't disappear at 3/4 of the screen
1729 ;       * A LOT of optimizations both in speed and size!!
1730 ;       + enemy type, frequency, and number specified per level
1731 ;       + bottom score bar displays score, lives and icons (to be used later)
1732 ;       * smarter enemy handling (so enemies have different sizes)
1733 ;       + bottom bar divided from playing field by a horizontal line
1734 ;       + five levels (and five enemies) made
1735 ;       # game vars reset at start and game over
1736 ;       + NEMESIS LOGO displayed at startup!! (also, program grew 350bytes ):
1737 ;       + version/credits string displayed below logo: v0.6.820 by shiar (ICQ#)
1738 ;
1739 ; 0.6.825 -- 25.IIX.99 -- size 2085
1740 ;
1741 ;       # pointer to fifth ship corrected (ships in level 5 weren't displayed)
1742 ;       # calc doesn't crash anymore when game is continued after game over!!
1743 ;       + lives are decreased when ship is destroyed
1744 ;       # last eight pixels of divider line are shown correctly now
1745 ;
1746 ;  0.7.92 -- 02.IX .99 -- size 2303
1747 ;
1748 ;       + contrast is increased one level at startup (and restored on exit)
1749 ;       + invulnerable for a sec when you enter the game (inv-pickup later)
1750 ;       + when in invulnerable-mode, your ship look different!
1751 ;       + at the beginning you get three *hitpoints* so you can be hit 3 times
1752 ;       * bottomline icons are now 16 pixels wide and 7 pixels high!
1753 ;       + hitpoint icon added: displays nr. of hps left next to a nice picture
1754 ;       * maximum invulnerability-time is increased (can last upto 1024 frames)
1755 ;       + when invulnerable-mode has nearly expired, your ship flashes!
1756 ;       * again a lot of optimizations esp. in size ('bout 100 bytes)
1757 ;       + pickups! 10% chance a destroyed enemy changes into an armor-pickup
1758 ;       # code optimization caused some bullets to reappear as "fake" bullets
1759 ;       * pickups can't be destroyed by bullets (they pass right through it)
1760 ;
1761 ;  0.8.93 -- 03.IX .99 -- size 2433
1762 ;
1763 ;       + enemies move individually, not all at the same time!! Looks very nice
1764 ;       # titlescreen background is cleared (looked weird in Rascall and TI-OS)
1765 ;       + enemies fire at a ### rate instead of firing at will (too random)
1766 ;       # moving enemies don't move off the screen top/bottom (they wait there)
1767 ;       + seven playable levels going easy to hard (including moving enemies)
1768 ;       # xtraInfo data wasn't reset when a moving enemy entered the game
1769 ;       * longer delay when level is completed (NextLevel screen came too soon)
1770 ;
1771 ;  0.9.94 -- 04.IX .99 -- size 2693
1772 ;
1773 ;       # pickups no longer fire bullets like normal enemies
1774 ;       + <halt>s added so the game runs slower and looks better
1775 ;       + TORPEDOES!!! Bullets that fire downwards! Just like in Nemesis
1776 ;       * a pickup selects the next icon on bottom bar instead of increasing hp
1777 ;       + an icon can be taken by pressing F2. second icon selects torpedoes
1778 ;       + first icon increases armor, icon 3 and 4 are unused for now
1779 ;       * selecting an unused icon (3+4) resets pickups like icon 1 and 2
1780 ;       * when you're destroyed, you loose one life instead of going game over
1781 ;         you also loose all upgrades and pickups, but remain in the same level
1782 ;       * random is more randomized, no more "tricks" to fool the randomizer
1783 ;       # after game over the game is terminated instead of continuing+crashing
1784 ;       - no more armor to start with. you'll have to collect them on your own
1785 ;       * of course optimizations and a few tiny bug fixes (not important)
1786 ;       * increased the size of the enemy bullets so they're better to see
1787
1788
1789 ;        + added        - removed       * changed       # bug fixed