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

This helps the compiler issue warning if there is some logical error in the code, and it helps the developer realize if some assumption with the code is wrong.
794 lines
21 KiB
C
794 lines
21 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 NETexture.c
|
|
|
|
typedef struct {
|
|
u32 param;
|
|
char *adress;
|
|
NE_Palette *palette;
|
|
int uses;
|
|
int sizex, sizey;
|
|
} ne_textureinfo_t;
|
|
|
|
static ne_textureinfo_t *NE_Texture = NULL;
|
|
static NE_Material **NE_UserMaterials = NULL;
|
|
|
|
static NEChunk *NE_TexAllocList; // See NEAlloc.h
|
|
|
|
static bool ne_texture_system_inited = false;
|
|
|
|
static int NE_MAX_TEXTURES;
|
|
|
|
// Default material propierties
|
|
static u32 ne_defaultdiffuse, ne_defaultambient;
|
|
static u32 ne_defaultspecular, ne_defaultemission;
|
|
static bool ne_defaultvtxcolor, ne_defaultuseshininess;
|
|
|
|
static int __NE_GetValidSize(int size)
|
|
{
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
if (size <= (8 << i))
|
|
return (8 << i);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int __NE_ConvertSizeRaw(int size)
|
|
{
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
if (size == 8)
|
|
return i;
|
|
size >>= 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static inline void NE_MaterialTexParam(NE_Material *tex, int sizeX, int sizeY,
|
|
uint32 *addr, GL_TEXTURE_TYPE_ENUM mode,
|
|
u32 param)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
NE_Assert(tex->texindex != NE_NO_TEXTURE, "No assigned texture");
|
|
NE_Texture[tex->texindex].param = param
|
|
| (__NE_ConvertSizeRaw(sizeX) << 20)
|
|
| (__NE_ConvertSizeRaw(sizeY) << 23)
|
|
| (((uint32) addr >> 3) & 0xFFFF) | (mode << 26);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
NE_Material *NE_MaterialCreate(void)
|
|
{
|
|
if (!ne_texture_system_inited)
|
|
return NULL;
|
|
|
|
for (int i = 0; i < NE_MAX_TEXTURES; i++)
|
|
{
|
|
if (NE_UserMaterials[i] != NULL)
|
|
continue;
|
|
|
|
NE_Material *mat = calloc(1, sizeof(NE_Material));
|
|
NE_AssertPointer(mat, "Not enough memory");
|
|
NE_UserMaterials[i] = mat;
|
|
mat->texindex = NE_NO_TEXTURE;
|
|
mat->color = NE_White;
|
|
mat->diffuse = ne_defaultdiffuse;
|
|
mat->ambient = ne_defaultambient;
|
|
mat->specular = ne_defaultspecular;
|
|
mat->emission = ne_defaultemission;
|
|
mat->vtxcolor = ne_defaultvtxcolor;
|
|
mat->useshininess = ne_defaultuseshininess;
|
|
|
|
return mat;
|
|
}
|
|
|
|
NE_DebugPrint("No free slots");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void NE_MaterialColorSet(NE_Material *tex, u32 color)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
tex->color = color;
|
|
}
|
|
|
|
void NE_MaterialColorDelete(NE_Material *tex)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
tex->color = NE_White;
|
|
}
|
|
|
|
int NE_MaterialTexLoadFAT(NE_Material *tex, NE_TextureFormat fmt,
|
|
int sizeX, int sizeY, NE_TextureFlags flags,
|
|
char *path)
|
|
{
|
|
NE_AssertPointer(tex, "NULL material pointer");
|
|
NE_AssertPointer(path, "NULL path pointer");
|
|
NE_Assert(sizeX > 0 && sizeY > 0, "Size must be positive");
|
|
|
|
char *ptr = NE_FATLoadData(path);
|
|
NE_AssertPointer(ptr, "Couldn't load file from FAT");
|
|
|
|
int ret = NE_MaterialTexLoad(tex, fmt, sizeX, sizeY, flags, (u8 *)ptr);
|
|
free(ptr);
|
|
return ret;
|
|
}
|
|
|
|
static int __NE_TextureResizeWidth(void *source, void *dest,
|
|
NE_TextureFormat fmt,
|
|
int height, int width, int newwidth)
|
|
{
|
|
NE_AssertPointer(source, "NULL source pointer");
|
|
NE_AssertPointer(dest, "NULL dest pointer");
|
|
|
|
static const int __NE_TextureDepth[] = {
|
|
0, // Nothing
|
|
8, // NE_A3PAL32
|
|
2, // NE_PAL4
|
|
4, // NE_PAL16
|
|
8, // NE_PAL256
|
|
0, // NE_COMPRESSED
|
|
8, // NE_A5PAL8
|
|
16, // NE_A1RGB5
|
|
16 // NE_RGB5
|
|
};
|
|
|
|
int bits = __NE_TextureDepth[fmt];
|
|
|
|
if (bits == 16)
|
|
{
|
|
// NE_A1RGB5 or NE_RGB5
|
|
// --------------------
|
|
|
|
// Cast to correct width
|
|
u16 *d = dest;
|
|
u16 *s = source;
|
|
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < newwidth; x++)
|
|
{
|
|
if (x < width)
|
|
*d = *s++;
|
|
d++;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
else if (bits == 8)
|
|
{
|
|
// NE_PAL256, NE_A3PAL32 or NE_A5PAL8
|
|
// ----------------------------------
|
|
|
|
// Cast to correct width
|
|
u8 *d = dest;
|
|
u8 *s = source;
|
|
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < newwidth; x++)
|
|
{
|
|
if (x < width)
|
|
*d = *s++;
|
|
d++;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
else if (bits == 4)
|
|
{
|
|
// NE_PAL16
|
|
// --------
|
|
|
|
// Cast to correct width
|
|
u8 *d = dest;
|
|
u8 *s = source;
|
|
int src_idx = 0;
|
|
int dst_idx = 0;
|
|
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < newwidth; x++)
|
|
{
|
|
if (x < width)
|
|
{
|
|
if (dst_idx == 0)
|
|
*d = 0;
|
|
|
|
*d |= ((*s >> (src_idx << 2)) & 0xF)
|
|
<< (dst_idx << 2);
|
|
|
|
if (src_idx == 1)
|
|
s++;
|
|
src_idx ^= 1;
|
|
}
|
|
|
|
if (dst_idx == 1)
|
|
d++;
|
|
|
|
dst_idx ^= 1;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
else if (bits == 2)
|
|
{
|
|
// NE_PAL4
|
|
// -------
|
|
|
|
// Cast to correct width
|
|
u8 *d = dest;
|
|
u8 *s = source;
|
|
int src_idx = 0;
|
|
int dst_idx = 0;
|
|
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < newwidth; x++)
|
|
{
|
|
if (x < width)
|
|
{
|
|
if (dst_idx == 0)
|
|
*d = 0;
|
|
|
|
*d |= ((*s >> (src_idx << 1)) & 0x3)
|
|
<< (dst_idx << 1);
|
|
|
|
if (src_idx == 3)
|
|
s++;
|
|
src_idx = (src_idx + 1) & 3;
|
|
}
|
|
|
|
if (dst_idx == 3)
|
|
d++;
|
|
dst_idx = (dst_idx + 1) & 3;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const int __NE_TextureSizeShift[] = {
|
|
0, // Nothing
|
|
1, // NE_A3PAL32
|
|
3, // NE_PAL4
|
|
2, // NE_PAL16
|
|
1, // NE_PAL256
|
|
0, // NE_COMPRESSED
|
|
1, // NE_A5PAL8
|
|
0, // NE_A1RGB5
|
|
0, // NE_RGB5
|
|
};
|
|
|
|
int NE_MaterialTexLoad(NE_Material *tex, NE_TextureFormat fmt,
|
|
int sizeX, int sizeY, NE_TextureFlags flags,
|
|
void *texture)
|
|
{
|
|
NE_AssertPointer(tex, "NULL material pointer");
|
|
|
|
// Check if texture exists
|
|
if (tex->texindex != NE_NO_TEXTURE)
|
|
{
|
|
NE_MaterialDelete(tex);
|
|
tex = NE_MaterialCreate();
|
|
}
|
|
|
|
// Get free slot
|
|
tex->texindex = NE_NO_TEXTURE;
|
|
for (int i = 0; i < NE_MAX_TEXTURES; i++)
|
|
{
|
|
if (NE_Texture[i].adress == NULL)
|
|
{
|
|
tex->texindex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (tex->texindex == NE_NO_TEXTURE)
|
|
{
|
|
NE_DebugPrint("No free slots");
|
|
tex->texindex = 0;
|
|
return 0;
|
|
}
|
|
|
|
int slot = tex->texindex;
|
|
|
|
// Save real size
|
|
NE_Texture[slot].sizex = sizeX;
|
|
NE_Texture[slot].sizey = sizeY;
|
|
|
|
u32 size = 0;
|
|
|
|
// If width is not a power of 2
|
|
bool invalidwidth = false;
|
|
if (__NE_GetValidSize(sizeX) != sizeX)
|
|
{
|
|
invalidwidth = true;
|
|
// The width must be a power of 2, but this texture has an invalid size.
|
|
// Let's expand the texture so that it is valid, load it to VRAM, and
|
|
// delete the temporary buffer used to expand it.
|
|
|
|
size = (__NE_GetValidSize(sizeX) * sizeY << 1) >>
|
|
__NE_TextureSizeShift[fmt];
|
|
|
|
void *newbuffer = malloc(size);
|
|
NE_AssertPointer(newbuffer, "Not enough memory for temporary buffer");
|
|
|
|
if (__NE_TextureResizeWidth(texture, newbuffer, fmt, sizeY, sizeX,
|
|
__NE_GetValidSize(sizeX)) == 0)
|
|
{
|
|
free(newbuffer);
|
|
return 0;
|
|
}
|
|
// New width
|
|
sizeX = __NE_GetValidSize(sizeX);
|
|
|
|
// Use new data
|
|
texture = newbuffer;
|
|
}
|
|
|
|
// The height doesn't need to be power of 2, but we will have to cheat later
|
|
// and make the DS believe it is a power of 2.
|
|
if (!invalidwidth)
|
|
size = (sizeX * sizeY << 1) >> __NE_TextureSizeShift[fmt];
|
|
|
|
u32 *addr = (u32 *) NE_Alloc(NE_TexAllocList, size, 8);
|
|
|
|
if (!addr)
|
|
{
|
|
NE_DebugPrint("Not enough memory");
|
|
if (invalidwidth)
|
|
free(texture); // Free temp data
|
|
return 0;
|
|
}
|
|
|
|
NE_Texture[slot].adress = (void *)addr;
|
|
// Initially only this material is using this texture
|
|
NE_Texture[slot].uses = 1;
|
|
|
|
// unlock texture memory
|
|
u32 vramTemp = vramSetPrimaryBanks(VRAM_A_LCD, VRAM_B_LCD, VRAM_C_LCD,
|
|
VRAM_D_LCD);
|
|
|
|
// We do NE_RGB5 as NE_A1RGB5, but we set each alpha bit to 1 during the
|
|
// copy to VRAM.
|
|
if (fmt == NE_RGB5)
|
|
{
|
|
u16 *src = (u16 *)texture;
|
|
u16 *dest = (u16 *)addr;
|
|
NE_MaterialTexParam(tex, sizeX, __NE_GetValidSize(sizeY), addr,
|
|
NE_A1RGB5, flags);
|
|
|
|
while (size--)
|
|
{
|
|
*dest++ = *src | (1 << 15);
|
|
src++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// For everything else, we do a straight copy
|
|
NE_MaterialTexParam(tex, sizeX, __NE_GetValidSize(sizeY), addr,
|
|
fmt, flags);
|
|
|
|
swiCopy((u32 *)texture, addr, (size >> 2) | COPY_MODE_WORD);
|
|
}
|
|
|
|
vramRestorePrimaryBanks(vramTemp);
|
|
if (invalidwidth)
|
|
free(texture); // Free temp data
|
|
|
|
return 1;
|
|
}
|
|
|
|
void NE_MaterialTexClone(NE_Material *source, NE_Material *dest)
|
|
{
|
|
NE_AssertPointer(source, "NULL source pointer");
|
|
NE_AssertPointer(dest, "NULL dest pointer");
|
|
NE_Assert(source->texindex != NE_NO_TEXTURE,
|
|
"No texture asigned to source material");
|
|
// Increase count of materials using this texture
|
|
NE_Texture[source->texindex].uses++;
|
|
dest->texindex = source->texindex;
|
|
}
|
|
|
|
void NE_MaterialTexSetPal(NE_Material *tex, NE_Palette *pal)
|
|
{
|
|
NE_AssertPointer(tex, "NULL material pointer");
|
|
NE_AssertPointer(pal, "NULL palette pointer");
|
|
NE_Assert(tex->texindex != NE_NO_TEXTURE, "No texture asigned to material");
|
|
NE_Texture[tex->texindex].palette = pal;
|
|
}
|
|
|
|
void NE_MaterialUse(const NE_Material *tex)
|
|
{
|
|
if (tex == NULL)
|
|
{
|
|
GFX_TEX_FORMAT = 0;
|
|
GFX_COLOR = NE_White;
|
|
GFX_DIFFUSE_AMBIENT = ne_defaultdiffuse
|
|
| (ne_defaultambient << 16)
|
|
| (ne_defaultvtxcolor << 15);
|
|
GFX_SPECULAR_EMISSION = ne_defaultspecular
|
|
| (ne_defaultemission << 16)
|
|
| (ne_defaultuseshininess << 15);
|
|
return;
|
|
}
|
|
|
|
GFX_DIFFUSE_AMBIENT = tex->diffuse | (tex->ambient << 16)
|
|
| (tex->vtxcolor << 15);
|
|
GFX_SPECULAR_EMISSION = tex->specular | (tex->emission << 16)
|
|
| (tex->useshininess << 15);
|
|
|
|
NE_Assert(tex->texindex != NE_NO_TEXTURE,
|
|
"No texture asigned to material");
|
|
|
|
if (NE_Texture[tex->texindex].palette)
|
|
NE_PaletteUse(NE_Texture[tex->texindex].palette);
|
|
|
|
GFX_COLOR = (u32) tex->color;
|
|
GFX_TEX_FORMAT = NE_Texture[tex->texindex].param;
|
|
}
|
|
|
|
extern bool NE_Dual;
|
|
|
|
void NE_TextureSystemReset(int max_textures, int max_palettes,
|
|
NE_VRAMBankFlags bank_flags)
|
|
{
|
|
if (ne_texture_system_inited)
|
|
NE_TextureSystemEnd();
|
|
|
|
if (max_textures < 1)
|
|
NE_MAX_TEXTURES = NE_DEFAULT_TEXTURES;
|
|
else
|
|
NE_MAX_TEXTURES = max_textures;
|
|
|
|
NE_AllocInit(&NE_TexAllocList, (void *)VRAM_A, (void *)VRAM_E);
|
|
|
|
NE_Assert((bank_flags & 0xF) != 0, "No VRAM banks selected");
|
|
|
|
// Prevent user from not selecting any bank
|
|
if ((bank_flags & 0xF) == 0)
|
|
bank_flags = NE_VRAM_ABCD;
|
|
|
|
// VRAM_C and VRAM_D can't be used in dual 3D mode
|
|
if (NE_Dual)
|
|
bank_flags &= ~NE_VRAM_CD;
|
|
|
|
// Now, configure allocation system. The buffer size always sees the
|
|
// four banks of VRAM. It is needed to allocate one chunk for each and
|
|
// lock the ones that aren't allowed to be used by Nitro Engine.
|
|
|
|
NE_Alloc(NE_TexAllocList, 128 * 1024, 0); // VRAM_A
|
|
NE_Alloc(NE_TexAllocList, 128 * 1024, 0); // VRAM_B
|
|
NE_Alloc(NE_TexAllocList, 128 * 1024, 0); // VRAM_C
|
|
NE_Alloc(NE_TexAllocList, 128 * 1024, 0); // VRAM_D
|
|
|
|
if (bank_flags & NE_VRAM_A)
|
|
{
|
|
vramSetBankA(VRAM_A_TEXTURE_SLOT0);
|
|
NE_Free(NE_TexAllocList, VRAM_A);
|
|
}
|
|
else
|
|
{
|
|
NE_Lock(NE_TexAllocList, VRAM_A);
|
|
}
|
|
|
|
if (bank_flags & NE_VRAM_B)
|
|
{
|
|
vramSetBankB(VRAM_B_TEXTURE_SLOT1);
|
|
NE_Free(NE_TexAllocList, VRAM_B);
|
|
}
|
|
else
|
|
{
|
|
NE_Lock(NE_TexAllocList, VRAM_B);
|
|
}
|
|
|
|
if (bank_flags & NE_VRAM_C)
|
|
{
|
|
vramSetBankC(VRAM_C_TEXTURE_SLOT2);
|
|
NE_Free(NE_TexAllocList, VRAM_C);
|
|
}
|
|
else
|
|
{
|
|
NE_Lock(NE_TexAllocList, VRAM_C);
|
|
}
|
|
|
|
if (bank_flags & NE_VRAM_D)
|
|
{
|
|
vramSetBankD(VRAM_D_TEXTURE_SLOT3);
|
|
NE_Free(NE_TexAllocList, VRAM_D);
|
|
}
|
|
else
|
|
{
|
|
NE_Lock(NE_TexAllocList, VRAM_D);
|
|
}
|
|
|
|
NE_Texture = calloc(NE_MAX_TEXTURES, sizeof(ne_textureinfo_t));
|
|
NE_AssertPointer(NE_Texture, "Not enough memory");
|
|
NE_UserMaterials = calloc(NE_MAX_TEXTURES, sizeof(NE_UserMaterials));
|
|
NE_AssertPointer(NE_UserMaterials, "Not enough memory");
|
|
|
|
NE_PaletteSystemReset(max_palettes);
|
|
|
|
GFX_TEX_FORMAT = 0;
|
|
|
|
ne_texture_system_inited = true;
|
|
}
|
|
|
|
void NE_MaterialDelete(NE_Material *tex)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
|
|
// If there is an asigned texture
|
|
if (tex->texindex != NE_NO_TEXTURE)
|
|
{
|
|
int slot = tex->texindex;
|
|
// A texture may be used by several materials
|
|
NE_Texture[slot].uses--;
|
|
// If this is the only material to use it, delete it
|
|
if (NE_Texture[slot].uses == 0)
|
|
{
|
|
NE_Free(NE_TexAllocList, NE_Texture[slot].adress);
|
|
NE_Texture[slot].adress = NULL;
|
|
NE_Texture[slot].param = 0;
|
|
NE_Texture[slot].palette = 0;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < NE_MAX_TEXTURES; i++)
|
|
{
|
|
if (NE_UserMaterials[i] == tex)
|
|
{
|
|
NE_UserMaterials[i] = NULL;
|
|
free(tex);
|
|
return;
|
|
}
|
|
}
|
|
|
|
NE_DebugPrint("Object not found");
|
|
}
|
|
|
|
int NE_TextureFreeMem(void)
|
|
{
|
|
if (!ne_texture_system_inited)
|
|
return 0;
|
|
|
|
NEMemInfo Info;
|
|
NE_MemGetInformation(NE_TexAllocList, &Info);
|
|
|
|
return Info.Free;
|
|
}
|
|
|
|
int NE_TextureFreeMemPercent(void)
|
|
{
|
|
if (!ne_texture_system_inited)
|
|
return 0;
|
|
|
|
NEMemInfo Info;
|
|
NE_MemGetInformation(NE_TexAllocList, &Info);
|
|
|
|
return Info.FreePercent;
|
|
}
|
|
|
|
void NE_TextureDefragMem(void)
|
|
{
|
|
NE_Assert(0, "This function doesn't work");
|
|
return;
|
|
/*
|
|
// REALLY OLD CODE -- DOESN'T WORK
|
|
|
|
if (!ne_texture_system_inited)
|
|
return;
|
|
|
|
uint32 vramTemp = vramSetMainBanks(VRAM_A_LCD, VRAM_B_LCD, VRAM_C_LCD,
|
|
VRAM_D_LCD);
|
|
|
|
bool ok = false;
|
|
while (!ok)
|
|
{
|
|
ok = true;
|
|
int i;
|
|
for (i = 0; i < NE_MAX_TEXTURES; i++)
|
|
{
|
|
int size = NE_GetSize(NE_TexAllocList, (void*)NE_Texture[i].adress);
|
|
NE_Free(NE_TexAllocList,(void*)NE_Texture[i].adress);
|
|
void *pointer = NE_Alloc(NE_TexAllocList, size, 8);
|
|
|
|
NE_AssertPointer(pointer, "Couldn't reallocate texture");
|
|
|
|
if (pointer != NE_Texture[i].adress)
|
|
{
|
|
dmaCopy((void*) NE_Texture[i].adress, pointer, size);
|
|
NE_Texture[i].adress = pointer;
|
|
NE_Texture[i].param &= 0xFFFF0000;
|
|
NE_Texture[i].param |= ((uint32)pointer >> 3) & 0xFFFF;
|
|
ok = false;
|
|
}
|
|
}
|
|
}
|
|
vramRestoreMainBanks(vramTemp);
|
|
*/
|
|
}
|
|
|
|
void NE_TextureSystemEnd(void)
|
|
{
|
|
if (!ne_texture_system_inited)
|
|
return;
|
|
|
|
NE_AllocEnd(NE_TexAllocList);
|
|
|
|
free(NE_Texture);
|
|
|
|
for (int i = 0; i < NE_MAX_TEXTURES; i++)
|
|
{
|
|
if (NE_UserMaterials[i])
|
|
free(NE_UserMaterials[i]);
|
|
}
|
|
|
|
free(NE_UserMaterials);
|
|
|
|
NE_Texture = NULL;
|
|
|
|
NE_PaletteSystemEnd();
|
|
|
|
ne_texture_system_inited = false;
|
|
}
|
|
|
|
// Internal use
|
|
int __NE_TextureGetRawX(const NE_Material *tex)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
NE_Assert(tex->texindex != NE_NO_TEXTURE,
|
|
"No texture asigned to material");
|
|
return (NE_Texture[tex->texindex].param & (0x7 << 20)) >> 20;
|
|
}
|
|
|
|
// Internal use
|
|
int __NE_TextureGetRawY(const NE_Material *tex)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
NE_Assert(tex->texindex != NE_NO_TEXTURE, "No texture asigned to material");
|
|
return (NE_Texture[tex->texindex].param & (0x7 << 23)) >> 23;
|
|
}
|
|
|
|
int NE_TextureGetRealSizeX(const NE_Material *tex)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
NE_Assert(tex->texindex != NE_NO_TEXTURE, "No texture asigned to material");
|
|
return 8 << __NE_TextureGetRawX(tex);
|
|
}
|
|
|
|
int NE_TextureGetRealSizeY(const NE_Material *tex)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
NE_Assert(tex->texindex != NE_NO_TEXTURE, "No texture asigned to material");
|
|
return 8 << __NE_TextureGetRawY(tex);
|
|
}
|
|
|
|
int NE_TextureGetSizeX(const NE_Material *tex)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
NE_Assert(tex->texindex != NE_NO_TEXTURE, "No texture asigned to material");
|
|
return NE_Texture[tex->texindex].sizex;
|
|
}
|
|
|
|
int NE_TextureGetSizeY(const NE_Material *tex)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
NE_Assert(tex->texindex != NE_NO_TEXTURE, "No texture asigned to material");
|
|
return NE_Texture[tex->texindex].sizey;
|
|
}
|
|
|
|
void NE_MaterialSetPropierties(NE_Material *tex, u32 diffuse,
|
|
u32 ambient, u32 specular, u32 emission,
|
|
bool vtxcolor, bool useshininess)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
tex->diffuse = diffuse;
|
|
tex->ambient = ambient;
|
|
tex->specular = specular;
|
|
tex->emission = emission;
|
|
tex->vtxcolor = vtxcolor;
|
|
tex->useshininess = useshininess;
|
|
}
|
|
|
|
void NE_MaterialSetDefaultPropierties(u32 diffuse, u32 ambient,
|
|
u32 specular, u32 emission,
|
|
bool vtxcolor, bool useshininess)
|
|
{
|
|
ne_defaultdiffuse = diffuse;
|
|
ne_defaultambient = ambient;
|
|
ne_defaultspecular = specular;
|
|
ne_defaultemission = emission;
|
|
ne_defaultvtxcolor = vtxcolor;
|
|
ne_defaultuseshininess = useshininess;
|
|
GFX_DIFFUSE_AMBIENT = ne_defaultdiffuse | (ne_defaultambient << 16)
|
|
| (ne_defaultvtxcolor << 15);
|
|
GFX_SPECULAR_EMISSION = ne_defaultspecular | (ne_defaultemission << 16)
|
|
| (ne_defaultuseshininess << 15);
|
|
}
|
|
|
|
static u16 *drawingtexture_adress = NULL;
|
|
static int drawingtexture_x, drawingtexture_y;
|
|
static int drawingtexture_type;
|
|
static int drawingtexture_realx;
|
|
static u32 ne_vram_saved;
|
|
|
|
void *NE_TextureDrawingStart(const NE_Material *tex)
|
|
{
|
|
NE_AssertPointer(tex, "NULL pointer");
|
|
NE_Assert(tex->texindex != NE_NO_TEXTURE, "No texture asigned to material");
|
|
|
|
NE_Assert(drawingtexture_adress == NULL,
|
|
"Another texture is already active");
|
|
|
|
drawingtexture_x = NE_TextureGetSizeX(tex);
|
|
drawingtexture_realx = NE_TextureGetRealSizeX(tex);
|
|
drawingtexture_y = NE_TextureGetSizeY(tex);
|
|
drawingtexture_adress = (u16 *) ((uintptr_t)VRAM_A
|
|
+ ((NE_Texture[tex->texindex].param & 0xFFFF) << 3));
|
|
drawingtexture_type = ((NE_Texture[tex->texindex].param >> 26) & 0x7);
|
|
|
|
ne_vram_saved = vramSetPrimaryBanks(VRAM_A_LCD, VRAM_B_LCD, VRAM_C_LCD,
|
|
VRAM_D_LCD);
|
|
|
|
return drawingtexture_adress;
|
|
}
|
|
|
|
void NE_TexturePutPixelRGBA(u32 x, u32 y, u16 color)
|
|
{
|
|
NE_AssertPointer(drawingtexture_adress,
|
|
"No texture active for drawing");
|
|
NE_Assert(drawingtexture_type == NE_A1RGB5,
|
|
"Ative texture isn't NE_A1RGB5");
|
|
|
|
if (x >= drawingtexture_x || y >= drawingtexture_y)
|
|
return;
|
|
|
|
drawingtexture_adress[x + (y * drawingtexture_realx)] = color;
|
|
}
|
|
|
|
void NE_TexturePutPixelRGB256(u32 x, u32 y, u8 palettecolor)
|
|
{
|
|
NE_AssertPointer(drawingtexture_adress,
|
|
"No texture active for drawing.");
|
|
NE_Assert(drawingtexture_type == NE_PAL256,
|
|
"Active texture isn't NE_PAL256");
|
|
|
|
if (x >= drawingtexture_x || y >= drawingtexture_y)
|
|
return;
|
|
|
|
int position = (x + (y * drawingtexture_realx)) >> 1;
|
|
int desp = (x & 1) << 3;
|
|
|
|
drawingtexture_adress[position] &= 0xFF00 >> desp;
|
|
drawingtexture_adress[position] |= ((u16) palettecolor) << desp;
|
|
}
|
|
|
|
void NE_TextureDrawingEnd(void)
|
|
{
|
|
NE_Assert(drawingtexture_adress != NULL, "No active texture");
|
|
|
|
vramRestorePrimaryBanks(ne_vram_saved);
|
|
|
|
drawingtexture_adress = NULL;
|
|
}
|