* added configurable on-screen CD leds [Gamecube/Wii]

* Wii DVD light is now used to indicate when virtual CD tray is open
* make sure Wiimote is connected before auto-detecting input settings
This commit is contained in:
EkeEke 2012-11-24 20:51:04 +01:00
parent 00be89a4a6
commit 68fd6e7e89
12 changed files with 208 additions and 81 deletions

View File

@ -1269,6 +1269,10 @@ void cdd_process(void)
scd.regs[0x3c>>1].w = 0x0000; scd.regs[0x3c>>1].w = 0x0000;
scd.regs[0x3e>>1].w = 0x0000; scd.regs[0x3e>>1].w = 0x0000;
scd.regs[0x40>>1].w = 0x000f; scd.regs[0x40>>1].w = 0x000f;
#ifdef CD_TRAY_CALLBACK
CD_TRAY_CALLBACK
#endif
return; return;
} }
@ -1283,6 +1287,10 @@ void cdd_process(void)
scd.regs[0x3c>>1].w = 0x0000; scd.regs[0x3c>>1].w = 0x0000;
scd.regs[0x3e>>1].w = 0x0000; scd.regs[0x3e>>1].w = 0x0000;
scd.regs[0x40>>1].w = 0x0001; scd.regs[0x40>>1].w = 0x0001;
#ifdef CD_TRAY_CALLBACK
CD_TRAY_CALLBACK
#endif
return; return;
} }

View File

@ -167,7 +167,9 @@ void config_default(void)
config.gun_cursor[0] = 1; config.gun_cursor[0] = 1;
config.gun_cursor[1] = 1; config.gun_cursor[1] = 1;
config.invert_mouse = 0; config.invert_mouse = 0;
gx_input_SetDefault();
/* on-screen options */
config.cd_leds = 0;
/* menu options */ /* menu options */
config.autoload = 0; config.autoload = 0;
@ -251,5 +253,6 @@ void config_default(void)
if (!loaded) if (!loaded)
{ {
GUI_WaitPrompt("Warning","Default Settings restored"); GUI_WaitPrompt("Warning","Default Settings restored");
gx_input_SetDefault();
} }
} }

View File

@ -40,7 +40,7 @@
#ifndef _CONFIG_H_ #ifndef _CONFIG_H_
#define _CONFIG_H_ #define _CONFIG_H_
#define CONFIG_VERSION "GENPLUS-GX 1.7.1" #define CONFIG_VERSION "GENPLUS-GX 1.7.2"
/**************************************************************************** /****************************************************************************
* Config Option * Config Option
@ -104,6 +104,7 @@ typedef struct
uint8 s_device; uint8 s_device;
uint8 l_device; uint8 l_device;
uint8 bg_overlay; uint8 bg_overlay;
uint8 cd_leds;
int16 screen_w; int16 screen_w;
float bgm_volume; float bgm_volume;
float sfx_volume; float sfx_volume;

View File

@ -387,7 +387,7 @@ static gui_item items_video[10] =
}; };
/* Menu options */ /* Menu options */
static gui_item items_prefs[9] = static gui_item items_prefs[10] =
{ {
{NULL,NULL,"Auto ROM Load: OFF", "Enable/Disable automatic ROM loading on startup", 56,132,276,48}, {NULL,NULL,"Auto ROM Load: OFF", "Enable/Disable automatic ROM loading on startup", 56,132,276,48},
{NULL,NULL,"Auto Cheats: OFF", "Enable/Disable automatic cheats activation", 56,132,276,48}, {NULL,NULL,"Auto Cheats: OFF", "Enable/Disable automatic cheats activation", 56,132,276,48},
@ -398,6 +398,7 @@ static gui_item items_prefs[9] =
{NULL,NULL,"BGM Volume: 100", "Adjust background music volume", 56,132,276,48}, {NULL,NULL,"BGM Volume: 100", "Adjust background music volume", 56,132,276,48},
{NULL,NULL,"BG Overlay: ON", "Enable/disable background overlay", 56,132,276,48}, {NULL,NULL,"BG Overlay: ON", "Enable/disable background overlay", 56,132,276,48},
{NULL,NULL,"Screen Width: 658", "Adjust menu screen width in pixels", 56,132,276,48}, {NULL,NULL,"Screen Width: 658", "Adjust menu screen width in pixels", 56,132,276,48},
{NULL,NULL,"Show CD Leds: OFF", "Enable/Disable CD leds display", 56,132,276,48},
}; };
/* Save Manager */ /* Save Manager */
@ -606,7 +607,7 @@ static gui_menu menu_prefs =
{ {
"Menu Settings", "Menu Settings",
0,0, 0,0,
9,4,6,0, 10,4,6,0,
items_prefs, items_prefs,
buttons_list, buttons_list,
bg_list, bg_list,
@ -673,6 +674,7 @@ static void prefmenu ()
sprintf (items[6].text, "BGM Volume: %1.1f", config.bgm_volume); sprintf (items[6].text, "BGM Volume: %1.1f", config.bgm_volume);
sprintf (items[7].text, "BG Overlay: %s", config.bg_overlay ? "ON":"OFF"); sprintf (items[7].text, "BG Overlay: %s", config.bg_overlay ? "ON":"OFF");
sprintf (items[8].text, "Screen Width: %d", config.screen_w); sprintf (items[8].text, "Screen Width: %d", config.screen_w);
sprintf (items[9].text, "Show CD Leds: %s", config.cd_leds ? "ON":"OFF");
GUI_InitMenu(m); GUI_InitMenu(m);
GUI_SlideMenuTitle(m,strlen("Menu ")); GUI_SlideMenuTitle(m,strlen("Menu "));
@ -757,6 +759,11 @@ static void prefmenu ()
sprintf (items[8].text, "Screen Width: %d", config.screen_w); sprintf (items[8].text, "Screen Width: %d", config.screen_w);
break; break;
case 9: /*** CD LEDS ***/
config.cd_leds ^= 1;
sprintf (items[9].text, "Show CD Leds: %s", config.cd_leds ? "ON":"OFF");
break;
case -1: case -1:
quit = 1; quit = 1;
break; break;
@ -3300,7 +3307,7 @@ static void exitmenu(void)
}; };
/* autodetect loader stub */ /* autodetect loader stub */
bool stub = FALSE; int maxitems = 2;
u32 *sig = (u32*)0x80001800; u32 *sig = (u32*)0x80001800;
void (*reload)() = (void(*)())0x80001800; void (*reload)() = (void(*)())0x80001800;
@ -3309,10 +3316,12 @@ static void exitmenu(void)
#else #else
if (sig[0] == 0x7c6000a6) // SDLOAD if (sig[0] == 0x7c6000a6) // SDLOAD
#endif #endif
stub = TRUE; {
maxitems = 3;
}
/* display option window */ /* display option window */
switch (GUI_OptionWindow(&menu_main, VERSION, items, stub ? 3:2)) switch (GUI_OptionWindow(&menu_main, osd_version, items, maxitems))
{ {
case 0: /* credits */ case 0: /* credits */
GUI_DeleteMenu(&menu_main); GUI_DeleteMenu(&menu_main);

View File

@ -1257,13 +1257,12 @@ void gx_input_SetDefault(void)
} }
#ifdef HW_RVL #ifdef HW_RVL
/* Autodetect Wii Controllers */ /* autodetect connected Wii Controllers */
WPAD_ScanPads();
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {
/* try to autodetect connected controller */
exp = 255; exp = 255;
WPAD_Probe(i, &exp); WPAD_Probe(i, &exp);
if (exp == WPAD_EXP_CLASSIC) if (exp == WPAD_EXP_CLASSIC)
{ {
/* use Classic Controller */ /* use Classic Controller */
@ -1276,7 +1275,7 @@ void gx_input_SetDefault(void)
config.input[i].device = 2; config.input[i].device = 2;
config.input[i].port = i; config.input[i].port = i;
} }
else if (exp <= EXP_MOTION_PLUS) else if (exp != 255)
{ {
/* use Wiimote by default */ /* use Wiimote by default */
config.input[i].device = 1; config.input[i].device = 1;

View File

@ -61,6 +61,10 @@ typedef struct
extern const u8 Crosshair_p1_png[]; extern const u8 Crosshair_p1_png[];
extern const u8 Crosshair_p2_png[]; extern const u8 Crosshair_p2_png[];
extern const u8 CD_access_off_png[];
extern const u8 CD_access_on_png[];
extern const u8 CD_ready_off_png[];
extern const u8 CD_ready_on_png[];
/*** VI ***/ /*** VI ***/
GXRModeObj *vmode; /* Default Video Mode */ GXRModeObj *vmode; /* Default Video Mode */
@ -80,6 +84,7 @@ static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32);
/*** GX Textures ***/ /*** GX Textures ***/
static u32 vwidth,vheight; static u32 vwidth,vheight;
static gx_texture *crosshair[2]; static gx_texture *crosshair[2];
static gx_texture *cd_leds[2][2];
/*** Framebuffers ***/ /*** Framebuffers ***/
static u32 *xfb[2]; static u32 *xfb[2];
@ -657,60 +662,134 @@ static void gxResetScaler(u32 width)
static void gxDrawCrosshair(gx_texture *texture, int x, int y) static void gxDrawCrosshair(gx_texture *texture, int x, int y)
{ {
if (texture->data) /* adjust texture dimensions to XFB->VI scaling */
int w = (texture->width * rmode->fbWidth) / (rmode->viWidth);
int h = (texture->height * rmode->efbHeight) / (rmode->viHeight);
/* EFB scale & shift */
int xwidth = square[3] - square[9];
int ywidth = square[4] - square[10];
/* adjust texture coordinates to EFB */
x = (((x + bitmap.viewport.x) * xwidth) / vwidth) + square[9] - w/2;
y = (((y + bitmap.viewport.y) * ywidth) / vheight) + square[10] - h/2;
/* reset GX rendering */
gxResetRendering(1);
/* load texture object */
GXTexObj texObj;
GX_InitTexObj(&texObj, texture->data, texture->width, texture->height, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_InitTexObjLOD(&texObj,GX_LINEAR,GX_LIN_MIP_LIN,0.0,10.0,0.0,GX_FALSE,GX_TRUE,GX_ANISO_4);
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* Draw textured quad */
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position2s16(x,y+h);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 1.0);
GX_Position2s16(x+w,y+h);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(1.0, 1.0);
GX_Position2s16(x+w,y);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(1.0, 0.0);
GX_Position2s16(x,y);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 0.0);
GX_End();
/* restore GX rendering */
gxResetRendering(0);
/* restore texture object */
GXTexObj texobj;
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
if (!config.bilinear)
{ {
/* EFB scale & shift */ GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,0.0,10.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1);
int xwidth = square[3] - square[9];
int ywidth = square[4] - square[10];
int xshift = (square[3] + square[9]) / 2;
int yshift = (square[4] + square[10]) / 2;
/* adjust texture dimensions to XFB->VI scaling */
int w = (texture->width * rmode->fbWidth) / (rmode->viWidth);
int h = (texture->height * rmode->efbHeight) / (rmode->viHeight);
/* adjust texture coordinates to EFB */
x = (((x + bitmap.viewport.x) * xwidth) / (bitmap.viewport.w + 2*bitmap.viewport.x)) - w/2 - (xwidth/2) + xshift;
y = (((y + bitmap.viewport.y) * ywidth) / (bitmap.viewport.h + 2*bitmap.viewport.y)) - h/2 - (ywidth/2) + yshift;
/* reset GX rendering */
gxResetRendering(1);
/* load texture object */
GXTexObj texObj;
GX_InitTexObj(&texObj, texture->data, texture->width, texture->height, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_InitTexObjLOD(&texObj,GX_LINEAR,GX_LIN_MIP_LIN,0.0,10.0,0.0,GX_FALSE,GX_TRUE,GX_ANISO_4);
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* Draw textured quad */
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position2s16(x,y+h);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 1.0);
GX_Position2s16(x+w,y+h);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(1.0, 1.0);
GX_Position2s16(x+w,y);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(1.0, 0.0);
GX_Position2s16(x,y);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 0.0);
GX_End();
/* restore GX rendering */
gxResetRendering(0);
/* restore texture object */
GXTexObj texobj;
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
if (!config.bilinear) GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,0.0,10.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1);
GX_LoadTexObj(&texobj, GX_TEXMAP0);
GX_InvalidateTexAll();
} }
GX_LoadTexObj(&texobj, GX_TEXMAP0);
GX_InvalidateTexAll();
} }
static void gxDrawCdLeds(gx_texture *texture_l, gx_texture *texture_r)
{
/* adjust texture dimensions to XFB->VI scaling */
int w = (texture_l->width * rmode->fbWidth) / (rmode->viWidth);
int h = (texture_r->height * rmode->efbHeight) / (rmode->viHeight);
/* EFB scale & shift */
int xwidth = square[3] - square[9];
int ywidth = square[4] - square[10];
/* adjust texture coordinates to EFB */
int xl = (((bitmap.viewport.x + 4) * xwidth) / vwidth) + square[9];
int xr = (((bitmap.viewport.x + bitmap.viewport.w - 4) * xwidth) / vwidth) + square[9] - w;
int y = (((bitmap.viewport.y + bitmap.viewport.h - 4) * ywidth) / vheight) + square[10] - h;
/* reset GX rendering */
gxResetRendering(1);
/* load left screen texture */
GXTexObj texObj;
GX_InitTexObj(&texObj, texture_l->data, texture_l->width, texture_l->height, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_InitTexObjLOD(&texObj,GX_LINEAR,GX_LIN_MIP_LIN,0.0,10.0,0.0,GX_FALSE,GX_TRUE,GX_ANISO_4);
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* Draw textured quad */
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position2s16(xl,y+h);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 1.0);
GX_Position2s16(xl+w,y+h);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(1.0, 1.0);
GX_Position2s16(xl+w,y);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(1.0, 0.0);
GX_Position2s16(xl,y);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 0.0);
GX_End();
/* load right screen texture */
GX_InitTexObj(&texObj, texture_r->data, texture_r->width, texture_r->height, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_InitTexObjLOD(&texObj,GX_LINEAR,GX_LIN_MIP_LIN,0.0,10.0,0.0,GX_FALSE,GX_TRUE,GX_ANISO_4);
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* Draw textured quad */
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position2s16(xr,y+h);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 1.0);
GX_Position2s16(xr+w,y+h);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(1.0, 1.0);
GX_Position2s16(xr+w,y);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(1.0, 0.0);
GX_Position2s16(xr,y);
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 0.0);
GX_End();
/* restore GX rendering */
gxResetRendering(0);
/* restore texture object */
GXTexObj texobj;
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
if (!config.bilinear)
{
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,0.0,10.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1);
}
GX_LoadTexObj(&texobj, GX_TEXMAP0);
GX_InvalidateTexAll();
}
void gxDrawRectangle(s32 x, s32 y, s32 w, s32 h, u8 alpha, GXColor color) void gxDrawRectangle(s32 x, s32 y, s32 w, s32 h, u8 alpha, GXColor color)
{ {
@ -1379,6 +1458,12 @@ void gx_video_Stop(void)
gxTextureClose(&crosshair[0]); gxTextureClose(&crosshair[0]);
gxTextureClose(&crosshair[1]); gxTextureClose(&crosshair[1]);
/* CD leds textures */
gxTextureClose(&cd_leds[0][0]);
gxTextureClose(&cd_leds[0][1]);
gxTextureClose(&cd_leds[1][0]);
gxTextureClose(&cd_leds[1][1]);
/* GX menu rendering */ /* GX menu rendering */
gxResetRendering(1); gxResetRendering(1);
gxResetMode(vmode); gxResetMode(vmode);
@ -1524,6 +1609,18 @@ void gx_video_Start(void)
} }
} }
/* CD leds textures */
if (system_hw == SYSTEM_MCD)
{
if (config.cd_leds)
{
cd_leds[0][0] = gxTextureOpenPNG(CD_access_off_png,0);
cd_leds[0][1] = gxTextureOpenPNG(CD_access_on_png,0);
cd_leds[1][0] = gxTextureOpenPNG(CD_ready_off_png,0);
cd_leds[1][1] = gxTextureOpenPNG(CD_ready_on_png,0);
}
}
/* GX emulation rendering */ /* GX emulation rendering */
gxResetRendering(0); gxResetRendering(0);
@ -1628,6 +1725,14 @@ int gx_video_Update(void)
} }
} }
/* CD LEDS */
if (cd_leds[1][1])
{
/* CD LEDS status */
u8 mode = scd.regs[0x06 >> 1].byte.h;
gxDrawCdLeds(cd_leds[1][(mode >> 1) & 1], cd_leds[0][mode & 1]);
}
/* swap XFB */ /* swap XFB */
whichfb ^= 1; whichfb ^= 1;

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -54,6 +54,7 @@
u32 Shutdown = 0; u32 Shutdown = 0;
u32 ConfigRequested = 1; u32 ConfigRequested = 1;
char osd_version[32];
#ifdef LOG_TIMING #ifdef LOG_TIMING
u64 prevtime; u64 prevtime;
@ -172,11 +173,6 @@ static void run_emulation(void)
/* clear flag */ /* clear flag */
bitmap.viewport.changed &= ~4; bitmap.viewport.changed &= ~4;
} }
#ifdef HW_RVL
/* use Wii DVD light to simulate CD Drive access led */
*(u32*)0xcd0000c0 = (*(u32*)0xcd0000c0 & ~0x20) | ((scd.regs[0x06>>1].byte.h & 0x01) << 5);
#endif
} }
} }
else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD) else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
@ -248,11 +244,6 @@ static void run_emulation(void)
} }
} }
#ifdef HW_RVL
/* reset Wii DVD light */
*(u32*)0xcd0000c0 = (*(u32*)0xcd0000c0 & ~0x20);
#endif
/* stop video & audio */ /* stop video & audio */
gx_audio_Stop(); gx_audio_Stop();
gx_video_Stop(); gx_video_Stop();
@ -456,6 +447,10 @@ int main (int argc, char *argv[])
/* initialize DI interface */ /* initialize DI interface */
DI_UseCache(0); DI_UseCache(0);
DI_Init(); DI_Init();
sprintf(osd_version, "%s (IOS %d)", VERSION, IOS_GetVersion());
#else
sprintf(osd_version, "%s (GCN)", VERSION);
#endif #endif
/* initialize video engine */ /* initialize video engine */

View File

@ -29,14 +29,14 @@
#include "file_load.h" #include "file_load.h"
#include "cheats.h" #include "cheats.h"
/*************************************************/
/* required by Genesis Plus GX core */
/*************************************************/
#include "config.h" #include "config.h"
#include "fileio.h" #include "fileio.h"
#define DEFAULT_PATH "/genplus" #define DEFAULT_PATH "/genplus"
/*************************************************/
/* required by Genesis Plus GX core */
/*************************************************/
#define GG_ROM "/genplus/lock-on/ggenie.bin" #define GG_ROM "/genplus/lock-on/ggenie.bin"
#define AR_ROM "/genplus/lock-on/areplay.bin" #define AR_ROM "/genplus/lock-on/areplay.bin"
#define SK_ROM "/genplus/lock-on/sk.bin" #define SK_ROM "/genplus/lock-on/sk.bin"
@ -54,15 +54,21 @@
#define CD_BRAM_JP "/genplus/saves/cd/scd_J.brm" #define CD_BRAM_JP "/genplus/saves/cd/scd_J.brm"
#define CART_BRAM "/genplus/saves/cd/cart.brm" #define CART_BRAM "/genplus/saves/cd/cart.brm"
#define ALIGN_SND 0xfffffff8 /* 32 bytes aligned sound buffers (8 samples alignment) */ /*********************************************************/
/* implemented by Genesis Plus GX core (GC/Wii specific) */
/*********************************************************/
/* 32 bytes aligned sound buffers (8 samples alignment) */
#define ALIGN_SND 0xfffffff8
/* use Wii DVD LED to indicate when virtual CD tray is open */
#ifdef HW_RVL
#define CD_TRAY_CALLBACK *(u32*)0xcd0000c0 = (*(u32*)0xcd0000c0 & ~0x20) | ((cdd.status == CD_OPEN) << 5);
#endif
/*************************************************/ /*************************************************/
#ifdef HW_RVL #define VERSION "Genesis Plus GX 1.7.2"
#define VERSION "Genesis Plus GX 1.7.1 (WII)"
#else
#define VERSION "Genesis Plus GX 1.7.1 (GCN)"
#endif
#define NO_SYNC 0 #define NO_SYNC 0
#define SYNC_VIDEO 1 #define SYNC_VIDEO 1
@ -75,6 +81,7 @@ extern void reloadrom(void);
extern void shutdown(void); extern void shutdown(void);
extern u32 Shutdown; extern u32 Shutdown;
extern u32 ConfigRequested; extern u32 ConfigRequested;
extern char osd_version[32];
#ifdef LOG_TIMING #ifdef LOG_TIMING
#include <ogc/lwp_watchdog.h> #include <ogc/lwp_watchdog.h>