mirror of
https://github.com/knightfox75/nds_nflib.git
synced 2025-06-18 16:55:32 -04:00
276 lines
7.4 KiB
C
276 lines
7.4 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);
|
|
FILE *file_id = fopen(filename, "rb");
|
|
if (file_id == NULL)
|
|
NF_Error(101, filename, 0);
|
|
|
|
// Get file size
|
|
fseek(file_id, 0, SEEK_END);
|
|
NF_CMAP[id].map_size = ftell(file_id);
|
|
rewind(file_id);
|
|
|
|
// Allocate space in RAM
|
|
NF_CMAP[id].map = malloc(NF_CMAP[id].map_size);
|
|
if (NF_CMAP[id].map == NULL)
|
|
NF_Error(102, NULL, NF_CMAP[id].map_size);
|
|
|
|
// Load file into RAM
|
|
fread(NF_CMAP[id].map, 1, NF_CMAP[id].map_size, file_id);
|
|
fclose(file_id);
|
|
|
|
// 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);
|
|
FILE *file_id = fopen(filename, "rb");
|
|
if (file_id == NULL)
|
|
NF_Error(101, filename, 0);
|
|
|
|
// Get file size
|
|
fseek(file_id, 0, SEEK_END);
|
|
NF_CMAP[id].tiles_size = ftell(file_id);
|
|
rewind(file_id);
|
|
|
|
// Allocate space in RAM
|
|
NF_CMAP[id].tiles = malloc(NF_CMAP[id].tiles_size);
|
|
if (NF_CMAP[id].tiles == NULL)
|
|
NF_Error(102, NULL, NF_CMAP[id].tiles_size);
|
|
|
|
// Load file into RAM
|
|
fread(NF_CMAP[id].tiles, 1, NF_CMAP[id].tiles_size, file_id);
|
|
fclose(file_id);
|
|
|
|
// Load .CMP file (tilemap)
|
|
snprintf(filename, sizeof(filename), "%s/%s.cmp", NF_ROOTFOLDER, file);
|
|
file_id = fopen(filename, "rb");
|
|
if (file_id == NULL)
|
|
NF_Error(101, filename, 0);
|
|
|
|
// Get file size
|
|
fseek(file_id, 0, SEEK_END);
|
|
NF_CMAP[id].map_size = ftell(file_id);
|
|
rewind(file_id);
|
|
|
|
// Allocate space in RAM
|
|
NF_CMAP[id].map = malloc(NF_CMAP[id].map_size);
|
|
if (NF_CMAP[id].map == NULL)
|
|
NF_Error(102, NULL, NF_CMAP[id].map_size);
|
|
|
|
// Load file into RAM
|
|
fread(NF_CMAP[id].map, 1, NF_CMAP[id].map_size, file_id);
|
|
fclose(file_id);
|
|
|
|
// 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;
|
|
}
|