gcsx_frontend.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /* GCSx
  2. ** FRONTEND.CPP
  3. **
  4. ** Front-end module- leads to game, editor, configuration, etc.
  5. */
  6. /*****************************************************************************
  7. ** Copyright (C) 2003-2006 Janson
  8. **
  9. ** This program is free software; you can redistribute it and/or modify
  10. ** it under the terms of the GNU General Public License as published by
  11. ** the Free Software Foundation; either version 2 of the License, or
  12. ** (at your option) any later version.
  13. **
  14. ** This program is distributed in the hope that it will be useful,
  15. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ** GNU General Public License for more details.
  18. **
  19. ** You should have received a copy of the GNU General Public License
  20. ** along with this program; if not, write to the Free Software
  21. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  22. *****************************************************************************/
  23. #include "all.h"
  24. int gameMode = MODE_FRONTEND;
  25. // overlay mode- game accepts keyboard input
  26. // desktop MAY be overlaid over game in a translucent state
  27. int gameOverlayMode = 0;
  28. int getProgramMode() { start_func
  29. return gameMode;
  30. }
  31. void exitGameOverlayMode() { start_func
  32. if (gameOverlayMode) {
  33. gameOverlayMode = 0;
  34. SDL_EnableUNICODE(1);
  35. SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
  36. setScreenGLAlpha(config->readNum(FRONTEND_ACTIVE_ALPHA));
  37. desktop->setBackgroundAlpha(config->readNum(FRONTEND_ACTIVE_BKALPHA));
  38. }
  39. }
  40. void enterGameOverlayMode() { start_func
  41. if (gameMode == MODE_GAMEPLAY) {
  42. gameOverlayMode = 1;
  43. SDL_EnableKeyRepeat(0, 0);
  44. SDL_EnableUNICODE(0);
  45. setScreenGLAlpha(config->readNum(FRONTEND_INACTIVE_ALPHA));
  46. desktop->setBackgroundAlpha(config->readNum(FRONTEND_INACTIVE_BKALPHA));
  47. }
  48. }
  49. void exitGameMode() { start_func
  50. if (gameMode == MODE_GAMEPLAY) {
  51. desktop->setGameLoop(NULL);
  52. gcsxEndgame();
  53. gameMode = MODE_FRONTEND;
  54. }
  55. exitGameOverlayMode();
  56. }
  57. void enterGameMode() { start_func
  58. // (presumes you loaded a game!)
  59. desktop->setGameLoop(gcsxGameloopGui);
  60. gameMode = MODE_GAMEPLAY;
  61. setScreenGLAlpha(config->readNum(FRONTEND_ACTIVE_ALPHA));
  62. desktop->setBackgroundAlpha(config->readNum(FRONTEND_ACTIVE_BKALPHA));
  63. }
  64. void initDefaultVideo() { start_func
  65. // Initialize default video mode
  66. int x = config->readNum(VIDEO_X);
  67. int y = config->readNum(VIDEO_Y);
  68. int bpp = config->readNum(VIDEO_BPP);
  69. if (x < 320) x = 320;
  70. if (y < 240) y = 240;
  71. if ((bpp != 15) && (bpp != 16) && (bpp != 24) && (bpp != 32)) bpp = -1;
  72. selectVideoMode(x, y, bpp, config->readNum(VIDEO_FULLSCREEN), config->readNum(VIDEO_RESIZABLE));
  73. }
  74. // Menu tree for front end
  75. PopupMenu::PopupGen frontEndMenuTree[] = {
  76. { MENU_SUB, "\tFile", 0 },
  77. { FILE_OPENEXIST, "\tLoad world...", 0 },
  78. { FILE_RETURNGAME, "\tReturn to game", 1 },
  79. { FILE_CLOSEGAME, "\tClose game", 1 },
  80. { MENU_SEP, NULL, 0 },
  81. { FILE_EDITOR, "\tEditor", 0 },
  82. { MENU_SEP, NULL, 0 },
  83. { FILE_EXIT, "E\txit", 0 },
  84. { 0, NULL, 0 },
  85. { MENU_SUB, "\tDebug", 0 },
  86. { VIEW_CONSOLE, "\tConsole", 1 },
  87. { 0, NULL, 0 },
  88. { MENU_SUB, "\tConfig", 0 },
  89. { CONFIG_RESOLUTION, "\tResolution...", 1 },
  90. { 0, NULL, 0 },
  91. /* Removed (@TODO:)
  92. { MENU_SUB, "\tHelp", 0 },
  93. { MENU_HELP_INDEX, "\tIndex", 0 },
  94. { 0, NULL, 0 },
  95. */
  96. { 0, NULL, 0 }
  97. };
  98. // Menu handler for front-end
  99. Window::CommandSupport frontEndCommandSupport(int code) { start_func
  100. switch (code) {
  101. case VIEW_CONSOLE:
  102. return (Window::CommandSupport)((debugWindow()->isOpen() ? Window::COMMAND_SELECTED : 0) | Window::COMMAND_CHECKBOX | Window::COMMAND_ENABLE);
  103. case CONFIG_RESOLUTION:
  104. return gameMode == MODE_GAMEPLAY ? Window::COMMAND_DISABLE : Window::COMMAND_ENABLE;
  105. case FILE_RETURNGAME:
  106. case FILE_CLOSEGAME:
  107. return gameMode == MODE_GAMEPLAY ? Window::COMMAND_ENABLE : Window::COMMAND_DISABLE;
  108. }
  109. return Window::COMMAND_HIDE;
  110. }
  111. // Command handler for front-end
  112. int frontEndHandleGlobalEvents(const SDL_Event* event) { start_func
  113. string myFile;
  114. switch (event->type) {
  115. case SDL_SYSKEY:
  116. // These work even if shortcuts have been removed
  117. if ((event->key.keysym.sym == SDLK_ESCAPE) ||
  118. (event->key.keysym.sym == SDLK_F12)) {
  119. if (gameMode == MODE_GAMEPLAY) {
  120. if (desktop->findWindow(Window::WINDOW_FRAME, 0)) {
  121. enterGameOverlayMode();
  122. desktop->bringToTop(NULL);
  123. }
  124. else {
  125. desktop->broadcastEvent(SDL_SPECIAL, SDL_QUITTOGAME);
  126. }
  127. }
  128. }
  129. break;
  130. case SDL_SPECIAL:
  131. if (event->user.code == SDL_IDLETIMEOUTSHORT) {
  132. config->performSave();
  133. return 1;
  134. }
  135. if (event->user.code == SDL_CLOSEGAME) {
  136. exitGameMode();
  137. }
  138. if ((event->user.code == SDL_DESKTOPACTIVE) && (gameMode == MODE_GAMEPLAY)) {
  139. // If windows, go into 'overlay' mode; otherwise just return to game
  140. if (desktop->findWindow(Window::WINDOW_FRAME, 0)) {
  141. enterGameOverlayMode();
  142. }
  143. else {
  144. desktop->broadcastEvent(SDL_SPECIAL, SDL_QUITTOGAME);
  145. }
  146. }
  147. if ((event->user.code == SDL_DESKTOPINACTIVE) && (gameMode == MODE_GAMEPLAY)) {
  148. // Exit 'overlay' mode
  149. exitGameOverlayMode();
  150. }
  151. break;
  152. case SDL_COMMAND:
  153. switch (event->user.code) {
  154. case FILE_RETURNGAME:
  155. if (gameMode == MODE_GAMEPLAY) {
  156. if (desktop->findWindow(Window::WINDOW_FRAME, 0)) {
  157. enterGameOverlayMode();
  158. desktop->bringToTop(NULL);
  159. }
  160. else {
  161. desktop->broadcastEvent(SDL_SPECIAL, SDL_QUITTOGAME);
  162. }
  163. }
  164. return 1;
  165. case FILE_CLOSEGAME:
  166. exitGameMode();
  167. return 1;
  168. case FILE_EDITOR:
  169. desktop->broadcastEvent(SDL_SPECIAL, SDL_QUITTOEDITOR);
  170. return 1;
  171. case FILE_OPENEXIST:
  172. try {
  173. if (fileOpen(FILETYPE_WORLD, 0, myFile)) {
  174. exitGameMode();
  175. gcsxGameplay(myFile);
  176. // Warning about F12
  177. if (config->readNum(WARN_GAMEMENU)) {
  178. if (guiRemindBox("During gameplay, press F12 to toggle the menu/desktop.", warnTitleReminder)) {
  179. config->write(WARN_GAMEMENU, 0);
  180. }
  181. }
  182. enterGameMode();
  183. desktop->broadcastEvent(SDL_SPECIAL, SDL_QUITTOGAME);
  184. }
  185. }
  186. catch (FileException& e) {
  187. guiErrorBox(string(e.details), errorTitleFile);
  188. }
  189. return 1;
  190. case FILE_EXIT:
  191. desktop->broadcastEvent(SDL_QUIT, 0);
  192. return 1;
  193. case CONFIG_RESOLUTION:
  194. if (gameMode != MODE_GAMEPLAY)
  195. ResolutionDialog::create()->chooseResolution();
  196. return 1;
  197. case VIEW_CONSOLE:
  198. if (debugWindow()->isOpen()) {
  199. // Attempting to access console in overlay mode just exits overlay mode
  200. if (gameOverlayMode) {
  201. desktop->bringToTop(dynamic_cast<Window*>(debugWindow()->getParent()));
  202. }
  203. else {
  204. debugWindow()->closeWindow();
  205. // If closing console during game, return to game
  206. if (gameMode == MODE_GAMEPLAY) {
  207. desktop->broadcastEvent(SDL_SPECIAL, SDL_QUITTOGAME);
  208. }
  209. }
  210. }
  211. else {
  212. debugWindow()->runWindowed();
  213. }
  214. return 1;
  215. case MENU_HELP_INDEX:
  216. // @TODO: Help system
  217. return 1;
  218. }
  219. break;
  220. }
  221. return 0;
  222. }
  223. void gcsxFrontEnd() { start_func
  224. PopupMenu* frontEndMenu = NULL;
  225. int quitType = 0;
  226. SDL_Surface* bk;
  227. do {
  228. gameMode = MODE_FRONTEND;
  229. gameOverlayMode = 0;
  230. try {
  231. // Until we enter a game module, we need unicode translation and repeating keys
  232. SDL_EnableUNICODE(1);
  233. SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
  234. // Our event handlers
  235. desktop->setEventHandler(frontEndHandleGlobalEvents);
  236. desktop->setSupportsHandler(frontEndCommandSupport);
  237. // Set up our menus
  238. frontEndMenu = PopupMenu::compileMenu(frontEndMenuTree, 1);
  239. frontEndMenu->menubar(1);
  240. // Background (error results in quietly having no bk image)
  241. string bkFile;
  242. createFilename(resourceDir->c_str(), FILENAME_BKFRONT, bkFile);
  243. bk = IMG_Load(bkFile.c_str());
  244. desktop->setBackground(bk, COLOR_FRONTDESKTOP);
  245. SDL_WM_SetCaption(PRODUCT_NAME, PRODUCT_NAME);
  246. // Enter main event loop
  247. do {
  248. quitType = desktop->eventLoop();
  249. if (quitType == SDL_QUITTOGAME) {
  250. // Enter pure-game mode
  251. enterGameOverlayMode();
  252. int result;
  253. do {
  254. result = gcsxGameloop();
  255. } while (!result);
  256. exitGameOverlayMode();
  257. clearEvents();
  258. // Exit?
  259. if (result == GAME_EXIT) {
  260. exitGameMode();
  261. }
  262. if (result == GAME_CONSOLE) {
  263. if (!debugWindow()->isOpen()) {
  264. debugWindow()->runWindowed();
  265. }
  266. }
  267. // Either way, loop back to main loop and make menu active
  268. desktop->bringToTop(desktop->findWindow(Window::WINDOW_MENUBAR, 0), 1);
  269. }
  270. } while (quitType == SDL_QUITTOGAME);
  271. exitGameMode();
  272. // Close all windows
  273. desktop->closeAllWindows();
  274. // Cleanup
  275. // @TODO: Standardize 3 sets of cleanup into one (don't run beginExitStage() here!)
  276. desktop->setBackground(NULL, COLOR_FRONTDESKTOP);
  277. SDL_FreeSurface(bk);
  278. delete frontEndMenu;
  279. frontEndMenu = NULL;
  280. desktop->setSupportsHandler(NULL);
  281. desktop->setEventHandler(NULL);
  282. desktop->initEventCleanup();
  283. SDL_EnableKeyRepeat(0, 0);
  284. SDL_EnableUNICODE(0);
  285. clearEvents();
  286. }
  287. // Any exceptions
  288. catch (...) {
  289. try {
  290. beginExitStage();
  291. // Cleanup
  292. desktop->deleteAllWindows();
  293. desktop->setBackground(NULL, COLOR_FRONTDESKTOP);
  294. SDL_FreeSurface(bk);
  295. delete frontEndMenu;
  296. desktop->setSupportsHandler(NULL);
  297. desktop->setEventHandler(NULL);
  298. desktop->initEventCleanup();
  299. SDL_EnableKeyRepeat(0, 0);
  300. SDL_EnableUNICODE(0);
  301. clearEvents();
  302. }
  303. catch (...) {
  304. }
  305. // Pass it on
  306. throw;
  307. }
  308. // Enter editor? (and then loops for more)
  309. if (quitType == SDL_QUITTOEDITOR) {
  310. gameMode = MODE_EDITOR;
  311. // Shall we return to front end?
  312. if (!gcsxEditor()) quitType = 0;
  313. gameMode = MODE_FRONTEND;
  314. }
  315. } while (quitType > 1);
  316. // Save configuration last, only if no exceptions
  317. // (if exceptions, it may be a faulty configuration change)
  318. config->performSave();
  319. }