diff --git a/source/ngc/gui/font.c b/source/ngc/gui/font.c index 32a2b2b..e8151a8 100644 --- a/source/ngc/gui/font.c +++ b/source/ngc/gui/font.c @@ -87,7 +87,7 @@ int FONT_Init(void) return 0; } -static void DrawChar(unsigned char c, int xpos, int ypos, int size) +static void DrawChar(unsigned char c, int xpos, int ypos, int size, GXColor color) { s32 width; @@ -108,12 +108,16 @@ static void DrawChar(unsigned char c, int xpos, int ypos, int size) /* GX rendering */ GX_Begin(GX_QUADS, GX_VTXFMT0, 4); GX_Position2s16(xpos, ypos - size); + GX_Color4u8(color.r, color.g, color.b, 0xff); GX_TexCoord2f32(0.0, 0.0); GX_Position2s16(xpos + width, ypos - size); + GX_Color4u8(color.r, color.g, color.b, 0xff); GX_TexCoord2f32(1.0, 0.0); GX_Position2s16(xpos + width, ypos); + GX_Color4u8(color.r, color.g, color.b, 0xff); GX_TexCoord2f32(1.0, 1.0); GX_Position2s16(xpos, ypos); + GX_Color4u8(color.r, color.g, color.b, 0xff); GX_TexCoord2f32(0.0, 1.0); GX_End (); GX_DrawDone(); @@ -125,7 +129,7 @@ void write_font(int x, int y, char *string) int ox = x; while (*string && (x < (ox + back_framewidth))) { - DrawChar(*string, x -(vmode->fbWidth/2), y-(vmode->efbHeight/2),fontHeader->cell_height); + DrawChar(*string, x -(vmode->fbWidth/2), y-(vmode->efbHeight/2),fontHeader->cell_height,(GXColor)WHITE); x += font_size[(u8)*string]; string++; } @@ -159,7 +163,7 @@ void FONT_alignLeft(char *string, int size, int x, int y) while (*string) { - DrawChar(*string, x, y, size); + DrawChar(*string, x, y, size,(GXColor)WHITE); x += (font_size[(u8)*string++] * size) / fheight; } } @@ -177,7 +181,7 @@ void FONT_alignRight(char *string, int size, int x, int y) while (*string) { - DrawChar(*string, x, y, size); + DrawChar(*string, x, y, size,(GXColor)WHITE); x += (font_size[(u8)*string++] * size) / fheight; } } @@ -195,7 +199,7 @@ void FONT_writeCenter(char *string, int size, int x1, int x2, int y) while (*string) { - DrawChar(*string, x1, y, size); + DrawChar(*string, x1, y, size,(GXColor)WHITE); x1 += (font_size[(u8)*string++] * size) / fheight; } } @@ -453,12 +457,16 @@ void DrawTexture(png_texture *texture, int x, int y, int w, int h) /* 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 (); GX_DrawDone(); diff --git a/source/ngc/gui/font.h b/source/ngc/gui/font.h index 4b7a930..3576f68 100644 --- a/source/ngc/gui/font.h +++ b/source/ngc/gui/font.h @@ -25,8 +25,8 @@ #ifndef _FONT_H #define _FONT_H -#define BLACK {0,0,0,255} -#define WHITE {255,255,255,255} +#define BLACK {0,0,0,0xff} +#define WHITE {0xff,0xff,0xff,0xff} typedef struct { diff --git a/source/ngc/gui/menu.c b/source/ngc/gui/menu.c index a865598..4326872 100644 --- a/source/ngc/gui/menu.c +++ b/source/ngc/gui/menu.c @@ -663,6 +663,11 @@ static void menu_draw(gui_menu *menu) /* clear EFB */ ClearScreen ((GXColor)BLACK); + if ((menu == &menu_main) && genromsize) + { + ogc_video_caption(128); + } + /* draw background image */ image = menu->background; if (image) DrawTexture(image->texture,image->x,image->y,image->w,image->h); @@ -742,6 +747,93 @@ static void menu_draw(gui_menu *menu) SetScreen (); } +static void menu_fade(gui_menu *menu, u8 speed, u8 out) +{ + int offset; + int yfinal[3]; + gui_image *image[3]; + + menu_initialize(menu); + + offset = 0; + yfinal[0] = 0; + yfinal[1] = 0; + yfinal[2] = 0; + + /* logo (top or bottom) */ + image[2] = menu->logo; + + /* Top banner */ + image[0] = menu->frames[0]; + if (image[0]) + { + /* intial offset */ + offset = image[0]->y + image[0]->h; + + /* final ypos */ + yfinal[0] = out ? (-image[0]->h) : (image[0]->y); + if (image[2] && !image[1]) yfinal[2] = out ? (image[2]->y - offset) : image[2]->y; + } + + /* Bottom banner */ + image[1] = menu->frames[1]; + if (image[1]) + { + if ((480 + image[1]->h - image[1]->y) > offset) + { + /* intial offset */ + offset = 480 - image[1]->y; + + /* final ypos */ + yfinal[1] = out ? 480 : (image[1]->y); + if (image[2] && !image[0]) yfinal[2] = out ? (image[2]->y + offset) : image[2]->y; + } + } + + /* alpha step */ + u16 alpha = out ? 128 : 255; + int alpha_step = out ? (128/offset) : -(128/offset); + + + /* loop until final position is reeached */ + while (offset > 0) + { + /* clear EFB */ + ClearScreen ((GXColor)BLACK); + + if ((menu == &menu_main) && genromsize) + { + ogc_video_caption(alpha); + } + + /* draw top banner + logo */ + if (image[out]) + { + DrawTexture(image[out]->texture,image[out]->x,yfinal[out]-offset,image[out]->w,image[out]->h); + if (image[2] && !image[out^1]) DrawTexture(image[2]->texture,image[2]->x,yfinal[2]-offset,image[2]->w,image[2]->h); + } + /* draw bottom banner + logo */ + if (image[out^1]) + { + DrawTexture(image[out^1]->texture,image[out^1]->x,yfinal[out^1]+offset,image[out^1]->w,image[out^1]->h); + if (image[2] && !image[out]) DrawTexture(image[2]->texture,image[2]->x,image[2]->y+offset,image[2]->w,image[2]->h); + } + + /* update offset */ + offset -= speed; + + /* update alpha */ + alpha += alpha_step; + if (alpha > 255) alpha = 255; + + /* copy EFB to XFB */ + SetScreen (); + } + + if (!out) menu_draw(menu); + menu_delete(menu); +} + static int menu_callback(gui_menu *menu) { u16 p; @@ -2030,6 +2122,9 @@ void MainMenu (u32 fps) VIDEO_SetPostRetraceCallback(menu_updateInputs); + /* basic fade-in effect */ + menu_fade(m,10,0); + while (quit == 0) { /* crccheck = crc32 (0, &sram.sram[0], 0x10000); @@ -2045,7 +2140,12 @@ void MainMenu (u32 fps) { case -1: /*** Button B ***/ case 0: /*** Play Game ***/ - if (genromsize) quit = 1; + if (genromsize) + { + /* basic fade-out effect */ + menu_fade(m,10,1); + quit = 1; + } break; case 1: /*** Load ROM Menu ***/ diff --git a/source/ngc/ogc_video.c b/source/ngc/ogc_video.c index 7806436..fe9b589 100644 --- a/source/ngc/ogc_video.c +++ b/source/ngc/ogc_video.c @@ -338,13 +338,8 @@ static void gxStart(void) GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); GX_SetCullMode(GX_CULL_NONE); GX_SetDispCopyGamma(GX_GM_1_0); - GX_SetBlendMode(GX_BM_BLEND,GX_BL_SRCALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR); GX_SetZMode(GX_FALSE, GX_ALWAYS, GX_TRUE); GX_SetColorUpdate(GX_TRUE); - GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); - GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLORNULL); - GX_SetNumTexGens(1); - GX_SetNumChans(0); /* Modelview */ Mtx view; @@ -358,31 +353,49 @@ static void gxStart(void) memset (texturemem, 0, TEX_SIZE); } -/* Reset GX vertex attributes */ -static void gxResetVtx(bool isMenu) +/* Reset GX rendering */ +static void gxResetRendering(bool isMenu) { GX_ClearVtxDesc(); - /* Set Position Params (quad aspect ratio) */ if (isMenu) { - /* menu uses direct position */ + /* GX menu (uses direct positionning, alpha blending & color channel) */ GX_SetBlendMode(GX_BM_BLEND,GX_BL_SRCALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR); GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); + GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GX_SetVtxDesc (GX_VA_CLR0, GX_DIRECT); + /* + Color.out = Color.rasterized*Color.texture + Alpha.out = Alpha.rasterized*Alpha.texture + */ + GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GX_SetNumTexGens(1); + GX_SetNumChans(1); } else { - /* emulation uses an indexed array for easy control on aspect ratio */ + /* video emulation (uses array positionning, no alpha blending, no color channel) */ GX_SetBlendMode(GX_BM_NONE,GX_BL_SRCALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR); GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GX_SetVtxDesc(GX_VA_POS, GX_INDEX8); + GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); GX_SetArray(GX_VA_POS, square, 3 * sizeof (s16)); + /* + Color.out = Color.texture + Alpha.out = Alpha.texture + */ + GX_SetTevOp (GX_TEVSTAGE0, GX_REPLACE); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLORNULL); + GX_SetNumTexGens(1); + GX_SetNumChans(0); } - /* Set Tex Coord Params */ - GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); - GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); GX_Flush(); } @@ -551,7 +564,7 @@ void ogc_video__stop(void) VIDEO_WaitVSync(); /* reset GX */ - gxResetVtx(GX_TRUE); + gxResetRendering(GX_TRUE); gxResetView(vmode); } @@ -609,21 +622,42 @@ void ogc_video__start(void) /* apply changes on next video update */ bitmap.viewport.changed = 1; - /* reset GX */ - gxResetVtx(GX_FALSE); + /* reset GX rendering */ + gxResetRendering(GX_FALSE); } -static GXTexObj texobj; +static u32 vwidth,vheight; -void ogc_video_caption(void) +void ogc_video_caption(u8 alpha) { - gxResetVtx(0); + GXTexObj texobj; + GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); GX_LoadTexObj(&texobj, GX_TEXMAP0); GX_InvalidateTexAll(); - draw_square(); + + /* reset Scaler (display screenshot in background) */ + s32 x = config.overscan ? -352 : -320; + s32 y = config.overscan ? -240 : -224; + s32 w = config.overscan ? 704 : 640; + s32 h = config.overscan ? 480 : 448; + + /* Draw textured quad */ + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + GX_Position2s16(x,y+h); + GX_Color4u8(0xff,0xff,0xff,alpha); + GX_TexCoord2f32(0.0, 1.0); + GX_Position2s16(x+w,y+h); + GX_Color4u8(0xff,0xff,0xff,alpha); + GX_TexCoord2f32(1.0, 1.0); + GX_Position2s16(x+w,y); + GX_Color4u8(0xff,0xff,0xff,alpha); + GX_TexCoord2f32(1.0, 0.0); + GX_Position2s16(x,y); + GX_Color4u8(0xff,0xff,0xff,alpha); + GX_TexCoord2f32(0.0, 0.0); + GX_End (); GX_DrawDone(); - gxResetVtx(1); } /* GX render update */ @@ -635,8 +669,8 @@ void ogc_video__update(void) bitmap.viewport.changed = 0; /* update texture size */ - u32 vwidth = bitmap.viewport.w + 2 * bitmap.viewport.x; - u32 vheight = bitmap.viewport.h + 2 * bitmap.viewport.y; + vwidth = bitmap.viewport.w + 2 * bitmap.viewport.x; + vheight = bitmap.viewport.h + 2 * bitmap.viewport.y; /* special cases */ if (config.render && interlaced) vheight = vheight << 1; @@ -647,6 +681,7 @@ void ogc_video__update(void) vheight = (vheight >> 2) << 2; /* initialize texture object */ + GXTexObj texobj; GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); /* configure texture filtering */ @@ -736,12 +771,8 @@ void ogc_video__init(void) TV60hz_480i.viTVMode = VI_TVMODE_EURGB60_INT; config.tv_mode = 1; - /* display should be centered vertically (borders) */ + /* use harwdare vertical scaling to fill screen */ vmode = &TVPal574IntDfScale; - vmode->xfbHeight = 480; - vmode->viYOrigin = (VI_MAX_HEIGHT_PAL - 480)/2; - vmode->viHeight = 480; - break; case VI_NTSC: /* 480 lines (NTSC 60hz) */ @@ -797,7 +828,7 @@ void ogc_video__init(void) /* Initialize GX */ gxStart(); - gxResetVtx(GX_TRUE); + gxResetRendering(GX_TRUE); gxResetView(vmode); /* Initialize Font */ diff --git a/source/ngc/ogc_video.h b/source/ngc/ogc_video.h index 4a8bc2b..d584cfe 100644 --- a/source/ngc/ogc_video.h +++ b/source/ngc/ogc_video.h @@ -34,7 +34,7 @@ extern void ogc_video__init(void); extern void ogc_video__start(void); extern void ogc_video__stop(void); extern void ogc_video__update(void); -extern void ogc_video_caption(void); +extern void ogc_video_caption(u8 alpha); extern void gxResetCamera(f32 angle);