nds_nflib/source/nf_collision.c
Antonio Niño Díaz aef2292857 library: Share most code that loads file from the filesystem
Instead of repeating the same code whenever a file needs to be loaded,
move it to a function.
2023-05-30 22:50:22 +01:00

228 lines
6.1 KiB
C

// SPDX-License-Identifier: MIT
//
// Copyright (c) 2009-2014 Cesar Rincon "NightFox"
// Copyright (c) 2023 Antonio Niño Díaz "AntonioND"
//
// NightFox LIB - Collision maps functions
// http://www.nightfoxandco.com/
#include <stdio.h>
#include <string.h>
#include <nds.h>
#include "nf_basic.h"
#include "nf_collision.h"
// Struct that holds information about all collision maps
NF_TYPE_CMAP_INFO NF_CMAP[NF_SLOTS_CMAP];
void NF_InitCmapBuffers(void)
{
for (int n = 0; n < NF_SLOTS_CMAP; n++)
{
NF_CMAP[n].tiles = NULL;
NF_CMAP[n].map = NULL;
NF_CMAP[n].tiles_size = 0;
NF_CMAP[n].map_size = 0;
NF_CMAP[n].width = 0;
NF_CMAP[n].height = 0;
NF_CMAP[n].inuse = false; // Mark as unused
}
}
void NF_ResetCmapBuffers(void)
{
// Free all buffers
for (int n = 0; n < NF_SLOTS_CMAP; n++)
{
free(NF_CMAP[n].tiles);
free(NF_CMAP[n].map);
}
// Reset state of the collision maps
NF_InitCmapBuffers();
}
void NF_LoadCollisionMap(const char *file, u32 id, u32 width, u32 height)
{
// Verify that the slot ID is valid
if (id >= NF_SLOTS_CMAP)
NF_Error(106, "Collision Map", NF_SLOTS_CMAP);
// Verify that this slot is free
if (NF_CMAP[id].inuse)
NF_Error(109, "Collision Map", id);
// Free buffers if they were in use
free(NF_CMAP[id].map);
NF_CMAP[id].map = NULL;
// File path
char filename[256];
// Load .CMP file (tilemap)
snprintf(filename, sizeof(filename), "%s/%s.cmp", NF_ROOTFOLDER, file);
NF_FileLoad(filename, &NF_CMAP[id].map, &NF_CMAP[id].map_size, 0);
// Save map size
NF_CMAP[id].width = width;
NF_CMAP[id].height = height;
// Mark this slot as in use
NF_CMAP[id].inuse = true;
}
void NF_UnloadCollisionMap(u32 id)
{
// Verify that the slot ID is valid
if (id >= NF_SLOTS_CMAP)
NF_Error(106, "Collision Map", NF_SLOTS_CMAP);
// Verify that this slot is used
if (!NF_CMAP[id].inuse)
NF_Error(110, "Collision Map", id);
// Free buffer
free(NF_CMAP[id].map);
NF_CMAP[id].map = NULL;
// Mark this slot as free
NF_CMAP[id].inuse = false;
}
u32 NF_GetTile(u32 slot, s32 x, s32 y)
{
// If the coordinate is outside of the map, return 0
if ((x < 0) || (y < 0) || (x >= NF_CMAP[slot].width) || (y >= NF_CMAP[slot].height))
return 0;
// Calculate width of the map in tiles
u32 columns = NF_CMAP[slot].width / 8;
// Calculate tile where the pixel is located
u32 tile_x = x / 8;
u32 tile_y = (y / 8) + 1; // Skip first row, it's used for the tile reference
// Calculate the address of the tile in the map
u32 address = ((tile_y * columns) + tile_x) * 2;
// Read tile number
u32 lobyte = *(NF_CMAP[slot].map + address);
u32 hibyte = *(NF_CMAP[slot].map + (address + 1));
return (hibyte << 8) | lobyte;
}
void NF_SetTile(u32 slot, s32 x, s32 y, u32 value)
{
// If the coordinate is outside of the map, return
if ((x < 0) && (y < 0) && (x >= NF_CMAP[slot].width) && (y >= NF_CMAP[slot].height))
return;
// Calculate width of the map in tiles
u32 columns = NF_CMAP[slot].width / 8;
// Calculate tile where the pixel is located
u32 tile_x = x / 8;
u32 tile_y = (y / 8) + 1; // Skip first row, it's used for the tile reference
// Calculate the address of the tile in the map
s32 address = ((tile_y * columns) + tile_x) * 2; // Each tile uses 2 bytes
// Split new tile number
u32 hibyte = (value >> 8) & 0xff;
u32 lobyte = value & 0xff;
// Write the new tile number
*(NF_CMAP[slot].map + address) = lobyte;
*(NF_CMAP[slot].map + (address + 1)) = hibyte;
}
void NF_LoadCollisionBg(const char *file, u32 id, u32 width, u32 height)
{
// Verify that the slot ID is valid
if (id >= NF_SLOTS_CMAP)
NF_Error(106, "Collision map", NF_SLOTS_CMAP);
// Verify that this slot is free
if (NF_CMAP[id].inuse)
NF_Error(109, "Collision map", id);
// Free buffers if they were in use
free(NF_CMAP[id].tiles);
NF_CMAP[id].tiles = NULL;
free(NF_CMAP[id].map);
NF_CMAP[id].map = NULL;
// File path
char filename[256];
// Load .DAT file (tileset)
snprintf(filename, sizeof(filename), "%s/%s.dat", NF_ROOTFOLDER, file);
NF_FileLoad(filename, &NF_CMAP[id].tiles, &NF_CMAP[id].tiles_size, 0);
// Load .CMP file (tilemap)
snprintf(filename, sizeof(filename), "%s/%s.cmp", NF_ROOTFOLDER, file);
NF_FileLoad(filename, &NF_CMAP[id].map, &NF_CMAP[id].map_size, 0);
// Save map size
NF_CMAP[id].width = width;
NF_CMAP[id].height = height;
// Mark this slot as in use
NF_CMAP[id].inuse = true;
}
void NF_UnloadCollisionBg(u32 id)
{
// Verify that the slot ID is valid
if (id >= NF_SLOTS_CMAP)
NF_Error(106, "Collision map", NF_SLOTS_CMAP);
// Verify that this slot is used
if (!NF_CMAP[id].inuse)
NF_Error(110, "Collision map", id);
// Free the buffers
free(NF_CMAP[id].tiles);
NF_CMAP[id].tiles = NULL;
free(NF_CMAP[id].map);
NF_CMAP[id].map = NULL;
// Mark this map as unused
NF_CMAP[id].inuse = false;
}
u8 NF_GetPoint(u32 slot, s32 x, s32 y)
{
// If the coordinate is outside of the map, return 0
if ((x < 0) || (y < 0) || (x >= NF_CMAP[slot].width) || (y >= NF_CMAP[slot].height))
return 0;
// Calculate width of the map in tiles
u32 columns = NF_CMAP[slot].width / 8;
// Calculate tile where the pixel is located
u32 tile_x = x / 8;
u32 tile_y = (y / 8) + 1; // Skip first row, it's used for the tile reference
// Calculate pixel coordinates inside the tile
u32 pixel_x = x & 7;
u32 pixel_y = y & 7;
// Calculate the address of the tile in the map
s32 address = ((tile_y * columns) + tile_x) * 2; // Each tile uses 2 bytes
// Read tile number
u32 lobyte = *(NF_CMAP[slot].map + address);
u32 hibyte = *(NF_CMAP[slot].map + (address + 1));
u32 tile = (hibyte << 8) | lobyte;
// Read value of the pixel inside the tile
address = (tile * 64) + (pixel_y * 8) + pixel_x;
lobyte = *(NF_CMAP[slot].tiles + address);
return lobyte;
}