mirror of
https://github.com/knightfox75/nds_nflib.git
synced 2025-06-18 16:55:32 -04:00

- Creative Commons (except for CC0) shouldn't be used for code: https://creativecommons.org/faq/#can-i-apply-a-creative-commons-license-to-software MIT has the same spirit as the CC-BY license. - CC-BY has been retained for the assets included in the repository. - Also, the years were wrong, this library was started in 2009. - Make all examples use the CC0 license.
1385 lines
42 KiB
C
1385 lines
42 KiB
C
// SPDX-License-Identifier: MIT
|
|
//
|
|
// Copyright (c) 2009-2014 Cesar Rincon "NightFox"
|
|
//
|
|
// NightFox LIB - Funciones de Fondos con tiles
|
|
// http://www.nightfoxandco.com/
|
|
// Version 20140413
|
|
|
|
|
|
|
|
|
|
|
|
// Includes devKitPro
|
|
#include <nds.h>
|
|
#include <filesystem.h>
|
|
#include <fat.h>
|
|
|
|
// Includes C
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
// Includes propios
|
|
#include "nf_basic.h"
|
|
#include "nf_2d.h"
|
|
#include "nf_tiledbg.h"
|
|
|
|
|
|
|
|
// Define los bancos de Mapas y Tiles
|
|
u8 NF_BANKS_TILES[2]; // (1 banks = 16kb) Cada banco de tiles puede alvergar 8 bancos de Mapas
|
|
u8 NF_BANKS_MAPS[2]; // (1 bank = 2kb) Usar multiplos de 8. Cada set de 8 bancos consume 1 banco de tiles
|
|
|
|
// Define los Buffers para almacenar los fondos
|
|
char* NF_BUFFER_BGTILES[NF_SLOTS_TBG];
|
|
char* NF_BUFFER_BGMAP[NF_SLOTS_TBG];
|
|
char* NF_BUFFER_BGPAL[NF_SLOTS_TBG];
|
|
|
|
// Define la estructura de propiedades de los fondos
|
|
NF_TYPE_TBG_INFO NF_TILEDBG[NF_SLOTS_TBG]; // Info de los fondos cargados en RAM
|
|
NF_TYPE_TBGLAYERS_INFO NF_TILEDBG_LAYERS[2][4]; // Info de los fondos en pantalla
|
|
|
|
// Define la estructura para las paletas extendidas
|
|
NF_TYPE_EXBGPAL_INFO NF_EXBGPAL[NF_SLOTS_EXBGPAL]; // Datos de las paletas extendidas
|
|
|
|
// Define el array de bloques libres
|
|
u8 NF_TILEBLOCKS[2][NF_MAX_BANKS_TILES];
|
|
u8 NF_MAPBLOCKS[2][NF_MAX_BANKS_MAPS];
|
|
|
|
|
|
|
|
// Funcion NF_InitTiledBgBuffers();
|
|
void NF_InitTiledBgBuffers(void) {
|
|
u8 n = 0;
|
|
// Buffers de fondos tileados
|
|
for (n = 0; n < NF_SLOTS_TBG; n ++) { // Inicializa todos los slots
|
|
NF_BUFFER_BGTILES[n] = NULL; // Buffer para los tiles
|
|
NF_BUFFER_BGMAP[n] = NULL; // Buffer para el map
|
|
NF_BUFFER_BGPAL[n] = NULL; // Buffer para la paleta
|
|
sprintf(NF_TILEDBG[n].name, "xxxNONAMExxx"); // Nombre del Tileset
|
|
NF_TILEDBG[n].tilesize = 0; // Tamaño del Tileset
|
|
NF_TILEDBG[n].mapsize = 0; // Tamaño del Mapa
|
|
NF_TILEDBG[n].palsize = 0; // Tamaño de la Paleta
|
|
NF_TILEDBG[n].width = 0; // Ancho del Mapa
|
|
NF_TILEDBG[n].height = 0; // Alto del Mapa
|
|
NF_TILEDBG[n].available = true; // Disponibilidad
|
|
}
|
|
// Buffers de paletas extendidas
|
|
for (n = 0; n < NF_SLOTS_EXBGPAL; n ++) {
|
|
NF_EXBGPAL[n].buffer = NULL;
|
|
NF_EXBGPAL[n].palsize = 0;
|
|
NF_EXBGPAL[n].inuse = false;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_ResetTiledBgBuffers();
|
|
void NF_ResetTiledBgBuffers(void) {
|
|
u8 n = 0;
|
|
for (n = 0; n < NF_SLOTS_TBG; n ++) { // Inicializa todos los slots
|
|
free(NF_BUFFER_BGTILES[n]); // Vacia el Buffer para los tiles
|
|
free(NF_BUFFER_BGMAP[n]); // Vacia Buffer para el map
|
|
free(NF_BUFFER_BGPAL[n]); // Vacia Buffer para la paleta
|
|
}
|
|
for (n = 0; n < NF_SLOTS_EXBGPAL; n ++) {
|
|
NF_EXBGPAL[n].buffer = NULL;
|
|
}
|
|
NF_InitTiledBgBuffers(); // Reinicia el resto de variables
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_InitTiledBgSys();
|
|
void NF_InitTiledBgSys(u8 screen) {
|
|
|
|
// Variables
|
|
u8 n = 0;
|
|
|
|
// Define el numero de 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 ++) {
|
|
NF_TILEBLOCKS[screen][n] = 0;
|
|
}
|
|
|
|
// Inicializa el array de bloques libres de Mapas
|
|
for (n = 0; n < NF_BANKS_MAPS[screen]; n ++) {
|
|
NF_MAPBLOCKS[screen][n] = 0;
|
|
}
|
|
|
|
// 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 ?
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
if (screen == 0) {
|
|
// Si es la pantalla 0 (Superior, Main engine)
|
|
REG_DISPCNT |= (DISPLAY_BG_EXT_PALETTE); // Activa las paletas extendidas
|
|
vramSetBankA(VRAM_A_MAIN_BG); // Banco A de la VRAM para fondos (128kb)
|
|
memset((void*)0x06000000, 0, 131072); // Borra el contenido del banco A
|
|
vramSetBankE(VRAM_E_LCD); // Reserva el banco E de la VRAM para Paletas Extendidas (0-3) (32kb de 64kb)
|
|
memset((void*)0x06880000, 0, 32768); // Borra el contenido del banco E
|
|
for (n = 0; n < 4; n ++) { // Oculta todas las 4 capas
|
|
NF_HideBg(0, n);
|
|
}
|
|
} else {
|
|
// Si es la pantalla 1 (Inferior, Sub engine)
|
|
REG_DISPCNT_SUB |= (DISPLAY_BG_EXT_PALETTE); // Activa las paletas extendidas
|
|
vramSetBankC(VRAM_C_SUB_BG); // Banco C de la VRAM para fondos (128kb)
|
|
memset((void*)0x06200000, 0, 131072); // Borra el contenido del banco C
|
|
vramSetBankH(VRAM_H_LCD); // Reserva el banco H de la VRAM para Paletas Extendidas (0-3) (32kb)
|
|
memset((void*)0x06898000, 0, 32768); // Borra el contenido del banco H
|
|
for (n = 0; n < 4; n ++) { // Oculta todas las 4 capas
|
|
NF_HideBg(1, n);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_LoadTiledBg();
|
|
void NF_LoadTiledBg(const char* file, const char* name, u16 width, u16 height) {
|
|
|
|
// Variable temporal del tamaño de la paleta
|
|
u32 pal_size = 0;
|
|
|
|
// Busca un slot libre
|
|
u8 n = 0;
|
|
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
|
|
}
|
|
}
|
|
// Si no hay ningun slot libre, error
|
|
if (slot == 255) {
|
|
NF_Error(103, "Tiled Bg", NF_SLOTS_TBG);
|
|
}
|
|
|
|
// Verifica que el fondo sea multiplo de 256px (32 tiles)
|
|
if (((width % 256) != 0) || ((height % 256) != 0)) {
|
|
NF_Error(115, file, 0);
|
|
}
|
|
|
|
// Vacia los buffers que se usaran
|
|
free(NF_BUFFER_BGMAP[slot]); // Buffer para los mapas
|
|
NF_BUFFER_BGMAP[slot] = NULL;
|
|
free(NF_BUFFER_BGTILES[slot]); // Buffer para los tiles
|
|
NF_BUFFER_BGTILES[slot] = NULL;
|
|
free(NF_BUFFER_BGPAL[slot]); // Buffer para los paletas
|
|
NF_BUFFER_BGPAL[slot] = NULL;
|
|
|
|
// Declara los punteros a los ficheros
|
|
FILE* file_id;
|
|
|
|
// Variable para almacenar el path al archivo
|
|
char filename[256];
|
|
|
|
// Carga el archivo .IMG
|
|
sprintf(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
|
|
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
|
|
NF_Error(102, NULL, NF_TILEDBG[slot].tilesize);
|
|
}
|
|
// Lee el archivo y ponlo en la 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
|
|
|
|
// Carga el archivo .MAP
|
|
sprintf(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) >> 11) + 1) << 11); // Ajusta el tamaño a bloques de 2kb
|
|
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...
|
|
NF_Error(101, filename, 0);
|
|
}
|
|
fclose(file_id); // Cierra el archivo
|
|
|
|
// Carga el archivo .PAL
|
|
sprintf(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
|
|
fseek(file_id, 0, SEEK_END);
|
|
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
|
|
sprintf(NF_TILEDBG[slot].name, "%s", name);
|
|
|
|
// Y las medidas
|
|
NF_TILEDBG[slot].width = width;
|
|
NF_TILEDBG[slot].height = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_LoadTilesForBg();
|
|
void NF_LoadTilesForBg(const char* file, const char* name, u16 width, u16 height, u16 tile_start, u16 tile_end) {
|
|
|
|
// Variable temporal del tamaño de los datos
|
|
u32 tile_size = 0;
|
|
u32 pal_size = 0;
|
|
|
|
// Busca un slot libre
|
|
u8 n = 0;
|
|
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
|
|
}
|
|
}
|
|
// Si no hay ningun slot libre, error
|
|
if (slot == 255) {
|
|
NF_Error(103, "Tiled Bg", NF_SLOTS_TBG);
|
|
}
|
|
|
|
// Verifica que el fondo sea multiplo de 256px (32 tiles)
|
|
if (((width % 256) != 0) || ((height % 256) != 0)) {
|
|
NF_Error(115, file, 0);
|
|
}
|
|
|
|
// Vacia los buffers que se usaran
|
|
free(NF_BUFFER_BGMAP[slot]); // Buffer para los mapas
|
|
NF_BUFFER_BGMAP[slot] = NULL;
|
|
free(NF_BUFFER_BGTILES[slot]); // Buffer para los tiles
|
|
NF_BUFFER_BGTILES[slot] = NULL;
|
|
free(NF_BUFFER_BGPAL[slot]); // Buffer para los paletas
|
|
NF_BUFFER_BGPAL[slot] = NULL;
|
|
|
|
// Declara los punteros a los ficheros
|
|
FILE* file_id;
|
|
|
|
// Variable para almacenar el path al archivo
|
|
char filename[256];
|
|
|
|
// Carga el archivo .IMG
|
|
sprintf(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
|
|
fseek(file_id, 0, SEEK_END);
|
|
tile_size = ftell(file_id);
|
|
rewind(file_id);
|
|
// Calcula el tamaño del tilesize a cargar
|
|
NF_TILEDBG[slot].tilesize = (((tile_end - tile_start) + 1) << 6); // nº de tiles x 64 bytes
|
|
// Si el tamaño del Tilesed solicitado excede del tamaño de archivo, error
|
|
if (((tile_end + 1) << 6) > tile_size) {
|
|
NF_Error(106, "Tilenumber", (tile_size >> 6));
|
|
}
|
|
// 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
|
|
NF_Error(102, NULL, NF_TILEDBG[slot].tilesize);
|
|
}
|
|
// Posicionate en la posicion donde esta el primer tile a cargar
|
|
fseek(file_id, (tile_start << 6), SEEK_SET);
|
|
// ahora lee el archivo y ponlo en la 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
|
|
|
|
|
|
// Crea un archivo .MAP vacio en RAM
|
|
// ((ancho / 8) * (alto / 8)) * 2
|
|
NF_TILEDBG[slot].mapsize = (((width >> 3) * (height >> 3)) << 1);
|
|
// 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);
|
|
}
|
|
// Y ponlo a 0
|
|
memset(NF_BUFFER_BGMAP[slot], 0, NF_TILEDBG[slot].mapsize);
|
|
|
|
|
|
// Carga el archivo .PAL
|
|
sprintf(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
|
|
fseek(file_id, 0, SEEK_END);
|
|
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
|
|
sprintf(NF_TILEDBG[slot].name, "%s", name);
|
|
|
|
// Y las medidas
|
|
NF_TILEDBG[slot].width = width;
|
|
NF_TILEDBG[slot].height = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_UnloadTiledBg();
|
|
void NF_UnloadTiledBg(const char* name) {
|
|
|
|
// Busca el fondo solicitado
|
|
u16 n = 0; // Bucle
|
|
u8 slot = 255; // Slot seleccionado
|
|
char bg[32]; // Nombre
|
|
|
|
// Busca el fondo solicitado
|
|
sprintf(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
|
|
}
|
|
}
|
|
// Si no se encuentra, error
|
|
if (slot == 255) {
|
|
NF_Error(104, name, 0);
|
|
}
|
|
|
|
// Vacia los buffers que se usaran
|
|
free(NF_BUFFER_BGMAP[slot]); // Buffer para los mapas
|
|
NF_BUFFER_BGMAP[slot] = NULL;
|
|
free(NF_BUFFER_BGTILES[slot]); // Buffer para los tiles
|
|
NF_BUFFER_BGTILES[slot] = NULL;
|
|
free(NF_BUFFER_BGPAL[slot]); // Buffer para los paletas
|
|
NF_BUFFER_BGPAL[slot] = NULL;
|
|
|
|
// Resetea las variables para ese fondo
|
|
sprintf(NF_TILEDBG[slot].name, "xxxNONAMExxx"); // Nombre del Tileset
|
|
NF_TILEDBG[slot].tilesize = 0; // Tamaño del Tileset
|
|
NF_TILEDBG[slot].mapsize = 0; // Tamaño del Mapa
|
|
NF_TILEDBG[slot].palsize = 0; // Tamaño de la Paleta
|
|
NF_TILEDBG[slot].width = 0; // Ancho del Mapa
|
|
NF_TILEDBG[slot].height = 0; // Alto del Mapa
|
|
NF_TILEDBG[slot].available = true; // Disponibilidad
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_CreateTiledBg();
|
|
void NF_CreateTiledBg(u8 screen, u8 layer, const char* name) {
|
|
|
|
// Variables
|
|
u8 n = 0; // Bucle
|
|
u8 slot = 255; // Slot seleccionado
|
|
char bg[32]; // Nombre
|
|
|
|
// Busca el fondo solicitado
|
|
sprintf(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
|
|
}
|
|
}
|
|
// Si no se encuentra, error
|
|
if (slot == 255) {
|
|
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) {
|
|
NF_DeleteTiledBg(screen, layer);
|
|
}
|
|
|
|
// Variables de control de Tiles
|
|
u8 counter = 0;
|
|
u8 start = 255;
|
|
u8 tilesblocks = 0;
|
|
u8 basetiles = 0;
|
|
|
|
// 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 si es Infinito ( >512 )
|
|
// ( >512 x n )
|
|
if ((NF_TILEDBG[slot].width >= 512) && (NF_TILEDBG[slot].height <= 256)) {
|
|
NF_TILEDBG_LAYERS[screen][layer].mapwidth = 512;
|
|
NF_TILEDBG_LAYERS[screen][layer].mapheight = NF_TILEDBG[slot].height;
|
|
NF_TILEDBG_LAYERS[screen][layer].bgtype = 1;
|
|
}
|
|
// ( n x >512 )
|
|
if ((NF_TILEDBG[slot].width <= 256) && (NF_TILEDBG[slot].height >= 512)) {
|
|
NF_TILEDBG_LAYERS[screen][layer].mapwidth = NF_TILEDBG[slot].width;
|
|
NF_TILEDBG_LAYERS[screen][layer].mapheight = 512;
|
|
NF_TILEDBG_LAYERS[screen][layer].bgtype = 2;
|
|
}
|
|
// ( >512 x >512 )
|
|
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 = 3;
|
|
}
|
|
|
|
// Busca un los bloques libres para almacenar los Tiles en VRAM
|
|
tilesblocks = ((NF_TILEDBG[slot].tilesize - 1) >> 14) + 1; // Bloques necesarios para el Tileset
|
|
|
|
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
|
|
}
|
|
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
|
|
}
|
|
}
|
|
|
|
// Si no se han encontrado bloques libres
|
|
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
|
|
}
|
|
|
|
// Variables de control de Maps
|
|
u8 mapblocks = 0;
|
|
u8 basemap = 0;
|
|
counter = 0;
|
|
start = 255;
|
|
u16 mapsize = 0;
|
|
|
|
// Busca un los bloques libres para almacenar los Mapas en VRAM
|
|
if (NF_TILEDBG_LAYERS[screen][layer].bgtype == 0) {
|
|
// Si el mapa es normal =<512
|
|
mapblocks = ((NF_TILEDBG[slot].mapsize - 1) >> 11) + 1;
|
|
} else {
|
|
// Si el mapa es infinito >512
|
|
mapsize = (((NF_TILEDBG_LAYERS[screen][layer].mapwidth >> 3) * (NF_TILEDBG_LAYERS[screen][layer].mapheight >> 3)) << 1);
|
|
mapblocks = ((mapsize - 1) >> 11) + 1;
|
|
}
|
|
|
|
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
|
|
}
|
|
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
|
|
}
|
|
}
|
|
|
|
// Si no se han encontrado bloques libres
|
|
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
|
|
}
|
|
|
|
|
|
// Obten el tamaño del fondo
|
|
u32 bg_size = 0;
|
|
// 256x256
|
|
if ((NF_TILEDBG_LAYERS[screen][layer].mapwidth == 256) && (NF_TILEDBG_LAYERS[screen][layer].mapheight == 256)) {
|
|
bg_size = BG_32x32;
|
|
}
|
|
// 512x256
|
|
if ((NF_TILEDBG_LAYERS[screen][layer].mapwidth == 512) && (NF_TILEDBG_LAYERS[screen][layer].mapheight == 256)) {
|
|
bg_size = BG_64x32;
|
|
}
|
|
// 256x512
|
|
if ((NF_TILEDBG_LAYERS[screen][layer].mapwidth == 256) && (NF_TILEDBG_LAYERS[screen][layer].mapheight == 512)) {
|
|
bg_size = BG_32x64;
|
|
}
|
|
// 512x512
|
|
if ((NF_TILEDBG_LAYERS[screen][layer].mapwidth == 512) && (NF_TILEDBG_LAYERS[screen][layer].mapheight == 512)) {
|
|
bg_size = BG_64x64;
|
|
}
|
|
|
|
|
|
// Crea el fondo segun la pantalla, capa y demas caracteristicas dadas
|
|
// REG_BG0CNT <- Carracteristicas del fondo
|
|
// REG_BG0HOFS <- Posicion X
|
|
// REG_BG0VOFS <- Posicion Y
|
|
if (screen == 0) {
|
|
switch (layer) {
|
|
case 0:
|
|
REG_BG0CNT = BgType_Text8bpp | bg_size | BG_PRIORITY_0 | BG_PALETTE_SLOT0 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap);
|
|
break;
|
|
case 1:
|
|
REG_BG1CNT = BgType_Text8bpp | bg_size | BG_PRIORITY_1 | BG_PALETTE_SLOT1 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap);
|
|
break;
|
|
case 2:
|
|
REG_BG2CNT = BgType_Text8bpp | bg_size | BG_PRIORITY_2 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap);
|
|
break;
|
|
case 3:
|
|
REG_BG3CNT = BgType_Text8bpp | bg_size | BG_PRIORITY_3 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap);
|
|
break;
|
|
}
|
|
} else {
|
|
switch (layer) {
|
|
case 0:
|
|
REG_BG0CNT_SUB = BgType_Text8bpp | bg_size | BG_PRIORITY_0 | BG_PALETTE_SLOT0 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap);
|
|
break;
|
|
case 1:
|
|
REG_BG1CNT_SUB = BgType_Text8bpp | bg_size | BG_PRIORITY_1 | BG_PALETTE_SLOT1 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap);
|
|
break;
|
|
case 2:
|
|
REG_BG2CNT_SUB = BgType_Text8bpp | bg_size | BG_PRIORITY_2 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap);
|
|
break;
|
|
case 3:
|
|
REG_BG3CNT_SUB = BgType_Text8bpp | bg_size | BG_PRIORITY_3 | BG_COLOR_256 | BG_TILE_BASE(basetiles) | BG_MAP_BASE(basemap);
|
|
break;
|
|
}
|
|
}
|
|
|
|
u32 address; // Variable de direccion de VRAM;
|
|
|
|
// 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);
|
|
|
|
|
|
// Transfiere el Mapa a VRAM
|
|
if (screen == 0) { // (VRAM_A)
|
|
address = (0x6000000) + (basemap << 11);
|
|
} else { // (VRAM_C)
|
|
address = (0x6200000) + (basemap << 11);
|
|
}
|
|
|
|
if (NF_TILEDBG_LAYERS[screen][layer].bgtype == 0) {
|
|
|
|
// Si el mapa es normal
|
|
NF_DmaMemCopy((void*)address, NF_BUFFER_BGMAP[slot], NF_TILEDBG[slot].mapsize);
|
|
|
|
} else {
|
|
|
|
// Segun el tipo de mapa infinito
|
|
switch (NF_TILEDBG_LAYERS[screen][layer].bgtype) {
|
|
|
|
case 1: // >512x256
|
|
// Bloque A y B (32x32) + (32x32) (2kb x 2 = 4kb)
|
|
NF_DmaMemCopy((void*)address, NF_BUFFER_BGMAP[slot], 4096);
|
|
break;
|
|
|
|
case 2: // 256x>512
|
|
// Bloque A (32x64) (2kb x 2 = 4kb)
|
|
NF_DmaMemCopy((void*)address, NF_BUFFER_BGMAP[slot], 4096);
|
|
break;
|
|
|
|
case 3: // >512x>512
|
|
// Bloque A y B (32x32) + (32x32) (2kb x 2 = 4kb)
|
|
NF_DmaMemCopy((void*)address, NF_BUFFER_BGMAP[slot], 4096);
|
|
// Bloque (+4096) C y D (32x32) + (32x32) (2kb x 2 = 4kb)
|
|
u16 nextrow = 0; // Desplazamiento para cargar la fila inferior
|
|
nextrow = ((((NF_TILEDBG_LAYERS[screen][layer].bgwidth - 1) >> 8) + 1) << 11);
|
|
NF_DmaMemCopy((void*)(address + 4096), (NF_BUFFER_BGMAP[slot] + nextrow), 4096);
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Tranfiere la Paleta a VRAM
|
|
if (screen == 0) {
|
|
|
|
vramSetBankE(VRAM_E_LCD);
|
|
address = (0x06880000) + (layer << 13);
|
|
NF_DmaMemCopy((void*)address, NF_BUFFER_BGPAL[slot], NF_TILEDBG[slot].palsize);
|
|
vramSetBankE(VRAM_E_BG_EXT_PALETTE);
|
|
|
|
} else { // Paletas de la pantalla 1 (VRAM_H)
|
|
|
|
vramSetBankH(VRAM_H_LCD);
|
|
address = (0x06898000) + (layer << 13);
|
|
NF_DmaMemCopy((void*)address, NF_BUFFER_BGPAL[slot], NF_TILEDBG[slot].palsize);
|
|
vramSetBankH(VRAM_H_SUB_BG_EXT_PALETTE);
|
|
|
|
}
|
|
|
|
// 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 ?
|
|
|
|
// Posiciona el fondo en las coordenadas 0,0
|
|
NF_ScrollBg(screen, layer, 0, 0);
|
|
|
|
// Haz visible el fondo creado
|
|
NF_ShowBg(screen, layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_DeleteTiledBg();
|
|
void NF_DeleteTiledBg(u8 screen, u8 layer) {
|
|
|
|
// Verifica que el fondo esta creado
|
|
if (!NF_TILEDBG_LAYERS[screen][layer].created) {
|
|
char text[32];
|
|
sprintf(text, "%d", screen);
|
|
NF_Error(105, text, layer); // Si no existe, error
|
|
}
|
|
|
|
// Esconde el fondo creado
|
|
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
|
|
|
|
// 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
|
|
|
|
// 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
|
|
|
|
|
|
// Borra la Paleta a VRAM
|
|
if (screen == 0) {
|
|
|
|
vramSetBankE(VRAM_E_LCD);
|
|
address = (0x06880000) + (layer << 13);
|
|
memset((void*)address, 0, 8192);
|
|
vramSetBankE(VRAM_E_BG_EXT_PALETTE);
|
|
|
|
} else { // Paletas de la pantalla 1 (VRAM_H)
|
|
|
|
vramSetBankH(VRAM_H_LCD);
|
|
address = (0x06898000) + (layer << 13);
|
|
memset((void*)address, 0, 8192);
|
|
vramSetBankH(VRAM_H_SUB_BG_EXT_PALETTE);
|
|
|
|
}
|
|
|
|
|
|
// Marca como libres los bancos de Tiles usados por este fondo
|
|
tilesize = (basetiles + NF_TILEDBG_LAYERS[screen][layer].tileblocks);
|
|
for (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 ++) {
|
|
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 ?
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_GetTileMapAddress();
|
|
u32 NF_GetTileMapAddress(u8 screen, u8 layer, u16 tile_x, u16 tile_y) {
|
|
|
|
// Verifica que el fondo esta creado
|
|
if (!NF_TILEDBG_LAYERS[screen][layer].created) {
|
|
char text[32];
|
|
sprintf(text, "%d", screen);
|
|
NF_Error(105, text, layer); // Si no existe, error
|
|
}
|
|
|
|
// Obtiene las medidas en tiles del mapa
|
|
u16 size_x = (NF_TILEDBG_LAYERS[screen][layer].bgwidth >> 3); // Tiles de ancho
|
|
u16 size_y = (NF_TILEDBG_LAYERS[screen][layer].bgheight >> 3); // Tiles de alto
|
|
u16 block_x = (tile_x >> 5); // nº de pantalla (X)
|
|
u16 block_y = (tile_y >> 5); // nº de pantalla (Y)
|
|
u32 row_size = ((size_x >> 5) << 11); // Tamaño en bytes de una fila de pantallas
|
|
|
|
// Protegete de los fuera de rango
|
|
if (tile_x > size_x) NF_Error(106, "Tile X", size_x);
|
|
if (tile_y > size_y) NF_Error(106, "Tile Y", size_y);
|
|
|
|
// Calcula la posicion de memoria que deberas leer
|
|
// El mapa esta ordenado en bloques de 32x32 tiles, en filas.
|
|
u32 scr_y = (block_y * row_size); // Desplazamiento en memoria, bloques de pantallas (32x32) sobre Y
|
|
u32 scr_x = (block_x << 11); // Desplazamiento en memoria, bloques de pantallas (32x32) sobre X
|
|
u32 tls_y = ((tile_y - (block_y << 5)) << 5); // Desplazamiento en memoria, tiles sobre X
|
|
u32 tls_x = (tile_x - (block_x << 5)); // Desplazamiento en memoria, tiles sobre Y
|
|
u32 address = scr_y + scr_x + ((tls_y + tls_x) << 1);
|
|
|
|
// Devuelve el la direccion en el buffer del Tile
|
|
return address;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_GetTileOfMap();
|
|
u16 NF_GetTileOfMap(u8 screen, u8 layer, u16 tile_x, u16 tile_y) {
|
|
|
|
// Obten la direccion en el buffer del Tile
|
|
u32 address = NF_GetTileMapAddress(screen, layer, tile_x, tile_y);
|
|
|
|
// Obten los bytes
|
|
u8 lobyte = *(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + address);
|
|
u8 hibyte = *(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (address + 1));
|
|
|
|
// Devuelve el valor del tile
|
|
return ((hibyte << 8) | lobyte);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_SetTileOfMap();
|
|
void NF_SetTileOfMap(u8 screen, u8 layer, u16 tile_x, u16 tile_y, u16 tile) {
|
|
|
|
// Obten la direccion en el buffer del Tile
|
|
u32 address = NF_GetTileMapAddress(screen, layer, tile_x, tile_y);
|
|
|
|
// Calcula los valores para el HI-Byte y el LO-Byte
|
|
u8 hibyte = ((tile >> 8) & 0xff);
|
|
u8 lobyte = (tile & 0xff);
|
|
|
|
// Graba los bytes
|
|
*(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + address) = lobyte;
|
|
*(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (address + 1)) = hibyte;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_UpdateVramMap();
|
|
void NF_UpdateVramMap(u8 screen, u8 layer) {
|
|
|
|
// Verifica que el fondo esta creado
|
|
if (!NF_TILEDBG_LAYERS[screen][layer].created) {
|
|
char text[32];
|
|
sprintf(text, "%d", screen);
|
|
NF_Error(105, text, layer); // Si no existe, error
|
|
}
|
|
|
|
// Variables
|
|
u32 address = 0; // Direccion de destino
|
|
u32 mov_x = 0; // Desplazamiento X
|
|
u32 mov_y = 0; // Desplazamiento Y
|
|
u32 rowsize = 0; // Tamaño de la fila de pantallas
|
|
|
|
// Calcula la direccion base del mapa
|
|
if (screen == 0) { // (VRAM_A)
|
|
address = (0x6000000) + (NF_TILEDBG_LAYERS[screen][layer].mapbase << 11);
|
|
} else { // (VRAM_C)
|
|
address = (0x6200000) + (NF_TILEDBG_LAYERS[screen][layer].mapbase << 11);
|
|
}
|
|
|
|
// Segun el tipo de mapa
|
|
switch (NF_TILEDBG_LAYERS[screen][layer].bgtype) {
|
|
|
|
case 0: // 256x256 - Bloque A (32x32) (2kb)
|
|
// Copias el Bloque A (32x32) (2kb)
|
|
NF_DmaMemCopy((void*)address, NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot], 2048);
|
|
break;
|
|
|
|
case 1: // 512x256 - Bloque A y B (32x32) + (32x32) (2kb x 2 = 4kb)
|
|
// Calcula el desplazamiento de datos
|
|
mov_x = (NF_TILEDBG_LAYERS[screen][layer].blockx << 11);
|
|
// Copias los Bloques A y B (32x32) + (32x32) (2kb x 2 = 4kb)
|
|
NF_DmaMemCopy((void*)address, (NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + mov_x), 4096);
|
|
break;
|
|
|
|
|
|
case 2: // 256x512 - Bloque A (32x64) (2kb x 2 = 4kb)
|
|
// Calcula el desplazamiento de datos
|
|
mov_y = (NF_TILEDBG_LAYERS[screen][layer].blocky << 11);
|
|
// Copias los Bloques A y B (32x32) + (32x32) (2kb x 2 = 4kb)
|
|
NF_DmaMemCopy((void*)address, (NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + mov_y), 4096);
|
|
break;
|
|
|
|
case 3: // >512x>512
|
|
// Calcula el Rowsize
|
|
rowsize = (((((NF_TILEDBG_LAYERS[screen][layer].bgwidth - 1) >> 8)) + 1) << 11);
|
|
// Y el desplazamiento de datos
|
|
mov_x = (NF_TILEDBG_LAYERS[screen][layer].blocky * rowsize) + (NF_TILEDBG_LAYERS[screen][layer].blockx << 11);
|
|
mov_y = mov_x + rowsize;
|
|
// Bloque A y B (32x32) + (32x32) (2kb x 2 = 4kb)
|
|
NF_DmaMemCopy((void*)address, (NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + mov_x), 4096);
|
|
// Bloque (+4096) C y D (32x32) + (32x32) (2kb x 2 = 4kb)
|
|
NF_DmaMemCopy((void*)(address + 4096), (NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + mov_y), 4096);
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funcion NF_BgSetPalColor();
|
|
void NF_BgSetPalColor(u8 screen, u8 layer, u8 number, u8 r, u8 g, u8 b) {
|
|
|
|
// Verifica que el fondo esta creado
|
|
if (!NF_TILEDBG_LAYERS[screen][layer].created) {
|
|
char text[32];
|
|
sprintf(text, "%d", screen);
|
|
NF_Error(105, text, layer); // Si no existe, error
|
|
}
|
|
|
|
// Calcula el valor RGB
|
|
u16 rgb = ((r)|((g) << 5)|((b) << 10));
|
|
// Direccion en VRAM
|
|
u32 address = 0;
|
|
|
|
// Modifica la paleta
|
|
if (screen == 0) {
|
|
|
|
vramSetBankE(VRAM_E_LCD);
|
|
address = (0x06880000) + (layer << 13) + (number << 1);
|
|
*((u16*)address) = rgb;
|
|
vramSetBankE(VRAM_E_BG_EXT_PALETTE);
|
|
|
|
} else { // Paletas de la pantalla 1 (VRAM_H)
|
|
|
|
vramSetBankH(VRAM_H_LCD);
|
|
address = (0x06898000) + (layer << 13) + (number << 1);
|
|
*((u16*)address) = rgb;
|
|
vramSetBankH(VRAM_H_SUB_BG_EXT_PALETTE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_BgEditPalColor();
|
|
void NF_BgEditPalColor(u8 screen, u8 layer, u8 number, u8 r, u8 g, u8 b) {
|
|
|
|
// Verifica que el fondo esta creado
|
|
if (!NF_TILEDBG_LAYERS[screen][layer].created) {
|
|
char text[32];
|
|
sprintf(text, "%d", screen);
|
|
NF_Error(105, text, layer); // Si no existe, error
|
|
}
|
|
|
|
// Calcula el valor RGB
|
|
u16 rgb = ((r)|((g) << 5)|((b) << 10));
|
|
|
|
// Calcula los valores para el HI-Byte y el LO-Byte
|
|
u8 hibyte = ((rgb >> 8) & 0xff);
|
|
u8 lobyte = (rgb & 0xff);
|
|
|
|
// Graba los bytes
|
|
*(NF_BUFFER_BGPAL[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (number << 1)) = lobyte;
|
|
*(NF_BUFFER_BGPAL[NF_TILEDBG_LAYERS[screen][layer].bgslot] + ((number << 1) + 1)) = hibyte;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_BgUpdatePalette();
|
|
void NF_BgUpdatePalette(u8 screen, u8 layer) {
|
|
|
|
// Verifica que el fondo esta creado
|
|
if (!NF_TILEDBG_LAYERS[screen][layer].created) {
|
|
char text[32];
|
|
sprintf(text, "%d", screen);
|
|
NF_Error(105, text, layer); // Si no existe, error
|
|
}
|
|
|
|
// Direccion en VRAM
|
|
u32 address = 0;
|
|
|
|
// Obten el slot donde esta la paleta en RAM
|
|
u8 slot = NF_TILEDBG_LAYERS[screen][layer].bgslot;
|
|
|
|
// Tranfiere la Paleta a VRAM
|
|
if (screen == 0) {
|
|
|
|
vramSetBankE(VRAM_E_LCD);
|
|
address = (0x06880000) + (layer << 13);
|
|
NF_DmaMemCopy((void*)address, NF_BUFFER_BGPAL[slot], NF_TILEDBG[slot].palsize);
|
|
vramSetBankE(VRAM_E_BG_EXT_PALETTE);
|
|
|
|
} else { // Paletas de la pantalla 1 (VRAM_H)
|
|
|
|
vramSetBankH(VRAM_H_LCD);
|
|
address = (0x06898000) + (layer << 13);
|
|
NF_DmaMemCopy((void*)address, NF_BUFFER_BGPAL[slot], NF_TILEDBG[slot].palsize);
|
|
vramSetBankH(VRAM_H_SUB_BG_EXT_PALETTE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_BgGetPalColor();
|
|
void NF_BgGetPalColor(u8 screen, u8 layer, u8 number, u8* r, u8* g, u8* b) {
|
|
|
|
// Verifica que el fondo esta creado
|
|
if (!NF_TILEDBG_LAYERS[screen][layer].created) {
|
|
char text[32];
|
|
sprintf(text, "%d", screen);
|
|
NF_Error(105, text, layer); // Si no existe, error
|
|
}
|
|
|
|
// Obten los bytes
|
|
u8 lobyte = *(NF_BUFFER_BGPAL[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (number << 1));
|
|
u8 hibyte = *(NF_BUFFER_BGPAL[NF_TILEDBG_LAYERS[screen][layer].bgslot] + ((number << 1) + 1));
|
|
|
|
// Calcula el RGB (compuesto)
|
|
u16 rgb = ((hibyte << 8) | lobyte);
|
|
|
|
// Calcula los RGB
|
|
*r = (rgb & 0x1F);
|
|
*g = ((rgb >> 5) & 0x1F);
|
|
*b = ((rgb >> 10) & 0x1F);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_GetTilePal();
|
|
u8 NF_GetTilePal(u8 screen, u8 layer, u16 tile_x, u16 tile_y) {
|
|
|
|
// Obten la direccion en el buffer del Tile
|
|
u32 address = NF_GetTileMapAddress(screen, layer, tile_x, tile_y);
|
|
|
|
// Obten los bytes
|
|
u8 hibyte = *(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (address + 1));
|
|
|
|
// Devuelve el nº de la paleta (4 ultimos bits del HI-Byte)
|
|
return ((hibyte >> 4) & 0x0F);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_SetTilePal();
|
|
void NF_SetTilePal(u8 screen, u8 layer, u16 tile_x, u16 tile_y, u8 pal) {
|
|
|
|
// Obten la direccion en el buffer del Tile
|
|
u32 address = NF_GetTileMapAddress(screen, layer, tile_x, tile_y);
|
|
|
|
// Obten el valor actual del HI-Byte
|
|
u8 hibyte = *(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (address + 1));
|
|
|
|
// Y determina el valor del resto de datos del byte, excluyendo la paleta
|
|
u8 data = (hibyte & 0x0F);
|
|
|
|
// Graba los bytes
|
|
*(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (address + 1)) = ((pal << 4) | data);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_LoadExBgPal();
|
|
void NF_LoadExBgPal(const char* file, u8 slot) {
|
|
|
|
// Verifica el rango de Id's de Gfx
|
|
if (slot > (NF_SLOTS_EXBGPAL - 1)) {
|
|
NF_Error(106, "ExBgPal", (NF_SLOTS_EXBGPAL - 1));
|
|
}
|
|
|
|
// Variable temporal del tamaño de la paleta
|
|
u32 pal_size = 0;
|
|
|
|
// Vacia el buffer
|
|
free(NF_EXBGPAL[slot].buffer);
|
|
NF_EXBGPAL[slot].buffer = NULL;
|
|
|
|
// Declara los punteros a los ficheros
|
|
FILE* file_id;
|
|
|
|
// Variable para almacenar el path al archivo
|
|
char filename[256];
|
|
|
|
// Carga el archivo .PAL
|
|
sprintf(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
|
|
fseek(file_id, 0, SEEK_END);
|
|
pal_size = ftell(file_id);
|
|
NF_EXBGPAL[slot].palsize = pal_size;
|
|
rewind(file_id);
|
|
// Si el tamaño es inferior a 512 bytes, ajustalo
|
|
if (NF_EXBGPAL[slot].palsize < 512) NF_EXBGPAL[slot].palsize = 512;
|
|
// Reserva el espacio en RAM
|
|
NF_EXBGPAL[slot].buffer = (char*) calloc (NF_EXBGPAL[slot].palsize, sizeof(char));
|
|
if (NF_EXBGPAL[slot].buffer == NULL) { // Si no hay suficiente RAM libre
|
|
NF_Error(102, NULL, NF_EXBGPAL[slot].palsize);
|
|
}
|
|
// Lee el archivo y ponlo en la RAM
|
|
fread(NF_EXBGPAL[slot].buffer, 1, pal_size, file_id);
|
|
} else { // Si el archivo no existe...
|
|
NF_Error(101, filename, 0);
|
|
}
|
|
fclose(file_id); // Cierra el archivo
|
|
|
|
// Guarda el estado del slot
|
|
NF_EXBGPAL[slot].inuse = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_UnloadExBgPal();
|
|
void NF_UnloadExBgPal(u8 slot) {
|
|
|
|
// Verifica el rango de Id's de Gfx
|
|
if (slot > (NF_SLOTS_EXBGPAL - 1)) {
|
|
NF_Error(106, "ExBgPal", (NF_SLOTS_EXBGPAL - 1));
|
|
}
|
|
|
|
// Verifica si la Id esta cargada
|
|
if (!NF_EXBGPAL[slot].inuse) {
|
|
NF_Error(110, "ExBgPal", slot);
|
|
}
|
|
|
|
// Vacia el buffer
|
|
free(NF_EXBGPAL[slot].buffer);
|
|
NF_EXBGPAL[slot].buffer = NULL;
|
|
|
|
// Tamaño de la paleta a 0
|
|
NF_EXBGPAL[slot].palsize = 0;
|
|
|
|
// Guarda el estado del slot
|
|
NF_EXBGPAL[slot].inuse = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_VramExBgPal();
|
|
void NF_VramExBgPal(u8 screen, u8 layer, u8 id, u8 slot) {
|
|
|
|
// Verifica el rango de Id's de Gfx
|
|
if (slot > (NF_SLOTS_EXBGPAL - 1)) {
|
|
NF_Error(106, "ExBgPal", (NF_SLOTS_EXBGPAL - 1));
|
|
}
|
|
|
|
// Verifica si la Id esta cargada
|
|
if (!NF_EXBGPAL[slot].inuse) {
|
|
NF_Error(110, "ExBgPal", slot);
|
|
}
|
|
|
|
// Tranfiere la Paleta a VRAM
|
|
u32 address = 0;
|
|
if (screen == 0) {
|
|
vramSetBankE(VRAM_E_LCD);
|
|
address = (0x06880000) + (layer << 13) + (slot << 9);
|
|
NF_DmaMemCopy((void*)address, NF_EXBGPAL[id].buffer, NF_EXBGPAL[id].palsize);
|
|
vramSetBankE(VRAM_E_BG_EXT_PALETTE);
|
|
} else { // Paletas de la pantalla 1 (VRAM_H)
|
|
vramSetBankH(VRAM_H_LCD);
|
|
address = (0x06898000) + (layer << 13) + (slot << 9);
|
|
NF_DmaMemCopy((void*)address, NF_EXBGPAL[id].buffer, NF_EXBGPAL[id].palsize);
|
|
vramSetBankH(VRAM_H_SUB_BG_EXT_PALETTE);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_SetExBgPal();
|
|
void NF_SetExBgPal(u8 screen, u8 layer, u8 pal) {
|
|
|
|
// Verifica el rango de Id's de Gfx
|
|
if (pal > 15) {
|
|
NF_Error(106, "ExBgPal", (NF_SLOTS_EXBGPAL - 1));
|
|
}
|
|
|
|
// Verifica que el fondo esta creado
|
|
if (!NF_TILEDBG_LAYERS[screen][layer].created) {
|
|
char text[32];
|
|
sprintf(text, "%d", screen);
|
|
NF_Error(105, text, layer); // Si no existe, error
|
|
}
|
|
|
|
// Tamaño del buffer
|
|
u32 mapsize = NF_TILEDBG[NF_TILEDBG_LAYERS[screen][layer].bgslot].mapsize;
|
|
// Variables comunes
|
|
u32 pos = 0;
|
|
u16 hibyte = 0;
|
|
u8 data = 0;
|
|
|
|
for (pos = 0; pos < mapsize; pos += 2) {
|
|
// Obten el valor actual del HI-Byte
|
|
hibyte = *(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (pos + 1));
|
|
// Y determina el valor del resto de datos del byte, excluyendo la paleta
|
|
data = (hibyte & 0x0F);
|
|
// Graba los bytes
|
|
*(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (pos + 1)) = ((pal << 4) | data);
|
|
}
|
|
|
|
// Actualiza el mapa en la VRAM
|
|
NF_UpdateVramMap(screen, layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_SetTileHflip();
|
|
void NF_SetTileHflip(u8 screen, u8 layer, u16 tile_x, u16 tile_y) {
|
|
|
|
// Obten la direccion en el buffer del Tile
|
|
u32 address = NF_GetTileMapAddress(screen, layer, tile_x, tile_y);
|
|
|
|
// Obten el valor actual del HI-Byte
|
|
u8 hibyte = *(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (address + 1));
|
|
|
|
// Invierte el BIT correspondiente a FLIP horizontal del tile (BIT 3)
|
|
hibyte ^= 0x04;
|
|
|
|
// Graba el valor actualizado
|
|
*(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (address + 1)) = hibyte;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Funcion NF_SetTileVflip();
|
|
void NF_SetTileVflip(u8 screen, u8 layer, u16 tile_x, u16 tile_y) {
|
|
|
|
// Obten la direccion en el buffer del Tile
|
|
u32 address = NF_GetTileMapAddress(screen, layer, tile_x, tile_y);
|
|
|
|
// Obten el valor actual del HI-Byte
|
|
u8 hibyte = *(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (address + 1));
|
|
|
|
// Invierte el BIT correspondiente a FLIP vertical del tile (BIT 4)
|
|
hibyte ^= 0x08;
|
|
|
|
// Graba el valor actualizado
|
|
*(NF_BUFFER_BGMAP[NF_TILEDBG_LAYERS[screen][layer].bgslot] + (address + 1)) = hibyte;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Funcion NF_RotateTileGfx();
|
|
void NF_RotateTileGfx(u8 slot, u16 tile, u8 rotation) {
|
|
|
|
// Buffers temporales
|
|
char* character_a;
|
|
character_a = NULL;
|
|
character_a = (char*) calloc (64, sizeof(char));
|
|
if (character_a == NULL) { // Si no hay suficiente RAM libre
|
|
NF_Error(102, NULL, 64);
|
|
}
|
|
char* character_b;
|
|
character_b = NULL;
|
|
character_b = (char*) calloc (64, sizeof(char));
|
|
if (character_b == NULL) { // Si no hay suficiente RAM libre
|
|
NF_Error(102, NULL, 64);
|
|
}
|
|
|
|
// Variables locales
|
|
s16 xa = 0;
|
|
s16 xb = 0;
|
|
s16 pos_a = 0;
|
|
s16 ya = 0;
|
|
s16 yb = 0;
|
|
s16 pos_b = 0;
|
|
|
|
// Copia el tile al buffer temporal A
|
|
memcpy(character_a, (NF_BUFFER_BGTILES[slot] + (tile << 6)), 64);
|
|
|
|
switch (rotation) {
|
|
|
|
case 1: // 90º a la derecha
|
|
xb = 7;
|
|
yb = 0;
|
|
for (ya = 0; ya < 8; ya ++) {
|
|
for (xa = 0; xa < 8; xa ++) {
|
|
pos_a = ((ya << 3) + xa);
|
|
pos_b = ((yb << 3) + xb);
|
|
character_b[pos_b] = character_a[pos_a];
|
|
yb ++;
|
|
if (yb > 7) {
|
|
yb = 0;
|
|
xb --;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2: // 90º a la izquierda
|
|
xb = 0;
|
|
yb = 7;
|
|
for (ya = 0; ya < 8; ya ++) {
|
|
for (xa = 0; xa < 8; xa ++) {
|
|
pos_a = ((ya << 3) + xa);
|
|
pos_b = ((yb << 3) + xb);
|
|
character_b[pos_b] = character_a[pos_a];
|
|
yb --;
|
|
if (yb < 0) {
|
|
yb = 7;
|
|
xb ++;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 3: // 180 º
|
|
xb = 7;
|
|
yb = 7;
|
|
for (ya = 0; ya < 8; ya ++) {
|
|
for (xa = 0; xa < 8; xa ++) {
|
|
pos_a = ((ya << 3) + xa);
|
|
pos_b = ((yb << 3) + xb);
|
|
character_b[pos_b] = character_a[pos_a];
|
|
xb --;
|
|
if (xb < 0) {
|
|
xb = 0;
|
|
yb --;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
// Copia el tile desde buffer temporal B
|
|
memcpy((NF_BUFFER_BGTILES[slot] + (tile << 6)), character_b, 64);
|
|
|
|
// Libera los buffers temporales
|
|
free (character_a);
|
|
free (character_b);
|
|
|
|
}
|