CfgUSBLoader/source/debug.c
2015-01-17 10:11:08 +00:00

353 lines
7.4 KiB
C

// by oggzee
#include <gccore.h>
#include <ogcsys.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include "cfg.h"
#include "console.h"
#include "fat.h"
struct timestats TIME;
int gecko_enabled = 0;
static long long dbg_t1, dbg_t2;
static long long dbg_t;
static int debug_inited = 0;
static int debug_logging = 1;
char dbg_log_buf[DBG_LOG_SIZE];
long long dbg_time_usec()
{
long long t = gettime();
long long d = diff_usec(dbg_t, t);
dbg_t = t;
return d;
}
void dbg_time1()
{
dbg_t1 = gettime();
}
unsigned dbg_time2(char *msg)
{
unsigned ms;
dbg_t2 = gettime();
ms = diff_msec(dbg_t1, dbg_t2);
if (msg) printf("%s %u", msg, ms);
dbg_t1 = dbg_t2;
return ms;
}
int gecko_prints(const char *str)
{
if (!gecko_enabled) return 0;
return usb_sendbuffer(EXI_CHANNEL_1, str, strlen(str));
}
int gecko_printv(const char *fmt, va_list ap)
{
char str[1024];
int r;
if (!gecko_enabled) return 0;
r = vsnprintf(str, sizeof(str), fmt, ap);
gecko_prints(str);
return r;
}
int gecko_printf(const char *fmt, ... )
{
va_list ap;
int r;
if (!gecko_enabled) return 0;
va_start(ap, fmt);
r = gecko_printv(fmt, ap);
va_end(ap);
return r;
}
int dbg_printv(int level, const char *fmt, va_list ap)
{
char str[1024];
int r = 0;
if (!CFG.debug && !CFG.debug_gecko && !debug_logging) return 0;
r = vsnprintf(str, sizeof(str), fmt, ap);
if (debug_logging) {
int len1 = strlen(dbg_log_buf);
int len2 = strlen(str);
if (len1 + len2 >= sizeof(dbg_log_buf)) {
// move text down
int need = len1 + len2 + 1 - sizeof(dbg_log_buf);
char *cut = dbg_log_buf + sizeof(dbg_log_buf) - DBG_LOG_CUT;
memmove(cut, cut + need, DBG_LOG_CUT - need);
memcpy(cut, "\n\n~~~\n\n", 7);
dbg_log_buf[sizeof(dbg_log_buf) - need] = 0;
}
strappend(dbg_log_buf, str, sizeof(dbg_log_buf));
/*
if (strlen(dbg_log_buf) >= sizeof(dbg_log_buf) - 1) {
// buf full, disable log
debug_logging = 0;
}*/
}
if (debug_inited) {
if (CFG.debug >= level) {
printf("%s", str);
}
if (gecko_enabled && (CFG.debug_gecko & 1)) {
gecko_prints(str);
}
}
return r;
}
int dbg_printf(const char *fmt, ... )
{
va_list ap;
int r = 0;
va_start(ap, fmt);
r = dbg_printv(1, fmt, ap);
va_end(ap);
return r;
}
int dbg_print(int level, const char *fmt, ...)
{
va_list ap;
int r = 0;
va_start(ap, fmt);
r = dbg_printv(level, fmt, ap);
va_end(ap);
return r;
}
/*
debug_gecko bits:
1 : all dbg_printf
2 : all printf
4 : only gecko_printf
*/
void InitDebug()
{
if (CFG.debug_gecko & (1|4))
{
if (usb_isgeckoalive(EXI_CHANNEL_1)) {
usb_flush(EXI_CHANNEL_1);
if (!gecko_enabled) {
gecko_enabled = 1;
gecko_prints("\n\n====================\n\n");
}
}
}
if (CFG.debug_gecko & 2) {
CON_EnableGecko(EXI_CHANNEL_1, 0);
}
debug_inited = 1;
if (strlen(dbg_log_buf)) {
gecko_printf(">>>\n%s\n<<<\n", dbg_log_buf);
}
}
/* seconds in float */
float diff_fsec(long long t1, long long t2)
{
return (float)diff_msec(t1, t2) / 1000.0;
}
void get_time2(long long *t, char *s)
{
if (!t) return;
if (*t == 0) *t = gettime();
char c;
char *p;
char ss[32];
char *dir;
int len;
long long tt = gettime();
p = strchr(s, '.');
if (p) p++; else p = s;
STRCOPY(ss, p);
len = strlen(ss) - 1;
c = ss[len];
if (c == '1') { dir = "-->"; ss[len] = 0; }
else if (c == '2') { dir = "<--"; ss[len] = 0; }
else return; //dir = "---";
dbg_printf("[%.3f] %s %s\n", diff_fsec(TIME.boot1, tt), dir, ss);
if (CFG.debug) __console_flush(0);
}
long tm_sum;
#define TIME_S(X) ((float)TIME_MS(X)/1000.0)
#define printx(...) do{ \
if (f) fprintf(f,__VA_ARGS__); \
if (str) { snprintf(str,size,__VA_ARGS__); str_seek_end(&str, &size); } \
gecko_printf(__VA_ARGS__); \
}while(0)
#define print_t3(S,X,Y) do{\
tm_sum += TIME_MS(X);\
printx("%s: %.3f%s", S, TIME_S(X),Y);\
}while(0)
#define print_t2(S,X) print_t3(S,X,"\n")
#define print_t_(X) print_t3(#X,X," ")
#define print_tn(X) print_t3(#X,X,"\n")
void time_statsf(FILE *f, char *str, int size)
{
long sum;
printx("times in seconds:\n");
tm_sum = 0;
print_t_(intro);
print_tn(wpad);
print_t_(ios1);
print_tn(ios2);
print_t_(sd_init);
print_tn(sd_mount);
print_t_(usb_init);
print_t3("mount", usb_mount, " ");
print_t3("retry", usb_retry, "\n");
printx("open: %.3f ini: %.3f cap: %.3f\n",
diff_fsec(TIME.usb_init1, TIME.usb_open),
diff_fsec(TIME.usb_open, TIME.usb_cap),
diff_fsec(TIME.usb_cap, TIME.usb_init2));
print_t3("cfg", cfg, " (config,settings,titles,theme)\n");
print_t3("misc", misc, " (lang,playstat,unifont)\n");
print_t_(wiitdb);
printx("load: %.3f parse: %.3f\n", TIME_S(db_load), TIME_S(wiitdb)-TIME_S(db_load));
print_t_(gamelist);
print_tn(mp3);
print_t_(conbg);
print_tn(guitheme);
sum = tm_sum;
printx("sum: %.3f ", (float)sum/1000.0);
printx("uncounted: %.3f\n", (float)((long)TIME_MS(boot)-sum)/1000.0);
print_t2("total startup", boot);
}
void time_stats()
{
time_statsf(stdout, NULL, 0);
}
void time_stats2()
{
FILE *f = stdout;
char *str = NULL;
int size = 0;
long sum;
if (!CFG.time_launch) {
if (CFG.debug) goto out;
return;
}
printx("times in seconds:\n");
tm_sum = 0;
print_tn(rios);
print_tn(gcard);
print_tn(playlog);
print_tn(playstat);
print_tn(load);
sum = tm_sum;
printx("sum: %.3f ", (float)sum/1000.0);
printx("uncounted: %.3f\n", (float)((long)TIME_MS(run)-sum)/1000.0);
print_t2("total launch", run);
printx("size: %.2f MB\n", (float)TIME.size / 1024.0 / 1024.0);
printx("speed: %.2f MB/s\n",
(float)TIME.size / (float)TIME_MS(load) * 1000.0 / 1024.0 / 1024.0);
out:;
extern void Menu_PrintWait();
Menu_PrintWait();
}
#if 0
// 7: text 11: data
typedef struct dolheader1
{
u32 pos[18];
u32 start[18];
u32 size[18];
u32 bss_start;
u32 bss_size;
u32 entry_point;
} dolheader1;
void compare_buf(int i, char *src, char *dest, int size)
{
if (!size) return;
int x;
int e = 0; // error counter
int esum = 0;
char *estart = NULL;
char *efirst = NULL;
char *elast = NULL;
int ecnt = 0;
dbg_printf("[%d] %p %p %d\n", i, src, dest, size);
for (x=0; x<size; x++) {
if (src[x] != dest[x]) {
if (!e) estart = dest + x;
if (!efirst) efirst = dest + x;
elast = dest + x;
esum++;
e++;
} else {
if (e && i < 7 && ecnt < 10) {
dbg_printf("E: %p %d\n", estart, e);
ecnt++;
}
e = 0;
}
}
if (e && i < 7) dbg_printf("E: %p %d\n", estart, e);
if (esum) dbg_printf("E tot: %d %p - %p\n", esum, efirst, elast);
}
void check_dol_buf(char *buf, int bufsize)
{
dolheader1 *hdr = (dolheader1*)buf;
int i;
char *src, *dest;
int size;
for (i=0; i<18; i++) {
size = hdr->size[i];
src = buf + hdr->pos[i];
dest = (char*)hdr->start[i];
compare_buf(i, src, dest, size);
}
}
void check_dol(char *name)
{
void *buf = NULL;
int size = -1;
if (name) {
dbg_printf("loading: %s\n", name);
size = Fat_ReadFile(name, &buf);
dbg_printf("size: %d\n", size);
}
if (size<0) {
name = "sd:/apps/USBLoader/boot.dol";
dbg_printf("loading: %s\n", name);
size = Fat_ReadFile(name, &buf);
dbg_printf("size: %d\n", size);
}
if (size < 0) return;
check_dol_buf(buf, size);
SAFE_FREE(buf);
}
#endif