diff --git a/examples/brew-volley/main.c b/examples/brew-volley/main.c old mode 100755 new mode 100644 index 16693116c6..82eee847fb --- a/examples/brew-volley/main.c +++ b/examples/brew-volley/main.c @@ -453,7 +453,7 @@ int main() debug_init_isviewer(); debug_init_usblog(); - display_init(RESOLUTION_640x480, DEPTH_16_BPP, 3, GAMMA_NONE, ANTIALIAS_RESAMPLE_FETCH_ALWAYS); + display_init(RESOLUTION_640x480, DEPTH_16_BPP, 3, GAMMA_NONE, FILTERS_DEDITHER); controller_init(); timer_init(); diff --git a/examples/fontdemo/fontdemo.c b/examples/fontdemo/fontdemo.c index 136265cc40..b7454f6b16 100644 --- a/examples/fontdemo/fontdemo.c +++ b/examples/fontdemo/fontdemo.c @@ -85,7 +85,7 @@ int main() controller_init(); dfs_init(DFS_DEFAULT_LOCATION); - display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, ANTIALIAS_RESAMPLE); + display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, FILTERS_RESAMPLE); rdpq_init(); // rdpq_debug_start(); // rdpq_debug_log(true); diff --git a/examples/gldemo/gldemo.c b/examples/gldemo/gldemo.c index 5db49e1695..000297f3a6 100644 --- a/examples/gldemo/gldemo.c +++ b/examples/gldemo/gldemo.c @@ -114,6 +114,8 @@ void setup() glFogf(GL_FOG_END, 20); glFogfv(GL_FOG_COLOR, environment_color); + glEnable(GL_MULTISAMPLE_ARB); + glGenTextures(4, textures); #if 0 @@ -204,7 +206,7 @@ int main() dfs_init(DFS_DEFAULT_LOCATION); - display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, ANTIALIAS_RESAMPLE_FETCH_ALWAYS); + display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, FILTERS_RESAMPLE_ANTIALIAS_DEDITHER); rdpq_init(); gl_init(); diff --git a/examples/overlays/actor/overlays_actor.c b/examples/overlays/actor/overlays_actor.c index 4be19fde83..6b4c144e4f 100644 --- a/examples/overlays/actor/overlays_actor.c +++ b/examples/overlays/actor/overlays_actor.c @@ -100,7 +100,7 @@ int main() debug_init_isviewer(); debug_init_usblog(); //Init rendering - display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, ANTIALIAS_RESAMPLE); + display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, FILTERS_RESAMPLE); rdpq_init(); rdpq_debug_start(); scr_width = display_get_width(); diff --git a/examples/overlays/scene/overlays_scene.cpp b/examples/overlays/scene/overlays_scene.cpp index d414de2a60..071c9289c0 100644 --- a/examples/overlays/scene/overlays_scene.cpp +++ b/examples/overlays/scene/overlays_scene.cpp @@ -7,7 +7,7 @@ int main() debug_init_isviewer(); debug_init_usblog(); //Init rendering - display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, ANTIALIAS_RESAMPLE); + display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, FILTERS_RESAMPLE); rdpq_init(); rdpq_debug_start(); //Init miscellaneous system diff --git a/examples/pixelshader/pixelshader.c b/examples/pixelshader/pixelshader.c index 6ff91efde7..ffaac0bf7c 100644 --- a/examples/pixelshader/pixelshader.c +++ b/examples/pixelshader/pixelshader.c @@ -62,7 +62,7 @@ void rsp_blend_process_line(surface_t *dest, int x0, int y0, int numlines) { int main(void) { debug_init_isviewer(); debug_init_usblog(); - display_init(RESOLUTION_640x480, DEPTH_16_BPP, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE); + display_init(RESOLUTION_640x480, DEPTH_16_BPP, 2, GAMMA_NONE, FILTERS_RESAMPLE); dfs_init(DFS_DEFAULT_LOCATION); controller_init(); rdpq_init(); diff --git a/examples/rdpqdemo/rdpqdemo.c b/examples/rdpqdemo/rdpqdemo.c index f89aa21db2..8d83382f45 100644 --- a/examples/rdpqdemo/rdpqdemo.c +++ b/examples/rdpqdemo/rdpqdemo.c @@ -21,7 +21,7 @@ static object_t objects[NUM_OBJECTS]; // Fair and fast random generation (using xorshift32, with explicit seed) static uint32_t rand_state = 1; -static uint32_t rand(void) { +static uint32_t myrand(void) { uint32_t x = rand_state; x ^= x << 13; x ^= x >> 7; @@ -32,8 +32,8 @@ static uint32_t rand(void) { // RANDN(n): generate a random number from 0 to n-1 #define RANDN(n) ({ \ __builtin_constant_p((n)) ? \ - (rand()%(n)) : \ - (uint32_t)(((uint64_t)rand() * (n)) >> 32); \ + (myrand()%(n)) : \ + (uint32_t)(((uint64_t)myrand() * (n)) >> 32); \ }) static int32_t obj_max_x; @@ -101,7 +101,7 @@ int main() debug_init_isviewer(); debug_init_usblog(); - display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, ANTIALIAS_RESAMPLE); + display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, FILTERS_RESAMPLE); controller_init(); timer_init(); diff --git a/examples/videoplayer/videoplayer.c b/examples/videoplayer/videoplayer.c index e5e69614a1..2268bd63a8 100644 --- a/examples/videoplayer/videoplayer.c +++ b/examples/videoplayer/videoplayer.c @@ -23,7 +23,7 @@ int main(void) { debug_init_isviewer(); debug_init_usblog(); - display_init(RESOLUTION_320x240, DEPTH_32_BPP, NUM_DISPLAY, GAMMA_NONE, ANTIALIAS_OFF); + display_init(RESOLUTION_320x240, DEPTH_32_BPP, NUM_DISPLAY, GAMMA_NONE, FILTERS_DISABLED); dfs_init(DFS_DEFAULT_LOCATION); rdpq_init(); diff --git a/include/display.h b/include/display.h index 19bb3e04f2..ce116f54b0 100644 --- a/include/display.h +++ b/include/display.h @@ -272,6 +272,13 @@ uint32_t display_get_bitdepth(void); */ uint32_t display_get_num_buffers(void); +/** + * @brief Get the current number of frames per second being rendered + * + * @return float Frames per second + */ +float display_get_fps(void); + /** @cond */ __attribute__((deprecated("use display_get or display_try_get instead"))) diff --git a/include/fmath.h b/include/fmath.h index 8c061cf14d..968c238b64 100644 --- a/include/fmath.h +++ b/include/fmath.h @@ -170,11 +170,23 @@ float fm_sinf_approx(float x, int approx); /** * @brief Faster version of cosf. * - * @see dragon_sinf for considerations on why and how to use this functions + * @see #fm_sinf for considerations on why and how to use this functions * instead of the standard sinf. */ float fm_cosf(float x); +/** + * @brief Faster version of sincosf. + * + * Similar to #fm_sinf and #fm_cosf, but calculates both sinf and cosf + * for the same angle. + * + * @param x The angle in radians + * @param sin The pointer to the variable that will contain the sine + * @param cos The pointer to the variable that will contain the cosine + */ +void fm_sincosf(float x, float *sin, float *cos); + /** * @brief Faster version of atan2f. * @@ -199,10 +211,11 @@ float fm_atan2f(float y, float x); // we expect that to be resolved at compile-time with the maximum accuracy, // so it's important to generate code that calls the standard C function // which is then intrinsified by the compiler. - #define fmodf(x, y) ((__builtin_constant_p(x) && __builtin_constant_p(y)) ? fmodf(x,y) : fm_fmodf(x,y)) - #define sinf(x) (__builtin_constant_p(x) ? sinf(x) : fm_sinf(x)) - #define cosf(x) (__builtin_constant_p(x) ? cosf(x) : fm_cosf(x)) - #define atan2f(y, x) ((__builtin_constant_p(x) && __builtin_constant_p(y)) ? atan2f(y, x) : fm_atan2f(y, x)) + #define fmodf(x, y) ((__builtin_constant_p(x) && __builtin_constant_p(y)) ? fmodf(x,y) : fm_fmodf(x,y)) + #define sinf(x) (__builtin_constant_p(x) ? sinf(x) : fm_sinf(x)) + #define cosf(x) (__builtin_constant_p(x) ? cosf(x) : fm_cosf(x)) + #define sincosf(x,s,c) (__builtin_constant_p(x) ? sincosf(x,s,c) : fm_sincosf(x,s,c)) + #define atan2f(y, x) ((__builtin_constant_p(x) && __builtin_constant_p(y)) ? atan2f(y, x) : fm_atan2f(y, x)) #endif #ifdef __cplusplus diff --git a/include/rsp.h b/include/rsp.h index 01e1fd44cc..80fa19cfb3 100644 --- a/include/rsp.h +++ b/include/rsp.h @@ -157,6 +157,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -468,9 +469,13 @@ void rsp_read_data(void* data, unsigned long size, unsigned int dmem_offset); * * @see #rsp_crashf */ +#ifndef NDEBUG #define rsp_crash() ({ \ __rsp_crash(__FILE__, __LINE__, __func__, NULL); \ -}) +}) +#else +#define rsp_crash() abort() +#endif /** * @brief Abort the program showing a RSP crash screen with a symptom message. @@ -487,9 +492,13 @@ void rsp_read_data(void* data, unsigned long size, unsigned int dmem_offset); * * @see #rsp_crash */ +#ifndef NDEBUG #define rsp_crashf(msg, ...) ({ \ __rsp_crash(__FILE__, __LINE__, __func__, msg, ##__VA_ARGS__); \ }) +#else +#define rsp_crashf(msg, ...) abort() +#endif /** * @brief Create a loop that waits for some condition that is related to RSP, @@ -549,9 +558,13 @@ void run_ucode(void) { // Internal function used by rsp_crash and rsp_crashf. These are not part // of the public API of rsp.h. Do not call them directly. /// @cond +#ifndef NDEBUG void __rsp_crash(const char *file, int line, const char *func, const char *msg, ...) __attribute__((noreturn, format(printf, 4, 5))); void __rsp_check_assert(const char *file, int line, const char *func); +#else +static inline void __rsp_check_assert(const char *file, int line, const char *func) {} +#endif /// @endcond #ifdef __cplusplus diff --git a/src/GL/gl_internal.h b/src/GL/gl_internal.h index 349fe89765..8dd2ea7533 100644 --- a/src/GL/gl_internal.h +++ b/src/GL/gl_internal.h @@ -808,6 +808,7 @@ inline void* gl_get_attrib_pointer(gl_obj_attributes_t *attribs, gl_array_type_t return attribs->mtx_index; default: assert(0); + return NULL; } } diff --git a/src/debug.c b/src/debug.c index 539bf32b70..9f0475cd02 100644 --- a/src/debug.c +++ b/src/debug.c @@ -2,7 +2,7 @@ * @file debug.c * @brief Debugging Support */ - +#ifndef NDEBUG #include #include #include @@ -651,3 +651,12 @@ void debug_backtrace(void) { __debug_backtrace(stderr, false); } +#else + +#include + +void debug_assert_func(...) { + abort(); +} + +#endif diff --git a/src/display.c b/src/display.c index b2fec553fb..a1fa64ef49 100644 --- a/src/display.c +++ b/src/display.c @@ -19,7 +19,8 @@ /** @brief Maximum number of video backbuffers */ #define NUM_BUFFERS 32 - +/** @brief Number of past frames used to evaluate FPS */ +#define FPS_WINDOW 32 static surface_t *surfaces; /** @brief Currently active bit depth */ @@ -40,6 +41,12 @@ static int now_showing = -1; static uint32_t drawing_mask = 0; /** @brief Bitmask of surfaces that are ready to be shown */ static volatile uint32_t ready_mask = 0; +/** @brief Window of absolute times at which previous frames were shown */ +static uint32_t frame_times[FPS_WINDOW]; +/** @brief Current index into the frame times window */ +static int frame_times_index = 0; +/** @brief Current duration of the frame window (time elapsed for FPS_WINDOW frames) */ +static uint32_t frame_times_duration; /** @brief Get the next buffer index (with wraparound) */ static inline int buffer_next(int idx) { @@ -86,15 +93,12 @@ void display_init( resolution_t res, bitdepth_t bit, uint32_t num_buffers, gamma /* Minimum is two buffers. */ __buffers = MAX(1, MIN(NUM_BUFFERS, num_buffers)); - - if( res.interlaced != INTERLACE_OFF ) - { - /* Serrate on to stop vertical jitter */ - control |= VI_CTRL_SERRATE; - } + bool serrate = res.interlaced != INTERLACE_OFF; + /* Serrate on to stop vertical jitter */ + if(serrate) control |= VI_CTRL_SERRATE; /* Copy over extra initializations */ - vi_write_config(&vi_config_presets[res.interlaced][tv_type]); + vi_write_config(&vi_config_presets[serrate][tv_type]); /* Figure out control register based on input given */ switch( bit ) @@ -349,6 +353,16 @@ void display_show( surface_t* surf ) drawing_mask &= ~(1 << i); ready_mask |= 1 << i; + /* Record the time at which this frame was (asked to be) shown */ + uint32_t old_ticks = frame_times[frame_times_index]; + uint32_t now = get_ticks(); + if (old_ticks) + frame_times_duration = TICKS_DISTANCE(old_ticks, now); + frame_times[frame_times_index] = now; + frame_times_index++; + if (frame_times_index == FPS_WINDOW) + frame_times_index = 0; + enable_interrupts(); } @@ -373,22 +387,28 @@ void display_show_force( display_context_t disp ) enable_interrupts(); } -uint32_t display_get_width() +uint32_t display_get_width(void) { return __width; } -uint32_t display_get_height() +uint32_t display_get_height(void) { return __height; } -uint32_t display_get_bitdepth() +uint32_t display_get_bitdepth(void) { return __bitdepth; } -uint32_t display_get_num_buffers() +uint32_t display_get_num_buffers(void) { return __buffers; } + +float display_get_fps(void) +{ + if (!frame_times_duration) return 0; + return (float)(FPS_WINDOW * TICKS_PER_SECOND) / frame_times_duration; +} diff --git a/src/exception.c b/src/exception.c index 12591f1302..3d7f6c7260 100644 --- a/src/exception.c +++ b/src/exception.c @@ -202,6 +202,7 @@ void __exception_dump_fpr(exception_t* ex, void (*cb)(void *arg, const char *reg } } +#ifndef NDEBUG static void debug_exception(exception_t* ex) { debugf("\n\n******* CPU EXCEPTION *******\n"); __exception_dump_header(stderr, ex); @@ -225,6 +226,7 @@ static void debug_exception(exception_t* ex) { debugf("\n"); } } +#endif /** * @brief Default exception handler. @@ -234,6 +236,7 @@ static void debug_exception(exception_t* ex) { * of all GPR/FPR registers. It then calls abort() to abort execution. */ void exception_default_handler(exception_t* ex) { + #ifndef NDEBUG static bool backtrace_exception = false; // Write immediately as much data as we can to the debug spew. This is the @@ -250,6 +253,7 @@ void exception_default_handler(exception_t* ex) { // Run the inspector __inspector_exception(ex); + #endif abort(); } diff --git a/src/fmath.c b/src/fmath.c index ba515cab2b..054287f6fa 100644 --- a/src/fmath.c +++ b/src/fmath.c @@ -49,6 +49,12 @@ float fm_cosf(float x) { return fm_sinf(half_pi_hi - x); } +void fm_sincosf(float x, float *sin, float *cos) { + float y = fm_sinf_approx(x, 0); + *sin = y; + *cos = sqrtf(1.0f - y * y); +} + float fm_atan2f(float y, float x) { // Approximation of atan2f using a polynomial minmax approximation in [0,1] // calculated via the Remez algorithm (https://math.stackexchange.com/a/1105038). diff --git a/src/inspector.c b/src/inspector.c index d5bc2948bd..069af8dd61 100644 --- a/src/inspector.c +++ b/src/inspector.c @@ -1,3 +1,4 @@ +#ifndef NDEBUG #include "graphics.h" #include "display.h" #include "debug.h" @@ -583,3 +584,4 @@ void __inspector_init(void) { } register_syscall_handler(handler, 0x00001, 0x00002); } +#endif /* NDBUEG */ diff --git a/src/rsp.c b/src/rsp.c index df1a63066e..98c423343f 100644 --- a/src/rsp.c +++ b/src/rsp.c @@ -41,7 +41,9 @@ static void __SP_DMA_wait(void) static void rsp_interrupt(void) { + #ifndef NDEBUG __rsp_check_assert(__FILE__, __LINE__, __func__); + #endif } void rsp_init(void) @@ -170,6 +172,7 @@ void rsp_run(void) rsp_wait(); } +#ifndef NDEBUG /// @cond // Check if the RSP has hit an internal assert, and call rsp_crash if so. // This function is invoked by #RSP_WAIT_LOOP while waiting for the RSP @@ -196,7 +199,9 @@ void __rsp_check_assert(const char *file, int line, const char *func) } } /// @endcond +#endif /* NDEBUG */ +#ifndef NDEBUG /// @cond // RSP crash handler implementation __attribute__((noreturn, format(printf, 4, 5))) @@ -447,5 +452,6 @@ void __rsp_crash(const char *file, int line, const char *func, const char *msg, abort(); } /// @endcond +#endif /* NDEBUG */ extern inline void rsp_run_async(void); diff --git a/src/rspq/rspq.c b/src/rspq/rspq.c index 4bd74077f6..c3ceb11cb4 100644 --- a/src/rspq/rspq.c +++ b/src/rspq/rspq.c @@ -754,6 +754,7 @@ static uint32_t rspq_overlay_get_command_count(rspq_overlay_header_t *header) } assertf(0, "Overlays can only define up to %d commands!", RSPQ_MAX_OVERLAY_COMMAND_COUNT); + return 0; } static uint32_t rspq_find_new_overlay_index(void) diff --git a/tests/testrom.c b/tests/testrom.c index a2788ebeac..c72aca38dd 100644 --- a/tests/testrom.c +++ b/tests/testrom.c @@ -58,7 +58,7 @@ typedef void (*TestFunc)(TestContext *ctx); // Fair and fast random generation (using xorshift32, with explicit seed) static uint32_t rand_state = 1; -static uint32_t rand(void) { +static uint32_t myrand(void) { uint32_t x = rand_state; x ^= x << 13; x ^= x >> 7; @@ -72,8 +72,8 @@ static uint32_t rand(void) { // RANDN(n): generate a random number from 0 to n-1 #define RANDN(n) ({ \ __builtin_constant_p((n)) ? \ - (rand()%(n)) : \ - (uint32_t)(((uint64_t)rand() * (n)) >> 32); \ + (myrand()%(n)) : \ + (uint32_t)(((uint64_t)myrand() * (n)) >> 32); \ }) // ASSERT(cond, msg): fail the test if the condition is false (with log message)