1 ;----------------------------------------------------------------------------
2 ;---------------------- NEMESIS ---------------------------------------------
3 ;----------------------------------------------------------------------------
5 ;by SHIAR | shiar0@hotmail.com | icq#43840958 | www.shiar.org
7 ;Description : cool arcade-shoot-em-up-game
8 ;Other games by author : Worm
9 ;This source should only be used for learning practises, do not
10 ;alter it, and certainly do not distribute an altered version!!
12 ;&&& marks uncertainties or things to optimize
14 ;---------------------- nemesis.z80 start -----------------------------------
17 #include "ti86asm.inc" ;standard ti86 romcalls
18 #include "ti86abs.inc" ;used to save hiscores and so
22 #define cal call ;just to make it harder for you to understand
23 #define psh push ; ^:D
24 #define dnz djnz ;Dec&Jump while NonZero becomes Do w.Non-Zero
26 ;GRAPH_MEM = $C9FA ;display buffer (virtual screen)
27 ;VIDEO_MEM = $FC00 ;tha big scareen
28 TEXT_MEM = _textShadow ;text buffer; C0F9-C1A0 (167/$A7 bytes)
30 _clrWindow = $4a86 ;_clrLCD and _clrScrn
31 _ex_ahl_bde = $45f3 ;exchange values between AHL and BDE
32 _shracc = $4383 ;like _shlacc but just the opposite :P
33 _dispahl = $4a33 ;display value in ahl <100000 (cheap TI)
34 _asapvar = $d6fc ;our own variable name (likely "nemesis")
36 storepos = _asm_exec_ram+7000 ;120 OF 165
37 storepos2 = _asm_exec_ram+7200 ;141 OF 167 9000 BYTES
39 ;---------------------- in-game vars ----------------------------------------
41 just_fired = storepos ; +0 ;counts how long a blast lasts
42 menuitem = storepos ; +0 ;used to store menu location
43 hiscorepos = storepos ; +0 ;entering hiscore name
45 x = storepos+1 ; +1 ;your ship's position
46 y = x+1 ; +2 ;your y-pos
47 firex = y+1 ; +3 ;(1 byte)
48 firey = firex+1 ; +4 ;(1 byte)
50 eventleft = storepos+5 ; +5 ;nr. of enemies still to come
51 nextevent = eventleft+1 ; +6 ;time to next event
52 level_enemy = nextevent+1 ; +7 ;enemy type
53 level_info = level_enemy+1 ; +8 ;info (see below)
54 level_move = level_info+1 ; +9 ;=
56 spacespace = storepos+19 ;+19
57 groundinfo = spacespace+1 ;+20
58 groundpos = groundinfo+1 ;+21 $10
59 ceilingpos = groundpos+16 ;+37 $10
61 stars1 = ceilingpos+16 ;+53
62 stars2 = stars1+1 ;+54
64 starx1 = storepos+55 ;+55
66 starx2 = starx1+(nrstars1*2) ;+69
68 mx = starx2+(nrstars2*2) ;+83 ;position of multiple#1
69 my = mx+1 ;+84 ;multiple y-pos
72 your_locpos = m2y+1 ;+87 ;position in your_prevpos tabl
73 your_prevpos = your_locpos+1 ;+88 ;save previous positions (32d)
75 ;^-----------------------------------<1 ;-120=$78
77 enemies = storepos2 ; +0 ;info about each enemy
78 enemysize = 9 ;infobytes per enemy
79 nrenemies = 16 ;max. nr of enemies
81 ybullets = enemies+(nrenemies*enemysize) ;60 bytes = 20(state,damg,x,y)
83 ebullets = ybullets+(nrybuls*4) ;+110 ;30 bytes = 10(state,x,y)
85 lvlenemies = ebullets+(nrebuls*3)
87 ;^-----------------------------------<2 ;-141=$8D
89 ; [0000:damage 0:diagfire 0:ground 0:ceiling 0:-]
91 ; [HP64] [000000:HP left 00:(00=no enemy 01=exploding 10=normal 11=moving)]
92 ; [ship type or explosion frame] [x] [y] [movetype] [movecounter] [firecounter] [firefreq]
94 ;---------------------- introduction ----------------------------------------
96 nop ;hello yas/ase/rascall/whathever
97 jp init ;here's the program, but first: a description
98 .dw $0001 ;description type 2 (description + YASicon)
99 .dw Title ;pointer to description (all shells)
100 .dw Icon ;pointer to YAS icon
102 Title: .db "Nemesis v0.97 by SHIAR",0
104 Icon: .db 8,1 ;icon for YAS: width = 1byte; height = 9bytes
107 .db %00111110 ; █████
108 .db %01111001 ; ████ █
109 .db %00111110 ; █████
111 .db %11100000 ; ███ ;recommend 80x50 screen mode
112 .DB 0 ;clear stupid YAS-line
114 ;---------------------- init ------------------------------------------------
126 init: cal BUSY_OFF ;turns the run-indicator off, obviously
127 cal _clrScrn ;clean the screen
129 res 2,(iy+13) ;don't scroll the screen
130 cal _flushallmenus ;remove TI menus
132 FixKeys: ;fixes some key problems like left+down bug
146 ld bc,int_end-int_handler
152 ;---------------------- main menu -------------------------------------------
155 xor a ;white bitmask (a=0)
156 ld hl,logo_nemesis ;from...
157 ld de,VIDEO_MEM+16 ;...to one line from top
158 ld b,e ;ld b,16: one line
160 ld (de),a ;clear/n byte
162 dnz AboveLogo ;repeat for the first line
163 ld bc,16*19 ;logo size
164 ldir ;display one line of logo
166 ld hl,16*$33+VIDEO_MEM ;$33 rows down
167 ld b,16*7 ;draw black 7 lines
168 ld a,%11111111 ;horizontal line mask
170 ld (hl),a ;draw one piece of the divider-line
171 inc hl ;move right (8 pixels = 1 byte)
172 dnz underline ;repeat
174 ld hl,_txt_email ;at the very bottom of tha screen
176 ld hl,txt_email ;hey, my e-mail address so SEND ME SOMETHING!!
177 cal _vputs ;VERY important, so display in small font ?:}
179 set 3,(iy+5) ;set white on black
180 ld de,_txt_about ;near the bottom of the screen
181 ld (_penCol),de ;hl=txt_email++=txt_about
182 cal _vputs ;display version + me
183 res 3,(iy+5) ;return to default black on white
220 cal GET_KEY ;wait for keypress
230 jr z,start_tha_freakin_game
233 start_tha_freakin_game:
237 cal nz,New_game ;NEW GAME
238 jp samelevel ;CONTINUE: game_main_loop
251 do_invert: ;invert screen (b<>w); destr:b
256 xor (hl) ;$2F (cpl) <-> $B7 (or a)
262 ;----------------------------------------------------------------------------
263 ;---------------------- game loop -------------------------------------------
264 ;----------------------------------------------------------------------------
266 game_main_loop: ;REPEATS FROM HERE EVERY FRAME
267 ld hl,timer ;update time
268 inc (hl) ;increase by 1
271 ld hl,1 ;once every 32 frames, increase score by 1
272 cal z,scoreInc ;do it
275 ld hl,GRAPH_MEM ;move from (hl) = top left
276 ld (hl),$00 ;first pixel will be copied all over the screen
277 ld de,GRAPH_MEM+1 ;(de) = next pixel, thus clearing whole screen
278 ld bc,896 ;loop 896 times = (128/8) * (64-8 for scorebar)
281 ld a,0 ;current frame/turn 0-255
283 and %11 ;a=0 once every 4 turns
284 jr z,movestarsdone ;don't move stars once every 4 frames
285 cal movestars1 ;move the stars on the FRONT layer
286 cal movestars2 ;move the distant stars
288 ld a,(stars1) ;star positions (the missing byte...)
289 ld b,nrstars1 ;how many stars? now we know.
290 ld hl,starx1 ;points to the position of the stars
291 cal DisplayStars ;display front layer stars
292 ld a,(stars2) ;weren't you paying attention five lines ago?
293 ld b,nrstars2 ;that many?! whow!
294 ld hl,starx2 ;and there they are
295 cal DisplayStars ;use the same procedure to display back layer
297 ld a,(level_info) ;level info
298 and %00000110 ;isolate ground&ceiling
299 jr z,game_stuff ;both non-present
300 and %00000010 ;bit representing the presence of any ceiling
301 cal nz,Handle_ceiling ;scroll the ceiling (if any) +check4collision
302 cal Handle_ground ;scroll the ground and check if we're dead
305 cal Handle_Ship ;move you
306 ld a,(your_occ) ;are you 100% OK?
308 jr nz,_gamestuff1 ;then don't check for movements/fires/...
311 ld a,%10111111 ;function keys (MORE,EXIT,2ND,F1,F2,F3,F4,F5)
312 out (1),a ;ask for them
313 nop \ nop ;delay 8 clocks
317 bit 6,a ;test bit 6 = exit-key = EXIT
318 jp z,game_over ;<exit> pressed, so be it
319 check_morekey: ;another unused label... poor compiler
320 bit 7,a ;test bit 7 = more-key = PAUSE
321 cal z,Pause ;yes, go to pause
324 bit 5,a ;test bit 5 = 2nd-key = FIRE
325 ld hl,check_selkey ;where to continue after executing Fire_bullet
326 psh hl ;push hl on stack (instead of cal Fire_bullet)
327 jp z,Fire_bullet ;fire smtn (bulletstaillasermultiples+stuff..)
328 pop hl ;no cal to Fire_bullet made, so pop stack
330 ld (just_fired),a ;reset just_fired
333 ld a,%01011111 ;look at first column of keys (ALPHA to STO)
335 nop \ nop ;what's taking you so long
336 in a,(1) ;at last... our precious keyzzz...
338 bit 6,a ;'bout the GRAPH key...
339 cal z,Teacher ;you didn't _press_ it, did you?!?
341 rla ;test bit7 so we know f ALPHA has been pressed
342 cal nc,select ;yeppy, select the currently selected upgrade
344 cal Enemies_hit ;check for collision with enemies
348 cal Handle_enemies ;move enemies
350 cal Handle_bullets ;move your bullets + check for hits
351 cal Enemy_bullets ;move enemy bullets
353 cal Level_event ;insert enemies
354 cal Display_Screen ;display all
360 jp game_main_loop ;LOOP ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
366 cp 97 ;max. 96 times (=96/16=6 increases)
367 ret nc ;return if already maxed
368 ld (weapincs),a ;save new incs
370 and %11110000 ;clear last 4 bits so no cf when rotating
372 rra ;rotate acting as shift (srl a) but just 1B
375 rra ;increase once just every 16 turns
376 ld b,a ;times to increase
378 add a,1 ;increase damage for one increase
380 dnz incthedamage ;a=total increase damage
381 ld b,1 ;minimal damage
383 add a,b ;a=total damage
384 ld (curweapdamage),a ;safe the current damage
388 ;--------------------------- ground -----------------------------------------
392 and %111 ;once every 8 frames
393 jr nz,Display_ground ;otherwise skip the scroll
394 ld bc,15 ;scroll all 16 bytes minus one (teh new byte)
395 ld hl,groundpos+1 ;from..
396 ld de,groundpos ;to (one byte to the left)
397 ldir ;LoaDIncreaseRepeat = scroll!
399 ld a,(groundinfo) ;what kind of ground
401 jr z,ground_tunnel ;tunnel effect
403 ld a,(groundpos) ;type 0
410 ld bc,$500 ;range=0..4
415 add a,(hl) ;add to spacesize (so +2..-2)
417 jr c,newground ;>=0 then don't change
420 add a,b ;new position
422 jr z,newground ;may not be 0 (=256)
424 jr nc,newground ;and not be <0 (>246)
430 ld (groundpos+15),a ;save new byte on the right
433 ld b,16 ;screen width
434 ld de,groundpos-1 ;height of current byte (previous actually)
436 ld hl,GRAPH_MEM+(56*16)-1 ;screen position
440 ld c,b ;push b for groundloopup
441 pop hl \ inc hl ;get screen position and go one right
442 pop de \ inc de ;get height info and set to the next byte
443 psh de \ psh hl ;save these for the next time
444 ld a,(de) ;height of current byte
447 ld de,16 ;to substract to go one line up
448 ld a,%11111111 ;bitmask black
451 ld (hl),a ;display black byte
452 sbc hl,de ;go up (sbc must be used for 16-bit sub)
453 dnz groundloopup ;and loop >groundpos< times
455 ld b,c ;pop b used by groundloopup
456 dnz groundloopright ;loop right for entire screen (16x)
457 pop hl \ pop hl ;restore stack
459 CheckGround: ;check for collision with the ground
477 ;--------------------------- ceiling ----------------------------------------
481 and %111 ;once every 8 frames
482 jr nz,Display_ceiling ;otherwise skip the scroll
483 ld bc,15 ;scroll all 15 bytes (16th is new position)
484 ld hl,ceilingpos+1 ;from..
485 ld de,ceilingpos ;to (one byte to the left)
486 ldir ;LoaDIncreaseRepeat = scroll!
488 ld a,(groundinfo) ;what kind of ceiling
490 jr z,ceiling_tunnel ;tunnel effect
495 ld d,a ;d=new ceiling
498 ld bc,$201 ;range=1..3
501 jr z,newceiling ;1:same
506 or a ;(spacespace)=0:
507 jr z,newceiling+2 ;keep same ceiling
513 cp d ;if size=1 then don't
519 ld (ceilingpos+15),a ;save the new byte
522 ld b,16 ;screen width
523 ld de,ceilingpos-1 ;height of current byte
525 ld hl,GRAPH_MEM-17 ;screen position
529 ld c,b ;push b for groundloopup
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
536 ld de,16 ;to substract to go one line up
537 ld a,%11111111 ;bitmask black
540 ld (hl),a ;display black byte
542 dnz ceilingloopdown ;and loop >groundpos< times
544 ld b,c ;pop b used by groundloopup
545 dnz ceilingloopright ;loop right for entire screen (16x)
546 pop hl \ pop hl ;restore stack
548 CheckCeiling: ;check for collision with the ground
552 srl a ;x/8 (current ceiling-byte)
557 ld de,ceilingpos ;first ceiling-byte
558 add hl,de ;current ceiling-byte
561 cp (hl) ;compare with ceiling
562 ret nc ;carry if ceiling is above you
564 jp damage_you ;otherwise you don't wanna be in that ship
566 ;--------------------------- move stars -------------------------------------
568 DisplayStars: ;inputs: hl=starx# a=stars# b=nrstars#
575 ret ;let's comment this: returns
604 cp 9 ;(GRAPH_MEM&%00001111)-- = $C9FAand15-1 = $A-1
613 ret ;for stupid people, here's another comment...
615 ;--------------------------- pause ------------------------------------------
618 ld hl,$0200 ;top left
620 ld hl,txt_pressenter ;"Enter to continue"
621 cal _puts ;display message
623 cal _getkey ;enter low-power mode and wait for key
624 cp kEnter ;keypressed = enter?
625 jr nz,pause ;no, wait some more
628 ;--------------------------- teacher ----------------------------------------
631 ld (iy+12),5 ;enable flashing cursor
633 cal _homeup ;top left
635 cal _puts ;display message
638 cal _getkey ;enter low-power mode and wait for key
639 cp kEnter ;enter pressed?
641 cp kGrMenu ;keypressed = graph?
642 jr nz,teacherloop ;no, wait some more
644 ld (iy+12),0 ;disable cursor
658 ;--------------------------- exit -------------------------------------------
660 quit: im 1 ;release keyfix procedure
661 set 2,(iy+13) ;set back screen scrolling
663 ld (_asapvar+1),a ;next Asm( run will reload the program
664 ld hl,GRAPH_MEM ;graph-screen location
667 ld bc,1024-1 ;do it 1024 times = entire screen
669 jp _clrWindow ;as _clrLCD but also clears TEXT_MEM (like the
670 ;_clrScrn) AND also executes _homeup and ret
672 ;--------------------------- display ----------------------------------------
675 ld hl,GRAPH_MEM ;from buffer (top left)
676 ld de,VIDEO_MEM ;to real screen (top left)
677 ld c,56 ;display height = 64 bytes (minus 8 for bar)
679 ld b,16 ;display width = 16 bytes (16*8bits=256pixels)
681 ld a,(hl) ;copy byte from (hl)
682 _invert: ;SMC: cpl <-> or a
683 cpl ;xor $ff: invert byte (white<=>black)
685 inc hl \ inc de ;next byte
686 dnz displaytloop ;16x hl >> de
688 jr nz,displayloop ;loop 56x
692 or a ;(time2invert)=0:
693 jr z,noinvert ; do nothing
694 dec a ;otherwise decrease
695 cal z,do_invert ;if it became 0 then invert
696 ld (hl),a ;save new value
699 ld hl,$396b ;Display Score
700 ld (_penCol),hl ;bottom right of screen
703 _D_HL_DECI: ;------- display 5-digit value -------
704 ld de,savestr+4 ;savenr saves number string
706 ldhld: cal UNPACK_HL ;one digit of hl
707 add a,'0' ;make number
708 ld (de),a ;save into savenr
709 dec de ;point to next digit
710 dnz ldhld ;repeat for all digits
712 ld hl,savestr ;we (the program) saved the value righthere
713 jp _vputs ;the only thing left to do is to display it
715 savestr: ;@here the score will be stored
716 .db "00000",0 ;don't worry, it's just temporary
718 ;------------------------- handle ship --------------------------------------
725 inc a ;no! next (explosion)frame
726 ld (your_occ),a ;save
728 cp 64+1 ;last explosion frame? (1-16=1st;49-64=4th)
729 jp c,exploding_you ;not yet: display explosion
730 cp 64+16 ;delay finished?
731 jp z,You_die ;yes = game over
732 ret ;don't display anything
736 ld a,%01111110 ;get arrow keys
737 out (1),a ;it's cold outside
738 ld hl,y ;instead of nop\nop do something usefull
739 in a,(1) ;come back in
742 xor %11111111 ;inverted a = 0 if arrow-key has been pressed
743 ld a,(your_multiples)
744 jr z,no_adv ;if so, leave the multiples where they are
745 or %100 ;set move bit
747 no_adv: and %11111011 ;reset move bit
749 adv_ok: ld (your_multiples),a
751 ld a,(timer) ;framecounter
752 and %1 ;switches 0<>1 each frame
753 inc a ;a = 1 or 2 (1.5 avg)
754 ld c,a ;c = your_speed
757 rra ;rotate right (put last bit in c)
758 ld b,a ;we need a later
763 cp 50 ;56-6 = bottom of screen
768 rr b ;because we now use b, it's rr instead of rra
771 sub c ;<dec a> doesn't affect c-flag
772 jr c,no_left ;-1 = left side
779 cp 122 ;128-6 = right side
788 sub c ;<dec a> doesn't affect carry-flag
789 jr c,no_up ;-1 = top of screen
790 ld (hl),a ;save new y
792 no_up: ld e,(hl) ;e=y
793 ld ix,spr_ship01 ;normal ship sprite
795 ld hl,your_inv ;invulnerable?
796 ld a,(hl) ;load time in a
798 jr z,disp_ship ;yes so ship = normal (display \ continue)
800 ld a,(timer) ;load frame nr.
801 and %00000111 ;a=0 once every four frames
802 jr nz,not_time ;a<>0 = not time to update counter
803 dec (hl) ;decrease inv-time left
805 and %00000100 ;a switches 0<->1 every 2 frames
806 jr z,disp_ship ;show normal ship
808 ld bc,spr_ship01i-spr_ship01
809 add ix,bc ;display invulnerable ship
811 cal safeputsprite ;display your ship; save de
816 ld a,(your_multiples) ;do you have multiples
817 ld b,a ;save a for 2nd check
818 and %11 ;no? (last two bits = nr of multiples)
819 ret z ;then don't handle them either
821 ld a,b ;restore a (your_multiples)
822 and %100 ;move the multiples??? (=move bit set?)
823 jr z,mult_adv ;nope, just let them (saves (y)in y, (x)in x)
825 ld hl,your_locpos ;location to save this position
827 inc a ;a=a+1 (next position)
828 and %00001111 ;if a>15 then a=a-16
829 ld (hl),a ;save new a
834 ld hl,your_prevpos ;previous positions
835 add hl,bc ;16 turns ago
839 ld (mx),bc ;save multiple position in (mx)
840 ld (hl),d ;save current pos. for 16 turns into the future
849 ld ix,spr_multiple ;sprite of the multiple
850 jp putsprite ;display it + <ret>
855 srl a ;half the framerate
856 srl a ;half that framerate
857 srl a ;and half again that framerate
859 ld ix,spr_yexplosion ;base sprite
861 explosion_stuff: ;in:a=frame*2+(0 to 1); (hl)=xpos-- ix=sprite
867 add ix,bc ;go to correct sprite (each spr. is 8 bytes)
872 jp putsprite ;and display it too
876 damage_you: ;damages you B points
877 ld a,(your_inv) ;shield left?
879 jr z,dothadamage ;no shield
880 srl b ;shield: half the damage
884 cp (hl) ;no already inverted?
885 cal z,do_invert ;then invert screen
887 ld (hl),a ;change back 2 frames from now
889 ld hl,your_armor ;armor left
890 ld a,(hl) ;load hp in A
891 sub b ;decrease hp by B
892 jp m,no_armor ;<0hp left so explode
893 ld (hl),a ;no, so save decreased hp
894 jp disp_armor ;and display new value
896 ld a,%01 ;occ %xxxxxx01 = explode
897 ld (your_occ),a ;too bad, you're dead meat
900 ;------------------------- place multiples ----------------------------------
903 ld (mx),de ;set last multiple-position
904 ld hl,your_prevpos ;place all previous positions
905 ld b,16 ;all 16 of them
907 ld (hl),d ;set prev-x to d
909 ld (hl),e ;set prev-y to e
911 dnz place_multiples ;repeat
914 ;------------------------- select upgrade -----------------------------------
917 ld a,(your_armor) ;load current armor
918 cp 25-6 ;may not become >=25
919 jr c,doincarmor ;ok then just add 6
920 ld a,24-6 ;set to maximum (6 will be added below)
922 add a,6 ;add 6 to armor
923 ld (your_armor),a ;change armor
926 ld hl,your_pickup ;select pickups
927 ld a,(hl) ;load pickups taken so far
929 ret m ;return if it's 0 (no pickups)
930 jr nz,select2 ;no, carry on
932 ld (hl),a ;reset pickups
934 jp disp_icons ;display and return
937 jr nz,select3 ;no, carry on
938 ld (hl),a ;reset pickups
940 ld (your_tail),a ;ready tail beam
941 jp disp_icons ;display 'n return
944 jr nz,select4 ;no, carry on
945 ld (hl),a ;reset pickups
950 jp nc,disp_icons ;weapon maxed out
951 ld (hl),a ;set new weapon
952 cal loadweapon ;load it (damage and stuff)
953 jp disp_icons ;display n return
956 jr nz,select5 ;no, carry on again
957 ld (hl),a ;reset pickups
960 cp maxweapon ;upgrade from bullet
961 jr nc,upgradelaser ;nope, just upgrade
962 ld a,maxweapon-1 ;yes, set laser #1
966 jp nc,disp_icons ;laser maxed out
969 jp disp_icons ;display + return
972 jr nz,select6 ;no, carry on once more
973 ld (hl),a ;reset pickups
975 ld (your_multiples),a
978 jp disp_icons ;display, return
980 ld (hl),0 ;reset pickups
981 jp disp_icons ;display/return
983 ;------------------------- fire bullet --------------------------------------
987 ld a,(hl) ;just_fired
988 cp 5 ;already pressed?
989 ret z ;return when already pressed (=5)
991 inc (hl) ;otherwise increase counter (0 to 4 >> 1 to 5)
992 ld a,(your_weapon) ;if you have bullets.....
994 jr nc,fireOK ;>weapons = laser
995 ld (hl),5 ;.....then can't fire next turn (go to 5 imm.)
998 ld hl,(x) ;yes: first fire from ship position (x)
999 ld a,(your_multiples) ;any multiples?
1001 jr z,fireany ;then just fire somethin'
1002 cal fireany ;and blast
1003 ld hl,(mx) ;then, fire from multiple position (mx)
1004 dec h ;one up (-2 height: keeps weapons centered)
1005 ;blast again and <ret>
1007 ld (firex),hl ;set position to fire from
1009 ld ix,weapondata+2-(256*3)
1014 ld b,3 ;go to current weapon (bc=a), b=3 :P
1018 psh bc ;save counter
1019 ld a,(ix) ;load this weapon
1020 cp %11100000 ;%11110000=laser
1021 cal z,fire_laser ;fire laser (will set a=0 when done)
1026 pop bc ;weapon counter (do 3 weapons)
1034 ld a,(ix-2) ;last weapon fired
1035 cp %11100000 ;issit laser
1037 xor %11111 ;smart way of going left instead of right :P
1038 jr fire_ybullet ;fire tail bullet and return
1040 ;-----fire LASER-----
1043 ld b,0 ;overflow counter
1045 ld d,(hl) ;d = your x-pos
1048 ld a,(hl) ;base y-coord (firey)
1049 add a,(ix+1) ;at specified offset (most likely the middle)
1050 ld e,a ;save laser-y in e
1051 psh de ;save unmodified (x,y)
1055 rl b ;b (=0) =b*2+overflow (if y>32 then bc=bc+256)
1056 add a,a ;y*16 (width of screen)
1057 rl b ;b=b*2+overflow (if y>64 then bc=bc+512)
1058 inc a ;8 pixels to right (a=even so no overflow)
1063 add a,d ;a = (Y*16+X/8) mod 256 (c set on overflow)
1065 jr nc,_nolc ;jump if no carry = no overflow = a<=255
1066 inc b ;a>255 so increase bc by 256
1067 _nolc: ld c,a ;c = (Y*16+X/8) mod 256
1068 ld hl,GRAPH_MEM ;save-location
1069 add hl,bc ;bc = Y*16+X/8: hl=screen address
1070 ld a,15 ;128/8=16=screen width ** minus one (inc a ^^)
1071 sub d ;minus x-start (d=X/8)
1075 inc hl ;Go to next byte
1078 pop de ;de=(firex): x-pos unmodified
1080 check_laserhits: ;de = (x,y)
1082 ld b,nrenemies ;check all enemies
1083 ld hl,enemies+1 ;enemy#1+occ/hp00
1084 laserhits: ;hits with normal enemies
1087 and %00000010 ;normal/moving occ.=%1x
1088 jr z,nolashit ;no hit when enemy_occ <> 2/3
1091 or a ;enemy #0 = pickup
1092 jr z,nolashit ;yes: don't destroy
1094 cal find_sprite ;ix=sprite to enemy (hl)
1098 jp m,nolashit ;no hit when enemy is left of you
1102 jr z,enemy_lashit ;a-e=0 = laser on top line of enemy = hit
1103 jr nc,nolashit ;a-e>0 = enemy above laser = no hit
1105 add a,(ix+1) ;add enemy height (according to sprite @ix)
1106 jp m,nolashit ;a-e>0 = hit
1108 ld a,(curweapdamage) ;damage
1109 cal enemy_hit ;hl=enemy+y
1114 add hl,bc ;go to next enemy
1116 dnz laserhits ;check all enemies
1117 xor a ;a=0 otherwise weird things might happen :P
1118 ld (weapincs),a ;reset damage
1122 ;-----fire BULLETs-----
1124 fire_ybullet: ;fire bullet type=C dam=(curweapdamage) at (firex/y)
1125 ld c,a ;save bulletType in c
1126 ld hl,ybullets ;check for unused bullet
1132 jr z,found_ybullet ;0 = no bullet here
1134 dnz find_ybullet ;look next bullet
1135 ret ;none found, return don't fire
1138 ld (hl),c ;use the bullet and set correct bullet-type
1140 ld (hl),1 ;set bullet damage
1142 ld a,(firex) ;your x-pos
1143 add a,5 ;place bullet in front of you
1144 inc hl ;go to bullet-x
1147 ld a,(firey) ;your y-pos
1148 add a,(ix+1) ;place bullet at the middle of your ship
1149 inc hl ;go to bullet-y
1153 ld (weapincs),a ;reset damage
1156 ;------------------------ handle bullets ------------------------------------
1160 and %11111 ;pixels to move
1161 add a,(hl) ;a = X + (hl) to the right
1162 sub 16 ;and 16 to the left (so -16..+15)
1163 jr c,remove_bullet ;remove if x<0
1165 jr nc,remove_bullet ;or x>=128
1166 ld (hl),a ;save new pos.
1171 cal _shracc ;%11110000->1111
1174 jr z,bullet_noymove ;1=straight forward
1176 jr z,bullet_up ;2=up
1178 jr z,bullet_halfup ;3=1/2up
1180 jr z,bullet_down ;4=down
1182 bullet_halfdown: ;5=1/2down
1206 pop hl ;cal bullet_left
1208 ld (hl),0 ;dump this bullet!
1209 jr next_ybullet+1 ;+1:skip pop hl at next_ybullet
1215 psh bc ;bullet counter
1216 psh hl ;save enemy+type
1217 ld (temp1),hl ;needed for check_bullethits
1218 ld a,(hl) ;@bulletType
1223 jp z,next_ybullet ;bulletType=0 >> no bullet
1224 cal bullet_left ;move bullet left
1227 psh de ;save de =position
1230 ld a,(hl) ;bullet damage=size
1231 ld hl,bullettable ;pointer to first bullet
1235 ld e,a ;->16bit (de=a)
1236 add hl,de ;point to correct bullet offset
1237 ld a,(hl) ;load bullet offset
1238 ld e,a ;convert to 16bit (d=0)
1239 ld ix,spr_bullet01 ;first sprite
1240 add ix,de ;add offset (go to correct sprite)
1241 pop de ;saved position
1243 ld a,(ix) ;bullet x-size
1244 ld (bulletxsize),a ;used at check_bullethits
1245 ld a,(ix+1) ;bullet y-size...
1246 ld (bulletysize),a ;...too
1248 cal safeputsprite ;display bullet; DE used for check_bullethits
1250 cal check_bullethits
1253 pop hl ;restore enemy+type
1257 inc hl ;skip type,dam,x,y: next enemy+type
1259 dnz scan_bullets ;next bullet (loop)
1262 ;--------------------------- check bullethits -------------------------------
1264 check_bullethits: ;INPUT: de=X,Y; (temp1)=bullet
1268 hit_enemies: ;Hits with normal enemies
1269 psh bc ;enemy counter
1274 jr z,nohit ;no hit when enemy_occ <> 2/3
1278 or a ;enemy #0 = pickup
1279 jr z,nohit ;yes: don't destroy
1281 cal find_sprite ;set ix to the sprite of this enemy
1285 sub d ;minus bullet x-position
1287 sub 5 ;minus bullet x-size
1291 add a,(ix) ;add enemy width
1296 sub e ;minus bullet y-position
1298 sub 3 ;substract bullet height
1300 jp p,nohit ;nope, missed it
1302 add a,(ix+1) ;add enemy height
1304 jp m,nohit ;missed after all
1306 ;---bullet hits enemy (auch-time!)---
1308 ld hl,0 ;@bulletType
1310 ld (hl),0 ;remove bullet
1312 ld a,(hl) ;set damage
1320 dnz hit_enemies ;check next enemy
1323 enemy_hit: ;*in:a=damage;hl=enemy+y
1324 add a,a ;a=damage to inflict
1325 add a,a ;first 2 bits used for occ.
1331 ld a,(hl) ;load hp00
1332 sub b ;decrease HP (if <0xx then c is set)
1333 ld (hl),a ;save (no flag-changes)
1334 dec hl ;@hp64; no change in c
1335 ld a,(hl) ;load; no c-change
1336 sbc a,0 ;if cf then decrease a
1337 ld (hl),a ;save back the new value
1338 ret nc ;if a>=0 then return, otherwise explode
1340 inc hl ;goto occ again
1341 ld (hl),%01 ;set to explode
1342 ld a,(pickuptimer) ;counts enemies destroyed
1343 dec a ;enough destroyed for a pickup?
1344 jr nz,pickupdone ;otherwise just explode
1345 ld (hl),%110 ;change it into a pickup (with 2 HP)
1346 ld a,18 ;reset enemies counter (18 hits = next)
1348 ld (pickuptimer),a ;save new enemiescounter value
1350 ld (hl),$00 ;explosionFrame 0
1352 ld hl,1 ;increase score by one
1355 ;--------------------------- level events -----------------------------------
1358 ld hl,nextevent ;time to next event <ld a,(nextevent)
1359 dec (hl) ;decrease counter <dec a
1360 ld a,(hl) ;look at counter <ld (nextevent),a
1361 or a ;has it reached zero?
1362 ret nz ;nope: get outta here!
1364 ld bc,0 ;enemy frequency (lvl)
1367 ld (nextevent),a ;set time to next event
1369 dec (hl) ;update enemy-counter
1371 ld a,(hl) ;look at counter
1372 or a ;has it reached 0?
1373 jp z,Next_level ;yes: level finished
1374 dec a ;has it reached 1?
1375 jr z,standby_event ;yes: wait until no enemies present/left
1376 dec a ;has it reached 2?
1377 jr z,place_boss ;yep: place the BigBossTM!
1378 dec a ;has it reached 3?
1379 jr nz,do_event ;nope: >3 = place an enemy
1380 inc hl ;nextevent located behind eventleft
1381 ld (hl),123 ;set delay
1382 ret ;don't place any more enemies
1386 ld hl,enemies+1-enemysize
1391 or a ;0 = no enemy present
1403 ld (nrlvlenemies),a ;just one enemy: the BOSS
1404 ld hl,(levelp) ;the leveldata (including the boss)
1405 dec hl ;points to leveldata\boss\enemynr
1407 ld (lvlenemies),a ;set new enemy (boss)
1410 ld hl,enemies+1-enemysize
1415 cp (hl) ;(hl) = 0 ??
1416 jr nz,chk_noenemy ;jump if enemy present (non-0)
1417 ex de,hl ;de=hl=usable enemy
1419 place_enemy: ;de = enemy+1
1421 nrlvlenemies =$-1 ;=nr of enemies minus 1
1422 cal Random ;random enemy b..b+c = 0..nrenemies-1
1426 add hl,bc ;go to a random enemy
1427 ld a,(hl) ;load enemy nr of this mysterious random enemy
1428 cal findenemyspecs ;hl = enemy #a specs
1430 dec de ;goto hp64 (before occ)
1432 ldi ;set hitpoints+occ of enemy class
1433 ldi ;set enemy class (nr)
1436 ld a,(hl) ;load placeInfo
1439 jr z,random_enemy ;yes: create random value <51 in a
1441 jr z,lure_enemy ;yes: create a 100% luring enemy
1443 halflure_enemy: ;yes (of course it is): pick one (50% lure)
1444 ld a,(timer) ;look at frame-number
1445 and %00000001 ;make random if odd frame nr.
1446 jr nz,random_enemy ;1st possibility: random enemy
1447 lure_enemy: ;2nd possibility: luring enemy
1448 ld a,(y) ;place at same y-pos as YOUR ship
1451 ld bc,256*51 ;range=0..51
1453 ypos_OK: ;random value successfully created
1454 ld (de),a ;save y-position
1455 inc de ;@movecounter
1457 ld a,1 ;movecounter = 1
1459 inc de ;@firecounter
1460 ldi ;set time-to-1st-fire
1464 ;--------------------------- enemy fires ------------------------------------
1466 Enemy_fires: ;de = x,y
1476 jr z,found_ebullet ;0 = not used
1477 inc hl \ inc hl \ inc hl
1478 dnz find_ebullet ;look next bullet
1491 ld b,%1011 ;yourY-bulY = negative (=bullet below you)
1494 ld b,%1001 ;yourY-bulY = even more negative (going up)
1499 ld b,%1010 ;bullet going down
1501 jp m,bulletok ;even more going down
1508 ld (hl),a ;set bullet direction
1510 ld (hl),d ;set x-pos
1512 ld (hl),e ;set y-pos
1515 ;----------------------------- enemy bullets --------------------------------
1523 ld a,(hl) ;load bulletType in a
1524 and %1111 ;select direction-bits
1525 jr nz,enemy_bullet ;non-0: handle bullet
1527 pop hl ;do not move the <pop hl>
1529 inc hl \ inc hl \ inc hl
1534 ld b,a ;save type&%1111
1536 ld a,(hl) ;check if it has reached the left side of scrn
1538 jr nz,remove_ebullet ;yes, remove bullet
1539 dec (hl) ;move one left
1540 dec (hl) ;and another one
1544 ld a,b ;restore type
1545 cp %1100 ;is it a normal bullet? (cp = faster than bit)
1546 jr z,ebullet_common ;type %1100: normal bullet
1547 and %111 ;isolate important bits
1548 jr z,ebullet_down ;type %1000: moving down
1550 jr z,ebullet_up ;type %1001: moving up
1559 jr z,ebullet_down ;type %1010: moving down 50%
1560 ;type %1011: moving up 50%
1577 ld ix,spr_bullete1 ;display enemy bullet
1583 jr nz,next_bullet ;0 = you're normal
1603 pop hl ;points to bullettype again
1604 psh hl ;and save it again (ivm call to damage_you)
1605 ld a,(hl) ;load bullettype
1606 cal _shracc ;isolate damage-bits (%1111???? -> %00001111)
1607 ld b,a ;set damage-amount
1608 cal damage_you ;HIT!!
1610 pop hl ;hl could be destroyed by damage_you
1611 ld (hl),0 ;bullet > unused
1612 jr next_bullet+1 ;next bullet (SKIP THE <POP HL> = one byte)
1614 ;--------------------------- handle enemies ---------------------------------
1618 ld b,nrenemies ;handle all enemies
1626 jr z,next_enemy ;occ "no enemy" 0
1628 jr z,exploding_enemy ;occ "exploding" 1
1632 ld c,(hl) ;c = enemy type = de
1646 jr c,enemyonscreen ;=on screen
1648 jr c,remove_enemy ;=off screen
1651 ld (hl),e ;store new y
1653 ld (hl),d ;store new x
1654 ld a,c ;a = enemy type
1655 or a ;type 0? (pickup)
1656 jr nz,check_enemyfire ;no, a normal enemy; let em fire
1657 ld a,(timer) ;load time
1658 and %1 ;move left once every 2 turns
1659 jr z,firing_done ;don't move now
1660 inc d ;increase x-position (don't move this turn)
1661 inc (hl) ;and save it
1662 jr firing_done ;continue
1669 dec (hl) ;decrease counter till next blast
1670 ld a,(hl) ;&&&doesn't seem efficient to me
1671 or a ;has it reached zero?
1672 jr nz,firing_done ;finished if not
1677 ld (hl),a ;reset counter for next blast
1678 psh de ;save registers for firing-use
1679 cal Enemy_fires ;fires bullet
1680 pop de ;restore (destroyed by Enemy_fires)
1682 cal putwidesprite ;display sprite @ix
1694 ld (hl),$0000 ;bye bye enemy
1695 jr next_enemy+1 ;continue AFTER pop hl (already done)
1701 jr z,remove_enemy ;remove when at last frame
1703 ld (hl),a ;next frame
1705 ld ix,spr_explosion ;base sprite
1706 cal explosion_stuff ;display explosion
1709 ;--------------------------- moving enemies ---------------------------------
1712 ld a,(hl) ;how does this enemy move?
1713 bit 7,a ;direction indicator
1723 ret z ;type 0 = don't move
1725 jr z,movetype_updown ;1 = up / down
1727 jr z,movetype_vslow ;2 = 1/4 speed
1729 jr z,movetype_slow ;3 = 1/2 speed
1731 jr z,movetype_fast ;3 = 1.5x speed
1733 jr z,movetype_vfast ;4 = 2x speed
1735 jr z,movetype_smart ;5
1737 jr z,movetype_lure ;6 = move y towards you
1739 jr z,movetype_slowlure ;7 = lure 1/2 speed
1741 jr z,movetype_stoplure ;8 = slowlure; stop at x=99
1743 ; jr z,movetype_fulllure ;9 = x+y towards you 1/2 speed
1763 jr c,movetype_slowlure
1764 inc d ;x<100: full stop
1781 inc hl ;hl =@ <move>
1790 or a ;reset carry flag
1791 dec hl ;reset hl to <y>
1813 pop hl ;restore stack (no ret used)
1814 jp remove_enemy ;remove this enemy (off screen)
1825 or a ;reset carry flag
1828 ld a,(hl);&&&ld a,e ;load current y-position
1831 moveup: dec a ;decrease y-pos (=move up)
1832 ret m ;don't move off the screen (y<0)
1833 dec e ;save new y-pos
1836 inc a ;increase y-pos
1837 cp 55 ;compare with bottom
1838 ret nc ;return if it has passed that line (>40)
1839 inc e ;otherwise save new position
1842 ;--------------------------- check collision --------------------------------
1845 ld hl,(x) ;e = X, d = Y
1846 ld de,$0707 ;add 7 to both d and e
1849 ld e,l ;e = X+7, d = Y+7
1852 ld b,nrenemies ;check all 20 enemies
1857 jr z,check_next ;2 or 3 = ok
1860 collide_enemy: ;&&& include in Handle_enemy proc
1864 ld a,(hl) ;check x match
1865 sub e ;enemy position minus yours minus 7
1868 add a,(ix) ;enemy width
1872 ld a,(hl) ;check y match
1873 sub d ;same as with x-check
1876 add a,(ix+1) ;enemy height
1883 ld hl,2 ;increase score by 2
1887 ld a,(hl) ;load enemy type
1889 jr nz,collide ;enemy when <>0
1892 ld hl,your_pickup ;your pickups
1897 ld a,1 ;yes: reset to pickup 1
1900 cal disp_icons ;display altered pickupicons
1903 dec hl ;to enemy occ
1904 xor a ;set to 0 = gone
1906 jr check_next ;all done, next..
1909 ld (hl),%01 ;set to explode
1911 ld (hl),0 ;explosionFrame 0
1923 ld b,collidedamage ;damage
1935 ;--------------------------- story ------------------------------------------
1955 ld hl,VIDEO_MEM ;copy text
1956 ld de,GRAPH_MEM ;to GRAPH_MEM
1957 ld bc,1024 ;entire screen
1973 cal storyPage ;do some story
1974 inc hl ;look at next hl
1975 ld a,(hl) ;load in a
1977 inc a ;set z-flag if a = $ff
1978 jr nz,dostory ;otherwise loop
1980 ld bc,2+1 ;story ends
1981 add hl,bc ;set hl to beginning of the level
1982 ld (levelp),hl ;set the level-pointer
1985 ;--------------------------- SFX --------------------------------------------
1987 DoSFX: ;in:a=beginLine;b=nrOfLines
1992 ld a,0 ;get line number
1994 inc a ;go to the next line
1995 ld (curline),a ;update
2002 add hl,hl ;*16 (a pixels down=a*16)
2004 ld b,h ;save hl for later
2007 ld de,VIDEO_MEM ;where to put sfx
2008 add hl,de ;go to ymin
2009 ex de,hl ;put into de again
2015 neg ;a=64-a (lines from bottom)
2017 ; ld c,a ;c=a=(curline)
2019 ; sub c ;lines from bottom
2021 SFXdisp: ;display this frame on screen
2022 ld bc,16 ;one line (=16 bytes, you'd know by now)
2023 ldir ;display (copy actually)
2024 ld bc,-16 ;go up one line (not on screen)
2025 add hl,bc ;so the same line will be displayed
2027 jr nz,SFXdisp ;repeat until whole screen is displayed
2038 ;--------------------------- show icon --------------------------------------
2041 ld (hl),a ;draw one piece of the divider-line
2042 inc hl ;move right (8 pixels = 1 byte)
2043 dnz drawline ;repeat (16bytes * 8pixels =128= screen width)
2047 psh bc \ psh de \ psh hl \ psh ix ;&&&
2049 ld hl,VIDEO_MEM+(16*56);56 rows down = eight rows from bottom
2050 ld (PutWhere),hl ;place icons at bottom of normal screen
2051 ld b,16 ;draw 16x (screen width)
2052 ld a,%11111111 ;horizontal line mask
2053 cal drawline ;draw divider-line
2055 ld b,16*7 ;draw 16x (screen width) 7x (height)
2056 xor a ;blank line mask
2057 cal drawline ;clear scorebar
2061 ld a,(your_lives) ;nr of lives
2063 jr z,displivesdone ;no lives
2068 cal safeputsprite ;put li'l ship
2073 dnz displivesloop ;one ship per life
2076 ld ix,spr_icon01 ;armorIcon
2077 ld de,$1901 ;icon #1
2078 cal putwidesprite ;display icon
2079 cal disp_armor ;display bar
2082 ld a,(your_weapon) ;ur weapon
2083 cp maxweapon ;laser?
2084 psh af ;(your_weapon)
2085 jr nc,no_tail ;if laser (nc) then tail ain't fired
2089 ld ix,spr_icon02 ;tailbeamIcon
2091 ld de,$2901 ;icon #2
2092 cal putwidesprite ;display
2095 pop af ;a=(your_weapon); cf=bullets
2097 jr nc,no_bullets ;=laser
2098 ld hl,$3945 ;position to display bullet-type digit
2099 pop af ;digit=(your_weapon)
2101 inc a ;1 = weapon #1 (=0)
2102 ld (_penCol),hl ;set location
2103 add a,'0' ;make digit
2104 cal _vputmap ;display char
2105 ld ix,spr_icon03 ;bulletIcon
2107 ld de,$3901 ;icon #3
2108 cal putwidesprite ;display icon
2110 ld ix,spr_icon00 ;emptyIcon
2111 pop af ;ld a,(your_weapon)
2113 jr c,no_laser ;popped carry
2114 ld hl,$3955 ;position to display bullet-type digit
2115 ld (_penCol),hl ;set location
2116 ld a,b ;(your_weapon) ;load = faster than push
2117 sub maxweapon-1 ;1 = laser #1 (=maxweapon)
2118 add a,'0' ;make digit
2119 cal _vputmap ;display char
2120 ld ix,spr_icon04 ;laserIcon
2122 ld de,$4901 ;icon #4
2125 ld ix,spr_icon00 ;emptyIcon
2126 ld a,(your_multiples)
2131 ld de,$5901 ;icon #5
2134 ld ix,spr_dividerline
2138 ld a,(your_pickup) ;pickups taken
2139 add a,a ;picks*2 (sets z-flag)
2140 jr z,iconsdone ;return if no pickups
2145 ld d,a ;y-pos = picks * $10 + $0a (19,29,39,49,59)
2146 ld e,$01 ;x-pos = bottom (1a01,2a01,3a01,4a01,5a01)
2151 ld hl,GRAPH_MEM ;normal game-screen
2152 ld (PutWhere),hl ;set sprite-position to normal screen
2154 pop ix \ pop hl \ pop de \ pop bc
2159 ld hl,(57*16)+VIDEO_MEM+3
2169 ld a,(your_armor) ;load your armor (<25)
2173 srl a ;/8: don't display last 3 bits of a (later)
2174 jr z,noarmorbar ;if a=0 then it would loop 256x so skip it
2175 ld b,a ;loop b=a times
2176 armorbar: ;starting at ($39*16)+VIDEO_MEM
2177 ld (hl),%11111111 ;draw a piece of the bar
2178 add hl,de ;one down (resets carry)
2179 ld (hl),%11111111 ;same piece
2181 inc hl ;next position
2182 dnz armorbar ;loop it b times
2186 and %111 ;display last bits of armor
2187 ret z ;if armor=0 then bit = %00000000 (don't disp)
2189 xor a ;bit = %00000000
2192 rra ;rotates A right and sets bit 7 (c-flag)
2193 dnz armorbarbit ;repeat B times (so if B=6 then a=%11111100)
2194 armorbarready: ; (an if B=3 then a=%11100000)
2195 ld (hl),a ;draw this last byte
2197 ld (hl),a ;and just below
2201 ld hl,(59*16)+VIDEO_MEM+3
2208 ld a,(weapincs) ;load bar size (0-80)
2209 srl a ;half the size (0-40)
2210 srl a ;again half that size (0-20 pixels)
2214 srl a ;/8: don't display last 3 bits of a (later)
2215 jr z,nochargebar ;if a=0 then it would loop 256x so skip it
2216 ld b,a ;loop b=a times
2217 chargebar: ;starting at ($39*16)+VIDEO_MEM
2218 ld (hl),%11111111 ;draw a piece of the bar
2219 inc hl ;next position
2220 dnz chargebar ;loop it b times
2223 and %111 ;display last bits of chargebar
2224 ret z ;if armor=0 then bit = %00000000 (don't disp)
2226 xor a ;bit = %00000000
2229 rra ;rotates A right and sets bit 7 (c-flag)
2230 dnz chargebarbit ;repeat B times (so if B=6 then a=%11111100)
2231 chargebarready: ; (an if B=3 then a=%11100000)
2232 ld (hl),a ;draw this last byte
2235 ;--------------------------- proc -------------------------------------------
2237 Random: ;a=c<random<b+c; destr:none
2239 ld hl,rancount ;amount to increase with (0-255)
2241 inc (hl) ;change for next time
2242 ld a,r ;value $0-7F (can be _anything_ so watch out!)
2243 add a,0 ;add to last random value
2244 ranseed =$-1 ;SMC :P
2245 add a,(hl) ;add the changing increase value
2246 ;(this is because R can be anything;
2247 ; ie always be even so freeze when a must be 1<=a<=1)
2248 ld (ranseed),a ;save for next time
2250 jr nc,randomloop ;then add again
2256 RandomY: ;HL = random Y 0..50 right side ((1..51)*16-1)
2258 ld bc,50*256+1 ;range=1..51
2259 cal Random ;a = 1..51
2265 add hl,hl ;hl = 1..51 * 16 (left side at random y)
2266 dec hl ;hl = 0..50 * 16 (" at right side of screen)
2268 add hl,de ;position on screen
2280 find_sprite: ;in:hl=enemy+type | out:ix=sprite to enemy
2283 ld e,(hl) ;e = enemy offset/2
2285 ld ix,spr_enemy00 ;first enemy sprite
2286 add ix,de ;add offset for current enemy
2287 add ix,de ;twice (offset stored as offset/2)
2293 ld hl,VIDEO_MEM ;screen location (top left)
2296 ld bc,1024-1 ;do it 1024 times = entire screen
2298 set 3,(iy+5) ;set white on black
2303 ld a,%10000000 ;all key-masks
2306 inc a ;cp %11111111 (no keys pressed)
2307 jr nz,releasekeys ;keep waitin
2308 cal GET_KEY ;clear buffer
2311 findenemyspecs: ;enemy #a specs in (hl); in:b=0; out:ac=?
2312 ld hl,enemyspecs-8 ;enemy "0" specs (1 before enemy #1)
2316 ld c,a ;b=0; c=bc=type*8
2317 add hl,bc ;hl = enemy specs
2320 ;--------------------------- game over / new game / death -------------------
2322 .db 0,".<>!",0,0,0,0 ;down,L,R,up
2323 .db 0,"xtoje0",0 ;enter..clear
2324 .db " wsnid9",0 ;(-)..custom
2325 .db "zvrmhc8",0 ;dot..del
2326 .db "yuqlgb7#" ;0..xvar
2327 .db $D9,"-pkfa6'" ;on..alpha
2328 .db "54321*",0,$D0 ;F5..more
2331 ld hl,_asapvar ;find own variable
2332 rst 20h ;cal _ABS_MOV10TOOP1
2333 rst 10h ;cal _FINDSYM
2334 ret c ;not found? who cares...
2337 ld hl,4+storehi_start-_asm_exec_ram
2338 add hl,de ;hl=pointer to data in original prog
2340 cal _SET_ABS_DEST_ADDR
2343 cal _SET_ABS_SRC_ADDR
2344 ld hl,storehi_end-storehi_start
2345 cal _SET_MM_NUM_BYTES
2346 cal _mm_ldir ;save done (cal \ ret)
2350 ld hl,_asapvar ;find own variable
2351 rst 20h ;cal _ABS_MOV10TOOP1
2352 rst 10h ;cal _FINDSYM
2353 ret c ;not found? who cares...
2356 ld hl,4+storesave_start-_asm_exec_ram
2357 add hl,de ;hl=pointer to data in original prog
2359 cal _SET_ABS_DEST_ADDR
2361 ld hl,storesave_start
2362 cal _SET_ABS_SRC_ADDR
2363 ld hl,storesave_end-storesave_start
2364 cal _SET_MM_NUM_BYTES
2365 cal _mm_ldir ;save done (cal \ ret)
2368 game_over: ;stack=+0
2369 cal BLACKLCD ;clear screen
2371 ld (_curRow),hl ;center
2373 cal _puts ;display "GAME OVER"
2374 cal releasekeys ;wait for all keys to be released
2455 xor a ;clear a (Ahl will be displayed)
2456 ld hl,$1006 ;bottom-1 right
2457 ld (_curRow),hl ;set
2458 ld hl,(your_score) ;your score
2459 cal _dispahl ;display it (a=0)
2461 ld hl,$314b ;bottom-1 right before score ^^
2462 ld (_penCol),hl ;set
2463 ld hl,txt_score ;"Score"
2464 cal _vputs ;display (small)
2466 ld hl,$1007 ;bottom right
2467 ld (_curRow),hl ;set
2468 ld hl,(hiscore) ;hi-score
2469 cal _dispahl ;display
2470 ld hl,$3946 ;bottom right before hiscore ^^
2471 ld (_penCol),hl ;set
2472 ld hl,txt_hiscore ;"Hiscore"
2473 cal _vputs ;display (small)
2478 ld hl,VIDEO_MEM+(49*16)-1
2484 cal _getkey ;wait for keypress
2485 jp quit ;restore some things and return to TI-OS/shell
2487 invship: ;procedure used in New_game
2491 ld hl,VIDEO_MEM+$30-$C0;begin pos
2495 ld b,$B0 ;12 lines down
2501 dnz invshiploop ;loop
2505 New_game: ;stack must be +1 (so change the jp in cal :)
2508 ld (PutWhere),hl ;will be reset after displaying iconbar
2509 ld ix,spr_ship01 ;first ship: sprite
2510 ld de,$0105 ;position
2511 ld b,4 ;number of ships to display
2515 cal putwidesprite ;display
2517 ld bc,spr_ship01i-spr_ship01+2
2518 add ix,bc ;go to next ship
2519 ld a,12 ;below the previous one
2523 dnz dispshipsloop ;loop
2539 jr z,startthenewgame
2541 jr z,startthenewgame
2556 ld hl,spr_ship01-(spr_ship02-spr_ship01)
2557 ld de,spr_ship02-spr_ship01
2558 inc b ;your ship #0-3++
2560 add hl,de ;next ship
2564 ld (your_score),a ;reset score
2565 ld (your_score+1),a ;reset score (0)
2566 ld (your_tail),a ;no tail beam
2567 ld (your_weapon),a ;no laser
2568 ld (your_pickup),a ;reset pickups
2569 ld (your_multiples),a ;no multiples
2571 ld (level),a ;reset level nr (#1)
2572 ld hl,level00 ;set level pointer to level#1
2573 ld (levelp),hl ;reset level pointer
2575 ld (your_lives),a ;3 lives (4 will be decreased @ You_die)
2576 ld (pickuptimer),a ;next pickup after 4 enemies destroyed
2578 You_die: ;stack must be +1
2579 pop hl ;restore stack
2581 ld (your_armor),a ;12 HPs/shields
2582 ld a,(your_lives) ;load lives left
2583 dec a ;decrease lives
2584 ld (your_lives),a ;if lives=0ffh GO
2585 inc a ;if -1 then zf set now
2586 jp z,game_over ;and game's over
2589 ;--------------------------- next level -------------------------------------
2591 Next_level: ;stack must be +1
2594 cal inc_armor ;increase armor
2595 ld hl,level ;level number
2602 ld h,0 ;increase score....
2603 ld l,a ;by level number * 4
2606 cal scoreInc ;update score
2608 ld hl,(levelp) ;level pointer
2609 ld b,0 ;advance one level
2611 add hl,bc ;passed the enemies
2613 add hl,bc ;update to point to next level
2614 ld (levelp),hl ;save
2618 ld (your_shipspr),hl
2621 ld (nextevent),a ;time to first enemy appearance
2623 ld hl,(levelp) ;level pointer
2628 ld a,(hl) ;number of (different) enemies in this level
2631 ld (nrlvlenemies),a ;set nr of enemies-1
2632 ld b,0 ;bc=c so we can use ldir
2633 ld de,lvlenemies ;table of enemies
2634 ldir ;load enemies to table
2635 ld a,(hl) ;load new appearance-time
2639 ld (eventtime+1),a ;set
2641 ld a,(hl) ;load nr of enemies in this level
2642 ld (eventleft),a ;set nr of events left
2647 ld a,(hl) ;movement of enemies in this level
2648 ld (level_move),a ;do it
2663 ld (timer),a ;reset time
2664 ld hl,your_occ ;hl = your_occ
2665 ld (hl),a ;reset your ship (not exploding)
2666 inc hl ;hl = your_inv
2667 ld (hl),25 ;set 25*4=100 frames invulnerable
2669 ld (x),de ;begin position (x,y)
2670 cal Place_multiples ;place all multiple-positions at that (0,24)
2672 cal loadweapon ;load (your_weapon)
2674 ld hl,enemies ;remove all enemies and bullets
2675 ld (hl),0 ;clear first byte
2676 ld de,enemies+1 ;copy this to the next byte
2677 ld bc,(nrenemies*enemysize)+(nrybuls*4)+(nrebuls*3)-1
2678 ldir ;clear enemies + bullets (y/e)
2680 ;--------------------------- setup game -------------------------------------
2683 cal BLACKLCD ;white on black
2686 ld (_curRow),de ;center
2687 cal _puts ;display "LEVEL "
2689 ld a,(level) ;current level
2692 cal UNPACK_HL ;create first digit
2695 cal UNPACK_HL ;second digit
2697 cal _putc ;display second digit
2699 cal _putmap ;display first digit
2701 ld hl,txt_lives ;bar text: "Lx0"...
2703 ld (_curRow),de ;display lives left below level nr
2705 ld a,(your_lives) ;lives left
2706 add a,'0' ;make value 0='0'
2709 cal releasekeys ;wait for user to release all keys
2710 ld hl,txt_savekey ;"Press [F1] to save"
2711 ld de,$3A46 ;bottom-right
2715 res 3,(iy+5) ;set white on black
2716 cal _getkey ;wait for keypress
2720 cal _clrLCD ;clear screen
2721 cal disp_icons ;display bottom icons +ret
2725 cal RandomY ;a = random y-pos 1..bottom
2726 ld a,b ;a = b = star nr. = 1..7
2727 add a,a ;a = 2b = 2..14
2729 ld e,a ;de = a = 2-14
2731 sbc hl,de ;substract from random y => random pos anywhere
2733 ld (ix),l ;save x-pos (l)
2734 ld (ix+1),h ;save y-pos (h)
2735 inc ix \ inc ix ;next star
2736 dnz placestars ;repeat for all stars
2749 ld (weapdamage),a ;damage of bullets
2752 ld (weapdaminc),a ;damage increase
2755 ;----------------------------------------------------------------------------
2756 ;--------------------------- putsprite --------------------------------------
2757 ;----------------------------------------------------------------------------
2758 ;in: de=(x,y); ix=sprite
2759 ;out: ix=behind sprite; hl:a=right below sprite; b=0; d=width; ce=?
2762 ld c,(ix) ;save width
2763 _putsprite: ;putsprite with custom width
2765 bit 7,d ;check sign bit of X
2766 jr z,CSpositive ;X>=0
2769 cp (ix) ;off screen?
2770 ret nc ;X<=-width: don't draw at all
2771 ld b,a ;b=|X|mod 8=1..7=bits to draw
2772 ld a,%11111111 ;all bits set (draw everything)
2774 srl a ;remove first bit in a for each b
2775 dnz CSclipleft ;b=1: a=%01111111
2782 res 7,d ;X+128 (right side of screen)
2784 jr CSdisplay ;done clipping
2787 sub 129-8 ;minus (screen width - byte width)
2789 ld a,%11111111 ;clipmask
2790 jr c,CSdisplay ;x+width<128 then entire sprite is on screen
2791 inc b ;b = number of pixels off screen
2793 add a,a ;remove last bit in a for each b
2794 dnz CSclipright ;b=1: a=%11111110
2801 ;b>7: a=%00000000 = off screen
2803 CSdisplay: ;display the sprite ix at (d,e) masked
2804 ld (CSclipmask),a ;set mask
2805 cal findpixel ;convert de to screen location hl:a
2811 psh bc ;save rows to go
2814 ld a,(ix+2) ;load image line
2820 ld a,1 ;saved bitmask
2822 sla c ;test leftmost pixel
2823 jr nc,CSnodraw ;don't draw if it's 0
2824 ld e,a ;psh af: save bitmask
2826 ld (hl),a ;OR pixel with screen
2830 jr nc,CSbitdrawn ;carry set if bit "jumped"
2834 pop hl ;screen at x-offset=0
2836 add hl,bc ;next line
2837 pop bc ;rows counter
2841 ;--------------------------- putbigsprite -----------------------------------
2844 ;destr: abcdehl+ix (ix=behind sprite; hl:a=right below sprite; b=0; d=width)
2847 jr c,putsprite ;width<=8: just draw the sprite
2854 cal _putsprite ;otherwise draw one column (8 pixels wide)
2856 inc ix ;no x-size to load
2858 add a,d ;8 pixels right
2860 pop bc ;then draw the remaining pixels (c=width-8)
2864 safeputsprite: ;cal putsprite with de intact
2870 ;------------------------------- findpixel ----------------------------------
2871 ;based upon CLEM's fp | 131 cycles | 28 bytes | in:(d,e); out:hla; destr:de
2876 add a,a ;add a,a is 7 cycles faster than add hl,hl
2877 ld h,0 ;switch to hl now (Y<64)
2880 rra ;RRA: carry flag must be reset!
2881 add hl,hl ;that's what the adds are for :P
2897 ld de,GRAPH_MEM ;screen base position (where x+y=0)
2902 ;----------------------------------------------------------------------------
2903 ;------------------------------- sprites ------------------------------------
2904 ;----------------------------------------------------------------------------
2907 .db 7,7 ;ship alpha class
2910 .db %01111110 ; ██████
2911 .db %11101000 ;███ █
2912 .db %01111110 ; ██████
2918 .db %11110001 ;████ █
2919 .db %01111111 ; ███████
2920 .db %11101001 ;███ █ █
2921 .db %01111111 ; ███████
2922 .db %11110001 ;████ █
2926 .db 7,7 ;ship beta class
2929 .db %01111100 ; █████
2930 .db %01110010 ; ███ █
2931 .db %01111100 ; █████
2936 .db %11100010 ;███ █
2937 .db %11110001 ;████ █
2938 .db %01111101 ; █████ █
2939 .db %01110011 ; ███ ██
2940 .db %01111101 ; █████ █
2941 .db %11110001 ;████ █
2942 .db %11100010 ;███ █
2945 .db 7,7 ;ship gamma class
2946 .db %11111000 ;█████
2948 .db %11111100 ;██████
2949 .db %11100110 ;███ ██
2950 .db %11111100 ;██████
2952 .db %11111000 ;█████
2955 .db %11111010 ;█████ █
2956 .db %01100001 ; ██ █
2957 .db %11111101 ;██████ █
2958 .db %11100111 ;███ ███
2959 .db %11111101 ;██████ █
2960 .db %01100001 ; ██ █
2961 .db %11111010 ;█████ █
2964 .db 7,7 ;ship delta class
2966 .db %11110000 ; ████
2967 .db %11111100 ; ██████
2968 .db %01100010 ; ██ █
2969 .db %11111100 ; ██████
2970 .db %11110000 ; ████
2974 .db %11000010 ; ██ █
2975 .db %11110001 ; ████ █
2976 .db %11111101 ; ██████ █
2977 .db %01100011 ; ██ ██
2978 .db %11111101 ; ██████ █
2979 .db %11110001 ; ████ █
2980 .db %11000010 ; ██ █
2984 .db %01111000 ; ████
2985 .db %11001100 ; ██ ██
2987 .db %11001100 ; ██ ██
2988 .db %01111000 ; ████
2990 ;-------------------------------- explosion ---------------------------------
2996 .db %00111110 ; █████
2997 .db %01010110 ; █ █ ██
3003 .db %01001110 ; █ ▒███
3004 .db %10111110 ; █ █████
3005 .db %01001111 ; █ ▒████
3007 .db %00011010 ; ██ █
3010 .db %10110000 ; █ ██
3011 .db %01001110 ; █ ███
3012 .db %10110101 ; █ ██▒█▒█
3013 .db %01000101 ; █ ▒█▒█
3014 .db %00111110 ; █████
3015 .db %01011010 ; █ ██ █
3018 .db %00101010 ; ▒ █▒█ █
3019 .db %01000110 ; █ ▒██
3020 .db %10110101 ; █ ██ █ █
3021 .db %01100110 ; ██ ██▒
3022 .db %00111100 ; ████▒
3023 .db %01011001 ; █ ██ ▒█
3026 .db %01000000 ; █▒ ▒ ▒
3027 .db %00100101 ; ▒█ █▒█
3028 .db %00010100 ; ▒ ▒█ █ ▒
3029 .db %01000100 ; █▒ █
3030 .db %00010010 ; ▒█▒▒█
3031 .db %10011010 ; █▒ ██ █▒
3035 .db %00100000 ; ▒█ ▒ ▒
3036 .db %00000001 ; ▒ ▒ █
3038 .db %00100010 ; █▒ █
3039 .db %01001000 ; ▒█ ▒█ ▒
3042 .db %00001000 ; ▒ █▒
3043 .db %11000010 ; ██ ▒ █
3045 .db %00100000 ; ▒█ ▒
3046 .db %00000001 ; ▒ ▒█
3047 .db %00110000 ; ▒██▒
3051 .db %00000000 ; ▒▒ ▒
3055 .db %00100100 ; █▒ █
3060 .db %00101100 ; █ ██
3061 .db %00011110 ; ████
3062 .db %00110100 ; ██ █
3068 .db %01011100 ; █ ███
3069 .db %10010111 ;█ █ ███
3070 .db %01000110 ; █ ██
3075 .db %00111100 ; ████
3076 .db %01001111 ; █ ████
3077 .db %10100011 ;█ █ ██
3078 .db %11000110 ;██ ██
3079 .db %01110101 ; ███ █ █
3083 .db %00110110 ; ██ ██
3086 .db %01100001 ; ██ █
3088 .db %01010001 ; █ █ █
3090 ;--------------------------------- bullets ----------------------------------
3097 .db %11110000 ;▒████
3109 .db %11110000 ;▒████
3114 .db %11111000 ;▒█████
3118 .db %01110000 ; ▒███
3119 .db %11111000 ;▒█████
3120 .db %01110000 ; ▒███
3123 .db %11110000 ;▒████
3124 .db %11111000 ;▒█████
3125 .db %11110000 ;▒████
3129 .db %10111000 ;▒█▒███
3130 .db %01111000 ; ▒████
3134 .db %00111000 ; ▒███
3135 .db %01111100 ; ▒█████
3136 .db %11111100 ;▒██████
3141 .db %11111100 ;▒██████
3142 .db %00111110 ; ▒█████
3143 .db %01111100 ; ▒█████
3148 .db %11111100 ;▒██████
3149 .db %00111110 ; ▒█████
3150 .db %01111110 ; ▒██████
3151 .db %11111100 ;▒██████
3152 .db %00111000 ; ▒███
3155 .db %00111100 ; ▒████
3156 .db %11111110 ;▒███████
3157 .db %01111111 ; ▒███████
3158 .db %00011111 ; ▒█████
3159 .db %01111111 ; ▒███████
3160 .db %11111110 ;▒███████
3161 .db %00111100 ; ▒████
3165 .db %11110000 ; ████
3169 .db 4,3 ;enemy bullets
3171 .db %11110000 ;████▒
3175 .db (spr_bullet01-spr_bullet01) ;0
3176 .db (spr_bullet02-spr_bullet01) ;4
3177 .db (spr_bullet03-spr_bullet01) ;8
3178 .db (spr_bullet04-spr_bullet01) ;12
3179 .db (spr_bullet05-spr_bullet01) ;16
3180 .db (spr_bullet06-spr_bullet01) ;20
3181 .db (spr_bullet07-spr_bullet01) ;24
3182 .db (spr_bullet08-spr_bullet01) ;28
3183 .db (spr_bullet09-spr_bullet01) ;32
3184 .db (spr_bullet10-spr_bullet01) ;36
3185 .db (spr_bullet11-spr_bullet01) ;40
3186 .db (spr_bullet12-spr_bullet01) ;44
3187 .db (spr_bullet13-spr_bullet01) ;48
3188 .db (spr_bullet13-spr_bullet01) ;52
3189 .db (spr_bullet13-spr_bullet01) ;56
3190 .db (spr_bullet13-spr_bullet01) ;60
3192 ;format:[min.damage] [dam.inc] [000:direction 00000:speed] [offset]
3193 ;damage = min.damage + dam.inc*incs (0<=incs<=6)
3194 ;speed in pixels/frame (>=%10010=forward; <=%01110=backwards)
3195 ;direction: 0=straight forward; 1=up; 2=1/2up; 3=down; 4=1/2down
3199 .db 1,1,%00000000,0,%00000000,0,%00010010,3 ;1 single fire
3200 .db 6,1,%00000000,0,%00000000,0,%00010011,3 ;2 fast single
3201 .db 1,1,%00000000,0,%00010010,0,%00010010,6 ;3 double
3202 .db 1,1,%01110010,2,%10010010,2,%00110010,2 ;4 triple
3203 .db 3,2,%01110011,2,%10010011,2,%00110011,2 ;5
3204 .db 5,3,%01110011,2,%10010100,2,%00110011,2 ;6
3205 .db 7,4,%01110100,2,%10010100,2,%00110100,2 ;7
3206 .db 12,5,%01110110,2,%10010110,2,%00110110,2 ;8
3208 .db 1,1,%00000000,0,%00000000,0,%11100000,3 ;1 single laser
3209 .db 1,1,%00000000,0,%11100000,0,%11100000,6 ;2 double laser
3210 .db 1,1,%11100000,0,%11100000,6,%11100000,3 ;3 triple laser
3215 ;------------------------------------ bar -----------------------------------
3225 .db 16,7 ;selected .......:.......:
3226 .db %11111111 ; ████████████████
3227 .db %11000000 ; ██ █
3228 .db %11000000 ; ██ █
3229 .db %11000000 ; ██ █
3230 .db %11000000 ; ██ █
3231 .db %11000000 ; ██ █
3232 .db %11111111 ; ████████████████
3242 .db 16,7 ;unused .......:.......:
3243 .db %10101010 ; █ █ █ █ █ █ █ █
3244 .db %11010101 ; ██ █ █ █ █ █ █ █
3245 .db %10101010 ; █ █ █ █ █ █ █ █
3246 .db %11010101 ; ██ █ █ █ █ █ █ █
3247 .db %10101010 ; █ █ █ █ █ █ █ █
3248 .db %11010101 ; ██ █ █ █ █ █ █ █
3249 .db %10101010 ; █ █ █ █ █ █ █ █
3259 .db 16,7 ;armor ; .......:.......:
3260 .db %10000111 ; █ ███████
3261 .db %10011000 ; █ ██ ██
3262 .db %10110011 ; █ ██ ████ ██
3263 .db %10110000 ; █ ██ ████ ██
3264 .db %10110011 ; █ ██ ████ ██
3265 .db %10011000 ; █ ██ ██
3266 .db %10000111 ; █ ███████
3276 .db 16,7 ;tailbeam .......:.......:
3278 .db %10000011 ; █ ██
3279 .db %10000001 ; █ ███
3280 .db %10111011 ; █ ███ ██████ ██
3281 .db %10000001 ; █ ███
3282 .db %10000011 ; █ ██
3293 .db 16,7 ;torpedo .......:.......:
3294 .db %10111000 ; █ ███ █ █ █
3295 .db %10011100 ; █ ███ █ █ █
3296 .db %10111000 ; █ ███ █ █ █
3297 .db %10000000 ; █ ███ █ █
3298 .db %11100001 ; ███ ████ █ █
3299 .db %10011000 ; █ ██ ████ █ █
3300 .db %11100110 ; ███ ██ ██ █
3310 .db 16,7 ;bullets .......:.......:
3311 .db %10000000 ; █ ██
3312 .db %10000011 ; █ █████ ▒▒▒
3313 .db %10011000 ; █ ██ ██ ▒▒▒
3314 .db %11111100 ; ██████ ▒▒▒
3315 .db %10011000 ; █ ██ ██ ▒▒▒
3316 .db %10000011 ; █ █████ ▒▒▒
3317 .db %10000000 ; █ ██
3327 .db 16,7 ;laser .......:.......:
3329 .db %10001010 ; █ █ █ ▒▒▒
3330 .db %11101100 ; ███ ██ ▒▒▒
3331 .db %11110111 ; ████ ███████▒▒▒█
3332 .db %11101100 ; ███ ██ ▒▒▒
3333 .db %10001010 ; █ █ █ ▒▒▒
3344 .db 16,7 ;multiple .......:.......:
3345 .db %10000011 ; █ ███
3346 .db %10000001 ; █ ████ ██
3347 .db %10000001 ; █ ████
3348 .db %10000011 ; █ ███
3349 .db %10011000 ; █ ██
3350 .db %10111100 ; █ ████ ██ ██
3351 .db %10011000 ; █ ██
3362 .db 128,128,128,128,128,128,128 ;128 = %10000000
3364 ;---------------------------- texts -----------------------------------------
3366 txt_email: .db "www.shiar.org ",127 ;title screen
3367 .db " shiar0@hotmail.com",0
3368 _txt_email = $3A01 ;$3A1E=just email
3369 txt_about: .db "v0.97.73 ",127," by Shiar",0 ;right behind txt_email
3371 txt_menu1: .db "NEW GAME",0
3372 txt_menu2: .db "CONTINUE",0
3374 txt_level: .db "LEVEL ",0 ;new level screen
3375 txt_lives: .db "Lx0",0
3376 txt_savekey: .db "Press [F1] to save",0
3378 txt_gameover: .db "GAME OVER!",0 ;game over screen
3379 txt_score: .db "Score",0
3380 txt_hiscore: .db "Hiscore",0
3382 txt_pressenter: .db "Enter to continue",0 ;pause
3383 txt_teacher: .db "(2",Lpi,"*.97)/sin 13",0 ;boss
3384 txt_teacherans: .db Lneg,"14.5053971725",0
3386 ;---------------------------- save data -------------------------------------
3390 hiname .db "shiar.97",0
3394 level .db $01 ;level number
3395 levelp .dw level01 ;pointer to level data
3396 pickuptimer .db $04 ;counts when to place a pickup
3397 your_ship .dw spr_ship01 ;your sprite
3398 your_score .dw $0000 ;current score
3401 your_occ .db $00 ;0=normal 1..16=exploding
3402 your_inv .db $00 ;invincibility left
3403 your_armor .db $0a ;HP left
3404 your_lives .db $03 ;
3406 your_weapon .db $00 ;current weapon upgrade
3407 your_multiples .db $00 ;multiples present
3408 your_tail .db $01 ;tail beam present
3411 time2invert: .db 0 ;time until b<>w switch (0 at startup)
3413 ;XLlevelsdata:---------------------------------------------------------------
3415 ;format:boss: [moveType] [enemyType]
3416 ; @level: [nr.dif.enemies]x [enemy nr]
3417 ; [min. enemy frequency] [enemy frequency max.inc] [next lvl]
3418 ; [level_info: 0000:damage 0:diagfire 0:ground 0:ceiling 0:?]
3419 ; [level_move] [tunnel size] [groundtype]
3420 ; [16_ground] [16_ceiling] [stars1] [stars2]
3421 ;efrequency must be odd if halfluring!
3424 .db 0 ;story identifier
3425 .db $21,$1d,"Cosmic year 6716" ,0,0,$1d,$06
3426 .db $1b,$1d,"STORYLINE COMING SOON" ,0,0,$1d,$06
3427 .db $09,$19,"STORYLINE COMING SOON" ,0,1
3428 .db $2e,$21,"**** NEMESIS 86" ,0,1
3429 .db $52,$36,"by Shiar" ,0,0,$19,$23
3433 level01: ;first wave of enemies; easeey
3435 .db 20,60,60,%00010000,0,0,0
3436 .db 1,2,3,4,5,6,6,5,4,3,4,5,4,5,6,5
3437 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3441 level02: ;some more enemies
3443 .db 17,40,75,%00010000,0,0,0
3444 .db 1,2,3,4,5,6,6,5,4,3,4,5,4,5,6,5
3445 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3451 .db 1,1,"Long-Range scanners are ",
3453 .db 1,8,"lots of enemy vessels on ",
3454 .db "an intercept",0,1
3455 .db 1,15,"course.",0,1
3456 .db 1,24,"I'm changing course to a",
3458 .db 1,31,"asteroid belt and try to",0,1
3459 .db 1,38,"lose them inthere.",0,0
3463 level04: ;light asteroid belt
3465 .db 12,24,80,%00011000
3467 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ;16
3468 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3472 level05: ;inside asteroid belt
3474 .db 6,10,180,%00101000
3476 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ;16
3477 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3483 .db 30,1,40,%00010000
3485 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ;16
3486 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3492 .db $01,01,"And the storyline conti",
3494 .db $01,09,"You decide to fly close",
3496 .db $01,15,"surface of a nearby pl",
3497 .db "anet =)",0,0,1,20
3503 .db $13,40,$4b,%00100100,0,-5,1
3504 .db 1,2,3,4,5,6,6,5,4,3,4,5,4,5,6,5
3505 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3511 .db $01,01,"Blablabla...",0,1
3512 .db $01,34,"this storyline sux",0,0,1,39
3518 .db $2d,$3f,%00010110,0,-9,1
3519 .db 3,2,4,3,2,2,1,1,1,1 ,1,1,21,17,18,20
3520 .db 1,1,1,1,1,1,1,3,6,12,9,1,21,19,18,18
3521 .db -1,-1 ;=%11111111=line
3526 .db $11,$41,%00100001,0,0,0
3527 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3528 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3533 .db $11,$45,%00100101,%10,-7,1
3534 .db 14,12,11,9,10,7,7,5,4,3,4,4,2,3,1,2
3535 .db 1, 1, 1, 1,1, 1,1,1,1,1,1,1,1,1,1,1
3540 .db $19,$3a,%00100111,0,-4,1
3541 .db 20,22,18,15,9,1,1,1,1,1,1,1,1,1,1,1
3542 .db 20,22,18,15,9,1,1,1,1,1,1,1,1,1,1,1
3548 .db $09,$ff,%00100001,0,0,0
3549 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3550 .db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3553 ;------------------------------ enemies -------------------------------------
3555 ;format: [HP64] [000000:HP 00:occ] [sprite] [xpos] [appearance(ypos)]
3556 ; [movetype] [time2fire] [firefreq]
3558 ; 1=updown; 2=1/4x; 3=1/2x; 4=1.5x; 5=2x; 6=smart; 7=y-lure;
3559 ; 8=y-lure 1/2x; 9=8 stop at x=99; 10=x+y-lure 1/2x
3562 .db 0,%00100110,(spr_enemyA1-spr_enemy00)/2,128,1,0,0,0
3563 .db 0,%00111110,(spr_enemyA2-spr_enemy00)/2,128,1,0,0,0
3564 .db 0,%01011010,(spr_enemyA3-spr_enemy00)/2,128,1,4,0,0
3565 .db 1,%00001010,(spr_enemyA4-spr_enemy00)/2,128,1,3,0,0
3566 .db 0,%00111110,(spr_enemyA4-spr_enemy00)/2,128,1,5,0,0
3568 .db 0,%00100110,(spr_enemy13-spr_enemy00)/2,128,1,0,1,0
3570 .db 0,%00101110,(spr_enemy04-spr_enemy00)/2,128,3,0,19,39
3571 ;8=jumping bug (up/down)
3572 .db 0,%00001111,(spr_enemy12-spr_enemy00)/2,128,2,1,87,5
3574 .db 0,%00000110,(spr_enemy04-spr_enemy00)/2,2,0,0,0,0 ;9=
3575 .db 0,%00000111,(spr_enemy05-spr_enemy00)/2,3,0,0,0,0 ;10=
3576 .db 0,%00001011,(spr_enemy06-spr_enemy00)/2,2,0,0,0,0 ;11=
3578 .db 0,%00011011,(spr_enemy07-spr_enemy00)/2,3,0,0,0,0 ;12=
3579 .db 0,%00000011,(spr_enemy07-spr_enemy00)/2,1,0,0,0,0 ;13=
3580 .db 0,%00000011,(spr_enemy07-spr_enemy00)/2,1,0,0,0,0 ;14=
3581 .db 0,%00000011,(spr_enemy07-spr_enemy00)/2,1,0,0,0,0 ;15=
3582 .db 0,%00000011,(spr_enemy07-spr_enemy00)/2,1,0,0,0,0 ;16=
3583 .db 0,%00000011,(spr_enemy07-spr_enemy00)/2,1,0,0,0,0 ;17=
3584 .db 0,%00000011,(spr_enemy07-spr_enemy00)/2,1,0,0,0,0 ;18=
3585 .db 0,%00000011,(spr_enemy07-spr_enemy00)/2,1,0,0,0,0 ;19=
3586 .db 0,%00000011,(spr_enemy07-spr_enemy00)/2,1,0,0,0,0 ;20=
3588 .db 1,%00110011,(spr_boss0_1-spr_enemy00)/2,128,1,7,15,10 ;21=sm_boss1
3589 .db 1,%01001011,(spr_boss0_2-spr_enemy00)/2,128,3,9,10,9 ;22=sm_boss2
3590 .db 2,%00001011,(spr_boss0_3-spr_enemy00)/2,128,1,0,36,14 ;23=asteroid
3591 .db 2,%00110011,(spr_boss0_3-spr_enemy00)/2,128,2,0,28,12 ;24=asteroid
3592 .db 2,%00000111,(spr_boss0_4-spr_enemy00)/2,128,3,0,18,7 ;25=bigboss1
3593 .db 2,%01001011,(spr_boss0_5-spr_enemy00)/2,128,3,0,18,7 ;26=bigboss2
3595 .db 0,%00000000,0,0,0,0,0,0
3596 .db 0,%00000000,0,0,0,0,0,0
3597 .db 0,%00000000,0,0,0,0,0,0
3598 .db 0,%00000000,0,0,0,0,0,0
3599 .db 0,%00000000,0,0,0,0,0,0
3600 .db 0,%00000000,0,0,0,0,0,0
3601 .db 0,%00000000,0,0,0,0,0,0
3605 .db %11111111 ; ████████████
3606 .db %10000110 ; █ ██ █
3607 .db %10000110 ; █ ██ █
3608 .db %10111111 ; █ ████████ █
3609 .db %10111111 ; █ ████████ █
3610 .db %10000110 ; █ ██ █
3611 .db %10000110 ; █ ██ █
3612 .db %11111111 ; ████████████
3625 .db 7,6 ;asteroid one
3627 .db %01101100 ; ██ ██
3628 .db %10011110 ;█ ████
3629 .db %11111010 ;█████ █
3630 .db %10111100 ;█ ████
3633 .db 8,7 ;asteroid two
3634 .db %00111100 ; ████
3635 .db %01011010 ; █ ██ █
3636 .db %01101101 ; ██ ██ █
3637 .db %11111101 ;██████ █
3638 .db %11111111 ;████████
3639 .db %10110110 ;█ ██ ██
3643 .db 8,8 ;asteroid three
3644 .db %00011110 ; ████
3645 .db %01110011 ; ███ ██
3646 .db %01111101 ; █████ █
3647 .db %10110111 ;█ ██ ███
3648 .db %11111110 ;███████
3649 .db %11111101 ;██████ █
3650 .db %01010111 ; █ █ ███
3653 .db 7,6 ;asteroid four
3654 .db %01111000 ; ████
3655 .db %10110110 ;█ ██ ██
3656 .db %11111101 ;██████ █
3657 .db %01111011 ; ████ ██
3658 .db %01001110 ; █ ███
3661 .db 6,6 ;enemy type one
3662 .db %00111100 ; ████
3664 .db %11110000 ; ████
3665 .db %11110000 ; ████
3667 .db %00111100 ; ████
3669 .db 8,6 ;enemy type two
3670 .db %00111111 ; █████
3671 .db %01111000 ; ████
3672 .db %11111100 ; ██████
3673 .db %11111100 ; ██████
3674 .db %01111000 ; ████
3675 .db %00111111 ; █████
3677 .db 6,6 ;enemy type three
3678 .db %01111100 ; █████
3679 .db %11110000 ; ████
3680 .db %11111000 ; █████
3681 .db %11111000 ; █████
3682 .db %11110000 ; ████
3683 .db %01111100 ; █████
3685 .db 6,6 ;enemy type four
3687 .db %01111100 ; █████
3688 .db %11111000 ; █████
3689 .db %11111000 ; █████
3690 .db %01111100 ; █████
3693 .db 7,6 ;enemy type five
3694 .db %00011110 ; ████
3695 .db %01111110 ; ██████
3696 .db %11111100 ; ██████
3697 .db %11111100 ; ██████
3698 .db %01111110 ; ██████
3699 .db %00011110 ; ████
3701 .db 7,6 ;enemy type six
3703 .db %01110010 ; ███ █
3704 .db %10101100 ; █ █ ██
3705 .db %10101100 ; █ █ ██
3706 .db %01110010 ; ███ █
3709 .db 8,6 ;enemy type seven
3710 .db %00011011 ; ██ ██
3711 .db %01110110 ; ███ ██
3712 .db %10111100 ; █ ████
3713 .db %10111100 ; █ ████
3714 .db %01110110 ; ███ ██
3715 .db %00011011 ; ██ ██
3717 .db 8,7 ;enemy type eight
3718 .db %00111110 ; █████
3719 .db %11110001 ;████ █
3721 .db %00010101 ; █ █ █
3723 .db %11110001 ;████ █
3724 .db %00111110 ; █████
3727 .db 8,7 ;enemy type nine
3728 .db %00111110 ; █████
3729 .db %00011101 ; ███ █
3730 .db %11111111 ;████ ███
3731 .db %01110110 ; ██ ███
3732 .db %11111111 ;████ ███
3733 .db %00011101 ; ███ █
3734 .db %00111110 ; █████
3737 .db 8,7 ;enemy type ten
3738 .db %10111110 ;█ █████
3739 .db %01011101 ; █ ███ █
3740 .db %01111110 ; ██████
3742 .db %01111110 ; ██████
3743 .db %01011101 ; █ ███ █
3744 .db %10111110 ;█ █████
3747 .db 6,6 ;enemy type eleven
3748 .db %00111100 ; ████
3753 .db %00111100 ; ████
3756 .db 16,10 ;boss type one :
3757 .db %00000001 ; █████████
3758 .db %00001111 ; ███████████
3759 .db %00111111 ; ██████████
3760 .db %01011111 ; █ ██████
3761 .db %10011111 ; █ █████ █
3762 .db %10011111 ; █ █████ █
3763 .db %01011111 ; █ ██████
3764 .db %00111111 ; ██████████
3765 .db %00001111 ; ███████████
3766 .db %00000001 ; █████████
3780 .db 16,10 ;boss type two :
3781 .db %11111110 ; ███████
3782 .db %00001111 ; █████ ████
3783 .db %00111111 ; █████████ ██
3784 .db %01001111 ; █ ███████████
3785 .db %10001101 ; █ ██ █ █████
3786 .db %10001101 ; █ ██ █ █████
3787 .db %01001111 ; █ ███████████
3788 .db %00111111 ; █████████ ██
3789 .db %00001111 ; █████ ████
3790 .db %11111110 ; ███████
3802 .db 16,11 ;bigasteroid one
3803 .db %00011110 ; ████
3804 .db %01110011 ; ███ ███
3805 .db %01111111 ; ███████ █
3806 .db %01111111 ; █████████
3807 .db %11111110 ;███████ ███
3808 .db %11111110 ;███████████
3809 .db %11111111 ;████████████
3810 .db %11111110 ;███████ ████
3811 .db %01111110 ; █████████
3812 .db %00111110 ; ██████
3826 .db 16,18 ;bigboss one :
3828 .db %00000111 ; ███ ███
3829 .db %00000011 ; ████ █
3830 .db %00000001 ; ██ ██
3831 .db %00000011 ; ███ ██
3832 .db %00000000 ; █████
3833 .db %00010111 ; █ ██████████
3834 .db %00111111 ; ██████ ██ ██
3835 .db %11111000 ;█████ ██ █ ███
3836 .db %00001111 ; █████ ██ █ █
3837 .db %11111000 ;█████ ██ █ ███
3838 .db %00111111 ; ██████ ██ ██
3839 .db %00010111 ; █ ██████████
3840 .db %00000000 ; █████
3841 .db %00000011 ; ███ ██
3842 .db %00000001 ; ██ ██
3843 .db %00000011 ; ████ █
3844 .db %00000111 ; ███ ███
3866 .db 16,15 ;bigboss two :
3867 .db %00001111 ; █████
3868 .db %00111110 ; █████ █████
3869 .db %01111101 ; █████ █ ███████
3872 .db %00000011 ; █████
3873 .db %00011110 ; ████ ██ ████
3874 .db %11110011 ;████ ██ █ █
3875 .db %00011110 ; ████ ██ ████
3876 .db %00000011 ; █████
3879 .db %01111101 ; █████ █ ███████
3880 .db %00111110 ; █████ █████
3881 .db %00001111 ; █████
3900 ;----------------------------------------------------------------------------
3901 ;----------------------------- logo ------------------------------------------
3902 ;----------------------------------------------------------------------------
3905 .db %11111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00001011,%11111111,%11111111,%11111111,%11111000
3906 .db %01111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00011011,%11111111,%11111111,%11111111,%11110000
3907 .db %00111111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%00111011,%11111111,%11111111,%11111111,%11100000
3908 .db %00011111,%11111111,%11111111,%11111110,%11111111,%11110111,%11111111,%11111110,%11111111,%111101111,%11111111,%01111011,%11111111,%11111111,%11111111,%11000000
3909 .db %00000000,%00000000,%00000001,%00011110,%00010000,%00000000,%10000001,%00011110,%00010000,%000000001,%00000000,%00001000,%01000000,%00000000,%00000000,%00000000
3910 .db %00000000,%00000000,%00000011,%00011110,%00110000,%00000001,%10000011,%00011110,%00110000,%000000011,%00000000,%00011000,%11000000,%00000000,%00000000,%00000000
3911 .db %00000000,%00000000,%00000111,%00011110,%01110000,%00000011,%10000111,%00011110,%01110000,%000000111,%00000000,%00111001,%11000000,%00000000,%00000000,%00000000
3912 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
3913 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
3914 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
3915 .db %00000000,%00000000,%00001111,%00011110,%11111111,%00000111,%10001111,%00011110,%11111111,%000001111,%11111111,%01111011,%11111111,%11000000,%00000000,%00000000
3916 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
3917 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
3918 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
3919 .db %00000000,%00000000,%00001111,%00011110,%11110000,%00000111,%10001111,%00011110,%11110000,%000000000,%00001111,%01111000,%00000011,%11000000,%00000000,%00000000
3920 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000111,%11010001
3921 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00011011
3922 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010101
3923 .db %00000000,%00000000,%00001111,%00011110,%11111111,%11110111,%10001111,%00011110,%11111111,%111101111,%11111111,%01111011,%11111111,%11000000,%00000001,%00010001
3925 ;----------------------------- end ------------------------------------------
3931 ;----------------------------------------------------------------------------
3932 ;----------------------------------------------------------------------------
3933 ;----------------------------------------------------------------------------
3935 ; 0.97.73 -- 3.VII.00 -- size 6612
3937 ; # bullets do damage in all levels
3938 ; * more armor at armor-upgrade and extra armor at end of a level
3939 ; - internal levels again (no need 4 external, safer/smaller)
3940 ; # some registers not correctly pushed/popped
3941 ; * several optimizations (init.procs some bytes smaller)
3942 ; # enemies hit with hitpoints left disappeared (one pop too much...)
3943 ; + bullets "charge up" (more damage) when not firing
3944 ; - removed contrast changes
3945 ; + more powerful bullets have different sprites (larger=more damage)
3946 ; # multiples appear at your position (begin level/just selected)
3947 ; # when invulnerable multiples acted weird
3948 ; # no more error at activation after APD off after running Nemesis
3949 ; # saves correctly if own name ain't "nemesis" + some bytes smaller
3950 ; # screen wasn't always entirely cleared after quit
3951 ; * waits until all keys have been released after death
3952 ; + different bullets sizes will miss if they're too small
3953 ; + at level start "press F1 to save"-text will be displayed
3954 ; * w3.shiar.org displayed at title screen, black bar behind version nr
3955 ; # score to 0 when exit pressed at main menu
3956 ; # no residual story-text in first frame of game
3957 ; # game doesn't continue again after death (stack messed up)
3958 ; # game over when lives<0 (didn't work in v0.96+)
3959 ; * using some self-modifiing code (so it's smaller)
3960 ; # new random procedure: stars don't appear on one line anymore
3961 ; * weapons appear centered at multiples
3962 ; * laser properties can be changed (damage, charge)
3963 ; + weapon can be combination of bullets/lasers (max. of 3 per weapon)
3964 ; * bullet-icon is removed when laser is selected
3965 ; * enemy sprite table integrated in enemy specs (-1 byte/enemy)
3966 ; + random enemy is chosen from any number of enemies per level
3967 ; * time to first enemy fire defined per enemy, not per level
3968 ; + CLIPPED sprites!! no more in/out popping enemies! wow...
3969 ; * bullets/enemies removed when _entirely_ off screen
3970 ; # enemies would sometimes be hit by bullets going right below them
3971 ; # size of the second bullet was too big (invisible hit)
3972 ; * the frequency an enemy fires bullets is defined per enemy
3973 ; + wide clipped sprites implemented (width 1-16 pixels)
3974 ; # bosses first move left until x=100, otherwise they'd be off-screen
3975 ; * at status bar left below ships are displayed for lives left
3976 ; * armor bar is two pixels high (better visible)
3977 ; # bullet overflow fixed again (>63 bullets fired)
3978 ; # correct weapon loaded when continuing a saved game
3979 ; # game freezed when generating a random value <=1
3980 ; * you explode in a different way than the enemies
3981 ; + screen inverts for a brief time when you are hit!
3982 ; # stats-bar was messed up when ya got 0 lives left
3983 ; * two new (big) bosses modeled after a common MSX Nemesis2-boss
3984 ; * score increased once every 32 frames (instead of every 256)
3985 ; # ground fixed for new random routine (smaller routine; incs -2 to 2)
3986 ; + laser will upgrade as well when you reselect it
3987 ; * 2nd can be used in main menu (wow!)
3988 ; # altered variable storage space because of Nemesis grew beyond 6kb
3989 ; # fixed armor bar display when at maximum
3990 ; + a few new enemies (asteroids) and remade 1st 4 levels; new pickup
3991 ; - torpedo since it was kinda useless
3992 ; + second icon now selects TAIL BEAM: bullet going backwards
3993 ; # armor increase at the end of a level doesn't overflow armorbar
3994 ; + you can choose your own ship out of four vessel after NEW GAME!
3995 ; + enemies can appear at any x-position and move both left and right
3996 ; + move patterns given per enemy, not per level
3997 ; * new (faster) enemy-move system; 10 basic moves (x2 left+right)
3999 ; ! game sometimes crashes after running Nemesis:
4000 ; (in TI-OS: screen misformed + freeze)
4002 ; + added - removed * changed # bug fixed