library: Handle failures correctly

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.
This commit is contained in:
Antonio Niño Díaz 2023-04-21 18:19:02 +01:00
parent 1dd798f250
commit f57fa76576
19 changed files with 379 additions and 115 deletions

View File

@ -129,7 +129,8 @@ void NE_SpriteDeleteAll(void);
///
/// @param max_sprites Number of sprites. If it is lower than 1, it will create
/// space for NE_DEFAULT_SPRITES.
void NE_SpriteSystemReset(int max_sprites);
/// @return Returns 0 on success.
int NE_SpriteSystemReset(int max_sprites);
/// Ends sprite system and all memory used by it.
void NE_SpriteSystemEnd(void);

View File

@ -55,7 +55,8 @@ void NE_AnimationDeleteAll(void);
///
/// @param max_animations Number of animations. If it is lower than 1, it
/// will create space for NE_DEFAULT_ANIMATIONS.
void NE_AnimationSystemReset(int max_animations);
/// @return Returns 0 on success.
int NE_AnimationSystemReset(int max_animations);
/// Ends animation system and all memory used by it.
void NE_AnimationSystemEnd(void);

View File

@ -150,7 +150,8 @@ void NE_CameraRotateFree(NE_Camera *cam, int rx, int ry, int rz);
///
/// @param max_cameras Number of cameras. If it is less than 1, it will create
/// space for NE_DEFAULT_CAMERAS.
void NE_CameraSystemReset(int max_cameras);
/// @return Returns 0 on success.
int NE_CameraSystemReset(int max_cameras);
/// Ends camera system and all memory used by it.
void NE_CameraSystemEnd(void);

View File

@ -218,7 +218,8 @@ void NE_GUIDeleteAll(void);
///
/// @param max_objects Max number of objects. If it is lower than 1, the
/// function will create space for NE_GUI_DEFAULT_OBJECTS.
void NE_GUISystemReset(int max_objects);
/// @return Returns 0 on success.
int NE_GUISystemReset(int max_objects);
/// Ends GUI system and all memory used by it.
void NE_GUISystemEnd(void);

View File

@ -48,7 +48,9 @@ void NE_UpdateInput(void);
void NE_End(void);
/// Inits Nitro Engine and 3D mode in one screen.
void NE_Init3D(void);
///
/// @return Returns 0 on success.
int NE_Init3D(void);
/// Draws a 3D scene.
///
@ -59,7 +61,9 @@ void NE_Process(NE_Voidfunc drawscene);
///
/// VRAM banks C and D are used as framebuffers, which means there is only 50%
/// of the normally available VRAM for textures.
void NE_InitDual3D(void);
///
/// @return Returns 0 on success.
int NE_InitDual3D(void);
/// Draws a 3D scene in each screen.
///

View File

@ -330,7 +330,8 @@ void NE_ModelDeleteAll(void);
///
/// @param max_models Number of models. If it is lower than 1, it will create
/// space for NE_DEFAULT_MODELS.
void NE_ModelSystemReset(int max_models);
/// @return Returns 0 on success.
int NE_ModelSystemReset(int max_models);
/// Ends model system and frees all memory used by it.
void NE_ModelSystemEnd(void);

View File

@ -77,7 +77,8 @@ void NE_PaletteUse(const NE_Palette *pal);
///
/// @param max_palettes Max number of palettes. If lower than 1, it will
/// create space for NE_DEFAULT_PALETTES.
void NE_PaletteSystemReset(int max_palettes);
/// @return Returns 0 on success.
int NE_PaletteSystemReset(int max_palettes);
/// Returns the available free memory for palettes.
///

View File

@ -88,7 +88,8 @@ void NE_PhysicsDeleteAll(void);
///
/// @param max_objects Number of objects. If it is lower than 1, it will create
/// space for NE_DEFAULT_PHYSICS.
void NE_PhysicsSystemReset(int max_objects);
/// @return Returns 0 on success.
int NE_PhysicsSystemReset(int max_objects);
/// Ends physics engine and frees all memory used by it.
void NE_PhysicsSystemEnd(void);

View File

@ -189,8 +189,9 @@ typedef enum {
/// @param max_palettes Max number of palettes. If lower than 1, it will
/// create space for NE_DEFAULT_PALETTES.
/// @param bank_flags VRAM banks where Nitro Engine can allocate textures.
void NE_TextureSystemReset(int max_textures, int max_palettes,
NE_VRAMBankFlags bank_flags);
/// @return Returns 0 on success.
int NE_TextureSystemReset(int max_textures, int max_palettes,
NE_VRAMBankFlags bank_flags);
/// Deletes a material object.
///

View File

@ -18,7 +18,7 @@ NE_Sprite *NE_SpriteCreate(void)
{
if (!ne_sprite_system_inited)
{
NE_DebugPrint("System not inited");
NE_DebugPrint("System not initialized");
return NULL;
}
@ -28,8 +28,11 @@ NE_Sprite *NE_SpriteCreate(void)
continue;
NE_Sprite *sprite = calloc(1, sizeof(NE_Sprite));
NE_AssertPointer(sprite, "Not enough memory");
if (sprite == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
sprite->visible = true;
sprite->scale = inttof32(1);
@ -133,7 +136,7 @@ void NE_SpriteDeleteAll(void)
NE_SpriteDelete(NE_spritepointers[i]);
}
void NE_SpriteSystemReset(int max_sprites)
int NE_SpriteSystemReset(int max_sprites)
{
if (ne_sprite_system_inited)
NE_SpriteSystemEnd();
@ -144,9 +147,14 @@ void NE_SpriteSystemReset(int max_sprites)
NE_MAX_SPRITES = max_sprites;
NE_spritepointers = calloc(NE_MAX_SPRITES, sizeof(NE_spritepointers));
NE_AssertPointer(NE_spritepointers, "Not enough memory");
if (NE_spritepointers == NULL)
{
NE_DebugPrint("Not enough memory");
return -1;
}
ne_sprite_system_inited = true;
return 0;
}
void NE_SpriteSystemEnd(void)

View File

@ -12,13 +12,23 @@
int NE_AllocInit(NEChunk **first_chunk, void *start, void *end)
{
if (first_chunk == NULL)
{
NE_DebugPrint("Invalid arguments");
return -1;
}
if (end <= start)
{
NE_DebugPrint("Invalid range");
return -2;
}
*first_chunk = malloc(sizeof(NEChunk));
NE_AssertPointer(*first_chunk, "Couldn't allocate chunk");
if (*first_chunk == NULL)
{
NE_DebugPrint("Not enough memory");
return -3;
}
(*first_chunk)->previous = NULL;
(*first_chunk)->state = NE_STATE_FREE;
@ -32,7 +42,10 @@ int NE_AllocInit(NEChunk **first_chunk, void *start, void *end)
int NE_AllocEnd(NEChunk **first_chunk)
{
if (first_chunk == NULL)
{
NE_DebugPrint("Invalid arguments");
return -1;
}
NEChunk *this = *first_chunk;
@ -61,12 +74,18 @@ int NE_AllocEnd(NEChunk **first_chunk)
// It returns a pointer to the new chunk.
static NEChunk *ne_split_chunk(NEChunk *this, size_t this_size)
{
NE_AssertPointer(this, "NULL pointer");
// Get next chunk and create a new one.
NEChunk *next = this->next;
NEChunk *new = malloc(sizeof(NEChunk));
NE_AssertPointer(new, "Couldn't allocate chunk metadata.");
if (new == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
// Update pointers in the linked list
// ----------------------------------
@ -85,8 +104,7 @@ static NEChunk *ne_split_chunk(NEChunk *this, size_t this_size)
// It shouldn't be free because deallocating a chunk should merge it
// with any free chunk next to it.
NE_Assert(next->state != NE_STATE_FREE,
"Possible list corruption");
NE_Assert(next->state != NE_STATE_FREE, "Possible list corruption");
}
// Update pointers to start and end of this chunk and the new chunk
@ -104,6 +122,8 @@ static NEChunk *ne_split_chunk(NEChunk *this, size_t this_size)
// the end address isn't considered part of that chunk.
static NEChunk *ne_search_address(NEChunk *first_chunk, void *address)
{
NE_AssertPointer(first_chunk, "NULL pointer");
NEChunk *this = first_chunk;
uintptr_t addr = (uintptr_t)address;
@ -128,7 +148,10 @@ static NEChunk *ne_search_address(NEChunk *first_chunk, void *address)
void *NE_AllocFindInRange(NEChunk *first_chunk, void *start, void *end, size_t size)
{
if ((first_chunk == NULL) || (start == NULL) || (end == NULL) || (size == 0))
{
NE_DebugPrint("Invalid arguments");
return NULL;
}
// Get the chunk that contains the first address. If the start address of
// the first chunk is after the provided start, get the first chunk.
@ -180,6 +203,8 @@ void *NE_AllocFindInRange(NEChunk *first_chunk, void *start, void *end, size_t s
static NEChunk *ne_search_free_range_chunk(NEChunk *first_chunk,
void *address, size_t size)
{
NE_AssertPointer(first_chunk, "NULL pointer");
// If that range of memory is free, it should be in one single chunk. Look
// for the chunk that contains the base address, and check if the end
// address is also part of that chunk.
@ -203,7 +228,10 @@ static NEChunk *ne_search_free_range_chunk(NEChunk *first_chunk,
int NE_AllocAddress(NEChunk *first_chunk, void *address, size_t size)
{
if ((first_chunk == NULL) || (address == NULL) || (size == 0))
{
NE_DebugPrint("Invalid arguments");
return -1;
}
// Force sizes multiple of NE_ALLOC_MIN_SIZE
const size_t mask = NE_ALLOC_MIN_SIZE - 1;
@ -233,11 +261,17 @@ int NE_AllocAddress(NEChunk *first_chunk, void *address, size_t size)
//
// Finally, return the chunk that stays in the middle.
bool this_is_modified = false;
if (this_start < alloc_start)
{
// Split this chunk into two, ignore the first one and get the second
// one (which contains the start address)
this = ne_split_chunk(this, alloc_start - this_start);
if (this == NULL)
return -3;
this_is_modified = true;
// Only the start has changed
this_start = (uintptr_t)this->start;
@ -245,11 +279,21 @@ int NE_AllocAddress(NEChunk *first_chunk, void *address, size_t size)
NE_Assert(this_end == (uintptr_t)this->end, "Unexpected error");
}
this->state = NE_STATE_USED;
if (alloc_end < this_end)
{
// Split this chunk into two as well. The first one is the final desired
// chunk, the second one is more free space.
NEChunk *next = ne_split_chunk(this, size);
if (next == NULL)
{
if (this_is_modified)
NE_Free(first_chunk, this);
return -4;
}
next->state = NE_STATE_FREE;
// Only the end has changed
@ -258,8 +302,6 @@ int NE_AllocAddress(NEChunk *first_chunk, void *address, size_t size)
NE_Assert(this_start == (uintptr_t)this->start, "Unexpected error");
}
this->state = NE_STATE_USED;
NE_Assert(size == (this_end - this_start), "Unexpected error");
NE_Assert(this->start == address, "Unexpected error");
@ -269,7 +311,10 @@ int NE_AllocAddress(NEChunk *first_chunk, void *address, size_t size)
void *NE_Alloc(NEChunk *first_chunk, size_t size)
{
if ((first_chunk == NULL) || (size == 0))
{
NE_DebugPrint("Invalid arguments");
return NULL;
}
// Force sizes multiple of NE_ALLOC_MIN_SIZE
const size_t mask = NE_ALLOC_MIN_SIZE - 1;
@ -308,6 +353,8 @@ void *NE_Alloc(NEChunk *first_chunk, size_t size)
// | USED | NOT USED | USED |
NEChunk *new = ne_split_chunk(this, size);
if (new == NULL)
return NULL;
// Flag this chunk as used and the new one as free
this->state = NE_STATE_USED;
@ -323,7 +370,10 @@ void *NE_Alloc(NEChunk *first_chunk, size_t size)
void *NE_AllocFromEnd(NEChunk *first_chunk, size_t size)
{
if ((first_chunk == NULL) || (size == 0))
{
NE_DebugPrint("Invalid arguments");
return NULL;
}
// Force sizes multiple of NE_ALLOC_MIN_SIZE
const size_t mask = NE_ALLOC_MIN_SIZE - 1;
@ -368,6 +418,8 @@ void *NE_AllocFromEnd(NEChunk *first_chunk, size_t size)
// The size of this chunk has to be the current one minus the requested
// size for the new chunk.
NEChunk *new = ne_split_chunk(this, this_size - size);
if (new == NULL)
return NULL;
// Flag the new chunk as used
new->state = NE_STATE_USED;
@ -382,7 +434,10 @@ void *NE_AllocFromEnd(NEChunk *first_chunk, size_t size)
int NE_Free(NEChunk *first_chunk, void *pointer)
{
if (first_chunk == NULL)
{
NE_DebugPrint("Invalid arguments");
return -1;
}
NEChunk *this = first_chunk;
@ -490,7 +545,10 @@ int NE_Free(NEChunk *first_chunk, void *pointer)
int NE_Lock(NEChunk *first_chunk, void *pointer)
{
if (first_chunk == NULL)
{
NE_DebugPrint("Invalid arguments");
return -1;
}
NEChunk *this = first_chunk;
@ -517,7 +575,10 @@ int NE_Lock(NEChunk *first_chunk, void *pointer)
int NE_Unlock(NEChunk *first_chunk, void *pointer)
{
if (first_chunk == NULL)
{
NE_DebugPrint("Invalid arguments");
return -1;
}
NEChunk *this = first_chunk;
@ -544,7 +605,10 @@ int NE_Unlock(NEChunk *first_chunk, void *pointer)
int NE_MemGetInformation(NEChunk *first_chunk, NEMemInfo *info)
{
if ((first_chunk == NULL) || (info == NULL))
{
NE_DebugPrint("Invalid arguments");
return -1;
}
info->free = 0;
info->used = 0;

View File

@ -17,10 +17,17 @@ static bool ne_animation_system_inited = false;
NE_Animation *NE_AnimationCreate(void)
{
if (!ne_animation_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
NE_Animation *animation = calloc(1, sizeof(NE_Animation));
NE_AssertPointer(animation, "Not enough memory");
if (animation == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
int i = 0;
while (1)
@ -85,7 +92,11 @@ int NE_AnimationLoadFAT(NE_Animation *animation, const char *dsa_path)
animation->loadedfromfat = true;
uint32_t *pointer = (uint32_t *)NE_FATLoadData(dsa_path);
NE_AssertPointer(pointer, "Couldn't load file from FAT");
if (pointer == NULL)
{
NE_DebugPrint("Couldn't load file from FAT");
return 0;
}
// Check version
uint32_t version = pointer[0];
@ -141,7 +152,7 @@ void NE_AnimationDeleteAll(void)
}
}
void NE_AnimationSystemReset(int max_animations)
int NE_AnimationSystemReset(int max_animations)
{
if (ne_animation_system_inited)
NE_AnimationSystemEnd();
@ -151,13 +162,15 @@ void NE_AnimationSystemReset(int max_animations)
else
NE_MAX_ANIMATIONS = max_animations;
NE_AnimationPointers = malloc(NE_MAX_ANIMATIONS * sizeof(NE_AnimationPointers));
NE_AssertPointer(NE_AnimationPointers, "Not enough memory");
for (int i = 0; i < NE_MAX_ANIMATIONS; i++)
NE_AnimationPointers[i] = NULL;
NE_AnimationPointers = calloc(NE_MAX_ANIMATIONS, sizeof(NE_AnimationPointers));
if (NE_AnimationPointers == NULL)
{
NE_DebugPrint("Not enough memory");
return -1;
}
ne_animation_system_inited = true;
return 0;
}
void NE_AnimationSystemEnd(void)

View File

@ -54,7 +54,10 @@ static void __NE_CameraUpdateMatrix(NE_Camera * cam)
NE_Camera *NE_CameraCreate(void)
{
if (!ne_camera_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
for (int i = 0; i < NE_MAX_CAMERAS; i++)
{
@ -62,7 +65,11 @@ NE_Camera *NE_CameraCreate(void)
continue;
NE_Camera *cam = calloc(1, sizeof(NE_Camera));
NE_AssertPointer(cam, "Not enough memory");
if (cam == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
cam->to[2] = inttof32(1);
cam->up[1] = inttof32(1);
@ -364,7 +371,7 @@ void NE_CameraDelete(NE_Camera *cam)
NE_DebugPrint("Object not found");
}
void NE_CameraSystemReset(int max_cameras)
int NE_CameraSystemReset(int max_cameras)
{
if (ne_camera_system_inited)
NE_CameraSystemEnd();
@ -375,9 +382,14 @@ void NE_CameraSystemReset(int max_cameras)
NE_MAX_CAMERAS = max_cameras;
NE_UserCamera = calloc(NE_MAX_CAMERAS, sizeof(NE_UserCamera));
NE_AssertPointer(NE_UserCamera, "Not enough memory");
if (NE_UserCamera == NULL)
{
NE_DebugPrint("Not enough memory");
return -1;
}
ne_camera_system_inited = true;
return 0;
}
void NE_CameraSystemEnd(void)

View File

@ -644,7 +644,10 @@ void NE_GUIDraw(void)
NE_GUIObj *NE_GUIButtonCreate(s16 x1, s16 y1, s16 x2, s16 y2)
{
if (!ne_gui_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
@ -652,10 +655,19 @@ NE_GUIObj *NE_GUIButtonCreate(s16 x1, s16 y1, s16 x2, s16 y2)
continue;
ne_button_t *ptr = malloc(sizeof(ne_button_t));
NE_AssertPointer(ptr, "Not enough memory");
if (ptr == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i] = malloc(sizeof(NE_GUIObj));
NE_AssertPointer(NE_guipointers[i], "Not enough memory");
if (NE_guipointers[i] == NULL)
{
free(ptr);
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i]->pointer = (void *)ptr;
NE_guipointers[i]->type = NE_Button;
@ -680,7 +692,10 @@ NE_GUIObj *NE_GUIButtonCreate(s16 x1, s16 y1, s16 x2, s16 y2)
NE_GUIObj *NE_GUICheckBoxCreate(s16 x1, s16 y1, s16 x2, s16 y2, bool initialvalue)
{
if (!ne_gui_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
@ -688,10 +703,19 @@ NE_GUIObj *NE_GUICheckBoxCreate(s16 x1, s16 y1, s16 x2, s16 y2, bool initialvalu
continue;
ne_checkbox_t *ptr = malloc(sizeof(ne_checkbox_t));
NE_AssertPointer(ptr, "Not enough memory");
if (ptr == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i] = malloc(sizeof(NE_GUIObj));
NE_AssertPointer(NE_guipointers[i], "Not enough memory");
if (NE_guipointers[i] == NULL)
{
free(ptr);
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i]->pointer = (void *)ptr;
NE_guipointers[i]->type = NE_CheckBox;
@ -718,7 +742,10 @@ NE_GUIObj *NE_GUIRadioButtonCreate(s16 x1, s16 y1, s16 x2, s16 y2, int group,
bool initialvalue)
{
if (!ne_gui_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
@ -726,10 +753,19 @@ NE_GUIObj *NE_GUIRadioButtonCreate(s16 x1, s16 y1, s16 x2, s16 y2, int group,
continue;
ne_radiobutton_t *ptr = malloc(sizeof(ne_radiobutton_t));
NE_AssertPointer(ptr, "Not enough memory");
if (ptr == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i] = malloc(sizeof(NE_GUIObj));
NE_AssertPointer(NE_guipointers[i], "Not enough memory");
if (NE_guipointers[i] == NULL)
{
free(ptr);
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i]->pointer = (void *)ptr;
NE_guipointers[i]->type = NE_RadioButton;
@ -760,7 +796,10 @@ NE_GUIObj *NE_GUISlideBarCreate(s16 x1, s16 y1, s16 x2, s16 y2, int min,
int max, int initialvalue)
{
if (!ne_gui_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
for (int i = 0; i < NE_GUI_OBJECTS; i++)
{
@ -768,10 +807,19 @@ NE_GUIObj *NE_GUISlideBarCreate(s16 x1, s16 y1, s16 x2, s16 y2, int min,
continue;
ne_slidebar_t *ptr = malloc(sizeof(ne_slidebar_t));
NE_AssertPointer(ptr, "Not enough memory");
if (ptr == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i] = malloc(sizeof(NE_GUIObj));
NE_AssertPointer(NE_guipointers[i], "Not enough memory");
if (NE_guipointers[i] == NULL)
{
free(ptr);
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_guipointers[i]->pointer = (void *)ptr;
NE_guipointers[i]->type = NE_SlideBar;
@ -991,7 +1039,7 @@ void NE_GUIDeleteAll(void)
}
}
void NE_GUISystemReset(int max_objects)
int NE_GUISystemReset(int max_objects)
{
if (ne_gui_system_inited)
NE_GUISystemEnd();
@ -1002,9 +1050,14 @@ void NE_GUISystemReset(int max_objects)
NE_GUI_OBJECTS = max_objects;
NE_guipointers = calloc(NE_GUI_OBJECTS, sizeof(NE_guipointers));
NE_AssertPointer(NE_guipointers, "Not enough memory");
if (NE_guipointers == NULL)
{
NE_DebugPrint("Not enough memory");
return -1;
}
ne_gui_system_inited = true;
return 0;
}
void NE_GUISystemEnd(void)

View File

@ -124,7 +124,47 @@ void NE_SetFov(int fovValue)
fov = fovValue;
}
static void NE_Init__(void)
static void ne_systems_end_all(void)
{
NE_GUISystemEnd();
NE_SpriteSystemEnd();
NE_PhysicsSystemEnd();
NE_ModelSystemEnd();
NE_AnimationSystemEnd();
NE_TextResetSystem();
NE_TextureSystemEnd();
NE_CameraSystemEnd();
NE_SpecialEffectSet(0);
}
static int ne_systems_reset_all(NE_VRAMBankFlags vram_banks)
{
// Default number of objects for everyting.
if (NE_CameraSystemReset(0) != 0)
goto cleanup;
if (NE_PhysicsSystemReset(0) != 0)
goto cleanup;
if (NE_SpriteSystemReset(0) != 0)
goto cleanup;
if (NE_GUISystemReset(0) != 0)
goto cleanup;
if (NE_ModelSystemReset(0) != 0)
goto cleanup;
if (NE_AnimationSystemReset(0) != 0)
goto cleanup;
if (NE_TextureSystemReset(0, 0, vram_banks) != 0)
goto cleanup;
NE_TextPriorityReset();
return 0;
cleanup:
ne_systems_end_all();
return -1;
}
static void ne_init_registers(void)
{
// Power all 3D and 2D. Hide 3D screen during init
powerOn(POWER_ALL);
@ -156,16 +196,6 @@ static void NE_Init__(void)
GFX_CLEAR_DEPTH = GL_MAX_DEPTH;
// Default number of objects for everyting. Textures are initialized in
// NE_Init3D and NE_InitDual3D
NE_CameraSystemReset(0);
NE_PhysicsSystemReset(0);
NE_SpriteSystemReset(0);
NE_GUISystemReset(0);
NE_ModelSystemReset(0);
NE_AnimationSystemReset(0);
NE_TextPriorityReset();
MATRIX_CONTROL = GL_TEXTURE;
MATRIX_IDENTITY = 0;
@ -213,48 +243,43 @@ void NE_UpdateInput(void)
touchRead(&ne_input.touch);
}
void NE_Init3D(void)
int NE_Init3D(void)
{
if (ne_inited)
NE_End();
NE_Init__();
NE_TextureSystemReset(0, 0, NE_VRAM_ABCD);
if (ne_systems_reset_all(NE_VRAM_ABCD) != 0)
return -1;
NE_UpdateInput();
ne_init_registers();
ne_inited = true;
NE_Dual = false;
NE_DebugPrint("Nitro Engine initialized in normal 3D mode");
return 0;
}
void NE_InitDual3D(void)
int NE_InitDual3D(void)
{
if (ne_inited)
NE_End();
NE_Init__();
NE_TextureSystemReset(0, 0, NE_VRAM_AB);
NE_UpdateInput();
videoSetModeSub(0);
REG_BG2CNT_SUB = BG_BMP16_256x256;
REG_BG2PA_SUB = 1 << 8;
REG_BG2PB_SUB = 0;
REG_BG2PC_SUB = 0;
REG_BG2PD_SUB = 1 << 8;
REG_BG2X_SUB = 0;
REG_BG2Y_SUB = 0;
vramSetBankC(VRAM_C_SUB_BG);
vramSetBankD(VRAM_D_SUB_SPRITE);
NE_Sprites = calloc(128, sizeof(SpriteEntry));
if (NE_Sprites == NULL)
{
NE_DebugPrint("Not enough memory");
return -1;
}
if (ne_systems_reset_all(NE_VRAM_AB) != 0)
{
free(NE_Sprites);
return -2;
}
// Reset sprites
for (int i = 0; i < 128; i++)
@ -273,6 +298,23 @@ void NE_InitDual3D(void)
}
}
NE_UpdateInput();
ne_init_registers();
videoSetModeSub(0);
REG_BG2CNT_SUB = BG_BMP16_256x256;
REG_BG2PA_SUB = 1 << 8;
REG_BG2PB_SUB = 0;
REG_BG2PC_SUB = 0;
REG_BG2PD_SUB = 1 << 8;
REG_BG2X_SUB = 0;
REG_BG2Y_SUB = 0;
vramSetBankC(VRAM_C_SUB_BG);
vramSetBankD(VRAM_D_SUB_SPRITE);
videoSetModeSub(MODE_5_2D | DISPLAY_BG2_ACTIVE | DISPLAY_SPR_ACTIVE |
DISPLAY_SPR_2D_BMP_256);
@ -280,6 +322,8 @@ void NE_InitDual3D(void)
NE_Dual = true;
NE_DebugPrint("Nitro Engine initialized in dual 3D mode");
return 0;
}
void NE_InitConsole(void)
@ -458,10 +502,14 @@ void NE_SpecialEffectPause(bool pause)
if (NE_Effect == 0)
return;
NE_effectpause = pause;
if (pause)
{
ne_noisepause = malloc(sizeof(int) * NE_NOISEPAUSE_SIZE);
if (ne_noisepause == NULL)
{
NE_DebugPrint("Not enough memory");
return;
}
for (int i = 0; i < NE_NOISEPAUSE_SIZE; i++)
{
@ -477,6 +525,8 @@ void NE_SpecialEffectPause(bool pause)
ne_noisepause = NULL;
}
}
NE_effectpause = pause;
}
void NE_HBLFunc(void)

View File

@ -110,10 +110,17 @@ static int ne_model_load_filesystem_common(NE_Model *model, const char *path)
NE_Model *NE_ModelCreate(NE_ModelType type)
{
if (!ne_model_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
NE_Model *model = calloc(1, sizeof(NE_Model));
NE_AssertPointer(model, "Not enough memory");
if (model == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
int i = 0;
while (1)
@ -564,7 +571,7 @@ void NE_ModelDeleteAll(void)
}
}
void NE_ModelSystemReset(int max_models)
int NE_ModelSystemReset(int max_models)
{
if (ne_model_system_inited)
NE_ModelSystemEnd();
@ -575,14 +582,17 @@ void NE_ModelSystemReset(int max_models)
NE_MAX_MODELS = max_models;
NE_Mesh = calloc(NE_MAX_MODELS, sizeof(ne_mesh_info_t));
NE_AssertPointer(NE_Mesh, "Not enough memory");
NE_ModelPointers = malloc(NE_MAX_MODELS * sizeof(NE_ModelPointers));
NE_AssertPointer(NE_ModelPointers, "Not enough memory");
for (int i = 0; i < NE_MAX_MODELS; i++)
NE_ModelPointers[i] = NULL;
NE_ModelPointers = calloc(NE_MAX_MODELS, sizeof(NE_ModelPointers));
if ((NE_Mesh == NULL) || (NE_ModelPointers == NULL))
{
free(NE_Mesh);
free(NE_ModelPointers);
NE_DebugPrint("Not enough memory");
return -1;
}
ne_model_system_inited = true;
return 0;
}
void NE_ModelSystemEnd(void)

View File

@ -26,7 +26,10 @@ 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++)
{
@ -34,7 +37,12 @@ NE_Palette *NE_PaletteCreate(void)
continue;
NE_Palette *ptr = malloc(sizeof(NE_Palette));
NE_AssertPointer(ptr, "Not enough memory");
if (ptr == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
ptr->index = NE_NO_PALETTE;
NE_UserPalette[i] = ptr;
return ptr;
@ -101,7 +109,6 @@ int NE_PaletteLoad(NE_Palette *pal, u16 *pointer, u16 numcolor,
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");
@ -161,7 +168,7 @@ void NE_PaletteUse(const NE_Palette *pal)
GFX_PAL_FORMAT = (uintptr_t)NE_PalInfo[pal->index].pointer >> shift;
}
void NE_PaletteSystemReset(int max_palettes)
int NE_PaletteSystemReset(int max_palettes)
{
if (ne_palette_system_inited)
NE_PaletteSystemEnd();
@ -171,19 +178,24 @@ void NE_PaletteSystemReset(int max_palettes)
else
NE_MAX_PALETTES = max_palettes;
NE_PalInfo = malloc(NE_MAX_PALETTES * sizeof(ne_palinfo_t));
NE_AssertPointer(NE_PalInfo, "Not enough memory");
NE_UserPalette = malloc(NE_MAX_PALETTES * sizeof(NE_UserPalette));
NE_AssertPointer(NE_UserPalette, "Not enough memory");
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;
NE_AllocInit(&NE_PalAllocList, (void *)VRAM_E, (void *)VRAM_F);
memset(NE_PalInfo, 0, NE_MAX_PALETTES * sizeof(ne_palinfo_t));
memset(NE_UserPalette, 0, NE_MAX_PALETTES * sizeof(NE_UserPalette));
ne_palette_system_inited = true;
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)

View File

@ -16,7 +16,10 @@ static int NE_MAX_PHYSICS;
NE_Physics *NE_PhysicsCreate(NE_PhysicsTypes type)
{
if (!ne_physics_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
// TODO
if (type == NE_BoundingSphere)
@ -31,7 +34,11 @@ NE_Physics *NE_PhysicsCreate(NE_PhysicsTypes type)
}
NE_Physics *temp = calloc(1, sizeof(NE_Physics));
NE_AssertPointer(temp, "Not enough memory");
if (temp == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
int i = 0;
while (1)
@ -94,7 +101,7 @@ void NE_PhysicsDeleteAll(void)
NE_PhysicsDelete(NE_PhysicsPointers[i]);
}
void NE_PhysicsSystemReset(int max_objects)
int NE_PhysicsSystemReset(int max_objects)
{
if (ne_physics_system_inited)
NE_PhysicsSystemEnd();
@ -105,9 +112,14 @@ void NE_PhysicsSystemReset(int max_objects)
NE_MAX_PHYSICS = max_objects;
NE_PhysicsPointers = calloc(NE_MAX_PHYSICS, sizeof(NE_PhysicsPointers));
NE_AssertPointer(NE_PhysicsPointers, "Not enough memory");
if (NE_PhysicsPointers == NULL)
{
NE_DebugPrint("Not enough memory");
return -1;
}
ne_physics_system_inited = true;
return 0;
}
void NE_PhysicsSystemEnd(void)

View File

@ -131,7 +131,10 @@ static void ne_texture_delete(int texture_index)
NE_Material *NE_MaterialCreate(void)
{
if (!ne_texture_system_inited)
{
NE_DebugPrint("System not initialized");
return NULL;
}
for (int i = 0; i < NE_MAX_TEXTURES; i++)
{
@ -139,7 +142,12 @@ NE_Material *NE_MaterialCreate(void)
continue;
NE_Material *mat = calloc(1, sizeof(NE_Material));
NE_AssertPointer(mat, "Not enough memory");
if (mat == NULL)
{
NE_DebugPrint("Not enough memory");
return NULL;
}
NE_UserMaterials[i] = mat;
mat->texindex = NE_NO_TEXTURE;
mat->palette = NULL;
@ -502,20 +510,29 @@ void NE_MaterialUse(const NE_Material *tex)
extern bool NE_Dual;
void NE_TextureSystemReset(int max_textures, int max_palettes,
NE_VRAMBankFlags bank_flags)
int NE_TextureSystemReset(int max_textures, int max_palettes,
NE_VRAMBankFlags bank_flags)
{
if (ne_texture_system_inited)
NE_TextureSystemEnd();
NE_Assert((bank_flags & 0xF) != 0, "No VRAM banks selected");
if (max_textures < 1)
NE_MAX_TEXTURES = NE_DEFAULT_TEXTURES;
else
NE_MAX_TEXTURES = max_textures;
NE_AllocInit(&NE_TexAllocList, VRAM_A, VRAM_E);
if (NE_PaletteSystemReset(max_palettes) != 0)
return -1;
NE_Assert((bank_flags & 0xF) != 0, "No VRAM banks selected");
NE_Texture = calloc(NE_MAX_TEXTURES, sizeof(ne_textureinfo_t));
NE_UserMaterials = calloc(NE_MAX_TEXTURES, sizeof(NE_UserMaterials));
if ((NE_Texture == NULL) || (NE_UserMaterials == NULL))
goto cleanup;
if (NE_AllocInit(&NE_TexAllocList, VRAM_A, VRAM_E) != 0)
goto cleanup;
// Prevent user from not selecting any bank
if ((bank_flags & 0xF) == 0)
@ -569,16 +586,17 @@ void NE_TextureSystemReset(int max_textures, int max_palettes,
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;
return 0;
cleanup:
NE_DebugPrint("Not enough memory");
NE_PaletteSystemEnd();
free(NE_Texture);
free(NE_UserMaterials);
return -1;
}
void NE_MaterialDelete(NE_Material *tex)