/* Kitsune's Curse Copyright (C) 2020-2023 Juan J. Martinez This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "main.h" #define LOCAL #include "entities.h" //#define ET_DEBUG struct st_entity *sp_free; struct st_entity entities[MAX_ENTITIES]; void init_entities() { uint8_t i; memset(entities, 0, sizeof(struct st_entity) * MAX_ENTITIES); for (i = 0; i < MAX_ENTITIES - 1; ++i) entities[i].n = entities + i + 1; sp_used = NULL; sp_free = entities; sp_collect = 0; } #pragma save #pragma disable_warning 59 uint8_t new_entity() { // new entity on sp_new on success /* if (!sp_free) return 0; sp_new = sp_free; sp_free = sp_free->n; sp_new->n = sp_used; sp_used = sp_new; return 1; */ // *INDENT-OFF* __asm; ; check MSB ld a, (_sp_free + 1) ld l, a or a #ifndef ET_DEBUG ret z #else jr nz, new_entity_free ld hl, #0x4a call _set_hw_border xor a ld l, a ret new_entity_free: #endif ld hl, (_sp_free) ld (_sp_new), hl ld bc, #ET_SIZE_PT add hl, bc ld e, (hl) inc hl ld d, (hl) ex de, hl ld (_sp_free), hl ld hl, (_sp_new) add hl, bc ld a, (_sp_used) ld (hl), a inc hl ld a, (_sp_used + 1) ld (hl), a ld hl, (_sp_new) ld (_sp_used), hl ld l, #1 __endasm; // *INDENT-ON* } #pragma restore void destroy_entity() { // entity on sp_it sp_it->type = ET_UNUSED; sp_collect++; } void free_entities() { /* if (!sp_used) return; // current, previous for (sp_it = sp_it2 = sp_used; sp_it && sp_collect;) { if (sp_it->type == ET_UNUSED) { sp_collect--; if (sp_it == sp_used) { sp_it2 = sp_free; sp_free = sp_used; sp_used = sp_used->n; sp_free->n = sp_it2; sp_it = sp_it2 = sp_used; continue; } else { sp_it2->n = sp_it->n; sp_it->n = sp_free; sp_free = sp_it; sp_it = sp_it2->n; continue; } } sp_it2 = sp_it; sp_it = sp_it->n; } */ // *INDENT-OFF* __asm; ; check MSB ld a, (_sp_used + 1) or a ret z ld hl, (_sp_used) ld (_sp_it2), hl ld (_sp_it), hl ld bc, #ET_SIZE_PT free_entities_loop: ; hl holds it ; check MSB ld a, (_sp_collect) or a ret z ld a, h or a ret z ld a, (hl) or a jr z, free_entities_unused ; next ; it2 is it ld (_sp_it2), hl ; it to it->n add hl, bc ld e, (hl) inc hl ld d, (hl) ex de, hl ld (_sp_it), hl jr free_entities_loop free_entities_unused: ld a, (_sp_collect) dec a ld (_sp_collect), a ld a, (_sp_used) cp l jr nz, free_entities_not_used ld a, (_sp_used + 1) cp h jr nz, free_entities_not_used ; it2 = free ld hl, (_sp_free) ld (_sp_it2), hl ; free = used ld hl, (_sp_used) ld (_sp_free), hl ; used = used->n add hl, bc ld e, (hl) inc hl ld d, (hl) ex de, hl ld (_sp_used), hl ; free->n = it2 ld hl, (_sp_it2) ex de, hl ld hl, (_sp_free) add hl, bc ld (hl), e inc hl ld (hl), d ; it = it2 = used ld hl, (_sp_used) ld (_sp_it2), hl ld (_sp_it), hl jr free_entities_loop free_entities_not_used: ; it2->n = it->n add hl, bc ld e, (hl) inc hl ld d, (hl) ld hl, (_sp_it2) add hl, bc ld (hl), e inc hl ld (hl), d ; it->n = free ld hl, (_sp_free) ex de, hl ld hl, (_sp_it) add hl, bc ld (hl), e inc hl ld (hl), d ; free = it ld hl, (_sp_it) ld (_sp_free), hl ; it = it2->n ld hl, (_sp_it2) add hl, bc ld e, (hl) inc hl ld d, (hl) ex de, hl ld (_sp_it), hl jp free_entities_loop __endasm; // *INDENT-ON* } #pragma save #pragma disable_warning 85 #pragma disable_warning 59 uint8_t check_for_point(struct st_entity *s, uint8_t x, uint8_t y, uint8_t w, uint8_t h) { // return (y < s->y + h && y >= s->y && x < s->x + w && x >= s->x); // *INDENT-OFF* __asm; ld hl, #2 add hl, sp ld e, (hl) inc hl ld d, (hl) ex de, hl ld bc, #4 add hl, bc ld a, (hl) inc hl inc hl ld h, (hl) ld l, a ex de, hl inc hl ld c, (hl) inc hl ld b, (hl) inc hl ld a, (hl) inc hl ld h, (hl) ld l, a ; de s (x, y) ; bc (x, y) ; hl (w, h) ld a, b cp d jr c, check_for_point_fail ld a, d add h cp b jr c, check_for_point_fail ld a, c cp e jr c, check_for_point_fail ld a, e add l cp c jr c, check_for_point_fail ld l, #1 ret check_for_point_fail: ld l, #0 __endasm; // *INDENT-ON* } #pragma restore void draw_entities() { /* draw_player(); for (sp_it = sp_used; sp_it; sp_it = sp_it->n) { it_x = &sp_it->x; it_y = &sp_it->y; it_ox = &sp_it->ox; it_oy = &sp_it->oy; it_frame = &sp_it->frame; it_param = &sp_it->param; it_extra = &sp_it->extra; sp_it->draw(); } */ // *INDENT-OFF* __asm; call _draw_player ld hl, (_sp_used) ld a, h or l jr z, draw_entities_done draw_entities_loop: ld (_sp_it), hl ld bc, #2 add hl, bc ld (_it_frame), hl add hl, bc ld (_it_x), hl inc hl ld (_it_ox), hl inc hl ld (_it_y), hl inc hl ld (_it_oy), hl inc hl ld (_it_param), hl inc hl ld (_it_extra), hl inc hl add hl, bc push hl ld a, (hl) inc hl ld h, (hl) ld l, a call ___sdcc_call_hl pop hl inc hl inc hl ld a, (hl) inc hl ld h, (hl) ld l, a or h jr nz, draw_entities_loop draw_entities_done: __endasm; // *INDENT-ON* } void update_entities() { /* for (sp_it = sp_used; sp_it; sp_it = sp_it->n) { if (sp_it->type == ET_UNUSED) continue; it_frame = &sp_it->frame; it_x = &sp_it->x; it_y = &sp_it->y; sp_it->ox = *it_x; it_ox = &sp_it->ox; sp_it->oy = *it_y; it_oy = &sp_it->oy; it_delay = &sp_it->delay; it_param = &sp_it->param; it_extra = &sp_it->extra; sp_it->update(); } if (sp_collect) free_entities(); update_player(); */ // *INDENT-OFF* __asm; ld hl, (_sp_used) ld a, h or l jr z, update_entities_done update_entities_loop: ld a, (hl) or a jr nz, update_entities_no_skip ld bc, #ET_SIZE_PT jr update_entities_next update_entities_no_skip: ld (_sp_it), hl inc hl inc hl ld (_it_frame), hl inc hl ld (_it_delay), hl inc hl ld (_it_x), hl ld a, (hl) inc hl ld (_it_ox), hl ld (hl), a inc hl ld (_it_y), hl ld a, (hl) inc hl ld (_it_oy), hl ld (hl), a inc hl ld (_it_param), hl inc hl ld (_it_extra), hl inc hl push hl ld a, (hl) inc hl ld h, (hl) ld l, a call ___sdcc_call_hl pop hl ld bc, #4 update_entities_next: add hl, bc ld a, (hl) inc hl ld h, (hl) ld l, a or h jr nz, update_entities_loop update_entities_done: ld a, (_sp_collect) or a jr z, update_entities_exit call _free_entities update_entities_exit: call _update_player __endasm; // *INDENT-ON* }