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