-
Notifications
You must be signed in to change notification settings - Fork 10
/
NEGeneral.h
415 lines (353 loc) · 14.3 KB
/
NEGeneral.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2008-2011, 2019, 2022 Antonio Niño Díaz
//
// This file is part of Nitro Engine
#ifndef NE_GENERAL_H__
#define NE_GENERAL_H__
#include <nds.h>
#include "NEMain.h"
/// @file NEGeneral.h
/// @brief Init 3D mode and process functions.
/// @defgroup general_utils General utilities
///
/// General functions to control Nitro Engine, setup screens, print debug
/// messages, etc.
///
/// If Nitro Engine is compiled with debug features, it will check a lot of
/// things and it will print error messages to an user-defined function. Check
/// the error handling example for more details. If you have finished testing
/// your code, just comment the define out and recompile Nitro Engine to save
/// RAM and CPU usage.
///
/// @{
/// Void function pointer used in NE_Process and NE_ProcessDual.
typedef void (*NE_Voidfunc)(void);
/// Holds information of keys and stylus input for internal use.
typedef struct {
uint32 kdown; ///< Keys that have just been pressed this frame.
uint32 kheld; ///< Keys that are pressed.
uint32 kup; ///< Keys that have just been released this frame.
touchPosition touch; ///< Touch screen state
} NE_Input;
/// Updates input data for internal use.
///
/// Use this if you are using NE_GUI or window system. You have to call
/// scanKeys() each frame for this to work.
void NE_UpdateInput(void);
/// Ends Nitro Engine and frees all memory used by it.
void NE_End(void);
/// Inits Nitro Engine and 3D mode in one screen.
///
/// @return Returns 0 on success.
int NE_Init3D(void);
/// Draws a 3D scene.
///
/// @param drawscene Function that draws the screen.
void NE_Process(NE_Voidfunc drawscene);
/// Inits Nitro Engine and 3D mode both screens.
///
/// VRAM banks C and D are used as framebuffers, which means there is only 50%
/// of the normally available VRAM for textures.
///
/// @return Returns 0 on success.
int NE_InitDual3D(void);
/// Draws a 3D scene in each screen.
///
/// 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.
void NE_ProcessDual(NE_Voidfunc mainscreen, NE_Voidfunc subscreen);
/// 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
/// layer that contains the text.
void NE_InitConsole(void);
/// Changes the color of the text of the console.
///
/// @param color New color.
void NE_SetConsoleColor(u32 color);
/// Set the top screen as main screen.
void NE_MainScreenSetOnTop(void);
/// Set the bottom screen as main screen.
void NE_MainScreenSetOnBottom(void);
/// Returns the current main screen.
///
/// @return Returns 1 if the top screen is the main screen, 0 otherwise.
int NE_MainScreenIsOnTop(void);
/// Swap top and bottom screen.
void NE_SwapScreens(void);
/// Setup the viewport.
///
/// The viewport is the part of the screen where the 3D scene is drawn.
///
/// NE_ProcessDual() sets the viewport is set to the full screen.
///
/// After NE_2DViewInit() the viewport is set to (0, 0, 255, 191).
///
/// NE_Process() sets the viewport back to the viewport set by NE_Viewport().
///
/// @param x1 (x1, y1) Bottom left pixel.
/// @param y1 (x1, y1) Bottom left pixel.
/// @param x2 (x2, y2) Top right pixel.
/// @param y2 (x2, y2) Top right pixel.
void NE_Viewport(int x1, int y1, int x2, int y2);
/// Set cameras field of view.
///
/// @param fovValue FOV [0, ...] in degrees.
void NE_SetFov(int fovValue);
/// Set near and far clipping planes.
///
/// @param znear Near plane (f32).
/// @param zfar Far plane (f32).
void NE_ClippingPlanesSetI(int znear, int zfar);
/// Set near and far clipping planes.
///
/// @param n Near plane (float).
/// @param f Far plane (float).
#define NE_ClippingPlanesSet(n, f) \
NE_ClippingPlanesSetI(floattof32(n), floattof32(f))
/// Enable or disable antialiasing.
///
/// @param value true enables antialiasing, false disables it.
void NE_AntialiasEnable(bool value);
/// Returns the number of polygons drawn since the last glFlush().
///
/// @return Returns the number of polygons (0 - 2048).
int NE_GetPolygonCount(void);
/// Returns the number of vertices drawn since the last glFlush().
///
/// @return Returns the number of vertices (0 - 6144).
int NE_GetVertexCount(void);
/// Effects supported by NE_SpecialEffectSet().
typedef enum {
NE_NONE, ///< Disable effects
NE_NOISE, ///< Horizontal noise
NE_SINE ///< Horizontal sine waves
} NE_SpecialEffects;
/// Vertical blank interrupt handler.
///
/// Internal use, must be called every vertical blank.
void NE_VBLFunc(void);
/// Pause or unpause special effects.
///
/// @param pause true pauses the effect, false unpauses it.
void NE_SpecialEffectPause(bool pause);
/// Horizontal blank interrupt handler.
///
/// Internal use, must be called every horizontal blank. It's only needed to
/// enable CPU usage measuring and things like special effects enabled by
/// NE_SpecialEffectSet().
void NE_HBLFunc(void);
/// Specify which special effect to display in the 3D screens.
///
/// @param effect One effect out of NE_NOISE, NE_SINE or NE_NONE.
void NE_SpecialEffectSet(NE_SpecialEffects effect);
/// Configures the special effect NE_NOISE.
///
/// If the effect is paused, the values won't be refreshed until it is unpaused.
///
/// @param value The value must be a power of two minus one. The default is 15.
void NE_SpecialEffectNoiseConfig(int value);
/// Configures the special effect NE_SINE.
///
/// @param mult Frecuency of the wave. The default value is 10.
/// @param shift Amplitude of the wave. The default value is 9. Bigger values
/// result in smaller waves.
void NE_SpecialEffectSineConfig(int mult, int shift);
/// Arguments for NE_WaitForVBL().
typedef enum {
/// Update the GUI implemented by Nitro Engine.
NE_UPDATE_GUI = BIT(0),
/// Update all animated models.
NE_UPDATE_ANIMATIONS = BIT(1),
/// Updates the physics engine.
NE_UPDATE_PHYSICS = BIT(2),
/// Allows Nitro Engine to skip the wait to the vertical blank if CPU load
/// is greater than 100%. You can use this if you don't need to load
/// textures or do anything else during the VBL. It is needed to set
/// NE_HBLFunc() as a HBL interrupt handler for this flag to work.
NE_CAN_SKIP_VBL = BIT(3)
} NE_UpdateFlags;
/// Waits for the vertical blank and updates the selected systems.
///
/// You should OR all the flags that you need. For example, you can call this
/// function like NE_WaitForVBL(NE_UPDATE_GUI | NE_UPDATE_ANIMATIONS);
///
/// @param flags Look at NE_UpdateFlags.
void NE_WaitForVBL(NE_UpdateFlags flags);
/// Returns the approximate CPU usage in the previous frame.
///
/// You need to set NE_WaitForVBL() as a VBL interrupt handler and NE_HBLFunc()
/// as a HBL interrupt handler for the CPU meter to work.
///
/// @return CPU usage (0 - 100).
int NE_GetCPUPercent(void);
/// Returns true if the GPU is in a rendering period.
///
/// The period when the GPU isn't drawing is when VCOUNT is between 192 and 213.
///
/// During the drawing period you should't load textures. If you try to load
/// textures, there is a moment when the GPU can't access that data, so there
/// will be glitches in the 3D output.
///
/// @return Returns true if the GPU is in the rendering period.
bool NE_GPUIsRendering(void);
#ifdef NE_DEBUG
// TODO: Replace sprintf by snprintf
/// TODO: Document
#define NE_AssertMinMax(min, value, max, format...) \
do \
{ \
if (((min) > (value)) || ((max) < (value))) \
{ \
char string[256]; \
sprintf(string, "%s:%d:", __func__, __LINE__); \
__NE_debugprint(string); \
sprintf(string, ##format); \
__NE_debugprint(string); \
__NE_debugprint("\n"); \
} \
} while (0)
/// TODO: Document
#define NE_AssertPointer(ptr, format...) \
do \
{ \
if (!(ptr)) \
{ \
char string[256]; \
sprintf(string, "%s:%d:", __func__, __LINE__); \
__NE_debugprint(string); \
sprintf(string, ##format); \
__NE_debugprint(string); \
__NE_debugprint("\n"); \
} \
} while (0)
/// TODO: Document
#define NE_Assert(cond, format...) \
do \
{ \
if (!(cond)) \
{ \
char string[256]; \
sprintf(string, "%s:%d:", __func__, __LINE__); \
__NE_debugprint(string); \
sprintf(string, ##format); \
__NE_debugprint(string); \
__NE_debugprint("\n"); \
} \
} while (0)
/// TODO: Document
#define NE_DebugPrint(format...) \
do \
{ \
char string[256]; \
sprintf(string, "%s:%d:", __func__, __LINE__); \
__NE_debugprint(string); \
sprintf(string, ##format); \
__NE_debugprint(string); \
__NE_debugprint("\n"); \
} while (0)
/// Function used internally by Nitro Engine to report error messages.
///
/// It is only used when NE_DEBUG is defined.
///
/// @param text Text to print.
void __NE_debugprint(const char *text);
/// Sets a debug handler where Nitro Engine will send debug information.
///
/// @param fn Handler where Nitro Engine will send debug information.
void NE_DebugSetHandler(void (*fn)(const char *));
/// Sets the console of libnds as destination of the debug information.
void NE_DebugSetHandlerConsole(void);
#else // #ifndef NE_DEBUG
#define NE_AssertMinMax(min, value, max, format...) \
do { \
(void)(min); \
(void)(value); \
(void)(max); \
} while (0);
#define NE_AssertPointer(ptr, format...) \
do { \
(void)(ptr); \
} while (0);
#define NE_Assert(cond, format...) \
do { \
(void)(cond); \
} while (0);
#define NE_DebugPrint(format...)
#define NE_DebugSetHandler(fn) \
do { \
(void)(fn); \
} while (0);
#define NE_DebugSetHandlerConsole()
#endif
/// @}
/// @defgroup touch_test Touch test
///
/// Functions to detect if an object is being pressed by the stylus.
///
/// If you want to know if you are touching something in the touch screen you
/// can use the functions of this group. They perform tests to know if an object
/// is under the coordinates of the stylus, and they return its distance from
/// the camera.
///
/// TODO: There is a bug in gluPickMatrix() when first two coordinates of
/// viewport are different from (0,0).
///
/// Note: This uses last stylus coordinates even if it has been released. You
/// will have to check by yourself if the stylus is really in contact with the
/// screen.
///
/// Note: It two objects overlap, the test may fail to diferenciate which of
/// them is closer to the camera.
///
/// Note: If you want to draw something without using NE_ModelDraw(), you will
/// have to move the view to the center of your model and use
/// PosTest_Asynch(0, 0, 0).
///
/// This doesn't work in most emulators, but it works in melonDS.
///
/// How to use this test:
///
/// 1. Init the "touch test mode" with NE_TouchTestStart() to prepare the
/// hardware. During this mode, polygons are not drawn on the screen. For
/// this reason, it is possible to use simplified models (without texture,
/// normals, with fewer polygons, etc) to speed up the process.
///
/// 2. Call NE_TouchTestObject().
///
/// 3. Draw the model with NE_ModelDraw(), for example.
///
/// 4. Call NE_TouchTestResult() to know if it is being touched. If it is being
/// touched, it returns the distance from the camera.
///
/// 5. Repeat 2-4 for each model you want to test.
///
/// 6. Call NE_TouchTestEnd() to exit "touch test mode".
///
/// Adapted from the Picking example of libnds by Gabe Ghearing.
///
/// @{
/// Starts "touch test mode" and saves all current matrices.
///
/// Polygons drawn after this won't be displayed on screen. It is a good idea to
/// use models with less details than the original to perform this test.
void NE_TouchTestStart(void);
/// Starts a test for a model.
void NE_TouchTestObject(void);
/// Gets the result of the touch test.
///
/// @return It returns -1 if the model is NOT being touched. If it is touched,
/// it returns the distance to the camera.
int NE_TouchTestResult(void);
/// Ends "touch test mode" and restores the previous matrices.
///
/// Polygons drawn after this will be displayed on screen.
void NE_TouchTestEnd(void);
/// @}
#endif // NE_GENERAL_H__