library: Cleanup affine background source files

This commit is contained in:
Antonio Niño Díaz 2023-05-25 21:56:27 +01:00
parent 89c6c00f9a
commit 5280f3fe64
2 changed files with 495 additions and 533 deletions

View File

@ -57,7 +57,7 @@ extern NF_TYPE_AFFINE_BG NF_AFFINE_BG[2][4];
/// ```
///
/// @param screen Screen (0 - 1).
void NF_InitAffineBgSys(u8 screen);
void NF_InitAffineBgSys(int screen);
/// Load an affine background to RAM from the filesystem.
///
@ -80,7 +80,7 @@ void NF_InitAffineBgSys(u8 screen);
/// @param name Name used for the BG for other functions.
/// @param width BG width.
/// @param height BG height.
void NF_LoadAffineBg(const char *file, const char *name, u16 width, u16 height);
void NF_LoadAffineBg(const char *file, const char *name, u32 width, u32 height);
/// Deletes the specified affine background from RAM.
///
@ -111,7 +111,7 @@ static inline void NF_UnloadAffineBg(const char *name)
/// @param layer Layer (2 - 3).
/// @param name Name of the background.
/// @param wrap True to enable wrap around mode.
void NF_CreateAffineBg(u8 screen, u8 layer, const char *name, u8 wrap);
void NF_CreateAffineBg(int screen, u32 layer, const char *name, u32 wrap);
/// Deletes from VRAM the background of the specified screen and layer.
///
@ -123,7 +123,7 @@ void NF_CreateAffineBg(u8 screen, u8 layer, const char *name, u8 wrap);
///
/// @param screen Screen (0 - 1).
/// @param layer Layer (2 - 3).
void NF_DeleteAffineBg(u8 screen, u8 layer);
void NF_DeleteAffineBg(int screen, u32 layer);
/// Modify the transformation matrix of the specified background.
///
@ -141,7 +141,8 @@ void NF_DeleteAffineBg(u8 screen, u8 layer);
/// @param y_scale Scale Y: 0 - 256 (original) - 512 (or more)
/// @param x_tilt Tilt X: 0 - 512 (or more)
/// @param y_tilt Tilt Y: 0 - 512 (or more)
void NF_AffineBgTransform(u8 screen, u8 layer, s32 x_scale, s32 y_scale, s32 x_tilt, s32 y_tilt);
void NF_AffineBgTransform(int screen, u32 layer, s32 x_scale, s32 y_scale,
s32 x_tilt, s32 y_tilt);
/// Moves the affine background to the specified position.
///
@ -160,7 +161,7 @@ void NF_AffineBgTransform(u8 screen, u8 layer, s32 x_scale, s32 y_scale, s32 x_t
/// @param x X coordinate.
/// @param y Y coordinate.
/// @param angle Rotation angle (-2048 to 2048).
void NF_AffineBgMove(u8 screen, u8 layer, s32 x, s32 y, s32 angle);
void NF_AffineBgMove(int screen, u32 layer, s32 x, s32 y, s32 angle);
/// Define the rotation center of the specified affine background.
///
@ -175,7 +176,7 @@ void NF_AffineBgMove(u8 screen, u8 layer, s32 x, s32 y, s32 angle);
/// @param layer Layer (2 - 3).
/// @param x X coordinate.
/// @param y Y coordinate.
static inline void NF_AffineBgCenter(u8 screen, u8 layer, s32 x, s32 y)
static inline void NF_AffineBgCenter(int screen, u32 layer, s32 x, s32 y)
{
NF_AFFINE_BG[screen][layer].x_center = x;
NF_AFFINE_BG[screen][layer].y_center = y;

View File

@ -2,12 +2,11 @@
//
// Copyright (c) 2009-2014 Cesar Rincon "NightFox"
//
// NightFox LIB - Funciones de Fondos Affine
// NightFox LIB - Affine background functions
// http://www.nightfoxandco.com/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <nds.h>
@ -16,485 +15,464 @@
#include "nf_basic.h"
#include "nf_tiledbg.h"
// Estructura para almacenar los parametros de los fondos Affine
// Struct that holds informatio about all affine backgrounds
NF_TYPE_AFFINE_BG NF_AFFINE_BG[2][4];
void NF_InitAffineBgSys(u8 screen) {
void NF_InitAffineBgSys(int screen)
{
// Define the number of banks of maps and tiles.
//
// Tile banks are 16 KB in size. Map banks are 2 KB in size. You can fit 8
// map banks in a tile bank. For that reason, the number of map banks must
// be a multiple of 8 banks.
//
// By default, use 8 tile banks and 16 map banks.
NF_BANKS_TILES[screen] = 8;
NF_BANKS_MAPS[screen] = 16;
u8 n = 0;
// Define los bancos de Mapas y Tiles
NF_BANKS_TILES[screen] = 8; // (1 banks = 16kb) Cada banco de tiles puede alvergar 8 bancos de Mapas
NF_BANKS_MAPS[screen] = 16; // (1 bank = 2kb) Usar multiplos de 8. Cada set de 8 bancos consume 1 banco de tiles
// Por defecto Tiles = 8, Mapas = 16
// Esto nos deja 6 bancos de 16kb para tiles
// y 16 bancos de 2kb para mapas
// Inicializa el array de bloques libres de Tiles
for (n = 0; n < NF_BANKS_TILES[screen]; n ++) {
// Set all tile and map blocks as free
for (u32 n = 0; n < NF_BANKS_TILES[screen]; n++)
NF_TILEBLOCKS[screen][n] = 0;
}
// Inicializa el array de bloques libres de Mapas
for (n = 0; n < NF_BANKS_MAPS[screen]; n ++) {
for (u32 n = 0; n < NF_BANKS_MAPS[screen]; n++)
NF_MAPBLOCKS[screen][n] = 0;
// Reset state of all layers
for (int n = 0; n < 4; n++)
{
NF_TILEDBG_LAYERS[screen][n].tilebase = 0;
NF_TILEDBG_LAYERS[screen][n].tileblocks = 0;
NF_TILEDBG_LAYERS[screen][n].mapbase = 0;
NF_TILEDBG_LAYERS[screen][n].mapblocks = 0;
NF_TILEDBG_LAYERS[screen][n].bgwidth = 0;
NF_TILEDBG_LAYERS[screen][n].bgheight = 0;
NF_TILEDBG_LAYERS[screen][n].mapwidth = 0;
NF_TILEDBG_LAYERS[screen][n].mapheight = 0;
NF_TILEDBG_LAYERS[screen][n].bgtype = 0;
NF_TILEDBG_LAYERS[screen][n].bgslot = 0;
NF_TILEDBG_LAYERS[screen][n].blockx = 0;
NF_TILEDBG_LAYERS[screen][n].blocky = 0;
NF_TILEDBG_LAYERS[screen][n].created = false; // Mark as not created
}
// Inicializa el array de informacion de fondos en pantalla
for (n = 0; n < 4; n ++) {
NF_TILEDBG_LAYERS[screen][n].tilebase = 0; // Base del Tileset
NF_TILEDBG_LAYERS[screen][n].tileblocks = 0; // Bloques usados por el Tileset
NF_TILEDBG_LAYERS[screen][n].mapbase = 0; // Base del Map
NF_TILEDBG_LAYERS[screen][n].mapblocks = 0; // Bloques usados por el Map
NF_TILEDBG_LAYERS[screen][n].bgwidth = 0; // Ancho del fondo
NF_TILEDBG_LAYERS[screen][n].bgheight = 0; // Altura del fondo
NF_TILEDBG_LAYERS[screen][n].mapwidth = 0; // Ancho del mapa
NF_TILEDBG_LAYERS[screen][n].mapheight = 0; // Altura del mapa
NF_TILEDBG_LAYERS[screen][n].bgtype = 0; // Tipo de mapa
NF_TILEDBG_LAYERS[screen][n].bgslot = 0; // Buffer de graficos usado
NF_TILEDBG_LAYERS[screen][n].blockx = 0; // Bloque de mapa actual (horizontal)
NF_TILEDBG_LAYERS[screen][n].blocky = 0; // Bloque de mapa actual (vertical)
NF_TILEDBG_LAYERS[screen][n].created = false; // Esta creado ?
}
// Now reserve as many VRAM banks as needed for maps. Each tile map is as
// big as 8 map banks.
// Ahora reserva los bancos necesarios de VRAM para mapas
// Cada bloque de 16kb (1 banco de tiles) permite 8 bancos de mapas (de 2kb cada uno)
u8 r_banks;
r_banks = ((NF_BANKS_MAPS[screen] - 1) >> 3) + 1; // Calcula los bancos de Tiles a reservar para Maps
for (n = 0; n < r_banks; n ++) {
NF_TILEBLOCKS[screen][n] = 128; // Marca que bancos de VRAM son para MAPS
}
// Number of required tile maps to reserve for maps
u32 r_banks = ((NF_BANKS_MAPS[screen] - 1) >> 3) + 1;
for (u32 n = 0; n < r_banks; n++)
NF_TILEBLOCKS[screen][n] = 128; // Mark as available for maps
if (screen == 0) {
// Si es la pantalla 0 (Superior, Main engine)
vramSetBankA(VRAM_A_MAIN_BG); // Banco A de la VRAM para fondos (128kb)
memset((void*)0x06000000, 0, 131072); // Borra el contenido del banco A
for (n = 0; n < 4; n ++) { // Oculta todas las 4 capas
if (screen == 0)
{
// Clear VRAM_A (128 KB)
vramSetBankA(VRAM_A_MAIN_BG);
memset((void *)0x06000000, 0, 131072);
for (int n = 0; n < 4; n++) // Hide all 4 layers
NF_HideBg(0, n);
}
} else {
// Si es la pantalla 1 (Inferior, Sub engine)
vramSetBankC(VRAM_C_SUB_BG); // Banco C de la VRAM para fondos (128kb)
memset((void*)0x06200000, 0, 131072); // Borra el contenido del banco C
for (n = 0; n < 4; n ++) { // Oculta todas las 4 capas
else
{
// Clear VRAM_C (128 KB)
vramSetBankC(VRAM_C_SUB_BG);
memset((void *)0x06200000, 0, 131072);
for (int n = 0; n < 4; n++) // Hide all 4 layers
NF_HideBg(1, n);
}
}
}
void NF_LoadAffineBg(const char* file, const char* name, u16 width, u16 height) {
// Verifica si el fondo cumple las medidas correctas
if (((width == 256) && (height == 256)) || ((width == 512) && (height == 512))) {
// Medida Ok
} else {
// Error de tamaño
void NF_LoadAffineBg(const char *file, const char *name, u32 width, u32 height)
{
// Verify that the background has the right size
if (!(((width == 256) && (height == 256)) || ((width == 512) && (height == 512))))
NF_Error(117, name, 0);
}
// Variable temporal del tamaño de la paleta
u32 pal_size = 0;
// Busca un slot libre
u8 n = 0;
// Look for a free tiled background slot
u8 slot = 255;
for (n = 0; n < NF_SLOTS_TBG; n ++) { // Busca en todos los slots
if (NF_TILEDBG[n].available) { // Si esta libre
NF_TILEDBG[n].available = false; // Marcalo como en uso
slot = n; // Guarda el slot a usar
n = NF_SLOTS_TBG; // Deja de buscar
for (u32 n = 0; n < NF_SLOTS_TBG; n++)
{
if (NF_TILEDBG[n].available)
{
NF_TILEDBG[n].available = false; // Mark it as used
slot = n;
break;
}
}
// Si no hay ningun slot libre, error
if (slot == 255) {
NF_Error(103, "Tiled Bg", NF_SLOTS_TBG);
}
// Vacia los buffers que se usaran
free(NF_BUFFER_BGMAP[slot]); // Buffer para los mapas
if (slot == 255) // No free slots, fail
NF_Error(103, "Tiled Bg", NF_SLOTS_TBG);
// Free buffers if they were in use
free(NF_BUFFER_BGMAP[slot]);
NF_BUFFER_BGMAP[slot] = NULL;
free(NF_BUFFER_BGTILES[slot]); // Buffer para los tiles
free(NF_BUFFER_BGTILES[slot]);
NF_BUFFER_BGTILES[slot] = NULL;
free(NF_BUFFER_BGPAL[slot]); // Buffer para los paletas
free(NF_BUFFER_BGPAL[slot]);
NF_BUFFER_BGPAL[slot] = NULL;
// Declara los punteros a los ficheros
FILE* file_id;
// Variable para almacenar el path al archivo
// File path
char filename[256];
// Carga el archivo .IMG
// Load .IMG file
snprintf(filename, sizeof(filename), "%s/%s.img", NF_ROOTFOLDER, file);
file_id = fopen(filename, "rb");
if (file_id) { // Si el archivo existe...
// Obten el tamaño del archivo
FILE *file_id = fopen(filename, "rb");
if (file_id == NULL) // If the file can't be opened
NF_Error(101, filename, 0);
// Get file size
fseek(file_id, 0, SEEK_END);
NF_TILEDBG[slot].tilesize = ftell(file_id);
rewind(file_id);
// Reserva el espacio en RAM
NF_BUFFER_BGTILES[slot] = (char*) calloc (NF_TILEDBG[slot].tilesize, sizeof(char));
if (NF_BUFFER_BGTILES[slot] == NULL) { // Si no hay suficiente RAM libre
// Allocate space in RAM
NF_BUFFER_BGTILES[slot] = malloc(NF_TILEDBG[slot].tilesize);
if (NF_BUFFER_BGTILES[slot] == NULL) // Not enough RAM
NF_Error(102, NULL, NF_TILEDBG[slot].tilesize);
}
// Lee el archivo y ponlo en la RAM
// Read file into RAM
fread(NF_BUFFER_BGTILES[slot], 1, NF_TILEDBG[slot].tilesize, file_id);
} else { // Si el archivo no existe...
NF_Error(101, filename, 0);
}
fclose(file_id); // Cierra el archivo
// swiWaitForVBlank(); // Espera al cierre del archivo (Usar en caso de corrupcion de datos)
fclose(file_id);
// Verifica el tamaño del tileset (Menos de 256 tiles)
if (NF_TILEDBG[slot].tilesize > 16384) NF_Error(117, name, 0);
// Verify that the tileset is at most 256 tiles
if (NF_TILEDBG[slot].tilesize > 16384)
NF_Error(117, name, 0);
// Carga el archivo .MAP
// Load .MAP file
snprintf(filename, sizeof(filename), "%s/%s.map", NF_ROOTFOLDER, file);
file_id = fopen(filename, "rb");
if (file_id) { // Si el archivo existe...
// Obten el tamaño del archivo
fseek(file_id, 0, SEEK_END);
NF_TILEDBG[slot].mapsize = ((((ftell(file_id) - 1) >> 10) + 1) << 10); // Ajusta el tamaño a bloques de 1kb
rewind(file_id);
// Reserva el espacio en RAM
NF_BUFFER_BGMAP[slot] = (char*) calloc (NF_TILEDBG[slot].mapsize, sizeof(char));
if (NF_BUFFER_BGMAP[slot] == NULL) { // Si no hay suficiente RAM libre
NF_Error(102, NULL, NF_TILEDBG[slot].mapsize);
}
// Lee el archivo y ponlo en la RAM
fread(NF_BUFFER_BGMAP[slot], 1, NF_TILEDBG[slot].mapsize, file_id);
} else { // Si el archivo no existe...
if (file_id == NULL) // If the file can't be opened
NF_Error(101, filename, 0);
}
fclose(file_id); // Cierra el archivo
// swiWaitForVBlank(); // Espera al cierre del archivo (Usar en caso de corrupcion de datos)
// Carga el archivo .PAL
// Get file size
fseek(file_id, 0, SEEK_END);
NF_TILEDBG[slot].mapsize = (((ftell(file_id) - 1) >> 10) + 1) << 10; // 1 KB blocks
rewind(file_id);
// Allocate space in RAM
NF_BUFFER_BGMAP[slot] = malloc (NF_TILEDBG[slot].mapsize);
if (NF_BUFFER_BGMAP[slot] == NULL) // Not enough available RAM
NF_Error(102, NULL, NF_TILEDBG[slot].mapsize);
// Read file into RAM
fread(NF_BUFFER_BGMAP[slot], 1, NF_TILEDBG[slot].mapsize, file_id);
fclose(file_id);
// Load .PAL file
snprintf(filename, sizeof(filename), "%s/%s.pal", NF_ROOTFOLDER, file);
file_id = fopen(filename, "rb");
if (file_id) { // Si el archivo existe...
// Obten el tamaño del archivo
if (file_id == NULL) // If the file can't be opened
NF_Error(101, filename, 0);
// Get file size
fseek(file_id, 0, SEEK_END);
pal_size = ftell(file_id);
u32 pal_size = ftell(file_id);
NF_TILEDBG[slot].palsize = pal_size;
rewind(file_id);
// Si el tamaño es inferior a 512 bytes, ajustalo
if (NF_TILEDBG[slot].palsize < 512) NF_TILEDBG[slot].palsize = 512;
// Reserva el espacio en RAM
NF_BUFFER_BGPAL[slot] = (char*) calloc (NF_TILEDBG[slot].palsize, sizeof(char));
if (NF_BUFFER_BGPAL[slot] == NULL) { // Si no hay suficiente RAM libre
NF_Error(102, NULL, NF_TILEDBG[slot].palsize);
}
// Lee el archivo y ponlo en la RAM
fread(NF_BUFFER_BGPAL[slot], 1, pal_size, file_id);
} else { // Si el archivo no existe...
NF_Error(101, filename, 0);
}
fclose(file_id); // Cierra el archivo
// Guarda el nombre del Fondo
// If the size is smaller than 512 bytes (256 colors) adjust it to 512 bytes
if (NF_TILEDBG[slot].palsize < 512)
NF_TILEDBG[slot].palsize = 512;
// Allocate space in RAM and zero it in case the real palette size was small
NF_BUFFER_BGPAL[slot] = calloc(NF_TILEDBG[slot].palsize, sizeof(char));
if (NF_BUFFER_BGPAL[slot] == NULL)
NF_Error(102, NULL, NF_TILEDBG[slot].palsize);
// Read file into RAM
fread(NF_BUFFER_BGPAL[slot], 1, pal_size, file_id);
fclose(file_id);
// Save information of the tiled background
snprintf(NF_TILEDBG[slot].name, sizeof(NF_TILEDBG[slot].name), "%s", name);
// Y las medidas
NF_TILEDBG[slot].width = width;
NF_TILEDBG[slot].height = height;
}
void NF_CreateAffineBg(u8 screen, u8 layer, const char* name, u8 wrap) {
void NF_CreateAffineBg(int screen, u32 layer, const char *name, u32 wrap)
{
// Verify that the destination layer is valid
if ((layer != 2) && (layer != 3))
NF_Error(118, name, 0);
// Variables
u8 n = 0; // Bucle
u8 slot = 255; // Slot seleccionado
char bg[32]; // Nombre
u32 slot = 255;
// Verifica la capa de destino
if ((layer != 2) && (layer != 3)) NF_Error(118, name, 0);
// Busca el fondo solicitado
snprintf(bg, sizeof(bg), "%s", name); // Obten el nombre del fondo a buscar
for (n = 0; n < NF_SLOTS_TBG; n ++) { // Busca en todos los slots
if (strcmp(bg, NF_TILEDBG[n].name) == 0) { // Si lo encuentras
slot = n; // Guarda el slot a usar
n = NF_SLOTS_TBG; // Deja de buscar
for (u32 n = 0; n < NF_SLOTS_TBG; n++)
{
if (strcmp(name, NF_TILEDBG[n].name) == 0)
{
slot = n;
break;
}
}
// Si no se encuentra, error
if (slot == 255) {
if (slot == 255) // The slot hasn't been found, fail
NF_Error(104, name, 0);
}
// Si ya hay un fondo existente en esta pantalla y capa, borralo antes
if (NF_TILEDBG_LAYERS[screen][layer].created) {
// If there is already a background in this layer, delete it before
if (NF_TILEDBG_LAYERS[screen][layer].created)
NF_DeleteTiledBg(screen, layer);
}
// Variables de control de Tiles
u8 counter = 0;
u8 start = 255;
u8 tilesblocks = 0;
u8 basetiles = 0;
// Copy the size of the background
NF_TILEDBG_LAYERS[screen][layer].bgwidth = NF_TILEDBG[slot].width;
NF_TILEDBG_LAYERS[screen][layer].bgheight = NF_TILEDBG[slot].height;
NF_TILEDBG_LAYERS[screen][layer].mapwidth = NF_TILEDBG[slot].width;
NF_TILEDBG_LAYERS[screen][layer].mapheight = NF_TILEDBG[slot].height;
NF_TILEDBG_LAYERS[screen][layer].bgtype = 0;
NF_TILEDBG_LAYERS[screen][layer].bgslot = slot;
// Transfiere el tamaño del fondo
NF_TILEDBG_LAYERS[screen][layer].bgwidth = NF_TILEDBG[slot].width; // Ancho del fondo
NF_TILEDBG_LAYERS[screen][layer].bgheight = NF_TILEDBG[slot].height; // Altura del fondo
NF_TILEDBG_LAYERS[screen][layer].mapwidth = NF_TILEDBG[slot].width; // Ancho del mapa
NF_TILEDBG_LAYERS[screen][layer].mapheight = NF_TILEDBG[slot].height; // Altura del mapa
NF_TILEDBG_LAYERS[screen][layer].bgtype = 0; // Tipo de fondo
NF_TILEDBG_LAYERS[screen][layer].bgslot = slot; // Buffer de graficos usado
// Calcula el tipo y tamaño del mapa
n = 0;
// ( 256 x 256 )
if ((NF_TILEDBG[slot].width == 256) && (NF_TILEDBG[slot].height == 256)) {
if ((NF_TILEDBG[slot].width == 256) && (NF_TILEDBG[slot].height == 256))
{
NF_TILEDBG_LAYERS[screen][layer].mapwidth = 256;
NF_TILEDBG_LAYERS[screen][layer].mapheight = 256;
NF_TILEDBG_LAYERS[screen][layer].bgtype = 11;
n = 1;
}
// ( 512 x 512 )
if ((NF_TILEDBG[slot].width == 512) && (NF_TILEDBG[slot].height == 512)) {
else if ((NF_TILEDBG[slot].width == 512) && (NF_TILEDBG[slot].height == 512))
{
NF_TILEDBG_LAYERS[screen][layer].mapwidth = 512;
NF_TILEDBG_LAYERS[screen][layer].mapheight = 512;
NF_TILEDBG_LAYERS[screen][layer].bgtype = 12;
n = 1;
}
else
{
NF_Error(117, name, 0);
}
// Verifica el tamaño del tileset (Menos de 256 tiles)
if (NF_TILEDBG[slot].tilesize > 16384) n = 0;
// Verify that the tileset is 256 tiles or fewer
if (NF_TILEDBG[slot].tilesize > 16384)
NF_Error(117, name, 0);
// Si el fondo es de una medida incorrecta...
if (n == 0) NF_Error(117, name, 0);
// Calculate the required number of blocks
u32 tilesblocks = ((NF_TILEDBG[slot].tilesize - 1) >> 14) + 1;
// Busca un los bloques libres para almacenar los Tiles en VRAM
tilesblocks = ((NF_TILEDBG[slot].tilesize - 1) >> 14) + 1; // Bloques necesarios para el Tileset
// Determine a location for the new tileset
u32 counter = 0;
u32 start = 255;
for (u32 n = 0; n < NF_BANKS_TILES[screen]; n++)
{
if (NF_TILEBLOCKS[screen][n] == 0)
{
// If the block is free and this is the first free block, save the
// start address.
if (counter == 0)
start = n;
for (n = 0; n < NF_BANKS_TILES[screen]; n ++) {
if (NF_TILEBLOCKS[screen][n] == 0) { // Si esta libre
if (counter == 0) { // Y el contador esta a 0
start = n; // Marca la posicion de inicio
// If enough blocks have been found stop the search
counter++;
if (counter == tilesblocks)
n = NF_BANKS_TILES[screen];
}
counter ++;
if (counter == tilesblocks) { // Si ya tienes suficientes bloques libres
n = NF_BANKS_TILES[screen]; // Termina de buscar
}
} else { // Si el bloque no esta libre
start = 255; // Borra el marcador
counter = 0; // Y resetea el contador
else
{
// If the block is not free, reset the counter and try again
start = 255;
counter = 0;
}
}
// Si no se han encontrado bloques libres
if ((start == 255) || (counter < tilesblocks)) {
// If no free blocks have been found
if ((start == 255) || (counter < tilesblocks))
NF_Error(107, name, tilesblocks);
} else {
basetiles = start; // Guarda donde empiezan los bloques libres
}
// Marca los bancos de Tiles usados por este fondo
for (n = basetiles; n < (basetiles + tilesblocks); n ++) {
NF_TILEBLOCKS[screen][n] = 255; // Marca los bloques usados por tiles
}
// Mark all required map banks as used
u32 basetiles = start;
for (u32 n = basetiles; n < (basetiles + tilesblocks); n ++)
NF_TILEBLOCKS[screen][n] = 255;
// Variables de control de Maps
u8 mapblocks = 0;
u8 basemap = 0;
// Calculate the required number of blocks
u32 mapblocks = ((NF_TILEDBG[slot].mapsize - 1) >> 11) + 1;
// Determine a location for the new map
counter = 0;
start = 255;
// Calcula los bloques para mapas necesarios
mapblocks = ((NF_TILEDBG[slot].mapsize - 1) >> 11) + 1;
for (u32 n = 0; n < NF_BANKS_MAPS[screen]; n++)
{
if (NF_MAPBLOCKS[screen][n] == 0)
{
// If the block is free and this is the first free block, save the
// start address.
if (counter == 0)
start = n;
for (n = 0; n < NF_BANKS_MAPS[screen]; n ++) {
if (NF_MAPBLOCKS[screen][n] == 0) { // Si esta libre
if (counter == 0) { // Y el contador esta a 0
start = n; // Marca la posicion de inicio
// If enough blocks have been found stop the search
counter++;
if (counter == mapblocks)
n = NF_BANKS_MAPS[screen];
}
counter ++;
if (counter == mapblocks) { // Si ya tienes suficientes bloques libres
n = NF_BANKS_MAPS[screen]; // Termina de buscar
}
} else { // Si el bloque no esta libre
start = 255; // Borra el marcador
counter = 0; // Y resetea el contador
else
{
// If the block is not free, reset the counter and try again
start = 255;
counter = 0;
}
}
// Si no se han encontrado bloques libres
if ((start == 255) || (counter < mapblocks)) {
// If no free blocks have been found
if ((start == 255) || (counter < mapblocks))
NF_Error(108, name, mapblocks);
} else {
basemap = start; // Guarda donde empiezan los bloques libres
}
// Marca los bancos de Mapa usados por este fondo
for (n = basemap; n < (basemap + mapblocks); n ++) {
NF_MAPBLOCKS[screen][n] = 255; // Marca los bloques usados por mapas
}
// Mark all required map banks as used
u32 basemap = start;
for (u32 n = basemap; n < (basemap + mapblocks); n++)
NF_MAPBLOCKS[screen][n] = 255;
// Obten el tamaño del fondo
s32 bg_size = 0;
// 256x256
if ((NF_TILEDBG_LAYERS[screen][layer].mapwidth == 256) && (NF_TILEDBG_LAYERS[screen][layer].mapheight == 256)) {
// Check the size of the background
s32 bg_size;
if ((NF_TILEDBG_LAYERS[screen][layer].mapwidth == 256) &&
(NF_TILEDBG_LAYERS[screen][layer].mapheight == 256))
{
bg_size = BG_RS_32x32;
}
// 512x512
if ((NF_TILEDBG_LAYERS[screen][layer].mapwidth == 512) && (NF_TILEDBG_LAYERS[screen][layer].mapheight == 512)) {
else if ((NF_TILEDBG_LAYERS[screen][layer].mapwidth == 512) &&
(NF_TILEDBG_LAYERS[screen][layer].mapheight == 512))
{
bg_size = BG_RS_64x64;
}
// Decide si se activa o no el WRAP
u32 wrap_mode = 0;
if (wrap == 0) {
wrap_mode = BG_WRAP_OFF;
} else {
wrap_mode = BG_WRAP_ON;
else
{
NF_Error(117, name, 0);
}
// Decide if wrap is enabled or not
u32 wrap_mode = wrap == 0 ? BG_WRAP_OFF : BG_WRAP_ON;
// Crea el fondo segun la pantalla, capa y demas caracteristicas dadas
// REG_BG0CNT <- Carracteristicas del fondo
if (screen == 0) {
switch (layer) {
// Setup the background properties
if (screen == 0)
{
switch (layer)
{
case 2:
REG_BG2CNT = BgType_Rotation | bg_size | BG_PRIORITY_2 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap) | wrap_mode;
REG_BG2CNT = BgType_Rotation | bg_size | BG_PRIORITY_2 | BG_COLOR_256 |
BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap) | wrap_mode;
break;
case 3:
REG_BG3CNT = BgType_Rotation | bg_size | BG_PRIORITY_3 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap) | wrap_mode;
REG_BG3CNT = BgType_Rotation | bg_size | BG_PRIORITY_3 | BG_COLOR_256 |
BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap) | wrap_mode;
break;
}
} else {
switch (layer) {
}
else
{
switch (layer)
{
case 2:
REG_BG2CNT_SUB = BgType_Rotation | bg_size | BG_PRIORITY_2 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap) | wrap_mode;
REG_BG2CNT_SUB = BgType_Rotation | bg_size | BG_PRIORITY_2 | BG_COLOR_256 |
BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap) | wrap_mode;
break;
case 3:
REG_BG3CNT_SUB = BgType_Rotation | bg_size | BG_PRIORITY_3 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap) | wrap_mode;
REG_BG3CNT_SUB = BgType_Rotation | bg_size | BG_PRIORITY_3 | BG_COLOR_256 |
BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap) | wrap_mode;
break;
}
}
u32 address; // Variable de direccion de VRAM;
u32 address;
// Transfiere el Tileset a VRAM
if (screen == 0) { // (VRAM_A)
address = (0x6000000) + (basetiles << 14);
} else { // (VRAM_C)
address = (0x6200000) + (basetiles << 14);
}
NF_DmaMemCopy((void*)address, NF_BUFFER_BGTILES[slot], NF_TILEDBG[slot].tilesize);
// Transfer tileset to VRAM
if (screen == 0) // VRAM_A
address = 0x6000000 + (basetiles << 14);
else // VRAM_C
address = 0x6200000 + (basetiles << 14);
NF_DmaMemCopy((void *)address, NF_BUFFER_BGTILES[slot], NF_TILEDBG[slot].tilesize);
// Transfer map to VRAM
if (screen == 0) // VRAM_A
address = 0x6000000 + (basemap << 11);
else // VRAM_C
address = 0x6200000 + (basemap << 11);
NF_DmaMemCopy((void *)address, NF_BUFFER_BGMAP[slot], NF_TILEDBG[slot].mapsize);
// Transfiere el Mapa a VRAM
if (screen == 0) { // (VRAM_A)
address = (0x6000000) + (basemap << 11);
} else { // (VRAM_C)
address = (0x6200000) + (basemap << 11);
}
NF_DmaMemCopy((void*)address, NF_BUFFER_BGMAP[slot], NF_TILEDBG[slot].mapsize);
// Tranfer palette to palette memory
if (screen == 0)
address = 0x05000000; // Main engine standard BG palette
else
address = 0x05000400; // Sub engine standard BG palette
NF_DmaMemCopy((void *)address, NF_BUFFER_BGPAL[slot], NF_TILEDBG[slot].palsize);
// Save information
NF_TILEDBG_LAYERS[screen][layer].tilebase = basetiles;
NF_TILEDBG_LAYERS[screen][layer].tileblocks = tilesblocks;
NF_TILEDBG_LAYERS[screen][layer].mapbase = basemap;
NF_TILEDBG_LAYERS[screen][layer].mapblocks = mapblocks;
NF_TILEDBG_LAYERS[screen][layer].created = true; // Mark as created
// Tranfiere la Paleta a VRAM
if (screen == 0) {
address = (0x05000000);
NF_DmaMemCopy((void*)address, NF_BUFFER_BGPAL[slot], NF_TILEDBG[slot].palsize);
} else { // Paletas de la pantalla 1 (VRAM_H)
address = (0x05000400);
NF_DmaMemCopy((void*)address, NF_BUFFER_BGPAL[slot], NF_TILEDBG[slot].palsize);
}
// Registra los datos del fondos en pantalla
NF_TILEDBG_LAYERS[screen][layer].tilebase = basetiles; // Base del Tileset
NF_TILEDBG_LAYERS[screen][layer].tileblocks = tilesblocks; // Bloques usados por el Tileset
NF_TILEDBG_LAYERS[screen][layer].mapbase = basemap; // Base del Map
NF_TILEDBG_LAYERS[screen][layer].mapblocks = mapblocks; // Bloques usados por el Map
NF_TILEDBG_LAYERS[screen][layer].created = true; // Esta creado ?
// Resetea los parametros del affine
NF_AffineBgTransform(screen, layer, 256, 256, 0, 0);
// Reset affine parameters
NF_AffineBgTransform(screen, layer, 1 << 8, 1 << 8, 0, 0);
NF_AffineBgMove(screen, layer, 0, 0, 0);
// Haz visible el fondo creado
// Make the newly created background visible
NF_ShowBg(screen, layer);
}
void NF_DeleteAffineBg(u8 screen, u8 layer) {
// Verifica que el fondo esta creado
if (!NF_TILEDBG_LAYERS[screen][layer].created) {
void NF_DeleteAffineBg(int screen, u32 layer)
{
// Verify that the background has been created
if (!NF_TILEDBG_LAYERS[screen][layer].created)
{
char text[32];
snprintf(text, sizeof(text), "%d", screen);
NF_Error(105, text, layer); // Si no existe, error
NF_Error(105, text, layer);
}
// Esconde el fondo creado
// Hide background
NF_HideBg(screen, layer);
// Variables de uso general
u32 address; // Direccion de VRAM;
u8 n; // Uso general
u16 basetiles = 0; // Base del Tileset
u16 basemap = 0; // Base del Map
u16 tilesize = 0; // Tamaño del Tileset
u16 mapsize = 0; // Tamaño del Map
// Clear tileset from VRAM
u32 basetiles = NF_TILEDBG_LAYERS[screen][layer].tilebase;
u32 tilesize = NF_TILEDBG_LAYERS[screen][layer].tileblocks << 14;
u32 address;
// Borra el Tileset de la VRAM
basetiles = NF_TILEDBG_LAYERS[screen][layer].tilebase;
tilesize = (NF_TILEDBG_LAYERS[screen][layer].tileblocks << 14);
if (screen == 0) { // (VRAM_A)
address = (0x6000000) + (basetiles << 14);
} else { // (VRAM_C)
address = (0x6200000) + (basetiles << 14);
}
memset((void*)address, 0, tilesize); // Pon a 0 todos los bytes de la area de VRAM
if (screen == 0) // VRAM_A
address = 0x6000000 + (basetiles << 14);
else // VRAM_C
address = 0x6200000 + (basetiles << 14);
// Borra el Mapa de la VRAM
basemap = NF_TILEDBG_LAYERS[screen][layer].mapbase;
mapsize = (NF_TILEDBG_LAYERS[screen][layer].mapblocks << 11);
if (screen == 0) { // (VRAM_A)
address = (0x6000000) + (basemap << 11);
} else { // (VRAM_C)
address = (0x6200000) + (basemap << 11);
}
memset((void*)address, 0, mapsize); // Pon a 0 todos los bytes de la area de VRAM
memset((void *)address, 0, tilesize);
// Marca como libres los bancos de Tiles usados por este fondo
// Clear map from VRAM
u32 basemap = NF_TILEDBG_LAYERS[screen][layer].mapbase;
u32 mapsize = NF_TILEDBG_LAYERS[screen][layer].mapblocks << 11;
if (screen == 0) // VRAM_A
address = 0x6000000 + (basemap << 11);
else // VRAM_C
address = 0x6200000 + (basemap << 11);
memset((void *)address, 0, mapsize);
// Mark as free all the tile banks used by this background
tilesize = (basetiles + NF_TILEDBG_LAYERS[screen][layer].tileblocks);
for (n = basetiles; n < tilesize; n ++) {
for (u32 n = basetiles; n < tilesize; n++)
NF_TILEBLOCKS[screen][n] = 0;
}
// Marca como libres los bancos de Mapa usados por este fondo
mapsize = (basemap + NF_TILEDBG_LAYERS[screen][layer].mapblocks);
for (n = basemap; n < mapsize; n ++) {
// Mark as free all the map banks used by this background
mapsize = basemap + NF_TILEDBG_LAYERS[screen][layer].mapblocks;
for (u32 n = basemap; n < mapsize; n++)
NF_MAPBLOCKS[screen][n] = 0;
}
// Borra los datos del fondos en pantalla
NF_TILEDBG_LAYERS[screen][layer].tilebase = 0; // Base del Tileset
NF_TILEDBG_LAYERS[screen][layer].tileblocks = 0; // Bloques usados por el Tileset
NF_TILEDBG_LAYERS[screen][layer].mapbase = 0; // Base del Map
NF_TILEDBG_LAYERS[screen][layer].mapblocks = 0; // Bloques usados por el Map
NF_TILEDBG_LAYERS[screen][layer].bgwidth = 0; // Ancho del fondo
NF_TILEDBG_LAYERS[screen][layer].bgheight = 0; // Altura del fondo
NF_TILEDBG_LAYERS[screen][layer].mapwidth = 0; // Ancho del mapa
NF_TILEDBG_LAYERS[screen][layer].mapheight = 0; // Altura del mapa
NF_TILEDBG_LAYERS[screen][layer].bgtype = 0; // Tipo de mapa
NF_TILEDBG_LAYERS[screen][layer].bgslot = 0; // Buffer de graficos usado
NF_TILEDBG_LAYERS[screen][layer].blockx = 0; // Bloque de mapa actual (horizontal)
NF_TILEDBG_LAYERS[screen][layer].blocky = 0; // Bloque de mapa actual (vertical)
NF_TILEDBG_LAYERS[screen][layer].created = false; // Esta creado ?
// Clear information of the background
NF_TILEDBG_LAYERS[screen][layer].tilebase = 0;
NF_TILEDBG_LAYERS[screen][layer].tileblocks = 0;
NF_TILEDBG_LAYERS[screen][layer].mapbase = 0;
NF_TILEDBG_LAYERS[screen][layer].mapblocks = 0;
NF_TILEDBG_LAYERS[screen][layer].bgwidth = 0;
NF_TILEDBG_LAYERS[screen][layer].bgheight = 0;
NF_TILEDBG_LAYERS[screen][layer].mapwidth = 0;
NF_TILEDBG_LAYERS[screen][layer].mapheight = 0;
NF_TILEDBG_LAYERS[screen][layer].bgtype = 0;
NF_TILEDBG_LAYERS[screen][layer].bgslot = 0;
NF_TILEDBG_LAYERS[screen][layer].blockx = 0;
NF_TILEDBG_LAYERS[screen][layer].blocky = 0;
NF_TILEDBG_LAYERS[screen][layer].created = false; // Mark as not created
}
void NF_AffineBgTransform(u8 screen, u8 layer, s32 x_scale, s32 y_scale, s32 x_tilt, s32 y_tilt) {
if (screen == 0) {
switch (layer) {
void NF_AffineBgTransform(int screen, u32 layer, s32 x_scale, s32 y_scale,
s32 x_tilt, s32 y_tilt)
{
if (screen == 0)
{
switch (layer)
{
case 2:
REG_BG2PA = x_scale;
REG_BG2PB = x_tilt;
@ -508,8 +486,11 @@ void NF_AffineBgTransform(u8 screen, u8 layer, s32 x_scale, s32 y_scale, s32 x_t
REG_BG3PD = y_scale;
break;
}
} else {
switch (layer) {
}
else
{
switch (layer)
{
case 2:
REG_BG2PA_SUB = x_scale;
REG_BG2PB_SUB = x_tilt;
@ -525,71 +506,49 @@ void NF_AffineBgTransform(u8 screen, u8 layer, s32 x_scale, s32 y_scale, s32 x_t
}
}
// Registra los valores asignados
// Save values
NF_AFFINE_BG[screen][layer].x_scale = x_scale;
NF_AFFINE_BG[screen][layer].x_tilt = x_tilt;
NF_AFFINE_BG[screen][layer].y_tilt = y_tilt;
NF_AFFINE_BG[screen][layer].y_scale = y_scale;
}
void NF_AffineBgMove(u8 screen, u8 layer, s32 x, s32 y, s32 angle) {
void NF_AffineBgMove(int screen, u32 layer, s32 x, s32 y, s32 angle)
{
// Based on the original function of libnds by Dovoto and WinterMute
// Funcion de rotacion basada en la original de Libnds
// creada por Dovoto y Wintermute.
// Limit angle
if (angle < -2048)
angle += 2048;
if (angle > 2048)
angle -= 2048;
// Variables
s32 pa = 0; // x_scale
s32 pb = 0; // x_tilt
s32 pc = 0; // y_tilt;
s32 pd = 0; // y_scale;
s16 angle_sin = 0; // Seno
s16 angle_cos = 0; // Coseno
s16 in = 0; // Angulo dado
s16 out = 0; // Angulo convertido
s32 pos_x = 0; // Posicion X del fondo
s32 pos_y = 0; // Posicion Y del fondo
angle = -angle << 4; // Switch from base 2048 to base 32768
in = angle;
s32 angle_sin = sinLerp(angle);
s32 angle_cos = cosLerp(angle);
// Limites del angulo
if (in < -2048) {
in += 2048;
}
if (in > 2048) {
in -= 2048;
}
// Calculate and apply transformation matrix
s32 pa = (angle_cos * NF_AFFINE_BG[screen][layer].x_scale) >> 12;
s32 pb = (-angle_sin * NF_AFFINE_BG[screen][layer].x_scale) >> 12;
s32 pc = (angle_sin * NF_AFFINE_BG[screen][layer].y_scale) >> 12;
s32 pd = (angle_cos * NF_AFFINE_BG[screen][layer].y_scale) >> 12;
// Si es un numero negativo...
if (in < 0) {
in = -in; // Pasa a positivo (para poder hacer el bitshift)
out = (in << 4); // (in * 16); Pasa de base 2048 a base 32768
// Dejalo en positivo para que <0 gire a la izquierda
} else {
out = (in << 4);
out = -out; // Pasalo a negativo para que >0 gire a la derecha
}
// Calcula los senos y cosenos
angle_sin = sinLerp(out);
angle_cos = cosLerp(out);
// Calcula la matriz de transformacion
pa = ( angle_cos * NF_AFFINE_BG[screen][layer].x_scale ) >> 12;
pb = (-angle_sin * NF_AFFINE_BG[screen][layer].x_scale ) >> 12;
pc = ( angle_sin * NF_AFFINE_BG[screen][layer].y_scale ) >> 12;
pd = ( angle_cos * NF_AFFINE_BG[screen][layer].y_scale ) >> 12;
// Aplica los parametros de tranformacion
NF_AffineBgTransform(screen, layer, pa, pd, pb, pc);
// Ahora calcula la posicion del fondo
pos_x = ((x << 8) - (((pa * (NF_AFFINE_BG[screen][layer].x_center << 8)) + (pb * (NF_AFFINE_BG[screen][layer].y_center << 8))) >> 8));
pos_y = ((y << 8) - (((pc * (NF_AFFINE_BG[screen][layer].x_center << 8)) + (pd * (NF_AFFINE_BG[screen][layer].y_center << 8))) >> 8));
// Calculate the position of the background
s32 pos_x = (x << 8) -
(((pa * (NF_AFFINE_BG[screen][layer].x_center << 8)) +
(pb * (NF_AFFINE_BG[screen][layer].y_center << 8))) >> 8);
s32 pos_y = (y << 8) -
(((pc * (NF_AFFINE_BG[screen][layer].x_center << 8)) +
(pd * (NF_AFFINE_BG[screen][layer].y_center << 8))) >> 8);
// Aplica la posicion del centro
if (screen == 0) {
switch (layer) {
// Set the position of the center
if (screen == 0)
{
switch (layer)
{
case 2:
REG_BG2X = pos_x;
REG_BG2Y = pos_y;
@ -599,8 +558,11 @@ void NF_AffineBgMove(u8 screen, u8 layer, s32 x, s32 y, s32 angle) {
REG_BG3Y = pos_y;
break;
}
} else {
switch (layer) {
}
else
{
switch (layer)
{
case 2:
REG_BG2X_SUB = pos_x;
REG_BG2Y_SUB = pos_y;
@ -612,9 +574,8 @@ void NF_AffineBgMove(u8 screen, u8 layer, s32 x, s32 y, s32 angle) {
}
}
// Guarda los parametros
NF_AFFINE_BG[screen][layer].angle = out;
// Save parameters
NF_AFFINE_BG[screen][layer].angle = angle;
NF_AFFINE_BG[screen][layer].x = x;
NF_AFFINE_BG[screen][layer].y = y;
}