version 0.6: logo, bottom stats bar, 5 random levels
[nemesis.git] / nemesis.z80
1         .include "asm86.h"
2         .include "ti86asm.inc"
3
4         .org _asm_exec_ram
5
6         nop
7         jp  Start
8         .dw $0001
9         .dw Title
10         .dw spr_ship
11 Title:  .db "Nemesis v0.6.820 by Shiar",0
12 Start:  jr init
13
14 just_fired      = $c0f9         ;byte
15 temp1           = $c100         ;word
16
17 ;---------------------- init --------------------------------------------------
18
19 init:
20         call _runindicoff
21
22 ;---------------------- main menu ---------------------------------------------
23
24 LogoPut:
25         ld hl,logo_nemesis      ;from...
26         ld de,$FC00+16          ;...to one line from top
27         ld a,19                 ;19 rows
28 LogoLoop:
29         ld bc,16                ;set screen width
30         ldir                    ;display one line
31         dec a                   ;decrease line-counter
32         jr nz,LogoLoop          ;repeat when counter is not yet zero
33
34 menutext:
35         ld  hl,$1608            ;just below logo
36         ld  (_penCol),hl
37         ld  hl,txt_about        ;display "by Shiar (ICQ#43840958)"
38         call _vputs
39
40         ld  hl,$0705            ;located one row above bottom
41         ld  (_curRow),hl        ;go there
42         ld  hl,txt_1player      ;display "ONE PLAYER"
43         call _puts
44         ld  hl,$0706            ;below oneplayer text
45         ld  (_curRow),hl
46         ld  hl,txt_2players     ;display "TWO PLAYERS"
47         call _puts
48
49         call _getkey            ;wait for keypress
50         call New_level          ;prepare level
51
52 ;------------------------------------------------------------------------------
53 ;---------------------- game loop ---------------------------------------------
54 ;------------------------------------------------------------------------------
55
56 game_main_loop:
57         ld  hl,timer            ;update time
58         inc (hl)
59
60 Clear_screen:
61         xor a                   ;empty bitmask
62         ld  hl,GRAPH_MEM        ;screen location (top left)
63         ld  b,$E0               ;loop 0E0h = 224 times = 256-32 for score-bar)
64 clearloop:
65         ld  (hl),a              ;clear four times (total = 224*4 = 896 bytes)
66         inc hl
67         ld  (hl),a
68         inc hl
69         ld  (hl),a
70         inc hl
71         ld  (hl),a
72         inc hl
73         djnz clearloop          ;repeat 224x
74
75 check_exitkey:
76         ld  a,%00111111         ;<exit> pressed?
77         out (1),a
78         nop \ nop
79         in  a,(1)
80         bit 6,a
81         jr  z,quit              ;yes: quit game
82
83 game_stuff:
84         call Level_event        ;insert enemies
85         call Handle_Ship        ;move you
86         call Fire_bullet        ;check for fire
87         call Handle_enemies     ;move enemies
88         call Handle_bullets     ;move your bullets
89         call Enemy_bullets      ;move enemy bullets
90         call Enemies_hit        ;check for collision with enemies
91
92         call Display_Screen     ;display all
93         halt \ halt             ;delay
94         jr   game_main_loop     ;loop
95
96 quit:   ret
97
98 ;---------------------- display -----------------------------------------------
99
100 Display_Screen:
101         ld  hl,GRAPH_MEM        ;from storage (top left)
102         ld  de,$fc00            ;to screen (top left)
103         ld  a,56                ;display height = 64 bytes (minus 8 for bar)
104 displayloop:
105         ld  bc,16               ;display width = 16 bytes (16*8bits=256pixels)
106         ldir                    ;16x de >> hl
107         dec a                   ;next line
108         jr  nz,displayloop      ;loop 64x
109
110         ld  hl,$3a6b            ;Display Score
111         ld  (_penCol),hl
112         ld  hl,(timer)
113         ld  h,0
114         jp  _D_HL_DECI
115         ret
116
117 ;------------------------- handle ship ----------------------------------------
118
119 Handle_Ship:
120         ld  a,(your_occ)
121         or  a
122         jr  z,ok                ;0 = normal stat
123
124         inc a                   ;next (explosion)frame
125         ld  (your_occ),a        ;save
126
127         cp  34                  ;last explosion frame?
128         jr  c,exploding_you     ;not yet: display explosion
129         cp  40                  ;delay finished?
130         jp  z,game_over         ;yes = game over
131         ret                     ;don't display anything
132
133 ok:
134         ld  a,%01111110
135         out (1),a
136         nop \ nop
137         in  a,(1)
138         ld  hl,y
139         rra
140         ld  b,a
141
142         jr  c,no_down
143         ld  a,(hl)
144         inc a
145         cp  50                  ;56-6 = bottom of screen
146         jr  z,no_down
147         ld  (hl),a
148 no_down:
149         dec hl
150         rr  b
151         jr  c,no_left
152         ld  a,(hl)
153         sub 1                   ;<dec 1> doesn't affect c-flag
154         jr  c,no_left           ;-1 = left side
155         ld  (hl),a
156 no_left:
157         rr b   
158         jr  c,no_right
159         ld  a,(hl)
160         inc a
161         cp  122                 ;128-6 = right side
162         jr  z,no_right
163         ld  (hl),a
164 no_right:
165         ld d,(hl)
166         inc hl
167         rr  b
168         jr  c,no_up
169         ld  a,(hl)
170         sub 1                   ;<dec a> doesn't affect carry-flag
171         jr  c,no_up             ;-1 = top of screen
172         ld  (hl),a
173 no_up:  ld  ix,spr_ship01
174
175 display_common:
176         ld  e,(hl)
177         jp  drw_spr             ;ret
178
179 exploding_you:
180         srl a                   ;half the framerate
181         dec a                   ;first frame is 1>inc>srl>dec = 0
182         ld  hl,x-1
183
184 explosion_stuff:
185         rra
186         add a,a
187         add a,a
188         add a,a
189         ld  c,a
190         ld  b,0
191         ld  ix,spr_explosion
192         add ix,bc
193         inc hl
194         ld  d,(hl)
195         inc hl
196         jr  display_common
197
198 damage_you:
199         ld  a,1                 ;set to explode (1st frame)
200         ld  (your_occ),a
201         ret
202
203 ;------------------------- fire bullet ----------------------------------------
204
205 Fire_bullet:
206         ld  a,%00111111
207         out (1),a
208         ld  a,(your_occ)
209         or  a
210         ret nz                  ;return if not normal stat
211         ld  hl,just_fired
212         in  a,(1)
213         bit 4,a
214         jr  z,fire              ;fire pressed?
215         ld  (hl),0              ;not fired
216         ret
217
218 fire:   ld  a,(hl)
219         or  a                   ;can't fire when 1
220         ret nz
221         ld  (hl),1              ;just fired
222
223         ld  hl,ybullets
224         ld  de,3
225         ld  b,10
226 find_ybullet:
227         ld  a,(hl)
228         or  a
229         jr  z,found_ybullet     ;0 = no bullet here
230         add hl,de
231         djnz find_ybullet       ;look next bullet
232         ret
233
234 found_ybullet:
235         ld  (hl),1              ;use bullet
236         inc hl
237         ld  a,(x)
238         add a,5
239         ld  (hl),a              ;set x
240         ld  a,(y)
241         add a,2
242         inc hl
243         ld  (hl),a              ;set y
244         ret
245
246 ;------------------------ handle bullets --------------------------------------
247
248 remove_bullet:
249         dec hl
250         ld  (hl),0              ;dump this bullet!
251         ret
252
253 Handle_bullets:
254         ld  hl,ybullets
255         ld  b,10
256 scan_bullets:
257         push bc
258         push hl
259         ld  (temp1),hl
260         ld  a,(hl)
261         inc hl
262         dec a
263         call z,bullet_type1
264         pop hl
265         pop bc
266         ld  de,3
267         add hl,de
268         djnz scan_bullets
269         ret
270
271 bullet_type1:
272         ld  a,(hl)              ;d = X
273         inc a                   ;move right
274         cp  121                 ;off screen? (x=127-5-1)
275         jr  z,remove_bullet
276         inc a                   ;move right
277         cp  121                 ;off screen?
278         jr  z,remove_bullet
279         ld  (hl),a              ;save new pos.
280         ld  d,a
281         inc hl
282         ld  e,(hl)              ;e = Y
283         ld  ix,spr_bullet01
284         push de
285         call drw_spr            ;display bullet
286         pop de
287         ld  b,nrenemies
288         ld  hl,enemies
289
290 hit_enemies:                    ;Hits with normal enemies
291         push hl
292
293         ld  a,(hl)
294         and %00000010
295         jr  z,nohit             ;no hit when enemy_occ <> 2/3
296
297         inc hl
298         inc hl
299         ld  a,(hl)              ;check x
300         sub d
301         add a,5
302         jp  m,nohit
303         cp  8
304         jr  nc,nohit
305
306         inc hl
307         ld  a,(hl)              ;check y
308         sub e
309         add a,5
310         jp  m,nohit
311         cp  10
312         jr  nc,nohit
313
314         xor a
315         push hl
316         ld  hl,(temp1)
317         ld  (hl),a              ;remove bullet
318         pop hl
319
320         dec hl
321         dec hl
322         dec hl
323         ld  a,(hl)              ;occ
324         ld  b,a                 ;push occ
325         and %11111100           ;occ/4 = HP left        ;<srl a\srl a
326         jr  nz,hpleft           ;not zero -> jump
327         ld  (hl),%01            ;set to explode
328         inc hl
329         ld  b,(hl)              ;save enemy type
330         ld  (hl),a              ;explosionFrame 0
331
332         pop hl
333         ret
334
335 hpleft:
336         ld  a,b                 ;pop occ
337         sub %00000100           ;decrease HP by one
338         ld  (hl),a              ;save
339         pop hl
340         ret
341
342 nohit:  pop hl
343         inc hl
344         inc hl
345         inc hl
346         inc hl
347         djnz hit_enemies        ;check next enemy
348         ret
349
350 ;--------------------------- level events -------------------------------------
351
352 Level_event:
353         ld  hl,nextevent        ;time to next event     <ld  a,(nextevent)
354         dec (hl)                ;decrease counter       <dec a
355         ld  a,(hl)              ;look at counter        <ld  (nextevent),a
356         or  a                   ;has it reached zero?
357         ret nz                  ;nope: get outta here!
358
359         ld  a,(eventtime)       ;enemy frequency (lvl)
360         ld  (nextevent),a       ;set time to next event
361         ld  hl,eventleft
362         dec (hl)                ;update enemy-counter
363
364         ld  a,(hl)              ;look at counter
365         or  a                   ;has it reached 0?
366         jp  z,Next_level        ;yes: level finished
367         dec a                   ;has it reached 1?
368         jr  nz,do_event         ;nope: wait for enemies to leave
369         inc hl                  ;nextevent located behind eventleft
370         ld  (hl),109            ;set delay
371         ret                     ;don't place any more enemies
372
373 do_event:
374         ld  de,enemies-4
375 chk_noenemy:
376         inc de
377         inc de
378         inc de
379         inc de
380         ld  a,(de)
381         or  a                   ;0 = no enemy present
382         jr  nz,chk_noenemy
383
384         ld  a,(eventenemy)      ;enemy type to place (lvl)
385         ld  hl,enemy01          ;enemy 1 specs
386         ld  c,a
387         ld  b,0                 ;bc = enemy nr.
388         add hl,bc               ;add 2*bc
389         add hl,bc               ;hl = enemy specs
390         ld  a,(hl)              ;load hitpoints+occ of this enemy class
391         ld  (de),a              ;occ
392
393         inc hl
394         inc de
395         ld  a,(hl)              ;load movement+type of this enemy class
396         ld  (de),a              ;enemy type
397
398         inc de                  ;_________
399         ld  a,122               ;appear at right edge of screen (128-6)
400         ld  (de),a              ;= x-position
401         inc de                  ;_________
402         ld  a,51                ;random number <51
403         call Random             ;create!
404         ld  (de),a              ;= y-position
405         ret
406
407 ;--------------------------- enemy fires --------------------------------------
408
409 Enemy_fires:                    ;de = x,y
410         dec d
411         dec d                   ;d = x-2
412         inc e                   ;e = y+1
413
414         ld  b,10
415         ld  hl,ebullets
416 find_ebullet:
417         ld  a,(hl)
418         or  a
419         jr  z,found_ebullet     ;0 = not used
420         inc hl
421         inc hl
422         inc hl
423         djnz find_ebullet       ;look next bullet
424         ret
425
426 found_ebullet:
427         ld  (hl),1              ;use bullet
428         inc hl
429         ld  (hl),d              ;set x-pos
430         inc hl
431         ld  (hl),e              ;set y-pos
432         ret         
433
434 ;----------------------------- enemy bullets ----------------------------------
435
436 Enemy_bullets:
437         ld  hl,ebullets
438         ld  b,10
439 handle_bullet:
440         push bc
441         push hl
442         ld  a,(hl)
443         or  a
444         jr  nz,enemy_bullet
445 next_bullet:
446         pop hl
447         pop bc
448         inc hl
449         inc hl
450         inc hl
451         djnz handle_bullet
452         ret
453
454 enemy_bullet:
455         inc hl
456         ld  a,(hl)              ;bullet x
457         dec a
458         jp  m,remove_ebullet    ;off screen?
459         jr  z,remove_ebullet    ;"
460         dec a                   ;move left
461         ld  (hl),a
462         ld  d,a                 ;d=x
463         inc hl
464         ld  e,(hl)              ;e=y
465         ld  ix,spr_bullet11     ;display enemy bullet
466         call drw_spr
467
468         ld  a,(your_occ)
469         or  a
470         jr  nz,next_bullet      ;0 = you're normal
471
472         pop hl
473         push hl
474         inc hl                  ;check x
475         ld  a,(x)
476         sub (hl)
477         add a,6
478         jp  m,next_bullet
479         cp  9
480         jr  nc,next_bullet
481
482         inc hl                  ;check y
483         ld  a,(y)
484         sub (hl)
485         add a,6
486         jp  m,next_bullet
487         cp  9
488         jr  nc,next_bullet
489
490         call damage_you         ;HIT!!
491 remove_ebullet:
492         dec hl
493         ld   (hl),0             ;bullet > unused
494         jr   next_bullet
495
496 ;--------------------------- handle enemies -----------------------------------
497
498 Handle_enemies:
499         ld  hl,enemies
500         ld  b,nrenemies         ;handle all enemies
501
502 handle_enemy:
503         push bc
504         push hl
505
506         ld  a,(hl)
507         and %00000011
508         jr  z,next_enemy        ;occ "no enemy" 0
509         dec a
510         jr  z,exploding_enemy   ;occ "exploding" 1
511         ld  b,1
512         dec a
513         jr  z,normal_enemy      ;occ "normal" 2
514
515 moving_enemy:                   ;occ "moving" 3
516         ld  b,0
517
518 normal_enemy:
519         inc hl
520         push hl
521
522         ld  e,(hl)              ;e = enemy type
523         ld  d,0                 ;de = e
524         ld  hl,sprites          ;hl = @sprites offset-table
525         add hl,de               ;points to offset of current enemy offset
526         ld  e,(hl)              ;de = @enemy offset
527
528         ld  ix,spr_enemy01      ;first enemy sprite
529         add ix,de               ;add offset for current enemy
530         pop hl
531
532         inc hl
533         ld  a,(hl)              ;x
534         dec a                   ;move left
535         jp  m,remove_enemy      ;off screen
536         jr  z,remove_enemy      ;"
537         ld  d,a
538
539         inc hl
540         ld  e,(hl)              ;y
541         ld  a,b                 ;%xxx00001=moving -0=normal
542         dec a
543         jr  z,ymove_done        ;skip y-move
544
545 ;       srl a
546 ;       ld  b,a                 ;b = %0xxx0000 (move stat)
547         ld  a,(timer)
548         and %00010000           ;switches 0<>1 every 16 turns
549 ;       add a,b                 ;a = new move stat
550 ;       add a,a
551 ;       ld  b,a                 ;b = %xxx00000 (new move stat*2)
552
553 ;       dec hl \ dec hl
554 ;       ld  a,(hl)              ;type
555 ;       and %00011111           ;reset move-type
556 ;       add a,b                 ;set new move-type
557 ;       ld  (hl),a
558 ;       inc hl \ inc hl         ;@y
559
560 ;       and %00100000
561         jr  z,movedown
562 moveup: dec (hl)                ;decrease y-pos
563         jr ymove_done
564 movedown:
565         inc (hl)                ;increase y-pos
566
567 ymove_done:
568         dec hl                  ;@x
569         ld  (hl),d              ;store new x
570
571         push de                 ;save registers
572         call drw_spr            ;display sprite @ix
573         pop  de                 ;restore (destroyed by drw_spr)
574
575         ld   a,$ff              ;fire frequency
576         call Random             ;random value < a
577         dec  a                  ;fire if 1
578         call z,Enemy_fires      ;fires bullet
579         jr   next_enemy         ;finished
580
581 remove_enemy:
582         pop hl
583         ld  (hl),$0000          ;bye bye enemy
584         push hl
585 next_enemy:
586         pop hl
587         ld  bc,$0004
588         add hl,bc
589         pop bc
590         djnz handle_enemy
591         ret
592
593 exploding_enemy:
594         inc  hl
595         push hl
596         ld   a,(hl)
597         call explosion_stuff    ;display explosion
598         pop  hl
599
600         ld  a,(hl)
601         cp  15
602         jr  z,remove_enemy      ;remove when at last frame
603         inc a
604         ld  (hl),a              ;next frame
605         jr  next_enemy
606
607 ;--------------------------- check collision ----------------------------------
608
609 Enemies_hit:
610         ld  a,(your_occ)
611         or  a                   ;0 = you're normal
612         ret nz
613
614         ld  de,(x)              ;e = X, d = Y
615         ld  hl,enemies
616         ld  b,nrenemies         ;check all 20 enemies
617 check_collision:
618         push hl
619         ld  a,(hl)
620         and %00000010
621         jr  z,check_next        ;2 or 3 = ok
622
623         inc hl
624         inc hl
625         ld  a,(hl)              ;check x match
626         sub e
627         add a,6
628         jp  m,check_next
629         cp  12
630         jr  nc,check_next
631
632         inc hl
633         ld  a,(hl)              ;check y match
634         sub d
635         add a,6
636         jp  m,check_next
637         cp  12
638         jr  nc,check_next
639
640         dec hl
641         dec hl
642         xor a
643         ld  (hl),a              ;explosionFrame 0
644         dec hl
645         inc a
646         ld  (hl),a              ;set to explode
647         call damage_you         ;auch!
648
649 check_next:
650         pop hl
651         inc hl
652         inc hl
653         inc hl
654         inc hl
655         djnz check_collision
656         ret
657
658 ;--------------------------- game over ----------------------------------------
659
660 game_over:
661         call _clrLCD            ;clear screen
662         ld  hl,$0603
663         ld  (_curRow),hl        ;center
664         ld  hl,txt_gameover
665         call _puts              ;display "GAME OVER"
666
667         ld  b,$20
668 wait2:  halt \ halt
669         djnz wait2              ;delay
670         call _getkey            ;wait for keypress
671
672 ;--------------------------- new game -----------------------------------------
673
674 New_level:
675         xor a                   ;a=0
676         ld  hl,x                ;begin position x=...
677         ld  (hl),a              ;...=a=0=left
678         inc hl                  ;y=...
679         ld  (hl),24             ;...=24=middle
680         ld  (level),a           ;reset level nr
681         ld  (score),a           ;reset score
682         ld  hl,level01-3        ;set level pointer to level#1
683         ld  (levelp),hl         ;reset level pointer
684
685 ;--------------------------- next level ---------------------------------------
686
687 Next_level:
688         ld  hl,level
689         inc (hl)                ;increase level nr.
690         ld  a,80
691         ld  (nextevent),a       ;time to first enemy appearance
692
693         ld  hl,(levelp)         ;level pointer
694         inc hl
695         inc hl
696         inc hl                  ;update to point to next level
697         ld  (levelp),hl         ;save
698
699         ld  a,(hl)              ;load new level-enemy type
700         ld  (eventenemy),a      ;set level-enemy
701         inc hl
702         ld  a,(hl)              ;load new appearance-time
703         ld  (eventtime),a       ;set
704         inc hl
705         ld  a,(hl)              ;load nr of enemies in this level
706         ld  (eventleft),a       ;set nr of events left
707
708         xor a
709         ld  (timer),a           ;reset time
710
711 ;--------------------------- setup game ---------------------------------------
712
713 game_setup:
714         call _clrLCD            ;clear screen
715         ld a,%10111011
716         ld  hl,$fc00            ;screen location (top left)
717         ld  b,0                 ;b = 0 (loop 0-1 = 0FFh = 256 times)
718 clearloop2:
719         inc a
720         ld  (hl),a              ;clear four times (total = 256*4 = 1024 bytes)
721         inc hl
722         ld  (hl),a
723         inc hl
724         xor $ff
725         ld  (hl),a
726         inc hl
727         ld  (hl),a
728         inc hl
729         xor $ff
730         djnz clearloop2         ;repeat 256x
731
732         ld  hl,$0703
733         ld  (_curRow),hl        ;center
734         ld  hl,txt_level
735         call _puts              ;display "LEVEL "
736
737         ld  a,(level)
738         ld  l,a
739         ld  h,$00
740
741         call UNPACK_HL
742         add a,'0'
743         ld  b,a
744         call UNPACK_HL
745         add a,'0'
746         call _putc              ;display second digit
747         ld  a,b
748         call _putmap            ;display first digit
749
750         ld  hl,$0904
751         ld  (_curRow),hl        ;display lives left below level nr
752         ld  hl,txt_lives        ;bar text: "Lx0"...
753         ld  a,(lives)           ;lives left
754         add a,'0'               ;make value
755         ld  (txt_lives+3),a     ;add to text
756         call _puts              ;display the string
757
758         ld  b,$20
759 wait:   halt \ halt
760         djnz wait               ;delay
761         call _getkey            ;wait for keypress
762
763         ld  ix,spr_icon00       ;display icons
764         ld  de,$1802            ;bottom left
765         call drw_spr
766         ld  ix,spr_icon00       ;display icons
767         ld  de,$2002            ;bottom left
768         call drw_spr
769         ld  ix,spr_icon00       ;display icons
770         ld  de,$2802            ;bottom left
771         call drw_spr
772         ld  ix,spr_icon00       ;display icons
773         ld  de,$3002            ;bottom left
774         call drw_spr
775         ld  ix,spr_icon00       ;display icons
776         ld  de,$3802            ;bottom left
777         call drw_spr
778
779         ld  hl,GRAPH_MEM        ;from storage (top left)
780         ld  de,$fc00+(56*16)    ;to screen (top left)
781         ld  a,8                 ;display height = 64 bytes (minus 8 for bar)
782 displayloop3:
783         ld  bc,16               ;display width = 16 bytes (16*8bits=256pixels)
784         ldir                    ;16x de >> hl
785         dec a                   ;next line
786         jr  nz,displayloop3     ;loop 8x
787
788         ld  hl,$3a00            ;display Lives
789         ld  (_penCol),hl        ;bottom left
790         ld  hl,savestr+2
791         ld  (hl),'L'
792         inc hl
793         ld  (hl),'x'
794         inc hl
795
796         ld  a,(lives)           ;nr of lives in a
797         add a,'0'               ;make digit
798         ld  (hl),a
799         dec hl \ dec hl
800         call _vputs             ;display on screen
801
802         ld  hl,$fc00+(16*57)    ;56 rows down = eight rows from bottom
803         ld  b,15                ;draw 16x (screen width)
804 drawline:
805         ld  a,%11111111         ;horizontal line mask
806         ld  (hl),a              ;draw one piece of the divider-line
807         inc hl                  ;move right (8 pixels = 1 byte)
808         djnz drawline           ;repeat (16bytes * 8pixels =128= screen width)
809
810                                         ;ret
811 ;--------------------------- exit ---------------------------------------------
812
813 exit_game:
814         ret
815
816 ;--------------------------- putsprite ----------------------------------------
817 ;--------------------------- de =(X,Y) ----------------------------------------
818
819 offsets_table:
820         .db 128,64,32,16,%1000,%0100,%0010,%0001
821 drw_spr:
822         ld  a,d                 ;a = X
823         and %00000111           ;a = X mod 8 = bit nr. to mask
824         ld  hl,offsets_table    ;pixel mask table
825         ld  c,a                 ;bit nr.
826         ld  b,0                 ;word
827         add hl,bc               ;add to table
828         ld  a,(hl)              ;a = pixel mask
829         ld  (_smc1+1),a         ;alter pixel mask
830         ld  (_smc1+1),a
831
832         ld  hl,GRAPH_MEM        ;save-location
833         ld  a,e                 ;y-coord
834         add a,a                 ;y*2
835         add a,a                 ;y*4
836         add a,a                 ;y*8
837  ;b=0
838         rl  b
839         add a,a                 ;y*16 (width of screen)
840         rl  b
841         srl d                   ;d/2
842         srl d                   ;d/4
843         srl d                   ;d/8 (8 bits in byte) ** c is set when overflow
844         add a,d                 ;a = (Y*16+X/8) mod 256
845         jr  nc,_n1              ;jump if no carry = no overflow = a<=255
846         inc b                   ;a>255 so increase bc by 256
847 _n1:    ld  c,a                 ;c = (Y*16+X/8) mod 256
848         add hl,bc               ;bc = Y*16+X/8
849                 ;optimize tip: reverse hl <-> bc (??)
850           
851         ld  d,(ix)
852         ld  b,(ix+1)
853 _oloop: push bc                 ;Save # of rows
854         push hl                 ;Save screen address
855         ld  b,d                 ;Load width
856         ld  c,(ix+2)            ;Load one line of image
857         inc ix
858 _smc1:  ld  a,1                 ;Load pixel mask
859 _iloop: sla c                   ;Test leftmost pixel
860         jr  nc,_noplot          ;See if a plot is needed
861         ld  e,a                 ;OR pixel with screen
862         or  (hl)
863         ld  (hl),a
864         ld  a,e
865 _noplot:rrca
866         jr  nc,_notedge         ;Test if edge of byte reached
867         inc hl                  ;Go to next byte
868 _notedge:
869         djnz _iloop
870         pop hl                  ;Restore address
871         ld  bc,16               ;Go to next line
872         add hl,bc
873         pop bc                  ;Restore data
874         djnz _oloop
875         ret
876
877 ;---------------------- random ------------------------------------------------
878
879 Random:                ; Creates a random number 0 <= x < A
880         push bc
881         push de
882         push hl
883         ld   b,a
884         ld   a,r
885         add  a,a
886         ld   hl,0
887         ld   d,0
888         ld   e,a
889 RMul:
890         add  hl,de
891         djnz RMul
892         ld   a,h
893         pop  hl
894         pop  de
895         pop  bc
896         ret
897
898 ;---------------------- display 5digit number ---------------------------------
899
900 _D_HL_DECI:
901         push bc                 ;save bc
902         ld   de,savestr+4       ;savenr saves number string
903         ld   b,5                ;five digits
904 ldhld:  call UNPACK_HL          ;one digit of hl
905         add  a,'0'              ;make number
906         ld   (de),a             ;save into savenr
907         dec  de                 ;point to next digit
908         djnz ldhld              ;repeat for all digits
909 dis:    ld   hl,savestr
910         call _vputs
911         pop  bc
912         ret
913
914 savestr:
915         .db "PAD98",0
916
917
918 ;------------------------------------------------------------------------------
919 ;------------------------------- sprites --------------------------------------
920 ;------------------------------------------------------------------------------
921
922 spr_ship:
923         .db 9,1         ;ship icon
924         .db %11100000   ; ███
925         .db %11111000   ; █████
926         .db %00111110   ;   █████
927         .db %11111001   ; █████  █
928         .db %11111001   ; █████  █
929         .db %11111001   ; █████  █
930         .db %00111110   ;   █████
931         .db %11111000   ; █████
932         .db %11100000   ; ███
933
934 spr_ship01:
935         .db 7,7         ;ship alpha class
936         .db %01111000   ;  ████
937         .db %11100000   ; ███
938         .db %11111100   ; ██████
939         .db %11110010   ; ████  █
940         .db %11111100   ; ██████
941         .db %11100000   ; ███
942         .db %01111000   ;  ████
943 spr_ship02:
944         .db 7,7         ;ship beta class
945         .db %11000000   ; ██
946         .db %11110000   ; ████
947         .db %01111100   ;  █████
948         .db %01110010   ;  ███  █
949         .db %01111100   ;  █████
950         .db %11110000   ; ████
951         .db %11000000   ; ██
952
953 spr_bullet01:
954         .db 5,3         ;your bullets
955         .db %00110000   ;   ░▒▓█▒
956         .db %11111000   ; ░▒▓████▒
957         .db %00110000   ;   ░▒▓█▒
958 spr_bullet02:
959         .db 5,3         ;your bullets
960         .db %11110000   ; ░▒▓███▒
961         .db %11111000   ; ░▒▓████▒
962         .db %11110000   ; ░▒▓███▒
963
964 spr_bullet11:
965         .db 3,3         ;enemy bullets
966         .db %01000000   ;  ▒▓▒░
967         .db %11100000   ; ▒██▓▒░
968         .db %01000000   ;  ▒▓▒░
969
970 ;---------------------------------------- explosion -------------------------------------------
971
972 spr_explosion:                               
973         .db 8,6         ;1
974         .db %00000000
975         .db %00011100   ;    ███
976         .db %00111110   ;   █████
977         .db %01010110   ;  █ █ ██
978         .db %00111000   ;   ███
979         .db %00000000
980
981         .db 8,6         ;2
982         .db %00110000   ;   ██
983         .db %01001110   ;  █ ▒███
984         .db %10111110   ; █ █████
985         .db %01001111   ;  █ ▒████
986         .db %00111000   ;   ███
987         .db %00011010   ;    ██ █
988
989         .db 8,6         ;3
990         .db %10110011   ; █ ██  ██
991         .db %01001110   ;  █  ███
992         .db %10110101   ; █ ██▒█▒█
993         .db %01000101   ;  █  ▒█▒█
994         .db %00111110   ;   █████
995         .db %11011010   ; ██ ██ █
996
997         .db 8,6         ;4
998         .db %00101010   ; ▒ █▒█ █▒
999         .db %01000110   ;  █  ▒██
1000         .db %10110101   ; █ ██ █ █
1001         .db %01100110   ;  ██  ██▒
1002         .db %00111100   ;   ████▒
1003         .db %01011001   ; ▒█ ██ ▒█
1004
1005         .db 8,6         ;5
1006         .db %01000001   ;  █▒ ▒ ▒█
1007         .db %00100101   ;  ▒█  █▒█
1008         .db %00010100   ; ▒ ▒█ █ ▒
1009         .db %01000100   ;  █▒  █
1010         .db %00010010   ;   ▒█▒▒█
1011         .db %10011010   ; █▒ ██ █▒
1012
1013         .db 8,6         ;6
1014         .db %01000100   ;  █   █ ▒
1015         .db %00100000   ;   ▒█ ▒ ▒
1016         .db %00000001   ;    ▒ ▒ █
1017         .db %01000100   ;  █   █
1018         .db %00100010   ;   █▒  █
1019         .db %01001000   ; ▒█ ▒█ ▒
1020
1021         .db 8,6         ;7
1022         .db %00001000   ;  ▒  █▒
1023         .db %11000010   ; ██ ▒  █
1024         .db %00000000   ;        ▒
1025         .db %00100000   ;  ▒█  ▒
1026         .db %00000001   ;   ▒   ▒█
1027         .db %00110000   ;  ▒██▒
1028
1029         .db 8,6         ;8
1030         .db %00000100   ;     ▒█
1031         .db %00000000   ; ▒▒    ▒
1032         .db %01000000   ;  █
1033         .db %00000000   ;   ▒
1034         .db %00000010   ;       █▒
1035         .db %00100100   ;   █▒ █
1036
1037 ;--------------------------------------- bar -----------------------------------
1038
1039 spr_icon00:
1040         .db 8,7
1041         .db %10101010   ; █ █ █ █
1042         .db %11010101   ; ██ █ █ █
1043         .db %10101010   ; █ █ █ █
1044         .db %11010101   ; ██ █ █ █
1045         .db %10101010   ; █ █ █ █
1046         .db %11010101   ; ██ █ █ █
1047         .db %10101010   ; █ █ █ █
1048 spr_icon01:
1049         .db 8,7
1050         .db %10000000   ; █.......
1051         .db %10000000   ; █
1052         .db %10000000   ; █
1053         .db %10000000   ; █
1054         .db %10000000   ; █
1055         .db %10000000   ; █
1056         .db %10000000   ; █
1057 spr_icon02:
1058         .db 8,7
1059         .db %10000000   ; █
1060         .db %10000000   ; █
1061         .db %10000000   ; █
1062         .db %10000000   ; █
1063         .db %10000000   ; █
1064         .db %10000000   ; █
1065         .db %10000000   ; █
1066
1067 ;---------------------------- texts -------------------------------------------
1068
1069 txt_about:      .db "v0.6.820 ","by Shiar  "
1070                 .db "(ICQ#43840958)",0
1071 txt_1player:    .db "1 PLAYER",0
1072 txt_2players:   .db "2 PLAYERS",0
1073 txt_level:      .db "LEVEL ",0
1074 txt_gameover:   .db "GAME OVER!",0
1075 txt_lives:      .db "Lx0?",0
1076
1077 ;---------------------------- save data ---------------------------------------
1078
1079 stored_data_start:
1080
1081 timer           .db $00                 ;frame counter
1082 level           .db $00                 ;level number
1083 levelp          .dw level01             ;pointer to level data
1084
1085 eventenemy      .db $02                 ;enemy type
1086 eventtime       .db $15                 ;enemy frequency
1087 eventleft       .db $00                 ;nr. of enemies still to come
1088 nextevent       .db $50                 ;time to next event
1089
1090 score           .dw $0000
1091
1092 your_occ        .db $00                 ;0=normal 1..16=exploding
1093 lives           .dw $0003       ;unused
1094 x               .db $16                 ;x-pos
1095 y               .db $46                 ;think about it..
1096 hp              .db $00                 ;hitpoints left
1097
1098 ybullets        .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0       ;10 x (state,x,y)
1099 ebullets        .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0       ;10 x (state,x,y)
1100
1101 nrenemies       = 20
1102 enemies         .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1103                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1104                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1105                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1106
1107                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1108                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1109                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1110                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1111
1112 ; %111111 (HP left) 11 (00=no enemy 01=exploding 10=normal 11=moving)
1113 ; %11111111 (ship type or explosion frame)  %11111111 (x) %11111111 (y)
1114
1115 ;---------------------------- enemy data --------------------------------------
1116
1117 sprites:
1118         .db $00
1119         .db spr_enemy02-spr_enemy01
1120         .db spr_enemy03-spr_enemy01
1121         .db spr_enemy04-spr_enemy01
1122
1123 spr_enemy01:
1124         .db 6,6         ;enemy type one
1125         .db %00111100   ;   ████
1126         .db %01110000   ;  ███
1127         .db %11110000   ; ████
1128         .db %11110000   ; ████
1129         .db %01110000   ;  ███
1130         .db %00111100   ;   ████
1131 spr_enemy02:
1132         .db 8,7         ;enemy type two
1133         .db %00111111   ;    █████
1134         .db %01111000   ;  ████
1135         .db %11111100   ; ██████
1136         .db %11111110   ; ███████
1137         .db %11111100   ; ██████
1138         .db %01111000   ;  ████
1139         .db %00111111   ;    █████
1140 spr_enemy03:
1141         .db 6,6         ;enemy type three
1142         .db %01111100   ;  █████
1143         .db %11110000   ; ████
1144         .db %11111000   ; █████
1145         .db %11111000   ; █████
1146         .db %11110000   ; ████
1147         .db %01111100   ;  █████
1148 spr_enemy04:
1149         .db 6,6         ;enemy type four
1150         .db %00111000   ;   ███
1151         .db %01111100   ;  █████
1152         .db %11111000   ; █████
1153         .db %11111000   ; █████
1154         .db %01111100   ;  █████
1155         .db %00111000   ;   ███
1156 spr_enemy05:
1157         .db 7,6         ;enemy type four
1158         .db %00011110   ;    ████
1159         .db %01111110   ;  ██████
1160         .db %11111100   ; ██████
1161         .db %11111100   ; ██████
1162         .db %01111110   ;  ██████
1163         .db %00011110   ;    ████
1164
1165 enemy01:                                ;HP:1  move:- fire:-
1166         .db %00000010,%00000000                 ;first two enemy bytes
1167 enemy02:                                ;HP:1  move:1 fire:1.5%
1168         .db %00000010,%00000001
1169 enemy03:                                ;HP:2  move:- fire:3%
1170         .db %00000110,%00000010
1171 enemy04:                                ;HP:5  move:- fire:6%
1172         .db %00010010,%00000011
1173 enemy05:                                ;HP:10 move:- fire:25%
1174         .db %00100111,%00000100
1175
1176 ;----------------------------- level info -------------------------------------
1177
1178 level01:
1179         .db $00,$15,$30                 ;enemy nr ; enemy frequency ; next lvl
1180 level02:
1181         .db $01,$11,$4c
1182 level03:
1183         .db $02,$19,$40
1184 level04:
1185         .db $03,$0f,$50
1186 level05:
1187         .db $04,$2e,$3e
1188
1189 ;----------------------------- logo -------------------------------------------
1190
1191 logo_nemesis:
1192 .db %11111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00001011,%11111111,%11111111,%11111111,%11111000
1193 .db %01111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00011011,%11111111,%11111111,%11111111,%11110000
1194 .db %00111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00111011,%11111111,%11111111,%11111111,%11100000
1195 .db %00011111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%01111011,%11111111,%11111111,%11111111,%11000000
1196 .db %00000000,%00000000,%00000001,%00011110,%00010000,%00000000,%10000001,%00011110,%00010000,%000000001,%00000000,%00001000,%01000000,%00000000,%00000000,%00000000
1197 .db %00000000,%00000000,%00000011,%00011110,%00110000,%00000001,%10000011,%00011110,%00110000,%000000011,%00000000,%00011000,%11000000,%00000000,%00000000,%00000000
1198 .db %00000000,%00000000,%00000111,%00011110,%01110000,%00000011,%10000111,%00011110,%01110000,%000000111,%00000000,%00111001,%11000000,%00000000,%00000000,%00000000
1199 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1200 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1201 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1202 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1203 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1204 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1205 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1206 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1207 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000111,%11010001
1208 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00011011
1209 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010101
1210 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010001
1211
1212 ;----------------------------- end --------------------------------------------
1213
1214         .end
1215 .end
1216
1217 ;----------------------------- NEMESIS'86 by Shiar ----------------------------
1218
1219 ;Game · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · NEMESIS
1220 ;Version  · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · 0.6.820
1221 ;Latest modification  · · · · · · · · · · · · · · · · · · · · · · · · 20.IIX.99
1222 ;Calc · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·  TI-86 only
1223 ;Size · · · · · · · · · · · · · · · · · · · · · · · · · · ·  2077 bytes on calc
1224
1225 ;Author · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · SHIAR
1226 ;ICQ · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·  #43840958
1227 ;E-mail · · · · · · · · · · · · · · · · · · · · · · · · · ·  shiar@wishmail.net
1228 ;Homepage · · · · · · · · · · · · · · · · · · coming soon (www.wish.net/~shiar)
1229
1230 ;Beta:  yes · ·  still to come: lives, armor, powerups, more levels, enemies...
1231 ;Sound:  no · · · · · · · · · · · · don't know if i'll make sounds... we'll see
1232 ;Fun:   yes · · · · · although not yet finished, the game is playable: 5 levels
1233 ;Bugs:  yes  crashes after death; press <EXIT> at GameOver-screen. Send me more
1234 ;Source: no · · · · · · · ·  not yet, will be released when Nemesis is finished
1235
1236 ;----------------------------- version history --------------------------------
1237
1238 ;0.01.717 -- 17.VII.99 -- size 984
1239 ;
1240 ;       + movement of ship over whole screen
1241 ;       + enemies moving from right to left, appearing right at specified times
1242 ;
1243 ; 0.1.718 -- 18.VII.99 -- size 907
1244 ;
1245 ;       # no crash when level restarts for the third time
1246 ;       * exit-procedure updated, unnecessary stuff/keychecks removed
1247 ;       * alot of unused code removed
1248 ;       + different types of enemies (just look different)
1249 ;       + collision detection!! enemy ships disappear when you hit them
1250 ;
1251 ; 0.2.718 -- 18.VII.99 -- size 1153
1252 ;
1253 ;       + ability to fire bullets (F1). Enemies disappear on impact
1254 ;       * enemies explode instead of disappearing
1255 ;
1256 ; 0.3.719 -- 19.VII.99 -- size 1401
1257 ;
1258 ;       * bullets appear correctly (not INSIDE your ship)
1259 ;       + some enemies can take multiple hits (differs per class)
1260 ;       + all enemies fire bullets at random
1261 ;       + if you're hit by bullet/enemy, you'll lose one hitpoint
1262 ;
1263 ; 0.4.720 -- 20.VII.99 -- size 1481
1264 ;
1265 ;       # collision detection fixed and optimized (much faster now!)
1266 ;       + shell-icon added (YAS type)
1267 ;       * code optimizations, some data "compression"
1268 ;       * explosion looks better, and some vars removed/smaller
1269 ;       # enemies are removed when at left side (instead of becoming invisible)
1270 ;       + displays level number before each level begins
1271 ;
1272 ; 0.5.725 -- 25.VII.99 -- size 1778
1273 ;
1274 ;       * waits a sec at level display (in case of accidental keypress)
1275 ;       * moving enemies (move up&down)
1276 ;       # bullets removed correctly so they can be used again later
1277 ;       * first level made
1278 ;       # enemy weaponfire is fired from correct positions
1279 ;       + your ship explodes on impact with ships/bullets
1280 ;       * game over screen will be displayed just *after* your ship's gone
1281 ;       + frame counter onscreen
1282 ;
1283 ; 0.6.820 -- 20.IIX.99 -- size 2152 (2077 on calc)
1284 ;
1285 ;       * play field increased to full screen instead of 3/4
1286 ;       + bottom eight lines used for score (etc) display
1287 ;       - no more solid levels, enemies are placed at random
1288 ;       + enemies appear every x turns (depends on level)
1289 ;       # fixed bullets so they don't disappear at 3/4 of the screen
1290 ;       * A LOT of optimizations both in speed and size!!
1291 ;       + enemy type, frequency, and number specified per level
1292 ;       + bottom score bar displays score, lives and icons (to be used later)
1293 ;       * smarter enemy handling (so enemies have different sizes)
1294 ;       + bottom bar divided from playing field by a horizontal line
1295 ;       + five levels (and five enemies) made
1296 ;       # game vars reset at start and game over
1297 ;       + NEMESIS LOGO displayed at startup!! (also, program grew 350bytes ):
1298 ;       + version/credits string displayed below logo: v0.6.820 by shiar (ICQ#)
1299
1300 ;        + added        - removed       * changed       # bug fixed