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