;-----------------------------------------------------------;
;                                                           ;
; Invaded                                                   ;
; Version 1.0                                               ;
; Screen Display Routines                                   ;
;                                                           ;
;-----------------------------------------------------------;

;------------------------------------------------
; loadLevel - Load a level and draw it and bottom bar
;
; Input:    A = Level to load
; Output:   None
;------------------------------------------------
loadLevel:
        ld      hl,(cmpPtr)
        ld      de,(tempMem)
        ld      ix,gbuf
        ld      b,a
        inc     b
        call    huffExtr                        ; Extract level to start of (tempMem)
        ld      de,(tempMem)                    ; DE => Start of level header
        inc     de                              ; DE => Number of enemies in this level
        ld      a,(de)                          ; A = Number of enemies in this level
        ld      (numEnemiesThisLevel),a         ; Save it for after
        dec     de                              ; DE => Length of level
        push    de
        ld      l,a
        ld      h,4
        bcall(_htimesl)                         ; HL = Offset to get past enemy data
        ex      (sp),hl                         ; HL => Start of level header, (SP) = Offset to get past enemy data
        ld      de,levelDataTable
        ld      bc,LEVEL_HEADER_LENGTH
        ldir                                    ; Load level header to storage
        push    hl
        ld      de,gbuf
        ld      bc,4*100
        ldir                                    ; Copy enemyIni data to gbuf
        pop     hl                              ; HL => Start of extracted enemyIni data
        pop     de
        add     hl,de                           ; HL => Start of tile data
        ld      de,(tempMem)
        push    de
        ld      bc,7*200
        ldir                                    ; Copy tile data to start of (tempMem)
        ld      (enemyIni),de                   ; DE => Where enemyIni data will soon be stored, so save pointer
        ld      hl,gbuf                         ; HL => Start of enemyIni data
        ld      bc,4*100
        ldir                                    ; Append enemyIni data to end of tile data
        bcall(_grbufclr)
        ld      a,(guardianSizeX)
        inc     a
        add     a,a
        add     a,a
        add     a,a
        ld      (guardianSizeX),a
        ld      a,(guardianSizeY)
        inc     a
        add     a,a
        add     a,a
        add     a,a
        ld      (guardianSizeY),a
        ld      hl,(xBlock)
        ld      h,7
        bcall(_htimesl)
        pop     de                              ; DE => Start of level data
        add     hl,de                           ; HL => Start of data to draw
; Now, draw level
        xor     a
drawLevelNextX:
        ld      (_drawLevelX),a
        xor     a
drawLevelNextY:
        ld      (_drawLevelY),a
        ld      a,(hl)                          ; A = Tile to draw
        push    hl
        ld      l,a
        ld      h,0
        add     hl,hl
        add     hl,hl
        add     hl,hl                           ; HL = Offset to tile in Tileset
        ld      de,(tileData)
        add     hl,de                           ; HL => Sprite data
        push    hl
        pop     ix                              ; IX => Sprite data
        ld      b,8                             ; B = 8 rows to draw
        ld      a,0                             ; A = XCoord to draw at
_drawLevelX             = $-1
        ld      l,0                             ; L = YCoord to draw at
_drawLevelY             = $-1
        call    ionPutSprite                    ; Draw sprite
        pop     hl
        inc     hl                              ; HL => Next tile to draw
        ld      a,(_drawLevelY)
        add     a,8
        cp      7*8                             ; Have we drawn 7 rows?
        jr      c,drawLevelNextY                ; If not, draw another one!
        ld      a,(_drawLevelX)
        add     a,8
        cp      12*8                            ; Have we draw 12 columns?
        jr      c,drawLevelNextX                ; If not, draw another one
; Now, fill bottom of playing screen
        ld      hl,gbuf+(56*12)
        ld      de,gbuf+(56*12)+1
        ld      b,8
        ld      a,$55
fillBottomScreen:
        push    bc
        ld      bc,11
        ld      (hl),a
        ldir
        inc     hl
        inc     de
        rrca
        pop     bc
        djnz    fillBottomScreen
; Show "S:" & "B:"
        ld      de,57*256+23
        ld      hl,strScore
        call    vPuts
        ld      de,57*256+63
        call    vPuts
; Show score
        call    showScore
; Clear box to show beam power
        call    clearBeamBox
; Draw lives left
showLives:
        ld      a,(lives)
        or      a
        ret     z                               ; If no ships to draw, leave
        ld      c,a
        ld      b,0
        ld      a,64
        call    modifyASCR83
drawLivesLoop:
        push    bc
        ld      c,56
        ld      hl,sprLife
        ld      de,playerBG
        call    PutSprite_MSB
        pop     bc
        inc     b
        inc     b
        inc     b
        inc     b
        dec     c
        jr      nz,drawLivesLoop
        ld      a,56
modifyASCR83:
        ld      (_bottomClip1),a
        dec     a
        ld      (_bottomClip2),a
        ld      (_bottomClip3),a
        ret

;------------------------------------------------
; scrollScreen - Scroll the screen
;
; Input:    None
; Output:   None
;------------------------------------------------
scrollScreen:
        ld      a,(xBlock)
        add     a,12
        ld      hl,levelLength
        cp      (hl)                            ; Are we at the end of the level?
        jp      nc,iniGuardian                  ; If so, try to initialise end-of-level boss
        ld      a,(dead)
        or      a                               ; Is player dead?
        jr      z,sNormalMoveRight              ; If not, do normal moveRight routine
        ld      hl,(x)                          ; Otherwise, move right regardless of what is there
        inc     hl
        ld      (x),hl
        jr      sAfterCheckLeft
sNormalMoveRight:
        call    moveRight                       ; Try to move player right
        jr      nc,sAfterCheckLeft              ; If successful, don't check to see if player is off left side
        call    getPlayerScreenX
        or      a
        jr      nz,sAfterCheckLeft
        ld      a,INI_DEAD
        ld      (dead),a
        ret
sAfterCheckLeft:
        ld      a,1
        ld      (scrolled),a
; Scroll current video mem contents to the left one bit
        ld      hl,gbuf+(56*12)-1               ; HL => End of block of video mem to scroll
        ld      c,64-8                          ; C = Number of rows to scroll
scrollLoop1:
        ld      b,3                             ; Repeat this part 3 times
        or      a                               ; Clear carry
scrollLoop2:
        rl      (hl)
        dec     hl
        rl      (hl)
        dec     hl
        rl      (hl)
        dec     hl
        rl      (hl)
        dec     hl
        djnz    scrollLoop2
        dec     c
        jr      nz,scrollLoop1
        ld      hl,(xScr)
        inc     hl
        ld      (xScr),hl
        ld      a,l
        ld      hl,xBlock
        and     $07
        jr      z,sIncXBlock
        scf
        jr      sGetRightBlock
sIncXBlock:
        inc     (hl)
sGetRightBlock:
        ld      a,(hl)
        adc     a,11
        ld      h,7
        ld      l,a
        bcall(_htimesl)
        ld      de,(tempMem)
        add     hl,de                           ; HL => Column in level data to draw
        di                                      ; Disable interrupts so we can use IY
        push    iy                              ; Save IY (because it's needed)
        push    hl
        pop     iy                              ; IY => Column in level data to draw
        ld      a,(xScr)
        and     $07
        ld      hl,pixelTable
        ld      d,0
        ld      e,a
        add     hl,de
        ld      d,(hl)                          ; D = Bitmask
        ld      c,7                             ; C = 7 tiles to put
        ld      ix,gbuf+11                      ; IX = Top row, right-hand column in video memory
scrollDrawLoop:
        push    de
        ld      l,(iy)
        inc     iy
        ld      h,0
        add     hl,hl
        add     hl,hl
        add     hl,hl
        ld      de,(tileData)
        add     hl,de                           ; HL => Sprite data
        pop     de
        ld      b,8                             ; B = 8 bits to check
scrollDoTile:
        ld      a,(hl)
        inc     hl
        and     d
        jr      z,scrollNextTile
        set     0,(ix)
scrollNextTile:
        push    de
        ld      de,12
        add     ix,de
        pop     de
        djnz    scrollDoTile
        dec     c
        jr      nz,scrollDrawLoop
        pop     iy                              ; Restore IY
        ei                                      ; We can put interrupts back on now :)
        ret
iniGuardian:
        ld      hl,guardian
        ld      a,(hl)
        or      a
        ret     nz
        ld      (hl),1
        ld      a,(gClearScreen)
        or      a
        ret     z
        ld      hl,gbuf                         ; Clear screen
        ld      de,gbuf+1
        ld      bc,56*12-1
        ld      (hl),0
        ldir
        ld      hl,(xBlock)
        ld      h,7
        bcall(_htimesl)
        ld      de,(tempMem)
        add     hl,de                           ; HL => Start of screen in level data
        ld      d,h
        ld      e,l
        inc     de
        ld      bc,7*12
        ld      (hl),0
        ldir
        ret

;------------------------------------------------
; clearBeamBox - Clear box in bottom-right to show beam power
;
; Input:    None
; Output:   None
;------------------------------------------------
clearBeamBox:
        ld      hl,gbuf+(57*12)+9
        ld      b,6
        ld      de,11
        xor     a
clearBeamBoxLoop:
        ld      (hl),a
        inc     hl
        ld      (hl),a
        add     hl,de
        djnz    clearBeamBoxLoop
        ret

;------------------------------------------------
; showBeamPower - Show beam power at bottom-right of screen
;
; Input:    None
; Output:   None
;------------------------------------------------
showBeamPower:
        call    clearBeamBox
        ld      a,(beam)
        srl     a
        srl     a
        or      a
        ret     z                               ; If no beam power, leave
        ld      b,a
        ld      c,72
showBeamLoop:
        push    bc
        ld      a,c
        ld      e,60
        call    ionGetPixel
        or      (hl)
        ld      (hl),a
        ld      de,12
        add     hl,de
        ld      (hl),a
        pop     bc
        inc     c
        djnz    showBeamLoop
        ret

.end
