mirror of
https://github.com/AntonioND/nitro-engine.git
synced 2025-06-18 16:45:33 -04:00

The previous code relied too much on assertions, even for things that are just regular things that may happen while the application is running (like running out of memory). - Many assertions have been turned into permanent checks - Some functions now return "success" or "failure". - NE_Init3D() and NE_InitDual3D() (and others) have been reworked to handle failures gracefully.
317 lines
7.1 KiB
C
317 lines
7.1 KiB
C
// SPDX-License-Identifier: MIT
|
|
//
|
|
// Copyright (c) 2008-2011, 2019, 2022 Antonio Niño Díaz
|
|
//
|
|
// This file is part of Nitro Engine
|
|
|
|
#include "NEMain.h"
|
|
#include "NEAlloc.h"
|
|
|
|
/// @file NEPalette.c
|
|
|
|
typedef struct {
|
|
u16 *pointer;
|
|
int format;
|
|
} ne_palinfo_t;
|
|
|
|
static ne_palinfo_t *NE_PalInfo = NULL;
|
|
static NE_Palette **NE_UserPalette = NULL;
|
|
|
|
static NEChunk *NE_PalAllocList; // See NEAlloc.h
|
|
|
|
static bool ne_palette_system_inited = false;
|
|
|
|
static int NE_MAX_PALETTES;
|
|
|
|
NE_Palette *NE_PaletteCreate(void)
|
|
{
|
|
if (!ne_palette_system_inited)
|
|
{
|
|
NE_DebugPrint("System not initialized");
|
|
return NULL;
|
|
}
|
|
|
|
for (int i = 0; i < NE_MAX_PALETTES; i++)
|
|
{
|
|
if (NE_UserPalette[i] != NULL)
|
|
continue;
|
|
|
|
NE_Palette *ptr = malloc(sizeof(NE_Palette));
|
|
if (ptr == NULL)
|
|
{
|
|
NE_DebugPrint("Not enough memory");
|
|
return NULL;
|
|
}
|
|
|
|
ptr->index = NE_NO_PALETTE;
|
|
NE_UserPalette[i] = ptr;
|
|
return ptr;
|
|
}
|
|
|
|
NE_DebugPrint("No free slots");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int NE_PaletteLoadFAT(NE_Palette *pal, char *path, NE_TextureFormat format)
|
|
{
|
|
if (!ne_palette_system_inited)
|
|
return 0;
|
|
|
|
NE_AssertPointer(pal, "NULL palette pointer");
|
|
NE_AssertPointer(path, "NULL path pointer");
|
|
|
|
u32 size = NE_FATFileSize(path);
|
|
if (size < 1)
|
|
{
|
|
NE_DebugPrint("Couldn't obtain file size");
|
|
return 0;
|
|
}
|
|
|
|
char *ptr = NE_FATLoadData(path);
|
|
NE_AssertPointer(ptr, "Couldn't load file from FAT");
|
|
int ret = NE_PaletteLoadSize(pal, (u16 *)ptr, size, format);
|
|
free(ptr);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int NE_PaletteLoad(NE_Palette *pal, u16 *pointer, u16 numcolor,
|
|
NE_TextureFormat format)
|
|
{
|
|
if (!ne_palette_system_inited)
|
|
return 0;
|
|
|
|
NE_AssertPointer(pal, "NULL pointer");
|
|
|
|
if (pal->index != NE_NO_PALETTE)
|
|
{
|
|
NE_DebugPrint("Palette already loaded");
|
|
NE_PaletteDelete(pal);
|
|
}
|
|
|
|
int slot = NE_NO_PALETTE;
|
|
|
|
for (int i = 0; i < NE_MAX_PALETTES; i++)
|
|
{
|
|
if (NE_PalInfo[i].pointer == NULL)
|
|
{
|
|
slot = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (slot == NE_NO_PALETTE)
|
|
{
|
|
NE_DebugPrint("No free lots");
|
|
return 0;
|
|
}
|
|
|
|
NE_PalInfo[slot].pointer = NE_Alloc(NE_PalAllocList, numcolor << 1);
|
|
// Aligned to 16 bytes (except 8 bytes for NE_PAL4).
|
|
if (NE_PalInfo[slot].pointer == NULL)
|
|
{
|
|
NE_DebugPrint("Not enough memory");
|
|
return 0;
|
|
}
|
|
|
|
NE_PalInfo[slot].format = format;
|
|
|
|
pal->index = slot;
|
|
|
|
// Allow CPU writes to VRAM_E
|
|
vramSetBankE(VRAM_E_LCD);
|
|
swiCopy(pointer, NE_PalInfo[slot].pointer, (numcolor / 2) | COPY_MODE_WORD);
|
|
vramSetBankE(VRAM_E_TEX_PALETTE);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int NE_PaletteLoadSize(NE_Palette *pal, u16 *pointer, size_t size,
|
|
NE_TextureFormat format)
|
|
{
|
|
return NE_PaletteLoad(pal, pointer, size >> 1, format);
|
|
}
|
|
|
|
void NE_PaletteDelete(NE_Palette *pal)
|
|
{
|
|
if (!ne_palette_system_inited)
|
|
return;
|
|
|
|
NE_AssertPointer(pal, "NULL pointer");
|
|
|
|
// If there is an asigned palette...
|
|
if (pal->index != NE_NO_PALETTE)
|
|
{
|
|
NE_Free(NE_PalAllocList, (void *)NE_PalInfo[pal->index].pointer);
|
|
NE_PalInfo[pal->index].pointer = NULL;
|
|
}
|
|
|
|
for (int i = 0; i < NE_MAX_PALETTES; i++)
|
|
{
|
|
if (NE_UserPalette[i] == pal)
|
|
{
|
|
NE_UserPalette[i] = NULL;
|
|
free(pal);
|
|
return;
|
|
}
|
|
}
|
|
|
|
NE_DebugPrint("Material not found");
|
|
}
|
|
|
|
void NE_PaletteUse(const NE_Palette *pal)
|
|
{
|
|
NE_AssertPointer(pal, "NULL pointer");
|
|
NE_Assert(pal->index != NE_NO_PALETTE, "No asigned palette");
|
|
unsigned int shift = 4 - (NE_PalInfo[pal->index].format == NE_PAL4);
|
|
GFX_PAL_FORMAT = (uintptr_t)NE_PalInfo[pal->index].pointer >> shift;
|
|
}
|
|
|
|
int NE_PaletteSystemReset(int max_palettes)
|
|
{
|
|
if (ne_palette_system_inited)
|
|
NE_PaletteSystemEnd();
|
|
|
|
if (max_palettes < 1)
|
|
NE_MAX_PALETTES = NE_DEFAULT_PALETTES;
|
|
else
|
|
NE_MAX_PALETTES = max_palettes;
|
|
|
|
NE_PalInfo = calloc(NE_MAX_PALETTES, sizeof(ne_palinfo_t));
|
|
NE_UserPalette = calloc(NE_MAX_PALETTES, sizeof(NE_UserPalette));
|
|
if ((NE_PalInfo == NULL) || (NE_UserPalette == NULL))
|
|
goto cleanup;
|
|
|
|
if (NE_AllocInit(&NE_PalAllocList, (void *)VRAM_E, (void *)VRAM_F) != 0)
|
|
goto cleanup;
|
|
|
|
GFX_PAL_FORMAT = 0;
|
|
|
|
ne_palette_system_inited = true;
|
|
return 0;
|
|
|
|
cleanup:
|
|
NE_DebugPrint("Not enough memory");
|
|
free(NE_PalInfo);
|
|
free(NE_UserPalette);
|
|
return -1;
|
|
}
|
|
|
|
int NE_PaletteFreeMem(void)
|
|
{
|
|
if (!ne_palette_system_inited)
|
|
return 0;
|
|
|
|
NEMemInfo info;
|
|
NE_MemGetInformation(NE_PalAllocList, &info);
|
|
|
|
return info.free;
|
|
}
|
|
|
|
int NE_PaletteFreeMemPercent(void)
|
|
{
|
|
if (!ne_palette_system_inited)
|
|
return 0;
|
|
|
|
NEMemInfo info;
|
|
NE_MemGetInformation(NE_PalAllocList, &info);
|
|
|
|
return info.free_percent;
|
|
}
|
|
|
|
void NE_PaletteDefragMem(void)
|
|
{
|
|
NE_Assert(0, "This function doesn't work");
|
|
return;
|
|
|
|
// TODO: Fix
|
|
|
|
/*
|
|
if (!ne_palette_system_inited)
|
|
return;
|
|
|
|
vramSetBankE(VRAM_E_LCD);
|
|
bool ok = false;
|
|
while (!ok)
|
|
{
|
|
ok = true;
|
|
for (int i = 0; i < NE_MAX_PALETTES; i++)
|
|
{
|
|
int size = NE_GetSize(NE_PalAllocList, (void*)NE_PalInfo[i].pointer);
|
|
|
|
NE_Free(NE_PalAllocList, (void*)NE_PalInfo[i].pointer);
|
|
void *pointer = NE_Alloc(NE_PalAllocList, size);
|
|
// Aligned to 16 bytes (except 8 bytes for NE_PAL4).
|
|
|
|
NE_AssertPointer(pointer, "Couldn't reallocate palette");
|
|
|
|
if ((int)pointer != (int)NE_PalInfo[i].pointer)
|
|
{
|
|
dmaCopy((void*)NE_PalInfo[i].pointer, pointer, size);
|
|
|
|
NE_PalInfo[i].pointer = (void*)pointer;
|
|
ok = false;
|
|
}
|
|
}
|
|
}
|
|
vramSetBankE(VRAM_E_TEX_PALETTE);
|
|
*/
|
|
}
|
|
|
|
void NE_PaletteSystemEnd(void)
|
|
{
|
|
if (!ne_palette_system_inited)
|
|
return;
|
|
|
|
NE_AllocEnd(&NE_PalAllocList);
|
|
|
|
free(NE_PalInfo);
|
|
|
|
for (int i = 0; i < NE_MAX_PALETTES; i++)
|
|
{
|
|
if (NE_UserPalette[i])
|
|
free(NE_UserPalette[i]);
|
|
}
|
|
|
|
free(NE_UserPalette);
|
|
|
|
ne_palette_system_inited = false;
|
|
}
|
|
|
|
static u16 *palette_adress = NULL;
|
|
static int palette_format;
|
|
|
|
void *NE_PaletteModificationStart(const NE_Palette *pal)
|
|
{
|
|
NE_AssertPointer(pal, "NULL pointer");
|
|
NE_Assert(pal->index != NE_NO_PALETTE, "No asigned palette");
|
|
NE_Assert(palette_adress == NULL, "Another palette already active");
|
|
|
|
palette_adress = NE_PalInfo[pal->index].pointer;
|
|
palette_format = NE_PalInfo[pal->index].format;
|
|
|
|
// Enable CPU accesses to VRAM_E
|
|
vramSetBankE(VRAM_E_LCD);
|
|
|
|
return palette_adress;
|
|
}
|
|
|
|
void NE_PaletteRGB256SetColor(u8 colorindex, u16 color)
|
|
{
|
|
NE_AssertPointer(palette_adress, "No active palette");
|
|
NE_Assert(palette_format == NE_PAL256, "Active palette isn't NE_PAL256");
|
|
|
|
palette_adress[colorindex] = color;
|
|
}
|
|
|
|
void NE_PaletteModificationEnd(void)
|
|
{
|
|
NE_Assert(palette_adress != NULL, "No active palette");
|
|
|
|
// Disable CPU accesses to VRAM_E
|
|
vramSetBankE(VRAM_E_TEX_PALETTE);
|
|
|
|
palette_adress = NULL;
|
|
}
|