1 ;------------------------------------------------------------------------------
2 ;---------------------- NEMESIS -----------------------------------------------
3 ;------------------------------------------------------------------------------
4 ; >>> NEMESIS <<< Version 0.95 BETA by SHIAR
5 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8 ; Release Date : 22.X.99
9 ; Filename : nemesis.86p (5321)
11 ; Email Address : shiar0@hotmail.com
13 ; Web Page : come.to/shiar
14 ; Description : cool arcade-shoot-em-up-game (release 12/99)
15 ; Where to get this game : www.ticalc.org
16 ; Other games by author : N/A
18 ; ABOUT: This source should only be used for learning practises, do not
19 ; alter it, and certainly do not distribute an altered version!!
20 ; NOTE: &&& marks uncertainties or things to optimize
22 ;---------------------- nemesis.z80 start -------------------------------------
25 #include "ti86asm.inc" ;standard ti86 romcalls
26 #include "ti86abs.inc" ;used to save hiscores and so
27 #include "ti86un .inc" ;_dispahl and _shracc
31 #define cal call ;just to make it harder for you to understand
32 #define psh push ; ^:D
34 TEXT_MEM = _textShadow ;167 bytes ($A7): C0F9-C1A0
36 storepos = $8000 ;120 OF 165
37 storepos2 = $8100 ;141 OF 167
39 ;---------------------- in-game vars ------------------------------------------
41 temp1 = storepos ;$C0FA-C0FB ;temp (2 bytes) bullet
43 just_fired = storepos+2 ; +2 ;counts how long a blast lasts
44 curline = storepos+2 ; +2 ;used to display SFX
45 menuitem = storepos+2 ; +2 ;used to store menu location
46 hiscorepos = storepos+2 ; +2
47 RanPos = storepos+3 ; +3 ;used for making random values
48 timer = storepos+4 ; +4 ;frame counter
50 x = storepos+5 ; +5 ;your ship's position
51 y = x+1 ; +6 ;your y-pos
52 firex = y+1 ; +7 ;(1 byte)
53 firey = firex+1 ; +8 ;(1 byte)
56 eventtime = storepos+10 ;+10 ;enemy frequency
57 eventleft = eventtime+1 ;+11 ;nr. of enemies still to come
58 nextevent = eventleft+1 ;+12 ;time to next event
59 pickuptimer = nextevent+1 ;+13 ;counts when to place a pickup
60 level_enemy = pickuptimer+1 ;+14 ;enemy type
61 level_move = level_enemy+1 ;=
62 level_fire = level_move+1 ;+16
65 spacespace = storepos+19 ;+19
66 groundinfo = spacespace+1 ;+20
67 groundpos = groundinfo+1 ;+21 $10
68 ceilingpos = groundpos+16 ;+37 $10
70 stars1 = ceilingpos+16 ;+53
71 stars2 = stars1+1 ;+54
73 starx1 = storepos+55 ;+55
75 starx2 = starx1+(nrstars1*2) ;+69
76 ; ^^ ;--------MULTIPLES
77 mx = starx2+(nrstars2*2) ;+83 ;position of multiple#1
78 my = mx+1 ;+84 ;multiple y-pos
81 your_locpos = m2y+1 ;+87 ;position in your_prevpos tabl
82 your_prevpos = your_locpos+1 ;+88 ;save previous positions (32d)
84 ;^-----------------------------------<1 ;-120=$78
86 nrenemies = 10 ;max. nr of enemies
87 enemies = storepos2 ; +0 ;info about each enemy (4byt)
88 add2enemy = nrenemies*4 ;size of "enemies"
89 enemiesxtra = enemies+add2enemy ;+40 ;more info 'bout enemies (4)
92 ybullets = enemiesxtra+add2enemy ;+80 ;60 bytes = 20(state,x,y)
94 ebullets = ybullets+(nrybuls*3) ;+110 ;30 bytes = 10(state,x,y)
96 ybuls = ebullets+(nrebuls*3) ;+140
98 ;^-----------------------------------<2 ;-141=$8D
100 ; %1 (directfire) 1 (ground) 1 (ceiling) 1 (diagfire) 1111 (move)
102 ; %111111 (HP left) 11 (00=no enemy 01=exploding 10=normal 11=moving)
103 ; %11111111 (ship type or explosion frame) %11111111 (x) %11111111 (y)
105 ; $11 (move) $11 (fire) $11 (bullettype)
107 ;---------------------- introduction ------------------------------------------
109 nop ;hello yas/ase/rascall/whathever
110 jp init ;here's the program, but first: a description
111 .dw $0001 ;description type 2 (description + YASicon)
112 .dw Title ;pointer to description (all shells)
113 .dw Icon ;pointer to YAS icon
115 Title: .db "Nemesis v0.95 by Shiar",0
117 Icon: .db 8,1 ;icon for YAS: width = 1byte; height = 9bytes
120 .db %00111110 ; █████
121 .db %01111001 ; ████ █
122 .db %00111110 ; █████
124 .db %11100000 ; ███ ;recommend 80x50 screen mode
125 .DB 0 ;clear stupid YAS-line
127 ;---------------------- init --------------------------------------------------
138 ld bc,int_end-int_handler
155 init: cal BUSY_OFF ;turns the run-indicator off, obviously
156 cal _clrScrn ;clean the screen
157 xor a ;<ld a,0>: reset:
158 ld (iy+13),a ;don't affect TEXT_MEM and don't scroll screen
159 ld (_asapvar+1),a ;Asm( thinks it's the first time it runs Nems.
162 ld a,(CONTRAST) ;load current contrast level
163 cp $1f ;if already at maximum...
164 jr z,skipdarken ;...then skip level increase
165 inc a ;otherwise increase contrast level
169 ;---------------------- main menu ---------------------------------------------
172 xor a ;white bitmask (a=0)
174 ld hl,logo_nemesis ;from...
175 ld de,VIDEO_MEM+16 ;...to one line from top
177 ld (de),a ;clear/n byte
179 djnz AboveLogo ;repeat for the first line
181 ld bc,16*19 ;logo size
182 ldir ;display one line of logo
184 ; ld hl,GRAPH_MEM ;cleared line
185 ; ld bc,16 ;size=one line
186 ; ldir ;also clear one line below the logo
188 ; ld a,-1 ;first line is -1+1=0
189 ; ld b,21 ;with first 21 lines:
190 ; cal DoSFX ;do special effect &&&skip
192 ld hl,VIDEO_MEM+(16*$39)+4 ;$39 rows down, 4 cols right (4*8=$20)
193 ld b,8 ;draw 8x one byte = 8*8 = 64 pixels wide
194 ld a,%11111111 ;horizontal line mask
196 ld (hl),a ;draw one piece of the divider-line
197 inc hl ;move right (8 pixels = 1 byte)
198 djnz underline ;repeat
200 set 3,(iy+5) ;set white on black
201 ld hl,$3320 ;near the bottom of the screen
203 ld hl,txt_about ;display version and author (yes, that's me!)
204 cal _vputs ;useful procedure if you want to display somtn
205 res 3,(iy+5) ;return to default black on white
207 ld hl,$3a1e ;below previous stuff
209 ld hl,txt_email ;hey, my e-mail address so SEND ME SOMETHING!!
210 cal _vputs ;VERY important, so display in small font ?:}
245 halt \ halt \ halt \ halt
247 cal GET_KEY ;wait for keypress
265 cal New_game ;prepare level
281 ;------------------------------------------------------------------------------
282 ;---------------------- game loop ---------------------------------------------
283 ;------------------------------------------------------------------------------
285 game_main_loop: ;REPEATS FROM HERE EVERY FRAME
286 ld hl,timer ;update time
287 inc (hl) ;increase by 1
288 ld b,(hl) ;new time, save for rand# upd. (no flag change)
289 jr nz,updaterandom ;continue when new time <> 0
290 ld hl,1 ;once every 256 frames, increase score by 1
294 ld hl,RanPos ;random counter
295 ld a,r ;add r register to randomize
296 add a,(hl) ;add previous random value
297 add a,b ;even more random by adding timer
298 ld (hl),a ;save even more random value back
301 ld hl,GRAPH_MEM ;move from (hl) = top left
302 ld (hl),$00 ;first pixel will be copied all over the screen
303 ld de,GRAPH_MEM+1 ;(de) = next pixel, thus clearing whole screen
304 ld bc,896 ;loop 896 times = (128/8) * (64-8 for scorebar)
309 jr z,movestarsdone ;don't move stars once every 4 frames
311 cal movestars1 ;move the stars on the FRONT layer
312 cal movestars2 ;move the distant stars
315 ld a,(stars1) ;star positions (the missing byte...)
316 ld b,nrstars1 ;how many stars? now we know.
317 ld hl,starx1 ;points to the position of the stars
318 cal DisplayStars ;display front layer stars
320 ld a,(stars2) ;weren't you paying attention five lines ago?
321 ld b,nrstars2 ;that many?! whow!
322 ld hl,starx2 ;and there they are
323 cal DisplayStars ;use the same procedure to display back layer
325 ld a,(level_move) ;level info
326 and %01100000 ;isolate ground&ceiling
327 jr z,game_stuff ;both non-present
328 and %00100000 ;bit representing the presence of any ceiling
329 cal nz,Handle_ceiling ;scroll the ceiling (if any)
330 cal Handle_ground ;scroll the ground
333 ld a,(your_occ) ;are you 100% OK?
335 jr nz,_gamestuff1 ;then don't check for movements/fires/...
337 ld a,(level_move) ;the same level info
338 and %01100000 ;isolate ground&ceiling again
339 jr z,check_keys ;no ceiling nor ground
340 and %00100000 ;this bit will tell us if there is a ceiling
341 cal nz,CheckCeiling ;if there is, check it
342 cal CheckGround ;check for collision with the ground
349 ld a,%00111111 ;function keys (MORE,EXIT,2ND,F1,F2,F3,F4,F5)
350 out (1),a ;ask for them
351 nop \ nop ;delay 8 clocks
355 bit 6,a ;test bit 6 = exit-key = EXIT
356 jp z,game_over_nopop ;<exit> pressed, so be it
357 check_morekey: ;another unused label... poor compiler
358 bit 7,a ;test bit 7 = more-key = PAUSE
359 cal z,Pause ;yes, go to pause
362 bit 5,a ;test bit 5 = 2nd-key = FIRE
363 ld hl,check_selkey ;where to continue after executing Fire_bullet
364 psh hl ;push hl on stack (instead of cal Fire_bullet)
365 jp z,Fire_bullet ;fire smtn (bulletstorplasermultiples+stuff..)
366 pop hl ;no cal to Fire_bullet made, so pop stack
367 ld hl,just_fired ;no:
368 ld (hl),0 ;reset just_fired
371 ld a,%01011111 ;look at first column of keys (ALPHA to STO)
373 nop \ nop ;what's taking you so long
374 in a,(1) ;at last... our precious keyzzz...
375 ;old: <bit 7,a \ cal z,select> now see this:
376 rla ;test bit7 so we know f ALPHA has been pressed
377 cal nc,select ;yeppy, select the currently selected upgrade
379 cal Enemies_hit ;check for collision with enemies
382 cal Handle_Ship ;move you
383 cal Handle_bullets ;move your bullets
384 cal Handle_torp ;move your torpedo
386 cal Handle_enemies ;move enemies
387 cal Enemy_bullets ;move enemy bullets
389 cal Level_event ;insert enemies
390 cal Display_Screen ;display all
393 jp game_main_loop ;LOOP
395 ;--------------------------- ground -------------------------------------------
399 and %111 ;once every 8 frames
400 jr nz,Display_ground ;otherwise skip the scroll
401 ld bc,15 ;scroll all 16 bytes minus one (teh new byte)
402 ld hl,groundpos+1 ;from..
403 ld de,groundpos ;to (one byte to the left)
404 ldir ;LoaDIncreaseRepeat = scroll!
406 ld a,(groundinfo) ;what kind of ground
408 jr z,ground_tunnel ;tunnel effect
425 jr z,ground_previous ;a>=0 (a=0 actually)
438 ld a,(groundpos+14) ;type 1
441 ld a,(groundpos) ;type 0
443 ld (groundpos+15),a ;save new byte on the right
453 ld b,16 ;screen width
454 ld de,groundpos-1 ;height of current byte (previous actually)
456 ld hl,GRAPH_MEM+(56*16)-1 ;screen position
460 ld c,b ;push b for groundloopup
461 pop hl \ inc hl ;get screen position and go one right
462 pop de \ inc de ;get height info and set to the next byte
463 psh de \ psh hl ;save these for the next time
464 ld a,(de) ;height of current byte
467 ld de,16 ;to substract to go one line up
468 ld a,%11111111 ;bitmask black
471 ld (hl),a ;display black byte
472 sbc hl,de ;go up (sbc must be used for 16-bit sub)
473 djnz groundloopup ;and loop >groundpos< times
475 ld b,c ;pop b used by groundloopup
476 djnz groundloopright ;loop right for entire screen (16x)
477 pop hl \ pop hl ;restore stack
480 CheckGround: ;check for collision with the ground
497 ;--------------------------- ceiling ------------------------------------------
501 and %111 ;once every 8 frames
502 jr nz,Display_ceiling ;otherwise skip the scroll
503 ld bc,15 ;scroll all 15 bytes (16th is new position)
504 ld hl,ceilingpos+1 ;from..
505 ld de,ceilingpos ;to (one byte to the left)
506 ld a,(de) ;load byte on left (will be lost after scroll)
507 ldir ;LoaDIncreaseRepeat = scroll!
509 ld a,(groundinfo) ;what kind of ceiling
511 jr z,ceiling_tunnel ;tunnel effect
522 jr z,ceiling_previous
528 jr z,ceiling_previous
536 jr z,ceiling_previous
541 ld a,(ceilingpos+14) ;type 1
544 ld a,(ceilingpos) ;type 0
546 ld (ceilingpos+15),a ;save the new byte
549 jr nc,Display_ceiling
556 ld b,16 ;screen width
557 ld de,ceilingpos-1 ;height of current byte
559 ld hl,GRAPH_MEM-17 ;screen position
563 ld c,b ;push b for groundloopup
564 pop hl \ inc hl ;get screen position and go one right
565 pop de \ inc de ;get height info and set to the next byte
566 psh de \ psh hl ;save these for the next time
567 ld a,(de) ;height of current byte
570 ld de,16 ;to substract to go one line up
571 ld a,%11111111 ;bitmask black
574 ld (hl),a ;display black byte
576 djnz ceilingloopdown ;and loop >groundpos< times
578 ld b,c ;pop b used by groundloopup
579 djnz ceilingloopright ;loop right for entire screen (16x)
580 pop hl \ pop hl ;restore stack
583 CheckCeiling: ;check for collision with the ground
587 srl a ;x/8 (current ceiling-byte)
591 ld de,ceilingpos ;first ceiling-byte
592 add hl,de ;current ceiling-byte
595 cp (hl) ;compare with ceiling
596 ret nc ;carry if ceiling is above you
597 jp damage_you ;otherwise you don't wanna be in that ship
599 ;--------------------------- move stars ---------------------------------------
601 DisplayStars: ;inputs: hl=starx# a=stars# b=nrstars#
608 ret ;let's comment this: returns
637 cp 9 ;(GRAPH_MEM&%00001111)-- = $C9FAand15-1 = $A-1
646 ret ;for stupid people, here's another comment...
648 ;--------------------------- pause --------------------------------------------
651 ld hl,$0200 ;top left
653 ld hl,txt_pressenter ;"Enter to continue"
654 cal _puts ;display message
656 cal _getkey ;enter low-power mode and wait for key
657 cp kEnter ;keypressed = enter?
658 jr nz,pause ;no, wait some more
661 ;--------------------------- teacher ------------------------------------------
664 ld (iy+12),5 ;enable flashing cursor
666 ld hl,$0000 ;top left
669 cal _puts ;display message
681 cal _getkey ;enter low-power mode and wait for key
682 cp kEnter ;enter pressed?
684 cp kGrMenu ;keypressed = graph?
685 jr nz,teacherloop ;no, wait some more
687 ld (iy+12),0 ;disable cursor
706 ;--------------------------- exit ---------------------------------------------
710 ld a,(CONTRAST) ;load original contrast level
711 out (2),a ;and set it back
712 ld (iy+13),3 ;use textshadow (TEXT_MEM) and scrolling
714 ld hl,GRAPH_MEM ;graph-screen location
717 ld bc,1024-1 ;do it 1024 times = entire screen
720 cal _clrScrn ;as _clrLCD but also clears TEXT_MEM
721 cal _homeup ;set cursor to top-left
724 ;--------------------------- display ------------------------------------------
727 ld hl,GRAPH_MEM ;from storage (top left)
728 ld de,VIDEO_MEM ;to screen (top left)
729 ld c,56 ;display height = 64 bytes (minus 8 for bar)
731 ld b,16 ;display width = 16 bytes (16*8bits=256pixels)
733 ld a,(hl) ;copy byte from (hl)
735 xor $ff ; } ;invert byte (white<=>black) &&&&
737 inc hl \ inc de ;next byte
738 djnz displaytloop ;16x hl >> de
740 jr nz,displayloop ;loop 64x
742 ld hl,$396b ;Display Score
743 ld (_penCol),hl ;bottom right of screen
746 _D_HL_DECI: ;------- display 5-digit value -------
747 ld de,savestr+4 ;savenr saves number string
749 ldhld: cal UNPACK_HL ;one digit of hl
750 add a,'0' ;make number
751 ld (de),a ;save into savenr
752 dec de ;point to next digit
753 djnz ldhld ;repeat for all digits
755 ld hl,savestr ;we (the program) saved the value righthere
756 cal _vputs ;the only thing left to do is to display it
757 ret ;and we're done again
759 savestr: ;@here the score will be stored
760 .db "00000",0 ;don't worry, it's just temporary
762 ;------------------------- handle ship ----------------------------------------
769 inc a ;no! next (explosion)frame
770 ld (your_occ),a ;save
772 cp 34 ;last explosion frame?
773 jp c,exploding_you ;not yet: display explosion
774 cp 40 ;delay finished?
775 jp z,You_die ;yes = game over
776 ret ;don't display anything
779 ld a,%01111110 ;get arrow keys
780 out (1),a ;it's cold outside
781 ld hl,y ;instead of nop\nop do something usefull
782 in a,(1) ;come back in
785 xor %11111111 ;inverted a = 0 if arrow-key has been pressed
786 ld a,(your_multiples)
787 jr z,no_adv ;if so, leave the multiples where they are
788 or %100 ;set move bit
790 no_adv: and %11111011 ;reset move bit
792 adv_ok: ld (your_multiples),a
795 rra ;rotate right (put last bit in c)
796 ld b,a ;we need a later
800 cp 49 ;55-6 = bottom of screen
806 rr b ;because we now use b, it's rr instead of rra
809 sub 1 ;<dec a> doesn't affect c-flag
810 jr c,no_left ;-1 = left side
816 cp 121 ;127-6 = right side
826 sub 1 ;<dec a> doesn't affect carry-flag
827 jr c,no_up ;-1 = top of screen
828 ld (hl),a ;save new y
831 ld ix,spr_ship01 ;ship sprite
832 ld hl,your_inv ;invulnerable?
833 ld a,(hl) ;load time in a
835 jr z,handle_multiples ;yes so ship = normal (display \ continue)
837 ld a,(timer) ;load frame nr.
838 and %00000111 ;a=0 once every four frames
839 jr nz,not_time ;a<>0 = not time to update counter
840 dec (hl) ;decrease inv-time left
842 and %00000100 ;a switches 0<->1 every 2 frames
843 jr z,handle_multiples ;show normal ship
845 ld ix,spr_ship01i ;don't display ship
848 cal putsprite ;display your ship
850 ld a,(your_multiples) ;do you have multiples
851 ld b,a ;save a for 2nd check
852 and %11 ;no? (last two bits = nr of multiples)
853 ret z ;then don't handle them either
856 ld a,b ;restore a (your_multiples)
857 and %100 ;move the multiples???
858 jr z,mult_adv ;nope, just let them (saves (y) in y, (x) in x)
860 ld hl,your_locpos ;location to save this position
863 and %00001111 ;if a>15 then a=a-16
864 ld (hl),a ;save new a
869 ld hl,your_prevpos ;previous positions
870 add hl,bc ;16 turns ago
874 ld (mx),de ;save multiple position in (mx)
876 ld a,(y) ;load new y-pos
877 ld (hl),a ;save it for 16 turns in the future
879 ld a,(x) ;load new x-pos
880 ld (hl),a ;save that too
884 ld ix,spr_multiple ;sprite of the multiple
885 jp putsprite ;display it + <ret>
888 srl a ;half the framerate
889 dec a ;first frame is 1>inc>srl>dec = 0
908 ld a,(your_inv) ;invulnerability left?
910 ret nz ;return if inv>0
911 ld hl,your_armor ;armor left
914 jp m,no_armor ;yes, 0hp left so explode
915 ld (hl),a ;no, so save decreased hp
916 cal disp_armor ;and display new value
918 ld a,(your_pickup) ;how many pickups do you have?
919 dec a ;is the armor-icon selected
920 ret nz ;return if not
922 ld hl,VIDEO_MEM+(16*56)
924 ld ix,spr_icon ;if so, highlight armorIcon again
925 ld de,$1901 ;position
926 cal putwidesprite ;display icon
932 ld a,%01 ;occ %xxxxxx01 = explode
933 ld (your_occ),a ;set to explode
936 ;------------------------- place multiples ------------------------------------
939 ld (mx),de ;set last multiple-position
940 ld hl,your_prevpos ;place all previous positions
941 ld b,16 ;all 16 of them
943 ld (hl),d ;set prev-x to d
945 ld (hl),e ;set prev-y to e
947 djnz place_multiples ;repeat
950 ;------------------------- select upgrade -------------------------------------
953 ld hl,your_pickup ;select pickups
954 ld a,(hl) ;load pickups taken so far
956 jr nz,select2 ;no, carry on
957 ld (hl),a ;reset pickups (a=0)
958 ld hl,your_armor ;change armor
959 inc (hl) ;increase HPs by one
960 jp disp_icons ;display and return
963 jr nz,select3 ;no, carry on
964 ld (hl),a ;reset pickups
966 ld (torp_occ),a ;ready torpedoes
967 jp disp_icons ;display 'n return
970 jr nz,select4 ;no, carry on
971 ld (hl),a ;reset pickups
976 jp nc,disp_icons ;>=10
989 jp disp_icons ;display n return
992 jr nz,select5 ;no, carry on again
993 ld (hl),a ;reset pickups
995 ld (your_weapon),a ;ready laser
996 jp disp_icons ;display + return
999 jr nz,select6 ;no, carry on once more
1000 ld (hl),a ;reset pickups
1002 ld (your_multiples),a
1005 jp disp_icons ;display, return
1007 ld (hl),0 ;reset pickups
1008 jp disp_icons ;display/return
1010 ;------------------------- fire bullet ----------------------------------------
1013 ld hl,RanPos ;random
1014 inc (hl) ;update random counter
1017 ld a,(hl) ;just_fired
1018 cp 5 ;already pressed?
1019 ret z ;return when already pressed (=5)
1020 inc (hl) ;otherwise increase counter (0 to 4 >> 1 to 5)
1021 ld a,(your_weapon) ;if you have bullets.....
1024 ld (hl),5 ;.....then can't fire next turn (go to 5 imm.)
1027 ld hl,(x) ;yes: first fire from ship position (x)
1028 ld (firex),hl ;set firepos
1029 ld a,(your_multiples) ;any multiples?
1031 jr z,fireany ;then just fire somethin'
1032 cal fireany ;and blast
1033 ld hl,(my) ;then, fire from multiple position (mx)
1036 ld (firex),hl ;set firepos
1037 ;blast again and <ret>
1041 ld a,(your_weapon) ;do you have laser?
1071 ld hl,torp_occ ;torpedo...
1072 ld a,(hl) ;load torpInfo
1073 dec a ;do you have (unused) torpedoes?
1074 ret nz ;nope (a must be 1)
1075 ld (hl),2 ;yes; use torpedo
1076 ld (torp_pos),de ;save torpedo position (in de)
1080 fire_laser: ;yes, fire that laser instead
1081 ld a,(firex) ;a = your x-pos
1084 ld hl,GRAPH_MEM ;save-location
1085 ld a,(firey) ;y-coord
1086 add a,3 ;at middle of your ship (y+3)
1087 ld e,a ;save laser-y in e
1091 rl b ;b (=0) =b*2+overflow (if y>32 then bc=bc+256)
1092 add a,a ;y*16 (width of screen)
1093 rl b ;b=b*2+overflow (if y>64 then bc=bc+512)
1094 inc a ;8 pixels to right (a=even so no overflow)
1099 add a,d ;a = (Y*16+X/8) mod 256 (c set on overflow)
1100 jr nc,_nolc ;jump if no carry = no overflow = a<=255
1101 inc b ;a>255 so increase bc by 256
1102 _nolc: ld c,a ;c = (Y*16+X/8) mod 256
1103 add hl,bc ;bc = Y*16+X/8
1105 ld a,15 ;128/8=16=screen width ** minus one (inc a ^^)
1106 sub d ;minus x-start (d=X/8)
1110 inc hl ;Go to next byte
1113 ld a,(just_fired) ;fired for how long
1115 ret nz ;then do damage, otherwise quit
1119 ld d,a ;d was divided, so reload the laser-x
1121 check_laserhits: ;de = (x,y)
1125 laserhits: ;Hits with normal enemies
1130 jr z,nolashit ;no hit when enemy_occ <> 2/3
1134 or a ;enemy #0 = pickup
1135 jr z,nolashit ;yes: don't destroy
1140 jp m,nolashit ;no hit when enemy is left of you
1145 jr z,enemy_lashit ;a-e=0 = laser on top line of enemy = hit
1146 jr nc,nolashit ;a-e>0 = enemy above laser = no hit
1147 add a,5 ;add enemy height
1148 jp p,enemy_lashit ;a-e>0 = hit
1152 inc hl ;go to next enemy
1156 djnz laserhits ;check all enemies
1171 jr z,found_ybullet ;0 = no bullet here
1173 djnz find_ybullet ;look next bullet
1177 ld (hl),c ;use the bullet and set correct bullet-type
1178 ld a,(firex) ;your x-pos
1179 add a,5 ;place bullet in front of you
1180 inc hl ;go to bullet-x
1183 ld a,(firey) ;your y-pos
1184 add a,(ix+1) ;place bullet at the middle of your ship
1185 inc hl ;go to bullet-y
1189 ;------------------------ handle bullets --------------------------------------
1195 cp (hl) ;off screen? (x>128-5)
1198 add a,b ;move 2 2 the right
1199 ld (hl),a ;save new pos.
1239 ld (hl),0 ;dump this bullet!
1243 Handle_bullets: ;&&&>>
1250 ld (temp1),hl ;needed for check_bullethits
1255 jp z,next_ybullet ;bulletType=0 >> no bullet
1260 cal bullet_left ;move bullet left
1265 cal putsprite ;display bullet
1268 cal check_bullethits
1276 djnz scan_bullets ;next bullet (loop)
1279 ;--------------------------- check bullethits --------------------------------
1281 check_bullethits: ;INPUT: de=X,Y; (temp1)=bullet
1285 hit_enemies: ;Hits with normal enemies
1290 jr z,nohit ;no hit when enemy_occ <> 2/3
1294 or a ;enemy #0 = pickup
1295 jr z,nohit ;yes: don't destroy
1321 ld (hl),$00 ;remove bullet
1332 djnz hit_enemies ;check next enemy
1341 and %11111100 ;occ/4 = HP left ;<srl a\srl a
1342 jr nz,hpleft ;not zero -> jump
1343 ld (hl),%01 ;set to explode
1345 ld a,(pickuptimer) ;counts enemies destroyed
1346 dec a ;enough destroyed for a pickup?
1347 jr nz,pickupdone ;otherwise just explode
1348 ld (hl),%00000110 ;change it into a pickup (with 2 HP)
1349 ld a,18 ;reset enemies counter (18 hits = next)
1351 ld (pickuptimer),a ;save new enemiescounter value
1353 ld (hl),$00 ;explosionFrame 0
1355 ld hl,1 ;increase score by one
1361 sub %00000100 ;decrease HP by one
1365 ;--------------------------- handle torpedo ----------------------------------
1370 ret m ;return if occ=0/1
1372 ld hl,torp_pos ;x-position
1373 ld a,(hl) ;load in a
1375 cp 125 ;right edge reached
1376 jr nc,remove_torp ;remove if x>125
1377 ld (hl),a ;save new x
1383 cp 56 ;bottom reached
1384 jr nc,remove_torp ;remove if y>40
1385 ld (hl),a ;save new y
1390 cal putsprite ;display torpedo
1392 jp check_bullethits ;check for hits with enemies
1399 ;--------------------------- level events -------------------------------------
1402 ld hl,nextevent ;time to next event <ld a,(nextevent)
1403 dec (hl) ;decrease counter <dec a
1404 ld a,(hl) ;look at counter <ld (nextevent),a
1405 or a ;has it reached zero?
1406 ret nz ;nope: get outta here!
1408 ld a,(eventtime) ;enemy frequency (lvl)
1409 ld (nextevent),a ;set time to next event
1411 dec (hl) ;update enemy-counter
1413 ld a,(hl) ;look at counter
1414 or a ;has it reached 0?
1415 jp z,Next_level ;yes: level finished
1416 dec a ;has it reached 1?
1417 jr z,standby_event ;yes: wait until no enemies present/left
1418 dec a ;has it reached 2?
1419 jr z,place_boss ;yep: place the BigBossTM!
1420 dec a ;has it reached 3?
1421 jr nz,do_event ;nope: >3 = place an enemy
1422 inc hl ;nextevent located behind eventleft
1423 ld (hl),123 ;set delay
1424 ret ;don't place any more enemies
1430 ld (level_enemy),a ;set new enemy (boss)
1433 ld (level_move),a ;set boss movement (very slow)
1436 ld (level_fire),a ;set rapid fire
1449 or a ;0 = no enemy present
1466 or a ;0 = no enemy present
1470 ld a,(level_enemy) ;enemy type to place (lvl)
1471 ld hl,enemy00 ;enemy 1 specs
1475 ld b,0 ;bc = enemy nr.
1476 add hl,bc ;hl = enemy specs
1477 ld a,(hl) ;load hitpoints+occ of this enemy class
1480 inc hl ;next enemyInfo byte
1481 inc de ;next byte of current enemy
1482 ld a,(hl) ;load enemy class (nr)
1483 ld (de),a ;enemy type
1489 ld a,128 ;appear at right edge of screen
1490 sub (ix) ;minus the width of this enemy (not offscreen)
1491 ld (de),a ;= x-position
1494 inc hl ;where to place??
1495 ld a,(hl) ;load placeInfo
1497 jr z,random_enemy ;yes: create random value <51 in a
1499 jr z,lure_enemy ;yes: create a 100% luring enemy
1501 halflure_enemy: ;yes (of course it is): pick one (50% lure)
1502 ld a,(timer) ;look at frame-number
1503 and %00000001 ;make random if odd frame nr.
1504 jr nz,random_enemy ;1st possibility: random enemy
1505 lure_enemy: ;2nd possibility: luring enemy
1506 ld a,(y) ;place at same y-pos as YOUR ship
1510 ld b,e ;b will be added to random-value
1511 cal Random50 ;make a (in a) random value 0-51
1513 ypos_OK: ;random value successfully created
1514 ld (de),a ;save y-position
1516 ld hl,add2enemy-3 ;offset to xtra enemy info
1517 add hl,de ;hl points to <xtra info: move>
1518 ld (hl),1 ;set move-counter to 1
1519 inc hl ;hl to <xtra info: fire>
1524 ld a,1 ;set time-to-fire to 1 frame (fires directly)
1527 ld a,(level_fire) ;set "ttf" to normal nr of frames
1530 inc hl ;hl to <xtra info: bullettype>
1532 inc hl ;hl to <xtra info: bullettype>
1538 ;--------------------------- enemy fires --------------------------------------
1540 Enemy_fires: ;de = x,y
1550 jr z,found_ebullet ;0 = not used
1551 inc hl \ inc hl \ inc hl
1552 djnz find_ebullet ;look next bullet
1565 ld b,%1011 ;yourY-bulY = negative (=bullet below you)
1568 ld b,%1001 ;yourY-bulY = even more negative (going up)
1573 ld b,%1010 ;bullet going down
1575 jp m,bulletok ;even more going down
1579 ; ld a,c ;load bullet type
1580 ; add a,a ;type*2 %..Btype.
1581 ; add a,a ;type*4 %.Btype..
1582 ; add a,a ;type*8 %Btype...
1583 ;add bullet direction %BtypeDir
1584 ld (hl),b ;set bullet direction
1586 ld (hl),d ;set x-pos
1588 ld (hl),e ;set y-pos
1591 ;----------------------------- enemy bullets ----------------------------------
1599 ld a,(hl) ;load bulletType in a
1601 jr nz,enemy_bullet ;no: handle bullet
1603 pop hl ;do not move the <pop hl>
1605 inc hl \ inc hl \ inc hl
1612 ld a,(hl) ;check if it has reached the left side of scrn
1613 and %11111110 ;it is <2 (0 or 1)?
1614 jr z,remove_ebullet ;yes, remove bullet
1615 dec (hl) ;move one left
1616 dec (hl) ;and another one
1620 ld a,b ;restore type
1621 cp %1100 ;&&& use <bit ?,a>
1622 jr z,ebullet_common ;type %1100: normal bullet
1624 jr z,ebullet_down ;type %1000: moving down
1626 jr z,ebullet_up ;type %1001: moving up
1635 jr z,ebullet_down ;type %1010: moving down 50%
1636 ;type %1011: moving up 50%
1653 ld ix,spr_bullete1 ;display enemy bullet
1659 jr nz,next_bullet ;0 = you're normal
1679 cal damage_you ;HIT!!
1681 pop hl ;hl could be destroyed by damage_you
1682 ld (hl),0 ;bullet > unused
1683 jr next_bullet+1 ;next bullet (SKIP THE <POP HL> = one byte)
1685 ;--------------------------- handle enemies -----------------------------------
1689 ld b,nrenemies ;handle all enemies
1697 jr z,next_enemy ;occ "no enemy" 0
1699 jr z,exploding_enemy ;occ "exploding" 1
1700 ld b,a ;b=2 if moving, otherwise b=1
1702 normal_enemy: ;occ "normal" 2 or "moving" 3
1704 ld c,(hl) ;c = enemy type = de
1710 jr c,remove_enemy ;off screen
1711 jr z,remove_enemy ;"
1716 ld a,b ;moving state was stored in b earlier
1718 cal nz,moving_enemy ;2 = moving enemy
1722 ld (hl),d ;store new x
1723 ld a,c ;a = enemy type
1724 or a ;type 0? (pickup)
1725 jr nz,check_enemyfire ;no, a normal enemy; let em fire
1726 ld a,(timer) ;load time
1727 and %1 ;move left once every 2 turns
1728 jr z,firing_done ;don't move now
1729 inc d ;increase x-position (don't move this turn)
1730 inc (hl) ;and save it
1731 jr firing_done ;continue
1734 ld bc,add2enemy+1-2 ;offset of <xtra enemy info: fire>
1735 add hl,bc ;go there (@hl)
1736 dec (hl) ;decrease counter till next blast
1737 ld a,(hl) ;load new counter
1738 or a ;has it reached zero?
1739 jr nz,firing_done ;finished if not
1741 ld a,(level_fire) ;re-set counter for next blast
1742 ld (hl),a ;save time to fire
1743 inc hl ;next byte = bullettype
1744 ld c,(hl) ;c = bullet type
1745 psh de ;save registers for firing-use
1746 cal Enemy_fires ;fires bullet
1747 pop de ;restore (destroyed by Enemy_fires)
1749 cal putwidesprite ;display sprite @ix
1761 ld (hl),$0000 ;bye bye enemy
1769 cal explosion_stuff ;display explosion
1774 jr z,remove_enemy ;remove when at last frame
1776 ld (hl),a ;next frame
1779 ;--------------------------- moving enemies -----------------------------------
1784 jr z,movetype_updown ;type 0
1786 jr z,movetype_vslow ;1
1788 jr z,movetype_fast ;2
1790 jr z,movetype_vfast ;3
1792 jr z,movetype_smart ;4
1794 jr z,movetype_lure ;5
1796 jr z,movetype_slowlure ;6
1798 jr z,movetype_stoplure ;7
1800 ; jr z,movetype_fulllure ;8
1820 jr movetype_slowlure
1850 or a ;reset carry flag
1869 pop hl ;restore stack (no ret used)
1870 jp remove_enemy ;remove this enemy (off screen)
1883 or a ;reset carry flag
1886 ld a,(hl);&&&ld a,e ;load current y-position
1889 moveup: dec a ;decrease y-pos (=move up)
1890 ret m ;don't move off the screen (y<0)
1891 dec e ;save new y-pos
1894 inc a ;increase y-pos
1895 cp 55 ;compare with bottom
1896 ret nc ;return if it has passed that line (>40)
1897 inc e ;otherwise save new position
1900 ;--------------------------- check collision ----------------------------------
1903 ld hl,(x) ;e = X, d = Y
1904 ld de,$0707 ;add 7 to both d and e
1907 ld e,l ;e = X+7, d = Y+7
1910 ld b,nrenemies ;check all 20 enemies
1915 jr z,check_next ;2 or 3 = ok
1918 collide_enemy: ;&&& include in Handle_enemy proc
1924 ld a,(hl) ;check x match
1925 sub e ;enemy position minus yours minus 7
1932 ld a,(hl) ;check y match
1933 sub d ;same as with x-check
1943 ld hl,2 ;increase score by 2
1947 ld a,(hl) ;load enemy type
1949 jr nz,collide ;enemy when <>0
1952 ld hl,your_pickup ;your pickups
1957 ld a,1 ;yes: reset to pickup 1
1960 cal disp_icons ;display altered pickupicons
1963 dec hl ;to enemy occ
1964 xor a ;set to 0 = gone
1966 jr check_next ;all done, next..
1969 ld (hl),%01 ;set to explode
1971 ld (hl),0 ;explosionFrame 0
1991 djnz check_collision
1994 ;--------------------------- story -------------------------------------------
2039 .db $21,$1d,"Cosmic year 6716" ,0,0,$1d,$06
2040 .db $1b,$1d,"storyline coming soon..." ,0,0,$1d,$06
2041 .db $09,$19,"the Nemesis saga continues",0,1
2042 .db $2e,$21,"with NEMESIS 86" ,0,1
2043 .db $52,$36,"by Shiar" ,0,0,$19,$23
2045 ;--------------------------- SFX ---------------------------------------------
2055 DoSFX: ;ins: a=beginLine b=nrOfLines
2060 ld a,(curline) ;get line number
2061 inc a ;go to the next line
2062 ld (curline),a ;update
2071 ld b,h ;save hl for later
2075 add hl,de ;go to ymin
2082 ld a,(curline) ;Calculate how many lines to draw
2088 SFXdisp: ;display this frame on screen
2089 ld a,b ;psh b (a will not be used)
2090 ld bc,16 ;one line (=16 bytes, you'd know by now)
2091 ldir ;display (copy actually)
2092 ld bc,-16 ;go up one line (not on screen)
2093 add hl,bc ;so the same line will be displayed
2095 djnz SFXdisp ;repeat until whole screen is displayed
2106 ;--------------------------- show icon ----------------------------------------
2109 ld (hl),a ;draw one piece of the divider-line
2110 inc hl ;move right (8 pixels = 1 byte)
2111 djnz drawline ;repeat (16bytes * 8pixels =128= screen width)
2115 ld hl,VIDEO_MEM+(16*56);56 rows down = eight rows from bottom
2116 ld (PutWhere),hl ;place icons at bottom of normal screen
2117 ld b,16 ;draw 16x (screen width)
2118 ld a,%11111111 ;horizontal line mask
2119 cal drawline ;draw divider-line
2121 ld b,16*7 ;draw 16x (screen width) 7x (height)
2122 xor a ;blank line mask
2123 cal drawline ;clear scorebar
2127 ld ix,spr_icon01 ;armorIcon
2128 ld de,$1901 ;icon #1
2129 cal putwidesprite ;display icon
2130 cal disp_armor ;display value
2136 ld ix,spr_icon02 ;torpedoIcon
2138 ld de,$2901 ;icon #2
2139 cal putwidesprite ;display
2141 ld ix,spr_icon03 ;bulletIcon
2142 ld de,$3901 ;icon #3
2143 cal putwidesprite ;display icon
2144 ld hl,$3945 ;position to display bullet-type digit
2145 ld a,(your_weapon) ;digit
2146 dec a ;minus one (1=laser)
2147 cal _disp_armor ;display digit
2149 ld ix,spr_icon00 ;emptyIcon
2153 ld ix,spr_icon04 ;laserIcon
2155 ld de,$4901 ;icon #4
2158 ld ix,spr_icon00 ;emptyIcon
2159 ld a,(your_multiples)
2164 ld de,$5901 ;icon #5
2167 ld ix,spr_dividerline
2171 ld a,(your_pickup) ;pickups taken
2172 add a,a ;picks*2 (sets z-flag)
2173 jr z,iconsdone ;return if no pickups
2178 ld d,a ;y-pos = picks * $10 + $0a (19,29,39,49,59)
2179 ld e,$01 ;x-pos = bottom (1a01,2a01,3a01,4a01,5a01)
2184 ld hl,GRAPH_MEM ;normal game-screen
2185 ld (PutWhere),hl ;set sprite-position to normal screen
2189 ld hl,$3925 ;Display Armor left
2190 ld a,(your_armor) ;load armor left
2192 ld (_penCol),hl ;place @ armorIcon
2193 add a,'0' ;make digit
2194 cal _vputmap ;display char
2198 ld hl,$3900 ;display Lives
2199 ld (_penCol),hl ;bottom left
2206 ld a,(your_lives) ;nr of lives in a
2207 add a,'0' ;make digit
2210 cal _vputs ;display on screen
2213 ;--------------------------- proc ---------------------------------------------
2216 cal Random50 ; a = 0..50
2220 add hl,hl ;hl = 1..51 * 2
2221 add hl,hl ;hl = 1..51 * 4
2222 add hl,hl ;hl = 1..51 * 8
2223 add hl,hl ;hl = 1..51 * 16 (left side at random y)
2224 dec hl ;hl = 1..51 * 16 (" at right side of screen)
2226 add hl,de ;position on screen
2231 cp 51 ;y may not be more than 50
2233 and %00111111 ;a = 0..63
2236 add a,13+(50-12) ;a = -13..-1 >=> 0..12 >=> 39..50
2240 ld a,(RanPos) ;a handy random-var.
2241 ld hl,x ;add your x-coord for randomness
2243 inc hl ;add your y-coord for randomness
2245 ld (RanPos),a ;save altered random-var
2246 ret ;RanPos also in #a
2256 find_sprite: ;destroyed: de ix
2258 ld e,(hl) ;e = enemy type
2260 ld hl,sprites ;hl = @sprites offset-table
2261 add hl,de ;points to offset of current enemy offset
2262 ld e,(hl) ;de = @enemy offset
2265 ld ix,spr_enemy00 ;first enemy sprite
2266 add ix,de ;add offset for current enemy
2267 add ix,de ;twice (offset stored as offset/2)
2272 ld hl,VIDEO_MEM ;screen location (top left)
2275 ld bc,1024-1 ;do it 1024 times = entire screen
2277 set 3,(iy+5) ;set white on black
2284 jr nz,waitnokeypressed
2322 ;--------------------------- game over / new game / death ---------------------
2324 .db 0,"!<>^",0,0,0,0
2325 .db 0,"xtoje0",0 ;enter..clear
2326 .db " wsnid9",0 ;(-)..custom
2327 .db "zvrmhc8",0 ;dot..del
2328 .db "yuqlgb7x" ;0..xvar
2329 .db 0,"-pkfa6'" ;on..alpha
2330 .db "54321.",0,0 ;F5..more
2336 ld hl,own_name-1 ;find own variable
2337 rst 20h ;cal _ABS_MOV10TOOP1
2338 rst 10h ;cal _FINDSYM
2339 ret c ;not found? who cares...
2342 ld hl,4+stored_data_start-_asm_exec_ram
2343 add hl,de ;hl=pointer to data in original prog
2345 cal _SET_ABS_DEST_ADDR
2347 ld hl,stored_data_start
2348 cal _SET_ABS_SRC_ADDR
2349 ld hl,stored_data_end-stored_data_start
2350 cal _SET_MM_NUM_BYTES
2351 jp _mm_ldir ;save done (cal \ ret)
2354 pop hl ;=ret (game_over was called from a procedure)
2356 cal BLACKLCD ;clear screen
2357 cal waitnokeypressed
2359 ld (_curRow),hl ;center
2361 cal _puts ;display "GAME OVER"
2411 cal waitnokeypressed
2442 xor a ;clear a (Ahl will be displayed)
2443 ld hl,$1006 ;bottom-1 right
2444 ld (_curRow),hl ;set
2445 ld hl,(score) ;your score
2446 cal _dispahl ;display it (a=0)
2448 ld hl,$314b ;bottom-1 right before score ^^
2449 ld (_penCol),hl ;set
2450 ld hl,txt_score ;"Score"
2451 cal _vputs ;display (small)
2453 ld hl,$1007 ;bottom right
2454 ld (_curRow),hl ;set
2455 ld hl,(hiscore) ;hi-score
2456 cal _dispahl ;display
2457 ld hl,$3946 ;bottom right before hiscore ^^
2458 ld (_penCol),hl ;set
2459 ld hl,txt_hiscore ;"Hiscore"
2460 cal _vputs ;display (small)
2465 ld hl,VIDEO_MEM+(49*16)-1
2471 cal _getkey ;wait for keypress
2472 jp quit ;restore some things and return to TI-OS/shell
2476 ld (score),a ;reset score
2477 ld (score+1),a ;reset score
2478 ld (torp_occ),a ;no torpedoes
2479 ld (your_weapon),a ;no laser
2480 ld (your_pickup),a ;reset pickups
2481 ld (your_multiples),a ;no multiples
2483 ld (level),a ;reset level nr
2484 ld hl,level01 ;set level pointer to level#1
2485 ld (levelp),hl ;reset level pointer
2487 ld (your_weapon),a ;default weapon
2489 ld (your_lives),a ;3 lives (4 will be decreased @ You_die)
2490 ld (pickuptimer),a ;next pickup after 4 enemies destroyed
2493 ld a,(weapons+1) ;max number of bullets (varies per weap.class)
2498 dec (hl) ;decrease lives
2499 ld a,(hl) ;load lives left
2500 inc a ;if lives=0ffh then a=0
2501 jp z,game_over ;if so, game's over
2504 ;--------------------------- next level ---------------------------------------
2507 ld hl,level ;level number
2512 ld hl,(levelp) ;level pointer
2513 ld bc,5+32+4+3 ;advance one level
2514 add hl,bc ;update to point to next level
2515 ld (levelp),hl ;save
2517 ld h,0 ;increase score....
2518 ld l,a ;by level number
2521 cal scoreInc ;update score
2525 ld (nextevent),a ;time to first enemy appearance
2527 ld hl,(levelp) ;level pointer
2528 ld a,(hl) ;load new level-enemy type
2529 ld (level_enemy),a ;set level-enemy
2531 ld a,(hl) ;load new appearance-time
2532 ld (eventtime),a ;set
2534 ld a,(hl) ;load nr of enemies in this level
2535 ld (eventleft),a ;set nr of events left
2537 ld a,(hl) ;movement of enemies in this level
2538 ld (level_move),a ;do it
2540 ld a,(hl) ;how frequent the enemies fire a bullet
2541 ld (level_fire),a ;consider it done
2558 ld (timer),a ;reset time
2559 ld hl,your_occ ;hl = your_occ
2560 ld (hl),a ;reset your ship (not exploding)
2561 inc hl ;hl = your_inv
2562 ld (hl),25 ;set 25*4=100 frames invulnerable
2563 ld hl,x ;begin position x=...
2564 ld (hl),a ;...=a=0=left
2566 ld a,24 ;...=24=middle
2571 jr z,torpsclear ;then just continue (=0)
2572 ld a,1 ;if so, set to "ready to fire" (=1)
2575 ld de,$0018 ;x=0, y=24 (like you..)
2576 ; cal Place_multiples ;place all multiple-positions at (0,24)
2578 ld hl,enemies ;remove all enemies and bullets
2579 ld (hl),0 ;clear first byte
2580 ld de,enemies+1 ;copy this to the next byte
2581 ld bc,(add2enemy*2)+((nrybuls+nrebuls)*3)-1
2582 ldir ;clear enemy-info + enemiesxtra + all bullets
2584 ;--------------------------- setup game ---------------------------------------
2589 ld (_curRow),hl ;center
2591 cal _puts ;display "LEVEL "
2602 cal _putc ;display second digit
2604 cal _putmap ;display first digit
2607 ld (_curRow),hl ;display lives left below level nr
2608 ld hl,txt_lives ;bar text: "Lx0"...
2609 ld a,(your_lives) ;lives left
2610 add a,'0' ;make value
2611 ld (txt_lives+3),a ;add to text
2612 cal _puts ;display the string
2613 res 3,(iy+5) ;set white on black
2615 cal _getkey ;wait for keypress
2617 cal CLEARLCD ;clear screen
2618 cal disp_icons ;display bottom icons
2622 cal Random5016 ;a = (0..50)*16 = random y-pos
2623 ld a,b ;a = b = star nr. = 1..7
2624 add a,a ;a = 2b = 2..14
2626 ld e,a ;de = a = 2-14
2627 add hl,de ;add to random y => random pos anywhere
2629 ld (ix),l ;save x-pos (l)
2630 ld (ix+1),h ;save y-pos (h)
2631 inc ix \ inc ix ;next star
2632 djnz placestars ;repeat for all stars
2635 ;--------------------------- putsprite ----------------------------------------
2636 ;--------------------------- de =(X,Y) ----------------------------------------
2639 .db 128,64,32,%10000,%01000,%00100,%00010,%00001
2642 and %00000111 ;a = X mod 8 = bit nr. to mask
2643 ld hl,offsets_table ;pixel mask table
2646 add hl,bc ;add to table
2647 ld a,(hl) ;a = pixel mask
2648 ld (_smc1+1),a ;alter pixel mask
2650 ld hl,GRAPH_MEM ;save-location
2655 rl b ;b (=0) =b*2+overflow (if y>32 then bc=bc+256)
2656 add a,a ;y*16 (width of screen)
2657 rl b ;b=b*2+overflow (if y>64 then bc=bc+512)
2660 srl d ;d/8 (8 bits in byte) ** c is set when overflow
2661 add a,d ;a = (Y*16+X/8) mod 256
2662 jr nc,_n1 ;jump if no carry = no overflow = a<=255
2663 inc b ;a>255 so increase bc by 256
2664 _n1: ld c,a ;c = (Y*16+X/8) mod 256
2665 add hl,bc ;bc = Y*16+X/8
2669 _oloop: psh bc ;Save # of rows
2670 psh hl ;Save screen address
2672 ld c,(ix+2) ;Load one line of image
2674 _smc1: ld a,1 ;Load pixel mask
2675 _iloop: sla c ;Test leftmost pixel
2676 jr nc,_noplot ;See if a plot is needed
2677 ld e,a ;OR pixel with screen
2682 jr nc,_notedge ;Test if edge of byte reached
2683 inc hl ;Go to next byte
2686 pop hl ;Restore address
2687 ld bc,16 ;Go to next line
2689 pop bc ;Restore data
2693 ;--------------------------- putbigsprite -------------------------------------
2726 woloop: psh bc ;Save # of rows
2727 psh hl ;Save screen address
2729 ld c,(ix+2) ;Load one line of image
2731 wsmc1: ld a,1 ;Load pixel mask
2732 wiloop: sla c ;Test leftmost pixel
2733 jr nc,wnoplot ;See if a plot is needed
2734 ld e,a ;OR pixel with screen
2740 jr nc,wnotedge ;Test if edge of byte reached
2741 inc hl ;Go to next byte
2747 pop hl ;Restore address
2748 ld bc,16 ;Go to next line
2750 pop bc ;Restore data
2765 ;------------------------------------------------------------------------------
2766 ;------------------------------- sprites --------------------------------------
2767 ;------------------------------------------------------------------------------
2770 .db 7,7 ;ship alpha class
2771 .db %01111000 ; ████
2773 .db %01111100 ; █████
2774 .db %11110010 ; ████ █
2775 .db %01111100 ; █████
2777 .db %01111000 ; ████
2779 .db 7,7 ;ship alpha class
2790 .db %01010100 ; █ █ █
2791 .db %10100010 ; █ █ █
2792 .db %01010100 ; █ █ █
2797 ; .db 7,7 ;ship beta class
2798 ; .db %11100000 ; ███
2799 ; .db %11110000 ; ████
2800 ; .db %01111100 ; █████
2801 ; .db %01110010 ; ███ █
2802 ; .db %01111100 ; █████
2803 ; .db %11110000 ; ████
2804 ; .db %11100000 ; ███
2806 ; .db 7,7 ;ship beta class
2808 ; .db %10100000 ; █ █
2809 ; .db %01010100 ; █ █ █
2810 ; .db %00100010 ; █ █
2811 ; .db %01010100 ; █ █ █
2812 ; .db %10100000 ; █ █
2817 .db %01111000 ; ████
2818 .db %11111100 ; ██████
2819 .db %11111100 ; ██████
2820 .db %01111000 ; ████
2823 .db 5,3 ;your bullets
2824 .db %00110000 ; ░▒▓█▒
2825 .db %11111000 ; ░▒▓████▒
2826 .db %00110000 ; ░▒▓█▒
2829 .db %11110000 ; ░▒▓███▒
2830 .db %11111000 ; ░▒▓████▒
2831 .db %11110000 ; ░▒▓███▒
2835 .db %11110000 ; ████
2839 .db 4,3 ;enemy bullets
2840 .db %01100000 ; ▒█▓▒░
2841 .db %11110000 ; ▒███▓▒░
2842 .db %01100000 ; ▒█▓▒░
2844 ;---------------------------------------- explosion -------------------------------------------
2850 .db %00111110 ; █████
2851 .db %01010110 ; █ █ ██
2857 .db %01001110 ; █ ▒███
2858 .db %10111110 ; █ █████
2859 .db %01001111 ; █ ▒████
2861 .db %00011010 ; ██ █
2864 .db %10110000 ; █ ██
2865 .db %01001110 ; █ ███
2866 .db %10110101 ; █ ██▒█▒█
2867 .db %01000101 ; █ ▒█▒█
2868 .db %00111110 ; █████
2869 .db %01011010 ; █ ██ █
2872 .db %00101010 ; ▒ █▒█ █
2873 .db %01000110 ; █ ▒██
2874 .db %10110101 ; █ ██ █ █
2875 .db %01100110 ; ██ ██▒
2876 .db %00111100 ; ████▒
2877 .db %01011001 ; █ ██ ▒█
2880 .db %01000000 ; █▒ ▒ ▒
2881 .db %00100101 ; ▒█ █▒█
2882 .db %00010100 ; ▒ ▒█ █ ▒
2883 .db %01000100 ; █▒ █
2884 .db %00010010 ; ▒█▒▒█
2885 .db %10011010 ; █▒ ██ █▒
2889 .db %00100000 ; ▒█ ▒ ▒
2890 .db %00000001 ; ▒ ▒ █
2892 .db %00100010 ; █▒ █
2893 .db %01001000 ; ▒█ ▒█ ▒
2896 .db %00001000 ; ▒ █▒
2897 .db %11000010 ; ██ ▒ █
2899 .db %00100000 ; ▒█ ▒
2900 .db %00000001 ; ▒ ▒█
2901 .db %00110000 ; ▒██▒
2905 .db %00000000 ; ▒▒ ▒
2909 .db %00100100 ; █▒ █
2920 ;--------------------------------------- bar -----------------------------------
2923 .db 16,7 ;selected .......:
2924 .db %11111111 ; ████████
2930 .db %11111111 ; ████████
2932 .db 16,7 ;selected .......:.......:
2933 .db %11111111,%11111111 ; ████████████████
2934 .db %11000000,%00000001 ; ██ █
2935 .db %11000000,%00000001 ; ██ █
2936 .db %11000000,%00000001 ; ██ █
2937 .db %11000000,%00000001 ; ██ █
2938 .db %11000000,%00000001 ; ██ █
2939 .db %11111111,%11111111 ; ████████████████
2941 .db 16,7 ;unused .......:.......:
2942 .db %10101010,%10101010 ; █ █ █ █ █ █ █ █
2943 .db %11010101,%01010101 ; ██ █ █ █ █ █ █ █
2944 .db %10101010,%10101010 ; █ █ █ █ █ █ █ █
2945 .db %11010101,%01010101 ; ██ █ █ █ █ █ █ █
2946 .db %10101010,%10101010 ; █ █ █ █ █ █ █ █
2947 .db %11010101,%01010101 ; ██ █ █ █ █ █ █ █
2948 .db %10101010,%10101010 ; █ █ █ █ █ █ █ █
2950 .db 16,7 ;armor ; .......:.......:
2951 .db %10001111,%10000000 ; █ █████
2952 .db %10010000,%01000000 ; █ █ █ ▒▒▒
2953 .db %10101110,%00100000 ; █ █ ███ █ ▒▒▒
2954 .db %10100111,%10100000 ; █ █ ████ █ ▒▒▒
2955 .db %10101110,%00100000 ; █ █ ███ █ ▒▒▒
2956 .db %10010000,%01000000 ; █ █ █ ▒▒▒
2957 .db %10001111,%10000000 ; █ █████
2959 .db 16,7 ;torpedo .......:.......:
2960 .db %10111000,%00010101 ; █ ███ █ █ █
2961 .db %10011100,%00010101 ; █ ███ █ █ █
2962 .db %10111000,%01001010 ; █ ███ █ █ █
2963 .db %10000000,%11101010 ; █ ███ █ █
2964 .db %11100001,%11100101 ; ███ ████ █ █
2965 .db %10011000,%11110101 ; █ ██ ████ █ █
2966 .db %11100110,%00110010 ; ███ ██ ██ █
2968 .db 16,7 ;bullets .......:.......:
2969 .db %10000000,%11000000 ; █ ██
2970 .db %10000011,%11100000 ; █ █████ ▒▒▒
2971 .db %10011000,%11000000 ; █ ██ ██ ▒▒▒
2972 .db %11111100,%00000000 ; ██████ ▒▒▒
2973 .db %10011000,%11000000 ; █ ██ ██ ▒▒▒
2974 .db %10000011,%11100000 ; █ █████ ▒▒▒
2975 .db %10000000,%11000000 ; █ ██
2977 .db 16,7 ;laser .......:.......:
2978 .db %10000000,%00000000 ; █
2979 .db %10110010,%10000000 ; █ ██ █ █
2980 .db %10111011,%00000000 ; █ ███ ██
2981 .db %10011101,%11111111 ; █ ███ █████████
2982 .db %10111011,%00000000 ; █ ███ ██
2983 .db %10110010,%10000000 ; █ ██ █ █
2984 .db %10000000,%00000000 ; █
2986 .db 16,7 ;multiple .......:.......:
2987 .db %10000011,%10000000 ; █ ███
2988 .db %10000001,%11100110 ; █ ████ ██
2989 .db %10000001,%11100000 ; █ ████
2990 .db %10000011,%10000000 ; █ ███
2991 .db %10011000,%00000000 ; █ ██
2992 .db %10111100,%11000011 ; █ ████ ██ ██
2993 .db %10011000,%00000000 ; █ ██
2996 .db 128,128,128,128,128,128,128 ;128 = %10000000
2998 ;---------------------------- texts -------------------------------------------
3000 txt_about: .db " v0.95.A22",127,"by Shiar",0
3001 txt_email: .db "shiar0@hotmail.com",0
3002 txt_menu1: .db "CONTINUE",0
3003 txt_menu2: .db "NEW GAME",0
3005 txt_level: .db "LEVEL ",0
3006 txt_gameover: .db "GAME OVER!",0
3007 txt_score: .db "Score",0
3008 txt_hiscore: .db "Hiscore",0
3009 txt_lives: .db "Lx0?",0
3011 txt_pressenter: .db "Enter to continue",0
3012 txt_teacher: .db "(2",Lpi,"*.95)/sin 13",0
3013 txt_teacherans: .db Lneg,"14.2063168184",0
3015 ;---------------------------- save data ---------------------------------------
3017 PutWhere .dw GRAPH_MEM ;where to put the wide sprites
3018 level .db $00 ;level number
3019 levelp .dw $0000 ;pointer to level data
3025 hiname .db "Shiar.95",0
3029 your_occ .db $00 ;0=normal 1..16=exploding
3030 your_inv .db $00 ;invincibility left
3031 your_armor .db $05 ;HP left
3032 your_lives .db $00 ;
3034 your_weapon .db $00 ;laser avail: 0=no, 1=yes
3035 your_multiples .db $00 ;multiples present
3036 torp_occ .db $00 ;torp.state: 0=unavail 1=avail 2=presnt
3037 torp_pos .dw $0000 ;torpedo position (x,y)
3039 #include nemesis0.z80
3041 ;----------------------------- logo -------------------------------------------
3044 .db %11111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00001011,%11111111,%11111111,%11111111,%11111000
3045 .db %01111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00011011,%11111111,%11111111,%11111111,%11110000
3046 .db %00111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00111011,%11111111,%11111111,%11111111,%11100000
3047 .db %00011111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%01111011,%11111111,%11111111,%11111111,%11000000
3048 .db %00000000,%00000000,%00000001,%00011110,%00010000,%00000000,%10000001,%00011110,%00010000,%000000001,%00000000,%00001000,%01000000,%00000000,%00000000,%00000000
3049 .db %00000000,%00000000,%00000011,%00011110,%00110000,%00000001,%10000011,%00011110,%00110000,%000000011,%00000000,%00011000,%11000000,%00000000,%00000000,%00000000
3050 .db %00000000,%00000000,%00000111,%00011110,%01110000,%00000011,%10000111,%00011110,%01110000,%000000111,%00000000,%00111001,%11000000,%00000000,%00000000,%00000000
3051 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
3052 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
3053 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
3054 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
3055 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
3056 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
3057 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
3058 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
3059 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000111,%11010001
3060 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00011011
3061 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010101
3062 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010001
3064 ;----------------------------- end --------------------------------------------
3070 ;------------------------------------------------------------------------------
3072 ; 0.94.A08 -- 08.X.99 -- size 4531 (4456)
3074 ; + starfield background scrolling left (2 layers (front and back))
3075 ; * enemies aim their bullets towards you: 5 different directions!
3076 ; # removed some unintended <add a,a> instructions
3077 ; * gamefield is now white on black instead of normal black on white!
3078 ; + enemies can also move slowly, fast, very fast, or 1st fast then slow
3079 ; # you can't fire when you're exploding
3080 ; + GROUND scrolling at bottom. You die if you hit the ground (!!!)
3081 ; (unlike the ground in version 0.925test there are NO bugs)
3082 ; + ceiling scrolling at top, just like the ground
3083 ; * ground and ceiling profile are different each level
3084 ; * ground and/or ceiling can be non-present (speeding up cause skipped)
3085 ; # no more BIG crash if enemies fire too much bullets ( >10)
3086 ; + frequency of enemies firing bullets differs per level
3087 ; * stars scroll at alternate speeds, different than any ship/pick (3/4)
3088 ; + special effect displaying titlescreen (stole from Spaze Invaders'83)
3089 ; * enemies can fire either directly on entering the level, or not
3090 ; + "tunnel" (playfield) can narrow/grow at random (depending on level)
3091 ; * minimum size of "tunnel" can be different per level
3092 ; + menu at startup. select "NEW GAME" and "LOAD GAME" with up/down
3093 ; - nemesis doesn't use the SpazeInvaders effect anymore (took too long)
3094 ; + choosing new game will display a demo first (text will be displayed
3095 ; with special effect [SI] saying the storyline will come soon)
3096 ; * levels altered to be more challenging and different (seven levels)
3097 ; # the usual bugs that come with new features removed (i think?)
3098 ; * you get 5 shield-points at start and after death
3100 ; 0.95.A13 -- 13.X.99 -- size 4656
3102 ; + BOSSES! at the end of a level a huge enemy will appear
3103 ; * bosses will move towards you, slowly. level=done when boss destroyed
3104 ; + normal enemies can also try to ram your ship (like bosses do)
3105 ; * when colliding with an enemy, his armor will decrease (if any)
3107 ; 0.95.A17 -- 17.X.99 -- size 4965
3109 ; # fix: bullets at right side weren't removed on time (1pix too late)
3110 ; * each level has it's own boss
3111 ; + your bullets can have different speeds/directions
3112 ; + third icon selects bullet-upgrade: single, faster, double, triple
3113 ; * number of bullets varies per bullet-class (type 1 is max. 2 bullets)
3114 ; * all temp. vars are stored in TEXT_MEM and TEXT_MEM2 (anti-crash:)
3116 ; 0.95.A18 -- 18.X.99 -- size 5052
3118 ; # vertical line next to score at game over screen removed (minor)
3119 ; # some unintended pixels at icon bar now gone (joy, joy)
3120 ; # number of bullets of a new weapon is loaded correctly
3121 ; # cleans GRAPH_MEM (Graph-screen) and TEXT_MEM (calculate screen)!
3122 ; # data not stored at TEXT_MEM2 but now at _asm_exec_ram+5100
3124 ; 0.95.A22 -- 22.X.99 -- size 5321
3126 ; * total size of enemy-sprites can now be 510 bytes (space = doubled!)
3127 ; # bullets hit enemies correctly that aren't 6x6; even the 16x10 bosses!
3128 ; * at g/o or nextlevel checks for keys released instead of waiting abit
3129 ; + name stored with hiscore (max. 8 chars, Shiar.95 by default)
3130 ; + when entering hi-name DEL goes back one char (with check 4 no chars)
3131 ; # program is reloaded at start so some score-bugs solved! (_asapvar=0)
3132 ; * at death, upgrades and pickups AREN'T removed! (just armor=0)
3133 ; # bullet is not displayed after being removed anymore
3134 ; # armor-icon stays hilighted when armor is decreased
3135 ; * when stars move off screen, they are placed at a NEW y-pos!
3136 ; * the starting x-positions of stars are not random, so the stars are
3137 ; spread all over screen. y is still random and changes during game
3138 ; * make_random functions smaller and used by different procs
3139 ; # MAJOR BUG! a "random" value was placed somewhere in mem thus
3140 ; creating bugs like unexplained loss of armor and stuff!
3143 ; + added - removed * changed # bug fixed