version 0.91: lasers, multiple
authorMischa Poslawsky <nemesis@shiar.org>
Tue, 7 Sep 1999 13:30:12 +0000 (15:30 +0200)
committerMischa Poslawsky <nemesis@shiar.org>
Wed, 18 Mar 2009 02:16:15 +0000 (03:16 +0100)
+ LASERS!!!! four pickups and youll fire laserbeams instead of bullets
* multiple enemies can be hit at once, very usefull when firing lasers
+ MULTIPLE!! like the (shadow)multiple from MSX-Nemesis. for 5 pickups
  you get an multiple following you, firing bullets & lasers like you
* most data (enemy positions) stored at TEXT_MEM & DELC_LEN positions
  instead of in program, saving A LOT of bytes in program-size
- at release of 0.91 bullets didn't work, laser is used instead

nemesis.z80

index cefd4d00cb14c4ef106b40a141b55a6002b91fea..fe86778efbe027b3cf2bdb45881bdcf2e0b19160 100644 (file)
@@ -1,27 +1,50 @@
        .include "asm86.h"
        .include "ti86asm.inc"
+       .include "ram86.inc"
 
        .org _asm_exec_ram
 
 TEXT_MEM = _textShadow
+DELC_LEN = _undelBufLen                ;$64 bytes long
 
-       nop
-       jp  init
+        nop
+        jp init
        .dw $0001               ;description type 2 (= +YASicon)
        .dw Title               ;pointer to description
        .dw spr_ship            ;pointer to YAS icon
 
-Title: .db "Nemesis v0.9.94 by Shiar",0
+Title: .db "Nemesis v0.91.95 by Shiar",0
 
 just_fired     = TEXT_MEM      ;byte
 temp1          = TEXT_MEM+1    ;word
 RanPos         = TEXT_MEM+3    ;byte
+firex          = TEXT_MEM+4    ;byte
+firey          = firex+1       ;byte
+mx             = TEXT_MEM+6    ;byte
+my             = mx+1          ;byte
+your_locpos    = TEXT_MEM+8    ;byte
+your_prevpos   = TEXT_MEM+9    ;16 words
+
+nrybullets     = 10
+ybullets       = your_prevpos+32                       ;20 x (state,x,y)
+nrebullets     = 10
+ebullets       = ybullets+(nrybullets*3)               ;10 x (state,x,y)
+
+nrenemies      = 10
+enemies                = DELC_LEN
+       ; %111111 (HP left) 11 (00=no enemy 01=exploding 10=normal 11=moving)
+       ; %11111111 (ship type or explosion frame)  %11111111 (x) %11111111 (y)
+add2enemy      = nrenemies*4
+enemiesxtra    = enemies+add2enemy
 
 ;---------------------- init --------------------------------------------------
 
 init:
        call _runindicoff       ;turn the run-indicator off, obviously
        call _clrLCD            ;clean the screen
+       ld  (iy+13),0
+       xor a
+       ld  (DELC_LEN),a
 
        ld  a,(CONTRAST)        ;load current contrast level
        cp  $1f                 ;if already at maximum...
@@ -90,32 +113,52 @@ clearloop:
        djnz clearloop          ;repeat 224x
 
 check_exitkey:
-       ld  a,%00111111         ;<exit> pressed?
-       out (1),a
-       nop \ nop
-       in  a,(1)
-       bit 6,a                 ;test bit 6 = <EXIT>
-        jr  z,quit              ;yes: quit game
+       call GET_KEY
+       cp  K_EXIT
+       jr  z,quit
+       cp  K_MORE
+       call z,Pause
+;      ld  a,%00111111         ;<exit> pressed?
+;      out (1),a
+;      nop \ nop
+;      in  a,(1)
+;      bit 6,a                 ;test bit 6 = <EXIT>
+;      jr  z,quit              ;yes: quit game
 
 game_stuff:
        call Level_event        ;insert enemies
        call Handle_Ship        ;move you
-       call Fire_bullet        ;check for fire
        call Handle_enemies     ;move enemies
+
+       call Fire_bullet        ;check for fire
        call Handle_bullets     ;move your bullets
        call Handle_torp        ;move your torpedo
        call Enemy_bullets      ;move enemy bullets
        call Enemies_hit        ;check for collision with enemies
 
        call Display_Screen     ;display all
-       halt ;\ halt            ;delay
+       halt \ halt             ;delay
        jr   game_main_loop     ;loop
 
+;--------------------------- pause --------------------------------------------
+
+Pause:
+       ld  hl,$0200            ;top left
+       ld  (_curRow),hl
+       ld  hl,txt_pressenter   ;"Enter to continue"
+       call _puts              ;display message
+pause:
+       call _getkey            ;enter low-power mode and wait for key
+       cp  kEnter              ;keypressed = enter?
+       jr  nz,pause            ;no, wait some more
+       ret                     ;continue
+
 ;--------------------------- exit ---------------------------------------------
 
 quit:
        ld  a,(CONTRAST)        ;load original contrast level
        out (2),a               ;and set it back
+       ld  (iy+13),6
        ret                     ;quit Nemesis :(
 
 ;--------------------------- display ------------------------------------------
@@ -162,7 +205,7 @@ Handle_Ship:
        ld  (your_occ),a        ;save
 
        cp  34                  ;last explosion frame?
-       jr  c,exploding_you     ;not yet: display explosion
+       jp  c,exploding_you     ;not yet: display explosion
        cp  40                  ;delay finished?
        jp  z,You_die           ;yes = game over
        ret                     ;don't display anything
@@ -212,7 +255,7 @@ no_up:      ld  e,(hl)
        ld  hl,your_inv         ;invulnerable?
        ld  a,(hl)              ;load time in a
        or  a                   ;is it 0?
-       jp  z,putsprite         ;yes so ship = normal (display \ ret)
+       jr  z,handle_multiples  ;yes so ship = normal (display \ continue)
 
        ld  b,a                 ;save inv-time
        ld  a,(timer)           ;load frame nr.
@@ -224,11 +267,42 @@ not_time:
        jr  z,no_flicker        ;don't show normal sprite anyway
        ld  a,b                 ;pop inv-time
        and %11110000           ;inv-time <16 ticks left?
-       jp  z,putsprite         ;yes: display normal sprite
+       jr  handle_multiples    ;yes: display normal sprite and continue
 
 no_flicker:
        ld  ix,spr_ship01i      ;display inv-ship (ld ix is faster than add ix)
-       jp  putsprite           ;ret
+
+handle_multiples:
+       call putsprite          ;display your ship
+
+       ld  a,(your_multiples)  ;do you have multiples
+       or  a                   ;no?
+       ret z                   ;then don't handle them either
+
+       ld  hl,your_locpos      ;location to save this position
+       ld  a,(hl)              ;load a
+       inc a                   ;a=a+1
+       and %00001111           ;if a>15 then a=a-16
+       ld  (hl),a              ;save new a
+       add a,a                 ;a=a*2
+       ld  c,a                 ;de=a
+       ld  b,0
+
+       ld  hl,your_prevpos     ;previous positions
+       add hl,bc               ;16 turns ago
+       ld  d,(hl)              ;old x-pos
+       inc hl                  ;and
+       ld  e,(hl)              ;old y-pos
+       ld  (mx),de             ;save multiple position in (mx)
+
+       ld  a,(y)               ;load new y-pos
+       ld  (hl),a              ;save it for 16 turns in the future
+       dec hl                  ;and
+       ld  a,(x)               ;load new x-pos
+       ld  (hl),a              ;save that too
+
+       ld  ix,spr_multiple     ;sprite of the multiple
+       jp  putsprite           ;display it + <ret>
 
 exploding_you:
        srl a                   ;half the framerate
@@ -289,7 +363,7 @@ select:
        ld  a,(hl)              ;load pickups taken so far
        dec a                   ;is it 1?
        jr  nz,select2          ;no, carry on
-       ld  (hl),a              ;reset pickups
+       ld  (hl),a              ;reset pickups (a=0)
        ld  hl,your_armor       ;change armor
        inc (hl)                ;increase HPs by one
        jp  disp_icons          ;display and return
@@ -301,8 +375,27 @@ select2:
        ld  (torp_occ),a        ;ready torpedoes
        jp  disp_icons          ;display 'n return
 select3:
-       ld  (hl),0              ;reset pickups
+       dec a                   ;is it 3?
+       jr  nz,select4          ;no, carry on
+       ld  (hl),a              ;reset pickups
        jp  disp_icons          ;display n return
+select4:
+       dec a                   ;is it 4?
+       jr  nz,select5          ;no, carry on again
+       ld  (hl),a              ;reset pickups
+       inc a                   ;a=1
+       ld  (your_laser),a      ;ready laser
+       jp  disp_icons          ;display + return
+select5:
+       dec a                   ;is it 5?
+       jr  nz,select6          ;no, carry on once more
+       ld  (hl),a              ;reset pickups
+       inc a
+       ld  (your_multiples),a
+       jp  disp_icons          ;display, return
+select6:
+       ld  (hl),0              ;reset pickups
+       jp  disp_icons          ;display/return
 
 fire:  ld  hl,RanPos           ;random
        inc (hl)                ;update random counter
@@ -312,9 +405,107 @@ fire:     ld  hl,RanPos           ;random
        ret nz                  ;return when already pressed
        inc (hl)                ;set just_fired to 1
 
+       ld  hl,(x)              ;yes: first fire from ship position (x)
+       ld  (firex),hl          ;set firepos
+       ld  a,(your_multiples)  ;any multiples?
+       dec a                   ;nope?
+       jr  nz,fireany          ;then just fire somethin'
+       call fireany            ;and blast
+       ld  hl,(my)             ;then, fire from multiple position (mx)
+       ld  a,(mx)              ;<ex h,l>
+       ld  h,a                 ; ^^^^^^
+       ld  (firex),hl          ;set firepos
+                               ;blast again and <ret>
+fireany:
+       ld  a,(your_laser)      ;do you have laser?
+       dec a                   ;1=yes
+       jr  nz,fire_ybullet     ;no, just fire a bullet
+
+fire_laser:                    ;yes, fire that laser instead
+       ld  a,(firex)           ;a = your x-pos
+       ld  d,a
+
+       ld  hl,GRAPH_MEM        ;save-location
+       ld  a,(firey)           ;y-coord
+       add a,3                 ;at middle of your ship (y+3)
+       ld  e,a                 ;save laser-y in e
+       add a,a                 ;y*2
+       add a,a                 ;y*4
+       add a,a                 ;y*8
+       rl  b                   ;b (=0) =b*2+overflow (if y>32 then bc=bc+256)
+       add a,a                 ;y*16 (width of screen)
+       rl  b                   ;b=b*2+overflow (if y>64 then bc=bc+512)
+       inc a                   ;8 pixels to right (a=even so no overflow)
+
+       srl d                   ;X/2
+       srl d                   ;X/4
+       srl d                   ;X/8
+       add a,d                 ;a = (Y*16+X/8) mod 256 (c set on overflow)
+       jr  nc,_nolc            ;jump if no carry = no overflow = a<=255
+       inc b                   ;a>255 so increase bc by 256
+_nolc: ld  c,a                 ;c = (Y*16+X/8) mod 256
+       add hl,bc               ;bc = Y*16+X/8
+          
+       ld  a,15                ;128/8=16=screen width ** minus one (inc a ^^)
+       sub d                   ;minus x-start (d=X/8)
+       ld  b,a
+       ld  c,0
+drawlaser:
+       ld  (hl),%11111111
+       inc hl                  ;Go to next byte
+       djnz drawlaser
+
+handle_laser:
+       ld  a,(firex)
+       ld  d,a                 ;d was divided, so reload the laser-x
+
+check_laserhits:               ;de = (x,y)
+       ld  ix,nolashit
+       ld  b,nrenemies
+       ld  hl,enemies
+
+laserhits:                     ;Hits with normal enemies
+       push hl
+
+       ld  a,(hl)
+       and %00000010
+       jr  z,nolashit          ;no hit when enemy_occ <> 2/3
+
+       inc hl                  ;enemy type
+       ld  a,(hl)
+       or  a                   ;enemy #0 = pickup
+       jr  z,nolashit          ;yes: don't destroy
+
+       inc hl
+       ld  a,(hl)              ;check x
+       sub d
+       jp  m,nolashit          ;no hit when enemy is left of you
+
+       inc hl
+       ld  a,(hl)              ;check y
+       sub e
+       jp  z,enemy_hit         ;a-e=0 = laser on top line of enemy = hit
+       jr  nc,nolashit         ;a-e>0 = enemy above laser = no hit
+       add a,5                 ;add enemy height
+       jp  p,enemy_hit         ;a-e>0 = hit
+
+nolashit:
+       pop hl
+       inc hl                  ;go to next enemy
+       inc hl
+       inc hl
+       inc hl
+       djnz laserhits          ;check all enemies
+
+       ld  a,d                 ;<ex d,e>
+       ld  d,e
+       ld  e,a
+       jr  fire_torp           ;fire torpedoes as well
+
+fire_ybullet:
        ld  hl,ybullets
        ld  de,3
-       ld  b,10
+       ld  b,nrybullets
 find_ybullet:
        ld  a,(hl)
        or  a
@@ -325,26 +516,26 @@ find_ybullet:
 
 found_ybullet:
        ld  (hl),1              ;use bullet
-       ld  a,(x)               ;your x-pos
+       ld  a,(firex)           ;your x-pos
        add a,5                 ;place bullet in front of you
        inc hl                  ;go to bullet-x
        ld  (hl),a              ;set x
        ld  e,a                 ;save torp-x in e
 
-       ld  a,(y)               ;your y-pos
+       ld  a,(firey)           ;your y-pos
        add a,2                 ;place bullet at the middle of your ship
        inc hl                  ;go to bullet-y
        ld  (hl),a              ;set y
        add a,3                 ;place torpedo at bottom of ship
        ld  d,a                 ;save torp-y in d
 
+fire_torp:
        ld  hl,torp_occ         ;torpedo...
        ld  a,(hl)              ;load torpInfo
        dec a                   ;do you have (unused) torpedoes?
        ret nz                  ;nope (a must be 1)
        ld  (hl),2              ;yes; use torpedo
        ld  (torp_pos),de       ;save torpedo position (in de)
-
        ret
 
 ;------------------------ handle bullets --------------------------------------
@@ -356,7 +547,7 @@ remove_bullet:
 
 Handle_bullets:
        ld  hl,ybullets
-       ld  b,10
+       ld  b,nrybullets
 scan_bullets:
        push bc
        push hl
@@ -391,6 +582,7 @@ bullet_2left:
 check_bullethits:              ;INPUT: de=X,Y
        ld  b,nrenemies
        ld  hl,enemies
+       ld  ix,nohit
 
 hit_enemies:                   ;Hits with normal enemies
        push hl
@@ -425,11 +617,12 @@ hit_enemies:                      ;Hits with normal enemies
        ld  (hl),$00            ;remove bullet
        pop hl
 
+enemy_hit:
        dec hl
        dec hl
        dec hl
        ld  a,(hl)              ;occ
-       ld  b,a                 ;push occ
+       ld  c,a                 ;push occ
        and %11111100           ;occ/4 = HP left        ;<srl a\srl a
        jr  nz,hpleft           ;not zero -> jump
        ld  (hl),%01            ;set to explode
@@ -440,18 +633,14 @@ hit_enemies:                      ;Hits with normal enemies
        ld  (hl),%00000110      ;change it into a pickup (with 2 HP)
 pickupdone:
        inc hl
-       ld  b,(hl)              ;save enemy type
        ld  (hl),$00            ;explosionFrame 0
-
-       pop hl
-       ret
+       jp  (ix)
 
 hpleft:
-       ld  a,b                 ;pop occ
+       ld  a,c                 ;pop occ
        sub %00000100           ;decrease HP by one
        ld  (hl),a              ;save
-       pop hl
-       ret
+       jp  (ix)
 
 nohit:
        pop hl
@@ -601,7 +790,7 @@ Enemy_fires:                        ;de = x,y
        dec d                   ;d = x-2
        inc e                   ;e = y+1
 
-       ld  b,10
+       ld  b,nrebullets
        ld  hl,ebullets
 find_ebullet:
        ld  a,(hl)
@@ -624,7 +813,7 @@ found_ebullet:
 
 Enemy_bullets:
        ld  hl,ebullets
-       ld  b,10
+       ld  b,nrebullets
 handle_bullet:
        push bc
        push hl
@@ -881,7 +1070,7 @@ take_pickup:
        ld  hl,your_pickup      ;your pickups
        ld  a,(hl)              ;current
        inc a                   ;go to next
-       cp  3                   ;pickups >3
+       cp  5                   ;pickups >=5
        jr  c,not_maxpickup
        ld  a,1                 ;yes: reset to pickup 1
 not_maxpickup:
@@ -944,10 +1133,22 @@ no_torp:
        ld  ix,spr_icon00       ;
        ld  de,$3a01            ;icon #3
        call putwidesprite
+
        ld  ix,spr_icon00       ;emptyIcon
+       ld  a,(your_laser)
+       or  a
+       jr  z,no_laser
+       ld  ix,spr_icon04       ;laserIcon
+no_laser:
        ld  de,$4a01            ;icon #4
        call putwidesprite
+
        ld  ix,spr_icon00       ;emptyIcon
+       ld  a,(your_multiples)
+       or  a
+       jr  z,no_multiples
+       ld  ix,spr_icon05
+no_multiples:
        ld  de,$5a01            ;icon #5
        call putwidesprite
 
@@ -1026,7 +1227,11 @@ You_die:
        xor a                   ;a=0
        ld  (your_armor),a      ;no armor
        ld  (torp_occ),a        ;no torpedoes
+ inc a
+       ld  (your_laser),a      ;no laser
+ xor a
        ld  (your_pickup),a     ;reset pickups
+       ld  (your_multiples),a  ;no multiples
        jr  nonext_level
 
 ;--------------------------- next level ---------------------------------------
@@ -1065,6 +1270,16 @@ nonext_level:
        inc hl                  ;y=...
        ld  (hl),24             ;...=24=middle
 
+       xor a                   ;reset previous positions
+       ld  hl,your_prevpos     ;place all previous positions
+       ld  b,16                ;all 16 of them
+place_multiples:
+       ld  (hl),a              ;set prev-x to 0
+       inc hl                  ;next
+       ld  (hl),24             ;set prev-y to 24
+       inc hl                  ;next
+       djnz place_multiples    ;repeat
+
 ;--------------------------- setup game ---------------------------------------
 
 game_setup:
@@ -1313,6 +1528,13 @@ spr_ship02i:
        .db %10100000   ; █ █
        .db %01000000   ;  █
 
+spr_multiple:
+       .db 6,4         ;multiples
+       .db %01111000   ;  ████
+       .db %11111100   ; ██████
+       .db %11111100   ; ██████
+       .db %01111000   ;  ████
+
 spr_bullet01:
        .db 5,3         ;your bullets
        .db %00110000   ;   ░▒▓█▒
@@ -1441,33 +1663,43 @@ spr_icon02:
        .db %10011000,%11110101 ; █  ██   ████ █ █
        .db %11100110,%00110010 ; ███  ██   ██  █
 spr_icon03:
-       .db 16,7        ;laser    ........:.......:
+       .db 16,7        ;         .......:.......:
+       .db %10000000,%01010100 ; █
+       .db %10011110,%00101010 ; █
+       .db %10111000,%00010101 ; █
+       .db %10111111,%10101010 ; █
+       .db %10111111,%00010101 ; █
+       .db %10111000,%00101010 ; █
+       .db %10011110,%01010100 ; █
+spr_icon04:
+       .db 16,7        ;laser    .......:.......:
        .db %10000000,%00000000 ; █
-       .db %10110001,%01000000 ; █ ██   █ █
-       .db %10111011,%10000000 ; █ ███ ███
-       .db %10011101,%11111111 ; █  ███ █████████
-       .db %10111011,%10000000 ; █ ███ ███
-       .db %10110001,%01000000 ; █ ██   █ █
+       .db %10110010,%10000000 ; █ ██  █ █
+       .db %10111011,%00000000 ; █ ███ ██
+       .db %10011101,%11111111 ; █  ███ █████████
+       .db %10111011,%00000000 ; █ ███ ██
+       .db %10110010,%10000000 ; █ ██  █ █
        .db %10000000,%00000000 ; █
-spr_icon04:
-       .db 16,7        ;invulnerable....:.......:
-       .db %10000000,%01010100 ; █        O O O
-       .db %10011110,%00101010 ; █  OOOO   O O O
-       .db %10111000,%00010101 ; █ OOO      O O O
-       .db %10111111,%10101010 ; █ OOOOOOO O O O
-       .db %10111111,%00010101 ; █ OOOOOOO  O O O
-       .db %10111000,%00101010 ; █ OOO     O O O
-       .db %10011110,%01010100 ; █  OOOO  O O O
+spr_icon05:
+       .db 16,7        ;multiple .......:.......:
+       .db %10000011,%10000000 ; █     ███
+       .db %10000001,%11100111 ; █      ████  ███
+       .db %10000001,%11100000 ; █      ████
+       .db %10000011,%10000000 ; █     ███
+       .db %10011000,%00000000 ; █  ██
+       .db %10111100,%01110000 ; █ ████   ███
+       .db %10011000,%00000000 ; █  ██
 
 ;---------------------------- texts -------------------------------------------
 
-txt_about:     .db "v0.9.94 ","by Shiar  "
+txt_about:     .db "v0.91.95 ","by Shiar  "
                .db "(ICQ#43840958)",0
 txt_1player:   .db "1 PLAYER",0
 txt_2players:  .db "2 PLAYERS",0
 txt_level:     .db "LEVEL ",0
 txt_gameover:  .db "GAME OVER!",0
 txt_lives:     .db "Lx0?",0
+txt_pressenter:        .db "Enter to continue",0
 
 ;---------------------------- save data ---------------------------------------
 
@@ -1495,27 +1727,11 @@ x               .db $16                 ;x-pos
 y              .db $46                 ;think about it..
 hp             .db $00                 ;hitpoints left
 
+your_laser     .db $01                 ;laser avail: 0=no, 1=yes
+your_multiples .db $00                 ;multiples present
 torp_occ       .db $00                 ;torp.state: 0=unavail 1=avail 2=presnt
 torp_pos       .dw $0000               ;torpedo position (x,y)
 
-ybullets       .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0       ;10 x (state,x,y)
-ebullets       .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0       ;10 x (state,x,y)
-
-nrenemies      = 10
-enemies                .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
-               .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
-               .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
-               .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
-
-enemiesxtra    .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
-               .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
-               .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
-               .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
-add2enemy      = 40
-
-; %111111 (HP left) 11 (00=no enemy 01=exploding 10=normal 11=moving)
-; %11111111 (ship type or explosion frame)  %11111111 (x) %11111111 (y)
-
 ;---------------------------- enemy data --------------------------------------
 
 sprites:
@@ -1784,6 +2000,16 @@ logo_nemesis:
 ;      - no more armor to start with. you'll have to collect them on your own
 ;      * of course optimizations and a few tiny bug fixes (not important)
 ;      * increased the size of the enemy bullets so they're better to see
+;
+; 0.91.95 -- 05.IX .99 -- size 2797
+;
+;      + LASERS!!!!! four pickups and you fire laserbeams instead of bullets
+;      * multiple enemies can be hit at once, very usefull when firing lasers
+;      + MULTIPLE!! like the (shadow-)multiple from MSX-Nemesis. for 5 pickups
+;        you get an multiple following you, firing bullets and lasers like you
+;      * most data (enemy positions) stored at TEXT_MEM and DELC_LEN positions
+;        instead of in program, saving A LOT of bytes in program-size
+;      - at release of 0.91 bullets didn't work, laser is used instead
 
 
 ;       + added        - removed       * changed       # bug fixed