/** * gens_window_reinit(): Reinitialize the Gens window. */ void gens_window_reinit(void) { // Determine the window size using the scaling factor. if (vdraw_scale <= 0) return; const int w = 320 * vdraw_scale; const int h = 240 * vdraw_scale; LONG_PTR lStyle; if (vdraw_get_fullscreen()) { // Fullscreen. Hide the mouse cursor and the window borders. while (ShowCursor(TRUE) < 1) { } while (ShowCursor(FALSE) >= 0) { } // Hide the window borders. lStyle = GetWindowLongPtr(gens_window, GWL_STYLE); lStyle &= ~(WS_POPUPWINDOW | WS_OVERLAPPEDWINDOW); SetWindowLongPtr(gens_window, GWL_STYLE, lStyle); SetWindowPos(gens_window, NULL, 0, 0, w, h, SWP_NOZORDER | SWP_NOACTIVATE); } else { // Windowed. Show the mouse cursor and the window borders. while (ShowCursor(FALSE) >= 0) { } while (ShowCursor(TRUE) < 1) { } // Adjust the window style. lStyle = GetWindowLongPtr(gens_window, GWL_STYLE); if (vdraw_cur_backend_flags & VDRAW_BACKEND_FLAG_WINRESIZE) { // Backend supports resizable windows. lStyle &= ~WS_POPUPWINDOW; lStyle |= WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE | WS_CLIPSIBLINGS; } else { // Backend does not support resizable windows. lStyle &= ~WS_OVERLAPPEDWINDOW; lStyle |= WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE | WS_CLIPSIBLINGS; } SetWindowLongPtr(gens_window, GWL_STYLE, lStyle); // Reposition the window. SetWindowPos(gens_window, NULL, Window_Pos.x, Window_Pos.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); } // Rebuild the menu bar. // This is needed if the mode is switched from windowed to fullscreen, or vice-versa. gens_window_create_menubar(); // Synchronize menus. Sync_Gens_Window(); }
/** * create_gens_window_menubar(): Create the menu bar. */ void gens_window_create_menubar(void) { if (gens_menu_bar != NULL) { // Menu bar already exists. Delete it. gtk_widget_destroy(gens_menu_bar); gens_menu_clear(); } if (!vdraw_get_fullscreen() && Settings.showMenuBar) { // Create a menu bar. gens_menu_bar = gtk_menu_bar_new(); gtk_widget_show(gens_menu_bar); gtk_box_pack_start(GTK_BOX(gens_vbox_main), gens_menu_bar, FALSE, FALSE, 0); } else { // Create a popup menu. gens_menu_bar = gtk_menu_new(); } // Connect the menu "deactivate" signal. // For whatever reason, GtkMenuShell has a "deactivate" signal, // but not an "activate" signal. g_signal_connect((gpointer)gens_menu_bar, "deactivate", G_CALLBACK(gens_menu_deactivate), NULL); // Accelerator Group. static GtkAccelGroup *gens_menu_accel_group = NULL; if (gens_menu_accel_group != NULL) { // Delete the accelerator group. gtk_window_remove_accel_group(GTK_WINDOW(gens_window), gens_menu_accel_group); g_object_unref(gens_menu_accel_group); } // Create an accelerator group. gens_menu_accel_group = gtk_accel_group_new(); // Parse the menus. gens_menu_parse(&gmiMain[0], GTK_MENU_SHELL(gens_menu_bar), gens_menu_accel_group); // Add the accel group. gtk_window_add_accel_group(GTK_WINDOW(gens_window), gens_menu_accel_group); // Synchronize the menus. Sync_Gens_Window(); #ifdef GDK_WINDOWING_QUARTZ // Set the menu bar as the MacOS X menu bar. if (!vdraw_get_fullscreen() && Settings.showMenuBar) ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(gens_menu_bar)); #endif }
/** * create_gens_window_menubar(): Create the menu bar. */ void gens_window_create_menubar(void) { if (gens_menu_bar != NULL) { // Menu bar already exists. Delete it. gtk_widget_destroy(gens_menu_bar); gens_menu_clear(); } if (!vdraw_get_fullscreen() && Settings.showMenuBar) { // Create a menu bar. gens_menu_bar = gtk_menu_bar_new(); gtk_widget_show(gens_menu_bar); gtk_box_pack_start(GTK_BOX(gens_vbox_main), gens_menu_bar, FALSE, FALSE, 0); } else { // Create a popup menu. gens_menu_bar = gtk_menu_new(); } // Accelerator Group. static GtkAccelGroup *gens_menu_accel_group = NULL; if (gens_menu_accel_group != NULL) { // Delete the accelerator group. gtk_window_remove_accel_group(GTK_WINDOW(gens_window), gens_menu_accel_group); g_object_unref(gens_menu_accel_group); } // Create an accelerator group. gens_menu_accel_group = gtk_accel_group_new(); // Parse the menus. gens_menu_parse(&gmiMain[0], gens_menu_bar, gens_menu_accel_group); // Add the accel group. gtk_window_add_accel_group(GTK_WINDOW(gens_window), gens_menu_accel_group); // Synchronize the menus. Sync_Gens_Window(); #ifdef GDK_WINDOWING_QUARTZ // Set the menu bar as the MacOS X menu bar. if (!vdraw_get_fullscreen() && Settings.showMenuBar) ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(gens_menu_bar)); #endif }
/** * gens_window_create_menubar(): Create the menu bar. */ void gens_window_create_menubar(void) { if (MainMenu) { // Menu bar already exists. Delete it. DestroyMenu(MainMenu); gens_menu_clear(); } DestroyMenu(MainMenu); // Create the main menu. if (!vdraw_get_fullscreen() && Settings.showMenuBar) { // Create a menu bar. MainMenu = CreateMenu(); } else { // Create a popup menu. MainMenu = CreatePopupMenu(); } // Parse the menus. gens_menu_parse(&gmiMain[0], MainMenu); // Synchronize the menus. Sync_Gens_Window(); // Set the menu bar. if (!vdraw_get_fullscreen() && Settings.showMenuBar) SetMenu(gens_window, MainMenu); else SetMenu(gens_window, NULL); if (!vdraw_get_fullscreen()) { // Resize the window after the menu bar is rebuilt. if (vdraw_scale <= 0) return; const int w = 320 * vdraw_scale; const int h = 240 * vdraw_scale; gsft_win32_set_actual_window_size(gens_window, w, h); } }
/** * SelCD_Save(): Save the settings. * @return 1 if settings were saved; 0 on error. */ int SelCD_Save(void) { // Save settings. int tmpDrive; bool restartCD = false; // CD-ROM drive tmpDrive = ComboBox_GetCurSel(SelCD_cdromDropdownBox); // Check if the drive ID was changed. if (tmpDrive == cdromDeviceID) { // Drive ID wasn't changed. Don't do anything. return 1; } // Drive ID was changed. // This will cause a reset of the ASPI subsystem. if (SegaCD_Started && (CD_Load_System == CDROM_)) { // ASPI is currently in use. Ask the user if they want to restart emulation. GensUI::MsgBox_Response response; response = GensUI::msgBox( "The CD-ROM drive is currently in use.\n" "Chanigng the CD-ROM drive will force the emulator to reset.\n" "Are you sure you want to do this?", "CD-ROM Drive in Use", GensUI::MSGBOX_ICON_WARNING | GensUI::MSGBOX_BUTTONS_YES_NO, select_cdrom_window); if (response == GensUI::MSGBOX_RESPONSE_NO) { // Don't change anything. return 0; } // Stop SegaCD emulation. // TODO: Don't allow this if Netplay is enabled. restartCD = true; ROM::freeROM(Game); } // Stop ASPI. ASPI_End(); cdromDeviceID = tmpDrive; // TODO: Drive speed (maybe) // Restart ASPI. ASPI_Init(); if (restartCD) { // Restart SegaCD emulation. SegaCD_Started = Init_SegaCD(NULL); Sync_Gens_Window(); } // Settings saved. return 1; }
/** * vdraw_ddraw_init(): Initialize the DirectDraw video subsystem. * @return 0 on success; non-zero on error. */ int vdraw_ddraw_init(void) { DDSURFACEDESC2 ddsd; vdraw_ddraw_end(); mdp_render_t *rendMode = get_mdp_render_t(); const int scale = rendMode->scale; // Determine the window size using the scaling factor. if (scale <= 0) return -1; const int w = 320 * scale; const int h = 240 * scale; if (vdraw_get_fullscreen()) { Res_X = w; Res_Y = h; } // Return value. int rval; // Initialize DirectDraw. // TODO: Initialize DirectDraw on the monitor with most of Gens/GS onscreen. LPDIRECTDRAW lpDD_Init; rval = DirectDrawCreate(NULL, &lpDD_Init, NULL); if (FAILED(rval)) { LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "DirectDrawCreate() failed: 0x%08X", rval); return -2; } rval = lpDD_Init->QueryInterface(IID_IDirectDraw7, (LPVOID*)&lpDD); if (FAILED(rval)) { if (lpDD_Init) lpDD_Init->Release(); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD_Init->QueryInterface(IID_IDirectDraw4) failed: 0x%08X", rval); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "This can usually be fixed by upgrading DirectX."); return -3; } // Free the DirectDraw initialization object. lpDD_Init->Release(); // Set the cooperative level. vdraw_ddraw_set_cooperative_level(); // TODO: 15-bit color override. ("Force 555" or "Force 565" in the config file.) memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); // TODO: Figure out what FS_No_Res_Change is for. // TODO: Figure out if this is correct. if (vdraw_get_fullscreen() /* && !FS_No_Res_Change*/) { // Use the color depth setting. // NOTE: "15-bit" color requires 16-bit to be specified. rval = lpDD->SetDisplayMode(Res_X, Res_Y, (bppOut == 15 ? 16 : bppOut), 0, 0); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->SetDisplayMode() failed: 0x%08X", rval); // If render mode is set to Normal, try using Double instead. if (rendMode_FS == RenderMgr::begin() && rendMode_FS != RenderMgr::end()) { LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "Renderer is set to Normal; attempting to use Double instead."); rendMode_FS++; vdraw_set_renderer(rendMode_FS); vdraw_text_write("Normal rendering failed. Using Double.", 1500); Sync_Gens_Window_GraphicsMenu(); } return -4; } } #if 0 // Check the current color depth. unsigned char newBpp; lpDD->GetDisplayMode(&ddsd); switch (ddsd.ddpfPixelFormat.dwGBitMask) { case 0x03E0: // 15-bit color. newBpp = 15; break; case 0x07E0: // 16-bit color. newBpp = 16; break; case 0x00FF00: default: // 32-bit color. newBpp = 32; break; } if (newBpp != bppOut) vdraw_set_bpp(newBpp, false); #endif // Clear ddsd. memset(&ddsd, 0x00, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); if (vdraw_get_fullscreen() && Video.VSync_FS) { ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; ddsd.dwBackBufferCount = 2; } else { ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; } // Create the primary surface. rval = lpDD->CreateSurface(&ddsd, &lpDDS_Primary, NULL); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->CreateSurface(&lpDDS_Primary) failed: 0x%08X", rval); return -5; } if (vdraw_get_fullscreen()) { if (Video.VSync_FS) { ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; rval = lpDDS_Primary->GetAttachedSurface(&ddsd.ddsCaps, &lpDDS_Flip); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDDS_Primary->GetAttachSurface() failed: 0x%08X", rval); return -6; } lpDDS_Blit = lpDDS_Flip; } else { lpDDS_Blit = lpDDS_Primary; } } else { rval = lpDD->CreateClipper(0, &lpDDC_Clipper, NULL); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->CreateClipper() failed: 0x%08X", rval); return -7; } rval = lpDDC_Clipper->SetHWnd(0, gens_window); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDDC_Clipper->SetHWnd() failed: 0x%08X", rval); return -8; } rval = lpDDS_Primary->SetClipper(lpDDC_Clipper); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDDC_Primary->SetClipper() failed: 0x%08X", rval); return -9; } } // Clear ddsd again. memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; // Determine the width and height. // NOTE: For DirectDraw, the actual 336 width is used. if (vdraw_ddraw_is_hw_render()) { // Normal render mode. 320x240 [336x240] ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.dwWidth = 336; ddsd.dwHeight = 240; } else { // Larger than 1x. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; ddsd.dwWidth = w; ddsd.dwHeight = h; } // Set the pixel format. ddsd.dwFlags |= DDSD_PIXELFORMAT; ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; ddsd.ddpfPixelFormat.dwFourCC = 0; // RGB ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0; // Bits per component. switch (bppOut) { case 15: // 15-bit color. (555) ddsd.ddpfPixelFormat.dwRGBBitCount = 16; ddsd.ddpfPixelFormat.dwRBitMask = 0x7C00; ddsd.ddpfPixelFormat.dwGBitMask = 0x03E0; ddsd.ddpfPixelFormat.dwBBitMask = 0x001F; break; case 16: // 16-bit color. (555) ddsd.ddpfPixelFormat.dwRGBBitCount = 16; ddsd.ddpfPixelFormat.dwRBitMask = 0xF800; ddsd.ddpfPixelFormat.dwGBitMask = 0x07E0; ddsd.ddpfPixelFormat.dwBBitMask = 0x001F; break; case 32: default: // 32-bit color. ddsd.ddpfPixelFormat.dwRGBBitCount = 32; ddsd.ddpfPixelFormat.dwRBitMask = 0xFF0000; ddsd.ddpfPixelFormat.dwGBitMask = 0x00FF00; ddsd.ddpfPixelFormat.dwBBitMask = 0x0000FF; break; } // Create the back surface. rval = lpDD->CreateSurface(&ddsd, &lpDDS_Back, NULL); if (FAILED(rval)) { // Failed to create the back surface. // If we attempted to create it in video memory, try system memory instead. if (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) { LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->CreateSurface(&lpDDS_Back, DDSCAPS_VIDEOMEMORY) failed: 0x%08X", rval); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "Attempting to use DDSCAPS_SYSTEMMEMORY instead."); ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; rval = lpDD->CreateSurface(&ddsd, &lpDDS_Back, NULL); if (FAILED(rval)) { // Failed to create the back surface in system memory. vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->CreateSurface(&lpDDS_Back, DDSCAPS_SYSTEMMEMORY) failed: 0x%08X", rval); return -10; } } else { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->CreateSurface(&lpDDS_Back, DDSCAPS_SYSTEMMEMORY) failed: 0x%08X", rval); return -11; } } // TODO: Check if this is right. // I think this might be causing the frame counter flicker in full screen mode. //if (!vdraw_get_fullscreen() || (rendMode >= 1 && (/*FS_No_Res_Change ||*/ Res_X != 640 || Res_Y != 480))) if (!vdraw_get_fullscreen() || !vdraw_ddraw_is_hw_render()) lpDDS_Blit = lpDDS_Back; if (vdraw_ddraw_is_hw_render()) { // Normal rendering mode uses MD_Screen directly. memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); // TODO: This causes issues if the selected color depth isn't the // same as the desktop color depth. This only affects windowed mode, // since in fullscreen, the desktop color depth is changed. rval = lpDDS_Back->GetSurfaceDesc(&ddsd); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDDS_Back->GetSurfaceDesc() failed: 0x%08X", rval); return -12; } ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE | DDSD_PIXELFORMAT; ddsd.dwWidth = 336; ddsd.dwHeight = 240; if (ddsd.ddpfPixelFormat.dwRGBBitCount > 16) { // 32-bit color. ddsd.lpSurface = MD_Screen.u32; ddsd.lPitch = 336 * 4; } else { // 15-bit or 16-bit color. ddsd.lpSurface = MD_Screen.u16; ddsd.lPitch = 336 * 2; } rval = lpDDS_Back->SetSurfaceDesc(&ddsd, 0); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDDS_Back->SetSurfaceDesc() failed: 0x%08X", rval); return -13; } } // Initialize the destination rectangle. vdraw_ddraw_adjust_RectDest(); // Reset the render mode. vdraw_reset_renderer(false); // Synchronize menus. Sync_Gens_Window(); // vdraw_ddraw initialized. return 0; }