summaryrefslogtreecommitdiffstats
path: root/docs/release/src/osd/winui/screenshot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'docs/release/src/osd/winui/screenshot.cpp')
-rw-r--r--docs/release/src/osd/winui/screenshot.cpp663
1 files changed, 663 insertions, 0 deletions
diff --git a/docs/release/src/osd/winui/screenshot.cpp b/docs/release/src/osd/winui/screenshot.cpp
new file mode 100644
index 00000000000..c85f712007b
--- /dev/null
+++ b/docs/release/src/osd/winui/screenshot.cpp
@@ -0,0 +1,663 @@
+// For licensing and usage information, read docs/winui_license.txt
+// MASTER
+//****************************************************************************
+
+/***************************************************************************
+
+ Screenshot.c
+
+ Win32 DIB handling.
+
+ Created 7/1/98 by Mike Haaland (mhaaland@hypertech.com)
+
+ 0.145u5
+ - Cleaned out unused code.
+ - If Software tab is chosen, software-specific pictures can be displayed.
+ - Background picture must be PNG, and can be chosen from anywhere, but
+ must be uncompressed (not in a zip file).
+
+***************************************************************************/
+
+// standard windows headers
+#include <windows.h>
+#include <windowsx.h>
+
+// MAME/MAMEUI headers
+#include "emu.h"
+#include "png.h"
+#include "unzip.h"
+#include "mui_opts.h"
+#include "mui_util.h"
+#include "winui.h"
+#include "drivenum.h"
+
+/***************************************************************************
+ Static global variables
+***************************************************************************/
+
+/* these refer to the single image currently loaded by the ScreenShot functions */
+static HGLOBAL m_hDIB = nullptr;
+static HPALETTE m_hPal = nullptr;
+static HANDLE m_hDDB = nullptr;
+
+/* PNG variables */
+
+static int copy_size = 0;
+static char* pixel_ptr = nullptr;
+static int row = 0;
+static int effWidth;
+static BOOL LoadDIB(const char *filename, HGLOBAL *phDIB, HPALETTE *pPal, int pic_type);
+
+/***************************************************************************
+ Functions
+***************************************************************************/
+
+BOOL ScreenShotLoaded(void)
+{
+ return m_hDDB != NULL;
+}
+
+static BOOL LoadSoftwareScreenShot(const game_driver *drv, LPCSTR lpSoftwareName, int nType)
+{
+ BOOL result;
+ char *s = (char*)alloca(strlen(drv->name) + 1 + strlen(lpSoftwareName) + 5);
+ sprintf(s, "%s", lpSoftwareName);
+ // oldest code --> sprintf(s, "%s/%s.png", drv->name, lpSoftwareName);
+ //sprintf(s, "%s:%s", drv->name, lpSoftwareName);
+ result = LoadDIB(s, &m_hDIB, &m_hPal, nType);
+ return result;
+}
+
+/* Allow us to pre-load the DIB once for future draws */
+BOOL LoadScreenShotEx(int nGame, LPCSTR lpSoftwareName, int nType)
+{
+ BOOL loaded = FALSE;
+
+ /* Delete the last ones */
+ FreeScreenShot();
+
+ /* Load the DIB */
+
+ if (lpSoftwareName)
+ {
+ int nParentIndex = -1;
+ loaded = LoadSoftwareScreenShot(&driver_list::driver(nGame), lpSoftwareName, nType);
+ if (!loaded && DriverIsClone(nGame) == TRUE)
+ {
+ nParentIndex = GetParentIndex(&driver_list::driver(nGame));
+ loaded = LoadSoftwareScreenShot(&driver_list::driver(nParentIndex), lpSoftwareName, nType);
+ }
+ }
+
+ if (!loaded)
+ loaded = LoadDIB(driver_list::driver(nGame).name, &m_hDIB, &m_hPal, nType);
+
+ /* If not loaded, see if there is a clone and try that */
+ if (!loaded)
+ {
+ int nParentIndex = GetParentIndex(&driver_list::driver(nGame));
+ if( nParentIndex >= 0)
+ {
+ loaded = LoadDIB(driver_list::driver(nParentIndex).name, &m_hDIB, &m_hPal, nType);
+ nParentIndex = GetParentIndex(&driver_list::driver(nParentIndex));
+ if (!loaded && nParentIndex >= 0)
+ loaded = LoadDIB(driver_list::driver(nParentIndex).name, &m_hDIB, &m_hPal, nType);
+ }
+ }
+
+ if (loaded)
+ {
+ HDC hdc = GetDC(GetMainWindow());
+ m_hDDB = DIBToDDB(hdc, m_hDIB, NULL);
+ ReleaseDC(GetMainWindow(),hdc);
+ }
+
+ return (loaded) ? TRUE : FALSE;
+}
+
+HANDLE GetScreenShotHandle()
+{
+ return m_hDDB;
+}
+
+int GetScreenShotWidth(void)
+{
+ return ((LPBITMAPINFO)m_hDIB)->bmiHeader.biWidth;
+}
+
+int GetScreenShotHeight(void)
+{
+ return ((LPBITMAPINFO)m_hDIB)->bmiHeader.biHeight;
+}
+
+/* Delete the HPALETTE and Free the HDIB memory */
+void FreeScreenShot(void)
+{
+ if (m_hDIB != NULL)
+ GlobalFree(m_hDIB);
+ m_hDIB = NULL;
+
+ if (m_hPal != NULL)
+ DeletePalette(m_hPal);
+ m_hPal = NULL;
+
+ if (m_hDDB != NULL)
+ DeleteObject(m_hDDB);
+ m_hDDB = NULL;
+
+ ///current_image_game = -1;
+ ///current_image_type = -1;
+}
+
+/***************************************************************************
+ PNG graphics handling functions
+***************************************************************************/
+
+BOOL AllocatePNG(png_info *p, HGLOBAL *phDIB, HPALETTE *pPal)
+{
+ int dibSize;
+ HGLOBAL hDIB;
+ BITMAPINFOHEADER bi;
+ LPBITMAPINFOHEADER lpbi;
+ LPBITMAPINFO bmInfo;
+ LPVOID lpDIBBits = 0;
+ int lineWidth = 0;
+ int nColors = 0;
+ RGBQUAD* pRgb;
+ copy_size = 0;
+ pixel_ptr = 0;
+ row = p->height - 1;
+ lineWidth = p->width;
+
+ if (p->color_type != 2 && p->num_palette <= 256)
+ nColors = p->num_palette;
+
+ bi.biSize = sizeof(BITMAPINFOHEADER);
+ bi.biWidth = p->width;
+ bi.biHeight = p->height;
+ bi.biPlanes = 1;
+ bi.biBitCount = (p->color_type == 3) ? 8 : 24; /* bit_depth; */
+
+ bi.biCompression = BI_RGB;
+ bi.biSizeImage = 0;
+ bi.biXPelsPerMeter = 0;
+ bi.biYPelsPerMeter = 0;
+ bi.biClrUsed = nColors;
+ bi.biClrImportant = nColors;
+
+ effWidth = (long)(((long)lineWidth*bi.biBitCount + 31) / 32) * 4;
+
+ dibSize = (effWidth * bi.biHeight);
+ hDIB = GlobalAlloc(GMEM_FIXED, bi.biSize + (nColors * sizeof(RGBQUAD)) + dibSize);
+
+ if (!hDIB)
+ return FALSE;
+
+ lpbi = (LPBITMAPINFOHEADER)hDIB;
+ memcpy(lpbi, &bi, sizeof(BITMAPINFOHEADER));
+ pRgb = (RGBQUAD*)((LPSTR)lpbi + bi.biSize);
+ lpDIBBits = (LPVOID)((LPSTR)lpbi + bi.biSize + (nColors * sizeof(RGBQUAD)));
+ if (nColors)
+ {
+ int i;
+ /* Convert a PNG palette (3 byte RGBTRIPLEs) to a new color table (4 byte RGBQUADs) */
+ for (i = 0; i < nColors; i++)
+ {
+ RGBQUAD rgb;
+
+ rgb.rgbRed = p->palette[i * 3 + 0];
+ rgb.rgbGreen = p->palette[i * 3 + 1];
+ rgb.rgbBlue = p->palette[i * 3 + 2];
+ rgb.rgbReserved = (BYTE)0;
+
+ pRgb[i] = rgb;
+ }
+ }
+
+ bmInfo = (LPBITMAPINFO)hDIB;
+
+ /* Create a halftone palette if colors > 256. */
+ if (0 == nColors || nColors > 256)
+ {
+ HDC hDC = CreateCompatibleDC(0); /* Desktop DC */
+ *pPal = CreateHalftonePalette(hDC);
+ DeleteDC(hDC);
+ }
+ else
+ {
+ UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
+ LOGPALETTE *pLP = (LOGPALETTE *)malloc(nSize);
+ int i;
+
+ pLP->palVersion = 0x300;
+ pLP->palNumEntries = nColors;
+
+ for (i = 0; i < nColors; i++)
+ {
+ pLP->palPalEntry[i].peRed = bmInfo->bmiColors[i].rgbRed;
+ pLP->palPalEntry[i].peGreen = bmInfo->bmiColors[i].rgbGreen;
+ pLP->palPalEntry[i].peBlue = bmInfo->bmiColors[i].rgbBlue;
+ pLP->palPalEntry[i].peFlags = 0;
+ }
+
+ *pPal = CreatePalette(pLP);
+
+ free (pLP);
+ }
+
+ copy_size = dibSize;
+ pixel_ptr = (char*)lpDIBBits;
+ *phDIB = hDIB;
+ return TRUE;
+}
+
+inline void store_pixels(UINT8 *buf, int len)
+{
+ if (pixel_ptr && copy_size)
+ {
+ memcpy(&pixel_ptr[row * effWidth], buf, len);
+ row--;
+ copy_size -= len;
+ }
+}
+
+
+/* Copied and modified from png.c
+ logerror doesn't work here... changed to printf */
+static int png_read_bitmap_gui(util::core_file &mfile, HGLOBAL *phDIB, HPALETTE *pPAL)
+{
+ png_info p;
+ UINT32 i;
+ int bytespp;
+
+ if (png_read_file(mfile, &p) != PNGERR_NONE)
+ return 0;
+
+ if (p.color_type != 3 && p.color_type != 2)
+ {
+ printf("PNG Unsupported color type %i (has to be 2 or 3)\n", p.color_type);
+ //png_free(&p);
+ //return 0; Leave in so ppl can see incompatibility
+ }
+
+ if (p.interlace_method != 0)
+ {
+ printf("PNG Interlace unsupported\n");
+ png_free(&p);
+ return 0;
+ }
+
+ /* Convert < 8 bit to 8 bit */
+ png_expand_buffer_8bit(&p);
+
+ if (!AllocatePNG(&p, phDIB, pPAL))
+ {
+ printf("PNG Unable to allocate memory to display screenshot\n");
+ png_free(&p);
+ return 0;
+ }
+
+ bytespp = (p.color_type == 2) ? 3 : 1;
+
+ for (i = 0; i < p.height; i++)
+ {
+ UINT8 *ptr = p.image + i * (p.width * bytespp);
+
+ if (p.color_type == 2) /*(p->bit_depth > 8) */
+ {
+ int j;
+ UINT8 bTmp;
+
+ for (j = 0; j < p.width; j++)
+ {
+ bTmp = ptr[0];
+ ptr[0] = ptr[2];
+ ptr[2] = bTmp;
+ ptr += 3;
+ }
+ }
+ store_pixels(p.image + i * (p.width * bytespp), p.width * bytespp);
+ }
+
+ png_free(&p);
+
+ return 1;
+}
+
+
+
+/***************************************************************************
+ File search functions
+***************************************************************************/
+
+static osd_file::error OpenBkgroundFile(const char *filename, util::core_file::ptr &file)
+{
+ osd_file::error filerr;
+
+ // clear out result
+ file = NULL;
+
+ // look for the raw file
+ std::string fname (filename);
+ filerr = util::core_file::open(fname.c_str(), OPEN_FLAG_READ, file);
+
+ return filerr;
+}
+
+static osd_file::error OpenRawDIBFile(const char *dir_name, const char *filename, util::core_file::ptr &file)
+{
+ osd_file::error filerr;
+
+ // clear out result
+ file = NULL;
+
+ // look for the raw file
+ std::string fname = std::string(dir_name) + PATH_SEPARATOR + std::string(filename);
+ filerr = util::core_file::open(fname.c_str(), OPEN_FLAG_READ, file);
+
+ return filerr;
+}
+
+static osd_file::error OpenZipDIBFile(const char *dir_name, const char *zip_name, const char *filename, util::core_file::ptr &file, void **buffer)
+{
+ osd_file::error filerr = osd_file::error::NOT_FOUND;
+ util::archive_file::error ziperr;
+ util::archive_file::ptr zip;
+
+ // clear out result
+ file = NULL;
+
+ // look into zip file
+ std::string fname = std::string(dir_name) + PATH_SEPARATOR + std::string(zip_name) + ".zip";
+ ziperr = util::archive_file::open_zip(fname, zip);
+
+ if (ziperr == util::archive_file::error::NONE)
+ {
+ int res = zip->search(filename, false);
+ if (res >= 0)
+ {
+ *buffer = malloc(zip->current_uncompressed_length());
+ ziperr = zip->decompress(*buffer, zip->current_uncompressed_length());
+ if (ziperr == util::archive_file::error::NONE)
+ {
+ filerr = util::core_file::open_ram(*buffer, zip->current_uncompressed_length(), OPEN_FLAG_READ, file);
+ }
+ }
+ zip.reset();
+ }
+ else
+ {
+ fname = std::string(dir_name) + PATH_SEPARATOR + std::string(zip_name) + ".7z";
+ ziperr = util::archive_file::open_7z(fname, zip);
+
+ if (ziperr == util::archive_file::error::NONE)
+ {
+ int res = zip->search(filename, false);
+ if (res >= 0)
+ {
+ *buffer = malloc(zip->current_uncompressed_length());
+ ziperr = zip->decompress(*buffer, zip->current_uncompressed_length());
+ if (ziperr == util::archive_file::error::NONE)
+ {
+ filerr = util::core_file::open_ram(*buffer, zip->current_uncompressed_length(), OPEN_FLAG_READ, file);
+ }
+ }
+ zip.reset();
+ }
+ }
+ return filerr;
+}
+
+// called from winui.c to display the background
+BOOL LoadDIBBG(HGLOBAL *phDIB, HPALETTE *pPal)
+{
+ osd_file::error filerr = osd_file::error::NOT_FOUND;
+ util::core_file::ptr file = NULL;
+ BOOL success = FALSE;
+ const char *dir_name;
+ if (pPal != NULL )
+ DeletePalette(pPal);
+
+ dir_name = GetBgDir();
+ filerr = OpenBkgroundFile(dir_name, file);
+ if (filerr == osd_file::error::NONE)
+ {
+ success = png_read_bitmap_gui(*file, phDIB, pPal);
+ file.reset();
+ }
+
+ return success;
+}
+
+// display a snap, cabinet, title, flyer, marquee, pcb, control panel
+static BOOL LoadDIB(const char *filename, HGLOBAL *phDIB, HPALETTE *pPal, int pic_type)
+{
+ osd_file::error filerr = osd_file::error::NOT_FOUND; // defined in osdcore.h
+ util::core_file::ptr file = NULL;
+ BOOL success = FALSE;
+ const char *dir_name;
+ const char *zip_name;
+ void *buffer = NULL;
+ std::string fname;
+ if (pPal != NULL )
+ DeletePalette(pPal);
+
+ char *system_name = 0;
+ char *file_name = 0;
+ char* dir_name1 = 0;
+ int i,j;
+ bool ok = FALSE; // TRUE indicates split success
+
+ switch (pic_type)
+ {
+ case TAB_SCREENSHOT:
+ dir_name = GetImgDir();
+ zip_name = "snap";
+ break;
+ case TAB_FLYER:
+ dir_name = GetFlyerDir();
+ zip_name = "flyers";
+ break;
+ case TAB_CABINET:
+ dir_name = GetCabinetDir();
+ zip_name = "cabinets";
+ break;
+ case TAB_MARQUEE:
+ dir_name = GetMarqueeDir();
+ zip_name = "marquees";
+ break;
+ case TAB_TITLE:
+ dir_name = GetTitlesDir();
+ zip_name = "titles";
+ break;
+ case TAB_CONTROL_PANEL:
+ dir_name = GetControlPanelDir();
+ zip_name = "cpanel";
+ break;
+ case TAB_PCB :
+ dir_name = GetPcbDir();
+ zip_name = "pcb";
+ break;
+ default :
+ // in case a non-image tab gets here, which can happen
+ return FALSE;
+ }
+
+ // allocate space
+ system_name = (char*)malloc(strlen(filename) + 1);
+ file_name = (char*)malloc(strlen(filename) + 1);
+
+ // if the filename contains a system, split them
+
+ // get system = find colon and truncate there
+ for (i = 0; filename[i] && !ok; i++)
+ {
+ if (filename[i] != ':')
+ system_name[i] = filename[i];
+ else
+ {
+ ok = TRUE;
+ system_name[i] = '\0';
+ }
+ }
+ system_name[i] = '\0'; // 'i' is one more here than above but needed if no colon
+
+ // now left-justify the filename
+ if (ok)
+ {
+ for (j = 0; filename[i]; j++,i++)
+ file_name[j] = filename[i];
+ file_name[j] = '\0';
+ }
+ else
+ // it wasn't a software title, copy over to get around const nonsense
+ {
+ for (i = 0; filename[i]; i++)
+ file_name[i] = filename[i];
+ file_name[i] = '\0';
+ }
+
+ // another const workaround
+ dir_name1 = (char*)malloc(strlen(dir_name) + 2);
+ for (i = 0; dir_name[i]; i++)
+ dir_name1[i] = dir_name[i];
+ dir_name1[i++] = ';';
+ dir_name1[i] = '\0';
+
+ // Support multiple paths
+ char* dir_one = strtok(dir_name1, ";");
+
+ while (dir_one && filerr != osd_file::error::NONE)
+ {
+ //Add handling for the displaying of all the different supported snapshot pattern types
+ //%g
+
+ // Do software checks first
+ if (ok)
+ {
+ // Try dir/system/game.png
+ fname = std::string(system_name) + PATH_SEPARATOR + std::string(file_name) + ".png";
+ filerr = OpenRawDIBFile(dir_one, fname.c_str(), file);
+
+ // Try dir/system.zip/game.png
+ if (filerr != osd_file::error::NONE)
+ {
+ fname = std::string(file_name) + ".png";
+ filerr = OpenZipDIBFile(dir_one, system_name, fname.c_str(), file, &buffer);
+ }
+
+ // Try dir/system.zip/system/game.png
+ if (filerr != osd_file::error::NONE)
+ {
+ fname = std::string(system_name) + "/" + std::string(file_name) + ".png";
+ filerr = OpenZipDIBFile(dir_one, system_name, fname.c_str(), file, &buffer);
+ }
+
+ // Try dir/zipfile/system/game.png
+ if (filerr != osd_file::error::NONE)
+ {
+ filerr = OpenZipDIBFile(dir_one, zip_name, fname.c_str(), file, &buffer);
+ }
+ }
+
+ // give up on software-specific, try dir/system.png
+ if (filerr != osd_file::error::NONE)
+ {
+ fname = std::string(system_name) + ".png";
+ filerr = OpenRawDIBFile(dir_one, fname.c_str(), file);
+ }
+
+ // For SNAPS only, try filenames with 0000.
+ if (pic_type == TAB_SCREENSHOT)
+ {
+ if (filerr != osd_file::error::NONE)
+ {
+ //%g/%i
+ fname = std::string(system_name) + PATH_SEPARATOR + "0000.png";
+ filerr = OpenRawDIBFile(dir_one, fname.c_str(), file);
+ }
+ if (filerr != osd_file::error::NONE)
+ {
+ //%g%i
+ fname = std::string(system_name) + "0000.png";
+ filerr = OpenRawDIBFile(dir_one, fname.c_str(), file);
+ }
+ if (filerr != osd_file::error::NONE)
+ {
+ //%g/%g%i
+ fname = std::string(system_name) + PATH_SEPARATOR + std::string(system_name) + "0000.png";
+ filerr = OpenRawDIBFile(dir_one, fname.c_str(), file);
+ }
+ }
+
+ // Try dir/zipfile/system.png
+ if (filerr != osd_file::error::NONE)
+ {
+ fname = std::string(file_name) + ".png";
+ filerr = OpenZipDIBFile(dir_one, zip_name, fname.c_str(), file, &buffer);
+ }
+
+ dir_one = strtok(NULL, ";");
+ }
+
+ if (filerr == osd_file::error::NONE)
+ {
+ success = png_read_bitmap_gui(*file, phDIB, pPal);
+ file.reset();
+ }
+
+ // free the buffer if we have to
+ if (buffer != NULL)
+ free(buffer);
+ free(system_name);
+ free(file_name);
+ free(dir_name1);
+
+ return success;
+}
+
+HBITMAP DIBToDDB(HDC hDC, HANDLE hDIB, LPMYBITMAPINFO desc)
+{
+ LPBITMAPINFOHEADER lpbi;
+ HBITMAP hBM;
+ int nColors;
+ BITMAPINFO * bmInfo = (LPBITMAPINFO)hDIB;
+ LPVOID lpDIBBits;
+
+ if (hDIB == NULL)
+ return NULL;
+
+ lpbi = (LPBITMAPINFOHEADER)hDIB;
+ nColors = lpbi->biClrUsed ? lpbi->biClrUsed : 1 << lpbi->biBitCount;
+
+ if (bmInfo->bmiHeader.biBitCount > 8)
+ lpDIBBits = (LPVOID)((LPDWORD)(bmInfo->bmiColors +
+ bmInfo->bmiHeader.biClrUsed) +
+ ((bmInfo->bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
+ else
+ lpDIBBits = (LPVOID)(bmInfo->bmiColors + nColors);
+
+ if (desc != 0)
+ {
+ /* Store for easy retrieval later */
+ desc->bmWidth = bmInfo->bmiHeader.biWidth;
+ desc->bmHeight = bmInfo->bmiHeader.biHeight;
+ desc->bmColors = (nColors <= 256) ? nColors : 0;
+ }
+
+ hBM = CreateDIBitmap(hDC, /* handle to device context */
+ (LPBITMAPINFOHEADER)lpbi, /* pointer to bitmap info header */
+ (LONG)CBM_INIT, /* initialization flag */
+ lpDIBBits, /* pointer to initialization data */
+ (LPBITMAPINFO)lpbi, /* pointer to bitmap info */
+ DIB_RGB_COLORS); /* color-data usage */
+
+ return hBM;
+}
+
+BOOL LoadScreenShot(int nGame, int nType)
+{
+ return LoadScreenShotEx(nGame, NULL, nType);
+}
+
+/* End of source */