- working on new gui

- video patch 1
This commit is contained in:
michniewski 2008-09-09 03:02:11 +00:00
parent 15d25fbe9d
commit 043e3ee61d
5 changed files with 1738 additions and 15 deletions

529
source/ngc/gui.cpp Normal file
View File

@ -0,0 +1,529 @@
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wiiuse/wpad.h>
#include <malloc.h>
#include <pngu/pngu.h>
#include <ft2build.h>
#include <zlib.h>
#include FT_FREETYPE_H
#include "video.h"
#include "snes9xGX.h"
#include "gui.h"
struct sGui Gui;
GXTexObj texobj_BG, texobj_MENU;
u8 texdata_bg[640 * 480 * 4] ATTRIBUTE_ALIGN (32); // stores the blended menu backdrop
u8 texdata_menu[640 * 480 * 4] ATTRIBUTE_ALIGN (32); // stores the menu overlay
extern GXTexObj texobj;
extern int vwidth, vheight;
extern s16 square[];
extern Mtx view;
extern int whichfb;
extern unsigned int copynow;
extern int screenheight;
extern unsigned int *xfb[2];
extern GXRModeObj *vmode;
extern FT_Library ftlibrary;
extern FT_Face face;
extern FT_GlyphSlot slot;
extern FT_UInt glyph_index;
extern int WaitButtonAB ();
// MAIN
static void
draw_vert (u8 pos, u8 c, f32 s, f32 t)
{
GX_Position1x8 (pos);
GX_Color1x8 (c);
GX_TexCoord2f32 (s, t);
}
static void
draw_square (Mtx v)
{
Mtx m; // model matrix.
Mtx mv; // modelview matrix.
guMtxIdentity (m);
guMtxTransApply (m, m, 0, 0, -100);
guMtxConcat (v, m, mv);
GX_LoadPosMtxImm (mv, GX_PNMTX0);
GX_Begin (GX_QUADS, GX_VTXFMT0, 4);
draw_vert (0, 0, 0.0, 0.0);
draw_vert (1, 0, 1.0, 0.0);
draw_vert (2, 0, 1.0, 1.0);
draw_vert (3, 0, 0.0, 1.0);
GX_End ();
}
void
gui_alphasetup ()
{
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
GX_SetAlphaUpdate(GX_ENABLE);
}
/****************************************************************************
* make BG
*
* Blend the last rendered emulator screen and the menu backdrop.
* Save this as a texture to be loaded later
****************************************************************************/
void
gui_makebg ()
{
IMGCTX ctx;
PNGUPROP imgProp;
/** Load menu backdrop (either from file or buffer) **/
ctx = PNGU_SelectImageFromDevice ("bg.png");
PNGU_GetImageProperties (ctx, &imgProp);
// can check image dimensions here
//texdata_bg = memalign (32, imgProp.imgWidth * imgProp.imgHeight * 4);
GX_InitTexObj (&texobj_BG, &texdata_bg, 640, 480, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
//PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, &texdata_bg, 255);
PNGU_DecodeToRGBA8 (ctx, 640, 480, Gui.texmem, 0, 7);
Make_Texture_RGBA8 (&texdata_bg, Gui.texmem, 640, 480);
PNGU_ReleaseImageContext (ctx);
DCFlushRange (&texdata_bg, imgProp.imgWidth * imgProp.imgHeight * 4);
/*
texdata_bg = memalign (32, 640 * 480 * 4);
#ifdef HW_RVL
// on wii copy from memory
memcpy (texdata_bg, (char *) backdrop, 640 * 480 * 2);
#else
// on gc copy from aram
ARAMFetch (texdata_bg, (char *) AR_BACKDROP, 640 * 480 * 2);
#endif
*/
/** blend last rendered snes frame and menu backdrop **/
// draw 640x480 quads
int xscale, yscale, xshift, yshift;
xshift = yshift = 0;
xscale = 320;
yscale = 240;
square[6] = square[3] = xscale + xshift;
square[0] = square[9] = -xscale + xshift;
square[4] = square[1] = yscale + yshift;
square[7] = square[10] = -yscale + yshift;
// draw 2 quads
GX_InvalidateTexAll ();
// behind (last snes frame)
square[2] = square[5] = square[8] = square[11] = 0; // z value
GX_InvVtxCache ();
GX_LoadTexObj (&texobj, GX_TEXMAP0); // load last rendered snes frame
draw_square (view);
// in front (menu backdrop)
square[2] = square[5] = square[8] = square[11] = 1; // z value
GX_InvVtxCache ();
GX_LoadTexObj (&texobj_BG, GX_TEXMAP0);
draw_square (view);
GX_DrawDone ();
/* DEBUG -----------
// show the output
VIDEO_SetNextFramebuffer (xfb[whichfb]);
VIDEO_Flush ();
copynow = GX_TRUE;
#ifdef VIDEO_THREADING
// Return to caller, don't waste time waiting for vb
LWP_ResumeThread (vbthread);
#endif
WaitButtonAB();
*/
// load blended image from efb to a texture
GX_InitTexObj (&texobj_BG, &texdata_bg, 640, 480, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_SetTexCopySrc ( 0,0,640,480 );
GX_SetTexCopyDst ( 640, 480, GX_TF_RGBA8, 0 );
GX_CopyTex (&texdata_bg, 0); // assuming that the efb is 640x480, which it should be
GX_PixModeSync (); // wait until copy has completed
DCFlushRange (&texdata_bg, 640 * 480 * 4);
square[2] = square[5] = square[8] = square[11] = 0; // reset z value
GX_InvVtxCache ();
}
void
gui_clearscreen ()
{
whichfb ^= 1;
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK);
memset ( Gui.texmem, 0, sizeof(Gui.texmem) );
Gui.fontcolour = 0;
}
void
gui_draw ()
{
gui_drawbox (0, 0, 640, 80, 255, 255, 255, 128); // topbar
gui_drawbox (0, 370, 640, 480, 255, 255, 255, 128); // bottombar
gui_setfontcolour (0,255,0,255);
// top bar text
setfontsize (32); // 32/24 depending on whether selected or not
gui_DrawText (-1, 113, (char *)"Hello World");
// main text
setfontsize (24);
gui_DrawText (-1, 113, (char *)"Hello World");
}
void
gui_savescreen ()
{
FILE* handle;
handle = fopen ("out.txt", "wb");
fwrite (Gui.texmem, 1, sizeof(Gui.texmem), handle);
fclose (handle);
printf("\nsaved screen.");
}
void
gui_showscreen ()
{
/** Screen to Texture **/
GX_InitTexObj (&texobj_MENU, texdata_menu, 640, 480, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
Make_Texture_RGBA8 (texdata_menu, Gui.texmem, 640, 480);
DCFlushRange (&texdata_menu, 640 * 480 * 4);
GX_InvalidateTexAll ();
/** thats nice, but will it blend? **/
// draw 640x480 quads
int xscale, yscale, xshift, yshift;
xshift = yshift = 0;
xscale = 320;
yscale = 240;
square[6] = square[3] = xscale + xshift;
square[0] = square[9] = -xscale + xshift;
square[4] = square[1] = yscale + yshift;
square[7] = square[10] = -yscale + yshift;
// draw 2 quads
// backdrop
square[2] = square[5] = square[8] = square[11] = 0; // z value
GX_InvVtxCache ();
GX_LoadTexObj (&texobj_BG, GX_TEXMAP0);
draw_square (view);
// menu overlay
square[2] = square[5] = square[8] = square[11] = 1; // z value
GX_InvVtxCache ();
GX_LoadTexObj (&texobj_MENU, GX_TEXMAP0);
draw_square (view);
GX_DrawDone ();
/** Display **/
// show the output
VIDEO_SetNextFramebuffer (xfb[whichfb]);
VIDEO_Flush ();
copynow = GX_TRUE;
#ifdef VIDEO_THREADING
/* Return to caller, don't waste time waiting for vb */
LWP_ResumeThread (vbthread);
#endif
WaitButtonAB();
square[2] = square[5] = square[8] = square[11] = 0; // z value
GX_InvVtxCache ();
}
/****************************************************************************
* Make Texture RGBA8
*
* input: pointer to RGBA data
* output: formatted texture data (GX_TF_RGBA8)
* code modified from quake wii (thanks :)
* todo: fix last few lines (?)
****************************************************************************/
void
Make_Texture_RGBA8 (void * dst_tex, void * src_data, int width, int height)
{
if ( (width % 4) || (height % 4) ) {
printf ("Error: make_texture_rgba8 width/height not multiple of 4");
return;
}
int i, x, y;
u8 *pos;
pos = (u8 *)dst_tex;
for (y = 0; y < height; y += 4) // process 4 lines at a time to make rows of tiles
{
u8* row1 = (u8 *) src_data;
u8* row2 = (u8 *) src_data;
u8* row3 = (u8 *) src_data;
u8* row4 = (u8 *) src_data;
row1 += width * 4 * (y + 0); // move 640 pixels x 4 bytes * line #
row2 += width * 4 * (y + 1);
row3 += width * 4 * (y + 2);
row4 += width * 4 * (y + 3);
for (x = 0; x < width; x += 4) // move across 4 pixels per tile
{
u8 AR[32];
u8 GB[32];
for (i = 0; i < 4; i++) // save those 4 pixels of data in texture format
{
u8* ptr1 = &(row1[(x + i) * 4]); // start at beginning of a row
u8* ptr2 = &(row2[(x + i) * 4]); // move across (4 pixels per tile + pixel offset within tile) * 4 bytes per pixel
u8* ptr3 = &(row3[(x + i) * 4]);
u8* ptr4 = &(row4[(x + i) * 4]);
AR[(i * 2) + 0] = ptr1[3]; // fill columns of tile with rgba data
AR[(i * 2) + 1] = ptr1[0];
AR[(i * 2) + 8] = ptr2[3];
AR[(i * 2) + 9] = ptr2[0];
AR[(i * 2) + 16] = ptr3[3];
AR[(i * 2) + 17] = ptr3[0];
AR[(i * 2) + 24] = ptr4[3];
AR[(i * 2) + 25] = ptr4[0];
GB[(i * 2) + 0] = ptr1[1];
GB[(i * 2) + 1] = ptr1[2];
GB[(i * 2) + 8] = ptr2[1];
GB[(i * 2) + 9] = ptr2[2];
GB[(i * 2) + 16] = ptr3[1];
GB[(i * 2) + 17] = ptr3[2];
GB[(i * 2) + 24] = ptr4[1];
GB[(i * 2) + 25] = ptr4[2];
}
memcpy(pos, AR, sizeof(AR)); // copy over to resulting texture
pos += sizeof(AR);
memcpy(pos, GB, sizeof(GB));
pos += sizeof(GB);
}
}
}
void
gui_drawbox (int x1, int y1, int width, int height, int r, int g, int b, int a)
{
u32 colour = ((u8)r << 24) | ((u8)g << 16) | ((u8)b << 8) | (u8)a;
int i, j;
u32* memory = (u32*) Gui.texmem;
for (j = y1; j<height; j++) {
for (i = x1; i<width; i++) {
memory[(j*640) + i] = colour;
}
}
}
/****************************************************************************
* DrawCharacter
* Draws a single character on the screen
****************************************************************************/
static void
gui_DrawCharacter (FT_Bitmap * bmp, FT_Int x, FT_Int y)
{
FT_Int i, j, p, q;
FT_Int x_max = x + bmp->width;
FT_Int y_max = y + bmp->rows;
int c;
u32* memory = (u32*)Gui.texmem;
for (i = x, p = 0; i < x_max; i++, p++)
{
for (j = y, q = 0; j < y_max; j++, q++)
{
if (i < 0 || j < 0 || i >= 640 || j >= 480)
continue;
c = bmp->buffer[q * bmp->width + p];
/*** Cool Anti-Aliasing doesn't work too well at hires on GC ***/
if (c > 128)
memory[(j * 640) + i] = Gui.fontcolour;
}
}
}
/****************************************************************************
* DrawText
*
* Place the font bitmap on the screen
****************************************************************************/
void
gui_DrawText (int x, int y, char *text)
{
int px, n;
int i;
int err;
int value, count;
n = strlen (text);
if (n == 0)
return;
/*** x == -1, auto centre ***/
if (x == -1)
{
value = 0;
px = 0;
}
else
{
value = 1;
px = x;
}
for (count = value; count < 2; count++)
{
/*** Draw the string ***/
for (i = 0; i < n; i++)
{
err = FT_Load_Char (face, text[i], FT_LOAD_RENDER);
if (err)
{
printf ("Error %c %d\n", text[i], err);
continue; /*** Skip unprintable characters ***/
}
if (count)
gui_DrawCharacter (&slot->bitmap, px + slot->bitmap_left, y - slot->bitmap_top);
px += slot->advance.x >> 6;
}
px = (640 - px) >> 1;
}
}
/****************************************************************************
* setfontcolour
*
* Uses RGB triple values.
****************************************************************************/
void
gui_setfontcolour (int r, int g, int b, int a)
{
Gui.fontcolour = ((u8)r << 24) | ((u8)g << 16) | ((u8)b << 8) | (u8)a;
}
/****************************************************************************
* DrawLine
*
* Quick'n'Dirty Bresenham line drawing routine.
****************************************************************************/
#define SIGN(x) ((x<0)?-1:((x>0)?1:0))
void
gui_DrawLine (int x1, int y1, int x2, int y2, int r, int g, int b, int a)
{
u32 colour;
int i, dx, dy, sdx, sdy, dxabs, dyabs, x, y, px, py;
int sp;
u32* memory = (u32*)Gui.texmem;
colour = ((u8)r << 24) | ((u8)g << 16) | ((u8)b << 8) | (u8)a;
dx = x2 - x1; /*** Horizontal distance ***/
dy = y2 - y1; /*** Vertical distance ***/
dxabs = abs (dx);
dyabs = abs (dy);
sdx = SIGN (dx);
sdy = SIGN (dy);
x = dyabs >> 1;
y = dxabs >> 1;
px = x1;
py = y1;
sp = (py * 640) + px;
/*** Plot this pixel ***/
memory[sp] = colour;
if (dxabs >= dyabs) /*** Mostly horizontal ***/
{
for (i = 0; i < dxabs; i++)
{
y += dyabs;
if (y >= dxabs)
{
y -= dxabs;
py += sdy;
}
px += sdx;
sp = (py * 640) + px;
memory[sp] = colour;
}
}
else
{
for (i = 0; i < dyabs; i++)
{
x += dxabs;
if (x >= dyabs)
{
x -= dyabs;
px += sdx;
}
py += sdy;
sp = (py * 640) + px;
memory[sp] = colour;
}
}
}
/* */
/** draw menu, etc **/
// - draw topbar, bottombar
// - draw icons
// - draw bar text
// draw main text
/** make textures **/
// - load background texture
// - draw onto quad
// - make foreground texture
// - draw onto quad
/** render image **/
/** update framebuffer **/
/* */
// EOF

36
source/ngc/gui.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef __GUI_H__
#define __GUI_H__
#include <gccore.h>
struct sGui {
u8 texmem[640 * 480 * 4] ATTRIBUTE_ALIGN (32); // rgba8 - working draw area
int currmenu;
int prevmenu;
u32 fontcolour;
int screenheight;
};
extern struct sGui Gui;
// Prototypes
void gui_alphasetup ();
void gui_makebg ();
void Make_Texture_RGBA8 (void * dst_tex, void * src_data, int width, int height);
void gui_drawbox (int x1, int y1, int width, int height, int r, int g, int b, int a);
void gui_DrawText (int x, int y, char *text);
void gui_setfontcolour (int r, int g, int b, int a);
void gui_DrawLine (int x1, int y1, int x2, int y2, int r, int g, int b, int a);
void gui_clearscreen ();
void gui_draw ();
void gui_showscreen ();
void gui_savescreen ();
// external functions
extern void setfontsize (int pixelsize);
#endif

1132
source/ngc/pngu.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -202,6 +202,8 @@ extern "C" {
#include "fileop.h"
#include "input.h"
#include "gui.h"
unsigned long ARAM_ROMSIZE = 0;
int ConfigRequested = 0;
extern int FrameTimer;
@ -288,6 +290,13 @@ emulate ()
NGCFreezeGame ( GCSettings.SaveMethod, SILENT );
}
}
// GUI Stuff
gui_makebg ();
gui_clearscreen();
gui_draw ();
gui_showscreen ();
//gui_savescreen ();
mainmenu (3); // go to game menu

View File

@ -21,6 +21,8 @@
#include "aram.h"
#include "snes9xGX.h"
#include "gui.h"
/*** Snes9x GFX Buffer ***/
static unsigned char snes9xgfx[1024 * 512 * 2];
@ -43,7 +45,7 @@ unsigned int copynow = GX_FALSE;
static unsigned char gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32);
static unsigned char texturemem[TEX_WIDTH * (TEX_HEIGHT + 8)] ATTRIBUTE_ALIGN (32);
GXTexObj texobj;
static Mtx view;
Mtx view;
int vwidth, vheight, oldvwidth, oldvheight;
u32 FrameTimer = 0;
@ -170,8 +172,8 @@ GXRModeObj TV_224p =
256, // fbWidth
224, // efbHeight
224, // xfbHeight
(VI_MAX_WIDTH_NTSC - 640)/2, // viXOrigin
(VI_MAX_HEIGHT_NTSC - 480)/2 + 8, // viYOrigin // +8 if we want to maintain rendered pixel aspect ratio (not 4:3)
(VI_MAX_WIDTH_NTSC - 640)/2, // viXOrigin
(VI_MAX_HEIGHT_NTSC - 480)/2, // viYOrigin
640, // viWidth
480, // viHeight
VI_XFBMODE_SF, // xFBmode
@ -301,8 +303,6 @@ copy_to_xfb (u32 arg)
if (copynow == GX_TRUE)
{
//GX_SetZMode (GX_TRUE, GX_LEQUAL, GX_TRUE);
//GX_SetColorUpdate (GX_TRUE);
GX_CopyDisp (xfb[whichfb], GX_TRUE);
GX_Flush ();
copynow = GX_FALSE;
@ -341,14 +341,6 @@ draw_init ()
memset (&view, 0, sizeof (Mtx));
guLookAt(view, &cam.pos, &cam.up, &cam.view);
GX_LoadPosMtxImm (view, GX_PNMTX0);
GX_InvalidateTexAll ();
GX_InitTexObj (&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
/* original video mode: force filtering OFF */
if (!GCSettings.render)
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1);
}
static void
@ -413,6 +405,8 @@ StartGX ()
GX_SetDispCopyGamma (GX_GM_1_0);
GX_SetZMode (GX_TRUE, GX_LEQUAL, GX_TRUE);
GX_SetColorUpdate (GX_TRUE);
gui_alphasetup ();
// guPerspective (p, 60, 1.33F, 10.0F, 1000.0F);
// GX_LoadProjectionMtx (p, GX_PERSPECTIVE);
@ -533,6 +527,12 @@ InitGCVideo ()
vmode_60hz = 1;
break;
}
// check for progressive scan
if (vmode->viTVMode == VI_TVMODE_NTSC_PROG) {
TV_239p.viTVMode = TV_478i.viTVMode = TV_224p.viTVMode = TV_448i.viTVMode = VI_TVMODE_NTSC_PROG;
TV_239p.xfbMode = TV_478i.xfbMode = TV_224p.xfbMode = TV_448i.xfbMode = VI_XFBMODE_SF;
}
VIDEO_Configure (vmode);
@ -588,7 +588,10 @@ ResetVideo_Emu ()
{
int i;
for (i=0; i<4; i++) {
if (tvmodes[i]->efbHeight == vheight) break;
if (tvmodes[i]->efbHeight == vheight) {
tvmodes[i]->fbWidth = vwidth; // update width - some games are 512x224 (super pang)
break;
}
}
rmode = tvmodes[i];
}
@ -620,11 +623,16 @@ ResetVideo_Emu ()
guOrtho(p, rmode->efbHeight/2, -(rmode->efbHeight/2), -(rmode->fbWidth/2), rmode->fbWidth/2, 10, 1000); // matrix, t, b, l, r, n, f
GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC);
// clear snes9x render screen
memset (snes9xgfx, 0, 1024 * 512 * 2);
// DEBUG
char* msg = (char*) malloc(256*sizeof(char));
sprintf (msg, (char*)"Interlaced: %i, vwidth: %d, vheight: %d, fb_W: %u, efb_H: %u", IPPU.Interlace, vwidth, vheight, rmode->fbWidth, rmode->efbHeight);
S9xMessage (0, 0, msg);
free(msg);
}
@ -732,7 +740,7 @@ update_video (int width, int height)
whichfb ^= 1;
if ((oldvheight != vheight) || (oldvwidth != vwidth) // if rendered width/height changes
if ((oldvheight != vheight) || (oldvwidth != vwidth) // if rendered width/height changes
|| (CheckVideo && (IPPU.RenderedFramesCount != prevRenderedFrameCount)) // or if we get back from the menu, and have rendered at least 1 frame
)
{
@ -765,12 +773,21 @@ update_video (int width, int height)
draw_init ();
GX_InvVtxCache ();
GX_InvalidateTexAll ();
GX_InitTexObj (&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
/* original video mode: force filtering OFF */
if (!GCSettings.render)
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1);
/*
// DEBUG
char* msg = (char*) malloc(256*sizeof(char));
sprintf (msg, (char*)"xscale: %d, yscale: %d", xscale, yscale);
S9xMessage (0, 0, msg);
free(msg);
*/
//GX_SetViewport (0, 0, rmode->fbWidth, rmode->efbHeight, 0, 1);