2229 lines
64 KiB
C
2229 lines
64 KiB
C
/* FCE Ultra - NES/Famicom Emulator
|
|
*
|
|
* Copyright notice for this file:
|
|
* Copyright (C) 2002 Xodnizel
|
|
*
|
|
* 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
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "state.c" /* Save/Load state AS */
|
|
|
|
extern char *md5_asciistr(uint8 digest[16]);
|
|
extern FCEUGI *FCEUGameInfo;
|
|
extern int EnableRewind;
|
|
|
|
void DSMFix(UINT msg)
|
|
{
|
|
switch(msg)
|
|
{
|
|
case WM_VSCROLL:
|
|
case WM_NCRBUTTONDOWN:
|
|
case WM_NCMBUTTONDOWN:
|
|
case WM_NCLBUTTONDOWN:
|
|
case WM_ENTERMENULOOP:StopSound();break;
|
|
}
|
|
}
|
|
static void ConfigGUI(void);
|
|
static void ConfigTiming(void);
|
|
static void ConfigPalette(void);
|
|
static void ConfigDirectories(void);
|
|
|
|
static HMENU fceumenu=0;
|
|
|
|
static int tog=0;
|
|
static int CheckedAutoFirePattern=40004;
|
|
static int CheckedAutoFireOffset=40016;
|
|
static int EnableBackgroundInput=0;
|
|
|
|
void ShowCursorAbs(int w)
|
|
{
|
|
static int stat=0;
|
|
if(w)
|
|
{
|
|
if(stat==-1) {stat++; ShowCursor(1);}
|
|
}
|
|
else
|
|
{
|
|
if(stat==0) {stat--; ShowCursor(0);}
|
|
}
|
|
}
|
|
|
|
|
|
void CalcWindowSize(RECT *al)
|
|
{
|
|
al->left=0;
|
|
al->right=VNSWID*winsizemulx;
|
|
al->top=0;
|
|
al->bottom=totallines*winsizemuly;
|
|
|
|
AdjustWindowRectEx(al,GetWindowLong(hAppWnd,GWL_STYLE),GetMenu(hAppWnd)!=NULL,GetWindowLong(hAppWnd,GWL_EXSTYLE));
|
|
|
|
al->right-=al->left;
|
|
al->left=0;
|
|
al->bottom-=al->top;
|
|
al->top=0;
|
|
}
|
|
|
|
|
|
void RedoMenuGI(FCEUGI *gi)
|
|
{
|
|
int simpled[]={101,111,110,200,201,204,203,141,142,143,151,152,300,40003,40028, 0};
|
|
int x;
|
|
|
|
x = 0;
|
|
while(simpled[x])
|
|
{
|
|
#ifndef FCEUDEF_DEBUGGER
|
|
if(simpled[x] == 203)
|
|
EnableMenuItem(fceumenu,simpled[x],MF_BYCOMMAND | MF_GRAYED);
|
|
else
|
|
#endif
|
|
#ifndef _USE_SHARED_MEMORY_
|
|
if(simpled[x] == 40002 || simpled[x] == 40003)
|
|
EnableMenuItem(fceumenu,simpled[x],MF_BYCOMMAND| MF_GRAYED);
|
|
else
|
|
#endif
|
|
EnableMenuItem(fceumenu,simpled[x],MF_BYCOMMAND | (gi?MF_ENABLED:MF_GRAYED));
|
|
x++;
|
|
}
|
|
}
|
|
|
|
void UpdateMenu(void)
|
|
{
|
|
static int *polo[3]={&genie,&palyo,&status_icon};
|
|
static int polo2[3]={310,311,303};
|
|
int x;
|
|
|
|
for(x=0;x<3;x++)
|
|
CheckMenuItem(fceumenu,polo2[x],*polo[x]?MF_CHECKED:MF_UNCHECKED);
|
|
|
|
if(eoptions&EO_BGRUN)
|
|
CheckMenuItem(fceumenu,301,MF_CHECKED);
|
|
else
|
|
CheckMenuItem(fceumenu,301,MF_UNCHECKED);
|
|
|
|
if(FCEU_BotMode())
|
|
CheckMenuItem(fceumenu,40003, MF_CHECKED);
|
|
else
|
|
CheckMenuItem(fceumenu,40003, MF_UNCHECKED);
|
|
|
|
if(GetAutoFireDesynch())
|
|
CheckMenuItem(fceumenu,40025, MF_CHECKED);
|
|
else
|
|
CheckMenuItem(fceumenu,40025, MF_UNCHECKED);
|
|
|
|
CheckMenuItem(fceumenu,302, EnableBackgroundInput?MF_CHECKED:MF_UNCHECKED);
|
|
CheckMenuItem(fceumenu,40029, EnableRewind?MF_CHECKED:MF_UNCHECKED);
|
|
|
|
int AutoFirePatternIDs[]={40004,40005,40006,40007,40008,40009,40010,40011,40012,40013,40014,40015,40022,40023,40024,0};
|
|
int AutoFireOffsetIDs[]={40016,40017,40018,40019,40020,40021,0};
|
|
|
|
x = 0;
|
|
while(AutoFirePatternIDs[x])
|
|
{
|
|
CheckMenuItem(fceumenu,AutoFirePatternIDs[x],
|
|
AutoFirePatternIDs[x]==CheckedAutoFirePattern?MF_CHECKED:MF_UNCHECKED);
|
|
x++;
|
|
}
|
|
|
|
x = 0;
|
|
while(AutoFireOffsetIDs[x])
|
|
{
|
|
CheckMenuItem(fceumenu,AutoFireOffsetIDs[x],
|
|
AutoFireOffsetIDs[x]==CheckedAutoFireOffset?MF_CHECKED:MF_UNCHECKED);
|
|
x++;
|
|
}
|
|
}
|
|
|
|
static HMENU recentmenu, recentdmenu;
|
|
char *rfiles[10]={0,0,0,0,0,0,0,0,0,0};
|
|
char *rdirs[10]={0,0,0,0,0,0,0,0,0,0};
|
|
|
|
void UpdateRMenu(HMENU menu, char **strs, int mitem, int baseid)
|
|
{
|
|
MENUITEMINFO moo;
|
|
int x;
|
|
|
|
moo.cbSize=sizeof(moo);
|
|
moo.fMask=MIIM_SUBMENU|MIIM_STATE;
|
|
|
|
GetMenuItemInfo(GetSubMenu(fceumenu,0),mitem,FALSE,&moo);
|
|
moo.hSubMenu=menu;
|
|
moo.fState=strs[0]?MFS_ENABLED:MFS_GRAYED;
|
|
|
|
SetMenuItemInfo(GetSubMenu(fceumenu,0),mitem,FALSE,&moo);
|
|
|
|
for(x=0;x<10;x++)
|
|
RemoveMenu(menu,baseid+x,MF_BYCOMMAND);
|
|
for(x=9;x>=0;x--)
|
|
{
|
|
char tmp[128+5];
|
|
if(!strs[x]) continue;
|
|
|
|
moo.cbSize=sizeof(moo);
|
|
moo.fMask=MIIM_DATA|MIIM_ID|MIIM_TYPE;
|
|
|
|
if(strlen(strs[x])<128)
|
|
{
|
|
sprintf(tmp,"&%d. %s",(x+1)%10,strs[x]);
|
|
}
|
|
else
|
|
sprintf(tmp,"&%d. %s",(x+1)%10,strs[x]+strlen(strs[x])-127);
|
|
|
|
moo.cch=strlen(tmp);
|
|
moo.fType=0;
|
|
moo.wID=baseid+x;
|
|
moo.dwTypeData=tmp;
|
|
InsertMenuItem(menu,0,1,&moo);
|
|
}
|
|
DrawMenuBar(hAppWnd);
|
|
}
|
|
|
|
void AddRecent(char *fn)
|
|
{
|
|
int x;
|
|
|
|
for(x=0;x<10;x++)
|
|
if(rfiles[x])
|
|
if(!strcmp(rfiles[x],fn)) // Item is already in list.
|
|
{
|
|
int y;
|
|
char *tmp;
|
|
|
|
tmp=rfiles[x]; // Save pointer.
|
|
for(y=x;y;y--)
|
|
rfiles[y]=rfiles[y-1]; // Move items down.
|
|
|
|
rfiles[0]=tmp; // Put item on top.
|
|
UpdateRMenu(recentmenu, rfiles, 102, 600);
|
|
return;
|
|
}
|
|
|
|
if(rfiles[9]) free(rfiles[9]);
|
|
for(x=9;x;x--) rfiles[x]=rfiles[x-1];
|
|
rfiles[0]=(char*)malloc(strlen(fn)+1); //mbg merge 7/17/06 added cast
|
|
strcpy(rfiles[0],fn);
|
|
UpdateRMenu(recentmenu, rfiles, 102, 600);
|
|
}
|
|
|
|
void AddRecentDir(char *fn)
|
|
{
|
|
int x;
|
|
|
|
for(x=0;x<10;x++)
|
|
if(rdirs[x])
|
|
if(!strcmp(rdirs[x],fn)) // Item is already in list.
|
|
{
|
|
int y;
|
|
char *tmp;
|
|
|
|
tmp=rdirs[x]; // Save pointer.
|
|
for(y=x;y;y--)
|
|
rdirs[y]=rdirs[y-1]; // Move items down.
|
|
|
|
rdirs[0]=tmp; // Put item on top.
|
|
UpdateRMenu(recentdmenu, rdirs, 103, 700);
|
|
return;
|
|
}
|
|
|
|
if(rdirs[9]) free(rdirs[9]);
|
|
for(x=9;x;x--) rdirs[x]=rdirs[x-1];
|
|
rdirs[0]=(char *)malloc(strlen(fn)+1); //mbg merge 7/17/06 added cast
|
|
strcpy(rdirs[0],fn);
|
|
UpdateRMenu(recentdmenu, rdirs, 103, 700);
|
|
}
|
|
|
|
|
|
|
|
void HideMenu(int h)
|
|
{
|
|
if(h)
|
|
{
|
|
SetMenu(hAppWnd,0);
|
|
}
|
|
else
|
|
{
|
|
SetMenu(hAppWnd,fceumenu);
|
|
}
|
|
}
|
|
|
|
static LONG WindowXC=1<<30,WindowYC;
|
|
void HideFWindow(int h)
|
|
{
|
|
LONG desa;
|
|
|
|
if(h) /* Full-screen. */
|
|
{
|
|
RECT bo;
|
|
GetWindowRect(hAppWnd,&bo);
|
|
WindowXC=bo.left;
|
|
WindowYC=bo.top;
|
|
|
|
SetMenu(hAppWnd,0);
|
|
desa=WS_POPUP|WS_CLIPSIBLINGS;
|
|
}
|
|
else
|
|
{
|
|
desa=WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS;
|
|
HideMenu(tog);
|
|
/* Stupid DirectDraw bug(I think?) requires this. Need to investigate it. */
|
|
SetWindowPos(hAppWnd,HWND_NOTOPMOST,0,0,0,0,SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE);
|
|
}
|
|
|
|
SetWindowLong(hAppWnd,GWL_STYLE,desa|(GetWindowLong(hAppWnd,GWL_STYLE)&WS_VISIBLE));
|
|
SetWindowPos(hAppWnd,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_NOZORDER);
|
|
}
|
|
|
|
void ToggleHideMenu(void)
|
|
{
|
|
extern FCEUGI *FCEUGameInfo;
|
|
if(!fullscreen && (FCEUGameInfo || tog))
|
|
{
|
|
tog^=1;
|
|
HideMenu(tog);
|
|
SetMainWindowStuff();
|
|
}
|
|
}
|
|
|
|
void FCEUD_HideMenuToggle(void)
|
|
{
|
|
ToggleHideMenu();
|
|
}
|
|
|
|
static void ALoad(char *nameo)
|
|
{
|
|
if((GI=FCEUI_LoadGame(nameo,1)))
|
|
{
|
|
palyo=FCEUI_GetCurrentVidSystem(0,0);
|
|
UpdateMenu();
|
|
FixFL();
|
|
SetMainWindowStuff();
|
|
AddRecent(nameo);
|
|
RefreshThrottleFPS();
|
|
if(eoptions&EO_HIDEMENU && !tog)
|
|
ToggleHideMenu();
|
|
if(eoptions&EO_FSAFTERLOAD)
|
|
SetFSVideoMode();
|
|
}
|
|
else
|
|
StopSound();
|
|
ParseGIInput(GI);
|
|
RedoMenuGI(GI);
|
|
}
|
|
|
|
void LoadNewGamey(HWND hParent, char *initialdir)
|
|
{
|
|
const char filter[]="All usable files(*.nes,*.nsf,*.fds,*.unf,*.zip,*.gz)\0*.nes;*.nsf;*.fds;*.unf;*.zip;*.gz\0All non-compressed usable files(*.nes,*.nsf,*.fds,*.unf)\0*.nes;*.nsf;*.fds;*.unf\0All files (*.*)\0*.*\0";
|
|
char nameo[2048];
|
|
OPENFILENAME ofn;
|
|
memset(&ofn,0,sizeof(ofn));
|
|
ofn.lStructSize=sizeof(ofn);
|
|
ofn.hInstance=fceu_hInstance;
|
|
ofn.lpstrTitle="FCE Ultra Open File...";
|
|
ofn.lpstrFilter=filter;
|
|
nameo[0]=0;
|
|
ofn.hwndOwner=hParent;
|
|
ofn.lpstrFile=nameo;
|
|
ofn.nMaxFile=256;
|
|
ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; //OFN_EXPLORER|OFN_ENABLETEMPLATE|OFN_ENABLEHOOK;
|
|
ofn.lpstrInitialDir=initialdir?initialdir:gfsdir;
|
|
if(GetOpenFileName(&ofn))
|
|
{
|
|
char *tmpdir;
|
|
|
|
if((tmpdir=(char *)malloc(ofn.nFileOffset+1))) //mbg merge 7/17/06 added cast
|
|
{
|
|
strncpy(tmpdir,ofn.lpstrFile,ofn.nFileOffset);
|
|
tmpdir[ofn.nFileOffset]=0;
|
|
AddRecentDir(tmpdir);
|
|
|
|
if(!initialdir) // Prevent setting the File->Open default
|
|
// directory when a "Recent Directory" is selected.
|
|
{
|
|
if(gfsdir)
|
|
free(gfsdir);
|
|
gfsdir = tmpdir;
|
|
}
|
|
else
|
|
free(tmpdir);
|
|
}
|
|
ALoad(nameo);
|
|
}
|
|
}
|
|
|
|
static uint32 mousex,mousey,mouseb;
|
|
void GetMouseData(uint32 *md)
|
|
{
|
|
if(FCEUI_IsMovieActive()<0)
|
|
return;
|
|
|
|
md[0]=mousex;
|
|
md[1]=mousey;
|
|
if(!fullscreen)
|
|
{
|
|
if(ismaximized)
|
|
{
|
|
RECT t;
|
|
GetClientRect(hAppWnd, &t);
|
|
md[0] = md[0] * VNSWID / (t.right?t.right:1);
|
|
md[1] = md[1] * totallines / (t.bottom?t.bottom:1);
|
|
}
|
|
else
|
|
{
|
|
md[0]/=winsizemulx;
|
|
md[1]/=winsizemuly;
|
|
}
|
|
md[0]+=VNSCLIP;
|
|
}
|
|
|
|
md[1]+=srendline;
|
|
md[2]=((mouseb==MK_LBUTTON)?1:0)|((mouseb==MK_RBUTTON)?2:0);
|
|
}
|
|
|
|
//static int sizchange=0;
|
|
static int vchanged=0;
|
|
|
|
extern void RestartMovieOrReset(int pow);
|
|
|
|
int KeyboardSetBackgroundAccess(int on); //mbg merge 7/17/06 YECH had to add
|
|
void SetJoystickBackgroundAccess(int background); //mbg merge 7/17/06 YECH had to add
|
|
void ShowNetplayConsole(void); //mbg merge 7/17/06 YECH had to add
|
|
int FCEUMOV_IsPlaying(void); //mbg merge 7/17/06 YECH had to add
|
|
|
|
|
|
void MapInput(void);
|
|
|
|
LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
|
{
|
|
DSMFix(msg);
|
|
switch(msg) {
|
|
case WM_LBUTTONDOWN:
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_RBUTTONUP:
|
|
mouseb=wParam;
|
|
goto proco;
|
|
case WM_MOUSEMOVE:
|
|
{
|
|
mousex=LOWORD(lParam);
|
|
mousey=HIWORD(lParam);
|
|
}
|
|
goto proco;
|
|
case WM_ERASEBKGND:
|
|
if(xbsave)
|
|
return(0);
|
|
else goto proco;
|
|
case WM_PAINT:if(xbsave)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
BeginPaint(hWnd,&ps);
|
|
FCEUD_BlitScreen(xbsave);
|
|
EndPaint(hWnd,&ps);
|
|
return(0);
|
|
}
|
|
goto proco;
|
|
case WM_SIZE:
|
|
if(!fullscreen && !changerecursive)
|
|
switch(wParam)
|
|
{
|
|
case SIZE_MAXIMIZED: ismaximized = 1;SetMainWindowStuff();break;
|
|
case SIZE_RESTORED: ismaximized = 0;SetMainWindowStuff();break;
|
|
}
|
|
break;
|
|
case WM_SIZING:
|
|
{
|
|
RECT *wrect=(RECT *)lParam;
|
|
RECT srect;
|
|
|
|
int h=wrect->bottom-wrect->top;
|
|
int w=wrect->right-wrect->left;
|
|
int how;
|
|
|
|
if(wParam == WMSZ_BOTTOM || wParam == WMSZ_TOP)
|
|
how = 2;
|
|
else if(wParam == WMSZ_LEFT || wParam == WMSZ_RIGHT)
|
|
how = 1;
|
|
else if(wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_BOTTOMRIGHT
|
|
|| wParam == WMSZ_TOPRIGHT || wParam == WMSZ_TOPLEFT)
|
|
how = 3;
|
|
if(how & 1)
|
|
winsizemulx*= (double)w/winwidth;
|
|
if(how & 2)
|
|
winsizemuly*= (double)h/winheight;
|
|
if(how & 1) FixWXY(0);
|
|
else FixWXY(1);
|
|
|
|
CalcWindowSize(&srect);
|
|
winwidth=srect.right;
|
|
winheight=srect.bottom;
|
|
wrect->right = wrect->left + srect.right;
|
|
wrect->bottom = wrect->top + srect.bottom;
|
|
}
|
|
//sizchange=1;
|
|
//break;
|
|
goto proco;
|
|
case WM_DISPLAYCHANGE:
|
|
if(!fullscreen && !changerecursive)
|
|
vchanged=1;
|
|
goto proco;
|
|
case WM_DROPFILES:
|
|
{
|
|
UINT len;
|
|
char *ftmp;
|
|
|
|
len=DragQueryFile((HDROP)wParam,0,0,0)+1; //mbg merge 7/17/06 changed (HANDLE) to (HDROP)
|
|
if((ftmp=(char*)malloc(len))) //mbg merge 7/17/06 added cast
|
|
{
|
|
DragQueryFile((HDROP)wParam,0,ftmp,len); //mbg merge 7/17/06 changed (HANDLE) to (HDROP)
|
|
ALoad(ftmp);
|
|
free(ftmp);
|
|
}
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
if(!(wParam>>16))
|
|
{
|
|
wParam&=0xFFFF;
|
|
if(wParam>=600 && wParam<=609) // Recent files
|
|
{
|
|
if(rfiles[wParam-600]) ALoad(rfiles[wParam-600]);
|
|
}
|
|
else if(wParam >= 700 && wParam <= 709) // Recent dirs
|
|
{
|
|
if(rdirs[wParam-700])
|
|
LoadNewGamey(hWnd, rdirs[wParam - 700]);
|
|
}
|
|
switch(wParam)
|
|
{
|
|
case 40004:
|
|
SetAutoFirePattern(1,1);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40005:
|
|
SetAutoFirePattern(1,2);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40006:
|
|
SetAutoFirePattern(1,3);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40007:
|
|
SetAutoFirePattern(1,4);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40008:
|
|
SetAutoFirePattern(1,5);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40009:
|
|
SetAutoFirePattern(2,1);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40010:
|
|
SetAutoFirePattern(2,2);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40011:
|
|
SetAutoFirePattern(2,3);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40012:
|
|
SetAutoFirePattern(2,4);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40013:
|
|
SetAutoFirePattern(3,1);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40014:
|
|
SetAutoFirePattern(3,2);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40015:
|
|
SetAutoFirePattern(3,3);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40022:
|
|
SetAutoFirePattern(4,1);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40023:
|
|
SetAutoFirePattern(4,2);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40024:
|
|
SetAutoFirePattern(5,1);
|
|
CheckedAutoFirePattern = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40016:
|
|
case 40017:
|
|
case 40018:
|
|
case 40019:
|
|
case 40020:
|
|
case 40021:
|
|
SetAutoFireOffset(wParam - 40016);
|
|
CheckedAutoFireOffset = wParam;
|
|
UpdateMenu();
|
|
break;
|
|
case 40025:
|
|
SetAutoFireDesynch(GetAutoFireDesynch()^1);
|
|
UpdateMenu();
|
|
break;
|
|
case 300:ToggleHideMenu();break;
|
|
case 301:
|
|
eoptions^=EO_BGRUN;
|
|
if((eoptions & EO_BGRUN) == 0)
|
|
{
|
|
EnableBackgroundInput = 0;
|
|
KeyboardSetBackgroundAccess(EnableBackgroundInput);
|
|
SetJoystickBackgroundAccess(EnableBackgroundInput);
|
|
}
|
|
UpdateMenu();
|
|
break;
|
|
case 302:EnableBackgroundInput ^= 1;
|
|
eoptions |= EO_BGRUN*EnableBackgroundInput;
|
|
KeyboardSetBackgroundAccess(EnableBackgroundInput);
|
|
SetJoystickBackgroundAccess(EnableBackgroundInput);
|
|
UpdateMenu();
|
|
break;
|
|
case 40029:
|
|
EnableRewind^= 1;
|
|
UpdateMenu();
|
|
break;
|
|
case 303:status_icon=!status_icon;UpdateMenu();break;
|
|
case 310:genie^=1;FCEUI_SetGameGenie(genie);UpdateMenu();break;
|
|
case 311:palyo^=1;
|
|
FCEUI_SetVidSystem(palyo);
|
|
RefreshThrottleFPS();
|
|
UpdateMenu();
|
|
FixFL();
|
|
// DoVideoConfigFix();
|
|
SetMainWindowStuff();
|
|
break;
|
|
case 40003: FCEU_SetBotMode(1^FCEU_BotMode());
|
|
UpdateMenu(); break;
|
|
case 40002: CreateBasicBot();break;
|
|
case 40028: DoMemmo(0); break;
|
|
case 320:StopSound();ConfigDirectories();break;
|
|
case 327:StopSound();ConfigGUI();break;
|
|
case 321:StopSound();ConfigInput(hWnd);break;
|
|
case 322:ConfigTiming();break;
|
|
case 323:StopSound();ShowNetplayConsole();break;
|
|
case 324:StopSound();ConfigPalette();break;
|
|
case 325:StopSound();ConfigSound();break;
|
|
case 326:ConfigVideo();break;
|
|
case 328:MapInput();break;
|
|
|
|
case 200:RestartMovieOrReset(0);break;
|
|
case 201:RestartMovieOrReset(1);break;
|
|
case 40026: FCEUI_FDSSelect();break;
|
|
case 40001: FCEUI_FDSInsert();break;
|
|
case 40027: FCEUI_VSUniCoin();break;
|
|
|
|
|
|
#ifdef FCEUDEF_DEBUGGER
|
|
case 203:BeginDSeq(hWnd);break;
|
|
#endif
|
|
|
|
case 204:ConfigAddCheat(hWnd);break;
|
|
//mbg merge TODO 7/17/06 - had to remove this
|
|
//case 205:CreateMemWatch(hWnd);break;
|
|
case 100:StopSound();
|
|
LoadNewGamey(hWnd, 0);
|
|
break;
|
|
case 101:if(GI)
|
|
{
|
|
#ifdef FCEUDEF_DEBUGGER
|
|
KillDebugger();
|
|
#endif
|
|
FCEUI_CloseGame();
|
|
GI=0;
|
|
RedoMenuGI(GI);
|
|
}
|
|
break;
|
|
case 110:FCEUD_SaveStateAs();break;
|
|
case 111:FCEUD_LoadStateFrom();break;
|
|
|
|
case 120:
|
|
{
|
|
MENUITEMINFO mi;
|
|
char *str;
|
|
|
|
StopSound();
|
|
if(CreateSoundSave())
|
|
str="Stop Sound Logging";
|
|
else
|
|
str="Log Sound As...";
|
|
memset(&mi,0,sizeof(mi));
|
|
mi.fMask=MIIM_DATA|MIIM_TYPE;
|
|
mi.cbSize=sizeof(mi);
|
|
GetMenuItemInfo(fceumenu,120,0,&mi);
|
|
mi.fMask=MIIM_DATA|MIIM_TYPE;
|
|
mi.cbSize=sizeof(mi);
|
|
mi.dwTypeData=str;
|
|
mi.cch=strlen(str);
|
|
SetMenuItemInfo(fceumenu,120,0,&mi);
|
|
}
|
|
break;
|
|
case 130:DoFCEUExit();break;
|
|
|
|
case 141:FCEUD_MovieRecordTo();break;
|
|
case 142:FCEUD_MovieReplayFrom();break;
|
|
case 143:FCEUI_StopMovie();break;
|
|
|
|
case 151:FCEUD_AviRecordTo();break;
|
|
case 152:FCEUD_AviStop();break;
|
|
|
|
case 400:StopSound();ShowAboutBox();break;
|
|
case 401:MakeLogWindow();break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_SYSCOMMAND:
|
|
if(GI && wParam == SC_SCREENSAVE && (goptions & GOO_DISABLESS))
|
|
return(0);
|
|
|
|
if(wParam==SC_KEYMENU)
|
|
{
|
|
if(GI && InputType[2]==SIFC_FKB && cidisabled)
|
|
break;
|
|
if(lParam == VK_RETURN || fullscreen || tog) break;
|
|
}
|
|
goto proco;
|
|
case WM_SYSKEYDOWN:
|
|
if(GI && InputType[2]==SIFC_FKB && cidisabled)
|
|
break; /* Hopefully this won't break DInput... */
|
|
|
|
if(fullscreen || tog)
|
|
{
|
|
if(wParam==VK_MENU)
|
|
break;
|
|
}
|
|
if(wParam==VK_F10)
|
|
{
|
|
return 0;
|
|
/*
|
|
if(!moocow) FCEUD_PrintError("Iyee");
|
|
if(!(lParam&0x40000000))
|
|
FCEUI_ResetNES();
|
|
break;
|
|
*/
|
|
}
|
|
|
|
if(wParam == VK_RETURN)
|
|
{
|
|
if(!(lParam&(1<<30)))
|
|
{
|
|
UpdateMenu();
|
|
changerecursive=1;
|
|
if(!SetVideoMode(fullscreen^1))
|
|
SetVideoMode(fullscreen);
|
|
changerecursive=0;
|
|
}
|
|
break;
|
|
}
|
|
goto proco;
|
|
|
|
case WM_KEYDOWN:
|
|
if(GI)
|
|
{
|
|
/* Only disable command keys if a game is loaded(and the other
|
|
conditions are right, of course). */
|
|
if(InputType[2]==SIFC_FKB)
|
|
{
|
|
if(wParam==VK_SCROLL)
|
|
{
|
|
cidisabled^=1;
|
|
FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis");
|
|
}
|
|
if(cidisabled)
|
|
break; /* Hopefully this won't break DInput... */
|
|
}
|
|
}
|
|
/*
|
|
if(!(lParam&0x40000000))
|
|
switch( wParam )
|
|
{
|
|
case VK_F11:FCEUI_PowerNES();break;
|
|
case VK_F12:DoFCEUExit();break;
|
|
//case VK_F2:userpause^=1;break;
|
|
case VK_F3:ToggleHideMenu();break;
|
|
}
|
|
*/
|
|
goto proco;
|
|
case WM_CLOSE:
|
|
case WM_DESTROY:
|
|
case WM_QUIT:DoFCEUExit();break;
|
|
case WM_ACTIVATEAPP:
|
|
if((BOOL)wParam)
|
|
{
|
|
nofocus=0;
|
|
}
|
|
else
|
|
{
|
|
nofocus=1;
|
|
}
|
|
goto proco;
|
|
case WM_ENTERMENULOOP:
|
|
EnableMenuItem(fceumenu,143,MF_BYCOMMAND | (FCEUI_IsMovieActive()?MF_ENABLED:MF_GRAYED));
|
|
EnableMenuItem(fceumenu,152,MF_BYCOMMAND | (FCEUI_AviIsRecording()?MF_ENABLED:MF_GRAYED));
|
|
default:
|
|
proco:
|
|
return DefWindowProc(hWnd,msg,wParam,lParam);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void FixWXY(int pref)
|
|
{
|
|
if(eoptions&EO_FORCEASPECT)
|
|
{
|
|
/* First, make sure the ratio is valid, and if it's not, change
|
|
it so that it doesn't break everything.
|
|
*/
|
|
if(saspectw < 0.01) saspectw = 0.01;
|
|
if(saspecth < 0.01) saspecth = 0.01;
|
|
if((saspectw / saspecth) > 100) saspecth = saspectw;
|
|
if((saspecth / saspectw) > 100) saspectw = saspecth;
|
|
|
|
if((saspectw / saspecth) < 0.1) saspecth = saspectw;
|
|
if((saspecth / saspectw) > 0.1) saspectw = saspecth;
|
|
|
|
if(!pref)
|
|
{
|
|
winsizemuly = winsizemulx * 256 / 240 * 3 / 4 * saspectw / saspecth;
|
|
}
|
|
else
|
|
{
|
|
winsizemulx = winsizemuly * 240 / 256 * 4 / 3 * saspecth / saspectw;
|
|
}
|
|
}
|
|
if(winspecial)
|
|
{
|
|
int mult;
|
|
if(winspecial == 1 || winspecial == 2) mult = 2;
|
|
else mult = 3;
|
|
if(winsizemulx < mult)
|
|
{
|
|
if(eoptions&EO_FORCEASPECT)
|
|
winsizemuly *= mult / winsizemulx;
|
|
winsizemulx = mult;
|
|
}
|
|
if(winsizemuly < mult)
|
|
{
|
|
if(eoptions&EO_FORCEASPECT)
|
|
winsizemulx *= mult / winsizemuly;
|
|
winsizemuly = mult;
|
|
}
|
|
}
|
|
|
|
if(winsizemulx<0.1)
|
|
winsizemulx=0.1;
|
|
if(winsizemuly<0.1)
|
|
winsizemuly=0.1;
|
|
|
|
if(eoptions & EO_FORCEISCALE)
|
|
{
|
|
int x,y;
|
|
|
|
x = winsizemulx * 2;
|
|
y = winsizemuly * 2;
|
|
|
|
x = (x>>1) + (x&1);
|
|
y = (y>>1) + (y&1);
|
|
|
|
if(!x) x=1;
|
|
if(!y) y=1;
|
|
|
|
winsizemulx = x;
|
|
winsizemuly = y;
|
|
}
|
|
|
|
if(winsizemulx > 100) winsizemulx = 100;
|
|
if(winsizemuly > 100) winsizemuly = 100;
|
|
}
|
|
|
|
void UpdateFCEUWindow(void)
|
|
{
|
|
//int w,h; //mbg merge 7/17/06 removed
|
|
// RECT wrect; //mbg merge 7/17/06 removed
|
|
|
|
if(vchanged && !fullscreen && !changerecursive && !nofocus)
|
|
{
|
|
SetVideoMode(0);
|
|
vchanged=0;
|
|
}
|
|
|
|
BlockingCheck();
|
|
#ifdef FCEUDEF_DEBUGGER
|
|
UpdateDebugger();
|
|
#endif
|
|
|
|
if(!(eoptions&EO_BGRUN))
|
|
while(nofocus)
|
|
{
|
|
StopSound();
|
|
Sleep(75);
|
|
BlockingCheck();
|
|
}
|
|
if(userpause)
|
|
{
|
|
StopSound();
|
|
while(userpause)
|
|
{
|
|
Sleep(50);
|
|
BlockingCheck();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ByebyeWindow(void)
|
|
{
|
|
SetMenu(hAppWnd,0);
|
|
DestroyMenu(fceumenu);
|
|
DestroyWindow(hAppWnd);
|
|
}
|
|
|
|
int CreateMainWindow(void)
|
|
{
|
|
WNDCLASSEX winclass;
|
|
RECT tmp;
|
|
|
|
memset(&winclass,0,sizeof(winclass));
|
|
winclass.cbSize=sizeof(WNDCLASSEX);
|
|
winclass.style=CS_OWNDC|CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS;
|
|
winclass.lpfnWndProc=AppWndProc;
|
|
winclass.cbClsExtra=0;
|
|
winclass.cbWndExtra=0;
|
|
winclass.hInstance=fceu_hInstance;
|
|
winclass.hIcon=LoadIcon(fceu_hInstance, "ICON_1");
|
|
winclass.hIconSm=LoadIcon(fceu_hInstance, "ICON_1");
|
|
winclass.hCursor=LoadCursor(NULL, IDC_ARROW);
|
|
winclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); //mbg merge 7/17/06 added cast
|
|
//winclass.lpszMenuName="FCEUMENU";
|
|
winclass.lpszClassName="FCEULTRA";
|
|
|
|
if(!RegisterClassEx(&winclass))
|
|
return FALSE;
|
|
|
|
AdjustWindowRectEx(&tmp,WS_OVERLAPPEDWINDOW,1,0);
|
|
|
|
fceumenu=LoadMenu(fceu_hInstance,"FCEUMENU");
|
|
|
|
recentmenu=CreateMenu();
|
|
recentdmenu = CreateMenu();
|
|
|
|
UpdateRMenu(recentmenu, rfiles, 102, 600);
|
|
UpdateRMenu(recentdmenu, rdirs, 103, 700);
|
|
|
|
RedoMenuGI(NULL);
|
|
|
|
hAppWnd = CreateWindowEx(0,"FCEULTRA","FCE Ultra",
|
|
WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS, /* Style */
|
|
CW_USEDEFAULT,CW_USEDEFAULT,256,240, /* X,Y ; Width, Height */
|
|
NULL,fceumenu,fceu_hInstance,NULL );
|
|
DragAcceptFiles(hAppWnd, 1);
|
|
SetMainWindowStuff();
|
|
return 1;
|
|
}
|
|
|
|
|
|
int SetMainWindowStuff(void)
|
|
{
|
|
RECT tmp;
|
|
|
|
GetWindowRect(hAppWnd,&tmp);
|
|
|
|
if(ismaximized)
|
|
{
|
|
winwidth=tmp.right - tmp.left;
|
|
winheight=tmp.bottom - tmp.top;
|
|
|
|
ShowWindow(hAppWnd, SW_SHOWMAXIMIZED);
|
|
}
|
|
else
|
|
{
|
|
RECT srect;
|
|
if(WindowXC!=(1<<30))
|
|
{
|
|
/* Subtracting and adding for if(eoptions&EO_USERFORCE) below. */
|
|
tmp.bottom-=tmp.top;
|
|
tmp.bottom+=WindowYC;
|
|
|
|
tmp.right-=tmp.left;
|
|
tmp.right+=WindowXC;
|
|
|
|
|
|
tmp.left=WindowXC;
|
|
tmp.top=WindowYC;
|
|
WindowXC=1<<30;
|
|
}
|
|
|
|
CalcWindowSize(&srect);
|
|
SetWindowPos(hAppWnd,HWND_TOP,tmp.left,tmp.top,srect.right,srect.bottom,SWP_SHOWWINDOW);
|
|
winwidth=srect.right;
|
|
winheight=srect.bottom;
|
|
|
|
ShowWindow(hAppWnd, SW_SHOWNORMAL);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int GetClientAbsRect(LPRECT lpRect)
|
|
{
|
|
POINT point;
|
|
point.x=point.y=0;
|
|
if(!ClientToScreen(hAppWnd,&point)) return 0;
|
|
|
|
lpRect->top=point.y;
|
|
lpRect->left=point.x;
|
|
|
|
if(ismaximized)
|
|
{
|
|
RECT al;
|
|
GetClientRect(hAppWnd, &al);
|
|
lpRect->right = point.x + al.right;
|
|
lpRect->bottom = point.y + al.bottom;
|
|
}
|
|
else
|
|
{
|
|
lpRect->right=point.x+VNSWID*winsizemulx;
|
|
lpRect->bottom=point.y+totallines*winsizemuly;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
int LoadPaletteFile(void)
|
|
{
|
|
FILE *fp;
|
|
const char filter[]="All usable files(*.pal)\0*.pal\0All files (*.*)\0*.*\0";
|
|
char nameo[2048];
|
|
OPENFILENAME ofn;
|
|
memset(&ofn,0,sizeof(ofn));
|
|
ofn.lStructSize=sizeof(ofn);
|
|
ofn.hInstance=fceu_hInstance;
|
|
ofn.lpstrTitle="FCE Ultra Open Palette File...";
|
|
ofn.lpstrFilter=filter;
|
|
nameo[0]=0;
|
|
ofn.lpstrFile=nameo;
|
|
ofn.nMaxFile=256;
|
|
ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
|
|
ofn.lpstrInitialDir=0;
|
|
if(GetOpenFileName(&ofn))
|
|
{
|
|
if((fp=FCEUD_UTF8fopen(nameo,"rb")))
|
|
{
|
|
fread(cpalette,1,192,fp);
|
|
fclose(fp);
|
|
FCEUI_SetPaletteArray(cpalette);
|
|
eoptions|=EO_CPALETTE;
|
|
return(1);
|
|
}
|
|
else
|
|
FCEUD_PrintError("Error opening palette file!");
|
|
}
|
|
return(0);
|
|
}
|
|
static HWND pwindow;
|
|
static BOOL CALLBACK PaletteConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DSMFix(uMsg);
|
|
switch(uMsg) {
|
|
case WM_INITDIALOG:
|
|
if(ntsccol)
|
|
CheckDlgButton(hwndDlg,100,BST_CHECKED);
|
|
SendDlgItemMessage(hwndDlg,500,TBM_SETRANGE,1,MAKELONG(0,128));
|
|
SendDlgItemMessage(hwndDlg,501,TBM_SETRANGE,1,MAKELONG(0,128));
|
|
FCEUI_GetNTSCTH(&ntsctint,&ntschue);
|
|
SendDlgItemMessage(hwndDlg,500,TBM_SETPOS,1,ntsctint);
|
|
SendDlgItemMessage(hwndDlg,501,TBM_SETPOS,1,ntschue);
|
|
EnableWindow(GetDlgItem(hwndDlg,201),(eoptions&EO_CPALETTE)?1:0);
|
|
break;
|
|
case WM_HSCROLL:
|
|
ntsctint=SendDlgItemMessage(hwndDlg,500,TBM_GETPOS,0,(LPARAM)(LPSTR)0);
|
|
ntschue=SendDlgItemMessage(hwndDlg,501,TBM_GETPOS,0,(LPARAM)(LPSTR)0);
|
|
FCEUI_SetNTSCTH(ntsccol,ntsctint,ntschue);
|
|
break;
|
|
case WM_CLOSE:
|
|
case WM_QUIT: goto gornk;
|
|
case WM_COMMAND:
|
|
if(!(wParam>>16))
|
|
switch(wParam&0xFFFF)
|
|
{
|
|
case 100:ntsccol^=1;FCEUI_SetNTSCTH(ntsccol,ntsctint,ntschue);break;
|
|
case 200:
|
|
StopSound();
|
|
if(LoadPaletteFile())
|
|
EnableWindow(GetDlgItem(hwndDlg,201),1);
|
|
break;
|
|
case 201:FCEUI_SetPaletteArray(0);
|
|
eoptions&=~EO_CPALETTE;
|
|
EnableWindow(GetDlgItem(hwndDlg,201),0);
|
|
break;
|
|
case 1:
|
|
gornk:
|
|
DestroyWindow(hwndDlg);
|
|
pwindow=0; // Yay for user race conditions.
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void ConfigPalette(void)
|
|
{
|
|
if(!pwindow)
|
|
pwindow=CreateDialog(fceu_hInstance,"PALCONFIG",0,PaletteConCallB);
|
|
else
|
|
SetFocus(pwindow);
|
|
}
|
|
|
|
|
|
static BOOL CALLBACK TimingConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int x;
|
|
|
|
switch(uMsg) {
|
|
case WM_INITDIALOG:
|
|
if(eoptions&EO_HIGHPRIO)
|
|
CheckDlgButton(hwndDlg,105,BST_CHECKED);
|
|
if(eoptions&EO_NOTHROTTLE)
|
|
CheckDlgButton(hwndDlg,101,BST_CHECKED);
|
|
for(x=0;x<10;x++)
|
|
{
|
|
char buf[8];
|
|
sprintf(buf,"%d",x);
|
|
SendDlgItemMessage(hwndDlg,110,CB_ADDSTRING,0,(LPARAM)(LPSTR)buf);
|
|
SendDlgItemMessage(hwndDlg,111,CB_ADDSTRING,0,(LPARAM)(LPSTR)buf);
|
|
}
|
|
SendDlgItemMessage(hwndDlg,110,CB_SETCURSEL,maxconbskip,(LPARAM)(LPSTR)0);
|
|
SendDlgItemMessage(hwndDlg,111,CB_SETCURSEL,ffbskip,(LPARAM)(LPSTR)0);
|
|
break;
|
|
case WM_CLOSE:
|
|
case WM_QUIT: goto gornk;
|
|
case WM_COMMAND:
|
|
if(!(wParam>>16))
|
|
switch(wParam&0xFFFF)
|
|
{
|
|
case 1:
|
|
gornk:
|
|
if(IsDlgButtonChecked(hwndDlg,105)==BST_CHECKED)
|
|
eoptions|=EO_HIGHPRIO;
|
|
else
|
|
eoptions&=~EO_HIGHPRIO;
|
|
|
|
if(IsDlgButtonChecked(hwndDlg,101)==BST_CHECKED)
|
|
eoptions|=EO_NOTHROTTLE;
|
|
else
|
|
eoptions&=~EO_NOTHROTTLE;
|
|
|
|
maxconbskip=SendDlgItemMessage(hwndDlg,110,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
|
|
ffbskip=SendDlgItemMessage(hwndDlg,111,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
|
|
EndDialog(hwndDlg,0);
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void DoTimingConfigFix(void)
|
|
{
|
|
DoPriority();
|
|
}
|
|
|
|
static void ConfigTiming(void)
|
|
{
|
|
DialogBox(fceu_hInstance,"TIMINGCONFIG",hAppWnd,TimingConCallB);
|
|
DoTimingConfigFix();
|
|
}
|
|
|
|
static BOOL CALLBACK GUIConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(uMsg) {
|
|
case WM_INITDIALOG:
|
|
if(eoptions&EO_FOAFTERSTART)
|
|
CheckDlgButton(hwndDlg,102,BST_CHECKED);
|
|
if(eoptions&EO_HIDEMENU)
|
|
CheckDlgButton(hwndDlg,104,BST_CHECKED);
|
|
if(goptions & GOO_CONFIRMEXIT)
|
|
CheckDlgButton(hwndDlg,110,BST_CHECKED);
|
|
if(goptions & GOO_DISABLESS)
|
|
CheckDlgButton(hwndDlg,111,BST_CHECKED);
|
|
break;
|
|
case WM_CLOSE:
|
|
case WM_QUIT: goto gornk;
|
|
case WM_COMMAND:
|
|
if(!(wParam>>16))
|
|
switch(wParam&0xFFFF)
|
|
{
|
|
case 1:
|
|
gornk:
|
|
if(IsDlgButtonChecked(hwndDlg,102)==BST_CHECKED)
|
|
eoptions|=EO_FOAFTERSTART;
|
|
else
|
|
eoptions&=~EO_FOAFTERSTART;
|
|
if(IsDlgButtonChecked(hwndDlg,104)==BST_CHECKED)
|
|
eoptions|=EO_HIDEMENU;
|
|
else
|
|
eoptions&=~EO_HIDEMENU;
|
|
|
|
goptions &= ~(GOO_CONFIRMEXIT | GOO_DISABLESS);
|
|
|
|
if(IsDlgButtonChecked(hwndDlg,110)==BST_CHECKED)
|
|
goptions |= GOO_CONFIRMEXIT;
|
|
if(IsDlgButtonChecked(hwndDlg,111)==BST_CHECKED)
|
|
goptions |= GOO_DISABLESS;
|
|
EndDialog(hwndDlg,0);
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void ConfigGUI(void)
|
|
{
|
|
DialogBox(fceu_hInstance,"GUICONFIG",hAppWnd,GUIConCallB);
|
|
}
|
|
|
|
|
|
static int BrowseForFolder(HWND hParent, char *htext, char *buf)
|
|
{
|
|
BROWSEINFO bi;
|
|
LPCITEMIDLIST pidl;
|
|
int ret=1;
|
|
|
|
buf[0]=0;
|
|
|
|
memset(&bi,0,sizeof(bi));
|
|
|
|
bi.hwndOwner=hParent;
|
|
bi.lpszTitle=htext;
|
|
bi.ulFlags=BIF_RETURNONLYFSDIRS;
|
|
|
|
if(FAILED(CoInitialize(0)))
|
|
return(0);
|
|
|
|
if(!(pidl=SHBrowseForFolder(&bi)))
|
|
{
|
|
ret=0;
|
|
goto end1;
|
|
}
|
|
|
|
if(!SHGetPathFromIDList(pidl,buf))
|
|
{
|
|
ret=0;
|
|
goto end2;
|
|
}
|
|
|
|
end2:
|
|
/* This probably isn't the best way to free the memory... */
|
|
CoTaskMemFree((PVOID)pidl);
|
|
|
|
end1:
|
|
CoUninitialize();
|
|
return(ret);
|
|
}
|
|
|
|
static BOOL CALLBACK DirConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int x;
|
|
|
|
switch(uMsg){
|
|
case WM_INITDIALOG:
|
|
for(x=0;x<6;x++)
|
|
SetDlgItemText(hwndDlg,100+x,DOvers[x]);
|
|
if(eoptions&EO_SNAPNAME)
|
|
CheckDlgButton(hwndDlg,300,BST_CHECKED);
|
|
break;
|
|
case WM_CLOSE:
|
|
case WM_QUIT: goto gornk;
|
|
case WM_COMMAND:
|
|
if(!(wParam>>16))
|
|
{
|
|
if((wParam&0xFFFF)>=200 && (wParam&0xFFFF)<=205)
|
|
{
|
|
static char *helpert[6]={"Cheats","Miscellaneous","Nonvolatile Game Data","Save States","Screen Snapshots","Base Directory"};
|
|
char name[MAX_PATH];
|
|
|
|
if(BrowseForFolder(hwndDlg,helpert[((wParam&0xFFFF)-200)],name))
|
|
SetDlgItemText(hwndDlg,100+((wParam&0xFFFF)-200),name);
|
|
}
|
|
else switch(wParam&0xFFFF)
|
|
{
|
|
case 1:
|
|
gornk:
|
|
|
|
if(IsDlgButtonChecked(hwndDlg,300)==BST_CHECKED)
|
|
eoptions|=EO_SNAPNAME;
|
|
else
|
|
eoptions&=~EO_SNAPNAME;
|
|
|
|
RemoveDirs(); // Remove empty directories.
|
|
|
|
for(x=0;x<6;x++)
|
|
{
|
|
LONG len;
|
|
len=SendDlgItemMessage(hwndDlg,100+x,WM_GETTEXTLENGTH,0,0);
|
|
if(len<=0)
|
|
{
|
|
if(DOvers[x]) free(DOvers[x]);
|
|
DOvers[x]=0;
|
|
continue;
|
|
}
|
|
len++; // Add 1 for null character.
|
|
if(!(DOvers[x]=(char*)malloc(len))) //mbg merge 7/17/06 added cast
|
|
continue;
|
|
if(!GetDlgItemText(hwndDlg,100+x,DOvers[x],len))
|
|
{
|
|
free(DOvers[x]);
|
|
DOvers[x]=0;
|
|
continue;
|
|
}
|
|
|
|
}
|
|
|
|
CreateDirs(); // Create needed directories.
|
|
SetDirs(); // Set the directories in the core.
|
|
EndDialog(hwndDlg,0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void ConfigDirectories(void)
|
|
{
|
|
DialogBox(fceu_hInstance,"DIRCONFIG",hAppWnd,DirConCallB);
|
|
}
|
|
|
|
static int ReplayDialogReadOnlyStatus = 0;
|
|
static int ReplayDialogStopFrame = 0;
|
|
|
|
static char* GetReplayPath(HWND hwndDlg)
|
|
{
|
|
char* fn=0;
|
|
char szChoice[MAX_PATH];
|
|
LONG lIndex = SendDlgItemMessage(hwndDlg, 200, CB_GETCURSEL, 0, 0);
|
|
LONG lCount = SendDlgItemMessage(hwndDlg, 200, CB_GETCOUNT, 0, 0);
|
|
|
|
// NOTE: lCount-1 is the "Browse..." list item
|
|
if(lIndex != CB_ERR && lIndex != lCount-1)
|
|
{
|
|
LONG lStringLength = SendDlgItemMessage(hwndDlg, 200, CB_GETLBTEXTLEN, (WPARAM)lIndex, 0);
|
|
if(lStringLength < MAX_PATH)
|
|
{
|
|
char szDrive[MAX_PATH]={0};
|
|
char szDirectory[MAX_PATH]={0};
|
|
char szFilename[MAX_PATH]={0};
|
|
char szExt[MAX_PATH]={0};
|
|
char szTemp[MAX_PATH]={0};
|
|
|
|
SendDlgItemMessage(hwndDlg, 200, CB_GETLBTEXT, (WPARAM)lIndex, (LPARAM)szTemp);
|
|
if(szTemp[0] && szTemp[1]!=':')
|
|
sprintf(szChoice, ".\\%s", szTemp);
|
|
else
|
|
strcpy(szChoice, szTemp);
|
|
|
|
SetCurrentDirectory(BaseDirectory);
|
|
|
|
_splitpath(szChoice, szDrive, szDirectory, szFilename, szExt);
|
|
if(szDrive[0]=='\0' && szDirectory[0]=='\0')
|
|
fn=FCEU_MakePath(FCEUMKF_MOVIE, szChoice); // need to make a full path
|
|
else
|
|
fn=strdup(szChoice); // given a full path
|
|
}
|
|
}
|
|
|
|
return fn;
|
|
}
|
|
|
|
static char* GetRecordPath(HWND hwndDlg)
|
|
{
|
|
char* fn=0;
|
|
char szChoice[MAX_PATH];
|
|
char szDrive[MAX_PATH]={0};
|
|
char szDirectory[MAX_PATH]={0};
|
|
char szFilename[MAX_PATH]={0};
|
|
char szExt[MAX_PATH]={0};
|
|
|
|
GetDlgItemText(hwndDlg, 200, szChoice, sizeof(szChoice));
|
|
|
|
_splitpath(szChoice, szDrive, szDirectory, szFilename, szExt);
|
|
if(szDrive[0]=='\0' && szDirectory[0]=='\0')
|
|
fn=FCEU_MakePath(FCEUMKF_MOVIE, szChoice); // need to make a full path
|
|
else
|
|
fn=strdup(szChoice); // given a full path
|
|
|
|
return fn;
|
|
}
|
|
|
|
static char* GetSavePath(HWND hwndDlg)
|
|
{
|
|
char* fn=0;
|
|
char szDrive[MAX_PATH]={0};
|
|
char szDirectory[MAX_PATH]={0};
|
|
char szFilename[MAX_PATH]={0};
|
|
char szExt[MAX_PATH]={0};
|
|
LONG lIndex = SendDlgItemMessage(hwndDlg, 301, CB_GETCURSEL, 0, 0);
|
|
LONG lStringLength = SendDlgItemMessage(hwndDlg, 301, CB_GETLBTEXTLEN, (WPARAM)lIndex, 0);
|
|
|
|
fn = (char*)malloc(lStringLength);
|
|
SendDlgItemMessage(hwndDlg, 301, CB_GETLBTEXT, (WPARAM)lIndex, (LPARAM)fn);
|
|
|
|
_splitpath(fn, szDrive, szDirectory, szFilename, szExt);
|
|
if(szDrive[0]=='\0' && szDirectory[0]=='\0')
|
|
{
|
|
char* newfn=FCEU_MakePath(FCEUMKF_MOVIE, fn); // need to make a full path
|
|
free(fn);
|
|
fn=newfn;
|
|
}
|
|
|
|
return fn;
|
|
}
|
|
|
|
|
|
// C:\fceu\movies\bla.fcm + C:\fceu\fceu\ -> C:\fceu\movies\bla.fcm
|
|
// movies\bla.fcm + fceu\ -> movies\bla.fcm
|
|
|
|
// C:\fceu\movies\bla.fcm + C:\fceu\ -> movies\bla.fcm
|
|
void AbsoluteToRelative(char *const dst, const char *const dir, const char *const root)
|
|
{
|
|
int i, igood=0;
|
|
|
|
for(i = 0 ; ; i++)
|
|
{
|
|
int a = tolower(dir[i]);
|
|
int b = tolower(root[i]);
|
|
if(a == '/' || a == '\0' || a == '.') a = '\\';
|
|
if(b == '/' || b == '\0' || b == '.') b = '\\';
|
|
|
|
if(a != b)
|
|
{
|
|
igood = 0;
|
|
break;
|
|
}
|
|
|
|
if(a == '\\')
|
|
igood = i+1;
|
|
|
|
if(!dir[i] || !root[i])
|
|
break;
|
|
}
|
|
|
|
// if(igood)
|
|
// sprintf(dst, ".\\%s", dir + igood);
|
|
// else
|
|
strcpy(dst, dir + igood);
|
|
}
|
|
|
|
extern int movieConvertOffset1, movieConvertOffset2,movieConvertOK;
|
|
static int movieHackType=3;
|
|
|
|
static void UpdateReplayDialog(HWND hwndDlg)
|
|
{
|
|
movieConvertOffset1=0, movieConvertOffset2=0,movieConvertOK=0;
|
|
|
|
int doClear=1;
|
|
char *fn=GetReplayPath(hwndDlg);
|
|
|
|
// remember the previous setting for the read-only checkbox
|
|
if(IsWindowEnabled(GetDlgItem(hwndDlg, 201)))
|
|
ReplayDialogReadOnlyStatus = (SendDlgItemMessage(hwndDlg, 201, BM_GETCHECK, 0, 0) == BST_CHECKED) ? 1 : 0;
|
|
|
|
if(fn)
|
|
{
|
|
MOVIE_INFO info;
|
|
char metadata[MOVIE_MAX_METADATA];
|
|
char rom_name[MAX_PATH];
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
info.metadata = metadata;
|
|
info.metadata_size = sizeof(metadata);
|
|
info.name_of_rom_used = rom_name;
|
|
info.name_of_rom_used_size = sizeof(rom_name);
|
|
|
|
if(FCEUI_MovieGetInfo(fn, &info))
|
|
{
|
|
#define MOVIE_FLAG_NOSYNCHACK (1<<4) // set in newer version, used for old movie compatibility
|
|
extern int resetDMCacc;
|
|
extern int justAutoConverted;
|
|
int noNoSyncHack=!(info.flags&MOVIE_FLAG_NOSYNCHACK) && resetDMCacc;
|
|
EnableWindow(GetDlgItem(hwndDlg,1000),justAutoConverted || noNoSyncHack);
|
|
EnableWindow(GetDlgItem(hwndDlg,1001),justAutoConverted || noNoSyncHack);
|
|
if(justAutoConverted)
|
|
{
|
|
// use values as nesmock offsets
|
|
if(movieHackType != 0)
|
|
{
|
|
movieHackType=0;
|
|
SendDlgItemMessage(hwndDlg, 1000, WM_SETTEXT, 0,(LPARAM)"2");
|
|
SendDlgItemMessage(hwndDlg, 1001, WM_SETTEXT, 0,(LPARAM)"0");
|
|
SendDlgItemMessage(hwndDlg, 2000, WM_SETTEXT, 0,(LPARAM)"Offset:");
|
|
SendDlgItemMessage(hwndDlg, 2001, WM_SETTEXT, 0,(LPARAM)"from");
|
|
}
|
|
}
|
|
else if(noNoSyncHack)
|
|
{
|
|
// use values as sound reset hack values
|
|
if(movieHackType != 1)
|
|
{
|
|
movieHackType=1;
|
|
// extern int32 DMCacc;
|
|
// extern int8 DMCBitCount;
|
|
// char str[256];
|
|
// sprintf(str, "%d", DMCacc);
|
|
// SendDlgItemMessage(hwndDlg, 1000, WM_SETTEXT, 0,(LPARAM)str);
|
|
// sprintf(str, "%d", DMCBitCount);
|
|
// SendDlgItemMessage(hwndDlg, 1001, WM_SETTEXT, 0,(LPARAM)str);
|
|
SendDlgItemMessage(hwndDlg, 1000, WM_SETTEXT, 0,(LPARAM)"8");
|
|
SendDlgItemMessage(hwndDlg, 1001, WM_SETTEXT, 0,(LPARAM)"0");
|
|
SendDlgItemMessage(hwndDlg, 2000, WM_SETTEXT, 0,(LPARAM)"Missing data: acc=");
|
|
SendDlgItemMessage(hwndDlg, 2001, WM_SETTEXT, 0,(LPARAM)"bc=");
|
|
}
|
|
}
|
|
else if(movieHackType != 2)
|
|
{
|
|
movieHackType=2;
|
|
SendDlgItemMessage(hwndDlg, 1000, WM_SETTEXT, 0,(LPARAM)"");
|
|
SendDlgItemMessage(hwndDlg, 1001, WM_SETTEXT, 0,(LPARAM)"");
|
|
SendDlgItemMessage(hwndDlg, 2000, WM_SETTEXT, 0,(LPARAM)"");
|
|
SendDlgItemMessage(hwndDlg, 2001, WM_SETTEXT, 0,(LPARAM)"");
|
|
}
|
|
|
|
/* { // select away to autoconverted movie... but actually we don't want to do that now that there's an offset setting in the dialog
|
|
extern char lastMovieInfoFilename [512];
|
|
char relative[MAX_PATH];
|
|
AbsoluteToRelative(relative, lastMovieInfoFilename, BaseDirectory);
|
|
|
|
LONG lOtherIndex = SendDlgItemMessage(hwndDlg, 200, CB_FINDSTRING, (WPARAM)-1, (LPARAM)relative);
|
|
if(lOtherIndex != CB_ERR)
|
|
{
|
|
// select already existing string
|
|
SendDlgItemMessage(hwndDlg, 200, CB_SETCURSEL, lOtherIndex, 0);
|
|
} else {
|
|
LONG lIndex = SendDlgItemMessage(hwndDlg, 200, CB_GETCURSEL, 0, 0);
|
|
SendDlgItemMessage(hwndDlg, 200, CB_INSERTSTRING, lIndex, (LPARAM)relative);
|
|
SendDlgItemMessage(hwndDlg, 200, CB_SETCURSEL, lIndex, 0);
|
|
}
|
|
|
|
// restore focus to the dialog
|
|
// SetFocus(GetDlgItem(hwndDlg, 200));
|
|
}*/
|
|
|
|
|
|
char tmp[256];
|
|
uint32 div;
|
|
|
|
sprintf(tmp, "%lu", info.num_frames);
|
|
SetWindowTextA(GetDlgItem(hwndDlg,301), tmp); // frames
|
|
SetDlgItemText(hwndDlg,1003,tmp);
|
|
|
|
div = (FCEUI_GetCurrentVidSystem(0,0)) ? 50 : 60; // PAL timing
|
|
info.num_frames += (div>>1); // round up
|
|
sprintf(tmp, "%02d:%02d:%02d", (info.num_frames/(div*60*60)), (info.num_frames/(div*60))%60, (info.num_frames/div) % 60);
|
|
SetWindowTextA(GetDlgItem(hwndDlg,300), tmp); // length
|
|
|
|
sprintf(tmp, "%lu", info.rerecord_count);
|
|
SetWindowTextA(GetDlgItem(hwndDlg,302), tmp); // rerecord
|
|
|
|
{
|
|
// convert utf8 metadata to windows widechar
|
|
WCHAR wszMeta[MOVIE_MAX_METADATA];
|
|
if(MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, metadata, -1, wszMeta, MOVIE_MAX_METADATA))
|
|
{
|
|
if(wszMeta[0])
|
|
SetWindowTextW(GetDlgItem(hwndDlg,303), wszMeta); // metadata
|
|
else
|
|
SetWindowTextW(GetDlgItem(hwndDlg,303), L"(this movie has no author info)"); // metadata
|
|
}
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg,201),(info.read_only)? FALSE : TRUE); // disable read-only checkbox if the file access is read-only
|
|
SendDlgItemMessage(hwndDlg,201,BM_SETCHECK,info.read_only ? BST_CHECKED : (ReplayDialogReadOnlyStatus ? BST_CHECKED : BST_UNCHECKED), 0);
|
|
|
|
SetWindowText(GetDlgItem(hwndDlg,306),(info.flags & MOVIE_FLAG_FROM_RESET) ? "Reset or Power-On" : "Savestate");
|
|
if(info.movie_version > 1)
|
|
{
|
|
char emuStr[128];
|
|
SetWindowText(GetDlgItem(hwndDlg,304),info.name_of_rom_used);
|
|
SetWindowText(GetDlgItem(hwndDlg,305),md5_asciistr(info.md5_of_rom_used));
|
|
if(info.emu_version_used > 64)
|
|
sprintf(emuStr, "FCEU %d.%02d.%02d%s", info.emu_version_used/10000, (info.emu_version_used/100)%100, (info.emu_version_used)%100, info.emu_version_used < 9813 ? " (blip)" : "");
|
|
else
|
|
{
|
|
if(info.emu_version_used == 1)
|
|
strcpy(emuStr, "Famtasia");
|
|
else if(info.emu_version_used == 2)
|
|
strcpy(emuStr, "Nintendulator");
|
|
else if(info.emu_version_used == 3)
|
|
strcpy(emuStr, "VirtuaNES");
|
|
else
|
|
{
|
|
strcpy(emuStr, "(unknown)");
|
|
char* dot = strrchr(fn,'.');
|
|
if(dot)
|
|
{
|
|
if(!stricmp(dot,".fmv"))
|
|
strcpy(emuStr, "Famtasia? (unknown version)");
|
|
else if(!stricmp(dot,".nmv"))
|
|
strcpy(emuStr, "Nintendulator? (unknown version)");
|
|
else if(!stricmp(dot,".vmv"))
|
|
strcpy(emuStr, "VirtuaNES? (unknown version)");
|
|
else if(!stricmp(dot,".fcm"))
|
|
strcpy(emuStr, "FCEU? (unknown version)");
|
|
}
|
|
}
|
|
}
|
|
SetWindowText(GetDlgItem(hwndDlg,307),emuStr);
|
|
}
|
|
else
|
|
{
|
|
SetWindowText(GetDlgItem(hwndDlg,304),"unknown");
|
|
SetWindowText(GetDlgItem(hwndDlg,305),"unknown");
|
|
SetWindowText(GetDlgItem(hwndDlg,307),"FCEU 0.98.10 (blip)");
|
|
}
|
|
|
|
SetWindowText(GetDlgItem(hwndDlg,308),md5_asciistr(FCEUGameInfo->MD5));
|
|
EnableWindow(GetDlgItem(hwndDlg,1),TRUE); // enable OK
|
|
|
|
doClear = 0;
|
|
}
|
|
|
|
free(fn);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwndDlg,1000),FALSE);
|
|
EnableWindow(GetDlgItem(hwndDlg,1001),FALSE);
|
|
}
|
|
|
|
if(doClear)
|
|
{
|
|
SetWindowText(GetDlgItem(hwndDlg,300),"");
|
|
SetWindowText(GetDlgItem(hwndDlg,301),"");
|
|
SetWindowText(GetDlgItem(hwndDlg,302),"");
|
|
SetWindowText(GetDlgItem(hwndDlg,303),"");
|
|
SetWindowText(GetDlgItem(hwndDlg,304),"");
|
|
SetWindowText(GetDlgItem(hwndDlg,305),"");
|
|
SetWindowText(GetDlgItem(hwndDlg,306),"Nothing (invalid movie)");
|
|
SetWindowText(GetDlgItem(hwndDlg,307),"");
|
|
SetWindowText(GetDlgItem(hwndDlg,308),md5_asciistr(FCEUGameInfo->MD5));
|
|
SetDlgItemText(hwndDlg,1003,"");
|
|
EnableWindow(GetDlgItem(hwndDlg,201),FALSE);
|
|
SendDlgItemMessage(hwndDlg,201,BM_SETCHECK,BST_UNCHECKED,0);
|
|
EnableWindow(GetDlgItem(hwndDlg,1),FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#define MAX(x,y) ((x)<(y)?(y):(x))
|
|
#define MIN(x,y) ((x)>(y)?(y):(x))
|
|
|
|
static BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
movieHackType=3;
|
|
SendDlgItemMessage(hwndDlg, 201, BM_SETCHECK, moviereadonly?BST_CHECKED:BST_UNCHECKED, 0);
|
|
SendDlgItemMessage(hwndDlg, 1002,BM_SETCHECK, BST_UNCHECKED, 0);
|
|
|
|
char* findGlob[2] = {FCEU_MakeFName(FCEUMKF_MOVIEGLOB, 0, 0),
|
|
FCEU_MakeFName(FCEUMKF_MOVIEGLOB2, 0, 0)};
|
|
|
|
extern int suppress_scan_chunks;
|
|
suppress_scan_chunks=1;
|
|
|
|
int i=0, j=0;
|
|
|
|
for(j=0;j<2;j++)
|
|
{
|
|
char* temp=0;
|
|
do {
|
|
temp=strchr(findGlob[j],'/');
|
|
if(temp)
|
|
*temp = '\\';
|
|
} while(temp);
|
|
|
|
// disabled because... apparently something is case sensitive??
|
|
// for(i=1;i<strlen(findGlob[j]);i++)
|
|
// findGlob[j][i] = tolower(findGlob[j][i]);
|
|
}
|
|
|
|
// FCEU_PrintError(findGlob[0]);
|
|
// FCEU_PrintError(findGlob[1]);
|
|
|
|
for(j=0;j<2;j++)
|
|
{
|
|
// if the two directories are the same, only look through one of them to avoid adding everything twice
|
|
if(j==1 && !strnicmp(findGlob[0],findGlob[1],MAX(strlen(findGlob[0]),strlen(findGlob[1]))-6))
|
|
continue;
|
|
|
|
char globBase[512];
|
|
strcpy(globBase,findGlob[j]);
|
|
globBase[strlen(globBase)-5]='\0';
|
|
|
|
extern char FileBase[];
|
|
//char szFindPath[512]; //mbg merge 7/17/06 removed
|
|
WIN32_FIND_DATA wfd;
|
|
HANDLE hFind;
|
|
|
|
memset(&wfd, 0, sizeof(wfd));
|
|
hFind = FindFirstFile(findGlob[j], &wfd);
|
|
if(hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
do
|
|
{
|
|
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
continue;
|
|
|
|
// filter out everything that's not *.fcm, *.fmv, *.vmv, or *.nmv
|
|
// (because FindFirstFile is too dumb to do that)
|
|
{
|
|
char* dot=strrchr(wfd.cFileName,'.');
|
|
if(!dot)
|
|
continue;
|
|
char ext [512];
|
|
strcpy(ext, dot+1);
|
|
int k, extlen=strlen(ext);
|
|
for(k=0;k<extlen;k++)
|
|
ext[k]=tolower(ext[k]);
|
|
if(strcmp(ext,"fcm") && strcmp(ext,"fmv") && strcmp(ext,"vmv") && strcmp(ext,"nmv"))
|
|
continue;
|
|
}
|
|
|
|
MOVIE_INFO info;
|
|
char metadata[MOVIE_MAX_METADATA];
|
|
char rom_name[MAX_PATH];
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
info.metadata = metadata;
|
|
info.metadata_size = sizeof(metadata);
|
|
info.name_of_rom_used = rom_name;
|
|
info.name_of_rom_used_size = sizeof(rom_name);
|
|
|
|
char filename [512];
|
|
sprintf(filename, "%s%s", globBase, wfd.cFileName);
|
|
|
|
char* dot = strrchr(filename, '.');
|
|
int fcm = (dot && tolower(dot[1]) == 'f' && tolower(dot[2]) == 'c' && tolower(dot[3]) == 'm');
|
|
|
|
if(fcm && !FCEUI_MovieGetInfo(filename, &info))
|
|
continue;
|
|
|
|
char md51 [256];
|
|
char md52 [256];
|
|
if(fcm) strcpy(md51, md5_asciistr(FCEUGameInfo->MD5));
|
|
if(fcm) strcpy(md52, md5_asciistr(info.md5_of_rom_used));
|
|
if(!fcm || strcmp(md51, md52))
|
|
{
|
|
if(fcm)
|
|
{
|
|
unsigned int k, count1=0, count2=0; //mbg merge 7/17/06 changed to uint
|
|
for(k=0;k<strlen(md51);k++) count1 += md51[k]-'0';
|
|
for(k=0;k<strlen(md52);k++) count2 += md52[k]-'0';
|
|
if(count1 && count2)
|
|
continue;
|
|
}
|
|
|
|
char* tlen1=strstr(wfd.cFileName, " (");
|
|
char* tlen2=strstr(FileBase, " (");
|
|
int tlen3=tlen1?(int)(tlen1-wfd.cFileName):strlen(wfd.cFileName);
|
|
int tlen4=tlen2?(int)(tlen2-FileBase):strlen(FileBase);
|
|
int len=MAX(0,MIN(tlen3,tlen4));
|
|
if(strnicmp(wfd.cFileName, FileBase, len))
|
|
{
|
|
char temp[512];
|
|
strcpy(temp,FileBase);
|
|
temp[len]='\0';
|
|
if(!strstr(wfd.cFileName, temp))
|
|
continue;
|
|
}
|
|
}
|
|
|
|
char relative[MAX_PATH];
|
|
AbsoluteToRelative(relative, filename, BaseDirectory);
|
|
SendDlgItemMessage(hwndDlg, 200, CB_INSERTSTRING, i++, (LPARAM)relative);
|
|
} while(FindNextFile(hFind, &wfd));
|
|
FindClose(hFind);
|
|
}
|
|
}
|
|
|
|
suppress_scan_chunks=0;
|
|
|
|
free(findGlob[0]);
|
|
free(findGlob[1]);
|
|
|
|
if(i>0)
|
|
SendDlgItemMessage(hwndDlg, 200, CB_SETCURSEL, i-1, 0);
|
|
SendDlgItemMessage(hwndDlg, 200, CB_INSERTSTRING, i++, (LPARAM)"Browse...");
|
|
|
|
UpdateReplayDialog(hwndDlg);
|
|
}
|
|
|
|
SetFocus(GetDlgItem(hwndDlg, 200));
|
|
return FALSE;
|
|
|
|
case WM_COMMAND:
|
|
if(HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
UpdateReplayDialog(hwndDlg);
|
|
}
|
|
else if(HIWORD(wParam) == CBN_CLOSEUP)
|
|
{
|
|
LONG lCount = SendDlgItemMessage(hwndDlg, 200, CB_GETCOUNT, 0, 0);
|
|
LONG lIndex = SendDlgItemMessage(hwndDlg, 200, CB_GETCURSEL, 0, 0);
|
|
if (lIndex != CB_ERR && lIndex == lCount-1)
|
|
SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDOK, 0); // send an OK notification to open the file browser
|
|
}
|
|
else
|
|
{
|
|
int wID = LOWORD(wParam);
|
|
switch(wID)
|
|
{
|
|
case IDOK:
|
|
{
|
|
LONG lCount = SendDlgItemMessage(hwndDlg, 200, CB_GETCOUNT, 0, 0);
|
|
LONG lIndex = SendDlgItemMessage(hwndDlg, 200, CB_GETCURSEL, 0, 0);
|
|
if(lIndex != CB_ERR)
|
|
{
|
|
if(lIndex == lCount-1)
|
|
{
|
|
// pop open a file browser...
|
|
char *pn=FCEU_GetPath(FCEUMKF_MOVIE);
|
|
char szFile[MAX_PATH]={0};
|
|
OPENFILENAME ofn;
|
|
//int nRet; //mbg merge 7/17/06 removed
|
|
|
|
memset(&ofn, 0, sizeof(ofn));
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = hwndDlg;
|
|
ofn.lpstrFilter = "Supported Movie Files (*.fcm|*.fmv|*.nmv|*.vmv)\0*.fcm;*.fmv;*.nmv;*.vmv\0FCEU Movie Files (*.fcm)\0*.fcm\0Famtasia Movie Files (*.fmv)\0*.fmv\0Nintendulator Movie Files (*.nmv)\0*.nmv\0VirtuaNES Movie Files (*.vmv)\0*.vmv\0All files(*.*)\0*.*\0\0";
|
|
ofn.lpstrFile = szFile;
|
|
ofn.nMaxFile = sizeof(szFile);
|
|
ofn.lpstrInitialDir = pn;
|
|
ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
|
|
ofn.lpstrDefExt = "fcm";
|
|
ofn.lpstrTitle = "Replay Movie from File";
|
|
|
|
if(GetOpenFileName(&ofn))
|
|
{
|
|
char relative[MAX_PATH];
|
|
AbsoluteToRelative(relative, szFile, BaseDirectory);
|
|
|
|
LONG lOtherIndex = SendDlgItemMessage(hwndDlg, 200, CB_FINDSTRING, (WPARAM)-1, (LPARAM)relative);
|
|
if(lOtherIndex != CB_ERR)
|
|
{
|
|
// select already existing string
|
|
SendDlgItemMessage(hwndDlg, 200, CB_SETCURSEL, lOtherIndex, 0);
|
|
} else {
|
|
SendDlgItemMessage(hwndDlg, 200, CB_INSERTSTRING, lIndex, (LPARAM)relative);
|
|
SendDlgItemMessage(hwndDlg, 200, CB_SETCURSEL, lIndex, 0);
|
|
}
|
|
|
|
// restore focus to the dialog
|
|
SetFocus(GetDlgItem(hwndDlg, 200));
|
|
UpdateReplayDialog(hwndDlg);
|
|
// if (ofn.Flags & OFN_READONLY)
|
|
// SendDlgItemMessage(hwndDlg, 201, BM_SETCHECK, BST_CHECKED, 0);
|
|
// else
|
|
// SendDlgItemMessage(hwndDlg, 201, BM_SETCHECK, BST_UNCHECKED, 0);
|
|
}
|
|
|
|
free(pn);
|
|
}
|
|
else
|
|
{
|
|
// user had made their choice
|
|
// TODO: warn the user when they open a movie made with a different ROM
|
|
char* fn=GetReplayPath(hwndDlg);
|
|
//char TempArray[16]; //mbg merge 7/17/06 removed
|
|
ReplayDialogReadOnlyStatus = (SendDlgItemMessage(hwndDlg, 201, BM_GETCHECK, 0, 0) == BST_CHECKED) ? 1 : 0;
|
|
|
|
char offset1Str[32]={0};
|
|
char offset2Str[32]={0};
|
|
|
|
SendDlgItemMessage(hwndDlg, 1003, WM_GETTEXT, (WPARAM)32, (LPARAM)offset1Str);
|
|
ReplayDialogStopFrame = (SendDlgItemMessage(hwndDlg, 1002, BM_GETCHECK,0,0) == BST_CHECKED)? strtol(offset1Str,0,10):0;
|
|
|
|
SendDlgItemMessage(hwndDlg, 1000, WM_GETTEXT, (WPARAM)32, (LPARAM)offset1Str);
|
|
SendDlgItemMessage(hwndDlg, 1001, WM_GETTEXT, (WPARAM)32, (LPARAM)offset2Str);
|
|
|
|
movieConvertOffset1=strtol(offset1Str,0,10);
|
|
movieConvertOffset2=strtol(offset2Str,0,10);
|
|
movieConvertOK=1;
|
|
|
|
EndDialog(hwndDlg, (INT_PTR)fn);
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, 0);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
if((HWND)lParam == GetDlgItem(hwndDlg, 308))
|
|
{
|
|
// draw the md5 sum in red if it's different from the md5 of the rom used in the replay
|
|
HDC hdcStatic = (HDC)wParam;
|
|
char szMd5Text[35];
|
|
|
|
GetDlgItemText(hwndDlg, 305, szMd5Text, 35);
|
|
if(!strlen(szMd5Text) || !strcmp(szMd5Text, "unknown") || !strcmp(szMd5Text, "00000000000000000000000000000000") || !strcmp(szMd5Text, md5_asciistr(FCEUGameInfo->MD5)))
|
|
SetTextColor(hdcStatic, RGB(0,0,0)); // use black color for a match (or no comparison)
|
|
else
|
|
SetTextColor(hdcStatic, RGB(255,0,0)); // use red for a mismatch
|
|
SetBkMode(hdcStatic, TRANSPARENT);
|
|
return (LONG)GetStockObject(NULL_BRUSH);
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
};
|
|
|
|
void FCEUD_MovieReplayFrom(void)
|
|
{
|
|
char* fn;
|
|
|
|
StopSound();
|
|
|
|
fn=(char*)DialogBox(fceu_hInstance, "IDD_REPLAYINP", hAppWnd, ReplayDialogProc);
|
|
if(fn)
|
|
{
|
|
FCEUI_LoadMovie(fn, ReplayDialogReadOnlyStatus, ReplayDialogStopFrame);
|
|
free(fn);
|
|
palyo=FCEUI_GetCurrentVidSystem(0,0);
|
|
UpdateMenu();
|
|
FixFL();
|
|
SetMainWindowStuff();
|
|
RefreshThrottleFPS();
|
|
|
|
extern int movie_readonly;
|
|
moviereadonly = movie_readonly; // for prefs
|
|
}
|
|
}
|
|
|
|
static void UpdateRecordDialogPath(HWND hwndDlg, const char* fname)
|
|
{
|
|
char* baseMovieDir = FCEU_GetPath(FCEUMKF_MOVIE);
|
|
char* fn=0;
|
|
|
|
// display a shortened filename if the file exists in the base movie directory
|
|
if(!strncmp(fname, baseMovieDir, strlen(baseMovieDir)))
|
|
{
|
|
char szDrive[MAX_PATH]={0};
|
|
char szDirectory[MAX_PATH]={0};
|
|
char szFilename[MAX_PATH]={0};
|
|
char szExt[MAX_PATH]={0};
|
|
|
|
_splitpath(fname, szDrive, szDirectory, szFilename, szExt);
|
|
fn=(char*)malloc(strlen(szFilename)+strlen(szExt)+1);
|
|
_makepath(fn, "", "", szFilename, szExt);
|
|
}
|
|
else
|
|
fn=strdup(fname);
|
|
|
|
if(fn)
|
|
{
|
|
SetWindowText(GetDlgItem(hwndDlg,200),fn); // FIXME: make utf-8?
|
|
free(fn);
|
|
}
|
|
}
|
|
|
|
static void UpdateRecordDialog(HWND hwndDlg)
|
|
{
|
|
int enable=0;
|
|
char* fn=0;
|
|
|
|
fn=GetRecordPath(hwndDlg);
|
|
|
|
if(fn)
|
|
{
|
|
if(access(fn, F_OK) ||
|
|
!access(fn, W_OK))
|
|
{
|
|
LONG lCount = SendDlgItemMessage(hwndDlg, 301, CB_GETCOUNT, 0, 0);
|
|
LONG lIndex = SendDlgItemMessage(hwndDlg, 301, CB_GETCURSEL, 0, 0);
|
|
if(lIndex != lCount-1)
|
|
{
|
|
enable=1;
|
|
}
|
|
}
|
|
|
|
free(fn);
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg,1),enable ? TRUE : FALSE);
|
|
}
|
|
|
|
struct CreateMovieParameters
|
|
{
|
|
char* szFilename; // on Dialog creation, this is the default filename to display. On return, this is the filename that the user chose.
|
|
int recordFrom; // 0 = "Power-On", 1 = "Reset", 2 = "Now", 3+ = savestate file in szSavestateFilename
|
|
char* szSavestateFilename;
|
|
WCHAR metadata[MOVIE_MAX_METADATA];
|
|
};
|
|
|
|
static BOOL CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static struct CreateMovieParameters* p = NULL;
|
|
|
|
switch(uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
p = (struct CreateMovieParameters*)lParam;
|
|
UpdateRecordDialogPath(hwndDlg, p->szFilename);
|
|
free(p->szFilename);
|
|
|
|
/* Populate the "record from..." dialog */
|
|
{
|
|
char* findGlob=FCEU_MakeFName(FCEUMKF_STATEGLOB, 0, 0);
|
|
WIN32_FIND_DATA wfd;
|
|
HANDLE hFind;
|
|
int i=0;
|
|
|
|
SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, i++, (LPARAM)"Start");
|
|
SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, i++, (LPARAM)"Reset");
|
|
SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, i++, (LPARAM)"Now");
|
|
|
|
memset(&wfd, 0, sizeof(wfd));
|
|
hFind = FindFirstFile(findGlob, &wfd);
|
|
if(hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
do
|
|
{
|
|
if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
|
|
(wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
|
|
continue;
|
|
|
|
if (strlen(wfd.cFileName) < 4 ||
|
|
!strcmp(wfd.cFileName + (strlen(wfd.cFileName) - 4), ".fcm"))
|
|
continue;
|
|
|
|
SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, i++, (LPARAM)wfd.cFileName);
|
|
} while(FindNextFile(hFind, &wfd));
|
|
FindClose(hFind);
|
|
}
|
|
free(findGlob);
|
|
|
|
SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, i++, (LPARAM)"Browse...");
|
|
SendDlgItemMessage(hwndDlg, 301, CB_SETCURSEL, 0, 0); // choose "from reset" as a default
|
|
}
|
|
UpdateRecordDialog(hwndDlg);
|
|
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
if(HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
LONG lIndex = SendDlgItemMessage(hwndDlg, 301, CB_GETCURSEL, 0, 0);
|
|
if(lIndex == CB_ERR)
|
|
{
|
|
// fix listbox selection
|
|
SendDlgItemMessage(hwndDlg, 301, CB_SETCURSEL, (WPARAM)0, 0);
|
|
}
|
|
UpdateRecordDialog(hwndDlg);
|
|
return TRUE;
|
|
}
|
|
else if(HIWORD(wParam) == CBN_CLOSEUP)
|
|
{
|
|
LONG lCount = SendDlgItemMessage(hwndDlg, 301, CB_GETCOUNT, 0, 0);
|
|
LONG lIndex = SendDlgItemMessage(hwndDlg, 301, CB_GETCURSEL, 0, 0);
|
|
if (lIndex != CB_ERR && lIndex == lCount-1)
|
|
{
|
|
OPENFILENAME ofn;
|
|
char szChoice[MAX_PATH]={0};
|
|
|
|
// pop open a file browser to choose the savestate
|
|
memset(&ofn, 0, sizeof(ofn));
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = hwndDlg;
|
|
ofn.lpstrFilter = "FCE Ultra Save State(*.fc?)\0*.fc?\0\0";
|
|
ofn.lpstrFile = szChoice;
|
|
ofn.lpstrDefExt = "fcs";
|
|
ofn.nMaxFile = MAX_PATH;
|
|
if(GetOpenFileName(&ofn))
|
|
{
|
|
SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, lIndex, (LPARAM)szChoice);
|
|
SendDlgItemMessage(hwndDlg, 301, CB_SETCURSEL, (WPARAM)lIndex, 0);
|
|
}
|
|
else
|
|
UpdateRecordDialog(hwndDlg);
|
|
}
|
|
return TRUE;
|
|
}
|
|
else if(HIWORD(wParam) == EN_CHANGE && LOWORD(wParam) == 200)
|
|
{
|
|
UpdateRecordDialog(hwndDlg);
|
|
}
|
|
else
|
|
{
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
{
|
|
LONG lIndex = SendDlgItemMessage(hwndDlg, 301, CB_GETCURSEL, 0, 0);
|
|
p->szFilename = GetRecordPath(hwndDlg);
|
|
GetDlgItemTextW(hwndDlg,300,p->metadata,MOVIE_MAX_METADATA);
|
|
p->recordFrom = (int)lIndex;
|
|
if(lIndex>=3)
|
|
p->szSavestateFilename = GetSavePath(hwndDlg);
|
|
EndDialog(hwndDlg, 1);
|
|
}
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, 0);
|
|
return TRUE;
|
|
|
|
case 201:
|
|
{
|
|
OPENFILENAME ofn;
|
|
char szChoice[MAX_PATH]={0};
|
|
|
|
// browse button
|
|
memset(&ofn, 0, sizeof(ofn));
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = hwndDlg;
|
|
ofn.lpstrFilter = "FCE Ultra Movie File(*.fcm)\0*.fcm\0All files(*.*)\0*.*\0\0";
|
|
ofn.lpstrFile = szChoice;
|
|
ofn.lpstrDefExt = "fcm";
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
|
if(GetSaveFileName(&ofn))
|
|
UpdateRecordDialogPath(hwndDlg,szChoice);
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void FCEUD_MovieRecordTo(void)
|
|
{
|
|
struct CreateMovieParameters p;
|
|
p.szFilename=FCEUI_MovieGetCurrentName(0);
|
|
|
|
StopSound();
|
|
|
|
if(DialogBoxParam(fceu_hInstance,"IDD_RECORDINP",hAppWnd,RecordDialogProc,(LPARAM)&p))
|
|
{
|
|
// turn WCHAR into UTF8
|
|
char meta[MOVIE_MAX_METADATA<<2];
|
|
WideCharToMultiByte(CP_UTF8, 0, p.metadata, -1, meta, sizeof(meta), NULL, NULL);
|
|
|
|
if(p.recordFrom >= 3)
|
|
{
|
|
// attempt to load the savestate
|
|
// FIXME: pop open a messagebox if this fails
|
|
FCEUI_LoadState(p.szSavestateFilename);
|
|
{
|
|
extern int loadStateFailed;
|
|
if(loadStateFailed)
|
|
{
|
|
char str [1024];
|
|
sprintf(str, "Failed to load save state \"%s\".\nRecording from current state instead...", p.szSavestateFilename);
|
|
FCEUD_PrintError(str);
|
|
}
|
|
}
|
|
free(p.szSavestateFilename);
|
|
}
|
|
|
|
FCEUI_SaveMovie(p.szFilename, (p.recordFrom==0) ? MOVIE_FLAG_FROM_POWERON : ((p.recordFrom==1) ? MOVIE_FLAG_FROM_RESET : 0), meta);
|
|
}
|
|
|
|
free(p.szFilename);
|
|
}
|
|
|
|
void FCEUD_AviRecordTo(void)
|
|
{
|
|
OPENFILENAME ofn;
|
|
char szChoice[MAX_PATH];
|
|
|
|
if(FCEUMOV_IsPlaying())
|
|
{
|
|
extern char curMovieFilename[];
|
|
strcpy(szChoice, curMovieFilename);
|
|
char* dot=strrchr(szChoice,'.');
|
|
if(dot) *dot='\0';
|
|
strcat(szChoice,".avi");
|
|
}
|
|
else
|
|
{
|
|
extern char FileBase[];
|
|
sprintf(szChoice, "%s.avi", FileBase);
|
|
}
|
|
|
|
StopSound();
|
|
|
|
// avi record file browser
|
|
memset(&ofn, 0, sizeof(ofn));
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = hAppWnd;
|
|
ofn.lpstrFilter = "AVI Files (*.avi)\0*.avi\0\0";
|
|
ofn.lpstrFile = szChoice;
|
|
ofn.lpstrDefExt = "avi";
|
|
ofn.lpstrTitle = "Save AVI as";
|
|
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
|
if(GetSaveFileName(&ofn))
|
|
{
|
|
FCEUI_AviBegin(szChoice);
|
|
}
|
|
}
|
|
|
|
void FCEUD_AviStop(void)
|
|
{
|
|
FCEUI_AviEnd();
|
|
}
|
|
|
|
void FCEUD_CmdOpen(void)
|
|
{
|
|
StopSound();
|
|
LoadNewGamey(hAppWnd, 0);
|
|
}
|
|
|