;DreamWalker: AlterEgo2 by Denis Grachev
;Main Source

NOPS_32 = deltas+256-32
startLevel = 1

flyDelay = 8

ROWREPT = 0
TOTAL_ROWS = 15

;is Pentagon
platformPentagon = 0
    
org 38680
;some delay to see pic
ld b,50
call n_Pause
;fade out pic
call fade_out

     
;init sound bank
ld hl,soundBank
call AFXINIT

call credits
call setup

;call showOutro
      
call showIntro
jp mainMenu

startGame
;set lives
ld a,5
ld (lives),a
add 48
ld (s_Lives+15),a
;max pre world
ld a,99
ld (preWorld),a
;load start level
ld a,startLevel
ld (currentLevel),a

call showEnterPassword

ld a,(currentLevel)
cp 1
call nz,succesPassword

;restart level label
restartLevel

call setup
call initLevel
call initParticles

;dup 5
;call doEnemies
;call doEnemiesAttach
;edup
         
call startNIRVANA

ld hl,updateGameFrame1
ld (updateGame+1),hl

call hidePressStart
         
main_loop
halt
        
updateGame:        call updateGameFrame1


;        ld a,0
;        out (254),a

        ld a,(heroState)
        cp 2
        jr c,notStateChange

        ;blink for lives
         ld a,(menuTicker)
         xor 1
         ld (menuTicker),a
         cp 1
         call z,doBlink
        
        ld a,(stateCount)
        inc a
        ld (stateCount),a

        cp 10
        call z,showLives

        
        cp 150
        jp z,endMainLoop
        ;======
        
        notStateChange

        jp main_loop

endMainLoop

        call clearStage
        call stopNIRVANA
        
        call setup

        ld a,(heroState)
        cp 3;level complete
        jp z,levelComplete

        ld a,(lives)
        cp 0
        jp z,mainMenu


        jp restartLevel
        
ret

showLives

        ld hl,s_Lives
        ld a,(lives)
        cp 0
        jr nz,notGO
        ld hl,s_GameOver
        notGO:

        ld bc,smallFont
        call PRINTSTRING
ret

startNIRVANA
ld      a, ($004c)
and     2
ld      (delay_128k-1), a
;enable interups im2
LD HL,main_engine
CALL IMON
ret

stopNIRVANA
  call IMOFF
ret
        
levelComplete
        ld a,(currentLevel)
        inc a
        ld (currentLevel),a
        cp 36
        jp z,showOutro
        
jp restartLevel
        

clearStage
        call player+8
        ld hl,AFXFRAME
        ld (ay_frame_proc+1),hl
        
        call hidePressStart
                 
        ld a,8
        call AFXPLAY
        
        ; start y
        ld d,16
                
        clrLoop
        dup 2
        halt
        edup
        
        ;y pos for line

        call xLine0
        call xLine3
        inc d
        inc d

        ld a,d
        cp 9*8+4
        jr nz,clrLoop
        
;        jp clrLoop
        
        ;final blow
;        finalClear:


        

ret

xLine0

ld b,30
;x=1
ld e,1
reXline0
push de
push bc
ld bc,clearBytes
call NIRVANA_paintC

pop bc
pop de
inc e
djnz reXline0
ret

xLine3


push de

ld a,17*8+8
sub d
ld d,a

ld b,30
;x=1
ld e,1
reXline3
push de
push bc
ld bc,clearBytes+4
call NIRVANA_paintC

pop bc
pop de
inc e
djnz reXline3

pop de

ret

clearBytes
  ;xxxxx
  defb 0*8+0+00,0*8+1+00,0*8+2+64,0*8+7+64
  ;xxxxxxx
  defb 0*8+7+64,0*8+2+64,0*8+1+00,0*8+0
  
;  defb 0*8+7+64,0*8+7+64,0*8+6+64,0*8+6
;
;  defb 0*8+2,0*8+2,0*8+1,0*8+0

;в этом кадре мало тактов
   
updateGameFrame1

;    ld a,1
;    out (254),a

        ld hl,updateGameFrame2
        ld (updateGame+1),hl

     ;   call calculateRestore0
        call calculateRestore1
        call calculateRestore
        ;переместим сменим адреса
        
        call doHero2
        call doPhantom
;        call doPixels
        ;attach enemies to sprite according to coords
        call doEnemiesAttach
        
        ;==============
     ;   ld a,(heroState)
;        cp 2
;        call z,doHeroDead
        
        call calculateDrawing0
        call calculateDrawing1
        call calculateDrawing

        call doSpecialSounds
ret

;в этом кадре больше тактов
updateGameFrame2

;        ld a,6
;        out (254),a
        
        ld hl,updateGameFrame1
        ld (updateGame+1),hl

        call calculateRestore0

        
        call doPixelsAnimation
        call doHero1
        call doBrokenBridge
        call doPhantom
        call doTeleporting
        call doEnemies
        call doPixels
        
        ;==============
        ld a,(heroState)
        cp 2
        call z,doHeroDead
        
        call calculateDrawing0

        call doParticlesFAST


        call doSounds

ret

;manage fall and land sounds
doSpecialSounds

        ld a,(heroState)
        cp 0
        ret nz
        
        ld a,(heroMoveDir)
        cp 13
        jr z,dss_falling
        ;not falling
        ;check if was falling then land
        ld a,(heroPreDir)
        cp 13
        ret nz
        ld a,6
        ld (soundToPlay),a
        ret
        dss_falling
        ;was falling ???
        ld a,(heroPreDir)
        cp 13
        ret z
        ;ok start falling
        ld a,2
        ld (soundToPlay),a
;        ld a,13
;        ld (heroPreDir),a
        
ret
        
doSounds

        ld a,(soundToPlay)
        cp 0
        ret z

        call AFXPLAY
        xor a
        ld (soundToPlay),a
ret

;put part on screen
putPart
        ld a,(hl)
        cp 0
        ret nz

        ld a,32
;        xor (hl)
        ld (hl),a
ret
;xor particle to screen
clearPart
        ;put on screen
        ld a,(hl)
        cp 32
        ret nz
        
   ;     ld a,32
        xor (hl)
        ld (hl),a
ret

;updtae magic particels
doParticlesFAST

        ld ix,particelsTable
        ;get coords
        ;and clear prev position
        ld c,(ix+0*6)
        ld b,(ix+1+0*6)
        call getPixel
        call clearPart
        ld b,(ix+1+0*6)
        dec b
        dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge0
        ld b,15*8+2
        dp_notEdge0
        ld (ix+0*6),c
        ld (ix+1+0*6),b
        call getPixel
        call putPart

        ld c,(ix+1*6)
        ld b,(ix+1+1*6)
        call getPixel
        call clearPart
        ld b,(ix+1+1*6)
    ;    dec b
        dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge1
        ld b,15*8+2
        dp_notEdge1
        ld (ix+1*6),c
        ld (ix+1+1*6),b
        call getPixel
        call putPart

        ld c,(ix+2*6)
        ld b,(ix+1+2*6)
        call getPixel
        call clearPart
        ld b,(ix+1+2*6)
        dec b
        dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge2
        ld b,15*8+2
        dp_notEdge2
        ld (ix+2*6),c
        ld (ix+1+2*6),b
        call getPixel
        call putPart

            ld c,(ix+3*6)
        ld b,(ix+1+3*6)
        call getPixel
        call clearPart
        ld b,(ix+1+3*6)
        dec b
    ;    dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge3
        ld b,15*8+2
        dp_notEdge3
        ld (ix+3*6),c
        ld (ix+1+3*6),b
        call getPixel
        call putPart

            ld c,(ix+4*6)
        ld b,(ix+1+4*6)
        call getPixel
        call clearPart
        ld b,(ix+1+4*6)
        dec b
        dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge4
        ld b,15*8+2
        dp_notEdge4
        ld (ix+4*6),c
        ld (ix+1+4*6),b
        call getPixel
        call putPart

            ld c,(ix+5*6)
        ld b,(ix+1+5*6)
        call getPixel
        call clearPart
        ld b,(ix+1+5*6)
        dec b
    ;    dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge5
        ld b,15*8+2
        dp_notEdge5
        ld (ix+5*6),c
        ld (ix+1+5*6),b
        call getPixel
        call putPart

            ld c,(ix+6*6)
        ld b,(ix+1+6*6)
        call getPixel
        call clearPart
        ld b,(ix+1+6*6)
        dec b
        dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge6
        ld b,15*8+2
        dp_notEdge6
        ld (ix+6*6),c
        ld (ix+1+6*6),b
        call getPixel
        call putPart

            ld c,(ix+7*6)
        ld b,(ix+1+7*6)
        call getPixel
        call clearPart
        ld b,(ix+1+7*6)
        dec b
     ;   dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge7
        ld b,15*8+2
        dp_notEdge7
        ld (ix+7*6),c
        ld (ix+1+7*6),b
        call getPixel
        call putPart

        ld c,(ix+8*6)
        ld b,(ix+1+8*6)
        call getPixel
        call clearPart
        ld b,(ix+1+8*6)
        dec b
        dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge8
        ld b,15*8+2
        dp_notEdge8
        ld (ix+8*6),c
        ld (ix+1+8*6),b
        call getPixel
        call putPart

            ld c,(ix+9*6)
        ld b,(ix+1+9*6)
        call getPixel
        call clearPart
        ld b,(ix+1+9*6)
        dec b
    ;    dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge9
        ld b,15*8+2
        dp_notEdge9
        ld (ix+9*6),c
        ld (ix+1+9*6),b
        call getPixel
        call putPart

            ld c,(ix+10*6)
        ld b,(ix+1+10*6)
        call getPixel
        call clearPart
        ld b,(ix+1+10*6)
        dec b
        dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge10
        ld b,15*8+2
        dp_notEdge10
        ld (ix+10*6),c
        ld (ix+1+10*6),b
        call getPixel
        call putPart

            ld c,(ix+11*6)
        ld b,(ix+1+11*6)
        call getPixel
        call clearPart
        ld b,(ix+1+11*6)
        dec b
    ;    dec b
        ld a,b
        cp 6
        jr nc,dp_notEdge11
        ld b,15*8+2
        dp_notEdge11
        ld (ix+11*6),c
        ld (ix+1+11*6),b
        call getPixel
        call putPart
ret

;enemies attach to sprite
doEnemiesAttach

        ld ix,enemiesTable
        ld b,6
dea_nextEnemy
        ;save counter
        push bc
        ;check if enemy is enabled
        ld a,(ix)
        cp 0
        jr z,dea_skipEnemy
        ;else updateEnemy
        call enemyAttachToSprite
dea_skipEnemy
        ;to the next enemy
        ld bc,00013
        add ix,bc
        ;restore counter
        pop bc
        djnz dea_nextEnemy
        
ret

decStartDelay

dec a
ld (ix+12),a
        
jp skipEnemy
        
;move enemies
doEnemies

      
        ;phantom enemies ticker
        ld a,(phantomEnemyTicker)
        xor 1
        ld (phantomEnemyTicker),a
      
        ;not update enemies if teleporting or level clear
        ld a,(heroState)
        cp 1
        ret z
        cp 3
        ret z

        ld ix,enemiesTable
        ld b,6
nextEnemy
        ;save counter
        push bc
        ;check if enemy is enabled
        ld a,(ix)
        cp 0
        jr z,skipEnemy
        ;check start delay
        ld a,(ix+12)
        cp 0
        jp nz,decStartDelay
        call z,doOneEnemy

   
skipEnemy
        ;to the next enemy
        ld bc,00013
        add ix,bc
        ;restore counter
        pop bc
        ;exit if some enemy swapped
        djnz nextEnemy
ret

;ix - points to enemy
doOneEnemy
;struct
;0 - enabled
;1 - movedir
;2 - movecount
;3,4 - real position
;5,6 - drawN where to draw
;7,8 - spriteN attached
;9,10 - sprite address

;if level complete don't move enemies
;    ld a,(heroState)
;    cp 3
;   ret z
        
call moveEnemy

ld a,(ix+11)
cp 0
jp z,checkHeroCollisions
jp checkPhantomCollisions
    
ret



killHero
        ld a,(heroState)
        cp 2
        ret z

        ;jp 00000
        ;hide hero
        ld hl,NOPS_32
        ;ld (sprite0),hl
        ld (sprite1),hl
        ;dead state
        ld a,2
        ld (heroState),a

        ld bc,0+136*256
        ;ld (heroPos),bc
        ld (phantomPos),bc

        ld a,5
        ld (soundToPlay),a

        ld hl,hero_dead
        ld (heroAnimation),hl

        ld hl,deadYpos
        ld (deadPointer),hl

        ld a,(lives)
        dec a
        ld (lives),a

        add 48
        ld (s_Lives+15),a

ret

checkHeroCollisions
        ;check hero only at normal state
        ld a,(heroState)
        cp 0
        ret nz
        
    ;  push hl
;      push de

      ld hl,(heroPos)
      ld e,(ix+3)
      ld d,(ix+4)

 ;     pop de
;      pop hl
      call check_collision
      call c,killHero

ret

checkPhantomCollisions
        ;check hero only at normal state
        ld a,(heroState)
        cp 0
        ret nz

    ;  push hl
;      push de

      ld hl,(phantomPos)
      ld e,(ix+3)
      ld d,(ix+4)

 ;     pop de
;      pop hl
      call check_collision
      call c,killHero

ret

;collision beetween hl and de
;distane -6

check_collision
       ; Check (l, h) for collision with (e, d), strict enforcement.
       ld a,l              ; x coord.
       sub e               ; subtract x.
       add a,6            ; add maximum distance.
       cp 12               ; within x range?
       ret nc              ; no - they've missed.
       ld a,h              ; y coord.
       sub d               ; subtract y.
       add a,6            ; add maximum distance.
       cp 12               ; within y range?
ret    

;move enemy according to dir
moveEnemy

;get move count
ld a,(ix+2)
cp 0
;if zero - check if we can move and change dir if need
call z,checkForMoving
;if 0 - we can't moving
;cp 0
;ret z
    
ld a,(ix+1)
ld c,(ix+3)
ld b,(ix+4)
call moveSprite
ld (ix+3),c
ld (ix+4),b

;inc MoveCount
ld a,(ix+2)
inc a
cp 8
jr nz,me_notEnd
;reset move count
xor a
me_notEnd
ld (ix+2),a

ret

checkForMoving

       ;get movedir
       ld a,(ix+1)
       cp 3
       jp c,checkForMovingX
       jp checkForMovingY
;-=============================

checkForMovingY

;load coords
ld c,(ix+3)
ld b,(ix+4)
;get dir
ld a,(ix+1)

;check top edge
cp 4
jr nz,skipTopEdge
ld a,b
cp 0
jr nz,skipTopEdge
call swapDir
xor a
ret
skipTopEdge
ld a,(ix+1)
       
;get new coords
call moveSprite8
call getTileOnLegs
cp 1
jr nz,cfmy_not_solid
;ok there is a wall
call swapDir
xor a
ret
cfmy_not_solid
cp 3
ret nz;and not bridge
;ok there is a bridge
call swapDir
xor a
     
ret
       
;check for moving in X direction
checkForMovingX

;load coords
ld c,(ix+3)
ld b,(ix+4)
;get dir
ld a,(ix+1)
;get new coords
call moveSprite8
;now in bc new coords
push bc
call getTileOnLegs
pop bc
cp 1
jr nz,cfm_notWall;no wall - continue moving
;ok there is a wall
call swapDir
xor a
ret
cfm_notWall
call getTileUnderLegs
cp 0 ;if not null
ret nz ;continue moving
;else
call swapDir
xor a

ret

;swap enemy dir
swapDir

ld a,(ix+1)

cp 1
jr nz,sd_not1
ld a,2
ld hl,enemy_right
jr sd_end

sd_not1
cp 2
jr nz,sd_not2
ld a,1
ld hl,enemy_left
jr sd_end

sd_not2
cp 3
jr nz,sd_not3
ld a,4
ld hl,enemy_up
jr sd_end

sd_not3
ld a,3
ld hl,enemy_up
sd_end
ld (ix+1),a
;attach new sprite
ld (ix+9),l
ld (ix+10),h


ret

enemyAttachToSprite

  ;if phantom kind and enemyticker = 1 then attach to null
  ;for blinking enemy
  ld a,(ix+11)
  cp 1
  jr nz,eats_normalType
  ld a,(phantomEnemyTicker)
  cp 1
  jr nz,eats_normalType
  ;else attach null sprite
  ;get where to attach
  ld l,(ix+7)
  ld h,(ix+8)
  ld (ph_attach+1),hl
  ld hl,NOPS_32
  ph_attach: ld (sprite0),hl
  ret
  eats_normalType
        
  ;load position
  ld c,(ix+3)
  ld b,(ix+4)
  ;calculate drawing address
  call getPixel
  ex de,hl
  ;get drawN pointer
  ld l,(ix+5)
  ld h,(ix+6)
  ;save DrawN
  ld (hl),e
  inc hl
  ld (hl),d
  ld l,(ix+7)
  
  ;in a - still dif
  ;get where to attach
  ld l,(ix+7)
  ld h,(ix+8)
  ld (ea_spriteToAttach+1),hl
  
  ;attach sprite
   ld l,(ix+9)
   ld h,(ix+10)
   ;add frame by movecount if Y enemy
   push af
   ;
   ld a,(ix+1)
   cp 3
   jr c,ea_x_move
   pop af
   ld a,(ix+2)
   push af
   ;
   ea_x_move
   pop af
   
   ld b,0
   add a;x2
   add a;x4
   add a;x8
   add a;x16
   add a;x32
   ld c,a
   add hl,bc
  ;======================
  ;save sprite
  ea_spriteToAttach: ld (sprite0),hl
 
ret

doTeleporting
     ld a,(heroState)
     cp 1 ;teleporting
     jp z,teleporting
ret

doPhantom

        
;if not deAD
LD A,(heroState)
cp 2
ret z


;calculate phantom coords from hero coords
call calculatePhantom
;phantom blink count
ld a,(phantomCount)
xor 1
ld (phantomCount),a
;draw or hide phantom
cp 0
jr z,hidePhantom
;attach phantom to sprite 1
ld hl,hero_phantom
ld a,(totalPhantoms)
;
add a,a  ;2
add a,a  ;4
add a,a  ;8
add a,a  ;16
add a,a  ;32

ld b,0
ld c,a
add hl,bc
        
ld (sprite1),hl
ld bc,(phantomPos)
call getPixel
ld (draw1),hl
        
ret

hidePhantom
        
        ld hl,NOPS_32
        ld (sprite1),hl
        
ret
        
;calculate phantom coords from hero coords
calculatePhantom

ld a,(heroMoveCount)
cp 0
ret nz
           
 ;b-y c-x
 ld bc,(heroPos)
 ld a,(phantomKind)
 cp 0
 jr nz,cp_vertical
 ;horizontal
 ;get hero x
 ld a,c
 cp 128
 ;more thean 128
 jp nc,cp_1;jump if bigger than 128
 ;ok less 128
 ld a,128
 sub c
 add 128
 ;offscreen fix if > 240 then -8
 cp 248
 jr c,cp_0
 sub 8
 cp_0:
 ld c,a
 ld (phantomPos),bc
 ret
 cp_1:
;ok more than 128
 ld a,c
 sub 128
 ld c,a
 ld a,128
 sub c
 ld c,a
 ld (phantomPos),bc
 ret

 
 ;vertical phantom
 cp_vertical
 ld a,b
 cp 56
 jr nc,cp_2 ;jump if bigger
 ;lowwer
 ld a,56
 sub b
 ld b,56
 add b
 ld b,a
 ld (phantomPos),bc
 ret
 cp_2
 ld a,b
 sub 56 ;get dif
 ld b,a;dif to b
 ld a,56
 sub b
 ld b,a
 ld (phantomPos),bc
 
ret

;collect pixels
collectPixel
;ix point to current pixel
    
;disable
xor a
ld (ix),a

;get kind
ld a,(ix+5)
;is it switch phantom pixel ??
cp 40
jr nz,cp_not_switch
ld a,(phantomKind)
xor 1
ld (phantomKind),a
cp_not_switch
    
    
;push ix


;clear

ld l,(ix+3)
ld h,(ix+4)
dup 4
ld (hl),0
edup


ld d,(ix+6)
ld e,(ix+7)
ld c,7+64+0*8
;ld bc,00000
call NIRVANA_fillC
      
;change drawing adr

ld hl,16384+4128
ld (ix+3),l
ld (ix+4),h

;push de
;push bc
;push af

;collect
ld a,1
ld (soundToPlay),a
      
ld a,(totalPixels)
dec a
ld (totalPixels),a
cp 0
ret nz

ld a,3
ld (heroState),a

;level complete
ld a,9
ld (soundToPlay),a

;pop af
;pop bc
;pop de
    
ret

;check pixels to collect
;0 - enabled
;1,2 - position
;3,4 drawing address
;5 kind - phantom or hero
   
doPixels

ld ix,pixelsTable
ld b,16

nextPixel
       push bc
       ;skip disabled pixels
       ld a,(ix)
       cp 0
       jr z,skipPixel
       ;check for collect by hero or phantom
       ;skip if we not in normal state and pixel not teleport
       ;get kind
       ld a,(ix+5)
       cp 39 ;teleport pixel
       jr nc,dp_continue
       ;switch pixel can be collected during fly to
       ld a,(heroState)
       cp 0
       jr nz,skipPixel
       ld a,(ix+5);get kind
       cp 16;phantom
       jr z,dp_phantom
       dp_continue
       ld hl,(heroPos)
       jr what_compare
       dp_phantom:
       ld hl,(phantomPos)
       what_compare:
       ld e,(ix+1)
       ld d,(ix+2)
       ;inc h by 8 to leg coords
       ld a,h
       add 8
       ld h,a
     ;  dup 8
     ;  inc h
     ;  edup
       call check_collision
       jr nc,skipPixel
       call collectPixel
skipPixel
       ld bc,00008
       add ix,bc
       pop bc
       djnz nextPixel
       
ret

;animate broken bridge
doBrokenBridge

         ;bridge out of frames
         ld a,(brokenBridgeFrame)
         cp 4
         ret z

         inc a
         ld (brokenBridgeFrame),a
         dec a
         ;one frame = 4 bytes
         add a,a ;x2
         add a,a ;x4
         add a,a

         ld ix,broken_bridge_sprite
         ld b,0
         ld c,a
         add ix,bc
         
         ld hl,(brokenBridgeDrawAdr)
         
         ;draw
         dup 3
         ld a,(ix)
         ld (hl),a
         inc h
         inc ix
         edup
         ld a,(ix)
         ld (hl),a

         ld a,(brokenBridgeFrame)
         cp 4
         ret nz

         ;if 4 - then clear attribs by FillC
         ld c,7+0*8+64
         ld de,(brokenBridgeCellCoords)
         ld a,e
         ld e,d
         
         add a,a
         add a,a
         add a,a

         add 8

         ld d,a

         call NIRVANA_fillC
        

ret

calculateHeroCellPos
         ;calculate only at movecount = 3
         ;in the middle of moving
;         ld a,(heroMoveCount)
;         cp 3
;         ret nz
         
         ;calculate
         ld bc,(heroPos)
         call getHeroCellCoords
         ;save it
         ld (heroCellPos),de
         ;e-y d-x
         ;and phantom cell coords
         ld bc,(phantomPos)
         call getHeroCellCoords
         ld (phantomCellPos),de

ret

doHeroDead

         ;'swing' hero position by y
         ld bc,(heroPos)
         ld a,r

         ld hl,(deadPointer)
         
         ld a,(hl)
         cp 128
         jr z,hideHero

;         dup 10
;         halt
;         edup
         
         ld a,b
         add (hl)
         ld b,a
         
         inc hl
         ld (deadPointer),hl
         ld (heroPos),bc
         ;

         dhd_end
         jp calculateDrawingAdressForHero
         hideHero
         ld hl,NOPS_32
         ld (sprite0),hl
ret
         
;less tStates - remove controls check for speed
doHero1
   ;if not deAD
   ld a,(heroState)
   cp 2
   ret z

   ld a,(heroMoveDir)
   ld (heroPreDir),a
   
   call heroGravity
   call moveHero
   call calculateDrawingAdressForHero
ret

;more tStates - controls,step sounds here
doHero2
   ;if not deAD
   ld a,(heroState)
   cp 2
   ret z

   ld a,(heroMoveDir)
   ld (heroPreDir),a
   
   call heroGravity
   call heroControls
   call moveHero
   call calculateDrawingAdressForHero
   call footStepSound

ret

footStepSound

   ld a,(heroMoveCount)
   cp 3
fs_proc:   jp z,footStep01
  
ret

footStep01

   ld a,(heroMoveDir)
   cp 5
   ret nc

   ld a,11
   ld (soundToPlay),a

;   ld hl,footStep02
;   ld (fs_proc+1),hl
   
ret

footStep02

   ld a,(heroMoveDir)
   cp 5
   ret nc

   ld a,10
   ld (soundToPlay),a

   ld hl,footStep01
   ld (fs_proc+1),hl

ret



heroGravity

   ld a,(heroState)
   cp 0
   ret nz
     
   ld a,(heroMoveCount)
   cp 0
   ret nz

   ;reset movedir
   ld (heroMoveDir),a
   
   ld bc,(heroPos)

   ;offscreen dead
   ld a,b
   cp 112
   jp nc,killHero
   
   call getTileUnderLegs

   ;dead
;   cp 4
;   jp z,killHero
   
   ;solid
   cp 1
   ret z
   ;ladder
 ;  cp 2
 ;  ret z
   ;bridge
   cp 3
   ret z

   ;check ladder on head
   ld bc,(heroPos)
   call getTileOnHead
   cp 2
   ret z;ladder - exit

   ld bc,(heroPos)
   call getTileOnLegs
   cp 2
   ret z;ladder - exit

   ;phantom collisions
   ld bc,(phantomPos)
   call getTileUnderLegs

   cp 5
   ret z
   
   ;no, we need to fall down
   ld a,13
   ld (heroMoveDir),a
   ld a,4
   ld (heroMoveCount),a
   
ret

;teleporting loop
teleporting


ld bc,(heroPos)
ld a,(teleportDir)
call moveSprite8
ld (heroPos),bc
call calculatePhantom
             
call calculateHeroCellPos

ld bc,(heroPos)
ld de,(teleportPos)

ld a,b
cp d
ret nz

ld a,c
cp e
ret nz

;reset
xor a
ld (teleportDir),a
ld (heroState),a

             
ret
   
heroControls

     ;controls only in normal state
     ld a,(heroState)
     cp 0
     ret nz
     
      ;normal controls
      ;check if we allready moving
      ld a,(heroMoveCount)
      cp 0
      ret nz;ret
      
     CONTROLS_LABEL call keyboard_controls
ret

;game controls keyboard
keyboard_controls
    
      LD    BC,57342
      ;P
      IN    A,(C)
      
      ld bc,(heroPos)
      
      BIT 0,A
      jp Z,heroMoveRight
      ;O
      BIT 1,A
      jp Z,heroMoveLeft

      ;Q
      LD BC,64510
      IN A,(C)
      BIT 0,A
      jp Z,heroLadderUp
      ;A
      LD BC,65022
      IN A,(C)
      BIT 0,A
      jp Z,heroLadderDown
  
      ;space and m to grab gravitrap
      
      ;space
      LD    BC,32766
      IN    A,(C)
      BIT 0,A
      jp z,checkTeleport
      ;M
      BIT 2,A
      jp Z,checkTeleport

      xor a
      ld (heroFireWas),a
      
ret

;game controls sinclair
sinclair_controls

      LD    BC,61438
      ;P
      IN    A,(C)

      ld bc,(heroPos)

      BIT 3,A
      jp Z,heroMoveRight
      ;O
      BIT 4,A
      jp Z,heroMoveLeft

      BIT 1,A
      jp Z,heroLadderUp
      BIT 2,A
      jp Z,heroLadderDown

      BIT 0,A
      jp z,checkTeleport
     
      xor a
      ld (heroFireWas),a

ret




;teleport pressed
checkTeleport

;if fire button not was keyUP
ld a,(heroFireWas)
cp 0
ret nz

;not teleport when at same pos
ld hl,(heroPos)
ld de,(phantomPos)
call check_collision
ret c
    
;set fire flag
ld a,1
ld (heroFireWas),a

;check if there is a not solid at head and body
ld bc,(phantomPos)
call getTileOnHead
cp 1
ret z
ld bc,(phantomPos)
call getTileOnLegs
cp 1
ret z

;check if we have phantoms
ld a,(totalPhantoms)
cp 0
ret z
;dec phantoms
dec a
ld (totalPhantoms),a

;ok we can teleport
ld hl,(phantomPos)
ld (teleportPos),hl
ld a,1
ld (heroState),a

;detect teleport dir
call getTeleportDir
ld (teleportDir),a

;sound
ld a,13
ld (soundToPlay),a

ret

getTeleportDir

        ;load coords
        ld bc,(heroPos)
        ;get phantom type
        ld a,(phantomKind)
        cp 0
        jr nz,gtd_vertical
        ;hor phantom
        ld a,c;x
        cp 128
        jr nc,gtd_more_X
        ld a,2
        ret
        gtd_more_X
        ld a,1
        ret
        ;vertical phantom
        gtd_vertical
        ;ver phantom
        ld a,b;y
        cp 56
        jr nc,gtd_more_Y
        ld a,3
        ret
        gtd_more_Y
        ld a,4
        
ret

heroLadderDown
     ld bc,(heroPos)
     ;ladder on legs ?
     call getTileOnLegs
     ;is ladder
     cp 2
     jr z,hldMove;continue moving
     cp 0
     jp z,hldFallLadder
     ret
     hldFallLadder
     ;check ladder on head
     ld bc,(heroPos)
     call getTileOnHead
     cp 2
     ret nz;no ladder - exit
     ;okay we on ladder - move down
     ;if there is a null or ladder under legs
     hldMove
     
     ;set sprite
     ld hl,hero_ladder
     ld (heroAnimation),hl
     
     ld bc,(heroPos)
     call getTileUnderLegs
     ;is null
     cp 0
     jr z,hldFinalMove;move
     ;is ladder
     cp 2
     ret nz;nope - solid - exit
     hldFinalMove
     ld a,3
     ld (heroMoveDir),a
     ld a,8
     ld (heroMoveCount),a

ret

heroLadderUp
     ;check ladder on head
     ld bc,(heroPos)
     call getTileOnHead
     cp 2
     ret nz;no ladder - exit
     ;okay we on ladder - move down
     ;if there is a null or ladder under legs
     hluMove

     ;set sprite
     ld hl,hero_ladder
     ld (heroAnimation),hl
     
     ld bc,(heroPos)
     call getTileAboveHead
     ;is null
     cp 0
     jr z,hluFinalMove;move
     ;is ladder
     cp 2
     ret nz;nope - solid - exit
     hluFinalMove
     ld a,4
     ld (heroMoveDir),a
     ld a,8
     ld (heroMoveCount),a

ret
     
heroMoveRight
      
;=check if we can move
;in bc allready hero pos
;   dup 8
   inc c
;   edup

   ld a,c
   cp 240
   ret nc

   push bc
   call getTileOnLegs
   pop bc

   cp 1
   ret z
   cp 3
   ret z

   call getTileOnHead
   cp 1
   ret z

;set sprite
ld hl,hero_right
ld (heroAnimation),hl
     
;set moving count and movedir
ld a,8
ld (heroMoveCount),a
ld a,2
ld (heroMoveDir),a

call checkBridge
      
ret

heroMoveLeft

;=check if we can move
;in bc allready hero pos
;   dup 8
;   dec c
;   edup
    ld a,c
    sub 8
    ld c,a

   push bc
   call getTileOnLegs
   pop bc
   
   cp 1
   ret z
   cp 3
   ret z

   call getTileOnHead
   cp 1
   ret z

;set sprite
ld hl,hero_left
ld (heroAnimation),hl
     
;set moving count and movedir
ld a,8
ld (heroMoveCount),a
ld a,1
ld (heroMoveDir),a

call checkBridge

ret

checkBridge

     ;check if was bridge under legs - kill it
     ld bc,(heroPos)
     call getTileUnderLegs
     cp 3
     ret nz
     
     call getHeroCellCoordsUnderLegs
     push de

     ld a,0
     call putTileToLevel

     
     pop de
     inc e
     inc d
;     push de
;     xor a
;     call drawTile
     
 ;    pop de
     push de
     call ClearBridgeinBuffer
     pop de
     ld (brokenBridgeCellCoords),de
     call DISP_ADDR_BY_CELL
     ld (brokenBridgeDrawAdr),hl
     xor a
     ld (brokenBridgeFrame),a


ret

moveHero
   
   ;check move count
   ld a,(heroMoveCount)
   cp 0 ;if zero
   ret z ;cancel moving

   dec a;dec movecoung
   ld (heroMoveCount),a;save it
   
   
   ;move hero according to dir
   ld a,(heroMoveDir)
   ld bc,(heroPos)
   call moveSprite
   ld (heroPos),bc;save new position

   ld a,(heroMoveCount)
   cp 0
   call z, calculateHeroCellPos
   
ret

calculateDrawingAdressForHero
   ;calculate hero address by position
   ld bc,(heroPos)
   call getPixel
   ld (draw0),hl
   ;set frame by a
   ;one frame = 32
   ;if we move down or up
   ;set frame by movecount

   push af
   
   ld a,(heroMoveDir)
   cp 3
   jr nz,cda_not_3
   pop af
   ld a,(heroMoveCount)
   push af
   jr cda_end
   cda_not_3
   cp 4
   jr nz,cda_end
   pop af
   ld a,(heroMoveCount)
   push af
   cda_end
   
   pop af
   
   add a,a ;x2
   add a,a ;x4
   add a,a ;x8
   add a,a ;x16
   add a,a ;x32
   ;load current animation
   ld hl,(heroAnimation)
   ;get frame
   ld b,0
   ld c,a
   add hl,bc
   ld (sprite0),hl
ret


;move sprite by dir
;in a - dir
;in bc - coords
;13-fall down 14-fall up
moveSprite

      ;X move by one pixel
      cp 1
      jr nz,movesNotLeft
      dec c
      ret
        
      movesNotLeft
      cp 2
      jr nz,movesNotRight
      inc c
      ret
        
      movesNotRight
      
      ;Y move by 2 pixels - high gravity
      cp 3
      jr nz, movesNotDown
      inc b
      ret
      
      movesNotDown

      cp 4
      jr nz, movesNotUp
      ret nz
      dec b
      ret
      movesNotUp
      
      cp 13
      jr nz,fallNotDown
      inc b
      inc b
      ret

      fallNotDown
      dec b
      dec b

ret

;move sprite by 8 pixels
;in a - dir
;in bc - coords
moveSprite8

      ;X move by one pixel
      cp 1
      jr nz,moves8NotLeft
      ld a,c
      sub 8
      ld c,a
      ret

      moves8NotLeft
      cp 2
      jr nz,moves8NotRight
      ld a,c
      add 8
      ld c,a
      ret

      moves8NotRight

      ;Y move by 2 pixels - high gravity
      cp 3
      jr nz, moves8NotDown
      ld a,b
      add 8
      ld b,a
      ret

      moves8NotDown
      cp 4
      ret nz
      ld a,b
      sub 8
      ld b,a

ret

      
doPixelsAnimation

        ;update animation frames
        ld a,(currentPixelsFrame)
        inc a
        cp 8
        jr nz,notMaxPixelsFrame
        ld a,0
        notMaxPixelsFrame
        ld (currentPixelsFrame),a
        ;
        ld hl,pixelFrames
        add a,a;x2
        add a,a;x4
        ld d,0
        ld e,a
        add hl,de
        ld (pixelsAnimation),hl
        
ret
        

setup
        ld hl,pixelFrames
        ld (pixelsAnimation),hl
        xor a
        ld (currentPixelsFrame),a
        
        ;clear screen
       
        XOR A               ; 0
        CALL 8859           ; black border
        LD HL,23693         ; const attr
        ld (HL),0*8+7+64          ;
        CALL 3503           ; clear screen

        ;put 2 black attr to hide something :)
        ld hl,16384+6144+32*17
        ld (hl),0
        inc hl
        ld (hl),0
        ld hl,16384+6144+32*18
        ld (hl),0
        inc hl
        ld (hl),0

ret


resetSprites

        ld hl,16384+4128
        ld (draw0),hl
        ld (draw1),hl
        ld (draw2),hl
        ld (draw3),hl
        ld (draw4),hl
        ld (draw5),hl
        ld (draw6),hl
        ld (draw7),hl

        ld hl,NOPS_32
        ld (sprite0),hl
        ld (sprite1),hl
        ld (sprite2),hl
        ld (sprite3),hl
        ld (sprite4),hl
        ld (sprite5),hl
        ld (sprite6),hl
        ld (sprite7),hl

        call calculateRestore0
        call calculateRestore1
        call calculateRestore
        call calculateDrawing
        call calculateDrawing0
        call calculateDrawing1
ret
;init particles - calculate drawing adr by cell coords
initParticles
        
        ld ix,particelsTable
        ld b,12

        ip_nextPart
        push bc
        ;===========
        ld c,(ix)
        ld b,(ix+1)
        call getPixel
        ;put on screen
        ld a,(hl)
        cp 0
        jr nz,ip_skip
        ld a,32
        xor (hl)
        ld (hl),a
        ip_skip
        ;===========
        ld bc,00006
        add ix,bc
        pop bc
        djnz ip_nextPart
ret
        
initHero

  xor a
  ld (heroMoveCount),a
  ld (heroState),a
  ld (phantomCount),a
  ld (teleportDir),a
  ld (heroPreDir),a

  ld a,2
  ld (heroMoveDir),a
  ld (heroLastXDir),a
  ld hl,hero_right
  ld (heroAnimation),hl
  
  ld bc,13*8+256*4*8
  ld (heroPos),bc
  ld (phantomPos),bc
  ld bc,00000
  ld (heroCellPos),bc
  ld (phantomCellPos),bc
        
ret

addStartPoint

  
  push bc

  ld a,e
   dec a
   add a,a
   add a,a
   add a,a
  ld b,a

  ld a,d
   add a,a
   add a,a
   add a,a
  ld c,a

  ld (heroPos),bc
  
  pop bc
  
  ld a,0
  
ret
  
;0 - enabled
;1,2 - position
;3,4 drawing address
     
addPixelToLevel

      push hl
      push de
      push ix

      ld ix,(pixelsPointer)

      ;save type as pixel kind
      ;9-normal - 16 - phantom - 39 fly 40-teleport
      ld (pixelKind+1),a
      ld (pixelKind2+1),a
      
      ;save cell coords
      ld a,d
      add a,a
      add a,a
      add a,a
      
      ld (ix+1),a

      ld a,e
      add a,a
      add a,a
      add a,a
      
      ld (ix+2),a
      
      call DISP_ADDR_BY_CELL

      ;save for FILLC
      ld (ix+7),d
      ld a,e
      ;calc pixel line
      add a,a ;x2
      add a,a ;x4
      add a,a ;x8

      add 8
      ld (ix+6),a
      
      
      inc h
      inc h
      inc h
      inc h

      ;enable it
      ld a,1
      ld ix,(pixelsPointer)
      ld (ix),a
      ;set kind
pixelKind: ld a,9
      ld (ix+5),a
      ;where draw
      ld (ix+3),l
      ld (ix+4),h
      ;inc block pointer
      ld de,00008
      add ix,de
      ld (pixelsPointer),ix
      pop ix
      pop de
      pop hl

      ;inc total pixels
      ld a,(totalPixels)
      inc a
      ld (totalPixels),a
      
pixelKind2:
      ld a,9;draw

ret

;0 - enabled
;1 - movedir
;2 - movecount
;3,4 - real position
;5,6 - drawN where to draw
;7,8 - spriteN attached
;9,10 - sprite address
;in a - input
;19 - right 20-left 21-up 22-down
addEnemyToLevel

    push ix
    push de
    push hl
    ;get current enemy pointer
    ld ix,(enemiesPointer)

    cp 19
    jr nz,aetl_not19
    ;19
    ld a,2
    ld hl,enemy_right
    jr aetl_end
    
    aetl_not19
    cp 20
    jr nz,aetl_not20
    ;20
    ld a,1
    ld hl,enemy_left
    jr aetl_end

    aetl_not20
    cp 21
    jr nz,aetl_not21
    ;21
    ld a,4
    ld hl,enemy_up
    jr aetl_end
    
    aetl_not21
    ;22 only
    ld a,3
    ld hl,enemy_up
    aetl_end
    
    ;get sprite and move dir by type
    ;set sprite +9 +10
    ld (ix+9),l
    ld (ix+10),h
    ;set movedir
    ld (ix+1),a
    
    ;enable
    ld a,1
    ld (ix),a
    ;reset movecount
    xor a
    ld (ix+2),a
    ;calc real position +3 +4
    ;de - position
    ld a,d
        add a,a
        add a,a
        add a,a
    ld (ix+3),a
    ld a,e
        dec a
        add a,a
        add a,a
        add a,a
    ld (ix+4),a
    ;point enemies pointer to the next enemy
    ld de,00013
    add ix,de
    ld (enemiesPointer),ix
    
    pop hl
    pop de
    pop ix
;draw nothing
    xor a
ret

addVerticalPhantom
    ld a,1
    ld (phantomKind),a
    xor a
    ret

initPixels
    ld hl,16384+4096+32
    ld (pixelsTable+3+0*8),hl
    ld (pixelsTable+3+1*8),hl
    ld (pixelsTable+3+2*8),hl
    ld (pixelsTable+3+3*8),hl
    ld (pixelsTable+3+4*8),hl
    ld (pixelsTable+3+5*8),hl
    ld (pixelsTable+3+6*8),hl
    ld (pixelsTable+3+7*8),hl
    ld (pixelsTable+3+8*8),hl
    ld (pixelsTable+3+9*8),hl
    ld (pixelsTable+3+10*8),hl
    ld (pixelsTable+3+11*8),hl
    ld (pixelsTable+3+12*8),hl
    ld (pixelsTable+3+13*8),hl
    ld (pixelsTable+3+14*8),hl
    ld (pixelsTable+3+15*8),hl
ret

initEnemies
    ;disable all enemies
    xor a
    ld (enemiesTable+0*13),a
        ld (enemiesTable+1*13),a
            ld (enemiesTable+2*13),a
                ld (enemiesTable+3*13),a
                    ld (enemiesTable+4*13),a
                        ld (enemiesTable+5*13),a
    ;set NORMAL TYPE
    ld (enemiesTable+0*13+11),a
        ld (enemiesTable+1*13+11),a
            ld (enemiesTable+2*13+11),a
                ld (enemiesTable+3*13+11),a
                    ld (enemiesTable+4*13+11),a
                        ld (enemiesTable+5*13+11),a
    ;reset enemies ticker
    ld (phantomEnemyTicker),a

    ;set start delay
    ld a,1
    ld (enemiesTable+1*13+12),a
    inc a
    ld (enemiesTable+2*13+12),a
    inc a
    ld (enemiesTable+3*13+12),a
    inc a
    ld (enemiesTable+4*13+12),a
    inc a
    ld (enemiesTable+5*13+12),a

ret

initPhantoms

ld ix,phantomsNumbers
ld a,(currentLevel)
ld d,0
ld e,a
add ix,de
ld a,(ix)
ld (totalPhantoms),a
ret


addPhantomEnemyToLevel
push ix
ld ix,(enemiesPointer)
;set phantom kind
ld (ix+11),1
;and add regular enemy by subtract
sub 25
call addEnemyToLevel
pop ix
ret

    
initLevel

;clear shadow buffer
ld hl,32768
ld de,32768+1
ld bc,4096
ld (hl),0
ldir
        
call showWorldName
call resetSprites
call calculateDrawing
call calculateRestore
call hidePreLevel
     
;setup broken bridge
ld hl,16384+4128
ld (brokenBridgeDrawAdr),hl
xor a
ld (stateCount),a
ld (phantomKind),a
ld (totalPixels),a

ld a,4
ld (brokenBridgeFrame),a
       
call initHero
call initEnemies
call initPhantoms

;reset pointers
ld hl,pixelsTable
ld (pixelsPointer),hl
ld hl,enemiesTable
ld (enemiesPointer),hl
;load level
ld a,(currentLevel)
add a,a;x2
ld d,0
ld e,a
ld ix,levelsTable
add ix,de
ld l,(ix)
ld h,(ix+1)
      
ld de,levelBuffer
call DEC40
;level start
ld hl,levelBuffer
;d=x=1 e=y=1
ld de,1+256*1

  nextLine
      ld d,1
  nextTile

      push de;save coords
      push hl;save level pointer
      ld a,(hl)

      cp 9
      call z,addPixelToLevel
      cp 16
      call z,addPixelToLevel
      cp 39
      call z,addPixelToLevel
      cp 40
      call z,addPixelToLevel
      
      cp 15
      call z,addStartPoint
      cp 19
      call z,addEnemyToLevel
      cp 20
      call z,addEnemyToLevel
      cp 21
      call z,addEnemyToLevel
      cp 22
      call z,addEnemyToLevel
      cp 23
      call z,addVerticalPhantom

      cp 44
      call z,addPhantomEnemyToLevel
      cp 45
      call z,addPhantomEnemyToLevel
      cp 46
      call z,addPhantomEnemyToLevel
      cp 47
      call z,addPhantomEnemyToLevel
      
      call drawTile

     ;=============================
      pop hl
      inc hl;next tile
      pop de;restore coords

      inc d;inc x
      ld a,d
      cp 31 ;compare 32
      jr nz,nextTile;if no next tilE in line

      inc e; inc y
      ld a,e
      cp 16;if no next line
      jp nz,nextLine
      ;finally end :)

      ;copy level to shadow buffer
      ld hl,16384
      ld de,32768
      ld bc,4096
      ldir
      
ret

;de - coords d=x, e=y a - number of tile
drawTile
    push af;save tile num
    push de
    push af
    call DISP_ADDR_BY_CELL;now in hl drawing address
    ex de,hl;now de point to screen
    pop af;restore tile num
    
    ld hl,tiles

    ;if tile number>32 then add 256 to hl
    cp 32
    jr c,dt_less32
    ld hl,tiles+256
    sub 32
    dt_less32
    
    ;one tile 8 bytes
    add a,a ;x2
    add a,a ;x4
    add a,a ;x8
    
    ld b,0;load
    ld c,a;to bc
    add hl,bc;now hl point to sprite

;    dup 7
;    ld a,(hl)
;    ld (de),a
;    inc hl
;    inc d
;    edup
     ld b,7
     retile
        ld a,(hl)
        ld (de),a
        inc hl
        inc d
     djnz retile
    
    ld a,(hl)
    ld (de),a
    
    pop de ;restore coords
    ;d=x , e=y
    ;calculate pixel line
;     BC = attributes address
;     D = pixel line (16-184, even values only)
;     E = char column (1-30)
      ;calculate pixel line
      ;swap d and e with a
      ld a,e
      ld e,d
      ld d,a
      ;calc pixel line
      add a,a ;x2
      add a,a ;x4
      add a,a ;x8

      add 8
      
      ld d,a
      ;color

      ;restore tile
      pop af

      add a,a;x2
      add a,a;x4

      
      ld hl,tilesColors
      ld b,0
      ld c,a
      add hl,bc

      ld c,l
      ld b,h
      call NIRVANA_paintC

ret

;de - coords d=x, e=y a - number of tile
ClearBridgeinBuffer
    call DISP_ADDR_BY_CELL;now in hl drawing address

;    push hl
    ;clear on screen
;    xor a
;    dup 3
;    ld (de),a
;    inc hl
;    inc d
;    edup
;    ld (de),a
;    pop hl

    ;clear in buffer
    ld de,16384
    add hl,de
    ex de,hl;now de point to buffer

    xor a
    dup 3
    ld (de),a
    inc hl
    inc d
    edup
    ld (de),a
ret
      
;b = y, c = x
;out: hl - address, a - xdif
getPixel

;y fix for 12 height sprite
 inc b
 inc b
 inc b
 inc b
   
  ld a,b;load y coord
  ld b,a
  and a
  rra
  scf
  rra
  and a
  rra
  xor b
  and 248
  xor b
  ld h,a
  ld a,c
  rlca
  rlca
  rlca
  xor b
  and 199
  xor b
  rlca
  rlca
  ld l,a
  ld a,c
  and 7

ret

getTileOnLegs
  call getTileTypeFromLevel
ret

getTileUnderLegs
  call getTileTypeFromLevelPlus8
ret

getTileOnHead
  call getTileTypeFromLevelMinus8
ret

getTileAboveHead
  call getTileTypeFromLevelMinus16
ret


getTileTypeFromLevelPlus8
;dup 8
;inc b
;edup
ld a,b
add 8
ld b,a
call getTileTypeFromLevel
ret

getTileTypeFromLevelMinus8
;dup 8
;dec b
;edup
ld a,b
sub 8
ld b,a
call getTileTypeFromLevel
ret

getTileTypeFromLevelMinus16
;dup 16
;dec b
;edup
ld a,b
sub 16
ld b,a
call getTileTypeFromLevel
ret

  
;get tile from level buffer by real 
;bc - real coords
;out in A - tile byte from level buffer
getTileTypeFromLevel
     
   push ix
   push bc
   
   ld ix,levelBufferLines;таблица адресов начала строк буфера
   
   ;y
   ld a,b
     ;ДЕЛИМ НА 8
     srl a
     srl a
     srl a
     ;умножаем на 2 - т.к. адрес 2 байта
     add a
  
   ld d,0
   ld e,a

   add ix,de 
   ld l,(ix)
   ld h,(ix+1)
   ;теперь hl указывает на адрес начала линии
   ;нужно добавить Х
   ;вычтем еденичку т.к. буфер с 1 начинается
   dec c
   
   ;x
   ld a,c
     ;ДЕЛИМ НА 8
     srl a
     srl a
     srl a
   ld c,a
   ld b,0
   
   add hl,bc ;теперь в HL адрес ячейки в буфере

   ld a,(hl);получаем тайл

   ld hl,tilesTypes
   ld c,a
   add hl,bc

   ld a,(hl);получаем тип обьекта
   pop bc
   pop ix
ret

;de - cell coords
;a-tile type
putTileToLevel
        
   push ix
   push de
   push af
   
   ld ix,levelBufferLines;таблица адресов начала строк буфера

   ld a,e;y
   add a,a ;x2
   
   ld b,0
   ld c,a

   add ix,bc
   
   ld l,(ix)
   ld h,(ix+1)
   ;теперь hl указывает на адрес начала линии
   ;нужно добавить Х

   ;x
   ld c,d
   ld b,0

   add hl,bc ;теперь в HL адрес ячейки в буфере
   pop af
   ld (hl),a;кладём тайл

   pop de
   pop ix
ret

getHeroCellCoords
   ;y
   ld a,b
     ;ДЕЛИМ НА 8
     srl a
     srl a
     srl a
   ld e,a

   ;x
   ;вычтем еденичку т.к. буфер с 1 начинается
  ; dec c
   ld a,c
     ;ДЕЛИМ НА 8
     srl a
     srl a
     srl a
   dec a
   ld d,a

ret

getPhantomCellCoords

   ;y
   ld a,b
     ;ДЕЛИМ НА 8
     srl a
     srl a
     srl a
   ld e,a

   dec e
   
  ;x
   ;вычтем еденичку т.к. буфер с 1 начинается
;   dec c
   ld a,c
     ;ДЕЛИМ НА 8
     srl a
     srl a
     srl a
;   dec a

   ld d,a
   dec d
   
ret

getHeroCellCoordsUnderLegs

   ld bc,(heroPos)
   call getHeroCellCoords
   ;now hl - cell coords
   inc e
ret

   
levelBufferLines
defw levelBuffer+0*30,levelBuffer+1*30,levelBuffer+2*30,levelBuffer+3*30,levelBuffer+4*30,levelBuffer+5*30,levelBuffer+6*30,levelBuffer+7*30,levelBuffer+8*30
defw levelBuffer+9*30,levelBuffer+10*30,levelBuffer+11*30,levelBuffer+12*30,levelBuffer+13*30,levelBuffer+14*30,levelBuffer+15*30,levelBuffer+16*30,levelBuffer+17*30

defb (30)1
levelBuffer
file levels\level0.bin
DEFB(30)1

   
;0 - pass 1-solid 2-ladder 3-bridge 4-dead 5-PHANTOMBLOCK
tilesTypes
defb            0,      1,      1,      0,      0,         2,       0,        0,     0,        0,       3,       1,      1,        1,       2,      0,     0,          4,       4,       0,       0,        0,       0,   0,           1,      1,    0,          0,     2,       2,       0,          0,      1,       1,       0,       0,        2,        2,        0,       0,       0,      5,       0,        0,      0,         0,       0,      0,       1,        1,     2,         0,       0

   
tiles defg ........ ........ ........ ........ ........ .X....X. .X..X.X. ..X...X. X..X.XX. ........ ........ XXXXXXXX XXXXXXXX ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ..X...X. ........ .X...X.. .X..X.X. ...XX... ........ ...XX... ...X....  ..X..X..  ........  ........ ........ ........ ........ ...X.... ........ ........ ........ ........ ........ ........ ........ ......X. ...X.... .X.X.X..
           ........ XXXXXXXX XXXXXXXX ........ ........ .X.XXXX. .X....X. .....X.. ......X. ........ XXX.XXXX XXXXXXXX XXXXXXXX XXXXXXXX ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ XXXXXXXX .XXXXXX. ........ ........ ..X...X. ........ ........ ........ XX.XX.XX XXXXXXXX ........ ....X...  ........  ........  ........ ........ ........ ........ ...X.... ........ ........ ........ ........ ........ XX.XX.XX .XXXXXX. ......X. ...X.... ...X....
           ........ XXXXXXXX XXXXXXXX ........ ........ .X....X. ........ ........ ..XX.... ........ ........ XXXXXXXX XXXXXXXX XXXXXXXX ........ ...XXX.. ........ .X.X.X.X ..X..... ........ ........ ........ ........ ........ ........ .X.XXX.. ........ ....X... ........ ........ X.X..X.. .X..X.X. ........ ........ .XXXXXX. ...X....  .XXXXXX.  ........  ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ XX.XX.XX .X..X.X. ..X.X.X. ........ ........
           ........ XXX.XXXX XXXXX.XX ........ ........ .X....X. ........ ........ ...X.... ........ .XXX.XXX XX.XXXXX XXXXX.XX XX.XXXXX ........ ..X..... ........ ..X...X. ........ ........ ........ ........ ........ ........ .X...X.. .XXXXXX. ........ ...X.X.. ..X...X. ........ .X...... ....X... .X.XX..X .X.X.X.X X......X ....X...  ........  ........  ....X... ........ ........ .X...X.. ...X.... ...X.... ........ ........ ........ ........ XX.XX.XX .XXXXXX. ......X. ...X.... ...X....
           ........ XXXXX.XX X.XXXXXX ........ ........ .X....X. ........ ........ ...X.... ........ ........ XXXXXXXX XXXXXXXX XXXXXXXX .X....X. ...XXX.. ........ ....X... ........ ........ ........ ........ ........ ........ ...X...X .XXX.X.. ..X..... ....X... .X.XXX.X ..X...X. ........ ...X.X.. X..XX.X. X.X.X.X. ..XX.X.. ...X....  ..X..X..  ........  ...XXX.. ........ ........ ...X...X ..X.X... ..XXX... ........ ........ ........ ........ ........ .XXXXXX. ......X. ..X.X... ........
           ........ XX.XXXXX XXXXXX.X ........ ........ .X.XXXX. ........ ........ ........ ........ ........ XXXXX.XX XX.XXXXX XXXXX.XX .X.XXXX. ......X. ........ ........ ........ ........ ........ ........ ........ ........ .X...X.. .XXXXXX. .X.X..X. .X..X.X. ..X...X. .X.XXX.X ........ ....X... .X.XX..X .X.X.X.X ...X.... ....X...  ........  ........  ........ ........ ........ ........ ...X.... ........ ........ ........ ........ ........ XX.XX.XX .X.X..X. ......X. ...X.... ...X....
           ........ .XXXXXX. ........ .X....X. .....X.. .X....X. ........ ........ ...X.... ........ ........ XXXXXXXX XXXXXXXX XXXXXXXX .X....X. ...XXX.. ........ ..X..... .....X.. ........ ........ ........ ........ ........ ........ .X.X.X.. ........ ........ ........ ........ ........ ........ ........ ........ ........ ...X....  ..XXXX..  X.XXXX.X  X...X... ........ ........ ........ ........ ...X..X. ........ ........ ........ ........ ........ .XXXXXX. .X.XX.X. ........ ........
           ........ ........ ........ .X..X.X. ..X...X. .X....X. ........ ........ ........ ........ ........ .XXXXXXX XXXXXXX. .XXXXXXX .X....X. ........ ........ .....X.. ........ ........ ........ ........ ........ ........ ........ ........ ..X...X. .X..X.X. ..X...X. ..X...X. ........ ........ ...XX... ........ ........ ....X...  ........  ........  .X..X.X. ........ ........ ........ ...X.... .X.X.X.. ........ ........ ........ ........ ........ ........ ......X. ........ ...X....

tilesColors
      defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7
      
      defb 0*8+64+4,7*8+64+2,7*8+00+3,0*8+00+3
      defb 0*8+64+4,7*8+64+2,7*8+00+3,0*8+00+3
      
      defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+00+4
      defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+00+4
      
      defb 0*8+64+6,0*8+64+6,0*8+00+6,0*8+00+6
      
      defb 0*8+00+4,0*8+64+7,0*8+64+7,0*8+64+7
      defb 0*8+00+4,0*8+64+7,0*8+64+7,0*8+64+7
      
      defb 0*8+00+4,0*8+00+4,0*8+64+4,0*8+64+4
      
      defb 0*8+64+7,0*8+64+7,0*8+00+3,0*8+64+3
      
      defb 0*8+64+6,0*8+00+6,0*8+64+7,0*8+64+7
      
      defb 0*8+00+2,7*8+00+2,7*8+00+2,0*8+00+2
      defb 0*8+00+2,7*8+00+2,7*8+00+2,0*8+00+2
      defb 0*8+64+4,7*8+64+2,7*8+00+2,7*8+00+2

      defb 0*8+64+7,0*8+64+7,0*8+00+6,0*8+64+6
      defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7

      defb 0*8+64+7,0*8+64+7,0*8+00+7,0*8+64+7

      defb 0*8+64+7,1*8+64+5,1*8+64+5,1*8+00+5
      defb 1*8+00+5,1*8+00+5,1*8+00+5,1*8+00+5

      defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7
      defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7
      defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7
      defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7
      defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7

      ;SPELLWORLD
      defb 0*8+64+7,0*8+00+7,3*8+00+7,0*8+00+7
      defb 0*8+64+7,0*8+64+7,0*8+00+7,0*8+00+7
      ;FLOWERS
      defb 0*8+64+7,0*8+64+5,0*8+64+5,0*8+64+7
      defb 0*8+64+7,0*8+64+5,0*8+64+5,0*8+64+7
      ;LADDER
      defb 0*8+64+3,0*8+00+2,0*8+64+2,0*8+00+3
      defb 0*8+64+7,0*8+64+7,0*8+64+2,0*8+64+3
      ;flowwers down
      defb 0*8+64+7,0*8+64+5,0*8+64+7,0*8+64+7
      defb 0*8+64+7,0*8+64+5,0*8+64+5,0*8+64+7

      ;CHINA TOWN
      defb 0*8+64+2,0*8+64+6,0*8+00+6,0*8+00+3
      defb 0*8+64+2,0*8+64+6,0*8+00+6,0*8+00+3
      ;FONAR
      defb 0*8+00+5,0*8+00+2,1*8+64+6,0*8+64+6
      defb 0*8+64+5,0*8+64+5,0*8+00+5,0*8+00+5
      ;LADDER
      defb 0*8+64+4,0*8+00+4,0*8+64+4,0*8+00+4
      defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+4
      ;BORTIK
      defb 0*8+64+7,0*8+64+7,0*8+00+6,0*8+00+4

      ;switch pixel
      defb 0*8+64+7,0*8+64+7,0*8+64+4,0*8+00+4
      ;teleport pixel
      defb 0*8+64+5,0*8+64+5,0*8+64+5,0*8+00+5

      ;PHANTOM BLOCK
       defb 0*8+00+7,1*8+64+7,1*8+7,0*8+00+7
      ;SPLIT
       defb 0*8+00+5,0*8+1,0*8+1,0*8+00+5
       ;FLOWER FOR FIRST LEVELS
       defb 0*8+64+7,0*8+00+7,0*8+3,0*8+00+4
       ;phantom enemies
       defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7
       defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7
       defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7
       defb 0*8+64+7,0*8+64+7,0*8+64+7,0*8+64+7
       ;LAST LANDS
       defb 0*8+64+5,2*8+0+5,1*8+0+5,0*8+64+7
       defb 0*8+64+7,0*8+0+7,1*8+0+7,0*8+64+3
       ;LAST LADDER
       defb 0*8+64+3,0*8+0+3,0*8+64+3,0*8+0+3
       ;LAST DOWN FLOWERS
       defb 0*8+64+5,0*8+0+5,0*8+64+2,0*8+0+6
       defb 0*8+64+6,0*8+0+5,0*8+64+5,0*8+0+5



n_Pause

    n_p_loop
        halt
        nop
    djnz n_p_loop
    
ret

mainMenu

    call stopNIRVANA
    call setup
    call resetSprites
    call initPixels
    call hidePressStart
    
xor a
ld (menuTicker),a
ld (menuCount),a

ld hl,menuYpos
ld (deadPointer),hl

;load menu level - it's 37
ld a,37
ld (currentLevel),a
call initLevel

call putTitleAttr

;draw texts
ld hl,s_PressFire
ld bc,smallFont
call PRINTSTRING

ld hl,s_Title
ld bc,bigFont
call PRINTSTRING

ld hl,musicPT3
call player+3
ld hl,player+5
ld (ay_frame_proc+1),hl

call startNIRVANA
      
ld hl,23560         ; LAST K system variable.
ld (hl),0           ; put null value there.

mainMenuLoop

      halt
      call calculateRestore0
      call calculateRestore1

      ;for blink phantom
      ld hl,NOPS_32
      ld (sprite1),hl
      ld a,(menuTicker)
      xor 1
      ld (menuTicker),a
      cp 0
      jr nz,mml_skip
      call doParticlesFAST
      call doPixelsAnimation
      call doMainMenuAnimation
      mml_skip

      ;blink for fire button
      ld a,(menuTicker)
      cp 1
      call z,doBlink
      
      call calculateDrawing0
      call calculateDrawing1

;      call checkPressFire

;      jp mainMenuLoop

       ld hl,23560         ; LAST K system variable.
       ld a,(hl)           ; new value of LAST K.

       cp ' '
       jp z,keyboardStart
       cp 'm'
       jp z,keyboardStart
       cp '0'
       jp z,sinclairStart
       ld hl,23560         ; LAST K system variable.
       ld (hl),0           ; put null value there.

       jp mainMenuLoop

       
keyboardStart
       call hidePressStart
       ;
       ld hl,keyboard_controls
       ld (CONTROLS_LABEL+1),hl
       call clearStage
       call stopNIRVANA
jp startGame

sinclairStart
       call hidePressStart
       ;
       ld hl,sinclair_controls
       ld (CONTROLS_LABEL+1),hl
       call clearStage
       call stopNIRVANA
jp startGame


hidePressStart
       ;hide press start and other stuf lower than 16
       
       ld hl,16384+6144+32*17
       ld de,16384+6144+32*17+1
       ld bc,32*7
       ld (hl),0
       ldir
       ;reset blink count
       ld c,0
       ld (blinkCount),bc
ret

;hide upper part with null
hidePreLevel
 ld hl,16384+6144
 ld de,16384+6144+1
 ld bc,32*15
 ld (hl),0
 ldir
ret
      
doBlink
      ld de,blinkBytes
      ld bc,(blinkCount)
      ld hl,16384+6144+32*19+0
      add hl,bc
      dup 4
      ld a,(de)
      ld (hl),a
      inc de
      inc hl
      edup
      ld a,(de)
      ld (hl),a
      inc bc
      ld (blinkCount),bc
      ld a,c
      cp 26
      ret nz
      ld c,0
      ld (blinkCount),bc
ret

doBlink2
      ld de,blinkBytes
      ld bc,(blinkCount)
      ld hl,16384+6144+32*23+0
      add hl,bc
      dup 4
      ld a,(de)
      ld (hl),a
      inc de
      inc hl
      edup
      ld a,(de)
      ld (hl),a
      inc bc
      ld (blinkCount),bc
      ld a,c
      cp 26
      ret nz
      ld c,0
      ld (blinkCount),bc
ret

blinkPointer: defw 16384+6144+32*19
blinkCount: defw 00000
      
blinkBytes: defb 7+64+0*8,6+64+0*8,2+64+0*8,1+64+0*8,3+64+0*8
      
putTitleAttr

      ld d,16
      ld e,3
      ld hl,titleBytes

      ld b,28
      call putXLine

      ld d,16+8
      ld e,3
      ld hl,titleBytes+4

      ld b,28
      call putXLine
      
ret

;de - start coords
;a - count
putXLine

    pxl
    ;save counter
    push bc
    ;save coords
    push de
    ;move to bc from hl
    push hl
    ld b,h
    ld c,l
    call NIRVANA_paintC
    pop hl
    ;restore coords
    pop de
    inc e
    ;restore counter
    pop bc
    djnz pxl
      
ret

titleBytes 
    defb 1+64,3+64,3,5+1*8+64
    defb 3,3+64,1+64,7
      
doMainMenuAnimation

      ;inc menu count
      ld a,(menuCount)
      inc a
      ld (menuCount),a
      cp 8
      jr nz,dmma0
      xor a
      ld (menuCount),a
      dmma0

      ld a,0
      ;animate frames of hero and phantom
      ld hl,hero_menu

      add a,a
      add a,a
      add a,a
      add a,a
      add a,a

      ld c,a
      ld b,0
      add hl,bc
      ld (sprite0),hl

      ld hl,phantom_menu
      add hl,bc
      ld (sprite1),hl

      ;positions
      ld bc,(heroPos)
      ld hl,(deadPointer)

      ld a,(hl)
      cp 128
      jr z,resetDP

      ld a,b
      add (hl)
      ld b,a

      inc hl
      ld (deadPointer),hl
      ld (heroPos),bc

      ;set sprites

      call getPixel
      ld (draw0),hl
      ld hl,(draw0)
      dup 8
      inc l
      edup
      ld (draw1),hl
      ret
      resetDP

      ld hl,menuYpos
      ld (deadPointer),hl

ret

showWorldName

;    ret
    call hidePressStart
    call hidePreLevel
    
    ld a,(currentLevel)
    cp 35
    ret nc
    
    call getWorldByLevel
    ld b,a
    ld a,(preWorld)
    cp b
    ret z
    ld a,b
    ld (preWorld),a

;    ld hl,whiteBYtes
;    call fillNirvana
;    ld hl,blackBytes
;    call fillNirvana
    halt
    call stopNIRVANA
    call setup
    call resetSprites
    call initPixels
    call hidePressStart
    
    LD HL,23693         ; const attr
    ld (HL),0          ;
    CALL 3503           ; clear screen
    ;nirvana allready stopped
    call putWorldNameAtr
    ;print names
    ld a,(currentLevel)
    call getWorldByLevel

    add a,a;x2

    ld ix,worldsNames
    ld b,0
    ld c,a
    add ix,bc
    push bc
    ld l,(ix)
    ld h,(ix+1)
    ;draw texts
    ld bc,smallFont
    call PRINTSTRING
    ld ix,dreamsNames
    pop bc
    add ix,bc
    ld l,(ix)
    ld h,(ix+1)
    ;draw big text
    ld bc,bigFont
    call PRINTSTRING
    
    ;draw press any key
    ld hl,s_PressKey
    ld bc,smallFont
    call PRINTSTRING


    ;start nirvana
;    halt
    call startNIRVANA
    ;some pause
 ;   ld b,128
;    call n_Pause

     ld hl,23560         ; LAST K system variable.
     ld (hl),0           ; put null value there.
     
     swn_loop
     halt

     ld a,(menuTicker)
     xor 1
     ld (menuTicker),a
     cp 1
     call z,doBlink

     ld hl,23560         ; LAST K system variable.
     ld a,(hl)           ; new value of LAST K.
     cp 0
     jp z,swn_loop
     
    ;clear stage
    call clearStage
    ;stop nirvana
    call stopNIRVANA
    ;
    call setup
ret

;put atr for world names
putWorldNameAtr
;for world name
      ld d,10*8+8
      ld e,3
      ld hl,worldBytes
      ld b,28
      call putXLine
      ld d,11*8+8
      ld e,3
      ld hl,worldBytes+4
      ld b,28
      call putXLine
;for dream name
      ld d,6*8+8
      ld e,3
      ld hl,worldBytes+8
      ld b,28
      call putXLine
      ld d,7*8+8
      ld e,3
      ld hl,worldBytes+12
      ld b,28
      call putXLine
;for password
     ld hl,16384+6144+16*32+4
     ld de,16384+6144+16*32+5
     ld bc,24
     ld (hl),71
     ldir
ret

worldBytes: defb 0*8+64+7,0*8+64+7,0*8+0+7,0*8+0+3
            defb 0*8+64+3,0*8+64+7,0*8+64+7,0*8+64+7
            ;big letters 2x8
            defb 0*8+64+3,0*8+64+2,0*8+64+2,0*8+0+2
            defb 0*8+0+2,0*8+00+2,0*8+00+3,0*8+64+7

;ret world by level num
getWorldByLevel
cp 11
jr nc,gw_more10
;less 10 - world 1
ld a,0
ret
gw_more10
cp 21
jr nc,gw_more20
;less 20 - world 2
ld a,1
ret
gw_more20
cp 31
jr nc,gw_more30
;less 30 - world 3
ld a,2
ret
gw_more30
ld a,3
ret



;some another include
;ay LIb
INCLUDE sound/ayfxplay.a80
;font driver
INCLUDE FZX.a80
;sounds
soundBank: FILE sound/sounds.afb

psChar: defb 0
      
showEnterPassword

      call stopNIRVANA
      
      call setup
      
      call resetPassword
      
      ld hl,s_EnterPassword
      ld bc,smallFont
      call PRINTSTRING

      ld hl,23560         ; LAST K system variable.
      ld (hl),0           ; put null value there.

enterPasswordLoop
      
      halt
      call AFXFRAME
      
       ld hl,23560         ; LAST K system variable.
       ld a,(hl)           ; new value of LAST K.
       ;end password check
       cp 13
       jp z,passwordCheck
       ;no key - loop
       cp 0
       jr z,enterPasswordLoop
       ;ok we get key
      ; ld hl,23560         ; LAST K system variable.
;       ld a,(hl)           ; new value of LAST K.
       ld hl,23560         ; LAST K system variable.
       ld (hl),0           ; put null value there.

      ; push af ;save char

       ld (psChar),a
      
       ;only numbers
       cp '0'
       jp c,enterPasswordLoop
       cp '9'+1
       jp nc,enterPasswordLoop

       ;end string allready
       ld a,(passwordCounter)
       cp 6
       jp z,enterPasswordLoop
              
       ld hl,s_EnterPassword1+2
       inc a
       ld (passwordCounter),a

       ld d,0
       ld e,a
       add hl,de
       ld a,(psChar);restore char

       ld (hl),a

       ld a,1
       call AFXPLAY

       ;clear string for 
       ld hl,s_EnterPassword1
       ld bc,smallFont
       call PRINTSTRING
       jp enterPasswordLoop

succesPassword
         ;end
       ld a,7;4-bad
       call AFXPLAY

       ld b,40
       pc_delayLoop:
         halt
         push bc
         call AFXFRAME
         pop bc
         djnz pc_delayLoop

ret

passwordCheck

       ld hl,s_EnterPassword1+3
       ld de,pass11
       call compareStrings

       jr nz,notLevel5
       ld a,11
       ld (currentLevel),a
       ret
       notLevel5

       ld hl,s_EnterPassword1+3
       ld de,pass21
       call compareStrings
       jr nz,notLevel10
       ld a,21
       ld (currentLevel),a
       ret
       notLevel10
       
       ld hl,s_EnterPassword1+3
       ld de,pass31
       call compareStrings
       ret nz
       ld a,31
       ld (currentLevel),a
      ;jp showEnterPassword

ret ;ret from all show password

;pure cmpStr
compareStrings
ld b,6
reCompare
ld a,(de)
cp (hl) 
ret nz 
inc de
inc hl 
djnz reCompare
ret

     
resetPassword

      ;reset password counter
      xor a
      ld (passwordCounter),a
      ;clear password string
      ld hl,s_EnterPassword1+3
      ld de,s_EnterPassword1+4
      ld bc,5
      ld (hl),' '
      ldir
ret
      
passwordCounter: defb 0 ;     password letter counter

;TEXT DATA
;---------------------y-x-
;passwords to compare
password: defb "------"
pass11:   defb "528435"
pass21:   defb "194673"
pass31:   defb "746659"
s_EnterPassword:     defb $16,6*8,6*8,"Enter Password (Enter=First Dream)"
s_EnterPassword0:    defb $16,9*8,14*8,"------",255
s_EnterPassword1:    defb $16,9*8-4,14*8,"      ",255


worldsNames: defw world1,world2,world3,world4
      
world1: defb $16,10*8,11*8,"Strawberry Fields",255
world2: defb $16,10*8,9*8,"Land Of Abandoned Bridges",$16,16*8,11*8+2,"Password: 528435",255
world3: defb $16,10*8,12*8,"Valley of Skulls",$16,16*8,11*8+2,"Password: 194673",255
world4: defb $16,10*8,12*8+4,"Dream Station",$16,16*8,11*8+2,"Password: 746659",255

dreamsNames: defw dream1,dream2,dream3,dream4
      
dream1: defb $16,6*8,6*8+2,"FIRST DREAM",255
dream2: defb $16,6*8,6*8-4,"SECOND DREAM",255
dream3: defb $16,6*8,6*8+2,"THIRD DREAM",255
dream4: defb $16,6*8,7*8,"LAST DREAM",255

s_PressFire: defb $16,19*8,11*8,"Press 'Fire' To Start",$16,3*8,22*8,"Alter Ego 2",255
s_Title: defb $16,1*8,6*8+2,"DREAMWALKER",255
s_PressKey: defb $16,19*8-1,09*8,"Press Any Key To Continue",255

s_Lives: defb $16,19*8,13*8,"Lives Left: 0",255
s_GameOver: defb $16,19*8,13*8,"Game  Over",255

s_NIRVANALOGO_small: defb $16,9*8-2,14*8-2,"Powered by",$16,13*8,15*8-2,"ENGINE"
                     defb 255

           
s_NIRVANALOGO_big: defb $16,11*8,10*8,"NIRVANA",255
;таблица собиралок
;0 - enabled
;1,2 - position
;3,4 drawing address
;5 kind - phantom or hero
;Кадр для всех один
;16 штук
pixelsTable
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0
defb 1 defw 00000,16384+4096+32 defb 0,0,0

;enemy table
;Max - 6 enemies
;0 - enabled
;1 - movedir
;2 - movecount
;3,4 - real position
;5,6 - drawN where to draw
;7,8 - spriteN attached
;9,10 - sprite address
;11 -phantom ??
;12 - start Delay
enemiesTable
defb 1,2,0 defw 4*8+6*8*256,draw2,sprite2,enemy_right defb 0,0
defb 0,2,0 defw 4*8+5*8*256,draw3,sprite3,enemy_right defb 0,1
defb 0,2,0 defw 4*8+6*8*256,draw4,sprite4,enemy_right defb 0,2
defb 0,2,0 defw 4*8+7*8*256,draw5,sprite5,enemy_right defb 0,3
defb 0,2,0 defw 4*8+8*8*256,draw6,sprite6,enemy_right defb 0,4
defb 0,2,0 defw 4*8+9*8*256,draw7,sprite7,enemy_right defb 0,5

;magic particles max 16
;0,1 - real coords
;2,3 - drawing address
;4,5 - pre drawing - for clear by XOR
particelsTable
defw 2*8+14*8*256,00000,00000
defw 6*8+13*8*256,00000,00000
defw 10*8+8*8*256,00000,00000
defw 14*8+4*8*256,00000,00000
defw 18*8+12*8*256,00000,00000
defw 22*8+11*8*256,00000,00000
defw 26*8+7*8*256,00000,00000
defw 30*8+2*8*256,00000,00000
defw 20*8+10*8*256,00000,00000
defw 16*8+9*8*256,00000,00000
defw 4*8+7*8*256,00000,00000
defw 24*8+6*8*256,00000,00000

pixelFrames
defg ........ ..XXXX.. ..XXXX.. ........ ........ ........ ........ ........
     ..XXXX.. ..X..X.. ..X..X.. ..XXXX.. ..XXXX.. ........ ........ ..XXXX..
     ..X..X.. ..XXXX.. ..XXXX.. ..X..X.. ..X..X.. ..XXXX.. ..XXXX.. ..X..X..
     ..XXXX.. ........ ........ ..XXXX.. ..XXXX.. .XXXXXX. .XXXXXX. ..XXXX..

hero_dead: include sprites\hero_dead.asm
hero_menu: include sprites\menu_hero2.asm
phantom_menu: include sprites\menu_phantom2.asm
     
deadYpos: defb -1,-2,-2,-3,-1,0,0,0,1,1,2,128
;menuYpos: defb -1,-1,-1,0,0,1,1,1,128
menuYpos: defb -1,0,0,-1,0,0,-1,0,0,-1,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,128


fillNirvana

      ld (fn_bytes+1),hl
      ld b,15
      ld d,16
      fnb
      push bc
      push de
      ld e,1
fn_bytes:     ld hl,blackBytes
      ld b,30
      call putXLine
      pop de
      dup 8
      inc d
      edup
      pop bc
      djnz fnb
      halt
           
ret
           
blackBytes defb 0,0,0,0
whiteBYtes defb 71,71,71,71

;outro texts
s_outroText1: defb $16,1*8,10*8,"THE END",255
s_outroText2: defb $16,19*8-2,11*8,"Thanks For Playing!"
              defb $16,4*8+4,9*8,"Dreamwalker, Dreamwalker."
              defb $16,5*8+4,11*8,"Where did you go?"
              defb $16,6*8+4,11*8+2,"There is no way,"
              defb $16,7*8+4,11*8-4,"There is only snow."
              
              defb $16,9*8+4,9*8,"Dreamwalker, Dreamwalker."
              defb $16,10*8+4,11*8+4,"It's just a dream."
              defb $16,11*8+4,10*8,"Wake up, Dreamwalker,"
              defb $16,12*8+4,12*8+2,"Become real."
              defb $16,16*8-1,7*8+4,"'DreamWalker' by Denis Grachev"
            ;  defb $16,16*8,18*8+2,"01 Feb.2014"
              defb 255

showOutro



    call stopNIRVANA
    call setup
    call resetSprites
    call initPixels
    call hidePressStart

xor a
ld (menuTicker),a
ld (menuCount),a

ld hl,menuYpos
ld (deadPointer),hl

;load outro level - it's 38
ld a,36
ld (currentLevel),a
call initLevel

call putTitleAttr
      
;put texts
ld hl,s_outroText1
ld bc,bigFont
call PRINTSTRING

ld hl,s_outroText2
ld bc,smallFont
call PRINTSTRING

ld hl,musicPT3
call player+3
ld hl,player+5
ld (ay_frame_proc+1),hl
     
call startNIRVANA

ld hl,23560         ; LAST K system variable.
ld (hl),0           ; put null value there
      
      
      outroLoop

      halt
      call calculateRestore0
      call calculateRestore1

      ;for blink phantom
      ld hl,NOPS_32
      ld (sprite1),hl
      ld a,(menuTicker)
      xor 1
      ld (menuTicker),a
      cp 0
      jr nz,mml_skip_outro
      call doParticlesFAST
      call doPixelsAnimation
      call doMainMenuAnimation

      ld hl,(draw0)
      ld a,l
      add 22
      ld l,a
      ld (draw1),hl
      
      mml_skip_outro
      ;blink for fire button
      ld a,(menuTicker)
      cp 1
      call z,doBlink

      call calculateDrawing0
      call calculateDrawing1

      jp outroLoop

IMON
       LD    A,24        ;код команды JR
       LD    (65535),A
       LD    A,195       ;код команды JP
       LD    (65524),A
       LD    (65525),HL  ;в HL - адрес обработчика прерываний
       LD    HL,FE00h    ;построение таблицы для векторов прерываний
       LD    DE,FE01h
       LD    BC,256      ;размер таблицы минус 1
       LD    (HL),FFh    ;адрес перехода #FFFF (65535)
       LD    A,H         ;запоминаем старший байт адреса таблицы
       LDIR              ;заполняем таблицу
       DI                ;запрещаем прерывания на время
                         ; установки второго режима
       LD    I,A         ;задаем в регистре I старший байт адреса
                         ; таблицы для векторов прерываний
       IM2           ;назначаем второй режим прерываний
       EI                ;разрешаем прерывания
       RET


IMOFF  DI
       LD    A,63
       LD    I,A
       IM1
       EI

       RET
;music
musicPT3: FILE music/mmcm_dreamwalker_final.pt3

;player
org 52320
player FILE music/player52320.bin
           
org 54480

;DISPLAY platformPentagon
       
;IF platformPentagon=1 THEN include nirvanaPentagon.a80 ENDIF
;IF platformPentagon=0 THEN include nirvanaSinclair.a80 ENDIF

;include nirvanaPentagon.a80
include nirvanaSinclair.a80

;Draw all pixel
drawPixels

ld hl,(pixelsTable+3+0*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a


ld hl,(pixelsTable+3+1*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+2*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+3*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a


ld hl,(pixelsTable+3+4*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+5*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+6*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+7*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+8*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+9*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a


ld hl,(pixelsTable+3+10*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+11*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+12*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+13*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+14*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ld hl,(pixelsTable+3+15*8)
;sprite source
ld de,(pixelsAnimation)

dup 3
    ld a,(de)
    ld (hl),a
    inc h
    inc de
edup
    ld a,(de)
    ld (hl),a

ret

include spritesLib2.a80
include DEC40.a80
      
org 65281-256*4
deltas
        defb      75, 75, 76, 71, 72, 79, 80, 58, 59, 61, 62, 65, 66, 97, 98, 100, 101
        defb      93, 94, 68, 69, 115, 116, 118, 119, 121, 122, 55, 56, 127, 128, 128
org 65281-256*3
deltasPG
        defb 71, 71, 72, 74, 75, 77, 78, 102, 103, 61, 62, 64, 65, 67, 68, 86, 87
        defb 89, 90, 92, 93, 109, 110, 112, 113, 115, 116, 121, 122, 127, 128, 128

org 32768
credits
     call setup
     ld hl,s_Credits
     ld bc,smallFont
     call PRINTSTRING
     ld hl,23560         ; LAST K system variable.
     ld (hl),0           ; put null value there.
     credits_loop
     halt
     ;intro attribs FX
     call updateCreditsAtribs
     ld hl,23560         ; LAST K system variable.
     ld a,(hl)           ; new value of LAST K.
     cp 0
     jp z,credits_loop

     call fade_out

ret

updateCreditsAtribs

     ld ix,uca_tabl
     ld hl,#5800
     ld bc,#0105
     call uca_atr
     call uca_intab
ret

uca_atr
     ld e,0
     ld a,c
     srl a
     inc a
     ld (uca_poke1+1),a
     ld a,b
     ld (uca_poke2+1),a
     add a,a
     ld (uca_poke3+1),a
uca_loop    ld b,#10
uca_loop1   inc e
     ld a,e
     and #1f
     ld (uca_num+2),a
uca_num ld a,(ix+0)
     ld (hl),a
     inc hl
     djnz uca_loop1
     ld b,#10
uca_loop2 dec e
     ld a,e
     and #1f
     ld (uca_num1+2),a
uca_num1 ld a,(ix+0)
     ld (hl),a
     inc hl
     djnz uca_loop2
     ld a,c
uca_poke1 cp 4
     jr z,uca_cont
     push af
     ld a,e
uca_poke2 add a,4
     ld e,a
     pop af
     jr nc,uca_cont
     ld a,e
uca_poke3 sub 4
     ld e,a
uca_cont dec c
     jr nz,uca_loop
     ret
uca_intab: ld hl,uca_tabl+1
           ld de,uca_tabl
           ld bc,#20
           ld a,(de)
           ldir
           ld (de),a
           ret

uca_tabl: defb 0,#40,1,#41
          defb 2,#42,3,#43
          defb 4,#44,5,#45
          defb 6,#46,7,#47
          defb #47,#47,7
          defb #46,6,#45,5
          defb #44,4,#43,3
          defb #42,2,#41,1
          defb #40,0


s_Credits: defb $16,3*8,2*8,"DreamWalker: AlterEgo 2"
           defb $16,3*8+6,2*8,"__________________________"
           defb $16,7*8,2*8,"Game by Denis Grachev"
           defb $16,8*8,2*8,"Nirvana Engine by Einar Saukas"
           defb $16,9*8,2*8,"AYFX Engine by Shiru"
           defb $16,10*8,2*8,"FZX Format by Andrew Owen"
           defb $16,11*8,2*8,"FZX Driver by Einar Saukas"
           defb $16,12*8,2*8,"Additional Code by Jerri"
           defb $16,13*8,2*8,"Screen by Diver"
           defb $16,14*8,2*8,"Music by MmcM"
           defb $16,15*8,2*8,"MegaLZ tools by Fyrex & LVD"
           defb $16,16*8,2*8,"Text Correction by IvanZX"
           defb $16,22*8,2*8,"Press any key to start"
           defb 255
showIntro
         call showNirvanaLogo
ret


fade_out

halt
        LD B,7
L0      LD C,4
L1      HALT
DEC C
JR NZ,L1
LD HL,23295
L2	LD A,(HL)
AND 56
JR Z,L3
SUB 8
L3	LD C,A
LD A,(HL)
AND 7
JR Z,L4
DEC A
L4	OR C
LD (HL),A
DEC HL
BIT 3,H
JR NZ,L2
DJNZ L0

CALL 3503           ; clear screen
        
ret

        
showNirvanaLogo

call hidePreLevel

;draw texts
ld hl,s_NIRVANALOGO_small
ld bc,smallFont
call PRINTSTRING

ld hl,s_NIRVANALOGO_big
ld bc,bigFont
call PRINTSTRING

call putLogoAttr

ld a,9
call AFXPLAY
call startNIRVANA

ld b,120
SNL_pause

      halt
      push bc
      pop bc
      djnz SNL_pause

      call clearStage

      call stopNIRVANA
      ;call setup

ret

putLogoAttr

      ld d,9*8+8
      ld e,8
      ld hl,logoBytes

      ld b,14
      call putXLine

      ld d,11*8+8
      ld e,8
      ld hl,logoBytes+4

      ld b,18
      call putXLine

      ld d,12*8+8
      ld e,8
      ld hl,logoBytes+8

      ld b,18
      call putXLine

      ld d,13*8+8
      ld e,8
      ld hl,logoBytes+12

      ld b,16
      call putXLine

ret

logoBytes: defb 7,7,7+64,7+64
           defb 1+64,2+64,3+64,4+64
           defb 5+64,6+64,7+64,7
           defb 7,7,7+64,2+64
           
org 32768+4096
hero_right: include sprites\hero_right.asm
hero_left: include sprites\hero_left.asm
hero_ladder: include sprites\hero_ladder.asm
hero_phantom: include sprites\hero_phantom.asm
broken_bridge_sprite: include sprites\brokenBridge.asm
enemy_right: include sprites\enemy_right.asm
enemy_left: include sprites\enemy_left.asm
enemy_up: include sprites\enemyup.asm

pixelsAnimation    defw 00000
currentPixelsFrame defw 00000
pixelsPointer      defw 00000;16 bit pointer to current pixel

heroPos        defw 00000 ;2 bytes
heroAnimation  defw 00000 ;current hero animation address
heroMoveCount  defb 0 ;move count - move by 8 pixels
heroMoveDir    defb 0 ;move direction as always 1-left 2-right 3-down 4-up
heroLastXDir   defb 0 ;last x move dir
heroFireWas    defb 0 ;if fire was pressed

brokenBridgeDrawAdr defw 00000 ;where to draw broken bridge on screen
brokenBridgeFrame   defw 00000 ;broken bridge frame
phantomPos          defw 00000 ;phantom coords
phantomKind         defb 0 ;kind of phantom 0-horizontal 1-vertical
phantomCount        defb 0 ;phantom xor count for blinking

heroCellPos         defw 00000 ;cell position of hero body
phantomCellPos      defw 00000;cell position of phantom body
teleportPos         defw 00000 ;where to teleport position
heroState           defb 0 ;state of hero 0-normal 1-teleporting 2-dead 3-level complete
teleportDir         defb 0 ;teleporting direction

enemiesPointer      defw 00000 ;2 bytes pointer to current enemy

soundToPlay         defb 0 ;which sound play
stateCount          defb 0 ;game state change count

totalPixels         defb 0 ;total pixels
currentLevel        defb 0 ;current level

totalPhantoms       defb 0 ;number of phantoms for level

brokenBridgeCellCoords defw 00000;cell coord of broken bridge

heroPreDir             defb 0 ;pre hero dir
deadPointer            defw 00000 ;dead pointer
menuTicker             defb 0 ;ticker
menuCount              defb 0 ;count
phantomEnemyTicker     defb 0 ;phantom enemies ticker
preWorld               defb 0 ;previous world
lives                  defb 0 ;lives
defb 255

org 25000

phantomsNumbers: defb 7
                 defb 3,2,1,2,1,3,2,2,4,1
                 defb 0,3,3,3,3,1,1,4,4,2
                 defb 1,2,5,2,3,4,2,2,2,1
                 defb 0,0,0,0,1,0,0,0
        
levelsTable: defw level0
        defw level1,level2,level3,level4,level5,level6,level7,level8,level9,level10
        defw level11,level12,level13,level14,level15,level16,level17,level18,level19,level20
        defw level21,level22,level23,level24,level25,level26,level27,level28,level29,level30
        defw level31,level32,level33,level34,level35,level36,level37

level0: FILE levels\level0.pk
level1: FILE levels\level1.pk
level2: FILE levels\level2.pk
level3: FILE levels\level3.pk
level4: FILE levels\level4.pk
level5: FILE levels\level5.pk
level6: FILE levels\level6.pk
level7: FILE levels\level7.pk
level8: FILE levels\level8.pk
level9: FILE levels\level9.pk
level10: FILE levels\level10.pk
level11: FILE levels\level11.pk
level12: FILE levels\level12.pk
level13: FILE levels\level13.pk
level14: FILE levels\level14.pk
level15: FILE levels\level15.pk
level16: FILE levels\level16.pk
level17: FILE levels\level17.pk
level18: FILE levels\level18.pk
level19: FILE levels\level19.pk
level20: FILE levels\level20.pk
level21: FILE levels\level21.pk
level22: FILE levels\level22.pk
level23: FILE levels\level23.pk
level24: FILE levels\level24.pk
level25: FILE levels\level25.pk
level26: FILE levels\level26.pk
level27: FILE levels\level27.pk
level28: FILE levels\level28.pk
level29: FILE levels\level29.pk
level30: FILE levels\level30.pk
level31: FILE levels\level31.pk
level32: FILE levels\level32.pk
level33: FILE levels\level33.pk
level34: FILE levels\level34.pk
level35: FILE levels\level35.pk
level36: FILE levels\level36.pk
level37: FILE levels\level37.pk
        
;fonts
smallFont: FILE fonts/little.fzx
bigFont: FILE fonts/font11.fzx
