From f78790ccb167040e6c66fe357042638bf689a13c Mon Sep 17 00:00:00 2001 From: Dimitris Panokostas Date: Sun, 25 Feb 2018 13:37:16 +0100 Subject: [PATCH] Fixed #259: Crash when trying to display message about unsupported resolution mode (HighGFX) --- src/custom.cpp | 18 ++-- src/osdep/amiberry_gui.cpp | 1 + src/osdep/gui/InGameMessage.cpp | 164 +++++++++++++++++++------------- src/osdep/gui/ShowMessage.cpp | 2 +- 4 files changed, 111 insertions(+), 74 deletions(-) diff --git a/src/custom.cpp b/src/custom.cpp index cfeb9b63..a124ca94 100644 --- a/src/custom.cpp +++ b/src/custom.cpp @@ -3218,11 +3218,11 @@ static void compute_framesync (void) lof_changing = 0; if (beamcon0 & 0x80) { - static bool warned = false; - if(!warned) { - warned = true; - gui_message(_T("Variable beam counter comparator enabled. Not supported in Amiberry.")); - } + static bool warned = false; + if (!warned) { + warned = true; + gui_message(_T("Variable beam counter comparator enabled. Not supported in Amiberry.")); + } } memset (line_decisions, 0, sizeof line_decisions); @@ -3316,10 +3316,10 @@ static void init_hz (bool checkvposw) if (beamcon0 & 0x80) { // programmable scanrates (ECS Agnus) static bool warned = false; - if(!warned) { - warned = true; - InGameMessage("Programmable scanrates (ECS Agnus) not supported."); - } + if (!warned) { + warned = true; + gui_message(_T("Programmable scanrates (ECS Agnus) not supported.")); + } } if (maxvpos_nom >= MAXVPOS) maxvpos_nom = MAXVPOS; diff --git a/src/osdep/amiberry_gui.cpp b/src/osdep/amiberry_gui.cpp index f8de6b39..21242355 100644 --- a/src/osdep/amiberry_gui.cpp +++ b/src/osdep/amiberry_gui.cpp @@ -631,6 +631,7 @@ void gui_message(const char* format, ...) printf("%s\n", msg); return; } + graphics_subshutdown(); InGameMessage(msg); } diff --git a/src/osdep/gui/InGameMessage.cpp b/src/osdep/gui/InGameMessage.cpp index 1eca5df6..1706d627 100644 --- a/src/osdep/gui/InGameMessage.cpp +++ b/src/osdep/gui/InGameMessage.cpp @@ -23,15 +23,21 @@ #include "gui.h" #include "gui_handling.h" #include "amiberry_gfx.h" - #include "inputdevice.h" - #ifdef ANDROIDSDL #include "androidsdl_event.h" #endif -int msg_done = 0; +#define DIALOG_WIDTH 600 +#define DIALOG_HEIGHT 200 + +SDL_Surface* msg_screen; +SDL_Event msg_event; +#ifdef USE_SDL2 +SDL_Texture* msg_texture; +#endif +bool msg_done = false; gcn::Gui* msg_gui; gcn::SDLGraphics* msg_graphics; gcn::SDLInput* msg_input; @@ -40,17 +46,12 @@ gcn::contrib::SDLTrueTypeFont* msg_font; #elif USE_SDL2 gcn::SDLTrueTypeFont* msg_font; #endif -SDL_Event msg_event; gcn::Color msg_baseCol; gcn::Container* msg_top; gcn::Window* wndMsg; gcn::Button* cmdDone; -gcn::TextBox* txtMsg; - -int msgWidth = 260; -int msgHeight = 110; -int borderSize = 6; +gcn::Label* txtMsg; class DoneActionListener : public gcn::ActionListener { @@ -79,6 +80,34 @@ void gui_halt() delete msg_gui; delete msg_input; delete msg_graphics; + + if (msg_screen != nullptr) + { + SDL_FreeSurface(msg_screen); + msg_screen = nullptr; + } +#ifdef USE_SDL2 + if (msg_texture != nullptr) + { + SDL_DestroyTexture(msg_texture); + msg_texture = nullptr; + } + // Clear the screen + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); +#endif +} + +void UpdateScreen() +{ +#ifdef USE_SDL1 + wait_for_vsync(); + SDL_Flip(msg_screen); +#elif USE_SDL2 + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, msg_texture, nullptr, nullptr); + SDL_RenderPresent(renderer); +#endif } void checkInput() @@ -124,7 +153,7 @@ void checkInput() androidsdl_event(event, msg_input); #else msg_input->pushInput(msg_event); -#endif +#endif } if (gotEvent) { @@ -133,18 +162,20 @@ void checkInput() // Now we let the Gui object draw itself. msg_gui->draw(); #ifdef USE_SDL2 - SDL_UpdateTexture(texture, nullptr, screen->pixels, screen->pitch); + SDL_UpdateTexture(msg_texture, nullptr, msg_screen->pixels, msg_screen->pitch); #endif } + // Finally we update the screen. + UpdateScreen(); } void gui_init(const char* msg) { #ifdef USE_SDL1 - if (screen == nullptr) + if (msg_screen == nullptr) { auto dummy_screen = SDL_SetVideoMode(GUI_WIDTH, GUI_HEIGHT, 16, SDL_SWSURFACE | SDL_FULLSCREEN); - screen = SDL_CreateRGBSurface(SDL_HWSURFACE, GUI_WIDTH, GUI_HEIGHT, 16, + msg_screen = SDL_CreateRGBSurface(SDL_HWSURFACE, GUI_WIDTH, GUI_HEIGHT, 16, dummy_screen->format->Rmask, dummy_screen->format->Gmask, dummy_screen->format->Bmask, dummy_screen->format->Amask); SDL_FreeSurface(dummy_screen); } @@ -152,18 +183,20 @@ void gui_init(const char* msg) if (sdlWindow == nullptr) { sdlWindow = SDL_CreateWindow("Amiberry-GUI", - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - 0, - 0, - SDL_WINDOW_FULLSCREEN_DESKTOP); + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + 0, + 0, + SDL_WINDOW_FULLSCREEN_DESKTOP); check_error_sdl(sdlWindow == nullptr, "Unable to create window"); } + // make the scaled rendering look smoother (linear scaling). + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - if (screen == nullptr) + if (msg_screen == nullptr) { - screen = SDL_CreateRGBSurface(0, GUI_WIDTH, GUI_HEIGHT, 16, 0, 0, 0, 0); - check_error_sdl(screen == nullptr, "Unable to create SDL surface"); + msg_screen = SDL_CreateRGBSurface(0, GUI_WIDTH, GUI_HEIGHT, 32, 0, 0, 0, 0); + check_error_sdl(msg_screen == nullptr, "Unable to create SDL surface"); } if (renderer == nullptr) @@ -172,28 +205,30 @@ void gui_init(const char* msg) check_error_sdl(renderer == nullptr, "Unable to create a renderer"); SDL_RenderSetLogicalSize(renderer, GUI_WIDTH, GUI_HEIGHT); } - - if (texture == nullptr) + + if (msg_texture == nullptr) { - texture = SDL_CreateTexture(renderer, screen->format->format, SDL_TEXTUREACCESS_STREAMING, screen->w, screen->h); - check_error_sdl(renderer == nullptr, "Unable to create texture from Surface"); + msg_texture = SDL_CreateTexture(renderer, msg_screen->format->format, SDL_TEXTUREACCESS_STREAMING, msg_screen->w, + msg_screen->h); + check_error_sdl(msg_texture == nullptr, "Unable to create texture from Surface"); } SDL_ShowCursor(SDL_ENABLE); #endif msg_graphics = new gcn::SDLGraphics(); - msg_graphics->setTarget(screen); + msg_graphics->setTarget(msg_screen); msg_input = new gcn::SDLInput(); msg_gui = new gcn::Gui(); msg_gui->setGraphics(msg_graphics); msg_gui->setInput(msg_input); +} - msg_baseCol.r = 160; - msg_baseCol.g = 160; - msg_baseCol.b = 160; +void widgets_init(const char* msg) +{ + msg_baseCol = gcn::Color(170, 170, 170); msg_top = new gcn::Container(); - msg_top->setDimension(gcn::Rectangle((screen->w - msgWidth + borderSize * 4) / 2, (screen->h - msgHeight + borderSize * 4) / 4, msgWidth + (borderSize * 2), msgHeight + (borderSize * 2) + BUTTON_HEIGHT)); + msg_top->setDimension(gcn::Rectangle(0, 0, GUI_WIDTH, GUI_HEIGHT)); msg_top->setBaseColor(msg_baseCol); msg_gui->setTop(msg_top); @@ -205,68 +240,69 @@ void gui_init(const char* msg) #endif gcn::Widget::setGlobalFont(msg_font); - doneActionListener = new DoneActionListener(); - - wndMsg = new gcn::Window("Load"); - wndMsg->setSize(msgWidth + (borderSize * 2), msgHeight + (borderSize * 2) + BUTTON_HEIGHT); - wndMsg->setPosition(0, 0); - wndMsg->setBaseColor(msg_baseCol + 0x202020); + wndMsg = new gcn::Window("InGameMessage"); + wndMsg->setSize(DIALOG_WIDTH, DIALOG_HEIGHT); + wndMsg->setPosition((GUI_WIDTH - DIALOG_WIDTH) / 2, (GUI_HEIGHT - DIALOG_HEIGHT) / 2); + wndMsg->setBaseColor(msg_baseCol); wndMsg->setCaption("Information"); - wndMsg->setTitleBarHeight(12); + wndMsg->setTitleBarHeight(TITLEBAR_HEIGHT); + + doneActionListener = new DoneActionListener(); cmdDone = new gcn::Button("Ok"); cmdDone->setSize(BUTTON_WIDTH, BUTTON_HEIGHT); - cmdDone->setBaseColor(msg_baseCol + 0x202020); + cmdDone->setPosition(DIALOG_WIDTH - DISTANCE_BORDER - 2 * BUTTON_WIDTH - DISTANCE_NEXT_X, + DIALOG_HEIGHT - 2 * DISTANCE_BORDER - BUTTON_HEIGHT - 10); + cmdDone->setBaseColor(msg_baseCol); cmdDone->setId("Done"); cmdDone->addActionListener(doneActionListener); - txtMsg = new gcn::TextBox(msg); - txtMsg->setPosition(0, 0); - txtMsg->setSize(msgWidth, msgHeight); + txtMsg = new gcn::Label(msg); + txtMsg->setSize(DIALOG_WIDTH - 2 * DISTANCE_BORDER, LABEL_HEIGHT); - wndMsg->add(txtMsg, borderSize, borderSize); - wndMsg->add(cmdDone, (wndMsg->getWidth() - cmdDone->getWidth()) / 2, wndMsg->getHeight() - (borderSize * 2) - BUTTON_HEIGHT); + wndMsg->add(txtMsg, DISTANCE_BORDER, DISTANCE_BORDER); + wndMsg->add(cmdDone); msg_top->add(wndMsg); cmdDone->requestFocus(); + wndMsg->requestModalFocus(); } -void InGameMessage(const char* msg) +void gui_run() { - gui_init(msg); - - msg_done = 0; - auto drawn = false; - if (SDL_NumJoysticks() > 0) - if (GUIjoy == nullptr) - GUIjoy = SDL_JoystickOpen(0); - if (!uae_gui) { printf("%s\n",msg); return; } + { + GUIjoy = SDL_JoystickOpen(0); + } // Prepare the screen once - uae_gui->logic(); - uae_gui->draw(); + msg_gui->logic(); + msg_gui->draw(); #ifdef USE_SDL2 - SDL_UpdateTexture(gui_texture, nullptr, gui_screen->pixels, gui_screen->pitch); + SDL_UpdateTexture(msg_texture, nullptr, msg_screen->pixels, msg_screen->pitch); #endif - UpdateGuiScreen(); + UpdateScreen(); while (!msg_done) { // Poll input checkInput(); - -#ifdef USE_SDL1 - SDL_Flip(screen); -#elif USE_SDL2 - SDL_RenderClear(renderer); - SDL_RenderCopy(renderer, texture, nullptr, nullptr); - SDL_RenderPresent(renderer); -#endif + UpdateScreen(); } if (GUIjoy) + { SDL_JoystickClose(GUIjoy); + GUIjoy = nullptr; + } +} + +void InGameMessage(const char* msg) +{ + gui_init(msg); + widgets_init(msg); + + gui_run(); gui_halt(); SDL_ShowCursor(SDL_DISABLE); diff --git a/src/osdep/gui/ShowMessage.cpp b/src/osdep/gui/ShowMessage.cpp index 1e9687bf..409d8573 100644 --- a/src/osdep/gui/ShowMessage.cpp +++ b/src/osdep/gui/ShowMessage.cpp @@ -28,7 +28,7 @@ #include "inputdevice.h" #include "amiberry_gfx.h" -#define DIALOG_WIDTH 340 +#define DIALOG_WIDTH 600 #define DIALOG_HEIGHT 140 static bool dialogResult = false;