mirror of https://github.com/snes9xgit/snes9x.git
win32: only load screenshots in preview dialogs
This commit is contained in:
parent
3c2ef2aa21
commit
04a15d9a2e
|
@ -71,88 +71,96 @@ bool CSaveLoadWithPreviewDlg::init_preview_bmps()
|
||||||
|
|
||||||
void CSaveLoadWithPreviewDlg::load_slot_image_text(int slot, HWND hDlg)
|
void CSaveLoadWithPreviewDlg::load_slot_image_text(int slot, HWND hDlg)
|
||||||
{
|
{
|
||||||
// load the snapshot to receive the saved screenshot
|
uint16 *image_buffer;
|
||||||
FreezeUnfreezeSlot(slot, FALSE);
|
int width, height;
|
||||||
|
|
||||||
// create temporary bitmap storage for screenshot, 16bit RGB
|
// load the saved screenshot from a snapshot
|
||||||
uint8_t* buffer = NULL;
|
if(UnfreezeScreenshotSlot(slot, &image_buffer, width, height))
|
||||||
BITMAPINFO *bm = (BITMAPINFO *)calloc(sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD), 1);
|
|
||||||
bm->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
||||||
bm->bmiHeader.biWidth = IPPU.RenderedScreenWidth;
|
|
||||||
bm->bmiHeader.biHeight = -IPPU.RenderedScreenHeight; // negative is top-down
|
|
||||||
bm->bmiHeader.biPlanes = 1;
|
|
||||||
bm->bmiHeader.biBitCount = 16;
|
|
||||||
bm->bmiHeader.biCompression = BI_BITFIELDS;
|
|
||||||
bm->bmiHeader.biSizeImage = IPPU.RenderedScreenWidth * IPPU.RenderedScreenHeight * 2;
|
|
||||||
*(unsigned long *)&bm->bmiColors[0] = FIRST_COLOR_MASK_RGB565;
|
|
||||||
*(unsigned long *)&bm->bmiColors[1] = SECOND_COLOR_MASK_RGB565;
|
|
||||||
*(unsigned long *)&bm->bmiColors[2] = THIRD_COLOR_MASK_RGB565;
|
|
||||||
HBITMAP imageBmp = CreateDIBSection(NULL, bm, DIB_RGB_COLORS, (void**)&buffer, 0, 0);
|
|
||||||
if(imageBmp == NULL)
|
|
||||||
{
|
{
|
||||||
|
// create temporary bitmap storage for screenshot, 16bit RGB
|
||||||
|
uint8_t* buffer = NULL;
|
||||||
|
BITMAPINFO *bm = (BITMAPINFO *)calloc(sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD), 1);
|
||||||
|
bm->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
bm->bmiHeader.biWidth = width;
|
||||||
|
bm->bmiHeader.biHeight = -height; // negative is top-down
|
||||||
|
bm->bmiHeader.biPlanes = 1;
|
||||||
|
bm->bmiHeader.biBitCount = 16;
|
||||||
|
bm->bmiHeader.biCompression = BI_BITFIELDS;
|
||||||
|
bm->bmiHeader.biSizeImage = width * height * 2;
|
||||||
|
*(unsigned long *)&bm->bmiColors[0] = FIRST_COLOR_MASK_RGB565;
|
||||||
|
*(unsigned long *)&bm->bmiColors[1] = SECOND_COLOR_MASK_RGB565;
|
||||||
|
*(unsigned long *)&bm->bmiColors[2] = THIRD_COLOR_MASK_RGB565;
|
||||||
|
HBITMAP imageBmp = CreateDIBSection(NULL, bm, DIB_RGB_COLORS, (void**)&buffer, 0, 0);
|
||||||
|
if(imageBmp == NULL)
|
||||||
|
{
|
||||||
|
free(bm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int row_bytes = width * 2 / 4 * 4; // DIBs always have 4-byte aligned rows
|
||||||
|
if(width * 2 % 4)
|
||||||
|
row_bytes += 4;
|
||||||
|
|
||||||
|
// copy saved screenshot into temporary bitmap
|
||||||
|
uint16 *screen = image_buffer;
|
||||||
|
for(int h = 0; h < height; h++, screen += width)
|
||||||
|
{
|
||||||
|
uint16_t *row_start = (uint16_t*)(buffer + (h * row_bytes));
|
||||||
|
for(int w = 0; w < width; w++)
|
||||||
|
{
|
||||||
|
row_start[w] = screen[w];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// strech temporary bitmap into HBIMAP for button
|
||||||
|
HDC cdc = CreateCompatibleDC(GetDC(NULL));
|
||||||
|
HGDIOBJ old = SelectObject(cdc, previewHbmps[slot]);
|
||||||
|
int ret = StretchDIBits(cdc, 0, 0, PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT, 0, 0, width, height, buffer, bm, DIB_RGB_COLORS, SRCCOPY);
|
||||||
|
SelectObject(cdc, old);
|
||||||
|
DeleteDC(cdc);
|
||||||
|
|
||||||
free(bm);
|
free(bm);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int row_bytes = IPPU.RenderedScreenWidth * 2 / 4 * 4; // DIBs always have 4-byte aligned rows
|
// set image to button
|
||||||
if(IPPU.RenderedScreenWidth * 2 % 4)
|
SendMessage(GetDlgItem(hDlg, IDC_BUTTON_SLOT_1 + slot), BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)previewHbmps[slot]);
|
||||||
row_bytes += 4;
|
|
||||||
|
|
||||||
// copy saved screenshot into temporary bitmap
|
char filename[_MAX_PATH + 1];
|
||||||
uint16 *screen = GFX.Screen;
|
GetSlotFilename(slot, filename);
|
||||||
for(int h = 0; h < IPPU.RenderedScreenHeight; h++, screen += GFX.RealPPL)
|
Utf8ToWide filenameW(filename);
|
||||||
{
|
|
||||||
uint16_t *row_start = (uint16_t*)(buffer + (h * row_bytes));
|
// text with filename and last write time
|
||||||
for(int w = 0; w < IPPU.RenderedScreenWidth; w++)
|
std::wstring static_text(PathFindFileName(filenameW));
|
||||||
|
|
||||||
|
// get file time details
|
||||||
|
HANDLE file_handle = CreateFile(filenameW, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if(file_handle != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
row_start[w] = screen[w];
|
FILETIME ft;
|
||||||
|
SYSTEMTIME stUTC, stLocal;
|
||||||
|
// transform from file time to local time
|
||||||
|
if(GetFileTime(file_handle, NULL, NULL, &ft) &&
|
||||||
|
FileTimeToSystemTime(&ft, &stUTC) &&
|
||||||
|
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal))
|
||||||
|
{
|
||||||
|
// reserve space for date and time (both received individually)
|
||||||
|
std::vector<wchar_t> date_string;
|
||||||
|
date_string.resize(max(
|
||||||
|
GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_AUTOLAYOUT | DATE_LONGDATE, &stLocal, NULL, NULL, 0, NULL),
|
||||||
|
GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &stLocal, NULL, NULL, 0)
|
||||||
|
));
|
||||||
|
|
||||||
|
GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_AUTOLAYOUT | DATE_LONGDATE, &stLocal, NULL, &date_string[0], 100, NULL);
|
||||||
|
static_text.append(L"\n").append(&date_string[0]);
|
||||||
|
GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &stLocal, NULL, &date_string[0], 100);
|
||||||
|
static_text.append(L" ").append(&date_string[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the description text
|
||||||
|
SetWindowText(GetDlgItem(hDlg, IDC_STATIC_SLOT_1 + slot), static_text.c_str());
|
||||||
|
|
||||||
|
free(image_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// strech temporary bitmap into HBIMAP for button
|
|
||||||
HDC cdc = CreateCompatibleDC(GetDC(NULL));
|
|
||||||
HGDIOBJ old = SelectObject(cdc, previewHbmps[slot]);
|
|
||||||
int ret = StretchDIBits(cdc, 0, 0, PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT, 0, 0, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, buffer, bm, DIB_RGB_COLORS, SRCCOPY);
|
|
||||||
SelectObject(cdc, old);
|
|
||||||
DeleteDC(cdc);
|
|
||||||
|
|
||||||
free(bm);
|
|
||||||
|
|
||||||
// set image to button
|
|
||||||
SendMessage(GetDlgItem(hDlg, IDC_BUTTON_SLOT_1 + slot), BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)previewHbmps[slot]);
|
|
||||||
|
|
||||||
// text with filename and last write time
|
|
||||||
std::wstring static_text(PathFindFileName((wchar_t*)_tFromChar(Memory.ROMFilename)));
|
|
||||||
|
|
||||||
// get file time details
|
|
||||||
char filename[_MAX_PATH + 1];
|
|
||||||
GetSlotFilename(slot, filename);
|
|
||||||
HANDLE file_handle = CreateFile(_tFromChar(filename), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if(file_handle != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
FILETIME ft;
|
|
||||||
SYSTEMTIME stUTC, stLocal;
|
|
||||||
// transform from file time to local time
|
|
||||||
if(GetFileTime(file_handle, NULL, NULL, &ft) &&
|
|
||||||
FileTimeToSystemTime(&ft, &stUTC) &&
|
|
||||||
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal))
|
|
||||||
{
|
|
||||||
// reserve space for date and time (both received individually)
|
|
||||||
std::vector<wchar_t> date_string;
|
|
||||||
date_string.resize(max(
|
|
||||||
GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_AUTOLAYOUT | DATE_LONGDATE, &stLocal, NULL, NULL, 0, NULL),
|
|
||||||
GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &stLocal, NULL, NULL, 0)
|
|
||||||
));
|
|
||||||
|
|
||||||
GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_AUTOLAYOUT | DATE_LONGDATE, &stLocal, NULL, &date_string[0], 100, NULL);
|
|
||||||
static_text.append(L"\n").append(&date_string[0]);
|
|
||||||
GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &stLocal, NULL, &date_string[0], 100);
|
|
||||||
static_text.append(L" ").append(&date_string[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the description text
|
|
||||||
SetWindowText(GetDlgItem(hDlg, IDC_STATIC_SLOT_1 + slot), static_text.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSaveLoadWithPreviewDlg::init_window(HWND hDlg)
|
void CSaveLoadWithPreviewDlg::init_window(HWND hDlg)
|
||||||
|
@ -160,13 +168,6 @@ void CSaveLoadWithPreviewDlg::init_window(HWND hDlg)
|
||||||
if(is_save_dialog)
|
if(is_save_dialog)
|
||||||
SetWindowText(hDlg, L"Save with preview");
|
SetWindowText(hDlg, L"Save with preview");
|
||||||
|
|
||||||
// we need to load snapshots to receive the preview images, so we save the current state,
|
|
||||||
// load the slots, then reload the backup
|
|
||||||
std::string backup_filename = S9xGetFilename(".preview_backup", SNAPSHOT_DIR);
|
|
||||||
|
|
||||||
// create backup
|
|
||||||
FreezeUnfreeze(backup_filename.c_str(), true);
|
|
||||||
|
|
||||||
int x_pos = 0;
|
int x_pos = 0;
|
||||||
int y_pos = 0;
|
int y_pos = 0;
|
||||||
for(int i = 0; i < NUM_DIALOG_SLOTS; i++)
|
for(int i = 0; i < NUM_DIALOG_SLOTS; i++)
|
||||||
|
@ -222,10 +223,6 @@ void CSaveLoadWithPreviewDlg::init_window(HWND hDlg)
|
||||||
int left = (mi.rcWork.right - mi.rcWork.left - dialog_width) / 2;
|
int left = (mi.rcWork.right - mi.rcWork.left - dialog_width) / 2;
|
||||||
int top = (mi.rcWork.bottom - mi.rcWork.top - dialog_height) / 2;
|
int top = (mi.rcWork.bottom - mi.rcWork.top - dialog_height) / 2;
|
||||||
SetWindowPos(hDlg, NULL, left, top, dialog_width, dialog_height, SWP_NOZORDER);
|
SetWindowPos(hDlg, NULL, left, top, dialog_width, dialog_height, SWP_NOZORDER);
|
||||||
|
|
||||||
// load backup, remove temporary state
|
|
||||||
FreezeUnfreeze(backup_filename.c_str(), false);
|
|
||||||
remove(backup_filename.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INT_PTR CALLBACK CSaveLoadWithPreviewDlg::DlgLoadWithPreview(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
INT_PTR CALLBACK CSaveLoadWithPreviewDlg::DlgLoadWithPreview(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
|
@ -3703,6 +3703,14 @@ void FreezeUnfreeze (const char *filename, bool8 freeze)
|
||||||
S9xClearPause (PAUSE_FREEZE_FILE);
|
S9xClearPause (PAUSE_FREEZE_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UnfreezeScreenshotSlot(int slot, uint16 **image_buffer, int &width, int &height)
|
||||||
|
{
|
||||||
|
char filename[_MAX_PATH + 1];
|
||||||
|
GetSlotFilename(slot, filename);
|
||||||
|
|
||||||
|
return S9xUnfreezeScreenshot(filename, image_buffer, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
void CheckDirectoryIsWritable (const char *filename)
|
void CheckDirectoryIsWritable (const char *filename)
|
||||||
{
|
{
|
||||||
FILE *fs = fopen (filename, "w+");
|
FILE *fs = fopen (filename, "w+");
|
||||||
|
|
|
@ -463,5 +463,6 @@ void GetSlotFilename(int slot, char filename[_MAX_PATH + 1]);
|
||||||
void FreezeUnfreezeSlot(int slot, bool8 freeze);
|
void FreezeUnfreezeSlot(int slot, bool8 freeze);
|
||||||
void FreezeUnfreezeDialog(bool8 freeze);
|
void FreezeUnfreezeDialog(bool8 freeze);
|
||||||
void FreezeUnfreeze(const char *filename, bool8 freeze);
|
void FreezeUnfreeze(const char *filename, bool8 freeze);
|
||||||
|
bool UnfreezeScreenshotSlot(int slot, uint16 **image_buffer, int &width, int &height);
|
||||||
|
|
||||||
#endif // !defined(SNES9X_H_INCLUDED)
|
#endif // !defined(SNES9X_H_INCLUDED)
|
||||||
|
|
Loading…
Reference in New Issue