From 04a15d9a2e4766caad28eb06c763a5d8f003c681 Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 19 Dec 2019 18:19:50 +0100 Subject: [PATCH] win32: only load screenshots in preview dialogs --- win32/CSaveLoadWithPreviewDlg.cpp | 167 +++++++++++++++--------------- win32/wsnes9x.cpp | 8 ++ win32/wsnes9x.h | 1 + 3 files changed, 91 insertions(+), 85 deletions(-) diff --git a/win32/CSaveLoadWithPreviewDlg.cpp b/win32/CSaveLoadWithPreviewDlg.cpp index e2f1f89c..fc4cb73b 100644 --- a/win32/CSaveLoadWithPreviewDlg.cpp +++ b/win32/CSaveLoadWithPreviewDlg.cpp @@ -71,88 +71,96 @@ bool CSaveLoadWithPreviewDlg::init_preview_bmps() void CSaveLoadWithPreviewDlg::load_slot_image_text(int slot, HWND hDlg) { - // load the snapshot to receive the saved screenshot - FreezeUnfreezeSlot(slot, FALSE); + uint16 *image_buffer; + int width, height; - // 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 = 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) + // load the saved screenshot from a snapshot + if(UnfreezeScreenshotSlot(slot, &image_buffer, width, height)) { + // 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); - return; - } - int row_bytes = IPPU.RenderedScreenWidth * 2 / 4 * 4; // DIBs always have 4-byte aligned rows - if(IPPU.RenderedScreenWidth * 2 % 4) - row_bytes += 4; + // set image to button + SendMessage(GetDlgItem(hDlg, IDC_BUTTON_SLOT_1 + slot), BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)previewHbmps[slot]); - // copy saved screenshot into temporary bitmap - uint16 *screen = GFX.Screen; - for(int h = 0; h < IPPU.RenderedScreenHeight; h++, screen += GFX.RealPPL) - { - uint16_t *row_start = (uint16_t*)(buffer + (h * row_bytes)); - for(int w = 0; w < IPPU.RenderedScreenWidth; w++) + char filename[_MAX_PATH + 1]; + GetSlotFilename(slot, filename); + Utf8ToWide filenameW(filename); + + // text with filename and last write time + 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 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 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) @@ -160,13 +168,6 @@ void CSaveLoadWithPreviewDlg::init_window(HWND hDlg) if(is_save_dialog) 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 y_pos = 0; 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 top = (mi.rcWork.bottom - mi.rcWork.top - dialog_height) / 2; 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) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 2424264c..6e01694f 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -3703,6 +3703,14 @@ void FreezeUnfreeze (const char *filename, bool8 freeze) 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) { FILE *fs = fopen (filename, "w+"); diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index 199ddd2e..d40b1ad0 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -463,5 +463,6 @@ void GetSlotFilename(int slot, char filename[_MAX_PATH + 1]); void FreezeUnfreezeSlot(int slot, bool8 freeze); void FreezeUnfreezeDialog(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)