.include "game.h.s"
.include "entity_templates.h.s"
.include "entity.h.s"
.include "sys/animations.h.s"
.include "sys/render.h.s"
.include "sys/physics.h.s"
.include "sys/ia.h.s"
.include "sys/collision.h.s"
.include "cpctelera.h.s"
.include "keyboard/keyboard.h.s"
.include "spawner.h.s"
.include "hud.h.s"
.include "compress/menu_pack.h.s"
.include "compress/ronda_pack.h.s"
.include "compress/gameover_pack.h.s"
.include "compress/win_pack.h.s"

.globl _menu
.globl _ingame
.globl _ronda
.globl _vida1
.globl _gameover1
.globl _win
.globl cpct_isAnyKeyPressed_f_asm
.globl cpct_scanKeyboard_f_asm
.globl key_actions
.globl key_actions2

registLow: .db 0x00
registHig: .db 0x00

bool_disparo:  .db #0x00
bool_muerte:   .db #0x00
bool_vida:     .db #0x00
bool_arcoiris: .db #0x00

uncontador: .db 06
int_handler:
    push af
    push bc
    push de
    push hl

    ld a, (uncontador)
    dec a
    jp nz, cont
        call cpct_akp_musicPlay_asm

        ld a, (bool_disparo)
        cp #1
        jr nz, nodisparo
            push af
            push de
            push hl
            push bc
            push ix
            
            ld de, #_vida1
            call cpct_akp_SFXInit_asm

            ;call cpct_akp_SFXGetInstrument_asm

            ;L -> sfx_num 
            ld l, #1
            ;H -> volume 0-15
            ld h, #15
            ;E -> note 0-143
            ld e, #40
            ;D -> speed 0=original 1-255 fastest
            ld d, #0
            ;BC -> pitch 0=no pitch 
            ld bc, #0x0000
            ;A -> bitmask channel
            ld a, #10

            call cpct_akp_SFXPlay_asm

            ld a, #0x00
            ld (bool_disparo), a
            
            pop ix
            pop bc
            pop hl
            pop de
            pop af
        nodisparo:

        ld a, (bool_muerte)
        cp #1
        jr nz, nomuerte
            push af
            push de
            push hl
            push bc
            push ix
            
            ld de, #_vida1
            call cpct_akp_SFXInit_asm

            ;call cpct_akp_SFXGetInstrument_asm

            ;L -> sfx_num 
            ld l, #1
            ;H -> volume 0-15
            ld h, #15
            ;E -> note 0-143
            ld e, #10
            ;D -> speed 0=original 1-255 fastest
            ld d, #0
            ;BC -> pitch 0=no pitch 
            ld bc, #0x00F0
            ;A -> bitmask channel
            ld a, #10

            call cpct_akp_SFXPlay_asm

            ld a, #0x00
            ld (bool_muerte), a
            
            pop ix
            pop bc
            pop hl
            pop de
            pop af
        nomuerte:

        ld a, (bool_vida)
        cp #1
        jr nz, novida
            push af
            push de
            push hl
            push bc
            push ix
            
            ld de, #_vida1
            call cpct_akp_SFXInit_asm

            ;call cpct_akp_SFXGetInstrument_asm

            ;L -> sfx_num 
            ld l, #1
            ;H -> volume 0-15
            ld h, #15
            ;E -> note 0-143
            ld e, #60
            ;D -> speed 0=original 1-255 fastest
            ld d, #0
            ;BC -> pitch 0=no pitch 
            ld bc, #0x0000
            ;A -> bitmask channel
            ld a, #10

            call cpct_akp_SFXPlay_asm

            ld a, #0x00
            ld (bool_vida), a
            
            pop ix
            pop bc
            pop hl
            pop de
            pop af
        novida:

        ld a, (bool_arcoiris)
        cp #1
        jr nz, noarcoiris
            push af
            push de
            push hl
            push bc
            push ix
            
            ld de, #_vida1
            call cpct_akp_SFXInit_asm

            ;call cpct_akp_SFXGetInstrument_asm

            ;L -> sfx_num 
            ld l, #1
            ;H -> volume 0-15
            ld h, #15
            ;E -> note 0-143
            ld e, #75
            ;D -> speed 0=original 1-255 fastest
            ld d, #0
            ;BC -> pitch 0=no pitch 
            ld bc, #0x0000
            ;A -> bitmask channel
            ld a, #10

            call cpct_akp_SFXPlay_asm

            ld a, #0x00
            ld (bool_arcoiris), a
            
            pop ix
            pop bc
            pop hl
            pop de
            pop af
        noarcoiris:
        ld a, #6
    cont:
    ld (uncontador), a

    ld h, a
    ld l, #16
    ;call cpct_setPALColour_asm



    pop hl
    pop de
    pop bc
    pop af
    

    ei
reti


set_int_handler:
    ld hl, #0x38
    ld (hl), #0xC3
    inc hl
    ld (hl), #<int_handler
    inc hl
    ld (hl), #>int_handler
    inc hl
    ld (hl), #0xC9
ret

registro_aux_ix: .db 0x0000 ;; registro auxiliar

bool_multijugador: .db 0x00 ;; 0->SINGLE 1->MULTI

;; Cuando valga 1 (true), GAME OVER ==>  InGAME cambia de estado
bool_game_over: .db 0x00 
;; Contador de tiempo para ver la animacion del gameOver
cont_game_over: .db 0x00

;; Cuando valga 1 (true), se ha terminado el juego ==>  InGAME cambia de estado
bool_final_juego: .db 0x00 

;; Cuando valga 1 (true), se ha terminado una ronda
bool_final_ronda: .db 0x00 

;; Contador que nos dice cuantos enemigos hemos matado (se debe resetear en cada ronda)
cont_bajas_enemigos: .db 0x00

;; Contador que nos dice en que ronda estamos (empieza en ronda 1)
cont_rondas: .db 0x01



;; Numero total de rondas en el juego
k_max_num_rondas = 9

;; Puntero al array que nos dice cuantos enemigos hay en cada ronda
ptr_num_enemigos_por_ronda: .dw tabla_num_enemigos_por_ronda

tabla_num_enemigos_por_ronda:
    .db #0x08   ;; ronda 1
    .db #0x0E   ;; ronda 2 => 11
    .db #0x15   ;; ronda 3 => 21
    .db #0x19   ;; ronda 4 => 25
    .db #0x0F   ;; ronda 5 => 15
    .db #0x10   ;; ronda 6 => 16
    .db #0x10   ;; ronda 7 => 16
    .db #0x16   ;; ronda 8 => 22
    .db #0x0B   ;; ronda 9 => 11



;; ===============================
;; CREA UNA ENTIDAD CON UN TEMPLATE
;; Input: DE --> template que queremos
;; Output: HL -->Entidad Creada
;;         IX -->Entidad Creada
;; ===============================
game_create_template:
    call entity_create
    ;; de tiene la template y hl la entidad creada, hay que intercambiarlas
    ex de, hl
    call entity_copy
ret

;; ===============================
;; INICIALIZA EL JUEGO
;; ===============================
game_init:
    
    ;; color de los textos
    ld l, #15  ;; color letra
    ld h, #0  ;; color fondo
    call cpct_setDrawCharM0_asm

    call render_init;; inicializamos pantalla

    ;;Creamos entidades iniciales
    ;; Crear al Jugador
    ld de, #player1
    call game_create_template



ret 


;; ===============================
;; INICIA ESTADO DE MENU
;; ===============================
string_menu_titulo:        .ascii 'CASTLE KID '
                           .ascii '\0'

string_menu_singleplayer: .ascii '1. Singleplayer'
                          .ascii '\0'

string_menu_multiplayer:  .ascii '2. Multiplayer'
                          .ascii '\0'

string_menu_options:      .ascii '3. Define Controls'
                          .ascii '\0'

game_menu:
    ;; color letras
    ld l, #15  ;; color letra
    ld h, #0  ;; color fondo
    call cpct_setDrawCharM0_asm

   
    ;cpctm_clearScreen_asm #0x00 
    ;;pinto fondo menu
    ld hl, #_menu_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ;; SINGLEPLAYER (le sumo F0 = 50+50+50 (X la primera, Y = 3 lineas de caracteres mas abajo))
    ld iy, #string_menu_singleplayer
    ld hl, #0xC324	
    call  cpct_drawStringM0_asm

    ;; MULTIPLAYER (X,la primera y Y = 190 = F0 + 50 + 50 = F0 + A0, 2 lineas de caracteres mas abajo)
    ld iy, #string_menu_multiplayer
    ld hl, #0xC3C4
    call  cpct_drawStringM0_asm

    ;; CONTROLS (X,la primera y Y = 190 = F0 + 50 + 50 = F0 + A0, 2 lineas de caracteres mas abajo)
    ld iy, #string_menu_options
    ld hl, #0xC464
    call  cpct_drawStringM0_asm

    ld de, #_menu
    call cpct_akp_musicInit_asm

    loop_menu:
        ;call cpct_waitVSYNC_asm
        ;call cpct_akp_musicPlay_asm
        ;; Comprueba el teclado
        call cpct_scanKeyboard_asm 

        ;; Comprobamos singleplayer
        ld hl, #Key_1
        call cpct_isKeyPressed_asm
        jr nz, jugar_singleplayer

        ;; Comprobamos multiplayer
        ld hl, #Key_2
        call cpct_isKeyPressed_asm
        jr nz, jugar_multiplayer

        ;; Compronamos controls P1
        ld hl, #Key_3
        call cpct_isKeyPressed_asm
        jp nz, controles1  

    jr loop_menu

    opciones2:
        call game_opciones2
    ret

    controles1:
        call game_opciones
ret

jugar_singleplayer:
    ld a, #0
    ld (bool_multijugador), a
    ;call cpct_akp_stop_asm
    ;; Si no hay player, lo creamos en la primera posicion
    ;; Para eso, borramos todas las entidades que haya para borrar con entity_update
    call entity_update

    ld ix, #entity_vector  

    ;; Comprobamos si hay player
    ld a, e_tipo(ix)
    cp #e_type_player
    jr z, no_creo_player1
        ld de, #player1
        call game_create_template
    no_creo_player1:  

ret

jugar_multiplayer:
    ld a, #1
    ld (bool_multijugador), a
    ;; Si no hay player, lo creamos en la primera posicion
    ;; Para eso, borramos todas las entidades que haya para borrar con entity_update
    call entity_update

    ld ix, #entity_vector  
    ;; Comprobamos si hay player
    ld a, e_tipo(ix)
    cp #e_type_player
    jr z, ya_hay_player_1
        ;; No hay player 1 --> lo creamos
        ld de, #player1
        call game_create_template
    ya_hay_player_1:

    ;; Comprobamos si hay player 2
    call getEntity2 ;; IX => 2a entidad
    ld a, e_tipo(ix)
    cp #e_type_player
    jr z, ya_hay_player_2
        ;; No hay player 1 --> lo creamos
        ld de, #player2
        call game_create_template
    ya_hay_player_2:
ret

cont_vueltas: .db -0x01
cont_vueltas2: .db -0x01

key_table:
    .dw 0x0100
    .dw 0x0101
    .dw 0x0102
    .dw 0x0103
    .dw 0x0104
    .dw 0x0105
    .dw 0x0106
    .dw 0x0107
    .dw 0x0108
    .dw 0x0109

    .dw 0x0000

ptr_key :               .dw key_table-2
ptr_keyAction_phisics:  .dw key_actions
ptr_string_key :        .dw tabla_strings

tabla_strings:
    .dw string_move_right_p1
    .dw string_move_left_p1
    .dw string_move_up_p1
    .dw string_move_down_p1
    .dw string_shoot_p1
    .dw 0x000 ;;--> hay que ponerle un tope para que cuando llegue cambie a PLAYER 2 o para que vuelva a empezar desde arriba


ptr_key2:               .dw key_table-2
ptr_string_key2:        .dw tabla_strings2
ptr_keyAction_phisics2:  .dw key_actions2
tabla_strings2:
    .dw string_move_right_p2
    .dw string_move_left_p2
    .dw string_move_up_p2
    .dw string_move_down_p2
    .dw string_shoot_p2
    .dw 0x000


;; Player 1
string_move_right_p1:   .ascii 'Right Player1'
                        .ascii '\0'

string_move_left_p1:    .ascii 'Left Player1'
                        .ascii '\0'

string_move_up_p1:      .ascii 'Up Player1'
                        .ascii '\0'

string_move_down_p1:    .ascii 'Down Player1'
                        .ascii '\0'

string_shoot_p1:        .ascii 'Shoot Player1'
                        .ascii '\0'

;; Player 2
string_move_right_p2:   .ascii 'Right Player2'
                        .ascii '\0'

string_move_left_p2:    .ascii 'Left Player2'
                        .ascii '\0'

string_move_up_p2:      .ascii 'Up Player2'
                        .ascii '\0'

string_move_down_p2:    .ascii 'Down Player2'
                        .ascii '\0'

string_shoot_p2:        .ascii 'Shoot Player2'
                        .ascii '\0'

;; ===============================
;; INICIA ESTADO DE CONTROLES
;; ===============================
game_opciones:
    ;cpctm_clearScreen_asm #0x00
    ;;pinto fondo menu
    ld hl, #_menu_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    okay:
    ;;  Control X
    ld hl, (ptr_string_key) ;; HL = Dir_memoria_tabla_strings
    ld e, (hl)  ;;
    inc hl      ;;       
    ld d, (hl)  ;;  DE = dir_memoria_string
    ld h, d
    ld l, e     ;; HL = dir_memoria_string

    ld (registro_aux_ix), hl
    ld iy, (registro_aux_ix)
    ld hl, #0xC3D0	
    call  cpct_drawStringM0_asm

    loop_opciones:
        ;; Comprueba el teclado
        call cpct_isAnyKeyPressed_f_asm
        push af
        call cpct_scanKeyboard_f_asm 
        pop af
        cp #0
        jr nz, loop_opciones
        ;; Una vez nos hemos asegurado de que no hay nada presionado, volvemos a escanear

        ;; Escaneamos hasta que se presione una tecla
        volverSegunda:
            call cpct_isAnyKeyPressed_f_asm
            call cpct_scanKeyboard_f_asm
            cp #0
        jr z, volverSegunda
        

        iteracion2_ptr:
        ld a, (cont_vueltas)
        inc a
        ld (cont_vueltas), a

        ld hl, #ptr_key     ;; al principio HL => 1a key-2 de la tabla
        inc (hl)            ;; esto actualiza HL = HL + 2
        inc (hl)            ;; 
        ;ld (ptr_key), bc   ;; \

        ;; HL = keytable(i)
        ld hl, (ptr_key)    ;; HL => Direccion de key_table(i)

        ld e, (hl)  ;; //                   
        inc hl      ;; || DE = Key_table(i)             
        ld d, (hl)  ;; \\ 
        ld h, d
        ld l, e     ;; HL = DE

        ;; Comprobamos si hemos llegado al final de las comprobaciones
        ld a, h
        cp #0
        jr nz, seguimooos
            ;; Comprobamos el bit alto
            ld a, l
            cp #0
            jr nz, seguimooos
                aqui_Acabo:
                push ix
                ld ix, #key_table-2
                ld (ptr_key), ix
                pop ix

                ld a, #-0x01
                ld (cont_vueltas), a

                jr loop_opciones
        seguimooos:

        ld c, #8

        jr primera_vez_keys
        actualiza_HL:
            
            add hl, hl ;; hl=hl*2
            ld a, (cont_vueltas)  ;
            ld d, #00
            ld e, a 
            sbc hl, de             ;
            ;; Miramos a ver si hemos comprobado ya las 7
            dec c
            ld a, c
            cp #0
            jr z, iteracion2_ptr

            primera_vez_keys:
            push hl
            push bc
            ;call waitKeyPressed
            call cpct_isKeyPressed_asm ;; Destroys A, B, HL, C
            pop bc
            pop hl
            jr z, actualiza_HL
                ;; Encontramos el KeyCode asociado a la tecla pulsada
                ;; Ahora tenemos que actualizar la tabla de Inputs
                encontrado:
                ld a, l
                ld (registLow), a
                ld a, h
                ld (registHig), a
                ld ix, (ptr_keyAction_phisics)
                ld a, (registHig)
                ld 1(ix), a
                ld a, (registLow)
                ld 0(ix), a

                ;; Actualizamos el puntero  de la tabla a la siguiente
                ld hl, #ptr_keyAction_phisics
                inc (hl)            
                inc (hl) 
                inc (hl) 
                inc (hl) 

                ld hl, #ptr_string_key
                inc (hl)
                inc (hl)

                ;; if (hl == 0)
                ld e, (hl)  ;; //                   
                inc hl      ;; || DE = Key_table(i)             
                ld d, (hl)  ;; \\ 
                ld h, d
                ld l, e     ;; HL = DE

                ld a, (hl)
                ld d, a
                inc hl
                ld a, (hl)
                or d
                cp #0
                jp nz, game_opciones
                    ;; Final de los string y tabla ==> reset punteros
                    ld hl, #tabla_strings
                    ld (ptr_string_key), hl
                    ld hl, #key_actions
                    ld (ptr_keyAction_phisics), hl
                    jr acaba_bucle

                ;jp game_opciones                

    jp z, loop_opciones
    
    acaba_bucle:
    ;; Una vez acabado el bucle, me voy al menu

    call game_opciones2
ret


game_opciones2:
    ;cpctm_clearScreen_asm #0x00
    ld hl, #_menu_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ;;  Control X
    ld hl, (ptr_string_key2) ;; HL = Dir_memoria_tabla_strings
    ld e, (hl)  ;;
    inc hl      ;;       
    ld d, (hl)  ;;  DE = dir_memoria_string
    ld h, d
    ld l, e     ;; HL = dir_memoria_string

    ld (registro_aux_ix), hl
    ld iy, (registro_aux_ix)
    ld hl, #0xC3D0	
    call  cpct_drawStringM0_asm

    loop_opciones2:
        ;; Comprueba el teclado
        call cpct_isAnyKeyPressed_f_asm
        push af
        call cpct_scanKeyboard_f_asm 
        pop af
        cp #0
        jr nz, loop_opciones2
        ;; Una vez nos hemos asegurado de que no hay nada presionado, volvemos a escanear

        ;; Escaneamos hasta que se presione una tecla
        volverSegunda2:
            call cpct_isAnyKeyPressed_f_asm
            call cpct_scanKeyboard_f_asm
            cp #0
        jr z, volverSegunda2
        

        iteracion2_ptr2:
        ld a, (cont_vueltas2)
        inc a
        ld (cont_vueltas2), a

        ld hl, #ptr_key2     ;; al principio HL => 1a key-2 de la tabla
        inc (hl)            ;; esto actualiza HL = HL + 2
        inc (hl)            ;; 
        ;ld (ptr_key), bc   ;; \

        ;; HL = keytable(i)
        ld hl, (ptr_key2)    ;; HL => Direccion de key_table(i)

        ld e, (hl)  ;; //                   
        inc hl      ;; || DE = Key_table(i)             
        ld d, (hl)  ;; \\ 
        ld h, d
        ld l, e     ;; HL = DE

        ;; Comprobamos si hemos llegado al final de las comprobaciones
        ld a, h
        cp #0
        jr nz, seguimooos2
            ;; Comprobamos el bit alto
            ld a, l
            cp #0
            jr nz, seguimooos2
                aqui_Acabo2:
                push ix
                ld ix, #key_table-2
                ld (ptr_key2), ix
                pop ix

                ld a, #-0x01
                ld (cont_vueltas2), a

                jr loop_opciones2
        seguimooos2:

        ld c, #8

        jr primera_vez_keys2
        actualiza_HL2:
            
            add hl, hl ;; hl=hl*2
            ld a, (cont_vueltas2)  ;
            ld d, #00
            ld e, a 
            sbc hl, de             ;
            ;; Miramos a ver si hemos comprobado ya las 7
            dec c
            ld a, c
            cp #0
            jr z, iteracion2_ptr2

            primera_vez_keys2:
            push hl
            push bc
            ;call waitKeyPressed
            call cpct_isKeyPressed_asm ;; Destroys A, B, HL, C
            pop bc
            pop hl
            jr z, actualiza_HL2
                ;; Encontramos el KeyCode asociado a la tecla pulsada
                ;; Ahora tenemos que actualizar la tabla de Inputs
                encontrado2:
                ld a, l
                ld (registLow), a
                ld a, h
                ld (registHig), a
                ld ix, (ptr_keyAction_phisics2)
                ld a, (registHig)
                ld 1(ix), a
                ld a, (registLow)
                ld 0(ix), a

                ;; Actualizamos el puntero  de la tabla a la siguiente
                ld hl, #ptr_keyAction_phisics2
                inc (hl)            
                inc (hl) 
                inc (hl) 
                inc (hl) 

                ld hl, #ptr_string_key2
                inc (hl)
                inc (hl)

                ;; if (hl == 0)
                ld e, (hl)  ;; //                   
                inc hl      ;; || DE = Key_table(i)             
                ld d, (hl)  ;; \\ 
                ld h, d
                ld l, e     ;; HL = DE

                ld a, (hl)
                ld d, a
                inc hl
                ld a, (hl)
                or d
                cp #0
                jp nz, game_opciones2
                    ;; Final de los string y tabla ==> reset punteros
                    ld hl, #tabla_strings2
                    ld (ptr_string_key2), hl
                    ld hl, #key_actions2
                    ld (ptr_keyAction_phisics2), hl
                    jr acaba_bucle2

                ;jp game_opciones                

    jp z, loop_opciones2
    
    acaba_bucle2:
    ;; Una vez acabado el bucle, me voy al menu
    call game_menu
ret



string_final_ronda: .ascii 'FINAL BOSS\0'
string_ronda: .ascii 'ROUND '
string_num_ronda:  .db #0x31 ;; el 31 es 1 en la tipografia  (32, es 2; 33 es 3...)
            .ascii '\0'



game_ronda:
    ld de, #_ronda
    call cpct_akp_musicInit_asm

    ld l, #15  ;; color letra
    ld h, #0  ;; color fondo
    call cpct_setDrawCharM0_asm

    ;cpctm_clearScreen_asm #0x00
    ;;pinto fondo menu
    ld hl, #_ronda_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ;; Ponemos texto RONDA X
    ld iy, #string_ronda
    ld a, (string_num_ronda)
    cp #0x39
    jr nz,no_final_round
        ;; Si estoy en la RONDA 9, ponemos el texto a FINAL BOSS
        ld iy, #string_final_ronda
    no_final_round:

    ld hl, #0xC3DA	
    call  cpct_drawStringM0_asm

    ;; Esperamos MAL CON HALTS
    ld e, #60
    call main_espera


    ld a, #0
    ld (bool_final_ronda), a
    ld (cont_bajas_enemigos), a

    ;; Eliminamos todas las entidades menos el player 
    call reset_datos

    ;; Elegimos tilemap segun ronda
    call descomprime_tilemap

    
    ld de, #_ingame
    call cpct_akp_musicInit_asm

ret



string_you_win: .ascii 'YOU WIN\0'
you_win:

    ld de, #_win
    call cpct_akp_musicInit_asm
    
    ld l, #15  ;; color letra
    ld h, #0  ;; color fondo
    call cpct_setDrawCharM0_asm

    ;cpctm_clearScreen_asm #0x00
    ;;pinto fondo menu
    ld hl, #_win_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ;; Dibujamos string YOU WIN
    ld iy, #string_you_win
    ld hl, #0xC3DA	
    call  cpct_drawStringM0_asm

    ;; Esperamos MAL CON HALTS
    ld e, #60
    call main_espera

    ;; bool_You_win = false
    ld a, #0
    ld (bool_final_juego), a

    ;ld ix, #entity_vector
    ;ld a, e_hp(ix)  ;; A = Vidas_player
    ;add #0x30       ;; A = A + 30  (30 es donde empieza el 0 en ASCII)
    ;ld (string_vidas_player), a

    call resetea_todo

ret

string_game_over: .ascii 'Game Over\0'
game_game_over:

    

    ld l, #15  ;; color letra
    ld h, #0  ;; color fondo
    call cpct_setDrawCharM0_asm

    ;cpctm_clearScreen_asm #0x00
    ;;pinto fondo menu
    ld hl, #_gameover_pack_end
    ld de, #0xFFFF
    call cpct_zx7b_decrunch_s_asm

    ;; Dibujamos string GAME OVER 
    ld iy, #string_game_over
    ld hl, #0xC3DA	
    call  cpct_drawStringM0_asm

    ;; Esperamos MAL CON HALTS
    ld e, #60
    call main_espera

    ;; Gameover = false 
    ld a, #0
    ld (bool_game_over), a

    call resetea_todo
    
ret

resetea_todo:
    ; Contador de rondas = 1
    ld a, #1
    ld (cont_rondas), a

    ;; Actualizamos el string de las rondas a 1
    ld a, #0x31 ;; el 31 es el 1
    ld (string_num_ronda), a

    ;; Reiniciamos el num_enemigo_por_ronda (que apunte a la ronda 1)
    ld hl, #tabla_num_enemigos_por_ronda
    ld (ptr_num_enemigos_por_ronda), hl

    ;; Reiniciamos el numero de enemigos maximo a 4 (primera ronda)
    call hud_reinicia_enemigos_maximo

    ;; Resetea el hud
    call hud_init 

    call reset_datos_game_over

    ;; Ponemos 3 vidas al player
    ld ix, #entity_vector
    ld e_hp(ix), #0x03  ;; A = Vidas_player
   
ret

game_play:
    
    fin_ronda:

        ;; --------- ESTE TROZO ES PARA TENER UN CONTADOR Y QUE SE VEA LA ANIMACION COMPLETA AL FINAL DE LA RONDA ---------
        ;; Compronamos si  llegado al final de la ronda
        ld a, (bool_final_ronda)
        cp #0
        jr z, primera_ronda 
            ;; Hemos llegado al final de la ronda
            ;; Tenemos que empezar a contar (para ver la animacion completa)
            ld a, (cont_game_over)
            inc a
            ld (cont_game_over), a
            cp #0x30
            jr nz, loop
                ;; Si hemos llegado al contadorTiempo = 70 (o sea si ya hemos esperado suficiente para ver la aniamcion del enemigo muriendo)
                ld a, #0x00 
                ld (cont_game_over), a      ;; Reseteo contador para la siguiente partida
        ; ------------------------------------------------------------------------------------------------------------


        ;; Mostramos el texto RONDA X 
        primera_ronda:
        call game_ronda
        ;; pinto tilemap al inicio
        call render_tilemap
        ;; Init hud
        call hud_init

        ;ld ix, #entity_vector   ;; IX => 1a entidad
        
    loop:
        
                ;cpctm_setBorder_asm HW_BRIGHT_RED ; PINTAMOS BORDE DE ROJO
        call ia_update

                ;cpctm_setBorder_asm HW_BRIGHT_YELLOW ; PINTAMOS BORDE DE AMARILLO
        call physics_update
        call sys_collision_update
                ;cpctm_setBorder_asm HW_ORANGE ; PINTAMOS BORDE DE NARANJA
        
        call hud_update

                ;cpctm_setBorder_asm HW_PINK  ; PINTAMOS BORDE DE ROSA
        call animations_update
 
                ;cpctm_setBorder_asm HW_GREEN   ; PINTAMOS BORDE DE VERDE
        call render_update

                ;cpctm_setBorder_asm HW_BLUE    ; PINTAMOS BORDE DE AZUL
        call spawnea_enemigo ;; Spawner de los enemigos

        
                ;cpctm_setBorder_asm HW_BLACK     ; PINTAMOS BORDE DE GRIS
        call entity_update ;; borramos entidades y creamos nuevas

        

        call cpct_waitVSYNC_asm

        ; Comprobamos GAME OVER
        ld a, (bool_game_over)
        cp #0
        jr nz, fin_el_juego

        ; Comprobamos fin del juego
        ld a, (bool_final_juego)
        cp #0
        jr nz, fin_win

        ; Comprobamos fin de ronda
        ld a, (bool_final_ronda)
        cp #0
        jr nz, fin_ronda

    jr    loop

    fin_el_juego:

        

        ld a, (cont_game_over)
        inc a
        ld (cont_game_over), a
        cp #0x70
        jr nz, loop
            ;; Si hemos llegado al contadorTiempo = FF (o sea si ya hemos esperado suficiente para ver la aniamcion del player muriendo)
            ld a, #0x00 
            ld (cont_game_over), a      ;; Reseteo contador para la siguiente partida
            call game_game_over  
            ret       

    fin_win: 

        

        ld a, (cont_game_over)
        inc a
        ld (cont_game_over), a
        cp #0x30
        jp nz, loop
            ;; Si hemos llegado al contadorTiempo = FF (o sea si ya hemos esperado suficiente para ver la aniamcion del player muriendo)
            ld a, #0x00 
            ld (cont_game_over), a      ;; Reseteo contador para la siguiente partida
            call you_win  
            ret       

ret 


main_espera:
      halt
      halt
      call cpct_waitVSYNC_asm
      dec e
    jp nz, main_espera
ret


posiciones_spawn_enemigos: 
    .db 0x08, 0x20 ;; arriba izq
    .db 0x44, 0x20 ;; arriba drcha
    .db 0x08, 0x94 ;; abajo izq
    .db 0x44, 0x94 ;; abajo drcha
    


spawnea_enemigo_aleatorio:
    call cpct_getRandom_mxor_u8_asm ;; Destroys AF, BC, DE, HL
    ld a, l
    and #0x03   ; Me devuelve una de estas opciones --> 00 01 10 11 (0,1,2 o 3 en A)

    ld hl, #posiciones_spawn_enemigos

    comprueba_posicion:
    or a
    cp #0
    jr z, posicion_conseguida
        ;; Tenemos que actualizar HL
        inc hl
        inc hl
        dec a
        jr comprueba_posicion
    posicion_conseguida:

    ld (registro_aux_ix), hl

    ld de, #zombie
    call game_create_template ;; en ix esta la nueva entidad
    
    ld iy, (registro_aux_ix) ;;cargamos las posiciones A y B
    ld a, 0(iy)
    ld b, 1(iy)
    ld e_x(ix), a
    ld e_y(ix), b

    ;ld de, #zombie
    ;ld c, #0
    ;ld h, #0
    ;ld l, #1
    ;call entity_set4creation ;; necesita en DE el template de entidad a crear, en A la X y en B la Y
ret


;; ====================================
;;     Destroy IY, HL, A, B...
;; ====================================
incrementa_cont_bajas_enemigos:
    
    call hud_actualiza_bajas

    ;; B = numero de enemigos en la ronda actual
    ld hl, (ptr_num_enemigos_por_ronda)
    ld a, (hl)
    ld b, a

    ;; A = enemigos derrotados en este ronda
    ld a, (cont_bajas_enemigos)
    inc a
    ld (cont_bajas_enemigos), a  ; A++
    cp b       
    ret nz
        ;; SI todos los enemigos de la ronda actual estan muertos
        ;ld a, #1
        ;ld (bool_final_ronda), a  ;;final_ronda = true

        ; cont_rondas ++
        ld a, (cont_rondas)
        inc a
        ld (cont_rondas), a 

        ;; Actualizamos el string de las rondas
        ld a, (string_num_ronda)    ;; A = num_ronda (ascii) --> Si ronda es 2, A=30+2
        inc a
        ld (string_num_ronda), a    
        sub #0x30                     ;; Restamos 30 a A para quedarnos con A=num_ronda(en decimal)

        ;; #2 = (max_rondas+1)
        ld b, #k_max_num_rondas
        inc b
        cp b
        jr nz, sigue_jugando
            ;; Fin del juego 
            ld a, #1
            ld (bool_final_juego), a
            ret
    sigue_jugando:

        ;; Si todavia quedan rondas
        ld a, #2
        ld (bool_fin_tabla_spawn), a    ;; esto significa que el spawn tiene que sumar 1 para ir a la siguiente ronda

        ld a, #0
        ld (inicializa_contador), a     ;; esto hara que el contador de tiempo para el siguiente enemigo empiece a contar

        ;; Ptr que apunta al numero de enemigos de cada ronda tiene que apuntar al siguiente 
        ld hl, (ptr_num_enemigos_por_ronda)
        inc hl
        ld (ptr_num_enemigos_por_ronda), hl

        call hud_actualiza_num_max_enemigos_ronda
        
        ;; SI todos los enemigos de la ronda actual estan muertos (y no es la ultima)
        ld a, #1
        ld (bool_final_ronda), a  ;;final_ronda = true


ret


;; datos para tilemaps
.globl _leve1_pack_end
.globl _leve2_pack_end
.globl _leve3_pack_end
.globl _leve4_pack_end
.globl _leve5_pack_end
.globl _leve6_pack_end
.globl _leve7_pack_end
.globl _leve8_pack_end
.globl _leve9_pack_end

decompress_buffer = 0x2b6
levelmaxsize =0xBF4
decompress_buffer_end =decompress_buffer+levelmaxsize-1

tilemaps_rondas: 
    .dw _leve1_pack_end
    .dw _leve2_pack_end
    .dw _leve3_pack_end
    .dw _leve4_pack_end
    .dw _leve5_pack_end
    .dw _leve6_pack_end
    .dw _leve7_pack_end
    .dw _leve8_pack_end
    .dw _leve9_pack_end

descomprime_tilemap:

    ld hl, #tilemaps_rondas

    ld a, (cont_rondas)
    dec a

    comprueba_posicion_tile:
    or a
    cp #0
    jr z, tile_conseguido
        ;; Tenemos que actualizar HL
        inc hl
        inc hl
        dec a
        jr comprueba_posicion_tile
    tile_conseguido:

    ld e, (hl)
    inc hl
    ld d, (hl)
    ld h, d
    ld l, e
    ;ld hl, #_leve1_pack_end
    ld de, #decompress_buffer_end
    call cpct_zx7b_decrunch_s_asm
ret