changeset 1823:24b70fa98474

Merge
author Grumpy7
date Wed, 09 Oct 2013 08:09:48 +0200
parents 5f9eeb7bf8e6 (current diff) 9442b7c19a64 (diff)
children 6788e58c1715
files UI/UiGame.cpp mm7_2.cpp mm7_data.cpp mm7_data.h
diffstat 27 files changed, 2064 insertions(+), 1428 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Oct 09 08:06:26 2013 +0200
+++ b/.hgignore	Wed Oct 09 08:09:48 2013 +0200
@@ -0,0 +1,4 @@
+syntax: glob
+Debug/
+Release/
+*.orig
--- a/AudioPlayer.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/AudioPlayer.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -1877,14 +1877,14 @@
 }
 
 //----- (004AB8CE) --------------------------------------------------------
-void AudioPlayer::Initialize(HWND hWnd)
+void AudioPlayer::Initialize()
 {
   //AudioPlayer *v2; // esi@1
   int v3; // ebx@1
   //_DIG_DRIVER *v4; // eax@1
   char v5; // dl@5
   _PROVIDER *v6; // eax@9
-  HWND v7; // ST00_4@9
+  //HWND v7; // ST00_4@9
   MixerChannel *pChannel; // edi@14
   _SAMPLE *v9; // eax@15
   //_REDBOOK *v10; // eax@19
@@ -1895,7 +1895,7 @@
 
   //v2 = this;
   v3 = 0;
-  this->hWindow = hWnd;
+  //this->hWindow = hWnd;
   this->hAILRedbook = 0;
   this->hDigDriver = 0;
   this->dword_0002AC = 0;
@@ -1926,11 +1926,12 @@
     ReadWindowsRegistryString("3DSoundProvider", p3DSoundProvider, 128u, "NONE");
     __debugbreak(); // audioplayer.cpp(1926): warning C4700: uninitialized local variable 'v5' used
     CheckA3DSupport(v5);
-    while ( AIL_enumerate_3D_providers(&v14, (HPROVIDER *)&hWnd, &Str1) )
+    HPROVIDER prov;
+    while ( AIL_enumerate_3D_providers(&v14, &prov, &Str1) )
     {
       if ( !strcmp(Str1, p3DSoundProvider) )
       {
-        if ( AIL_open_3D_provider((HPROVIDER)hWnd) )
+        if ( AIL_open_3D_provider(prov) )
         {
           bEAXSupported = 0;
           b3DSoundInitialized = 0;
@@ -1938,12 +1939,12 @@
         }
         else
         {
-          v6 = (_PROVIDER *)hWnd;
-          v7 = hWnd;
+          v6 = prov;
+          //v7 = prov;
           b3DSoundInitialized = 1;
           h3DSoundProvider = v6;
           uNum3DSamples = 4;
-          AIL_3D_provider_attribute((HPROVIDER)v7, "EAX environment selection", &v12);
+          AIL_3D_provider_attribute(prov, "EAX environment selection", &v12);
           if ( v12 != -1 )
             bEAXSupported = 1;
         }
--- a/AudioPlayer.h	Wed Oct 09 08:06:26 2013 +0200
+++ b/AudioPlayer.h	Wed Oct 09 08:09:48 2013 +0200
@@ -167,7 +167,7 @@
   void UpdateSounds();
   void StopChannels(int uStartChannel, int uEndChannel);
   void LoadAudioSnd();
-  void Initialize(HWND hWnd);
+  void Initialize();
   LSTATUS CheckA3DSupport(char a2);
   void Release();
   void FreeChannel(MixerChannel *pChannel);
@@ -189,7 +189,8 @@
   int sRedbookVolume;
   char p3DSoundProvider[128];
   unsigned int bPlayerReady;
-  HWND hWindow;
+  //HWND hWindow;
+  class OSWindow *window;
   struct _REDBOOK *hAILRedbook;
   struct _DIG_DRIVER *hDigDriver;
   int dword_0002AC;
--- a/GUIWindow.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/GUIWindow.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -2219,7 +2219,7 @@
   if ( GetCurrentMenuID() == -1 )
     GameUI_DrawFoodAndGold();
   if ( sub_4637E0_is_there_popup_onscreen() )
-    sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(0);
+    UI_OnMouseRightClick(0);
 }
 //----- (00415485) --------------------------------------------------------
 void DrawCopyrightWindow()
--- a/Game.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/Game.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -355,22 +355,8 @@
         pRenderer->Present();
         continue;
       }
-      if ( pVideoPlayer->pSmackerMovie && !SmackWait(pVideoPlayer->pSmackerMovie) )
-      {
-        pRenderer->BeginScene();
-        pMouse->DrawCursorToTarget();
-        pVideoPlayer->SmackUpdatePalette(pVideoPlayer->hWindow);
-        pMouse->_469EA4();
-        pRenderer->EndScene();
-      }
-      else if ( pVideoPlayer->pBinkMovie && !BinkWait(pVideoPlayer->pBinkMovie) )
-      {
-        pRenderer->BeginScene();
-        pMouse->DrawCursorToTarget();
-        pVideoPlayer->BinkUpdatePalette(pVideoPlayer->hWindow);
-        pMouse->_469EA4();
-        pRenderer->EndScene();
-      }
+
+      pVideoPlayer->_inlined_in_463149();
       
       pEventTimer->Update();
       pMiscTimer->Update();
@@ -755,11 +741,11 @@
 
 
   WriteWindowsRegistryInt("startinwindow", pRenderer->bWindowMode);
-  if ( GetWindowRect(hWnd, &Rect) && pRenderer->bWindowMode )
+  /*if ( GetWindowRect(hWnd, &Rect) && pRenderer->bWindowMode )
   {
     WriteWindowsRegistryInt("window X", Rect.left);
     WriteWindowsRegistryInt("window Y", Rect.top);
-  }
+  }*/
   WriteWindowsRegistryInt("valAlwaysRun", bAlwaysRun);
   pItemsTable->Release();
   pNPCStats->Release();
@@ -946,7 +932,7 @@
   //pThreadWardInstance = new ThreadWard;
   pThreadWardInstance = nullptr;
   pParticleEngine = new ParticleEngine;
-  pMouse = pMouseInstance = new Mouse(pThreadWardInstance);
+  pMouse = pMouseInstance = new Mouse;
   pLightmapBuilder = new LightmapBuilder;
   pVisInstance = new Vis;
   pStru6Instance = new stru6;
--- a/Indoor.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/Indoor.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -5179,14 +5179,14 @@
   {
     v19 = fixpoint_mul(a2, v8) + fixpoint_mul(a3, v29);
 
-    this->field_C = fixpoint_mul(v19, v28) + fixpoint_mul(a4, v9);
-    this->field_10 = fixpoint_mul(a3, v8) - fixpoint_mul(a2, v29);
+    this->angle_from_north = fixpoint_mul(v19, v28) + fixpoint_mul(a4, v9);
+    this->angle_from_west = fixpoint_mul(a3, v8) - fixpoint_mul(a2, v29);
     this->field_14 = fixpoint_mul(a4, v28) - fixpoint_mul(v19, v9);
   }
   else
   {
-    this->field_C = fixpoint_mul(a2, v8) + fixpoint_mul(a3, v29);
-    this->field_10 = fixpoint_mul(a3, v8) - fixpoint_mul(a2, v29);
+    this->angle_from_north = fixpoint_mul(a2, v8) + fixpoint_mul(a3, v29);
+    this->angle_from_west = fixpoint_mul(a3, v8) - fixpoint_mul(a2, v29);
     this->field_14 = a4;
   }
 
@@ -5194,26 +5194,26 @@
   {
     v21 = fixpoint_mul(a5, v8) + fixpoint_mul(a6, v29);
 
-    this->field_18 = fixpoint_mul(v21, v28) + fixpoint_mul(a7, v9);
-    this->field_1C = fixpoint_mul(a6, v8) - fixpoint_mul(a5, v29);
+    this->angle_from_east = fixpoint_mul(v21, v28) + fixpoint_mul(a7, v9);
+    this->angle_from_south = fixpoint_mul(a6, v8) - fixpoint_mul(a5, v29);
     this->field_20 = fixpoint_mul(a7, v28) - fixpoint_mul(v21, v9);
   }
   else
   {
-    this->field_18 = fixpoint_mul(a5, v8) + fixpoint_mul(a6, v29);
-    this->field_1C = fixpoint_mul(a6, v8) - fixpoint_mul(a5, v29);
+    this->angle_from_east = fixpoint_mul(a5, v8) + fixpoint_mul(a6, v29);
+    this->angle_from_south = fixpoint_mul(a6, v8) - fixpoint_mul(a5, v29);
     this->field_20 = a7;
   }
 
-  this->field_18 = -this->field_18;
-  this->field_1C = -this->field_1C;
+  this->angle_from_east = -this->angle_from_east;
+  this->angle_from_south = -this->angle_from_south;
   this->field_20 = -this->field_20;
 
-  this->field_24 = fixpoint_dot(this->field_C,  this->field_0_party_dir_x,
-                                this->field_10, this->field_4_party_dir_y,
+  this->field_24 = fixpoint_dot(this->angle_from_north,  this->field_0_party_dir_x,
+                                this->angle_from_west, this->field_4_party_dir_y,
                                 this->field_14, this->field_8_party_dir_z);
-  this->field_28 = fixpoint_dot(this->field_18, this->field_0_party_dir_x,
-                                this->field_1C, this->field_4_party_dir_y,
+  this->field_28 = fixpoint_dot(this->angle_from_east, this->field_0_party_dir_x,
+                                this->angle_from_south, this->field_4_party_dir_y,
                                 this->field_20, this->field_8_party_dir_z);
 }
 //----- (00407A1C) --------------------------------------------------------
--- a/Mouse.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/Mouse.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -57,8 +57,6 @@
 //----- (00469903) --------------------------------------------------------
 void Mouse::SetCursorBitmap(const char *pName)
 {
-  struct tagPOINT Point; // [sp+14h] [bp-8h]@20
-
   if ( !this->bInitialized || !pName )
     return;
   if ( _stricmp("MICON2", pName) )
@@ -84,17 +82,9 @@
     }
     return;
   }
-  this->bActive = 0;
+  this->bActive = false;
   this->field_C = 1;
-  if ( !strcmp(pName, "MICON1") )
-    SetClassLongA(hWnd, GCL_HCURSOR, (LONG)LoadCursorA(GetModuleHandleW(nullptr), "Arrow"));
-  else if ( !strcmp(pName, "MICON2") )
-    SetClassLongA(hWnd, -12, (LONG)LoadCursorA(GetModuleHandleW(nullptr), "Target"));
-  else if ( !strcmp(pName, "MICON3") )
-    SetClassLongA(hWnd, -12, (LONG)LoadCursorA(0, (LPCSTR)IDC_WAIT));
-  GetCursorPos(&Point);
-  ClientToScreen(hWnd,&Point);
-  SetCursorPos(Point.x, Point.y);
+  window->SetCursor(pName);
 }
 // 506128: using guessed type int areWeLoadingTexture;
 
@@ -118,7 +108,7 @@
   {*/
     GetCursorPos(&Point);
     if ( pRenderer->bWindowMode )
-      ScreenToClient(hWnd, &Point);
+      ScreenToClient(window->GetApiHandle(), &Point);
     result = Point.y;
     v2 = Point.x;
   //}
@@ -203,11 +193,11 @@
 }
 
 //----- (00469C65) --------------------------------------------------------
-void Mouse::Initialize(HWND hWnd)
+void Mouse::Initialize(OSWindow *window)
 {
-  this->hWnd = hWnd;
-  this->bActive = 0;
-  this->bInitialized = 1;
+  this->window = window;
+  this->bActive = false;
+  this->bInitialized = true;
   this->pCursorBitmapPos.x = 0;
   this->pCursorBitmapPos.y = 0;
   this->uMouseClickX = 0;
@@ -522,11 +512,11 @@
     y = pY;
     x = pX;
   }
-  if ( pCurrentScreen != SCREEN_GAME || !dword_507B98_ctrl_pressed )
+  if ( pCurrentScreen != SCREEN_GAME)// || !dword_507B98_ctrl_pressed ) // stealing cursor
     goto LABEL_30;
   v4 = GetCurrentMenuID();
   x = pX;
-  if ( (v4 & 0x80000000u) == 0
+  if ( v4 != 0xFFFFFFFF
     || (signed int)pX < (signed int)pViewport->uViewportTL_X
     || (signed int)pX > (signed int)pViewport->uViewportBR_X )
   {
--- a/Mouse.h	Wed Oct 09 08:06:26 2013 +0200
+++ b/Mouse.h	Wed Oct 09 08:09:48 2013 +0200
@@ -1,5 +1,5 @@
 #pragma once
-#include "OSAPI.h"
+#include "OSWindow.h"
 
 #include "VectorTypes.h"
 
@@ -46,11 +46,11 @@
 {
 public:
   //----- (00467E4E) --------------------------------------------------------
-  inline Mouse(void/*ThreadWard*/ *pWard)
+  inline Mouse():
+    window(nullptr)
   {
     uCursorTextureID = 0;
     uCursorTextureID_2 = 0;
-    hWnd = 0;
     pCursorBitmap_sysmem = 0;
     field_34 = 0;
     pCursorBitmap2_sysmem = 0;
@@ -69,7 +69,7 @@
   void AllocCursorSystemMem();
   void *DoAllocCursorMem();
   POINT *GetCursorPos(POINT *p);
-  void Initialize(HWND hWnd);
+  void Initialize(OSWindow *window);
   void SetActive(bool active);
   void Deactivate();
   void DrawCursor();
@@ -92,7 +92,8 @@
   int field_20;
   unsigned int uCursorTextureID;
   unsigned int uCursorTextureID_2;
-  HWND hWnd;
+  //HWND hWnd;
+  OSWindow *window;
   unsigned __int16 *pCursorBitmap_sysmem;
   int field_34;
   unsigned __int8 *pCursorBitmap2_sysmem;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NewUI/Core/UIControl.h	Wed Oct 09 08:09:48 2013 +0200
@@ -0,0 +1,75 @@
+#pragma once
+#include <list>
+
+class UIControl
+{
+  public:
+    virtual void Show() = 0;
+
+    virtual bool Focused() = 0;
+
+    // Events
+    virtual bool OnKey(int key)
+    {
+      for (auto i = children.begin(); i != children.end(); ++i)
+        if ((*i)->OnKey(key))
+          return true;
+      return false;
+    }
+
+    virtual bool OnMouseLeftClick(int x, int y)
+    {
+      for (auto i = children.begin(); i != children.end(); ++i)
+        if ((*i)->OnMouseLeftClick(x, y))
+          return true;
+      return false;
+    }
+
+    virtual bool OnMouseRightClick(int x, int y)
+    {
+      for (auto i = children.begin(); i != children.end(); ++i)
+        if ((*i)->OnMouseRightClick(x, y))
+          return true;
+      return false;
+    }
+
+    virtual bool OnMouseEnter()
+    {
+      for (auto i = children.begin(); i != children.end(); ++i)
+        if ((*i)->OnMouseEnter())
+          return true;
+      return false;
+    }
+
+    virtual bool OnMouseLeave()
+    {
+      for (auto i = children.begin(); i != children.end(); ++i)
+        if ((*i)->OnMouseLeave())
+          return true;
+      return false;
+    }
+
+    // Container
+    virtual bool AddControl(UIControl *ctrl)
+    {
+      if (std::find(children.begin(), children.end(), ctrl) == children.end())
+      {
+        children.push_back(ctrl);
+        return true;
+      }
+      return false;
+    }
+
+    virtual bool RemoveControl(UIControl *ctrl)
+    {
+      auto i = std::find(children.begin(), children.end(), ctrl);
+
+      children.remove(ctrl);
+      if (i != children.end())
+        return true;
+      return false;
+    }
+
+  protected:
+    std::list<UIControl *> children;
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NewUI/MainMenu.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -0,0 +1,44 @@
+#include "MainMenu.h"
+
+
+bool MainMenuWindow::OnMouseLeftClick(int x, int y)
+{
+  if (UIControl::OnMouseLeftClick(x, y))
+    return true;
+  return false;
+}
+
+bool MainMenuWindow::OnMouseRightClick(int x, int y)
+{
+  if (UIControl::OnMouseRightClick(x, y))
+    return true;
+  return false;
+}
+
+bool MainMenuWindow::OnKey(int key)
+{
+  if (UIControl::OnKey(key))
+    return true;
+  return false;
+}
+
+
+void MainMenuWindow::Show() {}
+bool MainMenuWindow::Focused() {return false;}
+
+bool MainMenuWindow::Initialize()
+{
+  return true;
+}
+
+MainMenuWindow *MainMenuWindow::Create()
+{
+  auto window = new MainMenuWindow;
+  if (window)
+    if (!window->Initialize())
+    {
+      delete window;
+      window = nullptr;
+    }
+  return window;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NewUI/MainMenu.h	Wed Oct 09 08:09:48 2013 +0200
@@ -0,0 +1,28 @@
+#pragma once
+#include "Core/UIControl.h"
+
+
+class MainMenuWindow: public UIControl
+{
+  public:
+    static MainMenuWindow *Create();
+
+    bool Initialize();
+
+    // UIControl
+    virtual void Show() override;
+    
+    // UIControl
+    virtual bool Focused() override;
+    
+    // UIControl
+    virtual bool OnKey(int key) override;
+    // UIControl
+    virtual bool OnMouseLeftClick(int x, int y) override;
+    // UIControl
+    virtual bool OnMouseRightClick(int x, int y) override;
+    // UIControl
+    //virtual bool OnMouseEnter() override;
+    // UIControl
+    //virtual bool OnMouseLeave() override;
+};
\ No newline at end of file
--- a/OSAPI.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/OSAPI.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -32,7 +32,6 @@
   delete pVersion;
   pVersion = nullptr;
 
-  SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
   if (hPrevWindow)
     SetActiveWindow(hPrevWindow);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OSWindow.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -0,0 +1,781 @@
+#include "OSWindow.h"
+#include "mm7_data.h"
+#include "Arcomage.h"
+#include "AudioPlayer.h"
+#include "VideoPlayer.h"
+#include "Mouse.h"
+#include "Time.h"
+#include "GUIWindow.h"
+#include "Party.h"
+#include "Game.h"
+#include "IndoorCameraD3D.h"
+#include "Keyboard.h"
+#include "Render.h"
+#include "Viewport.h"
+#include "Vis.h"
+#include "Texts.h"
+#include "AIL.h"
+#include "Bink_Smacker.h"
+#include "ErrorHandling.h"
+
+
+bool OSWindow::OnMouseLeftClick(int x, int y)
+{
+  if (UIControl::OnMouseLeftClick(x, y))
+    return true;
+
+  if (pVideoPlayer->pVideoFrame.pPixels)
+    pVideoPlayer->bStopBeforeSchedule = true;
+
+  pMouse->SetMouseClick(x, y);
+
+  if (GetCurrentMenuID() == MENU_CREATEPARTY)
+    UI_OnKeyDown(VK_SELECT);
+
+  if (pGame)
+    pGame->PickMouse(512.0, x, y, false, &vis_sprite_filter_3, &vis_door_filter);
+
+  UI_OnMouseLeftClick(0);
+  return true;
+}
+
+bool OSWindow::OnMouseRightClick(int x, int y)
+{
+  if (UIControl::OnMouseRightClick(x, y))
+    return true;
+
+  if (pVideoPlayer->pVideoFrame.pPixels)
+    pVideoPlayer->bStopBeforeSchedule = true;
+
+  pMouse->SetMouseClick(x, y);
+
+  if (pGame)
+    pGame->PickMouse(pGame->pIndoorCameraD3D->GetPickDepth(), x, y, 0, &vis_sprite_filter_2, &vis_door_filter);
+
+  UI_OnMouseRightClick(0);
+  return true;
+}
+
+
+bool OSWindow::WinApiMessageProc(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT *result)
+{
+  switch (msg)
+  {
+    case WM_KEYUP:
+    {
+      OnKey(wparam);
+      return *result = 0, true;
+    }
+
+    case WM_SIZING: return *result = 1, true;
+    case WM_WINDOWPOSCHANGED:
+      if (pVideoPlayer && pVideoPlayer->AnyMovieLoaded() && pVideoPlayer->pBinkBuffer)
+        BinkBufferSetOffset(pVideoPlayer->pBinkBuffer, 0, 0);
+      return false;
+
+    case WM_CHAR:
+      if (!pKeyActionMap->_459F10(wparam) && !viewparams->field_4C)
+        GUI_HandleHotkey(wparam);
+      return false;
+
+    case WM_DESTROY:
+      ExitProcess(GetLastError());
+    //  SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+    //  PostQuitMessage(0);
+    //  return 0;
+
+    //case WM_DEVICECHANGE:
+    //{
+    //  if (wParam == 0x8000)          // CD or some device has been inserted - notify InsertCD dialog
+    //    PostMessageW(hInsertCDWindow, WM_USER + 1, 0, 0);
+    //  return 0;
+    //}
+
+    case WM_COMMAND:
+      if (OnOSMenu(wparam))
+        return *result = 0, true;
+    return false;
+
+    case WM_LBUTTONDOWN:
+    {
+      if (pArcomageGame->bGameInProgress)
+      {
+        pArcomageGame->stru1.field_0 = 7;
+        ArcomageGame::OnMouseClick(0, true);
+        return false;
+      }
+
+      OnMouseLeftClick(LOWORD(lparam), HIWORD(lparam));
+    }
+    return false;
+
+
+    case WM_RBUTTONDOWN:
+    {
+      if (pArcomageGame->bGameInProgress)
+      {
+        pArcomageGame->stru1.field_0 = 8;
+        ArcomageGame::OnMouseClick(1, true);
+        return false;
+      }
+
+      OnMouseRightClick(LOWORD(lparam), HIWORD(lparam));
+    }
+    return false;
+
+
+    case WM_LBUTTONUP:
+      if ( !pArcomageGame->bGameInProgress )
+      {
+        back_to_game();
+        return false;
+      }
+      pArcomageGame->stru1.field_0 = 3;
+      ArcomageGame::OnMouseClick(0, 0);
+    return false;
+
+    case WM_RBUTTONUP:
+      if ( !pArcomageGame->bGameInProgress )
+      {
+        back_to_game();
+        return false;
+      }
+      pArcomageGame->stru1.field_0 = 4;
+      ArcomageGame::OnMouseClick(1, false);
+    return false;
+
+    case WM_LBUTTONDBLCLK:
+    {
+      if ( pArcomageGame->bGameInProgress )
+      {
+        pArcomageGame->stru1.field_0 = 7;
+        return false;
+      }
+
+      OnMouseLeftClick(LOWORD(lparam), HIWORD(lparam));
+    }
+    return false;
+
+    case WM_RBUTTONDBLCLK:
+    {
+      if (pArcomageGame->bGameInProgress)
+      {
+        pArcomageGame->stru1.field_0 = 8;
+        return false;
+      }
+
+      OnMouseRightClick(LOWORD(lparam), HIWORD(lparam));
+    }
+    return false;
+
+    /*case WM_MBUTTONDOWN:
+      if (pRenderer->pRenderD3D && pGame)
+      {
+        pGame->PickMouse(pGame->pIndoorCameraD3D->GetPickDepth(), LOWORD(lParam), HIWORD(lParam), 1, &vis_sprite_filter_3, &vis_face_filter);
+      }
+      return false;*/
+
+    case WM_MOUSEMOVE:
+      if ( pArcomageGame->bGameInProgress )
+      {
+        ArcomageGame::OnMouseMove(LOWORD(lparam), HIWORD(lparam));
+        ArcomageGame::OnMouseClick(0, wparam == MK_LBUTTON);
+        ArcomageGame::OnMouseClick(1, wparam == MK_RBUTTON);
+      }
+      else if (pMouse)
+        pMouse->SetMouseClick(LOWORD(lparam), HIWORD(lparam));
+    return false;
+
+    case WM_SYSCOMMAND:
+      if ( wparam == SC_SCREENSAVE || wparam == SC_MONITORPOWER )
+        return *result = 0, true;
+      return false;
+
+    case WM_KEYDOWN:
+      if ( uGameMenuUI_CurentlySelectedKeyIdx != -1 )
+      {
+        pKeyActionMap->_459F10(wparam);
+        return false;
+      }
+      if ( !pArcomageGame->bGameInProgress )
+      {
+        if ( pVideoPlayer->pVideoFrame.pPixels )
+          pVideoPlayer->bStopBeforeSchedule = 1;
+        if ( wparam == VK_RETURN )
+        {
+          if ( !viewparams->field_4C )
+            UI_OnKeyDown(wparam);
+          return 0;
+        }
+        if ( wparam == VK_ESCAPE )
+        {
+          pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, window_SpeakInHouse != 0, 0);
+          return 0;
+        }
+        if ( wparam <= VK_HOME )
+          return 0;
+        if ( wparam > VK_DOWN )
+        {
+          if ( wparam != VK_F4 || pVideoPlayer->AnyMovieLoaded() )
+            return 0;
+
+          // F4 - toggle fullscreen
+          SendMessageW(api_handle, WM_COMMAND, 104, 0);
+          return 0;
+        }
+        if ( wparam >= VK_LEFT && wparam <= VK_DOWN )
+        {
+          if ( pCurrentScreen != SCREEN_GAME && pCurrentScreen != SCREEN_MODAL_WINDOW )
+          {
+            if ( !viewparams->field_4C )
+              UI_OnKeyDown(wparam);
+            return 0;
+          }
+        }
+        if ( pCurrentScreen != SCREEN_GAME && pCurrentScreen != SCREEN_MODAL_WINDOW )
+          return 0;
+      }
+
+      pArcomageGame->stru1.field_0 = 1;
+
+      set_stru1_field_8_InArcomage(MapVirtualKey(wparam, MAPVK_VK_TO_CHAR));
+      if ( wparam == 27 )
+      {
+        pArcomageGame->GameOver = 1;
+        pArcomageGame->field_F4 = 1;
+        pArcomageGame->uGameResult = 2;
+        pArcomageGame->field_B0 = -2;
+        return false;
+      }
+      if ( wparam != 114 )
+      {
+        if ( wparam == 115 && !pVideoPlayer->AnyMovieLoaded() )
+          SendMessage(api_handle, WM_COMMAND, 104, 0);
+        return false;
+      }
+      SendMessageW(api_handle, WM_COMMAND, 103, 0);
+      return *result = 0, true;
+
+    case WM_ACTIVATEAPP:
+      if ( wparam && (GetForegroundWindow() == api_handle || GetForegroundWindow() == hInsertCDWindow) )
+      {
+        if ( BYTE1(dword_6BE364_game_settings_1) & 1 )
+        {
+          dword_4E98BC_bApplicationActive = 1;
+          if ( pRenderer->bWindowMode )
+          {
+            HDC hDC = GetDC(api_handle);
+            int bitsPerPixel = GetDeviceCaps(hDC, BITSPIXEL);
+            int planes = GetDeviceCaps(hDC, PLANES);
+            ReleaseDC(api_handle, hDC);
+            if (bitsPerPixel != 16 || planes != 1)
+              Error(pGlobalTXT_LocalizationStrings[62]);
+          }
+          BYTE1(dword_6BE364_game_settings_1) &= 0xFEu;
+
+          if ( pArcomageGame->bGameInProgress )
+          {
+            pArcomageGame->field_F9 = 1;
+          }
+          else
+          {
+            if ( BYTE1(dword_6BE364_game_settings_1) & 2 )
+              BYTE1(dword_6BE364_game_settings_1) &= 0xFDu;
+            else
+              pEventTimer->Resume();
+            if ( BYTE1(dword_6BE364_game_settings_1) & 4 )
+              BYTE1(dword_6BE364_game_settings_1) &= 0xFBu;
+            else
+              pMiscTimer->Resume();
+
+            viewparams->bRedrawGameUI = true;
+            if ( pVideoPlayer->pSmackerMovie )
+            {
+              pRenderer->RestoreFrontBuffer();
+              pRenderer->_4A184C();
+              pVideoPlayer->_4BF5B2();
+            }
+          }
+          if ( pAudioPlayer->hAILRedbook && !bGameoverLoop && !pVideoPlayer->pSmackerMovie )
+            AIL_redbook_resume(pAudioPlayer->hAILRedbook);
+        }
+      }
+      else
+      {
+        if (!(dword_6BE364_game_settings_1 & 0x100))
+        {
+          dword_4E98BC_bApplicationActive = 0;
+          if ( (pVideoPlayer->pSmackerMovie || pVideoPlayer->pBinkMovie) && pVideoPlayer->bPlayingMovie )
+            pVideoPlayer->bStopBeforeSchedule = 1;
+
+          if (/*pRenderer->bUserDirect3D && */pRenderer->uAcquiredDirect3DDevice == 1)
+            SetWindowPos(api_handle, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x18u);
+          ClipCursor(0);
+          dword_6BE364_game_settings_1 |= 0x100u;
+          if ( pEventTimer->bPaused )
+            BYTE1(dword_6BE364_game_settings_1) |= 2u;
+          else
+            pEventTimer->Pause();
+          if ( pMiscTimer->bPaused )
+            BYTE1(dword_6BE364_game_settings_1) |= 4u;
+          else
+            pMiscTimer->Pause();
+
+          pAudioPlayer->StopChannels(-1, -1);
+          if ( pAudioPlayer->hAILRedbook )
+            AIL_redbook_pause(pAudioPlayer->hAILRedbook);
+        }
+      }
+      return *result = 0, true;
+
+    case WM_SETFOCUS:
+      dword_4E98BC_bApplicationActive = 0;
+      if (pRenderer)
+      {
+        if (/*pRenderer->bUserDirect3D && */pRenderer->uAcquiredDirect3DDevice == 1)
+          SetWindowPos(api_handle, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x18u);
+      }
+      ClipCursor(0);
+      return false;
+
+    case WM_KILLFOCUS:
+      dword_4E98BC_bApplicationActive = 1;
+      return false;
+
+    case WM_PAINT:
+      if (pRenderer)
+      {
+        if ( !GetUpdateRect(api_handle, 0, 0) || !dword_4E98BC_bApplicationActive && !pRenderer->bWindowMode )
+          return *result = 0, true;
+      }
+      if (!api_handle || !pRenderer)
+        return false;
+      PAINTSTRUCT Paint;
+      BeginPaint(api_handle, &Paint);
+      if ( pArcomageGame->bGameInProgress )
+      {
+        pArcomageGame->field_F9 = 1;
+      }
+      else
+      {
+        if (/*!pRenderer->pRenderD3D && !pRenderer->UsingDirect3D() ||*/ !AreRenderSurfacesOk())
+        {
+          EndPaint(api_handle, &Paint);
+          return *result = 0, true;
+        }
+      }
+      pRenderer->Present();
+      EndPaint(api_handle, &Paint);
+      return *result = 0, true;
+
+  }
+  return false;
+}
+
+
+
+bool OSWindow::Initialize(const wchar_t *title, int window_width, int window_height)
+{
+  WNDCLASSEXW wcxw;
+  wcxw.cbClsExtra = 0;
+  wcxw.cbSize = sizeof(wcxw);
+  wcxw.cbWndExtra = 0;
+  wcxw.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
+  wcxw.hCursor = nullptr;
+  wcxw.hIcon = wcxw.hIconSm = nullptr;
+  wcxw.hInstance = GetModuleHandleW(nullptr);
+  wcxw.lpfnWndProc = WinApiMsgRouter;
+  wcxw.lpszClassName = L"M&MTrilogy";
+  wcxw.lpszMenuName = nullptr;
+  wcxw.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+  if (!RegisterClassExW(&wcxw))
+    return false;
+
+  api_handle = CreateWindowExW(0, wcxw.lpszClassName, title,
+                               0,
+                               0, 0, window_width, window_height, nullptr,
+                               nullptr, wcxw.hInstance, this);
+  if (!api_handle)
+  {
+    UnregisterClassW(wcxw.lpszClassName, wcxw.hInstance);
+    return false;
+  }
+
+  SetWindowedMode(window_width, window_height);
+  Show();
+
+  SetActiveWindow(api_handle);
+
+  MSG msg;
+  while (PeekMessageW(&msg, api_handle, 0, 0, PM_REMOVE))
+  {
+    TranslateMessage(&msg);
+    DispatchMessageW(&msg);
+  }
+
+  return true;
+}
+
+
+
+
+OSWindow *OSWindow::Create(const wchar_t *title, int window_width, int window_height)
+{
+  auto window = new OSWindow;
+  if (window)
+    if (!window->Initialize(title, window_width, window_height))
+    {
+      delete window;
+      window = nullptr;
+    }
+
+  return window;
+}
+
+
+
+LRESULT __stdcall OSWindow::WinApiMsgRouter(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+  if (msg == WM_NCCREATE)
+  {
+    auto cs = (CREATESTRUCTA *)(lparam);
+    auto window = (OSWindow *)cs->lpCreateParams;
+
+    SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)window);
+    return DefWindowProcW(hwnd, msg, wparam, lparam);
+  }
+
+  auto window = (OSWindow *)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
+  if (window && window->api_handle == hwnd)
+  {
+    LPARAM result;
+    if (window->WinApiMessageProc(msg, wparam, lparam, &result))
+      return result;
+  }
+  return DefWindowProcW(hwnd, msg, (WPARAM)wparam, (LPARAM)lparam);
+}
+
+
+void OSWindow::Show()
+{
+  ShowWindow(api_handle, SW_SHOWNORMAL);
+  UpdateWindow(api_handle);
+}
+
+
+void OSWindow::SetCursor(const char *cursor_name)
+{
+  POINT cursor_pos;
+  GetCursorPos(&cursor_pos);
+
+  if (!strcmp(cursor_name, "MICON1") )
+    SetClassLongPtrW(api_handle, GCLP_HCURSOR, (LONG)LoadCursorW(GetModuleHandleW(nullptr), IDC_ARROW));
+  else if (!strcmp(cursor_name, "MICON2") )
+    SetClassLongPtrW(api_handle, GCLP_HCURSOR, (LONG)LoadCursorW(GetModuleHandleW(nullptr), L"Target"));
+  else if (!strcmp(cursor_name, "MICON3") )
+    SetClassLongPtrW(api_handle, GCLP_HCURSOR, (LONG)LoadCursorW(GetModuleHandleW(nullptr), IDC_WAIT));
+
+  //ClientToScreen(api_handle, &cursor_pos);
+  SetCursorPos(cursor_pos.x, cursor_pos.y);
+}
+
+void OSWindow::SetFullscreenMode()
+{
+  SetMenu(api_handle, nullptr);
+  SetWindowLongW(api_handle, GWL_EXSTYLE, WS_EX_TOPMOST);
+  SetWindowLongW(api_handle, GWL_STYLE,   WS_VISIBLE | WS_POPUP);
+
+  SetWindowPos(api_handle, HWND_TOP, 0, 0, -1, -1, SWP_NOSIZE | SWP_SHOWWINDOW);
+}
+
+void OSWindow::SetWindowedMode(int new_window_width, int new_window_height)
+{
+  SetWindowLongW(api_handle, GWL_EXSTYLE, 0);
+  SetWindowLongW(api_handle, GWL_STYLE,   WS_VISIBLE | WS_OVERLAPPEDWINDOW);
+
+  RECT rcWindow;
+  GetWindowRect(api_handle, &rcWindow);
+
+  RECT rcClient;
+  GetClientRect(api_handle, &rcClient);
+
+  int window_borders_width = (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left),
+      window_borders_height = (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top);
+  int window_total_width = new_window_width + window_borders_width,
+      window_total_height = new_window_height + window_borders_height;
+
+  #ifdef _DEBUG
+    if (!GetMenu(api_handle))
+      window_total_height += GetSystemMetrics(SM_CYMENU);
+  #endif
+  MoveWindow(api_handle, (GetSystemMetrics(SM_CXSCREEN) - window_total_width) / 2,
+                         (GetSystemMetrics(SM_CYSCREEN) - window_total_height) / 2,
+                         window_total_width,
+                         window_total_height, 0);
+  #ifdef _DEBUG
+    static HMENU debug_menu = CreateDebugMenuPanel();
+    SetMenu(api_handle, debug_menu);
+  #endif
+}
+
+
+
+
+HMENU OSWindow::CreateDebugMenuPanel()
+{
+  HMENU menu = CreateMenu();
+  {
+    HMENU file = CreatePopupMenu();
+    AppendMenuW(menu, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)file, L"&File");
+    {
+      AppendMenuW(file, MF_ENABLED | MF_STRING, 40001, L"Exit");
+    }
+
+    HMENU debug = CreatePopupMenu();
+    AppendMenuW(menu, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug, L"&Debug");
+    {
+      HMENU debug_party = CreatePopupMenu();
+      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_party, L"&Party");
+      {
+        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40007, L"Give Gold (10 000)");
+        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40008, L"Give Exp (20 000)");
+        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40059, L"Give Skills (50 each)");
+        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40013, L"Remove Gold");
+
+        HMENU debug_party_setconditions = CreatePopupMenu();
+        AppendMenuW(debug_party, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_party_setconditions, L"Set Condition");
+        {
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40044, L"Afraid");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40043, L"Asleep");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40037, L"Curse");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40036, L"Disease1");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40035, L"Disease2");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40034, L"Disease3");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40041, L"Dead");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40039, L"Drunk");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40042, L"Eradicated");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40038, L"Insane");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40045, L"Paralyzed");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40033, L"Poison1");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40032, L"Poison2");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40031, L"Poison3");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40029, L"&Stone");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40040, L"Unconscious");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40030, L"Weak");
+          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40073, L"Zombie");
+        }
+
+        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40006, L"Set Food (20)");
+
+        HMENU debug_party_alignment = CreatePopupMenu();
+        AppendMenuW(debug_party, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_party_alignment, L"Alignment");
+        {
+          AppendMenuW(debug_party_alignment, MF_ENABLED | MF_STRING, 40062, L"Good");
+          AppendMenuW(debug_party_alignment, MF_ENABLED | MF_STRING | MF_CHECKED, 40063, L"Neutral");
+          AppendMenuW(debug_party_alignment, MF_ENABLED | MF_STRING, 40064, L"Evil");
+        }
+      }
+
+      HMENU debug_time = CreatePopupMenu();
+      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_time, L"&Time");
+      {
+        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40009, L"Add 1 Day");
+        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40010, L"Add 1 Week");
+        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40011, L"Add 1 Month");
+        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40012, L"Add 1 Year");
+      }
+
+      HMENU debug_items = CreatePopupMenu();
+      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_items, L"&Items");
+      {
+        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40015, L"Generate level &1 item");
+        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40016, L"Generate level &2 item");
+        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40017, L"Generate level &3 item");
+        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40018, L"Generate level &4 item");
+        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40019, L"Generate level &5 item");
+        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40020, L"Generate level &6 item");
+        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40061, L"Generate special item");
+      }
+
+      HMENU debug_graphics = CreatePopupMenu();
+      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_graphics, L"&Graphics");
+      {
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40023, L"Lighting Mode");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40024, L"Lighting Geometry");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING | MF_GRAYED, 40104, L"Lights Off");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40105, L"Colored Lights");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40025, L"Debug Lights");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40101, L"Debug Decals");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40027, L"HWID Portals");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40047, L"SWID Portals");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40051, L"OD Frustum");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40054, L"SWOD Constant Redraw");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40055, L"SWOD Lit Rasterizer");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40056, L"Party Light off");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40060, L"SWOD Nice Lighting off");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40067, L"HWOD Additive Fog Lights");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40072, L"HWID Nice Lighting");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40048, L"Wireframe");
+        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40049, L"Fog");
+      }
+
+      HMENU debug_misc = CreatePopupMenu();
+      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_misc, L"&Misc");
+      {
+        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40066, L"Object Viewcone Culling");
+        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40068, L"Red Tint");
+        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40071, L"Display Secrets");
+        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40102, L"Massive Bloodsplat");
+        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40103, L"Underwater Gravity");
+      }
+      
+      HMENU debug_eax = CreatePopupMenu();
+      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_eax, L"EAX Environs");
+      {
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40074, L"NONE");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40075, L"GENERIC");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40076, L"PADDEDCELL");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40077, L"ROOM");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40078, L"BATHROOM");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40079, L"LIVINGROOM");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40080, L"STONEROOM");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40081, L"AUDITORIUM");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40082, L"CONCERTHALL");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40083, L"CAVE");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40084, L"ARENA");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40085, L"HANGAR");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40086, L"CARPETEDHALLWAY");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40087, L"HALLWAY");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40088, L"STONECORRIDOR");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40089, L"ALLEY");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40090, L"FOREST");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40091, L"CITY");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40092, L"MOUNTAINS");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40093, L"QUARRY");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40094, L"PLAIN");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40095, L"PARKINGLOT");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40096, L"SEWERPIPE");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40097, L"UNDERWATER");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40098, L"DRUGGED");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40099, L"DIZZY");
+        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40100, L"PSICHOTIC");
+      }
+    }
+  }
+  return menu;
+}
+
+
+
+
+bool OSWindow::OnOSMenu(int item_id)
+{
+  switch (item_id)
+  {
+    default: return false;
+
+
+    case 103:  pRenderer->SavePCXScreenshot(); break;
+    case 101:  // Quit game
+    case 40001:
+      SendMessageW(api_handle, WM_DESTROY, 0, 0);
+    break;
+
+    case 104:
+      pRenderer->ChangeBetweenWinFullscreenModes();
+      if (pArcomageGame->bGameInProgress)
+        pArcomageGame->field_F6 = 1;
+    break;
+
+        //SubMenu "Party"
+    case 40006:  pParty->SetFood(pParty->uNumFoodRations + 20); break;
+    case 40007:  pParty->SetGold(pParty->uNumGold + 10000);     break;
+    case 40008:  GivePartyExp(20000);  break;
+    case 40013:  pParty->SetGold(0);   break;
+
+    case 40059:
+      for (uint i = 0; i < 4; ++i)
+        pParty->pPlayers[i].uSkillPoints = 50;
+    break;
+        
+    case 40029:  pPlayers[uActiveCharacter]->SetPertified(true);  break;
+    case 40030:  pPlayers[uActiveCharacter]->SetWeak(true);       break;
+    case 40031:  pPlayers[uActiveCharacter]->SetPoison3(true);    break;
+    case 40032:  pPlayers[uActiveCharacter]->SetPoison2(true);    break;
+    case 40033:  pPlayers[uActiveCharacter]->SetPoison1(true);    break;
+    case 40034:  pPlayers[uActiveCharacter]->SetDisease3(true);   break;
+    case 40035:  pPlayers[uActiveCharacter]->SetDisease2(true);   break;
+    case 40036:  pPlayers[uActiveCharacter]->SetDisease1(true);   break;
+    case 40037:  pPlayers[uActiveCharacter]->SetCursed(true);     break;
+    case 40038:  pPlayers[uActiveCharacter]->SetInsane(true);     break;
+    case 40039:  pPlayers[uActiveCharacter]->SetDrunk(true);      break;
+    case 40040:  pPlayers[uActiveCharacter]->SetUnconcious(true); break;
+    case 40041:  pPlayers[uActiveCharacter]->SetDead(true);       break;
+    case 40042:  pPlayers[uActiveCharacter]->SetEradicated(true); break;
+    case 40043:  pPlayers[uActiveCharacter]->SetAsleep(true);     break;
+    case 40044:  pPlayers[uActiveCharacter]->SetAfraid(true);     break;
+    case 40045:  pPlayers[uActiveCharacter]->SetParalyzed(true);  break;
+    case 40073:  pPlayers[uActiveCharacter]->SetZombie(true);     break;
+
+    case 40062:
+      pParty->alignment = PartyAlignment_Good;
+      SetUserInterface(pParty->alignment, true);
+    break;
+    case 40063:
+      pParty->alignment = PartyAlignment_Neutral;
+      SetUserInterface(pParty->alignment, true);
+    break;
+    case 40064:
+      pParty->alignment = PartyAlignment_Evil;
+      SetUserInterface(pParty->alignment, true);
+    break;
+
+
+
+        //SubMenu "Time"
+    case 40009:  pParty->uTimePlayed += Timer::Day;   break;
+    case 40010:  pParty->uTimePlayed += Timer::Week;  break;
+    case 40011:  pParty->uTimePlayed += Timer::Month; break;
+    case 40012:  pParty->uTimePlayed += Timer::Year;  break;
+
+        //SubMenu "Items"
+    case 40015: // uItemID_Rep_St == 1
+    case 40016: // uItemID_Rep_St == 2
+    case 40017: // uItemID_Rep_St == 3
+    case 40018: // uItemID_Rep_St == 4
+    case 40019: // uItemID_Rep_St == 5
+    case 40020: // uItemID_Rep_St == 6
+    {
+      int pItemID = rand() % 500;
+      for (uint i = 0; i < 500; ++i)
+      {
+        if (pItemID + i > 499)
+          pItemID = 0;
+        if (pItemsTable->pItems[pItemID + i].uItemID_Rep_St == (item_id - 40015 + 1))
+        {
+          pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
+          break;
+        }
+      }
+    }
+    break;
+
+    case 40061:
+    {
+      int pItemID = rand() % 500;
+      for (uint i = 0; i < 500; ++i)
+      {
+        if (pItemID + i > 499)
+          pItemID = 0;
+        if (pItemsTable->pItems[pItemID + i].uItemID_Rep_St > 6)
+        {
+          pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
+          break;
+        }
+      }
+    }
+    break;
+  }
+
+  return true;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OSWindow.h	Wed Oct 09 08:09:48 2013 +0200
@@ -0,0 +1,49 @@
+#pragma once
+#include "OSAPI.h"
+#include "NewUI/Core/UIControl.h"
+
+class OSWindow: public UIControl
+{
+  public:
+    static OSWindow *Create(const wchar_t *title, int window_width, int window_height);
+
+
+    void SetFullscreenMode();
+    void SetWindowedMode(int new_window_width, int new_window_height);
+    void SetCursor(const char *cursor_name);
+
+    inline HWND         GetApiHandle() const {return api_handle;}
+    inline unsigned int GetWidth() const     {RECT rc; GetClientRect(api_handle, &rc); return rc.right - rc.left;}
+    inline unsigned int GetHeight() const    {RECT rc; GetClientRect(api_handle, &rc); return rc.bottom - rc.top;}
+    
+
+    bool OnOSMenu(int item_id);
+
+    // UIControl
+    virtual void Show() override;
+    
+    // UIControl
+    virtual bool Focused() override  {return GetFocus() == api_handle;}
+    
+    // UIControl
+    //virtual bool OnKey(int key) override;
+    // UIControl
+    virtual bool OnMouseLeftClick(int x, int y) override;
+    // UIControl
+    virtual bool OnMouseRightClick(int x, int y) override;
+    // UIControl
+    //virtual bool OnMouseEnter() override;
+    // UIControl
+    //virtual bool OnMouseLeave() override;
+
+  protected:
+    bool Initialize(const wchar_t *title, int window_width, int window_height);
+    bool WinApiMessageProc(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT *result);
+
+    HWND  api_handle;
+
+  private:
+    static LPARAM __stdcall WinApiMsgRouter(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
+
+    HMENU CreateDebugMenuPanel();
+};
\ No newline at end of file
--- a/Outdoor_stuff.h	Wed Oct 09 08:06:26 2013 +0200
+++ b/Outdoor_stuff.h	Wed Oct 09 08:09:48 2013 +0200
@@ -75,11 +75,11 @@
   int field_0_party_dir_x;
   int field_4_party_dir_y;
   int field_8_party_dir_z;
-  int field_C;
-  int field_10;
+  int angle_from_north;//field_C
+  int angle_from_west;//field_10
   int field_14;
-  int field_18;
-  int field_1C;
+  int angle_from_east;//field_18
+  int angle_from_south;//field_1C
   int field_20;
   int field_24;
   int field_28;
--- a/Render.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/Render.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -177,11 +177,13 @@
 }
 
 //----- (004A16A5) --------------------------------------------------------
-bool  AreRenderSurfacesOk()
+bool AreRenderSurfacesOk()
 {
   char v0; // zf@4
   bool result; // eax@8
 
+  if (!pRenderer)
+    return true;
   if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
   {
     if ( !pRenderer->pBackBuffer4 )
@@ -2094,16 +2096,16 @@
   hd_water_current_frame = 0;
 }
 
-bool Render::Initialize(bool bWindowed, int windowed_width, int windowed_height, uint32_t uDefaultDevice,
-                        bool bColoredLights, uint32_t uDetailLevel, bool bTinting)
-{
-  bUserDirect3D = true;//ReadWindowsRegistryInt("Use D3D", 0);
-
+bool Render::Initialize(bool bWindowed, OSWindow *window, bool bColoredLights, uint32_t uDetailLevel, bool bTinting)
+{
+  //bUserDirect3D = true;//ReadWindowsRegistryInt("Use D3D", 0);
+
+  this->window = window;
   bStartInWindow = bWindowed;
-  windowed_mode_width = windowed_width;
-  windowed_mode_height = windowed_height;
-
-  uDesiredDirect3DDevice = uDefaultDevice;//ReadWindowsRegistryInt("D3D Device", 1);
+  //windowed_mode_width = windowed_width;
+  //windowed_mode_height = windowed_height;
+
+  uDesiredDirect3DDevice = 0;//ReadWindowsRegistryInt("D3D Device", 1);
 
   bUseColoredLights = bColoredLights;//ReadWindowsRegistryInt("Colored Lights", 0);
   uLevelOfDetail = uDetailLevel;//ReadWindowsRegistryInt("Detail Level", 1);
@@ -2186,7 +2188,7 @@
   RECT x; // [sp+68h] [bp-10h]@3
 
   memset(&v3, 0, sizeof(DDBLTFX));
-  GetWindowRect(hWnd, &x);
+  GetWindowRect(window->GetApiHandle(), &x);
   if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
       pVersion->pVersionInfo.dwMajorVersion >= 5)
   {
@@ -2909,8 +2911,8 @@
         pRenderD3D->Present(false);
       }
     }
-    else
-    {
+    else __debugbreak(); // no sr
+    /*{
       if ( v1->bWindowMode )
       {
         RestoreFrontBuffer();
@@ -2934,7 +2936,7 @@
         a4.right = 640;
         BltBackToFontFast(0, 0, &a4);
       }
-    }
+    }*/
   }
 }
 
@@ -2979,9 +2981,9 @@
 void Render::Release()
 {
   Render *v1; // esi@1
-  RenderD3D *v2; // ecx@1
-  char v3; // zf@4
-  void *v4; // ebx@6
+  //RenderD3D *v2; // ecx@1
+  //char v3; // zf@4
+  //void *v4; // ebx@6
   IDirectDraw *v5; // eax@10
   IDirectDrawSurface2 *v6; // eax@11
   IDirectDrawSurface2 *v7; // eax@13
@@ -2996,36 +2998,34 @@
   void **v16; // esi@29
 
   v1 = this;
-  v2 = this->pRenderD3D;
-  if ( v2 )
+  if (pRenderD3D)
   {
     if ( v1->field_40110 )
     {
-      pRenderD3D->ClearTarget(1u, 0, 0, 1.0);
+      pRenderD3D->ClearTarget(true, 0, false, 1.0);
       pRenderD3D->Present(0);
-      pRenderD3D->ClearTarget(1u, 0, 0, 1.0);
+      pRenderD3D->ClearTarget(true, 0, false, 1.0);
     }
     v1->pColorKeySurface4 = 0;
     v1->pBackBuffer4 = 0;
-    v3 = v1->pTargetSurface == 0;
     v1->pFrontBuffer4 = 0;
     v1->pDirectDraw4 = 0;
-    if ( !v3 )
+    if (v1->pTargetSurface)
     {
       free(v1->ptr_400E8);
       v1->pTargetSurface = 0;
       v1->ptr_400E8 = 0;
     }
-    v4 = v1->pRenderD3D;
-    if ( v4 )
+    if (pRenderD3D)
     {
       pRenderD3D->Release();
-      free(v4);
-    }
-    v1->pRenderD3D = 0;
+      delete pRenderD3D;
+    }
+    pRenderD3D = 0;
   }
   else
-  {
+    ;//__debugbreak(); // no sr
+  /*{
     if ( bWinNT4_0 == 1 )
     {
       v5 = (IDirectDraw *)v1->pDirectDraw2;
@@ -3098,7 +3098,7 @@
       *v15 = 0;
       *v16 = 0;
     }
-  }
+  }*/
 }
 
 //----- (0049FFD7) --------------------------------------------------------
@@ -3108,7 +3108,7 @@
 }
 
 //----- (0049FFFB) --------------------------------------------------------
-bool Render::InitializeFullscreen(HWND hWnd)
+bool Render::InitializeFullscreen()
 {
   //Render *v2; // esi@1
   //HWND v3; // ebx@1
@@ -3147,10 +3147,19 @@
   this->bColorKeySupported = 0;
   Release();
   //v3 = hWnd;
-  this->hWnd = hWnd;
+  this->window = window;
   CreateZBuffer();
-  if ( bUserDirect3D )
-  {
+
+  /*if (!bUserDirect3D)
+  {
+    CreateDirectDraw();
+    SetDirectDrawCooperationMode(hWnd, 1);
+    SetDirectDrawDisplayMode(640u, 480u, 16u);
+    CreateDirectDrawPrimarySurface();
+    v15 = 1;
+  }
+  else
+  {*/
     pRenderD3D = new RenderD3D;
     v28 = pRenderD3D;
     v6 = uDesiredDirect3DDevice;
@@ -3158,14 +3167,14 @@
     v7 = pRenderD3D->pAvailableDevices;
     if ( v7[v6].bIsDeviceCompatible )
     {
-      v8 = pRenderD3D->CreateDevice(v6, 0, hWnd);
+      v8 = pRenderD3D->CreateDevice(v6, 0, window->GetApiHandle());
       uAcquiredDirect3DDevice = uDesiredDirect3DDevice;
     }
     else
     {
       if ( v7[1].bIsDeviceCompatible )
       {
-        v8 = pRenderD3D->CreateDevice(1u, 0, hWnd);
+        v8 = pRenderD3D->CreateDevice(1u, 0, window->GetApiHandle());
         uAcquiredDirect3DDevice = 1;
       }
       else
@@ -3173,7 +3182,7 @@
         if ( !v7->bIsDeviceCompatible )
           Error("There aren't any D3D devices to create.");
 
-        v8 = pRenderD3D->CreateDevice(0, 0, hWnd);
+        v8 = pRenderD3D->CreateDevice(0, 0, window->GetApiHandle());
         uAcquiredDirect3DDevice = 0;
       }
     }
@@ -3261,15 +3270,7 @@
     ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, 2u));
     ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, 0));
     ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLOROP, 4u));
-  }
-  else
-  {
-    CreateDirectDraw();
-    SetDirectDrawCooperationMode(hWnd, 1);
-    SetDirectDrawDisplayMode(640u, 480u, 16u);
-    CreateDirectDrawPrimarySurface();
-    v15 = 1;
-  }
+  //}
   ddpfPrimareSuface.dwSize = 32;
   GetTargetPixelFormat(&ddpfPrimareSuface);
   ParseTargetPixelFormat();
@@ -3329,7 +3330,7 @@
 }
 
 //----- (004A05F3) --------------------------------------------------------
-bool Render::SwitchToWindow(HWND hWnd)
+bool Render::SwitchToWindow()
 {
   //Render *v2; // esi@1
   //void *v3; // eax@2
@@ -3371,8 +3372,19 @@
   pDirectDraw4 = 0;
   bColorKeySupported = 0;
   CreateZBuffer();
-  if ( bUserDirect3D )
-  {
+  /*if (!bUserDirect3D)
+  {
+    CreateDirectDraw();
+    SetDirectDrawCooperationMode(hWnd, 0);
+    field_4004C = 1;
+    CreateFrontBuffer();
+    CreateClipper(hWnd);
+    CreateBackBuffer();
+    field_40030 = 0;
+    field_18_locked_pitch = 0;
+  }
+  else
+  {*/
     /*v3 = malloc(0x148u);
     thisa = (RenderD3D *)v3;
     v29 = 0;
@@ -3388,7 +3400,7 @@
     if (pRenderD3D->pAvailableDevices[uDesiredDirect3DDevice].bIsDeviceCompatible &&
         uDesiredDirect3DDevice != 1 )
     {
-      v7 = pRenderD3D->CreateDevice(uDesiredDirect3DDevice, 1, hWnd);
+      v7 = pRenderD3D->CreateDevice(uDesiredDirect3DDevice, 1, window->GetApiHandle());
       uAcquiredDirect3DDevice = uDesiredDirect3DDevice;
     }
     else
@@ -3396,7 +3408,7 @@
       if ( !pRenderD3D->pAvailableDevices[0].bIsDeviceCompatible )
         Error("There aren't any D3D devices to init.");
 
-      v7 = pRenderD3D->CreateDevice(0, 1, hWnd);
+      v7 = pRenderD3D->CreateDevice(0, 1, window->GetApiHandle());
       uAcquiredDirect3DDevice = 0;
     }
     if ( !v7 )
@@ -3480,18 +3492,8 @@
     ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, 2u));
     ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, 0));
     ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_COLOROP, 4u));
-  }
-  else
-  {
-    CreateDirectDraw();
-    SetDirectDrawCooperationMode(hWnd, 0);
-    field_4004C = 1;
-    CreateFrontBuffer();
-    CreateClipper(hWnd);
-    CreateBackBuffer();
-    field_40030 = 0;
-    field_18_locked_pitch = 0;
-  }
+  //}
+
   ddpfPrimareSuface.dwSize = 32;
   GetTargetPixelFormat(&ddpfPrimareSuface);
   ParseTargetPixelFormat();
@@ -3523,7 +3525,7 @@
     field_40110 = 1;
 LABEL_47:
     bWindowMode = 1;
-    hWnd = hWnd;
+    //hWnd = hWnd;
     return 0;
   }
   pTargetSurface = 0;
@@ -3997,7 +3999,8 @@
   pDirectDraw2 = nullptr;
   pDirectDraw4 = nullptr;
 
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
     ErrD3D(lpDD->QueryInterface(IID_IDirectDraw4, (void **)&pDirectDraw4));
   else
     ErrD3D(lpDD->QueryInterface(IID_IDirectDraw2, (void **)&pDirectDraw2));
@@ -4018,7 +4021,8 @@
   flags = bFullscreen ? DDSCL_NORMAL | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN :
                         DDSCL_NORMAL;
 
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
     ErrD3D(pDirectDraw4->SetCooperativeLevel(hWnd, flags | DDSCL_MULTITHREADED));
   else
     ErrD3D(pDirectDraw2->SetCooperativeLevel(hWnd, flags));
@@ -4027,7 +4031,8 @@
 //----- (004A11C6) --------------------------------------------------------
 void Render::SetDirectDrawDisplayMode(unsigned int uWidth, unsigned int uHeight, unsigned int uBPP)
 {
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
     ErrD3D(pDirectDraw4->SetDisplayMode(uWidth, uHeight, uBPP, 0, 0));
   else
     ErrD3D(pDirectDraw2->SetDisplayMode(uWidth, uHeight, uBPP, 0, 0));
@@ -4046,7 +4051,8 @@
   DDSURFACEDESC2 a2; // [sp+4h] [bp-80h]@3
 
   v1 = this;
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
   {
     memset(&a2, 0, 0x7Cu);
     pDD = (IDirectDraw *)v1->pDirectDraw4;
@@ -4086,7 +4092,8 @@
   DDSURFACEDESC2 a2; // [sp+4h] [bp-80h]@3
 
   v1 = this;
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
   {
     memset(&a2, 0, 0x7Cu);
     v2 = (IDirectDraw *)v1->pDirectDraw4;
@@ -4140,7 +4147,8 @@
   int a4; // [sp+98h] [bp-8h]@3
 
   v1 = this;
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
   {
     v2 = 0;
     this->field_4004C = 1;
@@ -4191,7 +4199,8 @@
 //----- (004A14F4) --------------------------------------------------------
 void Render::CreateClipper(HWND a2)
 {
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
   {
     ErrD3D(pDirectDraw4->CreateClipper(0, &pDDrawClipper, 0));
     ErrD3D(pDDrawClipper->SetHWnd(0, a2));
@@ -4209,7 +4218,8 @@
 {
   IDirectDrawSurface *v2; // eax@3
 
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
     v2 = (IDirectDrawSurface *)this->pFrontBuffer4;
   else
     v2 = (IDirectDrawSurface *)this->pFrontBuffer2;
@@ -4223,7 +4233,8 @@
   signed int v4; // eax@3
 
   v3 = this;
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
   {
   DDSURFACEDESC2 pDesc; // [sp+4h] [bp-7Ch]@3
     memset(&pDesc, 0, 0x7Cu);
@@ -4244,16 +4255,11 @@
   *pOutPixelsPerRow = v4 >> 1;
 }
 
-//----- (004A169E) --------------------------------------------------------
-bool Render::UsingDirect3D()
-{
-  return bUserDirect3D == 0;
-}
-
 //----- (004A16E1) --------------------------------------------------------
 void Render::UnlockBackBuffer()
 {
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion != 4 )
     ErrD3D(pBackBuffer4->Unlock(0));
   else
     ErrD3D(pBackBuffer2->Unlock(0));
@@ -5155,11 +5161,11 @@
   {
     v15 = (void *)(v72 * (v70 - (int)array_507D30[_507D30_idx].vWorldViewProjY));
     v77 = (unsigned __int64)(v62.ptr_38->field_14 * (signed __int64)(signed int)v15) >> 16;
-    v74 = v77 + v62.ptr_38->field_C;
+    v74 = v77 + v62.ptr_38->angle_from_north;
     v77 = (int)v15;
     v77 = (unsigned __int64)(v62.ptr_38->field_20 * (signed __int64)(signed int)v15) >> 16;
     v79 = v15;
-    v75 = (RenderVertexSoft *)(v77 + v62.ptr_38->field_18);
+    v75 = (RenderVertexSoft *)(v77 + v62.ptr_38->angle_from_east);
     v79 = (void *)((unsigned __int64)(v62.v_18.z * (signed __int64)(signed int)v15) >> 16);
     v17 = v72 * (pBLVRenderParams->uViewportCenterX - (int)array_507D30[_507D30_idx].vWorldViewProjX);
     v18 = array_507D30[_507D30_idx].vWorldViewProjY - 1.0;
@@ -5195,8 +5201,8 @@
       v79 = (void *)(v23 / X);
       v77 = v17;
       v77 = v17;
-      LODWORD(v76) = v74 + ((unsigned __int64)(v62.ptr_38->field_10 * (signed __int64)v17) >> 16);
-      v75 = (RenderVertexSoft *)((char *)v75 + ((unsigned __int64)(v62.ptr_38->field_1C * (signed __int64)v17) >> 16));
+      LODWORD(v76) = v74 + ((unsigned __int64)(v62.ptr_38->angle_from_west * (signed __int64)v17) >> 16);
+      v75 = (RenderVertexSoft *)((char *)v75 + ((unsigned __int64)(v62.ptr_38->angle_from_south * (signed __int64)v17) >> 16));
       v77 = (unsigned __int64)(SLODWORD(v76) * v23 / X) >> 16;
       LODWORD(v73) = (unsigned __int64)((signed int)v75 * v23 / X) >> 16;
       //v14 += 48;
@@ -5271,13 +5277,13 @@
     v35 = (const void *)(v72 * (v70 - (unsigned __int64)(signed __int64)*(float *)v34));
     v78 = v62.ptr_38->field_14;
     v81 = (const void *)((unsigned __int64)(v78 * (signed __int64)(signed int)v35) >> 16);
-    v36 = (int)((char *)v81 + v62.ptr_38->field_C);
+    v36 = (int)((char *)v81 + v62.ptr_38->angle_from_north);
     v81 = v35;
     v74 = v36;
     v78 = v62.ptr_38->field_20;
     v81 = (const void *)((unsigned __int64)(v78 * (signed __int64)(signed int)v35) >> 16);
     v78 = (int)v35;
-    v75 = (RenderVertexSoft *)((char *)v81 + v62.ptr_38->field_18);
+    v75 = (RenderVertexSoft *)((char *)v81 + v62.ptr_38->angle_from_east);
     v81 = (const void *)v62.v_18.z;
     v78 = (unsigned __int64)(v62.v_18.z * (signed __int64)(signed int)v35) >> 16;
     v37 = (const void *)(v72
@@ -5320,12 +5326,12 @@
     HIDWORD(v42) = v77 >> 16;
     v79 = (void *)(v42 / X);
     v81 = v37;
-    v78 = v62.ptr_38->field_10;
+    v78 = v62.ptr_38->angle_from_west;
     v81 = (const void *)((unsigned __int64)(v78 * (signed __int64)(signed int)v37) >> 16);
     v43 = v74 + ((unsigned __int64)(v78 * (signed __int64)(signed int)v37) >> 16);
     v74 = (unsigned int)v37;
     LODWORD(v76) = v43;
-    v78 = v62.ptr_38->field_1C;
+    v78 = v62.ptr_38->angle_from_south;
     v75 = (RenderVertexSoft *)((char *)v75 + ((unsigned __int64)(v78 * (signed __int64)(signed int)v37) >> 16));
     v74 = (unsigned __int64)(v43 * v42 / X) >> 16;
     v81 = (const void *)((unsigned __int64)((signed int)v75 * v42 / X) >> 16);
@@ -8316,17 +8322,19 @@
     }
     if ( pRenderer->bWindowMode )
     {
-      SetMenu(hWnd, 0);
-      SetWindowLongA(hWnd, -20, 0);
-      SetWindowLongA(hWnd, -16, 0x10000000u);
-      pRenderer->InitializeFullscreen(hWnd);
+      //SetMenu(hWnd, 0);
+      //SetWindowLongA(hWnd, -20, 0);
+      //SetWindowLongA(hWnd, -16, 0x10000000u);
+      window->SetFullscreenMode();
+      pRenderer->InitializeFullscreen();
       v0 = (double)(signed int)uGammaPos * 0.1 + 0.6;
       pGame->pGammaController->Initialize(v0);
     }
     else
     {
-      ClipCursor(0);
-      pRenderer->SwitchToWindow(hWnd);
+      //ClipCursor(0);
+      window->SetWindowedMode(window->GetWidth(), window->GetHeight());
+      pRenderer->SwitchToWindow();
     }
     if ( pRenderer->pRenderD3D )
     {
@@ -8379,13 +8387,13 @@
     viewparams->bRedrawGameUI = 1;
     viewparams->InitGrayPalette();
     pMouse->SetCurrentCursorBitmap();
-    if ( pRenderer->bWindowMode )
+    /*if ( pRenderer->bWindowMode )
     {
       //MoveWindow(hWnd, uWindowX, uWindowY, uWindowWidth, uWindowHeight, 0);
       CenterWindowAndAdjustSize(hWnd, windowed_mode_width, windowed_mode_height);
       ShowWindow(hWnd, SW_SHOWNORMAL);
-    }
-    pMouse->bActive = 1;
+    }*/
+    pMouse->bActive = true;
     if ( pVideoPlayer->AnyMovieLoaded() )
       pVideoPlayer->SelectMovieType();
     if (dword_6BE364_game_settings_1 & 0x0800 )
@@ -8767,6 +8775,8 @@
     {
       pNextVertices = depth_num_vertices++;
       memcpy(&array_507D30[pNextVertices], &array_50AC10[i], 0x30);
+      //array_507D30[pNextVertices]._rhw = 1.0 / (array_50AC10[i].vWorldViewPosition.x + 0.0000001);
+      //array_507D30[pNextVertices].flt_2C = array_50AC10[i].flt_2C;
     }
     previous_vertices_flag = current_vertices_flag;
   }
--- a/Render.h	Wed Oct 09 08:06:26 2013 +0200
+++ b/Render.h	Wed Oct 09 08:09:48 2013 +0200
@@ -4,7 +4,7 @@
 #include <cstdio>
 
 #include "lib\legacy_dx\d3d.h"
-#include "OSAPI.h"
+#include "OSWindow.h"
 
 #include "VectorTypes.h"
 
@@ -269,8 +269,7 @@
 
   static Render *Create() {return new Render;}
 
-  bool Initialize(bool bWindowed, int window_width, int window_height, uint32_t uDefaultDevice,
-                  bool bColoredLights, uint32_t uDetailLevel, bool bTinting);
+  bool Initialize(bool bWindowed, OSWindow *window, bool bColoredLights, uint32_t uDetailLevel, bool bTinting);
 
 
   bool IsColorKeySupported(IDirectDraw4 *);
@@ -288,8 +287,8 @@
   void CreateZBuffer();
   void Release();
   void CreateSomeTexture();
-  bool InitializeFullscreen(HWND hWnd);
-  bool SwitchToWindow(HWND hWnd);
+  bool InitializeFullscreen();
+  bool SwitchToWindow();
   char RasterLine2D(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW, unsigned __int16 uColor);
   void ClearZBuffer(int a2, int a3);
   void SetRasterClipRect(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW);
@@ -305,7 +304,6 @@
   void CreateClipper(HWND a2);
   void GetTargetPixelFormat(DDPIXELFORMAT *pOut);
   void LockRenderSurface(void **pOutSurfacePtr, unsigned int *pOutPixelsPerRow);
-  bool UsingDirect3D();
   void UnlockBackBuffer();
   void LockFrontBuffer(void **pOutSurface, unsigned int *pOutPixelsPerRow);
   void UnlockFrontBuffer();
@@ -373,7 +371,7 @@
   void DrawBillboardList_BLV();
 
 
-  unsigned int bUserDirect3D;
+  //unsigned int bUserDirect3D;
   unsigned int bStartInWindow;
   unsigned int uDesiredDirect3DDevice;
   unsigned int uAcquiredDirect3DDevice;
@@ -395,7 +393,8 @@
   int field_40044;
   int field_40048;
   int field_4004C;
-  HWND hWnd;
+  //HWND hWnd;
+  OSWindow *window;
   int field_40054;
   unsigned int bWindowMode;
   int field_4005C[11];
@@ -459,8 +458,8 @@
   unsigned __int16 *pCurrentlyLockedSoftSurface;
 
 
-  int windowed_mode_width;
-  int windowed_mode_height;
+  //int windowed_mode_width;
+  //int windowed_mode_height;
 };
 #pragma pack(pop)
 
--- a/UI/UIPopup.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/UI/UIPopup.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -1284,7 +1284,7 @@
     // 507B00: using guessed type int dword_507B00_spell_info_to_draw_in_popup;
 
 //----- (00416D62) --------------------------------------------------------
-void sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(Vec2_int_ *_this)
+void UI_OnMouseRightClick(Vec2_int_ *_this)
 {
   int v5; // esi@62
   GUIButton *pButton; // esi@84
@@ -1309,7 +1309,7 @@
   if ( pRenderer->bWindowMode )
   {
     GetCursorPos(&Point);
-    ScreenToClient(hWnd, &Point);
+    ScreenToClient(window->GetApiHandle(), &Point);
     if ( Point.x < 1 || Point.y < 1 || Point.x > 638 || Point.y > 478 )
     {
       back_to_game();
--- a/UI/UiGame.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/UI/UiGame.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -2178,7 +2178,7 @@
         {
           uFrameID = pParty->pHirelings[(unsigned __int8)pTmpBuf[i]].evt_B;
           v13 = 0;
-          if ( (signed int)pIconsFrameTable->uNumIcons )
+          if (pIconsFrameTable->uNumIcons)
           {
             for ( v13 = 0; v13 < pIconsFrameTable->uNumIcons; ++v13 )
             {
@@ -2247,5 +2247,5 @@
     case Condition_Eradicated:
       return ui_character_condition_severe_color;
   }
-  assert(false && "Invalid condition");
+  Error("Invalid condition (%u)", uConditionIdx);
 }
--- a/VideoPlayer.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/VideoPlayer.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -68,7 +68,7 @@
 void BinkUnlockBuffer(struct _BINKBUF *_this);
 
 //----- (004BFE2D) --------------------------------------------------------
-_BINKBUF *VideoPlayer::CreateBinkBuffer(HWND hWindow, unsigned int uWidth, unsigned int uHeight, char a4)
+_BINKBUF *VideoPlayer::CreateBinkBuffer(unsigned int uWidth, unsigned int uHeight, char a4)
 {
   __int32 v4; // edi@3
   _BINKBUF *v5; // esi@3
@@ -79,14 +79,13 @@
   DDSURFACEDESC2 v11; // [sp+Ch] [bp-108h]@7
   DDSURFACEDESC Dst; // [sp+88h] [bp-8Ch]@3
   unsigned int v13; // [sp+F4h] [bp-20h]@1
-  struct tagRECT Rect; // [sp+F8h] [bp-1Ch]@11
+  //struct tagRECT Rect; // [sp+F8h] [bp-1Ch]@11
   IDirectDrawSurface4 *v15; // [sp+108h] [bp-Ch]@7
   IDirectDrawSurface2 *a2; // [sp+10Ch] [bp-8h]@3
-  HWND hWnd; // [sp+110h] [bp-4h]@1
 
   v13 = uWidth;
-  hWnd = hWindow;
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion >= 5u )
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
+      pVersion->pVersionInfo.dwMajorVersion >= 5u )
   {
     v4 = 0;
     v15 = 0;
@@ -101,6 +100,7 @@
       v5 = new _BINKBUF_3_0_0_0;
       memset(v5, 0, sizeof(_BINKBUF_3_0_0_0));
     }
+    else __debugbreak();
 
     memset(&v11, 0, 0x7Cu);
     v11.dwSize = 124;
@@ -142,6 +142,7 @@
       v5 = new _BINKBUF_3_0_0_0;
       memset(v5, 0, sizeof(_BINKBUF_3_0_0_0));
     }
+    else __debugbreak();
 
     memset(&Dst, 0, 0x6Cu);
     Dst.dwSize = 108;
@@ -170,27 +171,29 @@
     v7 = (IDirectDrawSurface *)a2;
   }
   v5->pTargetDDrawSurface = v7;
-  v5->hWnd = hWnd;
+  v5->hWnd = window->GetApiHandle();
   v9 = a4;
   v5->field_4C = v4;
   v5->field_68 = v4;
   v5->field_5C = v4;
   v5->field_74 = v9 & 0x1F;
   v5->field_78 = 1;
-  v5->field_24 = GetSystemMetrics(v4);
-  v5->field_28 = GetSystemMetrics(SM_CYSCREEN);
+  v5->target_width = GetSystemMetrics(SM_CXSCREEN);
+  v5->target_height = GetSystemMetrics(SM_CYSCREEN);
   v5->field_2C = 16;
-  GetWindowRect(hWnd, &Rect);
-  v5->field_8 = Rect.right - Rect.left;
-  v5->field_C = Rect.bottom - Rect.top;
+
+  RECT Rect;
+  GetWindowRect(window->GetApiHandle(), &Rect);
+  v5->field_8 = window->GetWidth();
+  v5->field_C = window->GetHeight();
   v5->field_1C = Rect.left;
   v5->field_20 = Rect.top;
   Rect.left = v4;
   Rect.top = v4;
-  ClientToScreen(hWnd, (LPPOINT)&Rect);
+  ClientToScreen(window->GetApiHandle(), (POINT *)&Rect);
   v5->field_1C = Rect.left - v5->field_1C;
   v5->field_20 = Rect.top - v5->field_20;
-  GetClientRect(hWnd, &Rect);
+  GetClientRect(window->GetApiHandle(), &Rect);
   v5->field_30 = v5->field_8 - Rect.right;
   v5->field_34 = v5->field_C - Rect.bottom;
   v5->field_8 = v5->uWidth + v5->field_30;
@@ -351,7 +354,7 @@
 
 
 //----- (004BE70E) --------------------------------------------------------
-void __fastcall VideoPlayer::MovieLoop(const char *pMovieName, int a2, int ScreenSizeFlag, int a4)
+void VideoPlayer::MovieLoop(const char *pMovieName, int a2, int ScreenSizeFlag, int a4)
 {
   int v4; // ebp@1
   const char *pName; // edi@1
@@ -382,7 +385,7 @@
     {
       if ( pVideoPlayer->pBinkMovie )
       {
-        pVideoPlayer->BinkDrawFrame(pVideoPlayer->hWindow, v4, ScreenSizeFlag);
+        pVideoPlayer->BinkDrawFrame(v4, ScreenSizeFlag);
         while ( pVideoPlayer->pBinkMovie )
         {
           if ( pVideoPlayer->bStopBeforeSchedule )
@@ -400,7 +403,7 @@
           if ( !pVideoPlayer->pBinkMovie )
             break;
           if ( !BinkWait(pVideoPlayer->pBinkMovie) && !pVideoPlayer->bStopBeforeSchedule )
-            pVideoPlayer->BinkDrawFrame(pVideoPlayer->hWindow, v4, ScreenSizeFlag);
+            pVideoPlayer->BinkDrawFrame(v4, ScreenSizeFlag);
         }
       }
       if ( pVideoPlayer->bStopBeforeSchedule == 1 )
@@ -412,7 +415,7 @@
       {
         if ( pVideoPlayer->pSmackerMovie )
         {
-          pVideoPlayer->SmackDrawFrame(pVideoPlayer->hWindow, v4, ScreenSizeFlag);
+          pVideoPlayer->SmackDrawFrame(v4, ScreenSizeFlag);
           while ( pVideoPlayer->pSmackerMovie )
           {
             if ( pVideoPlayer->bStopBeforeSchedule )
@@ -430,7 +433,7 @@
             if ( !pVideoPlayer->pSmackerMovie )
               break;
             if ( !SmackWait(pVideoPlayer->pSmackerMovie) && !pVideoPlayer->bStopBeforeSchedule )
-              pVideoPlayer->SmackDrawFrame(pVideoPlayer->hWindow, v4, ScreenSizeFlag);
+              pVideoPlayer->SmackDrawFrame(v4, ScreenSizeFlag);
           }
         }
       }
@@ -475,10 +478,12 @@
 }
 
 //----- (004BE9D8) --------------------------------------------------------
-void VideoPlayer::Initialize()
+void VideoPlayer::Initialize(OSWindow *target_window)
 {
   DWORD NumberOfBytesRead; // [sp+10h] [bp-4h]@9
     
+  window = target_window;
+
   uint uBinkVersionMajor = -1,
        uBinkVersionMinor = -1;
   GetDllVersion(L"BINKW32.DLL", &uBinkVersionMajor, &uBinkVersionMinor);
@@ -524,79 +529,70 @@
 //----- (004BEB41) --------------------------------------------------------
 void VideoPlayer::Prepare()
 {
-  VideoPlayer *pVideoPlayer; // esi@1
-  IDirectDrawSurface *v2; // [sp-4h] [bp-Ch]@5
-
-  pVideoPlayer = this;
   pEventTimer->Pause();
-  pVideoPlayer->bStopBeforeSchedule = 0;
   if ( pAudioPlayer->hAILRedbook )
     AIL_redbook_pause(pAudioPlayer->hAILRedbook);
-  pVideoPlayer->field_54 = 1;
-  pVideoPlayer->hWindow = hWnd;
-  pVideoPlayer->pSmackerMovie = 0;
-  pVideoPlayer->pSmackerBuffer = 0;
-  pVideoPlayer->pBinkMovie = 0;
-  pVideoPlayer->pBinkBuffer = 0;
-  pVideoPlayer->bPlayingMovie = 0;
-  pVideoPlayer->bFirstFrame = 0;
-  pVideoPlayer->bUsingSmackerMMX = SmackUseMMX(1);
+
+  bStopBeforeSchedule = false;
+  field_54 = 1;
+  pSmackerMovie = 0;
+  pSmackerBuffer = 0;
+  pBinkMovie = 0;
+  pBinkBuffer = 0;
+  bPlayingMovie = false;
+  bFirstFrame = false;
+  bUsingSmackerMMX = SmackUseMMX(1);
   BinkSetSoundSystem(BinkOpenMiles, pAudioPlayer->hDigDriver);
-  if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion >= 5 )
-    v2 = (IDirectDrawSurface*)pRenderer->pBackBuffer4;
+  if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion >= 5)
+    uBinkDirectDrawSurfaceType = BinkDDSurfaceType((IDirectDrawSurface *)pRenderer->pBackBuffer4);
   else
-    v2 = (IDirectDrawSurface*)pRenderer->pBackBuffer2;
-  pVideoPlayer->uBinkDirectDrawSurfaceType = BinkDDSurfaceType(v2);
-  _flushall();
+    uBinkDirectDrawSurfaceType = BinkDDSurfaceType((IDirectDrawSurface *)pRenderer->pBackBuffer2);
 }
 
 
 //----- (004BEBD7) --------------------------------------------------------
 void VideoPlayer::Unload()
 {
-  VideoPlayer *pVideoPlayer; // esi@1
-  _BINK *pBinkMovie; // eax@1
-  _BINKBUF *pBinkBuffer; // eax@3
-  _SMACK *pSmackerMovie; // eax@5
+  //_BINK *pBinkMovie; // eax@1
+  //_BINKBUF *pBinkBuffer; // eax@3
+  //_SMACK *pSmackerMovie; // eax@5
 
-  pVideoPlayer = this;
-  pBinkMovie = this->pBinkMovie;
   if ( pBinkMovie )
   {
     BinkPause(pBinkMovie, 1);
     Sleep(300);
-    BinkClose(pVideoPlayer->pBinkMovie);
-    pVideoPlayer->pBinkMovie = 0;
+    BinkClose(pBinkMovie);
+    pBinkMovie = 0;
   }
-  pBinkBuffer = pVideoPlayer->pBinkBuffer;
+
   if ( pBinkBuffer )
   {
     pBinkBuffer->pTargetDDrawSurface->Release();
-    pVideoPlayer->pBinkBuffer->pTargetDDrawSurface = 0;
-    free(pVideoPlayer->pBinkBuffer);
-    pVideoPlayer->pBinkBuffer = 0;
+    pBinkBuffer->pTargetDDrawSurface = 0;
+    free(pBinkBuffer);
+    pBinkBuffer = 0;
   }
-  pSmackerMovie = pVideoPlayer->pSmackerMovie;
+
   if ( pSmackerMovie )
   {
     SmackSoundOnOff(pSmackerMovie, 0);
-    SmackClose(pVideoPlayer->pSmackerMovie);
-    pVideoPlayer->pSmackerMovie = 0;
+    SmackClose(pSmackerMovie);
+    pSmackerMovie = 0;
   }
-  if ( pVideoPlayer->pSmackerBuffer )
+  if ( pSmackerBuffer )
   {
-    SmackBufferClose(pVideoPlayer->pSmackerBuffer);
-    pVideoPlayer->pSmackerBuffer = 0;
+    SmackBufferClose(pSmackerBuffer);
+    pSmackerBuffer = 0;
   }
-  if ( pVideoPlayer->pSmackMovieBlit )
+  if ( pSmackMovieBlit )
   {
-    SmackBlitClose(pVideoPlayer->pSmackMovieBlit);
-    pVideoPlayer->pSmackMovieBlit = 0;
+    SmackBlitClose(pSmackMovieBlit);
+    pSmackMovieBlit = 0;
   }
-  pVideoPlayer->field_54 = 0;
-  pVideoPlayer->uMovieFormat = 0;
-  pVideoPlayer->dword_0000A0 = 0;
-  memset(pVideoPlayer->pCurrentMovieName, 0, 0x40);
+  field_54 = 0;
+  uMovieFormat = 0;
+  dword_0000A0 = 0;
+  memset(pCurrentMovieName, 0, 0x40);
   if ( pAudioPlayer->hAILRedbook && !bGameoverLoop )
     AIL_redbook_resume(pAudioPlayer->hAILRedbook);
   pEventTimer->Resume();
@@ -643,7 +639,7 @@
 
 
 //----- (004BED4F) --------------------------------------------------------
-void VideoPlayer::BinkDrawFrame(HWND hWnd, int a3, int a4)
+void VideoPlayer::BinkDrawFrame(int a3, int a4)
 {
   //VideoPlayer *v4; // esi@1
   _BINKBUF *v5; // eax@5
@@ -712,7 +708,7 @@
 
 
 //----- (004BEE6B) --------------------------------------------------------
-void VideoPlayer::SmackDrawFrame(HWND hWnd, int a3, int a4)
+void VideoPlayer::SmackDrawFrame(int a3, int a4)
 {
   VideoPlayer *v4; // esi@1
   _SMACK *v5; // eax@3
@@ -733,7 +729,7 @@
   unsigned int uPixelsPerRow; // [sp+14h] [bp-4h]@5
 
   v4 = this;
-  if ( !pRenderer->bWindowMode || GetFocus() == hWnd )
+  if ( !pRenderer->bWindowMode || window->Focused())
   {
     v5 = v4->pSmackerMovie;
     if ( v5->NewPalette )
@@ -749,7 +745,7 @@
       {
         Point.y = 0;
         Point.x = 0;
-        ClientToScreen(hWnd, &Point);
+        ClientToScreen(window->GetApiHandle(), &Point);
         v17 = -1;
         v16 = 480;
         v15 = 640;
@@ -774,7 +770,7 @@
     {
       Point.y = 0;
       Point.x = 0;
-      ClientToScreen(hWnd, &Point);
+      ClientToScreen(window->GetApiHandle(), &Point);
       v8 = SmackToBufferRect(v4->pSmackerMovie, 0);
       if ( a4 )
       {
@@ -824,9 +820,28 @@
   }
 }
 
+void VideoPlayer::_inlined_in_463149()
+{
+      if ( pSmackerMovie && !SmackWait(pSmackerMovie) )
+      {
+        pRenderer->BeginScene();
+        pMouse->DrawCursorToTarget();
+        SmackUpdatePalette();
+        pMouse->_469EA4();
+        pRenderer->EndScene();
+      }
+      else if ( pBinkMovie && !BinkWait(pBinkMovie) )
+      {
+        pRenderer->BeginScene();
+        pMouse->DrawCursorToTarget();
+        BinkUpdatePalette();
+        pMouse->_469EA4();
+        pRenderer->EndScene();
+      }
+}
 
 //----- (004BF08B) --------------------------------------------------------
-void VideoPlayer::SmackUpdatePalette(HWND hWnd)
+void VideoPlayer::SmackUpdatePalette()
 {
   VideoPlayer *v2; // esi@1
   unsigned __int16 *v3; // ebx@1
@@ -950,7 +965,7 @@
     this->uMovieFormat = 1;
     strcpy(this->pCurrentMovieName, (const char *)pMovieName);
     this->dword_0000A0 = 1;
-    this->pSmackerBuffer = (_SMACKBUF *)SmackBufferOpen(this->hWindow, 4, LOWORD(this->pSmackerMovie->Width), LOWORD(this->pSmackerMovie->Height), LOWORD(this->pSmackerMovie->Width), LOWORD(this->pSmackerMovie->Height));
+    this->pSmackerBuffer = (_SMACKBUF *)SmackBufferOpen(window->GetApiHandle(), 4, LOWORD(this->pSmackerMovie->Width), LOWORD(this->pSmackerMovie->Height), LOWORD(this->pSmackerMovie->Width), LOWORD(this->pSmackerMovie->Height));
     if ( this->pSmackerBuffer )
     {
       pRenderer->BeginScene();
@@ -986,7 +1001,7 @@
       pBinkMovie = this->pBinkMovie;
       this->dword_0000A0 = 1;
       if ( pBinkMovie )
-        this->pBinkBuffer = CreateBinkBuffer(this->hWindow, pBinkMovie->uWidth, pBinkMovie->uHeight, 0);
+        this->pBinkBuffer = CreateBinkBuffer(pBinkMovie->uWidth, pBinkMovie->uHeight, 0);
     }
     else
     {
--- a/VideoPlayer.h	Wed Oct 09 08:06:26 2013 +0200
+++ b/VideoPlayer.h	Wed Oct 09 08:09:48 2013 +0200
@@ -1,5 +1,5 @@
 #pragma once
-#include "OSAPI.h"
+#include "OSWindow.h"
 #include "Texture.h"
 
 
@@ -47,8 +47,8 @@
   int uDDrawSurfacePitch;
   int field_1C;
   int field_20;
-  int field_24;
-  int field_28;
+  int target_width;
+  int target_height;
   int field_2C;
   int field_30;
   int field_34;
@@ -123,14 +123,14 @@
 
   void PlayDeathMovie();
   unsigned int SmackCheckSurfaceFromat();
-  void Initialize();
+  void Initialize(OSWindow *window);
   void Prepare();
   void Unload();
   void FastForwardToFrame(unsigned int uFrameNum);
-  void BinkDrawFrame(HWND hWnd, int a3, int a4);
-  void BinkUpdatePalette(HWND hWnd) {}
-  void SmackDrawFrame(HWND hWnd, int a3, int a4);
-  void SmackUpdatePalette(HWND hWnd);
+  void BinkDrawFrame(int a3, int a4);
+  void BinkUpdatePalette() {}
+  void SmackDrawFrame(int a3, int a4);
+  void SmackUpdatePalette();
   _BINK *OpenBink(const char *pName);
   struct _SMACK *OpenSmack(const char *pFilename);
   void OpenHouseMovie(const char *pMovieName, unsigned int a3_1);//0x4BF28F
@@ -138,9 +138,10 @@
   void OpenGlobalMovie(const char *pFilename, unsigned int bLoop, int a4);
   void _4BF5B2();
   void SelectMovieType();//0x4BF73A
-  _BINKBUF *CreateBinkBuffer(HWND a1, unsigned int uWidth, unsigned int uHeight, char a4);
+  _BINKBUF *CreateBinkBuffer(unsigned int uWidth, unsigned int uHeight, char a4);
+  void _inlined_in_463149();
 
-  static void __fastcall MovieLoop(const char *pMovieName, int a2, int a3, int a4);
+  static void MovieLoop(const char *pMovieName, int a2, int a3, int a4);
 
 
   RGBTexture pVideoFrame;
@@ -162,7 +163,8 @@
   unsigned int bLoopPlaying;
   int field_68;
   unsigned int bStopBeforeSchedule;
-  HWND hWindow;
+  //HWND hWindow;
+  OSWindow *window;
   struct _SMACKBLIT *pSmackMovieBlit;
   HANDLE hMightVid;
   HANDLE hMagicVid;
--- a/_deleted.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/_deleted.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -13206,8 +13206,556 @@
   camera_rotation_x_int_sine   = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX);
   camera_rotation_x_int_cosine = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX);
 }
-
-
+//----- (004A169E) --------------------------------------------------------
+bool Render::UsingDirect3D()
+{
+  return bUserDirect3D == 0;
+}
+
+//----- (004637EB) --------------------------------------------------------
+int __stdcall aWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+  //HANDLE v6; // eax@32
+  //HDC v10; // edi@50
+  //int v11; // esi@50
+  //signed int v13; // eax@135
+  //char v29; // dl@209
+  //bool v31; // ebx@211
+  //float v33; // ST04_4@246
+  //float v34; // ST04_4@254
+  //struct tagPAINTSTRUCT Paint; // [sp+24h] [bp-48h]@13
+  //int pXY[2]; // [sp+64h] [bp-8h]@261
+  //int a2; // [sp+7Ch] [bp+10h]@50
+
+  switch (uMsg)
+  {
+    case WM_SIZING: return 1;
+    
+    case WM_CREATE:  case WM_NCCREATE:
+    case WM_GETTEXT: case WM_SETTEXT:
+    case WM_SHOWWINDOW:
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+    case WM_DESTROY:
+      SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+      PostQuitMessage(0);
+      return 0;
+
+    case WM_WINDOWPOSCHANGED:
+    {
+      if (pVideoPlayer && pVideoPlayer->AnyMovieLoaded() && pVideoPlayer->pBinkBuffer)
+        BinkBufferSetOffset(pVideoPlayer->pBinkBuffer, 0, 0);
+
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+    }
+
+    case WM_CHAR:
+    {
+      if (!pKeyActionMap->_459F10(wParam) && !viewparams->field_4C)
+        GUI_HandleHotkey(wParam);
+    }
+    return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+
+    case WM_DEVICECHANGE:
+    {
+      if (wParam == 0x8000)          // CD or some device has been inserted - notify InsertCD dialog
+        PostMessageW(hInsertCDWindow, WM_USER + 1, 0, 0);
+      return 0;
+    }
+
+    case WM_COMMAND:
+    {
+      switch (wParam)
+      {
+        case 103:  pRenderer->SavePCXScreenshot();  return 0;
+
+        case 101:  // Quit game
+        case 40001:
+          SendMessageW(hWnd, WM_DESTROY, 0, 0);
+        return 0;
+
+
+        case 104:
+          pRenderer->ChangeBetweenWinFullscreenModes();
+          if ( pArcomageGame->bGameInProgress )
+            pArcomageGame->field_F6 = 1;
+        return 0;
+
+        //SubMenu "Party"
+        case 40007:  pParty->SetGold(pParty->uNumGold + 10000); return 0;
+        case 40008:  GivePartyExp(20000);  return 0;
+        case 40013:  pParty->SetGold(0);   return 0;
+
+        case 40059:
+          for (uint i = 0; i < 4; ++i)
+            pParty->pPlayers[i].uSkillPoints = 50;
+        return 0;
+        
+        case 40029:  pPlayers[uActiveCharacter]->SetPertified(true);  return 0;
+        case 40030:  pPlayers[uActiveCharacter]->SetWeak(true);       return 0;
+        case 40031:  pPlayers[uActiveCharacter]->SetPoison3(true);    return 0;
+        case 40032:  pPlayers[uActiveCharacter]->SetPoison2(true);    return 0;
+        case 40033:  pPlayers[uActiveCharacter]->SetPoison1(true);    return 0;
+        case 40034:  pPlayers[uActiveCharacter]->SetDisease3(true);   return 0;
+        case 40035:  pPlayers[uActiveCharacter]->SetDisease2(true);   return 0;
+        case 40036:  pPlayers[uActiveCharacter]->SetDisease1(true);   return 0;
+        case 40037:  pPlayers[uActiveCharacter]->SetCursed(true);     return 0;
+        case 40038:  pPlayers[uActiveCharacter]->SetInsane(true);     return 0;
+        case 40039:  pPlayers[uActiveCharacter]->SetDrunk(true);      return 0;
+        case 40040:  pPlayers[uActiveCharacter]->SetUnconcious(true); return 0;
+        case 40041:  pPlayers[uActiveCharacter]->SetDead(true);       return 0;
+        case 40042:  pPlayers[uActiveCharacter]->SetEradicated(true); return 0;
+        case 40043:  pPlayers[uActiveCharacter]->SetAsleep(true);     return 0;
+        case 40044:  pPlayers[uActiveCharacter]->SetAfraid(true);     return 0;
+        case 40045:  pPlayers[uActiveCharacter]->SetParalyzed(true);  return 0;
+        case 40073:  pPlayers[uActiveCharacter]->SetZombie(true);     return 0;
+
+        case 40006:  pParty->SetFood(pParty->uNumFoodRations + 20);   return 0;
+
+        case 40062:
+          pParty->alignment = PartyAlignment_Good;
+          SetUserInterface(pParty->alignment, true);
+          return 0;
+        case 40063:
+          pParty->alignment = PartyAlignment_Neutral;
+          SetUserInterface(pParty->alignment, true);
+          return 0;
+        case 40064:
+          pParty->alignment = PartyAlignment_Evil;
+          SetUserInterface(pParty->alignment, true);
+          return 0;
+
+        //SubMenu "Time"
+        case 40009:  pParty->uTimePlayed += Timer::Day;   return 0;
+        case 40010:  pParty->uTimePlayed += Timer::Week;   return 0;
+        case 40011:  pParty->uTimePlayed += Timer::Month;   return 0;
+        case 40012:  pParty->uTimePlayed += Timer::Year;   return 0;
+
+        //SubMenu "Items"
+        case 40015:
+        {
+          int pItemID = rand() % 500;
+          for ( uint i = 0; i < 500; ++i )
+          {
+            if ( pItemID + i > 499 )
+              pItemID = 0;
+            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 1 )
+            {
+              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
+              return 0;
+            }
+          }
+        }
+        return 0;
+        case 40016:
+        {
+          int pItemID = rand() % 500;
+          for ( uint i = 0; i < 500; ++i )
+          {
+            if ( pItemID + i > 499 )
+              pItemID = 0;
+            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 2 )
+            {
+              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
+              return 0;
+            }
+          }
+        }
+        return 0;
+        case 40017:
+        {
+          int pItemID = rand() % 500;
+          for ( uint i = 0; i < 500; ++i )
+          {
+            if ( pItemID + i > 499 )
+              pItemID = 0;
+            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 3 )
+            {
+              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
+              return 0;
+            }
+          }
+        }
+        return 0;
+        case 40018:
+        {
+          int pItemID = rand() % 500;
+          for ( uint i = 0; i < 500; ++i )
+          {
+            if ( pItemID + i > 499 )
+              pItemID = 0;
+            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 4 )
+            {
+              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
+              return 0;
+            }
+          }
+        }
+        return 0;
+        case 40019:
+        {
+          int pItemID = rand() % 500;
+          for ( uint i = 0; i < 500; ++i )
+          {
+            if ( pItemID + i > 499 )
+              pItemID = 0;
+            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 5 )
+            {
+              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
+              return 0;
+            }
+          }
+        }
+        return 0;
+        case 40020:
+        {
+          int pItemID = rand() % 500;
+          for ( uint i = 0; i < 500; ++i )
+          {
+            if ( pItemID + i > 499 )
+              pItemID = 0;
+            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 6 )
+            {
+              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
+              return 0;
+            }
+          }
+        }
+        return 0;
+        case 40061:
+        {
+          int pItemID = rand() % 500;
+          for ( uint i = 0; i < 500; ++i )
+          {
+            if ( pItemID + i > 499 )
+              pItemID = 0;
+            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St > 6 )
+            {
+              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
+              return 0;
+            }
+          }
+        }
+        return 0;
+
+      }
+    }
+    return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+    case WM_LBUTTONDOWN:
+      if (pArcomageGame->bGameInProgress)
+      {
+        pArcomageGame->stru1.field_0 = 7;
+        ArcomageGame::OnMouseClick(0, true);
+        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+      }
+
+      goto __handle_mouse_click;
+
+    case WM_RBUTTONDOWN:
+      if (pArcomageGame->bGameInProgress)
+      {
+        pArcomageGame->stru1.field_0 = 8;
+        ArcomageGame::OnMouseClick(1, true);
+        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+      }
+
+      if (pVideoPlayer->pVideoFrame.pPixels)
+        pVideoPlayer->bStopBeforeSchedule = 1;
+
+      pMouse->SetMouseClick(LOWORD(lParam), HIWORD(lParam));
+
+      if (pGame)
+      {
+        pGame->PickMouse(pGame->pIndoorCameraD3D->GetPickDepth(), LOWORD(lParam), HIWORD(lParam), 0, &vis_sprite_filter_2, &vis_door_filter);
+      }
+
+      UI_OnMouseRightClick(0);
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+
+    case WM_LBUTTONUP:
+      if ( !pArcomageGame->bGameInProgress )
+      {
+        back_to_game();
+        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+      }
+      pArcomageGame->stru1.field_0 = 3;
+      ArcomageGame::OnMouseClick(0, 0);
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+    case WM_RBUTTONUP:
+      if ( !pArcomageGame->bGameInProgress )
+      {
+        back_to_game();
+        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+      }
+      pArcomageGame->stru1.field_0 = 4;
+      ArcomageGame::OnMouseClick(1, false);
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+    case WM_LBUTTONDBLCLK:
+      if ( pArcomageGame->bGameInProgress )
+      {
+        pArcomageGame->stru1.field_0 = 7;
+        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+      }
+        
+__handle_mouse_click:
+      if (pVideoPlayer->pVideoFrame.pPixels)
+        pVideoPlayer->bStopBeforeSchedule = 1;
+
+      pMouse->SetMouseClick(LOWORD(lParam), HIWORD(lParam));
+
+      if (GetCurrentMenuID() == MENU_CREATEPARTY)
+      {
+        UI_OnKeyDown(VK_SELECT);
+      }
+
+      if (pGame)
+        pGame->PickMouse(512.0, LOWORD(lParam), HIWORD(lParam), false, &vis_sprite_filter_3, &vis_door_filter);
+
+      UI_OnMouseLeftClick(0);
+
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+    case WM_RBUTTONDBLCLK:
+      if (pArcomageGame->bGameInProgress)
+      {
+        pArcomageGame->stru1.field_0 = 8;
+        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+      }
+
+      if (pVideoPlayer->pVideoFrame.pPixels)
+        pVideoPlayer->bStopBeforeSchedule = true;
+
+      pMouse->SetMouseClick(LOWORD(lParam), HIWORD(lParam));
+
+      if (pGame)
+        pGame->PickMouse(pGame->pIndoorCameraD3D->GetPickDepth(), LOWORD(lParam), HIWORD(lParam), false, &vis_sprite_filter_2, &vis_door_filter);
+
+      UI_OnMouseRightClick(0);
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+
+    case WM_MBUTTONDOWN:
+      if (pRenderer->pRenderD3D && pGame)
+      {
+        pGame->PickMouse(pGame->pIndoorCameraD3D->GetPickDepth(), LOWORD(lParam), HIWORD(lParam), 1, &vis_sprite_filter_3, &vis_face_filter);
+      }
+
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+    case WM_MOUSEMOVE:
+      if ( pArcomageGame->bGameInProgress )
+      {
+        ArcomageGame::OnMouseMove(LOWORD(lParam), HIWORD(lParam));
+        ArcomageGame::OnMouseClick(0, wParam == MK_LBUTTON);
+        ArcomageGame::OnMouseClick(1, wParam == MK_RBUTTON);
+      }
+      else
+      {
+        pMouse->SetMouseClick(LOWORD(lParam), HIWORD(lParam));
+      }
+
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+    case WM_SYSCOMMAND:
+      if ( wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER )
+        return 0;
+
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+    //case WM_KEYUP:
+    //  if (wParam == VK_CONTROL)
+    //  {
+    //    dword_507B98_ctrl_pressed = 0;
+    //  }
+
+    //  return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+    case WM_KEYDOWN:
+      if ( uGameMenuUI_CurentlySelectedKeyIdx != -1 )
+      {
+        pKeyActionMap->_459F10(wParam);
+        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+      }
+      if ( !pArcomageGame->bGameInProgress )
+      {
+        if ( pVideoPlayer->pVideoFrame.pPixels )
+          pVideoPlayer->bStopBeforeSchedule = 1;
+        if ( wParam == VK_RETURN )
+        {
+          if ( !viewparams->field_4C )
+            UI_OnKeyDown(wParam);
+          return 0;
+        }
+        //if ( wParam == VK_CONTROL )
+        //{
+        //  dword_507B98_ctrl_pressed = 1;
+        //  return 0;
+        //}
+        if ( wParam == VK_ESCAPE )
+        {
+          pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, window_SpeakInHouse != 0, 0);
+          return 0;
+        }
+        if ( wParam <= VK_HOME )
+          return 0;
+        if ( wParam > VK_DOWN )
+        {
+          if ( wParam != VK_F4 || pVideoPlayer->AnyMovieLoaded() )
+            return 0;
+          SendMessageW(hWnd, WM_COMMAND, 104, 0);
+          return 0;
+        }
+        if ( wParam >= VK_LEFT && wParam <= VK_DOWN )
+        {
+          if ( pCurrentScreen != SCREEN_GAME && pCurrentScreen != SCREEN_MODAL_WINDOW )
+          {
+            if ( !viewparams->field_4C )
+              UI_OnKeyDown(wParam);
+            return 0;
+          }
+        }
+        if ( pCurrentScreen != SCREEN_GAME && pCurrentScreen != SCREEN_MODAL_WINDOW )
+          return 0;
+      }
+
+      pArcomageGame->stru1.field_0 = 1;
+
+      set_stru1_field_8_InArcomage(MapVirtualKey(wParam, MAPVK_VK_TO_CHAR));
+      if ( wParam == 27 )
+      {
+        pArcomageGame->GameOver = 1;
+        pArcomageGame->field_F4 = 1;
+        pArcomageGame->uGameResult = 2;
+        pArcomageGame->field_B0 = -2;
+        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+      }
+      if ( wParam != 114 )
+      {
+        if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
+          SendMessage(hWnd, WM_COMMAND, 0x68u, 0);
+        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+      }
+      SendMessageW(hWnd, WM_COMMAND, 103, 0);
+      return 0;
+
+    case WM_ACTIVATEAPP:
+      if ( wParam && (GetForegroundWindow() == hWnd || GetForegroundWindow() == hInsertCDWindow) )
+      {
+        if ( BYTE1(dword_6BE364_game_settings_1) & 1 )
+        {
+          dword_4E98BC_bApplicationActive = 1;
+          if ( pRenderer->bWindowMode )
+          {
+            HDC hDC = GetDC(hWnd);
+            int bitsPerPixel = GetDeviceCaps(hDC, BITSPIXEL);
+            int planes = GetDeviceCaps(hDC, PLANES);
+            ReleaseDC(hWnd, hDC);
+            if (bitsPerPixel != 16 || planes != 1)
+              Error(pGlobalTXT_LocalizationStrings[62]);
+          }
+          BYTE1(dword_6BE364_game_settings_1) &= 0xFEu;
+
+          if ( pArcomageGame->bGameInProgress )
+          {
+            pArcomageGame->field_F9 = 1;
+          }
+          else
+          {
+            if ( BYTE1(dword_6BE364_game_settings_1) & 2 )
+              BYTE1(dword_6BE364_game_settings_1) &= 0xFDu;
+            else
+              pEventTimer->Resume();
+            if ( BYTE1(dword_6BE364_game_settings_1) & 4 )
+              BYTE1(dword_6BE364_game_settings_1) &= 0xFBu;
+            else
+              pMiscTimer->Resume();
+
+            viewparams->bRedrawGameUI = true;
+            if ( pVideoPlayer->pSmackerMovie )
+            {
+              pRenderer->RestoreFrontBuffer();
+              pRenderer->_4A184C();
+              pVideoPlayer->_4BF5B2();
+            }
+          }
+          if ( pAudioPlayer->hAILRedbook && !bGameoverLoop && !pVideoPlayer->pSmackerMovie )
+            AIL_redbook_resume(pAudioPlayer->hAILRedbook);
+        }
+      }
+      else
+      {
+        if (!(dword_6BE364_game_settings_1 & 0x100))
+        {
+          dword_4E98BC_bApplicationActive = 0;
+          if ( (pVideoPlayer->pSmackerMovie || pVideoPlayer->pBinkMovie) && pVideoPlayer->bPlayingMovie )
+            pVideoPlayer->bStopBeforeSchedule = 1;
+
+          //if (pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1)
+          if (pRenderer->uAcquiredDirect3DDevice == 1)
+            SetWindowPos(hWnd, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x18u);
+          ClipCursor(0);
+          dword_6BE364_game_settings_1 |= 0x100u;
+          if ( pEventTimer->bPaused )
+            BYTE1(dword_6BE364_game_settings_1) |= 2u;
+          else
+            pEventTimer->Pause();
+          if ( pMiscTimer->bPaused )
+            BYTE1(dword_6BE364_game_settings_1) |= 4u;
+          else
+            pMiscTimer->Pause();
+
+          pAudioPlayer->StopChannels(-1, -1);
+          if ( pAudioPlayer->hAILRedbook )
+            AIL_redbook_pause(pAudioPlayer->hAILRedbook);
+        }
+      }
+      return 0;
+
+    case WM_SETFOCUS:
+      dword_4E98BC_bApplicationActive = 0;
+      if (pRenderer)
+      {
+        //if (pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1)
+        if (pRenderer->uAcquiredDirect3DDevice == 1)
+          SetWindowPos(hWnd, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x18u);
+      }
+      ClipCursor(0);
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+    case WM_KILLFOCUS:
+      dword_4E98BC_bApplicationActive = 1;
+      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+
+    case WM_PAINT:
+      if ( !GetUpdateRect(hWnd, 0, 0) || !dword_4E98BC_bApplicationActive && !pRenderer->bWindowMode )
+        return 0;
+      PAINTSTRUCT Paint;
+      BeginPaint(hWnd, &Paint);
+      if ( pArcomageGame->bGameInProgress )
+      {
+        pArcomageGame->field_F9 = 1;
+      }
+      else
+      {
+        //if (!pRenderer->pRenderD3D && !pRenderer->UsingDirect3D() || !AreRenderSurfacesOk())
+        if (!AreRenderSurfacesOk())
+        {
+          EndPaint(hWnd, &Paint);
+          return 0;
+        }
+      }
+      pRenderer->Present();
+      EndPaint(hWnd, &Paint);
+      return 0;
+
+    default:
+      return DefWindowProcA(hWnd, uMsg, wParam, lParam);
+  }
+}
 
 const wchar_t *UIMessage2String(UIMessageType msg)
 {
--- a/mm7_2.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/mm7_2.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -64,6 +64,7 @@
 #include "texts.h"
 #include "MM7.h"
 #include "Lights.h"
+#include "NewUI/MainMenu.h"
 
 //----- (004BB756) --------------------------------------------------------
 int UseNPCSkill(NPCProf profession)
@@ -2752,124 +2753,26 @@
 //----- (0045828B) --------------------------------------------------------
 unsigned int __fastcall GetSpellColor(signed int a1)
 {
-  unsigned __int16 v1; // dx@3
-  unsigned __int16 v2; // cx@6
-  unsigned __int16 v4; // [sp-4h] [bp-4h]@3
-
-  if ( a1 < 1 )
-  {
-    if ( a1 < 12 )
-    {
-      if ( a1 < 23 )
-      {
-        if ( a1 < 34 )
-        {
-          if ( a1 < 45 )
-          {
-            if ( a1 < 56 )
-            {
-              if ( a1 < 67 )
-              {
-                if ( a1 < 78 )
-                {
-                  if ( a1 < 89 )
-				  {
-					v4 = 0;
-					v1 = 0;
-					v2 = 0;
-					return TargetColor(v2, v1, v4);
-				  }
-                }
-				else
-				{
-LABEL_25:
-					if ( a1 < 89 )
-					{
-					  v4 = 155;
-					  v2 = 255;
-					  v1 = v2;
-					  return TargetColor(v2, v1, v4);
-					}
-				}
-                if ( a1 < 100 )
-                {
-                  v4 = 240;
-                  v2 = 192;
-				  v1 = v2;
-				  return TargetColor(v2, v1, v4);
-                }
-                v4 = 0;
-                v1 = 0;
-				v2 = 0;
-				return TargetColor(v2, v1, v4);
-              }
-LABEL_21:
-              if ( a1 < 78 )
-              {
-                v4 = 0;
-                v1 = 128;
-			    v2 = 255;
-			    return TargetColor(v2, v1, v4);
-              }
-              goto LABEL_25;
-            }
-LABEL_18:
-            if ( a1 < 67 )
-            {
-              v4 = 255;
-              v1 = 15;
-              v2 = 235;
-              return TargetColor(v2, v1, v4);
-            }
-            goto LABEL_21;
-          }
-LABEL_15:
-          if ( a1 < 56 )
-          {
-            v2 = 225;
-            v4 = v2;
-            v1 = v2;
-            return TargetColor(v2, v1, v4);
-          }
-          goto LABEL_18;
-        }
-LABEL_11:
-        if ( a1 < 45 )
-        {
-          v2 = 128;
-          v4 = v2;
-          v1 = v2;
-          return TargetColor(v2, v1, v4);
-        }
-        goto LABEL_15;
-      }
-LABEL_8:
-      if ( a1 < 34 )
-      {
-        v4 = 255;
-        v1 = 128;
-        v2 = 0;
-        return TargetColor(v2, v1, v4);
-      }
-      goto LABEL_11;
-    }
-  }
-  else
-  {
-    if ( a1 < 12 )
-    {
-      v4 = 0;
-      v1 = 85;
-      v2 = 255;
-      return TargetColor(v2, v1, v4);
-    }
-  }
-  if ( a1 >= 23 )
-    goto LABEL_8;
-  v4 = 255;
-  v1 = 212;
-  v2 = 150;
-  return TargetColor(v2, v1, v4);
+  if ( a1 == 0 )
+    return TargetColor(0, 0, 0);
+  if ( a1 < 12 )
+    return TargetColor(255, 85, 0);
+  if ( a1 < 23 )
+    return TargetColor(150, 212, 255);
+  if ( a1 < 34 )
+    return TargetColor(0, 128, 255);
+  if ( a1 < 45 )
+    return TargetColor(128, 128, 128);
+  if ( a1 < 56 )
+    return TargetColor(225, 225, 225);
+  if ( a1 < 67 )
+    return TargetColor(235, 15, 255);
+  if ( a1 < 78 )
+    return TargetColor(255, 128, 0);
+  if ( a1 < 89 )
+    return TargetColor(255, 255, 155);
+  if ( a1 < 100 )
+    return TargetColor(192, 192, 240);
 }
 
 //----- (004610AA) --------------------------------------------------------
@@ -2937,7 +2840,8 @@
     //{
       v3 = pActor->pMonsterInfo.uID;
       v17 = 0;
-      if ( v3 >= 115 && v3 <= 186 || v3 >= 232 && v3 <= 249 )
+      if ( pActor->pMonsterInfo.uID >= 115 && pActor->pMonsterInfo.uID <= 186
+        || pActor->pMonsterInfo.uID >= 232 && pActor->pMonsterInfo.uID <= 249 )
         v17 = 1;
       //v1 = 0;
       v4 = (v3 - 1) % 3;
@@ -3108,8 +3012,8 @@
   pTexture_PCX.Release();
   pTexture_PCX.Load("title.pcx", 0);
   SetCurrentMenuID(MENU_MAIN);
-  SetForegroundWindow(hWnd);
-  SendMessageW(hWnd, WM_ACTIVATEAPP, 1, 0);
+  //SetForegroundWindow(hWnd);
+  //SendMessageW(hWnd, WM_ACTIVATEAPP, 1, 0);
   while (GetCurrentMenuID() == MENU_MAIN || GetCurrentMenuID() == MENU_SAVELOAD)
   {
     POINT pt;
@@ -3213,549 +3117,6 @@
   pIcons_LOD->RemoveTexturesPackFromTextureList();
 }
 
-//----- (004637EB) --------------------------------------------------------
-int __stdcall aWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-  //HANDLE v6; // eax@32
-  //HDC v10; // edi@50
-  //int v11; // esi@50
-  //signed int v13; // eax@135
-  //char v29; // dl@209
-  //bool v31; // ebx@211
-  //float v33; // ST04_4@246
-  //float v34; // ST04_4@254
-  //struct tagPAINTSTRUCT Paint; // [sp+24h] [bp-48h]@13
-  //int pXY[2]; // [sp+64h] [bp-8h]@261
-  //int a2; // [sp+7Ch] [bp+10h]@50
-
-  switch (uMsg)
-  {
-    case WM_SIZING: return 1;
-    
-    case WM_CREATE:  case WM_NCCREATE:
-    case WM_GETTEXT: case WM_SETTEXT:
-    case WM_SHOWWINDOW:
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_DESTROY:
-      SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
-      PostQuitMessage(0);
-      return 0;
-
-    case WM_WINDOWPOSCHANGED:
-    {
-      if (pVideoPlayer && pVideoPlayer->AnyMovieLoaded() && pVideoPlayer->pBinkBuffer)
-        BinkBufferSetOffset(pVideoPlayer->pBinkBuffer, 0, 0);
-
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-    }
-
-    case WM_CHAR:
-    {
-      if (!pKeyActionMap->_459F10(wParam) && !viewparams->field_4C)
-        GUI_HandleHotkey(wParam);
-    }
-    return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-
-    case WM_DEVICECHANGE:
-    {
-      if (wParam == 0x8000)          // CD or some device has been inserted - notify InsertCD dialog
-        PostMessageW(hInsertCDWindow, WM_USER + 1, 0, 0);
-      return 0;
-    }
-
-    case WM_COMMAND:
-    {
-      switch (wParam)
-      {
-        case 103:  pRenderer->SavePCXScreenshot();  return 0;
-
-        case 101:  // Quit game
-        case 40001:
-          SendMessageW(hWnd, WM_DESTROY, 0, 0);
-        return 0;
-
-
-        case 104:
-          pRenderer->ChangeBetweenWinFullscreenModes();
-          if ( pArcomageGame->bGameInProgress )
-            pArcomageGame->field_F6 = 1;
-        return 0;
-
-        //SubMenu "Party"
-        case 40007:  pParty->SetGold(pParty->uNumGold + 10000); return 0;
-        case 40008:  GivePartyExp(20000);  return 0;
-        case 40013:  pParty->SetGold(0);   return 0;
-
-        case 40059:
-          for (uint i = 0; i < 4; ++i)
-            pParty->pPlayers[i].uSkillPoints = 50;
-        return 0;
-        
-        case 40029:  pPlayers[uActiveCharacter]->SetPertified(true);  return 0;
-        case 40030:  pPlayers[uActiveCharacter]->SetWeak(true);       return 0;
-        case 40031:  pPlayers[uActiveCharacter]->SetPoison3(true);    return 0;
-        case 40032:  pPlayers[uActiveCharacter]->SetPoison2(true);    return 0;
-        case 40033:  pPlayers[uActiveCharacter]->SetPoison1(true);    return 0;
-        case 40034:  pPlayers[uActiveCharacter]->SetDisease3(true);   return 0;
-        case 40035:  pPlayers[uActiveCharacter]->SetDisease2(true);   return 0;
-        case 40036:  pPlayers[uActiveCharacter]->SetDisease1(true);   return 0;
-        case 40037:  pPlayers[uActiveCharacter]->SetCursed(true);     return 0;
-        case 40038:  pPlayers[uActiveCharacter]->SetInsane(true);     return 0;
-        case 40039:  pPlayers[uActiveCharacter]->SetDrunk(true);      return 0;
-        case 40040:  pPlayers[uActiveCharacter]->SetUnconcious(true); return 0;
-        case 40041:  pPlayers[uActiveCharacter]->SetDead(true);       return 0;
-        case 40042:  pPlayers[uActiveCharacter]->SetEradicated(true); return 0;
-        case 40043:  pPlayers[uActiveCharacter]->SetAsleep(true);     return 0;
-        case 40044:  pPlayers[uActiveCharacter]->SetAfraid(true);     return 0;
-        case 40045:  pPlayers[uActiveCharacter]->SetParalyzed(true);  return 0;
-        case 40073:  pPlayers[uActiveCharacter]->SetZombie(true);     return 0;
-
-        case 40006:  pParty->SetFood(pParty->uNumFoodRations + 20);   return 0;
-
-        case 40062:
-          pParty->alignment = PartyAlignment_Good;
-          SetUserInterface(pParty->alignment, true);
-          return 0;
-        case 40063:
-          pParty->alignment = PartyAlignment_Neutral;
-          SetUserInterface(pParty->alignment, true);
-          return 0;
-        case 40064:
-          pParty->alignment = PartyAlignment_Evil;
-          SetUserInterface(pParty->alignment, true);
-          return 0;
-
-        //SubMenu "Time"
-        case 40009:  pParty->uTimePlayed += Timer::Day;   return 0;
-        case 40010:  pParty->uTimePlayed += Timer::Week;   return 0;
-        case 40011:  pParty->uTimePlayed += Timer::Month;   return 0;
-        case 40012:  pParty->uTimePlayed += Timer::Year;   return 0;
-
-        //SubMenu "Items"
-        case 40015:
-        {
-          int pItemID = rand() % 500;
-          for ( uint i = 0; i < 500; ++i )
-          {
-            if ( pItemID + i > 499 )
-              pItemID = 0;
-            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 1 )
-            {
-              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
-              return 0;
-            }
-          }
-        }
-        return 0;
-        case 40016:
-        {
-          int pItemID = rand() % 500;
-          for ( uint i = 0; i < 500; ++i )
-          {
-            if ( pItemID + i > 499 )
-              pItemID = 0;
-            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 2 )
-            {
-              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
-              return 0;
-            }
-          }
-        }
-        return 0;
-        case 40017:
-        {
-          int pItemID = rand() % 500;
-          for ( uint i = 0; i < 500; ++i )
-          {
-            if ( pItemID + i > 499 )
-              pItemID = 0;
-            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 3 )
-            {
-              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
-              return 0;
-            }
-          }
-        }
-        return 0;
-        case 40018:
-        {
-          int pItemID = rand() % 500;
-          for ( uint i = 0; i < 500; ++i )
-          {
-            if ( pItemID + i > 499 )
-              pItemID = 0;
-            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 4 )
-            {
-              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
-              return 0;
-            }
-          }
-        }
-        return 0;
-        case 40019:
-        {
-          int pItemID = rand() % 500;
-          for ( uint i = 0; i < 500; ++i )
-          {
-            if ( pItemID + i > 499 )
-              pItemID = 0;
-            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 5 )
-            {
-              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
-              return 0;
-            }
-          }
-        }
-        return 0;
-        case 40020:
-        {
-          int pItemID = rand() % 500;
-          for ( uint i = 0; i < 500; ++i )
-          {
-            if ( pItemID + i > 499 )
-              pItemID = 0;
-            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 6 )
-            {
-              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
-              return 0;
-            }
-          }
-        }
-        return 0;
-        case 40061:
-        {
-          int pItemID = rand() % 500;
-          for ( uint i = 0; i < 500; ++i )
-          {
-            if ( pItemID + i > 499 )
-              pItemID = 0;
-            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St > 6 )
-            {
-              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
-              return 0;
-            }
-          }
-        }
-        return 0;
-
-      }
-    }
-    return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_LBUTTONDOWN:
-      if (pArcomageGame->bGameInProgress)
-      {
-        pArcomageGame->stru1.field_0 = 7;
-        ArcomageGame::OnMouseClick(0, true);
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-      }
-
-      goto __handle_mouse_click;
-
-    case WM_RBUTTONDOWN:
-      if (pArcomageGame->bGameInProgress)
-      {
-        pArcomageGame->stru1.field_0 = 8;
-        ArcomageGame::OnMouseClick(1, true);
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-      }
-
-      if (pVideoPlayer->pVideoFrame.pPixels)
-        pVideoPlayer->bStopBeforeSchedule = 1;
-
-      pMouse->SetMouseClick(LOWORD(lParam), HIWORD(lParam));
-
-      if (pGame)
-      {
-        pGame->PickMouse(pGame->pIndoorCameraD3D->GetPickDepth(), LOWORD(lParam), HIWORD(lParam), 0, &vis_sprite_filter_2, &vis_door_filter);
-      }
-
-      sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(0);
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-
-    case WM_LBUTTONUP:
-      if ( !pArcomageGame->bGameInProgress )
-      {
-        back_to_game();
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-      }
-      pArcomageGame->stru1.field_0 = 3;
-      ArcomageGame::OnMouseClick(0, 0);
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-    case WM_RBUTTONUP:
-      if ( !pArcomageGame->bGameInProgress )
-      {
-        back_to_game();
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-      }
-      pArcomageGame->stru1.field_0 = 4;
-      ArcomageGame::OnMouseClick(1, false);
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_LBUTTONDBLCLK:
-      if ( pArcomageGame->bGameInProgress )
-      {
-        pArcomageGame->stru1.field_0 = 7;
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-      }
-        
-__handle_mouse_click:
-      if (pVideoPlayer->pVideoFrame.pPixels)
-        pVideoPlayer->bStopBeforeSchedule = 1;
-
-      pMouse->SetMouseClick(LOWORD(lParam), HIWORD(lParam));
-
-      if (GetCurrentMenuID() == MENU_CREATEPARTY)
-      {
-        UI_OnKeyDown(VK_SELECT);
-      }
-
-      if (pGame)
-        pGame->PickMouse(512.0, LOWORD(lParam), HIWORD(lParam), false, &vis_sprite_filter_3, &vis_door_filter);
-
-      UI_OnMouseLeftClick(0);
-
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_RBUTTONDBLCLK:
-      if ( !pArcomageGame->bGameInProgress )
-      {
-        if (pVideoPlayer->pVideoFrame.pPixels)
-          pVideoPlayer->bStopBeforeSchedule = 1;
-
-        pMouse->SetMouseClick(LOWORD(lParam), HIWORD(lParam));
-
-        if (pGame)
-        {
-          pGame->PickMouse(pGame->pIndoorCameraD3D->GetPickDepth(), LOWORD(lParam), HIWORD(lParam), false, &vis_sprite_filter_2, &vis_door_filter);
-        }
-
-        sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(0);
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-      }
-
-      pArcomageGame->stru1.field_0 = 8;
-
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_MBUTTONDOWN:
-      if (pRenderer->pRenderD3D && pGame)
-      {
-        pGame->PickMouse(pGame->pIndoorCameraD3D->GetPickDepth(), LOWORD(lParam), HIWORD(lParam), 1, &vis_sprite_filter_3, &vis_face_filter);
-      }
-
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_MOUSEMOVE:
-      if ( pArcomageGame->bGameInProgress )
-      {
-        ArcomageGame::OnMouseMove(LOWORD(lParam), HIWORD(lParam));
-        ArcomageGame::OnMouseClick(0, wParam == MK_LBUTTON);
-        ArcomageGame::OnMouseClick(1, wParam == MK_RBUTTON);
-      }
-      else
-      {
-        pMouse->SetMouseClick(LOWORD(lParam), HIWORD(lParam));
-      }
-
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_SYSCOMMAND:
-      if ( wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER )
-        return 0;
-
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_KEYUP:
-      if (wParam == VK_CONTROL)
-      {
-        dword_507B98_ctrl_pressed = 0;
-      }
-
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_KEYDOWN:
-      if ( uGameMenuUI_CurentlySelectedKeyIdx != -1 )
-      {
-        pKeyActionMap->_459F10(wParam);
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-      }
-      if ( !pArcomageGame->bGameInProgress )
-      {
-        if ( pVideoPlayer->pVideoFrame.pPixels )
-          pVideoPlayer->bStopBeforeSchedule = 1;
-        if ( wParam == VK_RETURN )
-        {
-          if ( !viewparams->field_4C )
-            UI_OnKeyDown(wParam);
-          return 0;
-        }
-        if ( wParam == VK_CONTROL )
-        {
-          dword_507B98_ctrl_pressed = 1;
-          return 0;
-        }
-        if ( wParam == VK_ESCAPE )
-        {
-          pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, window_SpeakInHouse != 0, 0);
-          return 0;
-        }
-        if ( wParam <= VK_HOME )
-          return 0;
-        if ( wParam > VK_DOWN )
-        {
-          if ( wParam != VK_F4 || pVideoPlayer->AnyMovieLoaded() )
-            return 0;
-          SendMessageW(hWnd, WM_COMMAND, 104, 0);
-          return 0;
-        }
-        if ( wParam >= VK_LEFT && wParam <= VK_DOWN )
-        {
-          if ( pCurrentScreen != SCREEN_GAME && pCurrentScreen != SCREEN_MODAL_WINDOW )
-          {
-            if ( !viewparams->field_4C )
-              UI_OnKeyDown(wParam);
-            return 0;
-          }
-        }
-        if ( pCurrentScreen != SCREEN_GAME && pCurrentScreen != SCREEN_MODAL_WINDOW )
-          return 0;
-      }
-
-      pArcomageGame->stru1.field_0 = 1;
-
-      set_stru1_field_8_InArcomage(MapVirtualKey(wParam, MAPVK_VK_TO_CHAR));
-      if ( wParam == 27 )
-      {
-        pArcomageGame->GameOver = 1;
-        pArcomageGame->field_F4 = 1;
-        pArcomageGame->uGameResult = 2;
-        pArcomageGame->field_B0 = -2;
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-      }
-      if ( wParam != 114 )
-      {
-        if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
-          SendMessage(hWnd, WM_COMMAND, 0x68u, 0);
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-      }
-      SendMessageW(hWnd, WM_COMMAND, 103, 0);
-      return 0;
-
-    case WM_ACTIVATEAPP:
-      if ( wParam && (GetForegroundWindow() == hWnd || GetForegroundWindow() == hInsertCDWindow) )
-      {
-        if ( BYTE1(dword_6BE364_game_settings_1) & 1 )
-        {
-          dword_4E98BC_bApplicationActive = 1;
-          if ( pRenderer->bWindowMode )
-          {
-            HDC hDC = GetDC(hWnd);
-            int bitsPerPixel = GetDeviceCaps(hDC, BITSPIXEL);
-            int planes = GetDeviceCaps(hDC, PLANES);
-            ReleaseDC(hWnd, hDC);
-            if (bitsPerPixel != 16 || planes != 1)
-              Error(pGlobalTXT_LocalizationStrings[62]);
-          }
-          BYTE1(dword_6BE364_game_settings_1) &= 0xFEu;
-
-          if ( pArcomageGame->bGameInProgress )
-          {
-            pArcomageGame->field_F9 = 1;
-          }
-          else
-          {
-            if ( BYTE1(dword_6BE364_game_settings_1) & 2 )
-              BYTE1(dword_6BE364_game_settings_1) &= 0xFDu;
-            else
-              pEventTimer->Resume();
-            if ( BYTE1(dword_6BE364_game_settings_1) & 4 )
-              BYTE1(dword_6BE364_game_settings_1) &= 0xFBu;
-            else
-              pMiscTimer->Resume();
-
-            viewparams->bRedrawGameUI = true;
-            if ( pVideoPlayer->pSmackerMovie )
-            {
-              pRenderer->RestoreFrontBuffer();
-              pRenderer->_4A184C();
-              pVideoPlayer->_4BF5B2();
-            }
-          }
-          if ( pAudioPlayer->hAILRedbook && !bGameoverLoop && !pVideoPlayer->pSmackerMovie )
-            AIL_redbook_resume(pAudioPlayer->hAILRedbook);
-        }
-      }
-      else
-      {
-        if (!(dword_6BE364_game_settings_1 & 0x100))
-        {
-          dword_4E98BC_bApplicationActive = 0;
-          if ( (pVideoPlayer->pSmackerMovie || pVideoPlayer->pBinkMovie) && pVideoPlayer->bPlayingMovie )
-            pVideoPlayer->bStopBeforeSchedule = 1;
-
-          if ( pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1 )
-            SetWindowPos(hWnd, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x18u);
-          ClipCursor(0);
-          dword_6BE364_game_settings_1 |= 0x100u;
-          if ( pEventTimer->bPaused )
-            BYTE1(dword_6BE364_game_settings_1) |= 2u;
-          else
-            pEventTimer->Pause();
-          if ( pMiscTimer->bPaused )
-            BYTE1(dword_6BE364_game_settings_1) |= 4u;
-          else
-            pMiscTimer->Pause();
-
-          pAudioPlayer->StopChannels(-1, -1);
-          if ( pAudioPlayer->hAILRedbook )
-            AIL_redbook_pause(pAudioPlayer->hAILRedbook);
-        }
-      }
-      return 0;
-
-    case WM_SETFOCUS:
-      dword_4E98BC_bApplicationActive = 0;
-      if (pRenderer)
-      {
-        if ( pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1 )
-          SetWindowPos(hWnd, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x18u);
-      }
-      ClipCursor(0);
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_KILLFOCUS:
-      dword_4E98BC_bApplicationActive = 1;
-      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-
-    case WM_PAINT:
-      if ( !GetUpdateRect(hWnd, 0, 0) || !dword_4E98BC_bApplicationActive && !pRenderer->bWindowMode )
-        return 0;
-      PAINTSTRUCT Paint;
-      BeginPaint(hWnd, &Paint);
-      if ( pArcomageGame->bGameInProgress )
-      {
-        pArcomageGame->field_F9 = 1;
-      }
-      else
-      {
-        if ( !pRenderer->pRenderD3D && !pRenderer->UsingDirect3D() || !AreRenderSurfacesOk() )
-        {
-          EndPaint(hWnd, &Paint);
-          return 0;
-        }
-      }
-      pRenderer->Present();
-      EndPaint(hWnd, &Paint);
-      return 0;
-
-    default:
-      return DefWindowProcA(hWnd, uMsg, wParam, lParam);
-  }
-}
 
 //----- (00464479) --------------------------------------------------------
 void ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows()
@@ -3812,9 +3173,9 @@
   ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows();
   pGame->Deinitialize();
   pRenderer->Release2();
-  if ( !DestroyWindow(hWnd) )
-    GetLastError();
-  hWnd = 0;
+  delete window;
+  //if ( !DestroyWindow(hWnd) )
+  //  GetLastError();
   exit(exitCode);
 }
 
@@ -4274,7 +3635,7 @@
         }
     }
 
-    if (DialogBoxParamA(GetModuleHandleW(nullptr), "InsertCD", ::hWnd, (DLGPROC)InsertMM7CDDialogFunc, 0))
+    if (DialogBoxParamA(GetModuleHandleW(nullptr), "InsertCD", hWnd, (DLGPROC)InsertMM7CDDialogFunc, 0))
       continue;
     return false;
   }
@@ -4282,35 +3643,6 @@
 
 
 
-void CenterWindowAndAdjustSize(HWND hwnd, int client_width, int client_height)
-{
-  RECT rcWindow;
-  GetWindowRect(hWnd, &rcWindow);
-
-  RECT rcClient;
-  GetClientRect(hWnd, &rcClient);
-
-  int window_borders_width = (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left),
-      window_borders_height = (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top);
-  int window_total_width = client_width + window_borders_width,
-      window_total_height = client_height + window_borders_height;
-
-  
-  if (GetMenu(hwnd))
-    window_total_height += GetSystemMetrics(SM_CYMENU);
-
-  MoveWindow(hWnd, (GetSystemMetrics(SM_CXSCREEN) - window_total_width) / 2,
-                   (GetSystemMetrics(SM_CYSCREEN) - window_total_height) / 2,
-                   window_total_width,
-                   window_total_height, 0);
-/*
-  auto hDesktopDC = GetDC(nullptr);
-  uint uDesktopWidth = GetDeviceCaps(hDesktopDC, HORZRES);
-  uint uDesktopHeight = GetDeviceCaps(hDesktopDC, VERTRES);
-  ReleaseDC(nullptr, hDesktopDC);
-*/
-}
-
 //----- (004651F4) --------------------------------------------------------
 bool MM7_Initialize(int game_width, int game_height)
 {
@@ -4325,187 +3657,14 @@
     bCanLoadFromCD = false;
   if (bCanLoadFromCD)
   {
-    if (!FindMM7CD(hWnd, &cMM7GameCDDriveLetter))
+    if (!FindMM7CD(nullptr, &cMM7GameCDDriveLetter))
       return false;
   }
 
 
   srand(GetTickCount());
-  
-  WNDCLASSEXW wcxw;
-  {
-    wcxw.cbSize = sizeof(wcxw);
-    wcxw.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
-    wcxw.lpfnWndProc = (WNDPROC)aWinProc;
-    wcxw.cbClsExtra = 0;
-    wcxw.cbWndExtra = 0;
-    wcxw.hInstance = GetModuleHandleW(nullptr);
-    wcxw.hCursor = 0;
-    wcxw.hIcon = wcxw.hIconSm = LoadIconW(wcxw.hInstance, L"MM7_ICON");
-    wcxw.lpszMenuName = nullptr;
-    wcxw.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
-    wcxw.lpszClassName = L"M&MTrilogy";
-  }
-  if (!RegisterClassExW(&wcxw))
-  {
-    Log::Warning(L"Cannot register window class");
-    return false;
-  }
-
-  hWnd = CreateWindowExW(0, wcxw.lpszClassName, L"Might and Magic® VII",
-                         WS_SYSMENU | WS_GROUP | WS_DLGFRAME | WS_BORDER,
-                         0, 0,
-                         1, 1,
-                         nullptr,
-                         nullptr,
-                         wcxw.hInstance,
-                         nullptr);
-
-  HMENU menu = CreateMenu();
-  {
-    HMENU file = CreatePopupMenu();
-    AppendMenuW(menu, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)file, L"&File");
-    {
-      AppendMenuW(file, MF_ENABLED | MF_STRING, 40001, L"Exit");
-    }
-
-    HMENU debug = CreatePopupMenu();
-    AppendMenuW(menu, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug, L"&Debug");
-    {
-      HMENU debug_party = CreatePopupMenu();
-      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_party, L"&Party");
-      {
-        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40007, L"Give Gold (10 000)");
-        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40008, L"Give Exp (20 000)");
-        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40059, L"Give Skills (50 each)");
-        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40013, L"Remove Gold");
-
-        HMENU debug_party_setconditions = CreatePopupMenu();
-        AppendMenuW(debug_party, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_party_setconditions, L"Set Condition");
-        {
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40044, L"Afraid");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40043, L"Asleep");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40037, L"Curse");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40036, L"Disease1");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40035, L"Disease2");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40034, L"Disease3");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40041, L"Dead");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40039, L"Drunk");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40042, L"Eradicated");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40038, L"Insane");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40045, L"Paralyzed");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40033, L"Poison1");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40032, L"Poison2");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40031, L"Poison3");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40029, L"&Stone");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40040, L"Unconscious");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40030, L"Weak");
-          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40073, L"Zombie");
-        }
-
-        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40006, L"Set Food (20)");
-
-        HMENU debug_party_alignment = CreatePopupMenu();
-        AppendMenuW(debug_party, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_party_alignment, L"Alignment");
-        {
-          AppendMenuW(debug_party_alignment, MF_ENABLED | MF_STRING, 40062, L"Good");
-          AppendMenuW(debug_party_alignment, MF_ENABLED | MF_STRING | MF_CHECKED, 40063, L"Neutral");
-          AppendMenuW(debug_party_alignment, MF_ENABLED | MF_STRING, 40064, L"Evil");
-        }
-      }
-
-      HMENU debug_time = CreatePopupMenu();
-      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_time, L"&Time");
-      {
-        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40009, L"Add 1 Day");
-        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40010, L"Add 1 Week");
-        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40011, L"Add 1 Month");
-        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40012, L"Add 1 Year");
-      }
-
-      HMENU debug_items = CreatePopupMenu();
-      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_items, L"&Items");
-      {
-        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40015, L"Generate level &1 item");
-        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40016, L"Generate level &2 item");
-        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40017, L"Generate level &3 item");
-        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40018, L"Generate level &4 item");
-        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40019, L"Generate level &5 item");
-        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40020, L"Generate level &6 item");
-        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40061, L"Generate special item");
-      }
-
-      HMENU debug_graphics = CreatePopupMenu();
-      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_graphics, L"&Graphics");
-      {
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40023, L"Lighting Mode");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40024, L"Lighting Geometry");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING | MF_GRAYED, 40104, L"Lights Off");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40105, L"Colored Lights");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40025, L"Debug Lights");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40101, L"Debug Decals");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40027, L"HWID Portals");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40047, L"SWID Portals");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40051, L"OD Frustum");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40054, L"SWOD Constant Redraw");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40055, L"SWOD Lit Rasterizer");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40056, L"Party Light off");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40060, L"SWOD Nice Lighting off");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40067, L"HWOD Additive Fog Lights");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40072, L"HWID Nice Lighting");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40048, L"Wireframe");
-        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40049, L"Fog");
-      }
-
-      HMENU debug_misc = CreatePopupMenu();
-      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_misc, L"&Misc");
-      {
-        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40066, L"Object Viewcone Culling");
-        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40068, L"Red Tint");
-        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40071, L"Display Secrets");
-        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40102, L"Massive Bloodsplat");
-        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40103, L"Underwater Gravity");
-      }
-      
-      HMENU debug_eax = CreatePopupMenu();
-      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_eax, L"EAX Environs");
-      {
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40074, L"NONE");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40075, L"GENERIC");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40076, L"PADDEDCELL");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40077, L"ROOM");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40078, L"BATHROOM");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40079, L"LIVINGROOM");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40080, L"STONEROOM");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40081, L"AUDITORIUM");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40082, L"CONCERTHALL");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40083, L"CAVE");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40084, L"ARENA");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40085, L"HANGAR");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40086, L"CARPETEDHALLWAY");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40087, L"HALLWAY");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40088, L"STONECORRIDOR");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40089, L"ALLEY");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40090, L"FOREST");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40091, L"CITY");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40092, L"MOUNTAINS");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40093, L"QUARRY");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40094, L"PLAIN");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40095, L"PARKINGLOT");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40096, L"SEWERPIPE");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40097, L"UNDERWATER");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40098, L"DRUGGED");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40099, L"DIZZY");
-        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40100, L"PSICHOTIC");
-      }
-    }
-  }
-
-  SetMenu(hWnd, menu);
-  CenterWindowAndAdjustSize(hWnd, game_width, game_height);
-  ShowWindow(hWnd, SW_SHOWNORMAL);
-  
-  SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+
+  window = OSWindow::Create(L"Might and Magic® Trilogy", game_width, game_height);
 
   pRenderer = Render::Create();
   if (!pRenderer)
@@ -4516,12 +3675,12 @@
   else
   {
     bool bWindowMode = ReadWindowsRegistryInt("startinwindow", false);
-    uint uDefaultDevice = ReadWindowsRegistryInt("D3D Device", 1);
+    //uint uDefaultDevice = ReadWindowsRegistryInt("D3D Device", 1);
     bool bColoredLights = ReadWindowsRegistryInt("Colored Lights", false);
     uint uLevelOfDetail = ReadWindowsRegistryInt("Detail Level", 1);
     uint bTinting = ReadWindowsRegistryInt("Tinting", 1) != 0;
 
-    if (!pRenderer->Initialize(bWindowMode, game_width, game_height, uDefaultDevice, bColoredLights, uLevelOfDetail, bTinting))
+    if (!pRenderer->Initialize(bWindowMode, window, bColoredLights, uLevelOfDetail, bTinting))
     {
       Log::Warning(L"Render failed to initialize");
       return false;
@@ -4797,15 +3956,13 @@
                                                 // or
                                                 //   not in window
   {
-    SetMenu(hWnd, 0);
-    SetWindowLongA(hWnd, GWL_EXSTYLE, 0);
-    SetWindowLongA(hWnd, GWL_STYLE, WS_VISIBLE);
-    pRenderer->InitializeFullscreen(hWnd);
+    window->SetFullscreenMode();
+    pRenderer->InitializeFullscreen();
   }
   else
   {
-    ClipCursor(nullptr);
-    pRenderer->SwitchToWindow(hWnd);
+    window->SetWindowedMode(game_width, game_height);
+    pRenderer->SwitchToWindow();
   }
 
   uSoundVolumeMultiplier = ReadWindowsRegistryInt("soundflag", 9);
@@ -4836,10 +3993,10 @@
   dword_6BE384_2dacceloff = ReadWindowsRegistryInt("2dacceloff", 0);
 
   if (!bNoSound)
-    pAudioPlayer->Initialize(hWnd);
+    pAudioPlayer->Initialize();
 
   pVideoPlayer = new VideoPlayer();
-  pVideoPlayer->Initialize();
+  pVideoPlayer->Initialize(window);
 
   dword_6BE364_game_settings_1 |= 0x4000;
 
@@ -4869,7 +4026,7 @@
 }
 
 //----- (00465D0B) --------------------------------------------------------
-void  SecondaryInitialization()
+void SecondaryInitialization()
 {
   __int16 v4; // ax@4
   signed int v5; // esi@5
@@ -4878,7 +4035,7 @@
   ObjectDesc *v8; // eax@7
   char pContainer[32]; // [sp+10h] [bp-Ch]@9
 
-  pMouse->Initialize(hWnd);
+  pMouse->Initialize(window);
 
   pItemsTable = new ItemsTable;
   pItemsTable->Initialize();
@@ -5182,6 +4339,9 @@
     Log::Warning(L"MM: entering main loop");
     while ( 1 )
     {
+      auto main_menu_window = MainMenuWindow::Create();
+      window->AddControl(main_menu_window);
+
       MainMenu_Loop();
       uGameState = GAME_STATE_PLAYING;
       while ( 1 )
--- a/mm7_3.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/mm7_3.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -751,102 +751,102 @@
 //----- (0047050A) --------------------------------------------------------
 int stru141_actor_collision_object::_47050A(int dt)
 {
-  stru141_actor_collision_object *v2; // esi@1
+  //stru141_actor_collision_object *v2; // esi@1
   //signed int v3; // eax@1
   //int v4; // ecx@1
   //int v5; // edx@1
   //int v6; // edx@1
   int v7; // eax@1
-  int v8; // eax@3
+  //int v8; // eax@3
   signed int result; // eax@4
-  int v10; // eax@5
-  int v11; // eax@5
-  int v12; // ebx@5
-  int v13; // edx@5
-  int v14; // edi@5
-  int v15; // ecx@5
-  int v16; // eax@5
+  //int v10; // eax@5
+  //int v11; // eax@5
+  //int v12; // ebx@5
+  //int v13; // edx@5
+  //int v14; // edi@5
+  //int v15; // ecx@5
+  //int v16; // eax@5
   int v17; // eax@5
   int v18; // eax@7
-  int v19; // edx@9
-  int v20; // edi@9
+  //int v19; // edx@9
+  //int v20; // edi@9
   int v21; // eax@9
   int v22; // eax@11
-  int v23; // edx@13
-  int v24; // eax@13
-  int v25; // eax@14
-  int v26; // eax@16
-  int v27; // eax@17
-  int v28; // [sp+14h] [bp+8h]@5
-
-  v2 = this;
+  //int v23; // edx@13
+  //int v24; // eax@13
+  //int v25; // eax@14
+  //int v26; // eax@16
+  //int v27; // eax@17
+  //int v28; // [sp+14h] [bp+8h]@5
+
+  //v2 = this;
   int speed = 1 | integer_sqrt(this->velocity.z * this->velocity.z + this->velocity.y * this->velocity.y + this->velocity.x * this->velocity.x);
 
-  v2->direction.x = 65536 / speed * v2->velocity.x;
-  v2->direction.y = 65536 / speed * v2->velocity.y;
-  v2->direction.z = 65536 / speed * v2->velocity.z;
-
-  v2->speed = speed;
-  v2->inv_speed = 65536 / speed;
+  this->direction.x = 65536 / speed * this->velocity.x;
+  this->direction.y = 65536 / speed * this->velocity.y;
+  this->direction.z = 65536 / speed * this->velocity.z;
+
+  this->speed = speed;
+  this->inv_speed = 65536 / speed;
 
   if (dt)
     v7 = dt;
   else
     v7 = pEventTimer->dt_in_some_format;
 
-  v8 = fixpoint_mul(v7, speed) - v2->field_70; // speed * dt - something
-  v2->field_6C = v8;
-  if ( v8 > 0 )
-  {
-    v10 = fixpoint_mul(v8, v2->direction.x) + v2->normal.x;
-    v2->field_4C = v10;
-    v2->normal2.x = v10;
-    v11 = fixpoint_mul(v2->field_6C, v2->direction.y) + v2->normal.y;
-    v2->field_50 = v11;
-    v2->normal2.y = v11;
-    v2->normal2.z = fixpoint_mul(v2->field_6C, v2->direction.z) + v2->normal.z;
-    v12 = v2->position.z;
-    v13 = v2->normal.x;
-    v14 = v2->normal2.x;
-    v15 = v2->prolly_normal_d;
-    v16 = v12 + fixpoint_mul(v2->field_6C, v2->direction.z);
-    v28 = v16;
-    v2->field_54 = v16;
-    v17 = v13;
-    if ( v13 >= v14 )
-      v17 = v14;
-    v2->sMaxX = v17 - v15;
-    v18 = v15 + v13;
-    if ( v13 <= v14 )
-      v18 = v15 + v14;
-    v19 = v2->normal.y;
-    v20 = v2->normal2.y;
-    v2->sMinX = v18;
-    v21 = v19;
-    if ( v19 >= v20 )
-      v21 = v20;
-    v2->sMaxY = v21 - v15;
-    v22 = v15 + v19;
-    if ( v19 <= v20 )
-      v22 = v20 + v15;
-    v23 = v2->normal2.z;
-    v2->sMinY = v22;
-    v24 = v2->normal.z;
-    if ( v24 >= v23 )
-      v25 = v23 - v15;
+  //v8 = fixpoint_mul(v7, speed) - this->field_70; // speed * dt - something
+  this->field_6C = fixpoint_mul(v7, speed) - this->field_70;
+  if ( this->field_6C > 0 )
+  {
+    //v10 = fixpoint_mul(v8, this->direction.x) + this->normal.x;
+    this->field_4C = fixpoint_mul(this->field_6C, this->direction.x) + this->normal.x;
+    this->normal2.x = fixpoint_mul(this->field_6C, this->direction.x) + this->normal.x;
+    //v11 = fixpoint_mul(this->field_6C, this->direction.y) + this->normal.y;
+    this->field_50 = fixpoint_mul(this->field_6C, this->direction.y) + this->normal.y;
+    this->normal2.y = fixpoint_mul(this->field_6C, this->direction.y) + this->normal.y;
+    this->normal2.z = fixpoint_mul(this->field_6C, this->direction.z) + this->normal.z;
+    //v12 = this->position.z;
+    //v13 = this->normal.x;
+    //v14 = this->normal2.x;
+    //v15 = this->prolly_normal_d;
+    //v16 = this->position.z + fixpoint_mul(this->field_6C, this->direction.z);
+    //v28 = this->position.z + fixpoint_mul(this->field_6C, this->direction.z);
+    this->field_54 = this->position.z + fixpoint_mul(this->field_6C, this->direction.z);
+    v17 = this->normal.x;
+    if ( v17 >= this->normal2.x )
+      v17 = this->normal2.x;
+    this->sMaxX = v17 - this->prolly_normal_d;
+    v18 = this->prolly_normal_d + this->normal.x;
+    if ( this->normal.x <= this->normal2.x )
+      v18 = this->prolly_normal_d + this->normal2.x;
+    //v19 = this->normal.y;
+    //v20 = this->normal2.y;
+    this->sMinX = v18;
+    v21 = this->normal.y;
+    if ( v21 >= this->normal2.y )
+      v21 = this->normal2.y;
+    this->sMaxY = v21 - this->prolly_normal_d;
+    v22 = this->prolly_normal_d + this->normal.y;
+    if ( this->normal.y <= this->normal2.y )
+      v22 = this->normal2.y + this->prolly_normal_d;
+    //v23 = this->normal2.z;
+    this->sMinY = v22;
+    //v24 = this->normal.z;
+    if ( this->normal.z >= this->normal2.z )
+      this->sMaxZ = this->normal2.z - this->prolly_normal_d;
     else
-      v25 = v24 - v15;
-    v2->sMaxZ = v25;
-    v26 = v2->field_8_radius;
-    if ( v12 <= v28 )
-      v27 = v28 + v26;
+      this->sMaxZ = this->normal.z - this->prolly_normal_d;
+    //this->sMaxZ = v25;
+    //v26 = this->field_8_radius;
+    if ( this->position.z <= this->position.z + fixpoint_mul(this->field_6C, this->direction.z) )
+      this->sMinZ = (this->position.z + fixpoint_mul(this->field_6C, this->direction.z)) + this->field_8_radius;
     else
-      v27 = v12 + v26;
-    v2->uFaceID = 0;
-    v2->field_80 = -1;
-    v2->field_88 = -1;
-    v2->sMinZ = v27;
-    v2->field_7C = 0xFFFFFFu;
+      this->sMinZ = this->position.z + this->field_8_radius;
+    this->uFaceID = 0;
+    this->field_80 = -1;
+    this->field_88 = -1;
+    //this->sMinZ = v27;
+    this->field_7C = 0xFFFFFFu;
     result = 0;
   }
   else
@@ -4879,69 +4879,51 @@
 //----- (00479543) --------------------------------------------------------
 void Render::DrawSkyD3D()
 {
-  int v0; // esi@2
-  int v1; // eax@2
-  int v8; // eax@4
   int v9; // eax@4
   int v10; // ebx@4
-  signed __int64 v11; // qax@6
   int v13; // edi@6
   int v14; // ecx@6
+  int v15; // eax@8
   int v16; // eax@12
-  //signed __int64 v17; // qtt@13
-  signed int pShading; // ecx@13
+  signed __int64 v17; // qtt@13
+  signed int v18; // ecx@13
   struct Polygon pSkyPolygon; // [sp+14h] [bp-150h]@1
-  float v28; // [sp+12Ch] [bp-38h]@2
-  int v29; // [sp+130h] [bp-34h]@4
+  double v26; // [sp+120h] [bp-44h]@4
   int v30; // [sp+134h] [bp-30h]@1
   int v32; // [sp+13Ch] [bp-28h]@6
   int v33; // [sp+140h] [bp-24h]@2
-  int v34; // [sp+144h] [bp-20h]@1
+  signed __int64 v34; // [sp+144h] [bp-20h]@1
   int v35; // [sp+148h] [bp-1Ch]@4
-  int screen_center_x; // [sp+14Ch] [bp-18h]@2
+  int v36; // [sp+14Ch] [bp-18h]@2
   int v37; // [sp+154h] [bp-10h]@8
-  int pViewportBR_Y; // [sp+158h] [bp-Ch]@1
+  int v38; // [sp+158h] [bp-Ch]@1
   int v39; // [sp+15Ch] [bp-8h]@4
-  //int v40; // [sp+160h] [bp-4h]@7
-
-//Хотя сами двухмерные изображения основаны на системе координат XY, накладываются  текстуры  на объект, основанный на
-//осях координат U (горизонталь) и V (вертикаль), обхватывающих поверхность объекта.
-
-  extern bool new_sky;
-  if (new_sky)
-  {
-    if (DrawSkyD3D_Skybox())
-    return;
-  }
-
-  v30 = ((double)(pODMRenderParams->int_fov_rad * pGame->pIndoorCameraD3D->vPartyPos.z)
-        / ((double)pODMRenderParams->int_fov_rad + 8192.0) + pViewport->uScreenCenterY);//184 изменяется при подъёме на высоту
-  pViewportBR_Y = pViewport->uScreenCenterY - pODMRenderParams->int_fov_rad /
-       (pODMRenderParams->shading_dist_mist *  cos(pGame->pIndoorCameraD3D->sRotationX * 0.003066406352445483) + 0.0000001000000011686097) *
-       (pODMRenderParams->shading_dist_mist * -sin(pGame->pIndoorCameraD3D->sRotationX * 0.003066406352445483) - pGame->pIndoorCameraD3D->vPartyPos.z);//61 / 184 / 310 изменяется при наклоне камеры
-
-  pSkyPolygon.Create_48607B(&stru_8019C8);
-  pSkyPolygon.ptr_38->_48694B_frustum_sky();//maybe creating skydome(возможно создание купола неба)
-  pSkyPolygon.uTileBitmapID = pOutdoor->uSky_TextureID;//номер текстуры
-  pSkyPolygon.pTexture = (Texture *)(pOutdoor->uSky_TextureID != -1 ? &pBitmaps_LOD->pTextures[pOutdoor->uSky_TextureID] : 0);//текстура неба
-  if (pOutdoor->uSky_TextureID == -1)
-    return;
-
-  pSkyPolygon.dimming_level = 0;//затемнение
-  pSkyPolygon.uNumVertices = 4;//количество вершин
-
-  //centering(центруем)--наклон камеры ----------------------------------------//
-  pSkyPolygon.v_18.x = -stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX + 16);//-3216, вверх: -28020, вниз: 22078
-  pSkyPolygon.v_18.y = 0;
-  pSkyPolygon.v_18.z = -stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX + 16);//-65457, вверх: -59244, вниз: -61705
-  //---------------------------------------------------------------------------//
-
-  pSkyPolygon.field_24 = 0x2000000;
-
-  pSkyPolygon.sTextureDeltaU = 224 * pMiscTimer->uTotalGameTimeElapsed;//60928
-  pSkyPolygon.sTextureDeltaV = 224 * pMiscTimer->uTotalGameTimeElapsed;
+  int v40; // [sp+160h] [bp-4h]@7
+
+  v30 = (signed __int64)((double)(pODMRenderParams->int_fov_rad * pGame->pIndoorCameraD3D->vPartyPos.z)
+                       / ((double)pODMRenderParams->int_fov_rad + 8192.0)
+                       + (double)(pViewport->uScreenCenterY + 7));//include "+ 7"
+  v34 = cos((double)pGame->pIndoorCameraD3D->sRotationX * 0.0030664064) * 0x2000;//(double)pODMRenderParams->shading_dist_mist
+  v38 = (signed __int64)((double)(pViewport->uScreenCenterY + 7)
+                       - (double)pODMRenderParams->int_fov_rad
+                       / (v34 + 0.0000001)
+                       * (sin((double)pGame->pIndoorCameraD3D->sRotationX * 0.0030664064)
+                        * (double)-0x2000//(double)pODMRenderParams->shading_dist_mist
+                        - (double)pGame->pIndoorCameraD3D->vPartyPos.z));
+  pSkyPolygon.Create_48607B(&stru_8019C8);//заполняется ptr_38
+  pSkyPolygon.ptr_38->_48694B_frustum_sky();
+  pSkyPolygon.uTileBitmapID = pOutdoor->uSky_TextureID;//179(original 166)
+  pSkyPolygon.pTexture = (Texture *)(SLOWORD(pOutdoor->uSky_TextureID) != -1 ? (int)&pBitmaps_LOD->pTextures[SLOWORD(pOutdoor->uSky_TextureID)] : 0);
+  if ( pSkyPolygon.pTexture )
+  {
+    pSkyPolygon.dimming_level = 0;
+    pSkyPolygon.uNumVertices = 4;
+  //centering(центруем)--наклон камеры ----------------------------------------
+    pSkyPolygon.v_18.x = -stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX + 16);
+    pSkyPolygon.v_18.y = 0;
+    pSkyPolygon.v_18.z = -stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX + 16);
   
-  //sky wiew position(положение неба)------------------------------------------
+  //sky wiew position(положение неба на экране)------------------------------------------
   //                X
   // 0._____________________________.3
   //  |8,8                    468,8 |
@@ -4952,133 +4934,98 @@
   //  |8,351                468,351 |
   // 1._____________________________.2
   // 
-
-  array_50AC10[0].vWorldViewProjX = pViewport->uViewportTL_X;//8
-  array_50AC10[0].vWorldViewProjY = pViewport->uViewportTL_Y;//8
-
-  array_50AC10[1].vWorldViewProjX = pViewport->uViewportTL_X;//8
-  array_50AC10[1].vWorldViewProjY = pViewportBR_Y;//61 / 184 / 310
-
-  array_50AC10[2].vWorldViewProjX = pViewport->uViewportBR_X;//468
-  array_50AC10[2].vWorldViewProjY = pViewportBR_Y;//61 / 184 / 310
-
-  array_50AC10[3].vWorldViewProjX = pViewport->uViewportBR_X;//468
-  array_50AC10[3].vWorldViewProjY = pViewport->uViewportTL_Y;//8
-  //--------------------------------------------------------------------------
-
-  //pParty->sRotationY / 2048.0f
-  // move sky(движение неба)--------------include(вставка)---------------------
-    float t = (GetTickCount() % 96000) / 96000.0f;
-    array_50AC10[0].u = t - pParty->sRotationY / 1024.0f;
-    array_50AC10[0].v = t - pParty->sRotationX / 512.0f;
-    
-    array_50AC10[1].u = t - pParty->sRotationY / 1024.0f;
-    array_50AC10[1].v = 1 + t - pParty->sRotationX / 512.0f;
-
-    array_50AC10[2].u = 1 + t - pParty->sRotationY / 1024.0f;
-    array_50AC10[2].v = 1 + t - pParty->sRotationX / 512.0f;
-
-    array_50AC10[3].u = 1 + t - pParty->sRotationY / 1024.0f;
-    array_50AC10[3].v = t - pParty->sRotationX / 512.0f;
-  //--------------------------------------------------------------------------//
-
-  //rotate skydome(вращение купола неба)--------------------------------------
-  // В игре принята своя система измерения углов. Полный угол в 2П радиан соответствует 65536 еденицам. Значению угла 0 соответствует 
-  // направление на восток, значению 16384(0х4000) - на север и т.д..
-
-  //нахождение вектора взгляда------------------------------------------------
-  //положение камеры----------------------------------------------------------
-  screen_center_x = (pViewport->uViewportBR_X - pViewport->uViewportTL_X) / 2;//центр экрана по X = 230
-  v33 = 65536 / (signed int)(screen_center_x / tan(0.6457717418670654) + 0.5);//360 : (расстояние от экрана до камеры в пикселях) = 214
-  //--------------------------------------------------------------------------
-
-  for ( uint vertex_id = 0; vertex_id < pSkyPolygon.uNumVertices; ++vertex_id )
-  {
-    v29 = floorf(array_50AC10[vertex_id].vWorldViewProjY + 0.5f);//8
-    v39 = (unsigned __int64)(pSkyPolygon.ptr_38->field_14 * v33 * (v30 - v29)) / 65536;//0
-    v8 = v39 + pSkyPolygon.ptr_38->field_C;//0
-
-    v39 = (unsigned __int64)(pSkyPolygon.ptr_38->field_20 * v33 * (v30 - v29)) / 65536;//0
-    screen_center_x = v39 + pSkyPolygon.ptr_38->field_18;//65536
-
-    v9 = (unsigned __int64)(pSkyPolygon.v_18.z * v33 * (v30 - v29)) / 65536;//27917
-    v10 = pSkyPolygon.v_18.x + v9;//24701
-    v39 = pSkyPolygon.v_18.x + v9;//24701
-    if ( pSkyPolygon.v_18.x + v9 > 0 )
+    array_50AC10[0].vWorldViewProjX = (double)(signed int)pViewport->uViewportTL_X;
+    array_50AC10[0].vWorldViewProjY = (double)(signed int)pViewport->uViewportTL_Y;
+
+    array_50AC10[1].vWorldViewProjX = (double)(signed int)pViewport->uViewportTL_X;
+    array_50AC10[1].vWorldViewProjY = (double)v38;
+
+    array_50AC10[2].vWorldViewProjX = (double)(signed int)pViewport->uViewportBR_X;
+    array_50AC10[2].vWorldViewProjY = (double)v38;
+
+    array_50AC10[3].vWorldViewProjX = (double)(signed int)pViewport->uViewportBR_X;
+    array_50AC10[3].vWorldViewProjY = (double)(signed int)pViewport->uViewportTL_Y;
+
+    pSkyPolygon.sTextureDeltaU = 224 * pMiscTimer->uTotalGameTimeElapsed;
+    pSkyPolygon.sTextureDeltaV = 224 * pMiscTimer->uTotalGameTimeElapsed;
+
+    pSkyPolygon.field_24 = 0x2000000u;
+    v33 = 65536 / (signed int)(signed __int64)(((double)(pViewport->uViewportBR_X - pViewport->uViewportTL_X) * 0.5) / tan(0.6457717418670654) + 0.5);
+    for ( uint i = 0; i < pSkyPolygon.uNumVertices; ++i )
     {
-      v10 = 0;
-      v39 = 0;
-    }
-    //v11 = (signed __int64)array_50AC10[i].vWorldViewProjX;
-    pViewportBR_Y = v10;
-    //v12 = array_50AC10[i].vWorldViewProjY - 1.0;
-    v13 = v33 * (pViewport->uScreenCenterX - (signed __int64)array_50AC10[vertex_id].vWorldViewProjX);
-    v34 = -pSkyPolygon.field_24;
-    v32 = (signed __int64)array_50AC10[vertex_id].vWorldViewProjY - 1.0;
-    v14 = v33 * (v30 - v32);
-
-    while ( 1 )
-    {
-      //v40 = v14;
-      if ( !v10 )
+      v26 = array_50AC10[i].vWorldViewProjY + 6.7553994e15;
+      //rotate skydome(вращение купола неба)--------------------------------------
+      // В игре принята своя система измерения углов. Полный угол (180). Значению угла 0 соответствует 
+      // направление на север и/или юг (либо на восток и/или запад), значению 65536 еденицам(0х10000) соответствует угол 90.
+      v39 = (unsigned __int64)(pSkyPolygon.ptr_38->field_14 * (signed __int64)(v33 * (v30 - array_50AC10[i].vWorldViewProjY))) >> 16;
+      v35 = v39 + pSkyPolygon.ptr_38->angle_from_north;
+
+      v39 = (unsigned __int64)(pSkyPolygon.ptr_38->field_20 * (signed __int64)(v33 * (v30 - array_50AC10[i].vWorldViewProjY))) >> 16;
+      v36 = v39 + pSkyPolygon.ptr_38->angle_from_east;
+
+      v38 = pSkyPolygon.v_18.z;
+      v9 = (unsigned __int64)(pSkyPolygon.v_18.z * (signed __int64)(v33 * (v30 - array_50AC10[i].vWorldViewProjY))) >> 16;
+      v10 = pSkyPolygon.v_18.x + v9;
+      v39 = pSkyPolygon.v_18.x + v9;
+      if ( pSkyPolygon.v_18.x + v9 > 0 )
       {
+        v10 = 0;
+        v39 = 0;
+      }
+      v38 = v10;
+      v13 = v33 * (pViewport->uScreenCenterX - (signed __int64)array_50AC10[i].vWorldViewProjX);
+      v34 = -pSkyPolygon.field_24;
+      v32 = (signed __int64)array_50AC10[i].vWorldViewProjX;
+      v14 = v33 * (v30 - (signed __int64)array_50AC10[i].vWorldViewProjX);
+      while ( 1 )
+      {
+        v40 = v14;
+        if ( !v10 )
+          goto LABEL_12;
+        v37 = abs((int)v34 >> 14);
+        v15 = abs(v10);
+        if ( v37 <= v15 || v32 <= (signed int)pViewport->uViewportTL_Y )
+        {
+          if ( v39 <= 0 )
+            break;
+        }
+        v14 = v40;
+LABEL_12:
         v37 = pSkyPolygon.v_18.z;
         v16 = (unsigned __int64)(pSkyPolygon.v_18.z * (signed __int64)v14) >> 16;
         --v32;
         v14 += v33;
         v10 = pSkyPolygon.v_18.x + v16;
         v39 = pSkyPolygon.v_18.x + v16;
-        pViewportBR_Y = pSkyPolygon.v_18.x + v16;
-        break;
-      }
-      v37 = abs(v34 >> 14);//2048
-      if ( abs(v34 >> 14) <= abs(v10) || v32 <= pViewport->uViewportTL_Y )
-      {
-        if ( v39 <= 0 )
-          break;
+        v38 = pSkyPolygon.v_18.x + v16;
       }
-      //v14 = v40;
-      v37 = pSkyPolygon.v_18.z;
-      v16 = (unsigned __int64)(pSkyPolygon.v_18.z * v14) >> 16;
-      --v32;
-      v14 += v33;
-      v10 = pSkyPolygon.v_18.x + v16;
-      v39 = pSkyPolygon.v_18.x + v16;
-      pViewportBR_Y = pSkyPolygon.v_18.x + v16;
-      break;
+      LODWORD(v17) = LODWORD(v34) << 16;
+      HIDWORD(v17) = v34 >> 16;
+      v40 = v17 / v38;
+      v18 = v17 / v38;
+      if ( v18 < 0 )
+        v18 = pODMRenderParams->shading_dist_mist;
+      v37 = v35 + ((unsigned __int64)(pSkyPolygon.ptr_38->angle_from_west * (signed __int64)v13) >> 16);
+      v35 = 224 * pMiscTimer->uTotalGameTimeElapsed
+          + ((signed int)((unsigned __int64)(v37 * (signed __int64)v18) >> 16) >> 3);
+      array_50AC10[i].u = (double)v35 / ((double)pSkyPolygon.pTexture->uTextureWidth * 65536.0);
+
+      v36 = v36 + ((unsigned __int64)(pSkyPolygon.ptr_38->angle_from_south * (signed __int64)v13) >> 16);
+      v35 = 224 * pMiscTimer->uTotalGameTimeElapsed
+         + ((signed int)((unsigned __int64)(v36 * (signed __int64)v18) >> 16) >> 3);
+      array_50AC10[i].v = (double)v35 / ((double)pSkyPolygon.pTexture->uTextureHeight * 65536.0);
+
+      array_50AC10[i].vWorldViewPosition.x = (double)0x2000;//pODMRenderParams->shading_dist_mist
+      array_50AC10[i]._rhw = 1.0 / (double)(v18 >> 16);
     }
-
-    pShading = fixpoint_div(v34, pViewportBR_Y);
-    if ( pShading < 0 )
-      pShading = pODMRenderParams->shading_dist_mist;
-
-    v37 += ((unsigned __int64)(pSkyPolygon.ptr_38->field_10 * v13) >> 16);
-    screen_center_x += ((unsigned __int64)(pSkyPolygon.ptr_38->field_1C * v13) >> 16);
-    v35 = 224 * pMiscTimer->uTotalGameTimeElapsed + fixpoint_mul(v37, pShading) / 8;// Медленно вращаем небесный купол
-    screen_center_x = 224 * pMiscTimer->uTotalGameTimeElapsed + fixpoint_mul(screen_center_x, pShading) / 8;
-
-    //array_50AC10[vertex_id].vWorldViewPosition.x = pODMRenderParams->shading_dist_mist;
-    //array_50AC10[vertex_id].vWorldPosition.x = v36 / (pSky.pTexture->uTextureHeight * 65536.0);
-    //array_50AC10[vertex_id].vWorldPosition.y = 1.0 / (pODMRenderParams->shading_dist_mist >> 16);
-    //array_50AC10[vertex_id].vWorldPosition.z = v35 / (pSky.pTexture->uTextureWidth * 65536.0);
-    //array_50AC10[vertex_id]._rhw = 1.0f / (pShading >> 16);
-    //array_50AC10[vertex_id].u = (double)v35 / (65536.0 * pSkyPolygon.pTexture->uTextureWidth);
-    //array_50AC10[vertex_id].v = (double)screen_center_x / (65536.0 * pSkyPolygon.pTexture->uTextureHeight);
-  //-----------------------------------------------------------------------------------------
-
-    array_50AC10[vertex_id]._rhw = 1.0f;
-  }
-  //if ( i  == _this.uNumVertices - 1 )
-  //{
-    pRenderer->DrawSkyPolygon(pSkyPolygon.uNumVertices, &pSkyPolygon, pBitmaps_LOD->pHardwareTextures[pSkyPolygon.uTileBitmapID]);
-
-    array_50AC10[0].vWorldViewProjY = pViewportBR_Y;
+    pRenderer->DrawSkyPolygon(pSkyPolygon.uNumVertices, &pSkyPolygon, pBitmaps_LOD->pHardwareTextures[(signed __int16)pSkyPolygon.uTileBitmapID]);
+    array_50AC10[0].vWorldViewProjY = (double)v38;
     array_50AC10[1].vWorldViewProjY = array_50AC10[1].vWorldViewProjY + 30.0;
     array_50AC10[2].vWorldViewProjY = array_50AC10[2].vWorldViewProjY + 30.0;
-    array_50AC10[3].vWorldViewProjY = pViewportBR_Y;
-
-    pRenderer->DrawSkyPolygon(pSkyPolygon.uNumVertices, &pSkyPolygon, pBitmaps_LOD->pHardwareTextures[pSkyPolygon.uTileBitmapID]);
-  //}
+    array_50AC10[3].vWorldViewProjY = (double)v38;
+    pRenderer->DrawSkyPolygon(pSkyPolygon.uNumVertices, &pSkyPolygon, pBitmaps_LOD->pHardwareTextures[(signed __int16)pSkyPolygon.uTileBitmapID]);
+    return;
+  }
 }
 
 //----- (0047A384) --------------------------------------------------------
@@ -5775,14 +5722,14 @@
   {
     v17 = fixpoint_mul(a2, v9) + fixpoint_mul(a3, v7);
 
-    this->field_C = fixpoint_mul(v17, v25) + fixpoint_mul(a4, v27);
-    this->field_10 = fixpoint_mul(a3, v9) - fixpoint_mul(a2, v7);
+    this->angle_from_north = fixpoint_mul(v17, v25) + fixpoint_mul(a4, v27);
+    this->angle_from_west = fixpoint_mul(a3, v9) - fixpoint_mul(a2, v7);
     this->field_14 = fixpoint_mul(a4, v25) - fixpoint_mul(v17, v27);
   }
   else
   {
-    this->field_C = fixpoint_mul(a2, v9) + fixpoint_mul(a3, v7);
-    this->field_10 = fixpoint_mul(a3, v9) - fixpoint_mul(a2, v7);
+    this->angle_from_north = fixpoint_mul(a2, v9) + fixpoint_mul(a3, v7);
+    this->angle_from_west = fixpoint_mul(a3, v9) - fixpoint_mul(a2, v7);
     this->field_14 = a4;
   }
 
@@ -5790,41 +5737,41 @@
   {
     v19 = fixpoint_mul(a5, v9) + fixpoint_mul(a6, v7);
 
-    this->field_18 = fixpoint_mul(v19, v25) + fixpoint_mul(a7, v27);
-    this->field_1C = fixpoint_mul(a6, v9) - fixpoint_mul(a5, v7);
+    this->angle_from_east = fixpoint_mul(v19, v25) + fixpoint_mul(a7, v27);
+    this->angle_from_south = fixpoint_mul(a6, v9) - fixpoint_mul(a5, v7);
     this->field_20 = fixpoint_mul(a7, v25) - fixpoint_mul(v19, v27);
   }
   else
   {
-    this->field_18 = fixpoint_mul(a5, v9) + fixpoint_mul(a6, v7);
-    this->field_1C = fixpoint_mul(a6, v9) - fixpoint_mul(a5, v7);
+    this->angle_from_east = fixpoint_mul(a5, v9) + fixpoint_mul(a6, v7);
+    this->angle_from_south = fixpoint_mul(a6, v9) - fixpoint_mul(a5, v7);
     this->field_20 = a7;
   }
 
-  this->field_18 = -this->field_18;
-  this->field_1C = -this->field_1C;
+  this->angle_from_east = -this->angle_from_east;
+  this->angle_from_south = -this->angle_from_south;
   this->field_20 = -this->field_20;
 
-  this->field_24 = fixpoint_dot(this->field_C,  this->field_0_party_dir_x,
-                                this->field_10, this->field_4_party_dir_y,
+  this->field_24 = fixpoint_dot(this->angle_from_north,  this->field_0_party_dir_x,
+                                this->angle_from_west, this->field_4_party_dir_y,
                                 this->field_14, this->field_8_party_dir_z);
-  this->field_28 = fixpoint_dot(this->field_18, this->field_0_party_dir_x,
-                                this->field_1C, this->field_4_party_dir_y,
+  this->field_28 = fixpoint_dot(this->angle_from_east, this->field_0_party_dir_x,
+                                this->angle_from_south, this->field_4_party_dir_y,
                                 this->field_20, this->field_8_party_dir_z);
 }
 
 //----- (0048694B) --------------------------------------------------------
 void stru149::_48694B_frustum_sky()
 {
-  this->field_18 = -this->field_18;
-  this->field_1C = -this->field_1C;
+  this->angle_from_east = -this->angle_from_east;
+  this->angle_from_south = -this->angle_from_south;
   this->field_20 = -this->field_20;
 
-  this->field_24 = fixpoint_dot(this->field_C,  this->field_0_party_dir_x,
-                                this->field_10, this->field_4_party_dir_y,
+  this->field_24 = fixpoint_dot(this->angle_from_north, this->field_0_party_dir_x,
+                                this->angle_from_west, this->field_4_party_dir_y,
                                 this->field_14, this->field_8_party_dir_z);
-  this->field_28 = fixpoint_dot(this->field_18, this->field_0_party_dir_x,
-                                this->field_1C, this->field_4_party_dir_y,
+  this->field_28 = fixpoint_dot(this->angle_from_east, this->field_0_party_dir_x,
+                                this->angle_from_south, this->field_4_party_dir_y,
                                 this->field_20, this->field_8_party_dir_z);
 }
 
--- a/mm7_4.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/mm7_4.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -123,11 +123,10 @@
   v31 = v4;
   v39 = 1;
   dword_720F20[0] = 10000;
-  v32 = 0;
   if ( (signed int)pOutdoor->uNumBModels > 0 )
   {
     v29 = 0;
-    do
+    for ( v32 = 0; v32 < (signed int)pOutdoor->uNumBModels; ++v32 )
     {
       v6 = &pOutdoor->pBModels[v29];
       if ( v4 <= pOutdoor->pBModels[v29].sMaxX )
@@ -239,11 +238,11 @@
           }
         }
       }
-      ++v32;
+      //++v32;
       ++v29;
       v5 = 0;
     }
-    while ( v32 < (signed int)pOutdoor->uNumBModels );
+    //while ( v32 < (signed int)pOutdoor->uNumBModels );
     if ( !v39 )
     {
       *(int *)a4 = 0;
--- a/mm7_data.cpp	Wed Oct 09 08:06:26 2013 +0200
+++ b/mm7_data.cpp	Wed Oct 09 08:09:48 2013 +0200
@@ -873,7 +873,7 @@
 
 _UNKNOWN unk_4FAA20; // weak
 char byte_4FAA24; // weak
-HWND dword_4FAA28; // idb
+//HWND dword_4FAA28; // idb
 
 
 
@@ -948,7 +948,6 @@
 std::array<char *, 9> aSpellSchoolNames;
 std::array<char *, 7> aAttributeNames;
 int dword_507B94; // weak
-int dword_507B98_ctrl_pressed; // weak
 unsigned int uActiveCharacter;
 int dword_507BF0_is_there_popup_onscreen; // weak
 int awards_scroll_bar_created; // weak
@@ -1194,7 +1193,8 @@
 float fBackwardWalkSpeedMultiplier = 1.0f; // weak
 float fTurnSpeedMultiplier = 1.0f; // weak
 float flt_6BE150_look_up_down_dangle = 1.0f; // weak
-HWND hWnd; // idb
+//HWND hWnd; // idb
+class OSWindow *window = nullptr;
 int dword_6BE340; // weak
 char pCurrentMapName[32]; // idb
 unsigned int uLevelMapStatsID;
@@ -1348,7 +1348,6 @@
 int dword_F8B1F4; // weak
 
 
-
 //_UNKNOWN unk_F8BA50; // weak
 char byte_F8BC0C; // weak
 int bGameoverLoop = 0; // weak
--- a/mm7_data.h	Wed Oct 09 08:06:26 2013 +0200
+++ b/mm7_data.h	Wed Oct 09 08:09:48 2013 +0200
@@ -519,7 +519,7 @@
 
 extern _UNKNOWN unk_4FAA20; // weak
 extern char byte_4FAA24; // weak
-extern HWND dword_4FAA28; // idb
+//extern HWND dword_4FAA28; // idb
 
 
 
@@ -593,7 +593,6 @@
 extern std::array<char *, 9> aSpellSchoolNames;
 extern std::array<char *, 7> aAttributeNames;
 extern int dword_507B94; // weak
-extern int dword_507B98_ctrl_pressed; // weak
 extern unsigned int uActiveCharacter;
 extern int dword_507BF0_is_there_popup_onscreen; // weak
 extern int awards_scroll_bar_created; // weak
@@ -844,7 +843,8 @@
 //extern char pMM7WindowClassName[]; // idb
 //extern HINSTANCE hInstance; // idb
 //extern char *pCmdLine;
-extern HWND hWnd; // idb
+//extern HWND hWnd; // idb
+extern class OSWindow *window;
 extern int dword_6BE340; // weak
 extern char pCurrentMapName[32]; // idb
 extern unsigned int uLevelMapStatsID;
@@ -1074,7 +1074,7 @@
 void uGameUIFontMain_initialize();
 void uGameUIFontShadow_initialize();
 void Inventory_ItemPopupAndAlchemy();
-void sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(struct Vec2_int_ *_this);
+void UI_OnMouseRightClick(struct Vec2_int_ *_this);
 void UI_OnMouseLeftClick(int *pXY); // idb
 unsigned int UI_GetHealthManaAndOtherQualitiesStringColor(signed int current_pos, signed int base_pos);
 unsigned int __fastcall GetSizeInInventorySlots(unsigned int uNumPixels);
@@ -1360,8 +1360,6 @@
 }
 //inline void __fastcall j_memset32(int a2, void *a1, unsigned int a3) {memset32(a1, a2, a3);}
 
-void CenterWindowAndAdjustSize(HWND hwnd, int client_width, int client_height);
-
 #define ErrD3D(hr) do {extern void ErrHR(HRESULT, const char *, const char *, const char *, int); ErrHR(hr, "Direct3D", __FUNCTION__, __FILE__, __LINE__);} while(0)