;;------------------------------------------------LICENSE NOTICE------------------------------------------------------------------------------
;;  This file is part of Amstrad CPC videogame "Redsea"
;;  Copyright (C) 2021 Crab Party / Elena López (AneleSplats in itch.io) / Iván Tortosa (Pluvs in itch.io, @IvanTortosaBer1 on Twitter) / Antonio Gosálvez (BalgroHub in itch.io)
;;  Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
;;
;;  This program is free software: you can redistribute it and/or modify
;;  it under the terms of the GNU Lesser General Public License as published by
;;  the Free Software Foundation, either version 3 of the License, or
;;  (at your option) any later version.
;;
;;  This program is distributed in the hope that it will be useful,
;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;  GNU Lesser General Public License for more details.
;;
;;  You should have received a copy of the GNU Lesser General Public License
;;  along with this program.  If not, see <http://www.gnu.org/licenses/>.
;;------------------------------------------------LICENSE NOTICE-------------------------------------------------------------------------
;Declaraciones globales
.globl cpct_memset_asm
.globl cpct_memcpy_asm

;Tipos de entidades
; e_type_invalid = #0x00 ; invalid entity type
; e_type_render = #0x01 ; renderable entity
; e_type_movable = #0x02 ; movable entity
; e_type_input = #0x04 ; Entity controllable by input
; e_type_ai = #0x08 ; Entity with ai
; e_type_animated = #0x10 ; Entity with animation
; e_type_collision = #0x20 ; Entity with collision
; e_type_non_loopable = #0x40 ; Entity with non loopable animations
e_type_dead = #0x80 ; upper bit signals dead entity
e_type_default = #0x7F ; default entity (all bits = 1)

;;chocarse con
e_type_player = #0x01 
e_type_pared = #0x02
e_type_spawner = #0x04
e_type_deadly = #0x08
e_type_goal = #0x10
e_type_arbol = #0x20
e_type_llave = #0x40
e_type_puerta = #0x80







;Variables en memoria
Invercosa: .ds 2
posAct: .ds 2
libres:: .db #0x00

MAX_ENTITIES = 7
entity_size = 18


Tam_ent = MAX_ENTITIES*entity_size

;m_num_entities:: .db 0
;entity_sizee:: .db #15
m_next_free_entity:: .dw m_entities

m_entities:: .ds Tam_ent
m_zero_type_at_the_end: .db #0x00

matching_type::  .db #0x00


;Se pone toda la memoria de las entidades a 0
;Se asigna m_next_free_entity y libres a su valor por defecto
man_entity_init::
    ld bc, #Tam_ent
    ld a, #0
    ld de, #m_entities
    call cpct_memset_asm

    ld hl, #m_entities
    ld (m_next_free_entity), hl

    ld a, #MAX_ENTITIES
    ld (#libres), a
ret


;Se le asigna a la siguiente entidad su tipo por defecto
;Se actualiza m_next_free_entity y libres
; OUTPUT:   ix es la dir de la entidad creada
man_entity_create::
    ld bc, (m_next_free_entity)
    ld a, #e_type_default
    ld (bc), a
    ld hl, #0d18

    add hl, bc
    ld (m_next_free_entity), hl
    ld l, c
    ld h, b

    push hl
    ld a, (#libres)
    sub #1
    ld (#libres), a

    pop ix
ret


; Elimina todas las entidades
man_entity_deleteAll::

    ld hl, #m_entities

    siguiente_ent32:
        ld a, (hl)
        or a
        jr z, salir32

        push hl
        pop ix
        call man_entity_set4destruction

        ld bc, #entity_size
        add hl, bc
        jr siguiente_ent32
    salir32:

ret


;;Recibe por ix la dir de la funcion y en matching_type la signature
man_entity_forall_matching_pairing::

;;Guardamos la dir de la funcion para luego saltar a ella
ld (Invercosa), ix

    ;;ix primera entidad
    ld ix, #m_entities

    ;;Comprobamos que la primera entidad sea valida, y recorre todas hasta que no lo sea
    ;;Dentro de cada iteracion tenemos que:
    ;;-Cojer la siguiente entidad y si es valida y coincide, se hace la funcion
    ;;-Tanto si lo hace como si no lo hace, se pasa a la siguiente entidad

siguiente_ent3:

    ;;Si no es válida, se sale de la funcion
    ld a, (ix)
    or a
    jr z, salir3

    ;;Si cumple la signature, se busca la segunda entidad, si no sigue con el bucle
    ld a, (#matching_type)
    ld d, a
    ld a, (ix)
    and d
    cp d    
    jr nz, salir3       ; Cambiado saltito3 a salir3

    push ix
    pop iy

    ;;Si la cumple, se busca la segunda entidad
saltito3_2:

    ;;iy segunda entidad
    ld bc, #entity_size
    add iy, bc

    ;;Si no es válida, se sale del bucle
    ld a, (iy)
    or a
    jr z, salir3    ;ambiado saltito3 a salir3

    ;;Si cumple la signature, se hace la funcion, si no sigue con el bucle
    ld a, (#matching_type)
    ld d, a
    ld a, (iy)
    and d
    cp d
jr nz, saltito3_2

    ;;Si la cumple hace el código y sigue a la siguiente entidad
    ld bc, #saltito3_2
    push bc
    ld hl, (#Invercosa)
    jp (hl)

    jr saltito3_2


    
saltito3:
    ld bc, #entity_size
    add ix, bc
    jr siguiente_ent3

salir3:

ret





;Se le pasa por ix la direccion de memoria de una funcion
;Esa funcion se le aplica a todas las entidades vivas que sean tengan todos los tipos de matching_type
man_entity_forall_matching::
    ld (Invercosa), ix
    ld ix, #m_entities

siguiente_ent2:

    ld a, (#matching_type)
    ld d, a
    ld a, (ix)
    or a
    jr z, salir2

    ld a, (ix)
    and d
    cp d
    jr nz, saltito2 ;Si no cumple todos los bites de d, se lleva a saltito


    ld bc, #saltito2
    push bc
    
    ;push hl
    ld hl, (#Invercosa)

    jp (hl)
    
saltito2:
    ld bc, #entity_size
    add ix, bc
    jr siguiente_ent2
salir2:

ret



;Se le pasa por hl la direccion de memoria de una funcion
;Esa funcion es aplicada a todas las entidades vivas
man_entity_forall::
    ld (Invercosa), hl
    ld hl, #m_entities

siguiente_ent:
    ld a, (hl)
    or a
    jr z, salir

    ld bc, #saltito
    push bc
    
    push hl
    ld hl, (#Invercosa)

    jp (hl)
    
saltito:
    ld bc, #entity_size
    add hl, bc
    jr siguiente_ent
salir:

ret


;Destruye una entidad, cogiendo la última válida y colocandola en su posición
man_entity_destroy::
;push hl

   ld a, (#libres) ;pones en hl temporal por el push, el numero de entidades libres que quedan
   add #1 ;le añades a hl temporal el bc
   ld (#libres), a ;metes dentro de libres el contenido de libres (dentro de hl temporal) + bc

   ;pop hl ;usas hl normal a partir de ahora

   ;ld bc, #11 ;le pones a bc donde esta el prevPos de la entidad
   ;add hl, bc  ;;prevPos1

   ld e, 11(ix) ;le metes a e el contenido de hl
   inc hl      ;;prevPos2
   ld d, 12(ix) ; le metes a d el contenido de hl+1

;    dec hl  ;;prevPos1
;    dec hl  ;;color
;    dec hl  ;;vx
;    dec hl  ;;y
;    dec hl  ;;x
;    dec hl  ;;tipo

   ;push hl

   ld h, d
   ld l, e
   ld (hl), #0

   ;pop hl

   ld bc, #0xFFEE
   ld (posAct), ix
   ld d, h
   ld e, l
   ld ix, (#m_next_free_entity)

   add ix, bc

   ld (m_next_free_entity), ix

   ld bc, #18

   call cpct_memcpy_asm

   ld bc, #18;; size

   ld a, #0 ;; value

   ld de, (#m_next_free_entity) ;; puntero al array, primer valor

   call cpct_memset_asm

   ld ix, (#posAct)
ret


;Cambia el tipo de la entidad pasada por ix a entidad_muerta
man_entity_set4destruction::
    ld a, (ix)
    or #e_type_dead
    ld (ix), a
ret


;Recorre todas las entidades, y borra las que están marcadas para morir
man_entity_update::
    ld ix, #m_entities
    jr siguiento

destruir_ent:
    call man_entity_destroy
siguiento:
    ld a, (ix)
    or a
    ret z

    ld a, #e_type_dead
    ld b, a
    ld a, (ix)
   and b
   jr nz, destruir_ent ;nz era como estaba y explota
no_destruir_ent:
    ld bc, #entity_size
    add ix, bc
    jr siguiento
ret


;Devuelve por a el número entidades libres que quedan
man_entity_freeSpace::
    ld a, (#libres)
ret

man_entity_get_from_idx::
    ld ix, #m_entities
ret

; Cambia la posicion de la entidad pasada
; Input: ix es la dir de la entidad / b es la x deseada y c es la y deseada
man_entity_moverEntidad::

    ld 1(ix), b
    ld 2(ix), c

ret
;CAMBIAR HL POR IX EN UPDATE ONE Y FORALL