Guest User

GUIApp.cpp

a guest
Sep 27th, 2012
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 79.29 KB | None | 0 0
  1. /*
  2. Copyright (C) 2002-2007 The Pentagram team
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17. */
  18.  
  19. #include "pent_include.h"
  20.  
  21. #include "GUIApp.h"
  22.  
  23. #include <SDL.h>
  24. #include <SDL_keyboard.h>
  25. //!! a lot of these includes are just for some hacks... clean up sometime
  26. #include "Kernel.h"
  27. #include "FileSystem.h"
  28. #include "SettingManager.h"
  29. #include "ConfigFileManager.h"
  30. #include "ObjectManager.h"
  31. #include "GameInfo.h"
  32. #include "FontManager.h"
  33. #include "MemoryManager.h"
  34.  
  35. #include "HIDManager.h"
  36. #include "Joystick.h"
  37.  
  38. #include "RenderSurface.h"
  39. #include "Texture.h"
  40. #include "FixedWidthFont.h"
  41. #include "PaletteManager.h"
  42. #include "Palette.h"
  43. #include "GameData.h"
  44. #include "World.h"
  45. #include "Direction.h"
  46. #include "Game.h"
  47. #include "getObject.h"
  48.  
  49. #include "SavegameWriter.h"
  50. #include "Savegame.h"
  51. #include <ctime>
  52.  
  53. #include "Gump.h"
  54. #include "DesktopGump.h"
  55. #include "ConsoleGump.h"
  56. #include "GameMapGump.h"
  57. #include "InverterGump.h"
  58. #include "ScalerGump.h"
  59. #include "FastAreaVisGump.h"
  60. #include "MiniMapGump.h"
  61. #include "QuitGump.h"
  62. #include "MenuGump.h"
  63. #include "PentagramMenuGump.h"
  64.  
  65. // For gump positioning... perhaps shouldn't do it this way....
  66. #include "BarkGump.h"
  67. #include "AskGump.h"
  68. #include "ModalGump.h"
  69. #include "MessageBoxGump.h"
  70.  
  71.  
  72. #include "QuickAvatarMoverProcess.h"
  73. #include "Actor.h"
  74. #include "ActorAnimProcess.h"
  75. #include "TargetedAnimProcess.h"
  76. #include "u8intrinsics.h"
  77. #include "remorseintrinsics.h"
  78. #include "Egg.h"
  79. #include "CurrentMap.h"
  80. #include "InverterProcess.h"
  81. #include "HealProcess.h"
  82. #include "SchedulerProcess.h"
  83.  
  84. #include "EggHatcherProcess.h" // for a hack
  85. #include "UCProcess.h" // more hacking
  86. #include "GumpNotifyProcess.h" // guess
  87. #include "ActorBarkNotifyProcess.h" // guess
  88. #include "DelayProcess.h"
  89. #include "AvatarGravityProcess.h"
  90. #include "MissileProcess.h"
  91. #include "TeleportToEggProcess.h"
  92. #include "ItemFactory.h"
  93. #include "PathfinderProcess.h"
  94. #include "AvatarMoverProcess.h"
  95. #include "ResurrectionProcess.h"
  96. #include "SplitItemProcess.h"
  97. #include "ClearFeignDeathProcess.h"
  98. #include "LoiterProcess.h"
  99. #include "AvatarDeathProcess.h"
  100. #include "GrantPeaceProcess.h"
  101. #include "CombatProcess.h"
  102. #include "FireballProcess.h"
  103. #include "DestroyItemProcess.h"
  104. #include "AmbushProcess.h"
  105. #include "Pathfinder.h"
  106.  
  107. #include "MovieGump.h"
  108. #include "ShapeViewerGump.h"
  109.  
  110. #include "AudioMixer.h"
  111.  
  112. #ifdef WIN32
  113. #include <windows.h>
  114. #endif
  115.  
  116. #if defined(WIN32) && defined(I_AM_COLOURLESS_EXPERIMENTING_WITH_HW_CURSORS)
  117. #include "Shape.h"
  118. #include "ShapeFrame.h"
  119. #include "SoftRenderSurface.h"
  120. #include "SDL_syswm.h"
  121.  
  122. struct HWMouseCursor {
  123.     HICON hCursor;
  124. };
  125.  
  126. #endif
  127.  
  128. #include "XFormBlend.h"
  129.  
  130. #include "MusicProcess.h"
  131. #include "AudioProcess.h"
  132.  
  133. #include "util.h"
  134.  
  135. using std::string;
  136.  
  137. DEFINE_RUNTIME_CLASSTYPE_CODE(GUIApp,CoreApp);
  138.  
  139. GUIApp::GUIApp(int argc, const char* const* argv)
  140.     : CoreApp(argc, argv), save_count(0), game(0), kernel(0), objectmanager(0),
  141.       hidmanager(0), ucmachine(0), screen(0), fullscreen(false), palettemanager(0),
  142.       gamedata(0), world(0), desktopGump(0), consoleGump(0), gameMapGump(0),
  143.       avatarMoverProcess(0), runSDLInit(false),
  144.       frameSkip(false), frameLimit(true), interpolate(true),
  145.       animationRate(100), avatarInStasis(false), paintEditorItems(false),
  146.       painting(false), showTouching(false), mouseX(0), mouseY(0),
  147.       defMouse(0), flashingcursor(0),
  148.       mouseOverGump(0), dragging(DRAG_NOT), dragging_offsetX(0),
  149.       dragging_offsetY(0), inversion(0), timeOffset(0), has_cheated(false),
  150.       drawRenderStats(false), ttfoverrides(false), audiomixer(0)
  151. {
  152.     application = this;
  153.  
  154.     for (int i = 0; i < MOUSE_LAST; ++i) {
  155.         mouseButton[i].downGump = 0;
  156.         mouseButton[i].lastDown = 0;
  157.         mouseButton[i].state = MBS_HANDLED;
  158.     }
  159.  
  160.     for (uint16 key=0; key < HID_LAST; ++key)
  161.     {
  162.         lastDown[key] = 0;
  163.         down[key] = 0;
  164.     }
  165.  
  166.     con.AddConsoleCommand("quit", ConCmd_quit);
  167.     con.AddConsoleCommand("GUIApp::quit", ConCmd_quit);
  168.     con.AddConsoleCommand("QuitGump::verifyQuit", QuitGump::ConCmd_verifyQuit);
  169.     con.AddConsoleCommand("ShapeViewerGump::U8ShapeViewer", ShapeViewerGump::ConCmd_U8ShapeViewer);
  170.     con.AddConsoleCommand("MenuGump::showMenu", MenuGump::ConCmd_showMenu);
  171.     con.AddConsoleCommand("GUIApp::drawRenderStats", ConCmd_drawRenderStats);
  172.     con.AddConsoleCommand("GUIApp::engineStats", ConCmd_engineStats);
  173.  
  174.     con.AddConsoleCommand("GUIApp::changeGame",ConCmd_changeGame);
  175.     con.AddConsoleCommand("GUIApp::listGames",ConCmd_listGames);
  176.  
  177.     con.AddConsoleCommand("GUIApp::memberVar", &GUIApp::ConCmd_memberVar);
  178.     con.AddConsoleCommand("GUIApp::setVideoMode",ConCmd_setVideoMode);
  179.     con.AddConsoleCommand("GUIApp::toggleFullscreen",ConCmd_toggleFullscreen);
  180.  
  181.     con.AddConsoleCommand("GUIApp::toggleAvatarInStasis",ConCmd_toggleAvatarInStasis);
  182.     con.AddConsoleCommand("GUIApp::togglePaintEditorItems",ConCmd_togglePaintEditorItems);
  183.     con.AddConsoleCommand("GUIApp::toggleShowTouchingItems",ConCmd_toggleShowTouchingItems);
  184.  
  185.     con.AddConsoleCommand("GUIApp::closeItemGumps",ConCmd_closeItemGumps);
  186.  
  187.     con.AddConsoleCommand("HIDManager::bind", HIDManager::ConCmd_bind);
  188.     con.AddConsoleCommand("HIDManager::unbind", HIDManager::ConCmd_unbind);
  189.     con.AddConsoleCommand("HIDManager::listbinds",
  190.                           HIDManager::ConCmd_listbinds);
  191.     con.AddConsoleCommand("HIDManager::save", HIDManager::ConCmd_save);
  192.     con.AddConsoleCommand("Kernel::processTypes", Kernel::ConCmd_processTypes);
  193.     con.AddConsoleCommand("Kernel::processInfo", Kernel::ConCmd_processInfo);
  194.     con.AddConsoleCommand("Kernel::listProcesses",
  195.                           Kernel::ConCmd_listProcesses);
  196.     con.AddConsoleCommand("Kernel::toggleFrameByFrame",
  197.                           Kernel::ConCmd_toggleFrameByFrame);
  198.     con.AddConsoleCommand("Kernel::advanceFrame", Kernel::ConCmd_advanceFrame);
  199.     con.AddConsoleCommand("ObjectManager::objectTypes",
  200.                           ObjectManager::ConCmd_objectTypes);
  201.     con.AddConsoleCommand("ObjectManager::objectInfo",
  202.                           ObjectManager::ConCmd_objectInfo);
  203.     con.AddConsoleCommand("MemoryManager::MemInfo",
  204.                           MemoryManager::ConCmd_MemInfo);
  205.     con.AddConsoleCommand("MemoryManager::test",
  206.                           MemoryManager::ConCmd_test);
  207.  
  208.     con.AddConsoleCommand("QuickAvatarMoverProcess::startMoveUp",
  209.                           QuickAvatarMoverProcess::ConCmd_startMoveUp);
  210.     con.AddConsoleCommand("QuickAvatarMoverProcess::startMoveDown",
  211.                           QuickAvatarMoverProcess::ConCmd_startMoveDown);
  212.     con.AddConsoleCommand("QuickAvatarMoverProcess::startMoveLeft",
  213.                           QuickAvatarMoverProcess::ConCmd_startMoveLeft);
  214.     con.AddConsoleCommand("QuickAvatarMoverProcess::startMoveRight",
  215.                           QuickAvatarMoverProcess::ConCmd_startMoveRight);
  216.     con.AddConsoleCommand("QuickAvatarMoverProcess::startAscend",
  217.                           QuickAvatarMoverProcess::ConCmd_startAscend);
  218.     con.AddConsoleCommand("QuickAvatarMoverProcess::startDescend",
  219.                           QuickAvatarMoverProcess::ConCmd_startDescend);
  220.     con.AddConsoleCommand("QuickAvatarMoverProcess::stopMoveUp",
  221.                           QuickAvatarMoverProcess::ConCmd_stopMoveUp);
  222.     con.AddConsoleCommand("QuickAvatarMoverProcess::stopMoveDown",
  223.                           QuickAvatarMoverProcess::ConCmd_stopMoveDown);
  224.     con.AddConsoleCommand("QuickAvatarMoverProcess::stopMoveLeft",
  225.                           QuickAvatarMoverProcess::ConCmd_stopMoveLeft);
  226.     con.AddConsoleCommand("QuickAvatarMoverProcess::stopMoveRight",
  227.                           QuickAvatarMoverProcess::ConCmd_stopMoveRight);
  228.     con.AddConsoleCommand("QuickAvatarMoverProcess::stopAscend",
  229.                           QuickAvatarMoverProcess::ConCmd_stopAscend);
  230.     con.AddConsoleCommand("QuickAvatarMoverProcess::stopDescend",
  231.                           QuickAvatarMoverProcess::ConCmd_stopDescend);
  232.     con.AddConsoleCommand("QuickAvatarMoverProcess::toggleQuarterSpeed",
  233.                           QuickAvatarMoverProcess::ConCmd_toggleQuarterSpeed);
  234.     con.AddConsoleCommand("QuickAvatarMoverProcess::toggleClipping",
  235.                           QuickAvatarMoverProcess::ConCmd_toggleClipping);
  236.  
  237.     con.AddConsoleCommand("GameMapGump::toggleHighlightItems",
  238.                           GameMapGump::ConCmd_toggleHighlightItems);
  239.     con.AddConsoleCommand("GameMapGump::dumpMap",
  240.                           GameMapGump::ConCmd_dumpMap);
  241.     con.AddConsoleCommand("GameMapGump::incrementSortOrder",
  242.                           GameMapGump::ConCmd_incrementSortOrder);
  243.     con.AddConsoleCommand("GameMapGump::decrementSortOrder",
  244.                           GameMapGump::ConCmd_decrementSortOrder);
  245.  
  246.     con.AddConsoleCommand("AudioProcess::listSFX", AudioProcess::ConCmd_listSFX);
  247.     con.AddConsoleCommand("AudioProcess::playSFX", AudioProcess::ConCmd_playSFX);
  248.     con.AddConsoleCommand("AudioProcess::stopSFX", AudioProcess::ConCmd_stopSFX);
  249.  
  250.     // Game related console commands are now added in startupGame
  251. }
  252.  
  253. GUIApp::~GUIApp()
  254. {
  255.     shutdown();
  256.  
  257.     con.RemoveConsoleCommand(GUIApp::ConCmd_quit);
  258.     con.RemoveConsoleCommand(QuitGump::ConCmd_verifyQuit);
  259.     con.RemoveConsoleCommand(ShapeViewerGump::ConCmd_U8ShapeViewer);
  260.     con.RemoveConsoleCommand(MenuGump::ConCmd_showMenu);
  261.     con.RemoveConsoleCommand(GUIApp::ConCmd_drawRenderStats);
  262.     con.RemoveConsoleCommand(GUIApp::ConCmd_engineStats);
  263.  
  264.     con.RemoveConsoleCommand(GUIApp::ConCmd_changeGame);
  265.     con.RemoveConsoleCommand(GUIApp::ConCmd_listGames);
  266.  
  267.     con.RemoveConsoleCommand(GUIApp::ConCmd_memberVar);
  268.     con.RemoveConsoleCommand(GUIApp::ConCmd_setVideoMode);
  269.     con.RemoveConsoleCommand(GUIApp::ConCmd_toggleFullscreen);
  270.  
  271.     con.RemoveConsoleCommand(GUIApp::ConCmd_toggleAvatarInStasis);
  272.     con.RemoveConsoleCommand(GUIApp::ConCmd_togglePaintEditorItems);
  273.     con.RemoveConsoleCommand(GUIApp::ConCmd_toggleShowTouchingItems);
  274.  
  275.     con.RemoveConsoleCommand(GUIApp::ConCmd_closeItemGumps);
  276.  
  277.     con.RemoveConsoleCommand(HIDManager::ConCmd_bind);
  278.     con.RemoveConsoleCommand(HIDManager::ConCmd_unbind);
  279.     con.RemoveConsoleCommand(HIDManager::ConCmd_listbinds);
  280.     con.RemoveConsoleCommand(HIDManager::ConCmd_save);
  281.     con.RemoveConsoleCommand(Kernel::ConCmd_processTypes);
  282.     con.RemoveConsoleCommand(Kernel::ConCmd_processInfo);
  283.     con.RemoveConsoleCommand(Kernel::ConCmd_listProcesses);
  284.     con.RemoveConsoleCommand(Kernel::ConCmd_toggleFrameByFrame);
  285.     con.RemoveConsoleCommand(Kernel::ConCmd_advanceFrame);
  286.     con.RemoveConsoleCommand(ObjectManager::ConCmd_objectTypes);
  287.     con.RemoveConsoleCommand(ObjectManager::ConCmd_objectInfo);
  288.     con.RemoveConsoleCommand(MemoryManager::ConCmd_MemInfo);
  289.     con.RemoveConsoleCommand(MemoryManager::ConCmd_test);
  290.  
  291.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startMoveUp);
  292.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startMoveDown);
  293.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startMoveLeft);
  294.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startMoveRight);
  295.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startAscend);
  296.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_startDescend);
  297.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopMoveUp);
  298.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopMoveDown);
  299.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopMoveLeft);
  300.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopMoveRight);
  301.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopAscend);
  302.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_stopDescend);
  303.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_toggleQuarterSpeed);
  304.     con.RemoveConsoleCommand(QuickAvatarMoverProcess::ConCmd_toggleClipping);
  305.  
  306.     con.RemoveConsoleCommand(GameMapGump::ConCmd_toggleHighlightItems);
  307.     con.RemoveConsoleCommand(GameMapGump::ConCmd_dumpMap);
  308.     con.RemoveConsoleCommand(GameMapGump::ConCmd_incrementSortOrder);
  309.     con.RemoveConsoleCommand(GameMapGump::ConCmd_decrementSortOrder);
  310.  
  311.     con.RemoveConsoleCommand(AudioProcess::ConCmd_listSFX);
  312.     con.RemoveConsoleCommand(AudioProcess::ConCmd_stopSFX);
  313.     con.RemoveConsoleCommand(AudioProcess::ConCmd_playSFX);
  314.  
  315.     // Game related console commands are now removed in shutdownGame
  316.  
  317.     FORGET_OBJECT(kernel);
  318.     FORGET_OBJECT(defMouse);
  319.     FORGET_OBJECT(objectmanager);
  320.     FORGET_OBJECT(hidmanager);
  321.     FORGET_OBJECT(audiomixer);
  322.     FORGET_OBJECT(ucmachine);
  323.     FORGET_OBJECT(palettemanager);
  324.     FORGET_OBJECT(gamedata);
  325.     FORGET_OBJECT(world);
  326.     FORGET_OBJECT(ucmachine);
  327.     FORGET_OBJECT(fontmanager);
  328.     FORGET_OBJECT(screen);
  329. }
  330.  
  331. // Init sdl
  332. void GUIApp::SDLInit()
  333. {
  334.     con.Print(MM_INFO, "Initialising SDL...\n");
  335.     SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
  336.     atexit(SDL_Quit);
  337. }
  338.  
  339. void GUIApp::startup()
  340. {
  341.     SDLInit();
  342.  
  343.     // Set the console to auto paint, till we have finished initing
  344.     con.SetAutoPaint(conAutoPaint);
  345.  
  346.     pout << "-- Initializing Pentagram -- " << std::endl;
  347.  
  348.     // parent's startup first
  349.     CoreApp::startup();
  350.  
  351.     bool dataoverride;
  352.     if (!settingman->get("dataoverride", dataoverride,
  353.                          SettingManager::DOM_GLOBAL))
  354.         dataoverride = false;
  355.     filesystem->initBuiltinData(dataoverride);
  356.  
  357.     kernel = new Kernel();
  358.  
  359.     //!! move this elsewhere
  360.     kernel->addProcessLoader("DelayProcess",
  361.                              ProcessLoader<DelayProcess>::load);
  362.     kernel->addProcessLoader("GravityProcess",
  363.                              ProcessLoader<GravityProcess>::load);
  364.     kernel->addProcessLoader("AvatarGravityProcess",
  365.                              ProcessLoader<AvatarGravityProcess>::load);
  366.     kernel->addProcessLoader("PaletteFaderProcess",
  367.                              ProcessLoader<PaletteFaderProcess>::load);
  368.     kernel->addProcessLoader("TeleportToEggProcess",
  369.                              ProcessLoader<TeleportToEggProcess>::load);
  370.     kernel->addProcessLoader("ActorAnimProcess",
  371.                              ProcessLoader<ActorAnimProcess>::load);
  372.     kernel->addProcessLoader("TargetedAnimProcess",
  373.                              ProcessLoader<TargetedAnimProcess>::load);
  374.     kernel->addProcessLoader("AvatarMoverProcess",
  375.                              ProcessLoader<AvatarMoverProcess>::load);
  376.     kernel->addProcessLoader("QuickAvatarMoverProcess",
  377.                              ProcessLoader<QuickAvatarMoverProcess>::load);
  378.     kernel->addProcessLoader("PathfinderProcess",
  379.                              ProcessLoader<PathfinderProcess>::load);
  380.     kernel->addProcessLoader("SpriteProcess",
  381.                              ProcessLoader<SpriteProcess>::load);
  382.     kernel->addProcessLoader("MissileProcess",
  383.                              ProcessLoader<MissileProcess>::load);
  384.     kernel->addProcessLoader("CameraProcess",
  385.                              ProcessLoader<CameraProcess>::load);
  386.     kernel->addProcessLoader("MusicProcess",
  387.                              ProcessLoader<MusicProcess>::load);
  388.     kernel->addProcessLoader("AudioProcess",
  389.                              ProcessLoader<AudioProcess>::load);
  390.     kernel->addProcessLoader("EggHatcherProcess",
  391.                              ProcessLoader<EggHatcherProcess>::load);
  392.     kernel->addProcessLoader("UCProcess",
  393.                              ProcessLoader<UCProcess>::load);
  394.     kernel->addProcessLoader("GumpNotifyProcess",
  395.                              ProcessLoader<GumpNotifyProcess>::load);
  396.     kernel->addProcessLoader("ResurrectionProcess",
  397.                              ProcessLoader<ResurrectionProcess>::load);
  398.     kernel->addProcessLoader("DeleteActorProcess",
  399.                              ProcessLoader<DestroyItemProcess>::load);  // YES, this is intentional
  400.     kernel->addProcessLoader("DestroyItemProcess",
  401.                              ProcessLoader<DestroyItemProcess>::load);
  402.     kernel->addProcessLoader("SplitItemProcess",
  403.                              ProcessLoader<SplitItemProcess>::load);
  404.     kernel->addProcessLoader("ClearFeignDeathProcess",
  405.                              ProcessLoader<ClearFeignDeathProcess>::load);
  406.     kernel->addProcessLoader("LoiterProcess",
  407.                              ProcessLoader<LoiterProcess>::load);
  408.     kernel->addProcessLoader("AvatarDeathProcess",
  409.                              ProcessLoader<AvatarDeathProcess>::load);
  410.     kernel->addProcessLoader("GrantPeaceProcess",
  411.                              ProcessLoader<GrantPeaceProcess>::load);
  412.     kernel->addProcessLoader("CombatProcess",
  413.                              ProcessLoader<CombatProcess>::load);
  414.     kernel->addProcessLoader("FireballProcess",
  415.                              ProcessLoader<FireballProcess>::load);
  416.     kernel->addProcessLoader("HealProcess",
  417.                              ProcessLoader<HealProcess>::load);
  418.     kernel->addProcessLoader("SchedulerProcess",
  419.                              ProcessLoader<SchedulerProcess>::load);
  420.     kernel->addProcessLoader("InverterProcess",
  421.                              ProcessLoader<InverterProcess>::load);
  422.     kernel->addProcessLoader("ActorBarkNotifyProcess",
  423.                              ProcessLoader<ActorBarkNotifyProcess>::load);
  424.     kernel->addProcessLoader("JoystickCursorProcess",
  425.                              ProcessLoader<JoystickCursorProcess>::load);
  426.     kernel->addProcessLoader("AmbushProcess",
  427.                              ProcessLoader<AmbushProcess>::load);
  428.  
  429.     objectmanager = new ObjectManager();
  430.  
  431.     GraphicSysInit();
  432.  
  433.     SDL_ShowCursor(SDL_DISABLE);
  434.     SDL_GetMouseState(&mouseX, &mouseY);
  435.  
  436.     hidmanager = new HIDManager();
  437.  
  438.     // Audio Mixer
  439.     audiomixer = new Pentagram::AudioMixer(22050,true,8);
  440.  
  441.     pout << "-- Pentagram Initialized -- " << std::endl << std::endl;
  442.  
  443.     // We Attempt to startup game
  444.     setupGameList();
  445.     GameInfo* info = getDefaultGame();
  446.     if (setupGame(info))
  447.         startupGame();
  448.     else
  449.         startupPentagramMenu();
  450.  
  451.     // Unset the console auto paint, since we have finished initing
  452.     con.SetAutoPaint(0);
  453.  
  454. //  pout << "Paint Initial display" << std::endl;
  455.     paint();
  456. }
  457.  
  458. void GUIApp::startupGame()
  459. {
  460.     con.SetAutoPaint(conAutoPaint);
  461.  
  462.     pout  << std::endl << "-- Initializing Game: " << gameinfo->name << " --" << std::endl;
  463.  
  464.     GraphicSysInit();
  465.  
  466.     // set window title to current game
  467.     std::string title = "Pentagram - ";
  468.     title += getGameInfo()->getGameTitle();
  469.     SDL_WM_SetCaption(title.c_str(), "");
  470.  
  471.     // Generic Commands
  472.     con.AddConsoleCommand("GUIApp::saveGame", ConCmd_saveGame);
  473.     con.AddConsoleCommand("GUIApp::loadGame", ConCmd_loadGame);
  474.     con.AddConsoleCommand("GUIApp::newGame", ConCmd_newGame);
  475. #ifdef DEBUG
  476.     con.AddConsoleCommand("Pathfinder::visualDebug",
  477.                           Pathfinder::ConCmd_visualDebug);
  478. #endif
  479.  
  480.     // U8 Game commands
  481.     con.AddConsoleCommand("MainActor::teleport", MainActor::ConCmd_teleport);
  482.     con.AddConsoleCommand("MainActor::mark", MainActor::ConCmd_mark);
  483.     con.AddConsoleCommand("MainActor::recall", MainActor::ConCmd_recall);
  484.     con.AddConsoleCommand("MainActor::listmarks", MainActor::ConCmd_listmarks);
  485.     con.AddConsoleCommand("Cheat::maxstats", MainActor::ConCmd_maxstats);
  486.     con.AddConsoleCommand("Cheat::heal", MainActor::ConCmd_heal);
  487.     con.AddConsoleCommand("Cheat::toggleInvincibility", MainActor::ConCmd_toggleInvincibility);
  488.     con.AddConsoleCommand("MainActor::name", MainActor::ConCmd_name);
  489.     con.AddConsoleCommand("MovieGump::play", MovieGump::ConCmd_play);
  490.     con.AddConsoleCommand("MusicProcess::playMusic", MusicProcess::ConCmd_playMusic);
  491.     con.AddConsoleCommand("InverterProcess::invertScreen",
  492.                           InverterProcess::ConCmd_invertScreen);
  493.     con.AddConsoleCommand("FastAreaVisGump::toggle",
  494.                           FastAreaVisGump::ConCmd_toggle);
  495.     con.AddConsoleCommand("MiniMapGump::toggle",
  496.                           MiniMapGump::ConCmd_toggle);
  497.     con.AddConsoleCommand("MainActor::useBackpack",
  498.                           MainActor::ConCmd_useBackpack);
  499.     con.AddConsoleCommand("MainActor::useInventory",
  500.                           MainActor::ConCmd_useInventory);
  501.     con.AddConsoleCommand("MainActor::useRecall",
  502.                           MainActor::ConCmd_useRecall);
  503.     con.AddConsoleCommand("MainActor::useBedroll",
  504.                           MainActor::ConCmd_useBedroll);
  505.     con.AddConsoleCommand("MainActor::useKeyring",
  506.                           MainActor::ConCmd_useKeyring);
  507.     con.AddConsoleCommand("MainActor::toggleCombat",
  508.                           MainActor::ConCmd_toggleCombat);
  509.  
  510.     gamedata = new GameData(gameinfo);
  511.  
  512.     std::string bindingsfile;
  513.     if (GAME_IS_U8) {
  514.         bindingsfile = "@data/u8bindings.ini";
  515.     } else if (GAME_IS_REMORSE) {
  516.         bindingsfile = "@data/remorsebindings.ini";
  517.     }
  518.     if (!bindingsfile.empty()) {
  519.         // system-wide config
  520.         if (configfileman->readConfigFile(bindingsfile,
  521.                                           "bindings", true))
  522.             con.Printf(MM_INFO, "%s... Ok\n", bindingsfile.c_str());
  523.         else
  524.             con.Printf(MM_MINOR_WARN, "%s... Failed\n", bindingsfile.c_str());
  525.     }
  526.  
  527.     hidmanager->loadBindings();
  528.    
  529.     if (GAME_IS_U8) {
  530.         ucmachine = new UCMachine(U8Intrinsics, 256);
  531.     } else if (GAME_IS_REMORSE) {
  532.         ucmachine = new UCMachine(RemorseIntrinsics, 308);
  533.     } else {
  534.         CANT_HAPPEN_MSG("Invalid game type.");
  535.     }
  536.  
  537.     inBetweenFrame = 0;
  538.     lerpFactor = 256;
  539.  
  540.     // Initialize world
  541.     world = new World();
  542.     world->initMaps();
  543.  
  544.     game = Game::createGame(getGameInfo());
  545.  
  546.     settingman->setDefault("ttf", false);
  547.     settingman->get("ttf", ttfoverrides);
  548.  
  549.     settingman->setDefault("frameSkip", false);
  550.     settingman->get("frameSkip", frameSkip);
  551.  
  552.     settingman->setDefault("frameLimit", true);
  553.     settingman->get("frameLimit", frameLimit);
  554.  
  555.     settingman->setDefault("interpolate", true);
  556.     settingman->get("interpolate", interpolate);
  557.  
  558.     game->loadFiles();
  559.     gamedata->setupFontOverrides();
  560.  
  561.     // Unset the console auto paint (can't have it from here on)
  562.     con.SetAutoPaint(0);
  563.  
  564.     // Create Midi Driver for Ultima 8
  565.     if (getGameInfo()->type == GameInfo::GAME_U8)
  566.         audiomixer->openMidiOutput();
  567.  
  568.     std::string savegame;
  569.     settingman->setDefault("lastSave", "");
  570.     settingman->get("lastSave", savegame);
  571.  
  572.     newGame(savegame);
  573.  
  574.     consoleGump->HideConsole();
  575.  
  576.     pout << "-- Game Initialized --" << std::endl << std::endl;
  577. }
  578.  
  579. void GUIApp::startupPentagramMenu()
  580. {
  581.     con.SetAutoPaint(conAutoPaint);
  582.  
  583.     pout << std::endl << "-- Initializing Pentagram Menu -- " << std::endl;
  584.  
  585.     setupGame(getGameInfo("pentagram"));
  586.     assert(gameinfo);
  587.  
  588.     GraphicSysInit();
  589.  
  590.     // Unset the console auto paint, since we have finished initing
  591.     con.SetAutoPaint(0);
  592.     consoleGump->HideConsole();
  593.  
  594.     Pentagram::Rect dims;
  595.     desktopGump->GetDims(dims);
  596.  
  597.     Gump* menugump = new PentagramMenuGump(0,0,dims.w,dims.h);
  598.     menugump->InitGump(0, true);
  599. }
  600.  
  601. void GUIApp::shutdown()
  602. {
  603.     shutdownGame(false);
  604. }
  605.  
  606. void GUIApp::shutdownGame(bool reloading)
  607. {
  608.     pout << "-- Shutting down Game -- " << std::endl;
  609.  
  610.     // Save config here....
  611.  
  612.     SDL_WM_SetCaption("Pentagram", "");
  613.  
  614.     textmodes.clear();
  615.  
  616.     // reset mouse cursor
  617.     while (!cursors.empty()) cursors.pop();
  618.     pushMouseCursor();
  619.  
  620.     if (audiomixer) {
  621.         audiomixer->closeMidiOutput();
  622.         audiomixer->reset();
  623.     }
  624.  
  625.     FORGET_OBJECT(world);
  626.     objectmanager->reset();
  627.     FORGET_OBJECT(ucmachine);
  628.     kernel->reset();
  629.     palettemanager->reset();
  630.     fontmanager->resetGameFonts();
  631.  
  632.     FORGET_OBJECT(game);
  633.     FORGET_OBJECT(gamedata);
  634.  
  635.     desktopGump = 0;
  636.     consoleGump = 0;
  637.     gameMapGump = 0;
  638.     scalerGump = 0;
  639.     inverterGump = 0;
  640.  
  641.     timeOffset = -(sint32)Kernel::get_instance()->getFrameNum();
  642.     inversion = 0;
  643.     save_count = 0;
  644.     has_cheated = false;
  645.  
  646.     // Generic Game
  647.     con.RemoveConsoleCommand(GUIApp::ConCmd_saveGame);
  648.     con.RemoveConsoleCommand(GUIApp::ConCmd_loadGame);
  649.     con.RemoveConsoleCommand(GUIApp::ConCmd_newGame);
  650. #ifdef DEBUG
  651.     con.RemoveConsoleCommand(Pathfinder::ConCmd_visualDebug);
  652. #endif
  653.  
  654.     // U8 Only kind of
  655.     con.RemoveConsoleCommand(MainActor::ConCmd_teleport);
  656.     con.RemoveConsoleCommand(MainActor::ConCmd_mark);
  657.     con.RemoveConsoleCommand(MainActor::ConCmd_recall);
  658.     con.RemoveConsoleCommand(MainActor::ConCmd_listmarks);
  659.     con.RemoveConsoleCommand(MainActor::ConCmd_maxstats);
  660.     con.RemoveConsoleCommand(MainActor::ConCmd_heal);
  661.     con.RemoveConsoleCommand(MainActor::ConCmd_toggleInvincibility);
  662.     con.RemoveConsoleCommand(MainActor::ConCmd_name);
  663.     con.RemoveConsoleCommand(MovieGump::ConCmd_play);
  664.     con.RemoveConsoleCommand(MusicProcess::ConCmd_playMusic);
  665.     con.RemoveConsoleCommand(InverterProcess::ConCmd_invertScreen);
  666.     con.RemoveConsoleCommand(FastAreaVisGump::ConCmd_toggle);
  667.     con.RemoveConsoleCommand(MiniMapGump::ConCmd_toggle);
  668.     con.RemoveConsoleCommand(MainActor::ConCmd_useBackpack);
  669.     con.RemoveConsoleCommand(MainActor::ConCmd_useInventory);
  670.     con.RemoveConsoleCommand(MainActor::ConCmd_useRecall);
  671.     con.RemoveConsoleCommand(MainActor::ConCmd_useBedroll);
  672.     con.RemoveConsoleCommand(MainActor::ConCmd_useKeyring);
  673.     con.RemoveConsoleCommand(MainActor::ConCmd_toggleCombat);
  674.  
  675.     // Kill Game
  676.     CoreApp::killGame();
  677.  
  678.     pout << "-- Game Shutdown -- " << std::endl;
  679.  
  680.     if (reloading) {
  681.         Pentagram::Rect dims;
  682.         screen->GetSurfaceDims(dims);
  683.  
  684.         con.Print(MM_INFO, "Creating Desktop...\n");
  685.         desktopGump = new DesktopGump(0,0, dims.w, dims.h);
  686.         desktopGump->InitGump(0);
  687.         desktopGump->MakeFocus();
  688.  
  689.         con.Print(MM_INFO, "Creating ScalerGump...\n");
  690.         scalerGump = new ScalerGump(0, 0, dims.w, dims.h);
  691.         scalerGump->InitGump(0);
  692.  
  693.         Pentagram::Rect scaled_dims;
  694.         scalerGump->GetDims(scaled_dims);
  695.  
  696.         con.Print(MM_INFO, "Creating Graphics Console...\n");
  697.         consoleGump = new ConsoleGump(0, 0, dims.w, dims.h);
  698.         consoleGump->InitGump(0);
  699.         consoleGump->HideConsole();
  700.        
  701.         con.Print(MM_INFO, "Creating Inverter...\n");
  702.         inverterGump = new InverterGump(0, 0, scaled_dims.w, scaled_dims.h);
  703.         inverterGump->InitGump(0);
  704.  
  705.         enterTextMode(consoleGump);
  706.     }
  707. }
  708.  
  709. void GUIApp::changeGame(Pentagram::istring newgame)
  710. {
  711.     change_gamename = newgame;
  712. }
  713.  
  714. void GUIApp::menuInitMinimal(Pentagram::istring gamename)
  715. {
  716.     // Only if in the pentagram menu
  717.     if (gameinfo->name != "pentagram") return;
  718.     GameInfo *info = getGameInfo(gamename);
  719.     if (!info) info = getGameInfo("pentagram");
  720.     assert(info);
  721.  
  722.     pout  << std::endl << "-- Loading minimal game data for: " << info->name << " --" << std::endl;
  723.  
  724.     FORGET_OBJECT(game);
  725.     FORGET_OBJECT(gamedata);
  726.  
  727.  
  728.     setupGamePaths(info);
  729.  
  730.     if (info->name == "pentagram") return;
  731.  
  732.     gamedata = new GameData(info);
  733.     game = Game::createGame(info);
  734.  
  735.     game->loadFiles();
  736.     gamedata->setupFontOverrides();
  737.  
  738.     pout << "-- Finished loading minimal--" << std::endl << std::endl;
  739. }
  740.  
  741. void GUIApp::DeclareArgs()
  742. {
  743.     // parent's arguments first
  744.     CoreApp::DeclareArgs();
  745.  
  746.     // anything else?
  747. }
  748.  
  749. void GUIApp::run()
  750. {
  751.     isRunning = true;
  752.  
  753.     sint32 next_ticks = SDL_GetTicks()*3;   // Next time is right now!
  754.    
  755.     SDL_Event event;
  756.     while (isRunning) {
  757.         inBetweenFrame = true;  // Will get set false if it's not an inBetweenFrame
  758.  
  759.         if (!frameLimit) {         
  760.             kernel->runProcesses();
  761.             desktopGump->run();
  762.             inBetweenFrame = false;
  763.             next_ticks = animationRate + SDL_GetTicks()*3;
  764.             lerpFactor = 256;
  765.         }
  766.         else
  767.         {
  768.             sint32 ticks = SDL_GetTicks()*3;
  769.             sint32 diff = next_ticks - ticks;
  770.  
  771.             while (diff < 0) {
  772.                 next_ticks += animationRate;
  773.                 kernel->runProcesses();
  774.                 desktopGump->run();
  775. #if 0
  776.                 perr << "--------------------------------------" << std::endl;
  777.                 perr << "NEW FRAME" << std::endl;
  778.                 perr << "--------------------------------------" << std::endl;
  779. #endif
  780.                 inBetweenFrame = false;
  781.  
  782.                 ticks = SDL_GetTicks()*3;
  783.  
  784.                 // If frame skipping is off, we will only recalc next
  785.                 // ticks IF the frames are taking up 'way' too much time.
  786.                 if (!frameSkip && diff <= -animationRate*2) next_ticks = animationRate + ticks;
  787.  
  788.                 diff = next_ticks - ticks;
  789.                 if (!frameSkip) break;
  790.             }
  791.  
  792.             // Calculate the lerp_factor
  793.             lerpFactor = ((animationRate-diff)*256)/animationRate;
  794.             //pout << "lerpFactor: " << lerpFactor << " framenum: " << framenum << std::endl;
  795.             if (!interpolate || kernel->isPaused() || lerpFactor > 256)
  796.                 lerpFactor = 256;
  797.         }
  798.  
  799.         // get & handle all events in queue
  800.         while (isRunning && SDL_PollEvent(&event)) {
  801.             handleEvent(event);
  802.         }
  803.         handleDelayedEvents();
  804.  
  805.         // Paint Screen
  806.         paint();
  807.  
  808.         if (!change_gamename.empty()) {
  809.             pout << "Changing Game to: " << change_gamename << std::endl;
  810.  
  811.             GameInfo* info = getGameInfo(change_gamename);
  812.  
  813.             if (info) {
  814.                 shutdownGame();
  815.  
  816.                 change_gamename.clear();
  817.  
  818.                 if (setupGame(info))
  819.                     startupGame();
  820.                 else
  821.                     startupPentagramMenu();
  822.             }
  823.             else {
  824.                 perr << "Game '" << change_gamename << "' not found" << std::endl;
  825.                 change_gamename.clear();
  826.             }
  827.         }
  828.  
  829.         if (!error_message.empty())
  830.         {
  831.             MessageBoxGump::Show(error_title, error_message, 0xFF8F3030);
  832.             error_title.clear();
  833.             error_message.clear();
  834.         }
  835.  
  836.         // Do a delay
  837.         SDL_Delay(5);
  838.     }
  839. }
  840.  
  841.  
  842. // conAutoPaint hackery
  843. void GUIApp::conAutoPaint(void)
  844. {
  845.     GUIApp *app = GUIApp::get_instance();
  846.     if (app && !app->isPainting()) app->paint();
  847. }
  848.  
  849. #if defined(WIN32) && defined(I_AM_COLOURLESS_EXPERIMENTING_WITH_HW_CURSORS)
  850.  
  851. WNDPROC oldWindowProc = 0;
  852. bool allow_set_cursor = true;
  853.  
  854. LRESULT CALLBACK GUIApp::myWindowProc(
  855.   HWND hwnd,      // handle to window
  856.   UINT uMsg,      // message identifier
  857.   WPARAM wParam,  // first message parameter
  858.   LPARAM lParam   // second message parameter
  859.   )
  860. {
  861.     if (uMsg == WM_SETCURSOR) {
  862.         if ( allow_set_cursor = (LOWORD(lParam) == HTCLIENT) ) {
  863.             GUIApp *app = GUIApp::get_instance();
  864.             GameData *gamedata = app->gamedata;
  865.  
  866.             if (gamedata) {
  867.                 Shape* mouse = gamedata->getMouse();
  868.                 if (mouse) {
  869.                     int frame = app->getMouseFrame();
  870.                     if (frame >= 0)
  871.                         SetCursor(app->hwcursors[frame].hCursor);
  872.                 }
  873.             }
  874.             return TRUE;
  875.         }
  876.     }
  877.  
  878.     return CallWindowProc(oldWindowProc, hwnd, uMsg, wParam, lParam);
  879. }
  880.  
  881. void GUIApp::CreateHWCursors()
  882. {
  883.     Shape* mouse = gamedata->getMouse();
  884.     hwcursors = new HWMouseCursor[mouse->frameCount()];
  885.     std::memset (hwcursors, 0, sizeof(HWMouseCursor) * mouse->frameCount());
  886.  
  887.     for (uint32 frame = 0; frame < mouse->frameCount(); frame++)
  888.     {
  889.         ShapeFrame *f = mouse->getFrame(frame);
  890.         uint32 bpp = BaseSoftRenderSurface::format.s_bpp;
  891.         int buf_width = f->width;
  892.         int buf_height = f->height;
  893.  
  894.         // DIB must be dword aligned
  895.         if (bpp != 32) buf_width = (buf_width+1)&~1;   
  896.  
  897.         uint8 *buf = new uint8 [bpp/8 * buf_width * buf_height];
  898.  
  899.         RenderSurface *surf;
  900.  
  901.         if (bpp == 32)
  902.             surf = new SoftRenderSurface<uint32>(buf_width, buf_height, buf);
  903.         else
  904.             surf = new SoftRenderSurface<uint16>(buf_width, buf_height, buf);
  905.  
  906.         surf->BeginPainting();
  907.         surf->Fill32(0x00FF00FF, 0, 0, buf_width, buf_height);
  908.         surf->Paint(mouse, frame, f->xoff, f->yoff);
  909.         surf->EndPainting();
  910.  
  911.         int clear_col = PACK_RGB8(0xFF,0x00,0xFF);
  912.  
  913.         //
  914.         // Mask
  915.         //
  916.  
  917.         // 1 bit bitmap must be word aligned
  918.         uint32 bit_width = (buf_width+15)&~15;
  919.         uint8 *buf_mask = new uint8 [bit_width/8 * buf_height*2];
  920.  
  921.         // Clear it
  922.         std::memset(buf_mask, 0x00, bit_width/8 * buf_height * 2);
  923.  
  924.  
  925.         if (bpp == 32)
  926.         {
  927.             uint32 *buf32 = (uint32*)buf;
  928.             for (int y = 0; y < buf_height; y++)
  929.             {
  930.                 for (int x = 0; x < buf_width; x++)
  931.                 {
  932.                     bool black = (x & 1) == (y & 1);
  933.                     uint32 bit = y * bit_width + x;
  934.                     uint32 byte = bit/8;
  935.                     bit = 7-(bit % 8);
  936.  
  937.                     // If background is clear colour, mask it out
  938.                     if (buf32[buf_width*y + x] == clear_col)
  939.                     {
  940.                         buf32[buf_width*y + x] = 0;
  941.                         buf_mask[byte] |=   1<< bit;
  942.                     }
  943.                     // Make any non black make white
  944.                     else if (buf32[buf_width*y + x])
  945.                         buf_mask[byte+((buf_height*bit_width)/8)] |= 1<<bit;
  946.                 }
  947.             }
  948.         }
  949.         else
  950.         {
  951.             uint16 *buf16 = (uint16*)buf;
  952.             for (int y = 0; y < buf_height; y++)
  953.             {
  954.                 for (int x = 0; x < buf_width; x++)
  955.                 {
  956.                     bool black = (x & 1) == (y & 1);
  957.                     uint32 bit = y * bit_width + x;
  958.                     uint32 byte = bit/8;
  959.                     bit = 7-(bit % 8);
  960.  
  961.                     // If background is clear colour, mask it out
  962.                     if (buf16[buf_width*y + x] == clear_col)
  963.                     {
  964.                         buf16[buf_width*y + x] = 0;
  965.                         buf_mask[byte] |=   1<< bit;
  966.                     }
  967.                     // Make any non black make white
  968.                     else if (buf16[buf_width*y + x])
  969.                         buf_mask[byte+((buf_height*bit_width)/8)] |= 1<<bit;
  970.                 }
  971.             }
  972.         }
  973.  
  974.         // Create an icon for our cursor
  975.         ICONINFO iconinfo;
  976.         iconinfo.fIcon = FALSE;
  977.         iconinfo.xHotspot = f->xoff;
  978.         iconinfo.yHotspot = f->yoff;
  979.         iconinfo.hbmMask = CreateBitmap(buf_width, buf_height, 1, 1, buf_mask);
  980.         iconinfo.hbmColor = CreateBitmap(buf_width, buf_height, 1, bpp, buf);
  981.  
  982.         hwcursors[frame].hCursor = CreateIconIndirect (&iconinfo);
  983.  
  984.         DeleteObject(iconinfo.hbmMask);
  985.         DeleteObject(iconinfo.hbmColor);
  986.  
  987.         delete [] buf;
  988.         delete [] buf_mask;
  989.         delete surf;
  990.     }
  991.  
  992.     // Lets screw with the window class
  993.     SDL_SysWMinfo info;
  994.     info.version.major = SDL_MAJOR_VERSION;
  995.     info.version.minor = SDL_MINOR_VERSION;
  996.     info.version.patch = SDL_PATCHLEVEL;
  997.     SDL_GetWMInfo(&info);
  998.     oldWindowProc = (WNDPROC) GetWindowLongPtr(info.window, GWLP_WNDPROC);
  999.     SetWindowLongPtr(info.window, GWLP_WNDPROC, (LONG) myWindowProc);
  1000.    
  1001. }
  1002. #endif
  1003.  
  1004. // Paint the screen
  1005. void GUIApp::paint()
  1006. {
  1007.     static long prev = 0;
  1008.     static long t = 0;
  1009.     static long tdiff = 0;
  1010.     static long tpaint = 0;
  1011.     long now = SDL_GetTicks();
  1012.  
  1013.     if(!screen) // need to worry if the graphics system has been started. Need nicer way.
  1014.         return;
  1015.  
  1016.     if (prev != 0)
  1017.         tdiff += now - prev;
  1018.     prev = now;
  1019.     ++t;
  1020.    
  1021.     painting = true;
  1022.  
  1023.     // Begin painting
  1024.     screen->BeginPainting();
  1025.  
  1026.     // We need to get the dims
  1027.     Pentagram::Rect dims;
  1028.     screen->GetSurfaceDims(dims);
  1029.  
  1030.     tpaint -= SDL_GetTicks();
  1031.     desktopGump->Paint(screen, lerpFactor, false);
  1032.     tpaint += SDL_GetTicks();
  1033.  
  1034.     // Mouse
  1035.     if (gamedata) {
  1036.         Shape* mouse = gamedata->getMouse();
  1037.         if (mouse) {
  1038.             int frame = getMouseFrame();
  1039.             if (frame >= 0)
  1040.             {
  1041. #if defined(WIN32) && defined(I_AM_COLOURLESS_EXPERIMENTING_WITH_HW_CURSORS)
  1042.                 if (allow_set_cursor) SetCursor(hwcursors[frame].hCursor);
  1043. #else
  1044.                 screen->Paint(mouse, frame, mouseX, mouseY, true);
  1045. #endif
  1046.             }
  1047.             else if (frame == -2)
  1048.                 screen->Blit(defMouse, 0, 0, defMouse->width, defMouse->height, mouseX, mouseY);
  1049.         }
  1050.     }
  1051.     else {
  1052.         if (getMouseFrame() != -1)
  1053.             screen->Blit(defMouse, 0, 0, defMouse->width, defMouse->height, mouseX, mouseY);
  1054.     }
  1055.    
  1056.     if (drawRenderStats)
  1057.     {
  1058.         static long diff = 0;
  1059.         static long fps = 0;
  1060.         static long paint = 0;
  1061.         char buf[256] = {'\0'};
  1062.         FixedWidthFont *confont = con.GetConFont();
  1063.         int v_offset = 0;
  1064.         int char_w = confont->width;
  1065.  
  1066.         if (tdiff >= 250) {
  1067.             diff = tdiff / t;
  1068.             paint = tpaint / t;
  1069.             fps = 1000 * t / tdiff;
  1070.             t = 0;
  1071.             tdiff = 0;
  1072.             tpaint = 0;
  1073.         }
  1074.  
  1075.         snprintf(buf, 255, "Rendering time %li ms %li FPS ", diff, fps);
  1076.         screen->PrintTextFixed(confont, buf, dims.w-char_w*strlen(buf), v_offset);
  1077.         v_offset += confont->height;
  1078.  
  1079.         snprintf(buf, 255, "Paint Gumps %li ms ", paint);
  1080.         screen->PrintTextFixed(confont, buf, dims.w-char_w*strlen(buf), v_offset);
  1081.         v_offset += confont->height;
  1082.  
  1083.         snprintf(buf, 255, "t %02d:%02d gh %i ", I_getTimeInMinutes(0,0), I_getTimeInSeconds(0,0)%60, I_getTimeInGameHours(0,0));
  1084.         screen->PrintTextFixed(confont, buf, dims.w-char_w*strlen(buf), v_offset);
  1085.         v_offset += confont->height;
  1086.     }
  1087.  
  1088.     // End painting
  1089.     screen->EndPainting();
  1090.  
  1091.     painting = false;
  1092. }
  1093.  
  1094. bool GUIApp::isMouseDown(MouseButton button)
  1095. {
  1096.     return (mouseButton[button].state & MBS_DOWN);
  1097. }
  1098.  
  1099. int GUIApp::getMouseLength(int mx, int my)
  1100. {
  1101.     Pentagram::Rect dims;
  1102.     screen->GetSurfaceDims(dims);
  1103.     // For now, reference point is (near) the center of the screen
  1104.     int dx = mx - dims.w/2;
  1105.     int dy = (dims.h/2+14) - my; //! constant
  1106.  
  1107.     int shortsq = (dims.w / 8);
  1108.     if (dims.h / 6 < shortsq)
  1109.         shortsq = (dims.h / 6);
  1110.     shortsq = shortsq*shortsq;
  1111.    
  1112.     int mediumsq = ((dims.w * 4) / 10);
  1113.     if (((dims.h * 4) / 10) < mediumsq)
  1114.         mediumsq = ((dims.h * 4) / 10);
  1115.     mediumsq = mediumsq * mediumsq;
  1116.    
  1117.     int dsq = dx*dx+dy*dy;
  1118.    
  1119.     // determine length of arrow
  1120.     if (dsq <= shortsq) {
  1121.         return 0;
  1122.     } else if (dsq <= mediumsq) {
  1123.         return 1;
  1124.     } else {
  1125.         return 2;
  1126.     }
  1127. }
  1128.  
  1129. int GUIApp::getMouseDirection(int mx, int my)
  1130. {
  1131.     Pentagram::Rect dims;
  1132.     screen->GetSurfaceDims(dims);
  1133.     // For now, reference point is (near) the center of the screen
  1134.     int dx = mx - dims.w/2;
  1135.     int dy = (dims.h/2+14) - my; //! constant
  1136.  
  1137.     return ((Get_direction(dy*2, dx))+1)%8;
  1138. }
  1139.  
  1140. int GUIApp::getMouseFrame()
  1141. {
  1142.     // Ultima 8 mouse cursors:
  1143.  
  1144.     // 0-7 = short (0 = up, 1 = up-right, 2 = right, ...)
  1145.     // 8-15 = medium
  1146.     // 16-23 = long
  1147.     // 24 = blue dot
  1148.     // 25-32 = combat
  1149.     // 33 = red dot
  1150.     // 34 = target
  1151.     // 35 = pentagram
  1152.     // 36 = skeletal hand
  1153.     // 38 = quill
  1154.     // 39 = magnifying glass
  1155.     // 40 = red cross
  1156.  
  1157.     MouseCursor cursor = cursors.top();
  1158.  
  1159.     if (flashingcursor > 0) {
  1160.         if (SDL_GetTicks() < flashingcursor + 250)
  1161.             cursor = MOUSE_CROSS;
  1162.         else
  1163.             flashingcursor = 0;
  1164.     }
  1165.  
  1166.  
  1167.     switch (cursor) {
  1168.     case MOUSE_NORMAL:
  1169.     {
  1170.         bool combat = false;
  1171.         MainActor* av = getMainActor();
  1172.         if (av) { combat = av->isInCombat(); }
  1173.  
  1174.         // Calculate frame based on direction
  1175.         int frame = getMouseDirection(mouseX, mouseY);
  1176.  
  1177.         /** length --- frame offset
  1178.          *    0              0
  1179.          *    1              8
  1180.          *    2             16
  1181.          *  combat          25
  1182.          **/
  1183.         int offset = getMouseLength(mouseX, mouseY) * 8;
  1184.         if (combat && offset != 16) //combat mouse is off if running
  1185.             offset = 25;
  1186.         return frame + offset;
  1187.     }
  1188.     //!! constants...
  1189.     case MOUSE_NONE: return -1;
  1190.     case MOUSE_POINTER: return -2;
  1191.     case MOUSE_TARGET: return 34;
  1192.     case MOUSE_PENTAGRAM: return 35;
  1193.     case MOUSE_HAND: return 36;
  1194.     case MOUSE_QUILL: return 38;
  1195.     case MOUSE_MAGGLASS: return 39;
  1196.     case MOUSE_CROSS: return 40;
  1197.     default: return -1;
  1198.     }
  1199.  
  1200. }
  1201.  
  1202. void GUIApp::setMouseCoords(int mx, int my)
  1203. {
  1204.     Pentagram::Rect dims;
  1205.     screen->GetSurfaceDims(dims);
  1206.  
  1207.     if (mx < dims.x)
  1208.         mx = dims.x;
  1209.     else if (mx > dims.w)
  1210.         mx = dims.w;
  1211.  
  1212.     if (my < dims.y)
  1213.         my = dims.y;
  1214.     else if (my > dims.h)
  1215.         my = dims.h;
  1216.  
  1217.     mouseX = mx; mouseY = my;
  1218.     Gump * gump = desktopGump->OnMouseMotion(mx, my);
  1219.     if (gump && mouseOverGump != gump->getObjId())
  1220.     {
  1221.         Gump * oldGump = getGump(mouseOverGump);
  1222.         std::list<Gump*> oldgumplist;
  1223.         std::list<Gump*> newgumplist;
  1224.  
  1225.         // create lists of parents of old and new 'mouseover' gumps
  1226.         if (oldGump) {
  1227.             while (oldGump) {
  1228.                 oldgumplist.push_front(oldGump);
  1229.                 oldGump = oldGump->GetParent();
  1230.             }
  1231.         }
  1232.         Gump* newGump = gump;
  1233.         while (newGump) {
  1234.             newgumplist.push_front(newGump);
  1235.             newGump = newGump->GetParent();
  1236.         }
  1237.  
  1238.         std::list<Gump*>::iterator olditer = oldgumplist.begin();
  1239.         std::list<Gump*>::iterator newiter = newgumplist.begin();
  1240.  
  1241.         // strip common prefix from lists
  1242.         while (olditer != oldgumplist.end() &&
  1243.                newiter != newgumplist.end() &&
  1244.                *olditer == *newiter)
  1245.         {
  1246.             ++olditer; ++newiter;
  1247.         }
  1248.  
  1249.         // send events to remaining gumps
  1250.         for (; olditer != oldgumplist.end(); ++olditer)
  1251.             (*olditer)->OnMouseLeft();
  1252.  
  1253.         mouseOverGump = gump->getObjId();
  1254.  
  1255.         for (; newiter != newgumplist.end(); ++newiter)
  1256.             (*newiter)->OnMouseOver();
  1257.     }
  1258.  
  1259.     if (dragging == DRAG_NOT) {
  1260.         if (mouseButton[BUTTON_LEFT].state & MBS_DOWN) {
  1261.             int startx = mouseButton[BUTTON_LEFT].downX;
  1262.             int starty = mouseButton[BUTTON_LEFT].downY;
  1263.             if (abs(startx - mx) > 2 ||
  1264.                 abs(starty - my) > 2)
  1265.             {
  1266.                 startDragging(startx, starty);
  1267.             }
  1268.         }
  1269.     }
  1270.  
  1271.     if (dragging == DRAG_OK || dragging == DRAG_TEMPFAIL) {
  1272.         moveDragging(mx, my);
  1273.     }
  1274. }
  1275.  
  1276. void GUIApp::setMouseCursor(MouseCursor cursor)
  1277. {
  1278.     cursors.pop();
  1279.     cursors.push(cursor);
  1280. }
  1281.  
  1282. void GUIApp::flashCrossCursor()
  1283. {
  1284.     flashingcursor = SDL_GetTicks();
  1285. }
  1286.  
  1287. void GUIApp::pushMouseCursor()
  1288. {
  1289.     cursors.push(MOUSE_NORMAL);
  1290. }
  1291.  
  1292. void GUIApp::popMouseCursor()
  1293. {
  1294.     cursors.pop();
  1295. }
  1296.  
  1297. void GUIApp::GraphicSysInit()
  1298. {
  1299.     settingman->setDefault("fullscreen", false);
  1300.     settingman->setDefault("width", 640);
  1301.     settingman->setDefault("height", 480);
  1302.     settingman->setDefault("bpp", 32);
  1303.  
  1304.     bool new_fullscreen;
  1305.     int width, height, bpp;
  1306.     settingman->get("fullscreen", new_fullscreen);
  1307.     settingman->get("width", width);
  1308.     settingman->get("height", height);
  1309.     settingman->get("bpp", bpp);
  1310.  
  1311. #ifdef UNDER_CE
  1312.     width = 240;
  1313.     height = 320;
  1314. #endif
  1315.  
  1316. #if 0
  1317.     // store values in user's config file
  1318.     settingman->set("width", width);
  1319.     settingman->set("height", height);
  1320.     settingman->set("bpp", bpp);
  1321.     settingman->set("fullscreen", new_fullscreen);
  1322. #endif
  1323.  
  1324.     if (screen) {
  1325.         Pentagram::Rect old_dims;
  1326.         screen->GetSurfaceDims(old_dims);
  1327.         if (new_fullscreen == fullscreen && width == old_dims.w && height == old_dims.h) return;
  1328.         bpp = RenderSurface::format.s_bpp;
  1329.  
  1330.         delete screen;
  1331.     }
  1332.     screen = 0;
  1333.  
  1334.     fullscreen = new_fullscreen;
  1335.  
  1336.     // Set Screen Resolution
  1337.     con.Printf(MM_INFO, "Setting Video Mode %ix%ix%i %s...\n", width, height, bpp, fullscreen?"fullscreen":"windowed");
  1338.  
  1339.     RenderSurface *new_screen = RenderSurface::SetVideoMode(width, height, bpp, fullscreen, false);
  1340.  
  1341.     if (!new_screen)
  1342.     {
  1343.         perr << "Unable to set new video mode. Trying 640x480x32 windowed" << std::endl;
  1344.         new_screen = RenderSurface::SetVideoMode(640, 480, 32, fullscreen=false, false);
  1345.     }
  1346.  
  1347.     if (!new_screen)
  1348.     {
  1349.         perr << "Unable to set video mode. Exiting." << std::endl;
  1350.         std::exit(-1);
  1351.     }
  1352.  
  1353.     if (desktopGump) {
  1354.         palettemanager->RenderSurfaceChanged(new_screen);
  1355.         static_cast<DesktopGump*>(desktopGump)->RenderSurfaceChanged(new_screen);
  1356.         screen = new_screen;
  1357.         paint();
  1358.         return;
  1359.     }
  1360.  
  1361.     // set window title
  1362.     SDL_WM_SetCaption("Pentagram", "");
  1363.  
  1364.     // setup normal mouse cursor
  1365.     con.Print(MM_INFO, "Loading Default Mouse Cursor...\n");
  1366.     IDataSource *dm = filesystem->ReadFile("@data/mouse.tga");
  1367.     if (dm) defMouse = Texture::Create(dm, "@data/mouse.tga");
  1368.     else defMouse = 0;
  1369.     if (!defMouse)
  1370.     {
  1371.         perr << "Unable to load '@data/mouse.tga'" << ". Exiting" << std::endl;
  1372.         std::exit(-1);
  1373.     }
  1374.     delete dm;
  1375.     pushMouseCursor();
  1376.  
  1377.     std::string alt_confont;
  1378.     bool confont_loaded = false;
  1379.  
  1380.     if (settingman->get("console_font", alt_confont)) {
  1381.         con.Print(MM_INFO, "Alternate console font found...\n");
  1382.         confont_loaded = LoadConsoleFont(alt_confont);
  1383.     }
  1384.  
  1385.     if (!confont_loaded) {
  1386.         con.Print(MM_INFO, "Loading default console font...\n");
  1387.         if (!LoadConsoleFont("@data/fixedfont.ini")) {
  1388.             perr << "Failed to load console font. Exiting" << std::endl;
  1389.             std::exit(-1);
  1390.         }
  1391.     }
  1392.  
  1393.     desktopGump = new DesktopGump(0,0, width, height);
  1394.     desktopGump->InitGump(0);
  1395.     desktopGump->MakeFocus();
  1396.  
  1397.     scalerGump = new ScalerGump(0, 0, width, height);
  1398.     scalerGump->InitGump(0);
  1399.  
  1400.     consoleGump = new ConsoleGump(0, 0, width, height);
  1401.     consoleGump->InitGump(0);
  1402.  
  1403.     Pentagram::Rect scaled_dims;
  1404.     scalerGump->GetDims(scaled_dims);
  1405.  
  1406.     inverterGump = new InverterGump(0, 0, scaled_dims.w, scaled_dims.h);
  1407.     inverterGump->InitGump(0);
  1408.  
  1409.     screen = new_screen;
  1410.  
  1411.     bool ttf_antialiasing = true;
  1412.     settingman->setDefault("ttf_antialiasing", true);
  1413.     settingman->get("ttf_antialiasing", ttf_antialiasing);
  1414.  
  1415.     fontmanager = new FontManager(ttf_antialiasing);
  1416.     palettemanager = new PaletteManager(new_screen);
  1417.  
  1418.     // TODO: assign names to these fontnumbers somehow
  1419.     fontmanager->loadTTFont(0, "Vera.ttf", 18, 0xFFFFFF, 0);
  1420.     fontmanager->loadTTFont(1, "VeraBd.ttf", 16, 0xFFFFFF, 0);
  1421.     // GameWidget's version number information:
  1422.     fontmanager->loadTTFont(2, "Vera.ttf", 8, 0xA0A0A0, 0);
  1423.  
  1424.     bool faded_modal = true;
  1425.     settingman->setDefault("fadedModal", faded_modal);
  1426.     settingman->get("fadedModal", faded_modal);
  1427.     DesktopGump::SetFadedModal(faded_modal);
  1428.  
  1429.     paint();
  1430. }
  1431.  
  1432. void GUIApp::changeVideoMode(int width, int height, int new_fullscreen)
  1433. {
  1434.     if (new_fullscreen == -2) settingman->set("fullscreen", !fullscreen);
  1435.     else if (new_fullscreen == 0) settingman->set("fullscreen", false);
  1436.     else if (new_fullscreen == 1) settingman->set("fullscreen", true);
  1437.  
  1438.     if (width > 0) settingman->set("width", width);
  1439.     if (height > 0) settingman->set("height", height);
  1440.  
  1441.     GraphicSysInit();
  1442. }
  1443.  
  1444. bool GUIApp::LoadConsoleFont(std::string confontini)
  1445. {
  1446.     // try to load the file
  1447.     con.Printf(MM_INFO, "Loading console font config: %s... ", confontini.c_str());
  1448.     if(configfileman->readConfigFile(confontini, "confont", true))
  1449.         pout << "Ok" << std::endl;
  1450.     else {
  1451.         pout << "Failed" << std::endl;
  1452.         return false;
  1453.     }
  1454.  
  1455.     FixedWidthFont *confont = FixedWidthFont::Create("confont");
  1456.  
  1457.     if (!confont) {
  1458.         perr << "Failed to load Console Font." << std::endl;
  1459.         return false;
  1460.     }
  1461.  
  1462.     con.SetConFont(confont);
  1463.  
  1464.     return true;
  1465. }
  1466.  
  1467. void GUIApp::enterTextMode(Gump *gump)
  1468. {
  1469.     uint16 key;
  1470.     for (key=0; key < HID_LAST; ++key)
  1471.     {
  1472.         if (down[key])
  1473.         {
  1474.             down[key] = 0;
  1475.             lastDown[key] = 0;
  1476.             hidmanager->handleEvent((HID_Key) key, HID_EVENT_RELEASE);
  1477.         }
  1478.     }
  1479.        
  1480.     if (!textmodes.empty()) {
  1481.         textmodes.remove(gump->getObjId());
  1482.     } else {
  1483.         SDL_EnableUNICODE(1);
  1484.         SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
  1485.                             SDL_DEFAULT_REPEAT_INTERVAL);
  1486.     }
  1487.     textmodes.push_front(gump->getObjId());
  1488. }
  1489.  
  1490. void GUIApp::leaveTextMode(Gump *gump)
  1491. {
  1492.     if (textmodes.empty()) return;
  1493.     textmodes.remove(gump->getObjId());
  1494.     if (textmodes.empty()) {
  1495.         SDL_EnableUNICODE(0);
  1496.         SDL_EnableKeyRepeat(0, 0);
  1497.     }
  1498. }
  1499.  
  1500. void GUIApp::handleEvent(const SDL_Event& event)
  1501. {
  1502.     uint32 now = SDL_GetTicks();
  1503.     HID_Key key = HID_LAST;
  1504.     HID_Event evn = HID_EVENT_LAST;
  1505.     SDL_Event fakeevent;
  1506.     int mx, my;
  1507.     bool handled = false;
  1508.     GUIApp * app = GUIApp::get_instance();
  1509.     app->getMouseCoords(mx, my);
  1510.        
  1511.     switch (event.type) {
  1512.         case SDL_KEYDOWN:
  1513.             key = HID_translateSDLKey(event.key.keysym.sym);
  1514.             evn = HID_EVENT_DEPRESS;
  1515.         break;
  1516.         case SDL_KEYUP:
  1517.             key = HID_translateSDLKey(event.key.keysym.sym);
  1518.             evn = HID_EVENT_RELEASE;
  1519.             if (dragging == DRAG_NOT)
  1520.             {
  1521.                 switch (event.key.keysym.sym) {
  1522.                     case SDLK_q: // Quick quit
  1523. #ifndef MACOSX
  1524.                         if (event.key.keysym.mod & KMOD_CTRL)
  1525.                             ForceQuit();
  1526. #else
  1527.                         if (event.key.keysym.mod & KMOD_META)
  1528.                             ForceQuit();
  1529. #endif
  1530.                     return;
  1531.                     default: break;
  1532.                 }
  1533.             }
  1534.         break;
  1535.         case SDL_MOUSEBUTTONDOWN:
  1536.             key = HID_translateSDLMouseButton(event.button.button);
  1537.             evn = HID_EVENT_DEPRESS;
  1538.         break;
  1539.         case SDL_MOUSEBUTTONUP:
  1540.             key = HID_translateSDLMouseButton(event.button.button);
  1541.             evn = HID_EVENT_RELEASE;
  1542.         break;
  1543.         case SDL_JOYBUTTONDOWN:
  1544.             key = HID_translateSDLJoystickButton(event.jbutton.button);
  1545.             evn = HID_EVENT_DEPRESS;
  1546.             switch (event.jbutton.button) {
  1547.                 case 6:
  1548.                     fakeevent.type = SDL_KEYDOWN;
  1549.                     fakeevent.key.type = SDL_KEYDOWN;
  1550.                     fakeevent.key.keysym.sym = SDLK_SPACE;
  1551.                     fakeevent.key.keysym.mod = KMOD_NONE;
  1552.                     SDL_PushEvent (&fakeevent);
  1553.                     break;
  1554.                 case 5:
  1555.                     fakeevent.type = SDL_KEYDOWN;
  1556.                     fakeevent.key.type = SDL_KEYDOWN;
  1557.                     fakeevent.key.keysym.sym = SDLK_RETURN;
  1558.                     fakeevent.key.keysym.mod = KMOD_NONE;
  1559.                     SDL_PushEvent (&fakeevent);
  1560.                     break;
  1561.                 case 4:
  1562.                     fakeevent.type = SDL_KEYDOWN;
  1563.                     fakeevent.key.type = SDL_KEYDOWN;
  1564.                     fakeevent.key.keysym.sym = SDLK_ESCAPE;
  1565.                     fakeevent.key.keysym.mod = KMOD_NONE;
  1566.                     SDL_PushEvent (&fakeevent);
  1567.                     break;
  1568.                 case 3:
  1569.                     fakeevent.type = SDL_KEYDOWN;
  1570.                     fakeevent.key.type = SDL_KEYDOWN;
  1571.                     fakeevent.key.keysym.sym = SDLK_c;
  1572.                     fakeevent.key.keysym.mod = KMOD_NONE;
  1573.                     SDL_PushEvent (&fakeevent);
  1574.                     break;
  1575.                 case 2:
  1576.                     fakeevent.type = SDL_KEYDOWN;
  1577.                     fakeevent.key.type = SDL_KEYDOWN;
  1578.                     fakeevent.key.keysym.sym = SDLK_i;
  1579.                     fakeevent.key.keysym.mod = KMOD_NONE;
  1580.                     SDL_PushEvent (&fakeevent);
  1581.                     break;
  1582.                 case 1:        
  1583.                     fakeevent.type = SDL_MOUSEBUTTONDOWN;
  1584.                     fakeevent.button.button = SDL_BUTTON_LEFT;
  1585.                     //perr << "mouse 1 Click: x (" << mx << ") y (" << my << ")" << std::endl;
  1586.                     fakeevent.button.x = mx;
  1587.                     fakeevent.button.y = my;
  1588.                     SDL_PushEvent (&fakeevent);
  1589.                     break;
  1590.                 case 0:        
  1591.                     fakeevent.type = SDL_MOUSEBUTTONDOWN;
  1592.                     fakeevent.button.button = SDL_BUTTON_RIGHT;
  1593.                     //perr << "mouse 2 Click: x (" << mx << ") y (" << my << ")" << std::endl;
  1594.                     fakeevent.button.x = mx;
  1595.                     fakeevent.button.y = my;
  1596.                     SDL_PushEvent (&fakeevent);
  1597.                     break;
  1598.                 default:
  1599.                     break;
  1600.             }
  1601.         break;
  1602.         case SDL_JOYBUTTONUP:
  1603.             key = HID_translateSDLJoystickButton(event.jbutton.button);
  1604.             evn = HID_EVENT_RELEASE;
  1605.             switch (event.jbutton.button) {
  1606.                 case 6:
  1607.                     fakeevent.type = SDL_KEYUP;
  1608.                     fakeevent.key.type = SDL_KEYUP;
  1609.                     fakeevent.key.keysym.sym = SDLK_SPACE;
  1610.                     fakeevent.key.keysym.mod = KMOD_NONE;
  1611.                     SDL_PushEvent (&fakeevent);
  1612.                     break;
  1613.                 case 5:
  1614.                     fakeevent.type = SDL_KEYUP;
  1615.                     fakeevent.key.type = SDL_KEYUP;
  1616.                     fakeevent.key.keysym.sym = SDLK_RETURN;
  1617.                     fakeevent.key.keysym.mod = KMOD_NONE;
  1618.                     SDL_PushEvent (&fakeevent);
  1619.                     break;
  1620.                 case 4:
  1621.                     fakeevent.type = SDL_KEYUP;
  1622.                     fakeevent.key.type = SDL_KEYUP;
  1623.                     fakeevent.key.keysym.sym = SDLK_ESCAPE;
  1624.                     fakeevent.key.keysym.mod = KMOD_NONE;
  1625.                     SDL_PushEvent (&fakeevent);
  1626.                     break;
  1627.                 case 3:
  1628.                     fakeevent.type = SDL_KEYUP;
  1629.                     fakeevent.key.type = SDL_KEYUP;
  1630.                     fakeevent.key.keysym.sym = SDLK_c;
  1631.                     fakeevent.key.keysym.mod = KMOD_NONE;
  1632.                     SDL_PushEvent (&fakeevent);
  1633.                     break;
  1634.                 case 2:
  1635.                     fakeevent.type = SDL_KEYUP;
  1636.                     fakeevent.key.type = SDL_KEYUP;
  1637.                     fakeevent.key.keysym.sym = SDLK_i;
  1638.                     fakeevent.key.keysym.mod = KMOD_NONE;
  1639.                     SDL_PushEvent (&fakeevent);
  1640.                     break;
  1641.                 case 1:        
  1642.                     fakeevent.type = SDL_MOUSEBUTTONUP;
  1643.                     fakeevent.button.button = SDL_BUTTON_LEFT;
  1644.                     //perr << "mouse 1 Click: x (" << mx << ") y (" << my << ")" << std::endl;
  1645.                     fakeevent.button.x = mx;
  1646.                     fakeevent.button.y = my;
  1647.                     SDL_PushEvent (&fakeevent);
  1648.                     break;
  1649.                 case 0:        
  1650.                     fakeevent.type = SDL_MOUSEBUTTONUP;
  1651.                     fakeevent.button.button = SDL_BUTTON_RIGHT;
  1652.                     //perr << "mouse 1 Click: x (" << mx << ") y (" << my << ")" << std::endl;
  1653.                     fakeevent.button.x = mx;
  1654.                     fakeevent.button.y = my;
  1655.                     SDL_PushEvent (&fakeevent);
  1656.                     break;
  1657.                 default:
  1658.                     break;
  1659.             }
  1660.         break;
  1661.         case SDL_MOUSEMOTION:
  1662.         {
  1663.             int mx = event.button.x;
  1664.             int my = event.button.y;
  1665.             setMouseCoords(mx, my);
  1666.         }
  1667.         break;
  1668.  
  1669.         case SDL_QUIT:
  1670.             isRunning = false;
  1671.         break;
  1672.         case SDL_ACTIVEEVENT:
  1673.             // pause when lost focus?
  1674.         break;
  1675.     }
  1676.  
  1677.     if (dragging == DRAG_NOT && evn == HID_EVENT_DEPRESS) {
  1678.         if (hidmanager->handleEvent(key, HID_EVENT_PREEMPT))
  1679.             return;
  1680.     }
  1681.  
  1682.     // Text mode input. A few hacks here
  1683.     if (!textmodes.empty()) {
  1684.         Gump *gump = 0;
  1685.  
  1686.         while (!textmodes.empty())
  1687.         {
  1688.             gump = p_dynamic_cast<Gump*>(objectmanager->getObject(textmodes.front()));
  1689.             if (gump) break;
  1690.  
  1691.             textmodes.pop_front();
  1692.         }
  1693.  
  1694.         if (gump) {
  1695.             switch (event.type) {
  1696.                 case SDL_KEYDOWN:
  1697. #ifdef WIN32
  1698.                     // Paste from Clip-Board on Ctrl-V - Note this should be a flag of some sort
  1699.                     if (event.key.keysym.sym == SDLK_v && event.key.keysym.mod & KMOD_CTRL)
  1700.                     {
  1701.                         if (!IsClipboardFormatAvailable(CF_TEXT))
  1702.                             return ;
  1703.                         if (!OpenClipboard(NULL))
  1704.                             return;
  1705.  
  1706.                         HGLOBAL hglb = GetClipboardData(CF_TEXT);
  1707.                         if (hglb != NULL)
  1708.                         {
  1709.                             LPTSTR lptstr = reinterpret_cast<LPTSTR>(GlobalLock(hglb));
  1710.                             if (lptstr != NULL)
  1711.                             {
  1712.                                 // Only read the first line of text
  1713.                                 while (*lptstr >= ' ') gump->OnTextInput(*lptstr++);
  1714.  
  1715.                                 GlobalUnlock(hglb);
  1716.                             }
  1717.                         }
  1718.                         CloseClipboard();
  1719.                         return;
  1720.                     }
  1721. #endif
  1722.  
  1723. #ifdef MACOSX
  1724.                     // Paste from Clip-Board on Command-V - Note this should be a flag of some sort
  1725.                     if (event.key.keysym.sym == SDLK_v && event.key.keysym.mod & KMOD_META)
  1726.                     {
  1727.                         const char * str = macosxPasteboardText();
  1728.                         if (str != NULL)
  1729.                         {
  1730.                             // Only read the first line of text
  1731.                             while (*str >= ' ')
  1732.                                 gump->OnTextInput(*str++);
  1733.                         }
  1734.                         return;
  1735.                     }
  1736. #endif
  1737.  
  1738.                     if (event.key.keysym.unicode >= ' ' &&
  1739.                         event.key.keysym.unicode <= 255 &&
  1740.                         !(event.key.keysym.unicode >= 0x7F && // control chars
  1741.                           event.key.keysym.unicode <= 0x9F))
  1742.                     {
  1743.                         gump->OnTextInput(event.key.keysym.unicode);
  1744.                     }
  1745.  
  1746.                     gump->OnKeyDown(event.key.keysym.sym, event.key.keysym.mod);
  1747.                     return;
  1748.  
  1749.                 case SDL_KEYUP:
  1750.                     gump->OnKeyUp(event.key.keysym.sym);
  1751.                     return;
  1752.  
  1753.                 default: break;
  1754.             }
  1755.         }
  1756.     }
  1757.  
  1758.     // Old style input begins here
  1759.     switch (event.type) {
  1760.  
  1761.     //!! TODO: handle mouse handedness. (swap left/right mouse buttons here)
  1762.  
  1763.     // most of these events will probably be passed to a gump manager,
  1764.     // since almost all (all?) user input will be handled by a gump
  1765.  
  1766.    
  1767.     case SDL_MOUSEBUTTONDOWN:
  1768.     {
  1769.         int button = event.button.button;
  1770.         int mx = event.button.x;
  1771.         int my = event.button.y;
  1772.  
  1773.         if (button >= MOUSE_LAST)
  1774.             break;
  1775.  
  1776.         Gump *mousedowngump = desktopGump->OnMouseDown(button, mx, my);
  1777.         if (mousedowngump)
  1778.         {
  1779.             mouseButton[button].downGump = mousedowngump->getObjId();
  1780.             handled = true;
  1781.         }
  1782.         else
  1783.             mouseButton[button].downGump = 0;
  1784.  
  1785.         mouseButton[button].curDown = now;
  1786.         mouseButton[button].downX = mx;
  1787.         mouseButton[button].downY = my;
  1788.         mouseButton[button].state |= MBS_DOWN;
  1789.         mouseButton[button].state &= ~MBS_HANDLED;
  1790.  
  1791.         if (now - mouseButton[button].lastDown < DOUBLE_CLICK_TIMEOUT) {
  1792.             if (dragging == DRAG_NOT) {
  1793.                 Gump* gump = getGump(mouseButton[button].downGump);
  1794.                 if (gump)
  1795.                 {
  1796.                     int mx2 = mx, my2 = my;
  1797.                     Gump *parent = gump->GetParent();
  1798.                     if (parent) parent->ScreenSpaceToGump(mx2,my2);
  1799.                     gump->OnMouseDouble(button, mx2, my2);
  1800.                 }
  1801.                 mouseButton[button].state |= MBS_HANDLED;
  1802.                 mouseButton[button].lastDown = 0;
  1803.             }
  1804.         }
  1805.         mouseButton[button].lastDown = now;
  1806.     }
  1807.     break;
  1808.  
  1809.     case SDL_MOUSEBUTTONUP:
  1810.     {
  1811.         int button = event.button.button;
  1812.         int mx = event.button.x;
  1813.         int my = event.button.y;
  1814.  
  1815.         if (button >= MOUSE_LAST)
  1816.             break;
  1817.  
  1818.         mouseButton[button].state &= ~MBS_DOWN;
  1819.  
  1820.         // Need to store the last down position of the mouse
  1821.         // when the button is released.
  1822.         mouseButton[button].downX = mx;
  1823.         mouseButton[button].downY = my;
  1824.  
  1825.         // Always send mouse up to the gump
  1826.         Gump* gump = getGump(mouseButton[button].downGump);
  1827.         if (gump)
  1828.         {
  1829.             int mx2 = mx, my2 = my;
  1830.             Gump *parent = gump->GetParent();
  1831.             if (parent)
  1832.                 parent->ScreenSpaceToGump(mx2,my2);
  1833.             gump->OnMouseUp(button, mx2, my2);
  1834.             handled = true;
  1835.         }
  1836.  
  1837.         if (button == BUTTON_LEFT && dragging != DRAG_NOT) {
  1838.             stopDragging(mx, my);
  1839.             handled = true;
  1840.             break;
  1841.         }
  1842.     }
  1843.     break;
  1844.  
  1845.     case SDL_KEYDOWN:
  1846.     {
  1847.         if (dragging != DRAG_NOT) break;
  1848.  
  1849.         /*
  1850.         switch (event.key.keysym.sym) {
  1851.             case SDLK_KP_PLUS: {
  1852.                 midi_volume+=8;
  1853.                 if (midi_volume>255) midi_volume =255;
  1854.                 pout << "Midi Volume is now: " << midi_volume << std::endl;
  1855.                 if (midi_driver) midi_driver->setGlobalVolume(midi_volume);
  1856.             } break;
  1857.             case SDLK_KP_MINUS: {
  1858.                 midi_volume-=8;
  1859.                 if (midi_volume<0) midi_volume = 0;
  1860.                 pout << "Midi Volume is now: " << midi_volume << std::endl;
  1861.                 if (midi_driver) midi_driver->setGlobalVolume(midi_volume);
  1862.             } break;
  1863.             default:
  1864.                 break;
  1865.         }
  1866.         */
  1867.     }
  1868.     break;
  1869.  
  1870.     // any more useful events?
  1871.  
  1872.     default:
  1873.         break;
  1874.     }
  1875.  
  1876.     if (dragging == DRAG_NOT && ! handled) {
  1877.         if (hidmanager->handleEvent(key, evn))
  1878.             handled = true;
  1879.         if (evn == HID_EVENT_DEPRESS)
  1880.         {
  1881.             down[key] = 1;
  1882.             if (now - lastDown[key] < DOUBLE_CLICK_TIMEOUT &&
  1883.                 lastDown[key] != 0)
  1884.             {
  1885.                 if (hidmanager->handleEvent(key, HID_EVENT_DOUBLE))
  1886.                     handled = true;
  1887.                 lastDown[key] = 0;
  1888.             }
  1889.             else
  1890.             {
  1891.                 lastDown[key] = now;
  1892.             }
  1893.         }
  1894.         else if (evn == HID_EVENT_RELEASE)
  1895.         {
  1896.             down[key] = 0;
  1897.             if (now - lastDown[key] > DOUBLE_CLICK_TIMEOUT &&
  1898.                 lastDown[key] != 0)
  1899.             {
  1900.                 lastDown[key] = 0;
  1901.             }
  1902.         }
  1903.     }
  1904. }
  1905.  
  1906. void GUIApp::handleDelayedEvents()
  1907. {
  1908.     uint32 now = SDL_GetTicks();
  1909.     uint16 key;
  1910.     int button;
  1911.     for (button = 0; button < MOUSE_LAST; ++button) {
  1912.         if (!(mouseButton[button].state & (MBS_HANDLED | MBS_DOWN)) &&
  1913.             now - mouseButton[button].lastDown > DOUBLE_CLICK_TIMEOUT)
  1914.         {
  1915.             Gump* gump = getGump(mouseButton[button].downGump);
  1916.             if (gump)
  1917.             {
  1918.                 int mx = mouseButton[button].downX;
  1919.                 int my = mouseButton[button].downY;
  1920.                 Gump *parent = gump->GetParent();
  1921.                 if (parent) parent->ScreenSpaceToGump(mx,my);
  1922.                 gump->OnMouseClick(button, mx, my);
  1923.             }
  1924.  
  1925.             mouseButton[button].downGump = 0;
  1926.             mouseButton[button].state |= MBS_HANDLED;
  1927.         }
  1928.     }
  1929.  
  1930.     for (key=0; key < HID_LAST; ++key)
  1931.     {
  1932.         if (now - lastDown[key] > DOUBLE_CLICK_TIMEOUT &&
  1933.             lastDown[key] != 0 && down[key] == 0)
  1934.         {
  1935.             lastDown[key] = 0;
  1936.             hidmanager->handleEvent((HID_Key) key, HID_EVENT_CLICK);
  1937.         }
  1938.     }
  1939.  
  1940. }
  1941.  
  1942. void GUIApp::startDragging(int startx, int starty)
  1943. {
  1944.     setDraggingOffset(0,0); // initialize
  1945.  
  1946.     dragging_objid = desktopGump->TraceObjId(startx, starty);
  1947.    
  1948.     Gump *gump = getGump(dragging_objid);
  1949.     Item *item = getItem(dragging_objid);
  1950.    
  1951.     // for a Gump, notify the Gump's parent that we started
  1952.     // dragging:
  1953.     if (gump) {
  1954.         Gump *parent = gump->GetParent();
  1955.         assert(parent); // can't drag root gump
  1956.         int px = startx, py = starty;
  1957.         parent->ScreenSpaceToGump(px, py);
  1958.         if (gump->IsDraggable() && parent->StartDraggingChild(gump, px, py))
  1959.             dragging = DRAG_OK;
  1960.         else {
  1961.             dragging_objid = 0;
  1962.             return;
  1963.         }
  1964.     } else
  1965.     // for an Item, notify the gump the item is in that we started dragging
  1966.     if (item) {
  1967.         // find gump item was in
  1968.         gump = desktopGump->FindGump(startx, starty);
  1969.         int gx = startx, gy = starty;
  1970.         gump->ScreenSpaceToGump(gx, gy);
  1971.         bool ok = !isAvatarInStasis() &&
  1972.             gump->StartDraggingItem(item,gx,gy);
  1973.         if (!ok) {
  1974.             dragging = DRAG_INVALID;
  1975.         } else {
  1976.             dragging = DRAG_OK;
  1977.            
  1978.             // this is the gump that'll get StopDraggingItem
  1979.             dragging_item_startgump = gump->getObjId();
  1980.            
  1981.             // this is the gump the item is currently over
  1982.             dragging_item_lastgump = gump->getObjId();
  1983.         }
  1984.     } else {
  1985.         dragging = DRAG_INVALID;
  1986.     }
  1987.  
  1988. #if 0
  1989.     Object* obj = ObjectManager::get_instance()->getObject(dragging_objid);
  1990.     perr << "Dragging object " << dragging_objid << " (class=" << (obj ? obj->GetClassType().class_name : "NULL") << ")" << std::endl;
  1991. #endif
  1992.  
  1993.     pushMouseCursor();
  1994.     setMouseCursor(MOUSE_NORMAL);
  1995.    
  1996.     // pause the kernel
  1997.     kernel->pause();
  1998.    
  1999.     mouseButton[BUTTON_LEFT].state |= MBS_HANDLED;
  2000.  
  2001.     if (dragging == DRAG_INVALID) {
  2002.         setMouseCursor(MOUSE_CROSS);
  2003.     }
  2004. }
  2005.  
  2006. void GUIApp::moveDragging(int mx, int my)
  2007. {
  2008.     Gump* gump = getGump(dragging_objid);
  2009.     Item *item = getItem(dragging_objid);
  2010.  
  2011.     setMouseCursor(MOUSE_NORMAL);
  2012.    
  2013.     // for a gump, notify Gump's parent that it was dragged
  2014.     if (gump) {
  2015.         Gump *parent = gump->GetParent();
  2016.         assert(parent); // can't drag root gump
  2017.         int px = mx, py = my;
  2018.         parent->ScreenSpaceToGump(px, py);
  2019.         parent->DraggingChild(gump, px, py);
  2020.     } else
  2021.     // for an item, notify the gump it's on
  2022.     if (item) {
  2023.         gump = desktopGump->FindGump(mx, my);
  2024.         assert(gump);
  2025.            
  2026.         if (gump->getObjId() != dragging_item_lastgump) {
  2027.             // item switched gump, so notify previous gump item left
  2028.             Gump *last = getGump(dragging_item_lastgump);
  2029.             if (last) last->DraggingItemLeftGump(item);
  2030.         }
  2031.         dragging_item_lastgump = gump->getObjId();
  2032.         int gx = mx, gy = my;
  2033.         gump->ScreenSpaceToGump(gx, gy);
  2034.         bool ok = gump->DraggingItem(item,gx,gy);
  2035.         if (!ok) {
  2036.             dragging = DRAG_TEMPFAIL;
  2037.         } else {
  2038.             dragging = DRAG_OK;
  2039.         }
  2040.     } else {
  2041.         CANT_HAPPEN();
  2042.     }
  2043.  
  2044.     if (dragging == DRAG_TEMPFAIL) {
  2045.         setMouseCursor(MOUSE_CROSS);
  2046.     }
  2047. }
  2048.  
  2049.  
  2050. void GUIApp::stopDragging(int mx, int my)
  2051. {
  2052. //  perr << "Dropping object " << dragging_objid << std::endl;
  2053.    
  2054.     Gump *gump = getGump(dragging_objid);
  2055.     Item *item = getItem(dragging_objid);
  2056.     // for a Gump: notify parent
  2057.     if (gump) {
  2058.         Gump *parent = gump->GetParent();
  2059.         assert(parent); // can't drag root gump
  2060.         parent->StopDraggingChild(gump);
  2061.     } else
  2062.     // for an item: notify gumps
  2063.     if (item) {
  2064.         if (dragging != DRAG_INVALID) {
  2065.             Gump *startgump = getGump(dragging_item_startgump);
  2066.             assert(startgump); // can't have disappeared
  2067.             bool moved = (dragging == DRAG_OK);
  2068.  
  2069.             if (dragging != DRAG_OK) {
  2070.                 Gump *last = getGump(dragging_item_lastgump);
  2071.                 if (last && last != startgump)
  2072.                     last->DraggingItemLeftGump(item);
  2073.             }
  2074.  
  2075.             startgump->StopDraggingItem(item, moved);
  2076.         }
  2077.        
  2078.         if (dragging == DRAG_OK) {
  2079.             item->movedByPlayer();
  2080.  
  2081.             gump = desktopGump->FindGump(mx, my);
  2082.             int gx = mx, gy = my;
  2083.             gump->ScreenSpaceToGump(gx, gy);
  2084.             gump->DropItem(item,gx,gy);
  2085.         }
  2086.     } else {
  2087.         assert(dragging == DRAG_INVALID);
  2088.     }
  2089.  
  2090.     dragging = DRAG_NOT;
  2091.  
  2092.     kernel->unpause();
  2093.  
  2094.     popMouseCursor();
  2095. }
  2096.  
  2097. void GUIApp::writeSaveInfo(ODataSource* ods)
  2098. {
  2099.     time_t t = std::time(0);
  2100.     struct tm *timeinfo = localtime (&t);
  2101.     ods->write2(static_cast<uint16>(timeinfo->tm_year + 1900));
  2102.     ods->write1(static_cast<uint8>(timeinfo->tm_mon+1));
  2103.     ods->write1(static_cast<uint8>(timeinfo->tm_mday));
  2104.     ods->write1(static_cast<uint8>(timeinfo->tm_hour));
  2105.     ods->write1(static_cast<uint8>(timeinfo->tm_min));
  2106.     ods->write1(static_cast<uint8>(timeinfo->tm_sec));
  2107.     ods->write4(save_count);
  2108.     ods->write4(getGameTimeInSeconds());
  2109.  
  2110.     uint8 c = (has_cheated ? 1 : 0);
  2111.     ods->write1(c);
  2112.  
  2113.     // write game-specific info
  2114.     game->writeSaveInfo(ods);
  2115. }
  2116.  
  2117. bool GUIApp::saveGame(std::string filename, std::string desc,
  2118.                       bool ignore_modals)
  2119. {
  2120.     // Don't allow saving with Modals open
  2121.     if (!ignore_modals && desktopGump->FindGump<ModalGump>()) {
  2122.         pout << "Can't save: modal gump open." << std::endl;
  2123.         return false;
  2124.     }
  2125.  
  2126.     // Don't allow saving when avatar is dead.
  2127.     // (Avatar is flagged dead by usecode when you finish the game as well.)
  2128.     MainActor* av = getMainActor();
  2129.     if (!av || (av->getActorFlags() & Actor::ACT_DEAD)) {
  2130.         pout << "Can't save: game over." << std::endl;
  2131.         return false;
  2132.     }
  2133.  
  2134.     pout << "Saving..." << std::endl;
  2135.  
  2136.     pout << "Savegame file: " << filename << std::endl;
  2137.     pout << "Description: " << desc << std::endl;
  2138.  
  2139.     // Hack - don't save mouse over status for gumps
  2140.     Gump * gump = getGump(mouseOverGump);
  2141.     if (gump) gump->OnMouseLeft();
  2142.  
  2143.     ODataSource* ods = filesystem->WriteFile(filename);
  2144.     if (!ods) return false;
  2145.  
  2146.     save_count++;
  2147.  
  2148.     SavegameWriter* sgw = new SavegameWriter(ods);
  2149.     sgw->writeVersion(Pentagram::savegame_version);
  2150.     sgw->writeDescription(desc);
  2151.  
  2152.     // We'll make it 2KB initially
  2153.     OAutoBufferDataSource buf(2048);
  2154.  
  2155.     gameinfo->save(&buf);
  2156.     sgw->writeFile("GAME", &buf);
  2157.     buf.clear();
  2158.  
  2159.     writeSaveInfo(&buf);
  2160.     sgw->writeFile("INFO", &buf);
  2161.     buf.clear();
  2162.  
  2163.     kernel->save(&buf);
  2164.     sgw->writeFile("KERNEL", &buf);
  2165.     buf.clear();
  2166.  
  2167.     objectmanager->save(&buf);
  2168.     sgw->writeFile("OBJECTS", &buf);
  2169.     buf.clear();
  2170.  
  2171.     world->save(&buf);
  2172.     sgw->writeFile("WORLD", &buf);
  2173.     buf.clear();
  2174.  
  2175.     world->saveMaps(&buf);
  2176.     sgw->writeFile("MAPS", &buf);
  2177.     buf.clear();
  2178.  
  2179.     world->getCurrentMap()->save(&buf);
  2180.     sgw->writeFile("CURRENTMAP", &buf);
  2181.     buf.clear();
  2182.  
  2183.     ucmachine->saveStrings(&buf);
  2184.     sgw->writeFile("UCSTRINGS", &buf);
  2185.     buf.clear();
  2186.  
  2187.     ucmachine->saveGlobals(&buf);
  2188.     sgw->writeFile("UCGLOBALS", &buf);
  2189.     buf.clear();
  2190.  
  2191.     ucmachine->saveLists(&buf);
  2192.     sgw->writeFile("UCLISTS", &buf);
  2193.     buf.clear();
  2194.  
  2195.     save(&buf);
  2196.     sgw->writeFile("APP", &buf);
  2197.     buf.clear();
  2198.  
  2199.     sgw->finish();
  2200.  
  2201.     delete sgw;
  2202.  
  2203.     // Restore mouse over
  2204.     if (gump) gump->OnMouseOver();
  2205.  
  2206.     settingman->set("lastSave", filename);
  2207.  
  2208.     pout << "Done" << std::endl;
  2209.  
  2210.     return true;
  2211. }
  2212.  
  2213. void GUIApp::resetEngine()
  2214. {
  2215.     con.Print(MM_INFO, "-- Resetting Engine --\n");
  2216.  
  2217.     // kill music
  2218.     if (audiomixer) audiomixer->reset();
  2219.  
  2220.     // now, reset everything (order matters)
  2221.     world->reset();
  2222.     ucmachine->reset();
  2223.     // ObjectManager, Kernel have to be last, because they kill
  2224.     // all processes/objects
  2225.     objectmanager->reset();
  2226.     kernel->reset();
  2227.     palettemanager->resetTransforms();
  2228.  
  2229.     // Reset thet gumps
  2230.     desktopGump = 0;
  2231.     consoleGump = 0;
  2232.     gameMapGump = 0;
  2233.     scalerGump = 0;
  2234.     inverterGump = 0;
  2235.  
  2236.     textmodes.clear();
  2237.  
  2238.     // reset mouse cursor
  2239.     while (!cursors.empty()) cursors.pop();
  2240.     pushMouseCursor();
  2241.  
  2242.     kernel->addProcess(new JoystickCursorProcess(JOY1, 0, 1));
  2243.  
  2244.     timeOffset = -(sint32)Kernel::get_instance()->getFrameNum();
  2245.     inversion = 0;
  2246.     save_count = 0;
  2247.     has_cheated = false;
  2248.  
  2249.     con.Print(MM_INFO, "-- Engine Reset --\n");
  2250. }
  2251.  
  2252. void GUIApp::setupCoreGumps()
  2253. {
  2254.     con.Print(MM_INFO, "Setting up core game gumps...\n");
  2255.  
  2256.     Pentagram::Rect dims;
  2257.     screen->GetSurfaceDims(dims);
  2258.  
  2259.     con.Print(MM_INFO, "Creating Desktop...\n");
  2260.     desktopGump = new DesktopGump(0,0, dims.w, dims.h);
  2261.     desktopGump->InitGump(0);
  2262.     desktopGump->MakeFocus();
  2263.  
  2264.     con.Print(MM_INFO, "Creating ScalerGump...\n");
  2265.     scalerGump = new ScalerGump(0, 0, dims.w, dims.h);
  2266.     scalerGump->InitGump(0);
  2267.  
  2268.     Pentagram::Rect scaled_dims;
  2269.     scalerGump->GetDims(scaled_dims);
  2270.  
  2271.     con.Print(MM_INFO, "Creating Graphics Console...\n");
  2272.     consoleGump = new ConsoleGump(0, 0, dims.w, dims.h);
  2273.     consoleGump->InitGump(0);
  2274.     consoleGump->HideConsole();
  2275.    
  2276.     con.Print(MM_INFO, "Creating Inverter...\n");
  2277.     inverterGump = new InverterGump(0, 0, scaled_dims.w, scaled_dims.h);
  2278.     inverterGump->InitGump(0);
  2279.  
  2280.     con.Print(MM_INFO, "Creating GameMapGump...\n");
  2281.     gameMapGump = new GameMapGump(0, 0, scaled_dims.w, scaled_dims.h);
  2282.     gameMapGump->InitGump(0);
  2283.  
  2284.  
  2285.     // TODO: clean this up
  2286.     assert(desktopGump->getObjId() == 256);
  2287.     assert(scalerGump->getObjId() == 257);
  2288.     assert(consoleGump->getObjId() == 258);
  2289.     assert(inverterGump->getObjId() == 259);
  2290.     assert(gameMapGump->getObjId() == 260);
  2291.  
  2292.  
  2293.     for (uint16 i = 261; i < 384; ++i)
  2294.         objectmanager->reserveObjId(i);
  2295. }
  2296.  
  2297. bool GUIApp::newGame(const std::string &savegame)
  2298. {
  2299.     con.Print(MM_INFO, "Starting New Game...\n");
  2300.  
  2301.     resetEngine();
  2302.  
  2303.     setupCoreGumps();
  2304.  
  2305.     game->startGame();
  2306.  
  2307.     con.Print(MM_INFO, "Create Camera...\n");
  2308.     CameraProcess::SetCameraProcess(new CameraProcess(1)); // Follow Avatar
  2309.  
  2310.     con.Print(MM_INFO, "Create persistent Processes...\n");
  2311.     avatarMoverProcess = new AvatarMoverProcess();
  2312.     kernel->addProcess(avatarMoverProcess);
  2313.  
  2314.     kernel->addProcess(new HealProcess());
  2315.  
  2316.     kernel->addProcess(new SchedulerProcess());
  2317.  
  2318.     if (audiomixer) audiomixer->createProcesses();
  2319.  
  2320. //  av->teleport(40, 16240, 15240, 64); // central Tenebrae
  2321. //  av->teleport(3, 11391, 1727, 64); // docks, near gate
  2322. //  av->teleport(39, 16240, 15240, 64); // West Tenebrae
  2323. //  av->teleport(41, 12000, 15000, 64); // East Tenebrae
  2324. //  av->teleport(8, 14462, 15178, 48); // before entrance to Mythran's house
  2325. //  av->teleport(40, 13102,9474,48); // entrance to Mordea's throne room
  2326. //  av->teleport(54, 14783,5959,8); // shrine of the Ancient Ones; Hanoi
  2327. //  av->teleport(5, 5104,22464,48); // East road (tenebrae end)
  2328.  
  2329.     game->startInitialUsecode(savegame);
  2330.  
  2331.     settingman->set("lastSave", savegame);
  2332.  
  2333.     return true;
  2334. }
  2335.  
  2336. bool GUIApp::loadGame(std::string filename)
  2337. {
  2338.     con.Print(MM_INFO, "Loading...\n");
  2339.  
  2340.     IDataSource* ids = filesystem->ReadFile(filename);
  2341.     if (!ids) {
  2342.         Error("Can't load file", "Error Loading savegame " + filename);
  2343.         settingman->set("lastSave", "");
  2344.         return false;
  2345.     }
  2346.  
  2347.     Savegame* sg = new Savegame(ids);
  2348.     uint32 version = sg->getVersion();
  2349.     if (version == 0) {
  2350.         Error("Invalid or corrupt savegame", "Error Loading savegame " + filename);
  2351.         delete sg;
  2352.         settingman->set("lastSave", "");
  2353.         return false;
  2354.     }
  2355.  
  2356.     if (version == 1 || version > Pentagram::savegame_version) {
  2357.         char vstring[16];
  2358.         std::sprintf (vstring,"%i", version);
  2359.         Error(std::string("Unsupported savegame version (") + vstring + ")", "Error Loading savegame " + filename);
  2360.         delete sg;
  2361.         settingman->set("lastSave", "");
  2362.         return false;
  2363.     }
  2364.     IDataSource* ds;
  2365.     GameInfo saveinfo;
  2366.     ds = sg->getDataSource("GAME");
  2367.     bool ok = saveinfo.load(ds, version);
  2368.  
  2369.     if (!ok) {
  2370.         Error("Invalid or corrupt savegame: missing GameInfo", "Error Loading savegame " + filename);
  2371.         delete sg;
  2372.         return false;
  2373.     }
  2374.  
  2375.     if (!gameinfo->match(saveinfo)) {
  2376.         std::string message = "Game mismatch\n";
  2377.                     message+= "Running game: " + gameinfo->getPrintDetails()  + "\n";
  2378.                     message+= "Savegame    : " + saveinfo.getPrintDetails();
  2379.  
  2380. #ifdef DEBUG
  2381.         bool ignore;
  2382.         settingman->setDefault("ignore_savegame_mismatch", false);
  2383.         settingman->get("ignore_savegame_mismatch", ignore);
  2384.  
  2385.         if (!ignore)
  2386.         {
  2387.             Error(message, "Error Loading savegame " + filename);
  2388.             delete sg;
  2389.             return false;
  2390.         }
  2391.         perr << message << std::endl;
  2392. #else
  2393.         settingman->set("lastSave", "");
  2394.         Error(message,"Error Loading savegame " + filename);
  2395.         return false;
  2396. #endif
  2397.     }
  2398.  
  2399.     resetEngine();
  2400.  
  2401.     setupCoreGumps();
  2402.  
  2403.     // and load everything back (order matters)
  2404.     bool totalok = true;
  2405.  
  2406.     std::string message;
  2407.  
  2408.     // UCSTRINGS, UCGLOBALS, UCLISTS don't depend on anything else,
  2409.     // so load these first
  2410.     ds = sg->getDataSource("UCSTRINGS");
  2411.     ok = ucmachine->loadStrings(ds, version);
  2412.     totalok &= ok;
  2413.     perr << "UCSTRINGS: " << (ok ? "ok" : "failed") << std::endl;
  2414.     if (!ok) message += "UCSTRINGS: failed\n";
  2415.     delete ds;
  2416.  
  2417.     ds = sg->getDataSource("UCGLOBALS");
  2418.     ok = ucmachine->loadGlobals(ds, version);
  2419.     totalok &= ok;
  2420.     perr << "UCGLOBALS: " << (ok ? "ok" : "failed") << std::endl;
  2421.     if (!ok) message += "UCGLOBALS: failed\n";
  2422.     delete ds;
  2423.  
  2424.     ds = sg->getDataSource("UCLISTS");
  2425.     ok = ucmachine->loadLists(ds, version);
  2426.     totalok &= ok;
  2427.     perr << "UCLISTS: " << (ok ? "ok" : "failed")<< std::endl;
  2428.     if (!ok) message += "UCLISTS: failed\n";
  2429.     delete ds;
  2430.  
  2431.     // KERNEL must be before OBJECTS, for the egghatcher
  2432.     // KERNEL must be before APP, for the avatarMoverProcess
  2433.     ds = sg->getDataSource("KERNEL");
  2434.     ok = kernel->load(ds, version);
  2435.     totalok &= ok;
  2436.     perr << "KERNEL: " << (ok ? "ok" : "failed") << std::endl;
  2437.     if (!ok) message += "KERNEL: failed\n";
  2438.     delete ds;
  2439.  
  2440.     ds = sg->getDataSource("APP");
  2441.     ok = load(ds, version);
  2442.     totalok &= ok;
  2443.     perr << "APP: " << (ok ? "ok" : "failed") << std::endl;
  2444.     if (!ok) message += "APP: failed\n";
  2445.     delete ds;
  2446.  
  2447.     // WORLD must be before OBJECTS, for the egghatcher
  2448.     ds = sg->getDataSource("WORLD");
  2449.     ok = world->load(ds, version);
  2450.     totalok &= ok;
  2451.     perr << "WORLD: " << (ok ? "ok" : "failed") << std::endl;
  2452.     if (!ok) message += "WORLD: failed\n";
  2453.     delete ds;
  2454.  
  2455.     ds = sg->getDataSource("CURRENTMAP");
  2456.     ok = world->getCurrentMap()->load(ds, version);
  2457.     totalok &= ok;
  2458.     perr << "CURRENTMAP: " << (ok ? "ok" : "failed") << std::endl;
  2459.     if (!ok) message += "CURRENTMAP: failed\n";
  2460.     delete ds;
  2461.  
  2462.     ds = sg->getDataSource("OBJECTS");
  2463.     ok = objectmanager->load(ds, version);
  2464.     totalok &= ok;
  2465.     perr << "OBJECTS: " << (ok ? "ok" : "failed") << std::endl;
  2466.     if (!ok) message += "OBJECTS: failed\n";
  2467.     delete ds;
  2468.  
  2469.     ds = sg->getDataSource("MAPS");
  2470.     ok = world->loadMaps(ds, version);
  2471.     totalok &= ok;
  2472.     perr << "MAPS: " << (ok ? "ok" : "failed") << std::endl;
  2473.     if (!ok) message += "MAPS: failed\n";
  2474.     delete ds;
  2475.  
  2476.     if (!totalok) {
  2477.         Error(message, "Error Loading savegame " + filename, true);
  2478.         delete sg;
  2479.         return false;
  2480.     }
  2481.  
  2482.     pout << "Done" << std::endl;
  2483.  
  2484.     settingman->set("lastSave", filename);
  2485.  
  2486.     delete sg;
  2487.     return true;
  2488. }
  2489.  
  2490. void GUIApp::Error(std::string message, std::string title, bool exit_to_menu)
  2491. {
  2492.     if (title.empty()) title = exit_to_menu?"Fatal Game Error":"Error";
  2493.  
  2494.     perr << title << ": " << message << std::endl;
  2495.    
  2496.     error_message = message;
  2497.     error_title = title;
  2498.  
  2499.     if (exit_to_menu)
  2500.     {
  2501.         change_gamename = "pentagram";
  2502.         Kernel::get_instance()->killProcesses(0,6,false);
  2503.     }
  2504. }
  2505.  
  2506. Gump* GUIApp::getGump(uint16 gumpid)
  2507. {
  2508.     return p_dynamic_cast<Gump*>(ObjectManager::get_instance()->
  2509.                                  getObject(gumpid));
  2510. }
  2511.  
  2512. void GUIApp::addGump(Gump* gump)
  2513. {
  2514.     // TODO: At some point, this will have to _properly_ choose to
  2515.     // which 'layer' to add the gump: inverted, scaled or neither.
  2516.  
  2517.     assert(desktopGump);
  2518.  
  2519.     if (gump->IsOfType<ShapeViewerGump>() || gump->IsOfType<MiniMapGump>() ||
  2520.         gump->IsOfType<ConsoleGump>() || gump->IsOfType<ScalerGump>() ||
  2521.         gump->IsOfType<PentagramMenuGump>() || gump->IsOfType<MessageBoxGump>()// ||
  2522.         //(ttfoverrides && (gump->IsOfType<BarkGump>() ||
  2523.         //                gump->IsOfType<AskGump>()))
  2524.         )
  2525.     {
  2526. //      pout << "adding to desktopgump: "; gump->dumpInfo();
  2527.         desktopGump->AddChild(gump);
  2528.     }
  2529.     else if (gump->IsOfType<GameMapGump>())
  2530.     {
  2531. //      pout << "adding to invertergump: "; gump->dumpInfo();
  2532.         inverterGump->AddChild(gump);
  2533.     }
  2534.     else if (gump->IsOfType<InverterGump>())
  2535.     {
  2536. //      pout << "adding to scalergump: "; gump->dumpInfo();
  2537.         scalerGump->AddChild(gump);
  2538.     }
  2539.     else if (gump->IsOfType<DesktopGump>())
  2540.     {
  2541.     }
  2542.     else
  2543.     {
  2544. //      pout << "adding to scalergump: "; gump->dumpInfo();
  2545.         scalerGump->AddChild(gump);
  2546.     }
  2547. }
  2548.  
  2549. uint32 GUIApp::getGameTimeInSeconds()
  2550. {
  2551.     // 1 second per every 30 frames
  2552.     return (Kernel::get_instance()->getFrameNum()+timeOffset)/30; // constant!
  2553. }
  2554.  
  2555.  
  2556. void GUIApp::save(ODataSource* ods)
  2557. {
  2558.     uint8 s = (avatarInStasis ? 1 : 0);
  2559.     ods->write1(s);
  2560.  
  2561.     sint32 absoluteTime = Kernel::get_instance()->getFrameNum()+timeOffset;
  2562.     ods->write4(static_cast<uint32>(absoluteTime));
  2563.     ods->write2(avatarMoverProcess->getPid());
  2564.  
  2565.     Pentagram::Palette *pal = PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game);
  2566.     for (int i = 0; i < 12; i++) ods->write2(pal->matrix[i]);
  2567.     ods->write2(pal->transform);
  2568.  
  2569.     ods->write2(static_cast<uint16>(inversion));
  2570.  
  2571.     ods->write4(save_count);
  2572.  
  2573.     uint8 c = (has_cheated ? 1 : 0);
  2574.     ods->write1(c);
  2575. }
  2576.  
  2577. bool GUIApp::load(IDataSource* ids, uint32 version)
  2578. {
  2579.     avatarInStasis = (ids->read1() != 0);
  2580.  
  2581.     // no gump should be moused over after load
  2582.     mouseOverGump = 0;
  2583.  
  2584.     sint32 absoluteTime = static_cast<sint32>(ids->read4());
  2585.     timeOffset = absoluteTime - Kernel::get_instance()->getFrameNum();
  2586.  
  2587.     uint16 amppid = ids->read2();
  2588.     avatarMoverProcess = p_dynamic_cast<AvatarMoverProcess*>(Kernel::get_instance()->getProcess(amppid));
  2589.  
  2590.     sint16 matrix[12];
  2591.     for (int i = 0; i < 12; i++)
  2592.         matrix[i] = ids->read2();
  2593.  
  2594.     PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game, matrix);
  2595.     Pentagram::Palette *pal = PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game);
  2596.     pal->transform = static_cast<Pentagram::PalTransforms>(ids->read2());
  2597.  
  2598.     inversion = ids->read2();
  2599.  
  2600.     save_count = ids->read4();
  2601.  
  2602.     has_cheated = (ids->read1() != 0);
  2603.  
  2604.     return true;
  2605. }
  2606.  
  2607. //
  2608. // Console Commands
  2609. //
  2610.  
  2611. void GUIApp::ConCmd_saveGame(const Console::ArgvType &argv)
  2612. {
  2613.     if (argv.size()==1)
  2614.     {
  2615.         pout << "Usage: GUIApp::saveGame <filename>" << std::endl;
  2616.         return;
  2617.     }
  2618.  
  2619.     std::string filename = "@save/";
  2620.     filename += argv[1].c_str();
  2621.     GUIApp::get_instance()->saveGame(filename, argv[1]);
  2622. }
  2623.  
  2624. void GUIApp::ConCmd_loadGame(const Console::ArgvType &argv)
  2625. {
  2626.     if (argv.size()==1)
  2627.     {
  2628.         pout << "Usage: GUIApp::loadGame <filename>" << std::endl;
  2629.         return;
  2630.     }
  2631.  
  2632.     std::string filename = "@save/";
  2633.     filename += argv[1].c_str();
  2634.     GUIApp::get_instance()->loadGame(filename);
  2635. }
  2636.  
  2637. void GUIApp::ConCmd_newGame(const Console::ArgvType &argv)
  2638. {
  2639.     GUIApp::get_instance()->newGame(std::string());
  2640. }
  2641.  
  2642.  
  2643. void GUIApp::ConCmd_quit(const Console::ArgvType &argv)
  2644. {
  2645.     GUIApp::get_instance()->isRunning = false;
  2646. }
  2647.  
  2648. void GUIApp::ConCmd_drawRenderStats(const Console::ArgvType &argv)
  2649. {
  2650.     if (argv.size() == 1)
  2651.     {
  2652.         pout << "GUIApp::drawRenderStats = " << GUIApp::get_instance()->drawRenderStats << std::endl;
  2653.     }
  2654.     else
  2655.     {
  2656.         GUIApp::get_instance()->drawRenderStats = std::strtol(argv[1].c_str(), 0, 0) != 0;
  2657.     }
  2658. }
  2659.  
  2660. void GUIApp::ConCmd_engineStats(const Console::ArgvType &argv)
  2661. {
  2662.     Kernel::get_instance()->kernelStats();
  2663.     ObjectManager::get_instance()->objectStats();
  2664.     UCMachine::get_instance()->usecodeStats();
  2665.     World::get_instance()->worldStats();
  2666. }
  2667.  
  2668. void GUIApp::ConCmd_changeGame(const Console::ArgvType &argv)
  2669. {
  2670.     if (argv.size() == 1)
  2671.     {
  2672.         pout << "Current game is: " << GUIApp::get_instance()->gameinfo->name << std::endl;
  2673.     }
  2674.     else
  2675.     {
  2676.         GUIApp::get_instance()->changeGame(argv[1]);
  2677.     }
  2678. }
  2679.  
  2680. void GUIApp::ConCmd_listGames(const Console::ArgvType &argv)
  2681. {
  2682.     GUIApp *app = GUIApp::get_instance();
  2683.     std::vector<Pentagram::istring> games;
  2684.     games = app->settingman->listGames();
  2685.     std::vector<Pentagram::istring>::iterator iter;
  2686.     for (iter = games.begin(); iter != games.end(); ++iter) {
  2687.         Pentagram::istring game = *iter;
  2688.         GameInfo* info = app->getGameInfo(game);
  2689.         con.Printf(MM_INFO, "%s: ", game.c_str());
  2690.         if (info) {
  2691.             std::string details = info->getPrintDetails();
  2692.             con.Print(MM_INFO, details.c_str());
  2693.         } else {
  2694.             con.Print(MM_INFO, "(unknown)");
  2695.         }
  2696.         con.Print(MM_INFO, "\n");
  2697.     }
  2698. }
  2699.  
  2700. void GUIApp::ConCmd_setVideoMode(const Console::ArgvType &argv)
  2701. {
  2702.     int fullscreen = -1;
  2703.    
  2704.     //if (argv.size() == 4) {
  2705.     //  if (argv[3] == "fullscreen") fullscreen = 1;
  2706.     //  else fullscreen = 0;
  2707.     //} else
  2708.     if (argv.size() != 3)
  2709.     {
  2710.         //pout << "Usage: GUIApp::setVidMode width height [fullscreen/windowed]" << std::endl;
  2711.         pout << "Usage: GUIApp::setVidMode width height" << std::endl;
  2712.         return;
  2713.     }
  2714.  
  2715.     GUIApp::get_instance()->changeVideoMode(strtol(argv[1].c_str(), 0, 0), strtol(argv[2].c_str(), 0, 0), fullscreen);
  2716. }
  2717.  
  2718. void GUIApp::ConCmd_toggleFullscreen(const Console::ArgvType &argv)
  2719. {
  2720.     GUIApp::get_instance()->changeVideoMode(-1, -1, -2);
  2721. }
  2722.  
  2723. void GUIApp::ConCmd_toggleAvatarInStasis(const Console::ArgvType &argv)
  2724. {
  2725.     GUIApp * g = GUIApp::get_instance();
  2726.     g->toggleAvatarInStasis();
  2727.     pout << "avatarInStasis = " << g->isAvatarInStasis() << std::endl;
  2728. }
  2729.  
  2730. void GUIApp::ConCmd_togglePaintEditorItems(const Console::ArgvType &argv)
  2731. {
  2732.     GUIApp * g = GUIApp::get_instance();
  2733.     g->togglePaintEditorItems();
  2734.     pout << "paintEditorItems = " << g->isPaintEditorItems() << std::endl;
  2735. }
  2736.  
  2737. void GUIApp::ConCmd_toggleShowTouchingItems(const Console::ArgvType &argv)
  2738. {
  2739.     GUIApp * g = GUIApp::get_instance();
  2740.     g->toggleShowTouchingItems();
  2741.     pout << "ShowTouchingItems = " << g->isShowTouchingItems() << std::endl;
  2742. }
  2743.  
  2744. void GUIApp::ConCmd_closeItemGumps(const Console::ArgvType &argv)
  2745. {
  2746.     GUIApp * g = GUIApp::get_instance();
  2747.     g->getDesktopGump()->CloseItemDependents();
  2748. }
  2749.  
  2750. void GUIApp::ConCmd_memberVar(const Console::ArgvType &argv)
  2751. {
  2752.     if (argv.size() == 1) {
  2753.         pout << "Usage: GUIApp::memberVar <member> [newvalue] [updateini]" << std::endl;
  2754.         return;
  2755.     }
  2756.  
  2757.     GUIApp * g = GUIApp::get_instance();
  2758.  
  2759.     // Set the pointer to the correct type
  2760.     bool *b = 0;
  2761.     int *i = 0;
  2762.     std::string *str = 0;
  2763.     Pentagram::istring *istr = 0;
  2764.  
  2765.     // ini entry name if supported
  2766.     const char *ini = 0;
  2767.  
  2768.     if (argv[1] == "frameLimit") {
  2769.         b = &g->frameLimit;
  2770.         ini = "frameLimit";
  2771.     }
  2772.     else if (argv[1] == "frameSkip") {
  2773.         b = &g->frameSkip;
  2774.         ini = "frameSkip";
  2775.     }
  2776.     else if (argv[1] == "interpolate") {
  2777.         b = &g->interpolate;
  2778.         ini = "interpolate";
  2779.     }
  2780.     else {
  2781.         pout << "Unknown member: " << argv[1] << std::endl;
  2782.         return;
  2783.     }
  2784.  
  2785.     // Set the value
  2786.     if (argv.size() >= 3) {
  2787.         if (b) *b = (argv[2] == "yes" || argv[2] == "true");
  2788.         else if (istr) *istr = argv[2];
  2789.         else if (i) *i = std::strtol(argv[2].c_str(), 0, 0);
  2790.         else if (str) *str = argv[2];
  2791.  
  2792.         // Set config value
  2793.         if (argv.size() >= 4 && ini && *ini && (argv[3] == "yes" || argv[3] == "true"))
  2794.         {
  2795.             if (b) g->settingman->set(ini,*b);
  2796.             else if (istr) g->settingman->set(ini,*istr);
  2797.             else if (i) g->settingman->set(ini,*i);
  2798.             else if (str) g->settingman->set(ini,*str);
  2799.         }
  2800.     }
  2801.  
  2802.     // Print the value
  2803.     pout << "GuiApp::" << argv[1] << " = ";
  2804.     if (b) pout << ((*b)?"true":"false");
  2805.     else if (istr) pout << *istr;
  2806.     else if (i) pout << *i;
  2807.     else if (str) pout << *str;
  2808.     pout << std::endl;
  2809.  
  2810.     return;
  2811. }
  2812.  
  2813. //
  2814. // Intrinsics
  2815. //
  2816.  
  2817. uint32 GUIApp::I_makeAvatarACheater(const uint8* /*args*/,
  2818.                                     unsigned int /*argsize*/)
  2819. {
  2820.     GUIApp::get_instance()->makeCheater();
  2821.     return 0;
  2822. }
  2823.  
  2824. uint32 GUIApp::I_getCurrentTimerTick(const uint8* /*args*/,
  2825.                                         unsigned int /*argsize*/)
  2826. {
  2827.     // number of ticks of a 60Hz timer, with the default animrate of 30Hz
  2828.     return Kernel::get_instance()->getFrameNum()*2;
  2829. }
  2830.  
  2831. uint32 GUIApp::I_setAvatarInStasis(const uint8* args, unsigned int /*argsize*/)
  2832. {
  2833.     ARG_SINT16(stasis);
  2834.     get_instance()->setAvatarInStasis(stasis!=0);
  2835.     return 0;
  2836. }
  2837.  
  2838. uint32 GUIApp::I_getAvatarInStasis(const uint8* /*args*/, unsigned int /*argsize*/)
  2839. {
  2840.     if (get_instance()->avatarInStasis)
  2841.         return 1;
  2842.     else
  2843.         return 0;
  2844. }
  2845.  
  2846. uint32 GUIApp::I_getTimeInGameHours(const uint8* /*args*/,
  2847.                                         unsigned int /*argsize*/)
  2848. {
  2849.     // 900 seconds per game hour
  2850.     return get_instance()->getGameTimeInSeconds() / 900;
  2851. }
  2852.  
  2853. uint32 GUIApp::I_getTimeInMinutes(const uint8* /*args*/,
  2854.                                         unsigned int /*argsize*/)
  2855. {
  2856.     // 60 seconds per minute
  2857.     return get_instance()->getGameTimeInSeconds() / 60;
  2858. }
  2859.  
  2860. uint32 GUIApp::I_getTimeInSeconds(const uint8* /*args*/,
  2861.                                         unsigned int /*argsize*/)
  2862. {
  2863.     return get_instance()->getGameTimeInSeconds();
  2864. }
  2865.  
  2866. uint32 GUIApp::I_setTimeInGameHours(const uint8* args,
  2867.                                         unsigned int /*argsize*/)
  2868. {
  2869.     ARG_UINT16(newhour);
  2870.  
  2871.     // 1 game hour per every 27000 frames
  2872.     sint32  absolute = newhour*27000;
  2873.     get_instance()->timeOffset = absolute-Kernel::get_instance()->getFrameNum();
  2874.  
  2875.     return 0;
  2876. }
  2877.  
  2878. uint32 GUIApp::I_closeItemGumps(const uint8* args, unsigned int /*argsize*/)
  2879. {
  2880.     GUIApp* g = GUIApp::get_instance();
  2881.     g->getDesktopGump()->CloseItemDependents();
  2882.  
  2883.     return 0;
  2884. }
Advertisement
Add Comment
Please, Sign In to add comment