diff --git a/src/driver.h b/src/driver.h index a5b6f881..662e01e3 100644 --- a/src/driver.h +++ b/src/driver.h @@ -178,6 +178,7 @@ void FCEUD_LuaRunFrom(void); int32 FCEUI_GetDesiredFPS(void); void FCEUI_SaveSnapshot(void); +void FCEUI_SaveSnapshotAs(void); void FCEU_DispMessage(char *format, int disppos, ...); #define FCEUI_DispMessage FCEU_DispMessage diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index 6139d010..3b8c971a 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -77,6 +77,7 @@ BEGIN MENUITEM "&Close All Script Windows", ID_FILE_CLOSELUAWINDOWS END MENUITEM "&Screenshot", ID_FILE_SCREENSHOT + MENUITEM "Save Screenshot As...", ID_FILE_SAVESCREENSHOTAS MENUITEM SEPARATOR MENUITEM "E&xit\tAlt+F4", MENU_EXIT END diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index fe78e9b0..04547b84 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -794,6 +794,7 @@ #define ID_SAVESTATE_RECOVERY 40408 #define ID_CONTEXT_FULLSAVESTATES 40409 #define ID_CHEATLISTPOPUP_DELETESELECTEDCHEATS 40410 +#define ID_FILE_SAVESCREENSHOTAS 40411 #define IDC_DEBUGGER_ICONTRAY 55535 #define MW_ValueLabel2 65423 #define MW_ValueLabel1 65426 @@ -803,7 +804,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 160 -#define _APS_NEXT_COMMAND_VALUE 40411 +#define _APS_NEXT_COMMAND_VALUE 40412 #define _APS_NEXT_CONTROL_VALUE 1259 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 49b07d20..0254c8cd 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -1642,6 +1642,9 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) case ID_FILE_SCREENSHOT: FCEUI_SaveSnapshot(); break; + case ID_FILE_SAVESCREENSHOTAS: + FCEUI_SaveSnapshotAs(); + break; //Lua submenu case ID_FILE_OPENLUAWINDOW: diff --git a/src/video.cpp b/src/video.cpp index 30a27a5c..46238f64 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -182,6 +182,10 @@ void FCEUI_SaveSnapshot(void) dosnapsave=1; } +void FCEUI_SaveSnapshotAs(void) +{ + dosnapsave=2; +} static void ReallySnap(void) @@ -198,13 +202,44 @@ void FCEU_PutImage(void) #ifdef SHOWFPS ShowFPS(); #endif + if(dosnapsave==2) + { +#ifdef WIN32 + const char filter[] = "Snapshot (*.png)\0*.png\0All Files (*.*)\0*.*\0\0"; + char nameo[512]; + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Save Snapshot As..."; + ofn.lpstrFilter = filter; + strcpy(nameo,FCEU_MakeFName(FCEUMKF_SNAP,0,"png").c_str()); + + nameo[strlen(nameo)-6] = '\0'; + + ofn.lpstrFile = nameo; + ofn.lpstrDefExt = "fcs"; + std::string initdir = FCEU_GetPath(FCEUMKF_SNAP); + ofn.lpstrInitialDir = initdir.c_str(); + ofn.nMaxFile = 256; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.lpstrDefExt = "png"; + dosnapsave=0; + if(GetSaveFileName(&ofn)) + { + SaveSnapshot(nameo); + FCEU_DispMessage("Snapshot Saved.",0); + } +#endif + dosnapsave=0; + } if(GameInfo->type==GIT_NSF) { DrawNSF(XBuf); //Save snapshot after NSF screen is drawn. Why would we want to do it before? - if(dosnapsave) + if(dosnapsave==1) { ReallySnap(); dosnapsave=0; @@ -229,7 +264,7 @@ void FCEU_PutImage(void) FCEUI_AviVideoUpdate(XBuf); //Save snapshot before overlay stuff is written. - if(dosnapsave) + if(dosnapsave==1) { ReallySnap(); dosnapsave=0; @@ -638,6 +673,98 @@ int SaveSnapshot(void) return u+1; +PNGerr: + if(compmem) + free(compmem); + if(pp) + fclose(pp); + return(0); +} +int SaveSnapshot(char fileName[512]) +{ + int totallines=FSettings.LastSLine-FSettings.FirstSLine+1; + int x,y; + FILE *pp=NULL; + uint8 *compmem=NULL; + uLongf compmemsize=totallines*263+12; + + if(!(compmem=(uint8 *)FCEU_malloc(compmemsize))) + return 0; + + pp = fopen(fileName, "w"); + + if(!(pp=FCEUD_UTF8fopen(fileName,"wb"))) + { + return 0; + } + + { + static uint8 header[8]={137,80,78,71,13,10,26,10}; + if(fwrite(header,8,1,pp)!=1) + goto PNGerr; + } + + { + uint8 chunko[13]; + + chunko[0]=chunko[1]=chunko[3]=0; + chunko[2]=0x1; // Width of 256 + + chunko[4]=chunko[5]=chunko[6]=0; + chunko[7]=totallines; // Height + + chunko[8]=8; // bit depth + chunko[9]=3; // Color type; indexed 8-bit + chunko[10]=0; // compression: deflate + chunko[11]=0; // Basic adapative filter set(though none are used). + chunko[12]=0; // No interlace. + + if(!WritePNGChunk(pp,13,"IHDR",chunko)) + goto PNGerr; + } + + { + uint8 pdata[256*3]; + for(x=0;x<256;x++) + FCEUD_GetPalette(x,pdata+x*3,pdata+x*3+1,pdata+x*3+2); + if(!WritePNGChunk(pp,256*3,"PLTE",pdata)) + goto PNGerr; + } + + { + uint8 *tmp=XBuf+FSettings.FirstSLine*256; + uint8 *dest,*mal,*mork; + + if(!(mal=mork=dest=(uint8 *)malloc((totallines<<8)+totallines))) + goto PNGerr; + // mork=dest=XBuf; + + for(y=0;y