~ fixed YM2612 channel connections when loading savestate

~ optimized VDP renderer buffers size
~ fixed directories automatic creation
+ added game screenshot feature
+ added game screenshot support in ROM File browser
+ improved Controller menu icons
+ added new images for the new Controller menu
- removed unused images
This commit is contained in:
ekeeke31 2009-05-01 12:56:48 +00:00
parent 3e82e4f058
commit b1f11ed311
63 changed files with 935 additions and 524 deletions

View File

@ -8,7 +8,7 @@ Genesis Plus GX 1.3.2 (??/??/????) (Eke-Eke)
* modified SN76489 cut-off frequency
* removed now outdated Gens YM2612 core
* improved MAME YM2612 emulation accuracy (SSG-EG, CSM mode and more), thanks to Nemesis for his tests on real hardware
* fixed FM context restore when loading savesates
* fixed FM context in savestates
* improved sprites masking emulation: fixes 3D level in Mickey Mania
* fixed lightgun games detection: fixes cursor position in Lethal Enforcers II
* various code cleanup & optimization
@ -16,9 +16,10 @@ Genesis Plus GX 1.3.2 (??/??/????) (Eke-Eke)
[Gamecube/Wii]
* improved audio/video synchronization: fixes video skipping issues with 60Hz modes
* fixed stability issues
* fixed stability issues and potential memory leaks
* added screenshot feature
* completely rewrote FONT & GUI engines (powered by GX hardware)
* new GUI design (incl. Wii Remote pointing, ROM snapshots & more)
* new GUI layout (incl. IR pointing, ROM snapshots, sound effects & more)

View File

@ -22,51 +22,45 @@
***************************************************************************/
#include "shared.h"
void config_save()
void config_save(void)
{
char pathname[MAXPATHLEN];
if (!fat_enabled) return;
/* first check if directory exist */
sprintf (pathname, DEFAULT_PATH);
DIR_ITER *dir = diropen(pathname);
if (dir == NULL) mkdir(pathname,S_IRWXU);
else dirclose(dir);
/* open configuration file */
sprintf (pathname, "%s/config.ini", pathname);
FILE *fp = fopen(pathname, "wb");
if (fp == NULL) return;
/* save options */
fwrite(&config, sizeof(config), 1, fp);
fclose(fp);
char fname[MAXPATHLEN];
sprintf (fname, "%s/config.ini", DEFAULT_PATH);
FILE *fp = fopen(fname, "wb");
if (fp)
{
/* write file */
fwrite(&config, sizeof(config), 1, fp);
fclose(fp);
}
}
void config_load()
void config_load(void)
{
char pathname[MAXPATHLEN];
/* open configuration file */
sprintf (pathname, "%s/config.ini", DEFAULT_PATH);
FILE *fp = fopen(pathname, "rb");
if (fp == NULL) return;
char fname[MAXPATHLEN];
sprintf (fname, "%s/config.ini", DEFAULT_PATH);
FILE *fp = fopen(fname, "rb");
if (fp)
{
/* read version */
char version[16];
fread(version, 16, 1, fp);
fclose(fp);
if (strcmp(version,VERSION)) return;
/* read version */
char version[16];
fread(version, 16, 1, fp);
fclose(fp);
if (strcmp(version,VERSION)) return;
/* read file */
fp = fopen(pathname, "rb");
fread(&config, sizeof(config), 1, fp);
fclose(fp);
/* read file */
fp = fopen(fname, "rb");
if (fp)
{
fread(&config, sizeof(config), 1, fp);
fclose(fp);
}
}
}
void config_setDefault(void)
void config_default(void)
{
/* version TAG */
strncpy(config.version,VERSION,16);
@ -109,5 +103,8 @@ void config_setDefault(void)
config.bg_color = 0;
config.bgm_volume = 100.0;
config.sfx_volume = 100.0;
/* restore saved configuration */
config_load();
}

View File

@ -65,9 +65,9 @@ typedef struct
t_config config;
extern void config_save();
extern void config_load();
extern void config_setDefault(void);
extern void config_save(void);
extern void config_load(void);
extern void config_default(void);
#endif /* _CONFIG_H_ */

View File

@ -96,28 +96,19 @@ void memfile_autosave(s8 autosram, s8 autostate)
*****************************************************************************/
static int FAT_ManageFile(char *filename, int direction, int filetype)
{
char pathname[MAXPATHLEN];
char fname[MAXPATHLEN];
int done = 0;
int filesize;
if (!fat_enabled) return 0;
/* first check if directory exist */
sprintf (pathname, "%s/saves", DEFAULT_PATH);
DIR_ITER *dir = diropen(pathname);
if (dir == NULL) mkdir(pathname,S_IRWXU);
else dirclose(dir);
/* build complete SDCARD filename */
sprintf (pathname, "%s/%s", pathname, filename);
sprintf (fname, "%s/saves/%s", DEFAULT_PATH, filename);
/* open file */
FILE *fp = fopen(pathname, direction ? "rb" : "wb");
FILE *fp = fopen(fname, direction ? "rb" : "wb");
if (fp == NULL)
{
sprintf (filename, "Error opening %s", pathname);
WaitPrompt(filename);
sprintf (fname, "Error opening %s", filename);
WaitPrompt(fname);
return 0;
}
@ -137,14 +128,14 @@ static int FAT_ManageFile(char *filename, int direction, int filetype)
done = fwrite(savebuffer, 1, filesize, fp);
if (done < filesize)
{
sprintf (filename, "Error writing %s", pathname);
WaitPrompt(filename);
sprintf (fname, "Error writing %s", filename);
WaitPrompt(fname);
return 0;
}
fclose(fp);
sprintf (filename, "Saved %d bytes successfully", done);
WaitPrompt (filename);
sprintf (fname, "Saved %d bytes successfully", done);
WaitPrompt (fname);
return 1;
case 1: /* LOADING */
@ -158,8 +149,8 @@ static int FAT_ManageFile(char *filename, int direction, int filetype)
done = fread(savebuffer, 1, filesize, fp);
if (done < filesize)
{
sprintf (filename, "Error reading %s", pathname);
WaitPrompt(filename);
sprintf (fname, "Error reading %s", filename);
WaitPrompt(fname);
return 0;
}
fclose(fp);
@ -172,8 +163,8 @@ static int FAT_ManageFile(char *filename, int direction, int filetype)
}
else state_load(savebuffer); /* STATE */
sprintf (filename, "Loaded %d bytes successfully", done);
WaitPrompt (filename);
sprintf (fname, "Loaded %d bytes successfully", done);
WaitPrompt (fname);
return 1;
}

View File

@ -26,28 +26,6 @@
t_history history;
void history_save()
{
char pathname[MAXPATHLEN];
if (!fat_enabled) return;
/* first check if directory exist */
sprintf (pathname, DEFAULT_PATH);
DIR_ITER *dir = diropen(pathname);
if (dir == NULL) mkdir(pathname,S_IRWXU);
else dirclose(dir);
/* open file for writing */
sprintf (pathname, "%s/history.ini", pathname);
FILE *fp = fopen(pathname, "wb");
if (fp == NULL) return;
/* save options */
fwrite(&history, sizeof(history), 1, fp);
fclose(fp);
}
/****************************************************************************
* history_add_file
@ -95,28 +73,44 @@ void history_add_file(char *filepath, char *filename)
history_save();
}
void history_load()
void history_save()
{
char pathname[MAXPATHLEN];
/* open file for reading */
sprintf (pathname, "%s/history.ini", DEFAULT_PATH);
FILE *fp = fopen(pathname, "rb");
if (fp == NULL) return;
/* read file */
fread(&history, sizeof(history), 1, fp);
fclose(fp);
/* open file */
char fname[MAXPATHLEN];
sprintf (fname, "%s/history.ini", DEFAULT_PATH);
FILE *fp = fopen(fname, "wb");
if (fp)
{
/* write file */
fwrite(&history, sizeof(history), 1, fp);
fclose(fp);
}
}
void history_setDefault(void)
void history_load(void)
{
/* open file */
char fname[MAXPATHLEN];
sprintf (fname, "%s/history.ini", DEFAULT_PATH);
FILE *fp = fopen(fname, "rb");
if (fp)
{
/* read file */
fread(&history, sizeof(history), 1, fp);
fclose(fp);
}
}
void history_default(void)
{
int i;
for(i=0; i < NUM_HISTORY_ENTRIES; i++)
{
memset(&history.entries[i], 0, sizeof(t_history_entry));
}
/* restore history */
history_load();
}

View File

@ -45,7 +45,8 @@ typedef struct
extern t_history history;
extern void history_add_file(char *filepath, char *filename);
extern void history_load();
extern void history_setDefault();
extern void history_save(void);
extern void history_load(void);
extern void history_default(void);
#endif

View File

@ -95,7 +95,7 @@ static gui_item action_select =
/*****************************************************************************/
/* GUI Background images */
/*****************************************************************************/
static gui_image bg_filesel[9] =
static gui_image bg_filesel[10] =
{
{NULL,Bg_main_png,IMAGE_VISIBLE,356,144,348,288,255,{0,0},{0,0}},
{NULL,Bg_overlay_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255,{0,0},{0,0}},
@ -105,6 +105,7 @@ static gui_image bg_filesel[9] =
{NULL,Frame_s1_png,IMAGE_VISIBLE,8,70,372,336,200,{0,0},{0,0}},
{NULL,Frame_s2_png,0,384,264,248,140,200,{0,0},{0,0}},
{NULL,Snap_empty_png,IMAGE_VISIBLE,422,114,164,116,255,{0,0},{0,0}},
{NULL,NULL,0,424,116,160,112,255,{0,0},{0,0}},
{NULL,Snap_frame_png,IMAGE_VISIBLE,388,112,236,148,255,{0,0},{0,0}}
};
@ -113,9 +114,9 @@ static gui_image bg_filesel[9] =
/*****************************************************************************/
static gui_menu menu_browser =
{
"ROM Selection",
"Game Selection",
-1,-1,
0,0,9,
0,0,10,
NULL,
NULL,
bg_filesel,
@ -165,6 +166,7 @@ int FileSelector(unsigned char *buffer)
int ret,i,yoffset,string_offset;
int go_up = 0;
int quit =0;
int old = -1;
char text[MAXJOLIET+2];
char fname[MAXPATHLEN];
FILE *xml,*snap;
@ -181,7 +183,7 @@ int FileSelector(unsigned char *buffer)
/* Initialize directory icon */
gui_image dir_icon;
dir_icon.texture = gxTextureOpenPNG(Browser_dir_png);
dir_icon.texture = gxTextureOpenPNG(Browser_dir_png,0);
dir_icon.w = dir_icon.texture->width;
dir_icon.h = dir_icon.texture->height;
dir_icon.x = 26;
@ -189,7 +191,7 @@ int FileSelector(unsigned char *buffer)
/* Initialize selection bar */
gui_image bar_over;
bar_over.texture = gxTextureOpenPNG(Overlay_bar_png);
bar_over.texture = gxTextureOpenPNG(Overlay_bar_png,0);
bar_over.w = bar_over.texture->width;
bar_over.h = bar_over.texture->height;
bar_over.x = 22;
@ -219,11 +221,23 @@ int FileSelector(unsigned char *buffer)
}
/* ROM snapshot */
sprintf (fname, "%s/snaps/%s.png", DEFAULT_PATH, text);
snap = fopen(fname, "rb");
if (snap)
if (old != selection)
{
fclose(snap); /* TODO */
old = selection;
/* delete previous texture if any */
gxTextureClose(&bg_filesel[8].texture);
bg_filesel[8].state &= ~IMAGE_VISIBLE;
/* open screenshot file */
sprintf (fname, "%s/snaps/%s.png", DEFAULT_PATH, text);
snap = fopen(fname, "rb");
if (snap)
{
bg_filesel[8].texture = gxTextureOpenPNG(0,snap);
fclose(snap);
if (bg_filesel[8].texture) bg_filesel[8].state |= IMAGE_VISIBLE;
}
}
/* Draw menu*/
@ -317,14 +331,14 @@ int FileSelector(unsigned char *buffer)
/* find selected button */
for (i=0; i<2; i++)
{
button = m->arrows[i];
if (button)
{
if (button->state & BUTTON_VISIBLE)
button = m->arrows[i];
if (button)
{
if ((x>=button->x)&&(x<=(button->x+button->w))&&(y>=button->y)&&(y<=(button->y+button->h)))
if (button->state & BUTTON_VISIBLE)
{
if ((x>=button->x)&&(x<=(button->x+button->w))&&(y>=button->y)&&(y<=(button->y+button->h)))
{
m->selected = m->max_buttons + i;
break;
}

View File

@ -154,7 +154,7 @@ void WriteCentre( int y, char *string)
void WriteCentre_HL( int y, char *string)
{
gx_texture *texture = gxTextureOpenPNG(Overlay_bar_png);
gx_texture *texture = gxTextureOpenPNG(Overlay_bar_png,0);
if (texture)
{
gxDrawTexture(texture, 0, y-fheight, 640, fheight,240);

View File

@ -61,7 +61,7 @@ void legal ()
WriteCentre (ypos, "You are free to use it as you wish.");
ypos += 2*fheight;
texture= gxTextureOpenPNG(Bg_intro_c4_png);
texture= gxTextureOpenPNG(Bg_intro_c4_png,0);
if (texture)
{
gxDrawTexture(texture, (640-texture->width)/2, ypos, texture->width, texture->height,255);
@ -84,7 +84,7 @@ void legal ()
}
gxClearScreen((GXColor)BLACK);
texture = gxTextureOpenPNG(Bg_intro_c1_png);
texture = gxTextureOpenPNG(Bg_intro_c1_png,0);
if (texture)
{
gxDrawTexture(texture, (640-texture->width)/2, (480-texture->height)/2, texture->width, texture->height,255);
@ -96,7 +96,7 @@ void legal ()
sleep (1);
gxClearScreen((GXColor)WHITE);
texture = gxTextureOpenPNG(Bg_intro_c2_png);
texture = gxTextureOpenPNG(Bg_intro_c2_png,0);
if (texture)
{
gxDrawTexture(texture, (640-texture->width)/2, (480-texture->height)/2, texture->width, texture->height,255);
@ -108,7 +108,7 @@ void legal ()
sleep (1);
gxClearScreen((GXColor)BLACK);
texture = gxTextureOpenPNG(Bg_intro_c3_png);
texture = gxTextureOpenPNG(Bg_intro_c3_png,0);
if (texture)
{
gxDrawTexture(texture, (640-texture->width)/2, (480-texture->height)/2, texture->width, texture->height,255);

View File

@ -39,16 +39,17 @@ t_input_menu m_input;
gx_texture *w_pointer;
#endif
#define BG_COLOR_MAX 14
#define BG_COLOR_MAX 15
/* various background colors */
static GXColor bg_colors[BG_COLOR_MAX]=
{
{0xd6,0xcb,0xba,0xff}, /* light gold */
{0xbb,0xb0,0x99,0xff}, /* gold */
{0xbb,0xb0,0x99,0xff}, /* gold */
{0x66,0x66,0x66,0xff}, /* faded grey */
{0xcc,0xcc,0xcc,0xff}, /* light grey */
{0xd4,0xd0,0xc8,0xff}, /* cream */
{0x50,0x51,0x5b,0xff}, /* grey blue */
{0xb8,0xc7,0xda,0xff}, /* light blue */
{0xc0,0xcf,0xe7,0xff}, /* sky blue */
{0x98,0xb1,0xd8,0xff}, /* sea blue */
@ -144,7 +145,7 @@ static gui_image bg_list[6] =
/*****************************************************************************/
/* Main menu */
static gui_item items_main[8] =
static gui_item items_main[9] =
{
{NULL,Main_quit_png ,"","",128, 84,52,80},
{NULL,Main_load_png ,"","",280, 72,80,92},
@ -153,11 +154,12 @@ static gui_item items_main[8] =
{NULL,Main_reset_png ,"","",282,224,76,84},
{NULL,Main_ggenie_png ,"","",450,224,72,84},
#ifdef HW_RVL
{NULL,Main_play_wii_png,"","", 10,368,84,32},
{NULL,Main_play_wii_png,"","", 10,372,84,32},
#else
{NULL,Main_play_gcn_png,"","", 10,368,84,32},
{NULL,Main_play_gcn_png,"","", 10,372,84,32},
#endif
{NULL,Main_showinfo_png,"","",546,368,84,32}
{NULL,Main_takeshot_png,"","",546,334,84,32},
{NULL,Main_showinfo_png,"","",546,372,84,32}
};
#ifdef HW_RVL
@ -246,7 +248,7 @@ static gui_butn buttons_list[4] =
};
/* Main menu */
static gui_butn buttons_main[8] =
static gui_butn buttons_main[9] =
{
{&button_icon_data,BUTTON_VISIBLE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,3}, 80, 50,148,132},
{&button_icon_data,BUTTON_VISIBLE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,3},246, 50,148,132},
@ -255,7 +257,8 @@ static gui_butn buttons_main[8] =
{&button_icon_data,BUTTON_VISIBLE|BUTTON_OVER_SFX ,{3,3},246,194,148,132},
{&button_icon_data,BUTTON_VISIBLE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{3,2},412,194,148,132},
{NULL ,BUTTON_VISIBLE|BUTTON_OVER_SFX ,{3,0}, 0,360, 88, 48},
{NULL ,BUTTON_VISIBLE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{3,0},552,360, 88, 48}
{NULL ,BUTTON_VISIBLE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{2,1},542,330, 88, 38},
{NULL ,BUTTON_VISIBLE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{1,0},542,370, 88, 48}
};
@ -296,7 +299,7 @@ static gui_menu menu_main =
{
"",
0,0,
8,8,4,
9,9,4,
items_main,
buttons_main,
bg_main,
@ -408,7 +411,7 @@ void GUI_InitMenu(gui_menu *menu)
for (i=0; i<menu->max_images; i++)
{
image = &menu->bg_images[i];
image->texture = gxTextureOpenPNG(image->data);
image->texture = gxTextureOpenPNG(image->data,0);
}
for (i=0; i<2; i++)
@ -417,15 +420,15 @@ void GUI_InitMenu(gui_menu *menu)
item = menu->helpers[i];
if (item)
{
item->texture = gxTextureOpenPNG(item->data);
item->texture = gxTextureOpenPNG(item->data,0);
}
/* arrows */
button = menu->arrows[i];
if (button)
{
if (!button->data->texture[0]) button->data->texture[0] = gxTextureOpenPNG(button->data->image[0]);
if (!button->data->texture[1]) button->data->texture[1] = gxTextureOpenPNG(button->data->image[1]);
if (!button->data->texture[0]) button->data->texture[0] = gxTextureOpenPNG(button->data->image[0],0);
if (!button->data->texture[1]) button->data->texture[1] = gxTextureOpenPNG(button->data->image[1],0);
/* initial state */
button->state &= ~BUTTON_VISIBLE;
@ -443,8 +446,8 @@ void GUI_InitMenu(gui_menu *menu)
button = &menu->buttons[i];
if (button->data)
{
if (!button->data->texture[0]) button->data->texture[0] = gxTextureOpenPNG(button->data->image[0]);
if (!button->data->texture[1]) button->data->texture[1] = gxTextureOpenPNG(button->data->image[1]);
if (!button->data->texture[0]) button->data->texture[0] = gxTextureOpenPNG(button->data->image[0],0);
if (!button->data->texture[1]) button->data->texture[1] = gxTextureOpenPNG(button->data->image[1],0);
}
}
@ -452,7 +455,7 @@ void GUI_InitMenu(gui_menu *menu)
for (i=0; i<menu->max_items; i++)
{
item = &menu->items[i];
if (item->data) item->texture = gxTextureOpenPNG(item->data);
if (item->data) item->texture = gxTextureOpenPNG(item->data,0);
}
}
@ -604,6 +607,21 @@ void GUI_DrawMenu(gui_menu *menu)
}
}
/* Menu fading */
void GUI_FadeMenu(gui_menu *menu, u8 speed, u8 out)
{
int alpha = 255;
while (alpha > 0)
{
GUI_DrawMenu(menu);
gxDrawRectangle(0, 0, 640, 480, out ? (255-alpha) : alpha, (GXColor)BLACK);
alpha -= speed;
}
if (out) gxDrawRectangle(0, 0, 640, 480, 255, (GXColor)BLACK);
}
/* Menu transitions effect */
void GUI_DrawMenuFX(gui_menu *menu, u8 speed, u8 out)
{
@ -768,14 +786,14 @@ int GUI_WindowPrompt(gui_menu *parent, char *title, char *items[], u8 nb_items)
delete_me[i] = 0;
if (!data->texture[i])
{
data->texture[i] = gxTextureOpenPNG(data->image[i]);
data->texture[i] = gxTextureOpenPNG(data->image[i],0);
delete_me[i] = 1;
}
}
/* initialize texture window */
gx_texture *window = gxTextureOpenPNG(Frame_s1_png);
gx_texture *top = gxTextureOpenPNG(Frame_title_png);
gx_texture *window = gxTextureOpenPNG(Frame_s1_png,0);
gx_texture *top = gxTextureOpenPNG(Frame_s1_title_png,0);
/* get initial positions */
int w = data->texture[0]->width;
@ -1191,6 +1209,12 @@ int GUI_RunMenu(gui_menu *menu)
/* basic slide effect for option menus */
static void GUI_SlideMenuTitle(gui_menu *m, int title_offset)
{
#ifdef HW_RVL
gui_butn *button;
int i,x,y;
struct orient_t orient;
#endif
char title[64];
strcpy(title,m->title);
@ -1199,6 +1223,53 @@ static void GUI_SlideMenuTitle(gui_menu *m, int title_offset)
strcpy(m->title,title+title_offset);
m->title[strlen(title)-title_offset-1] = 0;
GUI_DrawMenu(m);
#ifdef HW_RVL
if (m_input.ir.valid)
{
/* get cursor position */
x = m_input.ir.x;
y = m_input.ir.y;
/* draw wiimote pointer */
WPAD_Orientation(0,&orient);
gxResetAngle(orient.roll);
gxDrawTexture(w_pointer, x-w_pointer->width/2, y-w_pointer->height/2, w_pointer->width, w_pointer->height,255);
gxResetAngle(0.0);
/* check for valid buttons */
m->selected = m->max_buttons + 2;
for (i=0; i<m->max_buttons; i++)
{
button = &m->buttons[i];
if ((button->state & BUTTON_VISIBLE)&&(x>=button->x)&&(x<=(button->x+button->w))&&(y>=button->y)&&(y<=(button->y+button->h)))
{
m->selected = i;
break;
}
}
for (i=0; i<2; i++)
{
button = m->arrows[i];
if (button)
{
if (button->state & BUTTON_VISIBLE)
{
if ((x<=(button->x+button->w))&&(y>=button->y)&&(y<=(button->y+button->h)))
{
m->selected = m->max_buttons + i;
break;
}
}
}
}
}
else
{
/* reinitialize selection */
if (m->selected >= m->max_buttons) m->selected = 0;
}
#endif
gxSetScreen ();
usleep(6000);
title_offset--;
@ -1230,28 +1301,28 @@ static void drawmenu (char items[][25], int maxitems, int selected)
/* draw background items */
gxClearScreen (bg_colors[config.bg_color]);
texture= gxTextureOpenPNG(Bg_main_png);
texture= gxTextureOpenPNG(Bg_main_png,0);
if (texture)
{
gxDrawTexture(texture, (640-texture->width)/2, (480-texture->height)/2, texture->width, texture->height,255);
if (texture->data) free(texture->data);
free(texture);
}
texture= gxTextureOpenPNG(Banner_bottom_png);
texture= gxTextureOpenPNG(Banner_bottom_png,0);
if (texture)
{
gxDrawTexture(texture, 0, 480-texture->height, texture->width, texture->height, 255);
if (texture->data) free(texture->data);
free(texture);
}
texture= gxTextureOpenPNG(Banner_top_png);
texture= gxTextureOpenPNG(Banner_top_png,0);
if (texture)
{
gxDrawTexture(texture, 0, 0, texture->width, texture->height, 255);
if (texture->data) free(texture->data);
free(texture);
}
texture= gxTextureOpenPNG(Main_logo_png);
texture= gxTextureOpenPNG(Main_logo_png,0);
if (texture)
{
gxDrawTexture(texture, 444, 28, 176, 48, 255);
@ -1338,24 +1409,24 @@ static void prefmenu ()
gui_menu *m = &menu_prefs;
gui_item *items = m->items;
if (config.sram_auto == 0) sprintf (items[0].text, "SRAM Auto: FAT");
else if (config.sram_auto == 1) sprintf (items[0].text, "SRAM Auto: MCARD A");
else if (config.sram_auto == 2) sprintf (items[0].text, "SRAM Auto: MCARD B");
else sprintf (items[0].text, "SRAM Auto: OFF");
if (config.state_auto == 0) sprintf (items[1].text, "Savestate Auto: FAT");
else if (config.state_auto == 1) sprintf (items[1].text, "Savestate Auto: MCARD A");
else if (config.state_auto == 2) sprintf (items[1].text, "Savestate Auto: MCARD B");
else sprintf (items[1].text, "Savestate Auto: OFF");
sprintf (items[2].text, "SFX Volume: %1.1f", config.sfx_volume);
sprintf (items[3].text, "BGM Volume: %1.1f", config.bgm_volume);
if (config.bg_color) sprintf (items[4].text, "BG Color: Type %d", config.bg_color);
else sprintf (items[4].text, "BG Color: DEFAULT");
GUI_InitMenu(m);
GUI_SlideMenuTitle(m,strlen("Menu "));
while (quit == 0)
{
if (config.sram_auto == 0) sprintf (items[0].text, "SRAM Auto: FAT");
else if (config.sram_auto == 1) sprintf (items[0].text, "SRAM Auto: MCARD A");
else if (config.sram_auto == 2) sprintf (items[0].text, "SRAM Auto: MCARD B");
else sprintf (items[0].text, "SRAM Auto: OFF");
if (config.state_auto == 0) sprintf (items[1].text, "Savestate Auto: FAT");
else if (config.state_auto == 1) sprintf (items[1].text, "Savestate Auto: MCARD A");
else if (config.state_auto == 2) sprintf (items[1].text, "Savestate Auto: MCARD B");
else sprintf (items[1].text, "Savestate Auto: OFF");
sprintf (items[2].text, "SFX Volume: %1.1f", config.sfx_volume);
sprintf (items[3].text, "BGM Volume: %1.1f", config.bgm_volume);
if (config.bg_color) sprintf (items[4].text, "BG Color: Type %d", config.bg_color);
else sprintf (items[4].text, "BG Color: DEFAULT");
ret = GUI_RunMenu(m);
switch (ret)
@ -1363,11 +1434,19 @@ static void prefmenu ()
case 0: /*** SRAM auto load/save ***/
config.sram_auto ++;
if (config.sram_auto > 2) config.sram_auto = -1;
if (config.sram_auto == 0) sprintf (items[0].text, "SRAM Auto: FAT");
else if (config.sram_auto == 1) sprintf (items[0].text, "SRAM Auto: MCARD A");
else if (config.sram_auto == 2) sprintf (items[0].text, "SRAM Auto: MCARD B");
else sprintf (items[0].text, "SRAM Auto: OFF");
break;
case 1: /*** Savestate auto load/save ***/
config.state_auto ++;
if (config.state_auto > 2) config.state_auto = -1;
if (config.state_auto == 0) sprintf (items[1].text, "Savestate Auto: FAT");
else if (config.state_auto == 1) sprintf (items[1].text, "Savestate Auto: MCARD A");
else if (config.state_auto == 2) sprintf (items[1].text, "Savestate Auto: MCARD B");
else sprintf (items[1].text, "Savestate Auto: OFF");
break;
case 2: /*** Sound effects volume ***/
@ -1376,6 +1455,7 @@ static void prefmenu ()
else config.sfx_volume +=10;
if (config.sfx_volume < 0) config.sfx_volume = 100.0;
else if (config.sfx_volume > 100) config.sfx_volume = 0.0;
sprintf (items[2].text, "SFX Volume: %1.1f", config.sfx_volume);
break;
case 3: /*** Background music volume ***/
@ -1385,6 +1465,7 @@ static void prefmenu ()
if (config.bgm_volume < 0) config.bgm_volume = 100.0;
else if (config.bgm_volume > 100) config.bgm_volume = 0.0;
SetVolumeOgg(((int)config.bgm_volume * 255) / 100);
sprintf (items[3].text, "BGM Volume: %1.1f", config.bgm_volume);
break;
case 4: /*** Background color ***/
@ -1393,6 +1474,8 @@ static void prefmenu ()
else config.bg_color ++;
if (config.bg_color < 0) config.bg_color = BG_COLOR_MAX - 1;
if (config.bg_color >= BG_COLOR_MAX) config.bg_color = 0;
if (config.bg_color) sprintf (items[4].text, "BG Color: Type %d", config.bg_color);
else sprintf (items[4].text, "BG Color: DEFAULT");
break;
case -1:
@ -1414,18 +1497,19 @@ static void soundmenu ()
gui_menu *m = &menu_audio;
gui_item *items = m->items;
sprintf (items[0].text, "PSG Volume: %1.2f", (double)config.psg_preamp/100.0);
sprintf (items[1].text, "FM Volume: %1.2f", (double)config.fm_preamp/100.0);
sprintf (items[2].text, "Volume Boost: %dX", config.boost);
sprintf (items[3].text, "LowPass Filter: %s", config.filter ? " ON":"OFF");
if (config.hq_fm == 0) sprintf (items[4].text, "HQ YM2612: OFF");
else if (config.hq_fm == 1) sprintf (items[4].text, "HQ YM2612: LINEAR");
else sprintf (items[4].text, "HQ YM2612: SINC");
GUI_InitMenu(m);
GUI_SlideMenuTitle(m,strlen("Sound "));
while (quit == 0)
{
sprintf (items[0].text, "PSG Volume: %1.2f", (double)config.psg_preamp/100.0);
sprintf (items[1].text, "FM Volume: %1.2f", (double)config.fm_preamp/100.0);
sprintf (items[2].text, "Volume Boost: %dX", config.boost);
sprintf (items[3].text, "LowPass Filter: %s", config.filter ? " ON":"OFF");
if (config.hq_fm == 0) sprintf (items[4].text, "HQ YM2612: OFF");
else if (config.hq_fm == 1) sprintf (items[4].text, "HQ YM2612: LINEAR");
else sprintf (items[4].text, "HQ YM2612: SINC");
ret = GUI_RunMenu(m);
@ -1437,6 +1521,7 @@ static void soundmenu ()
else config.psg_preamp ++;
if (config.psg_preamp < 0) config.psg_preamp = 500;
if (config.psg_preamp > 500) config.psg_preamp = 0;
sprintf (items[0].text, "PSG Volume: %1.2f", (double)config.psg_preamp/100.0);
break;
case 1:
@ -1445,23 +1530,29 @@ static void soundmenu ()
else config.fm_preamp ++;
if (config.fm_preamp < 0) config.fm_preamp = 500;
if (config.fm_preamp > 500) config.fm_preamp = 0;
sprintf (items[1].text, "FM Volume: %1.2f", (double)config.fm_preamp/100.0);
break;
case 2:
config.boost ++;
if (config.boost > 4) config.boost = 0;
sprintf (items[2].text, "Volume Boost: %dX", config.boost);
break;
case 3:
config.filter ^= 1;
sprintf (items[3].text, "LowPass Filter: %s", config.filter ? " ON":"OFF");
break;
case 4:
config.hq_fm ++;
if (config.hq_fm>2) config.hq_fm = 0;
if (config.hq_fm == 0) sprintf (items[4].text, "HQ YM2612: OFF");
else if (config.hq_fm == 1) sprintf (items[4].text, "HQ YM2612: LINEAR");
else sprintf (items[4].text, "HQ YM2612: SINC");
if (genromsize)
{
unsigned char *temp = malloc(YM2612GetContextSize());
unsigned char *temp = memalign(32,YM2612GetContextSize());
if (temp) memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
audio_init(48000);
if (temp)
@ -1492,25 +1583,29 @@ static void systemmenu ()
gui_menu *m = &menu_system;
gui_item *items = m->items;
if (config.region_detect == 0) sprintf (items[0].text, "Console Region: AUTO");
else if (config.region_detect == 1) sprintf (items[0].text, "Console Region: USA");
else if (config.region_detect == 2) sprintf (items[0].text, "Console Region: EUR");
else if (config.region_detect == 3) sprintf (items[0].text, "Console Region: JAP");
sprintf (items[1].text, "System Lockups: %s", config.force_dtack ? "OFF" : "ON");
sprintf (items[2].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF");
sprintf (items[3].text, "SVP Cycles: %d", SVP_cycles);
GUI_InitMenu(m);
GUI_SlideMenuTitle(m,strlen("System "));
while (quit == 0)
{
if (config.region_detect == 0) sprintf (items[0].text, "Console Region: AUTO");
else if (config.region_detect == 1) sprintf (items[0].text, "Console Region: USA");
else if (config.region_detect == 2) sprintf (items[0].text, "Console Region: EUR");
else if (config.region_detect == 3) sprintf (items[0].text, "Console Region: JAP");
sprintf (items[1].text, "System Lockups: %s", config.force_dtack ? "OFF" : "ON");
sprintf (items[2].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF");
sprintf (items[3].text, "SVP Cycles: %d", SVP_cycles);
ret = GUI_RunMenu(m);
switch (ret)
{
case 0: /*** Region Force ***/
config.region_detect = (config.region_detect + 1) % 4;
if (config.region_detect == 0) sprintf (items[0].text, "Console Region: AUTO");
else if (config.region_detect == 1) sprintf (items[0].text, "Console Region: USA");
else if (config.region_detect == 2) sprintf (items[0].text, "Console Region: EUR");
else if (config.region_detect == 3) sprintf (items[0].text, "Console Region: JAP");
if (genromsize)
{
/* force region & cpu mode */
@ -1518,11 +1613,14 @@ static void systemmenu ()
/* reinitialize timings */
system_init ();
unsigned char *temp = malloc(YM2612GetContextSize());
unsigned char *temp = memalign(32,YM2612GetContextSize());
if (temp) memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
audio_init(48000);
YM2612Restore(temp);
if (temp) free(temp);
if (temp)
{
YM2612Restore(temp);
free(temp);
}
/* reinitialize HVC tables */
vctab = (vdp_pal) ? ((reg[1] & 8) ? vc_pal_240 : vc_pal_224) : vc_ntsc_224;
@ -1536,10 +1634,12 @@ static void systemmenu ()
case 1: /*** force DTACK ***/
config.force_dtack ^= 1;
sprintf (items[1].text, "System Lockups: %s", config.force_dtack ? "OFF" : "ON");
break;
case 2: /*** BIOS support ***/
config.bios_enabled ^= 1;
sprintf (items[2].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF");
if (genromsize || (config.bios_enabled == 3))
{
system_init ();
@ -1553,6 +1653,7 @@ static void systemmenu ()
if (ret<0) SVP_cycles = SVP_cycles ? (SVP_cycles-1) : 1500;
else SVP_cycles++;
if (SVP_cycles > 1500) SVP_cycles = 0;
sprintf (items[3].text, "SVP Cycles: %d", SVP_cycles);
break;
case -1:
@ -1574,24 +1675,25 @@ static void videomenu ()
gui_menu *m = &menu_video;
gui_item *items = m->items;
sprintf (items[0].text, "Aspect: %s", config.aspect ? "ORIGINAL" : "STRETCHED");
if (config.render == 1) sprintf (items[1].text,"Display: INTERLACED");
else if (config.render == 2) sprintf (items[1].text, "Display: PROGRESSIVE");
else sprintf (items[1].text, "Display: ORIGINAL");
if (config.tv_mode == 0) sprintf (items[2].text, "TV Mode: 60HZ");
else if (config.tv_mode == 1) sprintf (items[2].text, "TV Mode: 50HZ");
else sprintf (items[2].text, "TV Mode: 50/60HZ");
sprintf (items[3].text, "Bilinear Filter: %s", config.bilinear ? " ON" : "OFF");
if (config.ntsc == 1) sprintf (items[4].text, "NTSC Filter: COMPOSITE");
else if (config.ntsc == 2) sprintf (items[4].text, "NTSC Filter: S-VIDEO");
else if (config.ntsc == 3) sprintf (items[4].text, "NTSC Filter: RGB");
else sprintf (items[4].text, "NTSC Filter: OFF");
sprintf (items[5].text, "Borders: %s", config.overscan ? " ON" : "OFF");
GUI_InitMenu(m);
GUI_SlideMenuTitle(m,strlen("Video "));
while (quit == 0)
{
sprintf (items[0].text, "Aspect: %s", config.aspect ? "ORIGINAL" : "STRETCHED");
if (config.render == 1) sprintf (items[1].text,"Display: INTERLACED");
else if (config.render == 2) sprintf (items[1].text, "Display: PROGRESSIVE");
else sprintf (items[1].text, "Display: ORIGINAL");
if (config.tv_mode == 0) sprintf (items[2].text, "TV Mode: 60HZ");
else if (config.tv_mode == 1) sprintf (items[2].text, "TV Mode: 50HZ");
else sprintf (items[2].text, "TV Mode: 50/60HZ");
sprintf (items[3].text, "Bilinear Filter: %s", config.bilinear ? " ON" : "OFF");
if (config.ntsc == 1) sprintf (items[4].text, "NTSC Filter: COMPOSITE");
else if (config.ntsc == 2) sprintf (items[4].text, "NTSC Filter: S-VIDEO");
else if (config.ntsc == 3) sprintf (items[4].text, "NTSC Filter: RGB");
else sprintf (items[4].text, "NTSC Filter: OFF");
sprintf (items[5].text, "Borders: %s", config.overscan ? " ON" : "OFF");
ret = GUI_RunMenu(m);
@ -1599,6 +1701,7 @@ static void videomenu ()
{
case 0: /*** config.aspect ratio ***/
config.aspect ^= 1;
sprintf (items[0].text, "Aspect: %s", config.aspect ? "ORIGINAL" : "STRETCHED");
break;
case 1: /*** rendering ***/
@ -1616,25 +1719,38 @@ static void videomenu ()
config.render = 0;
}
}
if (config.render == 1) sprintf (items[1].text,"Display: INTERLACED");
else if (config.render == 2) sprintf (items[1].text, "Display: PROGRESSIVE");
else sprintf (items[1].text, "Display: ORIGINAL");
if (config.tv_mode == 0) sprintf (items[2].text, "TV Mode: 60HZ");
else if (config.tv_mode == 1) sprintf (items[2].text, "TV Mode: 50HZ");
else sprintf (items[2].text, "TV Mode: 50/60HZ");
break;
case 2: /*** tv mode ***/
if (config.render != 2) config.tv_mode = (config.tv_mode + 1) % 3;
if (config.tv_mode == 0) sprintf (items[2].text, "TV Mode: 60HZ");
else if (config.tv_mode == 1) sprintf (items[2].text, "TV Mode: 50HZ");
else sprintf (items[2].text, "TV Mode: 50/60HZ");
break;
case 3: /*** bilinear filtering ***/
config.bilinear ^= 1;
sprintf (items[3].text, "Bilinear Filter: %s", config.bilinear ? " ON" : "OFF");
break;
case 4: /*** NTSC filter ***/
config.ntsc ++;
if (config.ntsc > 3) config.ntsc = 0;
if (config.ntsc == 1) sprintf (items[4].text, "NTSC Filter: COMPOSITE");
else if (config.ntsc == 2) sprintf (items[4].text, "NTSC Filter: S-VIDEO");
else if (config.ntsc == 3) sprintf (items[4].text, "NTSC Filter: RGB");
else sprintf (items[4].text, "NTSC Filter: OFF");
break;
case 5: /*** overscan emulation ***/
config.overscan ^= 1;
bitmap.viewport.x = config.overscan ? ((reg[12] & 1) ? 16 : 12) : 0;
bitmap.viewport.y = config.overscan ? (((reg[1] & 8) ? 0 : 8) + (vdp_pal ? 24 : 0)) : 0;
sprintf (items[5].text, "Borders: %s", config.overscan ? " ON" : "OFF");
break;
/* case 6:
@ -1689,6 +1805,28 @@ static void inputsmenu(void)
u32 exp;
#endif
/* gui_item items_sys[7][2] =
{
{
{NULL,Ctrl_none ,"","Port 1 - Unconnected",110,130,48,72},
{NULL,Ctrl_gamepad ,"","Port 1 - Gamepad" , 87,117,96,84},
{NULL,Ctrl_mouse ,"","Port 1 - Mouse" , 97,113,64,88},
{NULL,Ctrl_menacer ,"","Port 1 - Menacer" , 94,113,80,88},
{NULL,Ctrl_justifier ,"","Port 1 - Justifiers" , 88,117,80,84}
{NULL,Ctrl_teamplayer,"","Port 1 - Teamplayer" , 94,109,80,92},
{NULL,Ctrl_4wayplay ,"","Port 1 - 4 Way Play" , 98,110,72,92}
},
{
{NULL,Ctrl_none ,"","Port 2 - Unconnected",110,130,48,72},
{NULL,Ctrl_gamepad ,"","Port 2 - Gamepad" , 87,117,96,84},
{NULL,Ctrl_mouse ,"","Port 2 - Mouse" , 97,113,64,88},
{NULL,Ctrl_menacer ,"","Port 2 - Menacer" , 94,113,80,88},
{NULL,Ctrl_justifier ,"","Port 2 - Justifiers" , 88,117,80,84}
{NULL,Ctrl_teamplayer,"","Port 2 - Teamplayer" , 94,109,80,92},
{NULL,Ctrl_4wayplay ,"","Port 2 - 4 Way Play" , 98,110,72,92}
}
};
*/
strcpy (menutitle, "Press B to return");
menu = 0;
@ -2323,7 +2461,7 @@ void MainMenu (void)
}
/* wiimote pointer */
w_pointer = gxTextureOpenPNG(generic_point_png);
w_pointer = gxTextureOpenPNG(generic_point_png,0);
#endif
gui_menu *m = &menu_main;
@ -2332,8 +2470,8 @@ void MainMenu (void)
if (genromsize)
{
m->screenshot = 1;
m->max_items = 8;
m->max_buttons = 8;
m->max_items = 9;
m->max_buttons = 9;
m->buttons[3].state |= BUTTON_SELECT_SFX;
m->buttons[5].state |= BUTTON_SELECT_SFX;
m->buttons[3].shift[1] = 3;
@ -2378,6 +2516,7 @@ void MainMenu (void)
switch (GUI_WindowPrompt(m, VERSION, items,3))
{
case 1:
GUI_FadeMenu(m,1,1);
#ifdef HW_RVL
gxTextureClose(&w_pointer);
#endif
@ -2387,6 +2526,7 @@ void MainMenu (void)
break;
case 2:
GUI_FadeMenu(m,1,1);
#ifdef HW_RVL
gxTextureClose(&w_pointer);
#endif
@ -2400,9 +2540,9 @@ void MainMenu (void)
break;
default: /* TODO */
GUI_DeleteMenu(m);
break;
}
GUI_DeleteMenu(m);
break;
}
@ -2431,8 +2571,12 @@ void MainMenu (void)
GetGGEntries();
break;
case 7: /*** ROM Information ***/
showrominfo ();
case 7: /*** ROM Captrure ***/
if (genromsize) gx_video_Capture();
break;
case 8: /*** ROM Information ***/
if (genromsize) showrominfo ();
break;
}
}

View File

@ -64,7 +64,9 @@ extern const u8 Banner_top_png[];
extern const u8 Frame_s1_png[];
extern const u8 Frame_s2_png[];
extern const u8 Frame_title_png[];
extern const u8 Frame_s3_png[];
extern const u8 Frame_s1_title_png[];
extern const u8 Frame_s3_title_png[];
extern const u8 Overlay_bar_png[];
@ -83,6 +85,7 @@ extern const u8 Main_file_png[];
extern const u8 Main_reset_png[];
extern const u8 Main_ggenie_png[];
extern const u8 Main_showinfo_png[];
extern const u8 Main_takeshot_png[];
#ifdef HW_RVL
extern const u8 Main_play_wii_png[];
#else
@ -221,6 +224,7 @@ extern void GUI_InitMenu(gui_menu *menu);
extern void GUI_DeleteMenu(gui_menu *menu);
extern void GUI_DrawMenu(gui_menu *menu);
extern void GUI_DrawMenuFX(gui_menu *menu, u8 speed, u8 out);
extern void GUI_FadeMenu(gui_menu *menu, u8 speed, u8 out);
extern int GUI_RunMenu(gui_menu *menu);
extern int GUI_WindowPrompt(gui_menu *parent, char *title, char *items[], u8 nb_items);
#endif

View File

@ -3,7 +3,7 @@
*
* Genesis Plus GX audio support
*
* code by Eke-Eke (2007,2008)
* code by Eke-Eke (2007,2009)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -54,25 +54,16 @@ static u8 audioStarted = 0;
static u8 *Bg_music_ogg = NULL;
static u32 Bg_music_ogg_size = 0;
/***
AudioDmaCallback
/***************************************************************************************/
/* Audio engine */
/***************************************************************************************/
In 50Hz emulation mode, we synchronize frame emulation with audio DMA
50Hz VSYNC period is shorter than DMA period so there is no video frameskipping
In 60Hz modes, VSYNC period is longer than default DMA period so it requires different sync.
***/
static void AudioDmaCallback(void)
/* Audio DMA callback */
static void ai_callback(void)
{
frameticker++;
}
/***
gx_audio__init
This function initializes the Audio Interface
Default samplerate is set to 48khZ
***/
void gx_audio_Init(void)
{
AUDIO_Init (NULL);
@ -171,7 +162,7 @@ void gx_audio_Start(void)
AUDIO_RegisterDMACallback(NULL);
/* let's use audio DMA to synchronize frame emulation */
if (vdp_pal | gc_pal) AUDIO_RegisterDMACallback(AudioDmaCallback);
if (vdp_pal | gc_pal) AUDIO_RegisterDMACallback(ai_callback);
/* 60hz video mode requires synchronization with Video interrupt */
/* VSYNC period is 16715 us which is approx. 802.32 samples */

View File

@ -3,7 +3,7 @@
*
* Genesis Plus GX input support
*
* code by Eke-Eke (2008)
* code by Eke-Eke (2008-2009)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -42,7 +42,7 @@ typedef struct
{
u8 *buffer;
u32 offset;
} png_file;
} png_image;
extern const u8 Crosshair_p1_png[];
extern const u8 Crosshair_p2_png[];
@ -52,6 +52,7 @@ unsigned int *xfb[2]; /* External Framebuffers */
int whichfb = 0; /* Current Framebuffer */
GXRModeObj *vmode; /* Default Video Mode */
u8 *texturemem; /* Texture Data */
u8 *screenshot; /* Texture Data */
/* 50/60hz flag */
u8 gc_pal = 0;
@ -65,13 +66,15 @@ static md_ntsc_setup_t md_setup;
/*** GX FIFO ***/
static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32);
/*** custom Video modes ***/
static GXRModeObj *rmode;
/*** GX Textures ***/
static u32 vwidth,vheight;
static gx_texture *crosshair[2];
/***************************************************************************************/
/* Emulation video modes */
/***************************************************************************************/
static GXRModeObj *rmode;
/* 288 lines progressive (PAL 50Hz) */
static GXRModeObj TV50hz_288p =
{
@ -296,6 +299,11 @@ static GXRModeObj *tvmodes[6] =
&TV50hz_576i
};
/***************************************************************************************/
/* GX rendering engine */
/***************************************************************************************/
typedef struct tagcamera
{
Vector pos;
@ -325,11 +333,6 @@ static camera cam = {
{0.0F, 0.0F, 0.0F}
};
static void updateFrameCount(u32 cnt)
{
frameticker++;
}
/* Vertex Rendering */
static inline void draw_vert(u8 pos, f32 s, f32 t)
{
@ -348,7 +351,7 @@ static inline void draw_square(void)
GX_End ();
}
/* Initialize GX renderer */
/* Initialize GX */
static void gxStart(void)
{
/*** Clear out FIFO area ***/
@ -589,79 +592,344 @@ static void gxDrawCrosshair(gx_texture *texture, int x, int y)
}
}
void gxDrawRectangle(s32 x, s32 y, s32 w, s32 h, u8 alpha, GXColor color)
{
/* GX only use Color channel for rendering */
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
GX_SetVtxDesc (GX_VA_TEX0, GX_NONE);
GX_Flush();
/* vertex coordinate */
x -= (vmode->fbWidth/2);
y -= (vmode->efbHeight/2);
/* draw colored quad */
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position2s16(x,y+h);
GX_Color4u8(color.r,color.g,color.b,alpha);
GX_Position2s16(x+w,y+h);
GX_Color4u8(color.r,color.g,color.b,alpha);
GX_Position2s16(x+w,y);
GX_Color4u8(color.r,color.g,color.b,alpha);
GX_Position2s16(x,y);
GX_Color4u8(color.r,color.g,color.b,alpha);
GX_End ();
GX_DrawDone();
/* restore GX rendering */
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
GX_Flush();
}
void gxDrawTexture(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha)
{
if (!texture) return;
if (texture->data)
{
/* 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); /* does this really change anything ? */
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* vertex coordinate */
x -= (vmode->fbWidth/2);
y -= (vmode->efbHeight/2);
/* 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();
}
}
void gxDrawTextureRepeat(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha)
{
if (!texture) return;
if (texture->data)
{
/* load texture object */
GXTexObj texObj;
GX_InitTexObj(&texObj, texture->data, texture->width, texture->height, GX_TF_RGBA8, GX_MIRROR, GX_MIRROR, GX_FALSE);
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* vertex coordinate */
x -= (vmode->fbWidth/2);
y -= (vmode->efbHeight/2);
/* texture coordinates */
f32 s = (f32)w / (f32)texture->width;
f32 t = (f32)h / (f32)texture->height;
/* 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, t);
GX_Position2s16(x+w,y+h);
GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(s, t);
GX_Position2s16(x+w,y);
GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(s, 0.0);
GX_Position2s16(x,y);
GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(0.0, 0.0);
GX_End ();
GX_DrawDone();
}
}
void gxDrawScreenshot(u8 alpha)
{
if (!rmode) return;
GXTexObj texobj;
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_LoadTexObj(&texobj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* retrieve current xscale/xshift values */
s32 xscale = (rmode->viWidth + square[6] - square[0] - rmode->fbWidth) / 2 - (vmode->viWidth - 640)/2;
s32 xshift = (square[6] + square[0]) / 2;
/* apply current position/size */
s32 x = xshift - xscale;
s32 y = square[7];
s32 w = xscale * 2;
s32 h = square[4] - square[7];
if (rmode->efbHeight < 480)
{
y = y * 2;
h = h * 2;
}
/* 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();
}
void gxCopyScreenshot(gx_texture *texture)
{
/* current game texture */
gxClearScreen((GXColor)BLACK);
GXTexObj texobj;
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_LoadTexObj(&texobj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* scale texture to EFB width */
s32 w = bitmap.viewport.x ? (704) : (640);
s32 h = (bitmap.viewport.h + 2*bitmap.viewport.y) * 2;
s32 x = -w/2;
s32 y = -(240+ 2*bitmap.viewport.y);
/* render gamescreen to EFB */
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();
/* copy EFB to texture */
texture->format = GX_TF_RGBA8;
texture->width = 320;
texture->height = bitmap.viewport.h;
texture->data = screenshot;
GX_SetTexCopySrc(0, 0, texture->width * 2, texture->height * 2);
GX_SetTexCopyDst(texture->width, texture->height, texture->format, GX_TRUE);
GX_CopyTex(texture->data, GX_TRUE);
GX_Flush();
/* wait for copy operation to finish */
/* GX_PixModeSync is only useful if GX_ command follows */
/* we use dummy GX commands to stall CPU execution */
GX_PixModeSync();
GX_LoadTexObj(&texobj, GX_TEXMAP0);
GX_InvalidateTexAll();
DCFlushRange(texture->data, texture->width * texture->height * 4);
}
void gxResetAngle(f32 angle)
{
Mtx view;
if (angle)
{
Mtx m,m1;
Vector axis = (Vector) {0,0,1};
guLookAt(m, &cam.pos, &cam.up, &cam.view);
guMtxRotAxisDeg (m1, &axis, angle);
guMtxConcat(m,m1,view);
}
else
{
guLookAt(view, &cam.pos, &cam.up, &cam.view);
}
GX_LoadPosMtxImm(view, GX_PNMTX0);
GX_Flush();
}
void gxSetScreen ()
{
GX_CopyDisp(xfb[whichfb], GX_FALSE);
GX_Flush();
VIDEO_SetNextFramebuffer (xfb[whichfb]);
VIDEO_Flush ();
VIDEO_WaitVSync ();
}
void gxClearScreen (GXColor color)
{
whichfb ^= 1;
GX_SetCopyClear(color,0x00ffffff);
GX_CopyDisp(xfb[whichfb], GX_TRUE);
GX_Flush();
}
/***************************************************************************************/
/* GX Texture <-> LibPNG routines */
/***************************************************************************************/
/* libpng read callback function */
static void png_read_from_mem (png_structp png_ptr, png_bytep data, png_size_t length)
{
png_file *file = (png_file *)png_get_io_ptr (png_ptr);
png_image *image = (png_image *)png_get_io_ptr(png_ptr);
/* copy data from image buffer */
memcpy (data, file->buffer + file->offset, length);
memcpy (data, image->buffer + image->offset, length);
/* advance in the file */
file->offset += length;
image->offset += length;
}
/* convert a png file into RGBA8 texture */
gx_texture *gxTextureOpenPNG(const u8 *buffer)
/* convert PNG image (from file or data buffer) into RGBA8 texture */
gx_texture *gxTextureOpenPNG(const u8 *png_data, FILE *png_file)
{
int i;
png_file file;
/* init PNG file structure */
file.buffer = (u8 *) buffer;
file.offset = 0;
/* check for valid magic number */
/*if (!png_check_sig (file.buffer, 8)) return;*/
/* create a png read struct */
png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
if (!png_ptr) return NULL;
/* create a png info struct */
png_infop info_ptr = png_create_info_struct (png_ptr);
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
png_destroy_read_struct (&png_ptr, NULL, NULL);
png_destroy_read_struct(&png_ptr,NULL,NULL);
return NULL;
}
/* set callback for the read function */
png_set_read_fn (png_ptr, (png_voidp *)(&file), png_read_from_mem);
if (png_data)
{
/* init PNG image structure */
png_image image;
image.buffer = (u8 *) png_data;
image.offset = 0;
/* set callback for the read function */
png_set_read_fn(png_ptr,(png_voidp *)(&image),png_read_from_mem);
}
else if (png_file)
{
/* check for valid magic number */
png_byte magic[8];
if (fread (magic, 1, 8, png_file) != 8)
{
png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
return NULL;
}
if (!png_check_sig (magic, 8))
if (fread (magic, 1, 8, png_file) != 8)
{
png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
return NULL;
}
/* set IO callback for read function */
png_init_io (png_ptr, png_file);
png_set_sig_bytes (png_ptr, 8);
}
else
{
png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
return NULL;
}
/* read png info */
png_read_info (png_ptr, info_ptr);
png_read_info(png_ptr,info_ptr);
/* retrieve image information */
u32 width = png_get_image_width(png_ptr, info_ptr);
u32 height = png_get_image_height(png_ptr, info_ptr);
u32 width = png_get_image_width(png_ptr,info_ptr);
u32 height = png_get_image_height(png_ptr,info_ptr);
u32 bit_depth = png_get_bit_depth(png_ptr,info_ptr);
u32 color_type = png_get_color_type(png_ptr,info_ptr);
#if 0
/* ensure PNG images are in the supported format */
u32 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
u32 color_type = png_get_color_type(png_ptr, info_ptr);
/* support for RGBA8 textures ONLY !*/
if ((color_type != PNG_COLOR_TYPE_RGB_ALPHA) || (bit_depth != 8))
/* ensure PNG file is in the supported format */
if (png_file)
{
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return;
}
/* support for RGBA8 textures ONLY !*/
if ((color_type != PNG_COLOR_TYPE_RGB_ALPHA) || (bit_depth != 8))
{
png_destroy_read_struct(&png_ptr, &info_ptr,NULL);
return NULL;
}
/* 4x4 tiles are required */
if ((width%4) || (height%4))
{
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return;
/* 4x4 tiles are required */
if ((width%4) || (height%4))
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return NULL;
}
}
#endif
/* allocate memory to store raw image data */
u32 stride = width << 2;
u8 *img_data = memalign (32, stride * height);
if (!img_data)
{
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
return NULL;
}
@ -670,7 +938,7 @@ gx_texture *gxTextureOpenPNG(const u8 *buffer)
if (!row_pointers)
{
free (img_data);
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
return NULL;
}
@ -681,11 +949,11 @@ gx_texture *gxTextureOpenPNG(const u8 *buffer)
}
/* decode image */
png_read_image (png_ptr, row_pointers);
png_read_image(png_ptr, row_pointers);
/* finish decompression and release memory */
png_read_end (png_ptr, NULL);
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
png_read_end(png_ptr, NULL);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
free(row_pointers);
/* initialize texture */
@ -776,6 +1044,127 @@ gx_texture *gxTextureOpenPNG(const u8 *buffer)
return texture;
}
/* Write RGBA8 Texture to PNG file */
void gxTextureWritePNG(gx_texture *texture, FILE *png_file)
{
/* allocate PNG data buffer */
u8 *img_data = (u8 *)memalign(32, texture->width * texture->height * 4);
if(!img_data) return;
/* decode GX_TF_RGBA8 format (4x4 pixels paired titles) */
u16 *ar = (u16 *)(texture->data);
u16 *gb = (u16 *)(texture->data + 32);
u32 *dst1 = (u32 *)(img_data);
u32 *dst2 = dst1 + texture->width;
u32 *dst3 = dst2 + texture->width;
u32 *dst4 = dst3 + texture->width;
u32 i,h,w,pixel;
for (h=0; h<texture->height; h+=4)
{
for (w=0; w<texture->width; w+=4)
{
/* line N (4 pixels) */
for (i=0; i<4; i++)
{
pixel = ((*ar & 0xff) << 24) | (*gb << 8) | ((*ar & 0xff00) >> 8);
*dst1++ = pixel;
ar++;
gb++;
}
/* line N + 1 (4 pixels) */
for (i=0; i<4; i++)
{
pixel = ((*ar & 0xff) << 24) | (*gb << 8) | ((*ar & 0xff00) >> 8);
*dst2++ = pixel;
ar++;
gb++;
}
/* line N + 2 (4 pixels) */
for (i=0; i<4; i++)
{
pixel = ((*ar & 0xff) << 24) | (*gb << 8) | ((*ar & 0xff00) >> 8);
*dst3++ = pixel;
ar++;
gb++;
}
/* line N + 3 (4 pixels) */
for (i=0; i<4; i++)
{
pixel = ((*ar & 0xff) << 24) | (*gb << 8) | ((*ar & 0xff00) >> 8);
*dst4++ = pixel;
ar++;
gb++;
}
/* next paired tiles */
ar += 16;
gb += 16;
}
/* next 4 lines */
dst1 = dst4;
dst2 = dst1 + texture->width;
dst3 = dst2 + texture->width;
dst4 = dst3 + texture->width;
}
/* create a png write struct */
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(!png_ptr)
{
free(img_data);
return;
}
/* create a png info struct */
png_infop info_ptr = png_create_info_struct (png_ptr);
if (!info_ptr)
{
free(img_data);
png_destroy_write_struct(&png_ptr, NULL);
return;
}
/* set IO callback for the write function */
png_init_io(png_ptr, png_file);
/* set PNG file properties */
png_set_IHDR(png_ptr, info_ptr, texture->width, texture->height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
/* allocate row pointer data */
png_bytep *row_pointers = (png_bytep *)memalign (32, sizeof (png_bytep) * texture->height);
if (!row_pointers)
{
free (img_data);
png_destroy_write_struct(&png_ptr, &info_ptr);
return;
}
/* store raw image data */
for (i = 0; i < texture->height; i++)
{
row_pointers[i] = img_data + (i * texture->width * 4);
}
/* configure libpng for image data */
png_set_rows(png_ptr,info_ptr,row_pointers);
/* write data to PNG file */
png_write_png(png_ptr,info_ptr,PNG_TRANSFORM_IDENTITY,NULL);
/* finish compression and release memory */
png_write_end(png_ptr, NULL);
free(row_pointers);
free(img_data);
png_destroy_write_struct(&png_ptr, &info_ptr);
}
void gxTextureClose(gx_texture **p_texture)
{
gx_texture *texture = *p_texture;
@ -788,177 +1177,42 @@ void gxTextureClose(gx_texture **p_texture)
}
}
void gxDrawScreenshot(u8 alpha)
/***************************************************************************************/
/* VIDEO engine */
/***************************************************************************************/
/* VIDEO callback */
static void vi_callback(u32 cnt)
{
if (rmode)
frameticker++;
}
/* Take Screenshot */
void gx_video_Capture(void)
{
/* capture screenshot into a texture */
gx_texture texture;
gxCopyScreenshot(&texture);
/* open PNG file */
char fname[MAXPATHLEN];
sprintf(fname,"%s/snaps/%s.png", DEFAULT_PATH, rom_filename);
FILE *f = fopen(fname,"wb");
if (f)
{
GXTexObj texobj;
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_LoadTexObj(&texobj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* retrieve current xscale/xshift values */
s32 xscale = (rmode->viWidth + square[6] - square[0] - rmode->fbWidth) / 2 - (vmode->viWidth - 640)/2;
s32 xshift = (square[6] + square[0]) / 2;
/* apply current position/size */
s32 x = xshift - xscale;
s32 y = square[7];
s32 w = xscale * 2;
s32 h = square[4] - square[7];
if (rmode->efbHeight < 480)
{
y = y * 2;
h = h * 2;
}
/* 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();
/* encode screenshot into PNG file */
gxTextureWritePNG(&texture,f);
fclose(f);
}
}
void gxDrawTexture(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha)
{
if (!texture) return;
if (texture->data)
{
/* 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); /* does this really change anything ? */
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* vertex coordinate */
x -= (vmode->fbWidth/2);
y -= (vmode->efbHeight/2);
/* 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();
}
}
void gxDrawTextureRepeat(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha)
{
if (!texture) return;
if (texture->data)
{
/* load texture object */
GXTexObj texObj;
GX_InitTexObj(&texObj, texture->data, texture->width, texture->height, GX_TF_RGBA8, GX_MIRROR, GX_MIRROR, GX_FALSE);
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_InvalidateTexAll();
/* vertex coordinate */
x -= (vmode->fbWidth/2);
y -= (vmode->efbHeight/2);
/* texture coordinates */
f32 s = (f32)w / (f32)texture->width;
f32 t = (f32)h / (f32)texture->height;
/* 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, t);
GX_Position2s16(x+w,y+h);
GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(s, t);
GX_Position2s16(x+w,y);
GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(s, 0.0);
GX_Position2s16(x,y);
GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(0.0, 0.0);
GX_End ();
GX_DrawDone();
}
}
void gxResetAngle(f32 angle)
{
Mtx view;
if (angle)
{
Mtx m,m1;
Vector axis = (Vector) {0,0,1};
guLookAt(m, &cam.pos, &cam.up, &cam.view);
guMtxRotAxisDeg (m1, &axis, angle);
guMtxConcat(m,m1,view);
}
else
{
guLookAt(view, &cam.pos, &cam.up, &cam.view);
}
GX_LoadPosMtxImm(view, GX_PNMTX0);
GX_Flush();
}
void gxSetScreen ()
{
GX_CopyDisp(xfb[whichfb], GX_FALSE);
GX_Flush();
VIDEO_SetNextFramebuffer (xfb[whichfb]);
VIDEO_Flush ();
VIDEO_WaitVSync ();
}
void gxClearScreen (GXColor color)
{
whichfb ^= 1;
GX_SetCopyClear(color,0x00ffffff);
GX_CopyDisp(xfb[whichfb], GX_TRUE);
GX_Flush();
}
/* Restore Menu Video mode */
/* Emulation mode -> Menu mode */
void gx_video_Stop(void)
{
/* lightgun textures */
if (crosshair[0])
{
if (crosshair[0]->data) free(crosshair[0]->data);
free(crosshair[0]);
crosshair[0] = NULL;
}
if (crosshair[1])
{
if (crosshair[1]->data) free(crosshair[1]->data);
free(crosshair[1]);
crosshair[1] = NULL;
}
gxTextureClose(&crosshair[0]);
gxTextureClose(&crosshair[1]);
/* reset GX */
gxResetRendering(1);
@ -972,16 +1226,17 @@ void gx_video_Stop(void)
gxSetScreen ();
}
/* Update Video settings */
/* Menu mode -> Emulation mode */
void gx_video_Start(void)
{
/* 50Hz/60Hz mode */
if ((config.tv_mode == 1) || ((config.tv_mode == 2) && vdp_pal)) gc_pal = 1;
else gc_pal = 0;
/* Video Interrupt synchronization */
/* VIDEO sync */
VIDEO_SetPostRetraceCallback(NULL);
if (!gc_pal && !vdp_pal) VIDEO_SetPreRetraceCallback(updateFrameCount);
if (!gc_pal && !vdp_pal)
VIDEO_SetPreRetraceCallback(vi_callback);
VIDEO_Flush();
/* interlaced/progressive mode */
@ -996,6 +1251,19 @@ void gx_video_Start(void)
tvmodes[2]->xfbMode = VI_XFBMODE_DF;
}
/* overscan */
if (config.overscan)
{
bitmap.viewport.x = (reg[12] & 1) ? 16 : 12;
bitmap.viewport.y = (reg[1] & 8) ? 0 : 8;
if (vdp_pal) bitmap.viewport.y += 24;
}
else
{
bitmap.viewport.x = 0;
bitmap.viewport.y = 0;
}
/* software NTSC filters */
if (config.ntsc == 1)
{
@ -1024,8 +1292,8 @@ void gx_video_Start(void)
{
if (config.gun_cursor)
{
if (input.dev[4] == DEVICE_LIGHTGUN) crosshair[0] = gxTextureOpenPNG(Crosshair_p1_png);
if (input.dev[5] == DEVICE_LIGHTGUN) crosshair[1] = gxTextureOpenPNG(Crosshair_p2_png);
if (input.dev[4] == DEVICE_LIGHTGUN) crosshair[0] = gxTextureOpenPNG(Crosshair_p1_png,0);
if (input.dev[5] == DEVICE_LIGHTGUN) crosshair[1] = gxTextureOpenPNG(Crosshair_p2_png,0);
}
}
@ -1034,10 +1302,8 @@ void gx_video_Start(void)
/* reset GX rendering */
gxResetRendering(0);
}
/* GX render update */
void gx_video_Update(void)
{
@ -1244,24 +1510,16 @@ void gx_video_Init(void)
#endif
}
/* Initialize texture data */
/* Initialize textures */
texturemem = memalign(32, TEX_SIZE);
if (!texturemem)
{
WaitPrompt("Failed to allocate texture buffer... Rebooting");
#ifdef HW_RVL
DI_Close();
SYS_ResetSystem(SYS_RESTART,0,0);
#else
SYS_ResetSystem(SYS_HOTRESET,0,0);
#endif
}
memset (texturemem, 0, TEX_SIZE);
screenshot = memalign(32, HASPECT*VASPECT*4);
if (!texturemem || !screenshot) gx_video_Shutdown();
}
void gx_video_Shutdown(void)
{
if (texturemem) free(texturemem);
if (screenshot) free(screenshot);
FONT_Shutdown();
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
VIDEO_Flush();

View File

@ -45,21 +45,28 @@ extern GXRModeObj *vmode;
extern u8 *texturemem;
extern u8 gc_pal;
/* GX video emulation functions */
/* GX rendering */
extern void gxDrawRectangle(s32 x, s32 y, s32 w, s32 h, u8 alpha, GXColor color);
extern void gxDrawTexture(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha);
extern void gxDrawTextureRepeat(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha);
extern void gxDrawScreenshot(u8 alpha);
extern void gxCopyScreenshot(gx_texture *texture);
extern void gxResetAngle(f32 angle);
extern void gxClearScreen (GXColor color);
extern void gxSetScreen ();
/* PNG textures */
extern gx_texture *gxTextureOpenPNG(const u8 *png_data, FILE *png_file);
extern void gxTextureWritePNG(gx_texture *p_texture, FILE *png_file);
extern void gxTextureClose(gx_texture **p_texture);
/* GX video engine */
extern void gx_video_Init(void);
extern void gx_video_Shutdown(void);
extern void gx_video_Start(void);
extern void gx_video_Stop(void);
extern void gx_video_Update(void);
/* GX draw functions */
extern gx_texture *gxTextureOpenPNG(const u8 *buffer);
extern void gxTextureClose(gx_texture **p_texture);
extern void gxDrawScreenshot(u8 alpha);
extern void gxDrawTexture(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha);
extern void gxDrawTextureRepeat(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha);
extern void gxResetAngle(f32 angle);
extern void gxClearScreen (GXColor color);
extern void gxSetScreen ();
extern void gx_video_Capture(void);
#endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 341 KiB

After

Width:  |  Height:  |  Size: 341 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 698 B

View File

@ -1,9 +1,9 @@
/****************************************************************************
* main.c
*
* Genesis Plus GX main
* Genesis Plus GX
*
* code by Softdev (2006), Eke-Eke (2007,2008)
* code by Softdev (2006), Eke-Eke (2007,2009)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -156,7 +156,7 @@ u32 frameticker = 0;
int main (int argc, char *argv[])
{
#ifdef HW_RVL
/* initialize DVD Mode */
/* initialize DVDX */
DI_Close();
DI_Init();
#endif
@ -168,7 +168,6 @@ int main (int argc, char *argv[])
/* initialize hardware */
gx_video_Init();
gx_input_Init();
gx_audio_Init();
#ifdef HW_DOL
DVD_Init ();
dvd_drive_detect();
@ -177,7 +176,6 @@ int main (int argc, char *argv[])
/* initialize FAT devices */
if (fatInitDefault())
{
fat_enabled = 1;
#ifdef HW_RVL
fatEnableReadAhead ("sd", 6, 64);
fatEnableReadAhead ("usb", 6, 64);
@ -185,22 +183,44 @@ int main (int argc, char *argv[])
fatEnableReadAhead ("carda", 6, 64);
fatEnableReadAhead ("cardb", 6, 64);
#endif
/* check for default directories */
DIR_ITER *dir = NULL;
/* base directory */
char pathname[MAXPATHLEN];
sprintf (pathname, DEFAULT_PATH);
dir = diropen(pathname);
if (dir == NULL) mkdir(pathname,S_IRWXU);
else dirclose(dir);
/* SRAM & Savestate files directory */
sprintf (pathname, "%s/saves",DEFAULT_PATH);
dir = diropen(pathname);
if (dir == NULL) mkdir(pathname,S_IRWXU);
else dirclose(dir);
/* Snapshot files directory */
sprintf (pathname, "%s/snaps",DEFAULT_PATH);
dir = diropen(pathname);
if (dir == NULL) mkdir(pathname,S_IRWXU);
else dirclose(dir);
/* Cheat files directory */
sprintf (pathname, "%s/cheats",DEFAULT_PATH);
dir = diropen(pathname);
if (dir == NULL) mkdir(pathname,S_IRWXU);
else dirclose(dir);
}
/* Initialize sound engine */
/* initialize sound engine */
gx_audio_Init();
/* default config */
/* initialize core engine */
legal();
config_setDefault();
config_load();
/* recent ROM files list */
history_setDefault();
history_load();
/* initialize Virtual Machine */
init_machine ();
config_default();
history_default();
init_machine();
/* run any injected rom */
if (genromsize)
@ -213,7 +233,7 @@ int main (int argc, char *argv[])
}
else
{
/* show menu first */
/* Main Menu */
ConfigRequested = 1;
}
@ -225,14 +245,14 @@ int main (int argc, char *argv[])
/* main emulation loop */
while (1)
{
/* check for menu request */
/* Main Menu request */
if (ConfigRequested)
{
/* stop audio & video */
gx_video_Stop();
gx_audio_Stop();
/* go to menu */
/* show menu */
MainMenu ();
ConfigRequested = 0;

View File

@ -23,9 +23,9 @@
#define DEFAULT_PATH "/genplus"
#ifdef HW_RVL
#define VERSION "v1.3.2 (WII)"
#define VERSION "version 1.3.2W"
#else
#define VERSION "v1.3.2 (GCN)"
#define VERSION "version 1.3.2G"
#endif
/* globals */
@ -42,7 +42,6 @@ extern int ManageState(u8 direction, u8 device);
extern void memfile_autosave(s8 autosram, s8 autostate);
extern void memfile_autoload(s8 autosram, s8 autostate);
extern u8 fat_enabled;
extern u32 frameticker;
extern char rom_filename[256];

View File

@ -387,11 +387,11 @@ static uint16 pixel_16[0x100];
static uint16 pixel_16_lut[3][0x200];
/* Line buffers */
static uint8 tmp_buf[0x400]; /* Temporary buffer */
static uint8 bg_buf[0x400]; /* Merged background buffer */
static uint8 nta_buf[0x400]; /* Plane A / Window line buffer */
static uint8 ntb_buf[0x400]; /* Plane B line buffer */
static uint8 obj_buf[0x400]; /* Object layer line buffer */
static uint8 tmp_buf[0x200]; /* Temporary buffer */
static uint8 bg_buf[0x200]; /* Merged background buffer */
static uint8 nta_buf[0x200]; /* Plane A / Window line buffer */
static uint8 ntb_buf[0x200]; /* Plane B line buffer */
static uint8 obj_buf[0x200]; /* Object layer line buffer */
/* Sprite line buffer data */
static uint32 object_index_count;

View File

@ -2156,4 +2156,12 @@ void YM2612Restore(unsigned char *buffer)
ym2612.OPN.ST.clock = clock;
ym2612.OPN.ST.rate = rate;
OPNSetPres(6*24);
/* restore outputs connections */
setup_connection(&ym2612.CH[0],0);
setup_connection(&ym2612.CH[1],1);
setup_connection(&ym2612.CH[2],2);
setup_connection(&ym2612.CH[3],3);
setup_connection(&ym2612.CH[4],4);
setup_connection(&ym2612.CH[5],5);
}

View File

@ -22,6 +22,8 @@
#include "shared.h"
static unsigned char state[STATE_SIZE];
#define load_param(param, size) \
memcpy(param, &state[bufferptr], size); \
bufferptr+= size;
@ -32,10 +34,6 @@
void state_load(unsigned char *buffer)
{
/* allocate memory */
unsigned char *state = malloc(STATE_SIZE);
if (state == NULL) return;
/* buffer size */
int bufferptr = 0;
@ -79,14 +77,8 @@ void state_load(unsigned char *buffer)
vdp_restore(temp_reg);
// FM
unsigned char *temp = malloc (YM2612GetContextSize());
if (temp)
{
load_param(temp,YM2612GetContextSize());
YM2612Restore(temp);
free(temp);
}
else bufferptr+=YM2612GetContextSize();
YM2612Restore(&state[bufferptr]);
bufferptr+= YM2612GetContextSize();
// PSG
load_param(SN76489_GetContextPtr (0),SN76489_GetContextSize ());
@ -116,17 +108,10 @@ void state_load(unsigned char *buffer)
// Z80
load_param(&Z80, sizeof(Z80_Regs));
/* Free memory */
free(state);
}
int state_save(unsigned char *buffer)
{
/* allocate memory */
unsigned char *state = malloc(STATE_SIZE);
if (state == NULL) return 0;
/* buffer size */
int bufferptr = 0;
@ -166,21 +151,21 @@ int state_save(unsigned char *buffer)
uint16 tmp16;
uint32 tmp32;
tmp32 = m68k_get_reg(NULL, M68K_REG_D0); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D1); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D2); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D3); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D4); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D5); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D6); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D7); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A0); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A1); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A2); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A3); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A4); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A5); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A6); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A7); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D1); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D2); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D3); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D4); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D5); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D6); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D7); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A0); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A1); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A2); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A3); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A4); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A5); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A6); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A7); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_PC); save_param(&tmp32, 4);
tmp16 = m68k_get_reg(NULL, M68K_REG_SR); save_param(&tmp16, 2);
tmp32 = m68k_get_reg(NULL, M68K_REG_USP); save_param(&tmp32, 4);
@ -194,9 +179,6 @@ int state_save(unsigned char *buffer)
compress2 ((Bytef *)(buffer + 4), &outbytes, (Bytef *)state, inbytes, 9);
memcpy(buffer, &outbytes, 4);
/* Free memory */
free(state);
/* return total size */
return (outbytes + 4);
}