;;;;;;;;;;;;;-------LICENSE NOTICE-----------;;;;;;;;;;;;;;;
;; MIT License

;; Copyright (c) 2021 DreamyZombies Studio

;; Permission is hereby granted, free of charge, to any person obtaining a copy
;; of this software and associated documentation files (the "Software"), to deal
;; in the Software without restriction, including without limitation the rights
;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
;; copies of the Software, and to permit persons to whom the Software is
;; furnished to do so, subject to the following conditions:

;; The above copyright notice and this permission notice shall be included in all
;; copies or substantial portions of the Software.

;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;; SOFTWARE.
;;
;; Authors:
;;  Abderrahamane Guermat Benaouali (agb139@alu.ua.es)
;;  Jorge Angulo Espí (jae17@alu.ua.es)
;;  Sami Hadj-Djilani (sh101@alu.ua.es)


;;
;; RENDER SYSTEM
;;

.include "cpctelera.h.s"
.include "../cpct_functions.h.s"
.include "../man/player.h.s"
.include "../man/input.h.s"

.globl _sprite_palette
.globl _sprite_tileset_00
.globl _sprite_hero1
.globl _sprite_hero2
.globl _world1_pack_end
.globl _world2_pack_end
.globl _world3_pack_end
.globl _lobby3_pack_end
.globl _lobby0_pack_end
.globl _lobby1_pack_end
.globl _lobby2_pack_end
.globl _sprite_hero1_d
.globl _sprite_hero2_d
.globl _sprite_hero1_j
.globl _sprite_hero2_j
.globl _sprite_hero1_r
.globl _sprite_hero2_r
.globl _main
.globl _menu_pack_end
.globl _credits1_pack_end
.globl _credits2_pack_end
.globl _controls1_pack_end
.globl _controls2_pack_end
.globl _w3_pack_end
.globl _w2_pack_end
.globl _w1_pack_end
.globl _completed_w_pack_end
.globl _completed_l_pack_end
.globl _end_pack_end

;; WORLD BUFFER
decompress_buffer == 0x0040
levelsize == 0x1F4
levelmaxsize = 0x1388
;;0x13C8
decompress_buffer_end == decompress_buffer + levelmaxsize - 1

;; LOBBY BUFFER
decompress_buffer_lobby == 0x13C8
lobbymaxsize = 0x1F4
;; 0x15BC
decompress_buffer_end_lobby == decompress_buffer_lobby + lobbymaxsize - 1

;; FIRST MAP TO LOAD, LOBBY0
map_ptr:: .dw #decompress_buffer_lobby

_player_last_x:: .db 0
_player_last_y:: .db 0
    
renderSys_init::
    
    ;; Video settings
    ld  c, #2
    call cpct_setVideoMode_asm
    
    ld  hl, #_sprite_palette
    ld  de, #2
    call cpct_setPalette_asm
    cpctm_setBorder_asm HW_BLACK

    ;; Hero
    ld a, #13
    ld (_player_last_x), a
    ld a, #20
    ld (_player_last_y), a
    
    ret
    
renderSys_white::

    cpctm_setBorder_asm HW_BRIGHT_WHITE

    ret

renderSys_remove_hero::
    
   
    ld   de, #0xC000
    ld a, (_player_last_y)
    ld b, a
    ld a, (_player_last_x)
    ld c, a

    call cpct_getScreenPtr_asm
    
    ex   de, hl
    ld   a, #0x00
    ld   c,  #2     ;; width adapted to mode 2
    ld   b,  #8     ;; heigth in bytes
    call cpct_drawSolidBox_asm

    ret
    
;;  INPUT:
;;     IX: Pointer to first entity to render.
;;      A: Number of entities to render.
renderSys_update::
    
    ;; REMOVE HERO
    call renderSys_remove_hero

    ;; PRINT HERO
    push af
    push IX
    call entityman_getHero_pos
    call render_hero
    pop IX
    pop af

    ret
    
    ;;  INPUT:
    ;;     IX: Pointer to hero.
render_hero:
    
    ld  de, #0xC000
    ld   c, 0(ix)
    ld   b, 1(ix)

    ld a, b
    ld (_player_last_y), a
    ld a, c
    ld (_player_last_x), a

    call cpct_getScreenPtr_asm
    
    ex  de, hl
    ld  bc, #0x0802

    ld a, 6(ix)
    dec a
    jp z, draw_left

    ;; Player left direction
    ;; Check if jumping
    ld a, (_isJumping)
    sub a, #1
    jp z, jumpingR

    ;; Not jumping right
    ld a, (_SpriteOrder)
    sub a, #1
    jp z, order0L
    ld hl, #_sprite_hero1
    jp  draw

    order0L:
        ld hl, #_sprite_hero1_r
        jp  draw


    ;; Jumping right
    jumpingR:
        ld hl, #_sprite_hero1_j
        jp draw

draw_left:
    
    ;; Player right direction
    ;; Check if jumping
    ld a, (_isJumping)
    sub a, #1
    jp z, jumpingL

    ;; Not jumping left
    ld a, (_SpriteOrder)
    sub a, #1
    jp z, order0R
    ld hl, #_sprite_hero2
    jp  draw

    order0R:
        ld hl, #_sprite_hero2_r
        jp  draw

    ;; Jumping left
    jumpingL:
        ld hl, #_sprite_hero2_j

draw:

    call cpct_drawSprite_asm
    ret

render_death::

    ld  de, #0xC000
    ld   c, 0(ix)
    ld   b, 1(ix)

    ld a, b
    ld (_player_last_y), a
    ld a, c
    ld (_player_last_x), a

    call cpct_getScreenPtr_asm
    
    ex  de, hl
    ld  bc, #0x0802

    ld a, 6(ix)
    dec a
    jp z, draw_left_death

    ;; Player left direction
    ld hl, #_sprite_hero1_d
    jp  draw_death

draw_left_death:

    ;; Player right direction
    ld hl, #_sprite_hero2_d

draw_death:

    call cpct_drawSprite_asm
    ret


;;  INPUT:
;;     A: lobby to set { 0, 1, 2}
;;     lobby 0 by default
render_set_lobby::

    ld b, a
    sub a, #1
    jp z, set_lobby1

    ld a, b
    sub a, #2
    jp z, set_lobby2

    ld a, b
    sub a, #3
    jp z, set_lobby3

    ;; LOBBY 0
        ld hl, #_lobby0_pack_end
        jp process_lobby

    ;; LOBBY 1
    set_lobby1:
        ld hl, #_lobby1_pack_end
        jp process_lobby

    ;; LOBBY 2
    set_lobby2:
        ld hl, #_lobby2_pack_end
        jp process_lobby

    set_lobby3:
        ld hl, #_lobby3_pack_end

process_lobby:

    ;; Process lobby
    ld de, #decompress_buffer_end_lobby
    call cpct_zx7b_decrunch_s_asm
    
    ;; Updating map_ptr to first lvl
    ld hl, #decompress_buffer_lobby
    ld (map_ptr), hl

    ret

    ;;  INPUT:
    ;;     A: World to set { 0, 1, 2}
render_set_world::
        
    ld b, a
    sub a, #1
    jp z, set_world1

    ld a, b
    sub a, #2
    jp z, set_world2

    ;; WORLD 0
        ld hl, #_world1_pack_end
        jp process_world

    ;; WORLD 1
    set_world1:
        ld hl, #_world2_pack_end
        jp process_world

    ;; WORLD 2
    set_world2:
        ld hl, #_world3_pack_end

process_world:

    ;; Decompressing world
    ld de, #decompress_buffer_end
    call cpct_zx7b_decrunch_s_asm

    ;; Updating map_ptr to first lvl
    ld hl, #decompress_buffer
    ld (map_ptr), hl

    ret
    
render_levelup::

    ld de, (map_ptr)
    ld hl, #levelsize
    add hl, de
    ld (map_ptr), hl

    ret

render_level::

    call renderSys_remove_hero 
    ld de, (map_ptr)
    call render_tilemap

    ret

    ;;  INPUT:
    ;;     A: Lobby to set (just for the string name) { 0, 1, 2}
render_lobby::

    call renderSys_remove_hero 
    ld de, (map_ptr)
    call render_tilemap

    ret

render_tilemap:
    
    push de
        
    ld b, #25
    ld c, #20
    ld de, #20
    ld hl, #_sprite_tileset_00
    call cpct_etm_setDrawTilemap4x8_ag_asm
    
    pop de
    ld hl, #0xC000
    call cpct_etm_drawTilemap4x8_ag_asm
    
    ret

loadMenu::

    ld hl, #_menu_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

loop_opc:

    call cpct_scanKeyboard_asm

    ld  hl, #Key_1 
    call cpct_isKeyPressed_asm
    ret nz

    ld  hl, #Key_2
    call cpct_isKeyPressed_asm
    jp  nz, renderControls

    ld  hl, #Key_3
    call cpct_isKeyPressed_asm
    jp  nz, renderCredits

    ld  hl, #Key_4
    call cpct_isKeyPressed_asm
    jp  nz, exit
    
    jp loop_opc

renderCredits:

    ld hl, #_credits1_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ld de, #0x0500

loop_cr:
    
    push  de

    call cpct_scanKeyboard_asm

    call cpct_isAnyKeyPressed_asm
    pop de
    jp nz, loadMenu

    dec de
    ld a, d
    or e
    jp nz, loop_cr

    ld hl, #_credits2_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ld de, #0x0500

loop_cr2:

    push  de

    call cpct_scanKeyboard_asm

    call cpct_isAnyKeyPressed_asm
    pop de
    jp nz, loadMenu


    dec de
    ld a, d
    or e
    jp nz, loop_cr2

    jp renderCredits

renderControls:


    ld hl, #_controls1_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ld de, #0x0500

loop_con:

    push  de

    call cpct_scanKeyboard_asm

    call cpct_isAnyKeyPressed_asm
    pop de
    jp nz, loadMenu


    dec de
    ld a, d
    or e
    jp nz, loop_con

    
    ld hl, #_controls2_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ld de, #0x0500

loop_con2:

    push  de

    call cpct_scanKeyboard_asm

    call cpct_isAnyKeyPressed_asm
    pop de
    jp nz, loadMenu

    dec de
    ld a, d
    or e
    jp nz, loop_con2

    jp renderControls

exit:

    or a
    ld a, #1
    sub #1
    ret

empty_background:

    ld hl, #0xC000
    ld de, #0xC001
    ld bc, #0x4000-1
    ld (hl), #0
    ldir

    ret

load_screen::

    ld hl, #_completed_l_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ret

load_lvl10_screen::

    ld hl, #_completed_w_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ret

load_start_screen::

    cp a, #2
    jp z, screen_world3

    cp a, #1
    jp z, screen_world2

    ld hl, #_w1_pack_end
    jp render_world_screen

screen_world3:
    ld hl, #_w3_pack_end
    jp render_world_screen

screen_world2:
    ld hl, #_w2_pack_end

render_world_screen:
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm
    ret

render_end_screen::
    ld hl, #_end_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm
    ret
