library: Add new process functions that can take arguments

The functions called by NE_Process() and NE_ProcessDual() rely on global
data to know what to draw on the screen.

The functions called by the new NE_ProcessArg() and NE_ProcessDualArg()
can take arguments passed from the caller of the process function. This way
it isn't needed to have global variables.
This commit is contained in:
Antonio Niño Díaz 2023-11-11 18:24:14 +00:00
parent bbe064db63
commit 88e222c756
2 changed files with 162 additions and 20 deletions

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2008-2011, 2019, 2022 Antonio Niño Díaz
// Copyright (c) 2008-2011, 2019, 2022-2023 Antonio Niño Díaz
//
// This file is part of Nitro Engine
@ -30,6 +30,11 @@
/// Void function pointer used in NE_Process and NE_ProcessDual.
typedef void (*NE_Voidfunc)(void);
/// Void function pointer that takes a void pointer as argument.
///
/// Used in NE_ProcessArg and NE_ProcessDualArg.
typedef void (*NE_VoidArgfunc)(void *);
/// Holds information of keys and stylus input for internal use.
typedef struct {
uint32 kdown; ///< Keys that have just been pressed this frame.
@ -71,6 +76,12 @@ int NE_Init3D(void);
/// @param drawscene Function that draws the screen.
void NE_Process(NE_Voidfunc drawscene);
/// Draws a 3D scene passing an argument to the draw function.
///
/// @param drawscene Function that draws the screen.
/// @param arg Argument to pass to the drawscene function.
void NE_ProcessArg(NE_VoidArgfunc drawscene, void *arg);
/// Inits Nitro Engine to draw 3D to both screens.
///
/// VRAM banks C and D are used as framebuffers, which means there is only 50%
@ -135,6 +146,20 @@ int NE_InitDual3D_DMA(void);
/// @param subscreen Function that draws the sub screen.
void NE_ProcessDual(NE_Voidfunc mainscreen, NE_Voidfunc subscreen);
/// Draws 3D scenes in both screens and passes arguments to the draw functions.
///
/// By default, the main screen is the top screen and the sub screen is the
/// bottom screen. This can be changed with NE_MainScreenSetOnTop(),
/// NE_MainScreenSetOnBottom() and NE_SwapScreens(). To check the current
/// position of the main screen, use NE_MainScreenIsOnTop().
///
/// @param mainscreen Function that draws the main screen.
/// @param subscreen Function that draws the sub screen.
/// @param argmain Argument to pass to the mainscreen function.
/// @param argsub Argument to pass to the subscreen function.
void NE_ProcessDualArg(NE_VoidArgfunc mainscreen, NE_VoidArgfunc subscreen,
void *argmain, void *argsub);
/// Inits the console of libnds in the main screen.
///
/// It works in dual 3D mode as well, and it uses VRAM_F for the background

View File

@ -597,7 +597,7 @@ void NE_SetConsoleColor(u32 color)
BG_PALETTE[255] = color;
}
void NE_Process(NE_Voidfunc drawscene)
static void ne_process_common(void)
{
NE_UpdateInput();
@ -617,6 +617,11 @@ void NE_Process(NE_Voidfunc drawscene)
MATRIX_CONTROL = GL_MODELVIEW;
MATRIX_IDENTITY = 0;
}
void NE_Process(NE_Voidfunc drawscene)
{
ne_process_common();
NE_AssertPointer(drawscene, "NULL function pointer");
drawscene();
@ -624,7 +629,17 @@ void NE_Process(NE_Voidfunc drawscene)
GFX_FLUSH = GL_TRANS_MANUALSORT;
}
static void ne_process_dual_3d(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
void NE_ProcessArg(NE_VoidArgfunc drawscene, void *arg)
{
ne_process_common();
NE_AssertPointer(drawscene, "NULL function pointer");
drawscene(arg);
GFX_FLUSH = GL_TRANS_MANUALSORT;
}
static void ne_process_dual_3d_common_start(void)
{
NE_UpdateInput();
@ -673,12 +688,10 @@ static void ne_process_dual_3d(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
NE_Viewport(0, 0, 255, 191);
MATRIX_IDENTITY = 0;
}
if (NE_Screen == 1)
mainscreen();
else
subscreen();
static void ne_process_dual_3d_common_end(void)
{
GFX_FLUSH = GL_TRANS_MANUALSORT;
dmaCopy(NE_Sprites, OAM_SUB, 128 * sizeof(SpriteEntry));
@ -686,9 +699,35 @@ static void ne_process_dual_3d(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
NE_Screen ^= 1;
}
static void ne_process_dual_3d(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
{
ne_process_dual_3d_common_start();
if (NE_Screen == 1)
mainscreen();
else
subscreen();
ne_process_dual_3d_common_end();
}
static void ne_process_dual_3d_arg(NE_VoidArgfunc mainscreen,
NE_VoidArgfunc subscreen,
void *argmain, void *argsub)
{
ne_process_dual_3d_common_start();
if (NE_Screen == 1)
mainscreen(argmain);
else
subscreen(argsub);
ne_process_dual_3d_common_end();
}
#define NE_DUAL_DMA_3D_LINES_OFFSET 20
static void ne_process_dual_3d_fb(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
static void ne_process_dual_3d_fb_common_start(void)
{
NE_UpdateInput();
@ -731,17 +770,41 @@ static void ne_process_dual_3d_fb(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
NE_Viewport(0, 0, 255, 191);
MATRIX_IDENTITY = 0;
}
static void ne_process_dual_3d_fb_common_end(void)
{
GFX_FLUSH = GL_TRANS_MANUALSORT;
dmaCopy(NE_Sprites, OAM_SUB, 128 * sizeof(SpriteEntry));
NE_Screen ^= 1;
}
static void ne_process_dual_3d_fb(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
{
ne_process_dual_3d_fb_common_start();
if (NE_Screen == 1)
mainscreen();
else
subscreen();
GFX_FLUSH = GL_TRANS_MANUALSORT;
ne_process_dual_3d_fb_common_end();
}
dmaCopy(NE_Sprites, OAM_SUB, 128 * sizeof(SpriteEntry));
static void ne_process_dual_3d_fb_arg(NE_VoidArgfunc mainscreen,
NE_VoidArgfunc subscreen,
void *argmain, void *argsub)
{
ne_process_dual_3d_fb_common_start();
NE_Screen ^= 1;
if (NE_Screen == 1)
mainscreen(argmain);
else
subscreen(argsub);
ne_process_dual_3d_fb_common_end();
}
static void ne_do_dma(void)
@ -762,11 +825,8 @@ static void ne_do_dma(void)
#endif
}
static void ne_process_dual_3d_dma(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
static void ne_process_dual_3d_dma_common_start(void)
{
NE_AssertPointer(mainscreen, "NULL function pointer (main screen)");
NE_AssertPointer(subscreen, "NULL function pointer (sub screen)");
if (NE_Screen == ne_main_screen)
lcdMainOnBottom();
else
@ -826,8 +886,6 @@ static void ne_process_dual_3d_dma(NE_Voidfunc mainscreen, NE_Voidfunc subscreen
DMA_START_HBL | DMA_REPEAT | DMA_SRC_INC | DMA_DST_RESET;
ne_do_dma();
mainscreen();
}
else
{
@ -882,10 +940,11 @@ static void ne_process_dual_3d_dma(NE_Voidfunc mainscreen, NE_Voidfunc subscreen
dmaCopyWords(3, BG_MAP_RAM_SUB(23), BG_MAP_RAM(8), 32 * 32 * 2);
ne_do_dma();
subscreen();
}
}
static void ne_process_dual_3d_dma_common_end(void)
{
GFX_FLUSH = GL_TRANS_MANUALSORT;
NE_Screen ^= 1;
@ -893,6 +952,32 @@ static void ne_process_dual_3d_dma(NE_Voidfunc mainscreen, NE_Voidfunc subscreen
NE_UpdateInput();
}
static void ne_process_dual_3d_dma(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
{
ne_process_dual_3d_dma_common_start();
if (NE_Screen == 1)
mainscreen();
else
subscreen();
ne_process_dual_3d_dma_common_end();
}
static void ne_process_dual_3d_dma_arg(NE_VoidArgfunc mainscreen,
NE_VoidArgfunc subscreen,
void *argmain, void *argsub)
{
ne_process_dual_3d_dma_common_start();
if (NE_Screen == 1)
mainscreen(argmain);
else
subscreen(argsub);
ne_process_dual_3d_dma_common_end();
}
void NE_ProcessDual(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
{
NE_AssertPointer(mainscreen, "NULL function pointer (main screen)");
@ -924,6 +1009,38 @@ void NE_ProcessDual(NE_Voidfunc mainscreen, NE_Voidfunc subscreen)
}
}
void NE_ProcessDualArg(NE_VoidArgfunc mainscreen, NE_VoidArgfunc subscreen,
void *argmain, void *argsub)
{
NE_AssertPointer(mainscreen, "NULL function pointer (main screen)");
NE_AssertPointer(subscreen, "NULL function pointer (sub screen)");
switch (ne_execution_mode)
{
case NE_ModeDual3D:
{
ne_process_dual_3d_arg(mainscreen, subscreen, argmain, argsub);
return;
}
case NE_ModeDual3D_FB:
{
ne_process_dual_3d_fb_arg(mainscreen, subscreen, argmain, argsub);
return;
}
case NE_ModeDual3D_DMA:
{
ne_process_dual_3d_dma_arg(mainscreen, subscreen, argmain, argsub);
return;
}
default:
{
return;
}
}
}
void NE_ClippingPlanesSetI(int znear, int zfar)
{
NE_Assert(znear < zfar, "znear must be smaller than zfar");