Custom assert

From WiiBrew
Jump to: navigation, search

Here is my custom assert


This code is for GX video only. note: after doing the below make sure you define USE_CUSTOM_ASSERT, i add -DUSE_CUSTOM_ASSERT in my makefile in the line with CFLAGS.

in your code define GXRModeObj *global_rmode; and set it to your rmode variable.


in assert.h there are two changes. The first is the prototype under the first extern "C" the second is at bottom, the #ifdef USE_CUSTOM_ASSERT / #endif block the below is my current assert.h, its found in devkitPro\devkitPPC\powerpc-gekko\include since cassert includes assert.h you can include either one.


assert.h

/*
	assert.h
*/

#ifdef __cplusplus
extern "C" {
#endif

void MyAssert__(const char *fn, long line);
#include "_ansi.h"

#undef assert

#ifdef NDEBUG /* required by ANSI standard */
# define assert(__e) ((void)0)
#else
# define assert(__e) ((__e) ? (void)0 : __assert_func (__FILE__, __LINE__, \
						 __ASSERT_FUNC, #__e))

# ifndef __ASSERT_FUNC
  /* Use g++'s demangled names in C++.  */
# if defined __cplusplus && defined __GNUC__
# define __ASSERT_FUNC __PRETTY_FUNCTION__

  /* C99 requires the use of __func__, gcc also supports it.  */
# elif defined __GNUC__ || __STDC_VERSION__ >= 199901L
# define __ASSERT_FUNC __func__

  /* failed to detect __func__ support.  */
# else
# define __ASSERT_FUNC ((char *) 0)
# endif
# endif /* !__ASSERT_FUNC */
#endif /* !NDEBUG */

void _EXFUN(__assert, (const char *, int, const char *)
	 _ATTRIBUTE ((__noreturn__)));
void _EXFUN(__assert_func, (const char *, int, const char *, const char *)
	 _ATTRIBUTE ((__noreturn__)));

#ifdef __cplusplus
}
#endif


#ifdef USE_CUSTOM_ASSERT
#undef assert
#define assert(e) e ? (void)0 : MyAssert__(__FILE__, __LINE__);
#endif


Thanks for dhewg for giving me this code. All i added was the extern "C" line. log_console.h

/*-------------------------------------------------------------

Copyright (C) 2008 dhewg

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.

Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:

1.	The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.

2.	Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.

3.	This notice may not be removed or altered from any source
distribution.

-------------------------------------------------------------*/

#ifndef _LOG_CONSOLE_H_
#define _LOG_CONSOLE_H_

#include <gccore.h>

 #ifdef __cplusplus
 extern "C" {
 #endif 
void log_console_init(GXRModeObj *vmode, u16 logsize);
void log_console_deinit(void);
void log_console_enable_log(bool enable);
void log_console_enable_video(bool enable);
#ifdef __cplusplus
}
#endif 
#endif


I added everything after /* Mavakadachi */


log_console.c

/*-------------------------------------------------------------

Copyright (C) 2008 dhewg

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.

Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:

1.	The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.

2.	Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.

3.	This notice may not be removed or altered from any source
distribution.

-------------------------------------------------------------*/

#include <sys/iosupport.h>
#include <reent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "log_console.h"

static bool gecko = false;
static const devoptab_t *dot_video = NULL;
static VIRetraceCallback rcb = NULL;
static char **log = NULL;
static u16 log_size = 0;
static u16 log_next = 0;
static bool log_active = true;
static bool video_active = true;

static int __out_write(struct _reent *r, int fd, const char *ptr, size_t len) {
	u16 l;

	if (!ptr || len <= 0)
		return -1;

	if (video_active) {
		dot_video->write_r(r, fd, ptr, len);
	} else {
		if (log_active) {
			l = (log_next + 1) % log_size;
			if (log[l])
				free(log[l]);
			log[l] = strndup(ptr, len);

			log_next = l;
		}
	}

	if (gecko)
		usb_sendbuffer(1, ptr, len);

	return len;
}

const devoptab_t dot_out = {
	"stdout",	// device name
	0,			// size of file structure
	NULL,		// device open
	NULL,		// device close
	__out_write,// device write
	NULL,		// device read
	NULL,		// device seek
	NULL,		// device fstat
	NULL,		// device stat
	NULL,		// device link
	NULL,		// device unlink
	NULL,		// device chdir
	NULL,		// device rename
	NULL,		// device mkdir
	0,			// dirStateSize
	NULL,		// device diropen_r
	NULL,		// device dirreset_r
	NULL,		// device dirnext_r
	NULL,		// device dirclose_r
	NULL		// device statvfs_r
};

void log_console_init(GXRModeObj *vmode, u16 logsize) {
	u16 i;

	CON_InitEx(vmode, 20, 30, vmode->fbWidth - 40, vmode->xfbHeight - 60);
	rcb = VIDEO_SetPostRetraceCallback(NULL);
	VIDEO_SetPostRetraceCallback(rcb);

	gecko = usb_isgeckoalive(1);

	if (log_size && log) {
		for (i = 0; i < log_size; ++i)
			if (log[i])
				free(log[i]);

		free(log);
	}

	log_size = logsize;
	log_next = 0;

	if (log_size) {
		log = (char **) malloc(log_size * sizeof(char *));

		for (i = 0; i < log_size; ++i)
			log[i] = NULL;
	}

	log_active = log_size > 0;

	dot_video = devoptab_list[STD_OUT];
	video_active = true;

	devoptab_list[STD_OUT] = &dot_out;
	devoptab_list[STD_ERR] = &dot_out;
}

void log_console_deinit(void) {
	u16 i;

	if (log_size && log) {
		for (i = 0; i < log_size; ++i)
			if (log[i])
				free(log[i]);

		free(log);
		log = NULL;
	}

	log_size = 0;
	log_next = 0;

	devoptab_list[STD_OUT] = dot_video;
	devoptab_list[STD_ERR] = dot_video;

	VIDEO_SetPostRetraceCallback(rcb);

	dot_video = NULL;
}

void log_console_enable_log(bool enable) {
	if (!log_size)
		return;

	log_active = enable;
}

void log_console_enable_video(bool enable) {
	struct _reent *r = _REENT;
	u16 i, l;

	if (video_active == enable)
		return;

	video_active = enable;

	if (enable)
		VIDEO_SetPostRetraceCallback(rcb);
	else
		VIDEO_SetPostRetraceCallback(NULL);

	if (!enable || !log_size)
		return;

	for (i = 0; i < log_size; ++i) {
		l = (log_next + 1 + i) % log_size;
		if (log[l]) {
			dot_video->write_r(r, 0, log[l], strlen(log[l]));
			free(log[l]);
			log[l] = NULL;
		}
	}

	fflush(stdout);
}

/* Mavakadachi */
#include <wiiuse/wpad.h>

extern GXRModeObj *global_rmode;

void MyAssert__(const char *fn, long line)
{
	log_console_init(global_rmode, 16);
	log_console_enable_video(1);
	log_console_enable_log(1);
	printf("Assert failed in file %s on line %d\n", fn, line);
	while (1)
	{
	WPAD_ScanPads();
	if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
		exit(0);

	VIDEO_Flush();
	VIDEO_WaitVSync();
	}
}