00d0554d621d140c3435375e79c2951ae0e1e328
[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.825 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  hl,lives
668         dec (hl)                ;decrease lives
669
670         ld  b,$20
671 wait2:  halt \ halt
672         djnz wait2              ;delay
673         call _getkey            ;wait for keypress
674
675 ;--------------------------- new game -----------------------------------------
676
677 New_level:
678         xor a                   ;a=0
679         ld  hl,x                ;begin position x=...
680         ld  (hl),a              ;...=a=0=left
681         inc hl                  ;y=...
682         ld  (hl),24             ;...=24=middle
683         ld  (level),a           ;reset level nr
684         ld  (score),a           ;reset score
685         ld  hl,level01-3        ;set level pointer to level#1
686         ld  (levelp),hl         ;reset level pointer
687
688 ;--------------------------- next level ---------------------------------------
689
690 Next_level:
691         ld  hl,level
692         inc (hl)                ;increase level nr.
693         ld  a,80
694         ld  (nextevent),a       ;time to first enemy appearance
695
696         ld  hl,(levelp)         ;level pointer
697         inc hl
698         inc hl
699         inc hl                  ;update to point to next level
700         ld  (levelp),hl         ;save
701
702         ld  a,(hl)              ;load new level-enemy type
703         ld  (eventenemy),a      ;set level-enemy
704         inc hl
705         ld  a,(hl)              ;load new appearance-time
706         ld  (eventtime),a       ;set
707         inc hl
708         ld  a,(hl)              ;load nr of enemies in this level
709         ld  (eventleft),a       ;set nr of events left
710
711         xor a
712         ld  (timer),a           ;reset time
713         ld  (your_occ),a        ;reset your ship (not exploding)
714
715 ;--------------------------- setup game ---------------------------------------
716
717 game_setup:
718         call _clrLCD            ;clear screen
719         ld a,%10111011
720         ld  hl,$fc00            ;screen location (top left)
721         ld  b,0                 ;b = 0 (loop 0-1 = 0FFh = 256 times)
722 clearloop2:
723         inc a
724         ld  (hl),a              ;clear four times (total = 256*4 = 1024 bytes)
725         inc hl
726         ld  (hl),a
727         inc hl
728         xor $ff
729         ld  (hl),a
730         inc hl
731         ld  (hl),a
732         inc hl
733         xor $ff
734         djnz clearloop2         ;repeat 256x
735
736         ld  hl,$0703
737         ld  (_curRow),hl        ;center
738         ld  hl,txt_level
739         call _puts              ;display "LEVEL "
740
741         ld  a,(level)
742         ld  l,a
743         ld  h,$00
744
745         call UNPACK_HL
746         add a,'0'
747         ld  b,a
748         call UNPACK_HL
749         add a,'0'
750         call _putc              ;display second digit
751         ld  a,b
752         call _putmap            ;display first digit
753
754         ld  hl,$0904
755         ld  (_curRow),hl        ;display lives left below level nr
756         ld  hl,txt_lives        ;bar text: "Lx0"...
757         ld  a,(lives)           ;lives left
758         add a,'0'               ;make value
759         ld  (txt_lives+3),a     ;add to text
760         call _puts              ;display the string
761
762         ld  b,$20
763 wait:   halt \ halt
764         djnz wait               ;delay
765         call _getkey            ;wait for keypress
766
767         ld  ix,spr_icon00       ;display icons
768         ld  de,$1802            ;bottom left
769         call drw_spr
770         ld  ix,spr_icon00       ;display icons
771         ld  de,$2002            ;bottom left
772         call drw_spr
773         ld  ix,spr_icon00       ;display icons
774         ld  de,$2802            ;bottom left
775         call drw_spr
776         ld  ix,spr_icon00       ;display icons
777         ld  de,$3002            ;bottom left
778         call drw_spr
779         ld  ix,spr_icon00       ;display icons
780         ld  de,$3802            ;bottom left
781         call drw_spr
782
783         ld  hl,GRAPH_MEM        ;from storage (top left)
784         ld  de,$fc00+(56*16)    ;to screen (top left)
785         ld  a,8                 ;display height = 64 bytes (minus 8 for bar)
786 displayloop3:
787         ld  bc,16               ;display width = 16 bytes (16*8bits=256pixels)
788         ldir                    ;16x de >> hl
789         dec a                   ;next line
790         jr  nz,displayloop3     ;loop 8x
791
792         ld  hl,$3a00            ;display Lives
793         ld  (_penCol),hl        ;bottom left
794         ld  hl,savestr+2
795         ld  (hl),'L'
796         inc hl
797         ld  (hl),'x'
798         inc hl
799
800         ld  a,(lives)           ;nr of lives in a
801         add a,'0'               ;make digit
802         ld  (hl),a
803         dec hl \ dec hl
804         call _vputs             ;display on screen
805
806         ld  hl,$fc00+(16*57)    ;56 rows down = eight rows from bottom
807         ld  b,16                ;draw 16x (screen width)
808 drawline:
809         ld  a,%11111111         ;horizontal line mask
810         ld  (hl),a              ;draw one piece of the divider-line
811         inc hl                  ;move right (8 pixels = 1 byte)
812         djnz drawline           ;repeat (16bytes * 8pixels =128= screen width)
813
814                                         ;ret
815 ;--------------------------- exit ---------------------------------------------
816
817 exit_game:
818         ret
819
820 ;--------------------------- putsprite ----------------------------------------
821 ;--------------------------- de =(X,Y) ----------------------------------------
822
823 offsets_table:
824         .db 128,64,32,16,%1000,%0100,%0010,%0001
825 drw_spr:
826         ld  a,d                 ;a = X
827         and %00000111           ;a = X mod 8 = bit nr. to mask
828         ld  hl,offsets_table    ;pixel mask table
829         ld  c,a                 ;bit nr.
830         ld  b,0                 ;word
831         add hl,bc               ;add to table
832         ld  a,(hl)              ;a = pixel mask
833         ld  (_smc1+1),a         ;alter pixel mask
834         ld  (_smc1+1),a
835
836         ld  hl,GRAPH_MEM        ;save-location
837         ld  a,e                 ;y-coord
838         add a,a                 ;y*2
839         add a,a                 ;y*4
840         add a,a                 ;y*8
841  ;b=0
842         rl  b
843         add a,a                 ;y*16 (width of screen)
844         rl  b
845         srl d                   ;d/2
846         srl d                   ;d/4
847         srl d                   ;d/8 (8 bits in byte) ** c is set when overflow
848         add a,d                 ;a = (Y*16+X/8) mod 256
849         jr  nc,_n1              ;jump if no carry = no overflow = a<=255
850         inc b                   ;a>255 so increase bc by 256
851 _n1:    ld  c,a                 ;c = (Y*16+X/8) mod 256
852         add hl,bc               ;bc = Y*16+X/8
853                 ;optimize tip: reverse hl <-> bc (??)
854           
855         ld  d,(ix)
856         ld  b,(ix+1)
857 _oloop: push bc                 ;Save # of rows
858         push hl                 ;Save screen address
859         ld  b,d                 ;Load width
860         ld  c,(ix+2)            ;Load one line of image
861         inc ix
862 _smc1:  ld  a,1                 ;Load pixel mask
863 _iloop: sla c                   ;Test leftmost pixel
864         jr  nc,_noplot          ;See if a plot is needed
865         ld  e,a                 ;OR pixel with screen
866         or  (hl)
867         ld  (hl),a
868         ld  a,e
869 _noplot:rrca
870         jr  nc,_notedge         ;Test if edge of byte reached
871         inc hl                  ;Go to next byte
872 _notedge:
873         djnz _iloop
874         pop hl                  ;Restore address
875         ld  bc,16               ;Go to next line
876         add hl,bc
877         pop bc                  ;Restore data
878         djnz _oloop
879         ret
880
881 ;---------------------- random ------------------------------------------------
882
883 Random:                ; Creates a random number 0 <= x < A
884         push bc
885         push de
886         push hl
887         ld   b,a
888         ld   a,r
889         add  a,a
890         ld   hl,0
891         ld   d,0
892         ld   e,a
893 RMul:
894         add  hl,de
895         djnz RMul
896         ld   a,h
897         pop  hl
898         pop  de
899         pop  bc
900         ret
901
902 ;---------------------- display 5digit number ---------------------------------
903
904 _D_HL_DECI:
905         push bc                 ;save bc
906         ld   de,savestr+4       ;savenr saves number string
907         ld   b,5                ;five digits
908 ldhld:  call UNPACK_HL          ;one digit of hl
909         add  a,'0'              ;make number
910         ld   (de),a             ;save into savenr
911         dec  de                 ;point to next digit
912         djnz ldhld              ;repeat for all digits
913 dis:    ld   hl,savestr
914         call _vputs
915         pop  bc
916         ret
917
918 savestr:
919         .db "PAD98",0
920
921
922 ;------------------------------------------------------------------------------
923 ;------------------------------- sprites --------------------------------------
924 ;------------------------------------------------------------------------------
925
926 spr_ship:
927         .db 9,1         ;ship icon
928         .db %11100000   ; ███
929         .db %11111000   ; █████
930         .db %00111110   ;   █████
931         .db %11111001   ; █████  █
932         .db %11111001   ; █████  █
933         .db %11111001   ; █████  █
934         .db %00111110   ;   █████
935         .db %11111000   ; █████
936         .db %11100000   ; ███
937
938 spr_ship01:
939         .db 7,7         ;ship alpha class
940         .db %01111000   ;  ████
941         .db %11100000   ; ███
942         .db %11111100   ; ██████
943         .db %11110010   ; ████  █
944         .db %11111100   ; ██████
945         .db %11100000   ; ███
946         .db %01111000   ;  ████
947 spr_ship02:
948         .db 7,7         ;ship beta class
949         .db %11000000   ; ██
950         .db %11110000   ; ████
951         .db %01111100   ;  █████
952         .db %01110010   ;  ███  █
953         .db %01111100   ;  █████
954         .db %11110000   ; ████
955         .db %11000000   ; ██
956
957 spr_bullet01:
958         .db 5,3         ;your bullets
959         .db %00110000   ;   ░▒▓█▒
960         .db %11111000   ; ░▒▓████▒
961         .db %00110000   ;   ░▒▓█▒
962 spr_bullet02:
963         .db 5,3         ;your bullets
964         .db %11110000   ; ░▒▓███▒
965         .db %11111000   ; ░▒▓████▒
966         .db %11110000   ; ░▒▓███▒
967
968 spr_bullet11:
969         .db 3,3         ;enemy bullets
970         .db %01000000   ;  ▒▓▒░
971         .db %11100000   ; ▒██▓▒░
972         .db %01000000   ;  ▒▓▒░
973
974 ;---------------------------------------- explosion -------------------------------------------
975
976 spr_explosion:                               
977         .db 8,6         ;1
978         .db %00000000
979         .db %00011100   ;    ███
980         .db %00111110   ;   █████
981         .db %01010110   ;  █ █ ██
982         .db %00111000   ;   ███
983         .db %00000000
984
985         .db 8,6         ;2
986         .db %00110000   ;   ██
987         .db %01001110   ;  █ ▒███
988         .db %10111110   ; █ █████
989         .db %01001111   ;  █ ▒████
990         .db %00111000   ;   ███
991         .db %00011010   ;    ██ █
992
993         .db 8,6         ;3
994         .db %10110011   ; █ ██  ██
995         .db %01001110   ;  █  ███
996         .db %10110101   ; █ ██▒█▒█
997         .db %01000101   ;  █  ▒█▒█
998         .db %00111110   ;   █████
999         .db %11011010   ; ██ ██ █
1000
1001         .db 8,6         ;4
1002         .db %00101010   ; ▒ █▒█ █▒
1003         .db %01000110   ;  █  ▒██
1004         .db %10110101   ; █ ██ █ █
1005         .db %01100110   ;  ██  ██▒
1006         .db %00111100   ;   ████▒
1007         .db %01011001   ; ▒█ ██ ▒█
1008
1009         .db 8,6         ;5
1010         .db %01000001   ;  █▒ ▒ ▒█
1011         .db %00100101   ;  ▒█  █▒█
1012         .db %00010100   ; ▒ ▒█ █ ▒
1013         .db %01000100   ;  █▒  █
1014         .db %00010010   ;   ▒█▒▒█
1015         .db %10011010   ; █▒ ██ █▒
1016
1017         .db 8,6         ;6
1018         .db %01000100   ;  █   █ ▒
1019         .db %00100000   ;   ▒█ ▒ ▒
1020         .db %00000001   ;    ▒ ▒ █
1021         .db %01000100   ;  █   █
1022         .db %00100010   ;   █▒  █
1023         .db %01001000   ; ▒█ ▒█ ▒
1024
1025         .db 8,6         ;7
1026         .db %00001000   ;  ▒  █▒
1027         .db %11000010   ; ██ ▒  █
1028         .db %00000000   ;        ▒
1029         .db %00100000   ;  ▒█  ▒
1030         .db %00000001   ;   ▒   ▒█
1031         .db %00110000   ;  ▒██▒
1032
1033         .db 8,6         ;8
1034         .db %00000100   ;     ▒█
1035         .db %00000000   ; ▒▒    ▒
1036         .db %01000000   ;  █
1037         .db %00000000   ;   ▒
1038         .db %00000010   ;       █▒
1039         .db %00100100   ;   █▒ █
1040
1041 ;--------------------------------------- bar -----------------------------------
1042
1043 spr_icon00:
1044         .db 8,7
1045         .db %10101010   ; █ █ █ █
1046         .db %11010101   ; ██ █ █ █
1047         .db %10101010   ; █ █ █ █
1048         .db %11010101   ; ██ █ █ █
1049         .db %10101010   ; █ █ █ █
1050         .db %11010101   ; ██ █ █ █
1051         .db %10101010   ; █ █ █ █
1052 spr_icon01:
1053         .db 8,7
1054         .db %10000000   ; █.......
1055         .db %10000000   ; █
1056         .db %10000000   ; █
1057         .db %10000000   ; █
1058         .db %10000000   ; █
1059         .db %10000000   ; █
1060         .db %10000000   ; █
1061 spr_icon02:
1062         .db 8,7
1063         .db %10000000   ; █
1064         .db %10000000   ; █
1065         .db %10000000   ; █
1066         .db %10000000   ; █
1067         .db %10000000   ; █
1068         .db %10000000   ; █
1069         .db %10000000   ; █
1070
1071 ;---------------------------- texts -------------------------------------------
1072
1073 txt_about:      .db "v0.6.825 ","by Shiar  "
1074                 .db "(ICQ#43840958)",0
1075 txt_1player:    .db "1 PLAYER",0
1076 txt_2players:   .db "2 PLAYERS",0
1077 txt_level:      .db "LEVEL ",0
1078 txt_gameover:   .db "GAME OVER!",0
1079 txt_lives:      .db "Lx0?",0
1080
1081 ;---------------------------- save data ---------------------------------------
1082
1083 stored_data_start:
1084
1085 timer           .db $00                 ;frame counter
1086 level           .db $00                 ;level number
1087 levelp          .dw level01             ;pointer to level data
1088
1089 eventenemy      .db $02                 ;enemy type
1090 eventtime       .db $15                 ;enemy frequency
1091 eventleft       .db $00                 ;nr. of enemies still to come
1092 nextevent       .db $50                 ;time to next event
1093
1094 score           .dw $0000
1095
1096 your_occ        .db $00                 ;0=normal 1..16=exploding
1097 lives           .dw $0003       ;unused
1098 x               .db $16                 ;x-pos
1099 y               .db $46                 ;think about it..
1100 hp              .db $00                 ;hitpoints left
1101
1102 ybullets        .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0       ;10 x (state,x,y)
1103 ebullets        .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0       ;10 x (state,x,y)
1104
1105 nrenemies       = 20
1106 enemies         .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
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
1111                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1112                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1113                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1114                 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
1115
1116 ; %111111 (HP left) 11 (00=no enemy 01=exploding 10=normal 11=moving)
1117 ; %11111111 (ship type or explosion frame)  %11111111 (x) %11111111 (y)
1118
1119 ;---------------------------- enemy data --------------------------------------
1120
1121 sprites:
1122         .db $00
1123         .db spr_enemy02-spr_enemy01
1124         .db spr_enemy03-spr_enemy01
1125         .db spr_enemy04-spr_enemy01
1126         .db spr_enemy05-spr_enemy01
1127
1128 spr_enemy01:
1129         .db 6,6         ;enemy type one
1130         .db %00111100   ;   ████
1131         .db %01110000   ;  ███
1132         .db %11110000   ; ████
1133         .db %11110000   ; ████
1134         .db %01110000   ;  ███
1135         .db %00111100   ;   ████
1136 spr_enemy02:
1137         .db 8,7         ;enemy type two
1138         .db %00111111   ;    █████
1139         .db %01111000   ;  ████
1140         .db %11111100   ; ██████
1141         .db %11111110   ; ███████
1142         .db %11111100   ; ██████
1143         .db %01111000   ;  ████
1144         .db %00111111   ;    █████
1145 spr_enemy03:
1146         .db 6,6         ;enemy type three
1147         .db %01111100   ;  █████
1148         .db %11110000   ; ████
1149         .db %11111000   ; █████
1150         .db %11111000   ; █████
1151         .db %11110000   ; ████
1152         .db %01111100   ;  █████
1153 spr_enemy04:
1154         .db 6,6         ;enemy type four
1155         .db %00111000   ;   ███
1156         .db %01111100   ;  █████
1157         .db %11111000   ; █████
1158         .db %11111000   ; █████
1159         .db %01111100   ;  █████
1160         .db %00111000   ;   ███
1161 spr_enemy05:
1162         .db 7,6         ;enemy type four
1163         .db %00011110   ;    ████
1164         .db %01111110   ;  ██████
1165         .db %11111100   ; ██████
1166         .db %11111100   ; ██████
1167         .db %01111110   ;  ██████
1168         .db %00011110   ;    ████
1169
1170 enemy01:                                ;HP:1  move:- fire:-
1171         .db %00000010,%00000000                 ;first two enemy bytes
1172 enemy02:                                ;HP:1  move:1 fire:1.5%
1173         .db %00000010,%00000001
1174 enemy03:                                ;HP:2  move:- fire:3%
1175         .db %00000110,%00000010
1176 enemy04:                                ;HP:5  move:- fire:6%
1177         .db %00010010,%00000011
1178 enemy05:                                ;HP:10 move:- fire:25%
1179         .db %00100111,%00000100
1180
1181 ;----------------------------- level info -------------------------------------
1182
1183 level01:
1184         .db $00,$15,$30                 ;enemy nr ; enemy frequency ; next lvl
1185 level02:
1186         .db $01,$11,$4c
1187 level03:
1188         .db $02,$19,$40
1189 level04:
1190         .db $03,$0f,$50
1191 level05:
1192         .db $04,$2e,$3e
1193
1194 ;----------------------------- logo -------------------------------------------
1195
1196 logo_nemesis:
1197 .db %11111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00001011,%11111111,%11111111,%11111111,%11111000
1198 .db %01111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00011011,%11111111,%11111111,%11111111,%11110000
1199 .db %00111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00111011,%11111111,%11111111,%11111111,%11100000
1200 .db %00011111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%01111011,%11111111,%11111111,%11111111,%11000000
1201 .db %00000000,%00000000,%00000001,%00011110,%00010000,%00000000,%10000001,%00011110,%00010000,%000000001,%00000000,%00001000,%01000000,%00000000,%00000000,%00000000
1202 .db %00000000,%00000000,%00000011,%00011110,%00110000,%00000001,%10000011,%00011110,%00110000,%000000011,%00000000,%00011000,%11000000,%00000000,%00000000,%00000000
1203 .db %00000000,%00000000,%00000111,%00011110,%01110000,%00000011,%10000111,%00011110,%01110000,%000000111,%00000000,%00111001,%11000000,%00000000,%00000000,%00000000
1204 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1205 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1206 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1207 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
1208 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1209 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1210 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1211 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
1212 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000111,%11010001
1213 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00011011
1214 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010101
1215 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010001
1216
1217 ;----------------------------- end --------------------------------------------
1218
1219         .end
1220 .end
1221
1222 ;----------------------------- NEMESIS'86 by Shiar ----------------------------
1223
1224 ;Game · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · NEMESIS
1225 ;Version  · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · 0.6.825
1226 ;Latest modification  · · · · · · · · · · · · · · · · · · · · · · · · 20.IIX.99
1227 ;Calc · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·  TI-86 only
1228 ;Size · · · · · · · · · · · · · · · · · · · · · · · · · · ·  2077 bytes on calc
1229
1230 ;Author · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · SHIAR
1231 ;ICQ · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·  #43840958
1232 ;E-mail · · · · · · · · · · · · · · · · · · · · · · · · · ·  shiar@wishmail.net
1233 ;Homepage · · · · · · · · · · · · · · · · · · coming soon (www.wish.net/~shiar)
1234
1235 ;Beta:  yes · ·  still to come: lives, armor, powerups, more levels, enemies...
1236 ;Sound:  no · · · · · · · · · · · · don't know if i'll make sounds... we'll see
1237 ;Fun:   yes · · · · · although not yet finished, the game is playable: 5 levels
1238 ;Bugs:  yes  crashes after death; press <EXIT> at GameOver-screen. Send me more
1239 ;Source: no · · · · · · · ·  not yet, will be released when Nemesis is finished
1240
1241 ;----------------------------- version history --------------------------------
1242
1243 ;0.01.717 -- 17.VII.99 -- size 984
1244 ;
1245 ;       + movement of ship over whole screen
1246 ;       + enemies moving from right to left, appearing right at specified times
1247 ;
1248 ; 0.1.718 -- 18.VII.99 -- size 907
1249 ;
1250 ;       # no crash when level restarts for the third time
1251 ;       * exit-procedure updated, unnecessary stuff/keychecks removed
1252 ;       * alot of unused code removed
1253 ;       + different types of enemies (just look different)
1254 ;       + collision detection!! enemy ships disappear when you hit them
1255 ;
1256 ; 0.2.718 -- 18.VII.99 -- size 1153
1257 ;
1258 ;       + ability to fire bullets (F1). Enemies disappear on impact
1259 ;       * enemies explode instead of disappearing
1260 ;
1261 ; 0.3.719 -- 19.VII.99 -- size 1401
1262 ;
1263 ;       * bullets appear correctly (not INSIDE your ship)
1264 ;       + some enemies can take multiple hits (differs per class)
1265 ;       + all enemies fire bullets at random
1266 ;       + if you're hit by bullet/enemy, you'll lose one hitpoint
1267 ;
1268 ; 0.4.720 -- 20.VII.99 -- size 1481
1269 ;
1270 ;       # collision detection fixed and optimized (much faster now!)
1271 ;       + shell-icon added (YAS type)
1272 ;       * code optimizations, some data "compression"
1273 ;       * explosion looks better, and some vars removed/smaller
1274 ;       # enemies are removed when at left side (instead of becoming invisible)
1275 ;       + displays level number before each level begins
1276 ;
1277 ; 0.5.725 -- 25.VII.99 -- size 1778
1278 ;
1279 ;       * waits a sec at level display (in case of accidental keypress)
1280 ;       * moving enemies (move up&down)
1281 ;       # bullets removed correctly so they can be used again later
1282 ;       * first level made
1283 ;       # enemy weaponfire is fired from correct positions
1284 ;       + your ship explodes on impact with ships/bullets
1285 ;       * game over screen will be displayed just *after* your ship's gone
1286 ;       + frame counter onscreen
1287 ;
1288 ; 0.6.820 -- 20.IIX.99 -- size 2152 (2077 on calc)
1289 ;
1290 ;       * play field increased to full screen instead of 3/4
1291 ;       + bottom eight lines used for score (etc) display
1292 ;       - no more solid levels, enemies are placed at random
1293 ;       + enemies appear every x turns (depends on level)
1294 ;       # fixed bullets so they don't disappear at 3/4 of the screen
1295 ;       * A LOT of optimizations both in speed and size!!
1296 ;       + enemy type, frequency, and number specified per level
1297 ;       + bottom score bar displays score, lives and icons (to be used later)
1298 ;       * smarter enemy handling (so enemies have different sizes)
1299 ;       + bottom bar divided from playing field by a horizontal line
1300 ;       + five levels (and five enemies) made
1301 ;       # game vars reset at start and game over
1302 ;       + NEMESIS LOGO displayed at startup!! (also, program grew 350bytes ):
1303 ;       + version/credits string displayed below logo: v0.6.820 by shiar (ICQ#)
1304 ;
1305 ; 0.6.825 -- 25.IIX.99 -- size 2160 (2085 on calc)
1306 ;
1307 ;       # pointer to fifth ship corrected (ships in level 5 weren't displayed)
1308 ;       # calc doesn't crash anymore when game is continued after game over!!
1309 ;       + lives are decreased when ship is destroyed
1310 ;       # last eight pixels of divider line are shown correctly now
1311
1312
1313 ;        + added        - removed       * changed       # bug fixed